Archive for the 'Implementations' Category
Captured in a Gem – The SoftLayer API Client for Ruby
When I first learned about object oriented programming, many years ago, I found that the technique fit me well. I found the process of breaking a computing problem down into objects to be a natural way to analyze many of them. At the same time, my designs are never as elegant as I would like them to be in the first draft. For me, the object oriented design process involves tinkering with the design, trying a couple of iterations, and refining the deconstruction over time. I prefer to work with prototypes and explore their interaction before settling on a final implementation.
When I wrote software in C++, however, I discovered that the language made prototyping difficult. I wanted to focus on objects and their interfaces. Unfortunately, C++ wanted me to concentrate on a number of picky details, the types of the objects, what their constructors might require, and most annoyingly how the source files should be squeezed into a project for the benefit of the compiler. Increasingly I found that the rigor of these details forced my focus on the tools, and not the design I was trying to study. Because of that, I did much of my prototyping in Smalltalk, more specifically Squeak Smalltalk.
Smalltalk is the language that originally coined the term “object oriented”. It is highly dynamic, weakly typed, and above all easy to learn. Squeak’s implementation is interpreted, rather than compiled, which means I could make small changes, and see them running almost immediately. The downside to Squeak is that it lives in its own environment. As with the C++ project/compiler, the Squeak environment requires a bit of struggling with the tools when you want to focus on design, but overall the environment was much more forgiving and offered faster turnarounds than C++.
I didn’t stop looking around for an even better way though. I like to learn new things and I’m a bit of a programming language geek anyway so I’ve tried lots of them. Eventually I found a new language for my prototypes, Ruby.
The Ruby programming language is a bit of a mutt in that it combines features of many other languages, including Smalltalk. Like Smalltalk, Ruby is a pervasively object oriented language, very dynamic, and uses a weak typing system. Unlike Smalltalk, however, Ruby doesn’t have its own environment. In fact, Ruby requires very little in the way of overhead. The language interpreter operates on simple text files and it can be invoked from the command line in a terminal. When prototyping, I find that the simple tool-chain keeps the turnaround after any change to a minimum. For me, that makes Ruby just about ideal.
As an added bonus, Ruby proved to be very helpful in other ways. The language has a full-featured standard library, as well as a thriving community that generates many helpful tools. While I started using it for prototypes, I quickly found other uses for Ruby. For example, at a previous job, on a cross-platform application project, we wanted a single build system that worked on each platform. We wrote it in Ruby, using the object oriented features of the language to factor out platform-specific behavior. The strategy was a solid success.
When I joined the SLDN team, I had been working with Ruby for an number of years. However, it had always been a secondary concern, a tool I picked up along the way to help me reach some other goal, rather than the focus of my effort. As you might imagine, when I started at SoftLayer I was presented with a new opportunity.
Our team’s primary responsibilities is helping developers use the SoftLayer APIs effectively. Before I got here, the team had developed many samples demonstrating how to call the SoftLayer API from different programming languages. Perl and PHP were early examples. Shortly after I arrived a Python sample followed. The similarities in functionality between Python and Ruby identified Ruby as a natural target for implementation. Ruby would also have an added benefit in that it satisfied a pent up desire for a sample in a language, any language, whose name didn’t start with the letter “P”. As the new guy on the team, with some Ruby under his belt, I was given the task of putting a code sample together.
One of the biggest decisions I had to make, right off the bat, was how the code would access the SoftLayer API. The samples we had for other languages relied on either SOAP or XML-RPC. Recently, however, we opened up another mechanism, inspired by the Representational State Transfer (REST) paradigm. I was more familiar with the REST interface than the others, having used to implement the SoftLayer Mobile Client. Moreover, support for SOAP and XML have been removed from the standard library of the latest revision of Ruby, Ruby 1.9. This was done in favor of the wide array of external libraries offered by the Ruby community. By using the REST interface, I would avoid having to tie the sample to one particular implementation of XML technologies to the exclusion of others.
After settling that question, I put my prototyping skills to work trying to find a nice programming model. For once, my prototypes were in the target language, a refreshing change I assure you. I did want to keep the Ruby code sample noticeably similar to the exiting Python code so many decisions from lifted from that sample. At the same time, it would not do to copy the Python design exactly. It was important that a Ruby client fit property in the Ruby language.
Once I had written the code, I prepared it for distribution as a source repository. A colleague, however, suggested that we take the extra step and package the code as a Ruby Gem. The Gems system is a mechanism for distributing Ruby libraries, very similar to the CPAN modules of Perl, or Python’s Eggs. As a Ruby programmer, I’d used Gems many times, but I’d never created one. Doing so required us to change the code a bit, and restructure the directory. On the whole however, the process was straightforward if not downright easy.
Creating the SoftLayer API code sample was fun. It was a quick, concentrated effort, and I’ve already found the resulting library to be very useful. The SLDN team would like to welcome you to check it out yourself. The source for the SoftLayer API Client for Ruby can be found github in the SoftLayer repository, http://github.com/softlayer/softlayer-api-ruby-client. You can also install it for your Ruby distribution as a Ruby Gem. Developers using jRuby users should look for the softlayer_api_jruby gem. Other Ruby distributions should install for the softlayer_api gem. All three distributions include examples that demonstrate how to use the library. The library is intended as sample code and you should feel free to improve upon it for your own use. If you add a particularly useful feature, find a bug, or would like to make a suggestion for improvements we can make ourselves please let us know either on the github page, or through the forums.
No commentsThe SoftLayer Mobile Client: A New Perspective
Much of the development work that goes on here centers on the SoftLayer Customer Portal. The Customer Portal is a traditional Web application that links your browser to the powerful back-end systems that our engineers have crafted over the course of many years. Most of the engineers around here are first rate hands at web application technologies like PHP, JavaScript, and HTML.
I don’t know much HTML. I know even less PHP. I spent many years working on desktop Macintosh applications in C and C++. With the introduction of the iPhone SDK, a new job opportunity made me an iPhone developer. The leap from the Cocoa framework, on the desktop Mac OS, to the Cocoa Touch framework of the iPhone was not difficult at all. The two frameworks share a lot in common and the parts that are different still share a lot of design patterns. All in all, making the transition to a company whose primary focus is web development was a lot more intimidating than picking up the iPhone API.
I joined SoftLayer specifically to work on the Mobile Client. The goal of the SoftLayer Mobile Client is pretty straightforward, put the essential parts of the SoftLayer Customer Portal in the palm of your hand, on your favorite mobile device. We wanted to move beyond the mobile web applications the team had already created, and craft an application with a look and feel only a native applications can provide, a first rate user experience.
At the same time, all the attention to detail you can possibly give the front end doesn’t matter unless you have some way to communicate with the server. That’s where the SoftLayer v3 API comes into play.
The smart folks on the the web application development team work behind the scenes on the server, enjoying full access to the complex machine behind the SoftLayer Customer Portal. Their target has been a traditional web browser, running on a computer with Gigabytes of available RAM, Gigahertz of processing power, and several Megabits per second of network connectivity.
Comparatively, on the Mobile Applications development team, we live across the wire on tiny computers with small pipes. Mobile devices have limited memory constraints, run on a “slow” 3G networks, and have processors running at less than 1/3 of the speed of their desktop counterparts.
With such vast differences between the environment of a desktop computer’s browser and an application running on a mobile device, SoftLayer could have crafted a custom API to give our mobile applications access tailored access to the machine behind the SoftLayer Customer Portal.
But we didn’t want to do that.
With great pride of principle, our mobile applications team makes it a point to use the same API that SoftLayer presents to you, the third party developers of the SLDN network. We don’t want to use back doors, and we don’t want to use secret calls. Consuming our own API, “eating our own dog food” as the saying goes, gives us a unique vantage point which we hope to use to improve the API for all SLDN developers.
In the course of developing the Mobile Client on a variety of platforms, the mobile team has found that most aspects of the SoftLayer API work very well! We’ve also found some that presented challenges to our mobile devices. Lucky for you, however, we’re working very closely with the web development team to remove those challenges.
We plan to bring new functionality that results from our experience directly to you. In the course of the next few months, look for some changes (large and small) to the services we provide. We hope you will find them a benefit to your application development regardless of where your application runs.
2 commentsOur Python client is out!
Lately I’ve seen a lot of people around me writing and hacking in Python. Way back when API v1 was out we noted that Python has built-in XML-RPC support. Built-in XML-RPC support is great. It makes calling our API, especially our latest API, a snap. Some of y’all on our forums have been doing very cool things with our API in Python.
Python hackers and users, we’ve just made your lives easier. I’m pleased to present our latest language tool for your API toolbox, a Python library for the SoftLayer API. This library functions very similarly to our PHP and Perl clients. Before you had to juggle API call headers to pass along things like initialization parameters and object masks to your API calls. Now you all you have to do is declare an API client object and run methods on it. It’s much easier and saves a lot of coding on your part.
I’ve been talking to a lot of people who are building dynamic Cloud Computing Instances using our API. I wrote a simple example for one of our forum users a while back to accomplish this task in Python using it’s built-in XML-RPC support:
Here’s that same functionality using our new Python library:
This saved 20 lines of code and is much easier to read. Our client is supported in both Python 2 and Python 3 and has a handy installation script. Please download it, go nuts, and speak up on our forums, IRC channel, or a support ticket if you have any questions. As always, we’re happy to hear your feedback. Thanks, everyone!
http://github.com/softlayer/softlayer-api-python-client/
No commentsSomething new for your API Toolbox
An interesting facet of the development and systems administration business is the number of 80% projects that build up over time. An 80% project is that awesome library, script, rewrite, new system, or what have you that’s cooling on your back burner. It’s almost done but it’s missing the finishing touches. Maybe it needs a few code tweaks. Maybe it needs a little more documentation. Maybe you’re still finalizing settings and playing with patches. Don’t lie; we know you’ve got these projects hanging around. I’ve got a list of 80% projects as long as my arm.
It’s time to check something off my 80% projects list. I’ve finally finished documenting and am happy to release the SoftLayer API Perl client library! This module will make Perl API hackers’ lives a whole lot easier. Previously you had to build SOAP API calls manually using the SOAP::Lite module and parse the response into something easier to handle. Now you can accomplish the same thing with a series of easy to use helper methods. Functionality is very similar to our PHP client but with a Perl twist. For instance, you can do clever one liners!
use SoftLayer::API::SOAP;
# Grab my account information.
my $account = SoftLayer::API::SOAP->new(
'SoftLayer_Account',
undef,
'my API username',
'my API key')->getObject();
Check out our README for many and more comprehensive examples. Download the library from our github page at:
http://github.com/softlayer/softlayer-api-perl-client
As with all of our projects we’re very open to feedback, so please comment or post on our forums and let us know what you think. I can’t wait knock a few more 80% projects off the ol’ list. You’re going to love them.
See y’all next time!
Object Masks and Filters in C Sharp
Object Masks, Filters, and Other V3 Black Magic
Everyone has heard the age old saying for any given job you need to have the right tool. Just as most of us have tried to use the flat rounded edge of a butter knife a time or two when what we desperately needed was a screw driver. Does that mean you weren’t able to open that little compartment on whatever gizmo and replace the batteries? Probably not. In most cases it is possible to use a butter knife when a screw driver is the tool of choice; it’s just more painful and a lot less effective.
The same can said of the SoftLayer API (SLAPI). It’s a toolset. A very flexible set of tools allowing a developer to manage every aspect of dedicated hosting from accounting and billing to physical status of remote hardware. And yet there are so many tools in the V3 API toolbox, a number of them only subtlety different from their binary brethren ( at least on the surface), it’s tempting just to reach your hand into the bag, find the first thing that resembles a screw driver, and begin turning.
I know. I’m speaking from my own experiences. As a developer who largely works on SoftLayer’s back end systems, somewhere between the bottom of TCP/IP stack and the top edge of the kernel, recently getting to do production user portal code was a new experience for me. Sure I wrote some demos, dabbled a little here and there, but when I started doing my first “real” V3/SLAPI intensive project I realized my prior attempts had entirely missed the true power and elegance of SLAPI. The magic if you will. A little something called ORM.
Those of you who spend your days toiling in the world or relational databases are probably fairly familiar with the term ORM. But for someone like me who usually comes no closer to a database than reading an I/O address from the Windows registry, I was only vaguely aware of what the acronym even stood for. I turned to Webopedia. There I discovered the following. “Short for object role modeling, ORM is a conceptual database design methodology that allows the user to express information as an object and explore how it relates to other information objects”.
So there we have it. Database. Objects. Relations. I learn hands on—so none of that amounts to a hill of beans without some real code I can see and type and run for myself. So rather than regurgitate the SLDN documentation, I will just share a simple yet real life example. Then, in the second part of the article, we can expand that example to show some of the more powerful and less documented features of the V3 SLAPI.
The code that follows is written in Microsoft C Sharp using Visual Studio 2008 Professional Edition. I am not going to step through the basics of connecting a WSDL and generating a SOAP wrapper in this article. If you need help with that, there is an SLDN blog I did a while back which covers those steps entitled, “Dot Net? You Bet!”. It is still available under the implementations section of the SLDN website. True to my MO, I am not a big GUI guy so the code I am presenting runs as a Windows console application.
For the sake of making the example clear, I am going to simplify my task. In the example in both this article, and the next in the series, we will be playing the role of a developer who needs to count how many of his or her servers are running the Microsoft Windows operating system, as opposed to one of the many Linux variants SoftLayer also offers its customers. For our first code sample, we require two WSDLs: the SoftLayer_Account service as well as the SoftLayer_Hardware_Server service. The console program below will get us connected to the SoftLayer application servers, as well as provide us some timing metrics.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SLDN_Magic
{
class Program
{
static void Main(string[] args)
{
//global timing vars
DateTime stopwatch;
TimeSpan elapsed;
//replace with your username and api key
string user_name = "Replace With Your User Name";
string api_key = "Replace With Your API Key";
Console.Write("Establishing connection to SLDN service...");
//time it
stopwatch = DateTime.Now;
//declare the services
SLDN_ACCT.SoftLayer_AccountService acct = new
SLDN_ACCT.SoftLayer_AccountService();
SLDN_SVR.SoftLayer_Hardware_ServerService svr = new
SLDN_SVR.SoftLayer_Hardware_ServerService();
//create an authentification object for each
SLDN_ACCT.authenticate credentials_a = new
SLDN_ACCT.authenticate();
SLDN_SVR.authenticate credentials_b = new
SLDN_SVR.authenticate();
//assign credentials
credentials_a.username = credentials_b.username = user_name;
credentials_a.apiKey = credentials_b.apiKey = api_key;
//authenticate
acct.authenticateValue = credentials_a;
svr.authenticateValue = credentials_b;
elapsed = DateTime.Now.Subtract(stopwatch);
Console.WriteLine("done (" + elapsed.TotalSeconds.ToString() + " seconds)");
Console.WriteLine("\nPress to exit.");
Console.ReadLine();
}
}
}
At this point, we can go ahead and run our code. It doesn’t really do anything all that useful. But never the less you should get an output similar to this.

