VMware Cloud Community
umms
Enthusiast
Enthusiast
Jump to solution

Move VMs to Folders

I have exported into CSV file the VMs and the Folder Paths in format:

Name                    Path

Not having much luck importing these to move the VMs to the folder structure (which is already in place). Can anyone give me some suggestions of Code to try? Thanks.

Reply
0 Kudos
55 Replies
LucD
Leadership
Leadership
Jump to solution

Can you just list the VM folders with

Get-Folder -Type VM

And check what is in there.


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

Reply
0 Kudos
umms
Enthusiast
Enthusiast
Jump to solution

I am guessing this command shows Root and Nested Folders

PS C:\temp> Get-Folder -Type VM

Name                           Type
----                           ----
vm                             VM
UMass_Worcester                VM
UMass_Lowell                   VM
UMass_Dartmouth                VM
UMass_Boston                   VM
Discovered virtual machine     VM
Management                     VM
UMW-TEMPLATES                  VM
SCHOOL                         VM
RESEARCH                       VM
INFRASTRUCTURE                 VM
CWM                            VM
!DECOM                         VM
Facilities                     VM
Campus Servers                 VM
Hosted                         VM
Information Security           VM
Systems Engineering            VM
Kronos                         VM
Library                        VM
Graylog                        VM
IDM                            VM
License Servers                VM
WebHelpDesk                    VM
Directory Services             VM
Veeam                          VM
Decommission                   VM
UCAPS                          VM
Tableau                        VM
Templates                      VM
Temp-Backup-Folder             VM
Network Services               VM
Platforms                      VM
Sandbox                        VM
Web Office                     VM

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Correct.
Now just try (mind the spelling and don't add spaces).

Get-Datacenter -Name UMASSHS | Get-Folder -Name 'Discovered virtual machine'

But I think the basic issue with the original script I gave is the fact the VM's Displayname is in the FolderName column.

Can you try this updated version of the short test I gave earlier?

$destVI = Read-Host "Please enter name or IP address of the vCenter"

$creds = Get-Credential -Message 'Enter credentials for $destVI'

$datacenter = Read-Host 'Please enter name of the Datacenter'

Connect-VIServer -server $destVI -Credential $creds


Import-Csv "c:\csv-files\04-$($datacenter)-vms-with-FolderPath.csv" |

ForEach-Object -Process {

    Write-Host -"Folder $($_.FolderName)"

    $path = $_.FolderName.Replace($_.VMName,'').TrimStart('\').TrimEnd('\')

    Get-FolderByPath -Path path

}


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

Reply
0 Kudos
umms
Enthusiast
Enthusiast
Jump to solution

Not having much luck on this forum posting consistently. I attached screenshot.

HEre is the test i ran:

$destVI = Read-Host " Please enter name or IP address of the vCenter "
$creds = Get-Credential -Message 'Enter credentials for $destVI'
$datacenter = Read-Host 'Please enter name of the Datacenter'

Connect-VIServer -server $destVI -Credential $creds

Import-Csv "c:\csv-files\04-$($datacenter)-vms-with-FolderPath.csv" |

ForEach-Object -Process {

    Write-Host -"Folder $($_.FolderName)"

    $path = $_.FolderName.Replace($_.VMName,'').TrimStart('\').TrimEnd('\')

    Get-FolderByPath -Path path

}

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

To make sure, the 2 columns in the CSV file are named VMName and FolderName?

And there are no blank lines in the CSV?


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

Reply
0 Kudos
umms
Enthusiast
Enthusiast
Jump to solution

Yes. VMName and FolderPath

The only blank spaces are in VM names.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, one more script to check the values, before I give up.
What does this return?

$destVI = Read-Host "Please enter name or IP address of the vCenter"

$creds = Get-Credential -Message 'Enter credentials for $destVI'

$datacenter = Read-Host 'Please enter name of the Datacenter'

Connect-VIServer -server $destVI -Credential $creds


Import-Csv "c:\csv-files\04-$($datacenter)-vms-with-FolderPath.csv" |

ForEach-Object -Process {

    Write-Host "VM $($_.VMName)"

    Write-Host "Folder $($_.FolderName)"

    $path = $_.FolderName.Replace($_.VMName,'').TrimStart('\').TrimEnd('\')

    Write-Host "Path $path"

    Get-FolderByPath -Path $path

}


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

Reply
0 Kudos
umms
Enthusiast
Enthusiast
Jump to solution

Looks like the furthest yet.... Screenshot attached.
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

There is nothing the FolderName property/column.


I'm afraid I can't check anything more without actually having access to the CSV.


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

Reply
0 Kudos
umms
Enthusiast
Enthusiast
Jump to solution

I sent you a slimmed down one via CSV
Reply
0 Kudos
umms
Enthusiast
Enthusiast
Jump to solution

Sorry I mean via email. I also just attached the ps1 that i used to EXTRACT the folders
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, two things.

- The name of the column is FolderPath, not FolderName as you showed in your previous output

- the FolderPath does not contain the datacenter name

For the datacenter name you might want to look at my Get The Folderpath function.

To fix the missing datacenter and use the correct columnname, can you try the following?

$destVI = Read-Host "Please enter name or IP address of the vCenter"

$creds = Get-Credential -Message 'Enter credentials for $destVI'

$datacenter = Read-Host 'Please enter name of the Datacenter'

Connect-VIServer -server $destVI -Credential $creds


Import-Csv "c:\csv-files\04-$($datacenter)-vms-with-FolderPath.csv" |

ForEach-Object -Process {

    Write-Host "VM $($_.VMName)"

    Write-Host "Folder $($_.FolderPath)"

    $path = $datacenter + $_.FolderPath.Replace("\$($_.VMName)",'')

    Write-Host "Path $path"

    Get-FolderByPath -Path $path

}


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

Reply
0 Kudos
umms
Enthusiast
Enthusiast
Jump to solution

I apologize. It has been a very long night last night and day today. I had taken out DC name to test. I emailed you the proper CSV.... Does that change what you want me to test?
Reply
0 Kudos
umms
Enthusiast
Enthusiast
Jump to solution

see attached.
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

After some further analysis, the following script worked.

function Get-FolderByPath {

    <#

    .SYNOPSIS Retrieve folders by giving a path

    .DESCRIPTION The function will retrieve a folder by it's path.

    The path can contain any type of leave (folder or datacenter).

    .NOTES

    Author: Luc Dekens .PARAMETER Path The path to the folder. This is a required parameter.

    .PARAMETER

    Path The path to the folder. This is a required parameter.

    .PARAMETER

    Separator The character that is used to separate the leaves in the path. The default is '/'

    .EXAMPLE

    PS> Get-FolderByPath -Path "Folder1/Datacenter/Folder2"

    .EXAMPLE

    PS> Get-FolderByPath -Path "Folder1>Folder2" -Separator '>'

    #>

    param(

        [CmdletBinding()]

        [parameter(Mandatory = $true)]

        [System.String[]]${Path},

        [char]${Separator} = '/'

    )

    process {

        if ((Get-PowerCLIConfiguration).DefaultVIServerMode -eq "Multiple") {

            $vcs = $global:defaultVIServers

        }

        else {

            $vcs = $global:defaultVIServers[0]

        }

        foreach ($vc in $vcs) {

            $si = Get-View ServiceInstance -Server $vc

            $rootName = (Get-View -Id $si.Content.RootFolder -Property Name).Name

            foreach ($strPath in $Path) {

                $root = Get-Folder -Name $rootName -Server $vc -ErrorAction SilentlyContinue

                $strPath.Split($Separator) | ForEach-Object {

                    $root = Get-Inventory -Name $_ -Location $root -Server $vc -ErrorAction SilentlyContinue

                    if ((Get-Inventory -Location $root -NoRecursion | Select-Object -ExpandProperty Name) -contains "vm") {

                        $root = Get-Inventory -Name "vm" -Location $root -Server $vc -NoRecursion

                    }

                }

                $root | Where-Object { $_ -is [VMware.VimAutomation.ViCore.Impl.V1.Inventory.FolderImpl] } | ForEach-Object {

                    Get-Folder -Name $_.Name -Location $root.Parent -NoRecursion -Server $vc

                }

            }

        }

    }

}

  

Import-Module -Name VMware.PowerCLI

If ($globale:DefaultVIServers) {

    Disconnect-VIServer -Server $global:DefaultVIServers -Force -ErrorAction SilentlyContinue

}


$destVI = Read-Host "Please enter name or IP address of the vCenter"

$creds = Get-Credential -Message 'Enter credentials for $destVI'

$datacenter = Read-Host 'Please enter name of the Datacenter'

Connect-VIServer -server $destVI -Credential $creds


# move the vm's to correct location

Import-Csv "c:\csv-files\04-$($datacenter)-vms-with-FolderPath.csv" |

ForEach-Object -Process {

    $pathStr = $_.FolderPath.Replace("\$($_.VMName)",'').TrimStart('\')

    $folder = Get-FolderByPath -Path $pathStr -Separator '\'

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

    Move-VM -VM $vm -Destination $vm.VMHost -InventoryLocation $folder -Confirm:$false

}


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

Reply
0 Kudos
umms
Enthusiast
Enthusiast
Jump to solution

Thank you for all your help!!!!!!!
Reply
0 Kudos