Add VM rebuild pipeline with isolated job chain and admin log API

This commit is contained in:
baodev0
2026-05-29 18:19:38 +07:00
parent 7ae237ee9d
commit 9c68273b4a
27 changed files with 2391 additions and 199 deletions
+102 -62
View File
@@ -59,17 +59,24 @@ final class VsphereHostSshService
: self::SCRIPT_LINUX;
$powerCliVmId = $this->powerCliVmId($vmId);
// Remote Windows cmd.exe command — all args double-quoted
$remoteCmd = sprintf(
'cd %s && powershell -ExecutionPolicy Bypass -NonInteractive -File %s %s %s %s %s %s',
self::SCRIPT_DIR,
$script,
$this->warg($powerCliVmId),
$this->warg($newPassword),
$this->warg($vcenterHost),
$this->warg($vcenterUser),
$this->warg($vcenterPassword),
);
$remoteCmd = strtoupper($osFamily) === VmProvisionService::OS_WINDOWS
? $this->windowsPowerShellCommand(self::SCRIPT_DIR, $script, [
$powerCliVmId,
$newPassword,
$vcenterHost,
$vcenterUser,
$vcenterPassword,
])
: sprintf(
'cd %s && powershell -ExecutionPolicy Bypass -NonInteractive -File %s %s %s %s %s %s',
self::SCRIPT_DIR,
$script,
$this->warg($powerCliVmId),
$this->warg($newPassword),
$this->warg($vcenterHost),
$this->warg($vcenterUser),
$this->warg($vcenterPassword),
);
Log::info('VsphereHostSshService: executing script', [
'vm_id' => $vmId,
@@ -93,8 +100,8 @@ final class VsphereHostSshService
* Assign a static IP to the VM guest OS via PS1 script.
* Calls assignIPLinux.ps1 or assignIPWindows.ps1 in C:\CLISave\AssignIP\.
*
* Windows script params (7): VMName IP MaskBits Gateway DNS GuestUser GuestPassword
* Linux script params (10): VCenter VCUser VCPass VMName IP MaskBits Gateway DNS GuestUser GuestPassword
* Script params:
* VmId IP Gateway Cidr VCenterHost VCenterUser VCenterPassword GuestPassword
*
* Script output: JSON {"status":"ok"} or {"status":"error","message":"..."}
*/
@@ -115,21 +122,30 @@ final class VsphereHostSshService
$script = $isWindows ? self::SCRIPT_ASSIGN_WINDOWS : self::SCRIPT_ASSIGN_LINUX;
$powerCliVmId = $this->powerCliVmId($vmId);
// assignIP{Linux|Windows}.ps1:
// VmId IP Gateway Cidr VCenterHost VCenterUser VCenterPassword GuestPassword
$remoteCmd = sprintf(
'cd %s && powershell -ExecutionPolicy Bypass -NonInteractive -File %s %s %s %s %s %s %s %s %s',
self::ASSIGN_DIR,
$script,
$this->warg($powerCliVmId),
$this->warg($ip),
$this->warg($gateway),
$this->warg($cidr),
$this->warg($vcenterHost),
$this->warg($vcenterUser),
$this->warg($vcenterPassword),
$this->warg($guestPassword),
);
$remoteCmd = $isWindows
? $this->windowsPowerShellCommand(self::ASSIGN_DIR, $script, [
$powerCliVmId,
$ip,
$gateway,
$cidr,
$vcenterHost,
$vcenterUser,
$vcenterPassword,
$guestPassword,
])
: sprintf(
'cd %s && powershell -ExecutionPolicy Bypass -NonInteractive -File %s %s %s %s %s %s %s %s %s',
self::ASSIGN_DIR,
$script,
$this->warg($powerCliVmId),
$this->warg($ip),
$this->warg($gateway),
$this->warg($cidr),
$this->warg($vcenterHost),
$this->warg($vcenterUser),
$this->warg($vcenterPassword),
$this->warg($guestPassword),
);
Log::info('VsphereHostSshService: executing assignIp', [
'vm_id' => $vmId,
@@ -154,8 +170,8 @@ final class VsphereHostSshService
* Verify that an IP is active inside the VM guest OS.
* Calls verifyIPLinux.ps1 or verifyIPWindows.ps1 in C:\CLISave\AssignIP\.
*
* Windows script params (4): VMName IP GuestUser GuestPassword
* Linux script params (7): VCenter VCUser VCPass VMName IP GuestUser GuestPassword
* Script params:
* VmId IP VCenterHost VCenterUser VCenterPassword GuestPassword
*
* Script output: JSON {"status":"ok"} or {"status":"error","message":"..."}
*/
@@ -173,19 +189,26 @@ final class VsphereHostSshService
$script = $isWindows ? self::SCRIPT_VERIFY_WINDOWS : self::SCRIPT_VERIFY_LINUX;
$powerCliVmId = $this->powerCliVmId($vmId);
// verifyIP{Linux|Windows}.ps1:
// VmId IP VCenterHost VCenterUser VCenterPassword GuestPassword
$remoteCmd = sprintf(
'cd %s && powershell -ExecutionPolicy Bypass -NonInteractive -File %s %s %s %s %s %s %s',
self::ASSIGN_DIR,
$script,
$this->warg($powerCliVmId),
$this->warg($ip),
$this->warg($vcenterHost),
$this->warg($vcenterUser),
$this->warg($vcenterPassword),
$this->warg($guestPassword),
);
$remoteCmd = $isWindows
? $this->windowsPowerShellCommand(self::ASSIGN_DIR, $script, [
$powerCliVmId,
$ip,
$vcenterHost,
$vcenterUser,
$vcenterPassword,
$guestPassword,
])
: sprintf(
'cd %s && powershell -ExecutionPolicy Bypass -NonInteractive -File %s %s %s %s %s %s %s',
self::ASSIGN_DIR,
$script,
$this->warg($powerCliVmId),
$this->warg($ip),
$this->warg($vcenterHost),
$this->warg($vcenterUser),
$this->warg($vcenterPassword),
$this->warg($guestPassword),
);
Log::info('VsphereHostSshService: executing verifyIpInGuest', [
'vm_id' => $vmId,
@@ -301,17 +324,26 @@ final class VsphereHostSshService
: self::SCRIPT_CHANGE_PWD_LINUX;
$powerCliVmId = $this->powerCliVmId($vmId);
$remoteCmd = sprintf(
'cd %s && powershell -ExecutionPolicy Bypass -NonInteractive -File %s %s %s %s %s %s %s',
self::CHANGE_PWD_DIR,
$script,
$this->warg($powerCliVmId),
$this->warg($newPassword),
$this->warg($vcenterHost),
$this->warg($vcenterUser),
$this->warg($vcenterPassword),
$this->warg($currentGuestPassword),
);
$remoteCmd = strtoupper($osFamily) === VmProvisionService::OS_WINDOWS
? $this->windowsPowerShellCommand(self::CHANGE_PWD_DIR, $script, [
$powerCliVmId,
$newPassword,
$vcenterHost,
$vcenterUser,
$vcenterPassword,
$currentGuestPassword,
])
: sprintf(
'cd %s && powershell -ExecutionPolicy Bypass -NonInteractive -File %s %s %s %s %s %s %s',
self::CHANGE_PWD_DIR,
$script,
$this->warg($powerCliVmId),
$this->warg($newPassword),
$this->warg($vcenterHost),
$this->warg($vcenterUser),
$this->warg($vcenterPassword),
$this->warg($currentGuestPassword),
);
Log::info('VsphereHostSshService: changePasswordCustomer', [
'vm_id' => $vmId,
@@ -331,6 +363,22 @@ final class VsphereHostSshService
// ─────────────────────────────────────────────────────────────────────────
/**
* @param array<int, string> $arguments
*/
private function windowsPowerShellCommand(string $workingDirectory, string $script, array $arguments): string
{
return sprintf(
'cd %s && powershell -ExecutionPolicy Bypass -File %s %s',
$workingDirectory,
$script,
implode(' ', array_map(
fn (string $argument): string => $this->warg($argument),
$arguments,
)),
);
}
/**
* Windows cmd.exe safe argument: wrap in double quotes, escape inner double quotes.
*/
@@ -348,12 +396,4 @@ final class VsphereHostSshService
return $vmId;
}
/**
* Single-quote wrap for passwords — prevents PowerShell variable expansion on $, %, ^ etc.
* Inside a single-quoted PS string, a literal single quote is escaped as ''.
*/
private function sarg(string $value): string
{
return "'" . str_replace("'", "''", $value) . "'";
}
}