get_user_cred(), get_auth_cred() and get_slice_cred() all return objects...for now...
[sfa.git] / sfa / client / sfi.py
1 #! /usr/bin/env python
2
3 # sfi -- slice-based facility interface
4
5 import sys
6 import os, os.path
7 import tempfile
8 import traceback
9 from types import StringTypes, ListType
10 from optparse import OptionParser
11
12 from sfa.trust.certificate import Keypair, Certificate
13 from sfa.trust.credential import Credential
14 from sfa.util.geniclient import GeniClient
15 from sfa.util.record import *
16 from sfa.util.rspec import Rspec
17 from sfa.util.xmlrpcprotocol import ServerException
18 import sfa.util.xmlrpcprotocol as xmlrpcprotocol
19 import sfa.util.soapprotocol as soapprotocol
20 from sfa.util.config import Config
21
22 class Sfi:
23     
24     slicemgr = None
25     registry = None
26     user = None
27     authority = None
28     options = None
29     
30     #
31     # Establish Connection to SliceMgr and Registry Servers
32     #
33     def set_servers(self):
34        config_file = self.options.sfi_dir + os.sep + "sfi_config"
35        try:
36           config = Config (config_file)
37        except:
38           print "Failed to read configuration file",config_file
39           print "Make sure to remove the export clauses and to add quotes"
40           if not self.options.verbose:
41              print "Re-run with -v for more details"
42           else:
43              traceback.print_exc()
44           sys.exit(1)
45     
46        errors=0
47        # Set SliceMgr URL
48        if (self.options.sm is not None):
49           sm_url = self.options.sm
50        elif hasattr(config,"SFI_SM"):
51           sm_url = config.SFI_SM
52        else:
53           print "You need to set e.g. SFI_SM='http://your.slicemanager.url:12347/' in %s"%config_file
54           errors +=1 
55     
56        # Set Registry URL
57        if (self.options.registry is not None):
58           reg_url = self.options.registry
59        elif hasattr(config,"SFI_REGISTRY"):
60           reg_url = config.SFI_REGISTRY
61        else:
62           print "You need to set e.g. SFI_REGISTRY='http://your.registry.url:12345/' in %s"%config_file
63           errors +=1 
64     
65        # Set user HRN
66        if (self.options.user is not None):
67           self.user = self.options.user
68        elif hasattr(config,"SFI_USER"):
69           self.user = config.SFI_USER
70        else:
71           print "You need to set e.g. SFI_USER='plc.princeton.username' in %s"%config_file
72           errors +=1 
73     
74        # Set authority HRN
75        if (self.options.auth is not None):
76           self.authority = self.options.auth
77        elif hasattr(config,"SFI_AUTH"):
78           self.authority = config.SFI_AUTH
79        else:
80           print "You need to set e.g. SFI_AUTH='plc.princeton' in %s"%config_file
81           errors +=1 
82     
83        if errors:
84           sys.exit(1)
85     
86        if self.options.verbose :
87           print "Contacting Slice Manager at:", sm_url
88           print "Contacting Registry at:", reg_url
89     
90        # Get key and certificate
91        key_file = self.get_key_file()
92        cert_file = self.get_cert_file(key_file)
93        self.key = Keypair(filename=key_file) 
94        self.key_file = key_file
95        self.cert_file = cert_file
96        self.cert = Certificate(filename=cert_file) 
97        # Establish connection to server(s)
98        #self.slicemgr = GeniClient(sm_url, key_file, cert_file, self.options.protocol)
99        #self.registry = GeniClient(reg_url, key_file, cert_file, self.options.protocol)
100        self.registry = xmlrpcprotocol.get_server(reg_url, key_file, cert_file)  
101        self.slicemgr = xmlrpcprotocol.get_server(sm_url, key_file, cert_file)  
102        return
103     
104     #
105     # Get various credential and spec files
106     #
107     # Establishes limiting conventions
108     #   - conflates MAs and SAs
109     #   - assumes last token in slice name is unique
110     #
111     # Bootstraps credentials
112     #   - bootstrap user credential from self-signed certificate
113     #   - bootstrap authority credential from user credential
114     #   - bootstrap slice credential from user credential
115     #
116     
117     def get_leaf(self,name):
118        parts = name.split(".")
119        return parts[-1]
120     
121     def get_key_file(self):
122        file = os.path.join(self.options.sfi_dir, self.get_leaf(self.user) + ".pkey")
123        if (os.path.isfile(file)):
124           return file
125        else:
126           print "Key file", file, "does not exist"
127           sys.exit(-1)
128        return
129     
130     def get_cert_file(self,key_file):
131     
132        file = os.path.join(self.options.sfi_dir, self.get_leaf(self.user) + ".cert")
133        if (os.path.isfile(file)):
134           return file
135        else:
136           k = Keypair(filename = key_file)
137           cert = Certificate(subject=self.user)
138           cert.set_pubkey(k)
139           cert.set_issuer(k, self.user)
140           cert.sign()
141           if self.options.verbose :
142              print "Writing self-signed certificate to", file
143           cert.save_to_file(file)
144           return file
145    
146     def get_gid(self):
147         file = os.path.join(self.options.sfi_dir, self.get_leaf(self.user) + ".gid")
148         if (os.path.isfile(file)):
149             gid = GID(filename=file)
150             return gid
151         else:
152             cert_str = self.cert.save_to_string(save_parents=True)
153             request_hash = self.key.compute_hash([cert_str, self.user, "user"])
154             gid_str = self.registry.get_gid(cert_str, self.user, "user", request_hash)
155             gid = GID(string=gid_str)
156             if self.options.verbose:
157                 print "Writing user gid to", file
158             gid.save_to_file(file, save_parents=True)
159             return gid       
160  
161     def get_user_cred(self):
162         file = os.path.join(self.options.sfi_dir, self.get_leaf(self.user) + ".cred")
163         if (os.path.isfile(file)):
164             user_cred = Credential(filename=file)
165             return user_cred
166         else:
167             # bootstrap user credential
168             cert_string = self.cert.save_to_string(save_parents=True)
169             request_hash = self.key.compute_hash([cert_string, "user", self.user])
170             user_cred = self.registry.get_self_credential(cert_string, "user", self.user, request_hash)
171             if user_cred:
172                cred = Credential(string=user_cred)
173                cred.save_to_file(file, save_parents=True)
174                if self.options.verbose:
175                     print "Writing user credential to", file
176                return cred
177             else:
178                print "Failed to get user credential"
179                sys.exit(-1)
180     
181     def get_auth_cred(self):
182     
183        if not self.authority:
184           print "no authority specified. Use -a or set SF_AUTH"
185           sys.exit(-1)
186     
187        file = os.path.join(self.options.sfi_dir, self.get_leaf("authority") +".cred")
188        if (os.path.isfile(file)):
189           auth_cred = Credential(filename=file)
190           return auth_cred
191        else:
192           # bootstrap authority credential from user credential
193           user_cred = self.get_user_cred().save_to_string(save_parents=True)
194           request_hash = self.key.compute_hash([user_cred, "authority", self.authority])
195           auth_cred = self.registry.get_credential(user_cred, "authority", self.authority, request_hash)
196           if auth_cred:
197              cred = Credential(string=auth_cred)
198              cred.save_to_file(file, save_parents=True)
199              if self.options.verbose:
200                 print "Writing authority credential to", file
201              return cred
202           else:
203              print "Failed to get authority credential"
204              sys.exit(-1)
205     
206     def get_slice_cred(self,name):
207        file = os.path.join(self.options.sfi_dir, "slice_" + self.get_leaf(name) + ".cred")
208        if (os.path.isfile(file)):
209           slice_cred = Credential(filename=file)
210           return slice_cred
211        else:
212           # bootstrap slice credential from user credential
213           user_cred = self.get_user_cred().save_to_string(save_parents=True)
214           arg_list = [user_cred, "slice", name]
215           request_hash = self.key.compute_hash(arg_list)  
216           slice_cred_str = self.registry.get_credential(user_cred, "slice", name, request_hash)
217           if slice_cred:
218              slice_cred = Credential(string=slice_cred_str)
219              slice_cred.save_to_file(file, save_parents=True)
220              if self.options.verbose:
221                 print "Writing slice credential to", file
222              return slice_cred
223           else:
224              print "Failed to get slice credential"
225              sys.exit(-1)
226     
227     def delegate_cred(self,cred, hrn, type = 'authority'):
228         # the gid and hrn of the object we are delegating
229         object_gid = cred.get_gid_object()
230         object_hrn = object_gid.get_hrn()
231         cred.set_delegate(True)
232         if not cred.get_delegate():
233             raise Exception, "Error: Object credential %(object_hrn)s does not have delegate bit set" % locals()
234            
235     
236         records = self.registry.resolve(cred, hrn)
237         records = self.filter_records(type, records)
238         
239         if not records:
240             raise Exception, "Error: Didn't find a %(type)s record for %(hrn)s" % locals()
241     
242         # the gid of the user who will be delegated too
243         delegee_gid = records[0].get_gid_object()
244         delegee_hrn = delegee_gid.get_hrn()
245         
246         # the key and hrn of the user who will be delegating
247         user_key = Keypair(filename = self.get_key_file())
248         user_hrn = cred.get_gid_caller().get_hrn()
249     
250         dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
251         dcred.set_gid_caller(delegee_gid)
252         dcred.set_gid_object(object_gid)
253         dcred.set_privileges(cred.get_privileges())
254         dcred.set_delegate(True)
255         dcred.set_pubkey(object_gid.get_pubkey())
256         dcred.set_issuer(user_key, user_hrn)
257         dcred.set_parent(cred)
258         dcred.encode()
259         dcred.sign()
260     
261         return dcred
262     
263     def get_rspec_file(self,rspec):
264        if (os.path.isabs(rspec)):
265           file = rspec
266        else:
267           file = os.path.join(self.options.sfi_dir, rspec)
268        if (os.path.isfile(file)):
269           return file
270        else:
271           print "No such rspec file", rspec
272           sys.exit(1)
273     
274     def get_record_file(self,record):
275        if (os.path.isabs(record)):
276           file = record
277        else:
278           file = os.path.join(self.options.sfi_dir, record)
279        if (os.path.isfile(file)):
280           return file
281        else:
282           print "No such registry record file", record
283           sys.exit(1)
284     
285     def load_publickey_string(self,fn):
286        f = file(fn,"r")
287        key_string = f.read()
288     
289        # if the filename is a private key file, then extract the public key
290        if "PRIVATE KEY" in key_string:
291            outfn = tempfile.mktemp()
292            cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
293            os.system(cmd)
294            f = file(outfn, "r")
295            key_string = f.read()
296            os.remove(outfn)
297     
298        return key_string
299     #
300     # Generate sub-command parser
301     #
302     def create_cmd_parser(self,command, additional_cmdargs = None):
303        cmdargs = {"gid": "",
304                   "list": "name",
305                   "show": "name",
306                   "remove": "name",
307                   "add": "record",
308                   "update": "record",
309                   "aggregates": "[name]",
310                   "registries": "[name]",   
311                   "slices": "",
312                   "resources": "[name]",
313                   "create": "name rspec",
314                   "delete": "name",
315                   "reset": "name",
316                   "start": "name",
317                   "stop": "name",
318                   "delegate": "name"
319                  }
320     
321        if additional_cmdargs:
322           cmdargs.update(additional_cmdargs)
323     
324        if command not in cmdargs:
325           print "Invalid command\n"
326           print "Commands: ",
327           for key in cmdargs.keys():
328               print key+",",
329           print ""
330           sys.exit(2)
331     
332        parser = OptionParser(usage="sfi [sfi_options] %s [options] %s" \
333           % (command, cmdargs[command]))
334
335        if command in ("resources"):
336            parser.add_option("-f", "--format", dest="format",type="choice",
337                              help="display format ([xml]|dns|ip)",default="xml",
338                              choices=("xml","dns","ip"))
339            parser.add_option("-a", "--aggregate", dest="aggregate",
340                              default=None, help="aggregate hrn")  
341     
342        if command in ("create"):
343            parser.add_option("-a", "--aggregate", dest="aggregate",default=None,
344                              help="aggregate hrn") 
345  
346        if command in ("list", "show", "remove"):
347           parser.add_option("-t", "--type", dest="type",type="choice",
348                             help="type filter ([all]|user|slice|sa|ma|node|aggregate)",
349                             choices=("all","user","slice","sa","ma","node","aggregate"),
350                             default="all")
351
352        if command in ("resources", "show", "list"):
353           parser.add_option("-o", "--output", dest="file",
354                             help="output XML to file", metavar="FILE", default=None)
355
356        if command in ("show", "list"):
357            parser.add_option("-f", "--format", dest="format", type="choice", 
358                              help="display format ([text]|xml)",default="text", 
359                              choices=("text","xml")) 
360
361        if command in ("delegate"):
362           parser.add_option("-u", "--user",
363                             action="store_true", dest="delegate_user", default=False,
364                             help="delegate user credential")
365           parser.add_option("-s", "--slice", dest="delegate_slice",
366                             help="delegate slice credential", metavar="HRN", default=None)
367        return parser
368     
369     def create_parser(self):
370
371        # Generate command line parser
372        parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
373                              description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
374        parser.add_option("-r", "--registry", dest="registry",
375                          help="root registry", metavar="URL", default=None)
376        parser.add_option("-s", "--slicemgr", dest="sm",
377                          help="slice manager", metavar="URL", default=None)
378        default_sfi_dir=os.path.expanduser("~/.sfi/")
379        parser.add_option("-d", "--dir", dest="sfi_dir",
380                          help="config & working directory - default is " + default_sfi_dir,
381                          metavar="PATH", default = default_sfi_dir)
382        parser.add_option("-u", "--user", dest="user",
383                          help="user name", metavar="HRN", default=None)
384        parser.add_option("-a", "--auth", dest="auth",
385                          help="authority name", metavar="HRN", default=None)
386        parser.add_option("-v", "--verbose",
387                          action="store_true", dest="verbose", default=False,
388                          help="verbose mode")
389        parser.add_option("-p", "--protocol",
390                          dest="protocol", default="xmlrpc",
391                          help="RPC protocol (xmlrpc or soap)")
392        parser.disable_interspersed_args()
393     
394        return parser
395     
396     def dispatch(self,command, cmd_opts, cmd_args):
397        getattr(self,command)(cmd_opts, cmd_args)
398     
399     #
400     # Following functions implement the commands
401     #
402     # Registry-related commands
403     #
404    
405     def gid(self, opts, args):
406        gid = self.get_gid()
407        print "GID: %s" % (gid.save_to_string(save_parents=True))
408        return   
409  
410     # list entires in named authority registry
411     def list(self,opts, args):
412        user_cred = self.get_user_cred().save_to_string(save_parents=True)
413        hrn = args[0]
414        request_hash = self.key.compute_hash([user_cred, hrn])    
415        try:
416           list = self.registry.list(user_cred, hrn, request_hash)
417        except IndexError:
418           raise Exception, "Not enough parameters for the 'list' command"
419           
420        # filter on person, slice, site, node, etc.  
421        # THis really should be in the self.filter_records funct def comment...
422        list = self.filter_records(opts.type, list)
423        for record in list:
424            print "%s (%s)" % (record['hrn'], record['type'])     
425        if opts.file:
426            self.save_records_to_file(opts.file, list)
427        return
428     
429     # show named registry record
430     def show(self,opts, args):
431        user_cred = self.get_user_cred().save_to_string(save_parents=True)
432        hrn = args[0]
433        request_hash = self.key.compute_hash([user_cred, hrn])    
434        records = self.registry.resolve(user_cred, hrn, request_hash)
435        records = self.filter_records(opts.type, records)
436        if not records:
437           print "No record of type", opts.type
438        for record in records:
439            if record['type'] in ['user']:
440                record = UserRecord(dict = record)
441            elif record['type'] in ['slice']:
442                record = SliceRecord(dict = record)
443            elif record['type'] in ['node']:
444                record = NodeRecord(dict = record)
445            elif record['type'] in ['authority', 'ma', 'sa']:
446                record = AuthorityRecord(dict = record)
447            else:
448                record = GeniRecord(dict = record)
449            if (opts.format=="text"): 
450                record.dump()  
451            else: 
452                print record.save_to_string() 
453        
454        if opts.file:
455            self.save_records_to_file(opts.file, records)
456        return
457     
458     def delegate(self,opts, args):
459        user_cred = self.get_user_cred()
460        if opts.delegate_user:
461            object_cred = user_cred
462        elif opts.delegate_slice:
463            object_cred = self.get_slice_cred(opts.delegate_slice)
464        else:
465            print "Must specify either --user or --slice <hrn>"
466            return
467     
468        # the gid and hrn of the object we are delegating
469        object_gid = object_cred.get_gid_object()
470        object_hrn = object_gid.get_hrn()
471     
472        if not object_cred.get_delegate():
473            print "Error: Object credential", object_hrn, "does not have delegate bit set"
474            return
475     
476        records = self.registry.resolve(user_cred, args[0])
477        records = self.filter_records("user", records)
478     
479        if not records:
480            print "Error: Didn't find a user record for", args[0]
481            return
482     
483        # the gid of the user who will be delegated too
484        delegee_gid = records[0].get_gid_object()
485        delegee_hrn = delegee_gid.get_hrn()
486     
487        # the key and hrn of the user who will be delegating
488        user_key = Keypair(filename = self.get_key_file())
489        user_hrn = user_cred.get_gid_caller().get_hrn()
490     
491        dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
492        dcred.set_gid_caller(delegee_gid)
493        dcred.set_gid_object(object_gid)
494        dcred.set_privileges(object_cred.get_privileges())
495        dcred.set_delegate(True)
496        dcred.set_pubkey(object_gid.get_pubkey())
497        dcred.set_issuer(user_key, user_hrn)
498        dcred.set_parent(object_cred)
499        dcred.encode()
500        dcred.sign()
501     
502        if opts.delegate_user:
503            dest_fn = os.path.join(self.options.sfi_dir, self.get_leaf(delegee_hrn) + "_" 
504                                   + self.get_leaf(object_hrn) + ".cred")
505        elif opts.delegate_slice:
506            dest_fn = os.path_join(self.options.sfi_dir, self.get_leaf(delegee_hrn) + "_slice_" 
507                                   + self.get_leaf(object_hrn) + ".cred")
508     
509        dcred.save_to_file(dest_fn, save_parents = True)
510     
511        print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
512     
513     # removed named registry record
514     #   - have to first retrieve the record to be removed
515     def remove(self,opts, args):
516        auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
517        hrn = args[0]
518        type = opts.type 
519        if type in ['all']:
520            type = '*'
521        arg_list = [auth_cred, type, hrn]
522        request_hash = self.key.compute_hash(arg_list)                   
523        return self.registry.remove(auth_cred, type, hrn, request_hash)
524     
525     # add named registry record
526     def add(self,opts, args):
527        auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
528        record_filepath = args[0]
529        rec_file = self.get_record_file(record_filepath)
530        record = self.load_record_from_file(rec_file).as_dict()
531        arg_list = [auth_cred]
532        request_hash = self.key.compute_hash(arg_list)
533        return self.registry.register(auth_cred, record, request_hash)
534     
535     # update named registry entry
536     def update(self,opts, args):
537        user_cred = self.get_user_cred()
538        rec_file = self.get_record_file(args[0])
539        record = self.load_record_from_file(rec_file)
540        if record['type'] == "user":
541            if record.get_name() == user_cred.get_gid_object().get_hrn():
542               cred = user_cred.save_to_string(save_parents=True)
543            else:
544               cred = self.get_auth_cred().save_to_string(save_parents=True)
545        elif record['type'] in ["slice"]:
546            try:
547                cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
548            except ServerException, e:
549                # XXX smbaker -- once we have better error return codes, update this
550                # to do something better than a string compare
551                if "Permission error" in e.args[0]:
552                    cred = self.get_auth_cred().save_to_string(save_parents=True)
553                else:
554                    raise
555        elif record.get_type() in ["authority"]:
556            cred = self.get_auth_cred().save_to_string(save_parents=True)
557        elif record.get_type() == 'node':
558            cred = self.get_auth_cred().save_to_string(save_parents=True)
559        else:
560            raise "unknown record type" + record.get_type()
561        record = record.as_dict()
562        arg_list = [cred]  
563        request_hash = self.key.compute_hash(arg_list)
564        return self.registry.update(cred, record, request_hash)
565    
566     
567     def aggregates(self, opts, args):
568         user_cred = self.get_user_cred().save_to_string(save_parents=True)
569         hrn = None
570         if args: 
571             hrn = args[0]
572         arg_list = [user_cred, hrn]  
573         request_hash = self.key.compute_hash(arg_list)
574         result = self.registry.get_aggregates(user_cred, hrn, request_hash)
575         self.display_list(result)
576         return 
577
578     def registries(self, opts, args):
579         user_cred = self.get_user_cred().save_to_string(save_parents=True)
580         hrn = None
581         if args:
582             hrn = args[0]
583         arg_list = [user_cred, hrn]  
584         request_hash = self.key.compute_hash(arg_list)
585         result = self.registry.get_registries(user_cred, hrn, request_hash)
586         self.display_list(result)
587         return
588  
589     #
590     # Slice-related commands
591     #
592     
593     # list available nodes -- use 'resources' w/ no argument instead
594
595     # list instantiated slices
596     def slices(self,opts, args):
597         user_cred = self.get_user_cred().save_to_string(save_parents=True)
598         arg_list = [user_cred]
599         request_hash = self.key.compute_hash(arg_list)
600         results = self.slicemgr.get_slices(user_cred, request_hash)
601         self.display_list(results)
602         return
603     
604     # show rspec for named slice
605     def resources(self,opts, args):
606         user_cred = self.get_user_cred().save_to_string(save_parents=True)
607         server = self.slicemgr
608         if opts.aggregate:
609             agg_hrn = opts.aggregate
610             arg_list = [user_cred, arg_hrn]
611             request_hash = self.key.compute_hash(arg_list)
612             aggregates = self.registry.get_aggregates(user_cred, agg_hrn, request_hash)
613             if not aggregates:
614                 raise Exception, "No such aggregate %s" % agg_hrn
615             aggregate = aggregates[0]
616             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])     
617             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
618         if args:
619             cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
620             hrn = args[0]
621         else:
622             cred = user_cred
623             hrn = None
624
625         arg_list = [cred, hrn]
626         request_hash = self.key.compute_hash(arg_list)  
627         result = server.get_resources(cred, hrn, request_hash)
628         format = opts.format
629        
630         self.display_rspec(result, format)
631         if (opts.file is not None):
632             self.save_rspec_to_file(result, opts.file)
633         return
634     
635     # created named slice with given rspec
636     def create(self,opts, args):
637        slice_hrn = args[0]
638        user_cred = self.get_user_cred()
639        slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
640        rspec_file = self.get_rspec_file(args[1])
641        rspec=open(rspec_file).read()
642        server = self.slicemgr
643        if opts.aggregate:
644            aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
645            if not aggregates:
646                raise Exception, "No such aggregate %s" % opts.aggregate
647            aggregate = aggregates[0]
648            url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
649            server = GeniClient(url, self.key_file, self.cert_file, self.options.protocol)
650        arg_list = [slice_cred, slice_hrn, rspec]
651        request_hash = self.key.compute_hash(arg_list) 
652        return server.create_slice(slice_cred, slice_hrn, rspec, request_hash)
653     
654     # delete named slice
655     def delete(self,opts, args):
656         slice_hrn = args[0]
657         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
658         arg_list = [slice_cred, slice_hrn]
659         request_hash = self.key.compute_hash(arg_list) 
660         return self.slicemgr.delete_slice(slice_cred, slice_hrn, request_hash)
661     
662     # start named slice
663     def start(self,opts, args):
664         slice_hrn = args[0]
665         slice_cred = self.get_slice_cred(args[0])
666         arg_list = [slice_cred, slice_hrn]
667         request_hash = self.key.compute_hash(arg_list)
668         return self.slicemgr.start_slice(slice_cred, slice_hrn, request_hash)
669     
670     # stop named slice
671     def stop(self,opts, args):
672         slice_hrn = args[0]
673         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
674         arg_list = [slice_cred, slice_hrn]
675         request_hash = self.key.compute_hash(arg_list)
676         return self.slicemgr.stop_slice(slice_cred, slice_hrn, request_hash)
677     
678     # reset named slice
679     def reset(self,opts, args):
680         slice_hrn = args[0]
681         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
682         arg_list = [slice_cred, slice_hrn]
683         request_hash = self.key.compute_hash(arg_list)
684         return self.slicemgr.reset_slice(slice_cred, slice_hrn, request_hash)
685     
686     #
687     #
688     # Display, Save, and Filter RSpecs and Records
689     #   - to be replace by EMF-generated routines
690     #
691     #
692     
693     def display_rspec(self,rspec, format = 'rspec'):
694         if format in ['dns']:
695             spec = Rspec()
696             spec.parseString(rspec)
697             hostnames = []
698             nodespecs = spec.getDictsByTagName('NodeSpec')
699             for nodespec in nodespecs:
700                 if nodespec.has_key('name') and nodespec['name']:
701                     if isinstance(nodespec['name'], ListType):
702                         hostnames.extend(nodespec['name'])
703                     elif isinstance(nodespec['name'], StringTypes):
704                         hostnames.append(nodespec['name'])
705             result = hostnames
706         elif format in ['ip']:
707             spec = Rspec()
708             spec.parseString(rspec)
709             ips = []
710             ifspecs = spec.getDictsByTagName('IfSpec')
711             for ifspec in ifspecs:
712                 if ifspec.has_key('addr') and ifspec['addr']:
713                     ips.append(ifspec['addr'])
714             result = ips 
715         else:     
716             result = rspec
717     
718         print result
719         return
720     
721     def display_list(self,results):
722         for result in results:
723             print result
724     
725     def save_rspec_to_file(self,rspec, filename):
726        if not filename.startswith(os.sep):
727            filename = self.options.sfi_dir + filename
728        if not filename.endswith(".rspec"):
729            filename = filename + ".rspec"
730     
731        f = open(filename, 'w')
732        f.write(rspec)
733        f.close()
734        return
735     
736     def display_records(self,recordList, dump = False):
737        ''' Print all fields in the record'''
738        for record in recordList:
739           self.display_record(record, dump)
740     
741     def display_record(self,record, dump = False):
742        if dump:
743            record.dump()
744        else:
745            info = record.getdict()
746            print "%s (%s)" % (info['hrn'], info['type'])
747        return
748     
749     def filter_records(self,type, records):
750        filtered_records = []
751        for record in records:
752            if (record['type'] == type) or (type == "all"):
753                filtered_records.append(record)
754        return filtered_records
755     
756     def save_records_to_file(self,filename, recordList):
757        index = 0
758        for record in recordList:
759            if index>0:
760                self.save_record_to_file(filename + "." + str(index), record)
761            else:
762                self.save_record_to_file(filename, record)
763            index = index + 1
764     
765     def save_record_to_file(self,filename, record):
766        if record['type'] in ['user']:
767            record = UserRecord(dict = record)
768        elif record['type'] in ['slice']:
769            record = SliceRecord(dict = record)
770        elif record['type'] in ['node']:
771            record = NodeRecord(dict = record)
772        elif record['type'] in ['authority', 'ma', 'sa']:
773           record = AuthorityRecord(dict = record)
774        else:
775            record = GeniRecord(dict = record) 
776        if not filename.startswith(os.sep):
777            filename = self.options.sfi_dir + filename
778        str = record.save_to_string()
779        file(filename, "w").write(str)
780        return
781     
782     def load_record_from_file(self,filename):
783        str = file(filename, "r").read()
784        record = GeniRecord(string=str)
785        return record
786     
787     #
788     # Main: parse arguments and dispatch to command
789     #
790     def main(self):
791        parser = self.create_parser()
792        (options, args) = parser.parse_args()
793        self.options = options
794     
795        if len(args) <= 0:
796             print "No command given. Use -h for help."
797             return -1
798     
799        command = args[0]
800        (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
801        if self.options.verbose :
802           print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry,
803                                                                    options.sm,
804                                                                    options.sfi_dir,
805                                                                    options.user,
806                                                                    options.auth)
807           print "Command %s" %command
808           if command in ("resources"):
809              print "resources cmd_opts %s" %cmd_opts.format
810           elif command in ("list","show","remove"):
811              print "cmd_opts.type %s" %cmd_opts.type
812           print "cmd_args %s" %cmd_args
813     
814        self.set_servers()
815     
816        try:
817           self.dispatch(command, cmd_opts, cmd_args)
818        except KeyError:
819           raise 
820           print "Command not found:", command
821           sys.exit(1)
822     
823        return
824     
825 if __name__=="__main__":
826    Sfi().main()