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.util.plxrn import PlXrn, slicename_to_hrn, hostname_to_hrn, hrn_to_pl_slicename
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 pointer = self.shell.AddSite(pl_record)
76 pointer = sites[0]['site_id']
79 acceptable_fields=['url', 'instantiation', 'name', 'description']
80 for key in pl_record.keys():
81 if key not in acceptable_fields:
83 slices = self.shell.GetSlices([pl_record['name']])
85 pointer = self.shell.AddSlice(pl_record)
87 pointer = slices[0]['slice_id']
90 persons = self.shell.GetPersons({'email':sfa_record['email']})
92 for key in ['first_name','last_name']:
93 if key not in sfa_record: sfa_record[key]='*from*sfa*'
94 pointer = self.shell.AddPerson(dict(sfa_record))
96 pointer = persons[0]['person_id']
98 if 'enabled' in sfa_record and sfa_record['enabled']:
99 self.shell.UpdatePerson(pointer, {'enabled': sfa_record['enabled']})
100 # add this person to the site only if she is being added for the first
101 # time by sfa and doesont already exist in plc
102 if not persons or not persons[0]['site_ids']:
103 login_base = get_leaf(sfa_record['authority'])
104 self.shell.AddPersonToSite(pointer, login_base)
106 # What roles should this user have?
108 if 'roles' in sfa_record:
109 # if specified in xml, but only low-level roles
110 roles = [ role for role in sfa_record['roles'] if role in ['user','tech'] ]
111 # at least user if no other cluse could be found
115 self.shell.AddRoleToPerson(role, pointer)
118 self.shell.AddPersonKey(pointer, {'key_type' : 'ssh', 'key' : pub_key})
121 login_base = PlXrn(xrn=sfa_record['authority'],type='node').pl_login_base()
122 nodes = self.shell.GetNodes([pl_record['hostname']])
124 pointer = self.shell.AddNode(login_base, pl_record)
126 pointer = nodes[0]['node_id']
131 # xxx actually old_sfa_record comes filled with plc stuff as well in the original code
132 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
133 pointer = old_sfa_record['pointer']
134 type = old_sfa_record['type']
136 # new_key implemented for users only
137 if new_key and type not in [ 'user' ]:
138 raise UnknownSfaType(type)
140 if (type == "authority"):
141 self.shell.UpdateSite(pointer, new_sfa_record)
143 elif type == "slice":
144 pl_record=self.sfa_fields_to_pl_fields(type, hrn, new_sfa_record)
145 if 'name' in pl_record:
146 pl_record.pop('name')
147 self.shell.UpdateSlice(pointer, pl_record)
150 # SMBAKER: UpdatePerson only allows a limited set of fields to be
151 # updated. Ideally we should have a more generic way of doing
152 # this. I copied the field names from UpdatePerson.py...
154 all_fields = new_sfa_record
155 for key in all_fields.keys():
156 if key in ['first_name', 'last_name', 'title', 'email',
157 'password', 'phone', 'url', 'bio', 'accepted_aup',
159 update_fields[key] = all_fields[key]
160 self.shell.UpdatePerson(pointer, update_fields)
163 # must check this key against the previous one if it exists
164 persons = self.shell.GetPersons([pointer], ['key_ids'])
166 keys = person['key_ids']
167 keys = self.shell.GetKeys(person['key_ids'])
169 # Delete all stale keys
172 if new_key != key['key']:
173 self.shell.DeleteKey(key['key_id'])
177 self.shell.AddPersonKey(pointer, {'key_type': 'ssh', 'key': new_key})
180 self.shell.UpdateNode(pointer, new_sfa_record)
186 def remove (self, sfa_record):
187 type=sfa_record['type']
188 pointer=sfa_record['pointer']
190 persons = self.shell.GetPersons(pointer)
191 # only delete this person if he has site ids. if he doesnt, it probably means
192 # he was just removed from a site, not actually deleted
193 if persons and persons[0]['site_ids']:
194 self.shell.DeletePerson(pointer)
195 elif type == 'slice':
196 if self.shell.GetSlices(pointer):
197 self.shell.DeleteSlice(pointer)
199 if self.shell.GetNodes(pointer):
200 self.shell.DeleteNode(pointer)
201 elif type == 'authority':
202 if self.shell.GetSites(pointer):
203 self.shell.DeleteSite(pointer)
212 # Convert SFA fields to PLC fields for use when registering or updating
213 # registry record in the PLC database
216 def sfa_fields_to_pl_fields(self, type, hrn, sfa_record):
221 pl_record["name"] = hrn_to_pl_slicename(hrn)
222 if "instantiation" in sfa_record:
223 pl_record['instantiation']=sfa_record['instantiation']
225 pl_record["instantiation"] = "plc-instantiated"
226 if "url" in sfa_record:
227 pl_record["url"] = sfa_record["url"]
228 if "description" in sfa_record:
229 pl_record["description"] = sfa_record["description"]
230 if "expires" in sfa_record:
231 date = utcparse(sfa_record['expires'])
232 expires = datetime_to_epoch(date)
233 pl_record["expires"] = expires
236 if not "hostname" in pl_record:
237 # fetch from sfa_record
238 if "hostname" not in sfa_record:
239 raise MissingSfaInfo("hostname")
240 pl_record["hostname"] = sfa_record["hostname"]
241 if "model" in sfa_record:
242 pl_record["model"] = sfa_record["model"]
244 pl_record["model"] = "geni"
246 elif type == "authority":
247 pl_record["login_base"] = PlXrn(xrn=hrn,type='authority').pl_login_base()
248 if "name" not in sfa_record:
249 pl_record["name"] = hrn
250 if "abbreviated_name" not in sfa_record:
251 pl_record["abbreviated_name"] = hrn
252 if "enabled" not in sfa_record:
253 pl_record["enabled"] = True
254 if "is_public" not in sfa_record:
255 pl_record["is_public"] = True
260 def fill_record_info(self, records):
262 Given a (list of) SFA record, fill in the PLC specific
263 and SFA specific fields in the record.
265 if not isinstance(records, list):
268 self.fill_record_pl_info(records)
269 self.fill_record_hrns(records)
270 self.fill_record_sfa_info(records)
273 def fill_record_pl_info(self, records):
275 Fill in the planetlab specific fields of a SFA record. This
276 involves calling the appropriate PLC method to retrieve the
277 database record for the object.
279 @param record: record to fill in field (in/out param)
282 node_ids, site_ids, slice_ids = [], [], []
283 person_ids, key_ids = [], []
284 type_map = {'node': node_ids, 'authority': site_ids,
285 'slice': slice_ids, 'user': person_ids}
287 for record in records:
288 for type in type_map:
289 if type == record['type']:
290 type_map[type].append(record['pointer'])
293 nodes, sites, slices, persons, keys = {}, {}, {}, {}, {}
295 node_list = self.shell.GetNodes(node_ids)
296 nodes = list_to_dict(node_list, 'node_id')
298 site_list = self.shell.GetSites(site_ids)
299 sites = list_to_dict(site_list, 'site_id')
301 slice_list = self.shell.GetSlices(slice_ids)
302 slices = list_to_dict(slice_list, 'slice_id')
304 person_list = self.shell.GetPersons(person_ids)
305 persons = list_to_dict(person_list, 'person_id')
306 for person in persons:
307 key_ids.extend(persons[person]['key_ids'])
309 pl_records = {'node': nodes, 'authority': sites,
310 'slice': slices, 'user': persons}
313 key_list = self.shell.GetKeys(key_ids)
314 keys = list_to_dict(key_list, 'key_id')
317 for record in records:
318 # records with pointer==-1 do not have plc info.
319 # for example, the top level authority records which are
320 # authorities, but not PL "sites"
321 if record['pointer'] == -1:
324 for type in pl_records:
325 if record['type'] == type:
326 if record['pointer'] in pl_records[type]:
327 record.update(pl_records[type][record['pointer']])
330 if record['type'] == 'user':
331 if 'key_ids' not in record:
332 logger.info("user record has no 'key_ids' - need to import from myplc ?")
334 pubkeys = [keys[key_id]['key'] for key_id in record['key_ids'] if key_id in keys]
335 record['keys'] = pubkeys
339 def fill_record_hrns(self, records):
341 convert pl ids to hrns
345 slice_ids, person_ids, site_ids, node_ids = [], [], [], []
346 for record in records:
347 if 'site_id' in record:
348 site_ids.append(record['site_id'])
349 if 'site_ids' in record:
350 site_ids.extend(record['site_ids'])
351 if 'person_ids' in record:
352 person_ids.extend(record['person_ids'])
353 if 'slice_ids' in record:
354 slice_ids.extend(record['slice_ids'])
355 if 'node_ids' in record:
356 node_ids.extend(record['node_ids'])
359 slices, persons, sites, nodes = {}, {}, {}, {}
361 site_list = self.shell.GetSites(site_ids, ['site_id', 'login_base'])
362 sites = list_to_dict(site_list, 'site_id')
364 person_list = self.shell.GetPersons(person_ids, ['person_id', 'email'])
365 persons = list_to_dict(person_list, 'person_id')
367 slice_list = self.shell.GetSlices(slice_ids, ['slice_id', 'name'])
368 slices = list_to_dict(slice_list, 'slice_id')
370 node_list = self.shell.GetNodes(node_ids, ['node_id', 'hostname'])
371 nodes = list_to_dict(node_list, 'node_id')
373 # convert ids to hrns
374 for record in records:
375 # get all relevant data
376 type = record['type']
377 pointer = record['pointer']
383 if 'site_id' in record:
384 site = sites[record['site_id']]
385 login_base = site['login_base']
386 record['site'] = ".".join([auth_hrn, login_base])
387 if 'person_ids' in record:
388 emails = [persons[person_id]['email'] for person_id in record['person_ids'] \
389 if person_id in persons]
390 usernames = [email.split('@')[0] for email in emails]
391 person_hrns = [".".join([auth_hrn, login_base, username]) for username in usernames]
392 record['persons'] = person_hrns
393 if 'slice_ids' in record:
394 slicenames = [slices[slice_id]['name'] for slice_id in record['slice_ids'] \
395 if slice_id in slices]
396 slice_hrns = [slicename_to_hrn(auth_hrn, slicename) for slicename in slicenames]
397 record['slices'] = slice_hrns
398 if 'node_ids' in record:
399 hostnames = [nodes[node_id]['hostname'] for node_id in record['node_ids'] \
401 node_hrns = [hostname_to_hrn(auth_hrn, login_base, hostname) for hostname in hostnames]
402 record['nodes'] = node_hrns
403 if 'site_ids' in record:
404 login_bases = [sites[site_id]['login_base'] for site_id in record['site_ids'] \
406 site_hrns = [".".join([auth_hrn, lbase]) for lbase in login_bases]
407 record['sites'] = site_hrns
409 if 'expires' in record:
410 date = utcparse(record['expires'])
411 datestring = datetime_to_string(date)
412 record['expires'] = datestring
416 def fill_record_sfa_info(self, records):
418 def startswith(prefix, values):
419 return [value for value in values if value.startswith(prefix)]
424 for record in records:
425 person_ids.extend(record.get("person_ids", []))
426 site_ids.extend(record.get("site_ids", []))
427 if 'site_id' in record:
428 site_ids.append(record['site_id'])
430 # get all pis from the sites we've encountered
431 # and store them in a dictionary keyed on site_id
434 pi_filter = {'|roles': ['pi'], '|site_ids': site_ids}
435 pi_list = self.shell.GetPersons(pi_filter, ['person_id', 'site_ids'])
437 # we will need the pi's hrns also
438 person_ids.append(pi['person_id'])
440 # we also need to keep track of the sites these pis
442 for site_id in pi['site_ids']:
443 if site_id in site_pis:
444 site_pis[site_id].append(pi)
446 site_pis[site_id] = [pi]
448 # get sfa records for all records associated with these records.
449 # we'll replace pl ids (person_ids) with hrns from the sfa records
452 # get the registry records
453 person_list, persons = [], {}
454 person_list = dbsession.query (RegRecord).filter(RegRecord.pointer.in_(person_ids))
455 # create a hrns keyed on the sfa record's pointer.
456 # Its possible for multiple records to have the same pointer so
457 # the dict's value will be a list of hrns.
458 persons = defaultdict(list)
459 for person in person_list:
460 persons[person.pointer].append(person)
463 pl_person_list, pl_persons = [], {}
464 pl_person_list = self.shell.GetPersons(person_ids, ['person_id', 'roles'])
465 pl_persons = list_to_dict(pl_person_list, 'person_id')
468 for record in records:
469 # skip records with no pl info (top level authorities)
470 #if record['pointer'] == -1:
473 type = record['type']
474 logger.info("fill_record_sfa_info - incoming record typed %s"%type)
475 if (type == "slice"):
476 # all slice users are researchers
477 record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
479 record['researcher'] = []
480 for person_id in record.get('person_ids', []):
481 hrns = [person.hrn for person in persons[person_id]]
482 record['researcher'].extend(hrns)
484 # pis at the slice's site
485 if 'site_id' in record and record['site_id'] in site_pis:
486 pl_pis = site_pis[record['site_id']]
487 pi_ids = [pi['person_id'] for pi in pl_pis]
488 for person_id in pi_ids:
489 hrns = [person.hrn for person in persons[person_id]]
490 record['PI'].extend(hrns)
491 record['geni_creator'] = record['PI']
493 elif (type.startswith("authority")):
495 logger.info("fill_record_sfa_info - authority xherex")
496 if record['pointer'] != -1:
498 record['operator'] = []
500 for pointer in record.get('person_ids', []):
501 if pointer not in persons or pointer not in pl_persons:
502 # this means there is not sfa or pl record for this user
504 hrns = [person.hrn for person in persons[pointer]]
505 roles = pl_persons[pointer]['roles']
507 record['PI'].extend(hrns)
509 record['operator'].extend(hrns)
511 record['owner'].extend(hrns)
512 # xxx TODO: OrganizationName
513 elif (type == "node"):
514 sfa_info['dns'] = record.get("hostname", "")
515 # xxx TODO: URI, LatLong, IP, DNS
517 elif (type == "user"):
518 logger.info('setting user.email')
519 sfa_info['email'] = record.get("email", "")
520 sfa_info['geni_urn'] = hrn_to_urn(record['hrn'], 'user')
521 sfa_info['geni_certificate'] = record['gid']
522 # xxx TODO: PostalAddress, Phone
523 record.update(sfa_info)
527 # plcapi works by changes, compute what needs to be added/deleted
528 def update_relation (self, subject_type, target_type, relation_name, subject_id, target_ids):
529 # hard-wire the code for slice/user for now, could be smarter if needed
530 if subject_type =='slice' and target_type == 'user' and relation_name == 'researcher':
531 subject=self.shell.GetSlices (subject_id)[0]
532 current_target_ids = subject['person_ids']
533 add_target_ids = list ( set (target_ids).difference(current_target_ids))
534 del_target_ids = list ( set (current_target_ids).difference(target_ids))
535 logger.debug ("subject_id = %s (type=%s)"%(subject_id,type(subject_id)))
536 for target_id in add_target_ids:
537 self.shell.AddPersonToSlice (target_id,subject_id)
538 logger.debug ("add_target_id = %s (type=%s)"%(target_id,type(target_id)))
539 for target_id in del_target_ids:
540 logger.debug ("del_target_id = %s (type=%s)"%(target_id,type(target_id)))
541 self.shell.DeletePersonFromSlice (target_id, subject_id)
542 elif subject_type == 'authority' and target_type == 'user' and relation_name == 'pi':
543 # due to the plcapi limitations this means essentially adding pi role to all people in the list
544 # it's tricky to remove any pi role here, although it might be desirable
545 persons = self.shell.GetPersons (target_ids)
546 for person in persons:
547 if 'pi' not in person['roles']:
548 self.shell.AddRoleToPerson('pi',person['person_id'])
550 logger.info('unexpected relation %s to maintain, %s -> %s'%(relation_name,subject_type,target_type))
553 ########################################
554 ########## aggregate oriented
555 ########################################
557 def testbed_name (self): return "myplc"
559 # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
560 def aggregate_version (self):
561 version_manager = VersionManager()
562 ad_rspec_versions = []
563 request_rspec_versions = []
564 for rspec_version in version_manager.versions:
565 if rspec_version.content_type in ['*', 'ad']:
566 ad_rspec_versions.append(rspec_version.to_dict())
567 if rspec_version.content_type in ['*', 'request']:
568 request_rspec_versions.append(rspec_version.to_dict())
570 'testbed':self.testbed_name(),
571 'geni_request_rspec_versions': request_rspec_versions,
572 'geni_ad_rspec_versions': ad_rspec_versions,
575 def list_slices (self, creds, options):
576 # look in cache first
578 slices = self.cache.get('slices')
580 logger.debug("PlDriver.list_slices returns from cache")
584 slices = self.shell.GetSlices({'peer_id': None}, ['name'])
585 slice_hrns = [slicename_to_hrn(self.hrn, slice['name']) for slice in slices]
586 slice_urns = [hrn_to_urn(slice_hrn, 'slice') for slice_hrn in slice_hrns]
590 logger.debug ("PlDriver.list_slices stores value in cache")
591 self.cache.add('slices', slice_urns)
595 # first 2 args are None in case of resource discovery
596 def list_resources (self, slice_urn, slice_hrn, creds, options):
597 cached_requested = options.get('cached', True)
599 version_manager = VersionManager()
600 # get the rspec's return format from options
601 rspec_version = version_manager.get_version(options.get('geni_rspec_version'))
602 version_string = "rspec_%s" % (rspec_version)
604 #panos adding the info option to the caching key (can be improved)
605 if options.get('info'):
606 version_string = version_string + "_"+options.get('info', 'default')
608 # look in cache first
609 if cached_requested and self.cache and not slice_hrn:
610 rspec = self.cache.get(version_string)
612 logger.debug("PlDriver.ListResources: returning cached advertisement")
615 #panos: passing user-defined options
616 #print "manager options = ",options
617 aggregate = PlAggregate(self)
618 rspec = aggregate.get_rspec(slice_xrn=slice_urn, version=rspec_version,
622 if self.cache and not slice_hrn:
623 logger.debug("PlDriver.ListResources: stores advertisement in cache")
624 self.cache.add(version_string, rspec)
628 def sliver_status (self, slice_urn, slice_hrn):
629 # find out where this slice is currently running
630 slicename = hrn_to_pl_slicename(slice_hrn)
632 slices = self.shell.GetSlices([slicename], ['slice_id', 'node_ids','person_ids','name','expires'])
634 raise SliverDoesNotExist("%s (used %s as slicename internally)" % (slice_hrn, slicename))
637 # report about the local nodes only
638 nodes = self.shell.GetNodes({'node_id':slice['node_ids'],'peer_id':None},
639 ['node_id', 'hostname', 'site_id', 'boot_state', 'last_contact'])
642 raise SliverDoesNotExist("You have not allocated any slivers here")
646 if slice['person_ids']:
647 persons = self.shell.GetPersons(slice['person_ids'], ['key_ids'])
648 key_ids = [key_id for person in persons for key_id in person['key_ids']]
649 person_keys = self.shell.GetKeys(key_ids)
650 keys = [key['key'] for key in keys]
652 user.update({'urn': slice_urn,
653 'login': slice['name'],
658 site_ids = [node['site_id'] for node in nodes]
661 top_level_status = 'unknown'
663 top_level_status = 'ready'
664 result['geni_urn'] = slice_urn
665 result['pl_login'] = slice['name']
666 result['pl_expires'] = datetime_to_string(utcparse(slice['expires']))
667 result['geni_expires'] = datetime_to_string(utcparse(slice['expires']))
672 res['pl_hostname'] = node['hostname']
673 res['pl_boot_state'] = node['boot_state']
674 res['pl_last_contact'] = node['last_contact']
675 res['geni_expires'] = datetime_to_string(utcparse(slice['expires']))
676 if node['last_contact'] is not None:
678 res['pl_last_contact'] = datetime_to_string(utcparse(node['last_contact']))
679 sliver_id = urn_to_sliver_id(slice_urn, slice['slice_id'], node['node_id'], authority=self.hrn)
680 res['geni_urn'] = sliver_id
681 if node['boot_state'] == 'boot':
682 res['geni_status'] = 'ready'
684 res['geni_status'] = 'failed'
685 top_level_status = 'failed'
687 res['geni_error'] = ''
688 res['users'] = [user]
690 resources.append(res)
692 result['geni_status'] = top_level_status
693 result['geni_resources'] = resources
696 def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, users, options):
698 aggregate = PlAggregate(self)
699 slices = PlSlices(self)
700 peer = slices.get_peer(slice_hrn)
701 sfa_peer = slices.get_sfa_peer(slice_hrn)
704 slice_record = users[0].get('slice_record', {})
707 rspec = RSpec(rspec_string)
708 requested_attributes = rspec.version.get_slice_attributes()
710 # ensure site record exists
711 site = slices.verify_site(slice_hrn, slice_record, peer, sfa_peer, options=options)
712 # ensure slice record exists
713 slice = slices.verify_slice(slice_hrn, slice_record, peer, sfa_peer, options=options)
714 # ensure person records exists
715 persons = slices.verify_persons(slice_hrn, slice, users, peer, sfa_peer, options=options)
716 # ensure slice attributes exists
717 slices.verify_slice_attributes(slice, requested_attributes, options=options)
719 # add/remove slice from nodes
720 requested_slivers = []
721 for node in rspec.version.get_nodes_with_slivers():
723 if node.get('component_name'):
724 hostname = node.get('component_name')
725 elif node.get('component_id'):
726 hostname = xrn_to_hostname(node.get('component_id'))
728 requested_slivers.append(hostname)
729 nodes = slices.verify_slice_nodes(slice, requested_slivers, peer)
731 # add/remove links links
732 slices.verify_slice_links(slice, rspec.version.get_link_requests(), nodes)
734 # handle MyPLC peer association.
735 # only used by plc and ple.
736 slices.handle_peer(site, slice, persons, peer)
738 return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
740 def delete_sliver (self, slice_urn, slice_hrn, creds, options):
741 slicename = hrn_to_pl_slicename(slice_hrn)
742 slices = self.shell.GetSlices({'name': slicename})
747 # determine if this is a peer slice
748 # xxx I wonder if this would not need to use PlSlices.get_peer instead
749 # in which case plc.peers could be deprecated as this here
750 # is the only/last call to this last method in plc.peers
751 peer = peers.get_peer(self, slice_hrn)
754 self.shell.UnBindObjectFromPeer('slice', slice['slice_id'], peer)
755 self.shell.DeleteSliceFromNodes(slicename, slice['node_ids'])
758 self.shell.BindObjectToPeer('slice', slice['slice_id'], peer, slice['peer_slice_id'])
761 def renew_sliver (self, slice_urn, slice_hrn, creds, expiration_time, options):
762 slicename = hrn_to_pl_slicename(slice_hrn)
763 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
765 raise RecordNotFound(slice_hrn)
767 requested_time = utcparse(expiration_time)
768 record = {'expires': int(datetime_to_epoch(requested_time))}
770 self.shell.UpdateSlice(slice['slice_id'], record)
775 # remove the 'enabled' tag
776 def start_slice (self, slice_urn, slice_hrn, creds):
777 slicename = hrn_to_pl_slicename(slice_hrn)
778 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
780 raise RecordNotFound(slice_hrn)
781 slice_id = slices[0]['slice_id']
782 slice_tags = self.shell.GetSliceTags({'slice_id': slice_id, 'tagname': 'enabled'}, ['slice_tag_id'])
783 # just remove the tag if it exists
785 self.shell.DeleteSliceTag(slice_tags[0]['slice_tag_id'])
788 # set the 'enabled' tag to 0
789 def stop_slice (self, slice_urn, slice_hrn, creds):
790 slicename = hrn_to_pl_slicename(slice_hrn)
791 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
793 raise RecordNotFound(slice_hrn)
794 slice_id = slices[0]['slice_id']
795 slice_tags = self.shell.GetSliceTags({'slice_id': slice_id, 'tagname': 'enabled'})
797 self.shell.AddSliceTag(slice_id, 'enabled', '0')
798 elif slice_tags[0]['value'] != "0":
799 tag_id = slice_tags[0]['slice_tag_id']
800 self.shell.UpdateSliceTag(tag_id, '0')
803 def reset_slice (self, slice_urn, slice_hrn, creds):
804 raise SfaNotImplemented ("reset_slice not available at this interface")
806 # xxx this code is quite old and has not run for ages
807 # it is obviously totally broken and needs a rewrite
808 def get_ticket (self, slice_urn, slice_hrn, creds, rspec_string, options):
809 raise SfaNotImplemented,"PlDriver.get_ticket needs a rewrite"
810 # please keep this code for future reference
811 # slices = PlSlices(self)
812 # peer = slices.get_peer(slice_hrn)
813 # sfa_peer = slices.get_sfa_peer(slice_hrn)
815 # # get the slice record
816 # credential = api.getCredential()
817 # interface = api.registries[api.hrn]
818 # registry = api.server_proxy(interface, credential)
819 # records = registry.Resolve(xrn, credential)
821 # # make sure we get a local slice record
823 # for tmp_record in records:
824 # if tmp_record['type'] == 'slice' and \
825 # not tmp_record['peer_authority']:
826 # #Error (E0602, GetTicket): Undefined variable 'SliceRecord'
827 # slice_record = SliceRecord(dict=tmp_record)
829 # raise RecordNotFound(slice_hrn)
831 # # similar to CreateSliver, we must verify that the required records exist
832 # # at this aggregate before we can issue a ticket
834 # rspec = RSpec(rspec_string)
835 # requested_attributes = rspec.version.get_slice_attributes()
837 # # ensure site record exists
838 # site = slices.verify_site(slice_hrn, slice_record, peer, sfa_peer)
839 # # ensure slice record exists
840 # slice = slices.verify_slice(slice_hrn, slice_record, peer, sfa_peer)
841 # # ensure person records exists
842 # # xxx users is undefined in this context
843 # persons = slices.verify_persons(slice_hrn, slice, users, peer, sfa_peer)
844 # # ensure slice attributes exists
845 # slices.verify_slice_attributes(slice, requested_attributes)
848 # slivers = slices.get_slivers(slice_hrn)
851 # raise SliverDoesNotExist(slice_hrn)
856 # 'timestamp': int(time.time()),
857 # 'initscripts': initscripts,
861 # # create the ticket
862 # object_gid = record.get_gid_object()
863 # new_ticket = SfaTicket(subject = object_gid.get_subject())
864 # new_ticket.set_gid_caller(api.auth.client_gid)
865 # new_ticket.set_gid_object(object_gid)
866 # new_ticket.set_issuer(key=api.key, subject=self.hrn)
867 # new_ticket.set_pubkey(object_gid.get_pubkey())
868 # new_ticket.set_attributes(data)
869 # new_ticket.set_rspec(rspec)
870 # #new_ticket.set_parent(api.auth.hierarchy.get_auth_ticket(auth_hrn))
871 # new_ticket.encode()
874 # return new_ticket.save_to_string(save_parents=True)