2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
8 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
12 <style type="text/css">
30 div, address, ol, ul, li, option, select {
42 font-family: Verdana, sans-serif;
44 background-color: #ffffff;
49 -moz-force-broken-image-icon: 1;
54 background-color: #f3f3f3 !important;
66 border-top: 1px solid #ccc;
67 border-left: 1px solid #ccc;
68 border-right: 2px solid #bbb;
69 border-bottom: 2px solid #bbb;
70 width: 648px !important;
71 margin: 15px auto 25px;
78 * html.pageview body {
81 /* Prevent repaint errors when scrolling in Safari. This "Star-7" css hack
82 targets Safari 3.1, but not WebKit nightlies and presumably Safari 4.
83 That's OK because this bug is fixed in WebKit nightlies/Safari 4 :-). */
84 html*#wys_frame::before {
97 .writely-callout-data {
100 .writely-footnote-marker {
101 background-image: url('MISSING');
102 background-color: transparent;
103 background-repeat: no-repeat;
109 .editor .writely-footnote-marker {
112 .writely-footnote-marker-highlight {
113 background-position: -15px 0;
115 .writely-footnote-hide-selection ::-moz-selection, .writely-footnote-hide-selection::-moz-selection {
116 background: transparent;
118 .writely-footnote-hide-selection ::selection, .writely-footnote-hide-selection::selection {
119 background: transparent;
121 .writely-footnote-hide-selection {
126 .editor .writely-comment-yellow {
127 background-color: #FF9;
128 background-position: -240px 0;
130 .editor .writely-comment-yellow-hover {
131 background-color: #FF0;
132 background-position: -224px 0;
134 .editor .writely-comment-blue {
135 background-color: #C0D3FF;
136 background-position: -16px 0;
138 .editor .writely-comment-blue-hover {
139 background-color: #6292FE;
140 background-position: 0 0;
142 .editor .writely-comment-orange {
143 background-color: #FFDEAD;
144 background-position: -80px 0;
146 .editor .writely-comment-orange-hover {
147 background-color: #F90;
148 background-position: -64px 0;
150 .editor .writely-comment-green {
151 background-color: #99FBB3;
152 background-position: -48px 0;
154 .editor .writely-comment-green-hover {
155 background-color: #00F442;
156 background-position: -32px 0;
158 .editor .writely-comment-cyan {
159 background-color: #CFF;
160 background-position: -208px 0;
162 .editor .writely-comment-cyan-hover {
163 background-color: #0FF;
164 background-position: -192px 0;
166 .editor .writely-comment-purple {
167 background-color: #EBCCFF;
168 background-position: -144px 0;
170 .editor .writely-comment-purple-hover {
171 background-color: #90F;
172 background-position: -128px 0;
174 .editor .writely-comment-magenta {
175 background-color: #FCF;
176 background-position: -112px 0;
178 .editor .writely-comment-magenta-hover {
179 background-color: #F0F;
180 background-position: -96px 0;
182 .editor .writely-comment-red {
183 background-color: #FFCACA;
184 background-position: -176px 0;
186 .editor .writely-comment-red-hover {
187 background-color: #FF7A7A;
188 background-position: -160px 0;
191 .editor .writely-comment-marker {
192 background-image: url('MISSING');
193 background-color: transparent;
195 background-repeat: no-repeat;
198 -moz-user-select: none;
201 .editor .writely-comment-hidden {
205 .editor .writely-comment-marker-hidden {
210 .editor .writely-comment-none {
212 filter:progid:DXImageTransform.Microsoft.Alpha(opacity=20);
215 .editor .writely-comment-none-hover {
217 filter:progid:DXImageTransform.Microsoft.Alpha(opacity=20);
224 .br_fix br:not(:-moz-last-node):not(:-moz-first-node) {
233 position: static !important
237 h6 { font-size: 8pt }
238 h5 { font-size: 8pt }
239 h4 { font-size: 10pt }
240 h3 { font-size: 12pt }
241 h2 { font-size: 14pt }
242 h1 { font-size: 18pt }
244 blockquote {padding: 10px; border: 1px #DDD dashed }
250 page-break-after: always;
251 /* We don't want this to be resizeable, so enforce a width and height
253 height: 1px !important;
254 width: 100% !important;
258 border-top: 1px dashed #C0C0C0;
259 border-bottom: 1px dashed #C0C0C0;
262 div.google_header, div.google_footer {
269 /* Table of contents */
270 .editor div.writely-toc {
271 background-color: #f3f3f3;
272 border: 1px solid #ccc;
278 ol.writely-toc-subheading {
283 * html writely-toc ol {
284 list-style-position: inside;
287 list-style-type: none;
289 .writely-toc-decimal {
290 list-style-type: decimal;
292 .writely-toc-upper-alpha {
293 list-style-type: upper-alpha;
295 .writely-toc-lower-alpha {
296 list-style-type: lower-alpha;
298 .writely-toc-upper-roman {
299 list-style-type: upper-roman;
301 .writely-toc-lower-roman {
302 list-style-type: lower-roman;
305 list-style-type: disc;
308 /* end default css */
311 /* default print css */
319 div.google_header, div.google_footer {
326 flow: static(header);
329 /* used to insert page numbers */
330 div.google_header::before, div.google_footer::before {
336 flow: static(footer);
339 /* always consider this element at the start of the doc */
341 flow: static(footer, start);
344 span.google_pagenumber {
345 content: counter(page);
348 span.google_pagecount {
349 content: counter(pages);
353 callout.google_footnote {
355 display: prince-footnote;
356 footnote-style-position: inside;
357 /* These styles keep the footnote from taking on the style of the text
358 surrounding the footnote marker. They can be overridden in the
361 font-family: Verdana;
366 /* Table of contents */
367 #WritelyTableOfContents a::after {
368 content: leader('.') target-counter(attr(href), page);
371 #WritelyTableOfContents a {
372 text-decoration: none;
379 content: flow(header);
382 content: flow(footer);
385 border-top: solid black thin;
389 /* end default print css */
402 font-family: Verdana;
406 background-color: #ffffff;
408 /* end ui edited css */
413 .editor a:visited {color: #551A8B}
414 .editor table.zeroBorder {border: 1px dotted gray}
415 .editor table.zeroBorder td {border: 1px dotted gray}
416 .editor table.zeroBorder th {border: 1px dotted gray}
419 .editor div.google_header, .editor div.google_footer {
420 border: 2px #DDDDDD dashed;
426 .editor .misspell {background-color: yellow}
428 .editor .writely-comment {
432 border: 1px dashed #C0C0C0
442 <body onload="DoPageLoad();"
444 revision="dhkdd78p_13kvrgbnfb:273">
451 <b>Geniwrapper Design Document</b>
\r
458 <b>1.0 High Level Overview</b>
\r
464 The purpose of Geniwrapper is to provide a Geni-like interface around the
\r
465 existing planetlab infrastructure. The existing infrastructure consists of two
\r
466 parts: planetlab central (PLC) and planetlab nodes. Geni consists of the
\r
467 Registry, Slice, and Component Management interfaces. PLC and Planetlab
\r
468 Nodes can be mapped into the Geni Registry and Geni Component
\r
469 interfaces respectively. However, due to the nature of
\r
470 planetlab, the Geni slice interface overlaps with PLC and
\r
471 planetlab nodes. For example, PLC takes an active role in managing state on
\r
472 planetlab nodes, and therefore some Geni component state exists on PLC,
\r
473 leading to some slice interface APIs to exist on PLC.
\r
479 Geniwrapper is comprised of the following logical modules: <i>utility
\r
480 classes</i>, <i>plc wrapper</i>, <i>component wrapper</i>, and <i>command
\r
481 line client</i>. Client-server communication uses a variant of XML-RPC called
\r
482 the <i>Geni protocol</i>. Section 1 of this document presents a very brief
\r
483 overview of each module. In-depth discussion occurs later.
\r
489 Much of this design adheres to the SFA, and as such this document avoids
\r
490 duplication of the information already presented in the SFA. For example, the
\r
491 description of privileges, which operations are allowed by a specific
\r
492 privileges, and how privileges are assigned to principals is described fully
\r
493 in the SFA and is therefore not duplicated here.
\r
499 NOTE: <b>API documentation</b> is extracted from code comments automatically
\r
500 and is maintained in separate files, one documentation file corresponding to
\r
501 each python source file. An effort has been made to keep API documentation
\r
502 separate from this document, so that the API documentation may be
\r
503 self-maintaining as the code is updated.
\r
509 Geniwrapper is checked into a subversion repository at
\r
510 <a href=http://svn.planetlab.org/geniwrapper>http://svn.planetlab.org/geniwrapper</a>.
\r
511 [TODO: verify link]
\r
518 <b>1.1 Utility classes</b>
\r
524 Utility classes include python classes that implement certificates, GIDs,
\r
525 credentials, and tickets. There are also utility classes for implementing
\r
526 the server and client stubs and the security protocol. The utility modules
\r
527 are designed to be generally re-usable. For example, the credential
\r
528 management class may be used as part of the Geni Registry, Geni Components,
\r
529 and the end-user tools that interact with Geni.
\r
535 The utility classes are located in the
\r
536 <i>util</i> subdirectory.
\r
543 <b>1.2 PLC wrapper</b>
\r
549 The plc wrapper is intended to be colocated with PLC. All communication
\r
550 between the plc wrapper and PLC uses the PLCAPI interface and as such,
\r
551 the plc wrapper can be run on a separate machine for ease of development.
\r
552 In addition to the Geni registry operations (register, update, ...),
\r
553 the plc wrapper also implements slice operations, such as GetTicket, that
\r
554 must be located on PLC due to SFA engineering decisions.
\r
560 The plc wrapper is located in the <i>plc</i> subdirectory.
\r
566 TODO: Slice interface shall be implemented in plc wrapper.
\r
572 <b>1.3 The component wrapper</b>
\r
578 The component wrapper is located on planetlab nodes. It implements
\r
579 the slice interface, and the component management interface. Due to SFA
\r
580 engineering decisions, some slice operations (i.e. GetTicket) are
\r
581 implemented in the plc wrapper and are unavaiable on
\r
582 the component wrapper.
\r
588 The component wrapper is located in the <i>component</i> subdirectory.
\r
594 <b>1.4 Command line client</b>
\r
600 The command line client exports a client interface to Geni that may be used
\r
601 for testing and demonstration purposes. It allows easy invocation of Geni api
\r
602 functions and dumps the results in a human-readable format.
\r
608 The command line client is located in the <i>cmdline</i>
\r
615 <b>1.5 Geni Protocol</b>
\r
621 The Geni protocol is based on XML-RPC. It is implemented primarily in the
\r
622 geniserver.py and geniclient.py files located with the utility classes.
\r
623 Modifications to the XML-RPC protocol include the following:
\r
630 The transport mechanism uses HTTPS instead of HTTP.
\r
633 HTTPS certificate verification is disabled so that custom Geni verification
\r
634 based on GID can be done instead.
\r
637 When an exception occurs on the server, verbose exception information is
\r
638 sent to the client, to assist debugging efforts
\r
651 Authentication of the client by the server is done by using Credentials/GIDs.
\r
652 Generally, each operation contains a credential as the first argument. This
\r
653 credential includes the GID of the caller, which in turn contains the public
\r
654 key of the caller. The server ensures that this public key matches the public
\r
655 key that is being used to decrypt the HTTPS connection, thus ensuring the
\r
656 caller must posess the private key that corresponds to the GID.
\r
662 Authentication of the server by the client is left as an exercise for the
\r
663 client. It may be done easily by specifying the server's public key when the
\r
664 client create the HTTPS connection. This presumes the client knows the public
\r
665 key (or GID) of the server he is trying to connect to.
\r
669 <b>1.6 Extending Geniwrapper to other environments</b><br>
\r
671 The PLC Wrapper and Component Wrapper are implemented to work on top of the
\r
672 Planetlab environment, but Geniwrapper was designed specifically to be easy to
\r
673 port to other platforms or environments. The utility classes are generally
\r
674 planetlab-independent, and the planetlab specific code is located in the
\r
675 directories that house the PLC and Component wrappers. The utility classes
\r
676 implement most of the complexity of the Geni wrapper, allowing the PLC and
\r
677 Component wrappers to be relatively lightweight.<br>
\r
679 For example, looking at the code for the stop_slice function implemented in
\r
680 the component wrapper:<br>
\r
682 def stop_slice(self, cred_str):<br>
\r
683
\r
684 self.decode_authentication(cred_str, "stopslice")<br>
\r
685 slicename =
\r
686 hrn_to_pl_slicename(self.object_gid.get_hrn())<br>
\r
687 print "stopslice:", slicename<br>
\r
688 accounts.get(slicename).stop()<br>
\r
690 The hrn_to_pl_slicename() function and accounts() class are planetlab-specific
\r
691 and implement the actual stopping of the slice. The remaining code that
\r
692 implements the Geni protocol, decodes credentials and authentication, etc., is
\r
693 planetlab-independent, and could be easily used in a non-planetlab
\r
698 <b>2.0 Utility Classes</b>
\r
704 <b>2.1 Certificates and Keys (cert.py)</b>
\r
710 Geniwrapper uses two crypto libraries: pyOpenSSL and M2Crypto to implement the
\r
711 necessary crypto functionality. Ideally just one of these libraries would be
\r
712 used, but unfortunately each of these libraries is independently lacking. The
\r
713 pyOpenSSL library is missing many necessary functions, and the M2Crypto
\r
714 library has crashed inside of some of the functions. The design decision is to
\r
715 use pyOpenSSL whenever possible as it seems more stable, and only use M2Crypto
\r
716 for those functions that are not possible in pyOpenSSL.
\r
728 Public-private key pairs are implemented by the <b>Keypair </b>class. A
\r
729 Keypair object may represent both a public and private key pair, or it may
\r
730 represent only a public key (this usage is consistent with OpenSSL).
\r
733
\r
736 <b>2.1.2 Certificates</b>
\r
742 The certificate class implements a general purpose X509 certificate, making
\r
743 use of the appropriate pyOpenSSL or M2Crypto abstractions. It also adds
\r
744 several addition features, such as the ability to maintain a chain of parent
\r
745 certificates, and storage of application-specific data.
\r
751 Certificates include the ability to maintain a chain of parents. Each
\r
752 certificate includes a pointer to it's parent certificate. When loaded from a
\r
753 file or a string, the parent chain will be automatically loaded. When saving a
\r
754 certificate to a file or a string, the caller can choose whether to save the
\r
755 parent certificates as well.
\r
761 Example creation of a certificate:
\r
767 # create a key for an issuer<br>
\r
768 issuerKey = Keypair(create=True)<br>
\r
769 issuerSubject = "testissuer"
\r
775 # create a key for the certificate
\r
778 userKey = KeyPair(create=True)
\r
784 # create the certificate, set the issuer, and
\r
788 cert = Certificate(subject="test")<br>
\r
789 cert.set_issuer(issuerKey, issuerSubject)
\r
792 cert.set_pubkey(userKey)<br>
\r
793 cert.sign()
\r
799 <b>2.1.3 Certificate Verification</b>
\r
806 Verification examines a chain of certificates to ensure that each parent
\r
807 signs the child, and that some certificate in the chain is signed by a
\r
808 trusted certificate. Verification is a basic recursion:
\r
810 <pre> if this_certificate was signed by trusted_certs:<br> return<br> else<br> return verify_chain(parent, trusted_certs)</pre>
\r
813 At each recursion, the parent is tested to ensure that it did sign the child.
\r
814 If a parent did not sign a child, then an exception is thrown. If the bottom
\r
815 of the recursion is reached and the certificate does not match a trusted root,
\r
816 then an exception is thrown.
\r
819 <br>
\r
820 <b>2.2 GIDS (gid.py)</b>
\r
826 GIDs are a derivative class of certificates and as such the GID class
\r
827 inherits all the methods of the certificate class. A GID includes a tuple
\r
828 of the following fields:
\r
834 (uuid, hrn, public_key)
\r
840 UUID is a unique identifier and is created by the python uuid module (or the
\r
841 utility function create_uuid() in gid.py).
\r
847 HRN is a human readable name. It is a dotted form similar to a backward domain
\r
848 name. For example, planetlab.us.arizona.bakers.
\r
854 PUBLIC_KEY is the public key of the principal identified by the UUID/HRN. It
\r
855 is a Keypair object as defined in the cert.py module.
\r
861 It is expected that there is a one-to-one pairing between UUIDs and HRN, but
\r
862 it is uncertain how this would be inforced or if it needs to be enforced.
\r
868 <b>2.2.1 Encoding and Decoding</b>
\r
874 The 5 fields of the GID tuple are stored in the subject-alt-name field of
\r
875 the X509 certificate. Two routines are included to package and unpackage these
\r
876 fields: Encode() and Decode(). Encode should be called prior to signing the
\r
877 GID. Decode is automatically called on demand by the various get_*()
\r
884 <b>2.2.2 Verification of GIDs</b>
\r
889 Verification first performs the checks of the certificate class (verifying that
\r
890 each parent signs the child, etc). In addition, GIDs also confirm that the
\r
891 parent's HRN is a prefix of the child's HRN. Verifying these prefixes prevents a
\r
892 rogue authority from signing a GID for a principal that is not a member of that
\r
893 authority. For example, planetlab.us.arizona cannot sign a GID for
\r
894 planetlab.us.princeton.foo.
\r
899 <b>2.3 Credentials (credential.py)</b>
\r
905 Credentials are a derivative class of certificates and as such the credential
\r
906 class inherits all the methods of the certificate class. A credential includes
\r
907 a tuple of the following fields:
\r
913 (GIDCaller, GIDObject, LifeTime, Privileges, Delegate)
\r
919 GIDCaller identifies the holder of the credential. When a credential is
\r
920 presented to a component, the security layer ensures that the client matches
\r
921 the public key that is contained in GIDCaller.
\r
927 GIDObject identifies the object of the credential. This object depends upon
\r
928 the type of the credential. For example, the credential for a user likely has
\r
929 GIDObject == GIDCaller. Credentials for slices would include the GID of the
\r
930 slice in the GIDObject field. Credentials for authorities include the GID of
\r
931 the authority in the GIDObject field.
\r
937 LifeTime is the lifetime of the credential. Currently not implemented; expect
\r
938 to implement it as an expiration date, and refuse credentials beyond that
\r
945 Privileges is a Rights object that describes the rights that are granted to
\r
946 the holder of the credential.
\r
952 Delegate is a True/False bit that indicates whether or not a credential can be
\r
953 delegated to a different caller.
\r
959 <b>2.3.1 Encoding and Decoding</b>
\r
965 The 5 fields of the credential tuple are stored in the subject-alt-name field
\r
966 of the X509 certificate. Two routines are included to package and unpackage
\r
967 these fields: Encode() and Decode(). Encode should be called prior to signing
\r
968 the credential. Decode is automatically called on demand by the various
\r
975 <b>2.3.2 Verification of Credentials</b>
\r
981 In addition to the checks for ordinary certificates, verification of
\r
982 credentials also ensures that the delegate bit was set by each parent in the
\r
983 chain. If a delegate bit was not set, then an exception is thrown. Each
\r
984 credential must also contain a subset of the rights of the parent credential
\r
985 (i.e. a user credential cannot delegate authority rights).<br>
\r
987 <b>2.4 Rights (rights.py)<br>
\r
989 </b>Rights are implemented by two classes:<br>
\r
991 Right - represents a single right<br>
\r
992 RightList - represents a list of rights A right may allow several different
\r
995 For example, the "info" right allows "listslices", "listcomponentresources",
\r
998 <b>2.5 Records (record.py)</b><br>
\r
1004 The GeniRecord class implements a Geni Record. The GeniRecord class implements
\r
1005 an abstract interface for the record, so that a client may use records without
\r
1006 having to understant the underlying implementation details, such as whether
\r
1007 the record is realized in the registry database, a local cache, or has been
\r
1008 transmitted over the wire by an interface. A GeniRecord is a tuple (Name, GID,
\r
1015 Name specifies the HRN of the object GID is the GID of the object
\r
1021 Type is user | sa | ma | slice | component Info is comprised of the
\r
1022 following sub-fields
\r
1028 Pointer is a pointer to the record in the PL database
\r
1034 pl_info is planetlab-specific info (when talking to client)
\r
1040 geni_info = geni-specific info (when talking to client)
\r
1046 The pointer is interpreted depending on the type of the record. For example,
\r
1047 if the type=="user", then pointer is assumed to be a person_id that indexes
\r
1048 into the persons table.
\r
1054 A given HRN may have more than one record, provided that the records are of
\r
1055 different types. For example, planetlab.us.arizona may have both an SA and a
\r
1056 MA record, but cannot have two SA records.
\r
1062 <b>2.6 Tickets (geniticket.py)</b>
\r
1068 Similar to GIDs and Credentials, tickets also leverage the certificate object.
\r
1074 A Ticket is tuple:<br>
\r
1075 (gidCaller, gidObject, attributes, rspec, delegate)<br>
\r
1077 gidCaller = GID of the caller performing the operation<br>
\r
1078 gidObject = GID of the slice<br>
\r
1079 attributes = slice attributes (keys, vref, instantiation,
\r
1081 rspec = resources
\r
1087 Tickets are created by invoking GetTicket() on the Registry. The slice
\r
1088 attributes and rspec are taken from the planetlab slice database and represent
\r
1089 the current state of the slice. As of yet, tickets do not include any concept
\r
1090 of time -- a ticket represents the state of the slice at the current time
\r
1097 Tickets are redeemed by invoking RedeemTicket() on the Registry. The
\r
1098 attributes and spec are combined back into a planetlab slice record and handed
\r
1099 off to the node manager.
\r
1105 Tickets are signed by an authority and include parentage information that
\r
1106 traces the chain of authorities back to a trusted root.
\r
1112 <b>2.6.1 rspecs</b>
\r
1118 The rspec is currently a dictionary of {name: value} pairs. These pairs are
\r
1119 taken verbatim from the planetlab slice database.
\r
1125 The general rule that is used is that things in the slice record that do not
\r
1126 specifically imply a tangible resource (initscripts, keys, etc) are treated as
\r
1127 attributes and things that do specify a tangible resource (disk, network, etc)
\r
1128 are treated as the rspec.
\r
1134 TODO: The definition of an rspec is evolving. It remains to reconcile the
\r
1135 eclipse schema with Geniwrapper. Gacks is also using another rspec format,
\r
1136 which may be need to be reconciled with the eclipse schema and/or geniwrapper.
\r
1143 <b>2.6.2 Encoding and Decoding</b>
\r
1149 The 5 fields of the credential tuple are stored in the subject-alt-name
\r
1150 field of the X509 certificate. Two routines are included to package and
\r
1151 unpackage these fields: Encode() and Decode(). Encode should be called prior
\r
1152 to signing the ticket. Decode is automatically called on demand by the
\r
1153 various get_*() functions.
\r
1159 <b>2.6.3 Verification of Tickets</b>
\r
1165 Verification uses the standard parentage verification provided by the
\r
1166 certificate class. Specifically, each certificate is signed by a parent, and
\r
1167 some certificate must resolve to the trusted root set that is specified on
\r
1174 Unlike credentials and GIDs, the parent of a ticket may be a degenerate
\r
1175 ticket that does not include the full 5-tuple (caller, object, attributes,
\r
1176 rspec, delegate). In such a case, the parent is just a placeholder in the
\r
1177 chain of authority used to convey the parentage information.
\r
1183 Delegation of tickets is not something that is discussed in the SFA, but it
\r
1184 is supported in the ticket class and may be a useful feature. For example,
\r
1185 Alice may hold a ticket for a particular component, and delegate that ticket
\r
1186 to Bob. Bob could then instantiate a slice for Alice. This may be one way to
\r
1187 implement a slice manager.<br>
\r
1189 <b>2.7 Hierarchy of Authorities (hierarchy.py)</b><br>
\r
1191 This module implements a hierarchy of authorities and performs a similar
\r
1192 function as the "tree" module of the original geniwrapper prototype. An HRN
\r
1193 is assumed to be a string of authorities separated by dots. For example,
\r
1194 "planetlab.us.arizona.bakers". Each component of the HRN is a different
\r
1195 authority, with the last component being a leaf in the tree. Each authority
\r
1196 is stored in a subdirectory on the registry.<br>
\r
1198 Inside this subdirectory are several files:<br>
\r
1199 *.GID - GID file<br>
\r
1200 *.PKEY - private key file<br>
\r
1201 *.DBINFO - database info<br>
\r
1203 The hierarchy class can be used to create GIDs, Credentials, and Tickets for
\r
1204 a given authority.
\r
1211 The default behavior is that all authorities contained in the hierarchy will
\r
1212 be located together in a single physical registry. However, this is not
\r
1213 strictly necessary. The *.DBINFO files contain the database information for an
\r
1214 authority and can easily be configured to point to other machines. How an
\r
1215 authority would cause the DBINFO files to be installed in the correct places
\r
1216 is left as a separate exercise, possibly via an out-of-band management
\r
1217 interface or a web page.
\r
1221 <b>2.8 Configuration Information (config.py)</b><br>
\r
1223 This module holds configuration parameters for geniwrapper. There are two main
\r
1224 pieces of information that are used: the database connection and the PLCAPI
\r
1227 Geniwrapper uses a MYSQL database to store records. This database may be
\r
1228 co-located with the PLC database, or it may be a separate database. The
\r
1229 following parameters define the connection to the database. Note that
\r
1230 Geniwrapper does not access any of the PLC databases directly via a mysql
\r
1231 connection; All PLC databases are accessed via PLCAPI.<br>
\r
1234 Geniwrapper uses a PLCAPI connection to perform operations on the registry,
\r
1235 such as creating and deleting slices. This connection requires an account on
\r
1236 the PLC server with full administrator access. The Url parameter controls
\r
1237 whether the connection uses PLCAPI directly (i.e. Geniwrapper is located on
\r
1238 the same machine as PLC), or uses a XMLRPC connection to the PLC machine. If
\r
1239 you wish to use the API directly, then remove the Url field from the
\r
1244 <b>2.8.1 Database Configuration</b>
\r
1250 Below is an example database configuration from config.py:
\r
1256 def get_default_dbinfo():<br>
\r
1257 dbinfo={}<br>
\r
1258 dbinfo['dbname'] = 'planetlab4'<br>
\r
1259 dbinfo['address'] = 'localhost'<br>
\r
1260 dbinfo['port'] = 5432<br>
\r
1261 dbinfo['user'] = 'pgsqluser'<br>
\r
1262 dbinfo['password'] = '4c77b272-c892-4bdf-a833-dddeeee1a2ed'
\r
1265 return dbinfo
\r
1271 This identifies several important pieces of the database configuration. The
\r
1272 name specifies the database name as used by pgsql. The address is the hostname
\r
1273 (or ip-address) of the machine that is hosting the database. It is most likely
\r
1274 the local machine. Port specifies the socket port where the pgsql is
\r
1275 listening. The user and password authenticate Geniwrapper to the pgsql
\r
1276 database. In this example, an existing PLC database was used. This is not
\r
1277 strictly necessary as only Geni-specific information is stored in this
\r
1278 database. A separate database could be used, on a separate machine than PLC if
\r
1285 <b>2.8.2 PLCAPI Configuration</b>
\r
1291 Blow is an example PLCAPI configuration from config.py:
\r
1297 def get_pl_auth():<br>
\r
1298 pl_auth = {'Username':
\r
1299 <a href=mailto:%27root@198.0.0.132%27>'root@198.0.0.132'</a>,<br>
\r
1300 'AuthMethod': 'password',<br>
\r
1301 'AuthString': 'root',<br>
\r
1302 "Url":
\r
1303 "<a href=https://localhost/PLCAPI/>https://localhost:443/PLCAPI/</a>"<br>
\r
1304 }
\r
1307 return pl_auth
\r
1313 The PLCAPI configuration tells Geniwrapper how to connect to PLC. There are
\r
1314 two options: a local connection or a remote connection. If the Url field is
\r
1315 defined, then a remote connection is assumed, and Geniwrapper will attempt to
\r
1316 connect via XMLRPC to a remote PLCAPI server. If the Url field is not defined,
\r
1317 then Geniwrapper will assume that PYTHONPATH includes the relevant PLCAPI
\r
1318 classes to use PLCAPI directly.
\r
1324 Username specifies the name of the PLCAPI user. It is suggested that a user
\r
1325 with full administrative authority be allowed. Otherwise, Geniwrapper will be
\r
1326 unable to lookup public keys and other information that PLC does not make
\r
1327 available publicly. Administrative permission is also required to create PLC
\r
1328 sites, users, etc. Authmethod and AuthString specify the password require to
\r
1335 <b>2.9 GeniServer and GeniClient</b>
\r
1341 Two files, geniserver.py and geniclient.py implement a basic Geni server and
\r
1348 Geniserver forms the basis of any server that exports a Geni interface.
\r
1349 Examples include the PLC and Component wrappers. The Geniserver class itself
\r
1350 does not export any useful API functions other than a "noop" function that can
\r
1351 be used to test the server interface. Descendant classes register additional
\r
1352 API functions by overriding the register_function() member of the geniserver
\r
1359 Geniserver provides a function, decode_authentication, that decodes
\r
1360 credentials. Credentials are supplied as the first parameter to many registry
\r
1361 and slice interface API functions. This function converts the credential
\r
1362 string supplied by the user into a credential object, checks to see that the
\r
1363 key the caller is using to encrypt the SSL connection matches the public key
\r
1364 in the caller GID of the credential, checks to see that the credential allows
\r
1365 the operation the caller is attempting to do, and finally verifies that the
\r
1366 parentage of the credential traces back to a trusted root.
\r
1372 Geniclient provides a variety of client-side stubs for invoking operations on
\r
1373 Geni interfaces. These stubs convert objects into strings that may be encoded
\r
1374 by XMLRPC, call the associated XMLRPC function, and convert the results back
\r
1375 into objects. Use of the Geniclient class is optional, but it makes a
\r
1376 convenient mechanism to execute API calls.
\r
1382 <b>3.0 The PLC Wrapper</b>
\r
1388 This wrapper implements the Registry and Slice interfaces. According to the
\r
1389 SFA, the basic functionality of a registry is to map HRNs into records.
\r
1390 However, because of the interactions between Geniwrapper and PLC, the registry
\r
1391 does more than act as a simple database. The registry performs API calls on
\r
1392 PLC that create slices, sites, users, etc., and as such may indirectly cause
\r
1393 slices to be instantiated on components, because components are also linked to
\r
1400 The mapping of Geni objects to planetlab objects is relatively
\r
1407 slice = slice
\r
1410 user = person
\r
1413 component = node
\r
1416 sa = site
\r
1419 ma = site
\r
1425 The one part that is slightly counterintuitive is SA and MA, which both map to
\r
1426 the planetlab site object. In a unified registry (a registry that serves as
\r
1427 both slice and component registry), these will map to the same site record in
\r
1428 the PLC database. However, there are two distinct Geni records, one for
\r
1429 the SA and one for the MA.
\r
1435 Registry and slice operations generally authenticate the caller by
\r
1436 credential. There are a few exceptions, and the registry API documents
\r
1437 should note those exceptions.
\r
1443 <b>3.1 PLC Wrapper Tools</b>
\r
1449 The registry include several additional tools that are used to manage it.
\r
1456 import.py - imports existing PLC records into the registry
\r
1462 nuke.py - deletes all Geni records
\r
1468 <b>3.1 Bootstrapping the PLC Wrapper</b>
\r
1474 There are several items that need to be done before starting the plc wrapper.
\r
1480 1) Update util/config.py to match the parameters of your PLC installation.
\r
1486 2) Import the existing planetlab database, creating the appropriate geni
\r
1487 records. This is done by running the "import.py" tool.
\r
1493 3) Create a "trusted_roots" directory and place the certificate of the root
\r
1494 authority in that directory. Given the defaults in import.py, this certificate
\r
1495 would be named "planetlab.gid". For example, mkdir trusted_roots; cp
\r
1496 authorities/planetlab.gid trusted_roots/
\r
1502 <b>4.0 The Component Wrapper</b>
\r
1506 The Geni Component Wrapper implements the Geni Slice and Component Management
\r
1507 interfaces. It includes functions for redeeming tickets,
\r
1508 starting/stopping/resetting/deleting slices, and management such as rebooting
\r
1515 The design of the component differs from the plc wrapper in the respect that
\r
1516 the component wrapper must be located physically on the planetlab node that it
\r
1517 is responsible for. The component wrapper interacts directly with portions of
\r
1518 the node manager code on the node.
\r
1524 <b>4.1 Component Authentication of Credentials</b>
\r
1530 The component authenticates credentials the same way that the plc wrapper
\r
1531 does. Specifically, there is a directory of trusted_root certificates (or
\r
1532 GIDs) on the component. Any credential presented to the component must include
\r
1533 in it's parentage some certificate in the set of trusted roots. Otherwise, and
\r
1534 exception is thrown.
\r
1540 <b>4.2 The Ticket interface</b>
\r
1546 The ticket interface is split between the PLC wrapper and the Component
\r
1547 wrapper. This is due to the SFA engineering decisions, specifically that
\r
1548 the authoritative copy of planetlab state is stored on PLC and only cached on
\r
1549 the components. Thus, GetTicket() is implemented on the Registry, and
\r
1550 RedeemTicket() is implemented on the component. Attempting to call GetTicket()
\r
1551 on a component will fail.<br>
\r
1553 InstantiateSlice is not implemented, as that operation is a combination of
\r
1554 GetTicket/RedeemTicket and would therefore span the PLC and Component
\r
1561 <b>4.3 Sliver Credentials</b>
\r
1567 A recent Geni Architecture call mentioned the need for sliver credentials. A
\r
1568 sliver credential would be identical to a slice credential, but would 1) only
\r
1569 be redeemable on a particular component, and 2) would resolve to a
\r
1570 trusted_root unique to that component (likely the component's GID
\r
1571 certificate). Sliver credentials would be returned by the RedeemTicket call
\r
1572 and would give the caller the permission required to start and stop the
\r
1579 Sliver credentials are not yet implemented, but their implementation would be
\r
1586 <b>4.4 Bootstrapping the Component Wrapper</b>
\r
1592 The first step is to install some required libraries on the component. These
\r
1593 include the m2crypto and pyopenssl libraries. Installing the actual RPMs for
\r
1594 these libaries on a running component proved difficult due to additional
\r
1595 support packages that require installation (python-devel, etc). For
\r
1596 development purposes, it was sufficient to copy the installed/compiled version
\r
1597 of the libraries from the development machine to the component.
\r
1603 The second step is to copy the files required by the component wrapper to
\r
1604 the node manager. They are copied to the /usr/share/Nodemanager directory. A
\r
1605 list of the files is contained in the copynode.sh script in the component
\r
1612 The third step is to copy the trusted root certificates to the component. They
\r
1613 are stored in /usr/share/Nodemanager/trusted_roots. This should include the
\r
1614 certificate for the registry.
\r
1620 The fourth step is to start the component manager. This is done by
\r
1621 connecting to the component via SSH and running
\r
1622 /usr/share/Nodemanager/component.py.
\r
1626 In a production environment, all of these steps would be integrated into the
\r
1627 DVD boot image for the planetlab node.
\r
1633 <b>5.0 Command-Line Interface</b>
\r
1639 A command-line interface is provided that allows a user to interact with the
\r
1640 Geni Registry and Component. This command line interface is located in the
\r
1641 cmdline directory and can be invoked by running genicli.py. Specifying
\r
1642 "genicli.py help" will display a list of available commands.
\r
1648 <b>5.1 Examples</b>
\r
1654 Several examples of using the CLI are presented in the form of shell scripts
\r
1655 in the cmdline directory. These scripts demonstrate creating slices,
\r
1656 authorities, users, nodes, and getting tickets and redeeming tickets. Rather
\r
1657 than duplicating all of those examples here, a few short examples are
\r
1664 <b>5.1.1 Getting a Credential</b>
\r
1670 python ./genicli.py --username root --credfile None --outfile test.cred
\r
1671 getCredential user planetlab.us.pl.account_test
\r
1677 The credential for planetlab.us.pl.account_test is retrieved and stored in the
\r
1678 local file test.cred. The private ket test.pkey is used when opening the
\r
1679 XMLRPC connection and authenticates the client. test.pkey must match the
\r
1680 public key that is in the GID for the user record for
\r
1681 planetlab.us.pl.account_test.
\r
1687 Sample output: (in human-readable summary)
\r
1693 CREDENTIAL planetlab.us.pl.account_test<br>
\r
1694 privs: refresh,resolve,info<br>
\r
1695 gidCaller:<br>
\r
1696 hrn:
\r
1697 planetlab.us.pl.account_test<br>
\r
1698 uuid:
\r
1699 276262316202422735940395896620385479122<br>
\r
1700 gidObject:<br>
\r
1701 hrn:
\r
1702 planetlab.us.pl.account_test<br>
\r
1703 uuid:
\r
1704 276262316202422735940395896620385479122<br>
\r
1705 delegate: False
\r
1714 <b>5.1.2 Resolving a record</b>
\r
1720 python ./genicli.py --username test resolve planetlab.us.pl.account_test
\r
1726 The record for planetlab.us.pl.account_test is retrieved and printed to
\r
1727 stdout. The credential used comes from the local file test.cred.
\r
1733 Sample output: (in human-readable summary)
\r
1739 RECORD planetlab.us.pl.account_test<br>
\r
1740 hrn: planetlab.us.pl.account_test<br>
\r
1741 type: user<br>
\r
1742 gid:<br>
\r
1743 hrn:
\r
1744 planetlab.us.pl.account_test<br>
\r
1745 uuid:
\r
1746 276262316202422735940395896620385479122<br>
\r
1747 pointer: 6<br>
\r
1748 geni_info:<br>
\r
1749 email :
\r
1750 <a href=mailto:test@test.com>test@test.com</a><br>
\r
1751 pl_info:<br>
\r
1752 bio : None<br>
\r
1753 first_name : test<br>
\r
1754 last_name : account<br>
\r
1755 last_updated : 1222497672<br>
\r
1756 uuid : None<br>
\r
1757 roles : ['user']<br>
\r
1758 title : None<br>
\r
1759 &nbsp; url : None<br>
\r
1760 key_ids : [1]<br>
\r
1761 enabled : True<br>
\r
1762 slice_ids : [24]<br>
\r
1763 phone : None<br>
\r
1764 peer_person_id : None<br>
\r
1765 role_ids : [30]<br>
\r
1766 person_id : 6<br>
\r
1767 date_created : 1219083140<br>
\r
1768 site_ids : [1]<br>
\r
1769 peer_id : None<br>
\r
1770 email :
\r
1771 <a href=mailto:test@test.com>test@test.com</a>
\r
1777 <b>5.1.3 Updating a record</b>
\r
1783 python ./genicli.py --username test update user planetlab.us.pl.account_test
\r
1789 The record for planetlab.us.pl.account_test is updated. The credential used
\r
1790 comes from the local file test.cred. No changes are specified, so the only
\r
1791 thing that should be updated is the expiration time.
\r
1797 <b>5.1.4 Resolving an authority</b>
\r
1803 An authority is an example of an HRN that might resolve to two different
\r
1804 records, an SA and a MA record.
\r
1810 python ./genicli.py --username test resolve planetlab.us.pl
\r
1816 Sample Output: (in human readable summary)
\r
1822 RECORD planetlab.us.pl<br>
\r
1823 hrn: planetlab.us.pl<br>
\r
1824 type: sa<br>
\r
1825 gid:<br>
\r
1826 hrn: planetlab.us.pl<br>
\r
1827 uuid:
\r
1828 294786197975089072547582920862317666209<br>
\r
1829 pointer: 1<br>
\r
1830 geni_info:<br>
\r
1831 pi :
\r
1832 ['planetlab.us.pl.Administrator_Default']<br>
\r
1833 pl_info:<br>
\r
1834 last_updated : 1224136003<br>
\r
1835 node_ids : [1]<br>
\r
1836 site_id : 1<br>
\r
1837 pcu_ids : []<br>
\r
1838 max_slices : 100<br>
\r
1839 ext_consortium_id : None<br>
\r
1840 peer_site_id : None<br>
\r
1841 abbreviated_name : plctest<br>
\r
1842 uuid :
\r
1843 230749975723590978208303655640765327534<br>
\r
1844 person_ids : [2, 4, 6]<br>
\r
1845 slice_ids : [24, 1, 2]<br>
\r
1846 latitude : None<br>
\r
1847 peer_id : None<br>
\r
1848 max_slivers : 1000<br>
\r
1849 is_public : False<br>
\r
1850 address_ids : []<br>
\r
1851 name : plctest Central<br>
\r
1852 url :
\r
1853 <a href=http://198.0.0.132/>http://198.0.0.132/</a><br>
\r
1854 enabled : True<br>
\r
1855 longitude : None<br>
\r
1856 login_base : pl<br>
\r
1857 date_created : 1209428329<br>
\r
1859 RECORD planetlab.us.pl<br>
\r
1860 hrn: planetlab.us.pl<br>
\r
1861 type: ma<br>
\r
1862 gid:<br>
\r
1863 hrn: planetlab.us.pl<br>
\r
1864 uuid:
\r
1865 294786197975089072547582920862317666209<br>
\r
1866 pointer: 1<br>
\r
1867 geni_info:<br>
\r
1868 operator : []<br>
\r
1869 owner :
\r
1870 ['planetlab.us.pl.Administrator_Default']<br>
\r
1871 pl_info:<br>
\r
1872 last_updated : 1224136003<br>
\r
1873 node_ids : [1]<br>
\r
1874 site_id : 1<br>
\r
1875 pcu_ids : []<br>
\r
1876 max_slices : 100<br>
\r
1877 ext_consortium_id : None<br>
\r
1878 peer_site_id : None<br>
\r
1879 abbreviated_name : plctest<br>
\r
1880 uuid :
\r
1881 230749975723590978208303655640765327534<br>
\r
1882 person_ids : [2, 4, 6]<br>
\r
1883 slice_ids : [24, 1, 2]<br>
\r
1884 latitude : None<br>
\r
1885 peer_id : None<br>
\r
1886 max_slivers : 1000<br>
\r
1887 is_public : False<br>
\r
1888 address_ids : []<br>
\r
1889 name : plctest Central<br>
\r
1890 url :
\r
1891 <a href=http://198.0.0.132/>http://198.0.0.132/</a><br>
\r
1892 enabled : True<br>
\r
1893 longitude : None<br>
\r
1894 login_base : pl<br>
\r
1895 date_created : 1209428329
\r