2to3 -f raise
[sfa.git] / sfa / nitos / nitosdriver.py
1 import time
2 import datetime
3 #
4 from sfa.util.faults import MissingSfaInfo, UnknownSfaType, \
5     RecordNotFound, SfaNotImplemented, SliverDoesNotExist
6
7 from sfa.util.sfalogging import logger
8 from sfa.util.defaultdict import defaultdict
9 from sfa.util.sfatime import utcparse, datetime_to_string, datetime_to_epoch
10 from sfa.util.xrn import Xrn, hrn_to_urn, get_leaf, urn_to_hrn
11 from sfa.util.cache import Cache
12
13 # one would think the driver should not need to mess with the SFA db, but..
14 from sfa.storage.model import RegRecord
15
16 # used to be used in get_ticket
17 #from sfa.trust.sfaticket import SfaTicket
18
19 from sfa.rspecs.version_manager import VersionManager
20 from sfa.rspecs.rspec import RSpec
21
22 # the driver interface, mostly provides default behaviours
23 from sfa.managers.driver import Driver
24
25 from sfa.nitos.nitosshell import NitosShell
26 from sfa.nitos.nitosaggregate import NitosAggregate
27 from sfa.nitos.nitosslices import NitosSlices
28
29 from sfa.nitos.nitosxrn import NitosXrn, slicename_to_hrn, hostname_to_hrn, hrn_to_nitos_slicename, xrn_to_hostname
30
31 def list_to_dict(recs, key):
32     """
33     convert a list of dictionaries into a dictionary keyed on the 
34     specified dictionary key 
35     """
36     return dict ( [ (rec[key],rec) for rec in recs ] )
37
38 #
39 # NitosShell is just an xmlrpc serverproxy where methods
40 # can be sent as-is; it takes care of authentication
41 # from the global config
42
43 class NitosDriver (Driver):
44
45     # the cache instance is a class member so it survives across incoming requests
46     cache = None
47
48     def __init__ (self, api):
49         Driver.__init__ (self, api)
50         config = api.config
51         self.shell = NitosShell (config)
52         self.cache=None
53         self.testbedInfo = self.shell.getTestbedInfo()
54 # un-comment below lines to enable caching
55 #        if config.SFA_AGGREGATE_CACHING:
56 #            if NitosDriver.cache is None:
57 #                NitosDriver.cache = Cache()
58 #            self.cache = NitosDriver.cache
59  
60     ###########################################
61     ########## utility methods for NITOS driver
62     ###########################################
63
64
65     def filter_nitos_results (self, listo, filters_dict):
66         """
67         the Nitos scheduler API does not provide a get result filtring so we do it here
68         """
69         mylist = []
70         mylist.extend(listo)
71         for dicto in mylist:
72              for filter in filters_dict:
73                   if filter not in dicto or dicto[filter] != filters_dict[filter]:
74                       listo.remove(dicto)
75                       break
76         return listo
77
78     def convert_id (self, list_of_dict):
79         """
80         convert object id retrived in string format to int format
81         """
82         for dicto in list_of_dict:
83              for key in dicto:
84                   if key in ['node_id', 'slice_id', 'user_id', 'channel_id', 'reservation_id'] and isinstance(dicto[key], str):
85                       dicto[key] = int(dicto[key])
86                   elif key in ['user_ids']:
87                       user_ids2 = []
88                       for user_id in dicto['user_ids']:
89                            user_ids2.append(int(user_id))
90                       dicto['user_ids'] = user_ids2
91         return list_of_dict
92
93
94
95     ########################################
96     ########## registry oriented
97     ########################################
98
99     def augment_records_with_testbed_info (self, sfa_records):
100         return self.fill_record_info (sfa_records)
101
102     ########## 
103     def register (self, sfa_record, hrn, pub_key):
104         type = sfa_record['type']
105         nitos_record = self.sfa_fields_to_nitos_fields(type, hrn, sfa_record)
106
107         if type == 'authority':
108             pointer = -1
109
110         elif type == 'slice':
111             slices = self.shell.getSlices()
112             # filter slices
113             for slice in slices:
114                  if slice['slice_name'] == nitos_record['name']:
115                      slice_id = slice['slice_id']
116                      break
117  
118             if not slice_id:
119                  pointer = self.shell.addSlice({'slice_name' : nitos_record['name']})
120             else:
121                  pointer = slice_id
122
123         elif type == 'user':
124             users = self.shell.getUsers()
125             # filter users
126             for user in users:
127                  if user['user_name'] == nitos_record['name']:
128                      user_id = user['user_id']
129                      break
130             if not user_id:
131                 pointer = self.shell.addUser({'username' : nitos_record['name'], 'email' : nitos_record['email']})
132             else:
133                 pointer = user_id
134     
135
136             # Add the user's key
137             if pub_key:
138                 self.shell.addUserKey({'user_id' : pointer,'key' : pub_key})
139
140         elif type == 'node':
141             nodes = self.shell.GetNodes({}, [])
142             # filter nodes
143             for node in nodes:
144                  if node['hostname'] == nitos_record['name']:
145                      node_id = node['node_id']
146                      break
147
148             if not node_id:
149                 pointer = self.shell.addNode(nitos_record)
150             else:
151                 pointer = node_id
152     
153         return pointer
154         
155     ##########
156     def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
157         
158         pointer = old_sfa_record['pointer']
159         type = old_sfa_record['type']
160         new_nitos_record = self.sfa_fields_to_nitos_fields(type, hrn, new_sfa_record)
161
162         # new_key implemented for users only
163         if new_key and type not in [ 'user' ]:
164             raise UnknownSfaType(type)
165
166         if type == "slice":
167             if 'name' in new_sfa_record:
168                 self.shell.updateSlice({'slice_id': pointer, 'fields': {'slice_name': new_sfa_record['name']}})
169     
170         elif type == "user":
171             update_fields = {}
172             if 'name' in new_sfa_record:
173                 update_fields['username'] = new_sfa_record['name']
174             if 'email' in new_sfa_record:
175                 update_fields['email'] = new_sfa_record['email']
176  
177             self.shell.updateUser({'user_id': pointer, 'fields': update_fields}) 
178     
179             if new_key:
180                 # needs to be improved 
181                 self.shell.addUserKey({'user_id': pointer, 'key': new_key}) 
182     
183         elif type == "node":
184             self.shell.updateNode({'node_id': pointer, 'fields': new_sfa_record})
185
186         return True
187         
188
189     ##########
190     def remove (self, sfa_record):
191
192         type=sfa_record['type']
193         pointer=sfa_record['pointer']
194         if type == 'user':
195             self.shell.deleteUser({'user_id': pointer})
196         elif type == 'slice':
197             self.shell.deleteSlice({'slice_id': pointer})
198         elif type == 'node':
199             self.shell.deleteNode({'node_id': pointer})
200
201         return True
202         
203
204
205
206
207     ##
208     # Convert SFA fields to NITOS fields for use when registering or updating
209     # registry record in the NITOS Scheduler database
210     #
211
212     def sfa_fields_to_nitos_fields(self, type, hrn, sfa_record):
213
214         nitos_record = {}
215  
216         if type == "slice":
217             nitos_record["slice_name"] = hrn_to_nitos_slicename(hrn)
218         elif type == "node":
219             if "hostname" not in sfa_record:
220                 raise MissingSfaInfo("hostname")
221             nitos_record["node_name"] = sfa_record["hostname"]
222
223         return nitos_record
224
225     ####################
226     def fill_record_info(self, records):
227         """
228         Given a (list of) SFA record, fill in the NITOS specific 
229         and SFA specific fields in the record. 
230         """
231         if not isinstance(records, list):
232             records = [records]
233
234         self.fill_record_nitos_info(records)
235         self.fill_record_hrns(records)
236         self.fill_record_sfa_info(records)
237         return records
238
239     def fill_record_nitos_info(self, records):
240         """
241         Fill in the nitos specific fields of a SFA record. This
242         involves calling the appropriate NITOS API method to retrieve the 
243         database record for the object.
244             
245         @param record: record to fill in field (in/out param)     
246         """
247         
248         # get ids by type
249         node_ids, slice_ids = [], [] 
250         user_ids, key_ids = [], []
251         type_map = {'node': node_ids, 'slice': slice_ids, 'user': user_ids}
252                   
253         for record in records:
254             for type in type_map:
255                 if type == record['type']:
256                     type_map[type].append(record['pointer'])
257
258         # get nitos records
259         nodes, slices, users, keys = {}, {}, {}, {}
260         if node_ids:
261             all_nodes = self.convert_id(self.shell.getNodes({}, []))
262             node_list =  [node for node in all_nodes if node['node_id'] in node_ids]
263             nodes = list_to_dict(node_list, 'node_id')
264         if slice_ids:
265             all_slices = self.convert_id(self.shell.getSlices({}, []))
266             slice_list =  [slice for slice in all_slices if slice['slice_id'] in slice_ids]
267             slices = list_to_dict(slice_list, 'slice_id')
268         if user_ids:
269             all_users = self.convert_id(self.shell.getUsers())
270             user_list = [user for user in all_users if user['user_id'] in user_ids] 
271             users = list_to_dict(user_list, 'user_id')
272
273         nitos_records = {'node': nodes, 'slice': slices, 'user': users}
274
275
276         # fill record info
277         for record in records:
278             if record['pointer'] == -1:
279                 continue
280            
281             for type in nitos_records:
282                 if record['type'] == type:
283                     if record['pointer'] in nitos_records[type]:
284                         record.update(nitos_records[type][record['pointer']])
285                         break
286             # fill in key info
287             if record['type'] == 'user':
288                 if record['pointer'] in nitos_records['user']:
289                     record['keys'] = nitos_records['user'][record['pointer']]['keys']
290
291         return records
292         
293  
294     def fill_record_hrns(self, records):
295         """
296         convert nitos ids to hrns
297         """
298
299
300         # get ids
301         slice_ids, user_ids, node_ids = [], [], []
302         for record in records:
303             if 'user_ids' in record:
304                 user_ids.extend(record['user_ids'])
305             if 'slice_ids' in record:
306                 slice_ids.extend(record['slice_ids'])
307             if 'node_ids' in record:
308                 node_ids.extend(record['node_ids'])
309
310         # get nitos records
311         slices, users, nodes = {}, {}, {}
312         if node_ids:
313             all_nodes = self.convert_id(self.shell.getNodes({}, []))
314             node_list =  [node for node in all_nodes if node['node_id'] in node_ids]
315             nodes = list_to_dict(node_list, 'node_id')
316         if slice_ids:
317             all_slices = self.convert_id(self.shell.getSlices({}, []))
318             slice_list =  [slice for slice in all_slices if slice['slice_id'] in slice_ids]
319             slices = list_to_dict(slice_list, 'slice_id')
320         if user_ids:
321             all_users = self.convert_id(self.shell.getUsers())
322             user_list = [user for user in all_users if user['user_id'] in user_ids]
323             users = list_to_dict(user_list, 'user_id')
324
325        
326         # convert ids to hrns
327         for record in records:
328             # get all relevant data
329             type = record['type']
330             pointer = record['pointer']
331             auth_hrn = self.hrn
332             testbed_name = self.testbedInfo['name']
333             if pointer == -1:
334                 continue
335             if 'user_ids' in record:
336                 usernames = [users[user_id]['username'] for user_id in record['user_ids'] \
337                           if user_id in  users]
338                 user_hrns = [".".join([auth_hrn, testbed_name, username]) for username in usernames]
339                 record['users'] = user_hrns 
340             if 'slice_ids' in record:
341                 slicenames = [slices[slice_id]['slice_name'] for slice_id in record['slice_ids'] \
342                               if slice_id in slices]
343                 slice_hrns = [slicename_to_hrn(auth_hrn, slicename) for slicename in slicenames]
344                 record['slices'] = slice_hrns
345             if 'node_ids' in record:
346                 hostnames = [nodes[node_id]['hostname'] for node_id in record['node_ids'] \
347                              if node_id in nodes]
348                 node_hrns = [hostname_to_hrn(auth_hrn, login_base, hostname) for hostname in hostnames]
349                 record['nodes'] = node_hrns
350
351             if 'expires' in record:
352                 date = utcparse(record['expires'])
353                 datestring = datetime_to_string(date)
354                 record['expires'] = datestring 
355             
356         return records   
357  
358     def fill_record_sfa_info(self, records):
359         
360         def startswith(prefix, values):
361             return [value for value in values if value.startswith(prefix)]
362
363         # get user ids
364         user_ids = []
365         for record in records:
366             user_ids.extend(record.get("user_ids", []))
367         
368         # get the registry records
369         user_list, users = [], {}
370         user_list = self.api.dbsession().query(RegRecord).filter(RegRecord.pointer.in_(user_ids)).all()
371         # create a hrns keyed on the sfa record's pointer.
372         # Its possible for multiple records to have the same pointer so
373         # the dict's value will be a list of hrns.
374         users = defaultdict(list)
375         for user in user_list:
376             users[user.pointer].append(user)
377
378         # get the nitos records
379         nitos_user_list, nitos_users = [], {}
380         nitos_all_users = self.convert_id(self.shell.getUsers())
381         nitos_user_list = [user for user in nitos_all_users if user['user_id'] in user_ids]
382         nitos_users = list_to_dict(nitos_user_list, 'user_id')
383
384
385         # fill sfa info
386         for record in records:
387             if record['pointer'] == -1:
388                 continue 
389
390             sfa_info = {}
391             type = record['type']
392             logger.info("fill_record_sfa_info - incoming record typed %s"%type)
393             if (type == "slice"):
394                 # all slice users are researchers
395                 record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
396                 record['researcher'] = []
397                 for user_id in record.get('user_ids', []):
398                     hrns = [user.hrn for user in users[user_id]]
399                     record['researcher'].extend(hrns)                
400                 
401             elif (type == "node"):
402                 sfa_info['dns'] = record.get("hostname", "")
403                 # xxx TODO: URI, LatLong, IP, DNS
404     
405             elif (type == "user"):
406                 logger.info('setting user.email')
407                 sfa_info['email'] = record.get("email", "")
408                 sfa_info['geni_urn'] = hrn_to_urn(record['hrn'], 'user')
409                 sfa_info['geni_certificate'] = record['gid'] 
410                 # xxx TODO: PostalAddress, Phone
411             record.update(sfa_info)
412
413     ####################
414     def update_relation (self, subject_type, target_type, relation_name, subject_id, target_ids):
415         
416         if subject_type =='slice' and target_type == 'user' and relation_name == 'researcher':
417             subject=self.shell.getSlices ({'slice_id': subject_id}, [])[0]
418             current_target_ids = subject['user_ids']
419             add_target_ids = list ( set (target_ids).difference(current_target_ids))
420             del_target_ids = list ( set (current_target_ids).difference(target_ids))
421             logger.debug ("subject_id = %s (type=%s)"%(subject_id,type(subject_id)))
422             for target_id in add_target_ids:
423                 self.shell.addUserToSlice ({'user_id': target_id, 'slice_id': subject_id})
424                 logger.debug ("add_target_id = %s (type=%s)"%(target_id,type(target_id)))
425             for target_id in del_target_ids:
426                 logger.debug ("del_target_id = %s (type=%s)"%(target_id,type(target_id)))
427                 self.shell.deleteUserFromSlice ({'user_id': target_id, 'slice_id': subject_id})
428         else:
429             logger.info('unexpected relation %s to maintain, %s -> %s'%(relation_name,subject_type,target_type))
430
431
432     ########################################
433     ########## aggregate oriented
434     ########################################
435
436     def testbed_name (self): return "nitos"
437
438     # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
439     def aggregate_version (self):
440         version_manager = VersionManager()
441         ad_rspec_versions = []
442         request_rspec_versions = []
443         for rspec_version in version_manager.versions:
444             if rspec_version.content_type in ['*', 'ad']:
445                 ad_rspec_versions.append(rspec_version.to_dict())
446             if rspec_version.content_type in ['*', 'request']:
447                 request_rspec_versions.append(rspec_version.to_dict()) 
448         return {
449             'testbed':self.testbed_name(),
450             'geni_request_rspec_versions': request_rspec_versions,
451             'geni_ad_rspec_versions': ad_rspec_versions,
452             }
453
454     def list_slices (self, creds, options):
455         # look in cache first
456         if self.cache:
457             slices = self.cache.get('slices')
458             if slices:
459                 logger.debug("NitosDriver.list_slices returns from cache")
460                 return slices
461
462         # get data from db 
463         slices = self.shell.getSlices({}, [])
464         testbed_name = self.testbedInfo['name']
465         slice_hrns = [slicename_to_hrn(self.hrn, testbed_name, slice['slice_name']) for slice in slices]
466         slice_urns = [hrn_to_urn(slice_hrn, 'slice') for slice_hrn in slice_hrns]
467
468         # cache the result
469         if self.cache:
470             logger.debug ("NitosDriver.list_slices stores value in cache")
471             self.cache.add('slices', slice_urns) 
472     
473         return slice_urns
474         
475     # first 2 args are None in case of resource discovery
476     def list_resources (self, slice_urn, slice_hrn, creds, options):
477         cached_requested = options.get('cached', True) 
478         version_manager = VersionManager()
479         # get the rspec's return format from options
480         #rspec_version = version_manager.get_version(options.get('geni_rspec_version'))
481         # rspec's return format for nitos aggregate is version  NITOS 1
482         rspec_version = version_manager.get_version('NITOS 1')
483         version_string = "rspec_%s" % (rspec_version)
484  
485         #panos adding the info option to the caching key (can be improved)
486         if options.get('info'):
487             version_string = version_string + "_"+options.get('info', 'default')
488
489         # Adding the list_leases option to the caching key
490         if options.get('list_leases'):
491             version_string = version_string + "_"+options.get('list_leases', 'default')
492
493         # Adding geni_available to caching key
494         if options.get('geni_available'):
495             version_string = version_string + "_" + str(options.get('geni_available'))
496     
497         # look in cache first
498         if cached_requested and self.cache and not slice_hrn:
499             rspec = self.cache.get(version_string)
500             if rspec:
501                 logger.debug("NitosDriver.ListResources: returning cached advertisement")
502                 return rspec 
503     
504         #panos: passing user-defined options
505         #print "manager options = ",options
506         aggregate = NitosAggregate(self)
507         rspec =  aggregate.get_rspec(slice_xrn=slice_urn, version=rspec_version, 
508                                      options=options)
509  
510         # cache the result
511         if self.cache and not slice_hrn:
512             logger.debug("NitosDriver.ListResources: stores advertisement in cache")
513             self.cache.add(version_string, rspec)
514     
515         return rspec
516     
517     def sliver_status (self, slice_urn, slice_hrn):
518         # find out where this slice is currently running
519         slicename = hrn_to_nitos_slicename(slice_hrn)
520         
521         slices = self.shell.getSlices({}, [])
522         # filter slicename
523         if len(slices) == 0:        
524             raise SliverDoesNotExist("%s (used %s as slicename internally)" % (slice_hrn, slicename))
525         
526         for slice in slices:
527              if slice['slice_name'] == slicename: 
528                  user_slice = slice
529                  break
530
531         if not user_slice:
532             raise SliverDoesNotExist("%s (used %s as slicename internally)" % (slice_hrn, slicename))
533
534         # report about the reserved nodes only
535         reserved_nodes = self.shell.getReservedNodes({}, [])
536         nodes = self.shell.getNodes({}, [])
537
538         slice_reserved_nodes = []
539         for r_node in reserved_nodes:
540              if r_node['slice_id'] == slice['slice_id']:
541                  for node in nodes:
542                      if node['node_id'] == r_node['node_id']:
543                          slice_reserved_nodes.append(node)
544         
545         
546
547
548         if len(slice_reserved_nodes) == 0:
549             raise SliverDoesNotExist("You have not allocated any slivers here") 
550
551 ##### continue from here
552         # get login info
553         user = {}
554         keys = []
555         if slice['user_ids']:
556             users = self.shell.getUsers()
557             # filter users on slice['user_ids']
558             for usr in users:
559                  if usr['user_id'] in slice['user_ids']:
560                      keys.extend(usr['keys'])
561                      
562
563             user.update({'urn': slice_urn,
564                          'login': slice['slice_name'],
565                          'protocol': ['ssh'],
566                          'port': ['22'],
567                          'keys': keys})
568
569     
570         result = {}
571         top_level_status = 'unknown'
572         if slice_reserved_nodes:
573             top_level_status = 'ready'
574         result['geni_urn'] = slice_urn
575         result['nitos_gateway_login'] = slice['slice_name']
576         #result['pl_expires'] = datetime_to_string(utcparse(slice['expires']))
577         #result['geni_expires'] = datetime_to_string(utcparse(slice['expires']))
578         
579         resources = []
580         for node in slice_reserved_nodes:
581             res = {}
582             res['nitos_hostname'] = node['hostname']
583             sliver_id = Xrn(slice_urn, type='slice', id=node['node_id']).urn
584             res['geni_urn'] = sliver_id
585             res['geni_status'] = 'ready'
586             res['geni_error'] = ''
587             res['users'] = [user]  
588     
589             resources.append(res)
590             
591         result['geni_status'] = top_level_status
592         result['geni_resources'] = resources
593         
594         return result
595
596     def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, users, options):
597
598         aggregate = NitosAggregate(self)
599         slices = NitosSlices(self)
600         sfa_peer = slices.get_sfa_peer(slice_hrn)
601         slice_record=None    
602         if users:
603             slice_record = users[0].get('slice_record', {})
604     
605         # parse rspec
606         rspec = RSpec(rspec_string, version='NITOS 1')
607
608         # ensure slice record exists
609         slice = slices.verify_slice(slice_hrn, slice_record, sfa_peer, options=options)
610         # ensure user records exists
611         users = slices.verify_users(slice_hrn, slice, users, sfa_peer, options=options)
612         
613         # add/remove leases (nodes and channels)
614         # a lease in Nitos RSpec case is a reservation of nodes and channels grouped by (slice,timeslot)
615         rspec_requested_leases = rspec.version.get_leases()
616         rspec_requested_nodes = []
617         rspec_requested_channels = []
618         for lease in rspec_requested_leases:
619              if lease['type'] == 'node':
620                  lease.pop('type', None)
621                  rspec_requested_nodes.append(lease)
622              else:
623                  lease.pop('type', None)
624                  rspec_requested_channels.append(lease)                 
625         
626         nodes = slices.verify_slice_leases_nodes(slice, rspec_requested_nodes)
627         channels = slices.verify_slice_leases_channels(slice, rspec_requested_channels)
628
629         return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
630
631     def delete_sliver (self, slice_urn, slice_hrn, creds, options):
632         slicename = hrn_to_nitos_slicename(slice_hrn)
633         slices = self.filter_nitos_results(self.shell.getSlices({}, []), {'slice_name': slicename})
634         if not slices:
635             return 1
636         slice = slices[0]
637
638         slice_reserved_nodes = self.filter_nitos_results(self.shell.getReservedNodes({}, []), {'slice_id': slice['slice_id'] })
639         slice_reserved_channels = self.filter_nitos_results(self.shell.getReservedChannels(), {'slice_id': slice['slice_id'] })
640
641         slice_reserved_nodes_ids = [node['reservation_id'] for node in slice_reserved_nodes]
642         slice_reserved_channels_ids = [channel['reservation_id'] for channel in slice_reserved_channels]
643
644         # release all reserved nodes and channels for that slice
645         try:
646             released_nodes = self.shell.releaseNodes({'reservation_ids': slice_reserved_nodes_ids})
647             released_channels = self.shell.releaseChannels({'reservation_ids': slice_reserved_channels_ids})
648         except:
649             pass
650         return 1
651
652     def renew_sliver (self, slice_urn, slice_hrn, creds, expiration_time, options):
653         slicename = hrn_to_nitos_slicename(slice_hrn)
654         slices = self.shell.GetSlices({'slicename': slicename}, ['slice_id'])
655         if not slices:
656             raise RecordNotFound(slice_hrn)
657         slice = slices[0]
658         requested_time = utcparse(expiration_time)
659         record = {'expires': int(datetime_to_epoch(requested_time))}
660         try:
661             self.shell.UpdateSlice(slice['slice_id'], record)
662
663             return True
664         except:
665             return False
666
667     
668     # xxx this code is quite old and has not run for ages
669     # it is obviously totally broken and needs a rewrite
670     def get_ticket (self, slice_urn, slice_hrn, creds, rspec_string, options):
671         raise SfaNotImplemented("NitosDriver.get_ticket needs a rewrite")
672 # please keep this code for future reference
673 #        slices = PlSlices(self)
674 #        peer = slices.get_peer(slice_hrn)
675 #        sfa_peer = slices.get_sfa_peer(slice_hrn)
676 #    
677 #        # get the slice record
678 #        credential = api.getCredential()
679 #        interface = api.registries[api.hrn]
680 #        registry = api.server_proxy(interface, credential)
681 #        records = registry.Resolve(xrn, credential)
682 #    
683 #        # make sure we get a local slice record
684 #        record = None
685 #        for tmp_record in records:
686 #            if tmp_record['type'] == 'slice' and \
687 #               not tmp_record['peer_authority']:
688 #    #Error (E0602, GetTicket): Undefined variable 'SliceRecord'
689 #                slice_record = SliceRecord(dict=tmp_record)
690 #        if not record:
691 #            raise RecordNotFound(slice_hrn)
692 #        
693 #        # similar to CreateSliver, we must verify that the required records exist
694 #        # at this aggregate before we can issue a ticket
695 #        # parse rspec
696 #        rspec = RSpec(rspec_string)
697 #        requested_attributes = rspec.version.get_slice_attributes()
698 #    
699 #        # ensure site record exists
700 #        site = slices.verify_site(slice_hrn, slice_record, peer, sfa_peer)
701 #        # ensure slice record exists
702 #        slice = slices.verify_slice(slice_hrn, slice_record, peer, sfa_peer)
703 #        # ensure person records exists
704 #    # xxx users is undefined in this context
705 #        persons = slices.verify_persons(slice_hrn, slice, users, peer, sfa_peer)
706 #        # ensure slice attributes exists
707 #        slices.verify_slice_attributes(slice, requested_attributes)
708 #        
709 #        # get sliver info
710 #        slivers = slices.get_slivers(slice_hrn)
711 #    
712 #        if not slivers:
713 #            raise SliverDoesNotExist(slice_hrn)
714 #    
715 #        # get initscripts
716 #        initscripts = []
717 #        data = {
718 #            'timestamp': int(time.time()),
719 #            'initscripts': initscripts,
720 #            'slivers': slivers
721 #        }
722 #    
723 #        # create the ticket
724 #        object_gid = record.get_gid_object()
725 #        new_ticket = SfaTicket(subject = object_gid.get_subject())
726 #        new_ticket.set_gid_caller(api.auth.client_gid)
727 #        new_ticket.set_gid_object(object_gid)
728 #        new_ticket.set_issuer(key=api.key, subject=self.hrn)
729 #        new_ticket.set_pubkey(object_gid.get_pubkey())
730 #        new_ticket.set_attributes(data)
731 #        new_ticket.set_rspec(rspec)
732 #        #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
733 #        new_ticket.encode()
734 #        new_ticket.sign()
735 #    
736 #        return new_ticket.save_to_string(save_parents=True)