While writing this article I connected to the SoftLayer API servers numerous times from my home. My connection times were pretty consistent. It took somewhere in the neighborhood of 20 seconds to get everything set up. That seems like a lot. But keep in mind that you only incur the overhead of connecting your services one time. Plus as we get a little further along in this article I will show you how we can use ORM to get rid of one of the references entirely. For now though, let’s move on.
For someone of my background and mindset, what seemed the most straight-forward and correct way to find out which servers were running MS Windows was to access the public method “isWindowsServer()“. This is a method off the server class. That’s why we needed to import the SoftLayer_Hardware_Server service. But we don’t want to check the OS on a single server. We want to recurse through all the servers for an account. Which is why we brought in the SoftLayer_Account service and its attractive public offering “getAllHardware()“.
Keeping this plan in mind, let’s go ahead and implement it in our console application.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SLDN_Magic
{
class Program
{
static void Main(string[] args)
{
//global timing vars
DateTime stopwatch;
TimeSpan elapsed;
//global container
SLDN_ACCT.SoftLayer_Hardware[] hw;
//replace with your username and api key
string user_name = "Replace With Your User Name";
string api_key = "Replace With Your API Key";
Console.Write("Establishing connection to SLDN service...");
//time it
stopwatch = DateTime.Now;
//declare the services
SLDN_ACCT.SoftLayer_AccountService acct = new
SLDN_ACCT.SoftLayer_AccountService();
SLDN_SVR.SoftLayer_Hardware_ServerService svr = new
SLDN_SVR.SoftLayer_Hardware_ServerService();
//create an authentification object for each
SLDN_ACCT.authenticate credentials_a = new
SLDN_ACCT.authenticate();
SLDN_SVR.authenticate credentials_b = new
SLDN_SVR.authenticate();
//assign credentials
credentials_a.username = credentials_b.username = user_name;
credentials_a.apiKey = credentials_b.apiKey = api_key;
//authenticate
acct.authenticateValue = credentials_a;
svr.authenticateValue = credentials_b;
elapsed = DateTime.Now.Subtract(stopwatch);
Console.WriteLine("done (" + elapsed.TotalSeconds.ToString() + " seconds)");
//butter knife method
Console.Write("Retrieving hardware using method 1...");
//get time stamp
stopwatch = DateTime.Now;
hw = null;
try
{
hw = acct.getHardware();
}
catch (Exception e)
{
Console.WriteLine("Exception encountered [" + e.Message + "]");
hw = null;
}
int cnt = 0;
foreach (SLDN_ACCT.SoftLayer_Hardware server in hw)
{
try
{
SLDN_SVR.SoftLayer_Hardware_ServerInitParameters box = new
SLDN_SVR.SoftLayer_Hardware_ServerInitParameters();
box.id = (int)server.id;
svr.SoftLayer_Hardware_ServerInitParametersValue = box;
if (svr.isWindowsServer())
{
cnt++;
}
}
catch (NullReferenceException)
{
//ignore...this server has not had the
//OS loaded on it yet!
}
}
elapsed = DateTime.Now.Subtract(stopwatch);
Console.WriteLine("done (" + elapsed.TotalSeconds.ToString() + " seconds)");
Console.WriteLine("counted " + cnt.ToString() + " MS Windows licenses");
Console.WriteLine("\nPress to exit.");
Console.ReadLine();
}
}
}
That’s it. Pretty straight forward stuff possibly with the exception of the way SLAPI allows you to reinitialize the server (or any object) on the fly by use of:”SoftLayer_Hardware_ServerInitParameters”. If this confuses you, again I’ll refer you to the blog “Dot Net? You Bet!”. At this point, I think we are ready for another test run.

