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));
}
}
}
}