change references of registry wrapper to plc wrapper, add info on extending to other...
[sfa.git] / docs / Geniwrapper_Design_Docu.html
1
2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
3
4 <html>
5
6
7 <head>
8 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
9
10 <base target="_top">
11
12 <style type="text/css">
13
14
15 /* default css */
16
17 table {
18   font-size: 1em;
19   line-height: inherit;
20 }
21
22
23 tr {
24   
25   text-align: left;
26   
27 }
28
29
30 div, address, ol, ul, li, option, select { 
31   margin-top: 0px;
32   margin-bottom: 0px;
33 }
34
35 p {
36   margin: 0px;
37 }
38
39 body {
40   margin: 6px;
41   padding: 0px;
42   font-family: Verdana, sans-serif;
43   font-size: 10pt;
44   background-color: #ffffff;
45 }
46
47
48 img {
49   -moz-force-broken-image-icon: 1;
50 }
51
52 @media screen {
53   html.pageview {
54     background-color: #f3f3f3 !important;
55   }
56
57   
58     
59   body { 
60     min-height: 1100px; 
61   }
62   * html body { 
63     height: 1100px; 
64   }
65   .pageview body {
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;
72     padding: 40px 50px; 
73   }
74   /* IE6 */
75   * html {
76     overflow-y: scroll;
77   }
78   * html.pageview body {
79     overflow-x: auto;
80   }
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 {
85     content: '\A0';
86     position: fixed;
87     overflow: hidden;
88     width: 0;
89     height: 0;
90     top: 0;
91     left: 0;
92   }
93   
94   
95
96   
97     .writely-callout-data {
98       display: none;
99     }
100     .writely-footnote-marker {
101       background-image: url('MISSING');
102       background-color: transparent;
103       background-repeat: no-repeat;
104       width: 7px;
105       overflow: hidden;
106       height: 16px;
107       vertical-align: top;
108     }
109     .editor .writely-footnote-marker {
110       cursor: move;
111     }
112     .writely-footnote-marker-highlight {
113       background-position: -15px 0;
114     }
115     .writely-footnote-hide-selection ::-moz-selection, .writely-footnote-hide-selection::-moz-selection {
116       background: transparent;
117     }
118     .writely-footnote-hide-selection ::selection, .writely-footnote-hide-selection::selection {
119       background: transparent;
120     }
121     .writely-footnote-hide-selection {
122       cursor: move;
123     }
124
125     
126     .editor .writely-comment-yellow {
127       background-color: #FF9;
128       background-position: -240px 0;
129     }
130     .editor .writely-comment-yellow-hover {
131       background-color: #FF0;
132       background-position: -224px 0;
133     }
134     .editor .writely-comment-blue {
135       background-color: #C0D3FF;
136       background-position: -16px 0;
137     }
138     .editor .writely-comment-blue-hover {
139       background-color: #6292FE;
140       background-position: 0 0;
141     }
142     .editor .writely-comment-orange {
143       background-color: #FFDEAD;
144       background-position: -80px 0;
145     }
146     .editor .writely-comment-orange-hover {
147       background-color: #F90;
148       background-position: -64px 0;
149     }
150     .editor .writely-comment-green {
151       background-color: #99FBB3;
152       background-position: -48px 0;
153     }
154     .editor .writely-comment-green-hover {
155       background-color: #00F442;
156       background-position: -32px 0;
157     }
158     .editor .writely-comment-cyan {
159       background-color: #CFF;
160       background-position: -208px 0;
161     }
162     .editor .writely-comment-cyan-hover {
163       background-color: #0FF;
164       background-position: -192px 0;
165     }
166     .editor .writely-comment-purple {
167       background-color: #EBCCFF;
168       background-position: -144px 0;
169     }
170     .editor .writely-comment-purple-hover {
171       background-color: #90F;
172       background-position: -128px 0;
173     }
174     .editor .writely-comment-magenta {
175       background-color: #FCF;
176       background-position: -112px 0;
177     }
178     .editor .writely-comment-magenta-hover {
179       background-color: #F0F;
180       background-position: -96px 0;
181     }
182     .editor .writely-comment-red {
183       background-color: #FFCACA;
184       background-position: -176px 0;
185     }
186     .editor .writely-comment-red-hover {
187       background-color: #FF7A7A;
188       background-position: -160px 0;
189     }
190     
191     .editor .writely-comment-marker {
192       background-image: url('MISSING');
193       background-color: transparent;
194       padding-right: 11px;
195       background-repeat: no-repeat;
196       width: 16px;
197       height: 16px;
198       -moz-user-select: none;
199     }
200
201     .editor .writely-comment-hidden {
202       padding: 0;
203       background: none;
204     }
205     .editor .writely-comment-marker-hidden {
206       background: none;
207       padding: 0;
208       width: 0;
209     }
210     .editor .writely-comment-none {
211       opacity: .2;
212       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=20);
213       -moz-opacity: .2;
214     }
215     .editor .writely-comment-none-hover {
216       opacity: .2;
217       filter:progid:DXImageTransform.Microsoft.Alpha(opacity=20);
218       -moz-opacity: .2;
219     }
220   
221
222
223   
224   .br_fix br:not(:-moz-last-node):not(:-moz-first-node) {
225     
226     position:relative;
227     
228     left: -1ex
229     
230   }
231   
232   .br_fix br+br {
233     position: static !important
234   }
235 }
236
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 }
243
244 blockquote {padding: 10px; border: 1px #DDD dashed }
245
246 a img {border: 0}
247
248 .pb {
249   border-width: 0;
250   page-break-after: always;
251   /* We don't want this to be resizeable, so enforce a width and height
252      using !important */
253   height: 1px !important;
254   width: 100% !important;
255 }
256
257 .editor .pb {
258   border-top: 1px dashed #C0C0C0;
259   border-bottom: 1px dashed #C0C0C0;
260 }
261
262 div.google_header, div.google_footer {
263   position: relative;
264   margin-top: 1em;
265   margin-bottom: 1em;
266 }
267
268
269 /* Table of contents */
270 .editor div.writely-toc {
271   background-color: #f3f3f3;
272   border: 1px solid #ccc;
273 }
274 .writely-toc > ol {
275   padding-left: 3em;
276   font-weight: bold;
277 }
278 ol.writely-toc-subheading {
279   padding-left: 1em;
280   font-weight: normal;
281 }
282 /* IE6 only */
283 * html writely-toc ol {
284   list-style-position: inside;
285 }
286 .writely-toc-none {
287   list-style-type: none;
288 }
289 .writely-toc-decimal {
290   list-style-type: decimal;
291 }
292 .writely-toc-upper-alpha {
293   list-style-type: upper-alpha;
294 }
295 .writely-toc-lower-alpha {
296   list-style-type: lower-alpha;
297 }
298 .writely-toc-upper-roman {
299   list-style-type: upper-roman;
300 }
301 .writely-toc-lower-roman {
302   list-style-type: lower-roman;
303 }
304 .writely-toc-disc {
305   list-style-type: disc;
306 }
307
308 /* end default css */
309
310
311   /* default print css */
312   
313   @media print {
314     body { 
315       padding: 0; 
316       margin: 0; 
317     }
318
319     div.google_header, div.google_footer {
320       display: block;
321       min-height: 0;
322       border: none;
323     }
324
325     div.google_header {
326       flow: static(header);
327     }
328
329     /* used to insert page numbers */
330     div.google_header::before, div.google_footer::before {
331       position: absolute;
332       top: 0;
333     }
334
335     div.google_footer {
336       flow: static(footer);
337     }
338
339     /* always consider this element at the start of the doc */
340     div#google_footer {
341       flow: static(footer, start);
342     }
343
344     span.google_pagenumber {
345       content: counter(page);
346     }
347
348     span.google_pagecount {
349       content: counter(pages);
350     }
351
352
353     callout.google_footnote {
354       
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
359          document CSS. */
360       color: #000;
361       font-family: Verdana;
362       font-size: 10.0pt;
363       font-weight: normal;
364     }
365
366     /* Table of contents */
367     #WritelyTableOfContents a::after {
368       content: leader('.') target-counter(attr(href), page);
369     }
370
371     #WritelyTableOfContents a {
372       text-decoration: none;
373       color: black;
374     }
375   }
376
377   @page {
378     @top {
379       content: flow(header);
380     }
381     @bottom {
382       content: flow(footer);
383     }
384     @footnotes {
385       border-top: solid black thin;
386       padding-top: 8pt;
387     }
388   }
389   /* end default print css */
390  
391
392 /* custom css */
393
394
395 /* end custom css */
396
397
398
399   /* ui edited css */
400   
401   body {
402     font-family: Verdana;
403     
404     font-size: 10.0pt;
405     line-height: normal;
406     background-color: #ffffff;
407   }
408   /* end ui edited css */
409
410
411
412 /* editor 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}
417
418
419 .editor div.google_header, .editor div.google_footer {
420   border: 2px #DDDDDD dashed;
421   position: static;
422   width: 100%;
423   min-height: 2em;
424 }
425
426 .editor .misspell {background-color: yellow}
427
428 .editor .writely-comment {
429   font-size: 9pt; 
430   line-height: 1.4; 
431   padding: 1px; 
432   border: 1px dashed #C0C0C0
433 }
434
435
436 /* end editor CSS */
437 </style>
438
439
440 </head>
441
442 <body onload="DoPageLoad();"
443     
444     revision="dhkdd78p_13kvrgbnfb:273">
445
446     
447     
448     
449 <div>\r
450   <div>\r
451     <b>Geniwrapper Design Document</b>\r
452   </div>\r
453 </div>\r
454 <div>\r
455   &nbsp;\r
456 </div>\r
457 <div>\r
458   <b>1.0 High Level Overview</b>\r
459 </div>\r
460 <div>\r
461   &nbsp;\r
462 </div>\r
463 <div>\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.&nbsp;PLC and Planetlab\r
468   Nodes can be mapped into the Geni Registry and Geni Component\r
469   interfaces&nbsp;respectively. However, due to the nature of\r
470   planetlab,&nbsp;the&nbsp;Geni slice interface&nbsp;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
474 </div>\r
475 <div>\r
476   &nbsp;\r
477 </div>\r
478 <div>\r
479   Geniwrapper is comprised of the following logical modules: <i>utility\r
480   classes</i>,&nbsp;<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
484 </div>\r
485 <div>\r
486   &nbsp;\r
487 </div>\r
488 <div>\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
494 </div>\r
495 <div>\r
496   &nbsp;\r
497 </div>\r
498 <div>\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
504 </div>\r
505 <div>\r
506   &nbsp;\r
507 </div>\r
508 <div>\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
512 </div>\r
513 <div>\r
514   &nbsp;\r
515 </div>\r
516 <div>\r
517   <div>\r
518     <b>1.1 Utility classes</b>\r
519   </div>\r
520   <div>\r
521     &nbsp;\r
522   </div>\r
523   <div>\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
530   </div>\r
531   <div>\r
532     &nbsp;\r
533   </div>\r
534   <div>\r
535     The&nbsp;utility classes&nbsp;are located in the\r
536     <i>util</i>&nbsp;subdirectory.\r
537   </div>\r
538 </div>\r
539 <div>\r
540   &nbsp;\r
541 </div>\r
542 <div>\r
543   <b>1.2&nbsp;PLC wrapper</b>\r
544 </div>\r
545 <div>\r
546   &nbsp;\r
547 </div>\r
548 <div>\r
549   The&nbsp;plc wrapper is intended to be colocated with PLC. All communication\r
550   between the&nbsp;plc wrapper and PLC uses the PLCAPI interface and as such,\r
551   the&nbsp;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&nbsp;plc wrapper also implements slice operations, such as GetTicket, that\r
554   must be located on PLC due to SFA engineering decisions.\r
555 </div>\r
556 <div>\r
557   &nbsp;\r
558 </div>\r
559 <div>\r
560   The&nbsp;plc wrapper is located in the&nbsp;<i>plc</i> subdirectory.\r
561 </div>\r
562 <div>\r
563   &nbsp;\r
564 </div>\r
565 <div>\r
566   TODO: Slice interface shall be implemented in&nbsp;plc wrapper.\r
567 </div>\r
568 <div>\r
569   &nbsp;\r
570 </div>\r
571 <div>\r
572   <b>1.3&nbsp;The component wrapper</b>\r
573 </div>\r
574 <div>\r
575   &nbsp;\r
576 </div>\r
577 <div>\r
578   The component wrapper is located on planetlab nodes. It implements\r
579   the&nbsp;slice interface, and the component management interface. Due to SFA\r
580   engineering decisions, some&nbsp;slice operations (i.e. GetTicket) are\r
581   implemented in the&nbsp;plc wrapper&nbsp;and are unavaiable on\r
582   the&nbsp;component wrapper.\r
583 </div>\r
584 <div>\r
585   &nbsp;\r
586 </div>\r
587 <div>\r
588   The component wrapper is located in the <i>component</i> subdirectory.\r
589 </div>\r
590 <div>\r
591   &nbsp;\r
592 </div>\r
593 <div>\r
594   <b>1.4 Command line client</b>\r
595 </div>\r
596 <div>\r
597   &nbsp;\r
598 </div>\r
599 <div>\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
603 </div>\r
604 <div>\r
605   &nbsp;\r
606 </div>\r
607 <div>\r
608   The command line client&nbsp;is located in the&nbsp;<i>cmdline</i>\r
609   subdirectory\r
610 </div>\r
611 <div>\r
612   &nbsp;\r
613 </div>\r
614 <div>\r
615   <b>1.5 Geni Protocol</b>\r
616 </div>\r
617 <div>\r
618   &nbsp;\r
619 </div>\r
620 <div>\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
624 </div>\r
625 <div>\r
626   &nbsp;\r
627 </div>\r
628 <ol>\r
629   <li>\r
630     The transport mechanism uses HTTPS instead of HTTP.\r
631   </li>\r
632   <li>\r
633     HTTPS certificate verification is disabled so that custom Geni verification\r
634     based on GID can be done instead.\r
635   </li>\r
636   <li>\r
637     When an exception occurs on the server, verbose exception information is\r
638     sent to the client, to assist debugging efforts\r
639   </li>\r
640 </ol>\r
641 <div>\r
642   &nbsp;\r
643 </div>\r
644 <div>\r
645   Authentication:\r
646 </div>\r
647 <div>\r
648   &nbsp;\r
649 </div>\r
650 <div>\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
657 </div>\r
658 <div>\r
659   &nbsp;\r
660 </div>\r
661 <div>\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
666 </div>\r
667 <div>\r
668   &nbsp;<br>\r
669   <b>1.6 Extending Geniwrapper to other environments</b><br>\r
670   <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
678   <br>\r
679   For example, looking at the code for the stop_slice function implemented in\r
680   the component wrapper:<br>\r
681   <br>\r
682   &nbsp;&nbsp;&nbsp; def stop_slice(self, cred_str):<br>\r
683   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r
684   self.decode_authentication(cred_str, "stopslice")<br>\r
685   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; slicename =\r
686   hrn_to_pl_slicename(self.object_gid.get_hrn())<br>\r
687   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print "stopslice:", slicename<br>\r
688   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; accounts.get(slicename).stop()<br>\r
689   <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
694   environment.<br>\r
695   <br>\r
696 </div>\r
697 <div>\r
698   <b>2.0 Utility Classes</b>\r
699 </div>\r
700 <div>\r
701   &nbsp;\r
702 </div>\r
703 <div>\r
704   <b>2.1 Certificates and Keys (cert.py)</b>\r
705 </div>\r
706 <div>\r
707   &nbsp;\r
708 </div>\r
709 <div>\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
717 </div>\r
718 <div>\r
719   &nbsp;\r
720 </div>\r
721 <div>\r
722   <b>2.1.1 Keys</b>\r
723 </div>\r
724 <div>\r
725   &nbsp;\r
726 </div>\r
727 <div>\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
731 </div>\r
732 <p>\r
733   &nbsp;&nbsp;&nbsp;&nbsp;\r
734 </p>\r
735 <div>\r
736   <b>2.1.2 Certificates</b>\r
737 </div>\r
738 <div>\r
739   &nbsp;\r
740 </div>\r
741 <div>\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
746 </div>\r
747 <div>\r
748   &nbsp;\r
749 </div>\r
750 <div>\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
756 </div>\r
757 <div>\r
758   &nbsp;\r
759 </div>\r
760 <div>\r
761   Example creation of a certificate:\r
762 </div>\r
763 <div>\r
764   &nbsp;\r
765 </div>\r
766 <div>\r
767   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # create&nbsp;a key for an issuer<br>\r
768   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; issuerKey = Keypair(create=True)<br>\r
769   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; issuerSubject = "testissuer"\r
770 </div>\r
771 <div>\r
772   &nbsp;\r
773 </div>\r
774 <div>\r
775   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # create a key for the certificate\r
776 </div>\r
777 <div>\r
778   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; userKey = KeyPair(create=True)\r
779 </div>\r
780 <div>\r
781   &nbsp;\r
782 </div>\r
783 <div>\r
784   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # create the certificate, set the issuer, and\r
785   sign it\r
786 </div>\r
787 <div>\r
788   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cert = Certificate(subject="test")<br>\r
789   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cert.set_issuer(issuerKey, issuerSubject)\r
790 </div>\r
791 <div>\r
792   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cert.set_pubkey(userKey)<br>\r
793   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cert.sign()\r
794 </div>\r
795 <div>\r
796   &nbsp;\r
797 </div>\r
798 <div>\r
799   <b>2.1.3 Certificate Verification</b>\r
800 </div>\r
801 <div>\r
802   &nbsp;\r
803 </div>\r
804 <div>\r
805   <p>\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
809   </p>\r
810   <pre>    if this_certificate was signed by trusted_certs:<br>        return<br>    else<br>        return verify_chain(parent, trusted_certs)</pre>\r
811 </div>\r
812 <div>\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
817 </div>\r
818 <div>\r
819   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>\r
820   <b>2.2 GIDS (gid.py)</b>\r
821 </div>\r
822 <div>\r
823   <b></b>&nbsp;\r
824 </div>\r
825 <div>\r
826   GIDs are a derivative class of certificates and as such the&nbsp;GID class\r
827   inherits all the methods of the certificate class. A&nbsp;GID includes a tuple\r
828   of the following fields:&nbsp;\r
829 </div>\r
830 <div>\r
831   &nbsp;\r
832 </div>\r
833 <div>\r
834   &nbsp;&nbsp; (uuid, hrn, public_key)\r
835 </div>\r
836 <div>\r
837   &nbsp;\r
838 </div>\r
839 <div>\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
842 </div>\r
843 <div>\r
844   &nbsp;\r
845 </div>\r
846 <div>\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
849 </div>\r
850 <div>\r
851   &nbsp;\r
852 </div>\r
853 <div>\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
856 </div>\r
857 <div>\r
858   &nbsp;\r
859 </div>\r
860 <div>\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
863 </div>\r
864 <div>\r
865   &nbsp;\r
866 </div>\r
867 <div>\r
868   <b>2.2.1 Encoding and Decoding</b>\r
869 </div>\r
870 <div>\r
871   &nbsp;\r
872 </div>\r
873 <div>\r
874   The 5 fields of the&nbsp;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
878   functions.\r
879 </div>\r
880 <div>\r
881   &nbsp;\r
882 </div>\r
883 <div>\r
884   <b>2.2.2 Verification of GIDs</b>\r
885 </div>\r
886 <div>\r
887   &nbsp;\r
888 </div>\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
895 <div>\r
896   &nbsp;\r
897 </div>\r
898 <div>\r
899   <b>2.3 Credentials (credential.py)</b>\r
900 </div>\r
901 <div>\r
902   &nbsp;\r
903 </div>\r
904 <div>\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
908 </div>\r
909 <div>\r
910   &nbsp;\r
911 </div>\r
912 <div>\r
913   &nbsp;&nbsp;&nbsp; (GIDCaller, GIDObject, LifeTime, Privileges, Delegate)\r
914 </div>\r
915 <div>\r
916   &nbsp;\r
917 </div>\r
918 <div>\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
922 </div>\r
923 <div>\r
924   &nbsp;\r
925 </div>\r
926 <div>\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
932 </div>\r
933 <div>\r
934   &nbsp;\r
935 </div>\r
936 <div>\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
939   date.\r
940 </div>\r
941 <div>\r
942   &nbsp;\r
943 </div>\r
944 <div>\r
945   Privileges is a Rights object that describes the rights that are granted to\r
946   the holder of the credential.\r
947 </div>\r
948 <div>\r
949   &nbsp;\r
950 </div>\r
951 <div>\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
954 </div>\r
955 <div>\r
956   &nbsp;\r
957 </div>\r
958 <div>\r
959   <b>2.3.1 Encoding and Decoding</b>\r
960 </div>\r
961 <div>\r
962   &nbsp;\r
963 </div>\r
964 <div>\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
969   get_*() functions.\r
970 </div>\r
971 <div>\r
972   &nbsp;\r
973 </div>\r
974 <div>\r
975   <b>2.3.2 Verification of Credentials</b>\r
976 </div>\r
977 <div>\r
978   &nbsp;\r
979 </div>\r
980 <div>\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.&nbsp;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
986   <br>\r
987   <b>2.4 Rights (rights.py)<br>\r
988   <br>\r
989   </b>Rights are implemented by two classes:<br>\r
990   <br>\r
991   Right - represents a single right<br>\r
992   RightList - represents a list of rights A right may allow several different\r
993   operations.<br>\r
994   <br>\r
995   For example, the "info" right allows "listslices", "listcomponentresources",\r
996   etc.<br>\r
997   <br>\r
998   <b>2.5 Records (record.py)</b><br>\r
999 </div>\r
1000 <div>\r
1001   &nbsp;\r
1002 </div>\r
1003 <div>\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
1009   Type, Info).\r
1010 </div>\r
1011 <div>\r
1012   &nbsp;\r
1013 </div>\r
1014 <div>\r
1015   &nbsp; Name specifies the HRN of the object GID is the GID of the object\r
1016 </div>\r
1017 <div>\r
1018   &nbsp;\r
1019 </div>\r
1020 <div>\r
1021   &nbsp; Type is user | sa | ma | slice | component Info is comprised of the\r
1022   following sub-fields\r
1023 </div>\r
1024 <div>\r
1025   &nbsp;\r
1026 </div>\r
1027 <div>\r
1028   &nbsp; Pointer&nbsp;is a pointer to the record in the PL database\r
1029 </div>\r
1030 <div>\r
1031   &nbsp;\r
1032 </div>\r
1033 <div>\r
1034   &nbsp; pl_info&nbsp;is planetlab-specific info (when talking to client)\r
1035 </div>\r
1036 <div>\r
1037   &nbsp;\r
1038 </div>\r
1039 <div>\r
1040   &nbsp; geni_info = geni-specific info (when talking to client)\r
1041 </div>\r
1042 <div>\r
1043   &nbsp;\r
1044 </div>\r
1045 <div>\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
1049 </div>\r
1050 <div>\r
1051   &nbsp;\r
1052 </div>\r
1053 <div>\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
1057 </div>\r
1058 <div>\r
1059   &nbsp;\r
1060 </div>\r
1061 <div>\r
1062   <b>2.6 Tickets (geniticket.py)</b>\r
1063 </div>\r
1064 <div>\r
1065   &nbsp;\r
1066 </div>\r
1067 <div>\r
1068   Similar to GIDs and Credentials, tickets also leverage the certificate object.\r
1069 </div>\r
1070 <div>\r
1071   &nbsp;\r
1072 </div>\r
1073 <div>\r
1074   A Ticket is tuple:<br>\r
1075   &nbsp;&nbsp; (gidCaller, gidObject, attributes, rspec, delegate)<br>\r
1076   <br>\r
1077   &nbsp;&nbsp;&nbsp; gidCaller = GID of the caller performing the operation<br>\r
1078   &nbsp;&nbsp;&nbsp; gidObject = GID of the slice<br>\r
1079   &nbsp;&nbsp;&nbsp; attributes = slice attributes (keys, vref, instantiation,\r
1080   etc)<br>\r
1081   &nbsp;&nbsp;&nbsp; rspec = resources\r
1082 </div>\r
1083 <div>\r
1084   &nbsp;\r
1085 </div>\r
1086 <div>\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
1091   only.\r
1092 </div>\r
1093 <div>\r
1094   &nbsp;\r
1095 </div>\r
1096 <div>\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
1100 </div>\r
1101 <div>\r
1102   &nbsp;\r
1103 </div>\r
1104 <div>\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
1107 </div>\r
1108 <div>\r
1109   &nbsp;\r
1110 </div>\r
1111 <div>\r
1112   <b>2.6.1 rspecs</b>\r
1113 </div>\r
1114 <div>\r
1115   &nbsp;\r
1116 </div>\r
1117 <div>\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
1120 </div>\r
1121 <div>\r
1122   &nbsp;\r
1123 </div>\r
1124 <div>\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
1129 </div>\r
1130 <div>\r
1131   &nbsp;\r
1132 </div>\r
1133 <div>\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
1137 </div>\r
1138 <div>\r
1139   &nbsp;\r
1140 </div>\r
1141 <div>\r
1142   <div>\r
1143     <b>2.6.2 Encoding and Decoding</b>\r
1144   </div>\r
1145   <div>\r
1146     &nbsp;\r
1147   </div>\r
1148   <div>\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
1154   </div>\r
1155   <div>\r
1156     &nbsp;\r
1157   </div>\r
1158   <div>\r
1159     <b>2.6.3 Verification of Tickets</b>\r
1160   </div>\r
1161   <div>\r
1162     &nbsp;\r
1163   </div>\r
1164   <div>\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
1168     the component.\r
1169   </div>\r
1170   <div>\r
1171     &nbsp;\r
1172   </div>\r
1173   <div>\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
1178   </div>\r
1179   <div>\r
1180     &nbsp;\r
1181   </div>\r
1182   <div>\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
1188     <br>\r
1189     <b>2.7 Hierarchy of Authorities (hierarchy.py)</b><br>\r
1190     <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
1197     <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
1202     <br>\r
1203     The hierarchy class can be used to create GIDs, Credentials, and Tickets for\r
1204     a given authority.\r
1205   </div>\r
1206 </div>\r
1207 <div>\r
1208   &nbsp;\r
1209 </div>\r
1210 <div>\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
1218 </div>\r
1219 <div>\r
1220   <br>\r
1221   <b>2.8 Configuration Information (config.py)</b><br>\r
1222   <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
1225   connection.<br>\r
1226   <br>\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
1232 </div>\r
1233 <p>\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
1240   dictionary.\r
1241 </p>\r
1242 <div>\r
1243   <br>\r
1244   <b>2.8.1 Database Configuration</b>\r
1245 </div>\r
1246 <div>\r
1247   &nbsp;\r
1248 </div>\r
1249 <div>\r
1250   Below is an example database configuration from config.py:\r
1251 </div>\r
1252 <div>\r
1253   &nbsp;\r
1254 </div>\r
1255 <div>\r
1256   def get_default_dbinfo():<br>\r
1257   &nbsp;&nbsp;&nbsp; dbinfo={}<br>\r
1258   &nbsp;&nbsp;&nbsp; dbinfo['dbname'] = 'planetlab4'<br>\r
1259   &nbsp;&nbsp;&nbsp; dbinfo['address'] = 'localhost'<br>\r
1260   &nbsp;&nbsp;&nbsp; dbinfo['port'] = 5432<br>\r
1261   &nbsp;&nbsp;&nbsp; dbinfo['user'] = 'pgsqluser'<br>\r
1262   &nbsp;&nbsp;&nbsp; dbinfo['password'] = '4c77b272-c892-4bdf-a833-dddeeee1a2ed'\r
1263 </div>\r
1264 <div>\r
1265   &nbsp;&nbsp;&nbsp; return dbinfo\r
1266 </div>\r
1267 <div>\r
1268   &nbsp;\r
1269 </div>\r
1270 <div>\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
1279   desired.\r
1280 </div>\r
1281 <div>\r
1282   &nbsp;\r
1283 </div>\r
1284 <div>\r
1285   <b>2.8.2 PLCAPI Configuration</b>\r
1286 </div>\r
1287 <div>\r
1288   &nbsp;\r
1289 </div>\r
1290 <div>\r
1291   Blow is an example PLCAPI configuration from config.py:\r
1292 </div>\r
1293 <div>\r
1294   &nbsp;\r
1295 </div>\r
1296 <div>\r
1297   def get_pl_auth():<br>\r
1298   &nbsp;&nbsp;&nbsp; pl_auth = {'Username':\r
1299   <a href=mailto:%27root@198.0.0.132%27>'root@198.0.0.132'</a>,<br>\r
1300   &nbsp;&nbsp;&nbsp; 'AuthMethod': 'password',<br>\r
1301   &nbsp;&nbsp;&nbsp; 'AuthString':&nbsp; 'root',<br>\r
1302   &nbsp;&nbsp;&nbsp; "Url":\r
1303   "<a href=https://localhost/PLCAPI/>https://localhost:443/PLCAPI/</a>"<br>\r
1304   &nbsp;&nbsp;&nbsp; }\r
1305 </div>\r
1306 <div>\r
1307   &nbsp;&nbsp;&nbsp; return pl_auth\r
1308 </div>\r
1309 <div>\r
1310   &nbsp;\r
1311 </div>\r
1312 <div>\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
1319 </div>\r
1320 <div>\r
1321   &nbsp;\r
1322 </div>\r
1323 <div>\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
1329   use this account.\r
1330 </div>\r
1331 <div>\r
1332   &nbsp;\r
1333 </div>\r
1334 <div>\r
1335   <b>2.9 GeniServer and GeniClient</b>\r
1336 </div>\r
1337 <div>\r
1338   &nbsp;\r
1339 </div>\r
1340 <div>\r
1341   Two files, geniserver.py and geniclient.py implement a basic Geni server and\r
1342   client.\r
1343 </div>\r
1344 <div>\r
1345   &nbsp;\r
1346 </div>\r
1347 <div>\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
1353   object.\r
1354 </div>\r
1355 <div>\r
1356   &nbsp;\r
1357 </div>\r
1358 <div>\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
1367 </div>\r
1368 <div>\r
1369   &nbsp;\r
1370 </div>\r
1371 <div>\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
1377 </div>\r
1378 <div>\r
1379   &nbsp;\r
1380 </div>\r
1381 <div>\r
1382   <b>3.0 The&nbsp;PLC Wrapper</b>\r
1383 </div>\r
1384 <div>\r
1385   &nbsp;\r
1386 </div>\r
1387 <div>\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
1394   PLC.\r
1395 </div>\r
1396 <div>\r
1397   &nbsp;\r
1398 </div>\r
1399 <div>\r
1400   The mapping of Geni objects to planetlab objects is relatively\r
1401   straightforward:\r
1402 </div>\r
1403 <div>\r
1404   &nbsp;\r
1405 </div>\r
1406 <div>\r
1407   &nbsp;&nbsp;&nbsp; slice&nbsp;= slice\r
1408 </div>\r
1409 <div>\r
1410   &nbsp;&nbsp;&nbsp; user&nbsp;= person\r
1411 </div>\r
1412 <div>\r
1413   &nbsp;&nbsp;&nbsp;&nbsp;component = node\r
1414 </div>\r
1415 <div>\r
1416   &nbsp;&nbsp;&nbsp; sa = site\r
1417 </div>\r
1418 <div>\r
1419   &nbsp;&nbsp;&nbsp; ma = site\r
1420 </div>\r
1421 <div>\r
1422   &nbsp;\r
1423 </div>\r
1424 <div>\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&nbsp;for\r
1429   the SA and one for the MA.&nbsp;\r
1430 </div>\r
1431 <div>\r
1432   &nbsp;\r
1433 </div>\r
1434 <div>\r
1435   Registry and slice&nbsp;operations generally authenticate the&nbsp;caller by\r
1436   credential. There are a few exceptions, and the registry API&nbsp;documents\r
1437   should note those exceptions.&nbsp;\r
1438 </div>\r
1439 <div>\r
1440   &nbsp;\r
1441 </div>\r
1442 <div>\r
1443   <b>3.1&nbsp;PLC&nbsp;Wrapper&nbsp;Tools</b>\r
1444 </div>\r
1445 <div>\r
1446   &nbsp;\r
1447 </div>\r
1448 <div>\r
1449   The registry include several additional tools that are used to manage it.\r
1450   These include:\r
1451 </div>\r
1452 <div>\r
1453   &nbsp;\r
1454 </div>\r
1455 <div>\r
1456   import.py - imports existing PLC records into the registry\r
1457 </div>\r
1458 <div>\r
1459   &nbsp;\r
1460 </div>\r
1461 <div>\r
1462   nuke.py - deletes all Geni records\r
1463 </div>\r
1464 <div>\r
1465   &nbsp;\r
1466 </div>\r
1467 <div>\r
1468   <b>3.1 Bootstrapping&nbsp;the PLC Wrapper</b>\r
1469 </div>\r
1470 <div>\r
1471   &nbsp;\r
1472 </div>\r
1473 <div>\r
1474   There are several items that need to be done before starting the plc wrapper.\r
1475 </div>\r
1476 <div>\r
1477   &nbsp;\r
1478 </div>\r
1479 <div>\r
1480   1) Update util/config.py to match the parameters of your PLC installation.\r
1481 </div>\r
1482 <div>\r
1483   &nbsp;\r
1484 </div>\r
1485 <div>\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
1488 </div>\r
1489 <div>\r
1490   &nbsp;\r
1491 </div>\r
1492 <div>\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
1497 </div>\r
1498 <div>\r
1499   &nbsp;\r
1500 </div>\r
1501 <div>\r
1502   <b>4.0 The Component Wrapper</b>\r
1503 </div>\r
1504 <div>\r
1505   <br>\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
1509   the component.\r
1510 </div>\r
1511 <div>\r
1512   &nbsp;\r
1513 </div>\r
1514 <div>\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
1519 </div>\r
1520 <div>\r
1521   &nbsp;\r
1522 </div>\r
1523 <div>\r
1524   <b>4.1 Component Authentication of Credentials</b>\r
1525 </div>\r
1526 <div>\r
1527   &nbsp;\r
1528 </div>\r
1529 <div>\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
1535 </div>\r
1536 <div>\r
1537   &nbsp;\r
1538 </div>\r
1539 <div>\r
1540   <b>4.2 The Ticket interface</b>\r
1541 </div>\r
1542 <div>\r
1543   &nbsp;\r
1544 </div>\r
1545 <div>\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&nbsp;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
1552   <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
1555   wrappers.<br>\r
1556 </div>\r
1557 <div>\r
1558   &nbsp;\r
1559 </div>\r
1560 <div>\r
1561   <b>4.3 Sliver Credentials</b>\r
1562 </div>\r
1563 <div>\r
1564   &nbsp;\r
1565 </div>\r
1566 <div>\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
1573   sliver, etc.\r
1574 </div>\r
1575 <div>\r
1576   &nbsp;\r
1577 </div>\r
1578 <div>\r
1579   Sliver credentials are not yet implemented, but their implementation would be\r
1580   straightforward.\r
1581 </div>\r
1582 <div>\r
1583   &nbsp;\r
1584 </div>\r
1585 <div>\r
1586   <b>4.4 Bootstrapping the Component Wrapper</b>\r
1587 </div>\r
1588 <div>\r
1589   &nbsp;\r
1590 </div>\r
1591 <div>\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
1598 </div>\r
1599 <div>\r
1600   &nbsp;\r
1601 </div>\r
1602 <div>\r
1603   The&nbsp;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
1606   subdirectory.\r
1607 </div>\r
1608 <div>\r
1609   &nbsp;\r
1610 </div>\r
1611 <div>\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
1615 </div>\r
1616 <div>\r
1617   &nbsp;\r
1618 </div>\r
1619 <div>\r
1620   The&nbsp;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
1623 </div>\r
1624 <div>\r
1625   <br>\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
1628 </div>\r
1629 <div>\r
1630   &nbsp;\r
1631 </div>\r
1632 <div>\r
1633   <b>5.0 Command-Line Interface</b>\r
1634 </div>\r
1635 <div>\r
1636   &nbsp;\r
1637 </div>\r
1638 <div>\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
1643 </div>\r
1644 <div>\r
1645   &nbsp;\r
1646 </div>\r
1647 <div>\r
1648   <b>5.1 Examples</b>\r
1649 </div>\r
1650 <div>\r
1651   &nbsp;\r
1652 </div>\r
1653 <div>\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
1658   presented below.\r
1659 </div>\r
1660 <div>\r
1661   &nbsp;\r
1662 </div>\r
1663 <div>\r
1664   <b>5.1.1 Getting a Credential</b>\r
1665 </div>\r
1666 <div>\r
1667   &nbsp;\r
1668 </div>\r
1669 <div>\r
1670   python ./genicli.py --username&nbsp;root --credfile None --outfile test.cred\r
1671   getCredential user planetlab.us.pl.account_test\r
1672 </div>\r
1673 <div>\r
1674   &nbsp;\r
1675 </div>\r
1676 <div>\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
1682 </div>\r
1683 <div>\r
1684   &nbsp;\r
1685 </div>\r
1686 <div>\r
1687   Sample output: (in human-readable summary)\r
1688 </div>\r
1689 <div>\r
1690   &nbsp;\r
1691 </div>\r
1692 <div>\r
1693   CREDENTIAL planetlab.us.pl.account_test<br>\r
1694   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; privs: refresh,resolve,info<br>\r
1695   &nbsp; gidCaller:<br>\r
1696   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn:\r
1697   planetlab.us.pl.account_test<br>\r
1698   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid:\r
1699   276262316202422735940395896620385479122<br>\r
1700   &nbsp; gidObject:<br>\r
1701   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn:\r
1702   planetlab.us.pl.account_test<br>\r
1703   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid:\r
1704   276262316202422735940395896620385479122<br>\r
1705   &nbsp;&nbsp; delegate: False\r
1706 </div>\r
1707 <div>\r
1708   &nbsp;\r
1709 </div>\r
1710 <div>\r
1711   &nbsp;\r
1712 </div>\r
1713 <div>\r
1714   <b>5.1.2 Resolving a record</b>\r
1715 </div>\r
1716 <div>\r
1717   &nbsp;\r
1718 </div>\r
1719 <div>\r
1720   python ./genicli.py --username test resolve planetlab.us.pl.account_test\r
1721 </div>\r
1722 <div>\r
1723   &nbsp;\r
1724 </div>\r
1725 <div>\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
1728 </div>\r
1729 <div>\r
1730   &nbsp;\r
1731 </div>\r
1732 <div>\r
1733   Sample output: (in human-readable summary)\r
1734 </div>\r
1735 <div>\r
1736   &nbsp;\r
1737 </div>\r
1738 <div>\r
1739   RECORD planetlab.us.pl.account_test<br>\r
1740   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn: planetlab.us.pl.account_test<br>\r
1741   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: user<br>\r
1742   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gid:<br>\r
1743   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn:\r
1744   planetlab.us.pl.account_test<br>\r
1745   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid:\r
1746   276262316202422735940395896620385479122<br>\r
1747   &nbsp;&nbsp;&nbsp; pointer: 6<br>\r
1748   &nbsp; geni_info:<br>\r
1749   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; email :\r
1750   <a href=mailto:test@test.com>test@test.com</a><br>\r
1751   &nbsp;&nbsp;&nbsp; pl_info:<br>\r
1752   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bio : None<br>\r
1753   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; first_name : test<br>\r
1754   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last_name : account<br>\r
1755   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last_updated : 1222497672<br>\r
1756   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid : None<br>\r
1757   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; roles : ['user']<br>\r
1758   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; title : None<br>\r
1759   &nbsp;&amp;nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url : None<br>\r
1760   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; key_ids : [1]<br>\r
1761   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enabled : True<br>\r
1762   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; slice_ids : [24]<br>\r
1763   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; phone : None<br>\r
1764   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; peer_person_id : None<br>\r
1765   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; role_ids : [30]<br>\r
1766   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; person_id : 6<br>\r
1767   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; date_created : 1219083140<br>\r
1768   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; site_ids : [1]<br>\r
1769   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; peer_id : None<br>\r
1770   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; email :\r
1771   <a href=mailto:test@test.com>test@test.com</a>\r
1772 </div>\r
1773 <div>\r
1774   &nbsp;\r
1775 </div>\r
1776 <div>\r
1777   <b>5.1.3 Updating a record</b>\r
1778 </div>\r
1779 <div>\r
1780   &nbsp;\r
1781 </div>\r
1782 <div>\r
1783   python ./genicli.py --username test update user planetlab.us.pl.account_test\r
1784 </div>\r
1785 <div>\r
1786   &nbsp;\r
1787 </div>\r
1788 <div>\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
1792 </div>\r
1793 <div>\r
1794   &nbsp;\r
1795 </div>\r
1796 <div>\r
1797   <b>5.1.4 Resolving an authority</b>\r
1798 </div>\r
1799 <div>\r
1800   &nbsp;\r
1801 </div>\r
1802 <div>\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
1805 </div>\r
1806 <div>\r
1807   &nbsp;\r
1808 </div>\r
1809 <div>\r
1810   python ./genicli.py --username test resolve planetlab.us.pl\r
1811 </div>\r
1812 <div>\r
1813   &nbsp;\r
1814 </div>\r
1815 <div>\r
1816   Sample Output: (in human readable summary)\r
1817 </div>\r
1818 <div>\r
1819   &nbsp;\r
1820 </div>\r
1821 <div>\r
1822   RECORD planetlab.us.pl<br>\r
1823   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn: planetlab.us.pl<br>\r
1824   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: sa<br>\r
1825   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gid:<br>\r
1826   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn: planetlab.us.pl<br>\r
1827   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid:\r
1828   294786197975089072547582920862317666209<br>\r
1829   &nbsp;&nbsp;&nbsp; pointer: 1<br>\r
1830   &nbsp; geni_info:<br>\r
1831   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pi :\r
1832   ['planetlab.us.pl.Administrator_Default']<br>\r
1833   &nbsp;&nbsp;&nbsp; pl_info:<br>\r
1834   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last_updated : 1224136003<br>\r
1835   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node_ids : [1]<br>\r
1836   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; site_id : 1<br>\r
1837   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pcu_ids : []<br>\r
1838   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max_slices : 100<br>\r
1839   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ext_consortium_id : None<br>\r
1840   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; peer_site_id : None<br>\r
1841   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; abbreviated_name : plctest<br>\r
1842   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid :\r
1843   230749975723590978208303655640765327534<br>\r
1844   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; person_ids : [2, 4, 6]<br>\r
1845   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; slice_ids : [24, 1, 2]<br>\r
1846   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; latitude : None<br>\r
1847   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; peer_id : None<br>\r
1848   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max_slivers : 1000<br>\r
1849   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is_public : False<br>\r
1850   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; address_ids : []<br>\r
1851   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name : plctest Central<br>\r
1852   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url :\r
1853   <a href=http://198.0.0.132/>http://198.0.0.132/</a><br>\r
1854   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enabled : True<br>\r
1855   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; longitude : None<br>\r
1856   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; login_base : pl<br>\r
1857   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; date_created : 1209428329<br>\r
1858   RESULT:<br>\r
1859   RECORD planetlab.us.pl<br>\r
1860   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn: planetlab.us.pl<br>\r
1861   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: ma<br>\r
1862   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gid:<br>\r
1863   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hrn: planetlab.us.pl<br>\r
1864   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid:\r
1865   294786197975089072547582920862317666209<br>\r
1866   &nbsp;&nbsp;&nbsp; pointer: 1<br>\r
1867   &nbsp; geni_info:<br>\r
1868   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; operator : []<br>\r
1869   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; owner :\r
1870   ['planetlab.us.pl.Administrator_Default']<br>\r
1871   &nbsp;&nbsp;&nbsp; pl_info:<br>\r
1872   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; last_updated : 1224136003<br>\r
1873   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node_ids : [1]<br>\r
1874   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; site_id : 1<br>\r
1875   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pcu_ids : []<br>\r
1876   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max_slices : 100<br>\r
1877   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ext_consortium_id : None<br>\r
1878   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; peer_site_id : None<br>\r
1879   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; abbreviated_name : plctest<br>\r
1880   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uuid :\r
1881   230749975723590978208303655640765327534<br>\r
1882   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; person_ids : [2, 4, 6]<br>\r
1883   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; slice_ids : [24, 1, 2]<br>\r
1884   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; latitude : None<br>\r
1885   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; peer_id : None<br>\r
1886   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max_slivers : 1000<br>\r
1887   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is_public : False<br>\r
1888   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; address_ids : []<br>\r
1889   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name : plctest Central<br>\r
1890   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url :\r
1891   <a href=http://198.0.0.132/>http://198.0.0.132/</a><br>\r
1892   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enabled : True<br>\r
1893   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; longitude : None<br>\r
1894   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; login_base : pl<br>\r
1895   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; date_created : 1209428329\r
1896 </div>\r
1897 <br>