VMware Cloud Community
jonebgood_157
Enthusiast
Enthusiast
Jump to solution

need help with scripting export of datacenter and clusters to import into brand new vcenter

I've successfully created scripts on exporting files/folder, etc. and importing, but I'm having a hard time figuring out how to script the hosts and clusters view.  I have a ROBO vcenter with tons of datacenters and clusters and obviously don't want to create by hand. I don't need all the cluster settings, I simply want the datacenter and clusters "shell".  Any powercli script help for exporting all the datacenters and clusters and then re-importing to populate new vcenter would be greatly appreciated. I went through these boards but no one really seems to be doing exactly this.

0 Kudos
52 Replies
jonebgood_157
Enthusiast
Enthusiast
Jump to solution

@LucD yeah, now I get this.

Get-Folder : Cannot bind parameter 'Type'. Cannot convert value "blue" to type "VMware.VimAutomation.ViCore.Types.V1.Inventory.FolderType". Error: "Unable to match the identifier name blue
to a valid enumerator name. Specify one of the following enumerator names and try again:
VM, HostAndCluster, Datacenter, Datastore, Network"
At D:\Scripts\vCenter Scripts\ImportNetworkFolders.ps1:15 char:96
+ ... atacenter -Name $dcName | Get-Folder -Name $dummy -Type $row.Type) }
+ ~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-Folder], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetFolder

0 Kudos
LucD
Leadership
Leadership
Jump to solution

That's normal, I thought the type would say network.

The export needs to adapted


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

0 Kudos
jonebgood_157
Enthusiast
Enthusiast
Jump to solution

@LucD A different export script entirely? I remember reading about this one you did, but I couldn't figure out how to do it for just datastore or network folders? 

New-VIProperty -Name 'BlueFolderPath' -ObjectType 'VirtualMachine' -Value {
    param($vm)

    function Get-ParentName{
        param($object)

        if($object.Folder){
            $blue = Get-ParentName $object.Folder
            $name = $object.Folder.Name
        }
        elseif($object.Parent -and $object.Parent.GetType().Name -like "Folder*"){
            $blue = Get-ParentName $object.Parent
            $name = $object.Parent.Name
        }
        elseif($object.ParentFolder){
            $blue = Get-ParentName $object.ParentFolder
            $name = $object.ParentFolder.Name
        }
        if("vm","Datacenters" -notcontains $name){
            $blue + "/" + $name
        }        
else{             $blue
        }     }     (
Get-ParentName $vm).Remove(0,1) } -Force | Out-Null
$dcName
= "MyDC"

Get-VM
-Location (Get-Datacenter -Name $dcName) | Select Name,BlueFolderPath |Export-Csv "C:\vm-folder.csv" -NoTypeInformation -UseCulture
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try these

For export

 

function Get-FolderPath {
  <#
.SYNOPSIS
Returns the folderpath for a folder
.DESCRIPTION
The function will return the complete folderpath for
a given folder, optionally with the "hidden" folders
included. The function also indicats if it is a "blue"
or "yellow" folder.
.NOTES
Authors: Luc Dekens
.PARAMETER Folder
On or more folders
.PARAMETER ShowHidden
Switch to specify if "hidden" folders should be included
in the returned path. The default is $false.
.EXAMPLE
PS> Get-FolderPath -Folder (Get-Folder -Name "MyFolder")
.EXAMPLE
PS> Get-Folder | Get-FolderPath -ShowHidden:$true
#>

  param(
    [parameter(valuefrompipeline = $true,
      position = 0,
      HelpMessage = "Enter a folder")]
    [VMware.VimAutomation.ViCore.Impl.V1.Inventory.FolderImpl[]]$Folder,
    [switch]$ShowHidden = $true
  )

  begin {
    $excludedNames = "Datacenters", "vm", "host"
  }

  process {
    $Folder | ForEach-Object {
      $fld = $_.Extensiondata
      $fldType = "yellow"
      if ($fld.ChildType -contains "Network") {
        $fldType = "blue"
      }
      $path = $fld.Name
      while ($fld.Parent) {
        $fld = Get-View $fld.Parent
        if ((!$ShowHidden -and $excludedNames -notcontains $fld.Name) -or $ShowHidden) {
          $path = $fld.Name + "\" + $path
        }
      }
      $row = "" | Select-Object Name, Path, Type
      $row.Name = $_.Name
      $row.Path = $path
      $row.Type = $fldType
      $row
    }
  }
}

$hidden = 'Datacenters','host','vm','network','datastore','vCLS'
Get-Folder | where{$_.Name -notin $hidden} |
Select @{N='Path';E={(Get-FolderPath -Folder $_).Path}} |
Export-Csv -Path .\export-folder.csv -NoTypeInformation -UseCulture

 

For import

 

