implement registry_import
[sfa.git] / sfa / clientbin / sfaadmin.py
1 #!/usr/bin/python
2 import os
3 import sys
4 import copy
5 from pprint import pformat 
6 from sfa.generic import Generic
7 from optparse import OptionParser
8 from pprint import PrettyPrinter
9 from sfa.util.xrn import Xrn
10 from sfa.storage.record import Record 
11 from sfa.client.sfi import save_records_to_file
12 from sfa.trust.hierarchy import Hierarchy
13 from sfa.trust.gid import GID
14
15 pprinter = PrettyPrinter(indent=4)
16
17 def args(*args, **kwargs):
18     def _decorator(func):
19         func.__dict__.setdefault('options', []).insert(0, (args, kwargs))
20         return func
21     return _decorator
22
23 class Commands(object):
24
25     def _get_commands(self):
26         available_methods = []
27         for attrib in dir(self):
28             if callable(getattr(self, attrib)) and not attrib.startswith('_'):
29                 available_methods.append(attrib)
30         return available_methods         
31
32
33 class RegistryCommands(Commands):
34     def __init__(self, *args, **kwds):
35         self.api= Generic.the_flavour().make_api(interface='registry')
36  
37     def version(self):
38         version = self.api.manager.GetVersion(self.api, {})
39         pprinter.pprint(version)
40
41     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn') 
42     @args('-t', '--type', dest='type', metavar='<type>', help='object type', default=None) 
43     def list(self, xrn, type=None):
44         xrn = Xrn(xrn, type) 
45         records = self.api.manager.List(self.api, xrn.get_hrn())
46         for record in records:
47             if not type or record['type'] == type:
48                 print "%s (%s)" % (record['hrn'], record['type'])
49
50
51     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn') 
52     @args('-t', '--type', dest='type', metavar='<type>', help='object type', default=None) 
53     @args('-o', '--outfile', dest='outfile', metavar='<outfile>', help='save record to file') 
54     @args('-f', '--format', dest='format', metavar='<display>', type='choice', 
55           choices=('text', 'xml', 'simple'), help='display record in different formats') 
56     def show(self, xrn, type=None, format=None, outfile=None):
57         records = self.api.manager.Resolve(self.api, xrn, type, True)
58         for record in records:
59             sfa_record = Record(dict=record)
60             sfa_record.dump(format) 
61         if outfile:
62             save_records_to_file(outfile, records)                
63
64     def register(self, record):
65         pass
66
67     def update(self, record):
68         pass
69         
70     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn') 
71     @args('-t', '--type', dest='type', metavar='<type>', help='object type', default=None) 
72     def remove(self, xrn, type=None):
73         xrn = Xrn(xrn, type)
74         self.api.manager.Remove(self.api, xrn)            
75
76
77     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn') 
78     @args('-t', '--type', dest='type', metavar='<type>', help='object type', default=None) 
79     def credential(self, xrn, type=None):
80         cred = self.api.manager.GetCredential(self.api, xrn, type, self.api.hrn)
81         print cred
82    
83
84     def import_registry(self):
85         from sfa.importer import Importer
86         importer = Importer()
87         importer.run()
88  
89     
90     @args('-a', '--all', dest='all', metavar='<all>', action='store_true', default=False,
91           help='Remove all registry records and all files in %s area' % Hierarchy().basedir)
92     @args('-c', '--certs', dest='certs', metavar='<certs>', action='store_true', default=False,
93           help='Remove all cached certs/gids found in %s' % Hierarchy().basedir )
94     @args('-0', '--no-reinit', dest='reinit', metavar='<reinit>', action='store_false', default=True,
95           help='Prevents new DB schema from being installed after cleanup')
96     def nuke(self, all=False, certs=False, reinit=True):
97         from sfa.storage.dbschema import DBSchema
98         from sfa.util.sfalogging import _SfaLogger
99         logger = _SfaLogger(logfile='/var/log/sfa_import.log', loggername='importlog')
100         logger.setLevelFromOptVerbose(self.api.config.SFA_API_LOGLEVEL)
101         logger.info("Purging SFA records from database")
102         dbschema=DBSchema()
103         dbschema.nuke()
104
105         # for convenience we re-create the schema here, so there's no need for an explicit
106         # service sfa restart
107         # however in some (upgrade) scenarios this might be wrong
108         if options.reinit:
109             logger.info("re-creating empty schema")
110             dbschema.init_or_upgrade()
111
112         # remove the server certificate and all gids found in /var/lib/sfa/authorities
113         if options.clean_certs:
114             logger.info("Purging cached certificates")
115             for (dir, _, files) in os.walk('/var/lib/sfa/authorities'):
116                 for file in files:
117                     if file.endswith('.gid') or file == 'server.cert':
118                         path=dir+os.sep+file
119                         os.unlink(path)
120
121         # just remove all files that do not match 'server.key' or 'server.cert'
122         if options.all:
123             logger.info("Purging registry filesystem cache")
124             preserved_files = [ 'server.key', 'server.cert']
125             for (dir,_,files) in os.walk(Hierarchy().basedir):
126                 for file in files:
127                     if file in preserved_files: continue
128                     path=dir+os.sep+file
129                     os.unlink(path)
130         
131     
132 class CertCommands(Commands):
133     
134     def import_gid(self, xrn):
135         pass
136
137     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn')
138     @args('-t', '--type', dest='type', metavar='<type>', help='object type', default=None)
139     @args('-o', '--outfile', dest='outfile', metavar='<outfile>', help='output file', default=None)
140     def export(self, xrn, type=None, outfile=None):
141         from sfa.storage.alchemy import dbsession
142         from sfa.storage.model import RegRecord
143         hrn = Xrn(xrn).get_hrn()
144         request=dbsession.query(RegRecord).filter_by(hrn=hrn)
145         if type: request = request.filter_by(type=type)
146         record=request.first()
147         if record:
148             gid = GID(string=record.gid)
149         else:
150             # check the authorities hierarchy
151             hierarchy = Hierarchy()
152             try:
153                 auth_info = hierarchy.get_auth_info(hrn)
154                 gid = auth_info.gid_object
155             except:
156                 print "Record: %s not found" % hrn
157                 sys.exit(1)
158         # save to file
159         if not outfile:
160             outfile = os.path.abspath('./%s.gid' % gid.get_hrn())
161         gid.save_to_file(outfile, save_parents=True)
162         
163     @args('-g', '--gidfile', dest='gid', metavar='<gid>', help='path of gid file to display') 
164     def display(self, gidfile):
165         gid_path = os.path.abspath(gidfile)
166         if not gid_path or not os.path.isfile(gid_path):
167             print "No such gid file: %s" % gidfile
168             sys.exit(1)
169         gid = GID(filename=gid_path)
170         gid.dump(dump_parents=True)
171     
172
173 class AggregateCommands(Commands):
174
175     def __init__(self, *args, **kwds):
176         self.api= Generic.the_flavour().make_api(interface='aggregate')
177    
178     def version(self):
179         version = self.api.manager.GetVersion(self.api, {})
180         pprinter.pprint(version)
181
182     def slices(self):
183         print self.api.manager.ListSlices(self.api, [], {})
184
185     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn') 
186     def status(self, xrn):
187         urn = Xrn(xrn, 'slice').get_urn()
188         status = self.api.manager.SliverStatus(self.api, urn, [], {})
189         pprinter.pprint(status)
190  
191     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn', default=None)
192     @args('-r', '--rspec-version', dest='rspec_version', metavar='<rspec_version>', 
193           default='GENI', help='version/format of the resulting rspec response')  
194     def resources(self, xrn=None, rspec_version='GENI'):
195         options = {'geni_rspec_version': rspec_version}
196         if xrn:
197             options['geni_slice_urn'] = xrn
198         resources = self.api.manager.ListResources(self.api, [], options)
199         pprinter.pprint(resources)
200         
201     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn', default=None)
202     @args('-r', '--rspec', dest='rspec', metavar='<rspec>', help='rspec file')  
203     @args('-u', '--user', dest='user', metavar='<user>', help='hrn/urn of slice user')  
204     @args('-k', '--key', dest='key', metavar='<key>', help="path to user's public key file")  
205     def create(self, xrn, rspec, user, key):
206         xrn = Xrn(xrn)
207         slice_urn=xrn.get_urn()
208         slice_hrn=xrn.get_hrn()
209         rspec_string = open(rspec).read()
210         user_xrn = Xrn(user, 'user')
211         user_urn = user_xrn.get_urn()
212         user_key_string = open(key).read()
213         users = [{'urn': user_urn, 'keys': [user_key_string]}]
214         options={}
215         self.api.manager.CreateSliver(self, slice_urn, slice_hrn, [], rspec_string, users, options) 
216
217     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn', default=None)
218     def delete(self, xrn):
219         self.api.manager.DeleteSliver(self.api, xrn, [], {})
220  
221     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn', default=None)
222     def start(self, xrn):
223         self.api.manager.start_slice(self.api, xrn, [])
224
225     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn', default=None)
226     def stop(self, xrn):
227         self.api.manager.stop_slice(self.api, xrn, [])      
228
229     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn', default=None)
230     def reset(self, xrn):
231         self.api.manager.reset_slice(self.api, xrn)
232
233
234     @args('-x', '--xrn', dest='xrn', metavar='<xrn>', help='object hrn/urn', default=None)
235     @args('-r', '--rspec', dest='rspec', metavar='<rspec>', help='request rspec', default=None)
236     def ticket(self, xrn, rspec):
237         pass
238
239
240
241 class SliceManagerCommands(AggregateCommands):
242     
243     def __init__(self, *args, **kwds):
244         self.api= Generic.the_flavour().make_api(interface='slicemgr')
245
246
247 CATEGORIES = {'cert': CertCommands,
248               'registry': RegistryCommands,
249               'aggregate': AggregateCommands,
250               'slicemgr': SliceManagerCommands}
251
252 def category_usage():
253     print "Available categories:"
254     for k in CATEGORIES:
255         print "\t%s" % k
256
257 def main():
258     argv = copy.deepcopy(sys.argv)
259     script_name = argv.pop(0)
260     # ensure category is specified    
261     if len(argv) < 1:
262         print script_name + " category action [<args>]"
263         category_usage()
264         sys.exit(2)
265
266     # ensure category is valid
267     category = argv.pop(0)
268     usage = "%%prog %s action <args> [options]" % (category)
269     parser = OptionParser(usage=usage)
270     command_class =  CATEGORIES.get(category, None)
271     if not command_class:
272         print "no such category %s " % category
273         category_usage()
274         sys.exit(2)  
275     
276     # ensure command is valid      
277     command_instance = command_class()
278     actions = command_instance._get_commands()
279     if len(argv) < 1:
280         if hasattr(command_instance, '__call__'):
281             action = ''
282             command = command_instance.__call__
283         else:
284             print script_name + " category action [<args>]"
285             print "Available actions for %s category:" % category
286             for k in actions:
287                 print "\t%s" % k 
288             sys.exit(2)
289     else:
290         action = argv.pop(0)
291         command = getattr(command_instance, action)
292
293     # ensure options are valid
294     options = getattr(command, 'options', [])
295     usage = "%%prog %s %s <args> [options]" % (category, action)
296     parser = OptionParser(usage=usage)
297     for arg, kwd in options:
298         parser.add_option(*arg, **kwd)
299     (opts, cmd_args) = parser.parse_args(argv)
300     cmd_kwds = vars(opts)
301
302     # dont overrride meth
303     for k, v in cmd_kwds.items():
304         if v is None:
305             del cmd_kwds[k]
306
307     # execute commadn
308     try:
309         command(*cmd_args, **cmd_kwds)
310         sys.exit(0)
311     except TypeError:
312         print "Possible wrong number of arguments supplied"
313         print command.__doc__
314         parser.print_help()
315         #raise
316         raise
317     except Exception:
318         print "Command failed, please check log for more info"
319         raise
320
321
322 if __name__ == '__main__':
323     main()
324     
325      
326         
327