VMware Cloud Community
jessem
Enthusiast
Enthusiast
Jump to solution

PowerCLI Script and folder organization help

Here is the deal.

I have a 5.0 vCenter with several hundred VMs that are all neatly organized under folders in the VMs and Templates Inventory View.

I am going to build a fresh new 5.5 vCenter with a new db in parallel with my 5.0 installation.

I want to disconnect the hosts, and have them be managed by the new 5.5 vCenter.


This will kill my folder organization.

Is there a script that can export my current folder hierarchy and then import that config so the script moves the VMs to their proper folder on the 5.5 vCenter?

1 Solution

Accepted Solutions
adamjg
Hot Shot
Hot Shot
Jump to solution

jessem wrote:

Hey adamjg,

I know that line calls the csv file, maybe I'm confusing the question.  If I run that script on the new vcenter just like that, it errors out because it doesn't know where that csv file is located.  So pretend I have my csv file ready to be imported.  Call is testfile.csv.  So now, in the script, where do I enter testfile.csv so it knows where to get it from?

The only thing I did to get it to work is to do:

$datacenter = testfile.csv

in the beginning of the import script.

Am I missing somethign?

That won't actually do anything.

#Import Folders

$datacenter = "name of datacenter"

$vmfolder = Import-Csv ".\$($Datacenter)-Folders-with-FolderPath.csv" | Sort-Object -Property Path

The first line is meant to create the variable for your datacenter name.  Let's simplify it and say:

$datacenter = "MyDC"

The next line uses the import-csv cmdlet to import the csv file into the variable $vmfolder.  The context is variable = import-csv <path to file>.  In this instance it would be looking for a file named MyDC-Folders-with-FolderPath.csv.  The .\ indicates current directory. If you want to change that and not use the variable, you can just use a line such as this:

$vmfolder = Import-Csv "c:\mydir\testfile.csv" | Sort-Object -Property Path

View solution in original post

Reply
0 Kudos
12 Replies
schepp
Leadership
Leadership
Jump to solution

Hey,

of course there are scripts. And of course they were written by LucD 😉

You can find several here in the forums:

Re: Folder migration

Re: Export / Import selective Folder structure

Tim

Reply
0 Kudos
jessem
Enthusiast
Enthusiast
Jump to solution

Thanks it gave me some good tips, but it doesn't give me exactly what I am looking for.

I'm going from 5.0 vCenter and moving to a 5.5 vCenter.  Perhaps there is something newer.

Reply
0 Kudos
jessem
Enthusiast
Enthusiast
Jump to solution

Can anyone help me please?

Reply
0 Kudos
adamjg
Hot Shot
Hot Shot
Jump to solution

I've scripted a bunch of stuff for my 5.0 to 5.5 migrations, so I probably don't have the exact thing you're looking for, but I should have something you can steal from.  I will say that the poster above is correct, all this info was borrowed/stolen from LucD.  For my environment the best way to migrate is to move a host at a time, so what I do is run the first script which pulls in all VM info on a particular host:

Function Get-VMFolderPath {

  Param($VMname)

  Get-VM $VMname | Get-View | %{

  $row = "" | select Name, ResourcePool, Path

  $row.Name = $_.Name

  $row.ResourcePool = (Get-View $_.ResourcePool[0]).Name

  $current = Get-View $_.Parent

  #$path = $_.Name

  $path = $null

  do {

    $parent = $current

      if($parent.Name -ne "vm"){$path =  $parent.Name + "/" + $path}

      $current = Get-View $current.Parent

  }

  while ($current.Parent -ne $null)

  $row.Path = $path

  $report += $row

  }

$Path

}

Write-Host

$SourceHost = Read-Host "Enter the fqdn name of the 5.0 source VM Host"

Write-Host

Write-Host "Gathering a list of VMs from $SourceHost..." -ForegroundColor "Green"

Write-Host

$VMList = @()

$VMs = Get-VMHost $SourceHost | Get-VM

ForEach ($VM in $VMs) {

  $obj = "" | Select Name, Folder

  $obj.Name = $VM.Name

  $OutputPath = Get-VMFolderPath $VM.Name

  $obj.Folder = $OutputPath.Substring(0,$OutputPath.Length-1)

  $VMList += $obj

}

