VMware Cloud Community
mike-p
Enthusiast
Enthusiast
Jump to solution

Object Relation List

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

Does anybody have a script which fits ?

Reply
0 Kudos
1 Solution

Accepted Solutions
RvdNieuwendijk
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
21 Replies
alefestaedist
Hot Shot
Hot Shot
Jump to solution

Reply
0 Kudos
RvdNieuwendijk
Leadership
Leadership
Jump to solution

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
Reply
0 Kudos
mike-p
Enthusiast
Enthusiast
Jump to solution

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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
mike-p
Enthusiast
Enthusiast
Jump to solution

No,

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

Reply
0 Kudos
RvdNieuwendijk
Leadership
Leadership
Jump to solution

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
Reply
0 Kudos
mike-p
Enthusiast
Enthusiast
Jump to solution

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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That must be ForEach-Object instead of For-EachObject


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

Reply
0 Kudos
mike-p
Enthusiast
Enthusiast
Jump to solution

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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

mike-p
Enthusiast
Enthusiast
Jump to solution

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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
mike-p
Enthusiast
Enthusiast
Jump to solution

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

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

It's corrected, try again please.


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

mike-p
Enthusiast
Enthusiast
Jump to solution

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.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
mike-p
Enthusiast
Enthusiast
Jump to solution

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.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

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

Reply
0 Kudos
mike-p
Enthusiast
Enthusiast
Jump to solution

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 ?

Reply
0 Kudos