Expanding an existing disk on a Virtual Machine with PowerCLI | Get-HardDisk & Set-HardDisk cmdlets

We recently had a sudden requirement to increase the C: drives of a set of VMs to assist with an Operating system patching process – its not practical to to manually do that one by one – so PowerCLI to the rescue. So if you get a scenario where you need to expand an existing disk of a virtual machine by a specified amount of GB (especially a bulk of VMs), the following script will make life much easier.

Get the current size of the required disk

Use the code below to get the size (in GB) of the harddisk in question (here I’m getting the size of “hard disk 1”)

$vm_info_dsk = (Get-HardDisk -VM $vm_name | Where-Object {$_.Name -eq "Hard Disk 1"}).CapacityGB

You can make this a more expandable/usable code by making the Hard disk number a variable as well. With this you can change the name of the Hard disk easily without having to replace all the instances where the name was used.

$hard_disk_number = "Hard Disk 1"

$vm_info_dsk = (Get-HardDisk -VM $vm_name | Where-Object {$_.Name -eq $hard_disk_number}).CapacityGB

Setting the hard disk to the new size

You can change the size of the disk using the Set-HardDisk command. Here I’m going to assume the size of the disk needs to be increased by 10GB

$space_to_increase = 10
$new_capacity = $vm_info_dsk + $space_to_increase

Get-HardDisk -VM $vm_name | Where-Object {$_.Name -eq "Hard Disk 1"} | Set-HardDisk -capacityGB $new_capacity -confirm:$false

How it all comes together (the complete script)

Lets see how to put this all in to a robust expandable script.

The script will read a list of vms from the vm_list.txt text file (vms should be separated by a new line) which would be useful for bulk list of VMs – for more clarity on Get-Content read that post here. To change any parameter (different disk size, different harddisk) simply change the relevant variable.

#Read list from a text file vm_list.txt - separated by a new line
$vm_list = Get-Content "vm_list.txt"

$vcenter = "vCenter1"
$space_to_increase = 20
$hard_disk_number = "Hard Disk 1"

Connect-VIServer $vcenter 

foreach($vm_name in $vm_list){
	write-host "Fetching information of $vm_name"
	$vm = Get-VM $vm_name

	$vm_info_dsk = (Get-HardDisk -VM $vm_name | Where-Object {$_.Name -eq $hard_disk_number}).CapacityGB

	Write-Host "$vm $hard_disk_number is $vm_info_dsk"

	$new_capacity = $vm_info_dsk + $space_to_increase

	Write-Host "new hard disk capacity $new_capacity"

	Get-HardDisk -VM $vm_name | Where-Object {$_.Name -eq $hard_disk_number} | Set-HardDisk -capacityGB $new_capacity -confirm:$false

#Check if it is successfully set and display the new size
	$vm_info_dsk = (Get-HardDisk -VM $vm_name | Where-Object {$_.Name -eq $hard_disk_number}).CapacityGB

	Write-Host "$vm new hard disk 1 is $vm_info_dsk"
Disconnect-VIServer -Confirm:$false

Listing all networks visible to an ESX host via PowerCLI

I had worked on an automation project to ease up virtual machine provisioning – for that it was necessary to create a script that would list out all the networks that is visible to an ESXi host (so that the correct one could be added to the new virtual machine). Turns this was quite easy with the Get-VirtualPortGroup cmdlet – here’s how to do it (its so simple that its going to be a smaller than normal post)

$host_info = Get-VMHost -VM $vmname
Get-VirtualPortGroup -VMHost $host_info.name

And that’s it! no magic to it at all!

Checking for and Setting Maintenance mode on an ESXi Host via PowerCLI

Say you have to do a configuration change on an ESXi host – you know you can script that stuff out and put your feet up while it does it’s thang… Buuut you’re unsure about whether the host is in maintenance mode… what if its not on maintenance mode? What if it screws it up! Well in this post I’ll cover how you can check for as well as set maintenance mode effectively via PowerCLI.

Checking whether ESXi host is in Maintenance mode

The Get-VMHost cmdlet get the connection state of the ESXi host as well whether its connected, disconnected or in maintenance mode.

$host = "esx_host1" 
#Use the fqdn of the host

if($host.ConnectionState -eq "Maintenance"){
	write-host "The host is in maintenance mode"
	#Your configuration change code can go here

Setting ESXi host to Maintenance mode

$host = "esx_host1" 
#Use the fqdn of the host

#Set host to maintenance mode
Get-VMHost -Name $hosts | set-vmhost -State Maintenance

	$host_info = Get-VMHost $hosts
	$count = $count + 1
	#check if 5 minutes had passed, if so exit 
	if ($count -gt 15){
		$failed = 1
		$msg = "Waiting for maintenance mode timed out. Please check the status from the vCenter"
		sleep 20
}until($host_info.ConnectionState -eq "Maintenance" )

This script issues the command to set the host to maintenance mode. Then checks every 20 seconds for 5 minutes whether the host is in maintenance mode. If not it will get a timeout error (say if one stubborn Virtual machine refuses to leave the host).