Automating VMware Memory Changes

VMware

I had to make some memory changes on a batch of VMs. I didn’t want to have to manually shutdown each VM, alter the memory setting and then restart as this would be very time consuming instead I prepared this script. You first need to create a CSV file, e.g. vmalterlist.csv and place it somewhere on your machine. The format of the file should be as follows, where VMName is the name of the VM (as shown in vCenter) and TargetMemoryGB is the number of GB of RAM you want the VM to be altered to. The script when run will stop each VM, ideally using VMTools, change the memory and start back up the VMs again. Note: If you don’t specify to start the VMs explicitly they wont start.

VMName,TargetMemoryGB
wintest1,2
ubuntutest1,1

The script takes three arguments at the command line when run from PowerCLI. It requires the vCenter FQDN, the location of the CSV file and if you want the VMs to be powered back up again at the end. It assumes about 5 minutes to allow the VMs to shutdown.

<#
.SYNOPSIS
This script will connect to vCenter, using the list specified shutdown each VM, alter the memory settings as per the CSV file and then start the VM again.
.DESCRIPTION
The script makes use of a connection to the vCenter server to shut down each VM in turn, alter its memory and restart it.
If a VM does not have VMware Tools installed or running, the VM will be force powered off.
.EXAMPLE
./shutVMaltermem.ps1 -VIserver <serverFQDN>  -FileNamePath <filenameandpath> -PowerOnAtEnd [Yes|No]
./shutVMaltermem.ps1 -VIserver vcenter.domain.com -FileNamePath c:\vmlist.csv -PowerOnAtEnd Yes
.NOTES
If you run the script without any arguments it will connect with the default parameters. VMs will not be started unless specified.
The CSV file should have the first line as: VMName,TargetMemoryGB, then each VM should be specified by its name followed 
by the amount of memory in GB the memory should be reduced to.
#>
param (
    [string]$VIserver = "vcenter.domain.com",
    [string]$filenamepath = "c:\vmalterlist.csv",
    [string]$poweronatend = "No"
)
Add-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue
# Connect to vcenter server
Write-Host "Connecting to vCenter......"  
connect-viserver $VIserver
Write-Host
Write-Host "Script is processing these VMs:"
Write-Host
# Import vm name from csv file  
Import-Csv $filenamepath |  
    foreach {
        $strVMName = $_.VMName
        $strTargetMemoryGB = $_.TargetMemoryGB
        
        # Get a view for the current VM
        $vm = Get-View -ViewType VirtualMachine -Filter @{"Name" = $strVMName}
        
        # If VM is powered on check VMTools status, otherwise move on.
        if ($vm.Runtime.PowerState -eq "PoweredOff") {
                # Write to the screen the current power state
                Write-Host $strVMName "=" $vm.Runtime.PowerState " - VM powered off, nothing to do!"
        }
        
        if ($vm.Runtime.PowerState -ne "PoweredOff") {  
            if ($vm.config.Tools.ToolsVersion -ne 0) {  
                # Write to the screen the current power state
                Write-Host $strVMName "=" $vm.Runtime.PowerState " - VMware tools installed, graceful shutdown attempted."
                
                # Graceful shutdown the VM
                Shutdown-VMGuest $strVMName -Confirm:$false  
                          
            } else {  
                # Write to the screen the current power state
                Write-Host $strVMName "=" $vm.Runtime.PowerState " - VMware tools not installed, forced shutdown attempted."
            
                # Force shutdown the VM 
                Stop-VM $strVMName -Confirm:$false
                
            }  
        }   
    }
    
Write-Host
Write-Host
Write-Host -NoNewLine "Waiting 5 minutes for all VMs to shutdown, before altering memory: "
for ($a=0; $a -le 4; $a++) {
  Write-Host -NoNewLine "`r#"
  Sleep 60
}
Write-Host -NoNewLine " Done!"
Write-Host
Write-Host "Altering memory on the following VMs:"
Write-Host
# Import vm name and new memory size from CSV file to perform the changes to the memory configuration on each VM.
Import-Csv $filenamepath | 
    foreach {
        $strVMName = $_.VMName
        $strTargetMemoryGB = $_.TargetMemoryGB   
              
        Write-Host $strVMName " - Memory set to:" $strTargetMemoryGB
        
        # Set the memory to the new value, and force to confirm its change.
        Set-VM -VM $strVMName -MemoryGB $strTargetMemoryGB -Confirm:$false
    }
    
# Import vm name from CSV file, to restart all the VMs again, it will give you the option to confirm if you want to start a particular VM.
Import-Csv $filenamepath | 
    foreach {
        $strVMName = $_.VMName             
               
        # Attempt to start the VMs, if the user has requested that.
        if ($poweronatend -eq "Yes") {
            Write-Host "Starting VM: "$strVMName
            Start-VM -VM $strVMName -Confirm:$false -RunAsync
            
        }
        
    }
    
if ($poweronatend -ne "Yes") {
    # Write to the screen that no VMs will be started.
    Write-Host "Not starting any VMs at request of the user."
}
# Disconnect from vCenter.
disconnect-viserver $VIserver -Confirm:$false 
Write-Host "Script complete, disconnected from vCenter."