explicitly call get_self_credential with the cliet cert as in argument instead of...
[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()
214           slice_cred = self.registry.get_credential(user_cred, "slice", name)
215           if slice_cred:
216              slice_cred.save_to_file(file, save_parents=True)
217              if self.options.verbose:
218                 print "Writing slice credential to", file
219              return slice_cred
220           else:
221              print "Failed to get slice credential"
222              sys.exit(-1)
223     
224     def delegate_cred(self,cred, hrn, type = 'authority'):
225         # the gid and hrn of the object we are delegating
226         object_gid = cred.get_gid_object()
227         object_hrn = object_gid.get_hrn()
228         cred.set_delegate(True)
229         if not cred.get_delegate():
230             raise Exception, "Error: Object credential %(object_hrn)s does not have delegate bit set" % locals()
231            
232     
233         records = self.registry.resolve(cred, hrn)
234         records = self.filter_records(type, records)
235         
236         if not records:
237             raise Exception, "Error: Didn't find a %(type)s record for %(hrn)s" % locals()
238     
239         # the gid of the user who will be delegated too
240         delegee_gid = records[0].get_gid_object()
241         delegee_hrn = delegee_gid.get_hrn()
242         
243         # the key and hrn of the user who will be delegating
244         user_key = Keypair(filename = self.get_key_file())
245         user_hrn = cred.get_gid_caller().get_hrn()
246     
247         dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
248         dcred.set_gid_caller(delegee_gid)
249         dcred.set_gid_object(object_gid)
250         dcred.set_privileges(cred.get_privileges())
251         dcred.set_delegate(True)
252         dcred.set_pubkey(object_gid.get_pubkey())
253         dcred.set_issuer(user_key, user_hrn)
254         dcred.set_parent(cred)
255         dcred.encode()
256         dcred.sign()
257     
258         return dcred
259     
260     def get_rspec_file(self,rspec):
261        if (os.path.isabs(rspec)):
262           file = rspec
263        else:
264           file = os.path.join(self.options.sfi_dir, rspec)
265        if (os.path.isfile(file)):
266           return file
267        else:
268           print "No such rspec file", rspec
269           sys.exit(1)
270     
271     def get_record_file(self,record):
272        if (os.path.isabs(record)):
273           file = record
274        else:
275           file = os.path.join(self.options.sfi_dir, record)
276        if (os.path.isfile(file)):
277           return file
278        else:
279           print "No such registry record file", record
280           sys.exit(1)
281     
282     def load_publickey_string(self,fn):
283        f = file(fn,"r")
284        key_string = f.read()
285     
286        # if the filename is a private key file, then extract the public key
287        if "PRIVATE KEY" in key_string:
288            outfn = tempfile.mktemp()
289            cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
290            os.system(cmd)
291            f = file(outfn, "r")
292            key_string = f.read()
293            os.remove(outfn)
294     
295        return key_string
296     #
297     # Generate sub-command parser
298     #
299     def create_cmd_parser(self,command, additional_cmdargs = None):
300        cmdargs = {"gid": "",
301                   "list": "name",
302                   "show": "name",
303                   "remove": "name",
304                   "add": "record",
305                   "update": "record",
306                   "aggregates": "[name]",
307                   "registries": "[name]",   
308                   "slices": "",
309                   "resources": "[name]",
310                   "create": "name rspec",
311                   "delete": "name",
312                   "reset": "name",
313                   "start": "name",
314                   "stop": "name",
315                   "delegate": "name"
316                  }
317     
318        if additional_cmdargs:
319           cmdargs.update(additional_cmdargs)
320     
321        if command not in cmdargs:
322           print "Invalid command\n"
323           print "Commands: ",
324           for key in cmdargs.keys():
325               print key+",",
326           print ""
327           sys.exit(2)
328     
329        parser = OptionParser(usage="sfi [sfi_options] %s [options] %s" \
330           % (command, cmdargs[command]))
331
332        if command in ("resources"):
333            parser.add_option("-f", "--format", dest="format",type="choice",
334                              help="display format ([xml]|dns|ip)",default="xml",
335                              choices=("xml","dns","ip"))
336            parser.add_option("-a", "--aggregate", dest="aggregate",
337                              default=None, help="aggregate hrn")  
338     
339        if command in ("create"):
340            parser.add_option("-a", "--aggregate", dest="aggregate",default=None,
341                              help="aggregate hrn") 
342  
343        if command in ("list", "show", "remove"):
344           parser.add_option("-t", "--type", dest="type",type="choice",
345                             help="type filter ([all]|user|slice|sa|ma|node|aggregate)",
346                             choices=("all","user","slice","sa","ma","node","aggregate"),
347                             default="all")
348
349        if command in ("resources", "show", "list"):
350           parser.add_option("-o", "--output", dest="file",
351                             help="output XML to file", metavar="FILE", default=None)
352
353        if command in ("show", "list"):
354            parser.add_option("-f", "--format", dest="format", type="choice", 
355                              help="display format ([text]|xml)",default="text", 
356                              choices=("text","xml")) 
357
358        if command in ("delegate"):
359           parser.add_option("-u", "--user",
360                             action="store_true", dest="delegate_user", default=False,
361                             help="delegate user credential")
362           parser.add_option("-s", "--slice", dest="delegate_slice",
363                             help="delegate slice credential", metavar="HRN", default=None)
364        return parser
365     
366     def create_parser(self):
367
368        # Generate command line parser
369        parser = OptionParser(usage="sfi [options] command [command_options] [command_args]",
370                              description="Commands: gid,list,show,remove,add,update,nodes,slices,resources,create,delete,start,stop,reset")
371        parser.add_option("-r", "--registry", dest="registry",
372                          help="root registry", metavar="URL", default=None)
373        parser.add_option("-s", "--slicemgr", dest="sm",
374                          help="slice manager", metavar="URL", default=None)
375        default_sfi_dir=os.path.expanduser("~/.sfi/")
376        parser.add_option("-d", "--dir", dest="sfi_dir",
377                          help="config & working directory - default is " + default_sfi_dir,
378                          metavar="PATH", default = default_sfi_dir)
379        parser.add_option("-u", "--user", dest="user",
380                          help="user name", metavar="HRN", default=None)
381        parser.add_option("-a", "--auth", dest="auth",
382                          help="authority name", metavar="HRN", default=None)
383        parser.add_option("-v", "--verbose",
384                          action="store_true", dest="verbose", default=False,
385                          help="verbose mode")
386        parser.add_option("-p", "--protocol",
387                          dest="protocol", default="xmlrpc",
388                          help="RPC protocol (xmlrpc or soap)")
389        parser.disable_interspersed_args()
390     
391        return parser
392     
393     def dispatch(self,command, cmd_opts, cmd_args):
394        getattr(self,command)(cmd_opts, cmd_args)
395     
396     #
397     # Following functions implement the commands
398     #
399     # Registry-related commands
400     #
401    
402     def gid(self, opts, args):
403        gid = self.get_gid()
404        print "GID: %s" % (gid.save_to_string(save_parents=True))
405        return   
406  
407     # list entires in named authority registry
408     def list(self,opts, args):
409        user_cred = self.get_user_cred().save_to_string(save_parents=True)
410        hrn = args[0]
411        request_hash = self.key.compute_hash([user_cred, hrn])    
412        try:
413           list = self.registry.list(user_cred, hrn, request_hash)
414        except IndexError:
415           raise Exception, "Not enough parameters for the 'list' command"
416           
417        # filter on person, slice, site, node, etc.  
418        # THis really should be in the self.filter_records funct def comment...
419        list = self.filter_records(opts.type, list)
420        for record in list:
421            print "%s (%s)" % (record['hrn'], record['type'])     
422        if opts.file:
423            self.save_records_to_file(opts.file, list)
424        return
425     
426     # show named registry record
427     def show(self,opts, args):
428        user_cred = self.get_user_cred().save_to_string(save_parents=True)
429        hrn = args[0]
430        request_hash = self.key.compute_hash([user_cred, hrn])    
431        records = self.registry.resolve(user_cred, hrn, request_hash)
432        records = self.filter_records(opts.type, records)
433        if not records:
434           print "No record of type", opts.type
435        for record in records:
436            if record['type'] in ['user']:
437                record = UserRecord(dict = record)
438            elif record['type'] in ['slice']:
439                record = SliceRecord(dict = record)
440            elif record['type'] in ['node']:
441                record = NodeRecord(dict = record)
442            elif record['type'] in ['authority', 'ma', 'sa']:
443                record = AuthorityRecord(dict = record)
444            else:
445                record = GeniRecord(dict = record)
446            if (opts.format=="text"): 
447                record.dump()  
448            else: 
449                print record.save_to_string() 
450        
451        if opts.file:
452            self.save_records_to_file(opts.file, records)
453        return
454     
455     def delegate(self,opts, args):
456        user_cred = self.get_user_cred()
457        if opts.delegate_user:
458            object_cred = user_cred
459        elif opts.delegate_slice:
460            object_cred = self.get_slice_cred(opts.delegate_slice)
461        else:
462            print "Must specify either --user or --slice <hrn>"
463            return
464     
465        # the gid and hrn of the object we are delegating
466        object_gid = object_cred.get_gid_object()
467        object_hrn = object_gid.get_hrn()
468     
469        if not object_cred.get_delegate():
470            print "Error: Object credential", object_hrn, "does not have delegate bit set"
471            return
472     
473        records = self.registry.resolve(user_cred, args[0])
474        records = self.filter_records("user", records)
475     
476        if not records:
477            print "Error: Didn't find a user record for", args[0]
478            return
479     
480        # the gid of the user who will be delegated too
481        delegee_gid = records[0].get_gid_object()
482        delegee_hrn = delegee_gid.get_hrn()
483     
484        # the key and hrn of the user who will be delegating
485        user_key = Keypair(filename = self.get_key_file())
486        user_hrn = user_cred.get_gid_caller().get_hrn()
487     
488        dcred = Credential(subject=object_hrn + " delegated to " + delegee_hrn)
489        dcred.set_gid_caller(delegee_gid)
490        dcred.set_gid_object(object_gid)
491        dcred.set_privileges(object_cred.get_privileges())
492        dcred.set_delegate(True)
493        dcred.set_pubkey(object_gid.get_pubkey())
494        dcred.set_issuer(user_key, user_hrn)
495        dcred.set_parent(object_cred)
496        dcred.encode()
497        dcred.sign()
498     
499        if opts.delegate_user:
500            dest_fn = os.path.join(self.options.sfi_dir, self.get_leaf(delegee_hrn) + "_" 
501                                   + self.get_leaf(object_hrn) + ".cred")
502        elif opts.delegate_slice:
503            dest_fn = os.path_join(self.options.sfi_dir, self.get_leaf(delegee_hrn) + "_slice_" 
504                                   + self.get_leaf(object_hrn) + ".cred")
505     
506        dcred.save_to_file(dest_fn, save_parents = True)
507     
508        print "delegated credential for", object_hrn, "to", delegee_hrn, "and wrote to", dest_fn
509     
510     # removed named registry record
511     #   - have to first retrieve the record to be removed
512     def remove(self,opts, args):
513        auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
514        hrn = args[0]
515        type = opts.type 
516        if type in ['all']:
517            type = '*'
518        arg_list = [auth_cred, type, hrn]
519        request_hash = self.key.compute_hash(arg_list)                   
520        return self.registry.remove(auth_cred, type, hrn, request_hash)
521     
522     # add named registry record
523     def add(self,opts, args):
524        auth_cred = self.get_auth_cred().save_to_string(save_parents=True)
525        record_filepath = args[0]
526        rec_file = self.get_record_file(record_filepath)
527        record = self.load_record_from_file(rec_file).as_dict()
528        arg_list = [auth_cred]
529        request_hash = self.key.compute_hash(arg_list)
530        return self.registry.register(auth_cred, record, request_hash)
531     
532     # update named registry entry
533     def update(self,opts, args):
534        user_cred = self.get_user_cred()
535        rec_file = self.get_record_file(args[0])
536        record = self.load_record_from_file(rec_file)
537        if record['type'] == "user":
538            if record.get_name() == user_cred.get_gid_object().get_hrn():
539               cred = user_cred.save_to_string(save_parents=True)
540            else:
541               cred = self.get_auth_cred().save_to_string(save_parents=True)
542        elif record['type'] in ["slice"]:
543            try:
544                cred = self.get_slice_cred(record.get_name()).save_to_string(save_parents=True)
545            except ServerException, e:
546                # XXX smbaker -- once we have better error return codes, update this
547                # to do something better than a string compare
548                if "Permission error" in e.args[0]:
549                    cred = self.get_auth_cred().save_to_string(save_parents=True)
550                else:
551                    raise
552        elif record.get_type() in ["authority"]:
553            cred = self.get_auth_cred().save_to_string(save_parents=True)
554        elif record.get_type() == 'node':
555            cred = self.get_auth_cred().save_to_string(save_parents=True)
556        else:
557            raise "unknown record type" + record.get_type()
558        record = record.as_dict()
559        arg_list = [cred]  
560        request_hash = self.key.compute_hash(arg_list)
561        return self.registry.update(cred, record, request_hash)
562    
563     
564     def aggregates(self, opts, args):
565         user_cred = self.get_user_cred().save_to_string(save_parents=True)
566         hrn = None
567         if args: 
568             hrn = args[0]
569         arg_list = [user_cred, hrn]  
570         request_hash = self.key.compute_hash(arg_list)
571         result = self.registry.get_aggregates(user_cred, hrn, request_hash)
572         self.display_list(result)
573         return 
574
575     def registries(self, opts, args):
576         user_cred = self.get_user_cred().save_to_string(save_parents=True)
577         hrn = None
578         if args:
579             hrn = args[0]
580         arg_list = [user_cred, hrn]  
581         request_hash = self.key.compute_hash(arg_list)
582         result = self.registry.get_registries(user_cred, hrn, request_hash)
583         self.display_list(result)
584         return
585  
586     #
587     # Slice-related commands
588     #
589     
590     # list available nodes -- use 'resources' w/ no argument instead
591
592     # list instantiated slices
593     def slices(self,opts, args):
594         user_cred = self.get_user_cred().save_to_string(save_parents=True)
595         arg_list = [user_cred]
596         request_hash = self.key.compute_hash(arg_list)
597         results = self.slicemgr.get_slices(user_cred, request_hash)
598         self.display_list(results)
599         return
600     
601     # show rspec for named slice
602     def resources(self,opts, args):
603         user_cred = self.get_user_cred().save_to_string(save_parents=True)
604         server = self.slicemgr
605         if opts.aggregate:
606             agg_hrn = opts.aggregate
607             arg_list = [user_cred, arg_hrn]
608             request_hash = self.key.compute_hash(arg_list)
609             aggregates = self.registry.get_aggregates(user_cred, agg_hrn, request_hash)
610             if not aggregates:
611                 raise Exception, "No such aggregate %s" % agg_hrn
612             aggregate = aggregates[0]
613             url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])     
614             server = xmlrpcprotocol.get_server(url, self.key_file, self.cert_file)
615         if args:
616             cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
617             hrn = args[0]
618         else:
619             cred = user_cred
620             hrn = None
621
622         arg_list = [cred, hrn]
623         request_hash = self.key.compute_hash(arg_list)  
624         result = server.get_resources(cred, hrn, request_hash)
625         format = opts.format
626        
627         self.display_rspec(result, format)
628         if (opts.file is not None):
629             self.save_rspec_to_file(result, opts.file)
630         return
631     
632     # created named slice with given rspec
633     def create(self,opts, args):
634        slice_hrn = args[0]
635        user_cred = self.get_user_cred()
636        slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
637        rspec_file = self.get_rspec_file(args[1])
638        rspec=open(rspec_file).read()
639        server = self.slicemgr
640        if opts.aggregate:
641            aggregates = self.registry.get_aggregates(user_cred, opts.aggregate)
642            if not aggregates:
643                raise Exception, "No such aggregate %s" % opts.aggregate
644            aggregate = aggregates[0]
645            url = "http://%s:%s" % (aggregate['addr'], aggregate['port'])
646            server = GeniClient(url, self.key_file, self.cert_file, self.options.protocol)
647        arg_list = [slice_cred, slice_hrn, rspec]
648        request_hash = self.key.compute_hash(arg_list) 
649        return server.create_slice(slice_cred, slice_hrn, rspec, request_hash)
650     
651     # delete named slice
652     def delete(self,opts, args):
653         slice_hrn = args[0]
654         slice_cred = self.get_slice_cred(slice_hrn).save_to_string(save_parents=True)
655         arg_list = [slice_cred, slice_hrn]
656         request_hash = self.key.compute_hash(arg_list) 
657         return self.slicemgr.delete_slice(slice_cred, slice_hrn, request_hash)
658     
659     # start named slice
660     def start(self,opts, args):
661         slice_hrn = args[0]
662         slice_cred = self.get_slice_cred(args[0])
663         arg_list = [slice_cred, slice_hrn]
664         request_hash = self.key.compute_hash(arg_list)
665         return self.slicemgr.start_slice(slice_cred, slice_hrn, request_hash)
666     
667     # stop named slice
668     def stop(self,opts, args):
669         slice_hrn = args[0]
670         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
671         arg_list = [slice_cred, slice_hrn]
672         request_hash = self.key.compute_hash(arg_list)
673         return self.slicemgr.stop_slice(slice_cred, slice_hrn, request_hash)
674     
675     # reset named slice
676     def reset(self,opts, args):
677         slice_hrn = args[0]
678         slice_cred = self.get_slice_cred(args[0]).save_to_string(save_parents=True)
679         arg_list = [slice_cred, slice_hrn]
680         request_hash = self.key.compute_hash(arg_list)
681         return self.slicemgr.reset_slice(slice_cred, slice_hrn, request_hash)
682     
683     #
684     #
685     # Display, Save, and Filter RSpecs and Records
686     #   - to be replace by EMF-generated routines
687     #
688     #
689     
690     def display_rspec(self,rspec, format = 'rspec'):
691         if format in ['dns']:
692             spec = Rspec()
693             spec.parseString(rspec)
694             hostnames = []
695             nodespecs = spec.getDictsByTagName('NodeSpec')
696             for nodespec in nodespecs:
697                 if nodespec.has_key('name') and nodespec['name']:
698                     if isinstance(nodespec['name'], ListType):
699                         hostnames.extend(nodespec['name'])
700                     elif isinstance(nodespec['name'], StringTypes):
701                         hostnames.append(nodespec['name'])
702             result = hostnames
703         elif format in ['ip']:
704             spec = Rspec()
705             spec.parseString(rspec)
706             ips = []
707             ifspecs = spec.getDictsByTagName('IfSpec')
708             for ifspec in ifspecs:
709                 if ifspec.has_key('addr') and ifspec['addr']:
710                     ips.append(ifspec['addr'])
711             result = ips 
712         else:     
713             result = rspec
714     
715         print result
716         return
717     
718     def display_list(self,results):
719         for result in results:
720             print result
721     
722     def save_rspec_to_file(self,rspec, filename):
723        if not filename.startswith(os.sep):
724            filename = self.options.sfi_dir + filename
725        if not filename.endswith(".rspec"):
726            filename = filename + ".rspec"
727     
728        f = open(filename, 'w')
729        f.write(rspec)
730        f.close()
731        return
732     
733     def display_records(self,recordList, dump = False):
734        ''' Print all fields in the record'''
735        for record in recordList:
736           self.display_record(record, dump)
737     
738     def display_record(self,record, dump = False):
739        if dump:
740            record.dump()
741        else:
742            info = record.getdict()
743            print "%s (%s)" % (info['hrn'], info['type'])
744        return
745     
746     def filter_records(self,type, records):
747        filtered_records = []
748        for record in records:
749            if (record['type'] == type) or (type == "all"):
750                filtered_records.append(record)
751        return filtered_records
752     
753     def save_records_to_file(self,filename, recordList):
754        index = 0
755        for record in recordList:
756            if index>0:
757                self.save_record_to_file(filename + "." + str(index), record)
758            else:
759                self.save_record_to_file(filename, record)
760            index = index + 1
761     
762     def save_record_to_file(self,filename, record):
763        if record['type'] in ['user']:
764            record = UserRecord(dict = record)
765        elif record['type'] in ['slice']:
766            record = SliceRecord(dict = record)
767        elif record['type'] in ['node']:
768            record = NodeRecord(dict = record)
769        elif record['type'] in ['authority', 'ma', 'sa']:
770           record = AuthorityRecord(dict = record)
771        else:
772            record = GeniRecord(dict = record) 
773        if not filename.startswith(os.sep):
774            filename = self.options.sfi_dir + filename
775        str = record.save_to_string()
776        file(filename, "w").write(str)
777        return
778     
779     def load_record_from_file(self,filename):
780        str = file(filename, "r").read()
781        record = GeniRecord(string=str)
782        return record
783     
784     #
785     # Main: parse arguments and dispatch to command
786     #
787     def main(self):
788        parser = self.create_parser()
789        (options, args) = parser.parse_args()
790        self.options = options
791     
792        if len(args) <= 0:
793             print "No command given. Use -h for help."
794             return -1
795     
796        command = args[0]
797        (cmd_opts, cmd_args) = self.create_cmd_parser(command).parse_args(args[1:])
798        if self.options.verbose :
799           print "Registry %s, sm %s, dir %s, user %s, auth %s" % (options.registry,
800                                                                    options.sm,
801                                                                    options.sfi_dir,
802                                                                    options.user,
803                                                                    options.auth)
804           print "Command %s" %command
805           if command in ("resources"):
806              print "resources cmd_opts %s" %cmd_opts.format
807           elif command in ("list","show","remove"):
808              print "cmd_opts.type %s" %cmd_opts.type
809           print "cmd_args %s" %cmd_args
810     
811        self.set_servers()
812     
813        try:
814           self.dispatch(command, cmd_opts, cmd_args)
815        except KeyError:
816           raise 
817           print "Command not found:", command
818           sys.exit(1)
819     
820        return
821     
822 if __name__=="__main__":
823    Sfi().main()