PowerCLI script to move a virtual disk between two VMs

<#
    MoveVD.ps1
    Move a virtual disk between two VMs

    Recently I was requested for writing a script to easily detach a virtual disk from a VM and attach it to another VM.
	

    .History.
	2020/05/28 - 0.1 - Reza Rafiee		- Initial version
	

#>

###############################
Write-host (" ")
$SourceVM = vRead-Host "Enter Source VM Name "
$srcVM=Get-VM -Name $SourceVM

Write-host ("The attached virtual disks on $srcVM.name ")
get-vm -name $srcVM | Get-HardDisk | Select Name,CapacityGB,Persistence,Filename

Write-host (" ")

$VDiskNumber =	Read-Host "Enter the Virtual Hard Disk Number that you want to detach from $srcVM.name  "

$VDiskSize = Read-Host "Enter the Disk Size (GB) "

Write-host (" ")

$TargetVM = Read-Host "Enter Target VM Name "




$trgVM= Get-VM -Name $TargetVM
$trgDisk="Hard Disk $VDiskNumber"

$disk=get-vm -name $srcVM | Get-HardDisk | Where-Object {($_.Name -eq $trgDisk) -AND ($_.CapacityGB -eq $VDiskSize)}


If ($disk -eq $null){
write-host ("No Hard Disk found as ($trgDisk - $VDiskSize GB) on $SourceVM")
exit
}

$confirmation = Read-Host -Prompt "Are you sure you want to detach ($trgDisk - $VDiskSize GB) on $SourceVM and attach it to $TargetVM ? [y/n]"

If ($confirmation -eq "y") {
	Remove-HardDisk $disk -Confirm:$false
	New-HardDisk -VM $trgVM -DiskPath $disk.Filename
#You can also specify the SCSI controller of which the disk should be attached to by adding the following parameter to the above command:  -Controller "SCSI Controller 0"
	Write-host (" ")
	Write-host ("The attached virtual disks on $trgVM.name ")
	get-vm -name $trgVM | Get-HardDisk | Select Name,CapacityGB,Persistence,Filename
	
	}
###############################

Automate SNMP configuration on multiple ESXi hosts

I have created a PowerCLI script that can be used for applying SNMP configuration on multiple ESXi hosts of a vSphere Cluster by replicating configuration from a reference ESXi host.

Leave a comment with your email address if you have a question and I will get back to you soon.

Enjoy the script 🙂

  1. <#
  2.   configure-snmp-on-esxi.ps1
  3.  
  4.   Configure SNMP settings on multiple ESXi hosts using a reference host settings
  5.  
  6.   .History.
  7.   2020/04/09 - 0.1 - Reza Rafiee - First version
  8.  
  9.   .Variables.
  10.   $VC: vCenter Server
  11.   $targethosts: Target ESXi host cluster
  12.   (to apply on single ESXi host refer to line30)
  13.   $refesxhost : Reference ESXi host
  14.  
  15. #>
  16.  
  17. $VC="vCenter Server Name"
  18. $targethosts="Target cluster name"
  19. $refesxhost = "Reference ESXi host name"
  20.  
  21.  
  22.  
  23. Connect-viserver $VCServer
  24. $refhost = get-vmhost $refesxhost
  25. $refesxcli = Get-EsxCli -VMhost $refhost -V2
  26. $snmp=$refesxcli.system.snmp.get.invoke()
  27. write-host "SNMP configuration on " $refesxhost," (Refernce Host): "
  28. $snmp
  29.  
  30. $vmhosts = get-cluster -name $targethosts | get-vmhost
  31. <#If you want to apply the snmp config on a single host
  32.  then enter ESXi host name for $targethosts variable and
  33.  replace the above line with the below line:
  34.  
  35.  $vmhosts = get-vmhost -name $targethosts
  36.  
  37.  #>
  38.  
  39.  
  40. foreach ($vmhost in $vmhosts){
  41.  
  42. $esxcli = Get-EsxCli -VMHost $vmhost -V2
  43.  
  44. <#Reset SNMP settings to factory default on the target host prior to
  45. reconfigure SNMP settings on that host#>
  46. $snmpreset = $esxcli.system.snmp.set.CreateArgs()
  47. $snmpreset.reset = $true
  48. $esxcli.system.snmp.set.Invoke($snmpreset)
  49.  
  50. write-host "SNMP settigs has been reset to default on $vmhost"
  51. #SNMP settings reset complete
  52.  
  53. $esxcli = Get-EsxCli -VMHost $vmhost -V2
  54. $arguments = $esxcli.system.snmp.set.CreateArgs()
  55.  
  56. #The below arguments (if statements) cannot be null hence we skip the null ones
  57.  
  58. if ($snmp.communities -ne $null) {
  59. $arguments.communities = $snmp.communities
  60. }
  61.  
  62. if ($snmp.engineid -ne "$null") {
  63. write-host "engineid is nt null"
  64. $arguments.engineid = $snmp.engineid
  65. }
  66.  
  67. if ($snmp.targets -ne $null) {
  68. $arguments.targets = $snmp.targets
  69. }
  70.  
  71. if ($snmp.users -ne $null) {
  72. $arguments.users = $snmp.users
  73. }
  74.  
  75. if ($snmp.privacy -in ("none", "AES128")) {
  76. $arguments.privacy = $snmp.privacy
  77. }
  78.  
  79. if ($snmp.remoteusers -ne $null) {
  80. $arguments.remoteusers = $snmp.remoteusers
  81. }
  82.  
  83. if ($snmp.authentication -in ("none", "MD5", "SHA1")) {
  84. $arguments.authentication = $snmp.authentication
  85. }
  86.  
  87. if ($snmp.v3targets -in ("none", "auth", "priv")) {
  88. $arguments.v3targets = $snmp.v3targets
  89. }
  90.  
  91. $arguments.hwsrc = $snmp.hwsrc
  92. $arguments.largestorage = $snmp.largestorage
  93. $arguments.loglevel = $snmp.loglevel
  94. $arguments.notraps = $snmp.notraps
  95. $arguments.enable = $snmp.enable
  96. $arguments.port = $snmp.port
  97. $arguments.syscontact = $snmp.syscontact
  98. $arguments.syslocation = $snmp.syslocation
  99.  
  100. $esxcli.system.snmp.set.Invoke($arguments)
  101.  
  102. $newsnmp=$esxcli.system.snmp.get.Invoke()
  103. write-host "SNMP configuration on", $vmhost, ": "
  104. $newsnmp
  105.  
  106. }

