“HelpDesk_QueryList_Service” with “3” argument(s): “There is an error in XML document (3, 4).

I wrote before some posts about getting tickets from BMC Remedy ITSM system. Recently i had to check for tickets on a different environments , and got stuck. It was ‘weird’, as i would thought that since it was working on previous environment it will work on new one. This post is not about how to query itsm tickets in general… it’s about how to make it working if you encounter issue like:


“HelpDesk_QueryList_Service” with “3” argument(s): “There is an error in XML document (3, 4).


I was investigating this issue first myself, then i was googling for about 3-4 hours… And, nothing. Found few places where this error was mentioned, but no working answers were posted. I do not want to write too much here, as my ITSM system knowledge is like… huh.. ok i have no knowledge of that 😉 I just want to get some tickets info 😉 Therefore, i will not comment much on what i have done , as i do not feel too comfortable about what i wrote 😉


While googling about this, i saw opinions like : “There is something wrong with New-WebServicePRoxy …” or “There is something wrong with the ITSM instance” or “the criteria is wrong” or “Authorization did not complete”. I can’t tell what exactly it is, well sort of… but since i am not an expert in this matter i shall keep it to myself 😉 For sure, there is no problem with logging in, or criteria query. It all comes down to what we are receiving from our itsm service, and i think this is problematic. Even if we are seeing on the powershell console the:
“”HelpDesk_QueryList_Service” with “3” argument(s): “There is an error in XML document (3, 4).”


It does not have to mean that we did not get our tickets back. We have put a proxy between powershell and the itsm service, and were checking the soap requests and replies. ITSM service was sending the tickets back, it’s just that powershell cmdlet New-WebserviceProxy decided that is something wrong with it, and decided not to “give it back to us”. I really do not know the details about it, please excuse me for not writing this.
Anyway… i even thought that there is something wrong with the new-webserviceproxy (it’s not the case) , and then i started to google if somebody has wrote his own function for sending receiving soap requests/answers.
Fortunately i found this website : http://iislogs.com/steveschofield/2010/01/17/execute-a-soap-request-from-powershell/ where Steve Schofield has written a function for that.
There are still few things that i don’t know about web services and soap and so on.. so i wanted just to see if it is even possible to get those tickets. For that i used soap ui. I managed to receive tickets from soap ui, so that has to be doable. Then it was just a matter of tries to do it in powershell.

itsma1

So i knew for sure that is possible to do it, as i was receiving tickets out of that call. If you know more about soap, xml , xsd maybe you will know the answer to why powershell keeps throwing that error. Feel free to share your thoughts. Ok, never mind the issues now. Let’s start making it working. So we got the function from Steve Schofield.

