When I publish scripts that use SDK properties or methods, one of the questions that comes back regularly is “Where do you find what to use ?“.
Let me assure you, there are no tricks, optical illusions or black magic involved. I’m simply using the numerous resources that are made available in the VMware Developer community.
Diving into the SDK is like making a big trip, you have to start prepared !
Start of by getting your hands on the vSphere Web Services SDK package.
Extract the files to a local folder
- the VMware vSphere API Reference Documentation
- a bit like Google Maps but then for vSphere. It allows you to find your way around and zoom in all the way to “street level” view !
- Just double-click on the index.html file and you have access to the complete Reference in your browser. No Internet connection required !
- several Java and .Net samples
- As I already remarked in PowerCLI and the SDK – Part 1 no PowerShell examples yet 🙁 But hey, we’re patient and let the fairies do their work 😉 And there is a lot to be learned by looking at the Java and .Net examples.
- the WSDL (Web Services Description Language) files for API 2.0 and API 2.5 (which also covers API 4.0).
- From the W3C definition: “…an XML format for describing network services as a set of endpoints operating on messages containing either document-oriented or procedure-oriented information“
- the VMware vCenter Storage Monitoring Service
- New since vSphere and (as always) still experimental. From the ReadMe page: “…simplified access to all vCenter storage information associated with VMware vCenter servers.“. These APIs are for querying only, no changes can be done through this interface.
While the intended use of the VMware vSphere API Reference Documentation is probably obvious, that of the WSDL files is perhaps less so.
In the W3C definition of a WSDL file it says XML, so I prefer to use XMLPad (see also My PS toolbelt) and it’s Table View.
When we open the bigger of the two WSDL files we see a wealth of information about the SDK.
Did you know for example, that there are 463 methods you can call via the API ? And did you know that there are 1361 messages/faults these methods can return ?
We can do lots of useful stuff with this file. As an example let’s take the AddHost_Task method.
From the above diagram we can see that this method requires a vim25.AddHostRequestType object to be passed. Looking up this vim25.AddHostRequestType we can see which are the parameters that need to be provided to the method.
The parameters are all “standard” types (boolean, string, MoRef) except for the spec parameter which is of the HostConnectSpec type.
We look up this “complex” type and see all it’s elements.
Note that the entry also shows which elements are “optional“. These are the ones that have a zero value in the MinOccurs column.
Now all this information is also available in the API Reference as the following screenshots confirm. Also if a parameter is optional or not (see the red asterisk after a property).
The AddHost_Task method …
… and the HostConnectSpec object.
Now we wouldn’t be real PowerShell adepts if we didn’t try to automate this process 😉
Below is my second version of such a script. It can be used in two different ways:
- looks for a specific method and returns the parameters and whether or not a parameter is required
- list all methods and their parameters
The major differences with the first version of the script:
- a better interpretation of the WSDL file
- stores all the required WSDL information in hash arrays. This means the script will take a bit longer before you see the first output. On the other hand the script will be a lot faster if you want to list all methods
- the parameters for each method are now in alphabetical order which makes it easier to cross-reference with the Reference Guide
- the ManagedObjectReference problem is still there, the output only shows the type property but not the value property because this last property is not present in the WSDL file. I started a thread on this in the vSphere Web Services SDK Community
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
function Out-WsdlComplexType{ param($ct, $prtOffset) $prtOffset += " " $ct | Sort-Object -Property Name | %{ Write-Host $prtOffset $_.Name $_.Type -NoNewline; Write-Host -for yellow " " $_.MinOcc $_.MaxOcc $splitArray = $_.Type.Split(":") if($splitArray[0] -eq "vim25"){ $nct = $alltypes[$splitArray[1]] switch ($nct.Type){ "simpleContent"{ $params = $nct.Defs Out-WsdlComplexType $params $prtOffset } "complexContent"{ $params = $nct.Defs.Sequence Out-WsdlComplexType $params $prtOffset } "simpleType"{ $line = "" $nct.Defs | % {$line += ($_.Value + ",")} Write-Host $prtOffset " Enum :" -NoNewline; Write-Host -for green " " $line.TrimEnd(",") } } } } } # Location of the WSDL files $wsdlRoot = "D:\Tools\PowerShell\Scripts\SDK\wsdl" # Go for the VIM 2.5 (and up) files $wsdlFile = $wsdlRoot + "\vim25\vim.wsdl" # Open (XML) file $wsdl = New-Object System.Xml.XmlDocument $wsdl.Load($wsdlFile) # Get all messages $messages = @{} $wsdl.definitions.message | % { $messages[$_.Name] = $_.part.element } # Get all elements $elements = @{} $wsdl.definitions.types.schema.element | % { $elements[$_.name] = $_.type } # Get all methods & their I/O messages $methods = @{} $wsdl.definitions.portType.operation | % { $method = New-Object PSObject -Property @{ Input = $elements[$messages[$_.input.message.Split(":")[1]].Split(":")[1]] Output = $elements[$messages[$_.output.message.Split(":")[1]].Split(":")[1]] } $methods[$_.Name] = $method } # Get all complex types $alltypes = @{} $wsdl.definitions.types.schema.complextype | % { $ct = $_ switch(($_ | Get-Member -MemberType Property | where{$_.Name -ne "name"}).Name){ "sequence"{ $array = @() $ct.sequence.element | % { $element = New-Object PSObject -Property @{ Name = $_.name Type = $_.type MinOcc = $_.minOccurs MaxOcc = $_.maxOccurs } $array += $element } $alltypes[$ct.name] = New-Object PSObject -Property @{ Type = "sequence" Defs = $array } } "simplecontent"{ $array = @() $ct.simpleContent.extension.attribute | % { $attribute = New-Object PSObject -Property @{ Name = $_.name Type = $_.type } $array += $attribute } $alltypes[$ct.name] = New-Object PSObject -Property @{ Type = "simpleContent" Defs = $array } } "complexContent"{ $ct.complexContent.extension | % { $array = @() if($_.sequence.element -ne $null){ $_.sequence.element | % { $element = New-Object PSObject -Property @{ Name = $_.name Type = $_.type MinOcc = $_.minOccurs MaxOcc = $_.maxOccurs } $array += $element } } $extension = New-Object PSObject -Property @{ Name = $ct.Name Sequence = $array } } $alltypes[$ct.name] = New-Object PSObject -Property @{ Type = "complexContent" Defs = $extension } } } } # Get all simple types $wsdl.definitions.types.schema.simpletype | % { $st = $_ $array = @() $_.restriction.enumeration | % { $enum = New-Object PSObject -Property @{ Value = $_.value } $array += $enum } $alltypes[$st.name] = New-Object PSObject -Property @{ Type = "simpleType" Defs = $array } Remove-Variable -Name array } # Method 1 # Display individual method & parameters # $tgtMethod = "AddHost_Task" $tgtMethod = "ReconfigVM_Task" $inputMsg = $methods[$tgtMethod].Input.Split(":")[1] Write-Host -for red $tgtMethod -NoNewline; Write-Host " " $inputMsg $parameters = $alltypes[$inputMsg].Defs Out-WsdlComplexType $parameters "" # Method 2 # Display all methods & their parameters # $methods.Keys | Sort-Object | %{ # $inputMsg = $methods[$_].Input.Split(":")[1] # Write-Host -for red $_ -NoNewline; Write-Host " " $inputMsg # # $parameters = $alltypes[$inputMsg].Defs # Out-WsdlComplexType $parameters "" # Write-Host "=====================" # } |
Annotation
Line 1-27: the core function of the script. This function recursively lists all the parameters, their type and, if defined, their minimum and maximum occurence
Line 33: the script uses the vim25 WSDL files. I haven’t tested the script with WSDL files for API 2.0
Line 39-138: these lines create the hash tables with the required WSDL information.
Line 140-148: the first option to use the script is to enter the name of a method in the $tgtMethod variable. The script will then list all the parameters for this one specific method
Line 150-159: the second option will list all 463 methods with their parameters
Some sample runs
AddHost_Task
This is a rather simple method (looking at the parameters at least).
The yellow numbers behind a property indicate what the minimum (and maximum) occurrence of the property may be. In this case we see for example that the port property may be left out.
This is what is indicated in the SDK Reference by the red asterisk behind a property.
When there is no number behind the property, a value for that property has to be provided to the method. One such example is the force property.
ReconfigVM_Task
This produced, as you could have guessed, a rather long list. That’s why I will only show some extracts.
With this method there are two noteworthy points.
- the backing property (2nd extract) has no further child-properties. That’s because, depending on the device you are manipulating, you will have overlay this property with a more specific object.
- this method has several properties that need to have Enum type values. For example, the operation property can only have one of these: add, remove or edit
All in all, this script was a personal exercise in getting to know WSDL files. As far as I could see there are no PS scripts/modules that allow you to extract this kind of information from a WSDL file.
The script also allows you to see all the properties for a method in one list. It avoids clicking through all the hyperlinks in the Reference Guide ;-).
In conclusion, you now have your maps (and even some very detailed plans with the script) to start your wonderful trip through SDK land.
More on the actual start of the trip in a next episode in this series.
Eric Gray
Outstanding post. I feel smarter after reading this. 🙂
LucD
Thanks Eric. Glad you liked it.
LucD
As some of you might have noticed there is an issue with the way the script displays the ManagedObjectReference.
This should be displayed as:
_this vim25:ManagedObjectReference
type xsd:string
value xsd:string
I’m looking into this “feature”.