minor updates
[sfa.git] / sfa / client / sfi.py
1 #! /usr/bin/env python
2
3 # sfi -- slice-based facility interface
4
5 import sys
6 sys.path.append('.')
7 import os, os.path
8 import tempfile
9 import traceback
10 import socket
11 import random
12 from types import StringTypes, ListType
13 from optparse import OptionParser
14 from sfa.trust.certificate import Keypair, Certificate
15 from sfa.trust.credential import Credential
16 from sfa.util.sfaticket import SfaTicket
17 from sfa.util.record import *
18 from sfa.util.namespace import *
19 from sfa.util.rspec import RSpec
20 from sfa.util.xmlrpcprotocol import ServerException
21 import sfa.util.xmlrpcprotocol as xmlrpcprotocol
22 from sfa.util.config import Config
23 import zlib
24
25 # utility methods here
26 # display methods
27 def display_rspec(rspec, format='rspec'):
28     if format in ['dns']:
29         spec = RSpec()
30         spec.parseString(rspec)
31         hostnames = []
32         nodespecs = spec.getDictsByTagName('NodeSpec')
33         for nodespec in nodespecs:
34             if nodespec.has_key('name') and nodespec['name']:
35                 if isinstance(nodespec['name'], ListType):
36                     hostnames.extend(nodespec['name'])
37                 elif isinstance(nodespec['name'], StringTypes):
38                      hostnames.append(nodespec['name'])
39         result = hostnames
40     elif format in ['ip']:
41         spec = RSpec()
42         spec.parseString(rspec)
43         ips = []
44         ifspecs = spec.getDictsByTagName('IfSpec')
45         for ifspec in ifspecs:
46             if ifspec.has_key('addr') and ifspec['addr']:
47                 ips.append(ifspec['addr'])
48         result = ips
49     else:
50         result = rspec
51
52     print result
53     return
54
55 def display_list(results):
56     for result in results:
57         print result
58
59
60 def display_records(recordList, dump=False):
61     ''' Print all fields in the record'''
62     for record in recordList:
63         display_record(record, dump)
64
65 def display_record(record, dump=False):
66     if dump:
67         record.dump()
68     else:
69         info = record.getdict()
70         print "%s (%s)" % (info['hrn'], info['type'])
71     return
72
73
74 def filter_records(type, records):
75     filtered_records = []
76     for record in records:
77         if (record['type'] == type) or (type == "all"):
78             filtered_records.append(record)
79     return filtered_records
80
81
82 # save methods
83 def save_rspec_to_file(rspec, filename):
84     if not filename.endswith(".rspec"):
85         filename = filename + ".rspec"
86
87     f = open(filename, 'w')
88     f.write(rspec)
89     f.close()
90     return
91
92 def save_records_to_file(filename, recordList):
93     index = 0
94     for record in recordList:
95         if index > 0:
96             save_record_to_file(filename + "." + str(index), record)
97         else:
98             save_record_to_file(filename, record)
99         index = index + 1
100
101 def save_record_to_file(filename, record):
102     if record['type'] in ['user']:
103         record = UserRecord(dict=record)
104     elif record['type'] in ['slice']:
105         record = SliceRecord(dict=record)
106     elif record['type'] in ['node']:
107         record = NodeRecord(dict=record)
108     elif record['type'] in ['authority', 'ma', 'sa']:
109         record = AuthorityRecord(dict=record)
110     else:
111         record = SfaRecord(dict=record)
112     str = record.save_to_string()
113     file(filename, "w").write(str)
114     return
115
116
117 # load methods
118 def load_record_from_file(filename):
119     str = file(filename, "r").read()
120     record = SfaRecord(string=str)
121     return record
122
123
124
125 class Sfi:
126
127     geni_am = None
128     slicemgr = None
129     registry = None
130     user = None
131     authority = None
132     options = None
133     hashrequest = False
134    
135     def create_cmd_parser(self, command, additional_cmdargs=None):
136         cmdargs = {"gid": "",
137                   "list": "name",
138                   "show": "name",
139                   "remove": "name",
140                   "add": "record",
141                   "update": "record",
142                   "aggregates": "[name]",
143                   "registries": "[name]",
144                   "slices": "",
145                   "resources": "[name]",
146                   "create": "name rspec",
147                   "get_trusted_certs": "cred",
148                   "get_ticket": "name rspec",
149                   "redeem_ticket": "ticket",
150                   "delete": "name",
151                   "reset": "name",
152                   "start": "name",
153                   "stop": "name",
154                   "delegate": "name",
155                   "GetVersion": "name",
156                   "ListResources": "name",
157                   "CreateSliver": "name",
158                   "get_geni_aggregates": "name",
159                   "DeleteSliver": "name",
160                   "SliverStatus": "name",
161                   "RenewSliver": "name",
162                   "Shutdown": "name"
163                  }
164
165         if additional_cmdargs:
166             cmdargs.update(additional_cmdargs)
167
168         if command not in cmdargs:
169             print "Invalid command\n"
170             print "Commands: ",
171             for key in cmdargs.keys():
172                 print key + ",",
173             print ""
174             sys.exit(2)
175
176         parser = OptionParser(usage="sfi [sfi_options] %s [options] %s" \
177                                      % (command, cmdargs[command]))
178
179         if command in ("resources"):
180             parser.add_option("-f", "--format", dest="format", type="choice",
181                              help="display format ([xml]|dns|ip)", default="xml",
182                              choices=("xml", "dns", "ip"))
183             parser.add_option("-a", "--aggregate", dest="aggregate",
184                              default=None, help="aggregate hrn")
185
186         if command in ("create", "get_ticket"):
187             parser.add_option("-a", "--aggregate", dest="aggregate", default=None,
188                              help="aggregate hrn")
189
190         if command in ("start", "stop", "reset", "delete", "slices"):
191             parser.add_option("-c", "--component", dest="component", default=None,
192                              help="component hrn")
193             
194         if command in ("list", "show", "remove"):
195             parser.add_option("-t", "--type", dest="type", type="choice",
196                             help="type filter ([all]|user|slice|sa|ma|node|aggregate)",
197                             choices=("all", "user", "slice", "sa", "ma", "node", "aggregate"),
198                             default="all")
199
200         if command in ("resources", "show", "list"):
201            parser.add_option("-o", "--output", dest="file",
202                             help="output XML to file", metavar="FILE", default=None)
203         
204         if command in ("show", "list"):
205            parser.add_option("-f", "--format", dest="format", type="choice",
206                              help="display format ([text]|xml)", default="text",
207                              choices=("text", "xml"))
208
209         if command in ("delegate"):
210            parser.add_option("-u", "--user",
211                             action="store_true", dest="delegate_user", default=False,
212                             help="delegate user credential")
213            parser.add_option("-s", "--slice", dest="delegate_slice",
214                             help="delegate slice credential", metavar="HRN", default=None)
215
216         return parser
217
218         
219     def create_parser(self):
220
221         # Generate command line parser
222         parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
223                              description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
224         parser.add_option("-g", "--geni_am", dest="geni_am",
225                           help="geni am", metavar="URL", default=None)
226         parser.add_option("-r", "--registry", dest="registry",
227                          help="root registry", metavar="URL", default=None)
228         parser.add_option("-s", "--slicemgr", dest="sm",
229                          help="slice manager", metavar="URL", default=None)
230         default_sfi_dir = os.path.expanduser("~/.sfi/")
231         parser.add_option("-d", "--dir", dest="sfi_dir",
232                          help="config & working directory - default is " + default_sfi_dir,
233                          metavar="PATH", default=default_sfi_dir)
234         parser.add_option("-u", "--user", dest="user",
235                          help="user name", metavar="HRN", default=None)
236         parser.add_option("-a", "--auth", dest="auth",
237                          help="authority name", metavar="HRN", default=None)
238         parser.add_option("-v", "--verbose",
239                          action="store_true", dest="verbose", default=False,
240                          help="verbose mode")
241         parser.add_option("-D", "--debug",
242                           action="store_true", dest="debug", default=False,
243                           help="Debug (xml-rpc) protocol messages")
244         parser.add_option("-p", "--protocol",
245                          dest="protocol", default="xmlrpc",
246                          help="RPC protocol (xmlrpc or soap)")
247         parser.add_option("-k", "--hashrequest",
248                          action="store_true", dest="hashrequest", default=False,
249                          help="Create a hash of the request that will be authenticated on the server")
250         parser.disable_interspersed_args()
251
252         return parser
253         
254  
255     #
256     # Establish Connection to SliceMgr and Registry Servers
257     #
258     def set_servers(self):
259        config_file = self.options.sfi_dir + os.sep + "sfi_config"
260        try:
261           config = Config (config_file)
262        except:
263           print "Failed to read configuration file", config_file
264           print "Make sure to remove the export clauses and to add quotes"
265           if not self.options.verbose:
266              print "Re-run with -v for more details"
267           else:
268              traceback.print_exc()
269           sys.exit(1)
270     
271        errors = 0
272        # Set SliceMgr URL
273        if (self.options.sm is not None):
274           sm_url = self.options.sm
275        elif hasattr(config, "SFI_SM"):
276           sm_url = config.SFI_SM
277        else:
278           print "You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s" % config_file
279           errors += 1 
280     
281        # Set Registry URL
282        if (self.options.registry is not None):
283           reg_url = self.options.registry
284        elif hasattr(config, "SFI_REGISTRY"):
285           reg_url = config.SFI_REGISTRY
286        else:
287           print "You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s" % config_file
288           errors += 1 
289           
290
291        if (self.options.geni_am is not None):
292            geni_am_url = self.options.geni_am
293        elif hasattr(config, "SFI_GENI_AM"):
294            geni_am_url = config.SFI_GENI_AM
295            
296        # Set user HRN
297        if (self.options.user is not None):
298           self.user = self.options.user
299        elif hasattr(config, "SFI_USER"):
300           self.user = config.SFI_USER
301        else:
302           print "You need to set e.g. SFI_USER='plc.princeton.username' in %s" % config_file
303           errors += 1 
304     
305        # Set authority HRN
306        if (self.options.auth is not None):
307           self.authority = self.options.auth
308        elif hasattr(config, "SFI_AUTH"):
309           self.authority = config.SFI_AUTH
310        else:
311           print "You need to set e.g. SFI_AUTH='plc.princeton' in %s" % config_file
312           errors += 1 
313     
314        if errors:
315           sys.exit(1)
316     
317        if self.options.verbose :
318           print "Contacting Slice Manager at:", sm_url
319           print "Contacting Registry at:", reg_url
320     
321        # Get key and certificate
322        key_file = self.get_key_file()
323        cert_file = self.get_cert_file(key_file)
324        self.key = Keypair(filename=key_file) 
325        self.key_file = key_file
326        self.cert_file = cert_file
327        self.cert = Certificate(filename=cert_file) 
328        # Establish connection to server(s)
329        self.registry = xmlrpcprotocol.get_server(reg_url, key_file, cert_file, self.options.debug)  
330        self.slicemgr = xmlrpcprotocol.get_server(sm_url, key_file, cert_file, self.options.debug)
331        self.geni_am = xmlrpcprotocol.get_server(geni_am_url, key_file, cert_file, self.options.debug)
332
333        return
334     
335     #
336     # Get various credential and spec files
337     #
338     # Establishes limiting conventions
339     #   - conflates MAs and SAs
340     #   - assumes last token in slice name is unique
341     #
342     # Bootstraps credentials
343     #   - bootstrap user credential from self-signed certificate
344     #   - bootstrap authority credential from user credential
345     #   - bootstrap slice credential from user credential
346     #
347     
348     
349     def get_key_file(self):
350        file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".pkey")
351        #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".pkey")
352        if (os.path.isfile(file)):
353           return file
354        else:
355           print "Key file", file, "does not exist"
356           sys.exit(-1)
357        return
358     
359     def get_cert_file(self, key_file):
360     
361        #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cert")
362        file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cert")
363        if (os.path.isfile(file)):
364           return file
365        else:
366           k = Keypair(filename=key_file)
367           cert = Certificate(subject=self.user)
368           cert.set_pubkey(k)
369           cert.set_issuer(k, self.user)
370           cert.sign()
371           if self.options.verbose :
372              print "Writing self-signed certificate to", file
373           cert.save_to_file(file)
374           return file
375    
376     def get_gid(self):
377         #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".gid")
378         file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".gid")
379         if (os.path.isfile(file)):
380             gid = GID(filename=file)
381             return gid
382         else:
383             cert_str = self.cert.save_to_string(save_parents=True)
384             gid_str = self.registry.get_gid(cert_str, self.user, "user")
385             gid = GID(string=gid_str)
386             if self.options.verbose:
387                 print "Writing user gid to", file
388             gid.save_to_file(file, save_parents=True)
389             return gid       
390  
391     def get_user_cred(self):
392         #file = os.path.join(self.options.sfi_dir, get_leaf(self.user) + ".cred")
393         file = os.path.join(self.options.sfi_dir, self.user.replace(self.authority + '.', '') + ".cred")
394         if (os.path.isfile(file)):
395             user_cred = Credential(filename=file)
396             return user_cred
397         else:
398             # bootstrap user credential
399             cert_string = self.cert.save_to_string(save_parents=True)
400             user_name = self.user.replace(self.authority + ".", '')
401             if user_name.count(".") > 0:
402                 user_name = user_name.replace(".", '_')
403                 self.user = self.authority + "." + user_name
404
405             user_cred = self.registry.get_self_credential(cert_string, "user", self.user)
406             if user_cred:
407                cred = Credential(string=user_cred)
408                cred.save_to_file(file, save_parents=True)
409                if self.options.verbose:
410                     print "Writing user credential to", file
411                return cred
412             else:
413                print "Failed to get user credential"
414                sys.exit(-1)
415   
416     def get_auth_cred(self):
417         if not self.authority:
418             print "no authority specified. Use -a or set SF_AUTH"
419             sys.exit(-1)
420     
421         file = os.path.join(self.options.sfi_dir, get_leaf("authority") + ".cred")
422         if (os.path.isfile(file)):
423             auth_cred = Credential(filename=file)
424             return auth_cred
425         else:
426             # bootstrap authority credential from user credential
427             user_cred = self.get_user_cred().save_to_string(save_parents=True)
428             auth_cred = self.registry.get_credential(user_cred, "authority", self.authority)
429             if auth_cred:
430                 cred = Credential(string=auth_cred)
431                 cred.save_to_file(file, save_parents=True)
432                 if self.options.verbose:
433                     print "Writing authority credential to", file
434                 return cred
435             else:
436                 print "Failed to get authority credential"
437                 sys.exit(-1)
438     
439     def get_slice_cred(self, name):
440         file = os.path.join(self.options.sfi_dir, "slice_" + get_leaf(name) + ".cred")
441         if (os.path.isfile(file)):
442             slice_cred = Credential(filename=file)
443             return slice_cred
444         else:
445             # bootstrap slice credential from user credential
446             user_cred = self.get_user_cred().save_to_string(save_parents=True)
447             arg_list = [user_cred, "slice", name]
448             slice_cred_str = self.registry.get_credential(user_cred, "slice", name)
449             if slice_cred_str:
450                 slice_cred = Credential(string=slice_cred_str)
451                 slice_cred.save_to_file(file, save_parents=True)
452                 if self.options.verbose:
453                     print "Writing slice credential to", file
454                 return slice_cred
455             else:
456                 print "Failed to get slice credential"
457                 sys.exit(-1)
458     
459     def delegate_cred(self, cred, hrn, type='authority'):
460         # the gid and hrn of the object we are delegating
461         user_cred = Credential(string=cred)
462         object_gid = user_cred.get_gid_object()
463         object_hrn = object_gid.get_hrn()
464         #cred.set_delegate(True)
465         #if not cred.get_delegate():
466         #    raise Exception, "Error: Object credential %(object_hrn)s does not have delegate bit set" % locals()
467            
468     
469         records = self.registry.resolve(cred, hrn)
470         records = filter_records(type, records)
471         
472         if not records:
473             raise Exception, "Error: Didn't find a %(type)s record for %(hrn)s" % locals()
474     
475         # the gid of the user who will be delegated too
476         record = SfaRecord(dict=records[0])
477         delegee_gid = record.get_gid_object()
478         delegee_hrn = delegee_gid.get_hrn()
479         
480         # the key and hrn of the user who will be delegating
481         user_key = Keypair(filename=self.get_key_file())
482         user_hrn = user_cred.get_gid_caller().get_hrn()
483     
484         dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
485         dcred.set_gid_caller(delegee_gid)
486         dcred.set_gid_object(object_gid)
487         dcred.set_privileges(user_cred.get_privileges())
488         dcred.get_privileges().delegate_all_privileges(True)
489         
490
491         # Save the issuer's gid to a file
492         fname = self.options.sfi_dir + os.sep + "gid_%d" % random.randint(0, 999999999)
493         f = open(fname, "w")
494         f.write(user_cred.get_gid_caller().save_to_string())
495         f.close()
496         dcred.set_issuer_keys(self.get_key_file(), fname)
497         os.remove(fname)
498         
499         dcred.set_parent(user_cred)
500         dcred.encode()
501         dcred.sign()
502     
503         return dcred.save_to_string(save_parents=True)
504     
505     def get_rspec_file(self, rspec):
506        if (os.path.isabs(rspec)):
507           file = rspec
508        else:
509           file = os.path.join(self.options.sfi_dir, rspec)
510        if (os.path.isfile(file)):
511           return file
512        else:
513           print "No such rspec file", rspec
514           sys.exit(1)
515     
516     def get_record_file(self, record):
517        if (os.path.isabs(record)):
518           file = record
519        else:
520           file = os.path.join(self.options.sfi_dir, record)
521        if (os.path.isfile(file)):
522           return file
523        else:
524           print "No such registry record file", record
525           sys.exit(1)
526     
527     def load_publickey_string(self, fn):
528        f = file(fn, "r")
529        key_string = f.read()
530     
531        # if the filename is a private key file, then extract the public key
532        if "PRIVATE KEY" in key_string:
533            outfn = tempfile.mktemp()
534            cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
535            os.system(cmd)
536            f = file(outfn, "r")
537            key_string = f.read()
538            os.remove(outfn)
539     
540        return key_string
541
542     def get_component_server_from_hrn(self, hrn):
543         # direct connection to the nodes component manager interface
544         user_cred = self.get_user_cred().save_to_string(save_parents=True)
545         records = self.registry.resolve(user_cred, hrn)
546         records = filter_records('node', records)
547         if not records:
548             print "No such component:", opts.component
549         record = records[0]
550         cm_port = "12346"
551         url = "https://%s:%s" % (record['hostname'], cm_port)
552         return xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
553     
554     #
555     # Following functions implement the commands
556     #
557     # Registry-related commands
558     #
559   
560     def dispatch(self, command, cmd_opts, cmd_args):
561         getattr(self, command)(cmd_opts, cmd_args)
562  
563     def gid(self, opts, args):
564         gid = self.get_gid()
565         print "GID: %s" % (gid.save_to_string(save_parents=True))
566         return   
567  
568     # list entires in named authority registry
569     def list(self, opts, args):
570         user_cred = self.get_user_cred().save_to_string(save_parents=True)
571         hrn = args[0]
572         try:
573             list = self.registry.list(user_cred, hrn)
574         except IndexError:
575             raise Exception, "Not enough parameters for the 'list' command"
576           
577         # filter on person, slice, site, node, etc.  
578         # THis really should be in the self.filter_records funct def comment...
579         list = filter_records(opts.type, list)
580         for record in list:
581             print "%s (%s)" % (record['hrn'], record['type'])     
582         if opts.file:
583             file = opts.file
584             if not file.startswith(os.sep):
585                 file = os.path.join(self.options.sfi_dir, file)
586             save_records_to_file(file, list)
587         return
588     
589     # show named registry record
590     def show(self, opts, args):
591         user_cred = self.get_user_cred().save_to_string(save_parents=True)
592         hrn = args[0]
593         records = self.registry.resolve(user_cred, hrn)
594         records = filter_records(opts.type, records)
595         if not records:
596             print "No record of type", opts.type
597         for record in records:
598             if record['type'] in ['user']:
599                 record = UserRecord(dict=record)
600             elif record['type'] in ['slice']:
601                 record = SliceRecord(dict=record)
602             elif record['type'] in ['node']:
603                 record = NodeRecord(dict=record)
604             elif record['type'] in ['authority', 'ma', 'sa']:
605                 record = AuthorityRecord(dict=record)
606             else:
607                 record = SfaRecord(dict=record)
608             if (opts.format == "text"): 
609                 record.dump()  
610             else:
611                 print record.save_to_string() 
612        
613         if opts.file:
614             file = opts.file
615             if not file.startswith(os.sep):
616                 file = os.path.join(self.options.sfi_dir, file)
617             save_records_to_file(file, records)
618         return
619     
620     def delegate(self, opts, args):
621        user_cred = self.get_user_cred()
622        if opts.delegate_user:
623            object_cred = user_cred
624        elif opts.delegate_slice:
625            object_cred = self.get_slice_cred(opts.delegate_slice)
626        else:
627            print "Must specify either --user or --slice <hrn>"
628            return
629     
630        # the gid and hrn of the object we are delegating
631        object_gid = object_cred.get_gid_object()
632        object_hrn = object_gid.get_hrn()
633     
634        if not object_cred.get_privileges().get_all_delegate():
635            print "Error: Object credential", object_hrn, "does not have delegate bit set"
636            return
637     
638        records = self.registry.resolve(user_cred.save_to_string(save_parents=True), args[0])
639        records = filter_records("user", records)
640     
641        if not records:
642            print "Error: Didn't find a user record for", args[0]
643            return
644     
645        # the gid of the user who will be delegated to
646        delegee_gid = GID(string=records[0]['gid'])
647        delegee_hrn = delegee_gid.get_hrn()
648    
649        # the key and hrn of the user who will be delegating
650        user_key = Keypair(filename=self.get_key_file())
651        user_hrn = user_cred.get_gid_caller().get_hrn()
652        subject_string = "%s delegated to %s" % (object_hrn, delegee_hrn)
653        dcred = Credential(subject=subject_string)
654        dcred.set_gid_caller(delegee_gid)
655        dcred.set_gid_object(object_gid)
656        privs = object_cred.get_privileges()
657        dcred.set_privileges(object_cred.get_privileges())
658        dcred.get_privileges().delegate_all_privileges(True)
659        dcred.set_pubkey(object_gid.get_pubkey())
660        dcred.set_issuer(user_key, user_hrn)
661        dcred.set_parent(object_cred)
662        dcred.encode()
663        dcred.sign()
664     
665        if opts.delegate_user:
666            dest_fn = os.path.join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_" 
667                                   + get_leaf(object_hrn) + ".cred")
668        elif opts.delegate_slice:
669            dest_fn = os.path_join(self.options.sfi_dir, get_leaf(delegee_hrn) + "_slice_" 
670                                   + get_leaf(object_hrn) + ".cred")
671     
672        dcred.save_to_file(dest_fn, save_parents=True)
673     
674        print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
675     
676     # removed named registry record
677     #   - have to first retrieve the record to be removed
678     def remove(self, opts, args):
679         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
680         hrn = args[0]
681         type = opts.type 
682         if type in ['all']:
683             type = '*'
684         return self.registry.remove(auth_cred, type, hrn)
685     
686     # add named registry record
687     def add(self, opts, args):
688         auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
689         record_filepath = args[0]
690         rec_file = self.get_record_file(record_filepath)
691         record = load_record_from_file(rec_file).as_dict()
692         print record
693         return self.registry.register(auth_cred, record)
694     
695     # update named registry entry
696     def update(self, opts, args):
697         user_cred = self.get_user_cred()
698         rec_file = self.get_record_file(args[0])
699         record = load_record_from_file(rec_file)
700         if record['type'] == "user":
701             if record.get_name() == user_cred.get_gid_object().get_hrn():
702                 cred = user_cred.save_to_string(save_parents=True)
703             else:
704                 cred = self.get_auth_cred().save_to_string(save_parents=True)
705         elif record['type'] in ["slice"]:
706             try:
707                 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
708             except ServerException, e:
709                # XXX smbaker -- once we have better error return codes, update this
710                # to do something better than a string compare
711                if "Permission error" in e.args[0]:
712                    cred = self.get_auth_cred().save_to_string(save_parents=True)
713                else:
714                    raise
715         elif record.get_type() in ["authority"]:
716             cred = self.get_auth_cred().save_to_string(save_parents=True)
717         elif record.get_type() == 'node':
718             cred = self.get_auth_cred().save_to_string(save_parents=True)
719         else:
720             raise "unknown record type" + record.get_type()
721         record = record.as_dict()
722         return self.registry.update(cred, record)
723   
724     def get_trusted_certs(self, opts, args):
725         """
726         return the trusted certs at this interface 
727         """ 
728         trusted_certs = self.registry.get_trusted_certs()
729         for trusted_cert in trusted_certs:
730             cert = Certificate(string=trusted_cert)
731             print cert.get_subject()
732         return 
733
734     def aggregates(self, opts, args):
735         """
736         return a list of details about known aggregates
737         """
738         user_cred = self.get_user_cred().save_to_string(save_parents=True)
739         hrn = None
740         if args:
741             hrn = args[0]
742
743         result = self.registry.get_aggregates(user_cred, hrn)
744         display_list(result)
745         return 
746
747     def get_geni_aggregates(self, opts, args):
748         """
749         return a list of details about known aggregates
750         """
751         user_cred = self.get_user_cred().save_to_string(save_parents=True)
752         hrn = None
753         if args:
754             hrn = args[0]
755
756         result = self.registry.get_geni_aggregates(user_cred, hrn)
757         display_list(result)
758         return 
759
760
761     def registries(self, opts, args):
762         """
763         return a list of details about known registries
764         """
765         user_cred = self.get_user_cred().save_to_string(save_parents=True)
766         hrn = None
767         if args:
768             hrn = args[0]
769         result = self.registry.get_registries(user_cred, hrn)
770         display_list(result)
771         return
772
773  
774     #
775     # Slice-related commands
776     #
777     
778     # list available nodes -- use 'resources' w/ no argument instead
779
780     # list instantiated slices
781     def slices(self, opts, args):
782         user_cred = self.get_user_cred().save_to_string(save_parents=True)
783         server = self.slicemgr
784         # direct connection to the nodes component manager interface
785         if opts.component:
786             server = self.get_component_server_from_hrn(opts.component)
787         results = server.get_slices(user_cred)
788         display_list(results)
789         return
790     
791     # show rspec for named slice
792     def resources(self, opts, args):
793         user_cred = self.get_user_cred().save_to_string(save_parents=True)
794         server = self.slicemgr
795         if opts.aggregate:
796             agg_hrn = opts.aggregate
797             aggregates = self.registry.get_aggregates(user_cred, agg_hrn)
798             if not aggregates:
799                 raise Exception, "No such aggregate %s" % agg_hrn
800             aggregate = aggregates[0]
801             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])     
802             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
803         if args:
804             cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
805             hrn = args[0]
806         else:
807             cred = user_cred
808             hrn = None
809
810         result = server.get_resources(cred, hrn)
811         format = opts.format
812        
813         display_rspec(result, format)
814         if (opts.file is not None):
815             file = opts.file
816             if not file.startswith(os.sep):
817                 file = os.path.join(self.options.sfi_dir, file)
818             save_rspec_to_file(result, file)
819         return
820     
821     # created named slice with given rspec
822     def create(self, opts, args):
823         slice_hrn = args[0]
824         user_cred = self.get_user_cred()
825         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
826         rspec_file = self.get_rspec_file(args[1])
827         rspec = open(rspec_file).read()
828         server = self.slicemgr
829         if opts.aggregate:
830             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
831             if not aggregates:
832                 raise Exception, "No such aggregate %s" % opts.aggregate
833             aggregate = aggregates[0]
834             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
835             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
836         return server.create_slice(slice_cred, slice_hrn, rspec)
837
838     # get a ticket for the specified slice
839     def get_ticket(self, opts, args):
840         slice_hrn, rspec_path = args[0], args[1]
841         user_cred = self.get_user_cred()
842         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
843         rspec_file = self.get_rspec_file(rspec_path) 
844         rspec = open(rspec_file).read()
845         server = self.slicemgr
846         if opts.aggregate:
847             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
848             if not aggregates:
849                 raise Exception, "No such aggregate %s" % opts.aggregate
850             aggregate = aggregates[0]
851             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
852             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
853         ticket_string = server.get_ticket(slice_cred, slice_hrn, rspec)
854         file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
855         print "writing ticket to ", file        
856         ticket = SfaTicket(string=ticket_string)
857         ticket.save_to_file(filename=file, save_parents=True)
858
859     def redeem_ticket(self, opts, args):
860         ticket_file = args[0]
861         
862         # get slice hrn from the ticket
863         # use this to get the right slice credential 
864         ticket = SfaTicket(filename=ticket_file)
865         ticket.decode()
866         slice_hrn = ticket.gidObject.get_hrn()
867         #slice_hrn = ticket.attributes['slivers'][0]['hrn']
868         user_cred = self.get_user_cred()
869         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
870         
871         # get a list node hostnames from the nodespecs in the rspec 
872         rspec = RSpec()
873         rspec.parseString(ticket.rspec)
874         nodespecs = rspec.getDictsByTagName('NodeSpec')
875         hostnames = [nodespec['name'] for nodespec in nodespecs]
876         
877         # create an xmlrpc connection to the component manager at each of these
878         # components and gall redeem_ticket
879         connections = {}
880         for hostname in hostnames:
881             try:
882                 cm_port = "12346" 
883                 url = "https://%(hostname)s:%(cm_port)s" % locals() 
884                 print "Calling redeem_ticket at %(url)s " % locals(),
885                 cm = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
886                 cm.redeem_ticket(slice_cred, ticket.save_to_string(save_parents=True))
887                 print "Success"
888             except socket.gaierror:
889                 print "Failed:",
890                 print "Componet Manager not accepting requests" 
891             except Exception, e:
892                 print "Failed:", e.message
893              
894         return
895  
896     # delete named slice
897     def delete(self, opts, args):
898         slice_hrn = args[0]
899         server = self.slicemgr
900         # direct connection to the nodes component manager interface
901         if opts.component:
902             server = self.get_component_server_from_hrn(opts.component)
903  
904         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
905         return server.delete_slice(slice_cred, slice_hrn)
906     
907     # start named slice
908     def start(self, opts, args):
909         slice_hrn = args[0]
910         server = self.slicemgr
911         # direct connection to the nodes component manager interface
912         if opts.component:
913             server = self.get_component_server_from_hrn(opts.component)
914  
915         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
916         return server.start_slice(slice_cred, slice_hrn)
917     
918     # stop named slice
919     def stop(self, opts, args):
920         slice_hrn = args[0]
921         server = self.slicemgr
922         # direct connection to the nodes component manager interface
923         if opts.component:
924             server = self.get_component_server_from_hrn(opts.component)
925
926         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
927         return server.stop_slice(slice_cred, slice_hrn)
928     
929     # reset named slice
930     def reset(self, opts, args):
931         slice_hrn = args[0]
932         server = self.slicemgr
933         # direct connection to the nodes component manager interface
934         if opts.component:
935             server = self.get_component_server_from_hrn(opts.component)
936         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
937         return server.reset_slice(slice_cred, slice_hrn)
938
939
940     # GENI AM related calls
941
942     def GetVersion(self, opts, args):
943         server = self.geni_am
944         print server.GetVersion()
945
946     def ListResources(self, opts, args):
947         user_cred = self.get_user_cred().save_to_string(save_parents=True)
948         server = self.geni_am
949         call_options = {'geni_compressed': True}
950         xrn = None
951         cred = user_cred
952         if args:
953             xrn = args[0]
954             cred = self.get_slice_cred(xrn).save_to_string(save_parents=True)
955
956         if xrn:
957             call_options['geni_slice_urn'] = xrn
958             
959         rspec = server.ListResources([cred], call_options)
960         rspec = zlib.decompress(rspec.decode('base64'))
961         print rspec
962         
963     def CreateSliver(self, opts, args):
964         slice_xrn = args[0]
965         slice_cred = self.get_slice_cred(slice_xrn).save_to_string(save_parents=True)
966         rspec_file = self.get_rspec_file(args[1])
967         rspec = open(rspec_file).read()
968         server = self.geni_am
969         return server.CreateSliver(slice_xrn, [slice_cred], rspec)
970     
971     def DeleteSliver(self, opts, args):
972         slice_xrn = args[0]
973         slice_cred = self.get_slice_cred(slice_xrn).save_to_string(save_parents=True)
974         server = self.geni_am
975         return server.DeleteSliver(slice_xrn, [slice_cred])    
976
977     def SliverStatus(self, opts, args):
978         slice_xrn = args[0]
979         slice_cred = self.get_slice_cred(slice_xrn).save_to_string(save_parents=True)
980         server = self.geni_am
981         print server.SliverStatus(slice_xrn, [slice_cred])
982     
983     def RenewSliver(self, opts, args):
984         slice_xrn = args[0]
985         slice_cred = self.get_slice_cred(slice_xrn).save_to_string(save_parents=True)
986         time = args[1]
987         server = self.geni_am
988         return server.RenewSliver(slice_xrn, [slice_cred], time)   
989
990     def Shutdown(self, opts, args):
991         slice_xrn = args[0]
992         slice_cred = self.get_slice_cred(slice_xrn).save_to_string(save_parents=True)
993         server = self.geni_am
994         return server.Shutdown(slice_xrn, [slice_cred])         
995     
996     #
997     # Main: parse arguments and dispatch to command
998     #
999     def main(self):
1000         parser = self.create_parser()
1001         (options, args) = parser.parse_args()
1002         self.options = options
1003    
1004         if options.hashrequest:
1005             self.hashrequest = True
1006  
1007         if len(args) <= 0:
1008             print "No command given. Use -h for help."
1009             return - 1
1010     
1011         command = args[0]
1012         (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
1013         if self.options.verbose :
1014             print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry, options.sm,
1015                                                                    options.sfi_dir, options.user,
1016                                                                    options.auth)
1017             print "Command %s" % command
1018             if command in ("resources"):
1019                 print "resources cmd_opts %s" % cmd_opts.format
1020             elif command in ("list", "show", "remove"):
1021                 print "cmd_opts.type %s" % cmd_opts.type
1022             print "cmd_args %s" % cmd_args
1023     
1024         self.set_servers()
1025     
1026         try:
1027             self.dispatch(command, cmd_opts, cmd_args)
1028         except KeyError:
1029             raise 
1030             print "Command not found:", command
1031             sys.exit(1)
1032     
1033         return
1034     
1035 if __name__ == "__main__":
1036    Sfi().main()