Create multiple VDS port groups using PowerCLI

This is a PowerCLI script for creating multiple portgroups in a VMware Distributed Switch.

It can be helpful for migrating from Nexus 1000v to VMware VDS.

Please note that this script is only for creating switchport port groups (single VLAN) and not for trunk port groups (VLAN range).

If you have any question about the script, please leave a comment.

<#
    Create_VDS_PortGroups

    Creates Port Groups in a VMware Distributed Switch

    Feed the script with "portgroups.csv" file with portgroup names and vlan IDs and then update $VDS with the terget VDS_Name.
	
	portgroup.csv must have "portgroup" and "vlan" header to identify the portgroup name and corresponding vlan ID.
	
	Please note that this code is only for creating switchports (single VLAN) not trunk port groups (VLAN range).
	
	I wrote this script for migrating portgroups from Nexus 1000v to VMware Distributed Switch
    
    .History.
	2020/03/06 - 0.1 - Reza Rafiee	- First version

#>

############################
$PGs = Import-CSV .\portgroups.csv
$VDS = "VDS Name"
$RefPG = Get-VDPortgroup -Name "Reference Portgroup Name"

ForEach ($PG in $PGs) {
    $newPG = Get-VDSwitch -Name $VDS |
    New-VDPortgroup -Name $PG.portgroup  -ReferencePortgroup $RefPG.Name | Set-VDPortgroup -Notes $PG.description
    Set-VDVlanConfiguration -VDPortgroup $newPG -VlanId $PG.vlan -Confirm:$false 
	}
############################





			

Compare Advanced Settings of two ESXi hosts

Of course you can use host profile templates to check compliance of ESXi host configuration against baseline configuration. But there might be some ad-hoc times that you need to compare Advanced Settings of two ESXi hosts and probably export a report out of it.

The below piece of PowerCLI code would be helpful for that purpose.

The credit for this code goes to Frederic Martin, the author of the code.

.SYNOPSIS 
    This script will compare all advanced settings between 2 ESXi servers
.DESCRIPTION 
    The script will compare each of all advanced settings between a source and a destination ESXi server and will display the difference
.NOTES 
    Author     : Frederic Martin - www.vmdude.fr
.LINK 
    http://www.vmdude.fr
.PARAMETER hostSourceName 
   Name of the host used for source compare
.PARAMETER hostDestinationName 
   Name of the host used for destination compare
.PARAMETER short 
   This switch allows you to bypass some advanced settings thanks to variable named $excludedSettings
