HVTools.psm1
<#
.SYNOPSIS PowerShell module for managing Hyper-V virtual machines across multiple hosts. .DESCRIPTION Posh-HVTools provides a comprehensive set of functions for creating, managing, and monitoring Hyper-V virtual machines across multiple Hyper-V hosts. The module simplifies common Hyper-V administration tasks such as: - Creating new virtual machines - Retrieving detailed VM information - Managing VM state (start, stop, restart) - Configuring boot devices - Managing virtual disks - Cleaning up VMs and disks .NOTES File Name : HVTools.psm1 Prerequisite : PowerShell 5.1 or later Hyper-V PowerShell module installed Administrative rights on Hyper-V hosts Configuration : Requires HVparam.xml file in the same directory .EXAMPLE # List all VMs matching a pattern across all Hyper-V hosts Get-HVMachineInfo -MachineName "Web*" .EXAMPLE # Create a new virtual machine New-HVMachine -MachineName "WebServer01" -HVServer "HyperVHost1" -RAM 8GB -NumCPU 4 .LINK https://github.com/yourusername/Posh-HVTools #> <# .SYNOPSIS Creates a new Hyper-V virtual machine. .DESCRIPTION Creates a new Generation 2 Hyper-V virtual machine with specified configuration parameters. The function handles virtual machine creation, processor assignment, memory allocation, virtual hard disk creation, and network configuration. .PARAMETER MachineName The name of the virtual machine to create. .PARAMETER HVServer The Hyper-V server to create the virtual machine on. .PARAMETER RAM The amount of RAM to allocate to the virtual machine. Default is 4 Gigabyte. The parameter is written in how many GB the machine should have. I.e. 8 = 8 Gigabyte .PARAMETER Switchname The name of the virtual switch to connect the virtual machine to. If not specified, uses the default switch name from the configuration. .PARAMETER NumCPU The number of virtual processors to assign to the virtual machine. Default is 2. .PARAMETER NotDynamicRam If specified, enables dynamic memory for the virtual machine. .PARAMETER MemoryMinimum The minimum memory for the virtual machine when using dynamic memory. Default is 1468006400 bytes. .PARAMETER HDSize The size of the virtual hard disk. Default is 32GB. .PARAMETER HDPath The path where the virtual hard disk will be stored. If not specified, uses the default disk path from the configuration. .PARAMETER AutomaticCheckPoints If specified, enables automatic checkpoints for the virtual machine. .PARAMETER VlanId The VLAN ID to assign to the virtual machine's network adapter. .EXAMPLE New-HVMachine -MachineName "TestVM" -HVServer "HyperVHost1" Creates a new virtual machine named "TestVM" on the Hyper-V server "HyperVHost1" with default settings. .EXAMPLE New-HVMachine -MachineName "TestVM" -HVServer "HyperVHost1" -RAM 8GB -NumCPU 4 -VlanId 10 Creates a new virtual machine with 8GB RAM, 4 virtual processors, and VLAN ID 10. .NOTES This function requires administrative privileges and the Hyper-V role installed. #> Function New-HVMachine { Param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $MachineName, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $HVServer, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [System.Int64] $RAM = 4, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $Switchname, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [int] $NumCPU = 2, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [switch] $NotDynamicRam, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [int] $MemoryMinimum = 1468006400, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $HDSize = [System.UInt64]32GB, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $HDPath, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [switch] $AutomaticCheckPoints, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [int] $VlanId ) begin {} process { $xml = Get-XMLConfig if (!($Switchname)) { $Switchname = $xml.config.Switchname } if (!($HDPath)) { $HDPath = $xml.config.Diskpaths.Diskpath[0] } $ProgressValue = 20 Write-Progress -Activity "Creating" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue New-VM -Name $MachineName -Generation 2 -MemoryStartupBytes ([system.int64]$RAM*1024*1024*1024) -SwitchName $Switchname -ComputerName $HVServer | Out-Null $ProgressValue = 40 Write-Progress -Activity "Creating" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue Set-VMProcessor -VMName $MachineName -Count $NumCPU -ComputerName $HVServer if ($NotDynamicRam) { Set-VM -VMName $MachineName -DynamicMemory -ComputerName $HVServer } $ProgressValue = 60 Write-Progress -Activity "Creating" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue set-vm -VMName $MachineName -MemoryMinimumBytes $MemoryMinimum -ComputerName $HVServer $VHD = Join-Path -Path $HDPath -ChildPath "$MachineName.vhdx" New-VHD -Path $VHD -SizeBytes $HDSize -Dynamic -ComputerName $HVServer | Out-Null $ProgressValue = 80 Write-Progress -Activity "Creating" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue Add-VMHardDiskDrive -Path $VHD -VMName $MachineName -ComputerName $HVServer $ProgressValue = 95 Write-Progress -Activity "Creating" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue if (!($AutomaticCheckPoints)) { set-vm -VMName $MachineName -AutomaticCheckpointsEnabled:$false -ComputerName $HVServer } if ($VlanId) { get-vmnetworkAdapter -VMname $MachineName -ComputerName $HVServer | set-VMNetworkAdapterVlan -Access -VlanId $VlanId } Start-VM -VMName $MachineName -ComputerName $hvserver Start-Sleep -Seconds 2 stop-VM -VMName $MachineName -ComputerName $hvserver -Force Get-HVMachineInfo -MachineName $MachineName -HVServer $HVServer } end {} } <# .SYNOPSIS Retrieves detailed information about Hyper-V virtual machines. .DESCRIPTION Gets comprehensive information about one or more Hyper-V virtual machines, including hardware configuration, network settings, disk information, and Hyper-V host details. .PARAMETER MachineName The name or pattern of the virtual machine(s) to retrieve information for. If empty, retrieves information for all virtual machines. .PARAMETER HVServers An array of Hyper-V server names to query. If not specified, uses servers from the configuration. .EXAMPLE Get-HVMachineInfo -MachineName "TestVM" Retrieves information about the virtual machine named "TestVM" from all configured Hyper-V servers. .EXAMPLE Get-HVMachineInfo -MachineName "Test" -HVServers @("HyperVHost1", "HyperVHost2") Retrieves information about all virtual machines with "Test" in their name from the specified Hyper-V servers. .NOTES Returns a collection of HVMachineInfo objects containing detailed virtual machine information. #> function Get-HVMachineInfo { Param( [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $MachineName = '', [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [array] $HVServers ) begin{} process { if (!($HVServers)) { $xml = Get-XMLConfig $HVServers = $xml.config.Servers.Server } [int]$ProgressValue = 0 [int]$ProgressPerHVServer = 100 / $HVServers.Count [int]$HVServerCount = 0 $MachineInfo = New-Object 'System.Collections.Generic.List[HVMachineInformation]' foreach ($HVServer in $HVServers) { $AllHV = get-vm -ComputerName $HVServer | Where-Object {$_.VMName -match $MachineName} [int]$AllHVCount = $AllHV.count [int]$HVMachineCount = 1 if ($AllHVCount -ne 0) { [int]$ProgressPerHV = $ProgressPerHVServer / $AllHVCount foreach ($HVName in ($AllHV).Name) { [float]$HVProgressValue = $HVServerCount * 100 / $HVServers.Count + $HVMachineCount * 100 / $HVServers.Count / $AllHVCount "procent: $HVProgressValue" Write-Progress -Activity "Processing" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue $ProgressValue += $ProgressPerHV $HVMachineCount++ $NIC = get-vmnetworkAdapter -VMname $HVName -ComputerName $HVServer $HVMachineInfo = get-vm -Name $HVName -ComputerName $HVServer | Select-Object Name, State, CPUUsage, ProcessorCount, MemoryAssigned, Uptime, Status, Version, Generation $HVHostInfo = get-vmhost -ComputerName $HVServer | Select-Object ComputerName, LogicalProcessorCount, MemoryCapacity $Gen = $HVMachineInfo.Generation switch ($Gen) { "1" { $BootOrder = (Get-VMBios -VMName $HVName -ComputerName $HVServer).StartupOrder } "2" { $BootOrder = (get-vmfirmware -VMName $HVName -ComputerName $HVServer).bootorder.BootType } } $HardDisk = (get-vmhardDiskDrive -VMName $HVName -ComputerName $HVServer).Path [bool]$HasCheckPoint = $false foreach ($EachHardDisk in $HardDisk) { if ((Get-VHD -Path $EachHardDisk -ComputerName $HVServer).ParentPath) { $HasCheckPoint = $true } } $Machine = [HVMachineInformation]::new( $HVMachineInfo.Name, $HVMachineInfo.State, $HVMachineInfo.CPUUsage, $HVMachineInfo.ProcessorCount, $HVMachineInfo.MemoryAssigned, $NIC.SwitchName, $NIC.VlanSetting.AccessVlanId, $NIC.IPaddresses, (Get-MACFormatted -Mac $NIC.macaddress), $HardDisk, $HasCheckPoint, $BootOrder, $HVMachineInfo.Uptime, $HVMachineInfo.Status, $HVMachineInfo.Version, $Gen, $HVHostInfo.ComputerName, $HVHostInfo.LogicalProcessorCount, $HVHostInfo.MemoryCapacity ) $MachineInfo.Add($Machine) } } $HVServerCount++ } return $MachineInfo } end {} } <# .SYNOPSIS Retrieves network information about Hyper-V virtual machines. .DESCRIPTION Gets detailed network configuration information for one or more Hyper-V virtual machines, including switch names, IP addresses, MAC addresses, VLAN settings, and operation modes. .PARAMETER MachineName The name or pattern of the virtual machine(s) to retrieve network information for. If empty, retrieves network information for all virtual machines. .PARAMETER HVServers An array of Hyper-V server names to query. If not specified, uses servers from the configuration. .EXAMPLE Get-HVMachineNetworkInfo -MachineName "TestVM" Retrieves network information for the virtual machine named "TestVM" from all configured Hyper-V servers. .EXAMPLE Get-HVMachineNetworkInfo -MachineName "Web" -HVServers @("HyperVHost1", "HyperVHost2") Retrieves network information for all virtual machines with "Web" in their name from the specified Hyper-V servers. .NOTES Returns a collection of HVNetworkInfo objects containing network configuration details. #> function Get-HVMachineNetworkInfo { Param( [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $MachineName = '', [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [array] $HVServers ) begin{} process { if (!($HVServers)) { $xml = Get-XMLConfig $HVServers = $xml.config.Servers.Server } [int]$ProgressValue = 0 [int]$ProgressPerHVServer = 100 / $HVServers.Count $NetworkInfo = New-Object 'System.Collections.Generic.List[HVNetworkInfo]' foreach ($HVServer in $HVServers) { $AllHV = get-vm -ComputerName $HVServer | Where-Object {$_.VMName -match $MachineName} [int]$AllHVCount = $AllHV.count if ($AllHVCount -ne 0) { [int]$ProgressPerHV =$ProgressPerHVServer / $AllHVCount foreach ($HVName in ($AllHV).Name) { Write-Progress -Activity "Processing" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue $AllNics = get-vmnetworkAdapter -VMname $HVName -ComputerName $HVServer foreach ($Nic in $AllNics) { $Network = [HVNetworkInfo]::new( $HVName, $NIC.SwitchName, $NIC.IPaddresses, (Get-MACFormatted -Mac $NIC.macaddress), $NIC.VlanSetting.OperationMode, $NIC.VlanSetting.AccessVlanId ) $NetworkInfo.Add($Network) } $ProgressValue += $ProgressPerHV } } } return $NetworkInfo } end {} } <# .SYNOPSIS Configures the boot device for a Hyper-V virtual machine. .DESCRIPTION Sets the boot device and boot order for a Generation 1 or Generation 2 Hyper-V virtual machine. The function supports configuring network, DVD, hard drive, file, or floppy boot devices. .PARAMETER MachineName The name of the virtual machine to configure. .PARAMETER HVServer The Hyper-V server where the virtual machine is located. .PARAMETER HVServers An array of Hyper-V servers to search for the virtual machine. .PARAMETER nic If specified, sets the network adapter as the primary boot device. .PARAMETER dvd If specified, sets the DVD drive as the primary boot device. .PARAMETER File If specified, sets the file as the primary boot device (Generation 2 VMs only). .PARAMETER Floppy If specified, sets the floppy drive as the primary boot device (Generation 1 VMs only). .PARAMETER Drive If specified, sets the hard drive as the primary boot device (Generation 2 VMs only). .EXAMPLE Set-HVMachineBootDevice -MachineName "TestVM" -HVServer "HyperVHost1" -nic Configures the virtual machine "TestVM" to boot from the network adapter. .EXAMPLE Set-HVMachineBootDevice -MachineName "TestVM" -HVServer "HyperVHost1" -dvd Configures the virtual machine "TestVM" to boot from the DVD drive. .NOTES The function automatically determines the VM generation and applies the appropriate boot configuration. #> function Set-HVMachineBootDevice { Param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $MachineName, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $HVServer, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [array] $HVServers, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'NIC')] [switch] $nic, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DVD')] [switch] $dvd, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'File')] [switch] $File, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Floppy')] [switch] $Floppy, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Drive')] [switch] $Drive ) begin{} process{ $HVServers = Get-HVServers -MachineName $MachineName -HVServer $HVServer -HVServers $HVServers foreach ($HVServer in $HVServers) { foreach ($Machine in (get-vm -ComputerName $HVServer | Where-Object {$_.Name -eq $MachineName})) { $FoundMachineName = $Machine.VMName switch ($machine.generation) { "1" { $StartupOrder = '' if ($nic) { $StartupOrder = @("LegacyNetworkAdapter", "Floppy", "CD", "IDE") } if ($dvd) { $StartupOrder = @("CD", "LegacyNetworkAdapter", "Floppy", "IDE") } if ($File) { $StartupOrder = @("IDE","LegacyNetworkAdapter", "Floppy", "CD") } if ($Floppy) { $StartupOrder = @("Floppy", "LegacyNetworkAdapter", "CD", "IDE") } Set-VMBios -VMName $FoundMachineName -ComputerName $HVServer -StartupOrder $StartupOrder Get-VMBios -VMName $FoundMachineName -ComputerName $HVServer } "2"{ if ($nic) { $BootDevice = Get-VMNetworkAdapter -VMName $FoundMachineName -ComputerName $HVServer } if ($dvd) { $BootDevice = Get-VMDvdDrive -VMName $FoundMachineName -ComputerName $HVServer } if ($File) { $BootDevice = (get-vmfirmware -VMName $FoundMachineName -ComputerName $HVServer).BootOrder | Where-Object {$_.BootType -eq 'File'} } if ($Drive) { $BootDevice = (get-vmfirmware -VMName $FoundMachineName -ComputerName $HVServer).BootOrder | Where-Object {$_.BootType -eq 'Drive'} } Set-VMFirmware -VMName $FoundMachineName -FirstBootDevice ($BootDevice) -ComputerName $HVServer get-vmfirmware -VMName $FoundMachineName -ComputerName $HVServer | Select-Object -ExpandProperty BootOrder } } } } } end {} } <# .SYNOPSIS Removes a Hyper-V virtual machine and its associated virtual hard disks. .DESCRIPTION Removes a Hyper-V virtual machine and all associated virtual hard disks, including any differencing disks or checkpoints. The function first stops the virtual machine, identifies all disk files, removes them, and then deletes the virtual machine. .PARAMETER MachineName The name of the virtual machine to remove. .PARAMETER HVServer The Hyper-V server where the virtual machine is located. .PARAMETER HVServers An array of Hyper-V servers to search for the virtual machine. .EXAMPLE Remove-HVMachine -MachineName "TestVM" -HVServer "HyperVHost1" Removes the virtual machine "TestVM" and its associated disks from the Hyper-V server "HyperVHost1". .NOTES This operation is destructive and cannot be undone. All virtual hard disks associated with the virtual machine will be permanently deleted. #> function Remove-HVMachine { Param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $MachineName, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $HVServer, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [array] $HVServers ) begin{} process { $HVServers = Get-HVServers -MachineName $MachineName -HVServer $HVServer -HVServers $HVServers [int]$ProgressValue = 0 Write-Progress -Activity "Processing" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue foreach ($HVServer in $HVServers) { [int]$ProgressValue = 25 Write-Progress -Activity "Processing" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue Stop-VM -Name $MachineName -ComputerName $HVServer -ErrorAction Ignore -WarningAction SilentlyContinue -Force | Out-Null $Disks = Get-VMHardDiskDrive -VMName $MachineName -ComputerName $HVServer $DisksToRemove = @() [int]$ProgressValue = 50 Write-Progress -Activity "Processing" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue foreach ($disk in $disks.path) { $DisksToRemove += $disk $vhd = (Get-VHD -Path $disk -ComputerName $HVServer).ParentPath if ($vhd) { $DisksToRemove += $vhd do { $vhd = (Get-VHD -Path $vhd -ComputerName $HVServer).ParentPath if ($vhd) { $DisksToRemove += $vhd } } while ($vhd) } } [int]$ProgressValue = 60 Write-Progress -Activity "Processing" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue foreach ($disk in $DisksToRemove) { $DiskSplit = $disk.split(':') $UNCPath = "\\$HVServer\$($DiskSplit[0])`$$($DiskSplit[1])" Remove-Item -Path $UNCPath -Force } [int]$ProgressValue = 80 Write-Progress -Activity "Processing" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue remove-vm -Name $MachineName -ComputerName $HVServer -Force } } end {} } <# .SYNOPSIS Identifies unassigned virtual hard disks on Hyper-V servers. .DESCRIPTION Scans the specified Hyper-V servers and disk paths to identify virtual hard disks and their association with virtual machines. This helps identify orphaned or unassigned disk files that may be candidates for cleanup. .PARAMETER DiskDrivePath The path to search for virtual hard disks. If not specified, uses paths from the configuration. .PARAMETER HVServers An array of Hyper-V servers to scan. If not specified, uses servers from the configuration. .EXAMPLE Get-HVUnassignedDiskDrive Scans all configured Hyper-V servers and disk paths for unassigned virtual hard disks. .EXAMPLE Get-HVUnassignedDiskDrive -HVServers @("HyperVHost1") -DiskDrivePath "D:\VirtualMachines" Scans the specified server and disk path for unassigned virtual hard disks. .NOTES Returns a collection of HVDiskInfo objects containing disk paths and their association status. #> function Get-HVUnassignedDiskDrive { Param( [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $DiskDrivePath, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [array] $HVServers ) begin{} process { $xml = Get-XMLConfig if (!($HVServers)) { $HVServers = $xml.config.Servers.Server } if (!($DiskDrivePath)) { $DiskDrivePaths = $xml.config.Diskpaths.Diskpath } [int]$ProgressValue = 0 [int]$ProgressPerHVServer = 100 / $HVServers.Count $DiskInfo = New-Object 'System.Collections.Generic.List[HVDiskInfo]' foreach ($HVServer in $HVServers) { [int]$DiskDriveCount = 0 foreach ($DiskDrivePath in $DiskDrivePaths) { $DiskSplit = $DiskDrivePath.split(':') $UNCPath = "\\$HVServer\$($DiskSplit[0])`$$($DiskSplit[1])" if (Test-Path -Path $UNCPath) { $DiskDriveCount += 1 } } if ($DiskDriveCount -gt 0) { foreach ($DiskDrivePath in $DiskDrivePaths) { $DiskSplit = $DiskDrivePath.split(':') $UNCPath = "\\$HVServer\$($DiskSplit[0])`$$($DiskSplit[1])" if (Test-Path -Path $UNCPath) { $HardDrives = (get-childitem -Path $UNCPath).FullName $AllHV = get-vm -ComputerName $HVServer [int]$AllDiskCount = $HardDrives.count [int]$ProgressPerDisk = $ProgressPerHVServer / $AllDiskCount / $DiskDriveCount foreach ($HardDrive in $HardDrives) { Write-Progress -Activity "Processing" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue $UNCDiskSplit = $HardDrive.split('$') $LocalDiskPath = "$($UNCDiskSplit[0][-1]):$($UNCDiskSplit[1])" $Outcome = "Not Assigned" [bool]$Match = $false foreach ($vm in $AllHV) { foreach ($VMDisk in (Get-VMHardDiskDrive -VMName $vm.name -ComputerName $HVServer).Path) { if ($VMDisk -eq $LocalDiskPath -and !($Match)) { $Outcome = $vm.Name $Match = $true } } } $ProgressValue += $ProgressPerDisk $Disk = [HVDiskInfo]::new( $HVServer, $LocalDiskPath, $Outcome ) $DiskInfo.add($Disk) } } } } } Return $DiskInfo } end {} } <# .SYNOPSIS Loads the module configuration from the XML file. .DESCRIPTION Retrieves the configuration settings from the HVparam.xml file located in the same directory as the module. This configuration contains Hyper-V server names, default disk paths, and other module settings. .EXAMPLE $config = Get-XMLConfig Loads the module configuration. .NOTES Internal helper function used by other module functions. #> function Get-XMLConfig { $xmlFilePath = Join-Path -Path $PSScriptRoot -ChildPath "HVparam.xml" Return [xml](Get-Content -Path $xmlFilePath) } <# .SYNOPSIS Resolves the Hyper-V servers for a virtual machine operation. .DESCRIPTION Determines which Hyper-V servers to use for a virtual machine operation based on the provided parameters. Returns a server name or an array of server names. .PARAMETER MachineName The name of the virtual machine to operate on. .PARAMETER HVServer A specific Hyper-V server to use. .PARAMETER HVServers An array of Hyper-V servers to use. .EXAMPLE $servers = Get-HVServers -MachineName "TestVM" -HVServer "HyperVHost1" Returns the specified Hyper-V server. .NOTES Internal helper function used by other module functions. #> function Get-HVServers { Param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $MachineName, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $HVServer, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [array] $HVServers ) if ($HVServer) { $HVServers = $HVServer } if (!($HVServers)) { $HVServers = Find-HVServers -MachineName $MachineName -ExactMatch } return $HVServers } <# .SYNOPSIS Finds Hyper-V servers hosting a specific virtual machine. .DESCRIPTION Searches through configured Hyper-V servers to find those hosting a virtual machine with the specified name or matching a pattern. .PARAMETER MachineName The name or pattern of the virtual machine to find. .PARAMETER ExactMatch If specified, requires an exact match of the virtual machine name. Otherwise, uses a pattern match. .EXAMPLE Find-HVServers -MachineName "TestVM" -ExactMatch Finds Hyper-V servers hosting a virtual machine named exactly "TestVM". .NOTES Internal helper function used by other module functions. #> Function Find-HVServers { Param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $MachineName, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [switch] $ExactMatch ) $xml = Get-XMLConfig $HVServers = $xml.config.Servers.Server $ReturnHVServers = @() [int]$ProgressValue = 0 [int]$ProgressPerHV = 100 / $HVServers.count [bool]$FoundMachine = $false foreach ($HVServer in $HVServers) { Write-Progress -Activity "Processing" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue if ($ExactMatch) { $FoundMachine = get-vm -ComputerName $HVServer | Where-Object {$_.Name -eq $MachineName} } else { $FoundMachine = get-vm -ComputerName $HVServer | Where-Object {$_.Name -match $MachineName} } if ($FoundMachine) { $ReturnHVServers += $HVServer } $ProgressValue += $ProgressPerHV } return $ReturnHVServers } <# .SYNOPSIS Formats a MAC address with colon separators. .DESCRIPTION Converts a MAC address to the standard format with colon separators between each octet. .PARAMETER Mac The MAC address to format. .EXAMPLE Get-MACFormatted -Mac "0123456789AB" Returns "01:23:45:67:89:AB" .NOTES Internal helper function used by other module functions. #> Function Get-MACFormatted { Param( [Parameter(Mandatory = $true)] [array] $Mac ) return $Mac -replace '(.{2})(?!$)', '$1:' } <# .SYNOPSIS Changes the state of a Hyper-V virtual machine. .DESCRIPTION Performs a state change operation (start, stop, or restart) on a virtual machine. .PARAMETER MachineName The name of the virtual machine to operate on. .PARAMETER HVServer The Hyper-V server where the virtual machine is located. .PARAMETER Action The action to perform: "Start", "Stop", or "Restart". .EXAMPLE Set-HVMachineState -MachineName "TestVM" -HVServer "HyperVHost1" -Action "Start" Starts the virtual machine "TestVM" on the Hyper-V server "HyperVHost1". .NOTES Internal helper function used by the state management functions. #> Function Set-HVMachineState { Param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $MachineName, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $HVServer, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [ValidateSet ("Stop", "Restart", "Start")] [string] $Action ) begin{} process { switch ($Action) { "Stop" { Stop-VM -ComputerName $HVServer -Name $MachineName -Force } "Restart" { Restart-VM -ComputerName $HVServer -Name $MachineName -Force } "Start" { Start-VM -ComputerName $HVServer -Name $MachineName } } } end {} } <# .SYNOPSIS Stops a Hyper-V virtual machine. .DESCRIPTION Forcibly stops a virtual machine on one or more Hyper-V servers. .PARAMETER MachineName The name of the virtual machine to stop. .PARAMETER HVServer The Hyper-V server where the virtual machine is located. .PARAMETER HVServers An array of Hyper-V servers to search for the virtual machine. .EXAMPLE Stop-HVMachine -MachineName "TestVM" -HVServer "HyperVHost1" Stops the virtual machine "TestVM" on the Hyper-V server "HyperVHost1". .NOTES This is a forceful shutdown equivalent to pulling the power cord. #> function Stop-HVMachine { Param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $MachineName, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $HVServer, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [array] $HVServers ) begin{} process { $HVServers = Get-HVServers -MachineName $MachineName -HVServer $HVServer -HVServers $HVServers foreach ($HVServer in $HVServers) { Set-HVMachineState -MachineName $MachineName -HVServer $HVServer -Action Stop } } end {} } <# .SYNOPSIS Restarts a Hyper-V virtual machine. .DESCRIPTION Forcibly restarts a virtual machine on one or more Hyper-V servers. .PARAMETER MachineName The name of the virtual machine to restart. .PARAMETER HVServer The Hyper-V server where the virtual machine is located. .PARAMETER HVServers An array of Hyper-V servers to search for the virtual machine. .EXAMPLE Restart-HVMachine -MachineName "TestVM" -HVServer "HyperVHost1" Restarts the virtual machine "TestVM" on the Hyper-V server "HyperVHost1". .NOTES This is a forceful restart. #> function Restart-HVMachine { Param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $MachineName, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $HVServer, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [array] $HVServers ) begin{} process { $HVServers = Get-HVServers -MachineName $MachineName -HVServer $HVServer -HVServers $HVServers foreach ($HVServer in $HVServers) { Set-HVMachineState -MachineName $MachineName -HVServer $HVServer -Action Restart } } end {} } <# .SYNOPSIS Starts a Hyper-V virtual machine. .DESCRIPTION Starts a virtual machine on one or more Hyper-V servers. .PARAMETER MachineName The name of the virtual machine to start. .PARAMETER HVServer The Hyper-V server where the virtual machine is located. .PARAMETER HVServers An array of Hyper-V servers to search for the virtual machine. .EXAMPLE Start-HVMachine -MachineName "TestVM" -HVServer "HyperVHost1" Starts the virtual machine "TestVM" on the Hyper-V server "HyperVHost1". #> function Start-HVMachine { Param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $MachineName, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $HVServer, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [array] $HVServers ) begin {} process { $HVServers = Get-HVServers -MachineName $MachineName -HVServer $HVServer -HVServers $HVServers foreach ($HVServer in $HVServers) { Set-HVMachineState -MachineName $MachineName -HVServer $HVServer -Action Start } } end {} } function Get-HVServerInfo { Param( [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [string] $HVServer ) begin{} process { if (!($HVServer)) { $xml = Get-XMLConfig $HVServers = $xml.config.Servers.Server } else { $HVServers = $HVServer } $HVServerInfo = New-Object 'System.Collections.Generic.List[HVServerInformation]' [float]$progressvalue = 0 [int]$progresscount = 0 foreach ($HVServer in $HVServers) { Write-Progress -Activity "Processing" -Status "$ProgressValue% complete" -PercentComplete $ProgressValue $progresscount ++ $progressvalue = [math]::round($progresscount * 100 / $HVServers.count,1) $SrvInfo1 = get-vmhost -ComputerName $HVServer $SrvInfo2 = Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName $HVServer | Select-Object PSComputerName, LastBootUpTime, @{Name='Uptime'; Expression={(Get-Date) - $_.LastBootUpTime}}, FreePhysicalMemory $SrvInfo3 = Get-CimInstance -ClassName Win32_LogicalDisk -ComputerName $HVServer -Filter "DriveType=3" | Select-Object DeviceID, @{Name='Size'; Expression={[math]::Round($_.Size/1GB, 2)}}, @{Name='FreeSpace'; Expression={[math]::Round($_.FreeSpace/1GB, 2)}} $Machine = [HVServerInformation]::new( $SrvInfo1.ComputerName, $SrvInfo3.DeviceID, $SrvInfo3.Size, $SrvInfo3.FreeSpace, $SrvInfo1.LogicalProcessorCount, $SrvInfo1.MemoryCapacity, $SrvInfo2.FreePhysicalMemory, $SrvInfo2.LastBootUpTime, $SrvInfo2.Uptime ) $HVServerInfo.Add($Machine) } return $HVServerInfo } end {} } # Class Definitions <# .SYNOPSIS Class for storing detailed Hyper-V virtual machine information. .DESCRIPTION Represents comprehensive information about a Hyper-V virtual machine, including its configuration, state, network settings, and host information. .NOTES Used by Get-HVMachineInfo to return structured information about virtual machines. #> Class HVMachineInformation { [string]$MachineName [string]$State [int]$CPUUsage [int]$CPUCount [UInt64]$MemoryAssigned [array]$SwitchName [array]$Vlan [array]$IPaddresses [array]$MACAddress [array]$HardDisk [bool]$Checkpoint [array]$BootInfo [timespan]$Uptime [string]$Status [string]$Version [string]$Generation [string]$HVServer [int]$LogicalProcessorCount [UInt64]$MemoryCapacity HVMachineInformation ( [string]$MachineName, [string]$State, [int]$CPUUsage, [int]$CPUCount, [UInt64]$MemoryAssigned, [array]$SwitchName, [array]$VLan, [array]$IPaddresses, [array]$MACAddress, [array]$HardDisk, [bool]$Checkpoint, [array]$BootInfo, [timespan]$Uptime, [string]$Status, [string]$Version, [string]$Generation, [string]$HVServer, [int]$LogicalProcessorCount, [UInt64]$MemoryCapacity ) { $this.MachineName = $MachineName $this.State = $State $this.CPUUsage = $CPUUsage $this.CPUCount = $CPUCount $this.MemoryAssigned = $MemoryAssigned $this.SwitchName = $SwitchName $this.Vlan = $VLan $this.IPaddresses = $IPaddresses $this.MacAddress = $MACAddress $this.HardDisk = $HardDisk $this.Checkpoint = $Checkpoint $this.BootInfo = $BootInfo $this.Uptime = $Uptime $this.Status = $Status $this.Version = $Version $this.Generation = $Generation $this.HVServer = $HVServer $this.LogicalProcessorCount = $LogicalProcessorCount $this.MemoryCapacity = $MemoryCapacity } } Class HVServerInformation { [string]$HVServer [array]$HardDisk [array]$HardDiskSize [array]$HardDiskFree [int]$LogicalProcessorCount [UInt64]$MemoryCapacity [UInt64]$FreePhysicalMemory [datetime]$LastBootUpTime [timespan]$Uptime HVServerInformation ( [string]$HVServer, [array]$HardDisk, [array]$HardDiskSize, [array]$HardDiskFree, [int]$LogicalProcessorCount, [UInt64]$MemoryCapacity, [UInt64]$FreePhysicalMemory, [datetime]$LastBootUpTime, [timespan]$Uptime ) { $this.HVServer = $HVServer $this.HardDisk = $HardDisk $this.HardDiskSize = $HardDiskSize $this.HardDiskFree = $HardDiskFree $this.LogicalProcessorCount = $LogicalProcessorCount $this.MemoryCapacity = $MemoryCapacity $this.FreePhysicalMemory = $FreePhysicalMemory $this.LastBootUpTime = $LastBootUpTime $this.Uptime = $Uptime } } <# .SYNOPSIS Class for storing Hyper-V disk information. .DESCRIPTION Represents information about a virtual hard disk file, including its location and associated virtual machine (if any). .NOTES Used by Get-HVUnassignedDiskDrive to return structured information about virtual disks. #> Class HVDiskInfo { [string]$HVServer [string]$Diskname [string]$MachineName HVDiskInfo ( [string]$HVServer, [string]$Diskname, [string]$MachineName ) { $this.HVServer = $HVServer $this.Diskname = $Diskname $this.MachineName = $MachineName } } <# .SYNOPSIS Class for storing Hyper-V network adapter information. .DESCRIPTION Represents detailed network configuration information for a virtual machine network adapter, including IP, MAC, and VLAN settings. .NOTES Used by Get-HVMachineNetworkInfo to return structured information about network adapters. #> Class HVNetworkInfo { [string]$MachineName [string]$SwitchName [array]$IPaddresses [string]$MacAddress [string]$OperationMode [int]$Vlan HVNetworkInfo ( [string]$MachineName, [string]$SwitchName, [array]$IPaddresses, [string]$MacAddress, [string]$OperationMode, [int]$Vlan ) { $this.MachineName = $MachineName $this.SwitchName = $SwitchName $this.IPaddresses = $IPaddresses $this.MacAddress = $MacAddress $this.OperationMode = $OperationMode $this.Vlan = $Vlan } } |