Use PowerCLI Set-HardDisk and Invoke-VMScript to increase the size of many virtual machine hard drives

Today I decided that I wanted to increase the C: volume of 20 VMware Horizon View parent virtual machines (the source for 1,000s of linked-clone virtual desktops) from 40 GB to 60 GB. The normal/painful way to do this would be:

  • vSphere > select the virtual machine > Edit Settings > change Hard Disk 1 from 40 GB to 60 GB > Okay
  • vSphere > power on virtual machine
  • vSphere > launch the console to the virtual machine
  • vSphere > Console > log into Windows
  • vSphere > Console > Windows > launch Disk Manager
  • vSphere > Console > Windows > Disk Manager > Action > Rescan Disk
  • vSphere > Console > Windows > Disk Manager > select Volume C > right-click Extend Volume
  • power off Windows, exit virtual machine console, repeat for the next virtual machine

Seeking to automate this process, I turned to VMware PowerCLI and learned more about these two commandlets:

After finding a few examples and refreshing my memory on how to use DISKPART from a command line, I created this PowerCLI script that successfully increased the size (both in vSphere and Windows) of my targeted virtual machines in just a few minutes.

PowerCLI Set-HardDisk and Invoke-VMScript (plain text version: PowerCLI-Extend-Disks.ps1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# PowerCLI-Extend-Disks.ps1
# Must be run in VMware PowerCLI
# Written by Jason Pearce, www.jasonpearce.com, (2015 June)
# Inspiration from Brian Wuchner, Adam Stahl, and of course Luc Dekens (LucD)
 
# BEGIN Variables
 
# vCenter that contains target VMs
$vCenter="vcenter.example.local"
 
# New hard drive size you want (should be larger than current drive size)
$NewCapacityGB=60
 
# One or more virtual machines you want to target (modify and uncomment this line)
# $VMs=(Get-Cluster -Name "ClusterName" | Get-VM -Name "VM-Prefix-*")
# $VMs=("VM1","VM2","VM3")
 
# Virtual Machine Windows Credentials (a local admin account)
$GuestUser="administrator"
$GuestPassword="password"
 
# END Variables
 
# BEGIN Script
 
# Connect to vCenter via PowerCLI
Connect-VIServer $vCenter
 
# BEGIN foreach loop
foreach ($VM in $VMs) {
 
# Have vSphere PowerCLI increase the size of the first hard drive in each target VM
Get-VM $VM | Get-HardDisk | Where-Object {$_.Name -eq "Hard Disk 1"} | Set-HardDisk -CapacityGB $NewCapacityGB -Confirm:$false
 
# Run DISKPART in the guest OS of each of the specified virtual machines
Invoke-VMScript -VM $VM -ScriptText "ECHO RESCAN > C:\DiskPart.txt && ECHO SELECT Volume C >> C:\DiskPart.txt && ECHO EXTEND >> C:\DiskPart.txt && ECHO EXIT >> C:\DiskPart.txt && DiskPart.exe /s C:\DiskPart.txt && DEL C:\DiskPart.txt /Q" -ScriptType BAT -GuestUser $GuestUser -GuestPassword $GuestPassword
 
}
# END foreach loop
 
# Disconnect from vCenter
Disconnect-VIserver -Confirm:$false
 
# END Script

Note that the script cleans up after itself. It creates a small DiskPart.txt file on the root of your virtual machine, runs DiskPart using the settings in the DiskPart.txt file, and then deletes the DiskPart.txt file when its done.

Now that I know how to use the Invoke-VMScript commandlet, I’m sure I’ll come up with many more time-saving ideas like this one.

4 Comments


  1. I was curious to know if there was a reason you used diskpart, instead of running

    Get-HardDisk -vm $vm | Where {$_.Name -eq "Hard disk 1"} | Set-HardDisk -CapacityGB 38 -ResizeGuestPartition -Confirm:$false

    to extend the volume inside the guest os.


  2. Thanks for this script, we were looking to do something similar and this works perfectly. I’ve added some other things such as a reboot, a bunch of logging, and some other thing but the core of the updated script is yours.


  3. I guess I didn’t think of it. I like your PowerShell one liner and will likely modify my script in the future. Thank you.


  4. Is there any way you can use the SSO of the account is executing the script to perform the extension on the Guest? instead of having to specify username and password?

    This is specially for Windows systems

Comments are closed.