checked in design document
authorScott Baker <bakers@cs.arizona.edu>
Thu, 16 Oct 2008 07:34:29 +0000 (07:34 +0000)
committerScott Baker <bakers@cs.arizona.edu>
Thu, 16 Oct 2008 07:34:29 +0000 (07:34 +0000)
docs/Geniwrapper_Design_Docu.html [new file with mode: 0644]

diff --git a/docs/Geniwrapper_Design_Docu.html b/docs/Geniwrapper_Design_Docu.html
new file mode 100644 (file)
index 0000000..5b7df52
--- /dev/null
@@ -0,0 +1,1690 @@
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+
+<base target="_top">
+
+<style type="text/css">
+
+
+/* default css */
+
+table {
+  font-size: 1em;
+  line-height: inherit;
+}
+
+
+tr {
+  
+  text-align: left;
+  
+}
+
+
+div, address, ol, ul, li, option, select { 
+  margin-top: 0px;
+  margin-bottom: 0px;
+}
+
+p {
+  margin: 0px;
+}
+
+body {
+  margin: 6px;
+  padding: 0px;
+  font-family: Verdana, sans-serif;
+  font-size: 10pt;
+  background-color: #ffffff;
+}
+
+
+img {
+  -moz-force-broken-image-icon: 1;
+}
+
+@media screen {
+  html.pageview {
+    background-color: #f3f3f3 !important;
+  }
+
+  
+    
+  body { 
+    min-height: 1100px; 
+  }
+  * html body { 
+    height: 1100px; 
+  }
+  .pageview body {
+    border-top: 1px solid #ccc;
+    border-left: 1px solid #ccc;
+    border-right: 2px solid #bbb;
+    border-bottom: 2px solid #bbb;
+    width: 648px !important;
+    margin: 15px auto 25px;
+    padding: 40px 50px; 
+  }
+  /* IE6 */
+  * html {
+    overflow-y: scroll;
+  }
+  * html.pageview body {
+    overflow-x: auto;
+  }
+  /* Prevent repaint errors when scrolling in Safari. This "Star-7" css hack
+     targets Safari 3.1, but not WebKit nightlies and presumably Safari 4.
+     That's OK because this bug is fixed in WebKit nightlies/Safari 4 :-). */
+  html*#wys_frame::before {
+    content: '\A0';
+    position: fixed;
+    overflow: hidden;
+    width: 0;
+    height: 0;
+    top: 0;
+    left: 0;
+  }
+  
+  
+
+  
+
+
+  
+  .br_fix br:not(:-moz-last-node):not(:-moz-first-node) {
+    
+    position:relative;
+    
+    left: -1ex
+    
+  }
+  
+  .br_fix br+br {
+    position: static !important
+  }
+}
+
+h6 { font-size: 8pt }
+h5 { font-size: 8pt }
+h4 { font-size: 10pt }
+h3 { font-size: 12pt }
+h2 { font-size: 14pt }
+h1 { font-size: 18pt }
+
+blockquote {padding: 10px; border: 1px #DDD dashed }
+
+a img {border: 0}
+
+.pb {
+  border-width: 0;
+  page-break-after: always;
+  /* We don't want this to be resizeable, so enforce a width and height
+     using !important */
+  height: 1px !important;
+  width: 100% !important;
+}
+
+.editor .pb {
+  border-top: 1px dashed #C0C0C0;
+  border-bottom: 1px dashed #C0C0C0;
+}
+
+div.google_header, div.google_footer {
+  position: relative;
+  margin-top: 1em;
+  margin-bottom: 1em;
+}
+
+
+/* Table of contents */
+.editor div.writely-toc {
+  background-color: #f3f3f3;
+  border: 1px solid #ccc;
+}
+.writely-toc > ol {
+  padding-left: 3em;
+  font-weight: bold;
+}
+ol.writely-toc-subheading {
+  padding-left: 1em;
+  font-weight: normal;
+}
+/* IE6 only */
+* html writely-toc ol {
+  list-style-position: inside;
+}
+.writely-toc-none {
+  list-style-type: none;
+}
+.writely-toc-decimal {
+  list-style-type: decimal;
+}
+.writely-toc-upper-alpha {
+  list-style-type: upper-alpha;
+}
+.writely-toc-lower-alpha {
+  list-style-type: lower-alpha;
+}
+.writely-toc-upper-roman {
+  list-style-type: upper-roman;
+}
+.writely-toc-lower-roman {
+  list-style-type: lower-roman;
+}
+.writely-toc-disc {
+  list-style-type: disc;
+}
+
+/* end default css */
+
+
+  /* default print css */
+  
+  @media print {
+    body { 
+      padding: 0; 
+      margin: 0; 
+    }
+
+    div.google_header, div.google_footer {
+      display: block;
+      min-height: 0;
+      border: none;
+    }
+
+    div.google_header {
+      flow: static(header);
+    }
+
+    /* used to insert page numbers */
+    div.google_header::before, div.google_footer::before {
+      position: absolute;
+      top: 0;
+    }
+
+    div.google_footer {
+      flow: static(footer);
+    }
+
+    /* always consider this element at the start of the doc */
+    div#google_footer {
+      flow: static(footer, start);
+    }
+
+    span.google_pagenumber {
+      content: counter(page);
+    }
+
+    span.google_pagecount {
+      content: counter(pages);
+    }
+
+
+    callout.google_footnote {
+      
+      display: prince-footnote;
+      footnote-style-position: inside;
+      /* These styles keep the footnote from taking on the style of the text
+         surrounding the footnote marker. They can be overridden in the
+         document CSS. */
+      color: #000;
+      font-family: Verdana;
+      font-size: 10.0pt;
+      font-weight: normal;
+    }
+
+    /* Table of contents */
+    #WritelyTableOfContents a::after {
+      content: leader('.') target-counter(attr(href), page);
+    }
+
+    #WritelyTableOfContents a {
+      text-decoration: none;
+      color: black;
+    }
+  }
+
+  @page {
+    @top {
+      content: flow(header);
+    }
+    @bottom {
+      content: flow(footer);
+    }
+    @footnotes {
+      border-top: solid black thin;
+      padding-top: 8pt;
+    }
+  }
+  /* end default print css */
+
+/* custom css */
+
+
+/* end custom css */
+
+
+
+  /* ui edited css */
+  
+  body {
+    font-family: Verdana;
+    
+    font-size: 10.0pt;
+    line-height: normal;
+    background-color: #ffffff;
+  }
+  /* end ui edited css */
+
+
+
+/* editor CSS */
+.editor a:visited {color: #551A8B}
+.editor table.zeroBorder {border: 1px dotted gray}
+.editor table.zeroBorder td {border: 1px dotted gray}
+.editor table.zeroBorder th {border: 1px dotted gray}
+
+
+.editor div.google_header, .editor div.google_footer {
+  border: 2px #DDDDDD dashed;
+  position: static;
+  width: 100%;
+  min-height: 2em;
+}
+
+.editor .misspell {background-color: yellow}
+
+.editor .writely-comment {
+  font-size: 9pt; 
+  line-height: 1.4; 
+  padding: 1px; 
+  border: 1px dashed #C0C0C0
+}
+
+
+/* end editor CSS */
+</style>
+
+
+</head>
+
+<body onload="DoPageLoad();"
+    
+    revision="dhkdd78p_13kvrgbnfb:231">
+
+    
+    
+    
+<DIV>\r
+  <DIV>\r
+    <B>Geniwrapper Design Document</B>\r
+  </DIV>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>1.0 High Level Overview</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The purpose of Geniwrapper is to provide a Geni-like interface around the\r
+  existing planetlab infrastructure. The existing infrastructure consists of two\r
+  parts: planetlab central (PLC) and planetlab nodes. These two parts map\r
+  logically into the Geni Registry and Geni Components. However, it is not an\r
+  exact mapping. Due to the nature of planetlab, some component functionality\r
+  overlaps with PLC. For example, PLC takes an active role in managing state on\r
+  planetlab nodes, and therefore some Geni component state exists on PLC,\r
+  leading to some component APIs to exist on PLC.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Geniwrapper is comprised of the following logical modules: <I>utility\r
+  classes</I>, <I>registry wrapper</I>, <I>component wrapper</I>, and <I>command\r
+  line client</I>. Client-server communication uses a variant of XML-RPC called\r
+  the <I>Geni protocol</I>. Section 1 of this document presents a very brief\r
+  overview of each module. In-depth discussion occurs later.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Much of this design adheres to the SFA, and as such this document avoids\r
+  duplication of the information already presented in the SFA. For example, the\r
+  description of privileges, which operations are allowed by a specific\r
+  privileges, and how privileges are assigned to principals is described fully\r
+  in the SFA and is therefore not duplicated here.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  NOTE: <b>API documentation</b> is extracted from code comments automatically\r
+  and is maintained in separate files, one documentation file corresponding to\r
+  each python source file. An effort has been made to keep API documentation\r
+  separate from this document, so that the API documentation may be\r
+  self-maintaining as the code is updated.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Geniwrapper is checked into a subversion repository at\r
+  <A href=http://svn.planetlab.org/geniwrapper>http://svn.planetlab.org/geniwrapper</A>.\r
+  [TODO: verify link]\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <DIV>\r
+    <B>1.1 Utility classes</B>\r
+  </DIV>\r
+  <DIV>\r
+    &nbsp;\r
+  </DIV>\r
+  <DIV>\r
+    Utility classes include python classes that implement certificates, GIDs,\r
+    credentials, and tickets. There are also utility classes for implementing\r
+    the server and client stubs and the security protocol. The utility modules\r
+    are designed to be generally re-usable. For example, the credential\r
+    management class may be used as part of the Geni Registry, Geni Components,\r
+    and the end-user tools that interact with Geni.\r
+  </DIV>\r
+  <DIV>\r
+    &nbsp;\r
+  </DIV>\r
+  <DIV>\r
+    The&nbsp;utility classes&nbsp;are located in the\r
+    <I>util</I>&nbsp;subdirectory.\r
+  </DIV>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>1.2 The registry (PLC) wrapper</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The registry wrapper is intended to be colocated with PLC. All communication\r
+  between the registry wrapper and PLC uses the PLCAPI interface and as such,\r
+  the registry wrapper can be run on a separate machine for ease of development.\r
+  In addition to the Geni registry operations (register, update, ...), the\r
+  registry also implements component operations, such as GetTicket, that must be\r
+  located on PLC due to SFA engineering decisions.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The&nbsp;registry wrapper is located in the&nbsp;<I>registry</I> subdirectory\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  TODO: Slice interface shall be implemented in registry wrapper.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>1.3&nbsp;The component wrapper</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The component wrapper is located on planetlab nodes. It implements the\r
+  component interface, management interface, and portions of the slice\r
+  interface. Due to SFA engineering decisions, some component operations (i.e.\r
+  GetTicket) are implemented in the registry wrapper instead of the component\r
+  wrapper.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The component wrapper is located in the <I>component</I> subdirectory.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>1.4 Command line client</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The command line client exports a client interface to Geni that may be used\r
+  for testing and demonstration purposes. It allows easy invocation of Geni api\r
+  functions and dumps the results in a human-readable format.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The command line client&nbsp;is located in the&nbsp;<I>cmdline</I>\r
+  subdirectory\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>1.5 Geni Protocol</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The Geni protocol is based on XML-RPC. It is implemented primarily in the\r
+  geniserver.py and geniclient.py files located with the utility classes.\r
+  Modifications to the XML-RPC protocol include the following:\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<OL>\r
+  <LI>\r
+    The transport mechanism uses HTTPS instead of HTTP.\r
+    <LI>\r
+      HTTPS certificate verification is disabled so that custom Geni\r
+      verification based on GID can be done instead.\r
+      <LI>\r
+        When an exception occurs on the server, verbose exception information is\r
+        sent to the client, to assist debugging efforts\r
+      </LI>\r
+</OL>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Authentication:\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Authentication of the client by the server is done by using Credentials/GIDs.\r
+  Generally, each operation contains a credential as the first argument. This\r
+  credential includes the GID of the caller, which in turn contains the public\r
+  key of the caller. The server ensures that this public key matches the public\r
+  key that is being used to decrypt the HTTPS connection, thus ensuring the\r
+  caller must posess the private key that corresponds to the GID.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Authentication of the server by the client is left as an exercise for the\r
+  client. It may be done easily by specifying the server's public key when the\r
+  client create the HTTPS connection. This presumes the client knows the public\r
+  key (or GID) of the server he is trying to connect to.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>2.0 Utility Classes</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>2.1 Certificates and Keys (cert.py)</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Geniwrapper uses two crypto libraries: pyOpenSSL and M2Crypto to implement the\r
+  necessary crypto functionality. Ideally just one of these libraries would be\r
+  used, but unfortunately each of these libraries is independently lacking. The\r
+  pyOpenSSL library is missing many necessary functions, and the M2Crypto\r
+  library has crashed inside of some of the functions. The design decision is to\r
+  use pyOpenSSL whenever possible as it seems more stable, and only use M2Crypto\r
+  for those functions that are not possible in pyOpenSSL.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>2.1.1 Keys</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Public-private key pairs are implemented by the <B>Keypair </B>class. A\r
+  Keypair object may represent both a public and private key pair, or it may\r
+  represent only a public key (this usage is consistent with OpenSSL).\r
+</DIV>\r
+<P>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;\r
+</P>\r
+<DIV>\r
+  <B>2.1.2 Certificates</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The certificate class implements a general purpose X509 certificate, making\r
+  use of the appropriate pyOpenSSL or M2Crypto abstractions. It also adds\r
+  several addition features, such as the ability to maintain a chain of parent\r
+  certificates, and storage of application-specific data.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Certificates include the ability to maintain a chain of parents. Each\r
+  certificate includes a pointer to it's parent certificate. When loaded from a\r
+  file or a string, the parent chain will be automatically loaded. When saving a\r
+  certificate to a file or a string, the caller can choose whether to save the\r
+  parent certificates as well.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Example creation of a certificate:\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # create&nbsp;a key for an issuer<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; issuerKey = Keypair(create=True)<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; issuerSubject = "testissuer"\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # create a key for the certificate\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; userKey = KeyPair(create=True)\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # create the certificate, set the issuer, and\r
+  sign it\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cert = Certificate(subject="test")<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cert.set_issuer(issuerKey, issuerSubject)\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cert.set_pubkey(userKey)<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cert.sign()\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>2.1.3 Certificate Verification</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <P>\r
+    Verification examines a chain of certificates to ensure that each parent\r
+    signs the child, and that some certificate in the chain is signed by a\r
+    trusted certificate. Verification is a basic recursion:\r
+  </P>\r
+  <PRE>    if this_certificate was signed by trusted_certs:<BR>        return<BR>    else<BR>        return verify_chain(parent, trusted_certs)</PRE>\r
+</DIV>\r
+<DIV>\r
+  At each recursion, the parent is tested to ensure that it did sign the child.\r
+  If a parent did not sign a child, then an exception is thrown. If the bottom\r
+  of the recursion is reached and the certificate does not match a trusted root,\r
+  then an exception is thrown.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>\r
+  <B>2.2 GIDS (gid.py)</B>\r
+</DIV>\r
+<DIV>\r
+  <B></B>&nbsp;\r
+</DIV>\r
+<DIV>\r
+  GIDs are a derivative class of certificates and as such the&nbsp;GID class\r
+  inherits all the methods of the certificate class. A&nbsp;GID includes a tuple\r
+  of the following fields:&nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp; (uuid, hrn, public_key)\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  UUID is a unique identifier and is created by the python uuid module (or the\r
+  utility function create_uuid() in gid.py).\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  HRN is a human readable name. It is a dotted form similar to a backward domain\r
+  name. For example, planetlab.us.arizona.bakers.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  PUBLIC_KEY is the public key of the principal identified by the UUID/HRN. It\r
+  is a Keypair object as defined in the cert.py module.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  It is expected that there is a one-to-one pairing between UUIDs and HRN, but\r
+  it is uncertain how this would be inforced or if it needs to be enforced.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>2.2.1 Encoding and Decoding</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The 5 fields of the&nbsp;GID tuple are stored in the subject-alt-name field of\r
+  the X509 certificate. Two routines are included to package and unpackage these\r
+  fields: Encode() and Decode(). Encode should be called prior to signing the\r
+  GID. Decode is automatically called on demand by the various get_*()\r
+  functions.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>2.2.2 Verification of GIDs</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+Verification first performs the checks of the certificate class (verifying that\r
+each parent signs the child, etc). In addition, GIDs also confirm that the\r
+parent's HRN is a prefix of the child's HRN. Verifying these prefixes prevents a\r
+rogue authority from signing a GID for a principal that is not a member of that\r
+authority. For example, planetlab.us.arizona cannot sign a GID for\r
+planetlab.us.princeton.foo.\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>2.3 Credentials (credential.py)</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Credentials are a derivative class of certificates and as such the credential\r
+  class inherits all the methods of the certificate class. A credential includes\r
+  a tuple of the following fields:\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp; (GIDCaller, GIDObject, LifeTime, Privileges, Delegate)\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  GIDCaller identifies the holder of the credential. When a credential is\r
+  presented to a component, the security layer ensures that the client matches\r
+  the public key that is contained in GIDCaller.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  GIDObject identifies the object of the credential. This object depends upon\r
+  the type of the credential. For example, the credential for a user likely has\r
+  GIDObject == GIDCaller. Credentials for slices would include the GID of the\r
+  slice in the GIDObject field. Credentials for authorities include the GID of\r
+  the authority in the GIDObject field.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  LifeTime is the lifetime of the credential. Currently not implemented; expect\r
+  to implement it as an expiration date, and refuse credentials beyond that\r
+  date.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Privileges is a Rights object that describes the rights that are granted to\r
+  the holder of the credential.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Delegate is a True/False bit that indicates whether or not a credential can be\r
+  delegated to a different caller.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>2.3.1 Encoding and Decoding</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The 5 fields of the credential tuple are stored in the subject-alt-name field\r
+  of the X509 certificate. Two routines are included to package and unpackage\r
+  these fields: Encode() and Decode(). Encode should be called prior to signing\r
+  the credential. Decode is automatically called on demand by the various\r
+  get_*() functions.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>2.3.2 Verification of Credentials</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  In addition to the checks for ordinary certificates, verification of\r
+  credentials also ensures that the delegate bit was set by each parent in the\r
+  chain. If a delegate bit was not set, then an exception is thrown.&nbsp;Each\r
+  credential must also contain a subset of the rights of the parent credential\r
+  (i.e. a user credential cannot delegate authority rights).<BR>\r
+  <BR>\r
+  <B>2.4 Rights (rights.py)<BR>\r
+  <BR>\r
+  </B>Rights are implemented by two classes:<BR>\r
+  <BR>\r
+  Right - represents a single right<BR>\r
+  RightList - represents a list of rights A right may allow several different\r
+  operations.<BR>\r
+  <BR>\r
+  For example, the "info" right allows "listslices", "listcomponentresources",\r
+  etc.<BR>\r
+  <BR>\r
+  <B>2.5 Records (record.py)</B><BR>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The GeniRecord class implements a Geni Record. The GeniRecord class implements\r
+  an abstract interface for the record, so that a client may use records without\r
+  having to understant the underlying implementation details, such as whether\r
+  the record is realized in the registry database, a local cache, or has been\r
+  transmitted over the wire by an interface. A GeniRecord is a tuple (Name, GID,\r
+  Type, Info).\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp; Name specifies the HRN of the object GID is the GID of the object\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp; Type is user | sa | ma | slice | component Info is comprised of the\r
+  following sub-fields\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp; Pointer&nbsp;is a pointer to the record in the PL database\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp; pl_info&nbsp;is planetlab-specific info (when talking to client)\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp; geni_info = geni-specific info (when talking to client)\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The pointer is interpreted depending on the type of the record. For example,\r
+  if the type=="user", then pointer is assumed to be a person_id that indexes\r
+  into the persons table.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  A given HRN may have more than one record, provided that the records are of\r
+  different types. For example, planetlab.us.arizona may have both an SA and a\r
+  MA record, but cannot have two SA records.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>2.6 Tickets (geniticket.py)</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Similar to GIDs and Credentials, tickets also leverage the certificate object.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  A Ticket is tuple:<BR>\r
+  &nbsp;&nbsp; (gidCaller, gidObject, attributes, rspec, delegate)<BR>\r
+  <BR>\r
+  &nbsp;&nbsp;&nbsp; gidCaller = GID of the caller performing the operation<BR>\r
+  &nbsp;&nbsp;&nbsp; gidObject = GID of the slice<BR>\r
+  &nbsp;&nbsp;&nbsp; attributes = slice attributes (keys, vref, instantiation,\r
+  etc)<BR>\r
+  &nbsp;&nbsp;&nbsp; rspec = resources\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Tickets are created by invoking GetTicket() on the Registry. The slice\r
+  attributes and rspec are taken from the planetlab slice database and represent\r
+  the current state of the slice. As of yet, tickets do not include any concept\r
+  of time -- a ticket represents the state of the slice at the current time\r
+  only.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Tickets are redeemed by invoking RedeemTicket() on the Registry. The\r
+  attributes and spec are combined back into a planetlab slice record and handed\r
+  off to the node manager.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Tickets are signed by an authority and include parentage information that\r
+  traces the chain of authorities back to a trusted root.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>2.6.1 rspecs</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The rspec is currently a dictionary of {name: value} pairs. These pairs are\r
+  taken verbatim from the planetlab slice database.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The general rule that is used is that things in the slice record that do not\r
+  specifically imply a tangible resource (initscripts, keys, etc) are treated as\r
+  attributes and things that do specify a tangible resource (disk, network, etc)\r
+  are treated as the rspec.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  TODO: The definition of an rspec is evolving. It remains to reconcile the\r
+  eclipse schema with Geniwrapper. Gacks is also using another rspec format,\r
+  which may be need to be reconciled with the eclipse schema and/or geniwrapper.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <DIV>\r
+    <B>2.6.2 Encoding and Decoding</B>\r
+  </DIV>\r
+  <DIV>\r
+    &nbsp;\r
+  </DIV>\r
+  <DIV>\r
+    The 5 fields of the credential tuple are stored in the subject-alt-name\r
+    field of the X509 certificate. Two routines are included to package and\r
+    unpackage these fields: Encode() and Decode(). Encode should be called prior\r
+    to signing the ticket. Decode is automatically called on demand by the\r
+    various get_*() functions.\r
+  </DIV>\r
+  <DIV>\r
+    &nbsp;\r
+  </DIV>\r
+  <DIV>\r
+    <B>2.6.3 Verification of Tickets</B>\r
+  </DIV>\r
+  <DIV>\r
+    &nbsp;\r
+  </DIV>\r
+  <DIV>\r
+    Verification uses the standard parentage verification provided by the\r
+    certificate class. Specifically, each certificate is signed by a parent, and\r
+    some certificate must resolve to the trusted root set that is specified on\r
+    the component.\r
+  </DIV>\r
+  <DIV>\r
+    &nbsp;\r
+  </DIV>\r
+  <DIV>\r
+    Unlike credentials and GIDs, the parent of a ticket may be a degenerate\r
+    ticket that does not include the full 5-tuple (caller, object, attributes,\r
+    rspec, delegate). In such a case, the parent is just a placeholder in the\r
+    chain of authority used to convey the parentage information.\r
+  </DIV>\r
+  <DIV>\r
+    &nbsp;\r
+  </DIV>\r
+  <DIV>\r
+    Delegation of tickets is not something that is discussed in the SFA, but it\r
+    is supported in the ticket class and may be a useful feature. For example,\r
+    Alice may hold a ticket for a particular component, and delegate that ticket\r
+    to Bob. Bob could then instantiate a slice for Alice. This may be one way to\r
+    implement a slice manager.<BR>\r
+    <BR>\r
+    <B>2.7 Hierarchy of Authorities (hierarchy.py)</B><BR>\r
+    <BR>\r
+    This module implements a hierarchy of authorities and performs a similar\r
+    function as the "tree" module of the original geniwrapper prototype. An HRN\r
+    is assumed to be a string of authorities separated by dots. For example,\r
+    "planetlab.us.arizona.bakers". Each component of the HRN is a different\r
+    authority, with the last component being a leaf in the tree. Each authority\r
+    is stored in a subdirectory on the registry.<BR>\r
+    <BR>\r
+    Inside this subdirectory are several files:<BR>\r
+    *.GID - GID file<BR>\r
+    *.PKEY - private key file<BR>\r
+    *.DBINFO - database info<BR>\r
+    <BR>\r
+    The hierarchy class can be used to create GIDs, Credentials, and Tickets for\r
+    a given authority.\r
+  </DIV>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The default behavior is that all authorities contained in the hierarchy will\r
+  be located together in a single physical registry. However, this is not\r
+  strictly necessary. The *.DBINFO files contain the database information for an\r
+  authority and can easily be configured to point to other machines. How an\r
+  authority would cause the DBINFO files to be installed in the correct places\r
+  is left as a separate exercise, possibly via an out-of-band management\r
+  interface or a web page.\r
+</DIV>\r
+<DIV>\r
+  <BR>\r
+  <B>2.8 Configuration Information (config.py)</B><BR>\r
+  <BR>\r
+  This module holds configuration parameters for geniwrapper. There are two main\r
+  pieces of information that are used: the database connection and the PLCAPI\r
+  connection.<BR>\r
+  <BR>\r
+  Geniwrapper uses a MYSQL database to store records. This database may be\r
+  co-located with the PLC database, or it may be a separate database. The\r
+  following parameters define the connection to the database. Note that\r
+  Geniwrapper does not access any of the PLC databases directly via a mysql\r
+  connection; All PLC databases are accessed via PLCAPI.<BR>\r
+</DIV>\r
+<P>\r
+  Geniwrapper uses a PLCAPI connection to perform operations on the registry,\r
+  such as creating and deleting slices. This connection requires an account on\r
+  the PLC server with full administrator access. The Url parameter controls\r
+  whether the connection uses PLCAPI directly (i.e. Geniwrapper is located on\r
+  the same machine as PLC), or uses a XMLRPC connection to the PLC machine. If\r
+  you wish to use the API directly, then remove the Url field from the\r
+  dictionary.\r
+</P>\r
+<DIV>\r
+  <BR>\r
+  <B>2.8.1 Database Configuration</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Below is an example database configuration from config.py:\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  def get_default_dbinfo():<BR>\r
+  &nbsp;&nbsp;&nbsp; dbinfo={}<BR>\r
+  &nbsp;&nbsp;&nbsp; dbinfo['dbname'] = 'planetlab4'<BR>\r
+  &nbsp;&nbsp;&nbsp; dbinfo['address'] = 'localhost'<BR>\r
+  &nbsp;&nbsp;&nbsp; dbinfo['port'] = 5432<BR>\r
+  &nbsp;&nbsp;&nbsp; dbinfo['user'] = 'pgsqluser'<BR>\r
+  &nbsp;&nbsp;&nbsp; dbinfo['password'] = '4c77b272-c892-4bdf-a833-dddeeee1a2ed'\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp; return dbinfo\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  This identifies several important pieces of the database configuration. The\r
+  name specifies the database name as used by pgsql. The address is the hostname\r
+  (or ip-address) of the machine that is hosting the database. It is most likely\r
+  the local machine. Port specifies the socket port where the pgsql is\r
+  listening. The user and password authenticate Geniwrapper to the pgsql\r
+  database. In this example, an existing PLC database was used. This is not\r
+  strictly necessary as only Geni-specific information is stored in this\r
+  database. A separate database could be used, on a separate machine than PLC if\r
+  desired.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>2.8.2 PLCAPI Configuration</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Blow is an example PLCAPI configuration from config.py:\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  def get_pl_auth():<BR>\r
+  &nbsp;&nbsp;&nbsp; pl_auth = {'Username':\r
+  <A href="mailto:'root@198.0.0.132'">'root@198.0.0.132'</A>,<BR>\r
+  &nbsp;&nbsp;&nbsp; 'AuthMethod': 'password',<BR>\r
+  &nbsp;&nbsp;&nbsp; 'AuthString':&nbsp; 'root',<BR>\r
+  &nbsp;&nbsp;&nbsp; "Url":\r
+  "<A href=https://localhost/PLCAPI/>https://localhost:443/PLCAPI/</A>"<BR>\r
+  &nbsp;&nbsp;&nbsp; }\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp; return pl_auth\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The PLCAPI configuration tells Geniwrapper how to connect to PLC. There are\r
+  two options: a local connection or a remote connection. If the Url field is\r
+  defined, then a remote connection is assumed, and Geniwrapper will attempt to\r
+  connect via XMLRPC to a remote PLCAPI server. If the Url field is not defined,\r
+  then Geniwrapper will assume that PYTHONPATH includes the relevant PLCAPI\r
+  classes to use PLCAPI directly.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Username specifies the name of the PLCAPI user. It is suggested that a user\r
+  with full administrative authority be allowed. Otherwise, Geniwrapper will be\r
+  unable to lookup public keys and other information that PLC does not make\r
+  available publicly. Administrative permission is also required to create PLC\r
+  sites, users, etc. Authmethod and AuthString specify the password require to\r
+  use this account.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>3.0 The Registry Wrapper</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  This wrapper implements the Geni Registry. According to the SFA, the basic\r
+  functionality of a registry is to map HRNs into records. However, because of\r
+  the interactions between Geniwrapper and PLC, the registry does more than act\r
+  as a simple database. The registry performs API calls on PLC that create\r
+  slices, sites, users, etc., and as such may indirectly cause slices to be\r
+  instantiated on components, because components are also linked to PLC.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The mapping of Geni objects to planetlab objects is relatively\r
+  straightforward:\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp; slice&nbsp;= slice\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp; user&nbsp;= person\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;component = node\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp; sa = site\r
+</DIV>\r
+<DIV>\r
+  &nbsp;&nbsp;&nbsp; ma = site\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The one part that is slightly counterintuitive is SA and MA, which both map to\r
+  the planetlab site object. In a unified registry (a registry that serves as\r
+  both slice and component registry), these will map to the same site record in\r
+  the PLC database. However, there are two distinct Geni records, one&nbsp;for\r
+  the SA and one for the MA.&nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Registry operations generally authenticate the&nbsp;caller by credential.\r
+  There are a few exceptions, and the registry API&nbsp;documents should note\r
+  those exceptions.&nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>3.1 Registry Tools</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The registry include several additional tools that are used to manage it.\r
+  These include:\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  import.py - imports existing PLC records into the registry\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  nuke.py - deletes all Geni records\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>3.1 Bootstrapping a Registry</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  There are several items that need to be done before starting the registry.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  1) Update util/config.py to match the parameters of your PLC installation.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  2) Import the existing planetlab database, creating the appropriate geni\r
+  records. This is done by running the "import.py" tool.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  3) Create a "trusted_roots" directory and place the certificate of the root\r
+  authority in that directory. Given the defaults in import.py, this certificate\r
+  would be named "planetlab.gid". For example, mkdir trusted_roots; cp\r
+  authorities/planetlab.gid trusted_roots/\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>4.0 The Component Wrapper</B>\r
+</DIV>\r
+<DIV>\r
+  <BR>\r
+  The Geni Component Wrapper implements the Geni Component Manager. It includes\r
+  functions for redeeming tickets, starting/stopping/resetting/deleting slices,\r
+  and management such as rebooting the component.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The design of the component differs from the registry wrapper in the respect\r
+  that the component wrapper must be located physically on the planetlab node\r
+  that it is responsible for. The component wrapper interacts directly with\r
+  portions of the node manager code on the node.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>4.1 Component Authentication of Credentials</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The component authenticates credentials the same way that the registry does.\r
+  Specifically, there is a directory of trusted_root certificates (or GIDs) on\r
+  the component. Any credential presented to the component must include in it's\r
+  parentage some certificate in the set of trusted roots. Otherwise, and\r
+  exception is thrown.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>4.2 The Ticket interface</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The ticket interface is split between the Registry (PLC) and the Component.\r
+  This is due to the SFA engineering decisions, specifically&nbsp;that the\r
+  authoritative copy of planetlab state is stored on PLC and only cached on the\r
+  components. Thus, GetTicket() is implemented on the Registry, and\r
+  RedeemTicket() is implemented on the component. InstantiateSlice is not\r
+  implemented, as that operation is a combination of GetTicket/RedeemTicket and\r
+  would therefore span the Registry and Component.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>4.3 Sliver Credentials</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  A recent Geni Architecture call mentioned the need for sliver credentials. A\r
+  sliver credential would be identical to a slice credential, but would 1) only\r
+  be redeemable on a particular component, and 2) would resolve to a\r
+  trusted_root unique to that component (likely the component's GID\r
+  certificate). Sliver credentials would be returned by the RedeemTicket call\r
+  and would give the caller the permission required to start and stop the\r
+  sliver, etc.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Sliver credentials are not yet implemented, but their implementation would be\r
+  straightforward.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>4.4 Bootstrapping the Component Wrapper</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The first step is to install some required libraries on the component. These\r
+  include the m2crypto and pyopenssl libraries. Installing the actual RPMs for\r
+  these libaries on a running component proved difficult due to additional\r
+  support packages that require installation (python-devel, etc). For\r
+  development purposes, it was sufficient to copy the installed/compiled version\r
+  of the libraries from the development machine to the component.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The&nbsp;second step is to copy the files required by the component wrapper to\r
+  the node manager. They are copied to the /usr/share/Nodemanager directory. A\r
+  list of the files is contained in the copynode.sh script in the component\r
+  subdirectory.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The third step is to copy the trusted root certificates to the component. They\r
+  are stored in /usr/share/Nodemanager/trusted_roots. This should include the\r
+  certificate for the registry.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The&nbsp;fourth step is to start the component manager. This is done by\r
+  connecting to the component via SSH and running\r
+  /usr/share/Nodemanager/component.py.\r
+</DIV>\r
+<DIV>\r
+  <BR>\r
+  In a production environment, all of these steps would be integrated into the\r
+  DVD boot image for the planetlab node.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>5.0 Command-Line Interface</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  A command-line interface is provided that allows a user to interact with the\r
+  Geni Registry and Component. This command line interface is located in the\r
+  cmdline directory and can be invoked by running genicli.py. Specifying\r
+  "genicli.py help" will display a list of available commands.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>5.1 Examples</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Several examples of using the CLI are presented in the form of shell scripts\r
+  in the cmdline directory. These scripts demonstrate creating slices,\r
+  authorities, users, nodes, and getting tickets and redeeming tickets. Rather\r
+  than duplicating all of those examples here, a few short examples are\r
+  presented below.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>5.1.1 Getting a Credential</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  python ./genicli.py --username&nbsp;root --credfile None --outfile test.cred\r
+  getCredential user planetlab.us.pl.account_test\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The credential for planetlab.us.pl.account_test is retrieved and stored in the\r
+  local file test.cred. The private ket test.pkey is used when opening the\r
+  XMLRPC connection and authenticates the client. test.pkey must match the\r
+  public key that is in the GID for the user record for\r
+  planetlab.us.pl.account_test.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Sample output: (in human-readable summary)\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  CREDENTIAL planetlab.us.pl.account_test<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; privs: refresh,resolve,info<BR>\r
+  &nbsp; gidCaller:<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn:\r
+  planetlab.us.pl.account_test<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid:\r
+  276262316202422735940395896620385479122<BR>\r
+  &nbsp; gidObject:<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn:\r
+  planetlab.us.pl.account_test<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid:\r
+  276262316202422735940395896620385479122<BR>\r
+  &nbsp;&nbsp; delegate: False\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>5.1.2 Resolving a record</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  python ./genicli.py --username test resolve planetlab.us.pl.account_test\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The record for planetlab.us.pl.account_test is retrieved and printed to\r
+  stdout. The credential used comes from the local file test.cred.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Sample output: (in human-readable summary)\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  RECORD planetlab.us.pl.account_test<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn: planetlab.us.pl.account_test<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: user<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gid:<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn:\r
+  planetlab.us.pl.account_test<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid:\r
+  276262316202422735940395896620385479122<BR>\r
+  &nbsp;&nbsp;&nbsp; pointer: 6<BR>\r
+  &nbsp; geni_info:<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; email :\r
+  <A href=mailto:test@test.com>test@test.com</A><BR>\r
+  &nbsp;&nbsp;&nbsp; pl_info:<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bio : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; first_name : test<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last_name : account<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last_updated : 1222497672<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; roles : ['user']<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; title : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; key_ids : [1]<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enabled : True<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; slice_ids : [24]<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; phone : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; peer_person_id : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; role_ids : [30]<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; person_id : 6<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; date_created : 1219083140<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; site_ids : [1]<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; peer_id : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; email :\r
+  <A href=mailto:test@test.com>test@test.com</A>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>5.1.3 Updating a record</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  python ./genicli.py --username test update user planetlab.us.pl.account_test\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  The record for planetlab.us.pl.account_test is updated. The credential used\r
+  comes from the local file test.cred. No changes are specified, so the only\r
+  thing that should be updated is the expiration time.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  <B>5.1.4 Resolving an authority</B>\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  An authority is an example of an HRN that might resolve to two different\r
+  records, an SA and a MA record.\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  python ./genicli.py --username test resolve planetlab.us.pl\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  Sample Output: (in human readable summary)\r
+</DIV>\r
+<DIV>\r
+  &nbsp;\r
+</DIV>\r
+<DIV>\r
+  RECORD planetlab.us.pl<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn: planetlab.us.pl<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: sa<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gid:<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn: planetlab.us.pl<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid:\r
+  294786197975089072547582920862317666209<BR>\r
+  &nbsp;&nbsp;&nbsp; pointer: 1<BR>\r
+  &nbsp; geni_info:<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pi :\r
+  ['planetlab.us.pl.Administrator_Default']<BR>\r
+  &nbsp;&nbsp;&nbsp; pl_info:<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last_updated : 1224136003<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node_ids : [1]<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; site_id : 1<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pcu_ids : []<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max_slices : 100<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ext_consortium_id : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; peer_site_id : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; abbreviated_name : plctest<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid :\r
+  230749975723590978208303655640765327534<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; person_ids : [2, 4, 6]<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; slice_ids : [24, 1, 2]<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; latitude : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; peer_id : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max_slivers : 1000<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is_public : False<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; address_ids : []<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name : plctest Central<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url :\r
+  <A href=http://198.0.0.132/>http://198.0.0.132/</A><BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enabled : True<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; longitude : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; login_base : pl<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; date_created : 1209428329<BR>\r
+  RESULT:<BR>\r
+  RECORD planetlab.us.pl<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn: planetlab.us.pl<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: ma<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gid:<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn: planetlab.us.pl<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid:\r
+  294786197975089072547582920862317666209<BR>\r
+  &nbsp;&nbsp;&nbsp; pointer: 1<BR>\r
+  &nbsp; geni_info:<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; operator : []<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; owner :\r
+  ['planetlab.us.pl.Administrator_Default']<BR>\r
+  &nbsp;&nbsp;&nbsp; pl_info:<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last_updated : 1224136003<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node_ids : [1]<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; site_id : 1<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pcu_ids : []<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max_slices : 100<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ext_consortium_id : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; peer_site_id : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; abbreviated_name : plctest<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid :\r
+  230749975723590978208303655640765327534<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; person_ids : [2, 4, 6]<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; slice_ids : [24, 1, 2]<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; latitude : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; peer_id : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max_slivers : 1000<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is_public : False<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; address_ids : []<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name : plctest Central<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url :\r
+  <A href=http://198.0.0.132/>http://198.0.0.132/</A><BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enabled : True<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; longitude : None<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; login_base : pl<BR>\r
+  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; date_created : 1209428329\r
+</DIV>\r
+<BR>
\ No newline at end of file