Skip to content. | Skip to navigation

Personal tools

Navigation

You are here: Home / Wiki / Rspeccreatingextension

Rspeccreatingextension

Creating an RSpec Extension

Creating an RSpec Extension

Below are the steps involved in creating a new RSpec2 extension. We use bgpmux as a running example. For a more reference-oriented description of extensions, see RSpecExtensions2.

Step 1: Choosing an RSpec Variation

There are four varieties of RSpecs: Advertisements (info to select a component), requests (which components I want), tickets (which components I got), and manifests (how do I use them?). Each variation has a different purpose. You should therefore decide which purposes your extension must fulfill.

In the case of bgpmux's, they are a special kind of node which can give an experiment access to bgp advertisements and allow the experimenter to make bgp advertisements themselves for some prefixes. So we will need to provide information about which nodes are special and which IP prefixes are available in the advertisement. And we will need to allow the user to ask for them and specify parameters in the request. That means that we want two different extensions, one for advertisements and one for requests. We will focus on creating an advertisement extension for the rest of this tutorial.

Step 2: Choose Elements to Extend

The extension mechanism allows you to add your own elements almost anywhere in the core RSpec. So you should figure out what information needs to be included and where it should go.

Since bgpmux nodes work differently than normal nodes, we need to give them a different type. This makes sure that any clients that don't know what they are, knows not to try to use them. In the advertisement, we will have to advertise the available upstream AS numbers for each bgpmux node. Since this information is only relevant if a node is being used as a bgpmux, we will add it to the type element. There are two types here. One is the hardware_type which describes the physical machine underlying the node. The other is the sliver_type which describes the sliver environment which will be given to the user. We will set the hardware type to 'pc', but the sliver type will be 'bgpmux'.

The other kind of resource that a bgpmux will use is a particular IP subnet prefix. This is a global resource that must be shared among all nodes, so we will add it as a new global resource type alongside nodes and links.

Step 3: Create a Schema

Now you should create a schema which will validate the pieces of your extension as start elements.

Here is an example schema in RelaxNG Compact Syntax:

# Your extension should have its own namespace to disambiguate it from
# others. Notice that there is a version number at the end so that if
# the bgpmux extension changes in the future, we will be able to write
# a client which can handle both versions.
default namespace = "http://www.protogeni.net/resources/rspec/ext/bgpmux/1"

# This is meant to extend the sliver_type element with information on each node.
SliverType = element sliver_type_upstream_as {
  attribute number { string }
}*

# This expends the root rspec element by specifying the global bgp
# prefix resource.
Rspec = element rspec_prefix {
  attribute address { string } &
  attribute netmask { string }
}*

# Both of the above are start elements.
start = SliverType | Rspec

Step 4: Publish the Schema

While RelaxNG Compact Syntax is more human readable, most validators require the XML Schema form. Use a tool such as trang to convert to XML Schema:

trang myschema.rnc myschema.xsd

Then host your document at a well-known web location. At that point, the extension is ready for use.

Step 5: Create Instance Documents

Now when you create an instance RSpec, you can add your new extension information and it will be validated. Clients or Component Managers which do not know about the extension will ignore it.

A final instance document for bgpmux advertisements might look like:

<?xml version="1.0" encoding="UTF-8"?>
<!-- xmlns:bgp="..." creates an identifier for this namespace which uses the namespace -->
<!-- xsi:schemaLocation="..." specifies which schema to use for which namespace. You put your well known published schema URL here. -->
<rspec xmlns="http://www.protogeni.net/resources/rspec/2"
       xmlns:bgp="http://www.protogeni.net/resources/rspec/ext/bgpmux/1"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.protogeni.net/resources/rspec/2
                           http://www.protogeni.net/resources/rspec/2/ad.xsd
                           http://www.protogeni.net/resources/rspec/ext/bgpmux/1
                           http://www.protogeni.net/resources/rspec/ext/bgpmux/1/ad.xsd"
       type="advertisement" >
  <node component_id="urn:publicid:IDN+emulab.net+bgpmux-0"
        component_manager_id="urn:publicid:IDN+emulab.net+authority+cm"
        component_name="bgpmux-0"
        exclusive="false">
<!-- The name of the sliver_type says that this is a special node which can only be used for its bgpmux facilities -->
    <sliver_type name="bgpmux">
<!-- Here is where we specify the upstream_as using our extension. This is validated using our schema because of its namespace -->
      <bgp:sliver_type_upstream_as number="2637" />
    </sliver_type>
    <hardware_type name="pc" />
    <available now="true" />
  </node>
  <node component_id="urn:publicid:IDN+emulab.net+bgpmux-1"
        component_manager_id="urn:publicid:IDN+emulab.net+authority+cm"
         component_name="bgpmux-1"
       exclusive="false">
    <sliver_type name="bgpmux">
      <bgp:sliver_type_upstream_as number="2831" />
    </sliver_type>
    <hardware_type name="pc" />
    <available now="true" />
  </node>
<!-- Our prefix is a global resource and so isn't part of any particular node. Again, note the different namespace -->
  <bgp:rspec_prefix address="168.62.16.0" netmask="21" />
</rspec>

Step 6: Write Clients Which Use Extension

Now that you have your extension created, you can create a component manager or clients which take advantage of the information inside of it. You can incrementally deploy these changes because it will be ignored and passed on by any entity which doesn't understand it. The new type designation helps ensure that a new kind of node won't be used by clients who don't know how to parameterize it or use it.