July 11, 2011


SOAP in Perl

Interacting with the SoftLayer API SOAP endpoint with Perl

Since writing this guide we've created a Perl specific implementation and manual page. Check them out!
Our Perl SOAP API examples perform simple retrieval operations and output results to your Perl console. We use the SOAP::Lite Perl module to handle generating our SOAP headers, generating our SOAP request, then interpreting the result from the method call. Each of these examples execute a single method call to retrieve its data. We'll start out with a simple direct call, implement an object mask, then combine the two.

In each of these examples you must set the $PORTAL_USERNAME and $API_KEY variables to authenticate to the API.

Example 1: Generating a Server List

First we'll retrieve a list of servers on an account and display their id numbers, hostnames, public IP addresses, and private IP addresses in a simple console table. Hostname, domain name, public IP address, and private IP address are all local properties to the SoftLayer_Hardware data type, so a single call to getHardware in the SoftLayer_Account service is all we need. This example will:

#Connect to the SoftLayer_Account SOAP endpoint via SOAP::Lite
#Build the authenticate SOAP header
#Call getHardware from the SoftLayer_Account service
#Loop through the results of the method call and display table output

This is a very simple call and loop script. The next examples will get more in depth. The output from the code below looks akin to the following:

 +------------+-------------------------------------------------------------+------------------+------------------+
 | HardwareId | Host Name                                                   | Public IP        | Private IP       |
 +------------+-------------------------------------------------------------+------------------+------------------+
 |       1001 | myhostname.example.org                                      |          x.y.z.w |        10.4.1.2  |
 |       1002 | another-server.example.org                                  |          a.b.c.d |        10.4.1.3  |
 |       1003 | and-another-server.example.org                              |          e.f.g.h |        10.4.1.4  |
 +------------+-------------------------------------------------------------+------------------+------------------+
# SoftLayer API Perl-SOAP Example #1 - A server list
#
# Retrieve and display a list of an account's servers id numbers, hostnames,
# public IP addresses, and private IP addresses. Do all of this through a single
# SOAP call to the SoftLayer API, in this case to the getHardware() method in
# the SoftLayer_Account service
# .
#
# Sample Output:
# +------------+-------------------------------------------------------------+------------------+------------------+
# | HardwareId | Host Name                                                   | Public IP        | Private IP       |
# +------------+-------------------------------------------------------------+------------------+------------------+
# |       1001 | myhostname.example.org                                      |          x.y.z.w |        10.4.1.2  |
# |       1002 | another-server.example.org                                  |          a.b.c.d |        10.4.1.3  |
# |       1003 | and-another-server.example.org                              |          e.f.g.h |        10.4.1.4  |
# +------------+-------------------------------------------------------------+------------------+------------------+
#
# The most up to date version of this code can be found at
# 
#
# This code is licensed under the Creative Commons 3.0 Attribute Unported
# License .
 
use SOAP::Lite;
 
# define variables
my $SOAP_ENDPOINT = 'http://api.service.softlayer.com/soap/v3/SoftLayer_Account';
 
# Your portal username
my $PORTAL_USERNAME = "set me";
 
# Your API Access key as generated from the portal
my $API_KEY = 'set me';
 
# Create a SOAP object to make queries to the endpoint
my $soap = SOAP::Lite
    -> uri($SOAP_ENDPOINT)
    -> proxy($SOAP_ENDPOINT)
    ;
 
# Create the header object to be sent along with the request, this will
# authenticate your request
# See 
my $header = SOAP::Header->name("authenticate" =>
  \SOAP::Header->value(
   SOAP::Header->name("username" => $PORTAL_USERNAME),
   SOAP::Header->name("apiKey" => $API_KEY)
   )
);
 
# Define the method you wish to call
my $method = SOAP::Data->name('getHardware');
 
# Call the method and assign the response to the $response object
my $response = $soap->call($method, $header);
 
