Skip to content. | Skip to navigation

Personal tools

Navigation

You are here: Home / Wiki / Tutorialnew

Tutorialnew

How to use ProtoGeni

How to use ProtoGeni

ProtoGeni is currently driven via various XMLRPC interfaces (see the Component Manager API and the Slice Authority API). Typically, users interact with the ProtoGeni XMLRPC servers using python or perl, but any language that supports XMLRPC will suffice. The ProtoGeni source code includes a set of test scripts in the protogeni/test directory for examples. These test scripts are intended both to test the system and to provide a demonstration of how to use ProtoGeni.

For the slides presented by Robert Ricci at GEC6 as a ProtoGeni tutorial, see the attachments section at the bottom of this page.

Getting Ready

Before running the test scripts or creating your own, there are a few things you will need to do to make sure everything runs smoothly.

Get an Emulab Account

You need to have an account on an Emulab running the ProtoGeni code. If you are unsure of where you should get your Emulab account, please send a message to Utah's Emulab.

Once you know which Emulab you need an account on, go to the WWW interface for that Emulab (http://www.xxx.yyy) and:

  1. Follow the Request Account link on the left side.
  2. Click on the Join Existing Project link (upper button).
  3. Fill out the form and submit.
  4. Follow the instructions that you will receive in email. Be sure to set you spam filter to allow email from your Emulab site.
  5. Wait for your account to be approved; you will receive another email message when that happens. The proceed to the next section.

SSL Certificate

The ProtoGeni interface runs over SSL, so it is necessary for Emulab users to create an encrypted SSL certificate. This certificate is the basis of user authorization in ProtoGeni. You create your certificate through the WWW interface on your Emulab:

  1. Log in to your Emulab site.
  2. Follow the My Emulab link in the upper left of every page.
  3. Select the Profile tab (the rightmost of the three).
  4. Follow the Generate SSL Cert link.
  5. Fill out the form and submit.

The new SSL certificate is saved as $HOME/.ssl/encrypted.pem on your users node. The test scripts look for the certificate in this location, but a command line argument allows you to override this. In addition, as a convenience, the test scripts will look for your pass-phrase in $HOME/.ssl/password so that you do not need to type your pass-phrase repeatedly.

SSH Keys

ProtoGENI nodes only allow login if you have SSH keys set up (accounts do not have regular passwords). If you are unfamiliar with how to create an encrypted SSH key, or how to upload it to your Emulab account, please read the section below on how to upload an SSH key.

Credentials

Before we get to the examples, it is necessary to understand how permissions and privileges are expressed in ProtoGeni. ProtoGeni Credentials are signed documents which describe privileges held by a principal (a user). Conceptually, they identify the owning user and a target ProtoGENI object to which the privileges apply.

Most operations in ProtoGeni require a credential of some kind. For example, to operate on a slice, you must have a slice credential; the owner of the credential is yourself and the target of the credential is the slice. All operations on slices require that you pass along your credential as one of the arguments. When you authenticate (using the SSL certificate mentioned above) to a ProtoGeni XMLRPC server, your certificate identity must match the identity in the credential, or the operation will fail. (note that credentials may be delegated to another principal)

Since you need a credential to do most anything in ProtoGeni, you first have to get your "self" credential, which is just a generic credential that gives you permission to do basic kinds of things, like register a slice name (see next section). Your self credential is issued by your local Emulab (which in ProtoGeni lingo, is also your Slice Authority). For example, to get your self credential, you would run the getcredential.py test script on users:

ops> getcredential.py
... ... ... ...

You can save the output to a file, but is not actually necessary for running the test scripts since they request your self credential if it is needed.

Specific Examples

The following sections describe in more detail the essential operations. In most cases, there is a corresponding test script so that you can look at and run actual working code. Please see the Glossary of Terms if you have trouble following the tutorial. Feel free to send us email if you have problems or questions.

For simplicity, the examples make use of a single Component Manager, the one hosted by your local Emulab. Later in the tutorial we will introduce multiple component managers and resource discovery.

Registering a Slice Name

What is a Slice? A slice is a network of computing and communication resources capable of running an experiment or a wide-area network service. More concretely, a slice is defined by a set of slivers spanning a set of network components, plus an associated set of users that are allowed to access those slivers for the purpose of running an experiment.

In practical terms, you register a slice name (a name is not currently in use) at your Slice Authority, and get back a credential whose owner is you and whose target is the new slice name. With this credential, you can then allocate resources to the slice (create slivers) on computing resources belonging to Component Managers that are part of the ProtoGeni federation.

The following code fragment is contained in the registerslice.py test script:

mycredential = get_self_credential()
params = {}
params["credential"] = mycredential
params["type"]       = "Slice"
params["hrn"]        = "mytestslice"
rval,response = do_method("sa", "Register", params)
if rval:
    Fatal("Could not get my slice")
    pass
myslicecredential = response["value"]

In the above python code, do_method() is a utility routine that invokes the named ("sa") XMLRPC server on your local boss node (remember, your local Emulab is your Slice Authority ).

The return value is a blob of XML; it is a signed document (credential) that belongs to you, and whose target is the newly created slice name. You use this credential to invoke operations on the new slice. At this point the slice is simply an empty container; no resources have been allocated.

If you would rather just run the registerslice.py test script:

ops> registerslice.py
Got my SA credential
No such slice registered here: Creating new slice called mytestslice
New slice created: urn:publicid:IDN+emulab.net+slice+mytestslice

The test script does not bother to print the new slice credential out, since all of the other scripts simply request a copy of the credential if needed. However, it does print out the slice URN (embedded in the slice credential), which is the format by which all ProtoGeni objects are named. In the examples below, mysliceurn is a reference to the URN of your new slice.

Note that the default expiration time of your new slice is fairly short; on the order of hours. Your slice and slivers will be terminated automatically unless you renew them before they expire. See the section on Renewing your Sliver below.

Allocating Computing Resources

Binding resources to a slice name is a two-step process; first you request a set of tickets from Component Managers, and then you redeem your tickets at those same Component Managers.

A ticket is simply another kind of credential. It is a (signed) promise by a Component Manager, to bind a specific set of resources to a slice. Tickets are said to be issued by a Component Manager, and later redeemed to acquire those resources. Tickets that are not redeemed quickly, timeout so that resources are not left dangling and unusable by others.

But how do you specify the computing resources you want? By creating an XML document in the rspec format, which specifies a (perhaps incomplete) mapping between physical components and abstract nodes and links. A simple example of a fully bound rspec is:

<rspec xmlns="http://protogeni.net/resources/rspec/0.1">
   <node virtual_id="mypc"
         component_uuid="urn:publicid:IDN+emulab.net+node+pc111"
	 component_manager_uuid="urn:publicid:IDN+emulab.net+authority+cm"
         virtualization_type="raw">
   </node>
</rspec>

which requests pc111 on Utah's Emulab. An example of an unbound rpsec is:

<rspec xmlns="http://protogeni.net/resources/rspec/0.1">
   <node virtual_id="mypc"
	 component_manager_uuid="urn:publicid:IDN+emulab.net+authority+cm"
         virtualization_type="raw">
   </node>
</rspec>

As you can see, the only difference is the removal of a single line. When you make a ticket request using an unbound (or partially bound) rspec, the Component Manager will attempt to assign appropriate resources, and then fill in the missing information.

So what is a ticket really? It is your rspec, signed by the Component Manager, and returned to you in the same XML format as all other ProtoGeni credentials. For example, requesting a ticket using the rspec above, would result in the following XML document:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<signed-credential>
  <credential xml:id="ref1">
    <type>ticket</type>
    <ticket>
      <can_delegate>1</can_delegate>
      <redeem_before>2010-03-30T14:46:41</redeem_before>
      <rspec xmlns="http://protogeni.net/resources/rspec/0.1">
        <node virtual_id="mypc"
              component_uuid="urn:publicid:IDN+emulab.net+node+pc111"
              component_manager_uuid="urn:publicid:IDN+emulab.net+authority+cm"
              virtualization_type="raw">
        </node>
      </rspec>
    </ticket>
  </credential>
  ... ... ...
</signed-credential>

If you had submitted an unbound or partially bound rspec, and you want to know what resources were assigned, you can dig inside the XML document and pull out the rspec.

Requesting a Ticket

Okay, so now that we know what rspecs and tickets are, lets see how to request a ticket. This example submits the rspec above to your local Emulab, which also functions as the Component Manager interface for your local cluster. The credential you send is the slice credential that you got back from the registerslice operation above. The rspec is just a string.

params = {}
params["slice_urn"]   = mysliceurn
params["credentials"] = (myslicecredential,)
params["rspec"]       = rspec
rval,response = do_method("cm", "GetTicket", params)
if rval:
    Fatal("Could not get ticket")
    pass
myticket = response["value"]

Or using the getticket.py test script:

ops> getticket.py anynode.rspec
Got my SA credential, looking up mytestslice
Asking for a ticket from the local CM
Got the ticket
... ... ...

The test script prints your ticket to stdout, or you can save it to a file (not necessary if you are using the test scripts). Remember, your tickets expire very quickly, so you want to move onto the next step, redeeming your ticket, as soon as possible. Otherwise, you will need to make a new ticket request.

Redeeming your Ticket

Once you have a ticket, you need to redeem it at the Component Manager that issued the ticket. Why? Because a ticket is just a promise to bind resources to your slice; when you redeem your ticket, those resources are actually bound (allocated) to your slice. After redemption, you have control over the resources, but not before.

More concretely, redeeming a ticket creates a sliver, and returns another credential to you. The sliver is the portion of the computing resource that has been granted to you (in the context of your slice), and the credential carries your permission to control the sliver, via other ProtoGeni APIs.

To redeem the ticket you requested in the previous section:

params = {}
params["slice_urn"]   = mysliceurn
params["credentials"] = (myslicecredential,)
params["ticket"]      = myticket
params["keys"]        = mykeys
rval,response = do_method("cm", "RedeemTicket", params)
if rval:
    Fatal("Could not redeem ticket")
    pass
myslivercredential,manifest = response["value"]

Or using the redeemticket.py test script:

ops> redeemticket.py
Got my SA credential
Asking for slice credential for mytestslice
Got the slice credential
Asking for a copy of the ticket
Got the ticket
Redeeming the ticket
... ... ...

The results of the XMLRPC call are two new XML documents (a credential and a manifest), while the redeemticket.py test script prints out a single document (the manifest). The new credential is the aforementioned sliver credential and does not need further discussion. The manifest is an annotated version of your rspec, describing various properties of resources within the sliver. The manifest will be discussed in more detail later in this tutorial.

Note that your sliver will be automatically terminated when the expiration time of the slice is reached. See the section on Renewing your Sliver below.

Lastly, a word about the keys argument to RedeemTicket above. As mentioned in the discussion of SSH Keys at the beginning of this tutorial, you must provide a set of SSH keys in your RedeemTicket call, if you want to log into your nodes. There is an example of how to do this in the redeemticket.py test script.

Using CreateSliver

CreateSliver is an alternate interface from the Minimal API. It is intended as a simpler interface, combining ticket request, ticket redemption, and sliver start.

params = {}
params["slice_urn"]   = mysliceurn
params["credentials"] = (myslicecredential,) 
params["rspec"]      = rspec
params["keys"]       = mykeys
rval,response = do_method("cm", "CreateSliver", params)
if rval:
    Fatal("Could not create sliver")
    pass
myslivercredential,manifest = response["value"]

Or using the createsliver.py test script:

ops> createsliver.py anynode.rspec
Got my SA credential
Asking for slice credential for mytestslice
Got the slice credential
Creating the sliver ...
Created the sliver
... ... ...

The results of the XMLRPC call are two new XML documents (a credential and a manifest), while the createsliver.py test script prints out a single document (the manifest). The new credential is the aforementioned sliver credential and does not need further discussion. The manifest is an annotated version of your rspec, describing various properties of resources within the sliver. The manifest will be discussed in more detail later in this tutorial.

CreateSliver automatically starts your sliver, but you should read that section to understand what starting a sliver means.

Lastly, a word about the keys argument above. As mentioned in the discussion of SSH Keys at the beginning of this tutorial, you must provide a set of SSH keys in your CreateSliver call, if you want to log into your nodes. There is an example of how to do this in the createsliver.py test script.

Starting your Sliver

After redeeming your tickets, you need to start your slivers. This is because while the computing resources have been bound to your slice, but they have not been initialized. Starting (or initializing) your sliver can mean different things, depending on what kinds of resources you have requested. For example, nodes need to be booted, vlans need to be created, etc. All of this happens when the sliver is started.

To start the sliver you created in the previous section:

params = {}
params["slice_urn"]   = mysliceurn
params["credentials"] = (myslivercredential,)
rval,response = do_method("cm", "StartSliver", params)
if rval:
    Fatal("Could not start sliver")
    pass

Or using the sliveraction.py test script:

ops> sliveraction.py start
Got my SA credential. Looking for slice
Found the slice, asking for a credential
Got the slice credential, asking for a sliver credential
Got the sliver credential, calling StartSliver on the sliver
Sliver has been started.

The StartSliver call returns immediately, so you will have to poll the Component Manager to determine when the sliver is fully initialized (eg: nodes are properly booted up, vlans fully created, etc.). This is discussed in the next section.

Restarting (Rebooting) your Sliver

Occasionally you will need to restart your sliver; this will reboot all of the nodes and synchronise your vlans with the switches to ensure they are setup properly. This is accomplished with the RestartSliver operation, or with the restart directive to the sliveraction.py test script (see above). As with start, you will then need to wait for your slivers, as discussed in the next section.

Waiting for Slivers to Start (or Restart)

As mentioned in the previous section, you must wait for your slivers to fully initialize before you can use them. Since StartSliver returns immediately, you must then poll the Component Manager using SliverStatus. For example:

params = {}
params["slice_urn"]   = mysliceurn
params["credentials"] = (myslivercredential,)
rval,response = do_method("cm", "SliverStatus", params)
if rval:
    Fatal("Could not get sliver status")
    pass
status = response["value"]

Or, using the sliverstatus.py test script:

ops> sliverstatus.py
Got my SA credential. Looking for slice ...
Found the slice, asking for a credential ...
Got the slice credential, asking for a sliver credential ...
Got the sliver credential, asking for sliver status ...
{'status'  : 'ready',
  'state'  : 'started',
  'details': {'urn:publicid:IDN+emulab.net+sliver+413':
               {'status'       : 'ready',
	        'state'        : 'started',
		'component_urn': 'urn:publicid:IDN+emulab.net+node+pc84',
		'error'        : ''}
	      }
}

I'm working on more details for the tutorial, but in the meantime, all of the gory details are in the CM API documentation.

Deleting your Sliver

When you are done with your sliver, you will want to delete it so that the resources are released. This is done with the method:

params = {}
params["slice_urn"]   = mysliceurn
params["credentials"] = (myslivercredential,)
rval,response = do_method("cm", "DeleteSlice", params)
if rval:
    Fatal("Could not delete sliver")
    pass

Or using the deleteslice.py test script:

ops> deleteslice.py
Got my SA credential. Looking for slice ...
Found the slice, asking for a credential ...
Got the slice credential
Deleting the slice
Slice has been deleted.

It is important to note that while your sliver/slice has been deleted at the Component Manager, the slice credential you obtained when you registered your slice name is still valid, and will remain valid until the expiration time in the slice credential is reached. You may continue to use the slice credential (say, to create new slivers) up until that time. You may also renew your slice credential so that it expires at a later time.

Renewing your Sliver

By default, your slice and any slivers will expire in a fairly short time, on the order of hours. More specifically, each Component Manager will automatically terminate your slivers, and your slice credential expires (becomes useless). This will happen unless you renew your slice and slivers before the expiration time is reached. For short lived slices, this happens without any notification, but for long lived (expiration previously set to longer then 24 hours), you will receive an email warning before expiration to give you a chance to renew (extend) your slice and slivers.

First a bit of background. When you registered your slice name, a default expiration time is assigned; the slice credential you get back has an expiration time equal to the slice expiration. In other words, when the slice expires, so does your credential and any slivers. In addition, the expiration time in the slice credential is an upper bound on the valid_until field of the rspec. If you do not specify a valid_until in the rspec, your slivers will expire when the slice credential says they should. This is to prevent the situation where the slice credential expires, but there are still slivers out in the wild.

The above also explains why you cannot delete a slice at the Slice Authority before it expires. Since the SA has no knowledge of existing slivers, you could get into a situation whereby there were existing slivers, but no way to request the slice credential (from the SA) to control (say, delete) those slivers. While this may seem odd, remember that if you have a registered slice that is not doing anything, you can just keep using it.

Therefore, in order to create a long lived sliver, you need a long lived slice and a slice credential for that slice, when you create your slivers, or when you renew your existing slivers.

The first step in extending your slice credential is to use your existing slice credential (before it expires) to invoke the RenewSlice at your Slice Authority:

expiration = time.strftime("%Y%m%dT%H:%M:%S",
                            time.gmtime(time.time() + (60 * int(minutes))))
params = {}
params["slice_urn"]   = mysliceurn
params["credentials"] = (myslicecredential,)
params["expiration"] = expiration
rval,response = do_method("sa", "RenewSlice", params)
if rval:
    Fatal("Could not renew slice at the SA")
    pass
myslicecredential = response["value"]

Your new slice credential can then be used to extend your sliver on the Component Manager.

params = {}
params["credential"] = myslicecredential
rval,response = do_method("cm", "RenewSlice", params)
if rval:
    Fatal("Could not renew slice at the CM")
    pass

Or you can use the renewsliver.py test script, which combines the two operations. The argument is the number of minutes to extend the slice for:

ops> renewsliver.py 60
Got my SA credential
Found the slice, asking for a credential ...
Got the slice credential, renewing the slice at the SA ...
Renewed the slice, renewing the sliver ...
Sliver has been renewed until 20100330T22:05:44

Discovering Resources

The previous examples have all used resources from your local Emulab, using an unbound rspec. In this section we will learn how to get a list of Component Managers from the ProtoGeni ClearingHouse, and then how to get a list of specific resources at a particular Component Manager. This resource list can be then used to do your own assignment of resources in your rspec (a bound rspec). Note that even if you do your own assignment, the Component Manager will verify that it is a proper assignment (does not violate local policies or hardware constraints) before it will issue a ticket.

The first step is to request a list of all available Component Managers from the ClearingHouse:

mycredential = get_self_credential()
params = {}
params["credential"] = mycredential
rval,response = do_method("ch", "ListComponents", params)
if rval:
    Fatal("Could not get a list of components from the ClearingHouse")
    pass
managers = response["value"]

The structure of the return value is documented in the ListComponents section of the ClearingHouse API documentation. Or, you can use the listcomponents.py test script:

ops> listcomponents.py
urn:publicid:IDN+emulab.net+authority+cm : https://www.emulab.net/protogeni/xmlrpc/cm
... ... ... ...

Which will print a list of Component Managers and the URL you need to access it.

The next step is to ask specific Component Managers for a list of resources using DiscoverResources:

for manager in managers:
    url    = manager["url"]
    params = {}
    params["credential"] = mycredential
    params["available"]  = True
    rval,response = do_method(None, "DiscoverResources", params, url)
    if rval:
        Fatal("Could not get a list of resources");
        pass
    advertisement = response["value"]
    pass

Or you can use the discovery.py test script:

ops> listcomponents.py https://www.emulab.net/protogeni/xmlrpc/cm
... ... ... ...

Which will print a giant blob of XML in rspec advertisement format. It is best to redirect the output to a file!

Is this enough said?

Advanced Example

Insert a more advanced example here, perhaps setting up a link or a tunnel between two nodes on different CMs.

Uploading SSH Keys

You must follow these instructions to log onto your ProtoGENI nodes.

As mentioned above, ProtoGeni nodes allow SSH login only, via public key authentication; accounts do not have regular passwords.

If you have not already done so, you should generate an encrypted ssh key pair before you allocate any resources (that way, the nodes you reserve will already be able to validate you when they start up). For instance.

mydesktop> ssh-keygen -f protogeni-key
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in protogeni-key.
Your public key has been saved in protogeni-key.pub.
The key fingerprint is:
01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef user@host

Key generation might not be necessary if you already have a valid ssh key pair you want to reuse.

The next step is to upload your public key (i.e. the file protogeni-key.pub in the example above). If you upload it to the local slice authority (i.e. Emulab), it can more easily be forwarded to appropriate experimental nodes you allocate. Uploading is done through the Emulab WWW interface:

  1. Log in to your Emulab site.
  2. Follow the My Emulab link in the upper left of every page.
  3. Select the Profile tab (the rightmost of the three).
  4. Follow the Edit SSH Keys link (the second one in the box on the left).
  5. Use the Browse button on that page to enter the filename you saved your public key to (protogeni-key.pub in the example above), and then select Add New Keys.

At this point, the Slice Authority should have your new authentication information recorded. You can verify that things have worked properly by running the lookupuser.py test script and checking that the contents of the protogeni-key.pub file are included in the output: these are the same keys that createsliver.py and redeemticket.py will pass on to the nodes in the slivers it requests.

Using ssh-agent to manage your private keys is optional, but highly recommended. (The most obvious difference it makes is that it will greatly reduce the number of times you need to type your passphrase.)

TODO

  1. Update to version 2 API when it goes live.
  2. Add multi-component manager example.
  3. Add links and or/tunnels.