$VMList | Sort Name | Export-Csv .\$SourceHost-VMList.csv -NoTypeInformation -UseCulture

In my script I'm also pulling resource pool and VLAN (port group) of network adapter 1 on the VM, but I took it out to simplify things.  Then I add the 5.0 host to the 5.5 vCenter live.  In my scripts I'm doing some things to manipulate the VMs between hosts and standard/distributed switches, but if you're only worried about the folders, this should work once the host is in 5.5:

#Adds in VDS PowerCLI snap in

Add-PSSnapin VMware.VimAutomation.Vds

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 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 = $defaultVIServers

    }

    else{

      $vcs = $defaultVIServers[0]

    }

    foreach($vc in $vcs){

      foreach($strPath in $Path){

        $root = Get-Folder -Name Datacenters -Server $vc

        $strPath.Split($Separator) | %{

          $root = Get-Inventory -Name $_ -Location $root -Server $vc -NoRecursion

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

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

          }

        }

        $root | where {$_ -is [VMware.VimAutomation.ViCore.Impl.V1.Inventory.FolderImpl]}|%{

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

        }

      }

    }

  }

}

$SourceHost = Read-Host "Enter the fqdn name of the 5.0 source VM Host"

$VMs = import-csv ".\$SourceHost-VMList.csv"

ForEach ($VM in $VMs) {

  Get-VM $VM.Name | Move-VM -Destination (Get-FolderByPath -Path $VM.Folder) | Out-Null

  Write-Host "$($VM.Name) moved to Folder $($VM.Folder)." -ForegroundColor "Green"

  Write-Host

}

If you want a script to export/import folder structures, try this for exporting from 5.0:

$datacenter = "Datacenter" #being lazy here and not prompting and auto connecting.

