HP server warranty via the ISEE API

TL;DR: Here’s a simple proof of concept program to look up HP server warranty details via the HP ISEE API. That’s right: no more web scraping.

If you’ve ever tried to look up warranty details for an HP server, you’ve probably come across some of these:

  1. http://h20566.www2.hp.com/portal/site/hpsc/public/wc/home/
  2. http://h20000.www2.hp.com/bizsupport/TechSupport/WarrantyLookup.jsp
  3. http://h10025.www1.hp.com/ewfrf/wc/weInput

For anything other than a couple of servers, these are useless. Also:

  • The last one is for non-server products. I wish it clearly said so.
  • Two different UIs for warranty lookup. No link between them.
  • One requires the product number for 10-digit serials, while the other does not. I’m guessing that’s due to duplicate serials coming from various aquisitions over the years.
  • The output data varies significantly. The first one is definitely the most interesting.

So you sit there and copy-paste serials and product numbers while your life drains away at every click, and then you get the brilliant idea of automating the process with some scripting and scraping. There are tons of implementations readily available, but you realize that each time you scrape HTML, another .NET-SOA-SAAS-XML-J2EE developer is employed somewhere in the world and will somehow find a way to get on your nerves with some poorly implemented, massively bloated piece of software that you have to run through fucking Mono.

So you curse and throw up your hands, and then someone comes along and suggests HP SIM. Yes, the 1.8GB interstellar monster that somehow runs with the smallest number of wtfs on Windows 2008 with another few gigabytes of MS SQL Server on board. Oh, and then you need 800 additional megabytes for HP Insight Remote Support Advanced (RSA) which lets you do warranty lookups. Great.

In reality, all you need when looking up warranty details is a couple of lines of XML.

RSA uses HP’s Instant Support Enterprise Edition (ISEE) API, and damn is it enterprise. In short, it’s a SOAP interface that sends embedded XML documents back and forth. There’s no WSDL available, so let’s walk through the process in full, including details on the service interface.

Client Registration

A client must supply a GDID and registrationToken parameter with every warranty lookup. These parameters are obtained from the server response when the client carries out the registration process, which goes as follows:

SOAP action: http://www.hp.com/isee/webservices/RegisterClient2
HTTP URL:    https://services.isee.hp.com/ClientRegistration/ClientRegistrationService.asmx

The SOAP envelope:

File: register_soapenv.xml

<SOAP-ENV:Envelope
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:iseeReg="http://www.hp.com/isee/webservices/">
  <SOAP-ENV:Body>
    <iseeReg:RegisterClient2>
      <iseeReg:request>
         ...
      </iseeReg:request/>
    </iseeReg:RegisterClient2>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The ISEE registration request is then inserted as text in the <iseeReg:request> tag. It is a fairly verbose blob, and yes, it has been stripped down to the bare minimum accepted by the server.

File: register_payload.xml

<isee:ISEE-Registration schemaVersion="5.00"
    xmlns:isee="http://www.hp.com/schemas/isee/5.00/event">
  <RegistrationSource>
    <HP_OOSIdentifiers>
      <OSID>
        <Section name="SYSTEM_IDENTIFIERS">
          <Property name="TimestampGenerated"/>
        </Section>
      </OSID>
      <CSID>
        <Section name="SYSTEM_IDENTIFIERS">
          <Property name="CollectorType" value="MC3"/>
          <Property name="CollectorVersion" value="T05.80.1 build 1"/>
          <Property name="AutoDetectedSystemSerialNumber" value="10"/>
          <Property name="SystemModel" value="HP ProLiant"/>
          <Property name="TimestampGenerated"/>
        </Section>
      </CSID>
    </HP_OOSIdentifiers>
    <PRS_Address>
      <AddressType>0</AddressType>
      <Address1/>
      <Address2/>
      <Address3/>
      <Address4/>
      <City/>
      <Region/>
      <PostalCode/>
      <TimeZone/>
      <Country/>
    </PRS_Address>
  </RegistrationSource>
  <HP_ISEECustomer>
    <Business/>
    <Name/>
  </HP_ISEECustomer>
  <HP_ISEEPerson>
    <CommunicationMode>255</CommunicationMode>
    <ContactType/>
    <FirstName/>
    <LastName/>
    <Salutation/>
    <Title/>
    <EmailAddress/>
    <TelephoneNumber/>
    <PreferredLanguage/>
    <Availability/>
  </HP_ISEEPerson>