# Error-checking...
if ($response->fault)
{
    print $response->faultcode, " ", $response->faultstring, "\n";
    die 'Terminating program';
}
else
{
    # For this particular example, we have an array of objects returned, so
    # break them into @hardwareObjects
    my @hardwareObjects = @{$response->result};
 
 
    # Print table headers
    print "+------------+-------------------------------------------------------------+------------------+------------------+\n";
    print "| HardwareId | Host Name                                                   | Public IP        | Private IP       |\n";
    print "+------------+-------------------------------------------------------------+------------------+------------------+\n";
 
    # Loop through the hardware objects and print their data
    foreach my $hardware (@hardwareObjects) {
        printf("| %10s ", $hardware->{id});
        printf("| %-59s ", $hardware->{hostname} . "." . $hardware->{domain});
        printf("| %16s ", $hardware->{primaryIpAddress});
        printf("| %16s |\n", $hardware->{primaryBackendIpAddress});
    }
    print "+------------+-------------------------------------------------------------+------------------+------------------+\n";
 
}

Example 2: Getting a server, its operating system, and its datacenter

Its easy to pull up an object and display its local properties. This next example deals with how to pull up an object and its relational properties with a single call using object masks. In this example we're going to retrieve a single server via its initialization parameter and also pick up its operating system and datacenter. Without an object mask this would require three method calls. One to getObject to retrieve the hardware, one to getOperatingSystem to get its operating system software object, and one to getDatacenter to get the hardware's datacenter location object.

Since operating system and datacenter are directly related to SoftLayer_Hardware objects we'll instead use an object mask to get these two properties when we get our hardware object. Our object mask will contain two items in the following structure:
*operatingSystem
*datacenter

The example code below builds the object mask as another SOAP header and sends it along with the authenticate header to our method call. It goes through the following process:

#Connect to the SoftLayer_Hardware SOAP endpoint via SOAP::Lite
#Build the authenticate SOAP header
#Build the SoftLayer_HardwareObjectMask SOAP header with the operatingSystem and datacenter properties
#Call getObject from the SoftLayer_Hardware service
#Display the results

Object masks make this process take much less time, but example three really shows off its power. Since example two deals with a single server you will need to know its ID number before proceeding. You can find a hardware object's ID number from the getHardware() method in the SoftLayer_Account service. Set the $SERVER_ID variable in this script to the hardware ID you want to fetch. It's output should look like this:

HardwareId: 1001
Host Name: myserver.example.org
Operating System: Redhat
Operating System Version: 4.6-32
Data Center: Seattle

# SoftLayer API Perl-SOAP Example #2 - Getting a server and its software
#
# Retrieve a single server and display its id number, hostname, operating 
# system, and datacenter. We're going to do this with one call to the 
# getObject() method in the SoftLayer_Hardware service 
# . 
# Since the operating system and datacenter are relational properties to 
# SoftLayer_Hardware we need to use an object mask to retrieve them when we get 
# our server record.
#
# Sample Output:
# HardwareId:               1001
# Host Name:                myserver.example.org
# Operating System:         Redhat
# Operating System Version: 4.6-32
# Data Center:              Seattle
#
# The most up to date version of this code can be found at
# 
#
# This code is licensed under the Creative Commons 3.0 Attribute Unported
# License .
 
use SOAP::Lite;
use Data::Dumper;
 
# define variables
my $SOAP_ENDPOINT = 'http://api.service.softlayer.com/soap/v3/SoftLayer_Hardware';
 
# Your portal username
my $PORTAL_USERNAME = "set me";
 
# Your API Access key as generated from the portal
my $API_KEY = 'set me';
 
# The ID of the server we wish to retrieve. You can get your server IDs by
# calling the getHardware() method in the SoftLayer_Account service.
my $SERVER_ID = 'set me';
 
# Create a SOAP object to make queries to the endpoint
my $soap = SOAP::Lite
    -> uri($SOAP_ENDPOINT)
    -> proxy($SOAP_ENDPOINT)
    ;
 
# Create the header object to be sent along with the request, this will
# authenticate your request
# See 
my $header = SOAP::Header->name("authenticate" =>
  \SOAP::Header->value(
   SOAP::Header->name("username" => $PORTAL_USERNAME),
   SOAP::Header->name("apiKey" => $API_KEY)
   )
);
 