Once again we find ourselves in the twenty second range both for connecting the services and counting the hardware. What you can’t tell from looking at this output is that the account I was using for testing had about 100 servers on it. So basically we are talking 1/5 of a second per server. It’s certainly doable with a handful of servers, but this would obviously never work if you were trying to present this information real time to users if you managed 500 or 5,000 or 50,000 servers. So you are probably asking yourself the same thing I did. What gives? If SoftLayer wishes its customers success on an enterprise level, why create an API that comes to its knees when you start trying to manage more than a few hundred servers?
Luckily, the architects of SLAPI were a lot more web / database savvy than me. The above implementation, while correct syntactically, is a gross misuse of the SLAPI. It’s the butter knife, when what we really need is the screwdriver. What we need are object masks. But exactly what are object masks and how do they relate to ORM?
The best way I have found to understand ORM and object masks, is to think of the SLAPI data objects, as a self supporting entities. Each object provides its own methods and exposes some properties specific to that object. Yet thanks to ORM, most objects can actually get to properties in related objects, through a process called tapping. You simply tap each object down the chain until you find the property or properties you are interested in, prior to retrieving an instance or instances of the object. Then the set of objects returned will expose any relevant properties in the same manner you tapped them.
For example in our case the SLDN architecture relates a server to an operating system in the following manner.

