Finding VMs on Standard Switches
One of my customers recently moved from standard vSwitches over to distributed vSwitches. After performing the move, they deleted all of the standard vSwitches from the environment. Unfortunately, a few weeks later it turned out that a few VMs had adapters that, for whatever reason, hadn't been moved over to the vDS and so I was tasked with finding any VM that might still be associated with the old (now deleted) standard vSwitches.
This was an interesting challenge, as my normal approach to finding all VMs on a given vSwitch would be to simply loop through every host, get the specific vSwitch and then get all VMs on that vSwitch. Since these vSwitches had already been deleted, that approach wouldn't work. Eventually, I came up with this command:
get-vm | % {if (($_ | get-virtualswitch).name -eq $null){$_.name}}
This gets all of the VMs in the inventory. For each VM, it then checks what vSwitch the VM is attached to. I found that when the VM only uses a vSwitch that no longer exists, the system returns a null reference when you request that vSwitch name. So, I wrote this to output the VM name if the vSwitch name is null. Unfortunately, further testing revealed that a VM on multiple vSwitches (both the new vDS and the old VSS) was not quite so easy to identify through this method, and so I ended up writing a slightly more complicated script.
This script works in a similar fashion, however instead of checking the vSwitch that the VM is associated with (which just doesn't return anything if the vSwitch no longer exists, hence my null check earlier), it checks each adapter on the VM and checks if they are connected to a distributed port group. If the get-vdportgroup cmdlet throws an error (which I have redirected into the $errVar variable via the -errorVariable option), the script reports that VM.
#Finds all VMs (and Templates) in an environment that are still attached to Standard vSwitches
$allVMs = get-vm
$allVMs += get-template
foreach ($thisVM in $allVMs)
{
#clears the error variable from the previous VM, then attempts to get a list of Distributed Port Groups that the VM uses and checks for null network names
$errVar = ""
#Ensure that the VM has a NIC before proceeding, ignore it if it doesn't
if (($thisVM | get-networkadapter).count -lt 1)
{
#echo "$($thisVM.name) has no NIC"
}
else
{
#If the VM has an adapter that isn't Distributed, check the type of error. If it's the expected one, report the VM otherwise report the exception.
get-vdportgroup ($thisVM | get-networkadapter).networkName -errorAction silentlycontinue -errorVariable errVar > $null
if ($errVar -ne "")
{
if ($errVar.Exception.message.contains("not found"))
{
echo "$($thisVM.name) is not entirely on the dVS"
}
else
{
echo "Unexpected error while examining $($thisVM.name):"
$errVar.Exception.message
}
}
}
}
This was an interesting challenge, as my normal approach to finding all VMs on a given vSwitch would be to simply loop through every host, get the specific vSwitch and then get all VMs on that vSwitch. Since these vSwitches had already been deleted, that approach wouldn't work. Eventually, I came up with this command:
get-vm | % {if (($_ | get-virtualswitch).name -eq $null){$_.name}}
This gets all of the VMs in the inventory. For each VM, it then checks what vSwitch the VM is attached to. I found that when the VM only uses a vSwitch that no longer exists, the system returns a null reference when you request that vSwitch name. So, I wrote this to output the VM name if the vSwitch name is null. Unfortunately, further testing revealed that a VM on multiple vSwitches (both the new vDS and the old VSS) was not quite so easy to identify through this method, and so I ended up writing a slightly more complicated script.
This script works in a similar fashion, however instead of checking the vSwitch that the VM is associated with (which just doesn't return anything if the vSwitch no longer exists, hence my null check earlier), it checks each adapter on the VM and checks if they are connected to a distributed port group. If the get-vdportgroup cmdlet throws an error (which I have redirected into the $errVar variable via the -errorVariable option), the script reports that VM.
#Finds all VMs (and Templates) in an environment that are still attached to Standard vSwitches
$allVMs = get-vm
$allVMs += get-template
foreach ($thisVM in $allVMs)
{
#clears the error variable from the previous VM, then attempts to get a list of Distributed Port Groups that the VM uses and checks for null network names
$errVar = ""
#Ensure that the VM has a NIC before proceeding, ignore it if it doesn't
if (($thisVM | get-networkadapter).count -lt 1)
{
#echo "$($thisVM.name) has no NIC"
}
else
{
#If the VM has an adapter that isn't Distributed, check the type of error. If it's the expected one, report the VM otherwise report the exception.
get-vdportgroup ($thisVM | get-networkadapter).networkName -errorAction silentlycontinue -errorVariable errVar > $null
if ($errVar -ne "")
{
if ($errVar.Exception.message.contains("not found"))
{
echo "$($thisVM.name) is not entirely on the dVS"
}
else
{
echo "Unexpected error while examining $($thisVM.name):"
$errVar.Exception.message
}
}
}
}
Comments
Post a Comment
Sorry guys, I've been getting a lot of spam recently, so I've had to turn on comment moderation. I'll do my best to moderate them swiftly after they're submitted,