mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-08-19 09:26:17 +00:00
feat: add -Detailed switch to Get-PveVm for accurate pause detection
PVE list endpoint reports Status=running for paused VMs. The new -Detailed switch queries status/current per VM to populate QmpStatus. - PveVm.EffectiveStatus computed property: returns QmpStatus ?? Status - PveVm.Status doc comment explains the limitation - VmService.EnrichVmStatus() queries status/current endpoint - Get-PveVm -Detailed enriches each VM with qmpstatus, pid, uptime - format.ps1xml table view uses EffectiveStatus for the Status column - Integration test asserts EffectiveStatus after suspend/resume Verified locally: Get-PveVm -Detailed correctly shows 'paused' for suspended VMs where Get-PveVm (without -Detailed) shows 'running'. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,7 +24,10 @@ public class PveVm
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The current runtime status of the VM (e.g., "running", "stopped").
|
||||
/// The runtime status from the VM list endpoint (e.g., "running", "stopped").
|
||||
/// Note: reports "running" for both running AND paused VMs. For accurate pause
|
||||
/// detection, use <see cref="EffectiveStatus"/> or <see cref="QmpStatus"/>,
|
||||
/// which are populated when using Get-PveVm -Detailed.
|
||||
/// </summary>
|
||||
[JsonPropertyName("status")]
|
||||
[JsonProperty("status")]
|
||||
@@ -94,12 +97,21 @@ public class PveVm
|
||||
public int? Pid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The QMP (QEMU Machine Protocol) status string.
|
||||
/// The QMP (QEMU Machine Protocol) status string (e.g., "running", "paused", "stopped").
|
||||
/// Only populated from the status/current endpoint (Get-PveVm -Detailed), not the list endpoint.
|
||||
/// </summary>
|
||||
[JsonPropertyName("qmpstatus")]
|
||||
[JsonProperty("qmpstatus")]
|
||||
public string? QmpStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The effective runtime status, preferring QmpStatus over Status for accurate
|
||||
/// pause detection. Returns QmpStatus when available (from -Detailed), otherwise Status.
|
||||
/// </summary>
|
||||
[System.Text.Json.Serialization.JsonIgnore]
|
||||
[Newtonsoft.Json.JsonIgnore]
|
||||
public string? EffectiveStatus => QmpStatus ?? Status;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the QEMU guest agent is running (non-zero) inside the VM.
|
||||
/// </summary>
|
||||
@@ -115,7 +127,7 @@ public class PveVm
|
||||
var uptimeStr = Uptime.HasValue ? TimeSpan.FromSeconds(Uptime.Value).ToString(@"d\.hh\:mm\:ss") : "N/A";
|
||||
var templateStr = Template is 1 ? " [template]" : string.Empty;
|
||||
return $"VM {VmId}{templateStr}: {Name ?? "(unnamed)"} | Node: {Node ?? "N/A"} | "
|
||||
+ $"Status: {Status ?? "N/A"} | CPUs: {CpuCount?.ToString() ?? "N/A"} | "
|
||||
+ $"Status: {EffectiveStatus ?? "N/A"} | CPUs: {CpuCount?.ToString() ?? "N/A"} | "
|
||||
+ $"Mem: {maxMemMb} | Disk: {maxDiskGb} | Uptime: {uptimeStr}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,34 @@ namespace PSProxmoxVE.Core.Services
|
||||
return vm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enriches a VM object with detailed status from the status/current endpoint,
|
||||
/// populating QmpStatus and other fields not available from the list endpoint.
|
||||
/// </summary>
|
||||
/// <param name="session">The authenticated PVE session.</param>
|
||||
/// <param name="node">The cluster node name.</param>
|
||||
/// <param name="vm">The VM to enrich.</param>
|
||||
public void EnrichVmStatus(PveSession session, string node, PveVm vm)
|
||||
{
|
||||
if (session == null) throw new ArgumentNullException(nameof(session));
|
||||
if (string.IsNullOrWhiteSpace(node)) throw new ArgumentNullException(nameof(node));
|
||||
if (vm == null) throw new ArgumentNullException(nameof(vm));
|
||||
|
||||
using var client = new PveHttpClient(session);
|
||||
var response = client.GetAsync($"nodes/{node}/qemu/{vm.VmId}/status/current")
|
||||
.GetAwaiter().GetResult();
|
||||
var data = JObject.Parse(response)["data"];
|
||||
if (data == null) return;
|
||||
|
||||
vm.QmpStatus = data["qmpstatus"]?.ToString();
|
||||
vm.Status = data["status"]?.ToString() ?? vm.Status;
|
||||
vm.Pid = data["pid"]?.ToObject<int?>();
|
||||
vm.Uptime = data["uptime"]?.ToObject<long?>();
|
||||
vm.CpuCount = data["cpus"]?.ToObject<int?>() ?? vm.CpuCount;
|
||||
vm.MaxMem = data["maxmem"]?.ToObject<long?>() ?? vm.MaxMem;
|
||||
vm.MaxDisk = data["maxdisk"]?.ToObject<long?>() ?? vm.MaxDisk;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the full configuration of a VM.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user