70 lines
1.8 KiB
PHP
70 lines
1.8 KiB
PHP
<?php
|
|
|
|
namespace App\Provisioning\Steps\Customer;
|
|
|
|
use App\Models\Instance;
|
|
use App\Models\Order;
|
|
use App\Models\ProvisioningRun;
|
|
use App\Provisioning\Contracts\ProvisioningStep;
|
|
use App\Provisioning\Steps\ManagesRunResources;
|
|
use App\Services\Proxmox\ProxmoxClient;
|
|
use RuntimeException;
|
|
|
|
/**
|
|
* Shared helpers for customer-provisioning steps: subject/instance/plan
|
|
* resolution, guest-agent command execution, and idempotency breadcrumbs.
|
|
*/
|
|
abstract class CustomerStep implements ProvisioningStep
|
|
{
|
|
use ManagesRunResources;
|
|
|
|
public function label(): string
|
|
{
|
|
return 'provisioning.step.'.$this->key();
|
|
}
|
|
|
|
public function maxDuration(): int
|
|
{
|
|
return 300;
|
|
}
|
|
|
|
protected function order(ProvisioningRun $run): Order
|
|
{
|
|
/** @var Order $order */
|
|
$order = $run->subject;
|
|
|
|
return $order;
|
|
}
|
|
|
|
protected function instance(ProvisioningRun $run): ?Instance
|
|
{
|
|
$id = $run->context('instance_id');
|
|
|
|
return $id ? Instance::query()->find($id) : null;
|
|
}
|
|
|
|
/** @return array<string, mixed> */
|
|
protected function plan(ProvisioningRun $run): array
|
|
{
|
|
return config('provisioning.plans.'.$this->order($run)->plan, []);
|
|
}
|
|
|
|
/**
|
|
* Run a command inside the guest via qemu-guest-agent. Throws on a non-zero
|
|
* exit code so the runner turns it into a retry.
|
|
*/
|
|
protected function guest(ProxmoxClient $pve, ProvisioningRun $run, string $command): string
|
|
{
|
|
$node = (string) $run->context('node');
|
|
$vmid = (int) $run->context('vmid');
|
|
|
|
$result = $pve->guestExec($node, $vmid, $command);
|
|
|
|
if ((int) ($result['exitcode'] ?? 1) !== 0) {
|
|
throw new RuntimeException("guest exec failed (exit {$result['exitcode']}): {$command}");
|
|
}
|
|
|
|
return (string) ($result['out-data'] ?? '');
|
|
}
|
|
}
|