The diagram shows us that essentially, as long as we can get a hardware object, we can tap all the way down to the software description — which as the SLDN documentation states has a “name” property. There by we eliminate two of our most time consuming tasks from our original application. First off we no longer need to instantiate the SoftLayer_Hardware_Server service, since we can get to server from hardware and hardware can be retrieved via the account class. Secondly, if when we return the hardware it already contains the name of the operating system, we no longer have a need to call the “isWindows()” method. Take a look.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SLDN_Magic
{
class Program
{
static void Main(string[] args)
{
//global timing vars
DateTime stopwatch;
TimeSpan elapsed;
//global container
SLDN_ACCT.SoftLayer_Hardware[] hw;
//replace with your username and api key
string user_name = "Your User Name Here";
string api_key = "Your Api Key Here";
Console.Write("Establishing connection to SLDN service...");
//time it
stopwatch = DateTime.Now;
//declare the services
SLDN_ACCT.SoftLayer_AccountService acct = new
SLDN_ACCT.SoftLayer_AccountService();
//create an authentification object
SLDN_ACCT.authenticate credentials_a = new
SLDN_ACCT.authenticate();
//assign credentials
credentials_a.username = user_name;
credentials_a.apiKey = api_key;
//authenticate
acct.authenticateValue = credentials_a;
elapsed = DateTime.Now.Subtract(stopwatch);
Console.WriteLine("done (" + elapsed.TotalSeconds.ToString() + " seconds)");
//method 2
Console.Write("Retrieving hardware using method 2...");
//get time stamp
stopwatch = DateTime.Now;
hw = null;
//attempt to pull a hardware list for this user
try
{
acct.SoftLayer_AccountObjectMaskValue = new
SLDN_ACCT.SoftLayer_AccountObjectMask();
acct.SoftLayer_AccountObjectMaskValue.mask = new
SLDN_ACCT.SoftLayer_Account();
acct.SoftLayer_AccountObjectMaskValue.mask.hardware = new
SLDN_ACCT.SoftLayer_Hardware_Server[1];
acct.SoftLayer_AccountObjectMaskValue.mask.hardware[0] = new
SLDN_ACCT.SoftLayer_Hardware_Server();
acct.SoftLayer_AccountObjectMaskValue.mask.hardware[0].operatingSystem = new
SLDN_ACCT.SoftLayer_Software_Component();
acct.SoftLayer_AccountObjectMaskValue.mask.hardware[0].operatingSystem.softwareLicense = new
SLDN_ACCT.SoftLayer_Software_License();
acct.SoftLayer_AccountObjectMaskValue.mask.hardware[0].operatingSystem.softwareLicense.softwareDescription = new
SLDN_ACCT.SoftLayer_Software_Description();
hw = acct.getHardware();
}
catch (Exception e)
{
Console.WriteLine("Exception encountered [" + e.Message + "]");
hw = null;
}
cnt = 0;
foreach (SLDN_ACCT.SoftLayer_Hardware server in hw)
{
try
{
if (server.operatingSystem.softwareLicense.
softwareDescription.name.ToLower().
Contains("windows"))
{
cnt++;
}
}
catch (NullReferenceException)
{
//ignore...this server has not
//had the OS loaded on it yet!!!
}
}
elapsed = DateTime.Now.Subtract(stopwatch);
Console.WriteLine("done ("+ elapsed.TotalSeconds.ToString()+" seconds)");
Console.WriteLine("counted " + cnt.ToString() + " MS Windows licenses");
Console.WriteLine("\nPress to exit.");
Console.ReadLine();
}
}
}
You should notice right away all the references to SoftLayer_AccountObjectMaskValue prior to calling the “getHardware()” method. This is the object mask. Essentially we must create a new instance of each entity we want to include down the chain. Then when the target object is retrieved, in our case the hardware, all related objects which we have made room for will get created for that specific instance of hardware, assuming of course a record exists. You must instantiate each object down the chain. If you skip any link your result set will not conatain the property or method you were trying to get to. Some less structured langagues, like PHP, do not have this requirement. But with V3 and dot NET there is no getting around it. You’re probably thinking this version of the code looks far more cluttered and is not as straight-forward to read. You’re right. But I contend this is the electric screwdriver in the SLDN toolbox. See for yourself.

