# Any Powershell xml-rpc api examples

**URL:** <https://forum.opennebula.io/t/any-powershell-xml-rpc-api-examples/1185>\
**Category:** Integration Support\
**Created:** [September 8, 2015, 1:42am UTC](https://forum.opennebula.io/t/any-powershell-xml-rpc-api-examples/1185 "2015-09-08T01:42:53Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pete](https://avatars.discourse-cdn.com/v4/letter/p/3ab097/32.png) [@Pete](https://forum.opennebula.io/u/Pete)\
**Post date:** [September 8, 2015, 1:42am UTC](https://forum.opennebula.io/t/any-powershell-xml-rpc-api-examples/1185/1 "2015-09-08T01:42:53Z")

</div>

Does anyone have any examples of using Powershell with the xml-rpc api? Trying to do something simple, like query the config of a vm.

---

<div class="post-metadata">

**Author:** ![Paul\_Batchelor](https://yyz1.discourse-cdn.com/flex031/user_avatar/forum.opennebula.io/paul_batchelor/32/4193_2.png) [@Paul\_Batchelor](https://forum.opennebula.io/u/Paul_Batchelor)\
**Post date:** [September 17, 2015, 12:41pm UTC](https://forum.opennebula.io/t/any-powershell-xml-rpc-api-examples/1185/2 "2015-09-17T12:41:23Z")

</div>

Hi Pete,

I’ve been doing some work around offline patching for non-persistent windows images

This is what I’ve been using -

Firstly, download the PS RPC-XML module from here - [https://github.com/mosserlee/PSClient-for-XML-RPC](https://github.com/mosserlee/PSClient-for-XML-RPC)  
I had to make some tweaks to this module to get it to work with OpenNebula, PM me and I can give you a copy of the updated module. (sorry I haven’t yet submitted it back to the original author)

After that it’s simply a matter of -

`
import-module RPC-Client
function getImageInfo( $id )
{
$uri = “http://your-frontend.domain:2633/RPC2”
$method = “one.image.info”
$creds = “userid:password”
$params = @( $creds, $id )
$body = New-RPCMethod -MethodName $method -Params $params
$image = Invoke-RPCMethod -RpcServerUri $uri -RequestBody $body
if ($image[0])
{
return [xml]$image[1]
}
else
{
return $image.faultCode
}
}
$imageinfo = getImageInfo( Image ID here )
return $imageinfo
`

This automatically casts the XML into PS objects, so you can just reference the properties with something like:  
`
$vmname = $imageinfo.IMAGE.NAME
`

I’ve only tried this on Powershell 4 but it _should_ work with other versions

---

<div class="post-metadata">

**Author:** ![pscookiemonster](https://yyz1.discourse-cdn.com/flex031/user_avatar/forum.opennebula.io/pscookiemonster/32/5693_2.png) [@pscookiemonster](https://forum.opennebula.io/u/pscookiemonster)\
**Post date:** [June 12, 2018, 5:12pm UTC](https://forum.opennebula.io/t/any-powershell-xml-rpc-api-examples/1185/3 "2018-06-12T17:12:10Z")

</div>

Hiyo! This is quite old, but did you ever end up publishing the changes you made Paul? Any chance you still have them and would be up for sharing?

Thanks!

---

<div class="post-metadata">

**Author:** ![pscookiemonster](https://yyz1.discourse-cdn.com/flex031/user_avatar/forum.opennebula.io/pscookiemonster/32/5693_2.png) [@pscookiemonster](https://forum.opennebula.io/u/pscookiemonster)\
**Post date:** [June 12, 2018, 6:37pm UTC](https://forum.opennebula.io/t/any-powershell-xml-rpc-api-examples/1185/4 "2018-06-12T18:37:38Z")

</div>

Alrighty!

In case anyone somehow ends up (1) with OpenNebula, and (2) using the xmlrpc API rather than CLI…

- Used [https://www.powershellgallery.com/packages/XmlRpc](https://www.powershellgallery.com/packages/XmlRpc)
- Used -Debug output to see the methodCall it was creating
- Used the screenshots from [this](https://forum.opennebula.io/t/postman-or-similar-application-for-opennebula-api/3201/6), to figure out the correct schema for the methodCall (i.e. the first parameter (“username:password”) should simple be enclosed in `<value>username:password</value>`, _not_ wrapped in a type
- Constructed the methodCall manually (todo: create function), everything worked!

---

<div class="post-metadata">

**Author:** ![Paul\_Batchelor](https://yyz1.discourse-cdn.com/flex031/user_avatar/forum.opennebula.io/paul_batchelor/32/4193_2.png) [@Paul\_Batchelor](https://forum.opennebula.io/u/Paul_Batchelor)\
**Post date:** [June 13, 2018, 1:45pm UTC](https://forum.opennebula.io/t/any-powershell-xml-rpc-api-examples/1185/5 "2018-06-13T13:45:19Z")

</div>

Hey Warren

I didn’t submit the updated module back to the original author as I only cared about making it work with OpenNebula, and didn’t want to bother testing the changes with any other XMLRPC APIs.

I see you’ve pretty much made the same changes I did (the original version of the module didn’t appear to set the property types (string, integer, etc) correctly.

Here’s a copy the updated module:

```
 <#
.Synopsis
   New XML_RPC method string.
.DESCRIPTION
   New XML_RPC method string with RPC method and parameters.
.EXAMPLE
   New-RPCMethod -MethodName 'new.post' -Params @("1",2,'string')
.INPUTS
   Object.
.OUTPUTS
   Xml format string.
#>
function New-RPCMethod
{
    param(
    [string]$MethodName,
    [Array]$Params
    )
    $xmlMethod = "<?xml version='1.0' encoding='ISO-8859-1' ?>
      <methodCall>
      <methodName>{0}</methodName>
      <params>{1}</params>
     </methodCall>"

     [string]$paramsValue=""
     foreach($param in $Params)
     {
        $paramsValue += '<param>{0}</param>' -f (ConvertTo-RPCXmlObject -Object $param)
     }
     return ([xml]($xmlMethod -f $MethodName,$paramsValue)).OuterXml
}

<#
.Synopsis
   Invoke XML_RPC method request.
.DESCRIPTION
   Invoke XML_RPC request to RPC server.
.EXAMPLE
   $blogUrl = 'http://www.pstips.net/myrpc.php'
   $method = New-RPCMethod -MethodName 'wp.getPostTypes' -Params @(1,'userName','password')
.OUTPUTS
   The response result from RPC server.
#>
function Invoke-RPCMethod
{
    param(
    [uri]$RpcServerUri,
    [string]$RequestBody
    )
    $xmlResponse = Invoke-RestMethod -Uri $RpcServerUri -Method Post -Body $RequestBody
    if($xmlResponse)
    {
        # Normal response
        $paramNodes = $xmlResponse.SelectNodes('methodResponse/params/param/value')
        if($paramNodes)
        {
            $paramNodes | foreach {
              $value = $_.ChildNodes |
               Where-Object { $_.NodeType -eq 'Element' } |
               Select-Object -First 1
              ConvertFrom-RPCXmlObject -XmlObject $value
            }
        }

        # Fault response
        $faultNode = $xmlResponse.SelectSingleNode('methodResponse/fault')
        if ($faultNode)
        {
            $fault = ConvertFrom-RPCXmlObject -XmlObject $faultNode.value.struct
            return $fault
        }
    }
}

<#
.Synopsis
   Convert object to XML-RPC object string.
.DESCRIPTION
   Convert object to XML-RPC object string.
.EXAMPLE
   ConvertTo-RPCXmlObject 3
   <int>3</int>

   ConvertTo-RPCXmlObject '3'
   <string>3</string>

   ConvertTo-RPCXmlObject 3.5
   <double>3.5</double>
.OUTPUTS
   The XML-RPC object string.
#>
function ConvertTo-RPCXmlObject
{
    param(
    $Object
    )
    if($Object -ne $null)
    {
        # integer type
        if( ($Object -is [int]) -or ($Object -is [int64]))
        {
            return "<value><int>$Object</int></value>"
        }
        # double type
        elseif( ($Object -is [float]) -or ($Object -is [double]) -or ($Object -is [decimal]))
        {
            return "<value><double>$Object</double></value>"
        }
        # string type
        elseif( $Object -is [string])
        {
            return "<value><string>$Object</string></value>"
        }
        # date/time type
        elseif($Object -is [datetime])
        {
            $dateStr = $Object.ToString('yyyyMMddTHH:mm:ss')
            return "<value><dateTime.iso8601>$dateStr</dateTime.iso8601></value>"
        }
        # boolean type
        elseif($Object -is [bool])
        {
            $bool = [int]$Object
            return "<value><boolean>$bool</boolean></value>"
        }
        # base64 type
        elseif( ($Object -is [array]) -and ($Object.GetType().GetElementType() -eq [byte]))
        {
            $base64Str = [Convert]::ToBase64String($Object)
            return "<value><base64>$base64Str</base64></value>"
        }
        # array type
        elseif( $Object -is [array])
        {
            $result = '<value><array>
            <data>'
            foreach($element in $Object)
            {
                $value = ConvertTo-RPCXmlObject -Object $element
                $result += "<value>{0}</value>" -f $value
            }
            $result += '</data>
            </array></value>'
            return $result
        }
        # struct type
        elseif($Object -is [Hashtable])
        {
            $result = '<value><struct>'
            foreach ($key in $Object.Keys)
            {
                $member = "<member>
                <name>{0}</name>
                <value>{1}</value>
                </member>"
                $member = $member -f $key, (ConvertTo-RPCXmlObject -Object $Object[$key])
                $result = $result + $member
            }
            $result = $result + '</struct></value>'
            return $result
        }
        elseif($Object -is [PSCustomObject])
        {
            $result = '<value><struct>'
            $Object | 
            Get-Member -MemberType NoteProperty | 
            ForEach-Object{
                $member = "<member>
                <name>{0}</name>
                <value>{1}</value>
                </member>"
                $member = $member -f $_.Name, (ConvertTo-RPCXmlObject -Object $Object.($_.Name))
                $result = $result + $member
            }
            $result = $result + '</struct></value>'
            return $result
        }
        else{
            throw "[$Object] type is not supported."
        }
    }
}

<#
.Synopsis
   Convert to object from XML-RPC object string.
.DESCRIPTION
   Convert to object from XML-RPC object string.
.EXAMPLE
   $s1= '<i4>1919</i4>'
   ConvertFrom-RPCXmlObject -XmlObject $s1
.OUTPUTS
   The XML-RPC object string.
#>
function ConvertFrom-RPCXmlObject
{
 param($XmlObject)
 if($XmlObject -is [string])
 {
    $XmlObject= ([xml]$XmlObject).DocumentElement
 }
 elseif( $XmlObject -is [xml] ){
    $XmlObject = $XmlObject.DocumentElement
 }
 elseif( $XmlObject -isnot [Xml.XmlElement])
 {
    throw 'Only types [string](xml format), [xml], [System.Xml.XmlElement] are supported'
 }
  
 $node = $XmlObject
 if($node)
 {
    $typeName = $node.Name
    switch($typeName)
    {
     # Bool
     ('boolean') { 
        if($node.InnerText -eq '1'){ 
            return $true
        } 
        return $false 
     }

     # Number
     ('i4') {[int64]::Parse($node.InnerText) }
     ('int') {[int64]::Parse($node.InnerText) }
     ('double'){ [double]::Parse($node.InnerText) }
     
     # String
     ('string'){ $node.InnerText }

     # Base64
     ('base64') {
      [Text.UTF8Encoding]::UTF8.GetBytes($node.InnerText)
     }

     # Date Time
     ('dateTime.iso8601'){
      $format = 'yyyyMMddTHH:mm:ss'
      $formatProvider = [Globalization.CultureInfo]::InvariantCulture
      [datetime]::ParseExact($node.InnerText, $format, $formatProvider) 
      }

      # Array
      ('array'){
        $node.SelectNodes('data/value') | foreach{
         ConvertFrom-RPCXmlObject -XmlObject $_.FirstChild
        }
      }

      # Struct
      ('struct'){
       $hashTable = @{}
       $node.SelectNodes('member') | foreach {
        $hashTable.Add($_.name,(ConvertFrom-RPCXmlObject -XmlObject $_.value.FirstChild))
       }
        [PSCustomObject]$hashTable
      }
    }
 }
}

```

Cheers
