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 Xrn, hrn_to_urn, get_leaf
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 # AddPerson does not allow everything to be set
98 can_add = ['first_name', 'last_name', 'title','email', 'password', 'phone', 'url', 'bio']
99 add_person_dict=dict ( [ (k,sfa_record[k]) for k in sfa_record if k in can_add ] )
100 pointer = self.shell.AddPerson(add_person_dict)
102 pointer = persons[0]['person_id']
104 if 'enabled' in sfa_record and sfa_record['enabled']:
105 self.shell.UpdatePerson(pointer, {'enabled': sfa_record['enabled']})
106 # add this person to the site only if she is being added for the first
107 # time by sfa and doesont already exist in plc
108 if not persons or not persons[0]['site_ids']:
109 login_base = get_leaf(sfa_record['authority'])
110 self.shell.AddPersonToSite(pointer, login_base)
112 # What roles should this user have?
114 if 'roles' in sfa_record:
115 # if specified in xml, but only low-level roles
116 roles = [ role for role in sfa_record['roles'] if role in ['user','tech'] ]
117 # at least user if no other cluse could be found
121 self.shell.AddRoleToPerson(role, pointer)
124 self.shell.AddPersonKey(pointer, {'key_type' : 'ssh', 'key' : pub_key})
127 login_base = PlXrn(xrn=sfa_record['authority'],type='authority').pl_login_base()
128 nodes = self.shell.GetNodes([pl_record['hostname']])
130 pointer = self.shell.AddNode(login_base, pl_record)
132 pointer = nodes[0]['node_id']
137 # xxx actually old_sfa_record comes filled with plc stuff as well in the original code
138 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
139 pointer = old_sfa_record['pointer']
140 type = old_sfa_record['type']
141 new_key_pointer = None
143 # new_key implemented for users only
144 if new_key and type not in [ 'user' ]:
145 raise UnknownSfaType(type)
147 if (type == "authority"):
148 self.shell.UpdateSite(pointer, new_sfa_record)
150 elif type == "slice":
151 pl_record=self.sfa_fields_to_pl_fields(type, hrn, new_sfa_record)
152 if 'name' in pl_record:
153 pl_record.pop('name')
154 self.shell.UpdateSlice(pointer, pl_record)
157 # SMBAKER: UpdatePerson only allows a limited set of fields to be
158 # updated. Ideally we should have a more generic way of doing
159 # this. I copied the field names from UpdatePerson.py...
161 all_fields = new_sfa_record
162 for key in all_fields.keys():
163 if key in ['first_name', 'last_name', 'title', 'email',
164 'password', 'phone', 'url', 'bio', 'accepted_aup',
166 update_fields[key] = all_fields[key]
167 # when updating a user, we always get a 'email' field at this point
168 # this is because 'email' is a native field in the RegUser object...
169 if 'email' in update_fields and not update_fields['email']:
170 del update_fields['email']
171 self.shell.UpdatePerson(pointer, update_fields)
174 # must check this key against the previous one if it exists
175 persons = self.shell.GetPersons([pointer], ['key_ids'])
177 keys = person['key_ids']
178 keys = self.shell.GetKeys(person['key_ids'])
182 if new_key == key['key']:
184 new_key_pointer = key['key_id']
187 new_key_pointer = self.shell.AddPersonKey(pointer, {'key_type': 'ssh', 'key': new_key})
190 self.shell.UpdateNode(pointer, new_sfa_record)
192 return (pointer, new_key_pointer)
196 def remove (self, sfa_record):
197 type=sfa_record['type']
198 pointer=sfa_record['pointer']
200 persons = self.shell.GetPersons(pointer)
201 # only delete this person if he has site ids. if he doesnt, it probably means
202 # he was just removed from a site, not actually deleted
203 if persons and persons[0]['site_ids']:
204 self.shell.DeletePerson(pointer)
205 elif type == 'slice':
206 if self.shell.GetSlices(pointer):
207 self.shell.DeleteSlice(pointer)
209 if self.shell.GetNodes(pointer):
210 self.shell.DeleteNode(pointer)
211 elif type == 'authority':
212 if self.shell.GetSites(pointer):
213 self.shell.DeleteSite(pointer)
222 # Convert SFA fields to PLC fields for use when registering or updating
223 # registry record in the PLC database
226 def sfa_fields_to_pl_fields(self, type, hrn, sfa_record):
231 pl_record["name"] = hrn_to_pl_slicename(hrn)
232 if "instantiation" in sfa_record:
233 pl_record['instantiation']=sfa_record['instantiation']
235 pl_record["instantiation"] = "plc-instantiated"
236 if "url" in sfa_record:
237 pl_record["url"] = sfa_record["url"]
238 if "description" in sfa_record:
239 pl_record["description"] = sfa_record["description"]
240 if "expires" in sfa_record:
241 date = utcparse(sfa_record['expires'])
242 expires = datetime_to_epoch(date)
243 pl_record["expires"] = expires
246 if not "hostname" in pl_record:
247 # fetch from sfa_record
248 if "hostname" not in sfa_record:
249 raise MissingSfaInfo("hostname")
250 pl_record["hostname"] = sfa_record["hostname"]
251 if "model" in sfa_record:
252 pl_record["model"] = sfa_record["model"]
254 pl_record["model"] = "geni"
256 elif type == "authority":
257 pl_record["login_base"] = PlXrn(xrn=hrn,type='authority').pl_login_base()
258 if "name" not in sfa_record:
259 pl_record["name"] = hrn
260 if "abbreviated_name" not in sfa_record:
261 pl_record["abbreviated_name"] = hrn
262 if "enabled" not in sfa_record:
263 pl_record["enabled"] = True
264 if "is_public" not in sfa_record:
265 pl_record["is_public"] = True
270 def fill_record_info(self, records):
272 Given a (list of) SFA record, fill in the PLC specific
273 and SFA specific fields in the record.
275 if not isinstance(records, list):
278 self.fill_record_pl_info(records)
279 self.fill_record_hrns(records)
280 self.fill_record_sfa_info(records)
283 def fill_record_pl_info(self, records):
285 Fill in the planetlab specific fields of a SFA record. This
286 involves calling the appropriate PLC method to retrieve the
287 database record for the object.
289 @param record: record to fill in field (in/out param)
292 node_ids, site_ids, slice_ids = [], [], []
293 person_ids, key_ids = [], []
294 type_map = {'node': node_ids, 'authority': site_ids,
295 'slice': slice_ids, 'user': person_ids}
297 for record in records:
298 for type in type_map:
299 if type == record['type']:
300 type_map[type].append(record['pointer'])
303 nodes, sites, slices, persons, keys = {}, {}, {}, {}, {}
305 node_list = self.shell.GetNodes(node_ids)
306 nodes = list_to_dict(node_list, 'node_id')
308 site_list = self.shell.GetSites(site_ids)
309 sites = list_to_dict(site_list, 'site_id')
311 slice_list = self.shell.GetSlices(slice_ids)
312 slices = list_to_dict(slice_list, 'slice_id')
314 person_list = self.shell.GetPersons(person_ids)
315 persons = list_to_dict(person_list, 'person_id')
316 for person in persons:
317 key_ids.extend(persons[person]['key_ids'])
319 pl_records = {'node': nodes, 'authority': sites,
320 'slice': slices, 'user': persons}
323 key_list = self.shell.GetKeys(key_ids)
324 keys = list_to_dict(key_list, 'key_id')
327 for record in records:
328 # records with pointer==-1 do not have plc info.
329 # for example, the top level authority records which are
330 # authorities, but not PL "sites"
331 if record['pointer'] == -1:
334 for type in pl_records:
335 if record['type'] == type:
336 if record['pointer'] in pl_records[type]:
337 record.update(pl_records[type][record['pointer']])
340 if record['type'] == 'user':
341 if 'key_ids' not in record:
342 logger.info("user record has no 'key_ids' - need to import from myplc ?")
344 pubkeys = [keys[key_id]['key'] for key_id in record['key_ids'] if key_id in keys]
345 record['keys'] = pubkeys
349 def fill_record_hrns(self, records):
351 convert pl ids to hrns
355 slice_ids, person_ids, site_ids, node_ids = [], [], [], []
356 for record in records:
357 if 'site_id' in record:
358 site_ids.append(record['site_id'])
359 if 'site_ids' in record:
360 site_ids.extend(record['site_ids'])
361 if 'person_ids' in record:
362 person_ids.extend(record['person_ids'])
363 if 'slice_ids' in record:
364 slice_ids.extend(record['slice_ids'])
365 if 'node_ids' in record:
366 node_ids.extend(record['node_ids'])
369 slices, persons, sites, nodes = {}, {}, {}, {}
371 site_list = self.shell.GetSites(site_ids, ['site_id', 'login_base'])
372 sites = list_to_dict(site_list, 'site_id')
374 person_list = self.shell.GetPersons(person_ids, ['person_id', 'email'])
375 persons = list_to_dict(person_list, 'person_id')
377 slice_list = self.shell.GetSlices(slice_ids, ['slice_id', 'name'])
378 slices = list_to_dict(slice_list, 'slice_id')
380 node_list = self.shell.GetNodes(node_ids, ['node_id', 'hostname'])
381 nodes = list_to_dict(node_list, 'node_id')
383 # convert ids to hrns
384 for record in records:
385 # get all relevant data
386 type = record['type']
387 pointer = record['pointer']
393 if 'site_id' in record:
394 site = sites[record['site_id']]
395 login_base = site['login_base']
396 record['site'] = ".".join([auth_hrn, login_base])
397 if 'person_ids' in record:
398 emails = [persons[person_id]['email'] for person_id in record['person_ids'] \
399 if person_id in persons]
400 usernames = [email.split('@')[0] for email in emails]
401 person_hrns = [".".join([auth_hrn, login_base, username]) for username in usernames]
402 record['persons'] = person_hrns
403 if 'slice_ids' in record:
404 slicenames = [slices[slice_id]['name'] for slice_id in record['slice_ids'] \
405 if slice_id in slices]
406 slice_hrns = [slicename_to_hrn(auth_hrn, slicename) for slicename in slicenames]
407 record['slices'] = slice_hrns
408 if 'node_ids' in record:
409 hostnames = [nodes[node_id]['hostname'] for node_id in record['node_ids'] \
411 node_hrns = [hostname_to_hrn(auth_hrn, login_base, hostname) for hostname in hostnames]
412 record['nodes'] = node_hrns
413 if 'site_ids' in record:
414 login_bases = [sites[site_id]['login_base'] for site_id in record['site_ids'] \
416 site_hrns = [".".join([auth_hrn, lbase]) for lbase in login_bases]
417 record['sites'] = site_hrns
419 if 'expires' in record:
420 date = utcparse(record['expires'])
421 datestring = datetime_to_string(date)
422 record['expires'] = datestring
426 def fill_record_sfa_info(self, records):
428 def startswith(prefix, values):
429 return [value for value in values if value.startswith(prefix)]
434 for record in records:
435 person_ids.extend(record.get("person_ids", []))
436 site_ids.extend(record.get("site_ids", []))
437 if 'site_id' in record:
438 site_ids.append(record['site_id'])
440 # get all pis from the sites we've encountered
441 # and store them in a dictionary keyed on site_id
444 pi_filter = {'|roles': ['pi'], '|site_ids': site_ids}
445 pi_list = self.shell.GetPersons(pi_filter, ['person_id', 'site_ids'])
447 # we will need the pi's hrns also
448 person_ids.append(pi['person_id'])
450 # we also need to keep track of the sites these pis
452 for site_id in pi['site_ids']:
453 if site_id in site_pis:
454 site_pis[site_id].append(pi)
456 site_pis[site_id] = [pi]
458 # get sfa records for all records associated with these records.
459 # we'll replace pl ids (person_ids) with hrns from the sfa records
462 # get the registry records
463 person_list, persons = [], {}
464 person_list = dbsession.query (RegRecord).filter(RegRecord.pointer.in_(person_ids))
465 # create a hrns keyed on the sfa record's pointer.
466 # Its possible for multiple records to have the same pointer so
467 # the dict's value will be a list of hrns.
468 persons = defaultdict(list)
469 for person in person_list:
470 persons[person.pointer].append(person)
473 pl_person_list, pl_persons = [], {}
474 pl_person_list = self.shell.GetPersons(person_ids, ['person_id', 'roles'])
475 pl_persons = list_to_dict(pl_person_list, 'person_id')
478 for record in records:
479 # skip records with no pl info (top level authorities)
480 #if record['pointer'] == -1:
483 type = record['type']
484 logger.info("fill_record_sfa_info - incoming record typed %s"%type)
485 if (type == "slice"):
486 # all slice users are researchers
487 record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
489 record['researcher'] = []
490 for person_id in record.get('person_ids', []):
491 hrns = [person.hrn for person in persons[person_id]]
492 record['researcher'].extend(hrns)
494 # pis at the slice's site
495 if 'site_id' in record and record['site_id'] in site_pis:
496 pl_pis = site_pis[record['site_id']]
497 pi_ids = [pi['person_id'] for pi in pl_pis]
498 for person_id in pi_ids:
499 hrns = [person.hrn for person in persons[person_id]]
500 record['PI'].extend(hrns)
501 record['geni_creator'] = record['PI']
503 elif (type.startswith("authority")):
505 logger.info("fill_record_sfa_info - authority xherex")
506 if record['pointer'] != -1:
508 record['operator'] = []
510 for pointer in record.get('person_ids', []):
511 if pointer not in persons or pointer not in pl_persons:
512 # this means there is not sfa or pl record for this user
514 hrns = [person.hrn for person in persons[pointer]]
515 roles = pl_persons[pointer]['roles']
517 record['PI'].extend(hrns)
519 record['operator'].extend(hrns)
521 record['owner'].extend(hrns)
522 # xxx TODO: OrganizationName
523 elif (type == "node"):
524 sfa_info['dns'] = record.get("hostname", "")
525 # xxx TODO: URI, LatLong, IP, DNS
527 elif (type == "user"):
528 logger.info('setting user.email')
529 sfa_info['email'] = record.get("email", "")
530 sfa_info['geni_urn'] = hrn_to_urn(record['hrn'], 'user')
531 sfa_info['geni_certificate'] = record['gid']
532 # xxx TODO: PostalAddress, Phone
533 record.update(sfa_info)
537 # plcapi works by changes, compute what needs to be added/deleted
538 def update_relation (self, subject_type, target_type, relation_name, subject_id, target_ids):
539 # hard-wire the code for slice/user for now, could be smarter if needed
540 if subject_type =='slice' and target_type == 'user' and relation_name == 'researcher':
541 subject=self.shell.GetSlices (subject_id)[0]
542 current_target_ids = subject['person_ids']
543 add_target_ids = list ( set (target_ids).difference(current_target_ids))
544 del_target_ids = list ( set (current_target_ids).difference(target_ids))
545 logger.debug ("subject_id = %s (type=%s)"%(subject_id,type(subject_id)))
546 for target_id in add_target_ids:
547 self.shell.AddPersonToSlice (target_id,subject_id)
548 logger.debug ("add_target_id = %s (type=%s)"%(target_id,type(target_id)))
549 for target_id in del_target_ids:
550 logger.debug ("del_target_id = %s (type=%s)"%(target_id,type(target_id)))
551 self.shell.DeletePersonFromSlice (target_id, subject_id)
552 elif subject_type == 'authority' and target_type == 'user' and relation_name == 'pi':
553 # due to the plcapi limitations this means essentially adding pi role to all people in the list
554 # it's tricky to remove any pi role here, although it might be desirable
555 persons = self.shell.GetPersons (target_ids)
556 for person in persons:
557 if 'pi' not in person['roles']:
558 self.shell.AddRoleToPerson('pi',person['person_id'])
560 logger.info('unexpected relation %s to maintain, %s -> %s'%(relation_name,subject_type,target_type))
563 ########################################
564 ########## aggregate oriented
565 ########################################
567 def testbed_name (self): return "myplc"
569 # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
570 def aggregate_version (self):
571 version_manager = VersionManager()
572 ad_rspec_versions = []
573 request_rspec_versions = []
574 for rspec_version in version_manager.versions:
575 if rspec_version.content_type in ['*', 'ad']:
576 ad_rspec_versions.append(rspec_version.to_dict())
577 if rspec_version.content_type in ['*', 'request']:
578 request_rspec_versions.append(rspec_version.to_dict())
580 'testbed':self.testbed_name(),
581 'geni_request_rspec_versions': request_rspec_versions,
582 'geni_ad_rspec_versions': ad_rspec_versions,
585 def list_slices (self, creds, options):
586 # look in cache first
588 slices = self.cache.get('slices')
590 logger.debug("PlDriver.list_slices returns from cache")
594 slices = self.shell.GetSlices({'peer_id': None}, ['name'])
595 slice_hrns = [slicename_to_hrn(self.hrn, slice['name']) for slice in slices]
596 slice_urns = [hrn_to_urn(slice_hrn, 'slice') for slice_hrn in slice_hrns]
600 logger.debug ("PlDriver.list_slices stores value in cache")
601 self.cache.add('slices', slice_urns)
605 # first 2 args are None in case of resource discovery
606 def list_resources (self, slice_urn, slice_hrn, creds, options):
607 cached_requested = options.get('cached', True)
609 version_manager = VersionManager()
610 # get the rspec's return format from options
611 rspec_version = version_manager.get_version(options.get('geni_rspec_version'))
612 version_string = "rspec_%s" % (rspec_version)
614 #panos adding the info option to the caching key (can be improved)
615 if options.get('info'):
616 version_string = version_string + "_"+options.get('info', 'default')
618 # Adding the list_leases option to the caching key
619 if options.get('list_leases'):
620 version_string = version_string + "_"+options.get('list_leases', 'default')
622 # Adding geni_available to caching key
623 if options.get('geni_available'):
624 version_string = version_string + "_" + str(options.get('geni_available'))
626 # look in cache first
627 if cached_requested and self.cache and not slice_hrn:
628 rspec = self.cache.get(version_string)
630 logger.debug("PlDriver.ListResources: returning cached advertisement")
633 #panos: passing user-defined options
634 #print "manager options = ",options
635 aggregate = PlAggregate(self)
636 rspec = aggregate.get_rspec(slice_xrn=slice_urn, version=rspec_version,
640 if self.cache and not slice_hrn:
641 logger.debug("PlDriver.ListResources: stores advertisement in cache")
642 self.cache.add(version_string, rspec)
646 def sliver_status (self, slice_urn, slice_hrn):
647 # find out where this slice is currently running
648 slicename = hrn_to_pl_slicename(slice_hrn)
650 slices = self.shell.GetSlices([slicename], ['slice_id', 'node_ids','person_ids','name','expires'])
652 raise SliverDoesNotExist("%s (used %s as slicename internally)" % (slice_hrn, slicename))
655 # report about the local nodes only
656 nodes = self.shell.GetNodes({'node_id':slice['node_ids'],'peer_id':None},
657 ['node_id', 'hostname', 'site_id', 'boot_state', 'last_contact'])
660 raise SliverDoesNotExist("You have not allocated any slivers here")
664 if slice['person_ids']:
665 persons = self.shell.GetPersons(slice['person_ids'], ['key_ids'])
666 key_ids = [key_id for person in persons for key_id in person['key_ids']]
667 person_keys = self.shell.GetKeys(key_ids)
668 keys = [key['key'] for key in person_keys]
670 user.update({'urn': slice_urn,
671 'login': slice['name'],
676 site_ids = [node['site_id'] for node in nodes]
679 top_level_status = 'unknown'
681 top_level_status = 'ready'
682 result['geni_urn'] = slice_urn
683 result['pl_login'] = slice['name']
684 result['pl_expires'] = datetime_to_string(utcparse(slice['expires']))
685 result['geni_expires'] = datetime_to_string(utcparse(slice['expires']))
690 res['pl_hostname'] = node['hostname']
691 res['pl_boot_state'] = node['boot_state']
692 res['pl_last_contact'] = node['last_contact']
693 res['geni_expires'] = datetime_to_string(utcparse(slice['expires']))
694 if node['last_contact'] is not None:
696 res['pl_last_contact'] = datetime_to_string(utcparse(node['last_contact']))
697 sliver_xrn = Xrn(slice_urn, type='sliver', id=node['node_id'])
698 sliver_xrn.set_authority(self.hrn)
700 res['geni_urn'] = sliver_xrn.urn
701 if node['boot_state'] == 'boot':
702 res['geni_status'] = 'ready'
704 res['geni_status'] = 'failed'
705 top_level_status = 'failed'
707 res['geni_error'] = ''
708 res['users'] = [user]
710 resources.append(res)
712 result['geni_status'] = top_level_status
713 result['geni_resources'] = resources
716 def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, users, options):
718 aggregate = PlAggregate(self)
719 slices = PlSlices(self)
720 peer = slices.get_peer(slice_hrn)
721 sfa_peer = slices.get_sfa_peer(slice_hrn)
724 slice_record = users[0].get('slice_record', {})
727 rspec = RSpec(rspec_string)
728 requested_attributes = rspec.version.get_slice_attributes()
730 # ensure site record exists
731 site = slices.verify_site(slice_hrn, slice_record, peer, sfa_peer, options=options)
732 # ensure slice record exists
733 slice = slices.verify_slice(slice_hrn, slice_record, peer, sfa_peer, options=options)
734 # ensure person records exists
735 persons = slices.verify_persons(slice_hrn, slice, users, peer, sfa_peer, options=options)
736 # ensure slice attributes exists
737 slices.verify_slice_attributes(slice, requested_attributes, options=options)
739 # add/remove slice from nodes
740 requested_slivers = {}
741 slivers = rspec.version.get_nodes_with_slivers()
742 nodes = slices.verify_slice_nodes(slice, slivers, peer)
744 # add/remove links links
745 slices.verify_slice_links(slice, rspec.version.get_link_requests(), nodes)
748 rspec_requested_leases = rspec.version.get_leases()
749 leases = slices.verify_slice_leases(slice, rspec_requested_leases, peer)
750 #requested_leases = []
752 #for lease in rspec.version.get_leases():
753 # requested_lease = {}
754 # if not lease.get('lease_id'):
755 # requested_lease['hostname'] = xrn_to_hostname(lease.get('component_id').strip())
756 # requested_lease['start_time'] = lease.get('start_time')
757 # requested_lease['duration'] = lease.get('duration')
759 # kept_leases.append(int(lease['lease_id']))
760 # if requested_lease.get('hostname'):
761 # requested_leases.append(requested_lease)
763 #leases = slices.verify_slice_leases(slice, requested_leases, kept_leases, peer)
765 # handle MyPLC peer association.
766 # only used by plc and ple.
767 slices.handle_peer(site, slice, persons, peer)
769 return aggregate.get_rspec(slice_xrn=slice_urn,
770 version=rspec.version)
772 def delete_sliver (self, slice_urn, slice_hrn, creds, options):
773 slicename = hrn_to_pl_slicename(slice_hrn)
774 slices = self.shell.GetSlices({'name': slicename})
779 # determine if this is a peer slice
780 # xxx I wonder if this would not need to use PlSlices.get_peer instead
781 # in which case plc.peers could be deprecated as this here
782 # is the only/last call to this last method in plc.peers
783 peer = peers.get_peer(self, slice_hrn)
786 self.shell.UnBindObjectFromPeer('slice', slice['slice_id'], peer)
787 self.shell.DeleteSliceFromNodes(slicename, slice['node_ids'])
790 self.shell.BindObjectToPeer('slice', slice['slice_id'], peer, slice['peer_slice_id'])
793 def renew_sliver (self, slice_urn, slice_hrn, creds, expiration_time, options):
794 slicename = hrn_to_pl_slicename(slice_hrn)
795 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
797 raise RecordNotFound(slice_hrn)
799 requested_time = utcparse(expiration_time)
800 record = {'expires': int(datetime_to_epoch(requested_time))}
802 self.shell.UpdateSlice(slice['slice_id'], record)
807 # remove the 'enabled' tag
808 def start_slice (self, slice_urn, slice_hrn, creds):
809 slicename = hrn_to_pl_slicename(slice_hrn)
810 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
812 raise RecordNotFound(slice_hrn)
813 slice_id = slices[0]['slice_id']
814 slice_tags = self.shell.GetSliceTags({'slice_id': slice_id, 'tagname': 'enabled'}, ['slice_tag_id'])
815 # just remove the tag if it exists
817 self.shell.DeleteSliceTag(slice_tags[0]['slice_tag_id'])
820 # set the 'enabled' tag to 0
821 def stop_slice (self, slice_urn, slice_hrn, creds):
822 slicename = hrn_to_pl_slicename(slice_hrn)
823 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
825 raise RecordNotFound(slice_hrn)
826 slice_id = slices[0]['slice_id']
827 slice_tags = self.shell.GetSliceTags({'slice_id': slice_id, 'tagname': 'enabled'})
829 self.shell.AddSliceTag(slice_id, 'enabled', '0')
830 elif slice_tags[0]['value'] != "0":
831 tag_id = slice_tags[0]['slice_tag_id']
832 self.shell.UpdateSliceTag(tag_id, '0')
835 def reset_slice (self, slice_urn, slice_hrn, creds):
836 raise SfaNotImplemented ("reset_slice not available at this interface")
838 # xxx this code is quite old and has not run for ages
839 # it is obviously totally broken and needs a rewrite
840 def get_ticket (self, slice_urn, slice_hrn, creds, rspec_string, options):
841 raise SfaNotImplemented,"PlDriver.get_ticket needs a rewrite"
842 # please keep this code for future reference
843 # slices = PlSlices(self)
844 # peer = slices.get_peer(slice_hrn)
845 # sfa_peer = slices.get_sfa_peer(slice_hrn)
847 # # get the slice record
848 # credential = api.getCredential()
849 # interface = api.registries[api.hrn]
850 # registry = api.server_proxy(interface, credential)
851 # records = registry.Resolve(xrn, credential)
853 # # make sure we get a local slice record
855 # for tmp_record in records:
856 # if tmp_record['type'] == 'slice' and \
857 # not tmp_record['peer_authority']:
858 # #Error (E0602, GetTicket): Undefined variable 'SliceRecord'
859 # slice_record = SliceRecord(dict=tmp_record)
861 # raise RecordNotFound(slice_hrn)
863 # # similar to CreateSliver, we must verify that the required records exist
864 # # at this aggregate before we can issue a ticket
866 # rspec = RSpec(rspec_string)
867 # requested_attributes = rspec.version.get_slice_attributes()
869 # # ensure site record exists
870 # site = slices.verify_site(slice_hrn, slice_record, peer, sfa_peer)
871 # # ensure slice record exists
872 # slice = slices.verify_slice(slice_hrn, slice_record, peer, sfa_peer)
873 # # ensure person records exists
874 # # xxx users is undefined in this context
875 # persons = slices.verify_persons(slice_hrn, slice, users, peer, sfa_peer)
876 # # ensure slice attributes exists
877 # slices.verify_slice_attributes(slice, requested_attributes)
880 # slivers = slices.get_slivers(slice_hrn)
883 # raise SliverDoesNotExist(slice_hrn)
888 # 'timestamp': int(time.time()),
889 # 'initscripts': initscripts,
893 # # create the ticket
894 # object_gid = record.get_gid_object()
895 # new_ticket = SfaTicket(subject = object_gid.get_subject())
896 # new_ticket.set_gid_caller(api.auth.client_gid)
897 # new_ticket.set_gid_object(object_gid)
898 # new_ticket.set_issuer(key=api.key, subject=self.hrn)
899 # new_ticket.set_pubkey(object_gid.get_pubkey())
900 # new_ticket.set_attributes(data)
901 # new_ticket.set_rspec(rspec)
902 # #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
903 # new_ticket.encode()
906 # return new_ticket.save_to_string(save_parents=True)