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