Highlighted
Contributor
Contributor

Object Relation List

Jump to solution

I want to create a list of DataCenters, Clusters, Resource Pools and their connected  VirtualPortGroups and Datastores.

Does anybody have a script which fits ?

0 Kudos
1 Solution

Accepted Solutions
Highlighted
User Moderator
User Moderator

You asked for three things, datastores, resourcepools and portgroups, that are not really related. So I made three different script for you. One for each. You have to run them seperately the get all the ouput in tables.

Get-Datacenter | ForEach-Object {
  $Datacenter = $_
  $Datacenter | Get-Cluster | ForEach-Object {
    $Cluster = $_
    $Cluster | Get-VMHost | Get-Datastore | ForEach-Object {
      $Datastore = $_
      $Report = "" | Select-Object -Property Datacenter,Cluster,Datastore
      $Report.Datacenter = $Datacenter.Name
      $Report.Cluster    = $Cluster.Name
      $Report.Datastore  = $Datastore.Name
      $Report
    }
  }
}

Get-Datacenter | ForEach-Object {
  $Datacenter = $_
  $Datacenter | Get-Cluster | ForEach-Object {
    $Cluster = $_
    $Cluster | Get-ResourcePool | ForEach-Object {
      $ResourcePool = $_
      $Report = "" | Select-Object -Property Datacenter,Cluster,ResourcePool
      $Report.Datacenter    = $Datacenter.Name
      $Report.Cluster       = $Cluster.Name
      $Report.ResourcePool  = $ResourcePool.Name
      $Report
    }
  }
}

Get-Datacenter | ForEach-Object {
  $Datacenter = $_
  $Datacenter | Get-Cluster | ForEach-Object {
    $Cluster = $_
    Get-View ($Cluster | Get-VMHost | `
    Select-Object -First 1).ExtensionData.Network| ForEach-Object {
      $PortGroup = $_
      $Report = "" | Select-Object -Property Datacenter,Cluster,PortGroup
      $Report.Datacenter = $Datacenter.Name
      $Report.Cluster    = $Cluster.Name
      $Report.PortGroup  = $PortGroup.Name
      $Report
    }
  }
}

Regards, Robert

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition

View solution in original post

0 Kudos
21 Replies
Highlighted
Hot Shot
Hot Shot
0 Kudos
Highlighted
User Moderator
User Moderator

You asked for three things, datastores, resourcepools and portgroups, that are not really related. So I made three different script for you. One for each. You have to run them seperately the get all the ouput in tables.

Get-Datacenter | ForEach-Object {
  $Datacenter = $_
  $Datacenter | Get-Cluster | ForEach-Object {
    $Cluster = $_
    $Cluster | Get-VMHost | Get-Datastore | ForEach-Object {
      $Datastore = $_
      $Report = "" | Select-Object -Property Datacenter,Cluster,Datastore
      $Report.Datacenter = $Datacenter.Name
      $Report.Cluster    = $Cluster.Name
      $Report.Datastore  = $Datastore.Name
      $Report
    }
  }
}

Get-Datacenter | ForEach-Object {
  $Datacenter = $_
  $Datacenter | Get-Cluster | ForEach-Object {
    $Cluster = $_
    $Cluster | Get-ResourcePool | ForEach-Object {
      $ResourcePool = $_
      $Report = "" | Select-Object -Property Datacenter,Cluster,ResourcePool
      $Report.Datacenter    = $Datacenter.Name
      $Report.Cluster       = $Cluster.Name
      $Report.ResourcePool  = $ResourcePool.Name
      $Report
    }
  }
}

Get-Datacenter | ForEach-Object {
  $Datacenter = $_
  $Datacenter | Get-Cluster | ForEach-Object {
    $Cluster = $_
    Get-View ($Cluster | Get-VMHost | `
    Select-Object -First 1).ExtensionData.Network| ForEach-Object {
      $PortGroup = $_
      $Report = "" | Select-Object -Property Datacenter,Cluster,PortGroup
      $Report.Datacenter = $Datacenter.Name
      $Report.Cluster    = $Cluster.Name
      $Report.PortGroup  = $PortGroup.Name
      $Report
    }
  }
}

Regards, Robert

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition

View solution in original post

0 Kudos
Highlighted
Contributor
Contributor

uups  -  little problem :

[vSphere PowerCLI] U:\PSH> .\portgroup.ps1

Get-View : Cannot validate argument on parameter 'VIObject'. The argument is null or empty. Supply an argument that is not null or empty an

d then try the command again.

At U:\PSH\portgroup.ps1:5 char:13

