A quick start to VMware automation

When I was in need of this kind of script, I wish there was easy accessible information available on them. That's why I want to make your life easier by sharing my findings with you through this blogpost!
6 min read
Arnaud Charles
A quick start to VMware automation

Do less to do more

VMware provides tools such as vCenter and vRealize. Here's a quick start on getting you onboarded with scripted tasks!

The CLI

Using the command line simply means that you will perform the same operation as you would with your mouse, but with a few lines of code instead.

Because there are UX people working on visual tools, they are obviously more user-friendly than a console view with no help or tips. If you need to complete a task, you must know the commands or have them saved somewhere as a cheatsheet. However, if you need to perform the same task 100 times, you must perform the same clicks manually each time. Using code allows you to do the same thing through a loop; basically, you just hit enter and the script does the rest.

Scripting takes time but can be repaid over time. This is why, before working on a script, we always consider recurrency. Should you spend 8 hours scripting a 5-minute job that you only do once a year?

The official tool

VMware PowerCLI is an official tool that VMware provides and supports.

This module is available from the PowerShell Gallery and can be easily installed on PowerShell starting with version 5.1 (Windows).

Install-Module -Name VMware.PowerCLI

Once installed, use the following command to connect to your environment.

Connect-VIServer -Server IP/Hostname -Protocol https

If you get a certificate issue, just ignore it with the following command.

Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false

Here is a list of useful scripts. These scripts work with an input file.

Before making any changes to the VM, check the free space on the Datastore.

This script receives a list of machines, reads them, determines which datastore is in use, and displays the remaining free space. This is useful to run prior to adding additional disks.

Input file

Input.csv with content :

HostName,DiskSize
vmansible001,300

# Check VM listed in the csv file
$tab = @()
$space = @()

$csv = Import-Csv .\input.csv
$csv | ForEach-Object {
    $vm = Get-VM -Name $($_.HostName)
    $datastore = $vm | Get-Datastore
    $tab += $datastore.Name
    $space += $datastore.FreeSpaceGB 
    Write-Output $tab","$space
}

Add a new disk to multiple VM

This script is excellent for attaching new disks to hundreds of virtual machines in a matter of seconds. The size of the disk can vary.

Input file

vCenter_AddDisk.csv with content :

HostName,DiskSize
myvm01,20
myvm02,20
myvm03,50

# Check all lines and ask if we can go on 
$csv = Import-Csv .\vCenter_AddDisk.csv
$csv | ForEach-Object {
    Write-Host "New disk of $($_.DiskSize)Go will be add to $($_.HostName)." 
}
$validate = Read-Host -Prompt "Is this list seems legit ? (y/n)"
if ($validate -eq 'y') {   
    $csv | ForEach-Object {
        Write-Host "Adding $($_.DiskSize)Go to $($_.HostName)..."
        Get-VM $_.HostName | New-HardDisk -CapacityGB $_.DiskSize 
        Get-HardDisk -VM $_.HostName 
    } | Out-File .\vCenter_AddDisk.log 

    Write-Host "DONE"
}
else {
    Write-Host "Aborting... "
    exit
}

Check attached Disk to VM

This one can refer to the previous script to see if all added disks are visible. You can also direct the output to a file, which you provide to the requester.

vCenter_CheckDisk.ps1 > AddedDisk.log

Input file

Input.txt with content :
vmansible001
vmansible002

# Check VM listed in the txt file

function Get-VMDisks {                       
    param(            
        [string]$VMName            
    )            
    $VMObj = Get-VM -Name $VMName            
    $Disks = Get-Harddisk -VM $VMObj            
    foreach ($disk in $Disks) {            
        $DiskName = $Disk.Name            
        $DisksizeinGB = ($Disk.CapacityKB * 1024) / 1GB            
        "{0}: {1} | " -f $DiskName, $DisksizeinGB            
    }            
}