# Create the init parameters to limit ourselves to a single object.
# See .
my $initParams = SOAP::Header->name("ns1:SoftLayer_HardwareInitParameters" =>
    \SOAP::Header->value(
        SOAP::Header->name("id" => $SERVER_ID)
    )
);
 
# Create the object mask to mask what you're interested in. In this case we want
# the datacenter and operating system associated with our server.
# see 
my $objectMask = SOAP::Header->name("ns1:SoftLayer_HardwareObjectMask" =>
    \SOAP::Header->value(
        SOAP::Header->name("mask" =>
            \SOAP::Header->value(
                SOAP::Header->name("datacenter"),
                SOAP::Header->name("operatingSystem")
            )
        ),
    )
);
 
# Define the method you wish to call
my $method = SOAP::Data->name('getObject');
 
# Call the method and assign the response to the $response object
# Note here that we've combined all our header objects into an array. You can do
# this as you go if you like.
my $response = $soap->call($method, ($header, $initParams, $objectMask));
 
# Error-checking...
if ($response->fault)
{
    print $response->faultcode, " ", $response->faultstring, "\n";
    die 'Terminating program';
}
else
{
    my $hardwareObject = $response->result;
 
    # Echo the results of this action:
    printf("%-25s %s\n", "HardwareId:", $hardwareObject->{id});
    printf("%-25s %s\n", "Host Name:", $hardwareObject->{hostname} . "." . $hardwareObject->{domain});
    printf("%-25s %s\n", "Operating System:", $hardwareObject->{operatingSystem}->{softwareLicense}->{softwareDescription}->{manufacturer});
    printf("%-25s %s\n", "Operating System Version:", $hardwareObject->{operatingSystem}->{softwareLicense}->{softwareDescription}->{version});
    printf("%-25s %s\n", "Data Center:", $hardwareObject->{datacenter}->{longName});
}

Example 3: Combining it up. Getting a server list along with each server's operating system and datacenter

Now that we know how to pull a list of hardware from a single method call and know how to pull relational properties through an object mask, let's combine the two techniques and get a list of our account's hardware, their operating systems, datacenters, and display the results in a console table. Since we need a list of hardware we're going to go to the getObject() method in the SoftLayer_Account service. This would normally retrieve your general account data. However by defining an object mask that grabs the SoftLayer_Account data type's relational properties for hardware, then get the operating system and datacenter that relate to that hardware. Our object mask now contains three items with the following structure.
*hardware
**operatingSystem
**datacenter

Without an object mask we would need to call getHardware as in the first example, but then loop through every hardware object and call getOperatingSystem and getDatacenter for every single hardware object under your account. This object mask saves you a lot of time as a developer, makes your code cleaner, and lighter to load on our backend systems. Our final example goes through the following process:

#Connect to the SoftLayer_Account SOAP endpoint via SOAP::Lite
#Build the authenticate SOAP header
#Build the SoftLayer_AccountObjectMask SOAP header with the hardware and hardware's operatingSystem and datacenter properties
#Call getObject from the SoftLayer_Account service
#Loop through the results of the method call and display table output

And it's output will look akin to this:

 +------------+-------------------------------------------------------------+---------------------------+--------------+
 | HardwareId | Host Name                                                   | OS Version                | Data Center  |
 +------------+-------------------------------------------------------------+---------------------------+--------------+
 |       1001 | myhostname.example.org                                      | Redhat 5.0-32             |       Dallas |
 |       1002 | another-server.example.org                                  | Microsoft STD-SRV-SP2-32  |      Seattle |
 |       1003 | and-another-server.example.org                              | Microsoft ENT-SRV-SP2-32  |      Seattle |
 +------------+-------------------------------------------------------------+---------------------------+--------------+
