using System; using System.Linq; using Newtonsoft.Json.Linq; using PSProxmoxVE.Core.Authentication; using PSProxmoxVE.Core.Client; using PSProxmoxVE.Core.Models.Vms; namespace PSProxmoxVE.Core.Services { /// /// Service for Proxmox VE VM template operations. /// Templates are VMs with the "template" flag set to 1. /// public class TemplateService : PveServiceBase { private readonly VmService _vmService; /// /// Initializes a new instance of the class. /// public TemplateService() { _vmService = new VmService(); } /// /// Initializes a new instance of the class with an injected HTTP client. /// /// The HTTP client to use for API calls. The caller owns its lifetime. public TemplateService(IPveHttpClient client) : base(client) { _vmService = new VmService(client); } /// /// Returns all VM templates. If is null, searches all cluster nodes. /// /// The authenticated PVE session. /// Optional cluster node name to filter templates by node. public PveVm[] GetTemplates(PveSession session, string? node = null) { if (session == null) throw new ArgumentNullException(nameof(session)); var vms = _vmService.GetVms(session, node); return vms.Where(v => v.Template == 1).ToArray(); } /// /// Converts an existing VM into a template. Returns the task UPID. /// /// The authenticated PVE session. /// The cluster node name. /// The VM ID. /// /// The VM must be stopped and must not already be a template. /// Once converted, this operation cannot be reversed via the API. /// public PveTask CreateTemplate(PveSession session, string node, int vmid) { if (session == null) throw new ArgumentNullException(nameof(session)); if (string.IsNullOrWhiteSpace(node)) throw new ArgumentNullException(nameof(node)); return Invoke(session, client => { var response = client.PostAsync($"nodes/{Uri.EscapeDataString(node)}/qemu/{vmid}/template") .GetAwaiter().GetResult(); return ParseTask(response, node); }); } /// /// Removes a VM template (delegates to ). /// /// The authenticated PVE session. /// The cluster node name. /// The VM ID. /// /// If true, also removes all associated backup files and jobs. /// public PveTask RemoveTemplate( PveSession session, string node, int vmid, bool purge = false) { if (session == null) throw new ArgumentNullException(nameof(session)); if (string.IsNullOrWhiteSpace(node)) throw new ArgumentNullException(nameof(node)); return _vmService.RemoveVm(session, node, vmid, purge); } // ------------------------------------------------------------------------- // 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() ?? new PveTask(); task.Node = node; return task; } } }