foreach ($vmlist in (Get-Content -Path '.\input.txt')) {
    $vm = Get-VM -Name $vmlist
    $Disk = Get-VMDisks $vmlist
    Write-Output "The VM $vm have :  $Disk"
}  

Check NICs

If you want to export all NIC details used by some hosts, use this one.

Input file

vCenter_CheckNIC.txt with content :
vmansible001
vmansible002

# Check NIC in the txt file

foreach ($vmlist in (Get-Content -Path '.\vCenter_CheckNIC.txt')) {

    if ((Get-VM -Name $vmlist).PowerState -ne 'PoweredOff') {
        $vm_epg = Get-VM -Name $vmlist | Get-NetworkAdapter
        $vm_ip = (Get-VM -Name $vmlist ).Guest.Nics


        Write-Host "The VM"$vmlist" have the following adapters ⤵" 
        foreach ($NIC in $vm_epg) { 
            Write-Host $NIC.Name "→ Type is" $NIC.Type "| NIC name is" $NIC.NetworkName "► MAC :" $NIC.MacAddress
        }
        Write-Host "Detail of these adapters :"
        foreach ($NIC in $vm_ip) {
            Write-Host "○" $NIC.Device "DVPortGroup ‣"$NIC.NetworkName "| Assigned IP :"$NIC.IPAddress
        }
        Write-Host "------------------------------------------------------------------------------------------------------------------------------------------------------"
    }  
}

Check VM Status

Used to show quickly the status of a VM, CPU and RAM. This is important to run before and after changes

Input file

vCenter_CheckVM.txt with content :
vmansible001
vmansible002

foreach($vmlist in (Get-Content -Path '.\vCenter_CheckVM.txt')){
$vm = Get-VM -Name $vmlist 
$vm 
} 

Start a list of VM

This one is obviously a must have after the changes

Input file

vCenter_StartVM.txt with content :
vmansible001
vmansible002

# Start VM listed in the txt file
foreach($vmlist in (Get-Content -Path '.\vCenter_StartVM.txt')){
$vm = Get-VM -Name $vmlist
Start-VM -VM $vm -Confirm:$false
}

Shutdown a list of VM

This is obviously another must-have before making changes.

Input file

vCenter_ShutdownVM.txt with content :
vmansible001
vmansible002

# Shutdown VM listed in the txt file
foreach($vmlist in (Get-Content -Path '.\vCenter_ShutdownVM.txt')){
$vm = Get-VM -Name $vmlist
Shutdown-VMGuest -VM $vm -Confirm:$false
}

Move VM from one storage to another

This is useful if you need to move a large number of virtual machines in a single step. The script will determine which VMs are in the source storage and will skip any ExcludedVMs. When the process is finished, the VM will be stopped, moved, and then restarted.

Take care not to shut down vCenter or the VPN VM if you are running it from a remote location.

# Variables 
$SourceDatastore = "iscsi_nas10"
$DestinationDatastore = "strnas01b5"
$ExcludedVM = @("myvm01","myvpn01","myvcenter01","myapp01")
$VMToMigrate = @()

# Functions
function Get-InstanceList (){
    $VmList = Get-VM -Datastore $SourceDatastore 
    foreach($VM in $VMList){
        if($VM -in $ExcludedVM)
        {
            Write-Host "The VM"$VM "will not be migrate"
        }
        else {
            $VMToMigrate = $VMToMigrate + $VM 
        }
    }
    Write-Host "To migrate :"
    foreach($Element in $VMToMigrate){
        Write-Host $Element
    }
    return $VMToMigrate
}

