jgillman's Liquid Web Update Unofficial tips, tricks, and happenings from a Liquid Web sales engineer

18Jul/114

Utilizing the Storm API with PHP

One of most powerful features of StormOnDemand is the API.

With the API, you can do anything with your Storm account programmaticaly that you can in the regular web based interface. It's a powerful tool that would allow for things such as automatic instance resizing based on load, emailed load reports, etc. However, I think that the API isn't utilized as much because people might not know how to work with it. What follows is a primer for utilizing PHP to interface with the API (I know PHP much, much, much more than Perl).

Although the documentation might seem a little terse in regards to making calls to the API, it essentially boils down to HTTP POST methods utilizing one of the supported encodings, which are currently JSON, YAML, and XML. Making these calls procedurally can quickly turn your code into something that resembles Italian cuisine, which is why I cobbled together a class to take a more object oriented approach.

The class utilizes the YAML encoding method, as well as the HTTP_REQUEST2 PEAR package. Again, this is just something that I put together, and there are probably much better ways to approach this. But it works. Here is the source:

 PHP | 
 
 copy code |
?

01
<?php
02
	/*
03
	 * Author: Jason Gillman Jr.
04
	 * Description: This is my attempt at writing a PHP wrapper that will ease Storm API calls with PHP
05
	 * 				It will be designed to use the YAML format for talking with the API server.
06
	 * 				$api_method is as described in docs (Case matters)
07
	 * 				request() method returns an array generated from the API return
08
	 */
09
	class StormAPI
10
	{
11
		// Let's define attributes
12
		private $api_user, $api_pass, $base_url, $api_format, $api_full_uri, $api_request;
13
		private $api_request_body, $api_method, $api_params, $api_return; 
14
 
15
		function __construct($api_user, $api_pass, $api_method)
16
		{
17
			// Requires PEAR Package HTTP_Request2
18
			require_once('HTTP/Request2.php');
19
 
20
			$this->api_user = $api_user;
21
			$this->api_pass = $api_pass;
22
			$this->api_method = $api_method;
23
			$this->base_url = 'https://api.stormondemand.com/';
24
			$this->api_format = 'yaml';
25
 
26
			$this->api_full_uri = $this->base_url . $this->api_method . "." .$this->api_format;
27
		}
28
 
29
		function add_param($parameter, $value)
30
		{
31
			$this->api_request_body['params'][$parameter] = $value;
32
		}
33
 
34
		function request()
35
		{
36
			// HTTP Request goodness
37
			if(isset($this->api_request_body)) // We have params
38
			{
39
				$api_request = new HTTP_Request2($this->api_full_uri, HTTP_Request2::METHOD_POST); // Instantiate with POST method since we'll be feeding params
40
				$api_request->setHeader('Content-type: application/yaml'); // Specify what you're feeding it
41
				$api_request->setBody(yaml_emit($this->api_request_body));
42
			}
43
			else // No params
44
			{
45
				$api_request = new HTTP_Request2($this->api_full_uri, HTTP_Request2::METHOD_GET); // Instantiate with GET method since no params
46
			}
47
			$api_request->setAuth($this->api_user, $this->api_pass, HTTP_Request2::AUTH_BASIC); // Auth stuff
48
			$api_request->setConfig('ssl_verify_peer', FALSE); // This is needed, otherwise HTTP_Request errors last I checked
49
 
50
			// Now send the request and get the return on investment
51
			try
52
			{
53
				$api_return = $api_request->send();
54
				return yaml_parse($api_return->getBody()); // We now have a nice array of all the returned data
55
			}
56
			catch (HTTP_Request2_Exception $e)
57
			{
58
				echo 'Error: ' . $e->getMessage();
59
			}
60
		}
61
	}
62
?>

One thing that I should mention before continuing is that you need to create an API user. This is done in the interface through Account >> Users

Essentially, you instantiate the class by passing the API username, password, and the API method you are going to be using. The API method comes in the format "First/Second/third" or "First/second" depending on the method you want to use. You don't include the leading slash, and the methods as far as I know are case sensitive.

Once you instantiate the object, you would use the add_param() method in the format of (parameter, value).

Once you add all the parameters (if any), just run the request() method, which will return an array containing the data.

So let's look at a real simple example scenario where you wanted to get the Five Minute load average for a particular server with a uniq_id of '123ABC':

 PHP | 
 
 copy code |
?

01
<?php
02
 
03
require_once(StormAPI.class.php); // Assuming we put the class in this file
04
 
05
$api_user = 'user';
06
$api_pass = 'pass';
07
$api_method = 'Monitoring/Load/stats';
08
 
09
$get_load = new StormAPI($api_user, $api_pass, $api_method);
10
$get_load->add_param('uniq_id', '123ABC'); // Where we pass our uniq_id
11
$results = $get_load->request(); // Initial array grab
12
 
13
// Now to get the five minute load
14
echo "Five Minute Load Average is: " . $results['loadavg']['five'];
15
 
16
//Done
17
?>

That's it. Relatively simple if you have a nice class to use. In order to get the uniq_id for a server, you would use the Server/list method.

Of course you can do this either via a web based application, or a CLI ran PHP script, for example, that might belong in a cron job (for checking load every so often for example).

Hopefully this gives a good starting point for working with the API. If you have questions, just leave a comment!

Updated as of April 2012: The class has been updated to utilize cURL and JSON

Comments (4) Trackbacks (1)
  1. You appear to have some whitespace issues in the plain text pop-ups because copy and pasting this code gave me errors but when I copied and pasted it line by line it worked. A diff on the two files (my manual creation versus a copy+paste) does show differences but it must be all whitespace.

    Also, for this to work on CentOS 5, you need to:
    yum install libyaml-devel
    pecl install yaml
    echo “extension=yaml.so” >> /etc/php.d/yaml.ini
    pear install channel://pear.php.net/Net_URL2-0.3.1 channel://pear.php.net/HTTP_Request2-2.0.0RC1

    • Alan,

      Thanks for the heads up. As I was writing this piece, I basically went and found a code display plugin for WordPress, and didn’t do much actual configuration of it. I basically just copy/pasted from my eclipse session. Musta done the hackjob there.

      Was the code of use to you though? I’m certainly looking to make it better if you have some ideas.

      • I used this with some preliminary testing of the API, so yeah it was helpful, thanks!

        I converted the YAML output to JSON to remove the need to install the YAML pecl plugin. JSON seems to be in PHP by default from at least 5.2 up while YAML isn’t in 5.2.x. Check it out: https://gist.github.com/5bd70668070580bcd121

        It might be worth looking at converting the HTTP_Request2 functions with a function using cURL commands so as to reduce all external dependencies. If I get around to it I’ll post it back here.

        • Alan,

          I’d be interested in seeing the new class based on cURL. I can’t remember why I wrote it the way I did – probably because for some reason I wasn’t able to figure out how to get it working with cURL and JSON (PHP is really just a side hobby of mine – I’m not the best at it by any means).


Leave a comment


*

FireStats icon Powered by FireStats
Optimization WordPress Plugins & Solutions by W3 EDGE