mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-08-26 04:16:51 +00:00
0c70e11fe8
- CS8604: Use cmdlet's own Node property instead of nullable task.Node in WaitForTask calls across all VM cmdlets - CS8618: Make PveSession.ServerVersion nullable (PveVersion?) since it is set post-construction by PveAuthenticator - CS8603: Add null-forgiving operator where IsNullOrWhiteSpace guards guarantee non-null in PveHttpClient - CS1573: Add XML param documentation to all public service methods - xUnit1012: Make test parameters nullable (string?) for null test cases Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
131 lines
5.5 KiB
C#
131 lines
5.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Newtonsoft.Json.Linq;
|
|
using PSProxmoxVE.Core.Authentication;
|
|
using PSProxmoxVE.Core.Client;
|
|
using PSProxmoxVE.Core.Models.Vms;
|
|
|
|
namespace PSProxmoxVE.Core.Services
|
|
{
|
|
/// <summary>
|
|
/// Service for Proxmox VE VM snapshot API operations.
|
|
/// All operations apply to QEMU/KVM VMs via the /nodes/{node}/qemu/{vmid}/snapshot endpoints.
|
|
/// </summary>
|
|
public class SnapshotService
|
|
{
|
|
/// <summary>
|
|
/// Returns all snapshots for a VM.
|
|
/// </summary>
|
|
/// <param name="session">The authenticated PVE session.</param>
|
|
/// <param name="node">The cluster node name.</param>
|
|
/// <param name="vmid">The VM ID.</param>
|
|
public PveSnapshot[] GetSnapshots(PveSession session, string node, int vmid)
|
|
{
|
|
if (session == null) throw new ArgumentNullException(nameof(session));
|
|
if (string.IsNullOrWhiteSpace(node)) throw new ArgumentNullException(nameof(node));
|
|
|
|
using var client = new PveHttpClient(session);
|
|
var response = client.GetAsync($"nodes/{node}/qemu/{vmid}/snapshot")
|
|
.GetAwaiter().GetResult();
|
|
var data = JObject.Parse(response)["data"];
|
|
return data?.ToObject<PveSnapshot[]>() ?? Array.Empty<PveSnapshot>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a snapshot of a VM. Returns the task UPID.
|
|
/// </summary>
|
|
/// <param name="session">The authenticated PVE session.</param>
|
|
/// <param name="node">The cluster node name.</param>
|
|
/// <param name="vmid">The VM ID.</param>
|
|
/// <param name="snapname">Snapshot name (alphanumeric, no spaces).</param>
|
|
/// <param name="description">Optional description.</param>
|
|
/// <param name="vmstate">Whether to save VM RAM state (live snapshot). Default false.</param>
|
|
public PveTask CreateSnapshot(
|
|
PveSession session,
|
|
string node,
|
|
int vmid,
|
|
string snapname,
|
|
string? description = null,
|
|
bool vmstate = false)
|
|
{
|
|
if (session == null) throw new ArgumentNullException(nameof(session));
|
|
if (string.IsNullOrWhiteSpace(node)) throw new ArgumentNullException(nameof(node));
|
|
if (string.IsNullOrWhiteSpace(snapname)) throw new ArgumentNullException(nameof(snapname));
|
|
|
|
var formData = new Dictionary<string, string>
|
|
{
|
|
["snapname"] = snapname,
|
|
["vmstate"] = vmstate ? "1" : "0"
|
|
};
|
|
if (!string.IsNullOrEmpty(description))
|
|
formData["description"] = description!;
|
|
|
|
using var client = new PveHttpClient(session);
|
|
var response = client.PostAsync($"nodes/{node}/qemu/{vmid}/snapshot", formData)
|
|
.GetAwaiter().GetResult();
|
|
return ParseTask(response, node);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes a snapshot from a VM. Returns the task UPID.
|
|
/// </summary>
|
|
/// <param name="session">The authenticated PVE session.</param>
|
|
/// <param name="node">The cluster node name.</param>
|
|
/// <param name="vmid">The VM ID.</param>
|
|
/// <param name="snapname">The snapshot name to remove.</param>
|
|
public PveTask RemoveSnapshot(
|
|
PveSession session,
|
|
string node,
|
|
int vmid,
|
|
string snapname)
|
|
{
|
|
if (session == null) throw new ArgumentNullException(nameof(session));
|
|
if (string.IsNullOrWhiteSpace(node)) throw new ArgumentNullException(nameof(node));
|
|
if (string.IsNullOrWhiteSpace(snapname)) throw new ArgumentNullException(nameof(snapname));
|
|
|
|
using var client = new PveHttpClient(session);
|
|
var response = client.DeleteAsync($"nodes/{node}/qemu/{vmid}/snapshot/{snapname}")
|
|
.GetAwaiter().GetResult();
|
|
return ParseTask(response, node);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rolls a VM back to a snapshot. Returns the task UPID.
|
|
/// </summary>
|
|
/// <param name="session">The authenticated PVE session.</param>
|
|
/// <param name="node">The cluster node name.</param>
|
|
/// <param name="vmid">The VM ID.</param>
|
|
/// <param name="snapname">The snapshot name to roll back to.</param>
|
|
public PveTask RollbackSnapshot(
|
|
PveSession session,
|
|
string node,
|
|
int vmid,
|
|
string snapname)
|
|
{
|
|
if (session == null) throw new ArgumentNullException(nameof(session));
|
|
if (string.IsNullOrWhiteSpace(node)) throw new ArgumentNullException(nameof(node));
|
|
if (string.IsNullOrWhiteSpace(snapname)) throw new ArgumentNullException(nameof(snapname));
|
|
|
|
using var client = new PveHttpClient(session);
|
|
var response = client.PostAsync($"nodes/{node}/qemu/{vmid}/snapshot/{snapname}/rollback")
|
|
.GetAwaiter().GetResult();
|
|
return ParseTask(response, node);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Private helpers
|
|
// -------------------------------------------------------------------------
|
|
|
|
private static PveTask ParseTask(string response, string node)
|
|
{
|
|
var data = JObject.Parse(response)["data"];
|
|
if (data?.Type == JTokenType.String)
|
|
return new PveTask { Upid = data.ToString(), Node = node };
|
|
|
|
var task = data?.ToObject<PveTask>() ?? new PveTask();
|
|
task.Node = node;
|
|
return task;
|
|
}
|
|
}
|
|
}
|