VMware Cloud Community
TheVMinator
Expert
Expert

Filtering an array of VMs based on name similarities

I have an array of VMs called $VMs from my current vCenter Server.

  • These VMs might have been migrated from my old vCenter server.
  • If they were migrated I want to remove them from my array.
  • If they were migrated from my old vCenter Server, they might have had their name changed. 

For example, in the $vms array there is a VM called:

bigvm1

which is running in my new vCenter Server.  I want to see if it was migrated from my old vcenter server.  If it was migrated from my old vcenter server, it would be in there with a name matching a pattern like this:

bigvm1_old

bigvm1

bigvm1_toberemoved

In other words, the name might be the same, or it might have characters added, but it won't have characters subtracted.

How do I cycle through the $vms array, and check if the VM was migrated from the old vcenter, and if so, remove it from the $vms array?

Reply
0 Kudos
9 Replies
RvdNieuwendijk
Leadership
Leadership

I assume you have an array $vmsold containing the vm objects of the old vCenter Server. Then you can use the following script to remove the vm's migrated from the old vCenter Server from the $vms array. The script loops through both lists and only returns the vm's in $vms that are not in $vmsold. It uses a wildcard to search for the vm's with characters added to their name.

$vms = foreach ($vm in $vms) {

  $vm |

  Where-Object {

    -not ($vmsold |

            ForEach-Object {

              if ($_.Name -like "$($vm.Name)*")

              {

                $_

              }

            }

          )

  }

}

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition
LucD
Leadership
Leadership

You could also do

$vms = $vms | where {$_.Name -notmatch "^bigvm1"}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
RvdNieuwendijk
Leadership
Leadership

Your example will only work for a vm named bigvm1. However, on the old vCenter Server there are also other vm's that might be migrated. The script should check for these vm's also, as does my script.

In my script you could use -notmatch instead of the -like operater. As always there are multiple ways to solve a problem.

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition
LucD
Leadership
Leadership

If there are multiple basenames, you can do

$vms = $vms | where {$_.Name -notmatch "^bigvm1|^another1|^andyetanother"}

If the to-be-excluded basenames are available, you can even create this RegEx expression by code.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
TheVMinator
Expert
Expert

OK thanks.  I'm starting with an array of objects.  This array contains VMs, but for each vm it has a number of custom properties.  Will these solutions allow me to retain the custom properties of each VM in the array?

For example, in the code below, the $vms array is an array of VMs but each VM has a number of custom properties.  Will the custom properties still be there after I do the operations below?

$vms = foreach ($vm in $vms) {

  $vm |

  Where-Object {

    -not ($vmsold |

            ForEach-Object {

              if ($_.Name -like "$($vm.Name)*")

              {

                $_

              }

            }

          )

  }

}


Reply
0 Kudos
TheVMinator
Expert
Expert

I think you are correct, because I have a whole array of VMs that might have a corresponding old VM in the old vcenter.  I can't hard code only the name of one VM in my code and only check for that one VM name in the old enviornment.  My code has to be able to cycle through a whole list of VMs from the new environment and see if there is a corresponding vm in the old.  So I think I have to use something that doesn't hard code the VM name I am looking for.

Reply
0 Kudos
LucD
Leadership
Leadership

Like I remarked, you can code the creation of the RegEx expression.

Something like this

$expression = [string]::Join('|',($newVMs | %{"^$($_.Name)"}))

It assumes the $newVMs array holds all the VMs you want to filter out.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
TheVMinator
Expert
Expert

ok thanks - what would the whole code look like if I did that?

Reply
0 Kudos
LucD
Leadership
Leadership

Something like this

$expression = [string]::Join('|',($newVMs | %{"^$($_.Name)"}))

$vms = $vms | where {$_.Name -notmatch $expression}

But it depends where you have an array of VMs to exclude (I assume they are in the array $newVMs)


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos