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(
74 slice_filter=str(slice_hrn),
75 slice_filter_type='slice_hrn',
78 logger.debug("IotlabAggregate api \tget_slice_and_slivers \
79 slice_hrn %s \r\n slices %s self.driver.hrn %s"
80 % (slice_hrn, slices, self.driver.hrn))
82 return (sfa_slice, slivers)
84 # sort slivers by node id , if there is a job
85 #and therefore, node allocated to this slice
86 # for sfa_slice in slices:
89 node_ids_list = sfa_slice['node_ids']
91 logger.log_exc("IOTLABAGGREGATE \t \
92 get_slice_and_slivers No nodes in the slice \
97 for node in node_ids_list:
98 sliver_xrn = Xrn(slice_urn, type='sliver', id=node)
99 sliver_xrn.set_authority(self.driver.hrn)
100 sliver = Sliver({'sliver_id': sliver_xrn.urn,
101 'name': sfa_slice['hrn'],
102 'type': 'iotlab-node',
105 slivers[node] = sliver
107 #Add default sliver attribute :
108 #connection information for iotlab
109 # if get_authority(sfa_slice['hrn']) == \
110 # self.driver.testbed_shell.root_auth:
111 # tmp = sfa_slice['hrn'].split('.')
112 # ldap_username = tmp[1].split('_')[0]
114 # slivers['default_sliver'] = {'ssh': ssh_access,
115 # 'login': ldap_username}
117 ldap_username = self.find_ldap_username_from_slice(sfa_slice)
119 if ldap_username is not None:
121 slivers['default_sliver'] = {'ssh': ssh_access,
122 'login': ldap_username}
125 logger.debug("IOTLABAGGREGATE api get_slice_and_slivers slivers %s "
127 return (slices, slivers)
129 def find_ldap_username_from_slice(self, sfa_slice):
131 Gets the ldap username of the user based on the information contained
132 in ist sfa_slice record.
134 :param sfa_slice: the user's slice record. Must contain the
136 :type sfa_slice: dictionary
137 :returns: ldap_username, the ldap user's login.
141 researchers = [sfa_slice['reg_researchers'][0].__dict__]
144 ret = self.driver.testbed_shell.GetPersons(researchers)
146 ldap_username = ret[0]['uid']
152 def get_nodes(self, options=None):
153 # def node_to_rspec_node(self, node, sites, node_tags,
154 # grain=None, options={}):
155 """Returns the nodes in the slice using the rspec format, with all the
158 Fetch the nodes ids in the slices dictionary and get all the nodes
159 properties from OAR. Makes a rspec dicitonary out of this and returns
160 it. If the slice does not have any job running or scheduled, that is
161 it has no reserved nodes, then returns an empty list.
163 :returns: An empty list if the slice has no reserved nodes, a rspec
164 list with all the nodes and their properties (a dict per node)
168 .. seealso:: get_slice_and_slivers
172 # NT: the semantic of this function is not clear to me :
173 # if slice is not defined, then all the nodes should be returned
174 # if slice is defined, we should return only the nodes that
175 # are part of this slice
176 # but what is the role of the slivers parameter ?
177 # So i assume that slice['node_ids'] will be the same as slivers for us
180 geni_available = options.get('geni_available')
181 if geni_available == True:
182 filter_nodes['boot_state'] = ['Alive']
184 # slice_nodes_list = []
185 # if slices is not None:
186 # for one_slice in slices:
188 # slice_nodes_list = one_slice['node_ids']
189 # # if we are dealing with a slice that has no node just
190 # # return an empty list. In iotlab a slice can have multiple
191 # # jobs scheduled, so it either has at least one lease or
196 # get the granularity in second for the reservation system
197 # grain = self.driver.testbed_shell.GetLeaseGranularity()
199 nodes = self.driver.testbed_shell.GetNodes(node_filter_dict =
204 #if slices, this means we got to list all the nodes given to this slice
205 # Make a list of all the nodes in the slice before getting their
209 # logger.debug("IOTLABAGGREGATE api get_nodes slices %s "
212 # reserved_nodes = self.driver.testbed_shell.GetNodesCurrentlyInUse()
213 # logger.debug("IOTLABAGGREGATE api get_nodes slice_nodes_list %s "
214 # % (slice_nodes_list))
216 nodes_dict[node['node_id']] = node
220 def node_to_rspec_node(self, node):
221 """ Creates a rspec node structure with the appropriate information
222 based on the node information that can be found in the node dictionary.
224 :param node: node data. this dict contains information about the node
225 and must have the following keys : mobile, radio, archi, hostname,
226 boot_state, site, x, y ,z (position).
227 :type node: dictionary.
229 :returns: node dictionary containing the following keys : mobile, archi,
230 radio, component_id, component_name, component_manager_id,
231 authority_id, boot_state, exclusive, hardware_types, location,
232 position, granularity, tags.
237 grain = self.driver.testbed_shell.GetLeaseGranularity()
239 rspec_node = IotlabNode()
240 # xxx how to retrieve site['login_base']
241 #site_id=node['site_id']
242 #site=sites_dict[site_id]
244 rspec_node['mobile'] = node['mobile']
245 rspec_node['archi'] = node['archi']
246 rspec_node['radio'] = node['radio']
248 iotlab_xrn = xrn_object(self.driver.testbed_shell.root_auth,
250 rspec_node['component_id'] = iotlab_xrn.urn
251 rspec_node['component_name'] = node['hostname']
252 rspec_node['component_manager_id'] = \
253 hrn_to_urn(self.driver.testbed_shell.root_auth,
256 # Iotlab's nodes are federated : there is only one authority
257 # for all Iotlab sites, registered in SFA.
258 # Removing the part including the site
259 # in authority_id SA 27/07/12
260 rspec_node['authority_id'] = rspec_node['component_manager_id']
262 # do not include boot state (<available> element)
263 #in the manifest rspec
266 rspec_node['boot_state'] = node['boot_state']
267 # if node['hostname'] in reserved_nodes:
268 # rspec_node['boot_state'] = "Reserved"
269 rspec_node['exclusive'] = 'true'
270 rspec_node['hardware_types'] = [HardwareType({'name': \
273 location = IotlabLocation({'country':'France', 'site': \
275 rspec_node['location'] = location
278 position = IotlabPosition()
279 for field in position :
281 position[field] = node[field]
282 except KeyError, error :
283 logger.log_exc("IOTLABAGGREGATE\t get_nodes \
284 position %s "% (error))
286 rspec_node['position'] = position
290 granularity = Granularity({'grain': grain})
291 rspec_node['granularity'] = granularity
292 rspec_node['tags'] = []
293 # if node['hostname'] in slivers:
295 # sliver = slivers[node['hostname']]
296 # rspec_node['sliver_id'] = sliver['sliver_id']
297 # rspec_node['client_id'] = node['hostname']
298 # rspec_node['slivers'] = [sliver]
300 # # slivers always provide the ssh service
301 # login = Login({'authentication': 'ssh-keys', \
302 # 'hostname': node['hostname'], 'port':'22', \
303 # 'username': sliver['name']})
304 # service = Services({'login': login})
305 # rspec_node['services'] = [service]
310 def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations = {}):
311 """Makes a geni sliver structure from all the nodes allocated
312 to slivers in the sliver_allocations dictionary. Returns the states
315 :param rspec_node: Node information contained in a rspec data structure
317 :type rspec_node: dictionary
318 :param sliver_allocations:
319 :type sliver_allocations: dictionary
321 :returns: Dictionary with the following keys: geni_sliver_urn,
322 geni_expires, geni_allocation_status, geni_operational_status,
327 .. seealso:: node_to_rspec_node
330 if rspec_node['sliver_id'] in sliver_allocations:
331 # set sliver allocation and operational status
332 sliver_allocation = sliver_allocations[rspec_node['sliver_id']]
333 if sliver_allocation:
334 allocation_status = sliver_allocation.allocation_state
335 if allocation_status == 'geni_allocated':
336 op_status = 'geni_pending_allocation'
337 elif allocation_status == 'geni_provisioned':
338 op_status = 'geni_ready'
340 op_status = 'geni_unknown'
342 allocation_status = 'geni_unallocated'
344 allocation_status = 'geni_unallocated'
345 op_status = 'geni_failed'
347 geni_sliver = {'geni_sliver_urn': rspec_node['sliver_id'],
348 'geni_expires': rspec_node['expires'],
349 'geni_allocation_status' : allocation_status,
350 'geni_operational_status': op_status,
356 def sliver_to_rspec_node(self, sliver, sliver_allocations):
357 """Used by describe to format node information into a rspec compliant
360 Creates a node rspec compliant structure by calling node_to_rspec_node.
361 Adds slivers, if any, to rspec node structure. Returns the updated
364 :param sliver: sliver dictionary. Contains keys: urn, slice_id, hostname
366 :type sliver: dictionary
367 :param sliver_allocations: dictionary of slivers
368 :type sliver_allocations: dict
370 :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}