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
16 # used to be used in get_ticket
17 #from sfa.trust.sfaticket import SfaTicket
18 from sfa.rspecs.version_manager import VersionManager
19 from sfa.rspecs.rspec import RSpec
21 # the driver interface, mostly provides default behaviours
22 from sfa.managers.driver import Driver
23 from sfa.planetlab.plshell import PlShell
24 import sfa.planetlab.peers as peers
25 from sfa.planetlab.plaggregate import PlAggregate
26 from sfa.planetlab.plslices import PlSlices
27 from sfa.planetlab.plxrn import PlXrn, slicename_to_hrn, hostname_to_hrn, hrn_to_pl_slicename, xrn_to_hostname
30 def list_to_dict(recs, key):
32 convert a list of dictionaries into a dictionary keyed on the
33 specified dictionary key
35 return dict ( [ (rec[key],rec) for rec in recs ] )
38 # PlShell is just an xmlrpc serverproxy where methods
39 # can be sent as-is; it takes care of authentication
40 # from the global config
42 class PlDriver (Driver):
44 # the cache instance is a class member so it survives across incoming requests
47 def __init__ (self, config):
48 Driver.__init__ (self, config)
49 self.shell = PlShell (config)
51 if config.SFA_AGGREGATE_CACHING:
52 if PlDriver.cache is None:
53 PlDriver.cache = Cache()
54 self.cache = PlDriver.cache
56 def sliver_to_slice_xrn(self, xrn):
57 sliver_id_parts = Xrn(xrn).get_sliver_id_parts()
58 slices = self.shell.GetSlices(sliver_id_parts[0])
60 raise Forbidden("Unable to locate slice record for sliver: %s" % xrn)
62 slice_xrn = Xrn(auth=self.hrn, slicename=slice['name'])
65 def check_sliver_credentials(self, creds, urns):
66 # build list of cred object hrns
69 slice_cred_hrn = Credential(cred=cred).get_gid_object().get_hrn()
70 slice_cred_names.append(PlXrn(xrn=slice_cred_hrn).pl_slicename())
72 # look slice names of slivers listed in urns arg
75 sliver_id_parts = Xrn(xrn=urn).get_sliver_id_parts()
76 slice_ids.append(sliver_id_parts[0])
79 raise Forbidden("sliver urn not provided")
81 slices = self.shell.GetSlices(slice_ids)
82 sliver_names = [slice['name'] for slice in slices]
84 # make sure we have a credential for every specified sliver ierd
85 for sliver_name in sliver_names:
86 if sliver_name not in slice_cred_names:
87 msg = "Valid credential not found for target: %s" % sliver_name
90 ########################################
91 ########## registry oriented
92 ########################################
94 def augment_records_with_testbed_info (self, sfa_records):
95 return self.fill_record_info (sfa_records)
98 def register (self, sfa_record, hrn, pub_key):
99 type = sfa_record['type']
100 pl_record = self.sfa_fields_to_pl_fields(type, hrn, sfa_record)
102 if type == 'authority':
103 sites = self.shell.GetSites([pl_record['login_base']])
105 # xxx when a site gets registered through SFA we need to set its max_slices
106 if 'max_slices' not in pl_record:
107 pl_record['max_slices']=2
108 pointer = self.shell.AddSite(pl_record)
110 pointer = sites[0]['site_id']
112 elif type == 'slice':
113 acceptable_fields=['url', 'instantiation', 'name', 'description']
114 for key in pl_record.keys():
115 if key not in acceptable_fields:
117 slices = self.shell.GetSlices([pl_record['name']])
119 pointer = self.shell.AddSlice(pl_record)
121 pointer = slices[0]['slice_id']
124 persons = self.shell.GetPersons({'email':sfa_record['email']})
126 for key in ['first_name','last_name']:
127 if key not in sfa_record: sfa_record[key]='*from*sfa*'
128 # AddPerson does not allow everything to be set
129 can_add = ['first_name', 'last_name', 'title','email', 'password', 'phone', 'url', 'bio']
130 add_person_dict=dict ( [ (k,sfa_record[k]) for k in sfa_record if k in can_add ] )
131 pointer = self.shell.AddPerson(add_person_dict)
133 pointer = persons[0]['person_id']
135 if 'enabled' in sfa_record and sfa_record['enabled']:
136 self.shell.UpdatePerson(pointer, {'enabled': sfa_record['enabled']})
137 # add this person to the site only if she is being added for the first
138 # time by sfa and doesont already exist in plc
139 if not persons or not persons[0]['site_ids']:
140 login_base = get_leaf(sfa_record['authority'])
141 self.shell.AddPersonToSite(pointer, login_base)
143 # What roles should this user have?
145 if 'roles' in sfa_record:
146 # if specified in xml, but only low-level roles
147 roles = [ role for role in sfa_record['roles'] if role in ['user','tech'] ]
148 # at least user if no other cluse could be found
152 self.shell.AddRoleToPerson(role, pointer)
155 self.shell.AddPersonKey(pointer, {'key_type' : 'ssh', 'key' : pub_key})
158 login_base = PlXrn(xrn=sfa_record['authority'],type='node').pl_login_base()
159 nodes = self.shell.GetNodes([pl_record['hostname']])
161 pointer = self.shell.AddNode(login_base, pl_record)
163 pointer = nodes[0]['node_id']
168 # xxx actually old_sfa_record comes filled with plc stuff as well in the original code
169 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
170 pointer = old_sfa_record['pointer']
171 type = old_sfa_record['type']
173 # new_key implemented for users only
174 if new_key and type not in [ 'user' ]:
175 raise UnknownSfaType(type)
177 if (type == "authority"):
178 self.shell.UpdateSite(pointer, new_sfa_record)
180 elif type == "slice":
181 pl_record=self.sfa_fields_to_pl_fields(type, hrn, new_sfa_record)
182 if 'name' in pl_record:
183 pl_record.pop('name')
184 self.shell.UpdateSlice(pointer, pl_record)
187 # SMBAKER: UpdatePerson only allows a limited set of fields to be
188 # updated. Ideally we should have a more generic way of doing
189 # this. I copied the field names from UpdatePerson.py...
191 all_fields = new_sfa_record
192 for key in all_fields.keys():
193 if key in ['first_name', 'last_name', 'title', 'email',
194 'password', 'phone', 'url', 'bio', 'accepted_aup',
196 update_fields[key] = all_fields[key]
197 # when updating a user, we always get a 'email' field at this point
198 # this is because 'email' is a native field in the RegUser object...
199 if 'email' in update_fields and not update_fields['email']:
200 del update_fields['email']
201 self.shell.UpdatePerson(pointer, update_fields)
204 # must check this key against the previous one if it exists
205 persons = self.shell.GetPersons([pointer], ['key_ids'])
207 keys = person['key_ids']
208 keys = self.shell.GetKeys(person['key_ids'])
210 # Delete all stale keys
213 if new_key != key['key']:
214 self.shell.DeleteKey(key['key_id'])
218 self.shell.AddPersonKey(pointer, {'key_type': 'ssh', 'key': new_key})
221 self.shell.UpdateNode(pointer, new_sfa_record)
227 def remove (self, sfa_record):
228 type=sfa_record['type']
229 pointer=sfa_record['pointer']
231 persons = self.shell.GetPersons(pointer)
232 # only delete this person if he has site ids. if he doesnt, it probably means
233 # he was just removed from a site, not actually deleted
234 if persons and persons[0]['site_ids']:
235 self.shell.DeletePerson(pointer)
236 elif type == 'slice':
237 if self.shell.GetSlices(pointer):
238 self.shell.DeleteSlice(pointer)
240 if self.shell.GetNodes(pointer):
241 self.shell.DeleteNode(pointer)
242 elif type == 'authority':
243 if self.shell.GetSites(pointer):
244 self.shell.DeleteSite(pointer)
253 # Convert SFA fields to PLC fields for use when registering or updating
254 # registry record in the PLC database
257 def sfa_fields_to_pl_fields(self, type, hrn, sfa_record):
262 pl_record["name"] = hrn_to_pl_slicename(hrn)
263 if "instantiation" in sfa_record:
264 pl_record['instantiation']=sfa_record['instantiation']
266 pl_record["instantiation"] = "plc-instantiated"
267 if "url" in sfa_record:
268 pl_record["url"] = sfa_record["url"]
269 if "description" in sfa_record:
270 pl_record["description"] = sfa_record["description"]
271 if "expires" in sfa_record:
272 date = utcparse(sfa_record['expires'])
273 expires = datetime_to_epoch(date)
274 pl_record["expires"] = expires
277 if not "hostname" in pl_record:
278 # fetch from sfa_record
279 if "hostname" not in sfa_record:
280 raise MissingSfaInfo("hostname")
281 pl_record["hostname"] = sfa_record["hostname"]
282 if "model" in sfa_record:
283 pl_record["model"] = sfa_record["model"]
285 pl_record["model"] = "geni"
287 elif type == "authority":
288 pl_record["login_base"] = PlXrn(xrn=hrn,type='authority').pl_login_base()
289 if "name" not in sfa_record:
290 pl_record["name"] = hrn
291 if "abbreviated_name" not in sfa_record:
292 pl_record["abbreviated_name"] = hrn
293 if "enabled" not in sfa_record:
294 pl_record["enabled"] = True
295 if "is_public" not in sfa_record:
296 pl_record["is_public"] = True
301 def fill_record_info(self, records):
303 Given a (list of) SFA record, fill in the PLC specific
304 and SFA specific fields in the record.
306 if not isinstance(records, list):
309 self.fill_record_pl_info(records)
310 self.fill_record_hrns(records)
311 self.fill_record_sfa_info(records)
314 def fill_record_pl_info(self, records):
316 Fill in the planetlab specific fields of a SFA record. This
317 involves calling the appropriate PLC method to retrieve the
318 database record for the object.
320 @param record: record to fill in field (in/out param)
323 node_ids, site_ids, slice_ids = [], [], []
324 person_ids, key_ids = [], []
325 type_map = {'node': node_ids, 'authority': site_ids,
326 'slice': slice_ids, 'user': person_ids}
328 for record in records:
329 for type in type_map:
330 if type == record['type']:
331 type_map[type].append(record['pointer'])
334 nodes, sites, slices, persons, keys = {}, {}, {}, {}, {}
336 node_list = self.shell.GetNodes(node_ids)
337 nodes = list_to_dict(node_list, 'node_id')
339 site_list = self.shell.GetSites(site_ids)
340 sites = list_to_dict(site_list, 'site_id')
342 slice_list = self.shell.GetSlices(slice_ids)
343 slices = list_to_dict(slice_list, 'slice_id')
345 person_list = self.shell.GetPersons(person_ids)
346 persons = list_to_dict(person_list, 'person_id')
347 for person in persons:
348 key_ids.extend(persons[person]['key_ids'])
350 pl_records = {'node': nodes, 'authority': sites,
351 'slice': slices, 'user': persons}
354 key_list = self.shell.GetKeys(key_ids)
355 keys = list_to_dict(key_list, 'key_id')
358 for record in records:
359 # records with pointer==-1 do not have plc info.
360 # for example, the top level authority records which are
361 # authorities, but not PL "sites"
362 if record['pointer'] == -1:
365 for type in pl_records:
366 if record['type'] == type:
367 if record['pointer'] in pl_records[type]:
368 record.update(pl_records[type][record['pointer']])
371 if record['type'] == 'user':
372 if 'key_ids' not in record:
373 logger.info("user record has no 'key_ids' - need to import from myplc ?")
375 pubkeys = [keys[key_id]['key'] for key_id in record['key_ids'] if key_id in keys]
376 record['keys'] = pubkeys
380 def fill_record_hrns(self, records):
382 convert pl ids to hrns
386 slice_ids, person_ids, site_ids, node_ids = [], [], [], []
387 for record in records:
388 if 'site_id' in record:
389 site_ids.append(record['site_id'])
390 if 'site_ids' in record:
391 site_ids.extend(record['site_ids'])
392 if 'person_ids' in record:
393 person_ids.extend(record['person_ids'])
394 if 'slice_ids' in record:
395 slice_ids.extend(record['slice_ids'])
396 if 'node_ids' in record:
397 node_ids.extend(record['node_ids'])
400 slices, persons, sites, nodes = {}, {}, {}, {}
402 site_list = self.shell.GetSites(site_ids, ['site_id', 'login_base'])
403 sites = list_to_dict(site_list, 'site_id')
405 person_list = self.shell.GetPersons(person_ids, ['person_id', 'email'])
406 persons = list_to_dict(person_list, 'person_id')
408 slice_list = self.shell.GetSlices(slice_ids, ['slice_id', 'name'])
409 slices = list_to_dict(slice_list, 'slice_id')
411 node_list = self.shell.GetNodes(node_ids, ['node_id', 'hostname'])
412 nodes = list_to_dict(node_list, 'node_id')
414 # convert ids to hrns
415 for record in records:
416 # get all relevant data
417 type = record['type']
418 pointer = record['pointer']
424 if 'site_id' in record:
425 site = sites[record['site_id']]
426 login_base = site['login_base']
427 record['site'] = ".".join([auth_hrn, login_base])
428 if 'person_ids' in record:
429 emails = [persons[person_id]['email'] for person_id in record['person_ids'] \
430 if person_id in persons]
431 usernames = [email.split('@')[0] for email in emails]
432 person_hrns = [".".join([auth_hrn, login_base, username]) for username in usernames]
433 record['persons'] = person_hrns
434 if 'slice_ids' in record:
435 slicenames = [slices[slice_id]['name'] for slice_id in record['slice_ids'] \
436 if slice_id in slices]
437 slice_hrns = [slicename_to_hrn(auth_hrn, slicename) for slicename in slicenames]
438 record['slices'] = slice_hrns
439 if 'node_ids' in record:
440 hostnames = [nodes[node_id]['hostname'] for node_id in record['node_ids'] \
442 node_hrns = [hostname_to_hrn(auth_hrn, login_base, hostname) for hostname in hostnames]
443 record['nodes'] = node_hrns
444 if 'site_ids' in record:
445 login_bases = [sites[site_id]['login_base'] for site_id in record['site_ids'] \
447 site_hrns = [".".join([auth_hrn, lbase]) for lbase in login_bases]
448 record['sites'] = site_hrns
450 if 'expires' in record:
451 date = utcparse(record['expires'])
452 datestring = datetime_to_string(date)
453 record['expires'] = datestring
457 def fill_record_sfa_info(self, records):
459 def startswith(prefix, values):
460 return [value for value in values if value.startswith(prefix)]
465 for record in records:
466 person_ids.extend(record.get("person_ids", []))
467 site_ids.extend(record.get("site_ids", []))
468 if 'site_id' in record:
469 site_ids.append(record['site_id'])
471 # get all pis from the sites we've encountered
472 # and store them in a dictionary keyed on site_id
475 pi_filter = {'|roles': ['pi'], '|site_ids': site_ids}
476 pi_list = self.shell.GetPersons(pi_filter, ['person_id', 'site_ids'])
478 # we will need the pi's hrns also
479 person_ids.append(pi['person_id'])
481 # we also need to keep track of the sites these pis
483 for site_id in pi['site_ids']:
484 if site_id in site_pis:
485 site_pis[site_id].append(pi)
487 site_pis[site_id] = [pi]
489 # get sfa records for all records associated with these records.
490 # we'll replace pl ids (person_ids) with hrns from the sfa records
493 # get the registry records
494 person_list, persons = [], {}
495 person_list = dbsession.query (RegRecord).filter(RegRecord.pointer.in_(person_ids))
496 # create a hrns keyed on the sfa record's pointer.
497 # Its possible for multiple records to have the same pointer so
498 # the dict's value will be a list of hrns.
499 persons = defaultdict(list)
500 for person in person_list:
501 persons[person.pointer].append(person)
504 pl_person_list, pl_persons = [], {}
505 pl_person_list = self.shell.GetPersons(person_ids, ['person_id', 'roles'])
506 pl_persons = list_to_dict(pl_person_list, 'person_id')
509 for record in records:
510 # skip records with no pl info (top level authorities)
511 #if record['pointer'] == -1:
514 type = record['type']
515 logger.info("fill_record_sfa_info - incoming record typed %s"%type)
516 if (type == "slice"):
517 # all slice users are researchers
518 record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
520 record['researcher'] = []
521 for person_id in record.get('person_ids', []):
522 hrns = [person.hrn for person in persons[person_id]]
523 record['researcher'].extend(hrns)
525 # pis at the slice's site
526 if 'site_id' in record and record['site_id'] in site_pis:
527 pl_pis = site_pis[record['site_id']]
528 pi_ids = [pi['person_id'] for pi in pl_pis]
529 for person_id in pi_ids:
530 hrns = [person.hrn for person in persons[person_id]]
531 record['PI'].extend(hrns)
532 record['geni_creator'] = record['PI']
534 elif (type.startswith("authority")):
536 logger.info("fill_record_sfa_info - authority xherex")
537 if record['pointer'] != -1:
539 record['operator'] = []
541 for pointer in record.get('person_ids', []):
542 if pointer not in persons or pointer not in pl_persons:
543 # this means there is not sfa or pl record for this user
545 hrns = [person.hrn for person in persons[pointer]]
546 roles = pl_persons[pointer]['roles']
548 record['PI'].extend(hrns)
550 record['operator'].extend(hrns)
552 record['owner'].extend(hrns)
553 # xxx TODO: OrganizationName
554 elif (type == "node"):
555 sfa_info['dns'] = record.get("hostname", "")
556 # xxx TODO: URI, LatLong, IP, DNS
558 elif (type == "user"):
559 logger.info('setting user.email')
560 sfa_info['email'] = record.get("email", "")
561 sfa_info['geni_urn'] = hrn_to_urn(record['hrn'], 'user')
562 sfa_info['geni_certificate'] = record['gid']
563 # xxx TODO: PostalAddress, Phone
564 record.update(sfa_info)
568 # plcapi works by changes, compute what needs to be added/deleted
569 def update_relation (self, subject_type, target_type, relation_name, subject_id, target_ids):
570 # hard-wire the code for slice/user for now, could be smarter if needed
571 if subject_type =='slice' and target_type == 'user' and relation_name == 'researcher':
572 subject=self.shell.GetSlices (subject_id)[0]
573 current_target_ids = subject['person_ids']
574 add_target_ids = list ( set (target_ids).difference(current_target_ids))
575 del_target_ids = list ( set (current_target_ids).difference(target_ids))
576 logger.debug ("subject_id = %s (type=%s)"%(subject_id,type(subject_id)))
577 for target_id in add_target_ids:
578 self.shell.AddPersonToSlice (target_id,subject_id)
579 logger.debug ("add_target_id = %s (type=%s)"%(target_id,type(target_id)))
580 for target_id in del_target_ids:
581 logger.debug ("del_target_id = %s (type=%s)"%(target_id,type(target_id)))
582 self.shell.DeletePersonFromSlice (target_id, subject_id)
583 elif subject_type == 'authority' and target_type == 'user' and relation_name == 'pi':
584 # due to the plcapi limitations this means essentially adding pi role to all people in the list
585 # it's tricky to remove any pi role here, although it might be desirable
586 persons = self.shell.GetPersons (target_ids)
587 for person in persons:
588 if 'pi' not in person['roles']:
589 self.shell.AddRoleToPerson('pi',person['person_id'])
591 logger.info('unexpected relation %s to maintain, %s -> %s'%(relation_name,subject_type,target_type))
594 ########################################
595 ########## aggregate oriented
596 ########################################
598 def testbed_name (self): return "myplc"
600 def aggregate_version (self):
603 # first 2 args are None in case of resource discovery
604 def list_resources (self, version=None, options={}):
605 aggregate = PlAggregate(self)
606 rspec = aggregate.list_resources(version=version, options=options)
609 def describe(self, urns, version, options={}):
610 aggregate = PlAggregate(self)
611 return aggregate.describe(urns, version=version, options=options)
613 def status (self, urns, options={}):
614 aggregate = PlAggregate(self)
615 desc = aggregate.describe(urns)
616 status = {'geni_urn': desc['geni_urn'],
617 'geni_slivers': desc['geni_slivers']}
620 def allocate (self, urn, rspec_string, options={}):
622 aggregate = PlAggregate(self)
623 slices = PlSlices(self)
624 peer = slices.get_peer(xrn.get_hrn())
625 sfa_peer = slices.get_sfa_peer(xrn.get_hrn())
627 users = options.get('geni_users', [])
629 slice_record = users[0].get('slice_record', {})
632 rspec = RSpec(rspec_string)
633 requested_attributes = rspec.version.get_slice_attributes()
635 # ensure site record exists
636 site = slices.verify_site(xrn.hrn, slice_record, peer, sfa_peer, options=options)
637 # ensure slice record exists
638 slice = slices.verify_slice(xrn.hrn, slice_record, peer, sfa_peer, options=options)
639 # ensure person records exists
640 persons = slices.verify_persons(xrn.hrn, slice, users, peer, sfa_peer, options=options)
641 # ensure slice attributes exists
642 slices.verify_slice_attributes(slice, requested_attributes, options=options)
644 # add/remove slice from nodes
645 request_nodes = rspec.version.get_nodes_with_slivers()
646 nodes = slices.verify_slice_nodes(slice, request_nodes, peer)
648 # add/remove links links
649 slices.verify_slice_links(slice, rspec.version.get_link_requests(), nodes)
652 requested_leases = []
654 for lease in rspec.version.get_leases():
656 if not lease.get('lease_id'):
657 requested_lease['hostname'] = xrn_to_hostname(lease.get('component_id').strip())
658 requested_lease['start_time'] = lease.get('start_time')
659 requested_lease['duration'] = lease.get('duration')
661 kept_leases.append(int(lease['lease_id']))
662 if requested_lease.get('hostname'):
663 requested_leases.append(requested_lease)
665 leases = slices.verify_slice_leases(slice, requested_leases, kept_leases, peer)
666 # handle MyPLC peer association.
667 # only used by plc and ple.
668 slices.handle_peer(site, slice, persons, peer)
670 return aggregate.describe([xrn.get_urn()], version=rspec.version)
672 def provision(self, urns, options={}):
673 # update sliver allocation states and set them to geni_provisioned
674 aggregate = PlAggregate(self)
675 slivers = aggregate.get_slivers(urns)
676 sliver_ids = [sliver['sliver_id'] for sliver in slivers]
677 SliverAllocation.set_allocations(sliver_ids, 'geni_provisioned')
678 version_manager = VersionManager()
679 rspec_version = version_manager.get_version(options['geni_rspec_version'])
680 return self.describe(urns, rspec_version, options=options)
682 def delete(self, urns, options={}):
683 # collect sliver ids so we can update sliver allocation states after
684 # we remove the slivers.
685 aggregate = PlAggregate(self)
686 slivers = aggregate.get_slivers(urns)
688 slice_id = slivers[0]['slice_id']
691 for sliver in slivers:
692 node_ids.append(sliver['node_id'])
693 sliver_ids.append(sliver['sliver_id'])
695 # determine if this is a peer slice
696 # xxx I wonder if this would not need to use PlSlices.get_peer instead
697 # in which case plc.peers could be deprecated as this here
698 # is the only/last call to this last method in plc.peers
699 slice_hrn = PlXrn(auth=self.hrn, slicename=slivers[0]['name']).get_hrn()
700 peer = peers.get_peer(self, slice_hrn)
703 self.shell.UnBindObjectFromPeer('slice', slice_id, peer)
705 self.shell.DeleteSliceFromNodes(slice_id, node_ids)
707 # delete sliver allocation states
708 SliverAllocation.delete_allocations(sliver_ids)
711 self.shell.BindObjectToPeer('slice', slice_id, peer, slice['peer_slice_id'])
713 # prepare return struct
715 for sliver in slivers:
717 {'geni_sliver_urn': sliver['sliver_id'],
718 'geni_allocation_status': 'geni_unallocated',
719 'geni_expires': datetime_to_string(utcparse(sliver['expires']))})
722 def renew (self, urns, expiration_time, options={}):
723 # we can only renew slices, not individual slivers. ignore sliver
727 xrn = PlXrn(xrn=urn, type='slice')
728 names.append(xrn.pl_slicename())
729 slices = self.shell.GetSlices(names, ['slice_id'])
731 raise SearchFailed(urns)
733 requested_time = utcparse(expiration_time)
734 record = {'expires': int(datetime_to_epoch(requested_time))}
735 self.shell.UpdateSlice(slice['slice_id'], record)
736 description = self.describe(urns, None, options)
737 return description['geni_slivers']
740 def perform_operational_action (self, urns, action, options={}):
741 # MyPLC doesn't support operational actions. Lets pretend like it
742 # supports start, but reject everything else.
743 action = action.lower()
744 if action not in ['geni_start']:
745 raise UnsupportedOperation(action)
747 # fault if sliver is not full allocated (operational status is geni_pending_allocation)
748 description = self.describe(urns, None, options)
749 for sliver in description['geni_slivers']:
750 if sliver['geni_operational_status'] == 'geni_pending_allocation':
751 raise UnsupportedOperation(action, "Sliver must be fully allocated (operational status is not geni_pending_allocation)")
753 # Perform Operational Action Here
756 geni_slivers = self.describe(urns, None, options)['geni_slivers']
759 # set the 'enabled' tag to 0
760 def shutdown (self, xrn, options={}):
761 xrn = PlXrn(xrn=xrn, type='slice')
762 slicename = xrn.pl_slicename()
763 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
765 raise RecordNotFound(slice_hrn)
766 slice_id = slices[0]['slice_id']
767 slice_tags = self.shell.GetSliceTags({'slice_id': slice_id, 'tagname': 'enabled'})
769 self.shell.AddSliceTag(slice_id, 'enabled', '0')
770 elif slice_tags[0]['value'] != "0":
771 tag_id = slice_tags[0]['slice_tag_id']
772 self.shell.UpdateSliceTag(tag_id, '0')