3 from sfa.util.faults import MissingSfaInfo, UnknownSfaType, \
4 RecordNotFound, SfaNotImplemented, SliverDoesNotExist, SearchFailed, \
5 UnsupportedOperation, Forbidden
6 from sfa.util.sfalogging import logger
7 from sfa.util.defaultdict import defaultdict
8 from sfa.util.sfatime import utcparse, datetime_to_string, datetime_to_epoch
9 from sfa.util.xrn import Xrn, hrn_to_urn, get_leaf
10 from sfa.util.cache import Cache
12 # one would think the driver should not need to mess with the SFA db, but..
13 from sfa.storage.alchemy import dbsession
14 from sfa.storage.model import RegRecord, SliverAllocation
15 from sfa.trust.credential import Credential
17 # used to be used in get_ticket
18 #from sfa.trust.sfaticket import SfaTicket
19 from sfa.rspecs.version_manager import VersionManager
20 from sfa.rspecs.rspec import RSpec
22 # the driver interface, mostly provides default behaviours
23 from sfa.managers.driver import Driver
24 from sfa.planetlab.plshell import PlShell
25 import sfa.planetlab.peers as peers
26 from sfa.planetlab.plaggregate import PlAggregate
27 from sfa.planetlab.plslices import PlSlices
28 from sfa.planetlab.plxrn import PlXrn, slicename_to_hrn, hostname_to_hrn, hrn_to_pl_slicename, xrn_to_hostname
31 def list_to_dict(recs, key):
33 convert a list of dictionaries into a dictionary keyed on the
34 specified dictionary key
36 return dict ( [ (rec[key],rec) for rec in recs ] )
39 # PlShell is just an xmlrpc serverproxy where methods
40 # can be sent as-is; it takes care of authentication
41 # from the global config
43 class PlDriver (Driver):
45 # the cache instance is a class member so it survives across incoming requests
48 def __init__ (self, config):
49 Driver.__init__ (self, config)
50 self.shell = PlShell (config)
52 if config.SFA_AGGREGATE_CACHING:
53 if PlDriver.cache is None:
54 PlDriver.cache = Cache()
55 self.cache = PlDriver.cache
57 def sliver_to_slice_xrn(self, xrn):
58 sliver_id_parts = Xrn(xrn).get_sliver_id_parts()
59 slice_id = int(sliver_id_parts[0])
60 slices = self.shell.GetSlices(slice_id)
62 raise Forbidden("Unable to locate slice record for sliver: %s" % xrn)
64 slice_xrn = PlXrn(auth=self.hrn, slicename=slice['name'])
67 def check_sliver_credentials(self, creds, urns):
68 # build list of cred object hrns
71 slice_cred_hrn = Credential(cred=cred).get_gid_object().get_hrn()
72 slice_cred_names.append(PlXrn(xrn=slice_cred_hrn).pl_slicename())
74 # look up slice name of slivers listed in urns arg
77 sliver_id_parts = Xrn(xrn=urn).get_sliver_id_parts()
78 slice_ids.append(sliver_id_parts[0])
81 raise Forbidden("sliver urn not provided")
83 slices = self.shell.GetSlices(slice_ids)
84 sliver_names = [slice['name'] for slice in slices]
86 # make sure we have a credential for every specified sliver ierd
87 for sliver_name in sliver_names:
88 if sliver_name not in slice_cred_names:
89 msg = "Valid credential not found for target: %s" % sliver_name
92 ########################################
93 ########## registry oriented
94 ########################################
96 def augment_records_with_testbed_info (self, sfa_records):
97 return self.fill_record_info (sfa_records)
100 def register (self, sfa_record, hrn, pub_key):
101 type = sfa_record['type']
102 pl_record = self.sfa_fields_to_pl_fields(type, hrn, sfa_record)
104 if type == 'authority':
105 sites = self.shell.GetSites([pl_record['login_base']])
107 # xxx when a site gets registered through SFA we need to set its max_slices
108 if 'max_slices' not in pl_record:
109 pl_record['max_slices']=2
110 pointer = self.shell.AddSite(pl_record)
112 pointer = sites[0]['site_id']
114 elif type == 'slice':
115 acceptable_fields=['url', 'instantiation', 'name', 'description']
116 for key in pl_record.keys():
117 if key not in acceptable_fields:
119 slices = self.shell.GetSlices([pl_record['name']])
121 pointer = self.shell.AddSlice(pl_record)
123 pointer = slices[0]['slice_id']
126 persons = self.shell.GetPersons({'email':sfa_record['email']})
128 for key in ['first_name','last_name']:
129 if key not in sfa_record: sfa_record[key]='*from*sfa*'
130 # AddPerson does not allow everything to be set
131 can_add = ['first_name', 'last_name', 'title','email', 'password', 'phone', 'url', 'bio']
132 add_person_dict=dict ( [ (k,sfa_record[k]) for k in sfa_record if k in can_add ] )
133 pointer = self.shell.AddPerson(add_person_dict)
135 pointer = persons[0]['person_id']
137 if 'enabled' in sfa_record and sfa_record['enabled']:
138 self.shell.UpdatePerson(pointer, {'enabled': sfa_record['enabled']})
139 # add this person to the site only if she is being added for the first
140 # time by sfa and doesont already exist in plc
141 if not persons or not persons[0]['site_ids']:
142 login_base = get_leaf(sfa_record['authority'])
143 self.shell.AddPersonToSite(pointer, login_base)
145 # What roles should this user have?
147 if 'roles' in sfa_record:
148 # if specified in xml, but only low-level roles
149 roles = [ role for role in sfa_record['roles'] if role in ['user','tech'] ]
150 # at least user if no other cluse could be found
154 self.shell.AddRoleToPerson(role, pointer)
157 self.shell.AddPersonKey(pointer, {'key_type' : 'ssh', 'key' : pub_key})
160 login_base = PlXrn(xrn=sfa_record['authority'],type='node').pl_login_base()
161 nodes = self.shell.GetNodes([pl_record['hostname']])
163 pointer = self.shell.AddNode(login_base, pl_record)
165 pointer = nodes[0]['node_id']
170 # xxx actually old_sfa_record comes filled with plc stuff as well in the original code
171 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
172 pointer = old_sfa_record['pointer']
173 type = old_sfa_record['type']
175 # new_key implemented for users only
176 if new_key and type not in [ 'user' ]:
177 raise UnknownSfaType(type)
179 if (type == "authority"):
180 self.shell.UpdateSite(pointer, new_sfa_record)
182 elif type == "slice":
183 pl_record=self.sfa_fields_to_pl_fields(type, hrn, new_sfa_record)
184 if 'name' in pl_record:
185 pl_record.pop('name')
186 self.shell.UpdateSlice(pointer, pl_record)
189 # SMBAKER: UpdatePerson only allows a limited set of fields to be
190 # updated. Ideally we should have a more generic way of doing
191 # this. I copied the field names from UpdatePerson.py...
193 all_fields = new_sfa_record
194 for key in all_fields.keys():
195 if key in ['first_name', 'last_name', 'title', 'email',
196 'password', 'phone', 'url', 'bio', 'accepted_aup',
198 update_fields[key] = all_fields[key]
199 # when updating a user, we always get a 'email' field at this point
200 # this is because 'email' is a native field in the RegUser object...
201 if 'email' in update_fields and not update_fields['email']:
202 del update_fields['email']
203 self.shell.UpdatePerson(pointer, update_fields)
206 # must check this key against the previous one if it exists
207 persons = self.shell.GetPersons([pointer], ['key_ids'])
209 keys = person['key_ids']
210 keys = self.shell.GetKeys(person['key_ids'])
212 # Delete all stale keys
215 if new_key != key['key']:
216 self.shell.DeleteKey(key['key_id'])
220 self.shell.AddPersonKey(pointer, {'key_type': 'ssh', 'key': new_key})
223 self.shell.UpdateNode(pointer, new_sfa_record)
229 def remove (self, sfa_record):
230 type=sfa_record['type']
231 pointer=sfa_record['pointer']
233 persons = self.shell.GetPersons(pointer)
234 # only delete this person if he has site ids. if he doesnt, it probably means
235 # he was just removed from a site, not actually deleted
236 if persons and persons[0]['site_ids']:
237 self.shell.DeletePerson(pointer)
238 elif type == 'slice':
239 if self.shell.GetSlices(pointer):
240 self.shell.DeleteSlice(pointer)
242 if self.shell.GetNodes(pointer):
243 self.shell.DeleteNode(pointer)
244 elif type == 'authority':
245 if self.shell.GetSites(pointer):
246 self.shell.DeleteSite(pointer)
255 # Convert SFA fields to PLC fields for use when registering or updating
256 # registry record in the PLC database
259 def sfa_fields_to_pl_fields(self, type, hrn, sfa_record):
264 pl_record["name"] = hrn_to_pl_slicename(hrn)
265 if "instantiation" in sfa_record:
266 pl_record['instantiation']=sfa_record['instantiation']
268 pl_record["instantiation"] = "plc-instantiated"
269 if "url" in sfa_record:
270 pl_record["url"] = sfa_record["url"]
271 if "description" in sfa_record:
272 pl_record["description"] = sfa_record["description"]
273 if "expires" in sfa_record:
274 date = utcparse(sfa_record['expires'])
275 expires = datetime_to_epoch(date)
276 pl_record["expires"] = expires
279 if not "hostname" in pl_record:
280 # fetch from sfa_record
281 if "hostname" not in sfa_record:
282 raise MissingSfaInfo("hostname")
283 pl_record["hostname"] = sfa_record["hostname"]
284 if "model" in sfa_record:
285 pl_record["model"] = sfa_record["model"]
287 pl_record["model"] = "geni"
289 elif type == "authority":
290 pl_record["login_base"] = PlXrn(xrn=hrn,type='authority').pl_login_base()
291 if "name" not in sfa_record:
292 pl_record["name"] = hrn
293 if "abbreviated_name" not in sfa_record:
294 pl_record["abbreviated_name"] = hrn
295 if "enabled" not in sfa_record:
296 pl_record["enabled"] = True
297 if "is_public" not in sfa_record:
298 pl_record["is_public"] = True
303 def fill_record_info(self, records):
305 Given a (list of) SFA record, fill in the PLC specific
306 and SFA specific fields in the record.
308 if not isinstance(records, list):
311 self.fill_record_pl_info(records)
312 self.fill_record_hrns(records)
313 self.fill_record_sfa_info(records)
316 def fill_record_pl_info(self, records):
318 Fill in the planetlab specific fields of a SFA record. This
319 involves calling the appropriate PLC method to retrieve the
320 database record for the object.
322 @param record: record to fill in field (in/out param)
325 node_ids, site_ids, slice_ids = [], [], []
326 person_ids, key_ids = [], []
327 type_map = {'node': node_ids, 'authority': site_ids,
328 'slice': slice_ids, 'user': person_ids}
330 for record in records:
331 for type in type_map:
332 if type == record['type']:
333 type_map[type].append(record['pointer'])
336 nodes, sites, slices, persons, keys = {}, {}, {}, {}, {}
338 node_list = self.shell.GetNodes(node_ids)
339 nodes = list_to_dict(node_list, 'node_id')
341 site_list = self.shell.GetSites(site_ids)
342 sites = list_to_dict(site_list, 'site_id')
344 slice_list = self.shell.GetSlices(slice_ids)
345 slices = list_to_dict(slice_list, 'slice_id')
347 person_list = self.shell.GetPersons(person_ids)
348 persons = list_to_dict(person_list, 'person_id')
349 for person in persons:
350 key_ids.extend(persons[person]['key_ids'])
352 pl_records = {'node': nodes, 'authority': sites,
353 'slice': slices, 'user': persons}
356 key_list = self.shell.GetKeys(key_ids)
357 keys = list_to_dict(key_list, 'key_id')
360 for record in records:
361 # records with pointer==-1 do not have plc info.
362 # for example, the top level authority records which are
363 # authorities, but not PL "sites"
364 if record['pointer'] == -1:
367 for type in pl_records:
368 if record['type'] == type:
369 if record['pointer'] in pl_records[type]:
370 record.update(pl_records[type][record['pointer']])
373 if record['type'] == 'user':
374 if 'key_ids' not in record:
375 logger.info("user record has no 'key_ids' - need to import from myplc ?")
377 pubkeys = [keys[key_id]['key'] for key_id in record['key_ids'] if key_id in keys]
378 record['keys'] = pubkeys
382 def fill_record_hrns(self, records):
384 convert pl ids to hrns
388 slice_ids, person_ids, site_ids, node_ids = [], [], [], []
389 for record in records:
390 if 'site_id' in record:
391 site_ids.append(record['site_id'])
392 if 'site_ids' in record:
393 site_ids.extend(record['site_ids'])
394 if 'person_ids' in record:
395 person_ids.extend(record['person_ids'])
396 if 'slice_ids' in record:
397 slice_ids.extend(record['slice_ids'])
398 if 'node_ids' in record:
399 node_ids.extend(record['node_ids'])
402 slices, persons, sites, nodes = {}, {}, {}, {}
404 site_list = self.shell.GetSites(site_ids, ['site_id', 'login_base'])
405 sites = list_to_dict(site_list, 'site_id')
407 person_list = self.shell.GetPersons(person_ids, ['person_id', 'email'])
408 persons = list_to_dict(person_list, 'person_id')
410 slice_list = self.shell.GetSlices(slice_ids, ['slice_id', 'name'])
411 slices = list_to_dict(slice_list, 'slice_id')
413 node_list = self.shell.GetNodes(node_ids, ['node_id', 'hostname'])
414 nodes = list_to_dict(node_list, 'node_id')
416 # convert ids to hrns
417 for record in records:
418 # get all relevant data
419 type = record['type']
420 pointer = record['pointer']
426 if 'site_id' in record:
427 site = sites[record['site_id']]
428 login_base = site['login_base']
429 record['site'] = ".".join([auth_hrn, login_base])
430 if 'person_ids' in record:
431 emails = [persons[person_id]['email'] for person_id in record['person_ids'] \
432 if person_id in persons]
433 usernames = [email.split('@')[0] for email in emails]
434 person_hrns = [".".join([auth_hrn, login_base, username]) for username in usernames]
435 record['persons'] = person_hrns
436 if 'slice_ids' in record:
437 slicenames = [slices[slice_id]['name'] for slice_id in record['slice_ids'] \
438 if slice_id in slices]
439 slice_hrns = [slicename_to_hrn(auth_hrn, slicename) for slicename in slicenames]
440 record['slices'] = slice_hrns
441 if 'node_ids' in record:
442 hostnames = [nodes[node_id]['hostname'] for node_id in record['node_ids'] \
444 node_hrns = [hostname_to_hrn(auth_hrn, login_base, hostname) for hostname in hostnames]
445 record['nodes'] = node_hrns
446 if 'site_ids' in record:
447 login_bases = [sites[site_id]['login_base'] for site_id in record['site_ids'] \
449 site_hrns = [".".join([auth_hrn, lbase]) for lbase in login_bases]
450 record['sites'] = site_hrns
452 if 'expires' in record:
453 date = utcparse(record['expires'])
454 datestring = datetime_to_string(date)
455 record['expires'] = datestring
459 def fill_record_sfa_info(self, records):
461 def startswith(prefix, values):
462 return [value for value in values if value.startswith(prefix)]
467 for record in records:
468 person_ids.extend(record.get("person_ids", []))
469 site_ids.extend(record.get("site_ids", []))
470 if 'site_id' in record:
471 site_ids.append(record['site_id'])
473 # get all pis from the sites we've encountered
474 # and store them in a dictionary keyed on site_id
477 pi_filter = {'|roles': ['pi'], '|site_ids': site_ids}
478 pi_list = self.shell.GetPersons(pi_filter, ['person_id', 'site_ids'])
480 # we will need the pi's hrns also
481 person_ids.append(pi['person_id'])
483 # we also need to keep track of the sites these pis
485 for site_id in pi['site_ids']:
486 if site_id in site_pis:
487 site_pis[site_id].append(pi)
489 site_pis[site_id] = [pi]
491 # get sfa records for all records associated with these records.
492 # we'll replace pl ids (person_ids) with hrns from the sfa records
495 # get the registry records
496 person_list, persons = [], {}
497 person_list = dbsession.query (RegRecord).filter(RegRecord.pointer.in_(person_ids))
498 # create a hrns keyed on the sfa record's pointer.
499 # Its possible for multiple records to have the same pointer so
500 # the dict's value will be a list of hrns.
501 persons = defaultdict(list)
502 for person in person_list:
503 persons[person.pointer].append(person)
506 pl_person_list, pl_persons = [], {}
507 pl_person_list = self.shell.GetPersons(person_ids, ['person_id', 'roles'])
508 pl_persons = list_to_dict(pl_person_list, 'person_id')
511 for record in records:
512 # skip records with no pl info (top level authorities)
513 #if record['pointer'] == -1:
516 type = record['type']
517 logger.info("fill_record_sfa_info - incoming record typed %s"%type)
518 if (type == "slice"):
519 # all slice users are researchers
520 record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
522 record['researcher'] = []
523 for person_id in record.get('person_ids', []):
524 hrns = [person.hrn for person in persons[person_id]]
525 record['researcher'].extend(hrns)
527 # pis at the slice's site
528 if 'site_id' in record and record['site_id'] in site_pis:
529 pl_pis = site_pis[record['site_id']]
530 pi_ids = [pi['person_id'] for pi in pl_pis]
531 for person_id in pi_ids:
532 hrns = [person.hrn for person in persons[person_id]]
533 record['PI'].extend(hrns)
534 record['geni_creator'] = record['PI']
536 elif (type.startswith("authority")):
538 logger.info("fill_record_sfa_info - authority xherex")
539 if record['pointer'] != -1:
541 record['operator'] = []
543 for pointer in record.get('person_ids', []):
544 if pointer not in persons or pointer not in pl_persons:
545 # this means there is not sfa or pl record for this user
547 hrns = [person.hrn for person in persons[pointer]]
548 roles = pl_persons[pointer]['roles']
550 record['PI'].extend(hrns)
552 record['operator'].extend(hrns)
554 record['owner'].extend(hrns)
555 # xxx TODO: OrganizationName
556 elif (type == "node"):
557 sfa_info['dns'] = record.get("hostname", "")
558 # xxx TODO: URI, LatLong, IP, DNS
560 elif (type == "user"):
561 logger.info('setting user.email')
562 sfa_info['email'] = record.get("email", "")
563 sfa_info['geni_urn'] = hrn_to_urn(record['hrn'], 'user')
564 sfa_info['geni_certificate'] = record['gid']
565 # xxx TODO: PostalAddress, Phone
566 record.update(sfa_info)
570 # plcapi works by changes, compute what needs to be added/deleted
571 def update_relation (self, subject_type, target_type, relation_name, subject_id, target_ids):
572 # hard-wire the code for slice/user for now, could be smarter if needed
573 if subject_type =='slice' and target_type == 'user' and relation_name == 'researcher':
574 subject=self.shell.GetSlices (subject_id)[0]
575 current_target_ids = subject['person_ids']
576 add_target_ids = list ( set (target_ids).difference(current_target_ids))
577 del_target_ids = list ( set (current_target_ids).difference(target_ids))
578 logger.debug ("subject_id = %s (type=%s)"%(subject_id,type(subject_id)))
579 for target_id in add_target_ids:
580 self.shell.AddPersonToSlice (target_id,subject_id)
581 logger.debug ("add_target_id = %s (type=%s)"%(target_id,type(target_id)))
582 for target_id in del_target_ids:
583 logger.debug ("del_target_id = %s (type=%s)"%(target_id,type(target_id)))
584 self.shell.DeletePersonFromSlice (target_id, subject_id)
585 elif subject_type == 'authority' and target_type == 'user' and relation_name == 'pi':
586 # due to the plcapi limitations this means essentially adding pi role to all people in the list
587 # it's tricky to remove any pi role here, although it might be desirable
588 persons = self.shell.GetPersons (target_ids)
589 for person in persons:
590 if 'pi' not in person['roles']:
591 self.shell.AddRoleToPerson('pi',person['person_id'])
593 logger.info('unexpected relation %s to maintain, %s -> %s'%(relation_name,subject_type,target_type))
596 ########################################
597 ########## aggregate oriented
598 ########################################
600 def testbed_name (self): return "myplc"
602 def aggregate_version (self):
605 # first 2 args are None in case of resource discovery
606 def list_resources (self, version=None, options={}):
607 aggregate = PlAggregate(self)
608 rspec = aggregate.list_resources(version=version, options=options)
611 def describe(self, urns, version, options={}):
612 aggregate = PlAggregate(self)
613 return aggregate.describe(urns, version=version, options=options)
615 def status (self, urns, options={}):
616 aggregate = PlAggregate(self)
617 desc = aggregate.describe(urns)
618 status = {'geni_urn': desc['geni_urn'],
619 'geni_slivers': desc['geni_slivers']}
622 def allocate (self, urn, rspec_string, expiration, options={}):
624 aggregate = PlAggregate(self)
625 slices = PlSlices(self)
626 peer = slices.get_peer(xrn.get_hrn())
627 sfa_peer = slices.get_sfa_peer(xrn.get_hrn())
629 users = options.get('geni_users', [])
631 slice_record = users[0].get('slice_record', {})
634 rspec = RSpec(rspec_string)
635 requested_attributes = rspec.version.get_slice_attributes()
637 # ensure site record exists
638 site = slices.verify_site(xrn.hrn, slice_record, peer, sfa_peer, options=options)
639 # ensure slice record exists
640 slice = slices.verify_slice(xrn.hrn, slice_record, peer, sfa_peer, expiration=expiration, options=options)
641 # ensure person records exists
642 persons = slices.verify_persons(xrn.hrn, slice, users, peer, sfa_peer, options=options)
643 # ensure slice attributes exists
644 slices.verify_slice_attributes(slice, requested_attributes, options=options)
646 # add/remove slice from nodes
647 request_nodes = rspec.version.get_nodes_with_slivers()
648 nodes = slices.verify_slice_nodes(urn, slice, request_nodes, peer)
650 # add/remove links links
651 slices.verify_slice_links(slice, rspec.version.get_link_requests(), nodes)
654 requested_leases = []
656 for lease in rspec.version.get_leases():
658 if not lease.get('lease_id'):
659 requested_lease['hostname'] = xrn_to_hostname(lease.get('component_id').strip())
660 requested_lease['start_time'] = lease.get('start_time')
661 requested_lease['duration'] = lease.get('duration')
663 kept_leases.append(int(lease['lease_id']))
664 if requested_lease.get('hostname'):
665 requested_leases.append(requested_lease)
667 leases = slices.verify_slice_leases(slice, requested_leases, kept_leases, peer)
668 # handle MyPLC peer association.
669 # only used by plc and ple.
670 slices.handle_peer(site, slice, persons, peer)
672 return aggregate.describe([xrn.get_urn()], version=rspec.version)
674 def provision(self, urns, options={}):
675 # update sliver allocation states and set them to geni_provisioned
676 aggregate = PlAggregate(self)
677 slivers = aggregate.get_slivers(urns)
678 sliver_ids = [sliver['sliver_id'] for sliver in slivers]
679 SliverAllocation.set_allocations(sliver_ids, 'geni_provisioned')
680 version_manager = VersionManager()
681 rspec_version = version_manager.get_version(options['geni_rspec_version'])
682 return self.describe(urns, rspec_version, options=options)
684 def delete(self, urns, options={}):
685 # collect sliver ids so we can update sliver allocation states after
686 # we remove the slivers.
687 aggregate = PlAggregate(self)
688 slivers = aggregate.get_slivers(urns)
690 slice_id = slivers[0]['slice_id']
693 for sliver in slivers:
694 node_ids.append(sliver['node_id'])
695 sliver_ids.append(sliver['sliver_id'])
697 # determine if this is a peer slice
698 # xxx I wonder if this would not need to use PlSlices.get_peer instead
699 # in which case plc.peers could be deprecated as this here
700 # is the only/last call to this last method in plc.peers
701 slice_hrn = PlXrn(auth=self.hrn, slicename=slivers[0]['name']).get_hrn()
702 peer = peers.get_peer(self, slice_hrn)
705 self.shell.UnBindObjectFromPeer('slice', slice_id, peer)
707 self.shell.DeleteSliceFromNodes(slice_id, node_ids)
709 # delete sliver allocation states
710 SliverAllocation.delete_allocations(sliver_ids)
713 self.shell.BindObjectToPeer('slice', slice_id, peer, slice['peer_slice_id'])
715 # prepare return struct
717 for sliver in slivers:
719 {'geni_sliver_urn': sliver['sliver_id'],
720 'geni_allocation_status': 'geni_unallocated',
721 'geni_expires': datetime_to_string(utcparse(sliver['expires']))})
724 def renew (self, urns, expiration_time, options={}):
725 aggregate = PlAggregate(self)
726 slivers = aggregate.get_slivers(urns)
728 raise SearchFailed(urns)
730 requested_time = utcparse(expiration_time)
731 record = {'expires': int(datetime_to_epoch(requested_time))}
732 self.shell.UpdateSlice(slice['slice_id'], record)
733 description = self.describe(urns, None, options)
734 return description['geni_slivers']
737 def perform_operational_action (self, urns, action, options={}):
738 # MyPLC doesn't support operational actions. Lets pretend like it
739 # supports start, but reject everything else.
740 action = action.lower()
741 if action not in ['geni_start']:
742 raise UnsupportedOperation(action)
744 # fault if sliver is not full allocated (operational status is geni_pending_allocation)
745 description = self.describe(urns, None, options)
746 for sliver in description['geni_slivers']:
747 if sliver['geni_operational_status'] == 'geni_pending_allocation':
748 raise UnsupportedOperation(action, "Sliver must be fully allocated (operational status is not geni_pending_allocation)")
750 # Perform Operational Action Here
753 geni_slivers = self.describe(urns, None, options)['geni_slivers']
756 # set the 'enabled' tag to 0
757 def shutdown (self, xrn, options={}):
758 xrn = PlXrn(xrn=xrn, type='slice')
759 slicename = xrn.pl_slicename()
760 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
762 raise RecordNotFound(slice_hrn)
763 slice_id = slices[0]['slice_id']
764 slice_tags = self.shell.GetSliceTags({'slice_id': slice_id, 'tagname': 'enabled'})
766 self.shell.AddSliceTag(slice_id, 'enabled', '0')
767 elif slice_tags[0]['value'] != "0":
768 tag_id = slice_tags[0]['slice_tag_id']
769 self.shell.UpdateSliceTag(tag_id, '0')