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.
372 .. seealso:: node_to_rspec_node
374 rspec_node = self.node_to_rspec_node(sliver)
375 rspec_node['expires'] = datetime_to_string(utcparse(sliver['expires']))
377 logger.debug("IOTLABAGGREGATE api \t sliver_to_rspec_node sliver \
378 %s \r\nsliver_allocations %s" % (sliver,
380 rspec_sliver = Sliver({'sliver_id': sliver['urn'],
381 'name': sliver['slice_id'],
382 'type': 'iotlab-exclusive',
384 rspec_node['sliver_id'] = rspec_sliver['sliver_id']
386 if sliver['urn'] in sliver_allocations:
387 rspec_node['client_id'] = sliver_allocations[
388 sliver['urn']].client_id
389 if sliver_allocations[sliver['urn']].component_id:
390 rspec_node['component_id'] = sliver_allocations[
391 sliver['urn']].component_id
392 rspec_node['slivers'] = [rspec_sliver]
394 # slivers always provide the ssh service
395 login = Login({'authentication': 'ssh-keys',
396 'hostname': sliver['hostname'],
398 'username': sliver['slice_name'],
399 'login': sliver['slice_name']
404 def get_all_leases(self, ldap_username):
406 Get list of lease dictionaries which all have the mandatory keys
407 ('lease_id', 'hostname', 'site_id', 'name', 'start_time', 'duration').
408 All the leases running or scheduled are returned.
410 :param ldap_username: if ldap uid is not None, looks for the leases
411 belonging to this user.
412 :type ldap_username: string
413 :returns: rspec lease dictionary with keys lease_id, component_id,
414 slice_id, start_time, duration where the lease_id is the oar job id,
415 component_id is the node's urn, slice_id is the slice urn,
416 start_time is the timestamp starting time and duration is expressed
417 in terms of the testbed's granularity.
420 .. note::There is no filtering of leases within a given time frame.
421 All the running or scheduled leases are returned. options
422 removed SA 15/05/2013
427 logger.debug("IOTLABAGGREGATE get_all_leases ldap_username %s "
429 leases = self.driver.GetLeases(login=ldap_username)
430 grain = self.driver.testbed_shell.GetLeaseGranularity()
434 #as many leases as there are nodes in the job
435 for node in lease['reserved_nodes']:
436 rspec_lease = Lease()
437 rspec_lease['lease_id'] = lease['lease_id']
438 #site = node['site_id']
439 iotlab_xrn = xrn_object(self.driver.testbed_shell.root_auth,
441 rspec_lease['component_id'] = iotlab_xrn.urn
442 #rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn,\
443 #site, node['hostname'])
445 rspec_lease['slice_id'] = lease['slice_id']
447 #No info on the slice used in testbed_xp table
449 rspec_lease['start_time'] = lease['t_from']
450 rspec_lease['duration'] = (lease['t_until'] - lease['t_from']) \
452 rspec_leases.append(rspec_lease)
455 def get_rspec(self, slice_xrn=None, login=None, version=None,
459 - a full advertisement rspec with the testbed resources if slice_xrn is
460 not specified.If a lease option is given, also returns the leases
461 scheduled on the testbed.
462 - a manifest Rspec with the leases and nodes in slice's leases if
463 slice_xrn is not None.
465 :param slice_xrn: srn of the slice
466 :type slice_xrn: string
467 :param login: user'uid (ldap login) on iotlab
469 :param version: can be set to sfa or iotlab
470 :type version: RSpecVersion
471 :param options: used to specify if the leases should also be included in
483 version_manager = VersionManager()
484 version = version_manager.get_version(version)
485 logger.debug("IotlabAggregate \t get_rspec ***version %s \
486 version.type %s version.version %s options %s \r\n"
487 % (version, version.type, version.version, options))
489 if slice_xrn is None:
490 rspec_version = version_manager._get_version(version.type,
491 version.version, 'ad')
494 rspec_version = version_manager._get_version(
495 version.type, version.version, 'manifest')
497 slices, slivers = self.get_slice_and_slivers(slice_xrn, login)
498 if slice_xrn and slices is not None:
499 #Get user associated with this slice
500 #for one_slice in slices :
501 ldap_username = self.find_ldap_username_from_slice(slices[0])
502 # ldap_username = slices[0]['reg_researchers'][0].__dict__['hrn']
503 # # ldap_username = slices[0]['user']
504 # tmp = ldap_username.split('.')
505 # ldap_username = tmp[1]
506 logger.debug("IotlabAggregate \tget_rspec **** \
507 LDAP USERNAME %s \r\n" \
509 #at this point sliver may be empty if no iotlab job
510 #is running for this user/slice.
511 rspec = RSpec(version=rspec_version, user_options=options)
513 logger.debug("\r\n \r\n IotlabAggregate \tget_rspec *** \
514 slice_xrn %s slices %s\r\n \r\n"
515 % (slice_xrn, slices))
517 if options is not None:
518 lease_option = options['list_leases']
520 #If no options are specified, at least print the resources
523 #lease_option = 'all'
525 if lease_option in ['all', 'resources']:
526 #if not options.get('list_leases') or options.get('list_leases')
527 #and options['list_leases'] != 'leases':
528 nodes = self.get_nodes()
530 logger.debug("IotlabAggregate \t lease_option %s \
531 get rspec ******* nodes %s"
532 % (lease_option, nodes))
534 sites_set = set([node['location']['site'] for node in nodes])
536 #In case creating a job, slice_xrn is not set to None
537 rspec.version.add_nodes(nodes)
538 if slice_xrn and slices is not None:
539 # #Get user associated with this slice
540 # #for one_slice in slices :
541 # ldap_username = slices[0]['reg_researchers']
542 # # ldap_username = slices[0]['user']
543 # tmp = ldap_username.split('.')
544 # ldap_username = tmp[1]
545 # # ldap_username = tmp[1].split('_')[0]
547 logger.debug("IotlabAggregate \tget_rspec **** \
548 version type %s ldap_ user %s \r\n" \
549 % (version.type, ldap_username))
550 if version.type == "Iotlab":
551 rspec.version.add_connection_information(
552 ldap_username, sites_set)
554 default_sliver = slivers.get('default_sliver', [])
555 if default_sliver and len(nodes) is not 0:
556 #default_sliver_attribs = default_sliver.get('tags', [])
557 logger.debug("IotlabAggregate \tget_rspec **** \
558 default_sliver%s \r\n" % (default_sliver))
559 for attrib in default_sliver:
560 rspec.version.add_default_sliver_attribute(
561 attrib, default_sliver[attrib])
563 if lease_option in ['all','leases']:
564 leases = self.get_all_leases(ldap_username)
565 rspec.version.add_leases(leases)
566 logger.debug("IotlabAggregate \tget_rspec **** \
567 FINAL RSPEC %s \r\n" % (rspec.toxml()))
570 def get_slivers(self, urns, options={}):
571 """Get slivers of the given slice urns. Slivers contains slice, node and
574 For Iotlab, returns the leases with sliver ids and their allocation
577 :param urns: list of slice urns.
578 :type urns: list of strings
579 :param options: unused
580 :type options: unused
582 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#urns
589 xrn = IotlabXrn(xrn=urn)
590 if xrn.type == 'sliver':
591 # id: slice_id-node_id
593 sliver_id_parts = xrn.get_sliver_id_parts()
594 slice_id = int(sliver_id_parts[0])
595 node_id = int(sliver_id_parts[1])
596 slice_ids.add(slice_id)
597 node_ids.append(node_id)
602 slice_names.add(xrn.hrn)
605 logger.debug("IotlabAggregate \t get_slivers urns %s slice_ids %s \
606 node_ids %s\r\n" % (urns, slice_ids, node_ids))
607 logger.debug("IotlabAggregate \t get_slivers xrn %s slice_names %s \
608 \r\n" % (xrn, slice_names))
611 filter_sliver['slice_hrn'] = list(slice_names)
612 slice_hrn = filter_sliver['slice_hrn'][0]
614 slice_filter_type = 'slice_hrn'
617 # filter['slice_id'] = list(slice_ids)
620 slices = self.driver.GetSlices(slice_hrn,
622 leases = self.driver.GetLeases({'slice_hrn':slice_hrn})
623 logger.debug("IotlabAggregate \t get_slivers \
624 slices %s leases %s\r\n" % (slices, leases ))
628 single_slice = slices[0]
630 user = single_slice['reg_researchers'][0].__dict__
631 logger.debug("IotlabAggregate \t get_slivers user %s \
634 # construct user key info
635 person = self.driver.testbed_shell.ldap.LdapFindUser(record=user)
636 logger.debug("IotlabAggregate \t get_slivers person %s \
638 # name = person['last_name']
639 user['login'] = person['uid']
640 user['user_urn'] = hrn_to_urn(user['hrn'], 'user')
641 user['keys'] = person['pkey']
645 node_ids = single_slice['node_ids']
646 node_list = self.driver.testbed_shell.GetNodes(
647 {'hostname':single_slice['node_ids']})
648 node_by_hostname = dict([(node['hostname'], node)
649 for node in node_list])
651 logger.warning("\t get_slivers No slivers in slice")
652 # slice['node_ids'] = node_ids
653 # nodes_dict = self.get_slice_nodes(slice, options)
656 for current_lease in leases:
657 for hostname in current_lease['reserved_nodes']:
659 node['slice_id'] = current_lease['slice_id']
660 node['slice_hrn'] = current_lease['slice_hrn']
661 slice_name = current_lease['slice_hrn'].split(".")[1]
662 node['slice_name'] = slice_name
663 index = current_lease['reserved_nodes'].index(hostname)
664 node_id = current_lease['resource_ids'][index]
665 # node['slice_name'] = user['login']
666 # node.update(single_slice)
667 more_info = node_by_hostname[hostname]
668 node.update(more_info)
669 # oar_job_id is the slice_id (lease_id)
670 sliver_hrn = '%s.%s-%s' % (self.driver.hrn,
671 current_lease['lease_id'], node_id)
672 node['node_id'] = node_id
673 node['expires'] = current_lease['t_until']
674 node['sliver_id'] = Xrn(sliver_hrn, type='sliver').urn
675 node['urn'] = node['sliver_id']
676 node['services_user'] = [user]
681 def list_resources(self, version = None, options={}):
683 Returns an advertisement Rspec of available resources at this
684 aggregate. This Rspec contains a resource listing along with their
685 description, providing sufficient information for clients to be able to
686 select among available resources.
688 :param options: various options. The valid options are: {boolean
689 geni_compressed <optional>; struct geni_rspec_version { string type;
690 #case insensitive , string version; # case insensitive}} . The only
691 mandatory options if options is specified is geni_rspec_version.
692 :type options: dictionary
694 :returns: On success, the value field of the return struct will contain
695 a geni.rspec advertisment RSpec
696 :rtype: Rspec advertisement in xml.
698 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#RSpecdatatype
699 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#ListResources
702 version_manager = VersionManager()
703 version = version_manager.get_version(version)
704 rspec_version = version_manager._get_version(version.type,
705 version.version, 'ad')
706 rspec = RSpec(version=rspec_version, user_options=options)
707 # variable ldap_username to be compliant with get_all_leases
708 # prototype. Now unused in geni-v3 since we are getting all the leases
711 if not options.get('list_leases') or options['list_leases'] != 'leases':
713 nodes_dict = self.get_nodes(options)
715 # no interfaces on iotlab nodes
716 # convert nodes to rspec nodes
718 for node_id in nodes_dict:
719 node = nodes_dict[node_id]
720 rspec_node = self.node_to_rspec_node(node)
721 rspec_nodes.append(rspec_node)
722 rspec.version.add_nodes(rspec_nodes)
725 # links = self.get_links(sites, nodes_dict, interfaces)
726 # rspec.version.add_links(links)
728 if not options.get('list_leases') or options.get('list_leases') \
729 and options['list_leases'] != 'resources':
730 leases = self.get_all_leases(ldap_username)
731 rspec.version.add_leases(leases)
736 def describe(self, urns, version=None, options={}):
738 Retrieve a manifest RSpec describing the resources contained by the
739 named entities, e.g. a single slice or a set of the slivers in a slice.
740 This listing and description should be sufficiently descriptive to allow
741 experimenters to use the resources.
743 :param urns: If a slice urn is supplied and there are no slivers in the
744 given slice at this aggregate, then geni_rspec shall be a valid
745 manifest RSpec, containing no node elements - no resources.
746 :type urns: list or strings
747 :param options: various options. the valid options are: {boolean
748 geni_compressed <optional>; struct geni_rspec_version { string type;
749 #case insensitive , string version; # case insensitive}}
750 :type options: dictionary
752 :returns: On success returns the following dictionary {geni_rspec:
753 <geni.rspec, a Manifest RSpec>, geni_urn: <string slice urn of the
754 containing slice>, geni_slivers:{ geni_sliver_urn:
755 <string sliver urn>, geni_expires: <dateTime.rfc3339 allocation
756 expiration string, as in geni_expires from SliversStatus>,
757 geni_allocation_status: <string sliver state - e.g. geni_allocated
758 or geni_provisioned >, geni_operational_status:
759 <string sliver operational state>, geni_error: <optional string.
760 The field may be omitted entirely but may not be null/None,
761 explaining any failure for a sliver.>}
763 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#Describe
764 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#urns
766 version_manager = VersionManager()
767 version = version_manager.get_version(version)
768 rspec_version = version_manager._get_version(
769 version.type, version.version, 'manifest')
770 rspec = RSpec(version=rspec_version, user_options=options)
774 slivers = self.get_slivers(urns, options)
776 rspec_expires = datetime_to_string(utcparse(slivers[0]['expires']))
778 rspec_expires = datetime_to_string(utcparse(time.time()))
779 rspec.xml.set('expires', rspec_expires)
781 # lookup the sliver allocations
783 sliver_ids = [sliver['sliver_id'] for sliver in slivers]
784 logger.debug(" IOTLAB_API.PY \tDescribe sliver_ids %s "
786 constraint = SliverAllocation.sliver_id.in_(sliver_ids)
787 query = self.driver.api.dbsession().query(SliverAllocation)
788 sliver_allocations = query.filter((constraint)).all()
789 logger.debug(" IOTLAB_API.PY \tDescribe sliver_allocations %s "
790 % (sliver_allocations))
791 sliver_allocation_dict = {}
792 for sliver_allocation in sliver_allocations:
793 geni_urn = sliver_allocation.slice_urn
794 sliver_allocation_dict[sliver_allocation.sliver_id] = \
799 for sliver in slivers:
800 nodes_dict[sliver['node_id']] = sliver
802 for sliver in slivers:
803 rspec_node = self.sliver_to_rspec_node(sliver,
804 sliver_allocation_dict)
805 rspec_nodes.append(rspec_node)
806 logger.debug(" IOTLAB_API.PY \tDescribe sliver_allocation_dict %s "
807 % (sliver_allocation_dict))
808 geni_sliver = self.rspec_node_to_geni_sliver(rspec_node,
809 sliver_allocation_dict)
810 geni_slivers.append(geni_sliver)
812 logger.debug(" IOTLAB_API.PY \tDescribe rspec_nodes %s\
814 % (rspec_nodes, rspec))
815 rspec.version.add_nodes(rspec_nodes)
817 return {'geni_urn': geni_urn,
818 'geni_rspec': rspec.toxml(),
819 'geni_slivers': geni_slivers}