.EXAMPLE 
	C:\foo> .\Compare-AdvancedSettings.ps1 -hostSourceName esx01.vmdude.fr -hostDestinationName esx02.vmdude.fr
	
	Description
	-----------
	Display all differences between advanced settings from host esx01.vmdude.fr and host esx02.vmdude.fr
.EXAMPLE 
	C:\foo> .\Compare-AdvancedSettings.ps1 -hostSourceName esx01.vmdude.fr -hostDestinationName esx02.vmdude.fr -short
	
	Description
	-----------
	Display differences (without those in $excludedSettings) between advanced settings from host esx01.vmdude.fr and host esx02.vmdude.fr
#> 

param (
	[Parameter(Mandatory=$True)]
	[string]$hostSourceName,
	[Parameter(Mandatory=$True)]
	[string]$hostDestinationName,
	[switch]$short
)

# Checking if source host exists
if (-Not ($hostSource = Get-VMHost $hostSourceName -ErrorAction SilentlyContinue)) {
	Write-Host -ForegroundColor Red "There is no source host available with name" $hostSourceName
	exit
}

# Checking if destination host exists
if (-Not ($hostDestination = Get-VMHost $hostDestinationName -ErrorAction SilentlyContinue)) {
	Write-Host -ForegroundColor Red "There is no destination host available with name" $hostDestinationName
	exit
}

$diffAdvancedSettings = @()
# Using hastable for easy and fast handle
$advancedSettingsSource = @{}
$advancedSettingsDestination = @{}
# You can filter unwanted advanced settings to be unchecked (regexp)
$excludedSettings = "ScratchConfig.CurrentScratchLocation|ScratchConfig.ConfiguredScratchLocation|Vpx.Vpxa.config.vpxa.|UserVars.ActiveDirectoryPreferredDomainControllers|Config.Defaults.cpuidMask|Mem.HostLocalSwapDir"

# Retrieving advanced settings
Get-AdvancedSetting -Entity $hostSource | %{$advancedSettingsSource.Add($_.Name,$_.Value)}
Get-AdvancedSetting -Entity $hostDestination | %{$advancedSettingsDestination.Add($_.Name,$_.Value)}

# Browsing advanced settings and check for mismatch
ForEach ($advancedSetting in $advancedSettingsSource.GetEnumerator()) {
	if ( ($short -And $advancedSetting.Name -notmatch $excludedSettings -And $advancedSetting.Value -ne $advancedSettingsDestination[$advancedSetting.Name]) -Or (-Not $short -And $advancedSetting.Value -ne $advancedSettingsDestination[$advancedSetting.Name]) ) {
		$line = "" | Select Settings, SourceValue, DestinationValue
		$line.Settings = $advancedSetting.Name
		$line.SourceValue = $advancedSetting.Value
		$line.DestinationValue = $advancedSettingsDestination[$advancedSetting.Name]
		$diffAdvancedSettings += $line
	}
}

# Displaying results
$diffAdvancedSettings

PowerCLI code to Find a datastore by NAA ID

There are times that you have a NAA ID of a LUN and need to find the corresponding datastore.

The below PowerCLI code is quite helpful that you can use to run to quickly find which datastore is attached to the NAA ID:


get-datastore |
Where-Object { $_.extensiondata.info.vmfs.extent.diskname -eq “NAA_ID of the Datastore”}

It returns the matching datastore name similar to this one:

get-datastore | Where-Object { $_.extensiondata.info.vmfs.extent.d
iskname -eq "naa.60060160f12335007e8600b99aeae211"}

Name                               FreeSpaceGB      CapacityGB
----                               -----------      ----------
DATASTORE_HIGH_0                       294.117       1,023.750

PowerCLI shortcode to find ESXi host using a Mac Address

There might be a situation that you need to look up an ESXi host with it’s Mac address especially when troubleshooting and tracing network connectivity issues.

Although you can use RVTools report to find the matching ESXi host but sometimes PowerCLI is just there and probably easier to run a single line code to grab the required information.

You can use the below single line PowerCLI to simply find which ESXi host owns the Mac address:

Get-VMHost | Get-VMHostNetworkAdapter | 
Where-Object {$_.Mac -eq "00:25:b5:01:00:1b"} | 
Select VMHost, Name, DeviceName, Mac

If there is an ESXi host in your vCenter environment that owns that Mac address then it will retrun the Hostname and the NIC name similar to the below:

VMHost                Name               Mac
------                ----               ---
ESXi01.mylab          vmnic9             00:25:b5:01:00:1b