</isee:ISEE-Registration>

Note:

  • Both TimestampGenerated properties must contain a near-current timestamp on the form %Y/%m/%d %H:%M:%S %Z. Use time zone “GMT” in case of problems.
  • The AutoDetectedSystemSerialNumber property need not contain a valid serial; it’s enough with two (or more) digits.

The server will then return:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <RegisterClient2Response xmlns="http://www.hp.com/isee/webservices/">
      <RegisterClient2Result>
        <IsSuccess>true</IsSuccess>
        <Gdid>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</Gdid>
        <BackoffMultiplier>1</BackoffMultiplier>
        <RegistrationToken>XXX</RegistrationToken>
      </RegisterClient2Result>
    </RegisterClient2Response>
  </soap:Body>
</soap:Envelope>

Save the Gdid and the massively long RegistrationToken values so they can be used in upcoming requests.

Warranty Lookup

Next up is the warranty (aka entitlement) lookup itself. The GDID and registrationToken parameters are included in the SOAP/ISEE header. Again, this is the bare minimum accepted by the server, so even the empty <isee:OSID/> and <isee:CSID/> tags must be present.

SOAP action: http://www.hp.com/isee/webservices/GetOOSEntitlementList2
HTTP URL:    https://services.isee.hp.com/EntitlementCheck/EntitlementCheckService.asmx

File: warranty_soapenv.xml

<SOAP-ENV:Envelope
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:isee="http://www.hp.com/isee/webservices/">
  <SOAP-ENV:Header>
    <isee:IseeWebServicesHeader>
      <isee:GDID>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</isee:GDID>
      <isee:registrationToken>XXX</isee:registrationToken>
      <isee:OSID/>
      <isee:CSID/>
    </isee:IseeWebServicesHeader>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <isee:GetOOSEntitlementList2>
      <isee:request>
        ...
      </isee:request>
    </isee:GetOOSEntitlementList2>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The <isee:request> tag should then contain the following payload.

File: warranty_payload.xml

<isee:ISEE-GetOOSEntitlementInfoRequest
    xmlns:isee="http://www.hp.com/schemas/isee/5.00/entitlement"
    schemaVersion="5.00">
  <HP_ISEEEntitlementParameters>
    <CountryCode>ES</CountryCode>
    <SerialNumber>CZ10130050</SerialNumber>
    <ProductNumber>519841-425</ProductNumber>
    <EntitlementType></EntitlementType>
    <EntitlementId></EntitlementId>
    <ObligationId></ObligationId>
  </HP_ISEEEntitlementParameters>
</isee:ISEE-GetOOSEntitlementInfoRequest>

Note:

  • The empty tags must also be present.
  • The CountryCode need not match the origin country.
  • To look up multiple entries, simply add more HP_ISEEEntitlementParameters sections.

The server response SOAP envelope:

<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <GetOOSEntitlementList2Response
        xmlns="http://www.hp.com/isee/webservices/">
      <GetOOSEntitlementList2Result>
        <IsSuccess>true</IsSuccess>
        <Gdid>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</Gdid>
        <BackoffMultiplier>1</BackoffMultiplier>
        <Response>
          ...
        </Response>
      </GetOOSEntitlementList2Result>
    </GetOOSEntitlementList2Response>
  </soap:Body>
</soap:Envelope>

..and then finally, the warranty data itself. It can easily be hundreds of lines, so here’s a link to an example result: warranty-ok.xml

Each entry in the lookup is returned in its own <Data> section with a running frame count. You can also see that since the lookup specified the wrong CountryCode “US”, the response includes a warning about a mismatch with the database’s ship-to country.

Notes

There appears to be no WSDL available, so the SOAP envelope can be constructed manually or a WSDL can be reconstructed from the XML. I’m guessing that the client and server applications have been built and deployed directly from a Visual Studio project with no particular need for a WSDL.

The web interface lets you look up the serial only, but that seems to be impossible in the api. This is unfortunate for quick manual lookups, but isn’t really an issue for batch requests; the product number is readily available in any kind of iLO and also in the SMBios system SKU number.

Multiple warranty entries per request saves a lot of round-trips, but there is bound to be a maximum number of entries allowed per request. That number is not yet known.

The server returns a variety of error codes on malformed input. With the missing WSDL, error handling has to be inferred from the api by fuzzing it with invalid data. Some common error examples:

