This is the third article in our OpenStack API tutorial series. To learn how you can deploy and administer OpenStack in an enterprise environment, check out OpenStack training from The Linux Foundation.
Today let’s use our knowledge of the OpenStack API (from Intro to the OpenStack API and Spinning up a Server with the OpenStack API) to put to use an OpenStack SDK.
The API is the basic interface through which you communicate with your OpenStack infrastructure. Using the API you make RESTful calls. While you’re free to use a library such as libcurl within your programs, making straight HTTP calls is a bit cumbersome. So instead, there are various libraries in different programming languages that simplify the process of calling into the OpenStack API. These libraries are called SDKs. Let’s look at one of them.
For these examples, I decided to use the Go programming language. The reason I chose that is that it’s a fun, cool language to use, and I wanted to steer towards something different from the usual Python used in OpenStack. (The only SDK officially create by the OpenStack group is for Python. All of the other SDKs, including the one for Go, are unofficial.)
Note that as I mentioned previously, I’m using Rackspace for these examples. (See the first article for an explanation why.)
Go Language
There are a few different SDKs for the Go language; I chose one created by Rackspace called Gophercloud. I’m going to assume you already have Go installed and your GOPATH set up appropriately. Now let’s install Gophercloud and try it out. To install it type:
go get github.com/rackspace/gophercloud
Easy enough. Now create a new text file using your favorite editor. I’m going to call my file test1.go. Because I want you to be able to try this out, instead of providing snippets, I’m going to provide you with an entire program you can type (or paste) in.
package mainimport (
"fmt"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack"
"github.com/rackspace/gophercloud/pagination"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
)func main() {
opts := gophercloud.AuthOptions{
IdentityEndpoint: "https://identity.api.rackspacecloud.com/v2.0",
Username: "RackspaceUsername",
Password: "RackspacePassword",
}
provider, err := openstack.AuthenticatedClient(opts)
if err != nil {
fmt.Println("AuthenticatedClient")
fmt.Println(err)
return
}
client, err :=
openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
Region: "IAD",
})
if err != nil {
fmt.Println("NewComputeV2 Error:")
fmt.Println(err)
return
}
opts2 := servers.ListOpts{}
pager := servers.List(client, opts2)
pager.EachPage(func(page pagination.Page) (bool, error) {
serverList, err := servers.ExtractServers(page)
if err != nil {
return false, err
}
for _, s := range serverList {
fmt.Println(s.ID, s.Name, s.Status)
// servers.Delete(client, s.ID);}
return true, nil
})
}
In this code, replace RackspaceUsername with your username and RackspacePassword with your password.
Next, log into your Rackspace console and create a server. (We could use code to create a server, but I just want to list the running servers in this short example.) Go ahead and create a couple servers. Create them both in a single region. Then in the code above, replace IAD with the abbreviation for the region if you’re using one other than Northern Virginia.
Finally run your code by typing
go run test1.go
replacing test1.go with whatever filename you chose. Here’s what I see when I run it:
jeff@JeffLinuxMint16 ~/dev/tests/openstack/go $ go run test1.go
dce631ce-71ff-4b9a-89f0-0ea7bf4a6770 Cloud-Server-02 BUILD
5500e1d6-2782-4971-9045-72c9b744d482 Cloud-Server-01 ACTIVE
I ran the test1.go program after one of the servers was finished being built and was active, and the second was still in the process of building. You can see in this list that indeed one is listed as BUILD, and the other as ACTIVE.
Digging into the code
Now let’s look at the code in detail. The imports section lists the external packages you need in your code. I’m using fmt so I can print out information, as well as several of the gophercloud packages. This part is kind of tricky; you need to look at the documentation and only list exactly the gophercloud packages you need, as there are different packages for different parts of the API.
The first part of code inside the main function creates an authentication options object, filling it in with your username, password, and the URL used for authenticating. Remember, to authenticate through the API, you send a request to the URL, passing your username and password; you get back an authentication token. Behind the scenes, that’s exactly what is going to happen here, but with less coding. Here, we’re filling that information into a structure; then in the line that follows we call openstack.AuthenticatedClient, passing in that structure. We’ll either get back an error or token information, and we save the token information in a variable called provider. (I just used the variable name “provider” because that’s what the samples used in the Gophercloud documentation.) Next, we check if there’s an error, and if so, print it out and exit. Otherwise continue.
The next step is to use the Compute service. To do so, we call openstack.NewComputeV2, passing the provider variable from the previous call, and the end points for this call. The second parameter to this call is an EndpointOpts structure, which specifies the endpoints for the call. In our case, that’s just a region, so we set it to IAD, or whatever region you’re using. The NewComputeV2 function will either return an error or an object representing the Compute service. We can use that object to make further API calls.
For the further API calls, we’re going to call servers.list. This part is a bit odd in terms of object-oriented programming. We don’t call a method on the Compute service object to list the servers; instead, we call call the list method found in the servers package (which we imported at the top of the file), passing in the Compute service object.
We then page through the list of servers. Remember, we’re limited on how much information we’ll get back in each API call. If there’s more information, we need to make further requests to get back additional data, continuing until there’s no more data. That’s why we use a pager object and call its EachPage function. That function takes a callback function as a parameter; the callback in turn has a parameter representing the current page. Using that page, we can extract the servers’ information from the page of data. Finally, we loop through the list of servers extracted from the page. For each server we print out the ID, Name, and Status.
Now you might be wondering how I knew I could print out ID, Name, and Status. What other parameters are there? For that I looked at the documentation. The documentation has URLs that match the URLs in the import statements, thanks to a cool website called godoc.org. The import statement in question is this:
github.com/rackspace/gophercloud/openstack/compute/v2/servers
Thus, tack on http://godoc.org/ before that and open the resulting address in your browser:
http://godoc.org/github.com/rackspace/gophercloud/openstack/compute/v2/servers
This is the full documentation for the servers package. Here’s a screenshot:
About halfway down this screenshot, for example, you can see the List function and the parameters it takes: a ServiceClient and a structure containing options. The function returns a Pager object. Farther down this page is a type called Server. This is where I found the members for the Server object, including Name, and so on. You can see other important parameters are AccessIPv4 and HostID.
Testing for errors
You can see the different kinds of errors you get by changing some of the parameters. For example, if you change the Region parameter in the NewComputeV2 call to a nonexistent region like so:
Region: "ABCDEF"
then you’ll see the following output:
NewComputeV2 Error:
No suitable endpoint could be found in the service catalog.
Shutting Down the Servers
Don’t forget to shut down your servers! Otherwise you’ll have to pay more than you intended to at the end of the month. Let’s modify the above code to shut down the servers. (Put the region back to your region if you changed it to test out the error.) Now if you look in the servers page of the documentation, you’ll find a Delete function. That function takes two parameters: a ServiceClient and an id. Let’s add a line of code to our program that deletes the servers right after printing out the information.
Warning! Warning! This will delete all the servers in your account for that region. If that’s not what you want, don’t run this. Instead, delete them manually from the Rackspace web console!
Here’s how you can delete all the servers. You can see in the code above that there’s a commented-out line. Uncomment it so it looks like this:
servers.Delete(client, s.ID);
Then, if you want to delete all your servers, run the program again. This time it will delete each server as it prints them out. Wait a few seconds to give Rackspace time to delete the servers. Then run the program again and you won’t see any servers listed. Done!
Finding all the docs
You can explore the documentation in full on the godoc server. Start at this page and from there you can drill down into the various services. There’s also some basic getting-started information. Scroll to the very bottom of the page and you’ll see a section called Directories where you can find the available services and objects contained within.
Conclusion
The OpenStack SDKs make it easier to call into the OpenStack APIs. There are different SDKs for different languages. Some languages are a bit incomplete (for example, there isn’t much available for C++). Other languages have several choices. Choose the language you’re comfortable in, and make sure you understand the API before embarking into the SDK. Then the SDK will make a lot more sense. This will conclude our brief introduction to the OpenStack API and SDKs. Is there more you’d like to see? If so, let us know in the comments.
See the previous two articles in this three-part series: