removing some spurious print statements
[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         return self.registry.register(auth_cred, record)
693     
694     # update named registry entry
695     def update(self, opts, args):
696         user_cred = self.get_user_cred()
697         rec_file = self.get_record_file(args[0])
698         record = load_record_from_file(rec_file)
699         if record['type'] == "user":
700             if record.get_name() == user_cred.get_gid_object().get_hrn():
701                 cred = user_cred.save_to_string(save_parents=True)
702             else:
703                 cred = self.get_auth_cred().save_to_string(save_parents=True)
704         elif record['type'] in ["slice"]:
705             try:
706                 cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
707             except ServerException, e:
708                # XXX smbaker -- once we have better error return codes, update this
709                # to do something better than a string compare
710                if "Permission error" in e.args[0]:
711                    cred = self.get_auth_cred().save_to_string(save_parents=True)
712                else:
713                    raise
714         elif record.get_type() in ["authority"]:
715             cred = self.get_auth_cred().save_to_string(save_parents=True)
716         elif record.get_type() == 'node':
717             cred = self.get_auth_cred().save_to_string(save_parents=True)
718         else:
719             raise "unknown record type" + record.get_type()
720         record = record.as_dict()
721         return self.registry.update(cred, record)
722   
723     def get_trusted_certs(self, opts, args):
724         """
725         return the trusted certs at this interface 
726         """ 
727         trusted_certs = self.registry.get_trusted_certs()
728         for trusted_cert in trusted_certs:
729             cert = Certificate(string=trusted_cert)
730             print cert.get_subject()
731         return 
732
733     def aggregates(self, opts, args):
734         """
735         return a list of details about known aggregates
736         """
737         user_cred = self.get_user_cred().save_to_string(save_parents=True)
738         hrn = None
739         if args:
740             hrn = args[0]
741
742         result = self.registry.get_aggregates(user_cred, hrn)
743         display_list(result)
744         return 
745
746     def get_geni_aggregates(self, opts, args):
747         """
748         return a list of details about known aggregates
749         """
750         user_cred = self.get_user_cred().save_to_string(save_parents=True)
751         hrn = None
752         if args:
753             hrn = args[0]
754
755         result = self.registry.get_geni_aggregates(user_cred, hrn)
756         display_list(result)
757         return 
758
759
760     def registries(self, opts, args):
761         """
762         return a list of details about known registries
763         """
764         user_cred = self.get_user_cred().save_to_string(save_parents=True)
765         hrn = None
766         if args:
767             hrn = args[0]
768         result = self.registry.get_registries(user_cred, hrn)
769         display_list(result)
770         return
771
772  
773     #
774     # Slice-related commands
775     #
776     
777     # list available nodes -- use 'resources' w/ no argument instead
778
779     # list instantiated slices
780     def slices(self, opts, args):
781         user_cred = self.get_user_cred().save_to_string(save_parents=True)
782         server = self.slicemgr
783         # direct connection to the nodes component manager interface
784         if opts.component:
785             server = self.get_component_server_from_hrn(opts.component)
786         results = server.get_slices(user_cred)
787         display_list(results)
788         return
789     
790     # show rspec for named slice
791     def resources(self, opts, args):
792         user_cred = self.get_user_cred().save_to_string(save_parents=True)
793         server = self.slicemgr
794         if opts.aggregate:
795             agg_hrn = opts.aggregate
796             aggregates = self.registry.get_aggregates(user_cred, agg_hrn)
797             if not aggregates:
798                 raise Exception, "No such aggregate %s" % agg_hrn
799             aggregate = aggregates[0]
800             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])     
801             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
802         if args:
803             cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
804             hrn = args[0]
805         else:
806             cred = user_cred
807             hrn = None
808
809         result = server.get_resources(cred, hrn)
810         format = opts.format
811        
812         display_rspec(result, format)
813         if (opts.file is not None):
814             file = opts.file
815             if not file.startswith(os.sep):
816                 file = os.path.join(self.options.sfi_dir, file)
817             save_rspec_to_file(result, file)
818         return
819     
820     # created named slice with given rspec
821     def create(self, opts, args):
822         slice_hrn = args[0]
823         user_cred = self.get_user_cred()
824         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
825         rspec_file = self.get_rspec_file(args[1])
826         rspec = open(rspec_file).read()
827         server = self.slicemgr
828         if opts.aggregate:
829             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
830             if not aggregates:
831                 raise Exception, "No such aggregate %s" % opts.aggregate
832             aggregate = aggregates[0]
833             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
834             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
835         return server.create_slice(slice_cred, slice_hrn, rspec)
836
837     # get a ticket for the specified slice
838     def get_ticket(self, opts, args):
839         slice_hrn, rspec_path = args[0], args[1]
840         user_cred = self.get_user_cred()
841         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
842         rspec_file = self.get_rspec_file(rspec_path) 
843         rspec = open(rspec_file).read()
844         server = self.slicemgr
845         if opts.aggregate:
846             aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
847             if not aggregates:
848                 raise Exception, "No such aggregate %s" % opts.aggregate
849             aggregate = aggregates[0]
850             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
851             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
852         ticket_string = server.get_ticket(slice_cred, slice_hrn, rspec)
853         file = os.path.join(self.options.sfi_dir, get_leaf(slice_hrn) + ".ticket")
854         print "writing ticket to ", file        
855         ticket = SfaTicket(string=ticket_string)
856         ticket.save_to_file(filename=file, save_parents=True)
857
858     def redeem_ticket(self, opts, args):
859         ticket_file = args[0]
860         
861         # get slice hrn from the ticket
862         # use this to get the right slice credential 
863         ticket = SfaTicket(filename=ticket_file)
864         ticket.decode()
865         slice_hrn = ticket.gidObject.get_hrn()
866         #slice_hrn = ticket.attributes['slivers'][0]['hrn']
867         user_cred = self.get_user_cred()
868         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
869         
870         # get a list node hostnames from the nodespecs in the rspec 
871         rspec = RSpec()
872         rspec.parseString(ticket.rspec)
873         nodespecs = rspec.getDictsByTagName('NodeSpec')
874         hostnames = [nodespec['name'] for nodespec in nodespecs]
875         
876         # create an xmlrpc connection to the component manager at each of these
877         # components and gall redeem_ticket
878         connections = {}
879         for hostname in hostnames:
880             try:
881                 cm_port = "12346" 
882                 url = "https://%(hostname)s:%(cm_port)s" % locals() 
883                 print "Calling redeem_ticket at %(url)s " % locals(),
884                 cm = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file, self.options.debug)
885                 cm.redeem_ticket(slice_cred, ticket.save_to_string(save_parents=True))
886                 print "Success"
887             except socket.gaierror:
888                 print "Failed:",
889                 print "Componet Manager not accepting requests" 
890             except Exception, e:
891                 print "Failed:", e.message
892              
893         return
894  
895     # delete named slice
896     def delete(self, opts, args):
897         slice_hrn = args[0]
898         server = self.slicemgr
899         # direct connection to the nodes component manager interface
900         if opts.component:
901             server = self.get_component_server_from_hrn(opts.component)
902  
903         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
904         return server.delete_slice(slice_cred, slice_hrn)
905     
906     # start named slice
907     def start(self, opts, args):
908         slice_hrn = args[0]
909         server = self.slicemgr
910         # direct connection to the nodes component manager interface
911         if opts.component:
912             server = self.get_component_server_from_hrn(opts.component)
913  
914         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
915         return server.start_slice(slice_cred, slice_hrn)
916     
917     # stop named slice
918     def stop(self, opts, args):
919         slice_hrn = args[0]
920         server = self.slicemgr
921         # direct connection to the nodes component manager interface
922         if opts.component:
923             server = self.get_component_server_from_hrn(opts.component)
924
925         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
926         return server.stop_slice(slice_cred, slice_hrn)
927     
928     # reset named slice
929     def reset(self, opts, args):
930         slice_hrn = args[0]
931         server = self.slicemgr
932         # direct connection to the nodes component manager interface
933         if opts.component:
934             server = self.get_component_server_from_hrn(opts.component)
935         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
936         return server.reset_slice(slice_cred, slice_hrn)
937
938
939     # GENI AM related calls
940
941     def GetVersion(self, opts, args):
942         server = self.geni_am
943         print server.GetVersion()
944
945     def ListResources(self, opts, args):
946         user_cred = self.get_user_cred().save_to_string(save_parents=True)
947         server = self.geni_am
948         call_options = {'geni_compressed': True}
949         xrn = None
950         cred = user_cred
951         if args:
952             xrn = args[0]
953             cred = self.get_slice_cred(xrn).save_to_string(save_parents=True)
954
955         if xrn:
956             call_options['geni_slice_urn'] = xrn
957             
958         rspec = server.ListResources([cred], call_options)
959         rspec = zlib.decompress(rspec.decode('base64'))
960         print rspec
961         
962     def CreateSliver(self, opts, args):
963         slice_xrn = args[0]
964         slice_cred = self.get_slice_cred(slice_xrn).save_to_string(save_parents=True)
965         rspec_file = self.get_rspec_file(args[1])
966         rspec = open(rspec_file).read()
967         server = self.geni_am
968         return server.CreateSliver(slice_xrn, [slice_cred], rspec)
969     
970     def DeleteSliver(self, opts, args):
971         slice_xrn = args[0]
972         slice_cred = self.get_slice_cred(slice_xrn).save_to_string(save_parents=True)
973         server = self.geni_am
974         return server.DeleteSliver(slice_xrn, [slice_cred])    
975
976     def SliverStatus(self, opts, args):
977         slice_xrn = args[0]
978         slice_cred = self.get_slice_cred(slice_xrn).save_to_string(save_parents=True)
979         server = self.geni_am
980         print server.SliverStatus(slice_xrn, [slice_cred])
981     
982     def RenewSliver(self, opts, args):
983         slice_xrn = args[0]
984         slice_cred = self.get_slice_cred(slice_xrn).save_to_string(save_parents=True)
985         time = args[1]
986         server = self.geni_am
987         return server.RenewSliver(slice_xrn, [slice_cred], time)   
988
989     def Shutdown(self, opts, args):
990         slice_xrn = args[0]
991         slice_cred = self.get_slice_cred(slice_xrn).save_to_string(save_parents=True)
992         server = self.geni_am
993         return server.Shutdown(slice_xrn, [slice_cred])         
994     
995     #
996     # Main: parse arguments and dispatch to command
997     #
998     def main(self):
999         parser = self.create_parser()
1000         (options, args) = parser.parse_args()
1001         self.options = options
1002    
1003         if options.hashrequest:
1004             self.hashrequest = True
1005  
1006         if len(args) <= 0:
1007             print "No command given. Use -h for help."
1008             return - 1
1009     
1010         command = args[0]
1011         (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
1012         if self.options.verbose :
1013             print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry, options.sm,
1014                                                                    options.sfi_dir, options.user,
1015                                                                    options.auth)
1016             print "Command %s" % command
1017             if command in ("resources"):
1018                 print "resources cmd_opts %s" % cmd_opts.format
1019             elif command in ("list", "show", "remove"):
1020                 print "cmd_opts.type %s" % cmd_opts.type
1021             print "cmd_args %s" % cmd_args
1022     
1023         self.set_servers()
1024     
1025         try:
1026             self.dispatch(command, cmd_opts, cmd_args)
1027         except KeyError:
1028             raise 
1029             print "Command not found:", command
1030             sys.exit(1)
1031     
1032         return
1033     
1034 if __name__ == "__main__":
1035    Sfi().main()