# SoftLayer API Perl-SOAP Example #3 - A server list with operating system and datacenter
#
# Retrieve and display a list of an account's servers id numbers, hostnames,
# operatign systems, and datacenters. Do all of this through a single
# SOAP call to the SoftLayer API, in this case to the getObject() method in
# the SoftLayer_Account service
# . Since
# hardware is a relational property to SoftLayer_Account and operating system
# and datacenter are relational properties to SoftLayer_Hardware we have to
# define an object mask to pull the account's associated hardware and each
# hardware's associated operating system and datacenter.
#
# Sample Output:
# +------------+-------------------------------------------------------------+---------------------------+--------------+
# | HardwareId | Host Name                                                   | OS Version                | Data Center  |
# +------------+-------------------------------------------------------------+---------------------------+--------------+
# |       1001 | myhostname.example.org                                      | Redhat 5.0-32             |       Dallas |
# |       1002 | another-server.example.org                                  | Microsoft STD-SRV-SP2-32  |      Seattle |
# |       1003 | and-another-server.example.org                              | Microsoft ENT-SRV-SP2-32  |      Seattle |
# +------------+-------------------------------------------------------------+---------------------------+--------------+
#
# The most up to date version of this code can be found at
# 
#
# This code is licensed under the Creative Commons 3.0 Attribute Unported
# License .
 
use SOAP::Lite;
use Data::Dumper;
 
# define variables
my $SOAP_ENDPOINT = 'http://api.service.softlayer.com/soap/v3/SoftLayer_Account';
 
# Your portal username
my $PORTAL_USERNAME = "set me";
 
# Your API Access key as generated from the portal
my $API_KEY = 'set me';
 
# Create a SOAP object to make queries to the endpoint
my $soap = SOAP::Lite
    -> uri($SOAP_ENDPOINT)
    -> proxy($SOAP_ENDPOINT)
    ;
 
# Create the header object to be sent along with the request, this will
# authenticate your request
# See 
my $header = SOAP::Header->name("authenticate" =>
  \SOAP::Header->value(
   SOAP::Header->name("username" => $PORTAL_USERNAME),
   SOAP::Header->name("apiKey" => $API_KEY)
   )
);
 
# Create the object mask to mask what you're interested in. In this case we want
# the datacenter and operating system associated with the hardware that's
# asscoiated with our account.
# see 
my $objectMask = SOAP::Header->name("ns1:SoftLayer_AccountObjectMask" =>
    \SOAP::Header->value(
        SOAP::Header->name("mask" =>
            \SOAP::Header->value(
                SOAP::Header->name("hardware" =>
                    \SOAP::Header->value(
                        SOAP::Header->name("datacenter"),
                        SOAP::Header->name("operatingSystem")
                    )
                )
            )
        ),
    )
);
 
# Define the method you wish to call
my $method = SOAP::Data->name('getObject');
 
# Call the method and assign the response to the $response object
# Note here that we've combined all our header objects into an array. You can do
# this as you go if you like.
my $response = $soap->call($method, ($header, $initParams, $objectMask));
 
# Error-checking...
if ($response->fault)
{
    print $response->faultcode, " ", $response->faultstring, "\n";
    die 'Terminating program';
}
else
{
    my $account = $response->result;
    my @hardwareObjects = @{$account->{hardware}};
 
    # Print table headers
    print "+------------+-------------------------------------------------------------+---------------------------+--------------+\n";
    print "| HardwareId | Host Name                                                   | OS Version                | Data Center  |\n";
    print "+------------+-------------------------------------------------------------+---------------------------+--------------+\n";
 
    # Loop through the hardware objects and print their data
    foreach my $hardware (@hardwareObjects) {
        printf("| %10s ", $hardware->{id});
        printf("| %-59s ", $hardware->{hostname} . "." . $hardware->{domain});
        printf("| %-25s ", $hardware->{operatingSystem}->{softwareLicense}->{softwareDescription}->{manufacturer} . " " . $hardware->{operatingSystem}->{softwareLicense}->{softwareDescription}->{version});
        printf("| %12s |\n", $hardware->{datacenter}->{longName});
    }
 
    # Print the table footer
    print "+------------+-------------------------------------------------------------+---------------------------+--------------+\n";
}

See Also

*SoftLayer_Account
*SoftLayer_Hardware
*Authenticating to the SoftLayer API
*Using Initialization Parameters in the SoftLayer API
*Using Object Masks in the SoftLayer API

Associated Methods

*SoftLayer_Account::getHardware
*SoftLayer_Account::getObject
*SoftLayer_Hardware::getObject

External Links

*The Perl Directory at perl.org
*SOAP::Lite at SourceForge