PowerCLI to Generate Nested VM Folder Structure

We are currently starting to plan for a disaster recovery test, and the first part is configuring Site Recovery Manager (SRM). We are still in the middle of the infrastructure replacement, so we are starting from scratch with everything. So for SRM to work the best we need to have identical folder structures in both locations.

The folder structure in our main vSphere data center has 555 folders, which most of them are nested folders. I need to figure out a way to create an identical copy of this structure in our recovery site. This was isn’t an easy feat, but give me a PowerShell and PowerCLI, and I’ll figure it out.

Gather the Folder Structure to be Generated

Before taking the time to write any script, I normally google the issue to see if anyone else has ran into the issue. No sense writing a script that has already been done. So I found a way to pull the folder structure using a script wrote by Luc Dekens.

http://www.lucd.info/2010/10/21/get-the-folderpath/

Using this function that Luc wrote, I was able to export the folder structure from vSphere using the following script.

Get-folder -type VM | Foreach {($_ | Get-FolderPath).Path | Out-file C:\scripts\logs\Folders.txt -Append}

Example of the output from the script above:

Making the Folders

So now that I have the folder structure in a text file, I can start the new folder creation, right? How?

There is a PowerCLI command, New-Folder. This is a great start, but how do I feed it my output from the last script to make the folders structure. I can read the file into a script, but I’ll then need to split the folders at the ‘\’, which isn’t difficult. Its making the nested folders that is the tricky part as I have multiple folders with the same name. For example, I have 24 folders with the name UAT, so if i just run Get-folder -name ‘UAT’, the results are not ideal as seen below.

In order to be able to target the correct folder when creating the nested folders, I’ll need to be able to determine the parent folder. Then if the parent folder to that is not a root folder, I’ll need to know the parent to that folder and so on. My head is spinning just thinking of this.

Are you my parent?

To get the parent of a folder you will just need to enumerate additional information when running the Get-Folder command.

So there are 2 different ways to target the parent folder, using the ID or the name. I prefer to use the ID as it is a unique identifier so I don’t have issues once I get deep into the nested folders by targeting the incorrect folder.

The Script that Makes Nests

Below is the script that creates the nested folders.

$ErrorActionPreference = 'SilentlyContinue' $folders = get-content C:\scripts\logs\folders.txt Foreach ($Folder in $folders){ $Path = $folder $SplitPath = $Path.split('\') $SplitPath = $SplitPath | Where {$_ -ne "DataCenterName"} Clear-Variable Folderpath Clear-Variable Parent Foreach ($directory in $SplitPath){ If ($Folderpath -ne $Null){ IF ($(Get-folder $directory | Where Parentid -eq $($Folderpath.id)) -eq $Null){ Write-Host "Generating new folder $directory" -ForegroundColor Green -BackgroundColor Black Get-Folder -id $parent | New-Folder $directory } Else{ Write-host "Folder $directory Exists!" -ForegroundColor Magenta -BackgroundColor Black $Folderpath = Get-Folder $directory | Where Parentid -eq $($Folderpath.id) $Parent = $Folderpath.Id } } Else { $FolderExist = Get-folder -Name $directory IF ($FolderExist -eq $Null){ Write-host "Generating new folder $directory" -ForegroundColor DarkGreen -BackgroundColor Black New-folder -Name $directory -Location VM $Folderpath = Get-folder $directory } Else{ Write-host "Folder $directory Exists!" -ForegroundColor DarkMagenta -BackgroundColor Black $Folderpath = Get-Folder $directory $Parent = $Folderpath.Id } } } }

There is the script in all of its glory.

-Stuart