mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-08-10 14:26:52 +00:00
feat(test): use new cmdlets in test VM setup and add guest agent tests
prepare-test-vm.sh now uses module cmdlets for 7 of 8 steps: - Set-PveVmConfig -AdditionalConfig replaces SSH qm set (8 config keys) - Test-PveVmGuestAgent replaces SSH qm agent ping - Only SSH remaining: pvesm set, SCP snippet, qm importdisk New integration tests for guest agent cmdlets: - Test-PveVmGuestAgent: verify agent responds - Get-PveVmGuestNetwork: verify interfaces with IPv4 addresses - Invoke-PveVmGuestExec: run hostname command, verify exit code + output Also force Node.js 24 for delete-package-versions (no v6 available yet). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -95,6 +95,8 @@ jobs:
|
||||
if: always()
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||||
steps:
|
||||
- name: Delete old container image versions
|
||||
uses: actions/delete-package-versions@v5
|
||||
|
||||
@@ -560,6 +560,38 @@ Describe 'Integration Tests' -Tag 'Integration' {
|
||||
}
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
Context 'Guest Agent — Cmdlets' {
|
||||
It 'Should ping guest agent (Test-PveVmGuestAgent)' {
|
||||
if (Skip-IfNoLinuxVm) { return }
|
||||
|
||||
$result = Test-PveVmGuestAgent -Node $script:Node -VmId $script:LinuxVmId
|
||||
$result | Should -BeTrue
|
||||
}
|
||||
|
||||
It 'Should discover guest network interfaces (Get-PveVmGuestNetwork)' {
|
||||
if (Skip-IfNoLinuxVm) { return }
|
||||
|
||||
$interfaces = Get-PveVmGuestNetwork -Node $script:Node -VmId $script:LinuxVmId
|
||||
$interfaces | Should -Not -BeNullOrEmpty
|
||||
|
||||
# Should have at least one interface with an IPv4 address
|
||||
$withIp = $interfaces | Where-Object {
|
||||
$_.IpAddresses | Where-Object { $_.Type -eq 'ipv4' -and $_.Address -ne '127.0.0.1' }
|
||||
}
|
||||
$withIp | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
|
||||
It 'Should execute a command in guest (Invoke-PveVmGuestExec)' {
|
||||
if (Skip-IfNoLinuxVm) { return }
|
||||
|
||||
$result = Invoke-PveVmGuestExec -Node $script:Node -VmId $script:LinuxVmId -Command 'hostname'
|
||||
$result | Should -Not -BeNullOrEmpty
|
||||
$result.ExitCode | Should -Be 0
|
||||
$result.Stdout | Should -Not -BeNullOrEmpty
|
||||
}
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
Context 'Guest Agent VM — Lifecycle' {
|
||||
It 'Should have a running Linux VM with guest agent' {
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# Prepares a Debian cloud image VM with qemu-guest-agent on the nested PVE.
|
||||
# Prepares an Ubuntu cloud image VM with qemu-guest-agent on the nested PVE.
|
||||
#
|
||||
# Uses PSProxmoxVE cmdlets where possible (we're integration testing the module
|
||||
# after all), SSH/SCP only for operations the API doesn't expose:
|
||||
# - SCP the cloud-init snippet (no snippet upload API)
|
||||
# - pvesm set to enable snippets content type
|
||||
# - qm importdisk (no API equivalent)
|
||||
# - qm set for --scsi0, --cicustom, --boot, --agent (Set-PveVmConfig doesn't expose these)
|
||||
# Uses PSProxmoxVE cmdlets for all supported operations:
|
||||
# - Invoke-PveStorageDownload (cloud image download)
|
||||
# - New-PveVm (VM creation)
|
||||
# - Set-PveVmConfig -AdditionalConfig (disk/boot/agent/cloud-init config)
|
||||
# - Set-PveCloudInitConfig (user/password/IP)
|
||||
# - Start-PveVm (boot)
|
||||
# - Test-PveVmGuestAgent (agent ping)
|
||||
#
|
||||
# SSH/SCP only for operations without API support:
|
||||
# - pvesm set (enable snippets content type)
|
||||
# - SCP snippet upload (no snippet API)
|
||||
# - qm importdisk (no disk import API)
|
||||
#
|
||||
# Usage: prepare-test-vm.sh <nested-pve-ip> <root-password> <vm-id> <node> <api-token>
|
||||
#
|
||||
@@ -28,6 +34,8 @@ SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLeve
|
||||
SSH_CMD="sshpass -p ${ROOT_PASS} ssh ${SSH_OPTS} root@${NESTED_IP}"
|
||||
SCP_CMD="sshpass -p ${ROOT_PASS} scp ${SSH_OPTS}"
|
||||
|
||||
CONNECT_CMD="Connect-PveServer -Server '${NESTED_IP}' -ApiToken '${API_TOKEN}' -SkipCertificateCheck"
|
||||
|
||||
echo "=== Preparing test Linux VM (VMID ${VMID}) on ${NESTED_IP} ==="
|
||||
|
||||
# ── Step 1: Upload cloud-init snippet (SSH — no API for snippets) ────
|
||||
@@ -46,92 +54,76 @@ ${SSH_CMD} "mkdir -p /var/lib/vz/snippets && pvesm set local --content iso,vztmp
|
||||
${SCP_CMD} "${USERDATA}" "root@${NESTED_IP}:/var/lib/vz/snippets/test-vm-userdata.yml"
|
||||
rm -f "${USERDATA}"
|
||||
|
||||
# ── Step 2: Download cloud image (PSProxmoxVE cmdlet) ────────────────
|
||||
# ── Step 2: Download cloud image (module cmdlet) ─────────────────────
|
||||
echo "Downloading Ubuntu cloud image via Invoke-PveStorageDownload..."
|
||||
pwsh -NoProfile -Command "
|
||||
Import-Module PSProxmoxVE
|
||||
Connect-PveServer -Server '${NESTED_IP}' -ApiToken '${API_TOKEN}' -SkipCertificateCheck
|
||||
Import-Module PSProxmoxVE; ${CONNECT_CMD}
|
||||
Invoke-PveStorageDownload \
|
||||
-Node '${NODE}' \
|
||||
-Storage 'local' \
|
||||
-Url '${CLOUD_IMAGE_URL}' \
|
||||
-Filename '${CLOUD_IMAGE_FILENAME}' \
|
||||
-ContentType 'iso' \
|
||||
-Wait
|
||||
-Node '${NODE}' -Storage 'local' \
|
||||
-Url '${CLOUD_IMAGE_URL}' -Filename '${CLOUD_IMAGE_FILENAME}' \
|
||||
-ContentType 'iso' -Wait
|
||||
"
|
||||
|
||||
# ── Step 3: Create VM (PSProxmoxVE cmdlet) ───────────────────────────
|
||||
# ── Step 3: Create VM (module cmdlet) ────────────────────────────────
|
||||
echo "Creating VM ${VMID} via New-PveVm..."
|
||||
pwsh -NoProfile -Command "
|
||||
Import-Module PSProxmoxVE
|
||||
Connect-PveServer -Server '${NESTED_IP}' -ApiToken '${API_TOKEN}' -SkipCertificateCheck
|
||||
New-PveVm \
|
||||
-Node '${NODE}' \
|
||||
-VmId ${VMID} \
|
||||
-Name 'debian-test' \
|
||||
-Memory 512 \
|
||||
-Cores 1 \
|
||||
-OsType 'l26' \
|
||||
-Wait
|
||||
Import-Module PSProxmoxVE; ${CONNECT_CMD}
|
||||
New-PveVm -Node '${NODE}' -VmId ${VMID} -Name 'ubuntu-test' \
|
||||
-Memory 512 -Cores 1 -OsType 'l26' -Wait
|
||||
"
|
||||
|
||||
# ── Step 4: Import disk and configure (SSH — no importdisk API) ──────
|
||||
echo "Importing disk and configuring VM..."
|
||||
${SSH_CMD} bash <<REMOTE
|
||||
set -e
|
||||
# ── Step 4: Import disk (SSH — no importdisk API) ────────────────────
|
||||
echo "Importing disk image..."
|
||||
${SSH_CMD} "qm importdisk ${VMID} /var/lib/vz/template/iso/${CLOUD_IMAGE_FILENAME} local-lvm 2>&1 | tail -1"
|
||||
|
||||
# Import the downloaded image as a disk (stored in local ISO dir by download-url API)
|
||||
qm importdisk ${VMID} /var/lib/vz/template/iso/${CLOUD_IMAGE_FILENAME} local-lvm 2>&1 | tail -1
|
||||
# ── Step 5: Configure VM (module cmdlet — AdditionalConfig) ──────────
|
||||
echo "Configuring VM via Set-PveVmConfig -AdditionalConfig..."
|
||||
pwsh -NoProfile -Command "
|
||||
Import-Module PSProxmoxVE; ${CONNECT_CMD}
|
||||
Set-PveVmConfig -Node '${NODE}' -VmId ${VMID} -AdditionalConfig @{
|
||||
scsihw = 'virtio-scsi-single'
|
||||
scsi0 = 'local-lvm:vm-${VMID}-disk-0'
|
||||
boot = 'order=scsi0'
|
||||
serial0 = 'socket'
|
||||
agent = '1'
|
||||
net0 = 'virtio,bridge=vmbr0'
|
||||
ide2 = 'local-lvm:cloudinit'
|
||||
cicustom = 'user=local:snippets/test-vm-userdata.yml'
|
||||
}
|
||||
"
|
||||
|
||||
# Attach disk, enable agent, configure boot, add cloud-init
|
||||
qm set ${VMID} \
|
||||
--scsihw virtio-scsi-single \
|
||||
--scsi0 local-lvm:vm-${VMID}-disk-0 \
|
||||
--boot order=scsi0 \
|
||||
--serial0 socket \
|
||||
--agent 1 \
|
||||
--net0 virtio,bridge=vmbr0 \
|
||||
--ide2 local-lvm:cloudinit \
|
||||
--cicustom "user=local:snippets/test-vm-userdata.yml"
|
||||
REMOTE
|
||||
|
||||
# ── Step 5: Set cloud-init config (PSProxmoxVE cmdlet) ───────────────
|
||||
# ── Step 6: Set cloud-init config (module cmdlet) ────────────────────
|
||||
echo "Setting cloud-init config via Set-PveCloudInitConfig..."
|
||||
pwsh -NoProfile -Command "
|
||||
Import-Module PSProxmoxVE
|
||||
Connect-PveServer -Server '${NESTED_IP}' -ApiToken '${API_TOKEN}' -SkipCertificateCheck
|
||||
Set-PveCloudInitConfig \
|
||||
-Node '${NODE}' \
|
||||
-VmId ${VMID} \
|
||||
Import-Module PSProxmoxVE; ${CONNECT_CMD}
|
||||
Set-PveCloudInitConfig -Node '${NODE}' -VmId ${VMID} \
|
||||
-CiUser 'root' \
|
||||
-Password (ConvertTo-SecureString '${ROOT_PASS}' -AsPlainText -Force) \
|
||||
-IpConfig0 'ip=dhcp'
|
||||
# Note: Invoke-PveCloudInitRegenerate has a bug (returns cloud-config
|
||||
# content as UPID). Skipping — PVE regenerates cloud-init on VM start.
|
||||
"
|
||||
|
||||
# ── Step 6: Start VM (PSProxmoxVE cmdlet) ────────────────────────────
|
||||
# ── Step 7: Start VM (module cmdlet) ─────────────────────────────────
|
||||
echo "Starting VM ${VMID} via Start-PveVm..."
|
||||
pwsh -NoProfile -Command "
|
||||
Import-Module PSProxmoxVE
|
||||
Connect-PveServer -Server '${NESTED_IP}' -ApiToken '${API_TOKEN}' -SkipCertificateCheck
|
||||
Import-Module PSProxmoxVE; ${CONNECT_CMD}
|
||||
Start-PveVm -Node '${NODE}' -VmId ${VMID} -Wait
|
||||
"
|
||||
|
||||
# ── Step 7: Wait for guest agent ─────────────────────────────────────
|
||||
# ── Step 8: Wait for guest agent (module cmdlet) ─────────────────────
|
||||
echo "Waiting for guest agent on VM ${VMID} (cloud-init installing packages)..."
|
||||
TIMEOUT=300
|
||||
ELAPSED=0
|
||||
while [ $ELAPSED -lt $TIMEOUT ]; do
|
||||
if ${SSH_CMD} "qm agent ${VMID} ping" 2>/dev/null; then
|
||||
echo "Guest agent responding on VM ${VMID}"
|
||||
echo "LINUX_VMID=${VMID}"
|
||||
exit 0
|
||||
fi
|
||||
sleep 10
|
||||
ELAPSED=$((ELAPSED + 10))
|
||||
echo " Waiting... (${ELAPSED}s / ${TIMEOUT}s)"
|
||||
done
|
||||
pwsh -NoProfile -Command "
|
||||
Import-Module PSProxmoxVE; ${CONNECT_CMD}
|
||||
\$timeout = 300; \$elapsed = 0
|
||||
while (\$elapsed -lt \$timeout) {
|
||||
if (Test-PveVmGuestAgent -Node '${NODE}' -VmId ${VMID}) {
|
||||
Write-Host 'Guest agent responding on VM ${VMID}'
|
||||
exit 0
|
||||
}
|
||||
Start-Sleep -Seconds 10
|
||||
\$elapsed += 10
|
||||
Write-Host \" Waiting... (\${elapsed}s / \${timeout}s)\"
|
||||
}
|
||||
throw 'Timeout waiting for guest agent on VM ${VMID}'
|
||||
"
|
||||
|
||||
echo "ERROR: Timeout waiting for guest agent on VM ${VMID}" >&2
|
||||
exit 1
|
||||
echo "LINUX_VMID=${VMID}"
|
||||
|
||||
Reference in New Issue
Block a user