using System; using System.Collections.Generic; using System.Management.Automation; using PSProxmox.Client; using PSProxmox.Models; using PSProxmox.Session; using PSProxmox.Templates; using PSProxmox.Utilities; namespace PSProxmox.Cmdlets { /// /// Creates a new virtual machine from a template in Proxmox VE. /// The New-ProxmoxVMFromTemplate cmdlet creates a new virtual machine from a template in Proxmox VE. /// /// Create a new VM from a template /// $vm = New-ProxmoxVMFromTemplate -Connection $connection -Node "pve1" -TemplateName "Ubuntu-Template" -Name "web01" -Start /// /// /// Create multiple VMs from a template with a prefix and counter /// $vms = New-ProxmoxVMFromTemplate -Connection $connection -Node "pve1" -TemplateName "Ubuntu-Template" -Prefix "web" -Count 3 -Start /// /// [Cmdlet(VerbsCommon.New, "ProxmoxVMFromTemplate")] [OutputType(typeof(ProxmoxVM))] public class NewProxmoxVMFromTemplateCmdlet : PSCmdlet { /// /// The connection to the Proxmox VE server. /// [Parameter(Mandatory = true, Position = 0)] public ProxmoxConnection Connection { get; set; } /// /// The node to create the VM on. /// [Parameter(Mandatory = true)] public string Node { get; set; } /// /// The name of the template to use. /// [Parameter(Mandatory = true)] public string TemplateName { get; set; } /// /// The name of the VM to create. /// [Parameter(Mandatory = true, ParameterSetName = "SingleVM")] public string Name { get; set; } /// /// The prefix for the VM names when creating multiple VMs. /// [Parameter(Mandatory = true, ParameterSetName = "MultipleVMs")] public string Prefix { get; set; } /// /// The number of VMs to create. /// [Parameter(Mandatory = true, ParameterSetName = "MultipleVMs")] public int Count { get; set; } /// /// The starting index for the VM names when creating multiple VMs. /// [Parameter(Mandatory = false, ParameterSetName = "MultipleVMs")] public int StartIndex { get; set; } = 1; /// /// The VM ID. If not specified, the next available ID will be used. /// [Parameter(Mandatory = false, ParameterSetName = "SingleVM")] public int? VMID { get; set; } /// /// Whether to start the VM after creation. /// [Parameter(Mandatory = false)] public SwitchParameter Start { get; set; } /// /// The IP pool to use for assigning an IP address. /// [Parameter(Mandatory = false)] public string IPPool { get; set; } /// /// The amount of memory in MB. If specified, overrides the template value. /// [Parameter(Mandatory = false)] public int? Memory { get; set; } /// /// The number of CPU cores. If specified, overrides the template value. /// [Parameter(Mandatory = false)] public int? Cores { get; set; } /// /// The disk size in GB. If specified, overrides the template value. /// [Parameter(Mandatory = false)] public int? DiskSize { get; set; } /// /// The storage location for the disk. If specified, overrides the template value. /// [Parameter(Mandatory = false)] public string Storage { get; set; } /// /// The network interface model. If specified, overrides the template value. /// [Parameter(Mandatory = false)] public string NetworkModel { get; set; } /// /// The network bridge. If specified, overrides the template value. /// [Parameter(Mandatory = false)] public string NetworkBridge { get; set; } /// /// The description of the VM. If specified, overrides the template value. /// [Parameter(Mandatory = false)] public string Description { get; set; } /// /// Processes the cmdlet. /// protected override void ProcessRecord() { try { var client = new ProxmoxApiClient(Connection, this); // Get the template ProxmoxVMTemplate template; try { template = TemplateManager.GetTemplate(TemplateName); } catch (Exception ex) { WriteError(new ErrorRecord( new Exception($"Template '{TemplateName}' not found: {ex.Message}"), "TemplateNotFound", ErrorCategory.ObjectNotFound, TemplateName)); return; } // Create VMs if (ParameterSetName == "SingleVM") { // Create a single VM var vm = CreateVMFromTemplate(client, template, Name, VMID); WriteObject(vm); } else { // Create multiple VMs var vms = new List(); for (int i = 0; i < Count; i++) { string vmName = $"{Prefix}{StartIndex + i}"; var vm = CreateVMFromTemplate(client, template, vmName, null); vms.Add(vm); } WriteObject(vms, true); } } catch (Exception ex) { WriteError(new ErrorRecord(ex, "NewProxmoxVMFromTemplateError", ErrorCategory.OperationStopped, Connection)); } } private ProxmoxVM CreateVMFromTemplate(ProxmoxApiClient client, ProxmoxVMTemplate template, string vmName, int? vmId) { // Get the next available VMID if not specified if (!vmId.HasValue) { string response = client.Get("cluster/nextid"); var nextId = JsonUtility.DeserializeResponse(response); vmId = int.Parse(nextId); } // Clone the template VM var parameters = new Dictionary { ["newid"] = vmId.Value.ToString(), ["name"] = vmName }; if (Memory.HasValue) { parameters["memory"] = Memory.Value.ToString(); } if (Cores.HasValue) { parameters["cores"] = Cores.Value.ToString(); } if (DiskSize.HasValue) { parameters["disksize"] = DiskSize.Value.ToString(); } if (!string.IsNullOrEmpty(Storage)) { parameters["storage"] = Storage; } if (!string.IsNullOrEmpty(Description)) { parameters["description"] = Description; } // Clone the VM WriteVerbose($"Creating VM {vmName} from template {template.Name}"); client.Post($"nodes/{template.Node}/qemu/{template.VMID}/clone", parameters); // Get the created VM string vmResponse = client.Get($"nodes/{Node}/qemu/{vmId.Value}/status/current"); var vm = JsonUtility.DeserializeResponse(vmResponse); vm.Node = Node; vm.VMID = vmId.Value; // Update network settings if specified if (!string.IsNullOrEmpty(NetworkModel) || !string.IsNullOrEmpty(NetworkBridge)) { var networkParams = new Dictionary(); string netModel = NetworkModel ?? "virtio"; string netBridge = NetworkBridge ?? "vmbr0"; networkParams["net0"] = $"{netModel},bridge={netBridge}"; client.Put($"nodes/{Node}/qemu/{vmId.Value}/config", networkParams); } // Assign IP if pool is specified if (!string.IsNullOrEmpty(IPPool)) { try { var ipamManager = new IPAM.IPAMManager(); var pool = ipamManager.GetPool(IPPool); var ip = pool.GetNextIP(); WriteVerbose($"Assigned IP {ip} from pool {IPPool} to VM {vmName}"); } catch (Exception ex) { WriteWarning($"Failed to assign IP from pool {IPPool}: {ex.Message}"); } } // Start the VM if requested if (Start.IsPresent) { WriteVerbose($"Starting VM {vmName}"); client.Post($"nodes/{Node}/qemu/{vmId.Value}/status/start", null); // Refresh VM status vmResponse = client.Get($"nodes/{Node}/qemu/{vmId.Value}/status/current"); vm = JsonUtility.DeserializeResponse(vmResponse); vm.Node = Node; vm.VMID = vmId.Value; } return vm; } } }