4 from sfa.util.faults import MissingSfaInfo, UnknownSfaType, \
5 RecordNotFound, SfaNotImplemented, SliverDoesNotExist
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 hrn_to_urn, get_leaf, urn_to_sliver_id
11 from sfa.util.cache import Cache
13 # one would think the driver should not need to mess with the SFA db, but..
14 from sfa.storage.alchemy import dbsession
15 from sfa.storage.model import RegRecord
17 # used to be used in get_ticket
18 #from sfa.trust.sfaticket import SfaTicket
20 from sfa.rspecs.version_manager import VersionManager
21 from sfa.rspecs.rspec import RSpec
23 # the driver interface, mostly provides default behaviours
24 from sfa.managers.driver import Driver
26 from sfa.planetlab.plshell import PlShell
27 import sfa.planetlab.peers as peers
28 from sfa.planetlab.plaggregate import PlAggregate
29 from sfa.planetlab.plslices import PlSlices
30 from sfa.planetlab.plxrn import PlXrn, slicename_to_hrn, hostname_to_hrn, hrn_to_pl_slicename, xrn_to_hostname
33 def list_to_dict(recs, key):
35 convert a list of dictionaries into a dictionary keyed on the
36 specified dictionary key
38 return dict ( [ (rec[key],rec) for rec in recs ] )
41 # PlShell is just an xmlrpc serverproxy where methods
42 # can be sent as-is; it takes care of authentication
43 # from the global config
45 class PlDriver (Driver):
47 # the cache instance is a class member so it survives across incoming requests
50 def __init__ (self, config):
51 Driver.__init__ (self, config)
52 self.shell = PlShell (config)
54 if config.SFA_AGGREGATE_CACHING:
55 if PlDriver.cache is None:
56 PlDriver.cache = Cache()
57 self.cache = PlDriver.cache
59 ########################################
60 ########## registry oriented
61 ########################################
63 def augment_records_with_testbed_info (self, sfa_records):
64 return self.fill_record_info (sfa_records)
67 def register (self, sfa_record, hrn, pub_key):
68 type = sfa_record['type']
69 pl_record = self.sfa_fields_to_pl_fields(type, hrn, sfa_record)
71 if type == 'authority':
72 sites = self.shell.GetSites([pl_record['login_base']])
74 # xxx when a site gets registered through SFA we need to set its max_slices
75 if 'max_slices' not in pl_record:
76 pl_record['max_slices']=2
77 pointer = self.shell.AddSite(pl_record)
79 pointer = sites[0]['site_id']
82 acceptable_fields=['url', 'instantiation', 'name', 'description']
83 for key in pl_record.keys():
84 if key not in acceptable_fields:
86 slices = self.shell.GetSlices([pl_record['name']])
88 pointer = self.shell.AddSlice(pl_record)
90 pointer = slices[0]['slice_id']
93 persons = self.shell.GetPersons({'email':sfa_record['email']})
95 for key in ['first_name','last_name']:
96 if key not in sfa_record: sfa_record[key]='*from*sfa*'
97 pointer = self.shell.AddPerson(dict(sfa_record))
99 pointer = persons[0]['person_id']
101 if 'enabled' in sfa_record and sfa_record['enabled']:
102 self.shell.UpdatePerson(pointer, {'enabled': sfa_record['enabled']})
103 # add this person to the site only if she is being added for the first
104 # time by sfa and doesont already exist in plc
105 if not persons or not persons[0]['site_ids']:
106 login_base = get_leaf(sfa_record['authority'])
107 self.shell.AddPersonToSite(pointer, login_base)
109 # What roles should this user have?
111 if 'roles' in sfa_record:
112 # if specified in xml, but only low-level roles
113 roles = [ role for role in sfa_record['roles'] if role in ['user','tech'] ]
114 # at least user if no other cluse could be found
118 self.shell.AddRoleToPerson(role, pointer)
121 self.shell.AddPersonKey(pointer, {'key_type' : 'ssh', 'key' : pub_key})
124 login_base = PlXrn(xrn=sfa_record['authority'],type='node').pl_login_base()
125 nodes = self.shell.GetNodes([pl_record['hostname']])
127 pointer = self.shell.AddNode(login_base, pl_record)
129 pointer = nodes[0]['node_id']
134 # xxx actually old_sfa_record comes filled with plc stuff as well in the original code
135 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
136 pointer = old_sfa_record['pointer']
137 type = old_sfa_record['type']
139 # new_key implemented for users only
140 if new_key and type not in [ 'user' ]:
141 raise UnknownSfaType(type)
143 if (type == "authority"):
144 self.shell.UpdateSite(pointer, new_sfa_record)
146 elif type == "slice":
147 pl_record=self.sfa_fields_to_pl_fields(type, hrn, new_sfa_record)
148 if 'name' in pl_record:
149 pl_record.pop('name')
150 self.shell.UpdateSlice(pointer, pl_record)
153 # SMBAKER: UpdatePerson only allows a limited set of fields to be
154 # updated. Ideally we should have a more generic way of doing
155 # this. I copied the field names from UpdatePerson.py...
157 all_fields = new_sfa_record
158 for key in all_fields.keys():
159 if key in ['first_name', 'last_name', 'title', 'email',
160 'password', 'phone', 'url', 'bio', 'accepted_aup',
162 update_fields[key] = all_fields[key]
163 # when updating a user, we always get a 'email' field at this point
164 # this is because 'email' is a native field in the RegUser object...
165 if 'email' in update_fields and not update_fields['email']:
166 del update_fields['email']
167 self.shell.UpdatePerson(pointer, update_fields)
170 # must check this key against the previous one if it exists
171 persons = self.shell.GetPersons([pointer], ['key_ids'])
173 keys = person['key_ids']
174 keys = self.shell.GetKeys(person['key_ids'])
176 # Delete all stale keys
179 if new_key != key['key']:
180 self.shell.DeleteKey(key['key_id'])
184 self.shell.AddPersonKey(pointer, {'key_type': 'ssh', 'key': new_key})
187 self.shell.UpdateNode(pointer, new_sfa_record)
193 def remove (self, sfa_record):
194 type=sfa_record['type']
195 pointer=sfa_record['pointer']
197 persons = self.shell.GetPersons(pointer)
198 # only delete this person if he has site ids. if he doesnt, it probably means
199 # he was just removed from a site, not actually deleted
200 if persons and persons[0]['site_ids']:
201 self.shell.DeletePerson(pointer)
202 elif type == 'slice':
203 if self.shell.GetSlices(pointer):
204 self.shell.DeleteSlice(pointer)
206 if self.shell.GetNodes(pointer):
207 self.shell.DeleteNode(pointer)
208 elif type == 'authority':
209 if self.shell.GetSites(pointer):
210 self.shell.DeleteSite(pointer)
219 # Convert SFA fields to PLC fields for use when registering or updating
220 # registry record in the PLC database
223 def sfa_fields_to_pl_fields(self, type, hrn, sfa_record):
228 pl_record["name"] = hrn_to_pl_slicename(hrn)
229 if "instantiation" in sfa_record:
230 pl_record['instantiation']=sfa_record['instantiation']
232 pl_record["instantiation"] = "plc-instantiated"
233 if "url" in sfa_record:
234 pl_record["url"] = sfa_record["url"]
235 if "description" in sfa_record:
236 pl_record["description"] = sfa_record["description"]
237 if "expires" in sfa_record:
238 date = utcparse(sfa_record['expires'])
239 expires = datetime_to_epoch(date)
240 pl_record["expires"] = expires
243 if not "hostname" in pl_record:
244 # fetch from sfa_record
245 if "hostname" not in sfa_record:
246 raise MissingSfaInfo("hostname")
247 pl_record["hostname"] = sfa_record["hostname"]
248 if "model" in sfa_record:
249 pl_record["model"] = sfa_record["model"]
251 pl_record["model"] = "geni"
253 elif type == "authority":
254 pl_record["login_base"] = PlXrn(xrn=hrn,type='authority').pl_login_base()
255 if "name" not in sfa_record:
256 pl_record["name"] = hrn
257 if "abbreviated_name" not in sfa_record:
258 pl_record["abbreviated_name"] = hrn
259 if "enabled" not in sfa_record:
260 pl_record["enabled"] = True
261 if "is_public" not in sfa_record:
262 pl_record["is_public"] = True
267 def fill_record_info(self, records):
269 Given a (list of) SFA record, fill in the PLC specific
270 and SFA specific fields in the record.
272 if not isinstance(records, list):
275 self.fill_record_pl_info(records)
276 self.fill_record_hrns(records)
277 self.fill_record_sfa_info(records)
280 def fill_record_pl_info(self, records):
282 Fill in the planetlab specific fields of a SFA record. This
283 involves calling the appropriate PLC method to retrieve the
284 database record for the object.
286 @param record: record to fill in field (in/out param)
289 node_ids, site_ids, slice_ids = [], [], []
290 person_ids, key_ids = [], []
291 type_map = {'node': node_ids, 'authority': site_ids,
292 'slice': slice_ids, 'user': person_ids}
294 for record in records:
295 for type in type_map:
296 if type == record['type']:
297 type_map[type].append(record['pointer'])
300 nodes, sites, slices, persons, keys = {}, {}, {}, {}, {}
302 node_list = self.shell.GetNodes(node_ids)
303 nodes = list_to_dict(node_list, 'node_id')
305 site_list = self.shell.GetSites(site_ids)
306 sites = list_to_dict(site_list, 'site_id')
308 slice_list = self.shell.GetSlices(slice_ids)
309 slices = list_to_dict(slice_list, 'slice_id')
311 person_list = self.shell.GetPersons(person_ids)
312 persons = list_to_dict(person_list, 'person_id')
313 for person in persons:
314 key_ids.extend(persons[person]['key_ids'])
316 pl_records = {'node': nodes, 'authority': sites,
317 'slice': slices, 'user': persons}
320 key_list = self.shell.GetKeys(key_ids)
321 keys = list_to_dict(key_list, 'key_id')
324 for record in records:
325 # records with pointer==-1 do not have plc info.
326 # for example, the top level authority records which are
327 # authorities, but not PL "sites"
328 if record['pointer'] == -1:
331 for type in pl_records:
332 if record['type'] == type:
333 if record['pointer'] in pl_records[type]:
334 record.update(pl_records[type][record['pointer']])
337 if record['type'] == 'user':
338 if 'key_ids' not in record:
339 logger.info("user record has no 'key_ids' - need to import from myplc ?")
341 pubkeys = [keys[key_id]['key'] for key_id in record['key_ids'] if key_id in keys]
342 record['keys'] = pubkeys
346 def fill_record_hrns(self, records):
348 convert pl ids to hrns
352 slice_ids, person_ids, site_ids, node_ids = [], [], [], []
353 for record in records:
354 if 'site_id' in record:
355 site_ids.append(record['site_id'])
356 if 'site_ids' in record:
357 site_ids.extend(record['site_ids'])
358 if 'person_ids' in record:
359 person_ids.extend(record['person_ids'])
360 if 'slice_ids' in record:
361 slice_ids.extend(record['slice_ids'])
362 if 'node_ids' in record:
363 node_ids.extend(record['node_ids'])
366 slices, persons, sites, nodes = {}, {}, {}, {}
368 site_list = self.shell.GetSites(site_ids, ['site_id', 'login_base'])
369 sites = list_to_dict(site_list, 'site_id')
371 person_list = self.shell.GetPersons(person_ids, ['person_id', 'email'])
372 persons = list_to_dict(person_list, 'person_id')
374 slice_list = self.shell.GetSlices(slice_ids, ['slice_id', 'name'])
375 slices = list_to_dict(slice_list, 'slice_id')
377 node_list = self.shell.GetNodes(node_ids, ['node_id', 'hostname'])
378 nodes = list_to_dict(node_list, 'node_id')
380 # convert ids to hrns
381 for record in records:
382 # get all relevant data
383 type = record['type']
384 pointer = record['pointer']
390 if 'site_id' in record:
391 site = sites[record['site_id']]
392 login_base = site['login_base']
393 record['site'] = ".".join([auth_hrn, login_base])
394 if 'person_ids' in record:
395 emails = [persons[person_id]['email'] for person_id in record['person_ids'] \
396 if person_id in persons]
397 usernames = [email.split('@')[0] for email in emails]
398 person_hrns = [".".join([auth_hrn, login_base, username]) for username in usernames]
399 record['persons'] = person_hrns
400 if 'slice_ids' in record:
401 slicenames = [slices[slice_id]['name'] for slice_id in record['slice_ids'] \
402 if slice_id in slices]
403 slice_hrns = [slicename_to_hrn(auth_hrn, slicename) for slicename in slicenames]
404 record['slices'] = slice_hrns
405 if 'node_ids' in record:
406 hostnames = [nodes[node_id]['hostname'] for node_id in record['node_ids'] \
408 node_hrns = [hostname_to_hrn(auth_hrn, login_base, hostname) for hostname in hostnames]
409 record['nodes'] = node_hrns
410 if 'site_ids' in record:
411 login_bases = [sites[site_id]['login_base'] for site_id in record['site_ids'] \
413 site_hrns = [".".join([auth_hrn, lbase]) for lbase in login_bases]
414 record['sites'] = site_hrns
416 if 'expires' in record:
417 date = utcparse(record['expires'])
418 datestring = datetime_to_string(date)
419 record['expires'] = datestring
423 def fill_record_sfa_info(self, records):
425 def startswith(prefix, values):
426 return [value for value in values if value.startswith(prefix)]
431 for record in records:
432 person_ids.extend(record.get("person_ids", []))
433 site_ids.extend(record.get("site_ids", []))
434 if 'site_id' in record:
435 site_ids.append(record['site_id'])
437 # get all pis from the sites we've encountered
438 # and store them in a dictionary keyed on site_id
441 pi_filter = {'|roles': ['pi'], '|site_ids': site_ids}
442 pi_list = self.shell.GetPersons(pi_filter, ['person_id', 'site_ids'])
444 # we will need the pi's hrns also
445 person_ids.append(pi['person_id'])
447 # we also need to keep track of the sites these pis
449 for site_id in pi['site_ids']:
450 if site_id in site_pis:
451 site_pis[site_id].append(pi)
453 site_pis[site_id] = [pi]
455 # get sfa records for all records associated with these records.
456 # we'll replace pl ids (person_ids) with hrns from the sfa records
459 # get the registry records
460 person_list, persons = [], {}
461 person_list = dbsession.query (RegRecord).filter(RegRecord.pointer.in_(person_ids))
462 # create a hrns keyed on the sfa record's pointer.
463 # Its possible for multiple records to have the same pointer so
464 # the dict's value will be a list of hrns.
465 persons = defaultdict(list)
466 for person in person_list:
467 persons[person.pointer].append(person)
470 pl_person_list, pl_persons = [], {}
471 pl_person_list = self.shell.GetPersons(person_ids, ['person_id', 'roles'])
472 pl_persons = list_to_dict(pl_person_list, 'person_id')
475 for record in records:
476 # skip records with no pl info (top level authorities)
477 #if record['pointer'] == -1:
480 type = record['type']
481 logger.info("fill_record_sfa_info - incoming record typed %s"%type)
482 if (type == "slice"):
483 # all slice users are researchers
484 record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
486 record['researcher'] = []
487 for person_id in record.get('person_ids', []):
488 hrns = [person.hrn for person in persons[person_id]]
489 record['researcher'].extend(hrns)
491 # pis at the slice's site
492 if 'site_id' in record and record['site_id'] in site_pis:
493 pl_pis = site_pis[record['site_id']]
494 pi_ids = [pi['person_id'] for pi in pl_pis]
495 for person_id in pi_ids:
496 hrns = [person.hrn for person in persons[person_id]]
497 record['PI'].extend(hrns)
498 record['geni_creator'] = record['PI']
500 elif (type.startswith("authority")):
502 logger.info("fill_record_sfa_info - authority xherex")
503 if record['pointer'] != -1:
505 record['operator'] = []
507 for pointer in record.get('person_ids', []):
508 if pointer not in persons or pointer not in pl_persons:
509 # this means there is not sfa or pl record for this user
511 hrns = [person.hrn for person in persons[pointer]]
512 roles = pl_persons[pointer]['roles']
514 record['PI'].extend(hrns)
516 record['operator'].extend(hrns)
518 record['owner'].extend(hrns)
519 # xxx TODO: OrganizationName
520 elif (type == "node"):
521 sfa_info['dns'] = record.get("hostname", "")
522 # xxx TODO: URI, LatLong, IP, DNS
524 elif (type == "user"):
525 logger.info('setting user.email')
526 sfa_info['email'] = record.get("email", "")
527 sfa_info['geni_urn'] = hrn_to_urn(record['hrn'], 'user')
528 sfa_info['geni_certificate'] = record['gid']
529 # xxx TODO: PostalAddress, Phone
530 record.update(sfa_info)
534 # plcapi works by changes, compute what needs to be added/deleted
535 def update_relation (self, subject_type, target_type, relation_name, subject_id, target_ids):
536 # hard-wire the code for slice/user for now, could be smarter if needed
537 if subject_type =='slice' and target_type == 'user' and relation_name == 'researcher':
538 subject=self.shell.GetSlices (subject_id)[0]
539 current_target_ids = subject['person_ids']
540 add_target_ids = list ( set (target_ids).difference(current_target_ids))
541 del_target_ids = list ( set (current_target_ids).difference(target_ids))
542 logger.debug ("subject_id = %s (type=%s)"%(subject_id,type(subject_id)))
543 for target_id in add_target_ids:
544 self.shell.AddPersonToSlice (target_id,subject_id)
545 logger.debug ("add_target_id = %s (type=%s)"%(target_id,type(target_id)))
546 for target_id in del_target_ids:
547 logger.debug ("del_target_id = %s (type=%s)"%(target_id,type(target_id)))
548 self.shell.DeletePersonFromSlice (target_id, subject_id)
549 elif subject_type == 'authority' and target_type == 'user' and relation_name == 'pi':
550 # due to the plcapi limitations this means essentially adding pi role to all people in the list
551 # it's tricky to remove any pi role here, although it might be desirable
552 persons = self.shell.GetPersons (target_ids)
553 for person in persons:
554 if 'pi' not in person['roles']:
555 self.shell.AddRoleToPerson('pi',person['person_id'])
557 logger.info('unexpected relation %s to maintain, %s -> %s'%(relation_name,subject_type,target_type))
560 ########################################
561 ########## aggregate oriented
562 ########################################
564 def testbed_name (self): return "myplc"
566 # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
567 def aggregate_version (self):
568 version_manager = VersionManager()
569 ad_rspec_versions = []
570 request_rspec_versions = []
571 for rspec_version in version_manager.versions:
572 if rspec_version.content_type in ['*', 'ad']:
573 ad_rspec_versions.append(rspec_version.to_dict())
574 if rspec_version.content_type in ['*', 'request']:
575 request_rspec_versions.append(rspec_version.to_dict())
577 'testbed':self.testbed_name(),
578 'geni_request_rspec_versions': request_rspec_versions,
579 'geni_ad_rspec_versions': ad_rspec_versions,
582 def list_slices (self, creds, options):
583 # look in cache first
585 slices = self.cache.get('slices')
587 logger.debug("PlDriver.list_slices returns from cache")
591 slices = self.shell.GetSlices({'peer_id': None}, ['name'])
592 slice_hrns = [slicename_to_hrn(self.hrn, slice['name']) for slice in slices]
593 slice_urns = [hrn_to_urn(slice_hrn, 'slice') for slice_hrn in slice_hrns]
597 logger.debug ("PlDriver.list_slices stores value in cache")
598 self.cache.add('slices', slice_urns)
602 # first 2 args are None in case of resource discovery
603 def list_resources (self, slice_urn, slice_hrn, creds, options):
604 cached_requested = options.get('cached', True)
606 version_manager = VersionManager()
607 # get the rspec's return format from options
608 rspec_version = version_manager.get_version(options.get('geni_rspec_version'))
609 version_string = "rspec_%s" % (rspec_version)
611 #panos adding the info option to the caching key (can be improved)
612 if options.get('info'):
613 version_string = version_string + "_"+options.get('info', 'default')
615 # Adding the list_leases option to the caching key
616 if options.get('list_leases'):
617 version_string = version_string + "_"+options.get('list_leases', 'default')
619 # look in cache first
620 if cached_requested and self.cache and not slice_hrn:
621 rspec = self.cache.get(version_string)
623 logger.debug("PlDriver.ListResources: returning cached advertisement")
626 #panos: passing user-defined options
627 #print "manager options = ",options
628 aggregate = PlAggregate(self)
629 rspec = aggregate.get_rspec(slice_xrn=slice_urn, version=rspec_version,
633 if self.cache and not slice_hrn:
634 logger.debug("PlDriver.ListResources: stores advertisement in cache")
635 self.cache.add(version_string, rspec)
639 def sliver_status (self, slice_urn, slice_hrn):
640 # find out where this slice is currently running
641 slicename = hrn_to_pl_slicename(slice_hrn)
643 slices = self.shell.GetSlices([slicename], ['slice_id', 'node_ids','person_ids','name','expires'])
645 raise SliverDoesNotExist("%s (used %s as slicename internally)" % (slice_hrn, slicename))
648 # report about the local nodes only
649 nodes = self.shell.GetNodes({'node_id':slice['node_ids'],'peer_id':None},
650 ['node_id', 'hostname', 'site_id', 'boot_state', 'last_contact'])
653 raise SliverDoesNotExist("You have not allocated any slivers here")
657 if slice['person_ids']:
658 persons = self.shell.GetPersons(slice['person_ids'], ['key_ids'])
659 key_ids = [key_id for person in persons for key_id in person['key_ids']]
660 person_keys = self.shell.GetKeys(key_ids)
661 keys = [key['key'] for key in keys]
663 user.update({'urn': slice_urn,
664 'login': slice['name'],
669 site_ids = [node['site_id'] for node in nodes]
672 top_level_status = 'unknown'
674 top_level_status = 'ready'
675 result['geni_urn'] = slice_urn
676 result['pl_login'] = slice['name']
677 result['pl_expires'] = datetime_to_string(utcparse(slice['expires']))
678 result['geni_expires'] = datetime_to_string(utcparse(slice['expires']))
683 res['pl_hostname'] = node['hostname']
684 res['pl_boot_state'] = node['boot_state']
685 res['pl_last_contact'] = node['last_contact']
686 res['geni_expires'] = datetime_to_string(utcparse(slice['expires']))
687 if node['last_contact'] is not None:
689 res['pl_last_contact'] = datetime_to_string(utcparse(node['last_contact']))
690 sliver_id = urn_to_sliver_id(slice_urn, slice['slice_id'], node['node_id'], authority=self.hrn)
691 res['geni_urn'] = sliver_id
692 if node['boot_state'] == 'boot':
693 res['geni_status'] = 'ready'
695 res['geni_status'] = 'failed'
696 top_level_status = 'failed'
698 res['geni_error'] = ''
699 res['users'] = [user]
701 resources.append(res)
703 result['geni_status'] = top_level_status
704 result['geni_resources'] = resources
707 def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, users, options):
709 aggregate = PlAggregate(self)
710 slices = PlSlices(self)
711 peer = slices.get_peer(slice_hrn)
712 sfa_peer = slices.get_sfa_peer(slice_hrn)
715 slice_record = users[0].get('slice_record', {})
718 rspec = RSpec(rspec_string)
719 requested_attributes = rspec.version.get_slice_attributes()
721 # ensure site record exists
722 site = slices.verify_site(slice_hrn, slice_record, peer, sfa_peer, options=options)
723 # ensure slice record exists
724 slice = slices.verify_slice(slice_hrn, slice_record, peer, sfa_peer, options=options)
725 # ensure person records exists
726 persons = slices.verify_persons(slice_hrn, slice, users, peer, sfa_peer, options=options)
727 # ensure slice attributes exists
728 slices.verify_slice_attributes(slice, requested_attributes, options=options)
730 # add/remove slice from nodes
731 requested_slivers = []
732 for node in rspec.version.get_nodes_with_slivers():
734 if node.get('component_name'):
735 hostname = node.get('component_name').strip()
736 elif node.get('component_id'):
737 hostname = xrn_to_hostname(node.get('component_id').strip())
739 requested_slivers.append(hostname)
740 nodes = slices.verify_slice_nodes(slice, requested_slivers, peer)
742 # add/remove links links
743 slices.verify_slice_links(slice, rspec.version.get_link_requests(), nodes)
746 requested_leases = []
748 for lease in rspec.version.get_leases():
750 if not lease.get('lease_id'):
751 requested_lease['hostname'] = xrn_to_hostname(lease.get('component_id').strip())
752 requested_lease['start_time'] = lease.get('start_time')
753 requested_lease['duration'] = lease.get('duration')
755 kept_leases.append(int(lease['lease_id']))
756 if requested_lease.get('hostname'):
757 requested_leases.append(requested_lease)
759 leases = slices.verify_slice_leases(slice, requested_leases, kept_leases, peer)
761 # handle MyPLC peer association.
762 # only used by plc and ple.
763 slices.handle_peer(site, slice, persons, peer)
765 return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
767 def delete_sliver (self, slice_urn, slice_hrn, creds, options):
768 slicename = hrn_to_pl_slicename(slice_hrn)
769 slices = self.shell.GetSlices({'name': slicename})
774 # determine if this is a peer slice
775 # xxx I wonder if this would not need to use PlSlices.get_peer instead
776 # in which case plc.peers could be deprecated as this here
777 # is the only/last call to this last method in plc.peers
778 peer = peers.get_peer(self, slice_hrn)
781 self.shell.UnBindObjectFromPeer('slice', slice['slice_id'], peer)
782 self.shell.DeleteSliceFromNodes(slicename, slice['node_ids'])
785 self.shell.BindObjectToPeer('slice', slice['slice_id'], peer, slice['peer_slice_id'])
788 def renew_sliver (self, slice_urn, slice_hrn, creds, expiration_time, options):
789 slicename = hrn_to_pl_slicename(slice_hrn)
790 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
792 raise RecordNotFound(slice_hrn)
794 requested_time = utcparse(expiration_time)
795 record = {'expires': int(datetime_to_epoch(requested_time))}
797 self.shell.UpdateSlice(slice['slice_id'], record)
802 # remove the 'enabled' tag
803 def start_slice (self, slice_urn, slice_hrn, creds):
804 slicename = hrn_to_pl_slicename(slice_hrn)
805 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
807 raise RecordNotFound(slice_hrn)
808 slice_id = slices[0]['slice_id']
809 slice_tags = self.shell.GetSliceTags({'slice_id': slice_id, 'tagname': 'enabled'}, ['slice_tag_id'])
810 # just remove the tag if it exists
812 self.shell.DeleteSliceTag(slice_tags[0]['slice_tag_id'])
815 # set the 'enabled' tag to 0
816 def stop_slice (self, slice_urn, slice_hrn, creds):
817 slicename = hrn_to_pl_slicename(slice_hrn)
818 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
820 raise RecordNotFound(slice_hrn)
821 slice_id = slices[0]['slice_id']
822 slice_tags = self.shell.GetSliceTags({'slice_id': slice_id, 'tagname': 'enabled'})
824 self.shell.AddSliceTag(slice_id, 'enabled', '0')
825 elif slice_tags[0]['value'] != "0":
826 tag_id = slice_tags[0]['slice_tag_id']
827 self.shell.UpdateSliceTag(tag_id, '0')
830 def reset_slice (self, slice_urn, slice_hrn, creds):
831 raise SfaNotImplemented ("reset_slice not available at this interface")
833 # xxx this code is quite old and has not run for ages
834 # it is obviously totally broken and needs a rewrite
835 def get_ticket (self, slice_urn, slice_hrn, creds, rspec_string, options):
836 raise SfaNotImplemented,"PlDriver.get_ticket needs a rewrite"
837 # please keep this code for future reference
838 # slices = PlSlices(self)
839 # peer = slices.get_peer(slice_hrn)
840 # sfa_peer = slices.get_sfa_peer(slice_hrn)
842 # # get the slice record
843 # credential = api.getCredential()
844 # interface = api.registries[api.hrn]
845 # registry = api.server_proxy(interface, credential)
846 # records = registry.Resolve(xrn, credential)
848 # # make sure we get a local slice record
850 # for tmp_record in records:
851 # if tmp_record['type'] == 'slice' and \
852 # not tmp_record['peer_authority']:
853 # #Error (E0602, GetTicket): Undefined variable 'SliceRecord'
854 # slice_record = SliceRecord(dict=tmp_record)
856 # raise RecordNotFound(slice_hrn)
858 # # similar to CreateSliver, we must verify that the required records exist
859 # # at this aggregate before we can issue a ticket
861 # rspec = RSpec(rspec_string)
862 # requested_attributes = rspec.version.get_slice_attributes()
864 # # ensure site record exists
865 # site = slices.verify_site(slice_hrn, slice_record, peer, sfa_peer)
866 # # ensure slice record exists
867 # slice = slices.verify_slice(slice_hrn, slice_record, peer, sfa_peer)
868 # # ensure person records exists
869 # # xxx users is undefined in this context
870 # persons = slices.verify_persons(slice_hrn, slice, users, peer, sfa_peer)
871 # # ensure slice attributes exists
872 # slices.verify_slice_attributes(slice, requested_attributes)
875 # slivers = slices.get_slivers(slice_hrn)
878 # raise SliverDoesNotExist(slice_hrn)
883 # 'timestamp': int(time.time()),
884 # 'initscripts': initscripts,
888 # # create the ticket
889 # object_gid = record.get_gid_object()
890 # new_ticket = SfaTicket(subject = object_gid.get_subject())
891 # new_ticket.set_gid_caller(api.auth.client_gid)
892 # new_ticket.set_gid_object(object_gid)
893 # new_ticket.set_issuer(key=api.key, subject=self.hrn)
894 # new_ticket.set_pubkey(object_gid.get_pubkey())
895 # new_ticket.set_attributes(data)
896 # new_ticket.set_rspec(rspec)
897 # #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
898 # new_ticket.encode()
901 # return new_ticket.save_to_string(save_parents=True)