filter Get-FolderPath {

    $_ | Get-View | % {

        $row = "" | select Name, Path

        $row.Name = $_.Name

        $current = Get-View $_.Parent

        $path = $_.Name

        do {

            $parent = $current

            if($parent.Name -ne "vm"){$path = $parent.Name + "\" + $path}

            $current = Get-View $current.Parent

        } while ($current.Parent -ne $null)

        $row.Path = $path

        $row

    }

}

#Export all folders

$report = @()

$report = get-datacenter $datacenter | Get-folder vm | get-folder | Get-Folderpath

        #Replace the top level with vm

        foreach ($line in $report) {

        $line.Path = ($line.Path).Replace($datacenter + "\","vm\")

        }

$report | Sort Path | Export-Csv ".\$($datacenter)-Folders-with-FolderPath.csv" -NoTypeInformation

And this to import into 5.5:

#Import Folders

$vmfolder = Import-Csv ".\$($Datacenter)-Folders-with-FolderPath.csv" | Sort-Object -Property Path

foreach($folder in $VMfolder){

    $key = @()

    $key =  ($folder.Path -split "\\")[-2]

    if ($key -eq "vm") {

        get-datacenter $datacenter | get-folder vm | New-Folder -Name $folder.Name

    }

  else {

        get-datacenter $datacenter | get-folder vm | get-folder $key | New-Folder -Name $folder.Name

    }

}

Hope this helps!

jessem
Enthusiast
Enthusiast
Jump to solution

Hey, having problems with importing into my target 5.5 vcenter.

I have the file I want to import called "Lab 03-Folders-with-FolderPath.csv"

But according to the import script, WHERE exactly am I placing this into?

#Import Folders

$vmfolder = Import-Csv ".\$($Datacenter)-Folders-with-FolderPath.csv" | Sort-Object -Property Path

foreach($folder in $VMfolder){

    $key = @()

    $key =  ($folder.Path -split "\\")[-2]

    if ($key -eq "vm") {

        get-datacenter $datacenter | get-folder vm | New-Folder -Name $folder.Name

    }

  else {

        get-datacenter $datacenter | get-folder vm | get-folder $key | New-Folder -Name $folder.Name

    }

}

Reply
0 Kudos
adamjg
Hot Shot
Hot Shot
Jump to solution

jessem wrote:

Hey, having problems with importing into my target 5.5 vcenter.

I have the file I want to import called "Lab 03-Folders-with-FolderPath.csv"

But according to the import script, WHERE exactly am I placing this into?

#Import Folders

$vmfolder = Import-Csv ".\$($Datacenter)-Folders-with-FolderPath.csv" | Sort-Object -Property Path

foreach($folder in $VMfolder){

    $key = @()

    $key =  ($folder.Path -split "\\")[-2]

    if ($key -eq "vm") {

        get-datacenter $datacenter | get-folder vm | New-Folder -Name $folder.Name

    }

  else {

        get-datacenter $datacenter | get-folder vm | get-folder $key | New-Folder -Name $folder.Name

    }

}

Are you talking about where to put the CSV file?  The .\ indicates the current directory.  So basically whatever directory you run the script from.  Let me know if you're looking for something else.

Reply
0 Kudos
jessem
Enthusiast
Enthusiast
Jump to solution

No I was referring to where the script is calling the csv file?

Is it like this?

#Import Folders

$ datacenter = "name of datacenter"

$vmfolder = Import-Csv ".\$($Datacenter)-Folders-with-FolderPath.csv" | Sort-Object -Property Path

foreach($folder in $VMfolder){

    $key = @()

    $key =  ($folder.Path -split "\\")[-2]

    if ($key -eq "vm") {

        get-datacenter $datacenter | get-folder vm | New-Folder -Name $folder.Name

    }

  else {

        get-datacenter $datacenter | get-folder vm | get-folder $key | New-Folder -Name $folder.Name

    }

}

Reply
0 Kudos
adamjg
Hot Shot
Hot Shot
Jump to solution

This is the line that imports the CSV file:

$vmfolder = Import-Csv ".\$($Datacenter)-Folders-with-FolderPath.csv" | Sort-Object -Property Path

Reply
0 Kudos
jessem
Enthusiast
Enthusiast
Jump to solution

Hey adamjg,

I know that line calls the csv file, maybe I'm confusing the question.  If I run that script on the new vcenter just like that, it errors out because it doesn't know where that csv file is located.  So pretend I have my csv file ready to be imported.  Call is testfile.csv.  So now, in the script, where do I enter testfile.csv so it knows where to get it from?

The only thing I did to get it to work is to do:

$datacenter = testfile.csv

in the beginning of the import script.

Am I missing somethign?

Reply
0 Kudos
adamjg
Hot Shot
Hot Shot
Jump to solution

jessem wrote:

Hey adamjg,

I know that line calls the csv file, maybe I'm confusing the question.  If I run that script on the new vcenter just like that, it errors out because it doesn't know where that csv file is located.  So pretend I have my csv file ready to be imported.  Call is testfile.csv.  So now, in the script, where do I enter testfile.csv so it knows where to get it from?

The only thing I did to get it to work is to do:

$datacenter = testfile.csv

in the beginning of the import script.

Am I missing somethign?

That won't actually do anything.

#Import Folders

$datacenter = "name of datacenter"

$vmfolder = Import-Csv ".\$($Datacenter)-Folders-with-FolderPath.csv" | Sort-Object -Property Path

The first line is meant to create the variable for your datacenter name.  Let's simplify it and say:

$datacenter = "MyDC"

The next line uses the import-csv cmdlet to import the csv file into the variable $vmfolder.  The context is variable = import-csv <path to file>.  In this instance it would be looking for a file named MyDC-Folders-with-FolderPath.csv.  The .\ indicates current directory. If you want to change that and not use the variable, you can just use a line such as this:

$vmfolder = Import-Csv "c:\mydir\testfile.csv" | Sort-Object -Property Path

Reply
0 Kudos
jessem
Enthusiast
Enthusiast
Jump to solution

Perfect - that's exactly what I was looking for - thanks.

Reply
0 Kudos
jterryii
Contributor
Contributor
Jump to solution

I've seen several noble attempts out there to export and re-create folders but these rock!!  They worked perfectly!! Thank you!!

Reply
0 Kudos