function Set-ShutdownInstance(){
   ## Shutdown instances
    Write-Host "Cheking which instances are Powered On to gracefully shut them down"
    foreach($VM in $VMToMigrate){
        $VMStatus = @()
        $VMStatus = (Get-VM $VM).PowerState
        $VMToShutdown = @()
        if($VMStatus -eq "PoweredOn"){
            Write-Host "Instance" $VM "is PoweredOn"
            $VMToShutdown = $VMToShutdown+ $VM
            Stop-VM $VM -Confirm:$false
        }
        else{ 
            Write-Host "Instance" $VM "is already PoweredOff"
        }
    }
  ## Verify that all instances are shutdown
    Write-Host "Checking that all instances are PoweredOff"
    foreach ($VM in $VMToShutdown){
        if((Get-VM $VM).PowerState -eq "PoweredOn"){
            Do{Stop-VM $VM -Confirm:$false} 
            Until((Get-VM $VM).PowerState -eq "PoweredOff")
        }
    }    
}

function Set-MoveInstances(){
    foreach($VM in $VMToMigrate){
        Move-VM $VM -Datastore $DestinationDatastore -Confirm:$false -RunAsync
        Start-Sleep -Seconds 3
    }
}

function Get-CheckDatastoreRemaining(){
    Get-VM -Datastore $SourceDatastore 
}

function Set-VMStart(){
    foreach ($VM in $VMToShutdown){
        Start-VM $VM
    }
}

# Code
$VMToMigrate = Get-InstanceList
$Validation = Read-Host -Prompt 'Is the list looking good ? (y/n)'
If($Validation -eq "y"){
    Set-ShutdownInstance
    Set-MoveInstances
    Get-CheckDatastoreRemaining
    Set-VMStart
}

Delete a list of VM

When decommissioning is approved, run this to quickly remove the VM. The argument "-DeletePermanently" is used to request removal from the datastore as well.

Input file

vCenter_DeleteVM.txt with content :
vmansible001
vmansible002

# Delete VM listed in the txt file
foreach($vmlist in (Get-Content -Path '.\vCenter_DeleteVM.txt')){
$vm = Get-VM -Name $vmlist
Remove-VM -VM $vm -Confirm:$false -DeletePermanently
}

Change CPU and RAM to a list of VM

Input file

AddCPUandRAM.csv with content :
HostName,oldCPU,oldRAM,CPU,RAM
vm-l-p-customer01,16,64,24,256
vm-l-p-customer02,16,64,24,256
vm-l-p-customer03,16,64,24,256

# Check all lines and ask if we can go on 
$csv = Import-Csv .\AddCPUandRAM.csv
$checkOldValues = Read-Host -Prompt "Do you want to run a check on values listed on the file ? (y/n)"
if ($checkOldValues -eq 'y')
{
    $csv | ForEach-Object {
        $vm = Get-VM $_.HostName 
        $vCenterVMCPU = $vm | Select-Object NumCpu
        $vCenterVMRAM = $vm | Select-Object MemoryGB
        Write-Host "Host : $($_.HostName) | CSV CPU = $($_.oldCPU) & RAM = $($_.oldRAM) | vCenter CPU = $vCenterVMCPU & RAM = $vCenterVMRAM." 
        if ($_.oldCPU -ne $vCenterVMCPU) {
            Write-Host "CPU in CSV is not correct" -ForegroundColor Red -BackgroundColor Yellow
        }
        elseif ($_.oldRAM -ne $vCenterVMRAM) {
            Write-Host "RAM in CSV is not correct" -ForegroundColor Red -BackgroundColor Yellow
        }
        else {
            Write-Host "Values are consistent" -ForegroundColor Green
        }
    }
}

$validate = Read-Host -Prompt "Apply changes ? (y/n)"
if ($validate -eq 'y') 
{   
    $csv | ForEach-Object {
        $vm = Get-VM $_.HostName 
        Write-Host "Processing $($_.HostName) ..."
        $vm | Set-VM -MemoryGB $($_.RAM) -NumCpu $($_.CPU)
        $vm | Select-Object Name,NumCpu,MemoryGB
    } | Out-File .\AddCPUandRAM.log 

    Write-Host "DONE"
}
else {
    Write-Host "Aborting... "
    exit
}

The CLI

These are only a few PowerCLI examples; in a future blog post, we may share more advanced scripts made using vRa API calls. So make sure to keep an eye on our social media!