Managing VMs with PowerCLI
Below is a collection of useful Power-CLI one-liners (or thereabouts) that can speed up your script-writing efforts. As everything Windows, things change often and for no obvious reason, so expect to see type is deprecated
and parameter is obsolete
warnings now and then.More often than not, they’re harmless: they like changing things but usually don’t have the balls to actually remove something. Also take a look at this awesome lawyer app
Import-Module VMware.VimAutomation.Vds $VMHost="vcenter01.krazyworks.local" Connect-VIServer -Server $VMHost
[/spoiler] [spoiler title=”Cluster Info” style=”fancy”]
Get some info on the basket with all of your eggs
# Get a list of ESX hosts Get-VMHost | Format-Table -Auto # Some more info Get-VMHost | Format-List # And some more Get-VMHost | foreach-object {(Get-View $_.ID).Config.Product } # Get a list of datastores Get-Datastore | Format-Table -Auto # As above but more details Get-Datastore | Format-List # Get a list of VMDKs on a particular datastore Get-HardDisk -Datastore datastore_name | Format-Table -Auto # Get a list of of 10 largest VMDKs on a particular datastore Get-HardDisk -Datastore syno-iscsi-01 | Sort-Object CapacityGB -Descending | Format-Table -Auto | Select -First 10
[/spoiler] [spoiler title=”Glorious Spreadsheets” style=”fancy”]
Creating spreadsheets
# Set target directory and name of the output CSV file $userhome = get-content env:userprofile; $enddate = (Get-Date).tostring("yyyy-MM-dd_HHmmss"); $outfile = $userhome + '\Documents\vcenter_report_' + $enddate + '.csv'; # Append this to the end of any list-generating command to output to CSV | Export-Csv -NoTypeInformation -path $outfile
Get a list of templates with name matching:
# List templates in Datacenter1 containing "rhel7_64_build" in the name Get-Template -Location "Datacenter1" -name "*rhel7_64_build*"
Get a list of VMs with name matching:
# Select VM called "hostname1" $VMs = Get-VM | Where-Object { $_.Name -match 'hostname1'} # Select VMs named "hostname1*", or "hostname3*" $VMs = Get-VM | Where-Object { $_.Name -like 'hostname1*' -or $_.Name -like 'hostname3*'} # Select VMs named "hostname1*", but not "hostname10*" $VMs = Get-VM | Where-Object { $_.Name -like 'hostname1*' -and $_.Name -notlike 'hostname10*'} # Select VMs named "hostname1*", but not "hostname10*" with description containing "decom" or in powered-off state Get-VM | Where-Object {$_.Name -like 'hostname1*' -and $_.Name -notlike 'hostname10*' -and ($_.Description1 -like '*decom*' -or $_.PowerState -match 'PoweredOff')}
Get VM details:
# Get VMWare-Tools version for VMs matching 'prod*' name Get-VM | Where-Object { $_.Name -like 'prod*'} |% { get-view $_.id } | select Name, @{ Name=";ToolsVersion";; Expression={$_.config.tools.toolsVersion}} | Format-Table -Auto
Below is a quick PowerShell script to gather VM details based on the VM name regular expression. Note the
Where-Object
syntax and modify to suit your needs.Import-Module VMware.VimAutomation.Vds; $VMHost="vcenter1.your.domain"; Connect-VIServer -Server $VMHost; $userhome = get-content env:userprofile; $enddate = (Get-Date).tostring("yyyy-MM-dd_HHmmss"); $outfile = $userhome + '\Documents\vcenter_report_' + $enddate + '.csv'; Get-VM | Where-Object {$_.Name -like [regex]"[pd]lhttp*" -and $_.PowerState -match 'PoweredOn'} | Select Name, @{N="IP";E={@($_.Guest.IPAddress[0])}}, @{N="MAC";E={($_ | Get-NetworkAdapter).MacAddress -join ", "}}, @{N="NIC";E={$vNicInfo = Get-VM -Name $_ | Get-NetworkAdapter; $Result = foreach ($vNic in $VnicInfo) {"{0}={1}"-f ($vnic.Name.split("")[2]), ($vNic.Type)}; $Result -join (", ")}}, @{N="VLAN";E={($_ | Get-NetworkAdapter).NetworkName -join ", "}}, @{N="DnsName"; E={$_.ExtensionData.Guest.Hostname}}, NumCPU, MemoryGB, @{N="SizeGB";E={[math]::round($_.ProvisionedSpaceGB, 1)}}, @{N="HDDs (GB)";E={[math]::round(($_ | get-harddisk | select-object -ExpandProperty CapacityGB) -join " + ", 1)}}, Version, @{N="Boot Time";E={(Get-Date).AddSeconds(- (Get-Stat -Entity $_ -Stat sys.uptime.latest -Realtime -MaxSamples 1).value).ToString("yyyy-MM-dd HH:mm:ss")}}, @{N="Running OS";E={$_.ExtensionData.Guest.GuestFullName}}, @{N="VMTools";E={$_.ExtensionData.Guest.ToolsRunningStatus + " version " + $_.ExtensionData.Guest.ToolsVersion + ", " + $_.ExtensionData.Guest.ToolsVersionStatus}}, @{N="VMX";E={$_.ExtensionData.config.files.VMpathname}}, @{N="VMDK";E={($_ | Get-HardDisk).filename -join ", "}}, @{N="Snapshots";E={($_ | get-snapshot).count}}, @{N="Cluster";E={Get-Cluster -VM $_}}, @{N="ESX Host";E={Get-VMHost -VM $_}}, @{N="Datastore";E={Get-Datastore -VM $_}} | Export-Csv -NoTypeInformation -path $outfile;
Generate a datastore audit report in CSV format showing capacity, provisioned, and available space
$report = @() foreach($cluster in Get-Cluster){ Get-VMHost -Location $cluster | Get-Datastore | %{ $info = "" | select DataCenter, Cluster, Name, Capacity, Provisioned, Available $info.Datacenter = $_.Datacenter $info.Cluster = $cluster.Name $info.Name = $_.Name $info.Capacity = [math]::Round($_.capacityMB/1024,2) $info.Provisioned = [math]::Round(($_.ExtensionData.Summary.Capacity - $_.ExtensionData.Summary.FreeSpace + $_.ExtensionData.Summary.Uncommitted)/1GB,2) $info.Available = [math]::Round($info.Capacity - $info.Provisioned,2) $report += $info } } $report | Export-Csv "C:\datastore_report.csv" -NoTypeInformation -UseCulture
Same as above, but one cluster per Excel spreadsheet tab
foreach($cluster in Get-Cluster){ $report = @() Get-VMHost -Location $cluster | Get-Datastore | %{ $info = "" | select DataCenter, Cluster, Name, Capacity, Provisioned, Available $info.Datacenter = $_.Datacenter $info.Cluster = $cluster.Name $info.Name = $_.Name $info.Capacity = [math]::Round($_.capacityMB/1024,2) $info.Provisioned = [math]::Round(($_.ExtensionData.Summary.Capacity - $_.ExtensionData.Summary.FreeSpace + $_.ExtensionData.Summary.Uncommitted)/1GB,2) $info.Available = [math]::Round($info.Capacity - $info.Provisioned,2) $report += $info } $report | Export-Xls -Path C:\datastore_report.xls -WorksheetName $cluster.Name -SheetPosition "end" }
Generate a VMDK report in Excel format showing VM name, datastore, VMDK path, storage format, and capacity
$VMs = Get-VM * $Data = @() foreach ($VM in $VMs){ $VMDKs = $VM | get-HardDisk foreach ($VMDK in $VMDKs) { if ($VMDK -ne $null){ $CapacityGB = $VMDK.CapacityKB/1024/1024 $CapacityGB = [int]$CapacityGB $into = New-Object PSObject Add-Member -InputObject $into -MemberType NoteProperty -Name VMname $VM.Name Add-Member -InputObject $into -MemberType NoteProperty -Name Datastore $VMDK.FileName.Split(']')[0].TrimStart('[') Add-Member -InputObject $into -MemberType NoteProperty -Name VMDK $VMDK.FileName.Split(']')[1].TrimStart('[') Add-Member -InputObject $into -MemberType NoteProperty -Name StorageFormat $VMDK.StorageFormat Add-Member -InputObject $into -MemberType NoteProperty -Name CapacityGB $CapacityGB $Data += $into } } } $Data | Sort-Object VMname,Datastore,VMDK | Export-Xls -Path C:\vmdk_report.xls -NoTypeInformation -UseCulture
[/spoiler] [spoiler title=”Wasting Disks” style=”fancy”]
Get a list of Snapshots
# Show all snapshots for all VMs Get-VM | Get-Snapshot # Show any snapshots older than 7 days and their sizes Get-VM | Get-Snapshot | Where {$_.Created -lt (Get-Date).AddDays(-7)} | Select-Object VM, Name, Created, @{N="SizeGB";E={[math]::round($_.SizeGB, 1)}} # Same as above, but nicely formatted Get-VM | Get-Snapshot | Where {$_.Created -lt (Get-Date).AddDays(-7)} | Select-Object VM, Name, Created, @{N="SizeGB";E={[math]::round($_.SizeGB, 1)}} | Sort SizeGB | Format-Table -Auto
Create Snapshots
# Snapshot all VMs called prod* with snapshot description $Description = (Get-Date).ToString("yyyy-MM-dd")+'_before_patching' New-Snapshot -VM vmname -Name $Description Get-VM | Where-Object { $_.Name -like 'prod*'} | New-Snapshot -Name $Description
Delete the Snapshots
# Remove all snapshots for a VM Get-VM -Name vmname | Get-Snapshot | Remove-Snapshot # Remove a particular snapshot Get-VM -Name vmname | Get-Snapshot -Name snapshot_name | Remove-Snapshot # Remove all snapshots older than 90 days from all VMs Get-VM | Get-Snapshot | Where {$_.Created -lt (Get-Date).AddDays(-90)} | Remove-Snapshot
Disk Consolidation
# Get a list of VMs in need of disk consolidation Get-VM | Where-Object {$_.Extensiondata.Runtime.ConsolidationNeeded} # Consolidate disks on all VMs that need it Get-VM | Where-Object {$_.Extensiondata.Runtime.ConsolidationNeeded} | foreach {$_.ExtensionData.ConsolidateVMDisks_Task()}
[/spoiler] [spoiler title=”Abusing CPUs” style=”fancy”]
# Give VM 2 CPU sockets get-VM -name vmname | set-VM -NumCpu 2 -Confirm:$false # Give VM 2 CPU sockets with 2 cores in each $VM=Get-VM -Name vmanme $VMSpec=New-Object –Type VMware.Vim.VirtualMAchineConfigSpec –Property @{“NumCoresPerSocket” = 2} <em>$VM.ExtensionData.ReconfigVM_Task($VMSpec) $VM | Set-VM -NumCPU 2</em> # Get a list of VMs with CPU reservations Get-VM | Get-VMResourceConfiguration | where {$_.CPUReservationMhz -ne '0'} | Sort-Object NumCpuShares -Descending | Format-Table -Auto # Get a list of VMs with CPU reservations and set reservations to zero Get-VM | Get-VMResourceConfiguration | where {$_.CPUReservationMhz -ne '0'} | Set-VMResourceConfiguration -CPUReservationMhz 0 # Get a list of VM with CPU limit set Get-VM | Get-VMResourceConfiguration | where {$_.CPULimitMhz -ne '-1'} | Format-Table -Auto # As above and unset the CPU limit Get-VM | Get-VMResourceConfiguration | where {$_.CPULimitMhz -ne '-1'} | Set-VMResourceConfiguration -CPULimitMhz $null
[/spoiler] [spoiler title=”Hogging RAM” style=”fancy”]
# Give VM 2GB of RAM Get-VM -Name vmname | Set-VM -MemoryGB 2 # Reduce RAM to 1GB (requires shutdown) Get-VM -Name vmname | Shutdown-VMGuest | Set-VM -MemoryGB 1 # Double VM's RAM Set-VM -VM vmname -MemoryGB ((Get-VM -Name vmname).MemoryGB * 2) # Set VM RAM to match another VM Set-VM -VM vmname -MemoryGB (Get-VM -Name vmname2).MemoryGB # Get a list of VMs with memory reservations Get-VM | Get-VMResourceConfiguration | where {$_.MemReservationMB -ne '0'} | Format-Table -Auto # As above and unset memory reservations Get-VM | Get-VMResourceConfiguration | where {$_.MemReservationMB -ne '0'} | Set-VMResourceConfiguration -MemReservationMB 0 # Get a list of VMs with memory reservations and the amount of associated datastore free space ForEach ($vm in (Get-VM | Get-VMResourceConfiguration | where {$_.MemReservationMB -ne '0'} | ForEach {$_.VM})){Get-VM $vm | Select Name,PowerState,@{N="Reservation";E={Get-VMResourceConfiguration -VM $_ | ForEach {$_.MemReservationMB}}},@{N="Datastore";E={Get-Datastore -VM $_}},@{N="Datastore Free Space";E={Get-Datastore -VM $_ | ForEach {$_.FreeSpaceMB}}}} # Remove memory reservations on VMs if there is enough free datastore space ForEach ($vm in (Get-VM | Get-VMResourceConfiguration | where {$_.MemReservationMB -ne '0'} | ForEach {$_.VM})){ # $name = (Get-VM $vm | ForEach {$_.Name}) $powerstate = (Get-VM $vm | ForEach {$_.PowerState}) [int]$reservation = (Get-VMResourceConfiguration -VM $vm | ForEach {$_.MemReservationMB}) $datastore = (Get-Datastore -VM $vm ) [int]$dsfreespace = $datastore.FreeSpaceMB [int]$numberofds = (Get-Datastore -VM $vm |Measure-object).Count write-host "VM = $vm `n`t PowerState = $powerstate `n`t Memory Reservation = $reservation `n`t DataStore VM = $datastore `n`t Free Space on datastore = $dsfreespace `n`t Number of Datastores is $numberofds" if ((($dsfreespace - $reservation) -gt "0") -and ($numberofds -eq "1")){ Write-Host "Now removing the memory reservation $reservation for VM $vm" -ForegroundColor Green Get-VMResourceConfiguration -VM $vm | Set-VMResourceConfiguration -MemReservationMB 0 } else { Write-Host "Memory reservation ($reservation) cannot be removed because there is not enough free space on the datastore, or because the VM has multiple datastores." -ForegroundColor Red } } # Get a list of VMs with memory limit Get-VM | Get-VMResourceConfiguration | where {$_.MemLimitMB -ne '-1'} | Format-Table -Auto
[/spoiler] [/accordion]