Import-Csv -Path .\export-folder.csv -UseCulture -PipelineVariable row |
ForEach-Object -Process {
  $root,$dcName,$path = $row.Path.Split('\',3)
  $location = Get-Datacenter -Name $dcName
  $path.Split('\') | ForEach-Object -Process {
    $name = $_
    try{
      $location = Get-Folder -Name $_ -Location $location -ErrorAction Stop
    }
    catch{
      New-Folder -Name $name -Location $location
    }
  }
}

 




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

0 Kudos
jonebgood_157
Enthusiast
Enthusiast
Jump to solution

@luc 

Getting some new errors on the import with these scripts....

 

New-Folder : 10/18/2022 7:35:09 AM New-Folder '10/18/2022 7:35:09 AM Get-Folder Folder with name 'Virtual Machine' was not found using the specified filter(s). ' is invalid or exceeds the maximum number of characters
permitted.
At line:10 char:7
+ New-Folder -Name $_ -Location $location
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-Folder], InvalidName
+ FullyQualifiedErrorId : Client20_InventoryServiceImpl_NewFolder_ViError,VMware.VimAutomation.ViCore.Cmdlets.Commands.NewFolder

New-Folder : 10/18/2022 7:35:09 AM New-Folder '10/18/2022 7:35:09 AM Get-Folder Folder with name 'VMkernel' was not found using the specified filter(s). ' is invalid or exceeds the maximum number of characters permitted.
At line:10 char:7
+ New-Folder -Name $_ -Location $location
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-Folder], InvalidName
+ FullyQualifiedErrorId : Client20_InventoryServiceImpl_NewFolder_ViError,VMware.VimAutomation.ViCore.Cmdlets.Commands.NewFolder

 

my .csv output

"Path"
"Datacenters\testing2\network\Virtual Machine"
"Datacenters\testing2\network\VMkernel"
"Datacenters\testing2\datastore\System"
"Datacenters\testing2\datastore\Virtual Machine"

0 Kudos
LucD
Leadership
Leadership
Jump to solution

My bad, I forgot that the $_ variable inside a catch-block contains the error, not the value from the loop.
I corrected the code above


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

0 Kudos
jonebgood_157
Enthusiast
Enthusiast
Jump to solution

Thanks for all the help. These scripts worked perfectly in my Lab but got the same errors in my other system. I think something is wrong with the PowerCLI install. It does the very first line in the import script and then simply errors out the rest with the same error. I do notice the $PSTableVersion shows 5.1.19041.1682 for the lab one and the non-working one is 5.1.14393.2125.

 

0 Kudos
LucD
Leadership
Leadership
Jump to solution

Those PS version differences shouldn't cause those errors.

You are sure that $name variable I added is there?


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

0 Kudos
jonebgood_157
Enthusiast
Enthusiast
Jump to solution

Yeah, i got your updated script and it worked fine in my lab. I have to use the other powershell instance because of security; basically I'm running it from a jumpbox that has access to those particular vcenters. 

i run it and it just errors.


New-Folder : Cannot convert 'System.Object[]' to the type 'VMware.VimAutomation.ViCore.Types.V1.Inventory.VIContainer' required by parameter 'Location'. Specified
method is not supported.
At line:11 char:40
+ New-Folder -Name $name -Location $location
+ ~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [New-Folder], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,VMware.VimAutomation.ViCore.Cmdlets.Commands.NewFolder

0 Kudos
LucD
Leadership
Leadership
Jump to solution

But that is again that original error which seems to indicate an array instead of single object is passed on the Location parameter.
You could do those 2 tests I mentioned yesterday


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

0 Kudos
jonebgood_157
Enthusiast
Enthusiast
Jump to solution

@LucD Get-Datacenter on any of the DC's just return one value.

The 2nd command returns 3 values Get-Datacenter -Name 'robo.dc.00001' | Get-Folder -Name 'Network'

Name Type
---- ----
network Network
Network VM
Network VM

0 Kudos
LucD
Leadership
Leadership
Jump to solution

So you have 2 VM folders that are named Network, and on Network folder that is also named Network.
Not sure how to code around that (yet)


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

0 Kudos
jonebgood_157
Enthusiast
Enthusiast
Jump to solution

yeah, i was thinking the same thing. so I tried adding -type network to your script. It worked...kind of. created my network folders, but also created a bunch of folders at the hosts and clusters view at the Datacenter root. I'm thinking I could just edit my .csv and trim out everything except the network folders

 

Import-Csv -Path c:\temp\export-networkfolder-test.csv -UseCulture -PipelineVariable row |
ForEach-Object -Process {
$root,$dcName,$path = $row.Path.Split('\',3)
$location = Get-Datacenter -Name $dcName
$path.Split('\') | ForEach-Object -Process {
$name = $_
try{
$location = Get-Folder -Type Network -Name $_ -Location $location -ErrorAction Stop
}
catch{
New-Folder -Name $name -Location $location
}
}
}

0 Kudos