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 slice_id = int(sliver_id_parts[0])
59 slices = self.shell.GetSlices(slice_id)
61 raise Forbidden("Unable to locate slice record for sliver: %s" % xrn)
63 slice_xrn = PlXrn(auth=self.hrn, slicename=slice['name'])
66 def check_sliver_credentials(self, creds, urns):
67 # build list of cred object hrns
70 slice_cred_hrn = Credential(cred=cred).get_gid_object().get_hrn()
71 slice_cred_names.append(PlXrn(xrn=slice_cred_hrn).pl_slicename())
73 # look slice names of slivers listed in urns arg
76 sliver_id_parts = Xrn(xrn=urn).get_sliver_id_parts()
77 slice_ids.append(sliver_id_parts[0])
80 raise Forbidden("sliver urn not provided")
82 slices = self.shell.GetSlices(slice_ids)
83 sliver_names = [slice['name'] for slice in slices]
85 # make sure we have a credential for every specified sliver ierd
86 for sliver_name in sliver_names:
87 if sliver_name not in slice_cred_names:
88 msg = "Valid credential not found for target: %s" % sliver_name
91 ########################################
92 ########## registry oriented
93 ########################################
95 def augment_records_with_testbed_info (self, sfa_records):
96 return self.fill_record_info (sfa_records)
99 def register (self, sfa_record, hrn, pub_key):
100 type = sfa_record['type']
101 pl_record = self.sfa_fields_to_pl_fields(type, hrn, sfa_record)
103 if type == 'authority':
104 sites = self.shell.GetSites([pl_record['login_base']])
106 # xxx when a site gets registered through SFA we need to set its max_slices
107 if 'max_slices' not in pl_record:
108 pl_record['max_slices']=2
109 pointer = self.shell.AddSite(pl_record)
111 pointer = sites[0]['site_id']
113 elif type == 'slice':
114 acceptable_fields=['url', 'instantiation', 'name', 'description']
115 for key in pl_record.keys():
116 if key not in acceptable_fields:
118 slices = self.shell.GetSlices([pl_record['name']])
120 pointer = self.shell.AddSlice(pl_record)
122 pointer = slices[0]['slice_id']
125 persons = self.shell.GetPersons({'email':sfa_record['email']})
127 for key in ['first_name','last_name']:
128 if key not in sfa_record: sfa_record[key]='*from*sfa*'
129 # AddPerson does not allow everything to be set
130 can_add = ['first_name', 'last_name', 'title','email', 'password', 'phone', 'url', 'bio']
131 add_person_dict=dict ( [ (k,sfa_record[k]) for k in sfa_record if k in can_add ] )
132 pointer = self.shell.AddPerson(add_person_dict)
134 pointer = persons[0]['person_id']
136 if 'enabled' in sfa_record and sfa_record['enabled']:
137 self.shell.UpdatePerson(pointer, {'enabled': sfa_record['enabled']})
138 # add this person to the site only if she is being added for the first
139 # time by sfa and doesont already exist in plc
140 if not persons or not persons[0]['site_ids']:
141 login_base = get_leaf(sfa_record['authority'])
142 self.shell.AddPersonToSite(pointer, login_base)
144 # What roles should this user have?
146 if 'roles' in sfa_record:
147 # if specified in xml, but only low-level roles
148 roles = [ role for role in sfa_record['roles'] if role in ['user','tech'] ]
149 # at least user if no other cluse could be found
153 self.shell.AddRoleToPerson(role, pointer)
156 self.shell.AddPersonKey(pointer, {'key_type' : 'ssh', 'key' : pub_key})
159 login_base = PlXrn(xrn=sfa_record['authority'],type='node').pl_login_base()
160 nodes = self.shell.GetNodes([pl_record['hostname']])
162 pointer = self.shell.AddNode(login_base, pl_record)
164 pointer = nodes[0]['node_id']
169 # xxx actually old_sfa_record comes filled with plc stuff as well in the original code
170 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
171 pointer = old_sfa_record['pointer']
172 type = old_sfa_record['type']
174 # new_key implemented for users only
175 if new_key and type not in [ 'user' ]:
176 raise UnknownSfaType(type)
178 if (type == "authority"):
179 self.shell.UpdateSite(pointer, new_sfa_record)
181 elif type == "slice":
182 pl_record=self.sfa_fields_to_pl_fields(type, hrn, new_sfa_record)
183 if 'name' in pl_record:
184 pl_record.pop('name')
185 self.shell.UpdateSlice(pointer, pl_record)
188 # SMBAKER: UpdatePerson only allows a limited set of fields to be
189 # updated. Ideally we should have a more generic way of doing
190 # this. I copied the field names from UpdatePerson.py...
192 all_fields = new_sfa_record
193 for key in all_fields.keys():
194 if key in ['first_name', 'last_name', 'title', 'email',
195 'password', 'phone', 'url', 'bio', 'accepted_aup',
197 update_fields[key] = all_fields[key]
198 # when updating a user, we always get a 'email' field at this point
199 # this is because 'email' is a native field in the RegUser object...
200 if 'email' in update_fields and not update_fields['email']:
201 del update_fields['email']
202 self.shell.UpdatePerson(pointer, update_fields)
205 # must check this key against the previous one if it exists
206 persons = self.shell.GetPersons([pointer], ['key_ids'])
208 keys = person['key_ids']
209 keys = self.shell.GetKeys(person['key_ids'])
211 # Delete all stale keys
214 if new_key != key['key']:
215 self.shell.DeleteKey(key['key_id'])
219 self.shell.AddPersonKey(pointer, {'key_type': 'ssh', 'key': new_key})
222 self.shell.UpdateNode(pointer, new_sfa_record)
228 def remove (self, sfa_record):
229 type=sfa_record['type']
230 pointer=sfa_record['pointer']
232 persons = self.shell.GetPersons(pointer)
233 # only delete this person if he has site ids. if he doesnt, it probably means
234 # he was just removed from a site, not actually deleted
235 if persons and persons[0]['site_ids']:
236 self.shell.DeletePerson(pointer)
237 elif type == 'slice':
238 if self.shell.GetSlices(pointer):
239 self.shell.DeleteSlice(pointer)
241 if self.shell.GetNodes(pointer):
242 self.shell.DeleteNode(pointer)
243 elif type == 'authority':
244 if self.shell.GetSites(pointer):
245 self.shell.DeleteSite(pointer)
254 # Convert SFA fields to PLC fields for use when registering or updating
255 # registry record in the PLC database
258 def sfa_fields_to_pl_fields(self, type, hrn, sfa_record):
263 pl_record["name"] = hrn_to_pl_slicename(hrn)
264 if "instantiation" in sfa_record:
265 pl_record['instantiation']=sfa_record['instantiation']
267 pl_record["instantiation"] = "plc-instantiated"
268 if "url" in sfa_record:
269 pl_record["url"] = sfa_record["url"]
270 if "description" in sfa_record:
271 pl_record["description"] = sfa_record["description"]
272 if "expires" in sfa_record:
273 date = utcparse(sfa_record['expires'])
274 expires = datetime_to_epoch(date)
275 pl_record["expires"] = expires
278 if not "hostname" in pl_record:
279 # fetch from sfa_record
280 if "hostname" not in sfa_record:
281 raise MissingSfaInfo("hostname")
282 pl_record["hostname"] = sfa_record["hostname"]
283 if "model" in sfa_record:
284 pl_record["model"] = sfa_record["model"]
286 pl_record["model"] = "geni"
288 elif type == "authority":
289 pl_record["login_base"] = PlXrn(xrn=hrn,type='authority').pl_login_base()
290 if "name" not in sfa_record:
291 pl_record["name"] = hrn
292 if "abbreviated_name" not in sfa_record:
293 pl_record["abbreviated_name"] = hrn
294 if "enabled" not in sfa_record:
295 pl_record["enabled"] = True
296 if "is_public" not in sfa_record:
297 pl_record["is_public"] = True
302 def fill_record_info(self, records):
304 Given a (list of) SFA record, fill in the PLC specific
305 and SFA specific fields in the record.
307 if not isinstance(records, list):
310 self.fill_record_pl_info(records)
311 self.fill_record_hrns(records)
312 self.fill_record_sfa_info(records)
315 def fill_record_pl_info(self, records):
317 Fill in the planetlab specific fields of a SFA record. This
318 involves calling the appropriate PLC method to retrieve the
319 database record for the object.
321 @param record: record to fill in field (in/out param)
324 node_ids, site_ids, slice_ids = [], [], []
325 person_ids, key_ids = [], []
326 type_map = {'node': node_ids, 'authority': site_ids,
327 'slice': slice_ids, 'user': person_ids}
329 for record in records:
330 for type in type_map:
331 if type == record['type']:
332 type_map[type].append(record['pointer'])
335 nodes, sites, slices, persons, keys = {}, {}, {}, {}, {}
337 node_list = self.shell.GetNodes(node_ids)
338 nodes = list_to_dict(node_list, 'node_id')
340 site_list = self.shell.GetSites(site_ids)
341 sites = list_to_dict(site_list, 'site_id')
343 slice_list = self.shell.GetSlices(slice_ids)
344 slices = list_to_dict(slice_list, 'slice_id')
346 person_list = self.shell.GetPersons(person_ids)
347 persons = list_to_dict(person_list, 'person_id')
348 for person in persons:
349 key_ids.extend(persons[person]['key_ids'])
351 pl_records = {'node': nodes, 'authority': sites,
352 'slice': slices, 'user': persons}
355 key_list = self.shell.GetKeys(key_ids)
356 keys = list_to_dict(key_list, 'key_id')
359 for record in records:
360 # records with pointer==-1 do not have plc info.
361 # for example, the top level authority records which are
362 # authorities, but not PL "sites"
363 if record['pointer'] == -1:
366 for type in pl_records:
367 if record['type'] == type:
368 if record['pointer'] in pl_records[type]:
369 record.update(pl_records[type][record['pointer']])
372 if record['type'] == 'user':
373 if 'key_ids' not in record:
374 logger.info("user record has no 'key_ids' - need to import from myplc ?")
376 pubkeys = [keys[key_id]['key'] for key_id in record['key_ids'] if key_id in keys]
377 record['keys'] = pubkeys
381 def fill_record_hrns(self, records):
383 convert pl ids to hrns
387 slice_ids, person_ids, site_ids, node_ids = [], [], [], []
388 for record in records:
389 if 'site_id' in record:
390 site_ids.append(record['site_id'])
391 if 'site_ids' in record:
392 site_ids.extend(record['site_ids'])
393 if 'person_ids' in record:
394 person_ids.extend(record['person_ids'])
395 if 'slice_ids' in record:
396 slice_ids.extend(record['slice_ids'])
397 if 'node_ids' in record:
398 node_ids.extend(record['node_ids'])
401 slices, persons, sites, nodes = {}, {}, {}, {}
403 site_list = self.shell.GetSites(site_ids, ['site_id', 'login_base'])
404 sites = list_to_dict(site_list, 'site_id')
406 person_list = self.shell.GetPersons(person_ids, ['person_id', 'email'])
407 persons = list_to_dict(person_list, 'person_id')
409 slice_list = self.shell.GetSlices(slice_ids, ['slice_id', 'name'])
410 slices = list_to_dict(slice_list, 'slice_id')
412 node_list = self.shell.GetNodes(node_ids, ['node_id', 'hostname'])
413 nodes = list_to_dict(node_list, 'node_id')
415 # convert ids to hrns
416 for record in records:
417 # get all relevant data
418 type = record['type']
419 pointer = record['pointer']
425 if 'site_id' in record:
426 site = sites[record['site_id']]
427 login_base = site['login_base']
428 record['site'] = ".".join([auth_hrn, login_base])
429 if 'person_ids' in record:
430 emails = [persons[person_id]['email'] for person_id in record['person_ids'] \
431 if person_id in persons]
432 usernames = [email.split('@')[0] for email in emails]
433 person_hrns = [".".join([auth_hrn, login_base, username]) for username in usernames]
434 record['persons'] = person_hrns
435 if 'slice_ids' in record:
436 slicenames = [slices[slice_id]['name'] for slice_id in record['slice_ids'] \
437 if slice_id in slices]
438 slice_hrns = [slicename_to_hrn(auth_hrn, slicename) for slicename in slicenames]
439 record['slices'] = slice_hrns
440 if 'node_ids' in record:
441 hostnames = [nodes[node_id]['hostname'] for node_id in record['node_ids'] \
443 node_hrns = [hostname_to_hrn(auth_hrn, login_base, hostname) for hostname in hostnames]
444 record['nodes'] = node_hrns
445 if 'site_ids' in record:
446 login_bases = [sites[site_id]['login_base'] for site_id in record['site_ids'] \
448 site_hrns = [".".join([auth_hrn, lbase]) for lbase in login_bases]
449 record['sites'] = site_hrns
451 if 'expires' in record:
452 date = utcparse(record['expires'])
453 datestring = datetime_to_string(date)
454 record['expires'] = datestring
458 def fill_record_sfa_info(self, records):
460 def startswith(prefix, values):
461 return [value for value in values if value.startswith(prefix)]
466 for record in records:
467 person_ids.extend(record.get("person_ids", []))
468 site_ids.extend(record.get("site_ids", []))
469 if 'site_id' in record:
470 site_ids.append(record['site_id'])
472 # get all pis from the sites we've encountered
473 # and store them in a dictionary keyed on site_id
476 pi_filter = {'|roles': ['pi'], '|site_ids': site_ids}
477 pi_list = self.shell.GetPersons(pi_filter, ['person_id', 'site_ids'])
479 # we will need the pi's hrns also
480 person_ids.append(pi['person_id'])
482 # we also need to keep track of the sites these pis
484 for site_id in pi['site_ids']:
485 if site_id in site_pis:
486 site_pis[site_id].append(pi)
488 site_pis[site_id] = [pi]
490 # get sfa records for all records associated with these records.
491 # we'll replace pl ids (person_ids) with hrns from the sfa records
494 # get the registry records
495 person_list, persons = [], {}
496 person_list = dbsession.query (RegRecord).filter(RegRecord.pointer.in_(person_ids))
497 # create a hrns keyed on the sfa record's pointer.
498 # Its possible for multiple records to have the same pointer so
499 # the dict's value will be a list of hrns.
500 persons = defaultdict(list)
501 for person in person_list:
502 persons[person.pointer].append(person)
505 pl_person_list, pl_persons = [], {}
506 pl_person_list = self.shell.GetPersons(person_ids, ['person_id', 'roles'])
507 pl_persons = list_to_dict(pl_person_list, 'person_id')
510 for record in records:
511 # skip records with no pl info (top level authorities)
512 #if record['pointer'] == -1:
515 type = record['type']
516 logger.info("fill_record_sfa_info - incoming record typed %s"%type)
517 if (type == "slice"):
518 # all slice users are researchers
519 record['geni_urn'] = hrn_to_urn(record['hrn'], 'slice')
521 record['researcher'] = []
522 for person_id in record.get('person_ids', []):
523 hrns = [person.hrn for person in persons[person_id]]
524 record['researcher'].extend(hrns)
526 # pis at the slice's site
527 if 'site_id' in record and record['site_id'] in site_pis:
528 pl_pis = site_pis[record['site_id']]
529 pi_ids = [pi['person_id'] for pi in pl_pis]
530 for person_id in pi_ids:
531 hrns = [person.hrn for person in persons[person_id]]
532 record['PI'].extend(hrns)
533 record['geni_creator'] = record['PI']
535 elif (type.startswith("authority")):
537 logger.info("fill_record_sfa_info - authority xherex")
538 if record['pointer'] != -1:
540 record['operator'] = []
542 for pointer in record.get('person_ids', []):
543 if pointer not in persons or pointer not in pl_persons:
544 # this means there is not sfa or pl record for this user
546 hrns = [person.hrn for person in persons[pointer]]
547 roles = pl_persons[pointer]['roles']
549 record['PI'].extend(hrns)
551 record['operator'].extend(hrns)
553 record['owner'].extend(hrns)
554 # xxx TODO: OrganizationName
555 elif (type == "node"):
556 sfa_info['dns'] = record.get("hostname", "")
557 # xxx TODO: URI, LatLong, IP, DNS
559 elif (type == "user"):
560 logger.info('setting user.email')
561 sfa_info['email'] = record.get("email", "")
562 sfa_info['geni_urn'] = hrn_to_urn(record['hrn'], 'user')
563 sfa_info['geni_certificate'] = record['gid']
564 # xxx TODO: PostalAddress, Phone
565 record.update(sfa_info)
569 # plcapi works by changes, compute what needs to be added/deleted
570 def update_relation (self, subject_type, target_type, relation_name, subject_id, target_ids):
571 # hard-wire the code for slice/user for now, could be smarter if needed
572 if subject_type =='slice' and target_type == 'user' and relation_name == 'researcher':
573 subject=self.shell.GetSlices (subject_id)[0]
574 current_target_ids = subject['person_ids']
575 add_target_ids = list ( set (target_ids).difference(current_target_ids))
576 del_target_ids = list ( set (current_target_ids).difference(target_ids))
577 logger.debug ("subject_id = %s (type=%s)"%(subject_id,type(subject_id)))
578 for target_id in add_target_ids:
579 self.shell.AddPersonToSlice (target_id,subject_id)
580 logger.debug ("add_target_id = %s (type=%s)"%(target_id,type(target_id)))
581 for target_id in del_target_ids:
582 logger.debug ("del_target_id = %s (type=%s)"%(target_id,type(target_id)))
583 self.shell.DeletePersonFromSlice (target_id, subject_id)
584 elif subject_type == 'authority' and target_type == 'user' and relation_name == 'pi':
585 # due to the plcapi limitations this means essentially adding pi role to all people in the list
586 # it's tricky to remove any pi role here, although it might be desirable
587 persons = self.shell.GetPersons (target_ids)
588 for person in persons:
589 if 'pi' not in person['roles']:
590 self.shell.AddRoleToPerson('pi',person['person_id'])
592 logger.info('unexpected relation %s to maintain, %s -> %s'%(relation_name,subject_type,target_type))
595 ########################################
596 ########## aggregate oriented
597 ########################################
599 def testbed_name (self): return "myplc"
601 def aggregate_version (self):
604 # first 2 args are None in case of resource discovery
605 def list_resources (self, version=None, options={}):
606 aggregate = PlAggregate(self)
607 rspec = aggregate.list_resources(version=version, options=options)
610 def describe(self, urns, version, options={}):
611 aggregate = PlAggregate(self)
612 return aggregate.describe(urns, version=version, options=options)
614 def status (self, urns, options={}):
615 aggregate = PlAggregate(self)
616 desc = aggregate.describe(urns)
617 status = {'geni_urn': desc['geni_urn'],
618 'geni_slivers': desc['geni_slivers']}
621 def allocate (self, urn, rspec_string, options={}):
623 aggregate = PlAggregate(self)
624 slices = PlSlices(self)
625 peer = slices.get_peer(xrn.get_hrn())
626 sfa_peer = slices.get_sfa_peer(xrn.get_hrn())
628 users = options.get('geni_users', [])
630 slice_record = users[0].get('slice_record', {})
633 rspec = RSpec(rspec_string)
634 requested_attributes = rspec.version.get_slice_attributes()
636 # ensure site record exists
637 site = slices.verify_site(xrn.hrn, slice_record, peer, sfa_peer, options=options)
638 # ensure slice record exists
639 slice = slices.verify_slice(xrn.hrn, slice_record, peer, sfa_peer, options=options)
640 # ensure person records exists
641 persons = slices.verify_persons(xrn.hrn, slice, users, peer, sfa_peer, options=options)
642 # ensure slice attributes exists
643 slices.verify_slice_attributes(slice, requested_attributes, options=options)
645 # add/remove slice from nodes
646 request_nodes = rspec.version.get_nodes_with_slivers()
647 nodes = slices.verify_slice_nodes(slice, request_nodes, peer)
649 # add/remove links links
650 slices.verify_slice_links(slice, rspec.version.get_link_requests(), nodes)
653 requested_leases = []
655 for lease in rspec.version.get_leases():
657 if not lease.get('lease_id'):
658 requested_lease['hostname'] = xrn_to_hostname(lease.get('component_id').strip())
659 requested_lease['start_time'] = lease.get('start_time')
660 requested_lease['duration'] = lease.get('duration')
662 kept_leases.append(int(lease['lease_id']))
663 if requested_lease.get('hostname'):
664 requested_leases.append(requested_lease)
666 leases = slices.verify_slice_leases(slice, requested_leases, kept_leases, peer)
667 # handle MyPLC peer association.
668 # only used by plc and ple.
669 slices.handle_peer(site, slice, persons, peer)
671 return aggregate.describe([xrn.get_urn()], version=rspec.version)
673 def provision(self, urns, options={}):
674 # update sliver allocation states and set them to geni_provisioned
675 aggregate = PlAggregate(self)
676 slivers = aggregate.get_slivers(urns)
677 sliver_ids = [sliver['sliver_id'] for sliver in slivers]
678 SliverAllocation.set_allocations(sliver_ids, 'geni_provisioned')
679 version_manager = VersionManager()
680 rspec_version = version_manager.get_version(options['geni_rspec_version'])
681 return self.describe(urns, rspec_version, options=options)
683 def delete(self, urns, options={}):
684 # collect sliver ids so we can update sliver allocation states after
685 # we remove the slivers.
686 aggregate = PlAggregate(self)
687 slivers = aggregate.get_slivers(urns)
689 slice_id = slivers[0]['slice_id']
692 for sliver in slivers:
693 node_ids.append(sliver['node_id'])
694 sliver_ids.append(sliver['sliver_id'])
696 # determine if this is a peer slice
697 # xxx I wonder if this would not need to use PlSlices.get_peer instead
698 # in which case plc.peers could be deprecated as this here
699 # is the only/last call to this last method in plc.peers
700 slice_hrn = PlXrn(auth=self.hrn, slicename=slivers[0]['name']).get_hrn()
701 peer = peers.get_peer(self, slice_hrn)
704 self.shell.UnBindObjectFromPeer('slice', slice_id, peer)
706 self.shell.DeleteSliceFromNodes(slice_id, node_ids)
708 # delete sliver allocation states
709 SliverAllocation.delete_allocations(sliver_ids)
712 self.shell.BindObjectToPeer('slice', slice_id, peer, slice['peer_slice_id'])
714 # prepare return struct
716 for sliver in slivers:
718 {'geni_sliver_urn': sliver['sliver_id'],
719 'geni_allocation_status': 'geni_unallocated',
720 'geni_expires': datetime_to_string(utcparse(sliver['expires']))})
723 def renew (self, urns, expiration_time, options={}):
724 # we can only renew slices, not individual slivers. ignore sliver
728 xrn = PlXrn(xrn=urn, type='slice')
729 names.append(xrn.pl_slicename())
730 slices = self.shell.GetSlices(names, ['slice_id'])
732 raise SearchFailed(urns)
734 requested_time = utcparse(expiration_time)
735 record = {'expires': int(datetime_to_epoch(requested_time))}
736 self.shell.UpdateSlice(slice['slice_id'], record)
737 description = self.describe(urns, None, options)
738 return description['geni_slivers']
741 def perform_operational_action (self, urns, action, options={}):
742 # MyPLC doesn't support operational actions. Lets pretend like it
743 # supports start, but reject everything else.
744 action = action.lower()
745 if action not in ['geni_start']:
746 raise UnsupportedOperation(action)
748 # fault if sliver is not full allocated (operational status is geni_pending_allocation)
749 description = self.describe(urns, None, options)
750 for sliver in description['geni_slivers']:
751 if sliver['geni_operational_status'] == 'geni_pending_allocation':
752 raise UnsupportedOperation(action, "Sliver must be fully allocated (operational status is not geni_pending_allocation)")
754 # Perform Operational Action Here
757 geni_slivers = self.describe(urns, None, options)['geni_slivers']
760 # set the 'enabled' tag to 0
761 def shutdown (self, xrn, options={}):
762 xrn = PlXrn(xrn=xrn, type='slice')
763 slicename = xrn.pl_slicename()
764 slices = self.shell.GetSlices({'name': slicename}, ['slice_id'])
766 raise RecordNotFound(slice_hrn)
767 slice_id = slices[0]['slice_id']
768 slice_tags = self.shell.GetSliceTags({'slice_id': slice_id, 'tagname': 'enabled'})
770 self.shell.AddSliceTag(slice_id, 'enabled', '0')
771 elif slice_tags[0]['value'] != "0":
772 tag_id = slice_tags[0]['slice_tag_id']
773 self.shell.UpdateSliceTag(tag_id, '0')