Originally published February 20, 2017 @ 1:21 am

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.

Entering the Chicken Coop
Import-Module VMware.VimAutomation.Vds
$VMHost="vcenter01.krazyworks.local"
Connect-VIServer -Server $VMHost

Cluster Info

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

Glorious Spreadsheets

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

 

Wasting Disks

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

Abusing CPUs
# 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

Hogging RAM
# 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