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, get_authority
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)
71 slice_name = slice_hrn
73 # GetSlices always returns a list, even if there is only one element
74 slices = self.driver.testbed_shell.GetSlices(slice_filter=str(slice_name),
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']) == 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):
129 researchers = [sfa_slice['reg_researchers'][0].__dict__]
132 ret = self.driver.testbed_shell.GetPersons(researchers)
134 ldap_username = ret[0]['uid']
140 def get_nodes(self, slices=None, slivers=[], options=None):
141 # def node_to_rspec_node(self, node, sites, node_tags,
142 # grain=None, options={}):
143 """Returns the nodes in the slice using the rspec format, with all the
146 Fetch the nodes ids in the slices dictionary and get all the nodes
147 properties from OAR. Makes a rspec dicitonary out of this and returns
148 it. If the slice does not have any job running or scheduled, that is
149 it has no reserved nodes, then returns an empty list.
151 :param slices: list of slices (record dictionaries)
152 :param slivers: the list of slivers in all the slices
153 :type slices: list of dicts
154 :type slivers: list of Sliver object (dictionaries)
155 :returns: An empty list if the slice has no reserved nodes, a rspec
156 list with all the nodes and their properties (a dict per node)
160 .. seealso:: get_slice_and_slivers
164 # NT: the semantic of this function is not clear to me :
165 # if slice is not defined, then all the nodes should be returned
166 # if slice is defined, we should return only the nodes that
167 # are part of this slice
168 # but what is the role of the slivers parameter ?
169 # So i assume that slice['node_ids'] will be the same as slivers for us
172 geni_available = options.get('geni_available')
173 if geni_available == True:
174 filter_nodes['boot_state'] = ['Alive']
176 # slice_nodes_list = []
177 # if slices is not None:
178 # for one_slice in slices:
180 # slice_nodes_list = one_slice['node_ids']
181 # # if we are dealing with a slice that has no node just
182 # # return an empty list. In iotlab a slice can have multiple
183 # # jobs scheduled, so it either has at least one lease or
188 # get the granularity in second for the reservation system
189 # grain = self.driver.testbed_shell.GetLeaseGranularity()
191 nodes = self.driver.testbed_shell.GetNodes()
195 #if slices, this means we got to list all the nodes given to this slice
196 # Make a list of all the nodes in the slice before getting their
200 # logger.debug("IOTLABAGGREGATE api get_nodes slices %s "
203 # reserved_nodes = self.driver.testbed_shell.GetNodesCurrentlyInUse()
204 # logger.debug("IOTLABAGGREGATE api get_nodes slice_nodes_list %s "
205 # % (slice_nodes_list))
207 nodes_dict[node['node_id']] = node
208 # if slice_nodes_list == [] or node['hostname'] in slice_nodes_list:
210 # rspec_node = IotlabNode()
211 # # xxx how to retrieve site['login_base']
212 # #site_id=node['site_id']
213 # #site=sites_dict[site_id]
215 # rspec_node['mobile'] = node['mobile']
216 # rspec_node['archi'] = node['archi']
217 # rspec_node['radio'] = node['radio']
219 # iotlab_xrn = xrn_object(self.driver.testbed_shell.root_auth,
221 # rspec_node['component_id'] = iotlab_xrn.urn
222 # rspec_node['component_name'] = node['hostname']
223 # rspec_node['component_manager_id'] = \
224 # hrn_to_urn(self.driver.testbed_shell.root_auth,
227 # # Iotlab's nodes are federated : there is only one authority
228 # # for all Iotlab sites, registered in SFA.
229 # # Removing the part including the site
230 # # in authority_id SA 27/07/12
231 # rspec_node['authority_id'] = rspec_node['component_manager_id']
233 # # do not include boot state (<available> element)
234 # #in the manifest rspec
237 # rspec_node['boot_state'] = node['boot_state']
238 # if node['hostname'] in reserved_nodes:
239 # rspec_node['boot_state'] = "Reserved"
240 # rspec_node['exclusive'] = 'true'
241 # rspec_node['hardware_types'] = [HardwareType({'name': \
245 # location = IotlabLocation({'country':'France', 'site': \
247 # rspec_node['location'] = location
250 # position = IotlabPosition()
251 # for field in position :
253 # position[field] = node[field]
254 # except KeyError, error :
255 # logger.log_exc("IOTLABAGGREGATE\t get_nodes \
256 # position %s "% (error))
258 # rspec_node['position'] = position
259 # #rspec_node['interfaces'] = []
262 # granularity = Granularity({'grain': grain})
263 # rspec_node['granularity'] = granularity
264 # rspec_node['tags'] = []
265 # if node['hostname'] in slivers:
267 # sliver = slivers[node['hostname']]
268 # rspec_node['sliver_id'] = sliver['sliver_id']
269 # rspec_node['client_id'] = node['hostname']
270 # rspec_node['slivers'] = [sliver]
272 # # slivers always provide the ssh service
273 # login = Login({'authentication': 'ssh-keys', \
274 # 'hostname': node['hostname'], 'port':'22', \
275 # 'username': sliver['name']})
276 # service = Services({'login': login})
277 # rspec_node['services'] = [service]
278 # rspec_nodes.append(rspec_node)
280 # return (rspec_nodes)
283 def node_to_rspec_node(self, node):
285 grain = self.driver.testbed_shell.GetLeaseGranularity()
287 rspec_node = IotlabNode()
288 # xxx how to retrieve site['login_base']
289 #site_id=node['site_id']
290 #site=sites_dict[site_id]
292 rspec_node['mobile'] = node['mobile']
293 rspec_node['archi'] = node['archi']
294 rspec_node['radio'] = node['radio']
296 iotlab_xrn = xrn_object(self.driver.testbed_shell.root_auth,
298 rspec_node['component_id'] = iotlab_xrn.urn
299 rspec_node['component_name'] = node['hostname']
300 rspec_node['component_manager_id'] = \
301 hrn_to_urn(self.driver.testbed_shell.root_auth,
304 # Iotlab's nodes are federated : there is only one authority
305 # for all Iotlab sites, registered in SFA.
306 # Removing the part including the site
307 # in authority_id SA 27/07/12
308 rspec_node['authority_id'] = rspec_node['component_manager_id']
310 # do not include boot state (<available> element)
311 #in the manifest rspec
314 rspec_node['boot_state'] = node['boot_state']
315 # if node['hostname'] in reserved_nodes:
316 # rspec_node['boot_state'] = "Reserved"
317 rspec_node['exclusive'] = 'true'
318 rspec_node['hardware_types'] = [HardwareType({'name': \
321 location = IotlabLocation({'country':'France', 'site': \
323 rspec_node['location'] = location
326 position = IotlabPosition()
327 for field in position :
329 position[field] = node[field]
330 except KeyError, error :
331 logger.log_exc("IOTLABAGGREGATE\t get_nodes \
332 position %s "% (error))
334 rspec_node['position'] = position
338 granularity = Granularity({'grain': grain})
339 rspec_node['granularity'] = granularity
340 rspec_node['tags'] = []
341 # if node['hostname'] in slivers:
343 # sliver = slivers[node['hostname']]
344 # rspec_node['sliver_id'] = sliver['sliver_id']
345 # rspec_node['client_id'] = node['hostname']
346 # rspec_node['slivers'] = [sliver]
348 # # slivers always provide the ssh service
349 # login = Login({'authentication': 'ssh-keys', \
350 # 'hostname': node['hostname'], 'port':'22', \
351 # 'username': sliver['name']})
352 # service = Services({'login': login})
353 # rspec_node['services'] = [service]
358 def rspec_node_to_geni_sliver(self, rspec_node, sliver_allocations = {}):
359 if rspec_node['sliver_id'] in sliver_allocations:
360 # set sliver allocation and operational status
361 sliver_allocation = sliver_allocations[rspec_node['sliver_id']]
362 if sliver_allocation:
363 allocation_status = sliver_allocation.allocation_state
364 if allocation_status == 'geni_allocated':
365 op_status = 'geni_pending_allocation'
366 elif allocation_status == 'geni_provisioned':
367 op_status = 'geni_ready'
369 op_status = 'geni_unknown'
371 allocation_status = 'geni_unallocated'
373 allocation_status = 'geni_unallocated'
374 op_status = 'geni_failed'
376 geni_sliver = {'geni_sliver_urn': rspec_node['sliver_id'],
377 'geni_expires': rspec_node['expires'],
378 'geni_allocation_status' : allocation_status,
379 'geni_operational_status': op_status,
385 def sliver_to_rspec_node(self, sliver, sliver_allocations):
386 rspec_node = self.node_to_rspec_node(sliver)
387 rspec_node['expires'] = datetime_to_string(utcparse(sliver['expires']))
389 logger.debug("IOTLABAGGREGATE api \t sliver_to_rspec_node sliverr %s \r\nsliver_allocations %s"
390 % (sliver, sliver_allocations))
391 rspec_sliver = Sliver({'sliver_id': sliver['urn'],
392 'name': sliver['slice_id'],
393 'type': 'iotlab-exclusive',
395 rspec_node['sliver_id'] = rspec_sliver['sliver_id']
396 if sliver['urn'] in sliver_allocations:
397 rspec_node['client_id'] = sliver_allocations[sliver['urn']].client_id
398 if sliver_allocations[sliver['urn']].component_id:
399 rspec_node['component_id'] = sliver_allocations[sliver['urn']].component_id
400 rspec_node['slivers'] = [rspec_sliver]
402 # slivers always provide the ssh service
403 login = Login({'authentication': 'ssh-keys',
404 'hostname': sliver['hostname'],
406 'username': sliver['slice_name'],
407 'login': sliver['slice_name']
412 def get_all_leases(self, ldap_username):
415 Get list of lease dictionaries which all have the mandatory keys
416 ('lease_id', 'hostname', 'site_id', 'name', 'start_time', 'duration').
417 All the leases running or scheduled are returned.
419 :param ldap_username: if ldap uid is not None, looks for the leases
420 belonging to this user.
421 :type ldap_username: string
422 :returns: rspec lease dictionary with keys lease_id, component_id,
423 slice_id, start_time, duration.
426 .. note::There is no filtering of leases within a given time frame.
427 All the running or scheduled leases are returned. options
428 removed SA 15/05/2013
433 #now = int(time.time())
434 #lease_filter = {'clip': now }
437 #lease_filter.update({'name': slice_record['name']})
439 #leases = self.driver.testbed_shell.GetLeases(lease_filter)
441 logger.debug("IOTLABAGGREGATE get_all_leases ldap_username %s "
443 leases = self.driver.testbed_shell.GetLeases(login=ldap_username)
444 grain = self.driver.testbed_shell.GetLeaseGranularity()
448 #as many leases as there are nodes in the job
449 for node in lease['reserved_nodes']:
450 rspec_lease = Lease()
451 rspec_lease['lease_id'] = lease['lease_id']
452 #site = node['site_id']
453 iotlab_xrn = xrn_object(self.driver.testbed_shell.root_auth,
455 rspec_lease['component_id'] = iotlab_xrn.urn
456 #rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn,\
457 #site, node['hostname'])
459 rspec_lease['slice_id'] = lease['slice_id']
461 #No info on the slice used in testbed_xp table
463 rspec_lease['start_time'] = lease['t_from']
464 rspec_lease['duration'] = (lease['t_until'] - lease['t_from']) \
466 rspec_leases.append(rspec_lease)
469 def get_rspec(self, slice_xrn=None, login=None, version=None,
473 - a full advertisement rspec with the testbed resources if slice_xrn is
474 not specified.If a lease option is given, also returns the leases
475 scheduled on the testbed.
476 - a manifest Rspec with the leases and nodes in slice's leases if
477 slice_xrn is not None.
479 :param slice_xrn: srn of the slice
480 :type slice_xrn: string
481 :param login: user'uid (ldap login) on iotlab
483 :param version: can be set to sfa or iotlab
484 :type version: RSpecVersion
485 :param options: used to specify if the leases should also be included in
497 version_manager = VersionManager()
498 version = version_manager.get_version(version)
499 logger.debug("IotlabAggregate \t get_rspec ***version %s \
500 version.type %s version.version %s options %s \r\n"
501 % (version, version.type, version.version, options))
503 if slice_xrn is None:
504 rspec_version = version_manager._get_version(version.type,
505 version.version, 'ad')
508 rspec_version = version_manager._get_version(
509 version.type, version.version, 'manifest')
511 slices, slivers = self.get_slice_and_slivers(slice_xrn, login)
512 if slice_xrn and slices is not None:
513 #Get user associated with this slice
514 #for one_slice in slices :
515 ldap_username = self.find_ldap_username_from_slice(slices[0])
516 # ldap_username = slices[0]['reg_researchers'][0].__dict__['hrn']
517 # # ldap_username = slices[0]['user']
518 # tmp = ldap_username.split('.')
519 # ldap_username = tmp[1]
520 logger.debug("IotlabAggregate \tget_rspec **** \
521 LDAP USERNAME %s \r\n" \
523 #at this point sliver may be empty if no iotlab job
524 #is running for this user/slice.
525 rspec = RSpec(version=rspec_version, user_options=options)
527 logger.debug("\r\n \r\n IotlabAggregate \tget_rspec *** \
528 slice_xrn %s slices %s\r\n \r\n"
529 % (slice_xrn, slices))
531 if options is not None:
532 lease_option = options['list_leases']
534 #If no options are specified, at least print the resources
537 #lease_option = 'all'
539 if lease_option in ['all', 'resources']:
540 #if not options.get('list_leases') or options.get('list_leases')
541 #and options['list_leases'] != 'leases':
542 nodes = self.get_nodes(slices, slivers)
544 logger.debug("IotlabAggregate \t lease_option %s \
545 get rspec ******* nodes %s"
546 % (lease_option, nodes))
548 sites_set = set([node['location']['site'] for node in nodes])
550 #In case creating a job, slice_xrn is not set to None
551 rspec.version.add_nodes(nodes)
552 if slice_xrn and slices is not None:
553 # #Get user associated with this slice
554 # #for one_slice in slices :
555 # ldap_username = slices[0]['reg_researchers']
556 # # ldap_username = slices[0]['user']
557 # tmp = ldap_username.split('.')
558 # ldap_username = tmp[1]
559 # # ldap_username = tmp[1].split('_')[0]
561 logger.debug("IotlabAggregate \tget_rspec **** \
562 version type %s ldap_ user %s \r\n" \
563 % (version.type, ldap_username))
564 if version.type == "Iotlab":
565 rspec.version.add_connection_information(
566 ldap_username, sites_set)
568 default_sliver = slivers.get('default_sliver', [])
569 if default_sliver and len(nodes) is not 0:
570 #default_sliver_attribs = default_sliver.get('tags', [])
571 logger.debug("IotlabAggregate \tget_rspec **** \
572 default_sliver%s \r\n" % (default_sliver))
573 for attrib in default_sliver:
574 rspec.version.add_default_sliver_attribute(
575 attrib, default_sliver[attrib])
577 if lease_option in ['all','leases']:
578 leases = self.get_all_leases(ldap_username)
579 rspec.version.add_leases(leases)
580 logger.debug("IotlabAggregate \tget_rspec **** \
581 FINAL RSPEC %s \r\n" % (rspec.toxml()))
584 def get_slivers(self, urns, options={}):
593 xrn = IotlabXrn(xrn=urn)
594 if xrn.type == 'sliver':
595 # id: slice_id-node_id
597 sliver_id_parts = xrn.get_sliver_id_parts()
598 slice_id = int(sliver_id_parts[0])
599 node_id = int(sliver_id_parts[1])
600 slice_ids.add(slice_id)
601 node_ids.append(node_id)
606 slice_names.add(xrn.hrn)
609 logger.debug("IotlabAggregate \t get_slivers urns %s slice_ids %s \
610 node_ids %s\r\n" % (urns, slice_ids, node_ids))
611 logger.debug("IotlabAggregate \t get_slivers xrn %s slice_names %s \
612 \r\n" % (xrn, slice_names))
615 filter['slice_hrn'] = list(slice_names)
616 slice_hrn = filter['slice_hrn'][0]
618 slice_filter_type = 'slice_hrn'
619 logger.debug("IotlabAggregate \t get_slivers slice_hrn%s \
620 \r\n" % (slice_hrn ))
622 # filter['slice_id'] = list(slice_ids)
625 slices = self.driver.testbed_shell.GetSlices(slice_hrn,
627 leases = self.driver.testbed_shell.GetLeases(
628 {'slice_hrn':slice_hrn})
629 logger.debug("IotlabAggregate \t get_slivers \
630 slices %s leases %s\r\n" % (slices, leases ))
634 # slice['hrn'] = DummyXrn(auth=self.driver.hrn, slicename=slice['slice_name']).hrn
635 single_slice = slices[0]
639 # for slice in slices:
640 # user_ids.extend(slice['user_ids'])
642 # users = self.driver.shell.GetUsers({'user_ids': user_ids})
644 user = single_slice['reg_researchers'][0].__dict__
645 logger.debug("IotlabAggregate \t get_slivers user %s \
648 # construct user key info
651 person = self.driver.testbed_shell.ldap.LdapFindUser(record=user)
652 logger.debug("IotlabAggregate \t get_slivers person %s \
654 name = person['last_name']
655 user['login'] = person['uid']
656 user['user_urn'] = hrn_to_urn(user['hrn'], 'user')
657 user['keys'] = person['pkey']
658 # name = user['email'][0:user['email'].index('@')]
660 # 'login': slice['slice_name'],
661 # 'user_urn': Xrn('%s.%s' % (self.driver.hrn, name), type='user').urn,
662 # 'keys': user['keys']
664 # users_list.append(user)
667 node_ids = single_slice['node_ids']
668 node_list = self.driver.testbed_shell.GetNodes(
669 {'hostname':single_slice['node_ids']})
670 node_by_hostname = dict([(node['hostname'], node) for node in node_list])
672 logger.warning("\t get_slivers No slivers in slice")
673 # slice['node_ids'] = node_ids
674 # nodes_dict = self.get_slice_nodes(slice, options)
675 logger.debug("IotlabAggregate \t get_slivers node_by_hostname%s \
676 \r\n" % (node_by_hostname))
678 for current_lease in leases:
679 for hostname in current_lease['reserved_nodes']:
681 node['slice_id'] = current_lease['slice_id']
682 node['slice_hrn'] = current_lease['slice_hrn']
683 slice_name = current_lease['slice_hrn'].split(".")[1]
684 node['slice_name'] = slice_name
685 index = current_lease['reserved_nodes'].index(hostname)
686 node_id = current_lease['resource_ids'][index]
687 # node['slice_name'] = user['login']
688 # node.update(single_slice)
689 more_info = node_by_hostname[hostname]
690 node.update(more_info)
691 # oar_job_id is the slice_id (lease_id)
692 sliver_hrn = '%s.%s-%s' % (self.driver.hrn,
693 current_lease['lease_id'], node_id)
694 node['node_id'] = node_id
695 node['expires'] = current_lease['t_until']
696 node['sliver_id'] = Xrn(sliver_hrn, type='sliver').urn
697 node['urn'] = node['sliver_id']
698 node['services_user'] = [user]
699 logger.debug("IotlabAggregate \t get_slivers node %s current_lease %s\
700 \r\n more_info %s" % (node, current_lease, more_info))
704 def list_resources(self, version = None, options={}):
706 version_manager = VersionManager()
707 version = version_manager.get_version(version)
708 rspec_version = version_manager._get_version(version.type, version.version, 'ad')
709 rspec = RSpec(version=rspec_version, user_options=options)
710 # variable ldap_username to be compliant with the get_all_leases
711 # prototype. Now unused in geni-v3 since we are getting all the leases
714 if not options.get('list_leases') or options['list_leases'] != 'leases':
716 nodes_dict = self.get_nodes(options)
722 # site_ids.append(node['site_id'])
723 # interface_ids.extend(node['interface_ids'])
724 # tag_ids.extend(node['node_tag_ids'])
725 # nodes_dict[node['node_id']] = node
726 # sites = self.get_sites({'site_id': site_ids})
727 # interfaces = self.get_interfaces({'interface_id':interface_ids})
728 # node_tags = self.get_node_tags({'node_tag_id': tag_ids})
729 # pl_initscripts = self.get_pl_initscripts()
730 # convert nodes to rspec nodes
732 for node_id in nodes_dict:
733 node = nodes_dict[node_id]
734 # rspec_node = self.node_to_rspec_node(node, sites, interfaces, node_tags, pl_initscripts)
735 rspec_node = self.node_to_rspec_node(node)
736 rspec_nodes.append(rspec_node)
737 rspec.version.add_nodes(rspec_nodes)
740 # links = self.get_links(sites, nodes_dict, interfaces)
741 # rspec.version.add_links(links)
743 if not options.get('list_leases') or options.get('list_leases') \
744 and options['list_leases'] != 'resources':
745 leases = self.get_all_leases(ldap_username)
746 rspec.version.add_leases(leases)
751 def describe(self, urns, version=None, options={}):
753 Retrieve a manifest RSpec describing the resources contained by the
754 named entities, e.g. a single slice or a set of the slivers in a slice.
755 This listing and description should be sufficiently descriptive to allow
756 experimenters to use the resources.
758 returns: On success returns the following struct:
760 geni_rspec: <geni.rspec, a Manifest RSpec>
761 geni_urn: <string slice urn of the containing slice>
763 geni_sliver_urn: <string sliver urn>
764 geni_expires: <dateTime.rfc3339
765 allocation expiration string, as in geni_expires
767 geni_allocation_status: <string sliver state -
768 e.g. geni_allocated or geni_provisioned >,
769 geni_operational_status: <string sliver operational
771 geni_error: <optional string. The field may be omitted
772 entirely but may not be null/None, explaining any
773 failure for a sliver.>
776 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#Describe
778 version_manager = VersionManager()
779 version = version_manager.get_version(version)
780 rspec_version = version_manager._get_version(
781 version.type, version.version, 'manifest')
782 rspec = RSpec(version=rspec_version, user_options=options)
786 slivers = self.get_slivers(urns, options)
788 rspec_expires = datetime_to_string(utcparse(slivers[0]['expires']))
790 rspec_expires = datetime_to_string(utcparse(time.time()))
791 rspec.xml.set('expires', rspec_expires)
793 # lookup the sliver allocations
795 sliver_ids = [sliver['sliver_id'] for sliver in slivers]
796 logger.debug(" IOTLAB_API.PY \tDescribe sliver_ids %s "
798 constraint = SliverAllocation.sliver_id.in_(sliver_ids)
799 logger.debug(" IOTLAB_API.PY \tDescribe constraint %s "
801 sliver_allocations = self.driver.api.dbsession().query(SliverAllocation).filter((constraint)).all()
802 logger.debug(" IOTLAB_API.PY \tDescribe sliver_allocations %s "
803 % (sliver_allocations))
804 sliver_allocation_dict = {}
805 for sliver_allocation in sliver_allocations:
806 geni_urn = sliver_allocation.slice_urn
807 sliver_allocation_dict[sliver_allocation.sliver_id] = sliver_allocation
811 for sliver in slivers:
812 nodes_dict[sliver['node_id']] = sliver
814 for sliver in slivers:
815 rspec_node = self.sliver_to_rspec_node(sliver, sliver_allocation_dict)
816 rspec_nodes.append(rspec_node)
817 logger.debug(" IOTLAB_API.PY \tDescribe sliver_allocation_dict %s "
818 % (sliver_allocation_dict))
819 geni_sliver = self.rspec_node_to_geni_sliver(rspec_node, sliver_allocation_dict)
820 geni_slivers.append(geni_sliver)
822 logger.debug(" IOTLAB_API.PY \tDescribe rspec_nodes %s\
824 % (rspec_nodes, rspec))
825 rspec.version.add_nodes(rspec_nodes)
827 return {'geni_urn': geni_urn,
828 'geni_rspec': rspec.toxml(),
829 'geni_slivers': geni_slivers}