function Execute-SOAPRequest 
( 
        [Xml]    $SOAPRequest, 
        [String] $URL 
) 
{ 
        write-host "Sending SOAP Request To Server: $URL" 
        $soapWebRequest = [System.Net.WebRequest]::Create($URL) 
        $soapWebRequest.Headers.Add("SOAPAction","`"urn:HPD_IncidentInterface_WS/HelpDesk_QueryList_Service`"")  #this i took directly from SoapUI after completing request there

        $soapWebRequest.ContentType = "text/xml;charset=`"utf-8`"" 
        $soapWebRequest.Accept      = "text/xml" 
        $soapWebRequest.Method      = "POST" 
        
        write-host "Initiating Send." 
        $requestStream = $soapWebRequest.GetRequestStream() 
        $SOAPRequest.Save($requestStream) 
        $requestStream.Close() 
        
        write-host "Send Complete, Waiting For Response." 
        $resp = $soapWebRequest.GetResponse() 
        $responseStream = $resp.GetResponseStream() 
        $soapReader = [System.IO.StreamReader]($responseStream) 
        $ReturnXml = [Xml] $soapReader.ReadToEnd() 
        $responseStream.Close() 
        
        write-host "Response Received."

        return $ReturnXml 
}

Then we need the endpoint url:

‘$url = ‘https://XYZ/arsys/services/ARService?server=ABC&webService=HPD_IncidentInterface_WS”
You can also get this from SoapUI request that you have previously made ( or even from (new-webserviceproxy ..).Url)
Now we have to create our SOAP envelope , i just copied what SoapUI has generated for me. So in my case that was:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:HPD_IncidentInterface_WS">
   <soapenv:Header>
      <urn:AuthenticationInfo>
         <urn:userName>Domain\User</urn:userName>
         <urn:password>pwd</urn:password>
         <!--Optional:-->
         <urn:authentication></urn:authentication>
         <!--Optional:-->
         <urn:locale></urn:locale>
         <!--Optional:-->
         <urn:timeZone></urn:timeZone>
      </urn:AuthenticationInfo>
   </soapenv:Header>
   <soapenv:Body>
      <urn:HelpDesk_QueryList_Service>
         <urn:Qualification>'Status' = "Assigned"</urn:Qualification>
         <urn:startRecord>0</urn:startRecord>
         <urn:maxLimit>1</urn:maxLimit>
      </urn:HelpDesk_QueryList_Service>
   </soapenv:Body>
</soapenv:Envelope>

We can push this to a file and call it C:\mes.xml
We can then read it from file:
[xml]$mysoap = gc C:\mes.xml
Once this is done we have to send it using previously created function so:
$answers = Execute-SOAPRequest $mysoap $url

Putting it all together :

function Execute-SOAPRequest 
( 
        [Xml]    $SOAPRequest, 
        [String] $URL 
) 
{ 
        write-host "Sending SOAP Request To Server: $URL" 
        $soapWebRequest = [System.Net.WebRequest]::Create($URL) 
        $soapWebRequest.Headers.Add("SOAPAction","`"urn:HPD_IncidentInterface_WS/HelpDesk_QueryList_Service`"")

        $soapWebRequest.ContentType = "text/xml;charset=`"utf-8`"" 
        $soapWebRequest.Accept      = "text/xml" 
        $soapWebRequest.Method      = "POST" 
        
        write-host "Initiating Send." 
        $requestStream = $soapWebRequest.GetRequestStream() 
        $SOAPRequest.Save($requestStream) 
        $requestStream.Close() 
        
        write-host "Send Complete, Waiting For Response." 
        $resp = $soapWebRequest.GetResponse() 
        $responseStream = $resp.GetResponseStream() 
        $soapReader = [System.IO.StreamReader]($responseStream) 
        $ReturnXml = [Xml] $soapReader.ReadToEnd() 
        $responseStream.Close() 
        
        write-host "Response Received."

        return $ReturnXml 
}

$url = 'https://XYZ/arsys/services/ARService?server=ABC&webService=HPD_IncidentInterface_WS'
[xml]$mysoap = gc C:\mes.xml
$answers = Execute-SOAPRequest $mysoap $url

In the query for ITSM i put maxlimit 1 , so i will receive at the end only 1 ticket. Below is the screenshot while reading it:
itsm3

Which proves that it’s possible to get the ticket. Maybe i can figure it out more in upcoming days. Will update this post if i have something new about this topic.

I think that what is happening is … ( will continue this, once i will gather some more information )
UPDATE:
My colleage Viktor Bocz wrote me some explanation about what is happening there. He has also written for me an altered wsdl file, which i have been reading using new-webserviceproxy instead of connecting to the one from where itsm webservice sits.

The issue is with the definition of the response to the HelpDesk_QueryList_Service call in the wsdl.

original

<xsd:element type="s0:GetListOutputMap" name="HelpDesk_QueryList_ServiceResponse"/>
<xsd:complexType name="GetListOutputMap">
<xsd:sequence><xsd:element type="xsd:string" name="getListValues" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>

The soap response usms returns looks like:

    <ns0:HelpDesk_QueryList_ServiceResponse xmlns:ns0="urn:HPD_IncidentInterface_WS">
       <ns0:getListValues>
          <ns0:Assigned_Group>XYZ</ns0:Assigned_Group>
          <ns0:Assigned_Support_Company>XYZ</ns0:Assigned_Support_Company>
…

The response body is expected to be a string as per the definition, but the xml in the response body it’s not escaped or returned as character data (xml cdata). For this reason the cmdlet tries to unmarshall (not sure if this is the right term here for parsing xml, in java it is) the response, but fails as it encounters an unexpected element. As per the SOAP protocol this behavior is correct, the cmdlet properly verifies the response syntax.

To resolve the issue on the client side (ultimately it should be corrected on the server-side), we need to alter the wsdl to have the proper response type definition. The below complex type was made up by inspecting the response (changed/new in red), so there’s no guarantee that it’s 100% correct, all we know that it works for us.

Altered element and type definition to match the response (s0 is the target namespace):

   <xsd:element name="HelpDesk_QueryList_ServiceResponse" type="s0:GetListOutputMap"/>
   <xsd:complexType name="GetListOutputMap">
    <xsd:sequence>
     <xsd:element maxOccurs="unbounded" name="getListValues" type="s0:GetOutputListMap"/>
    </xsd:sequence>
   </xsd:complexType>

<xsd:complexType name="GetOutputListMap">
    <xsd:sequence>
     <xsd:element name="Assigned_Group" type="xsd:string"  minoccurs="0" maxoccurs="unbounded"/>
     <xsd:element name="Assigned_Support_Company" type="xsd:string" minoccurs="0" maxoccurs="unbounded"/>
     <xsd:element name="Assigned_Support_Organization" type="xsd:string" minoccurs="0" maxoccurs="unbounded"/>
     <xsd:element name="Assignee" type="xsd:string" minoccurs="0" maxoccurs="unbounded"/>
     (...)
     <xsd:element name="Submit_Date" type="xsd:string" minoccurs="0" maxoccurs="unbounded"/>
    </xsd:sequence> 
   </xsd:complexType>


So from those remarks from Viktor and new wsdl file, we can get our tickets using the “standard” approach:
finalitsm

PLVMUG Q2 2014 “PowerCLI in examples”

So.. yeah.. um.. i know, not the first time, not the last.. i have not been writing much recently. That is due to…. ‘like you care’ 🙂 anyway as always , i had something to do… But… i wanted to share with you the video from last PLVMUG about PowerCLI. My session can be watched below. I am still working on english subtitles. Be patient 😉 I know that it is sometimes hard to see what is being displayed.

Listing vSphere alarms actions other than SendEmail, ExecuteScript, SendSNMP

It’s gonna be quick one today.

If you are familiar with dell openmanage integration plugin for vSphere Virtual Center, you know that it can create custom alarms. Those alarms can be triggered, and an action will be performed. What action you might wonder ? Put host into maintenance mode. If you are wondering which alarms will do this, here it is how to quickly check this.

Before we start you should know that Get-AlarmAction supports only ‘SendEmail’, ‘ExecuteScript’, ‘SendSNMP’ , since those dell alarms have something else then that, we have to change our approach to get them.
That is our alarm defined by dell openmanage integration. We want to check the actions from it.
o4

Getting the alarm definitions:

$DellAlarmDefinitions = Get-AlarmDefinition  -Name 'Dell*'
$DellAlarmDefinitions | ? {$_.Extensiondata.Info.Action.Action.Action} |Select Name, Description

o1

What is being checked is the Action object in the alarm definition. We inspect the view of the alarm by checking .Extensiondata:

o6
We can also easily make a table : Alarm name | Action to be taken

o3

Below is the source of what’s on the screenshot:

($DellAlarmDefinitions | ? {$_.Extensiondata.Info.Action.Action.Action}) | Select Name, @{n='Action';e={$_.Extensiondata.Info.Action.Action.Action.Name}}

This might now work within Powershell v2, so make sure you are running this in v3, or modify the lines.