2 File providing methods to generate valid RSpecs for the Iotlab testbed.
3 Contains methods to get information on slice, slivers, nodes and leases,
4 formatting them and turn it into a RSpec.
6 from sfa.util.sfatime import utcparse, datetime_to_string
7 from sfa.util.xrn import Xrn, hrn_to_urn, urn_to_hrn
8 from sfa.iotlab.iotlabxrn import IotlabXrn
9 from sfa.rspecs.rspec import RSpec
10 #from sfa.rspecs.elements.location import Location
11 from sfa.rspecs.elements.hardware_type import HardwareType
12 from sfa.rspecs.elements.login import Login
13 # from sfa.rspecs.elements.services import ServicesElement
14 from sfa.rspecs.elements.sliver import Sliver
15 from sfa.rspecs.elements.lease import Lease
16 from sfa.rspecs.elements.granularity import Granularity
17 from sfa.rspecs.version_manager import VersionManager
18 from sfa.storage.model import SliverAllocation
19 from sfa.rspecs.elements.versions.iotlabv1Node import IotlabPosition, \
20 IotlabNode, IotlabLocation
21 from sfa.iotlab.iotlabxrn import xrn_object
22 from sfa.util.sfalogging import logger
25 class IotlabAggregate:
26 """Aggregate manager class for Iotlab. """
39 def __init__(self, driver):
42 def get_slice_and_slivers(self, slice_xrn, login=None):
44 Get the slices and the associated leases if any from the iotlab
45 testbed. One slice can have mutliple leases.
46 For each slice, get the nodes in the associated lease
47 and create a sliver with the necessary info and insert it into the
48 sliver dictionary, keyed on the node hostnames.
49 Returns a dict of slivers based on the sliver's node_id.
53 :param slice_xrn: xrn of the slice
54 :param login: user's login on iotlab ldap
56 :type slice_xrn: string
58 :returns: a list of slices dict and a list of Sliver object
61 .. note: There is no real slivers in iotlab, only leases. The goal
62 is to be consistent with the SFA standard.
68 return (sfa_slice, slivers)
69 slice_urn = hrn_to_urn(slice_xrn, 'slice')
70 slice_hrn, _ = urn_to_hrn(slice_xrn)
72 # GetSlices always returns a list, even if there is only one element
73 slices = self.driver.GetSlices(slice_filter=str(slice_hrn),
74 slice_filter_type='slice_hrn',
77 logger.debug("IotlabAggregate api \tget_slice_and_slivers \
78 slice_hrn %s \r\n slices %s self.driver.hrn %s"
79 % (slice_hrn, slices, self.driver.hrn))
81 return (sfa_slice, slivers)
83 # sort slivers by node id , if there is a job
84 #and therefore, node allocated to this slice
85 # for sfa_slice in slices:
88 node_ids_list = sfa_slice['node_ids']
90 logger.log_exc("IOTLABAGGREGATE \t \
91 get_slice_and_slivers No nodes in the slice \
96 for node in node_ids_list:
97 sliver_xrn = Xrn(slice_urn, type='sliver', id=node)
98 sliver_xrn.set_authority(self.driver.hrn)
99 sliver = Sliver({'sliver_id': sliver_xrn.urn,
100 'name': sfa_slice['hrn'],
101 'type': 'iotlab-node',
104 slivers[node] = sliver
106 #Add default sliver attribute :
107 #connection information for iotlab
108 # if get_authority(sfa_slice['hrn']) == \
109 # self.driver.testbed_shell.root_auth:
110 # tmp = sfa_slice['hrn'].split('.')
111 # ldap_username = tmp[1].split('_')[0]
113 # slivers['default_sliver'] = {'ssh': ssh_access,
114 # 'login': ldap_username}
116 ldap_username = self.find_ldap_username_from_slice(sfa_slice)
118 if ldap_username is not None:
120 slivers['default_sliver'] = {'ssh': ssh_access,
121 'login': ldap_username}
124 logger.debug("IOTLABAGGREGATE api get_slice_and_slivers slivers %s "
126 return (slices, slivers)
128 def find_ldap_username_from_slice(self, sfa_slice):
130 Gets the ldap username of the user based on the information contained
131 in ist sfa_slice record.
133 :param sfa_slice: the user's slice record. Must contain the
135 :type sfa_slice: dictionary
136 :returns: ldap_username, the ldap user's login.
140 researchers = [sfa_slice['reg_researchers'][0].__dict__]
143 ret = self.driver.testbed_shell.GetPersons(researchers)
145 ldap_username = ret[0]['uid']
151 def get_nodes(self, options=None):
152 # def node_to_rspec_node(self, node, sites, node_tags,
153 # grain=None, options={}):
154 """Returns the nodes in the slice using the rspec format, with all the
157 Fetch the nodes ids in the slices dictionary and get all the nodes
158 properties from OAR. Makes a rspec dicitonary out of this and returns
159 it. If the slice does not have any job running or scheduled, that is
160 it has no reserved nodes, then returns an empty list.
162 :returns: An empty list if the slice has no reserved nodes, a rspec
163 list with all the nodes and their properties (a dict per node)
167 .. seealso:: get_slice_and_slivers
171 # NT: the semantic of this function is not clear to me :
172 # if slice is not defined, then all the nodes should be returned
173 # if slice is defined, we should return only the nodes that
174 # are part of this slice
175 # but what is the role of the slivers parameter ?
176 # So i assume that slice['node_ids'] will be the same as slivers for us
179 geni_available = options.get('geni_available')
180 if geni_available == True:
181 filter_nodes['boot_state'] = ['Alive']
183 # slice_nodes_list = []
184 # if slices is not None:
185 # for one_slice in slices:
187 # slice_nodes_list = one_slice['node_ids']
188 # # if we are dealing with a slice that has no node just
189 # # return an empty list. In iotlab a slice can have multiple
190 # # jobs scheduled, so it either has at least one lease or
195 # get the granularity in second for the reservation system
196 # grain = self.driver.testbed_shell.GetLeaseGranularity()
198 nodes = self.driver.testbed_shell.GetNodes(node_filter_dict =
203 #if slices, this means we got to list all the nodes given to this slice
204 # Make a list of all the nodes in the slice before getting their
208 # logger.debug("IOTLABAGGREGATE api get_nodes slices %s "
211 # reserved_nodes = self.driver.testbed_shell.GetNodesCurrentlyInUse()
212 # logger.debug("IOTLABAGGREGATE api get_nodes slice_nodes_list %s "
213 # % (slice_nodes_list))
215 nodes_dict[node['node_id']] = node
219 def node_to_rspec_node(self, node):
220 """ Creates a rspec node structure with the appropriate information
221 based on the node information that can be found in the node dictionary.
223 :param node: node data. this dict contains information about the node
224 and must have the following keys : mobile, radio, archi, hostname,
225 boot_state, site, x, y ,z (position).
226 :type node: dictionary.
228 :returns: node dictionary containing the following keys : mobile, archi,
229 radio, component_id, component_name, component_manager_id,
230 authority_id, boot_state, exclusive, hardware_types, location,
231 position, granularity, tags.
236 grain = self.driver.testbed_shell.GetLeaseGranularity()
238 rspec_node = IotlabNode()
239 # xxx how to retrieve site['login_base']
240 #site_id=node['site_id']
241 #site=sites_dict[site_id]
243 rspec_node['mobile'] = node['mobile']
244 rspec_node['archi'] = node['archi']
245 rspec_node['radio'] = node['radio']
247 iotlab_xrn = xrn_object(self.driver.testbed_shell.root_auth,
249 rspec_node['component_id'] = iotlab_xrn.urn
250 rspec_node['component_name'] = node['hostname']
251 rspec_node['component_manager_id'] = \
252 hrn_to_urn(self.driver.testbed_shell.root_auth,
255 # Iotlab's nodes are federated : there is only one authority
256 # for all Iotlab sites, registered in SFA.
257 # Removing the part including the site
258 # in authority_id SA 27/07/12
259 rspec_node['authority_id'] = rspec_node['component_manager_id']
261 # do not include boot state (<available> element)
262 #in the manifest rspec
265 rspec_node['boot_state'] = node['boot_state']
266 # if node['hostname'] in reserved_nodes:
267 # rspec_node['boot_state'] = "Reserved"
268 rspec_node['exclusive'] = 'true'
269 rspec_node['hardware_types'] = [HardwareType({'name': \
272 location = IotlabLocation({'country':'France', 'site': \
274 rspec_node['location'] = location
277 position = IotlabPosition()
278 for field in position :
280 position[field] = node[field]
281 except KeyError, error :
282 logger.log_exc("IOTLABAGGREGATE\t get_nodes \
283 position %s "% (error))
285 rspec_node['position'] = position
289 granularity = Granularity({'grain': grain})
290 rspec_node['granularity'] = granularity
291 rspec_node['tags'] = []
292 # if node['hostname'] in slivers:
294 # sliver = slivers[node['hostname']]
295 # rspec_node['sliver_id'] = sliver['sliver_id']
296 # rspec_node['client_id'] = node['hostname']
297 # rspec_node['slivers'] = [sliver]
299 # # slivers always provide the ssh service
300 # login = Login({'authentication': 'ssh-keys', \
301 # 'hostname': node['hostname'], 'port':'22', \
302 # 'username': sliver['name']})
303 # service = Services({'login': login})
304 # rspec_node['services'] = [service]
309 def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations = {}):
310 """Makes a geni sliver structure from all the nodes allocated
311 to slivers in the sliver_allocations dictionary. Returns the states
314 :param rspec_node: Node information contained in a rspec data structure
316 :type rspec_node: dictionary
317 :param sliver_allocations:
318 :type sliver_allocations: dictionary
320 :returns: Dictionary with the following keys: geni_sliver_urn,
321 geni_expires, geni_allocation_status, geni_operational_status,
326 .. seealso:: node_to_rspec_node
329 if rspec_node['sliver_id'] in sliver_allocations:
330 # set sliver allocation and operational status
331 sliver_allocation = sliver_allocations[rspec_node['sliver_id']]
332 if sliver_allocation:
333 allocation_status = sliver_allocation.allocation_state
334 if allocation_status == 'geni_allocated':
335 op_status = 'geni_pending_allocation'
336 elif allocation_status == 'geni_provisioned':
337 op_status = 'geni_ready'
339 op_status = 'geni_unknown'
341 allocation_status = 'geni_unallocated'
343 allocation_status = 'geni_unallocated'
344 op_status = 'geni_failed'
346 geni_sliver = {'geni_sliver_urn': rspec_node['sliver_id'],
347 'geni_expires': rspec_node['expires'],
348 'geni_allocation_status' : allocation_status,
349 'geni_operational_status': op_status,
355 def sliver_to_rspec_node(self, sliver, sliver_allocations):
356 """Used by describe to format node information into a rspec compliant
359 Creates a node rspec compliant structure by calling node_to_rspec_node.
360 Adds slivers, if any, to rspec node structure. Returns the updated
363 :param sliver: sliver dictionary. Contains keys: urn, slice_id, hostname
365 :type sliver: dictionary
366 :param sliver_allocations: dictionary of slivers
367 :type sliver_allocations: dict
369 :returns: Node dictionary with all necessary data.
371 .. seealso:: node_to_rspec_node
373 rspec_node = self.node_to_rspec_node(sliver)
374 rspec_node['expires'] = datetime_to_string(utcparse(sliver['expires']))
376 logger.debug("IOTLABAGGREGATE api \t sliver_to_rspec_node sliver \
377 %s \r\nsliver_allocations %s" % (sliver,
379 rspec_sliver = Sliver({'sliver_id': sliver['urn'],
380 'name': sliver['slice_id'],
381 'type': 'iotlab-exclusive',
383 rspec_node['sliver_id'] = rspec_sliver['sliver_id']
385 if sliver['urn'] in sliver_allocations:
386 rspec_node['client_id'] = sliver_allocations[
387 sliver['urn']].client_id
388 if sliver_allocations[sliver['urn']].component_id:
389 rspec_node['component_id'] = sliver_allocations[
390 sliver['urn']].component_id
391 rspec_node['slivers'] = [rspec_sliver]
393 # slivers always provide the ssh service
394 login = Login({'authentication': 'ssh-keys',
395 'hostname': sliver['hostname'],
397 'username': sliver['slice_name'],
398 'login': sliver['slice_name']
403 def get_all_leases(self, ldap_username):
405 Get list of lease dictionaries which all have the mandatory keys
406 ('lease_id', 'hostname', 'site_id', 'name', 'start_time', 'duration').
407 All the leases running or scheduled are returned.
409 :param ldap_username: if ldap uid is not None, looks for the leases
410 belonging to this user.
411 :type ldap_username: string
412 :returns: rspec lease dictionary with keys lease_id, component_id,
413 slice_id, start_time, duration where the lease_id is the oar job id,
414 component_id is the node's urn, slice_id is the slice urn,
415 start_time is the timestamp starting time and duration is expressed
416 in terms of the testbed's granularity.
419 .. note::There is no filtering of leases within a given time frame.
420 All the running or scheduled leases are returned. options
421 removed SA 15/05/2013
426 logger.debug("IOTLABAGGREGATE get_all_leases ldap_username %s "
428 leases = self.driver.GetLeases(login=ldap_username)
429 grain = self.driver.testbed_shell.GetLeaseGranularity()
433 #as many leases as there are nodes in the job
434 for node in lease['reserved_nodes']:
435 rspec_lease = Lease()
436 rspec_lease['lease_id'] = lease['lease_id']
437 #site = node['site_id']
438 iotlab_xrn = xrn_object(self.driver.testbed_shell.root_auth,
440 rspec_lease['component_id'] = iotlab_xrn.urn
441 #rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn,\
442 #site, node['hostname'])
444 rspec_lease['slice_id'] = lease['slice_id']
446 #No info on the slice used in testbed_xp table
448 rspec_lease['start_time'] = lease['t_from']
449 rspec_lease['duration'] = (lease['t_until'] - lease['t_from']) \
451 rspec_leases.append(rspec_lease)
454 def get_rspec(self, slice_xrn=None, login=None, version=None,
458 - a full advertisement rspec with the testbed resources if slice_xrn is
459 not specified.If a lease option is given, also returns the leases
460 scheduled on the testbed.
461 - a manifest Rspec with the leases and nodes in slice's leases if
462 slice_xrn is not None.
464 :param slice_xrn: srn of the slice
465 :type slice_xrn: string
466 :param login: user'uid (ldap login) on iotlab
468 :param version: can be set to sfa or iotlab
469 :type version: RSpecVersion
470 :param options: used to specify if the leases should also be included in
482 version_manager = VersionManager()
483 version = version_manager.get_version(version)
484 logger.debug("IotlabAggregate \t get_rspec ***version %s \
485 version.type %s version.version %s options %s \r\n"
486 % (version, version.type, version.version, options))
488 if slice_xrn is None:
489 rspec_version = version_manager._get_version(version.type,
490 version.version, 'ad')
493 rspec_version = version_manager._get_version(
494 version.type, version.version, 'manifest')
496 slices, slivers = self.get_slice_and_slivers(slice_xrn, login)
497 if slice_xrn and slices is not None:
498 #Get user associated with this slice
499 #for one_slice in slices :
500 ldap_username = self.find_ldap_username_from_slice(slices[0])
501 # ldap_username = slices[0]['reg_researchers'][0].__dict__['hrn']
502 # # ldap_username = slices[0]['user']
503 # tmp = ldap_username.split('.')
504 # ldap_username = tmp[1]
505 logger.debug("IotlabAggregate \tget_rspec **** \
506 LDAP USERNAME %s \r\n" \
508 #at this point sliver may be empty if no iotlab job
509 #is running for this user/slice.
510 rspec = RSpec(version=rspec_version, user_options=options)
512 logger.debug("\r\n \r\n IotlabAggregate \tget_rspec *** \
513 slice_xrn %s slices %s\r\n \r\n"
514 % (slice_xrn, slices))
516 if options is not None:
517 lease_option = options['list_leases']
519 #If no options are specified, at least print the resources
522 #lease_option = 'all'
524 if lease_option in ['all', 'resources']:
525 #if not options.get('list_leases') or options.get('list_leases')
526 #and options['list_leases'] != 'leases':
527 nodes = self.get_nodes()
529 logger.debug("IotlabAggregate \t lease_option %s \
530 get rspec ******* nodes %s"
531 % (lease_option, nodes))
533 sites_set = set([node['location']['site'] for node in nodes])
535 #In case creating a job, slice_xrn is not set to None
536 rspec.version.add_nodes(nodes)
537 if slice_xrn and slices is not None:
538 # #Get user associated with this slice
539 # #for one_slice in slices :
540 # ldap_username = slices[0]['reg_researchers']
541 # # ldap_username = slices[0]['user']
542 # tmp = ldap_username.split('.')
543 # ldap_username = tmp[1]
544 # # ldap_username = tmp[1].split('_')[0]
546 logger.debug("IotlabAggregate \tget_rspec **** \
547 version type %s ldap_ user %s \r\n" \
548 % (version.type, ldap_username))
549 if version.type == "Iotlab":
550 rspec.version.add_connection_information(
551 ldap_username, sites_set)
553 default_sliver = slivers.get('default_sliver', [])
554 if default_sliver and len(nodes) is not 0:
555 #default_sliver_attribs = default_sliver.get('tags', [])
556 logger.debug("IotlabAggregate \tget_rspec **** \
557 default_sliver%s \r\n" % (default_sliver))
558 for attrib in default_sliver:
559 rspec.version.add_default_sliver_attribute(
560 attrib, default_sliver[attrib])
562 if lease_option in ['all','leases']:
563 leases = self.get_all_leases(ldap_username)
564 rspec.version.add_leases(leases)
565 logger.debug("IotlabAggregate \tget_rspec **** \
566 FINAL RSPEC %s \r\n" % (rspec.toxml()))
569 def get_slivers(self, urns, options={}):
570 """Get slivers of the given slice urns. Slivers contains slice, node and
573 For Iotlab, returns the leases with sliver ids and their allocation
576 :param urns: list of slice urns.
577 :type urns: list of strings
578 :param options: unused
579 :type options: unused
581 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#urns
588 xrn = IotlabXrn(xrn=urn)
589 if xrn.type == 'sliver':
590 # id: slice_id-node_id
592 sliver_id_parts = xrn.get_sliver_id_parts()
593 slice_id = int(sliver_id_parts[0])
594 node_id = int(sliver_id_parts[1])
595 slice_ids.add(slice_id)
596 node_ids.append(node_id)
601 slice_names.add(xrn.hrn)
604 logger.debug("IotlabAggregate \t get_slivers urns %s slice_ids %s \
605 node_ids %s\r\n" % (urns, slice_ids, node_ids))
606 logger.debug("IotlabAggregate \t get_slivers xrn %s slice_names %s \
607 \r\n" % (xrn, slice_names))
610 filter_sliver['slice_hrn'] = list(slice_names)
611 slice_hrn = filter_sliver['slice_hrn'][0]
613 slice_filter_type = 'slice_hrn'
616 # filter['slice_id'] = list(slice_ids)
619 slices = self.driver.GetSlices(slice_hrn,
621 leases = self.driver.GetLeases({'slice_hrn':slice_hrn})
622 logger.debug("IotlabAggregate \t get_slivers \
623 slices %s leases %s\r\n" % (slices, leases ))
627 single_slice = slices[0]
629 user = single_slice['reg_researchers'][0].__dict__
630 logger.debug("IotlabAggregate \t get_slivers user %s \
633 # construct user key info
634 person = self.driver.testbed_shell.ldap.LdapFindUser(record=user)
635 logger.debug("IotlabAggregate \t get_slivers person %s \
637 # name = person['last_name']
638 user['login'] = person['uid']
639 user['user_urn'] = hrn_to_urn(user['hrn'], 'user')
640 user['keys'] = person['pkey']
644 node_ids = single_slice['node_ids']
645 node_list = self.driver.testbed_shell.GetNodes(
646 {'hostname':single_slice['node_ids']})
647 node_by_hostname = dict([(node['hostname'], node)
648 for node in node_list])
650 logger.warning("\t get_slivers No slivers in slice")
651 # slice['node_ids'] = node_ids
652 # nodes_dict = self.get_slice_nodes(slice, options)
655 for current_lease in leases:
656 for hostname in current_lease['reserved_nodes']:
658 node['slice_id'] = current_lease['slice_id']
659 node['slice_hrn'] = current_lease['slice_hrn']
660 slice_name = current_lease['slice_hrn'].split(".")[1]
661 node['slice_name'] = slice_name
662 index = current_lease['reserved_nodes'].index(hostname)
663 node_id = current_lease['resource_ids'][index]
664 # node['slice_name'] = user['login']
665 # node.update(single_slice)
666 more_info = node_by_hostname[hostname]
667 node.update(more_info)
668 # oar_job_id is the slice_id (lease_id)
669 sliver_hrn = '%s.%s-%s' % (self.driver.hrn,
670 current_lease['lease_id'], node_id)
671 node['node_id'] = node_id
672 node['expires'] = current_lease['t_until']
673 node['sliver_id'] = Xrn(sliver_hrn, type='sliver').urn
674 node['urn'] = node['sliver_id']
675 node['services_user'] = [user]
680 def list_resources(self, version = None, options={}):
682 Returns an advertisement Rspec of available resources at this
683 aggregate. This Rspec contains a resource listing along with their
684 description, providing sufficient information for clients to be able to
685 select among available resources.
687 :param options: various options. The valid options are: {boolean
688 geni_compressed <optional>; struct geni_rspec_version { string type;
689 #case insensitive , string version; # case insensitive}} . The only
690 mandatory options if options is specified is geni_rspec_version.
691 :type options: dictionary
693 :returns: On success, the value field of the return struct will contain
694 a geni.rspec advertisment RSpec
695 :rtype: Rspec advertisement in xml.
697 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#RSpecdatatype
698 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#ListResources
701 version_manager = VersionManager()
702 version = version_manager.get_version(version)
703 rspec_version = version_manager._get_version(version.type,
704 version.version, 'ad')
705 rspec = RSpec(version=rspec_version, user_options=options)
706 # variable ldap_username to be compliant with get_all_leases
707 # prototype. Now unused in geni-v3 since we are getting all the leases
710 if not options.get('list_leases') or options['list_leases'] != 'leases':
712 nodes_dict = self.get_nodes(options)
714 # no interfaces on iotlab nodes
715 # convert nodes to rspec nodes
717 for node_id in nodes_dict:
718 node = nodes_dict[node_id]
719 rspec_node = self.node_to_rspec_node(node)
720 rspec_nodes.append(rspec_node)
721 rspec.version.add_nodes(rspec_nodes)
724 # links = self.get_links(sites, nodes_dict, interfaces)
725 # rspec.version.add_links(links)
727 if not options.get('list_leases') or options.get('list_leases') \
728 and options['list_leases'] != 'resources':
729 leases = self.get_all_leases(ldap_username)
730 rspec.version.add_leases(leases)
735 def describe(self, urns, version=None, options={}):
737 Retrieve a manifest RSpec describing the resources contained by the
738 named entities, e.g. a single slice or a set of the slivers in a slice.
739 This listing and description should be sufficiently descriptive to allow
740 experimenters to use the resources.
742 :param urns: If a slice urn is supplied and there are no slivers in the
743 given slice at this aggregate, then geni_rspec shall be a valid
744 manifest RSpec, containing no node elements - no resources.
745 :type urns: list or strings
746 :param options: various options. the valid options are: {boolean
747 geni_compressed <optional>; struct geni_rspec_version { string type;
748 #case insensitive , string version; # case insensitive}}
749 :type options: dictionary
751 :returns: On success returns the following dictionary {geni_rspec:
752 <geni.rspec, a Manifest RSpec>, geni_urn: <string slice urn of the
753 containing slice>, geni_slivers:{ geni_sliver_urn:
754 <string sliver urn>, geni_expires: <dateTime.rfc3339 allocation
755 expiration string, as in geni_expires from SliversStatus>,
756 geni_allocation_status: <string sliver state - e.g. geni_allocated
757 or geni_provisioned >, geni_operational_status:
758 <string sliver operational state>, geni_error: <optional string.
759 The field may be omitted entirely but may not be null/None,
760 explaining any failure for a sliver.>}
762 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#Describe
763 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#urns
765 version_manager = VersionManager()
766 version = version_manager.get_version(version)
767 rspec_version = version_manager._get_version(
768 version.type, version.version, 'manifest')
769 rspec = RSpec(version=rspec_version, user_options=options)
773 slivers = self.get_slivers(urns, options)
775 rspec_expires = datetime_to_string(utcparse(slivers[0]['expires']))
777 rspec_expires = datetime_to_string(utcparse(time.time()))
778 rspec.xml.set('expires', rspec_expires)
780 # lookup the sliver allocations
782 sliver_ids = [sliver['sliver_id'] for sliver in slivers]
783 logger.debug(" IOTLAB_API.PY \tDescribe sliver_ids %s "
785 constraint = SliverAllocation.sliver_id.in_(sliver_ids)
786 query = self.driver.api.dbsession().query(SliverAllocation)
787 sliver_allocations = query.filter((constraint)).all()
788 logger.debug(" IOTLAB_API.PY \tDescribe sliver_allocations %s "
789 % (sliver_allocations))
790 sliver_allocation_dict = {}
791 for sliver_allocation in sliver_allocations:
792 geni_urn = sliver_allocation.slice_urn
793 sliver_allocation_dict[sliver_allocation.sliver_id] = \
798 for sliver in slivers:
799 nodes_dict[sliver['node_id']] = sliver
801 for sliver in slivers:
802 rspec_node = self.sliver_to_rspec_node(sliver,
803 sliver_allocation_dict)
804 rspec_nodes.append(rspec_node)
805 logger.debug(" IOTLAB_API.PY \tDescribe sliver_allocation_dict %s "
806 % (sliver_allocation_dict))
807 geni_sliver = self.rspec_node_to_geni_sliver(rspec_node,
808 sliver_allocation_dict)
809 geni_slivers.append(geni_sliver)
811 logger.debug(" IOTLAB_API.PY \tDescribe rspec_nodes %s\
813 % (rspec_nodes, rspec))
814 rspec.version.add_nodes(rspec_nodes)
816 return {'geni_urn': geni_urn,
817 'geni_rspec': rspec.toxml(),
818 'geni_slivers': geni_slivers}