VMware Cloud Community
BostonTechGuy
Enthusiast
Enthusiast
Jump to solution

Creating Folder Structure

Trying to find a quick way to import all the VM & Templates (aka BLUE Folders) from Site A to Site B.  Each Site has its own vCenter with multiple "Datacenters" located inside.  I just want all the folders and subfolders of one Datacenter.. Now that explained here's whats happening

Exporting Site A folders using this line of code is working perfectly:

Get-Datacenter "Datacenter1" | Get-Folder | Get-FolderPath | Export-Csv "C:\Scripts\learning\folders.csv" -NoTypeInformation

I get a nice CSV file with NAME and PATH headings with all the names and paths of each folder.

Now when I try to Create the folders at Site B, it doesnt work most of the time. All these failed:

Import-Csv $importlist -UseCulture | %{

    New-Folder -Name $_."Name" -Location $_."Path"

}

Import-Csv $importlist -UseCulture | %{

    New-Folder -Name $_."Name" -Location (Get-Folder -Name $_."Path")

}

Import-Csv $importlist -UseCulture | %{

    New-Folder -Name $_."Name" -Location (Get-Datacenter "Datacenter1" | Get-Folder -Name $_."Path")

}

Now.. if I do that last script AND remove "DATACENTER1" from the cell in CSV file under Path, the root folders get created.  Still no joy on the subfolders.

Now I have reviewed other code in other posts on this site.  And several from "some of people who are on this site offen and wrote some books" (you know who you are Smiley Wink ).  None of them work for me.  All I need is to have several hundred (yes hundred) folders created with multi-sub levels deep.  Some case 5 or 6 levels deep.. IE:  DATACENTER\VM\ROOT FOLDER\ SUB LEVEL1\SUB LEVEL2\SUB LEVEL3\SUB LEVEL4\ <here be vms>

Thanks,

Boston Tech Guy

Tags (1)
Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Ok, try this updated version

