mhops
Enthusiast
Enthusiast

Move VMs to specific folder based on Custom Attribute

Jump to solution

Hello,

I'm just starting my learning journey in scripting at Powercli and I'm currently writing one to move VMs from anywhere at the Datacenter level to a specific folder inside the same Datacenter that matches the "Value" of a specific custom attribute, at the VM. The idea is to run this script once and a while to sort the VMs at the correct folder based on the VM Custom Attributes field.

I have many Datacenter inside the same vCenter and each Datacenter has the same structure of folders (i.g. production, development, infrastructure ) The idea is to move the VM for the specific folder set the Custom Attribute and if the "Value" is empty or does not match whit any folder name it should move the VM to the "Discovered virtual machines" folder. I have tried some functions from LucD​ and It gave some good ideas, but I could not implement it well.

When I run the script for singles machines it seems to work, but when the CSV file has a more than one VM of fields it behavior unexpectedly. I'm sure my script is full of mistakes, but I'm trying.

get-vm | get-annotation -customattribute "VM Folder" | Select-Object annotatedentity, value | Export-Csv -Path C:\Users\mhops\Documents\movevms\attributes.csv –NoTypeInformation

Import-Csv C:\Users\mhops\Documents\movevms\attributes.csv -UseCulture | %{

$vm = Get-VM -Name $_.AnnotatedEntity | Select-Object Name

$folder = Get-Folder -Name $_.Value

$dc = Get-View -ViewType VirtualMachine -filter @{ "name" = $vm.Name} | Select-Object -Property Name,

@{ Label = "Datacenter"; Expression = { (Get-view (Get-View (Get-view $_.parent).parent).Parent).name } } | Select-Object Datacenter

$path = Get-Datacenter -Name $dc.Datacenter | Get-Folder -Name $folder

$pathdefault = Get-Datacenter -Name $dc.Datacenter | Get-Folder -Name "Discovered virtual machine"

    if (!$folder.Value) {

   

    Move-VM -VM $vm.Name -InventoryLocation $pathdefault

   

    }

else {

      Move-VM -VM $vm.Name -InventoryLocation $path

    }

}


Thanks for your help

1 Solution

Accepted Solutions
LucD
Leadership
Leadership

Try like this

Get-VM -PipelineVariable vm | Get-Annotation -CustomAttribute 'VM Folder' |

Select-Object @{N='VM';E={$vm.Name}}, Value |

Export-Csv -Path C:\Users\mhops\Documents\movevms\attributes.csv –NoTypeInformation

Import-Csv C:\Users\mhops\Documents\movevms\attributes.csv -UseCulture | %{

    $vm = Get-VM -Name $_.VM

    $dc = Get-Datacenter -VM $vm

    if($_.Value -ne ''){

        $path = Get-Folder -Name $_.Value -Location $dc

        if(-not $path){

            $path = Get-Folder -Name 'Discovered virtual machine' -Location $dc

        }

    }

    else{

        $path = Get-Folder -Name 'Discovered virtual machine' -Location $dc

    }


    if ($vm.Folder.Name -ne $path.Name) {

        Move-VM -VM $vm -InventoryLocation $path -Confirm:$false

    }

}


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

View solution in original post

10 Replies
LucD
Leadership
Leadership

Try something like this.
This does not change the Custom Attribute, only moves the VM to the folder (if not already there).

Get-VM -PipelineVariable vm | Get-Annotation -CustomAttribute 'VM Folder' |

Select-Object @{N='VM';E={$vm.Name}}, Value |

Export-Csv -Path C:\Users\mhops\Documents\movevms\attributes.csv –NoTypeInformation

Import-Csv C:\Users\mhops\Documents\movevms\attributes.csv -UseCulture | %{ 

    $vm = Get-VM -Name $_.VM

    $dc = Get-Datacenter -VM $vm

  

    if($_.Value -ne ''){

        $path = Get-Folder -Name $_.Value -Location $dc

    }

    else{

        $path = Get-Folder -Name 'Discovered virtual machine' -Location $dc

    }


    if ($vm.Folder.Name -ne $path.Name) { 

        Move-VM -VM $vm -InventoryLocation $path -Confirm:$false

    }

}


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

mhops
Enthusiast
Enthusiast

Thanks for your lightspeed reply LucD​, that worked like a charm :smileyblush::smileycheck:

In fact, I don't need to change the Custom Attributes, I did express myself wrong at my last post.

