Welcome to geni-lib’s documentation!¶
Contents:
Introduction¶
geni-lib is a Python library for interacting with the NSF GENI Federation, or any federation that uses components of the GENI Software Architecture.
Common uses include orchestrating repeatable experiments and writing small tools for inspecting the resources available in a given federation. There are also a number of administrative API handlers available for interacting with software commonly used in experiments - particularly those exposing services to other experimenters.
Credentials¶
Using geni-lib to interact with cloud / testbed resources requires credentials for your account with a given provider (GENI, CloudLab, Emulab, etc.). The following guides provide documentation for how to acquire the credentials that geni-lib needs for each environment.
Note
If you only want to use geni-lib to manipulate XML resource files (RSpecs) to use with another tool, you do not need to install any credentials
Guides:
Getting Credentials from the NSF GENI Portal¶
Download The omni.bundle¶
You need a file called omni.bundle
which is available from the GENI Portal web
interface. Once you log into the GENI Portal you can use the following steps to locate your
omni.bundle
download:
- At the top of the Portal home page click on the tab labeled Profile
- In the tabs on the Profile page click on the one labeled Configure omni
- Embedded in the text under the Option 1: Automatic omni configuration header, there is a button labeled Download your omni data. Click this button.
Note
If you see a warning that no SSH keys have been uploaded you can still use the bundle, but you will need to specify an SSH public key path later if you want to use resources that require SSH login
- Click the Download your omni data button at the bottom of the next page and it should start downloading immediately in your browser.
Getting Credentials from the CloudLab Portal¶
CloudLab only provides your x509 certificate from the web interface. You will have to provide your own SSH public key for use with geni-lib when you set up your context for using reserved resources.
- Log in to the CloudLab Portal.
- From the <your-username> dropdown at the top right of the interface, select the Download Credentials option
- Save this text (either via copy/paste or Save As… in your brower) to
a file called
cloudlab.pem
for use when creating your context.
You will also need to take note of the projects of which you are a member, in order to set up your context. You can view your projects by clicking on the Membership tab on the user dashboard interface.
Installation¶
Ubuntu 14.04¶
Release versions of geni-lib are delivered via PyPI, but some system dependencies must be supplied, typically through the use of apt.
High-Level Dependencies¶
- Python 2.7.x (http://www.python.org)
- Pip
- OpenSSL
- LibXML
The above packages of course have their own dependencies which will be satisfied along the way.
Warning
The version of pip supplied via apt packages for Ubuntu 14.04 for Python 2.x is sufficiently broken that it is unlikely to be able to install geni-lib (or many other packages). The instructions below install pip outside of the package management system, using the most up-to-date installer. If you are already using virtualenv or otherwise maintain a sane Python environment you likely do not need to install a new pip.
Install Dependencies¶
$ sudo apt-get update
$ sudo apt-get install --no-install-recommends python libxml2 libssl1.0.0
$ wget https://bootstrap.pypa.io/get-pip.py
$ sudo python2 get-pip.py
Install¶
$ pip install geni-lib
Note
You may need to install with sudo if you are attempting to install system-wide.
Ubuntu 16.04¶
Release versions of geni-lib are delivered via PyPI, but some system dependencies must be supplied, typically through the use of apt.
High-Level Dependencies¶
- Python 2.7.x (http://www.python.org)
- Pip
- OpenSSL
- LibXML
The above packages of course have their own dependencies which will be satisfied along the way.
Warning
The version of pip supplied via apt packages for Ubuntu 16.04 for Python 2.x is sufficiently broken that it is unlikely to be able to install geni-lib (or many other packages). The instructions below install pip outside of the package management system, using the most up-to-date installer. If you are already using virtualenv or otherwise maintain a sane Python environment you likely do not need to install a new pip.
Install Dependencies¶
$ sudo apt-get update
$ sudo apt-get install --no-install-recommends python2.7 libxml2 libssl1.0.0
$ wget https://bootstrap.pypa.io/get-pip.py
$ sudo python2.7 get-pip.py
Install¶
$ pip install geni-lib
Note
You may need to install with sudo if you are attempting to install system-wide.
MacOS X 10.10.x / 10.11.x¶
These installations require the use of HomeBrew (http://brew.sh). If you use MacPorts or a different manager for installing open source tools on your system you will need to satisfy the dependencies using your tool of choice.
Note
These instructions have not been tested on older versions of MacOS X
Installation Dependencies¶
- HomeBrew (http://brew.sh)
- Apple Command Line Tools for XCode (normally downloaded as part of Brew install)
Install / Setup¶
Using HomeBrew (accessible via the brew
command in your terminal, once you have it installed)
we will install the necessary tools and library dependencies for typical geni-lib
use:
$ brew install mercurial
$ brew install python
Note
You will now have two version of python
installed on your system - the one that Apple ships
with your computer, and the one that we have now installed via brew
. Only the brew
-installed
python
will work for running geni-lib
scripts, which can be launched by running
/usr/local/bin/python
or by changing your $PATH
variable to have /usr/local/bin
as the
first entry (by editing ~/.profile
, typically).
Get geni-lib¶
You can place the geni-lib repository anywhere on your system that you prefer.
$ hg clone http://bitbucket.org/barnstorm/geni-lib
Install geni-lib¶
We can now install geni-lib
into your Python environment:
$ cd geni-lib
$ hg update -C 0.9-DEV
$ python setup.py install
Congratulations, you are now ready to launch python
and import geni lib modules!
Vagrant¶
geni-lib
can be installed on any platform that supports Vagrant using the instructions
below.
Two variants of the Vagrant environment can be created - a lite version that only contains geni-lib
and should only be used by developers that are accustomed to working with Vagrant or similar environments,
and a lab version that is more fully-featured and should be used by new geni-lib
users or those
using geni-lib
for a class or conference tutorial.
The documentation here currently only covers the lab version.
The Vagrant VM created by this process automatically sets up your geni-lib context and provides a web interface for creating Jupyter notebooks using GENI resources, as well as a web-based interface for accessing the VM shell.
Note
See the Configurable Options section below for environment variables which can tweak the settings of the VM environment that is created.
Installation Dependencies¶
Install these dependencies before creating the Vagrant VM.
- VirtualBox (https://www.virtualbox.org/wiki/Downloads)
- Vagrant (https://www.vagrantup.com/downloads.html)
Set up your geni-lib VM directory¶
- Create a directory on your system named
genivm
to hold your GENI environment - Copy your
omni.bundle
to this directory - Download the
geni-lib
Vagrant setup file to this directory from https://bitbucket.org/barnstorm/geni-lib/raw/tip/support/Vagrantfile-lab and rename it to be calledVagrantfile
On systems with
curl
(MacOS X, Linux) you can use the following command:curl https://bitbucket.org/barnstorm/geni-lib/raw/tip/support/Vagrantfile-lab -o VagrantfileOn Windows systems with Powershell you can use the following:
PS C:\genivm> $client = new-object System.Net.WebClient PS C:\genivm> $client.DownloadFile("https://bitbucket.org/barnstorm/geni-lib/raw/tip/support/Vagrantfile-lab", "C:/genivm/Vagrantfile")Note
The full path for the destination must be specified in the second argument to DownloadFile
- Create your vagrant vm using
vagrant up
in this directory
Note
This may take a long time (20+ minutes) depending on the speed of your internet connection
Load the Jupyter web interface¶
- Open any web browser and load
http://localhost:8900
- In the upper right-hand corner of the UI, choose
New->(Notebooks) Python 2
from the dropdown menu - In the new notebook enter
%load_ext genish
in the first cell and enter your key passphrase if necessary (otherwise just hit enter to skip the passphrase entry)
Accessing the VM Terminal¶
You may often want to access the VM command line for accessing your GENI resources, updating geni-lib
,
etc. While you can use vagrant ssh on some platforms, this doesn’t work very well on Windows, so the VM
provides a web-based mechanism for accessing the VM shell directly.
- Open any web browser and load
http://localhost:8900
- In the upper right-hand corner of the UI, choose
New->Terminal
from the dropdown menu
This will automatically log you into the VM and provide you a shell interface for using the VM OS directly.
Configurable Options¶
The following environment variables can be set to change the parameters under which the VM is created when vagrant up is first executed:
Name | Default | Description |
glv_port |
8900 | Local port the Jupyter web interface will be exposed on |
glv_ram |
1024 | Amount of memory available to the VM |
apt_cache |
unset | URL of proxy used for apt downloads |
pypi_test |
unset | If set, use the test PyPI repository instead of production |
CentOS 7¶
geni-lib is currently delivered only as a source repository via mercurial, although dependencies are installed as proper packages using yum.
High-Level Dependencies¶
- Mercurial (http://mercurial.selenic.com)
- Python 2.7.x (http://www.python.org)
- OpenSSL
- LibXML
The above packages of course have their own dependencies which will be satisfied along the way.
Install Dependencies¶
These instructions install dependencies using yum - it is also possible to install the Python packages using pip if you prefer.
The dependencies rely on EPEL (https://fedoraproject.org/wiki/EPEL), so install that first.
$ yum install epel-release
Now install the dependencies:
$ yum install mercurial python-lxml python-requests \
python-pip python-devel libffi-devel gcc openssl-devel
Get geni-lib¶
$ hg clone http://bitbucket.org/barnstorm/geni-lib
Install¶
$ cd geni-lib
$ hg update -C 0.9-DEV
$ pip install .
Tutorials / How-Tos¶
Importing a Context from a bundle¶
In order to communicate with any federation resource using geni-lib
you need to construct
a Context
object that contains information about the framework you are using (for example
ProtoGENI, Emulab, GENI Clearinghouse, etc.), as well as your user information (SSH keys,
login username, federation urn, etc.). This simple tutorial will walk you through the easiest
way to create a Context
if you have an account at the GENI Portal.
First you need to acquire your GENI credentials.
Run Context Import Tool¶
A script called context-from-bundle
was installed as part of your geni-lib
installation, which can convert your omni.bundle
into the data necessary for geni-lib
to create a Context
object for you. The instructions for using this tool are below -
choose the section appropriate for your OS.
MacOS X / Linux¶
In most installations your path should already include the import tool and it should run cleanly without any additional configuration:
$ context-from-bundle --bundle /path/to/omni.bundle
If no arguments are supplied the bundle is assumed to be in the current directory. If your
bundle does not contain an SSH public key you will be required to supply a path to one using
the --pubkey
argument at the command line.
Windows¶
Unfortunately the default Python installation on Windows does not add the site Scripts
directory to your path, so you need to invoke it directly. If you are using Python 2.8 you
will need to replace Python27
with Python28
below:
C:\> python C:\Python27\Scripts\context-from-bundle --bundle path\to\omni.bundle
If no arguments are supplied the bundle is assumed to be in the current directory. If your
bundle does not contain an SSH public key you will be required to supply a path to one using
the --pubkey
argument at the command line.
Test It Out!¶
Now we can take your newly imported information, instantiate our context, and query an aggregate:
$ python
>>> import geni.util
>>> context = geni.util.loadContext()
>>> import geni.aggregate.instageni as IG
>>> import pprint
>>> pprint.pprint(IG.GPO.getversion(context))
{'code': {'am_code': 0,
'am_type': 'protogeni',
'geni_code': 0,
'protogeni_error_log': 'urn:publicid:IDN+instageni.gpolab.bbn.com+log+abedbcc20e6defe716eb83b8586c7e08',
'protogeni_error_url': 'https://boss.instageni.gpolab.bbn.com/spewlogfile.php3?logfile=abedbcc20e6defe716eb83b8586c7e08'},
...snip...
You should get a large structure of formatted output telling you version and configuration information about the GPO InstaGENI aggregate. If you get any errors read them thorougly and review what they may be telling you about any mistakes you may have made. You can also ask your instructor if at an in-person tutorial.
Finished!¶
Assuming you have experienced no errors, your geni-lib
installation is now set up and
can communicate with all aggregates in the federation. If you have any issues you can
send a message to the geni-users
google group for help.
Creating a Context from Cloudlab Credentials¶
You can use the generic build-context tool included with geni-lib to build a context definition for use with Cloudlab. You will need the following files before you start:
- A Cloudlab x509 credential in .pem format
- The name of a project of which you are a member
- An ssh public key
Given the above, you can run the build-context tool directly:
build-context --type cloudlab --cert /path/to/cloudlab.pem \
--pubkey /path/to/ssh_key.pub --project projectname
Replacing the paths and project name with values appropriate for your environment. This will create a context definition which will be loaded automatically when using the genish or ipython interfaces, and can be loaded into your custom scripts using geni.util.loadContext().
Creating a Custom Context¶
In order to communicate with any federation resource using geni-lib
you need to construct
a Context
object that contains information about the framework you are using (for example
ProtoGENI, Emulab, GENI Clearinghouse, etc.), as well as your user information (SSH keys,
login username, federation urn, etc.). You can use the context-from-bundle
script that
comes with geni-lib
to create a context from an omni.bundle
provided by the GENI Portal
as documented in the “Importing a Context from the GENI Portal” tutorial, or you can create one
using a small Python module which allows for more configurability, and we illustrate that
method here.
To start, we will create a new Python file called
mycontext.py
and (inside the directory containing yourgeni-lib
clone) import the necessary modules to start building your own context using your favorite editor:from geni.aggregate import FrameworkRegistry from geni.aggregate.context import Context from geni.aggregate.user import User
Now we add a function that you will call each time you want to create your context (using the GENI Clearinghouse as the default framework):
def buildContext (): framework = FrameworkRegistry.get("portal")()
You need to give the framework instance the location of your user certificate and key files:
framework.cert = "/home/user/.ssh/portal-user.pem" framework.key = "/home/user/.ssh/portal-user.key"
Note
You may only have one file which contains both items - you can use the same path for both variables if this is the case.
Now we need to define an account and SSH key(s) that will be used to access reserved compute resources:
user = User() user.name = "myusername" user.urn = "urn:publicid:IDN+ch.geni.net+user+myusername" user.addKey("/home/user/.ssh/geni_dsa.pub")
We create a
User()
object, give it a name (no spaces, commonly a username), and the user URN. We then add an SSH public key that will be installed on any compute resources that you reserve in order to authenticate with those resources.Next we make the parent
Context
object and add our user and framework to it, with a default project:context = Context() context.addUser(user, default = True) context.cf = framework context.project = "GEC21"
This adds the user we created above, sets the control framework (
cf
), and sets your default project.You now want to return this object so that you can use this function every time you need a context:
return context
Now to see the complete code in one block:
from geni.aggregate import FrameworkRegistry
from geni.aggregate.context import Context
from geni.aggregate.user import User
def buildContext ():
framework = FrameworkRegistry.get("portal")()
framework.cert = "/home/user/.ssh/portal-user.pem"
framework.key = "/home/user/.ssh/portal-user.key"
user = User()
user.name = "myusername"
user.urn = "urn:publicid:IDN+ch.geni.net+user+myusername"
user.addKey("/home/user/.ssh/geni_dsa.pub")
context = Context()
context.addUser(user, default = True)
context.cf = framework
context.project = "GEC21"
return context
You can dynamically alter this object at any time, but your defaults will serve your purposes for the vast majority of your use cases.
Test It Out!¶
Now we can take your newly written file, instantiate our context, and query an aggregate:
$ python
>>> import mycontext
>>> context = mycontext.buildContext()
>>> import geni.aggregate.instageni as IG
>>> import pprint
>>> pprint.pprint(IG.GPO.getversion(context))
{'code': {'am_code': 0,
'am_type': 'protogeni',
'geni_code': 0,
'protogeni_error_log': 'urn:publicid:IDN+instageni.gpolab.bbn.com+log+abedbcc20e6defe716eb83b8586c7e08',
'protogeni_error_url': 'https://boss.instageni.gpolab.bbn.com/spewlogfile.php3?logfile=abedbcc20e6defe716eb83b8586c7e08'},
...snip...
You should get a large structure of formatted output telling you version and configuration information about the GPO InstaGENI aggregate. If you get any errors read them thorougly and review what they may be telling you about any mistakes you may have made. You can also ask your instructor (if at a GEC / Live Tutorial), or send a message to the geni-users google group.
Querying the Federation¶
Before we can reserve resources, it is useful to know what resources are available across the
federation. This tutorial will walk you through using the Context
object you created in
the previous tutorial to communicate with aggregates known to geni-lib
.
Finding Aggregate Locations¶
geni-lib
contains a set of package files which have pre-built objects representing known
aggregates that are ready for you to use, contained within the following Python modules:
geni.aggregate.exogeni
geni.aggregate.instageni
geni.aggregate.instageni_openflow
geni.aggregate.opengeni
geni.aggregate.protogeni
geni.aggregate.vts
While these aggregates objects will likely cover your needs, geni-lib
may of course not be
updated as frequently as new aggregates come online. You can find a list of the current set of
aggregates on the GENI Wiki.
Getting Aggregate Information¶
Given that we have our previously created Context
object, and a wealth of aggregate objects
available to us, the GENI federation provides the ability to request two blocks of information
from each aggregate - the version information (which you may have seen briefly in a previous
tutorial), and a list of the advertised resources.
The result from getversion
, as we saw in the previous tutorial, is reasonably concise and
human readable (but also contains information about API versions and supported request formats
that you may need to extract in your tools). The list of advertised resources is acquired using
the listresources
call, and returns a large XML document describing the available resources,
which is relatively difficult to work with without a tool.
Note
We will be using GENI AM API version 2 throughout this tutorial. Some API call names will be different if you elect to interact with aggregates using AM API version 3 in the future.
Lets start by getting an advertisement from a single aggregate. If you built a custom context using Python code you will need to replace the code below to load your custom context:
$ python >>> import geni.util >>> context = geni.util.loadContext() >>> import geni.aggregate.instageni as IGAM >>> ad = IGAM.Illinois.listresources(context)
Now of course we have an advertisement (assuming everything went well) stored into a Python object, which is reasonably boring!
Note
If you get timeouts or failures, you may want to try a different InstaGENI aggregate (this one may
be particularly busy). You can get a list of (mostly) aggregate objects by using the dir()
command
on the IGAM module - dir(IGAM)
.
We can simply print out the advertisement raw text to see what the aggregate sent us:
>>> print ad.text <rspec xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ...... ...
As you can see, even with this relatively small rack (5 hosts) the amount of data is significant.
As
geni-lib
has parsed this advertisement into a more functional object, we have access to data objects instead of just raw xml. For example, we can inspect the routable address space available at a site:>>> ad.routable_addresses.available 167 >>> ad.routable_addresses.capacity 190
You may have noticed that if you just print the
routable_addresses
attribute, you get nothing useful:>>> ad.routable_addresses <geni.rspec.pgad.RoutableAddresses object at 0x1717f10>
While we are adding online documentation for
geni-lib
objects, there are many objects that are undocumented. However, you can still gain some insight by using thedir()
built-in to see what attributes are available:>>> dir(ad.routable_addresses) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'available', 'capacity', 'configured']
In general attributes starting with underscores are not useful to us, so we can see 3 attributes of value -
available
,capacity
, andconfigured
. In most cases their meanings should be obvious, so just knowing they exist even without documentation is quite helpful.There are also 3 iterators that are provided with
Advertisement
objects -nodes
,links
, andshared_vlans
:>>> for svlan in ad.shared_vlans: ... print svlan ... mesoscale-openflow exclusive-openflow-1755 exclusive-openflow-1756 exclusive-openflow-1757 ...snip...
While
shared_vlans
just iterates over a set of strings,node
objects are much more complex and have many more attributes and nested data structures to allow you to fully inspect their state:>>> print dir(ad.nodes[0]) [..., 'available', 'component_id', 'component_manager_id', 'exclusive', 'hardware_types', 'images', 'interfaces', 'location', 'name', 'shared', 'sliver_types']
Particularly useful for the puposes of binding requests to certain nodes at a given site is the component_id:
>>> for node in ad.nodes: ... print node.component_id ... urn:publicid:IDN+instageni.illinois.edu+node+procurve2 urn:publicid:IDN+instageni.illinois.edu+node+pc3 urn:publicid:IDN+instageni.illinois.edu+node+pc5 urn:publicid:IDN+instageni.illinois.edu+node+interconnect-ion urn:publicid:IDN+instageni.illinois.edu+node+pc1 urn:publicid:IDN+instageni.illinois.edu+node+interconnect-campus urn:publicid:IDN+instageni.illinois.edu+node+pc2 urn:publicid:IDN+instageni.illinois.edu+node+interconnect-geni-core urn:publicid:IDN+instageni.illinois.edu+node+pc4 urn:publicid:IDN+instageni.illinois.edu+node+internet
Spend some time inspecting the other attributes of each node. You can get a specific node by using Python indexing on the
nodes
iterator:>>> node = ad.nodes[1] >>> node.component_id 'urn:publicid:IDN+instageni.illinois.edu+node+pc3'
Iterating Over Aggregates¶
Often you will want to inspect a large number of aggregates (particularly if there are of an idential or
similar type) in order to find those that have availability in the resources that you require. The aggregate
modules in geni-lib
provide some convenience methods for assisting in this task:
>>> import geni.aggregate.instageni as IGAM
>>> for am in IGAM.aggregates():
... print am.name
...
ig-cenic
ig-cwru
ig-clemson
ig-cornell
ig-ohmetrodc
ig-gatech
ig-gpo
ig-illinois
...snip...
Using this iterator you can act on each aggregate in a given module with the same snippet of code.
Lets try getting (and saving) the
getversion
output from each InstaGENI site:>>> import json >>> for am in IGAM.aggregates(): ... print am.name ... verdata = am.getversion(context) ... ver_file = open("%s-version.json" % (am.name), "w+") ... json.dump(verdata, ver_file) ... ig-cenic ig-cwru ig-clemson ...snip...
This will write out a file for every aggregate (barring any exceptions) to the current directory.
Note
verdata
in the above case is a Python dict
object, so we need to pick a way to write it
(in a human readable form) to a file. In the above example we pick serializing to JSON (which is
reasonably readable), but you could also use the pprint
module to format it nicely to a file
as a nice string.
Exercises¶
We can now combine all of the above pieces, plus some Python knowledge, into some useful scripts.
- Move the
getversion
code fragment above into a standalone script, and improve it to continue to the next aggregate if any exceptions are thrown by the current aggregate (unreachable, busy, etc.). - Write a script that prints out the number of availble routable IPs for each InstaGENI aggregate.
Creating a Request for a Single VM¶
This example walks through the basic of creating an RSpec (xml file) requesting a single VM from a compute aggregate. This example does not require that geni-lib is configured with user credentials or keys - it will create an XML file that you can feed into another tool such as Jacks or Omni (other examples cover how to make this request using geni-lib itself).
Note
You can find the complete source code for this example in a single file in the geni-lib distribution in samples/onevm.py.
Walk-through¶
Since we only want to output the XML of the request, we need very few imports:
import geni.rspec.pg as PG import geni.rspec.egext as EGX import geni.rspec.igext as IGX
Note
While the first module is named ‘pg’ (after ProtoGENI), the base rspec format is common across compute aggregates and all will use the same Request container, although the resources in that container will differ based on what is available at a given site.
Now we need to create the basic Request container:
r = PG.Request()
Unfortunately there is no unified VM object for all compute aggregates, so you will need to know which “flavor” of compute aggregate you intend to use (most commonly either InstaGENI or ExoGENI).
Note
In later examples you will see how, if you are using geni-lib to make your reservations directly with the aggregates, you can indeed create a single VM request that can be used across aggregate “flavors”.
Now we will allocate a VM object that can be added to our request (examples shown here for both ExoGENI and InstaGENI):
# ExoGENI exovm = EGX.XOSmall("vm1") # InstaGENI igvm = IGX.XenVM("vm1")
Note
The only required configuration for each resource is the name argument that is passed to the constructor. These names must be unique within a single site, but can be reused at different sites.
For the purposes of this example we will only add the InstaGENI VM to the actual request that we will produce:
r.addResource(igvm)
Now that we have a request that contains a resource, we can write the XML to disk that represents this request:
r.writeXML("onevm-request.xml")
VTS: Basic Single-Site Topology¶
This example walks through creating a simple VTS topology with one forwarding element (an Open vSwitch instance) connected to two virtual machines provided by the site compute aggregate. Resources for this request will come from two different aggregate managers at the same site, using information returned from the VTS aggregate to structure the second request to the compute aggregate.
The resultant topology will be as in the diagram below. The resources are color-coded to indicate which aggregate will provision them:

This obviously has no advantage over having the local site compute aggregate connect the VMs directly, but it serves as the simplest example of how to stage the provisioning of VTS resources and forms the basis for more advanced use cases.
Note
This example requires that you have set up a valid context object with GENI credentials.
Set up VTS Sliver¶
For this example we’ll use InstaGENI compute resources, but this would work for ExoGENI sites that have VTS support as well if you change the InstaGENI imports to the relevant ones for ExoGENI.
We need to set up basic imports to create requests and send them to the aggregate:
import geni.rspec.pg as PG import geni.rspec.igext as IGX import geni.rspec.vts as VTS import geni.aggregate.instageni as IGAM import geni.aggregate.vts as VTSAM
Here we also set up the slice name you’re going to use, as well as the context object that specifies your credential information. If you set up your
geni-lib
using the GENI Portal Import method, the code below will directly work. If you built a custom context using Python code you will need to replace the code below to load your custom context:import geni.util context = geni.util.loadContext() SLICENAME = "my-slice-name" # Change this to be your slice name
Note
If you do not have a slice available in your project, you may need to go back to the GENI Portal web interface and create a new slice.
VTS reservations are a two-stage process, where the VTS resources must be reserved first and the results used to create the proper compute request:
vtsr = VTS.Request()
First we select the image we want to use for our VTS forwarding elements:
image = VTS.OVSL2Image()
Note
Images support varying functionality that can be configured here, such as sflow and netflow collectors, openflow controllers, etc.
We then instantiate a single forwarding element with this image, and request two local circuits to connect to our VMs:
felement = VTS.Datapath(image, "fe0") felement.attachPort(VTS.LocalCircuit()) felement.attachPort(VTS.LocalCircuit()) vtsr.addResource(felement)
Now the request object is complete - we need to contact the aggregate and have it build our topology for us:
manifest = VTSAM.UtahDDC.createsliver(context, SLICENAME, vtsr)
Note
If you are at an in-person tutorial at GEC, etc., please replace VTSAM.UtahDDC
with the aggregate you have been given on your tutorial worksheet.
Set up InstaGENI Compute Sliver¶
The VTS aggregate manager returned to us a manifest containing information about the resources we have provisioned - specifically identifying information about the local circuits we requested. We will now use this information to request compute resources and connect them to the VTS sliver.
Initialize a basic GENI compute request:
igr = PG.Request()
The VTS Manifest object allows us to iterate over the local circuits that were returned, and we’ll make a VM with a single interface and link for each one, and give them IPs in the same subnet:
IP = "10.50.1.%d" for idx,circuit in enumerate(manifest.local_circuits): vm = IGX.XenVM("vm%d" % (idx)) intf = vm.addInterface("if0") intf.addAddress(PG.IPv4Address(IP % (idx+1), "255.255.255.0")) igr.addResource(vm) lnk = PG.Link() lnk.addInterface(intf) lnk.connectSharedVlan(circuit) igr.addResource(lnk)
There is a lot of code above, but the workflow is fairly simple:
- First, we set up a simple string substitution so we can add a small number of IP addresses in the same subnet (otherwise the compute AM will give the interfaces IP addresses in different subnets and you will have to fix them after you log into the nodes).
- Next we iterate over all of the circuits returned from the VTS AM that
match a certain type (“local”), while using the Python
enumerate
built-in to maintain a counter. - For each circuit we create a VM object, add an interface to it, give that
interface a unique IP address on our chosen subnet, and add that interface
to a
Link
object, along with the circuit ID (which in this case is a shared VLAN).
Now we just need to make the reservation and wait for our nodes to come up:
igm = IGAM.UtahDDC.createsliver(context, SLICENAME, igr) geni.util.printlogininfo(manifest = igm)
Note
If you are at an in-person tutorial at GEC, etc., please replace IGAM.UtahDDC
with the aggregate you have been given on your tutorial worksheet.
In a few minutes you should be able to log into your VMs with the info printed out by the above step and send test traffic (ping, etc.) between the VMs across your VTS topology.
Once you are done using your topology and exploring the tutorial, please delete all the resources you have reserved:
IGAM.UtahDDC.deletesliver(context, SLICENAME) VTSAM.UtahDDC.deletesliver(context, SLICENAME)
VTS: Basic WAN Topology¶
This example walks through creating a two-site WAN topology with one forwarding element at each site. Like all VTS reservations that require compute resources, the resources for each site will come from two different aggregate managers. This example also employs further sequencing constraints in order to build the WAN circuit.

In order to build a circuit between two sites those sites need to share a
common circuit plane. This is simply a named substrate that both sides have
a common attachment to. In this tutorial we will use the geni-al2s
circuit plane, which is currently available at most GENI VTS sites and replaces the
geni-mesoscale
circuit plane that is available at some sites but is being phased
out.
Note
This example requires that you have set up a valid context object with GENI credentials.
For this example we’ll use InstaGENI compute resources, but this would work for ExoGENI sites that have VTS support as well if you change the InstaGENI imports to the relevant ones for ExoGENI.
Set up VTS Slivers¶
We will first set up VTS slivers at both sites, before creating the local compute resources. This is not a strict requirement - you must always set up the VTS sliver at a site before the compute sliver, but you can request the compute sliver at a site before requesting the next site VTS sliver if that better fits your workflow.
In this example we will save the VTS manifests for later use to get compute resources, in case your interactive Python session needs to be restarted.
We need to set up basic imports to create requests and send them to the aggregate:
import geni.rspec.pg as PG import geni.rspec.igext as IGX import geni.rspec.vts as VTS import geni.aggregate.instageni as IGAM import geni.aggregate.vts as VTSAM
Here we also set up the slice name you’re going to use, as well as the context object that specifies your credential information. If you set up your
geni-lib
using the GENI Portal Import method, the code below will directly work. If you built a custom context using your own Python code you will need to replace the code below to load your custom context:import geni.util context = geni.util.loadContext() SLICENAME = "my-slice-name" # Change this to be your slice name
Note
If you do not have a slice available in your project, you may need to go back
to the GENI Portal web interface and create a new slice. Also if you have multiple
projects you may need to modify which one is being used by setting the
context.project
attribute.
VTS reservations are typically a multistage process, where the VTS resources at a site must be reserved before the compute resources, or neighbour site VTS resources, and the results from the earlier reservations will be used to seed data in all subsequent reservations. In the case of WAN reservations we will need advertisement information from the remote VTS site we intend to connect our circuits to:
remote_ad = VTSAM.NPS.listresources(context)
We need to search this remote advertisement for information that describes the endpoint we want to use for our chosen circuit plane:
for cp in remote_ad.circuit_planes: if cp.label == "geni-al2s": remote_endpoint = cp.endpoint
We now start to build our primary site VTS request rspec:
s1r = VTS.Request()
As in previous tutorials we will select a default L2 learning image for our forwarding elements:
image = VTS.OVSL2Image()
We the instantiate a single forwarding element with this image, and request a local circuit to connect to our VM, as well as a WAN circuit to connect to the remote site:
felement = VTS.Datapath(image, "fe0") felement.attachPort(VTS.LocalCircuit()) wan_port = felement.attachPort(VTS.GRECircuit("geni-al2s", remote_endpoint)) s1r.addResource(felement)
Note
We have chosen to use a GRE Circuit here to reach the remote site, although other types might be available. Each site advertises a list of supported encapsulation types for each circuit plane, allowing you to choose the one that best suits your needs based on performance and packet overhead.
Now our request object is complete for our first site, so we can contact the aggregate manager and make the reservation:
ukym = VTSAM.UKYPKS2.createsliver(context, SLICENAME, s1r)
Note
If you are at an in-person tutorial you may need to replace VTSAM.UKYPKS2
with the aggregate you have been given on your tutorial worksheet.
We will write out our returned manifest to disk in case we need to restart our Python session:
ukym.writeXML("vts-ukypks2-manifest.xml")
Now we will start building the VTS request at the remote site:
s2r = VTS.Request()
The basic parts of the request are the same at each site:
felement = VTS.Datapath(image, "fe0") felement.attachPort(VTS.LocalCircuit()) s2r.addResource(felement)
Now we need to attach one port to our forwarding element that connects to the remote site that we have already configured:
felement.attachPort(VTS.GRECircuit("geni-al2s", ukym.findPort(wan_port.clientid).local_endpoint))
This searches our previous manifest for the WAN port we have already defined, and gathers the endpoint information to put in a remote request. The combination of this inforamtion will create a complete WAN circuit.
Having created our request, we send it to the aggregate manager to reserve our resources, and write the output to a file:
npsm = VTSAM.NPS.createsliver(context, SLICENAME, s2r) npsm.writeXML("vts-nps-manifest.xml")
Set up InstaGENI Compute Slivers¶
As we have two sites, we will need to set up our compute slivers at both sites, using the manifests returned from each VTS request. We want to set up IP addresses that we will use on both sides of our WAN topology:
IP = "10.50.1.%d"
NETMASK = "255.255.255.0"
Each request is relatively simple, containing only a single VM connected to a single VTS port, pulled from the site VTS manifest:
ukyr = PG.Request() for idx,circuit in enumerate(ukym.local_circuits): vm = IGX.XenVM("vm%d" % (idx)) intf = vm.addInterface("if0") intf.addAddress(PG.IPv4Address(IP % (1), NETMASK)) ukyr.addResource(vm) lnk = PG.Link() lnk.addInterface(intf) lnk.connectSharedVlan(circuit) ukyr.addResource(lnk)
The code above is the same as in earlier tutorials, which you can refer to for more thorough explanation.
Now we make the reservation:
ukyigm = IGAM.UKYPKS2.createsliver(context, SLICENAME, ukyr) geni.util.printlogininfo(manifest=ukyigm)
We execute nearly identical code for the second site (note the IP address change):
npsr = PG.Request() for idx,circuit in enumerate(npsm.local_circuits): vm = IGX.XenVM("vm%d" % (idx)) intf = vm.addInterface("if0") intf.addAddress(PG.IPv4Address(IP % (2), NETMASK)) npsr.addResource(vm) lnk = PG.Link() lnk.addInterface(intf) lnk.connectSharedVlan(circuit) npsr.addResource(lnk)
Now we make the second site reservation:
npsigm = IGAM.NPS.createsliver(context, SLICENAME, npsr) geni.util.printlogininfo(manifest=npsigm)
In a few minutes you should be able to log into your VMs with the info printed out by the above step and send test traffic (ping, etc.) between the VMs across your VTS WAN topology.
Once you are done using your topology and exploring the tutorial, please delete all the resources you have reserved:
IGAM.NPS.deletesliver(context, SLICENAME) IGAM.UKYPKS2.deletesliver(context, SLICENAME) VTSAM.NPS.deletesliver(context, SLICENAME) VTSAM.UKYPKS2.deletesliver(context, SLICENAME)
API¶
geni.aggregate¶
geni.aggregate.cloudlab¶
-
class
CloudLabAM
(name, host, cmid=None, url=None)[source]¶ -
-
amtype
¶
-
api
¶
-
component_manager_id
¶
-
createsliver
(context, sname, rspec)¶ GENI AM APIv2 method to reserve resources at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- rspec (geni.rspec.RSpec) – Valid request RSpec
-
deletesliver
(context, sname)¶ GENI AM APIv2 method to delete a resource reservation at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
-
geniCancelUpdateUsers
(context, sname)¶
-
geniRestart
(context, sname, urns)¶
-
geniStart
(context, sname)¶
-
geniUpdateUsers
(context, sname, user_info_list)¶
-
getConsoleURL
(context, sname, urn)¶
-
getversion
(context)¶ GENI AM API method to get the version information for this aggregate.
Parameters: context – geni-lib context Returns: dict – Dictionary of key/value pairs with version information from this aggregate.
-
listresources
(context, sname=None, available=False)¶ GENI AM APIv2 method to get available resources from an aggregate, or resources allocated to a specific sliver.
Parameters: - context – geni-lib context
- sname (str) – Slice name (optional)
- available (bool) – Only list available resources
Returns: geni.rspec.RSpec – If sname is provided, listresources will return a manifest rspec for the given slice name. Otherwise, listresources will return the advertisement rspec for the given aggregate.
-
renewsliver
(context, sname, date)¶ GENI AM APIv2 method to renew a sliver until the given datetime.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- date (str) – RFC 3339-compliant date string for new expiration date
Note
Aggregates may have maximum expiration limits, restricting how far in the future you can set your expiration. This call may result in an error in such cases, or success with a sooner future date.
-
sliverstatus
(context, sname)¶ GENI AM APIv2 method to get the status of a current sliver at the given aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
Returns: dict – Mapping of key/value pairs for status information the aggregate supports.
-
geni.aggregate.exogeni¶
-
class
EGCompute
(name, host, cmid=None, url=None)[source]¶ -
-
amtype
¶
-
api
¶
-
component_manager_id
¶
-
createsliver
(context, sname, rspec)¶ GENI AM APIv2 method to reserve resources at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- rspec (geni.rspec.RSpec) – Valid request RSpec
-
deletesliver
(context, sname)¶ GENI AM APIv2 method to delete a resource reservation at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
-
getversion
(context)¶ GENI AM API method to get the version information for this aggregate.
Parameters: context – geni-lib context Returns: dict – Dictionary of key/value pairs with version information from this aggregate.
-
listresources
(context, sname=None, available=False)¶ GENI AM APIv2 method to get available resources from an aggregate, or resources allocated to a specific sliver.
Parameters: - context – geni-lib context
- sname (str) – Slice name (optional)
- available (bool) – Only list available resources
Returns: geni.rspec.RSpec – If sname is provided, listresources will return a manifest rspec for the given slice name. Otherwise, listresources will return the advertisement rspec for the given aggregate.
-
renewsliver
(context, sname, date)¶ GENI AM APIv2 method to renew a sliver until the given datetime.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- date (str) – RFC 3339-compliant date string for new expiration date
Note
Aggregates may have maximum expiration limits, restricting how far in the future you can set your expiration. This call may result in an error in such cases, or success with a sooner future date.
-
sliverstatus
(context, sname)¶ GENI AM APIv2 method to get the status of a current sliver at the given aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
Returns: dict – Mapping of key/value pairs for status information the aggregate supports.
-
geni.aggregate.instageni¶
-
class
IGCompute
(name, host, cmid=None, url=None)[source]¶ -
-
amtype
¶
-
api
¶
-
component_manager_id
¶
-
createsliver
(context, sname, rspec)¶ GENI AM APIv2 method to reserve resources at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- rspec (geni.rspec.RSpec) – Valid request RSpec
-
deletesliver
(context, sname)¶ GENI AM APIv2 method to delete a resource reservation at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
-
geniCancelUpdateUsers
(context, sname)¶
-
geniRestart
(context, sname, urns)¶
-
geniStart
(context, sname)¶
-
geniUpdateUsers
(context, sname, user_info_list)¶
-
getConsoleURL
(context, sname, urn)¶
-
getversion
(context)¶ GENI AM API method to get the version information for this aggregate.
Parameters: context – geni-lib context Returns: dict – Dictionary of key/value pairs with version information from this aggregate.
-
listresources
(context, sname=None, available=False)¶ GENI AM APIv2 method to get available resources from an aggregate, or resources allocated to a specific sliver.
Parameters: - context – geni-lib context
- sname (str) – Slice name (optional)
- available (bool) – Only list available resources
Returns: geni.rspec.RSpec – If sname is provided, listresources will return a manifest rspec for the given slice name. Otherwise, listresources will return the advertisement rspec for the given aggregate.
-
renewsliver
(context, sname, date)¶ GENI AM APIv2 method to renew a sliver until the given datetime.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- date (str) – RFC 3339-compliant date string for new expiration date
Note
Aggregates may have maximum expiration limits, restricting how far in the future you can set your expiration. This call may result in an error in such cases, or success with a sooner future date.
-
sliverstatus
(context, sname)¶ GENI AM APIv2 method to get the status of a current sliver at the given aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
Returns: dict – Mapping of key/value pairs for status information the aggregate supports.
-
geni.aggregate.opengeni¶
-
class
OGCompute
(name, host, cmid=None, url=None)[source]¶ -
-
amtype
¶
-
api
¶
-
component_manager_id
¶
-
createsliver
(context, sname, rspec)¶ GENI AM APIv2 method to reserve resources at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- rspec (geni.rspec.RSpec) – Valid request RSpec
-
deletesliver
(context, sname)¶ GENI AM APIv2 method to delete a resource reservation at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
-
getversion
(context)¶ GENI AM API method to get the version information for this aggregate.
Parameters: context – geni-lib context Returns: dict – Dictionary of key/value pairs with version information from this aggregate.
-
listresources
(context, sname=None, available=False)¶ GENI AM APIv2 method to get available resources from an aggregate, or resources allocated to a specific sliver.
Parameters: - context – geni-lib context
- sname (str) – Slice name (optional)
- available (bool) – Only list available resources
Returns: geni.rspec.RSpec – If sname is provided, listresources will return a manifest rspec for the given slice name. Otherwise, listresources will return the advertisement rspec for the given aggregate.
-
renewsliver
(context, sname, date)¶ GENI AM APIv2 method to renew a sliver until the given datetime.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- date (str) – RFC 3339-compliant date string for new expiration date
Note
Aggregates may have maximum expiration limits, restricting how far in the future you can set your expiration. This call may result in an error in such cases, or success with a sooner future date.
-
sliverstatus
(context, sname)¶ GENI AM APIv2 method to get the status of a current sliver at the given aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
Returns: dict – Mapping of key/value pairs for status information the aggregate supports.
-
geni.aggregate.protogeni¶
-
class
PGCompute
(name, host, cmid=None, url=None)[source]¶ -
-
amtype
¶
-
api
¶
-
component_manager_id
¶
-
createsliver
(context, sname, rspec)¶ GENI AM APIv2 method to reserve resources at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- rspec (geni.rspec.RSpec) – Valid request RSpec
-
deletesliver
(context, sname)¶ GENI AM APIv2 method to delete a resource reservation at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
-
getversion
(context)¶ GENI AM API method to get the version information for this aggregate.
Parameters: context – geni-lib context Returns: dict – Dictionary of key/value pairs with version information from this aggregate.
-
listresources
(context, sname=None, available=False)¶ GENI AM APIv2 method to get available resources from an aggregate, or resources allocated to a specific sliver.
Parameters: - context – geni-lib context
- sname (str) – Slice name (optional)
- available (bool) – Only list available resources
Returns: geni.rspec.RSpec – If sname is provided, listresources will return a manifest rspec for the given slice name. Otherwise, listresources will return the advertisement rspec for the given aggregate.
-
renewsliver
(context, sname, date)¶ GENI AM APIv2 method to renew a sliver until the given datetime.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- date (str) – RFC 3339-compliant date string for new expiration date
Note
Aggregates may have maximum expiration limits, restricting how far in the future you can set your expiration. This call may result in an error in such cases, or success with a sooner future date.
-
sliverstatus
(context, sname)¶ GENI AM APIv2 method to get the status of a current sliver at the given aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
Returns: dict – Mapping of key/value pairs for status information the aggregate supports.
-
geni.aggregate.transit¶
-
class
Transit
(name, amtype, cmid, url)[source]¶ -
-
amtype
¶
-
api
¶
-
component_manager_id
¶
-
createsliver
(context, sname, rspec)¶ GENI AM APIv2 method to reserve resources at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- rspec (geni.rspec.RSpec) – Valid request RSpec
-
deletesliver
(context, sname)¶ GENI AM APIv2 method to delete a resource reservation at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
-
getversion
(context)¶ GENI AM API method to get the version information for this aggregate.
Parameters: context – geni-lib context Returns: dict – Dictionary of key/value pairs with version information from this aggregate.
-
listresources
(context, sname=None, available=False)¶ GENI AM APIv2 method to get available resources from an aggregate, or resources allocated to a specific sliver.
Parameters: - context – geni-lib context
- sname (str) – Slice name (optional)
- available (bool) – Only list available resources
Returns: geni.rspec.RSpec – If sname is provided, listresources will return a manifest rspec for the given slice name. Otherwise, listresources will return the advertisement rspec for the given aggregate.
-
renewsliver
(context, sname, date)¶ GENI AM APIv2 method to renew a sliver until the given datetime.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- date (str) – RFC 3339-compliant date string for new expiration date
Note
Aggregates may have maximum expiration limits, restricting how far in the future you can set your expiration. This call may result in an error in such cases, or success with a sooner future date.
-
sliverstatus
(context, sname)¶ GENI AM APIv2 method to get the status of a current sliver at the given aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
Returns: dict – Mapping of key/value pairs for status information the aggregate supports.
-
geni.aggregate.vts¶
-
class
Policy
(vtsam)[source]¶ -
getText
(context, pid=None)[source]¶ Get the text contents of the policy requested. If no policy is specified and only one policy exists at the aggregate, that policy text will be returned.
Parameters: - context – geni-lib context
- pid – policy ID (typically from getversion output)
Returns: str – Text contents of policy
-
-
class
VTS
(name, host, url=None)[source]¶ Wrapper for all VTS-supported AMAPI functions
-
addDNSResourceRecord
(context, sname, client_id, record_name, record_type, record_value, record_ttl=7200)[source]¶
-
amtype
¶
-
api
¶
-
clearFlows
(context, sname, datapaths)[source]¶ Clear all installed flows from the requested datapaths.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- datapaths (list) – A list of datapath client_id strings
-
component_manager_id
¶
-
createsliver
(context, sname, rspec)¶ GENI AM APIv2 method to reserve resources at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- rspec (geni.rspec.RSpec) – Valid request RSpec
-
deletesliver
(context, sname)¶ GENI AM APIv2 method to delete a resource reservation at this aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
-
dropboxFinalize
(context, authcode)[source]¶ Finalize the Dropbox account link for this aggregate.
Parameters: - context – geni-lib context
- authcode (str) – Authorization code given by Dropbox
-
dropboxLink
(context)[source]¶ Link your user_urn to a Dropbox account at this aggregate.
Parameters: context – geni-lib context Returns: str – Dropbox authorization URL to paste into web browser
-
dropboxUpload
(context, sname, cvols)[source]¶ Trigger upload to associated Dropbox account from requested container volumes.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- cvols (list) – List of (container client-id, volume-id) tuples
-
dumpFlows
(context, sname, datapaths, show_hidden=False)[source]¶ Get the current flows and flow stats from the requested datapaths.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- datapaths (list) – A list of datapath client_id strings
- show_hidden (bool) – Show hidden flows (if any)
Returns: dict – Key/Value dictionary of format { client_id : [(flow_field, …), …] }
-
getversion
(context)¶ GENI AM API method to get the version information for this aggregate.
Parameters: context – geni-lib context Returns: dict – Dictionary of key/value pairs with version information from this aggregate.
-
hgPull
(context, sname, cvols)[source]¶ Update an HgMount volume with the latest data from the source repository.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- cvols (list) – List of (container client-id, volume-id) tuples
-
listresources
(context, sname=None, available=False)¶ GENI AM APIv2 method to get available resources from an aggregate, or resources allocated to a specific sliver.
Parameters: - context – geni-lib context
- sname (str) – Slice name (optional)
- available (bool) – Only list available resources
Returns: geni.rspec.RSpec – If sname is provided, listresources will return a manifest rspec for the given slice name. Otherwise, listresources will return the advertisement rspec for the given aggregate.
-
renewsliver
(context, sname, date)¶ GENI AM APIv2 method to renew a sliver until the given datetime.
Parameters: - context – geni-lib context
- sname (str) – Slice name
- date (str) – RFC 3339-compliant date string for new expiration date
Note
Aggregates may have maximum expiration limits, restricting how far in the future you can set your expiration. This call may result in an error in such cases, or success with a sooner future date.
-
setDeleteLock
(context, sname)[source]¶ Prevent the given sliver from being deleted by another user with the credential.
Note
Locks are cumulative, and removed by calling deletesliver. When the last locking user calls deletesliver, the sliver will be deleted. It is not possible to remove your lock without risking deletion.
Parameters: - context – geni-lib context
- sname (str) – Slice name
-
sliverstatus
(context, sname)¶ GENI AM APIv2 method to get the status of a current sliver at the given aggregate.
Parameters: - context – geni-lib context
- sname (str) – Slice name
Returns: dict – Mapping of key/value pairs for status information the aggregate supports.
-
-
class
v4RouterPOAs
(vtsam)[source]¶
geni.minigcf.config¶
-
class
HTTP
[source]¶ Global configuration options for MiniGCF HTTP(S) calls.
-
ALLOW_REDIRECTS
= False¶ Allow MiniGCF to follow HTTP redirects (301).
-
LOG_RAW_REQUESTS
= False¶ If set to a valid (log_handle, log_level) tuple, will write all raw requests (before any parsing) to AM API and CH API calls to that log at the given level.
-
LOG_RAW_RESPONSES
= False¶ If set to a valid (log_handle, log_level) tuple, will write all raw responses (before any parsing) from AM API and CH API calls to that log at the given level.
-
LOG_URLS
= False¶ If set to a valid (log_handle, log_level) tuple, will log all URLs as they are used.
-
TIMEOUT
= 60¶ Initial response timeout. Note that this is not the time limit on the entire download, just the initial server response.
-
geni.portal¶
Library for dealing with scripts that are run in the context of a portal.
-
class
Context
[source]¶ Handle context for scripts being run inside a portal.
This class handles context for the portal, including where to put output RSpecs and handling parameterized scripts.
Scripts using this class can also be run “standalone” (ie. not by the portal), in which case they take parameters on the command line and put RSpecs on the standard output.
This class is a singleton. Most programs should access it through the portal.context variable; any additional “instances” of the object will be references to this.
-
bindParameters
(altParamSrc=None)[source]¶ Returns values for the parameters defined by defineParameter().
Returns a Namespace (like argparse), so if you call foo = bindParameters(), a parameter defined with name “bar” is accessed as foo.bar . Since defaults are required, all parameters are guaranteed to have values in the Namespace
If run standaline (not in the portal), parameters are pulled from the command line (try running with –help); if run in the portal, they are pulled from the portal itself. Or, if you provide the altParamSrc argument, you can specify your own parameters. If altParamSrc is a dict, we will bind the params as a dict, using the keys as parameter names, and the values as parameter values. If altParamSrc is a geni.rspec.pgmanifest.Manifest, we will extract the parameters and their values from the Manifest. Finally, if altParamSrc is a string, we’ll try to parse it as a PG manifest xml document. No other forms of altParamSrc are currently specified.
-
bindRequestRSpec
(rspec)[source]¶ Bind the given request RSpec to the context, so that it can be automatically used with methods like printRequestRSpec.
At the present time, only one request can be bound to a context
-
defineParameter
(name, description, typ, defaultValue, legalValues=None, longDescription=None, advanced=False, groupId=None, hide=False, prefix='emulab.net.parameter.')[source]¶ Define a new paramter to the script.
The given name will be used when parameters are bound. The description is brief help text that will be shown to the user when making his/her selection. The type should be one of the types defined by ParameterType. defaultValue is required, but legalValues (a list) is optional; the defaultValue must be one of the legalValues. Entries in the legalValues list may be either simple strings (eg. “m400”), in which case they will be show directly to the user, or 2-element tuples (eg. (“m400”, “ARM64”),), in which the second entry is what is shown to the user. defaultValue may be a tuple, so that one can pass, say, ‘legalvalues[0]’ for the option. The longDescription is an optional, detailed description of this parameter and how it relates to other parameters; it will be shown to the user if they ask to see the help, or as a pop-up/tooltip. advanced, group, and groupName all provide parameter group abstractions. Parameter groups are hidden by default from the user, and the user can expand them to view and modify them if desired. By setting advanced to True, you create a parameter group named “Advanced Parameters”; this group will not exist or be shown if none of your parameters set the ‘advanced’ argument to True.
After defining parameters, bindParameters() must be called exactly once.
-
defineParameterGroup
(groupId, groupName)[source]¶ Define a parameter group. Parameters may be added to this group, which has an identifying token composed of alphanumeric characters (groupId), and a human-readable name (groupName). Groups are intended to be used for advanced parameters; in the portal UI, they hidden in an expandable panel with the groupName — and the user can choose to see and modify them, or not. You do not need to specify any groups; you can simply stuff all your parameters into the “Advanced Parameters” group by setting the ‘advanced’ argument of defineParameter to True. If you need multiple groups, define your own groups this way.
-
makeParameterWarningsFatal
()[source]¶ Enable this option if you want to return an error to the user for incorrect parameter values, even if they can be autocorrected. This can be useful to show the user that
-
printRequestRSpec
(rspec=None)[source]¶ Print the given request RSpec, or the one bound to this context if none is given.
If run standalone (not in the portal), the request will be printed to the standard output; if run in the portal, it will be placed someplace the portal can pick it up.
If the given rspec does not have a Tour object, this will attempt to build one from the file’s docstring
-
reportError
(parameterError, immediate=False)[source]¶ Report a parameter error to the portal. @parameterError is an exception object of type ParameterError. If @immediate is True, your script will exit immediately at this point with a dump of the errors (and fatal warnings, if enabled via Context.makeParameterWarningsFatal) in JSON format. If @immediate is False, the errors will accumulate until Context.verifyParameters is called (and the errors will then be printed).
-
reportWarning
(parameterError)[source]¶ Record a parameter warning. Warnings will be printed if there are other errors or if warnings have been set to be fatal, when Context.verifyParameters() is called, or when there is another subsequent immediate error.
-
-
exception
ParameterError
(message, paramList)[source]¶ A simple class to describe a parameter error. If you need to report an error with a user-specified parameter value to the Portal UI, please create (don’t throw) one of these error objects, and tell the Portal about it by calling Context.reportError.
-
class
ParameterType
[source]¶ Parameter types understood by Context.defineParameter().
-
AGGREGATE
= 'aggregate'¶ URN specifying an Aggregate Manger
-
BANDWIDTH
= 'bandwidth'¶ Floating-point number to be used for bandwidth
-
BOOLEAN
= 'boolean'¶ True/False
-
IMAGE
= 'image'¶ URN specifying a particular image
-
INTEGER
= 'integer'¶ Simple integer
-
LATENCY
= 'latency'¶ Floating-point number to be used for latency
-
LOSSRATE
= 'lossrate'¶ Floating-point number 0.0 <= N < 1.0
-
NODETYPE
= 'nodetype'¶ String specifying a type of node
-
PUBKEY
= 'pubkey'¶ An RSA public key.
-
SIZE
= 'size'¶ Integer for size (eg. MB, GB, etc.)
-
STRING
= 'string'¶ Any string
-
-
exception
ParameterWarning
(message, paramList, fixedValues=None)[source]¶ A simple class to describe a parameter warning. If you need to report an warning with a user-specified parameter value to the Portal UI, please create (don’t throw) one of these error objects, and tell the Portal about it by calling Context.reportWarning . The first time the Portal UI runs your geni-lib script with a user’s parameter values, it turns on the “warnings are fatal” mode (and then warnings are reported as errors). This gives you a chance to warn the user that they might be about to do something stupid, and/or suggest a set of modified values that will improve the situation. .
-
class
PortalJSONEncoder
(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, encoding='utf-8', default=None)[source]¶ -
default
(o)[source]¶ Implement this method in a subclass such that it returns a serializable object for
o
, or calls the base implementation (to raise aTypeError
).For example, to support arbitrary iterators, you could implement default like this:
def default(self, o): try: iterable = iter(o) except TypeError: pass else: return list(iterable) # Let the base class default method raise the TypeError return JSONEncoder.default(self, o)
-
-
context
= <geni.portal.Context object>¶ Module-global Context object - most users of this module should simply use this rather than trying to create a new Context object
geni.rspec¶
geni.rspec.emulab¶
Convenience library to load all extensions supported by Emulab-based aggregates. In most cases, you will not need to load these extension libraries individually, just load this one.
geni.rspec.emulab.emuext¶
Common set of RSpec extensions supported by many Emulab-based aggregates
-
class
BridgedLink
(name=None)[source]¶ A bridged link is syntactic sugar used to create two links separated by an Emulab delay (bridge) node. The BridgedLink class will create the following topology:
left-link right-linknode1 =========== bridge ============ node2
The bridge is a special node type (sliver_type=”delay”) that tells the CM to insert an Emulab delay node instead of a plain (router) node. A delay node is a transparent Ethernet bridge between the left and right segments above, but on which the traffic can be shaped wrt. bandwidth, latency, and loss. For example:
# Create the bridged link between the two nodes. link = request.BridgedLink(“link”) # Add two interfaces link.addInterface(iface1) link.addInterface(iface2) # Give the link (bridge) some shaping parameters. link.bandwidth = 10000 link.latency = 15 link.plr = 0.01-
bandwidth
¶
-
latency
¶
-
plr
¶
-
-
class
InstantiateOn
(parent)[source]¶ Added to a node to specify that it a Xen VM should be bound to (instantiated on) another node in the topology. Argument is the node instance or the client id of another node in the topology.
-
class
ProgramAgent
(name, command, directory=None, onexpstart=False)[source]¶ Add an Emulab Program Agent, which can be controlled via the Emulab event system. Optional argument ‘directory’ specifies where to invoke the command from. Optional argument ‘onexpstart’ says to invoke the command when the experiment starts (time=0 in event speak). This is different than the Execute service, which runs every time the node boots.
-
class
setCollocateFactor
(mfactor)[source]¶ Added to a top-level Request object, this extension limits the number of VMs from one experiment that Emulab will collocate on each physical host.
-
class
setDelayImage
(urn)[source]¶ Added to a top-level Request object, this extension sets the disk image that will be used for all delay nodes configured for the experiment.
-
class
setFailureAction
(action)[source]¶ Added to a node this extension will tell Emulab based aggregates to ignore errors booting this node when starting an experiment. This allows the experiment to proceed so that the user has time to debug.
-
class
setForceShaping
[source]¶ Added to a Link or LAN object, this extension forces Emulab link shaping to be enabled, even if it is not strictly necessary. This allows the link properties to be changed dynamically via the Emulab event system.
-
class
setNoBandwidthShaping
[source]¶ Added to a Link or LAN object, this extension forces Emulab link shaping to be disabled for bandwidth, even if it is necessary. This is ignored if the link must be shaped for other reason (delay, loss).
-
class
setNoInterSwitchLinks
[source]¶ Added to a Link or LAN object, this extension forces the Emulab mapper to disallow mapping a link in the request topology to an inter-switch link. This allows users to require that specific nodes in their topology be attached to the same switch(es).
-
class
setPackingStrategy
(strategy)[source]¶ Added to a top-level Request object, this extension controls the strategy used for distributing VMs across physical hosts
geni.rspec.igext¶
-
class
AddressPool
(name, count=1, type='any')[source]¶ A pool of public dynamic IP addresses belonging to a slice.
-
name
¶
-
-
class
OFController
(host, port=6633)[source]¶ OpenFlow controller specification to be used on a PG VLAN.
Add to link objects using the Link.addChild() method.
Note
This will have no effect if a trivial link is created by the aggregate. You need to make sure that a VLAN will be provisioned (typically by making sure that at least two interfaces on the link are on different physical hosts).
-
class
Password
(name=None)[source]¶ A declaration for a randomly generated password.
The portal will generate the password, encrypt it, and pass on the encrypted value to the AM(s) and therefore the node(s).
-
class
RemoteBlockstore
(name, mount=None, ifacename='if0')[source]¶ -
dataset
¶
-
interface
¶
-
mountpoint
¶
-
placement
¶
-
readonly
¶
-
rwclone
¶
-
size
¶
-
-
class
Tour
[source]¶ -
-
MARKDOWN
= 'markdown'¶
-
SPLIT_REGEX
= <_sre.SRE_Pattern object>¶
-
class
Step
(target, description, steptype=None, description_type='markdown')[source]¶ -
MARKDOWN
= 'markdown'¶
-
TEXT
= 'text'¶
-
-
TEXT
= 'text'¶
-
-
class
XenVM
(client_id, component_id=None, exclusive=False)[source]¶ Xen-based Virtual Machine resource
Parameters: - client_id (str) – Your name for this VM. This must be unique within a single Request object.
- component_id (Optional[str]) – The component_id of the site node you want to bind this VM to
- exclusive (Optional[bool]) – Request this VM on an isolated host used only by your sliver.
-
cores
¶ int – Number of CPU cores
-
ram
¶ int – Amount of memory in megabytes
-
disk
¶ int – Amount of disk space in gigabytes
-
xen_ptype
¶ str – Physical node type on which to instantiate the VM. Types are AM-specific.
geni.rspec.pg¶
-
class
Link
(name=None, ltype='', members=None)[source]¶ -
DEFAULT_BW
= -1¶
-
DEFAULT_LAT
= 0¶
-
DEFAULT_PLR
= 0.0¶
-
EXTENSIONS
= [('Site', <class 'geni.rspec.igext.Site'>), ('setForceShaping', <class 'geni.rspec.emulab.emuext.setForceShaping'>), ('setNoBandwidthShaping', <class 'geni.rspec.emulab.emuext.setNoBandwidthShaping'>), ('setNoInterSwitchLinks', <class 'geni.rspec.emulab.emuext.setNoInterSwitchLinks'>), ('UserData', <class 'geni.rspec.emulab.userdata.UserData'>)]¶
-
LNKID
= 0¶
-
best_effort
¶
-
link_multiplexing
¶
-
trivial_ok
¶
-
vlan_tagging
¶
-
-
class
Namespaces
[source]¶ -
CLIENT
= http://www.protogeni.net/resources/rspec/ext/client/1¶
-
DATA
= http://www.protogeni.net/resources/rspec/ext/user-data/1¶
-
DELAY
= http://www.protogeni.net/resources/rspec/ext/delay/1¶
-
EMULAB
= http://www.protogeni.net/resources/rspec/ext/emulab/1¶
-
INFO
= http://www.protogeni.net/resources/rspec/ext/site-info/1¶
-
JACKS
= http://www.protogeni.net/resources/rspec/ext/jacks/1¶
-
PARAMS
= http://www.protogeni.net/resources/rspec/ext/profile-parameters/1¶
-
RS
= http://www.protogeni.net/resources/rspec/ext/emulab/1¶
-
TOUR
= http://www.protogeni.net/resources/rspec/ext/apt-tour/1¶
-
VTOP
= http://www.protogeni.net/resources/rspec/ext/emulab/1¶
-
-
class
Node
(name, ntype, component_id=None, exclusive=None)[source]¶ -
-
EXTENSIONS
= [('Blockstore', <class 'geni.rspec.igext.Blockstore'>), ('Firewall', <class 'geni.rspec.igext.Firewall'>), ('Site', <class 'geni.rspec.igext.Site'>), ('Desire', <class 'geni.rspec.igext.Desire'>), ('setUseTypeDefaultImage', <class 'geni.rspec.emulab.emuext.setUseTypeDefaultImage'>), ('setFailureAction', <class 'geni.rspec.emulab.emuext.setFailureAction'>), ('InstantiateOn', <class 'geni.rspec.emulab.emuext.InstantiateOn'>), ('UserData', <class 'geni.rspec.emulab.userdata.UserData'>)]¶
-
name
¶
-
-
class
Request
[source]¶ -
EXTENSIONS
= [('Link', <class 'geni.rspec.pg.Link'>), ('LAN', <class 'geni.rspec.pg.LAN'>), ('L3GRE', <class 'geni.rspec.pg.L3GRE'>), ('L2GRE', <class 'geni.rspec.pg.L2GRE'>), ('StitchedLink', <class 'geni.rspec.pg.StitchedLink'>), ('Node', <class 'geni.rspec.pg.Node'>), ('RawPC', <class 'geni.rspec.pg.RawPC'>), ('XenVM', <class 'geni.rspec.igext.XenVM'>), ('AddressPool', <class 'geni.rspec.igext.AddressPool'>), ('RemoteBlockstore', <class 'geni.rspec.igext.RemoteBlockstore'>), ('Bridge', <class 'geni.rspec.igext.Bridge'>), ('ParameterData', <class 'geni.rspec.igext.ParameterData'>), ('setCollocateFactor', <class 'geni.rspec.emulab.emuext.setCollocateFactor'>), ('setPackingStrategy', <class 'geni.rspec.emulab.emuext.setPackingStrategy'>), ('setRoutingStyle', <class 'geni.rspec.emulab.emuext.setRoutingStyle'>), ('setDelayImage', <class 'geni.rspec.emulab.emuext.setDelayImage'>), ('BridgedLink', <class 'geni.rspec.emulab.emuext.BridgedLink'>), ('ShapedLink', <class 'geni.rspec.emulab.emuext.ShapedLink'>), ('EPClan', <class 'geni.rspec.emulab.epclan.EPClan'>), ('EPCNode', <class 'geni.rspec.emulab.epcnode.EPCNode'>), ('EPCVMNode', <class 'geni.rspec.emulab.epcnode.EPCVMNode'>), ('eNodeB', <class 'geni.rspec.emulab.enodeb.eNodeB'>), ('UE', <class 'geni.rspec.emulab.ue.UE'>), ('RFLink', <class 'geni.rspec.emulab.rflink.RFLink'>)]¶
-
resources
¶
-
-
VM
¶ alias of
geni.rspec.pg.XenVM
-
class
XenVM
(name, component_id=None, exclusive=False)[source]¶ Deprecated since version 0.4: Use
geni.rspec.igext.XenVM
instead.
geni.rspec.pgad¶
-
class
AdInterface
(name)[source]¶ Wrapper object for a Node Interface in a GENIv3 Advertisement.
-
component_id
¶ str – Component ID URN
-
role
¶ str – The resource role of this interface (typically “control” or “experimental”). None if unset.
-
name
¶ str – Friendly name for this interface, None if unset.
-
-
class
AdNode
[source]¶ Wrapper object for a Node in a GENIv3 advertisement.
Note
In general this object is created on-demand through Advertisement objects, but you can load this object from a Node XML element by using the _fromdom classmethod.
- Attributes:
- component_id (str): Component ID URN
component_manager_id (str): Component Manager ID URN
name (str): Friendly name provided by aggregate for this resource.
exclusive (bool): True if a node can be reserved as a raw PC
available (bool): Whether this node is currently available for reservations
hardware_types (dict): Mapping of { type_name : type_slots, … }
sliver_types (set): Supported sliver type
images (dict): Mapping of { sliver_type : [supported_image_name, …], … }
shared (bool): True if currently being used as a shared resource
interfaces (list): List of
AdInterface
objects for this Node location (AdLocation
): None if not available ram (int): Currently available system RAM in megabytes. None if not available. cpu (int): Maximum Per-core CPU speed in Mhz. None if not available.
-
text
¶
-
class
Advertisement
(path=None, xml=None)[source]¶ Wrapper object for a GENIv3 XML advertisement.
Only one argument can be supplied (if both are provided path will be used)
Parameters: - path (str, unicode) – Path to XML file on disk containing an advertisement
- xml (str, unicode) – In-memory XML byte stream containing an advertisement
-
images
¶ An iterable of the unique images found in this advertisement.
-
links
¶ An indexable iterator over the AdLink objects in this advertisement.
-
nodes
¶ An indexable iterator over the AdNode objects in this advertisement.
-
routable_addresses
¶ A RoutableAddresses object containing the number of configured and available publicly routable IP addresses at this site.
An indexable iterator of the shared vlan names found in this advertisement.
-
stitchinfo
¶ Reference to the stitching info in the manifest, if present.
-
text
¶ Advertisement XML contents as a string, formatted with whitespace for easier reading.
geni.rspec.vts¶
-
class
Container
(image, name)[source]¶ -
EXTENSIONS
= [('Mount', <class 'geni.rspec.vts.Mount'>), ('HgMount', <class 'geni.rspec.vts.HgMount'>), ('SecureHgMount', <class 'geni.rspec.vts.SecureHgMount'>), ('DropboxMount', <class 'geni.rspec.vts.DropboxMount'>)]¶
-
-
class
HgMount
(name, source, mount_path, branch='default')[source]¶ Clone a public mercurial repo on a host
Parameters: - name (str) – a reference name given on the mounting AM, must be unique within a sliver
- source (str) – the URL to the source of repository
- mount_path (str) – the path where the repository would be mounted in the host filesystem
- branch (str) – the branch of the repository to be cloned on host (if any)
-
LocalCircuit
¶ alias of
geni.rspec.vts.PGCircuit
-
class
Namespaces
[source]¶ -
SDN
= http://geni.bssoftworks.com/rspec/ext/sdn/request/1¶
-
VTS
= http://geni.bssoftworks.com/rspec/ext/vts/request/1¶
-
-
class
OVSL2STP
[source]¶ -
RSTP
= 2¶
-
STP
= 1¶
-
address
¶
-
ageing_time
¶
-
forward_delay
¶
-
hello_time
¶
-
max_age
¶
-
mode
¶
-
priority
¶
-
system_id
¶
-
type
¶
-
xmit_hold_count
¶
-
-
class
Request
[source]¶ -
EXTENSIONS
= [('SSLVPNFunction', <class 'geni.rspec.vts.SSLVPNFunction'>), ('L2SSLVPNServer', <class 'geni.rspec.vts.SSLVPNFunction'>), ('L2SSLVPNClient', <class 'geni.rspec.vts.L2SSLVPNClient'>), ('Datapath', <class 'geni.rspec.vts.Datapath'>), ('Container', <class 'geni.rspec.vts.Container'>)]¶
-
resources
¶
-
geni.rspec.vtsmanifest¶
-
class
Manifest
(path=None, xml=None)[source]¶ Wrapper object for GENI XML manifest rspec, providing a pythonic API to the contained data
-
containers
¶ Iterator over all allocated containers as
ManifestContainer
objects.
-
datapaths
¶ Iterator over all allocated datapaths as
ManifestDatapath
objects.
-
findPort
(client_id)[source]¶ Get the datapath port object representing the given client_id.
Parameters: client_id (str) – client_id of the port you want to find Returns: GenericPort
or None
-
findTarget
(client_id)[source]¶ Get the container or datapath representing the given client_id in the manifest.
Parameters: client_id (str) – Requested client ID of the object you want to find Returns: ManifestDatapath
,ManifestContainer
, or None
-
functions
¶ Iterator over all allocated functions as
ManifestFunction
objects.
-
local_circuits
¶ Iterator for allocated circuit names on the local PG circuit plane (as strings).
-
pg_circuits
¶ Iterator for allocated circuit names on the local PG circuit plane (as strings).
-
ports
¶ Iterator for all datapath and container ports as subclasses of
GenericPort
objects.
-
text
¶ String representation of original XML content, with added whitespace for easier reading
-
write
(path)[source]¶ Deprecated since version 0.4: Use
geni.rspec.vtsmanifest.Manifest.writeXML()
instead.
-
geni.types¶
-
class
DPID
(val)[source]¶ Utility class representing OpenFlow Datapath IDs
This class tries to handle all likely inputs and desired outputs, while providing a single internal type to work with in the code.
String representations passed in must be represented in hex, but may contain common separators (colon, dash, and period) in any configuration.
Parameters: val (int, long, unicode, str) –
Raises: DPID.OutOfRangeError
– If the DPID represented by val is larger than the spec allows or less than zero.DPID.InputTypeError
– If val is not a supported data type
-
MAX
= 18446744073709551615L¶
-
class
EthernetMAC
(val)[source]¶ Utility class representing 48-bit Ethernet MAC Addresses
This class tries to handle all likely inputs and desired outputs, while providing a single internal type to work with in the code.
String representations passed in must be represented in hex, but may contain common separators (colon, dash, and period) in any configuration.
Parameters: val (int, long, unicode, str) –
Raises: EthernetMAC.OutOfRangeError
– If the MAC represented by val is larger than than 48-bits or less than zero.EthernetMAC.InputTypeError
– If val is not a supported data type
-
MAX
= 281474976710656¶
geni.urn¶
Simple library for manipulating URNs, particularly those used for GENI objects
-
class
Base
(*args)[source]¶ Base class representing any URN (RFC 2141).
-
__init__
(*args)[source]¶ Create a new generic URN
URNs can be initialized in one of two ways:
- Passing a single string in URN format (‘urn:NID:NSS’)
- Passing two strings (the NID and the NSS) separately
-
__repr__
()¶ x.__str__() <==> str(x)
-
-
class
GENI
(*args)[source]¶ Class representing the URNs used by GENI, which use the publicid NID and IDN (domain name) scheme, then impose some additional strucutre.
-
static
GENIURNType
(s)[source]¶ Returns the type of the object if the URN is a valid GENI URN, or None otherwise.
-
TYPE_AUTHORITY
= 'authority'¶ Aggregate Managers, Slice Authorities, etc.
-
TYPE_IMAGE
= 'image'¶ Disk images
-
TYPE_INTERFACE
= 'interface'¶ Network interfaces
-
TYPE_LINK
= 'link'¶ Point-to-point and multipoint links
-
TYPE_NODE
= 'node'¶ Physical and virtual machines
-
TYPE_SLICE
= 'slice'¶ Container for allocated resources
-
TYPE_SLIVER
= 'sliver'¶ Slice of a specific resource
-
TYPE_USER
= 'user'¶ Principal
-
__init__
(*args)[source]¶ Create a URN in the format used for GENI objects
There are four forms of this constructor:
- Pass a single string in GENI URN format (‘urn:publicid:IDN+auth+type+name’)
- Pass three arguments: the authority (a single string), the type (see the TYPE_ variables in this class), and the object name
- Pass three arguments: as #2, but the authorit(ies) are passed as a list, with the top-level authority coming first, followed by any subauthorities
- Pass three arguments: as #2, but the authority is a geni.aggregate.core.AM object, and the authority is taken from that object
Returns a list containing at least one authority string (the top level authority) and possibly additional subauthorities.
Return a single string capturing the entire authority/subauthority chain
-
static
isValidGENIURN
(s)[source]¶ Returns True if the given string is a valid URN in GENI format, False otherwise.
-
name
¶ Returns the ‘name’ part of a GENI URN.
-
type
¶ Returns the ‘type’ part of a GENI URN.
-
static
-
Make
(s)[source]¶ Returns the ‘most specific’ URN object that it can for the given string.
Specifically, returns a GENI URN if the string is in GENI format, or a Base URN if it is not. May throw a MalformedURNError exception if the string is not a valid URN at all.
geni.util¶
-
class
APIEncoder
(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, encoding='utf-8', default=None)[source]¶ -
default
(obj)[source]¶ Implement this method in a subclass such that it returns a serializable object for
o
, or calls the base implementation (to raise aTypeError
).For example, to support arbitrary iterators, you could implement default like this:
def default(self, o): try: iterable = iter(o) except TypeError: pass else: return list(iterable) # Let the base class default method raise the TypeError return JSONEncoder.default(self, o)
-
-
builddot
(manifests)[source]¶ Constructs a dotfile of the topology described in the passed in manifest list and returns it as a string.
-
checkavailrawpc
(context, am)[source]¶ Returns a list of node objects representing available raw PCs at the given aggregate.
-
deleteSliverExists
(am, context, slice)[source]¶ Attempts to delete all slivers for the given slice at the given AM, suppressing all returned errors.
-
getAdvertisements
(context, ams)[source]¶ Returns a dictionary of the form:
{ site_object : advertisement_object, ...}
Containing the advertisements for all the requested aggregates. Requests are made in parallel and the function blocks until the slowest site returns (or times out).
Warning
Particularly large advertisements may break the shared memory queue used by this function.
-
getManifests
(context, ams, slices)[source]¶ Returns a two-level dictionary of the form:
{slice_name : { site_object : manifest_object, ... }, ...}
Containing the manifests for all provided slices at all the provided sites. Requests are made in parallel and the function blocks until the slowest site returns (or times out).
-
printlogininfo
(context=None, am=None, slice=None, manifest=None)[source]¶ Prints out host login info in the format:
[client_id][username] hostname:port
If a manifest object is provided the information will be mined from this data, otherwise you must supply a context, slice, and am and a manifest will be requested from the given aggregate.
Development¶
This section of the documentation is for people wishing to contribute to the geni-lib
project, or at least
hoping to gain further insight into the existing code internals. This documentation is even less complete
than the other sections, but hopefully will be useful.
Supported Use Cases¶
This document makes a weak stab at articulating the use cases which geni-lib
is expected to support. This is in
an attempt to provide guidance on architecture decisions for new features to make sure we don’t break existing use
cases.
Exact Request Rspec Creation¶
The most basic use of geni-lib
is to write a small script whose sole purpose is to create a single rspec, from
a simple evaluation of end-to-end instructions. Such a use may involve basic parameters, but does not take input from
active querying of the federation. This provides code that is easy to edit to change behaviour, but otherwise is
indistinguishable from editing an XML file.
This use case should not be complicated.
Modular / Multi-rspec Creation¶
It is often useful to provide subtrees of resource definitions that are not complete Request objects (a specific VM disk image, memory/disk configuration and execution scripts, etc). These trees can then be composed into Request objects for novel topologies. In this vein, it is also useful to create more than one Request at a time, composing them together for issuing to separate aggregates.
Federation Querying¶
It is valuable and must be possible for users to hold in memory multiple advertisement and manifest rspec wrappers at the same time. At the very minimum the following resource tuples must be able to exist in memory at the same time:
- (site, advertisement)
- (site, slice, manifest)
At the moment any number of instances of these combinations are supported - any change to restrict these instances to being unique (e.g. only one advertisement per site at a time, etc.) will have to be well justified.
Aggregate / Clearinghouse Actions¶
Users should be able to operate on many aggregates and clearinghouses in the same script. There is a current (and likely ongoing) requirement that the user only be configured to use one control framework (and credentials) at a time. If more than one CH supports the same credentials and API, they should be able to be used concurrently, as AMs also must. Users are responsible for completing all previous credentialed federation actions before changing the CF or credentials their context refers to.
Coding Conventions¶
There is a pylint.rc
file that is tweaked for most of the project style. It is not perfect, but is a good
check to run immediately after cloning, and then right before a pull request (as pylint
will report the
difference in compliance once you have run it once). The script lint.sh
in the root directory will run
pylint
with this file over the proper directory tree.
All indentation uses spaces
Indents are 2 spaces
Exceptions that exist only for specializing names should be written on one line:
class MyCommonException(Exception): def __init__ (self, some_data): ... def __str__ (self): ... class SpecificNameOne(MyCommonException): pass class SpecificNameTwo(MyCommonException): pass
There is an example of this use case in
geni.aggregate.pgutil
Maximum line length is 132 characters
Class-level and global variables are highly discouraged
Never use bare
except:
clausesDo not use
print
Pattern Conventions¶
- Exception hierarchies are highly encouraged, as they allow users to dispatch their own scripting on the
the type of exception, rather than having a single exception with varying messages or
errno
-like mechanics. - Anything that imports
cryptography
should never be imported at module level. Always import crypto and network functionality inside functions, as this minimizes the dependencies for users who are only generating or parsing XML. - All public attribute storage types should be internally consistent for reads. If you want to support setting an underlying float storage type using a string or integer, use a property. Non-public attributes should also follow this rule unless there is a really good reason not to.
- If you can foresee a problem in the future, but don’t have time to fix it now, at least leave a
# TODO
note. - At the moment many
geni-lib
instances are re-entrant. However, while we should support this where possible, it is not required nor will it be guaranteed to users.
Philosophy Notes¶
geni-lib
is a surprisingly useful tool for end-users. However, that does not mean it is designed as a user
tool. As it is a library, constraints and “convenience” can always be wrapped around it, but they can’t be removed
if the library is too opinionated at a base level. Convenience is generally acceptable if the underlying
functionality can be directly accessed by the user should they want to avoid whatever level of “help” is being
offered.
- Do not provide Magic(tm) to users in the base API.
geni-lib
should not go out of its’ way to protect the user from building a request that we believe the be impossible to satisfy, or from passing “bad” data to AM API calls. - AM wrappers provide some basic level of sanity checking of input values (specifically for POAs in the VTS
support). This is acceptable as there is a lower-level API a user may use if they want to ignore those
checks (
geni.minigcf.amapi3
). That being said, this level of convenience should be limited. - While we support IronPython and Jython, those
geni-lib
users should still prefermultiprocessing
for parallel execution, instead ofthreading
. - Providing convenience shouldn’t extend to essentially providing new tools - it’s hard to say where this line is,
but providing too much tool-like functionality in
geni-lib
puts pressure on both the release schedule and the versioning and API stability.
Things That Don’t Belong¶
For legacy reasons, geni-lib
includes code that either doesn’t belong entirely, or is in the wrong place.
Anything enumerated here should not be referred to as an example of good practice moving forward:
geni.aggregate.*
- This package is a mess. Frameworks need to move out somewhere else, and the AM locations should not be in the code (they should be loaded from data files which can be updated independently of thegeni-lib
code).context
also doesn’t belong here, once framework support moves.geni.rspec.pg*
- The “pg” rspec is now the “GENI” rspec, and we should rename accordingly. Things that are actually part of Emulab and not the base functionality should live in extensions.