$root = Get-Folder -Name Datacenters
$folders= Import-Csv C:\folder.csv -UseCulture
$folders |
where {"vm","host","network","datastore" -notcontains $_.Name} |
Sort-Object -Property {(Select-String -InputObject $_.Path -Pattern '\\+' -AllMatches).Matches.Count} | %{
   
$location = $root
   
$qualifiers = $_.Path.Split('\')
   
$qualifiers[0..($qualifiers.Count -2)] | %{
       
$location = Get-Inventory -Name $_ -Location $location -NoRecursion
       
if($location.EXtensionData -is [VMware.Vim.Datacenter]){
         
$location = Get-Folder -Name vm -Location $location
        }
    }
   
New-Folder -Name $_.Name -Location $location
}


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

View solution in original post

Reply
0 Kudos
21 Replies
LucD
Leadership
Leadership
Jump to solution

The New-Folder cmdlet unfortunately doesn't allow to specify a folderpath for the Location parameter.

But you could try something like this

$root = Get-Folder -Name Datacenters
Import-Csv $importlist -UseCulture |
Sort-Object -Property {(Select-String -InputObject $_.Path -Pattern '/+' -AllMatches).Matches.Count} | %{
   
$location = $root
   
$qualifiers = $_.Path.Split('/')
   
$qualifiers[0..($qualifiers.Count -2)] | %{
       
$location = Get-Inventory -Name $_ -Location $location
    }
   
New-Folder -Name $qualfiers[-1] -Location $location
}

We start in the 'root' of the vCenter.

The script first take the folders with shortest path.

It follows all the qualifiers in the Path, except for the last one, which is the new folder.


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

Reply
0 Kudos
BostonTechGuy
Enthusiast
Enthusiast
Jump to solution

Still getting errors.  Also my editor is not recognizing some of the strings used in the code above.  Here is what PowerGUI shows for the code


$root = Get-Folder -Name Datacenters
Import-Csv $importlist -UseCulture |
Sort-Object -Property {(Select-String -InputObject $_.Path -Pattern '/+' -AllMatches).Matches.Count} | %{
   
$location = $root
   
$qualifiers = $_.Path.Split('/')
   
$qualifiers[0..($qualifiers.Count -2)] | %{
       
$location = Get-Inventory -Name $_ -Location $location
    }
   
New-Folder -Name $qualfiers[-1] -Location $location
}

The script you have provided is above my knowledge to understand without some help.  The errors I am getting back are:

Get-Inventory : 8/5/2013 11:24:07 AMGet-Inventory    Inventory with name 'vm\FolderTest' was not found using the specified

filter(s).   

At C:\Users\##########\AppData\Local\Temp\a3e47d9d-2312-40d2-8767-bd6fea574ca1.ps1:17 char:21

+     $location = Get-Inventory -Name $_ -Location $location
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo      : ObjectNotFound: (:) [Get-Inventory], VimException

+ FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetInventory

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I used the Get-Inventory cmdlet because it can return any object by name from your vSphere hierarchy.

In the Path that is imported from the CSV there can be different type of nodes in there; datacenter, folder...

The Path content is deconstructed in separate qualifiers. The script starts on the left and stores the object in the $location variable.

For the last qualifier in the Path, the script assumes it is a Folder, and so it creates the folder.

The error seems to come from the Path with value vm\FolderTest.

That is apparently a folder created in the root of the vSphere hierarchy.

I find it strange that the Path seems to contain a back-slash, I would assume that the Path only has forward-slashes.

What do you see in the CSV file ? Back- or forward-slash ?

If it is all back-slashes, the argument for the Split method has to be changed to '/'.


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

Reply
0 Kudos
BostonTechGuy
Enthusiast
Enthusiast
Jump to solution

That is interesting... The output in the CSV file from my Export Script above is this:

#TYPE Selected.System.String
NamePath
vmDATACENTER1\vm
networkDATACENTER1\network
hostDATACENTER1\host
datastoreDATACENTER1\datastore
SecurityDATACENTER1\Security
FoldertestDATACENTER1\Foldertest
Test1DATACENTER1\Foldertest\Test1
Test 2DATACENTER1\Foldertest\Test 2

Clearly "\"

Now I changed the Path.Split to a backslash, got errors.  Changed all the forward slashes in quotes to backslashes, got errors... They were all the same

Cannot index into a null array.

At C:\Users\\########\AppData\Local\Temp\a3e47d9d-2312-40d2-8767-bd6fea574ca1.ps1:19 char:5

+     New-Folder -Name $qualfiers[-1] -Location $location

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

    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException

    + FullyQualifiedErrorId : NullArray

When back to my test CSV replaced all the backslashes with forward slashes, went back to your original code AND... got new errors:

Get-Inventory : 8/5/2013 1:36:23 PM Get-Inventory    Inventory with name 'vm' was not found using the specified filter(s).   

At C:\Users\########\AppData\Local\Temp\a3e47d9d-2312-40d2-8767-bd6fea574ca1.ps1:17 char:21

+     $location = Get-Inventory -Name $_ -Location $location
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo      : ObjectNotFound: (:) [Get-Inventory], VimException
+ FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetInventory

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Those first 4 lines are hidden system folders that are present in the vSphere hierarchy.

I should adapt the script to skip those when they are the last qualifier, since you obviously can't create them.

Try perhaps with removing lines 3-6 from the CSV (the vm, host, network and datastore lines)


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

Reply
0 Kudos
BostonTechGuy
Enthusiast
Enthusiast
Jump to solution

Already did that on the IMPORT CSV. :smileycool:  Then I created a plain testing CSV file just to get a success.  My testing CSV is listed below.

NamePath
NewTest1vm
NewSub1vm\Foldertest
NewSub2vm\Foldertest
Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, now I see where I went wrong, I assumed the CSV only had the Path column in there.

Something like this

Path

vm\NewTest1

vm\Foldertest\NewSub1

vm\Foldertest\NewSub2


I'll have to update the script.


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

Reply
0 Kudos
BostonTechGuy
Enthusiast
Enthusiast
Jump to solution

Ahhhh. OK.  Thank you.  Would it be better for me to change the CSV File?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You can give it a try with an updated CSV


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

Reply
0 Kudos
BostonTechGuy
Enthusiast
Enthusiast
Jump to solution

Just did.  No go.  Plus in the long run, that wouldnt help with all the folders that need to be created at the second location to look like the original source.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, try this updated version

$root = Get-Folder -Name Datacenters
$folders= Import-Csv C:\folder.csv -UseCulture
$folders |
where {"vm","host","network","datastore" -notcontains $_.Name} |
Sort-Object -Property {(Select-String -InputObject $_.Path -Pattern '\\+' -AllMatches).Matches.Count} | %{
   
$location = $root
   
$qualifiers = $_.Path.Split('\')
   
$qualifiers[0..($qualifiers.Count -2)] | %{
       
$location = Get-Inventory -Name $_ -Location $location -NoRecursion
       
if($location.EXtensionData -is [VMware.Vim.Datacenter]){
         
$location = Get-Folder -Name vm -Location $location
        }
    }
   
New-Folder -Name $_.Name -Location $location
}


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

Reply
0 Kudos
BostonTechGuy
Enthusiast
Enthusiast
Jump to solution

Ok got some forward movement. :smileygrin:  Still getting error messages though..  Folders at the parent level worked.  None of the subfolders.

I am using a test CSV file so not to play with production systems but everything is setup the same.  When I run my export script on my DEV Environment I get the list located below (same as what I posted previously):

#TYPE Selected.System.String
NamePath
vmDATACENTER1\vm
networkDATACENTER1\network
hostDATACENTER1\host
datastoreDATACENTER1\datastore
SecurityDATACENTER1\Security
FoldertestDATACENTER1\Foldertest
Test1DATACENTER1\Foldertest\Test1
Test 2DATACENTER1\Foldertest\Test 2

So to add new folders and sub folders to my Dev environment my test CSV file looks like this:

NamePath
NewParent1DATACENTER1\vm
NewSub1DATACENTER1\vm\Foldertest
NewSub2DATACENTER1\vm\Foldertest

With the new code that you have provided I get these error messages (they come back very very quick) on Sub Folders.  The folder NewParent1 was created.

Get-Inventory : 8/5/2013 3:52:20 PM Get-Inventory    Inventory with name 'vm' was not found using the specified filter(s).   

At C:\Users\######\AppData\Local\Temp\a3e47d9d-2312-40d2-8767-bd6fea574ca1.ps1:18 char:21

+     $location = Get-Inventory -Name $_ -Location $location -NoRecursion
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo      : ObjectNotFound: (:) [Get-Inventory], VimException
+ FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetInventory

New-Folder : 8/5/2013 3:52:20 PM New-Folder    Value cannot be found for the mandatory parameter Location   

At C:\Users\######\AppData\Local\Temp\a3e47d9d-2312-40d2-8767-bd6fea574ca1.ps1:23 char:5

+ New-Folder -Name $_.Name -Location $location
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo      : NotSpecified: (:) [New-Folder], VimException
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.NewFolder

Get-Inventory : 8/5/2013 3:52:21 PM Get-Inventory    Inventory with name 'vm' was not found using the specified filter(s).   

At C:\Users\######\AppData\Local\Temp\a3e47d9d-2312-40d2-8767-bd6fea574ca1.ps1:18 char:21

+     $location = Get-Inventory -Name $_ -Location $location -NoRecursion
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo      : ObjectNotFound: (:) [Get-Inventory], VimException
+ FullyQualifiedErrorId : Core_OutputHelper_WriteNotFoundError,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetInventory

New-Folder : 8/5/2013 3:52:21 PM New-Folder    Value cannot be found for the mandatory parameter Location   

At C:\Users\######\AppData\Local\Temp\a3e47d9d-2312-40d2-8767-bd6fea574ca1.ps1:23 char:5

+ New-Folder -Name $_.Name -Location $location
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo      : NotSpecified: (:) [New-Folder], VimException
+ FullyQualifiedErrorId : Core_BaseCmdlet_UnknownError,VMware.VimAutomation.ViCore.Cmdlets.Commands.NewFolder

Thanks.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

My test CSV file looked like this (the one you gave earlier).

NamePath
vmDATACENTER1\vm
networkDATACENTER1\network
hostDATACENTER1\host
datastoreDATACENTER1\datastore
SecurityDATACENTER1\Security
FoldertestDATACENTER1\Foldertest
Test1DATACENTER1\Foldertest\Test1
Test 2DATACENTER1\Foldertest\Test 2


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

Reply
0 Kudos
BostonTechGuy
Enthusiast
Enthusiast
Jump to solution

That should be perfectly fine.  Also that is what this script is going to use in Production.  I only created a small CSV file to test with as I dont have two DEV environments.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

But does the script work correctly when the CSV looks like that ?


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

Reply
0 Kudos
BostonTechGuy
Enthusiast
Enthusiast
Jump to solution

Luc,

Sorry I didnt get back to you yesterday.  Started building out a new datacenter for a client.

YES! The script worked perfectly.  I even went 4 levels deep into a directory, still kept working.

This is huge!  This script would now give a simple process of exporting folder structure from vCenter and using the same file to import/create the folders in a second vCenter.  This would be key if you were working on... oh I dont know... say a massive SRM Project Smiley Wink

Thank you!!!!! HUGE!!!

Boston Tech Guy

Reply
0 Kudos
KulvinderJutla
Contributor
Contributor
Jump to solution

Hey 

I want to copy the folder structure from our current vCenter to new Vcenter

Folder structure will be like this ( Same folder name can come in various paths)

UR\User1\Folder1\1
UR\User1\Folder1\1\2
UR\User1\Folder2\2
UR\User2\Folder4\4
UR\User2\Folder4\4\4\5\2
UR\User2\Folder4\4\4\5\2\Folder1

I have used the attached script, however it create the folder Structure as shown in the screenshot attached.

 

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Where do you initialise $Folderpath?

Btw, always nice when you mention the source of your code.
I assume you forgot that you got this code from the post "PowerCLI to Generate Nested VM Folder Structure".

In the Remarks on that post, you'll notice that the same issue has been reported there as well.


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

Reply
0 Kudos
KulvinderJutla
Contributor
Contributor
Jump to solution

 

I apologies. Yeh That was my source for the code. 
Yeh I noticed it after couple of hours and have fixed the issue now.

Thanks for your time and comments 🙂

 

Reply
0 Kudos