The Values are already set to match the folder's name or in some cases, they might be a random Value or wrong Value.

  • Seems that those VMs which Custom Attributes which Value does not match with any folders are not been affected. I would like to also sort those VMs to "Discovered virtual machine" or any other folder as "Other" for example.  (i.e. the VM has has a Values of "lab" but there's no "lab" foder, sou it goes to "Discovered virtual machine" as well )

  • Also for some reason, the VMs in powered off state does not move, only if I leave them powered on. ( this is more a cosmetic need since most of the time the VMs will be ON )

 

I'm a big fan of you and all work you have done contributing to the PowerCli community. I really appreciate your support and I'm learning a lot with your posts.

Regards

0 Kudos
LucD
Leadership
Leadership

The powerstate of a VM should have no impact on whether or not it can be moved to a folder.

Did you try to move one of those VMs manually or directly with the Move-VM cmdlet?

Did that work?


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

0 Kudos
mhops
Enthusiast
Enthusiast

When I try to move the VM which is powered off using the Move-VM cmdlet it shows this error:

Move-VM -VM vm-lab-01 -InventoryLocation $path -Confirm:$false

Move-VM : 2020-09-03 10:22:24 AM Move-VM Index was outside the bounds of the array.

At line:5 char:3

+   Move-VM -VM vm-lab-01 -InventoryLocation $path -Confirm:$false

+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [Move-VM], VimException

    + FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.MoveVM

However, when I power it on, it does work perfectly. The same behavior happens for all powered off VMs. When I move manually (drag-drop on UI) it works as expected.

Something else that I could not figure out:  The way it's right now, the VMs which custom attribute does not match any folder, are not affected and they stay where they are, however I would like those VMs which Value on a custom attribute does not match any folder also been moved to "Discovered virtual machines". How can I filter that?ks

Thank you so much for your help!

0 Kudos
LucD
Leadership
Leadership

Which PowerCLI version are you using?
This is an error that I know from older PowerCLI versions.


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

0 Kudos
mhops
Enthusiast
Enthusiast

I guess this is the latest one.

PowerCLI Version

----------------

   VMware PowerCLI 12.0.0 build 15947286

---------------

Component Versions

---------------

   VMware Common PowerCLI Component 12.0 build 15939652

   VMware Cis Core PowerCLI Component PowerCLI Component 12.0 build 15939657

   VMware VimAutomation VICore Commands PowerCLI Component PowerCLI Component 12.0 build 15939655

   VMware VimAutomation Storage PowerCLI Component PowerCLI Component 12.0 build 15939648

   VMware VimAutomation Vds Commands PowerCLI Component PowerCLI Component 12.0 build 15940185

   VMware vSphere Update Manager PowerCLI 6.5 build 7862888

0 Kudos
LucD
Leadership
Leadership

That is indeed the latest version.

Do these VMs that produce the error happen to have long Displaynames?

See move-vm returns array out of bounds


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

0 Kudos
mhops
Enthusiast
Enthusiast

Thanks for sharing the other thread,  did a test whit a new VM called VM-TMP and the behavior is the same:

- when powered off does not move ( Index was outside the bounds of the array.)

- when powered on it moves as expected

Well... it seems to be a bug, but honestly, it has no much impact since most of VMs are in fact powered on, so not a big deal anyways.

In fact, I was wondering more about how to add to the script a way to move as well the VMs which custom attribute value does not match any folder, I would like those VMs to be also moved to "Discovered virtual machines". ( or any other folder I designated for VM's which Value does not fit any folder )

Regards

0 Kudos
LucD
Leadership
Leadership

Try like this

Get-VM -PipelineVariable vm | Get-Annotation -CustomAttribute 'VM Folder' |

Select-Object @{N='VM';E={$vm.Name}}, Value |

Export-Csv -Path C:\Users\mhops\Documents\movevms\attributes.csv –NoTypeInformation

Import-Csv C:\Users\mhops\Documents\movevms\attributes.csv -UseCulture | %{

    $vm = Get-VM -Name $_.VM

    $dc = Get-Datacenter -VM $vm

    if($_.Value -ne ''){

        $path = Get-Folder -Name $_.Value -Location $dc

        if(-not $path){

            $path = Get-Folder -Name 'Discovered virtual machine' -Location $dc

        }

    }

    else{

        $path = Get-Folder -Name 'Discovered virtual machine' -Location $dc

    }


    if ($vm.Folder.Name -ne $path.Name) {

        Move-VM -VM $vm -InventoryLocation $path -Confirm:$false

    }

}


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

mhops
Enthusiast
Enthusiast

Now It worked perfectly LucD​​! Sweet Smiley Happy

Thanks for the opportunity to follow along whit you, I could learn a lot from those examples. You're a legend.

I strong appreciate your help, have a great day! 

0 Kudos