PLC API Examples

PLC API Examples

Table of Contents

  1. Introduction
  2. Connecting and authenticating
  3. Getting information about PlanetLab nodes
  4. Creating a slice and assigning a user to it
  5. Manipulating a slice
  6. Introspection and multicall
  7. API command line utility and shell, plcsh

1. Introduction

This document demonstrates some uses of the XML-RPC programmatic interface to PlanetLab Central, or PLC API. The examples below are Python code, but the concepts apply to any language with a similar XML-RPC library. A complete PLC API reference is available here. As a last resort, contact PlanetLab Support with any questions.

2. Connecting and authenticating

The URL of the XML-RPC interface to PLC is https://www.planet-lab.org/PLCAPI/ . The following Python code creates an object api_server whose methods invoke the method of the same name at PLC; the keyword parameter allow_none=True enables a non-standard extension to XML-RPC that allows null values (None in Python) to be passed.

import xmlrpclib
api_server = xmlrpclib.ServerProxy('https://www.planet-lab.org/PLCAPI/', allow_none=True)

The first parameter to each XML-RPC call is an authentication structure. The code below shows how to set up this structure for password-based authentication.

# Create an empty dictionary (XML-RPC struct)
auth = {}
# Specify password authentication
auth['AuthMethod'] = 'password'
# Username and password
auth['Username'] = 'my.email.address@example.com'
auth['AuthString'] = 'xxxxxx'

Now we can verify this structure with the PLC API method AuthCheck(), which returns 1 if the authentication structure is valid.

authorized = api_server.AuthCheck(auth)
if authorized:
    print 'We are authorized!'

3. Getting information about PlanetLab nodes

The GetNodes() method is the primary source of information about PlanetLab nodes. The first parameter is always an authentication structure. The other two parameters specify how the information returned should be filtered, and if they are not present, GetNodes() returns everything. The return value is a list containing one structure for each node, and each structure consists of several named fields.

# This may take a while.
all_nodes = api_server.GetNodes(auth)
print all_nodes

If the second parameter is a list of node IDs or hostnames, GetNodes() will return information only about these nodes. Alternatively, the second parameter can be a structure that specifies values for certain fields, in which case GetNodes() will return only those nodes whose fields match. Finally, the third parameter specifies which fields to return.

Each construct described in the preceding paragraph is used in the following example.

# Get information about two nodes at Princeton.
princeton_nodes = api_server.GetNodes(auth, ['planetlab-1.cs.princeton.edu', 'planetlab-2.cs.princeton.edu'])
print princeton_nodes

# Get node IDs and hostnames of nodes whose boot state is "boot"
boot_state_filter = {'boot_state': 'boot'}
return_fields = ['node_id', 'hostname']
nodes_in_boot = api_server.GetNodes(auth, boot_state_filter, return_fields)
print nodes_in_boot

If you wish to specify a list of fields but not a list of nodes, pass None or {}, the empty structure, as the second argument. In general, you should request as little information as possible, as this will create less load at PLC and make your query run faster.

4. Creating a slice and assigning a user to it

Note: you must be a PI to create a new slice or change the users of an existing slice. If you are not a PI, ask your PI to create a slice for you and skip ahead to the next section.

The method to create a new slice is AddSlice(). It takes two parameters: the authentication structure and a structure containing information about your new slice. The "name" field is the name of your new slice. It consists of your site prefix, followed by an underscore, followed by a sequence of letters, digits, and underscores of your choosing. The "url" field is a link to a description of your project. The "description" field describes what your slice is supposed to be doing so that PlanetLab Operations can determine if it is malfunctioning. Finally, the "instantiation" field specifies how your slice will be instantiated on the nodes. If it succeeds, AddSlice() returns the slice ID of your slice.

The following code uses AddSlice() to create a new slice.

slice_data = {}
slice_data['name'] = 'mysite_slicename'
slice_data['url'] = 'http://example.com/myproject/'
slice_data['description'] = '''Test slice.
This slice should not generate traffic external to PlanetLab.
'''
slice_data['instantiation'] = 'plc-instantiated'
slice_id = api_server.AddSlice(auth, slice_data)
print slice_id

The method to add a user to a slice is AddPersonToSlice(). It takes three parameters: an authentication structure, a username, and a slice ID or name. The following code will add you to your new slice.

me = auth['Username']
api_server.AddPersonToSlice(auth, me, slice_id)

5. Manipulating a slice

Members of a slice can update its description and change the nodes assigned to it. The former is accomplished by the UpdateSlice() method, which takes an authentication structure, a slice ID or name, and a structure containing the updated fields. The following code changes the slice description.

new_slice_description = '''Test slice.
This slice generates only ICMP traffic between PlanetLab nodes.
'''
new_slice_details = {'description': new_slice_description}
api_server.UpdateSlice(auth, slice_id, new_slice_details)

The AddSliceToNodes() method causes your slice to be instantiated on the requested nodes, when they are up. It may take a little while before the nodes find out about your slice. The two non-authentication arguments are the slice ID or name and the list of node IDs or hostnames to be added.

api_server.AddSliceToNodes(auth, slice_id, ['planetlab-1.cs.princeton.edu', 'planetlab-2.cs.princeton.edu'])

The GetSlices() method returns information about slices, including the list of node IDs to which they have been added. In order to get the hostnames of these nodes, you must call GetNodes().

node_ids = api_server.GetSlices(auth, [slice_data['name']], ['node_ids'])[0]['node_ids']
node_hostnames = [node['hostname'] for node in api_server.GetNodes(auth, node_ids, ['hostname'])]
print node_hostnames

6. Introspection and multicall

The PLC API supports the de facto standard XML-RPC introspection and multicall methods described here.

7. API command line utility and shell, plcsh

For interactive use, a command-line program called plcsh extends a Python interpreter to pass authentication structures automatically and support tab completion. To use plcsh, check out the (historically named) directory plcmdline:

$ cvs -d :pserver:anon@cvs.planet-lab.org:/cvs checkout plcmdline

To run plcsh, type

$ cd plcmdline
$ ./plcsh -u my.email.address@example.com -r any

The -r flag, for "Role", is left over from the previous version of the PLC API, and while it must be specified, its value does not matter. A typical interaction with the shell is given below; note the lack of authentication structures passed as arguments.

deisenst@bach:~/plcmdline$ ./plcsh -u deisenst@cs.princeton.edu -r any
Password: ******
PlanetLab Central API server at https://www.planet-lab.org/PLCAPI/
deisenst@cs.princeton.edu connected as using password authentication
Type "system.listMethods()" or "help(method)" for more information.
[deisenst@cs.princeton.edu ]>>> AuthCheck()
1
[deisenst@cs.princeton.edu ]>>> GetNodes(['planetlab-1.cs.princeton.edu'], ['node_id'])
[{'node_id': 121}]