+     Get-View <<<<  ($Cluster | Get-VMHost | `

    + CategoryInfo          : InvalidData: (:) [Get-View], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.DotNetInterop.GetVIView

0 Kudos
Highlighted
User Moderator
User Moderator

Could it be that you have a cluster with no nodes in there ?

What does return ? Do you see at least 1 host for each cluster ?

Get-Cluster | %{

     $_ | Select Name

     $_ | Get-VMHost  | Select Name

}


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

0 Kudos
Highlighted
Contributor
Contributor

No,

strange is that the error only occurs if i am connected to more than 1 vCenter.

0 Kudos
Highlighted
User Moderator
User Moderator

Try to change the line starting with Get-View into:

$Cluster | Get-VMHost | Select-Object -First 1 | For-EachObject {

Get-View $_ | For-EachObject {

And add a } sign at the end of the script.

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition
0 Kudos
Highlighted
Contributor
Contributor

like this :

Get-Datacenter | ForEach-Object {
  $Datacenter = $_
  $Datacenter | Get-Cluster | ForEach-Object {
    $Cluster = $_
    Get-View $Cluster | Get-VMHost | Select-Object -First 1 | For-EachObject {
    Get-View $_ | For-EachObject {
      $PortGroup = $_
       $Report = "" | Select-Object -Property vCenter,Datacenter,Cluster,PortGroup
      $Report.vCenter    = $global:DefaultVIServer.name
      $Report.Datacenter = $Datacenter.Name
      $Report.Cluster    = $Cluster.Name
      $Report.PortGroup  = $PortGroup.Name
      $Report
       
    }   
  }
}
}

+++++++++++++++++++++++++++++++++++++++++++++++++++

The term 'For-EachObject' is not recognized as the name of a cmdlet, function, script file, or operable program. Check
the spelling of the name, or if a path was included, verify that the path is correct and try again.
At F:\PSH\pgr2.ps1:5 char:77
+     Get-View $Cluster | Get-VMHost | Select-Object -First 1 | For-EachObject <<<<  {
    + CategoryInfo          : ObjectNotFound: (For-EachObject:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

0 Kudos
Highlighted
User Moderator
User Moderator

That must be ForEach-Object instead of For-EachObject


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

0 Kudos
Highlighted
Contributor
Contributor

modified :

Get-Datacenter | ForEach-Object {
  $Datacenter = $_
  $Datacenter | Get-Cluster | ForEach-Object {
    $Cluster = $_
    Get-View $Cluster | Get-VMHost | Select-Object -First 1 | ForEach-Object {
    Get-View $_ | ForEach-Object {
      $PortGroup = $_
       $Report = "" | Select-Object -Property vCenter,Datacenter,Cluster,PortGroup
      $Report.vCenter    = $global:DefaultVIServer.name
      $Report.Datacenter = $Datacenter.Name
      $Report.Cluster    = $Cluster.Name
      $Report.PortGroup  = $PortGroup.Name
      $Report
       
    }   
  }
}
}

but :

Get-VMHost : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
At F:\PSH\pgr2.ps1:5 char:35
+     Get-View $Cluster | Get-VMHost <<<<  | Select-Object -First 1 | ForEach-Object {
    + CategoryInfo          : InvalidArgument: (VMware.Vim.ClusterComputeResource:PSObject) [Get-VMHost], ParameterBin
   dingException
    + FullyQualifiedErrorId : InputObjectNotBound,VMware.VimAutomation.ViCore.Cmdlets.Commands.GetVMHost

0 Kudos
Highlighted
User Moderator
User Moderator

Try it like this

Get-Datacenter | ForEach-Object {
 
$Datacenter = $_
  $Datacenter | Get-Cluster | ForEach-Object {
   
$Cluster = $_
    ($Cluster | Get-VMHost | Select-Object -First 1).ExtensionData.Network| %{
     
$portgroup = Get-View $_
      $Report = "" | Select-Object -Property Datacenter,Cluster,PortGroup
     
$Report.Datacenter = $Datacenter.Name
     
$Report.Cluster    = $Cluster.Name
     
$Report.PortGroup  = $portgroup.Name
     
$Report
    }
  }
}


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

Highlighted
Contributor
Contributor

No success - we are at point 1 again. If i call the script manually for 1 vCenter it works. If i run it from my script where multiple servers are connected it fails:

Get-View : 15.03.2011 09:28:48    Get-View        vmodl.fault.InvalidRequest
At F:\PSH\portgroup.ps1:6 char:28
+       $portgroup = Get-View <<<<  $_
    + CategoryInfo          : NotSpecified: (:) [Get-View], InvalidRequest
    + FullyQualifiedErrorId : Client20_MoServiceImpl_GetNetInteropView_ViError,VMware.VimAutomation.ViCore.Cmdlets.Com
   mands.DotNetInterop.GetVIView

Let's exactly explain what i do in my script which will be called by the task scheduler:

$cred=Get-VICredentialStoreItem -file F:\PSH\mycred.xml

Connect-VIServer Server1 -user $cred.User -password $cred.Password

Connect-VIServer Server2 -user $cred.User -password $cred.Password   . . . . .

. . . .

$global:DefaultVIServers

f:\PSH\portgroup.ps1 | Export-Clixml \\path_to_file.xml

Disconnect-VIServer * -confirm:$FALSE

Interesting is that $global:DefaultVIServers lists the last connected server twice like this :

Server11     port 443     username

Server11     port 443     username

Server10     port 443     username . . . . .

. . . .

Server1     port 443     username

0 Kudos
Highlighted
User Moderator
User Moderator

Where do you run the script from ?

PowerCLI prompt, PS command prompt, PowerGui... ?

In fact you do not need the Get-View cmdlet at all.

Try this version

Get-Datacenter | ForEach-Object {
  $Datacenter = $_
 
$Datacenter | Get-Cluster | ForEach-Object {     $Cluster = $_
   
$Cluster | Get-VMHost | Select-Object -First 1 | Get-VirtualPortGroup | %{       $Report = "" | Select-Object -Property Datacenter,Cluster,PortGroup       $Report.Datacenter = $Datacenter.Name       $Report.Cluster    = $Cluster.Name       $Report.PortGroup  = $_.Name       $Report
    }   } }


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

0 Kudos
Highlighted
Contributor
Contributor

For the tests i run it from the shell . Later it will run from Task Scheduler :

C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe -command "& 'F:\PSH\datastores-task.ps1'"

Your last  suggestion does not work .

[vSphere PowerCLI] C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI> F:\PSH\pgr2.ps1
Unexpected token 'Datacenter' in expression or statement.
At F:\PSH\pgr2.ps1:2 char:32
+   $Datacenter = $_  $Datacenter <<<<  | Get-Cluster | ForEach-Object {
    + CategoryInfo          : ParserError: (Datacenter:String) [], ParseException
    + FullyQualifiedErrorId : UnexpectedToken

0 Kudos
Highlighted
User Moderator
User Moderator

There was a <CR> missing after my copy/paste.

It's corrected, try again please.


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

Highlighted
Contributor
Contributor

Perfect - this works nice 🙂

In addition to that i intend to add the relation to the vCenter servers in the list. I tested by adding this statement :

New-VIProperty -Name vCenterServer -ObjectType VirtualMachine `
    -Value {$Args[0].Uid.Split(“:”)[0].Split(“@”)[1]} -Force

.....

$Cluster | Get-VMHost | Select-Object -First 1 | Get-VirtualPortGroup | %{
      $Report = "" | Select-Object -Property vCenterServer,Datacenter,Cluster,PortGroup     
      $Report.vCenterServer = $vCeterServer.Name
      $Report.Datacenter = $Datacenter.Name
      $Report.Cluster    = $Cluster.Name
.....


Is this correct ? I get an output without errors but the report of "vCenterServer" always shows the latest connected server.

0 Kudos
Highlighted
User Moderator
User Moderator

You have to define the new property on the Portgroup objects.

Like this

New-VIProperty -Name vCenterServer -ObjectType DistributedPortgroup,VirtualPortgroup `
-Value {$Args[0].Uid.Split(:)[0].Split(@)[1]} -Force

Get-Datacenter | ForEach-Object {
 
$Datacenter = $_
  $Datacenter | Get-Cluster | ForEach-Object {
   
$Cluster = $_
   
$Cluster | Get-VMHost | Select-Object -First 1 | Get-VirtualPortGroup | %{
     
$Report = "" | Select-Object -Property vCenter,Datacenter,Cluster,PortGroup
     
$Report.vCenter = $_.vCenterServer
     
$Report.Datacenter = $Datacenter.Name
     
$Report.Cluster    = $Cluster.Name
     
$Report.PortGroup  = $_.Name
     
$Report
    }
  }
}

Note that I use the DistributedPortgroup and the VirtualPortgroup, because those are the 2 objects which can appear in the inner loop.


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

0 Kudos
Highlighted
Contributor
Contributor

ok, i have the 2 other scripts for datastores and resource pools. Is the implementation in one these objects is easier ?

At the end i need one of the scripts which shows the relation of cluster or  datacenter and Vcenter server.

0 Kudos
Highlighted
User Moderator
User Moderator

You can create the new property on all 4 objects in 1 statement like this.

New-VIProperty -Name vCenterServer `
    -ObjectType DistributedPortgroup,VirtualPortgroup,Datastore,ResourcePool `
-Value {$Args[0].Uid.Split(:)[0].Split(@)[1]} -Force

You can now retrieve the vCenterServer property from all 4 objects that are used in those scripts.


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

0 Kudos
Highlighted
Contributor
Contributor

Cool - how works the New-VIProperty cmdlet ? get-help shows me that it is a kind of schema extension.

Normally those extensions need only to run once because it extends the object db with new properties.

Do i need the cmdlet every time the script starts or only once ?

0 Kudos