using System; using System.Collections.Generic; using System.Management.Automation; using Newtonsoft.Json; using PSProxmox.Client; using PSProxmox.Models; using PSProxmox.Session; using PSProxmox.Utilities; namespace PSProxmox.Cmdlets { /// /// Creates a new virtual machine in Proxmox VE. /// The New-ProxmoxVM cmdlet creates a new virtual machine in Proxmox VE. /// /// Create a new virtual machine using direct parameters /// $vm = New-ProxmoxVM -Connection $connection -Node "pve1" -Name "test-vm" -Memory 2048 -Cores 2 -DiskSize 32 /// /// /// Create a new virtual machine using a builder /// $builder = New-ProxmoxVMBuilder -Name "web-server" /// $builder.WithMemory(4096).WithCores(2).WithDisk(50, "local-lvm") /// $builder.WithNetwork("virtio", "vmbr0").WithIPConfig("192.168.1.10/24", "192.168.1.1") /// $vm = New-ProxmoxVM -Connection $connection -Node "pve1" -Builder $builder /// /// [Cmdlet(VerbsCommon.New, "ProxmoxVM")] [OutputType(typeof(ProxmoxVM))] public class NewProxmoxVMCmdlet : 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 VM configuration builder. /// [Parameter(Mandatory = true, ParameterSetName = "Builder")] public ProxmoxVMBuilder Builder { get; set; } /// /// The name of the VM. /// [Parameter(Mandatory = true, ParameterSetName = "Direct")] public string Name { get; set; } /// /// The VM ID. If not specified, the next available ID will be used. /// [Parameter(Mandatory = false, ParameterSetName = "Direct")] public int? VMID { get; set; } /// /// The amount of memory in MB. /// [Parameter(Mandatory = false, ParameterSetName = "Direct")] public int Memory { get; set; } = 512; /// /// The number of CPU cores. /// [Parameter(Mandatory = false, ParameterSetName = "Direct")] public int Cores { get; set; } = 1; /// /// The disk size in GB. /// [Parameter(Mandatory = false, ParameterSetName = "Direct")] public int DiskSize { get; set; } = 8; /// /// The storage location for the disk. /// [Parameter(Mandatory = false, ParameterSetName = "Direct")] public string Storage { get; set; } = "local"; /// /// The operating system type. /// [Parameter(Mandatory = false, ParameterSetName = "Direct")] public string OSType { get; set; } = "l26"; // Linux 2.6+ /// /// The network interface model. /// [Parameter(Mandatory = false, ParameterSetName = "Direct")] public string NetworkModel { get; set; } = "virtio"; /// /// The network bridge. /// [Parameter(Mandatory = false, ParameterSetName = "Direct")] public string NetworkBridge { get; set; } = "vmbr0"; /// /// Whether to start the VM after creation. /// [Parameter(Mandatory = false, ParameterSetName = "Direct")] public SwitchParameter Start { get; set; } /// /// The IP pool to use for assigning an IP address. /// [Parameter(Mandatory = false, ParameterSetName = "Direct")] public string IPPool { get; set; } /// /// Processes the cmdlet. /// protected override void ProcessRecord() { try { var client = new ProxmoxApiClient(Connection, this); Dictionary parameters; int vmid; string vmName; string ipPool; bool startVm; // Process based on parameter set if (ParameterSetName == "Builder") { // Use the builder to create parameters if (Builder == null) { throw new PSArgumentNullException(nameof(Builder)); } // Set the node if not already set in the builder if (string.IsNullOrEmpty(Builder.Node)) { Builder.WithNode(Node); } // Get the next available VMID if not specified if (!Builder.VMID.HasValue) { string response = client.Get("cluster/nextid"); var nextId = JsonUtility.DeserializeResponse(response); Builder.WithVMID(int.Parse(nextId)); } // Build the parameters parameters = Builder.Build(); vmid = Builder.VMID.Value; vmName = Builder.Name; ipPool = Builder.IPPool; startVm = Builder.Start; } else // Direct parameters { // 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); } // Create the VM parameters parameters = new Dictionary { ["vmid"] = VMID.Value.ToString(), ["name"] = Name, ["memory"] = Memory.ToString(), ["cores"] = Cores.ToString(), ["ostype"] = OSType, ["net0"] = $"{NetworkModel},bridge={NetworkBridge}" }; // Add disk parameters["ide0"] = $"{Storage}:{DiskSize}"; vmid = VMID.Value; vmName = Name; ipPool = IPPool; startVm = Start.IsPresent; } // Create the VM WriteVerbose($"Creating VM {vmName} on node {Node}"); client.Post($"nodes/{Node}/qemu", parameters); // Get the created VM string vmResponse = client.Get($"nodes/{Node}/qemu/{vmid}/status/current"); var vm = JsonUtility.DeserializeResponse(vmResponse); vm.Node = Node; vm.VMID = vmid; // 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 (startVm) { WriteVerbose($"Starting VM {vmName}"); client.Post($"nodes/{Node}/qemu/{vmid}/status/start", null); // Refresh VM status vmResponse = client.Get($"nodes/{Node}/qemu/{vmid}/status/current"); vm = JsonUtility.DeserializeResponse(vmResponse); vm.Node = Node; vm.VMID = vmid; } WriteObject(vm); } catch (Exception ex) { WriteError(new ErrorRecord(ex, "NewProxmoxVMError", ErrorCategory.OperationStopped, Connection)); } } } }