In addition to the enterprise choice of XML-in-XML, there are some odd inconsistencies in the api, such as Gdid vs GDID and RegistrationToken vs registrationToken, unused XML namespaces, inconsistent namespace local names, versioned SOAP actions (GetOOSEntitlementList2), etc. Beware when coding.

Apart from the register and entitlement lookup functions, the api supports other SOAP actions. Here’s a partial(?) list:

SOAP URLs that match some of the actions above:

Closing Words

The overall characteristics of the api makes it pretty clear that it is not designed for 3rd party use, but it certainly provides all the warranty info you need and it lets you avoid embarrassing HTML scraping. So I wish HP would publish api details and openly encourage its use, particularly for read-only authoritative data like warranty details. It doesn’t need to be the ISEE api in particular, but something well-engineered that provides the same (or better) level of detail.

As for functions other than warranty lookup, I can understand the desire to limit access to phone-home mechanisms for error reporting, hardware replacements, support cases, etc, but I would maintain that a strict api would easily limit abuse and poorly formed requests, and let competent users integrate the functionality into their own systems. One thing is for sure: Being forced to use vendor-specific, sub-par management software is definitely not the right way to go.

RAID management from hell

This, ladies and gentlemen, is the state of the art when it comes to RAID management in 2013. It’s the monumentally awful LSI MegaRAID BIOS configuration interface on a fairly recent Dell C8000 series system:

My First RAIDâ„¢ by Hasbro

My First RAIDâ„¢ by Hasbro

I’m seriously offended. Who the hell lets this sort of garbage through QA for a high end product? It features such brilliant highlights as:

  • A faux windowing UI, with a god damn mouse cursor as primary input.
  • Yes, your eyes do not deceive you: A fucking WordArt logo.
  • A beautiful color scheme inspired by Windows 3.1.
  • A mouse cursor with Parkinson’s, simply useless over remote KVM.
  • Rage-inducing tab-tab-tab-enter keyboard navigation.
  • Highlighted shortcut keys with no obvious way of activating them (no Alt+key).
  • “WebBIOS is an HTML-based utility that is embedded in the firmware”. So they’ve implemented a browser in the BIOS firmware. Top job, I say, and an exquisite choice of technology. If only the Internet was more like LSI’s vision of the web.
  • A bad idea in 2003; a terrible idea in 2013; a horrible idea since always.

Luckily there’s an alternative to this madness in the slightly less dreadful MegaCLI command line tool. It’s a proprietary binary that at least doesn’t limit your options, but it is clearly not a work of art.

LSI: Get your shit together. Release full specs and source for MegaCLI and its character device interface under a permissive license to let distros include it or better yet, write a better one. You obviously do hardware better than software.

Dell: Demand better from LSI and raise the bar for software quality, both for third parties and yourself.

Dell serial number to UUID transform

This week’s useless exercise is about transforming between Dell serial numbers and UUIDs (in network byte order). Here’s an example showing how it works. The vv indicates direct ascii en/decoding and xx are unused constants. Those constants might mean something, but I have no idea what.

44 45 4c 4c - 33 00 - 10 34 - 80 36 - c4 c0 4f 32 33 4a
 D  E  L  L   vv xx - xx vv   xx vv   || xx xx vv vv vv
                                      ||
            +---<---- AND 0x7f ---<---++
            +--->----  OR 0x80 --->---++
            |
            D  3          4       6             2  3  J

Doing the en/decoding in Python:

import binascii

def decodeuuid(uuid):
    data = binascii.unhexlify(uuid.replace('-',''))
    assert len(data) == 16
    return ''.join([
        chr(ord(data[10]) & 0x7f),
        data[4],
        data[7],
        data[9],
        data[13:]   
    ])

def encodeserial(serial):
    assert len(serial) == 7
    return binascii.hexlify('DELL%c%c%c%c%c%c%c%c%c%c%c%c' % (
        serial[1],  
        0x00,
        0x10,
        serial[2],  
        0x80,
        serial[3],  
        ord(serial[0]) | 0x80,
        0xc0,
        0x4f,
        serial[4],  
        serial[5],  
        serial[6],  
    ))

I originally wanted to fix a blank serial number on a system. It has UUID 44454c4c-0000-1020-8020-80c04f202020, and I thought I could derive the serial from that. Of course it turns out that the serial was just spaces after decoding. This indicates that the UUID is generated from the serial number and not the other way around.

Pulling warranty details from api.dell.com

Update 2014-04-04: In a moment of brilliance, Dell has published documentation for both their warranty and case management APIs! Mind blown. Thanks, Dell. Thell.