As you can see the connection overhead dropped in half, which is to be expected since we are only authenticating to half the number of services. But take a look at the second number, the number of seconds it takes to count the servers with Windows installed. It dropped from 20 seconds, to under 2 seconds. That’s a 10 times speed gain. And wait there’s more– because we are only making one call to the SLDN application servers to retrieve those records what you see is what you get. Meaning you should not expect that time to increase noticeably whether you have a hundred servers or a hundred thousand servers! That my friend is the magic of V3. The power of ORM.
Following this article I will include the entire code base, in a combined application that lets you run the tests sequentially so you can see the amazing difference object masks make for yourself. In the second part to this article, we’ll continue with the sample so if you download it keep it handy. In part two I’ll discuss the next best thing to object masks—object filters. With object filters we’ll be able to streamline this code even more. Until then…happy SLDNing!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SLDN_Magic
{
class Program
{
static void Main(string[] args)
{
//global timing vars
DateTime stopwatch;
TimeSpan elapsed;
//global container
SLDN_ACCT.SoftLayer_Hardware[] hw;
//replace with your username and api key
string user_name = "";
string api_key = "";
Console.Write("Establishing connection to SLDN service...");
//time it
stopwatch = DateTime.Now;
//declare the services
SLDN_ACCT.SoftLayer_AccountService acct = new SLDN_ACCT.SoftLayer_AccountService();
SLDN_SVR.SoftLayer_Hardware_ServerService svr = new SLDN_SVR.SoftLayer_Hardware_ServerService();
//create an authentification object for each
SLDN_ACCT.authenticate credentials_a = new SLDN_ACCT.authenticate();
SLDN_SVR.authenticate credentials_b = new SLDN_SVR.authenticate();
//assign credentials
credentials_a.username = credentials_b.username = user_name;
credentials_a.apiKey = credentials_b.apiKey = api_key;
//authenticate
acct.authenticateValue = credentials_a;
svr.authenticateValue = credentials_b;
elapsed = DateTime.Now.Subtract(stopwatch);
Console.WriteLine("done (" + elapsed.TotalSeconds.ToString() + " seconds)");
//method 1
Console.Write("Retrieving hardware using method 1...");
//get time stamp
stopwatch = DateTime.Now;
hw = null;
try
{
hw = acct.getHardware();
}
catch (Exception e)
{
Console.WriteLine("Exception encountered [" + e.Message + "]");
hw = null;
}
int cnt = 0;
foreach (SLDN_ACCT.SoftLayer_Hardware server in hw)
{
try
{
SLDN_SVR.SoftLayer_Hardware_ServerInitParameters box = new SLDN_SVR.SoftLayer_Hardware_ServerInitParameters();
box.id = (int)server.id;
svr.SoftLayer_Hardware_ServerInitParametersValue = box;
if (svr.isWindowsServer())
{
cnt++;
}
}
catch (NullReferenceException)
{
//ignore...this server has not had the OS loaded on it yet
}
}
elapsed = DateTime.Now.Subtract(stopwatch);
Console.WriteLine("done (" + elapsed.TotalSeconds.ToString() + " seconds)");
Console.WriteLine("counted " + cnt.ToString() + " MS Windows licenses");
//method 2
Console.Write("Retrieving hardware using method 2...");
//get time stamp
stopwatch = DateTime.Now;
hw = null;
//attempt to pull a hardware list for this user
try
{
acct.SoftLayer_AccountObjectMaskValue = new SLDN_ACCT.SoftLayer_AccountObjectMask();
acct.SoftLayer_AccountObjectMaskValue.mask = new SLDN_ACCT.SoftLayer_Account();
acct.SoftLayer_AccountObjectMaskValue.mask.hardware = new SLDN_ACCT.SoftLayer_Hardware_Server[1];
acct.SoftLayer_AccountObjectMaskValue.mask.hardware[0] = new SLDN_ACCT.SoftLayer_Hardware_Server();
acct.SoftLayer_AccountObjectMaskValue.mask.hardware[0].operatingSystem = new SLDN_ACCT.SoftLayer_Software_Component();
acct.SoftLayer_AccountObjectMaskValue.mask.hardware[0].operatingSystem.softwareLicense = new SLDN_ACCT.SoftLayer_Software_License();
acct.SoftLayer_AccountObjectMaskValue.mask.hardware[0].operatingSystem.softwareLicense.softwareDescription = new SLDN_ACCT.SoftLayer_Software_Description();
hw = acct.getHardware();
}
catch (Exception e)
{
Console.WriteLine("Exception encountered [" + e.Message + "]");
hw = null;
}
cnt = 0;
foreach (SLDN_ACCT.SoftLayer_Hardware server in hw)
{
try
{
if (server.operatingSystem.softwareLicense.softwareDescription.name.ToLower().Contains("windows"))
{
cnt++;
}
}
catch (NullReferenceException)
{
//ignore...this server has not had the OS loaded on it yet
}
}
elapsed = DateTime.Now.Subtract(stopwatch);
Console.WriteLine("done ("+elapsed.TotalSeconds.ToString()+" seconds)");
Console.WriteLine("counted " + cnt.ToString() + " MS Windows licenses");
Console.WriteLine("\nPress to exit.");
Console.ReadLine();
}
}
}
No comments
Using CURL to access CloudLayer Storage
CloudLayer Storage is billed as providing “anytime, anywhere access to your data”. This isn’t just referring to human interfaces, but also includes automated interfaces.
One easy way to automate access to CloudLayer Storage is through curl. Curl is available as a command-line tool in most every operating system and is typically used for transferring files. In this post I’ll show some examples on how to use curl to add, get, delete, or otherwise manipulate files in CloudLayer Storage. Note that this isn’t using the SoftLayer API, but instead interfaces directly with CloudLayer Storage.
Upload a file named “DSC1012.jpg” to an account owned by username “user@example.com” with a password of “PaSsWoRd”:
# curl –F filename=@DSC1012.jpg –u user@example.com:PaSsWoRd \
https://storage.cloudlayer.com/v1/files/
The command will return some XML tags. The items of interest are “FileID” and “lockID”. These values are important for future operations on the file.
<fileID>102C9C28-65C3-11DE-1234-2BE68BA216C2</fileID>
<lockID>6CDCEEB2-6B38-11DE-A510-123F439A2728</lockID>
<lockDuration>120</lockDuration>
The lock is to protect a file form reading or being manipulated during the upload process. The lock will expire in “lockDuration” seconds or the user can disable the lock manually.
Here is how to disable the lock using the lockID and the fileID generated from the upload operation:
# curl –d \
'action=unlock&lockid=6CDCEEB2-6B38-11DE-A510-123F439A2728' \
–u user@example.com:PaSsWoRd \
https://storage.cloudlayer.com/v1/files/102C9C28-65C3-11DE-1234-2BE68BA216C2/lock
If you ever lose track of the FileID, you can use this command to retrieve a listing of the files and containers (directories) in an account along with the FileIDs which are listed as an “oid” XML tag.
# curl –u user@example.com:PaSsWoRd \
https://storage.cloudlayer.com/v1/files/list
To get the list of files in a container, just append the container oid to the URL.
# curl –u user@example.com:PaSsWoRd \
https://storage.cloudlayer.com/v1/files/list?oid=37D0F2AC-08FC-11DE-1234-3FA3A91CD1B4
To retrieve the file from CloudLayer Storage, use the FileID to retrieve it.
# curl -u user@example.com:PaSsWoRd \
https://storage.cloudlayer.com/v1/files/37D0F2AC-08FC-11DE-1234-3FA3A91CD1B4/ -o outputfilename
Alternatively, you could use “wget” to retrieve the file
# wget –http-user=user@example.com -–http-password=PaSsWoRd \
https://storage.cloudlayer.com/v1/files/37D0F2AC-08FC-11DE-1234-3FA3A91CD1B4/ -O outputfilename
To delete a file just add the POST form variable “action” with the value “delete”.
# curl –d 'action=delete' –u user@example.com:PaSsWoRd \
https://storage.cloudlayer.com/v1/files/37D0F2AC-08FC-11DE-1234-3FA3A91CD1B4/
Each of the commands listed above return data in XML format. If you would prefer json format, add a query parameter “output=json” to the query string.
# curl –u user@example.com:PaSsWoRd \
https://storage.cloudlayer.com/v1/files/list?output=json
In order to create a public URL for a file, just send a POST variable of “action=create” to the “token” endpoint.
# curl -d 'action=create' -u user@example.com:PaSsWoRd \
https://storage.cloudlayer.com/v1/files/37D0F2AC-08FC-11DE-1234-3FA3A91CD1B4/token/
The long string “37D0F2…” is the oid (a.k.a FileID) of the file that you can get from the XML returned when the file was uploaded, or retrived using the file listing example above.
In the XML (or JSON) data that is returned, there will be a “token”.
<token>B2891F7B054EF2DF764801E1CFF0079057291234</token>
That token can be combined with the oid to create a URL that anyone can use to retrieve the file.
The URL looks like this:
https://storage.cloudlayer.com/v1/public/{oid}/{token}
In our example it would be:
https://storage.cloudlayer.com/v1/public/37D0F2AC-08FC-11DE-1234-3FA3A91CD1B4/B2891F7B054EF2DF764801E1CFF0079057291234
If you are accessing CloudLayer Storage from inside a SoftLayer datacenter, you can access the storage over the SoftLayer private network (no bandwidth fees!). Just use “scs.service.softlayer.com” instead of “storage.cloudlayer.com”.
You can use the information above in conjunction with the curl libraries in PHP, C++, or one of many other programming languages with curl bindings.
1 commentThe start of something good
I’ve been working with quite a few PHP users on our forums over the past few months. One thing I love is the sheer variety of tasks you guys are accomplishing. One thing I don’t really love is how y’all use the sample code we provided when we launched our new API last year. Our examples work great for API v1 to API v3 migrations, but those simple functions don’t really do our current API justice.
To that end I’ve written a new PHP API client. This small library will let you take real advantage of the features our API has to offer (like object masks, result limits, proper exception catching, and the like) in both SOAP and XML-RPC. Please download it from our new presence on the github social code hosting site. Come check us out at:
Right now all that’s up there is our PHP API client. We’ll put more client libraries and projects up as we make them. We’ve got a a few in the works right now. If you’ve already got a github account come find us! We love to meet those who want to use and modify our work. If you have a favorite language that you want to see a client library for please let us know and we’ll see what we can do. The next language on my hit list is Python 2.6. See y’all next time!
No commentsDot Net? You Bet!
Greetings fellow SLAPI enthusiasts! When the call went out for examples I figured why not cowboy up and try my hand at with a .NET example. After all, being an MCP in a largely PHP shop makes me as qualified as anyone. Plus I am constantly pushing the Microsoft Kool-Aid around the office so this was a chance to put my money where my mouth is.
Unfortunately, there was just one catch—I’m not a .NET programmer. I’ve got 10 years of experience writing drivers, protocol suites, and firmware. In other words, C/C++ with a little bit of assembler thrown in when push comes to shove. Sure I can write a c-sharp application, but I’m pretty green at it and until a month ago if someone had told me they had a problem with their WSDL (pronounced wiz’duhl) I would have wondered why they were telling me instead of their urologist!
That said, what follows is a pretty basic SLAPI example, done in both C# and VB.NET (because I’m ambi-dot-dextrous). Don’t expect anything more than a DOS-style command console for the UI. I’m used to letting the Microsoft’s control panel give the user any feedback and usually consider my code to be ready to ship if it can run for 24 hours without blue-screening the box!
My chops are on display at the SLDN API Wiki. Let me know what you think!
No commentsPerls of Wisdom
It’s been a little over a week since our API launch. I haven’t heard from anyone who doesn’t like it, so that must mean we’re doing it right. We’ve been spending time lately catching up on little quirks and documentation bugs. Our first example is up. Its for you Perl jockeys, and really exemplifies the flexibility and power of object masks in your API handling code. We’ve got a .NET one coming up soon. You guys are going to love how easy it is to use this in Visual Studio. We’ve got plans for PHP and Java coming up too. If there’s a language or implementation you want to see please let us know!
In other news, SoftLayer has recently launched a shiny new Facebook group. Sign in and join up to talk with us and get your hands-on exclusive content (which currently is videos of me rambling about the API). As always, we’re here if you have questions, concerns, or just want to chat. See you next time!
No commentsTime for some morning Java
(This post refers to SoftLayer API version 1. Check out API version 3 for our latest updates.)
We’ve put a Java SOAP example up on our downloads page. This was written in Eclipse 3.2.2, and for your convenience the example package contains our Eclipse project files. The code should run on JVM version 1.4 and above. We’d love to hear your feedback on this example. Reply here or post on our forums and let us know what you think. See ya’ll later!
No comments