In 2012 Brian Mulloy helped Dell launch api.dell.com. As opposed to their older SOAP API for warranty lookup, this one actually gives you the full warranty details. Let’s get straight to it.

For any URL access, you need to supply a 16-character apikey URL parameter. Until there’s some sort of registration service available, valid API keys at the moment are:

1adecee8a60444738f280aad1cd87d0e
d676cf6e1e0ceb8fd14e8cb69acd812d
849e027f476027a394edd656eaef4842

The URL resources (the last part of the URL path) can generally be accessed three ways:

resource       Returns XML
resource.xml   Returns XML
resource.json  Returns JSON (poorly disguised XML)

There are two interesting URLs. First, the warranty lookup:

https://api.dell.com/support/v2/assetinfo/warranty/tags?<args>

Apart from the apikey, you must supply a svctags parameter consisting of a list of 1 to 100 (max) service tags, separated by | (pipe symbol). Here’s an example.

The second interesting URL provides a mapping of codes to descriptions:

https://api.dell.com/support/v2/assetinfo/codemapping/type?ctype=<ctype>

where

ctype=type1    Country code to country name or region
ctype=type2    Warranty type code to description

Note that type2 descriptions are already present in the warranty info, so it’s not really necessary to fetch it. Plus, some warranty codes are not listed in the type2 list anyway (for example BZ for “Bronze Software Support”).

Dell have clearly thought of more uses for their api, such as case reporting. While it would be interesting to figure out how it works, it’ll have to wait for now.

I think this api is a very nice step in the right direction, although I wish Dell would open up more to free and independent use (especially of read-only operations such as warranty lookup) instead of the fairly closed approach they’ve taken so far: There’s nearly nearly zero published information about past and current apis — only sporadic forum posts and the occational WDSL — and lots of focus on pushing their management software as the sole consumer of the api. And let’s be honest, Dell does hardware a billion times better than they do software, which is why I prefer the option of handling the software on my own.

HP iLO authorization? Nah

This is old news and certainly not the end of the world, but just so it’s clear: Always keep your management network internal only.

Any version of iLO will by default happily provide anyone who can access it with details on product type, serial number, iLO firmware version, etc. This can be a convenience when autodetecting nodes on your management network.

Here are some exposed iLOs, courtesy of Shodan:

There’s also /xmldata?item=CpqKey that’s probably useful for something.

Oh, and FORTRAN called and congratulated on the all-caps XML.

Fuckin’ UUIDs, how do they work?

Pretty much any computer these days has an smbios full of lovely data. The system UUID is particularly useful for identifying and keeping track of your servers. You happily assume it’s set in stone from now until the end of time, but then someone comes along and fucks up the byte order.

Here are some brilliant wtfs from a HP server:

# dmidecode -s system-uuid
43315434-3341-3255-5832-333731303946

$ curl -ks "https://ilo4/xmldata?item=All"
34543143-4133-5532-5832-333731303946

So the first three fields are in reverse byte order. Which one is the right one? Neither. Or both? Hngh!

HP’s UUID is a simple ascii encoding of the six-digit product number plus the ten-digit serial number:

$ python -c "import binascii as b
print b.hexlify('C1T43A2UX237109F');"
43315434334132555832333731303946

So dmidecode gets it right? Yeeaano. Not according to section 7.2.1 in version 2.6 of the smbios spec. In short, assumptions and poor specs have resulted in yet another mess. Dmidecode 2.10 adds the little endian parsing for smbios versions >= 2.6.

Here’s Dell doing the same thing:

# dmidecode -s system-uuid
44454c4c-4d00-105a-8058-cac04ca8474a

Note the broken UUID format in the second field in the iDRAC’s SMASH CLP:

-> show admin1/system1
OtherIdentifyingInfo={
  4c4c4544-04d-5a10-8058-cac04ca8474a,

..and enumerating the WSMan CIM_ComputerSystem class gives the same result:

<wsinst:OtherIdentifyingInfo>
  4c4c4544-04d-5a10-8058-cac04ca8474a
</wsinst:OtherIdentifyingInfo>

Dell have later added the WSMan DCIM_SystemView:smbiosGUID value that presents the uuid in network byte order (same as dmidecode <= 2.9).

Oh, and Dell’s C6100 servers come with the same UUID and serial numbers for all nodes in the enclosure. Thanks a lot, Dell.

More details on this UUID wtfery here.