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 = None):
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 sliver_allocations is None: sliver_allocations={}
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_leases(self, slice=None, options=None):
405 if options is None: options={}
408 #filter.update({'name':slice['slice_name']}) # JORDAN: this is = "upmc" !!!
409 filter.update({'slice_hrn':slice['slice_hrn']}) # JORDAN: this is = "upmc" !!!
410 # slice_hrn = "ple.upmc.myslicedemo
411 #return_fields = ['lease_id', 'hostname', 'site_id', 'name', 't_from', 't_until']
412 leases = self.driver.GetLeases(lease_filter_dict=filter)
413 grain = self.driver.testbed_shell.GetLeaseGranularity()
417 #as many leases as there are nodes in the job
418 for node in lease['reserved_nodes']:
419 rspec_lease = Lease()
420 rspec_lease['lease_id'] = lease['lease_id']
421 #site = node['site_id']
422 iotlab_xrn = xrn_object(self.driver.testbed_shell.root_auth,
424 rspec_lease['component_id'] = iotlab_xrn.urn
425 #rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn,\
426 #site, node['hostname'])
428 rspec_lease['slice_id'] = lease['slice_id']
430 #No info on the slice used in testbed_xp table
432 rspec_lease['start_time'] = lease['t_from']
433 rspec_lease['duration'] = (lease['t_until'] - lease['t_from']) \
435 rspec_leases.append(rspec_lease)
439 def get_all_leases(self, ldap_username):
441 Get list of lease dictionaries which all have the mandatory keys
442 ('lease_id', 'hostname', 'site_id', 'name', 'start_time', 'duration').
443 All the leases running or scheduled are returned.
445 :param ldap_username: if ldap uid is not None, looks for the leases
446 belonging to this user.
447 :type ldap_username: string
448 :returns: rspec lease dictionary with keys lease_id, component_id,
449 slice_id, start_time, duration where the lease_id is the oar job id,
450 component_id is the node's urn, slice_id is the slice urn,
451 start_time is the timestamp starting time and duration is expressed
452 in terms of the testbed's granularity.
455 .. note::There is no filtering of leases within a given time frame.
456 All the running or scheduled leases are returned. options
457 removed SA 15/05/2013
462 logger.debug("IOTLABAGGREGATE get_all_leases ldap_username %s "
464 leases = self.driver.GetLeases(login=ldap_username)
465 grain = self.driver.testbed_shell.GetLeaseGranularity()
469 #as many leases as there are nodes in the job
470 for node in lease['reserved_nodes']:
471 rspec_lease = Lease()
472 rspec_lease['lease_id'] = lease['lease_id']
473 #site = node['site_id']
474 iotlab_xrn = xrn_object(self.driver.testbed_shell.root_auth,
476 rspec_lease['component_id'] = iotlab_xrn.urn
477 #rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn,\
478 #site, node['hostname'])
480 rspec_lease['slice_id'] = lease['slice_id']
482 #No info on the slice used in testbed_xp table
484 rspec_lease['start_time'] = lease['t_from']
485 rspec_lease['duration'] = (lease['t_until'] - lease['t_from']) \
487 rspec_leases.append(rspec_lease)
490 def get_rspec(self, slice_xrn=None, login=None, version=None,
494 - a full advertisement rspec with the testbed resources if slice_xrn is
495 not specified.If a lease option is given, also returns the leases
496 scheduled on the testbed.
497 - a manifest Rspec with the leases and nodes in slice's leases if
498 slice_xrn is not None.
500 :param slice_xrn: srn of the slice
501 :type slice_xrn: string
502 :param login: user'uid (ldap login) on iotlab
504 :param version: can be set to sfa or iotlab
505 :type version: RSpecVersion
506 :param options: used to specify if the leases should also be included in
518 version_manager = VersionManager()
519 version = version_manager.get_version(version)
520 logger.debug("IotlabAggregate \t get_rspec ***version %s \
521 version.type %s version.version %s options %s \r\n"
522 % (version, version.type, version.version, options))
524 if slice_xrn is None:
525 rspec_version = version_manager._get_version(version.type,
526 version.version, 'ad')
529 rspec_version = version_manager._get_version(
530 version.type, version.version, 'manifest')
532 slices, slivers = self.get_slice_and_slivers(slice_xrn, login)
533 if slice_xrn and slices is not None:
534 #Get user associated with this slice
535 #for one_slice in slices :
536 ldap_username = self.find_ldap_username_from_slice(slices[0])
537 # ldap_username = slices[0]['reg_researchers'][0].__dict__['hrn']
538 # # ldap_username = slices[0]['user']
539 # tmp = ldap_username.split('.')
540 # ldap_username = tmp[1]
541 logger.debug("IotlabAggregate \tget_rspec **** \
542 LDAP USERNAME %s \r\n" \
544 #at this point sliver may be empty if no iotlab job
545 #is running for this user/slice.
546 rspec = RSpec(version=rspec_version, user_options=options)
548 logger.debug("\r\n \r\n IotlabAggregate \tget_rspec *** \
549 slice_xrn %s slices %s\r\n \r\n"
550 % (slice_xrn, slices))
552 if options is not None:
553 lease_option = options['list_leases']
555 #If no options are specified, at least print the resources
558 #lease_option = 'all'
560 if lease_option in ['all', 'resources']:
561 #if not options.get('list_leases') or options.get('list_leases')
562 #and options['list_leases'] != 'leases':
563 nodes = self.get_nodes()
565 logger.debug("IotlabAggregate \t lease_option %s \
566 get rspec ******* nodes %s"
567 % (lease_option, nodes))
569 sites_set = set([node['location']['site'] for node in nodes])
571 #In case creating a job, slice_xrn is not set to None
572 rspec.version.add_nodes(nodes)
573 if slice_xrn and slices is not None:
574 # #Get user associated with this slice
575 # #for one_slice in slices :
576 # ldap_username = slices[0]['reg_researchers']
577 # # ldap_username = slices[0]['user']
578 # tmp = ldap_username.split('.')
579 # ldap_username = tmp[1]
580 # # ldap_username = tmp[1].split('_')[0]
582 logger.debug("IotlabAggregate \tget_rspec **** \
583 version type %s ldap_ user %s \r\n" \
584 % (version.type, ldap_username))
585 if version.type == "Iotlab":
586 rspec.version.add_connection_information(
587 ldap_username, sites_set)
589 default_sliver = slivers.get('default_sliver', [])
590 if default_sliver and len(nodes) is not 0:
591 #default_sliver_attribs = default_sliver.get('tags', [])
592 logger.debug("IotlabAggregate \tget_rspec **** \
593 default_sliver%s \r\n" % (default_sliver))
594 for attrib in default_sliver:
595 rspec.version.add_default_sliver_attribute(
596 attrib, default_sliver[attrib])
598 if lease_option in ['all','leases']:
599 leases = self.get_all_leases(ldap_username)
600 rspec.version.add_leases(leases)
601 logger.debug("IotlabAggregate \tget_rspec **** \
602 FINAL RSPEC %s \r\n" % (rspec.toxml()))
605 def get_slivers(self, urns, options=None):
606 """Get slivers of the given slice urns. Slivers contains slice, node and
609 For Iotlab, returns the leases with sliver ids and their allocation
612 :param urns: list of slice urns.
613 :type urns: list of strings
614 :param options: unused
615 :type options: unused
617 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#urns
620 SLICE_KEY = 'slice_hrn' # slice_hrn
621 if options is None: options={}
625 xrn = IotlabXrn(xrn=urn)
626 if xrn.type == 'sliver':
627 # id: slice_id-node_id
629 sliver_id_parts = xrn.get_sliver_id_parts()
630 slice_id = int(sliver_id_parts[0])
631 node_id = int(sliver_id_parts[1])
632 slice_ids.add(slice_id)
633 node_ids.append(node_id)
638 slice_names.add(xrn.hrn)
641 logger.debug("IotlabAggregate \t get_slivers urns %s slice_ids %s \
642 node_ids %s\r\n" % (urns, slice_ids, node_ids))
643 logger.debug("IotlabAggregate \t get_slivers xrn %s slice_names %s \
644 \r\n" % (xrn, slice_names))
647 filter_sliver[SLICE_KEY] = list(slice_names)
648 slice_hrn = filter_sliver[SLICE_KEY][0]
650 slice_filter_type = SLICE_KEY
653 # filter['slice_id'] = list(slice_ids)
656 logger.debug("JORDAN SLICE_HRN=%r" % slice_hrn)
657 slices = self.driver.GetSlices(slice_hrn,
659 leases = self.driver.GetLeases({SLICE_KEY:slice_hrn})
660 logger.debug("IotlabAggregate \t get_slivers \
661 slices %s leases %s\r\n" % (slices, leases ))
665 logger.debug("LOIC SLICES = %r" % slices)
666 single_slice = slices[0]
669 # XXX LOIC !!! XXX QUICK AND DIRTY - Let's try...
670 logger.debug("LOIC Number of reg_researchers = %s" % len(single_slice['reg_researchers']))
671 if 'reg_researchers' in single_slice and len(single_slice['reg_researchers'])==0:
672 user = {'uid':single_slice['user']}
674 user = single_slice['reg_researchers'][0].__dict__
675 logger.debug("IotlabAggregate \t get_slivers user %s \
678 # construct user key info
679 person = self.driver.testbed_shell.ldap.LdapFindUser(record=user)
680 logger.debug("IotlabAggregate \t get_slivers person %s \
682 # name = person['last_name']
683 user['login'] = person['uid']
685 # XXX LOIC !!! if we have more info, let's fill user
687 user['user_urn'] = hrn_to_urn(user['hrn'], 'user')
689 user['keys'] = person['pkey']
693 node_ids = single_slice['node_ids']
694 node_list = self.driver.testbed_shell.GetNodes()
695 # JORDAN REMOVED FILTER so that next check always succeed
696 # {'hostname':single_slice['node_ids']})
697 node_by_hostname = dict([(node['hostname'], node)
698 for node in node_list])
700 logger.warning("\t get_slivers No slivers in slice")
701 # slice['node_ids'] = node_ids
702 # nodes_dict = self.get_slice_nodes(slice, options)
705 for current_lease in leases:
706 for hostname in current_lease['reserved_nodes']:
708 node['slice_id'] = current_lease['slice_id']
709 node['slice_hrn'] = current_lease['slice_hrn']
710 slice_name = current_lease['slice_hrn'].split(".")[1]
711 node['slice_name'] = slice_name
712 index = current_lease['reserved_nodes'].index(hostname)
713 node_id = current_lease['resource_ids'][index]
714 # node['slice_name'] = user['login']
715 # node.update(single_slice)
716 # JORDAN XXX This fails sometimes when hostname not in the list
717 #if hostname in node_by_hostname:
718 more_info = node_by_hostname[hostname]
719 node.update(more_info)
721 # # This can happen when specifying a lease without the resource, then all subsequent calls will fail
722 # logger.debug("Ignored missing hostname for now one")
723 # oar_job_id is the slice_id (lease_id)
724 sliver_hrn = '%s.%s-%s' % (self.driver.hrn,
725 current_lease['lease_id'], node_id)
726 node['node_id'] = node_id
727 node['expires'] = current_lease['t_until']
728 node['sliver_id'] = Xrn(sliver_hrn, type='sliver').urn
729 node['urn'] = node['sliver_id']
730 node['services_user'] = [user]
735 def list_resources(self, version = None, options=None):
737 Returns an advertisement Rspec of available resources at this
738 aggregate. This Rspec contains a resource listing along with their
739 description, providing sufficient information for clients to be able to
740 select among available resources.
742 :param options: various options. The valid options are: {boolean
743 geni_compressed <optional>; struct geni_rspec_version { string type;
744 #case insensitive , string version; # case insensitive}} . The only
745 mandatory options if options is specified is geni_rspec_version.
746 :type options: dictionary
748 :returns: On success, the value field of the return struct will contain
749 a geni.rspec advertisment RSpec
750 :rtype: Rspec advertisement in xml.
752 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#RSpecdatatype
753 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#ListResources
756 if options is None: options={}
757 version_manager = VersionManager()
758 version = version_manager.get_version(version)
759 rspec_version = version_manager._get_version(version.type,
760 version.version, 'ad')
761 rspec = RSpec(version=rspec_version, user_options=options)
762 # variable ldap_username to be compliant with get_all_leases
763 # prototype. Now unused in geni-v3 since we are getting all the leases
766 if not options.get('list_leases') or options['list_leases'] != 'leases':
768 nodes_dict = self.get_nodes(options)
770 # no interfaces on iotlab nodes
771 # convert nodes to rspec nodes
773 for node_id in nodes_dict:
774 node = nodes_dict[node_id]
775 rspec_node = self.node_to_rspec_node(node)
776 rspec_nodes.append(rspec_node)
777 rspec.version.add_nodes(rspec_nodes)
780 # links = self.get_links(sites, nodes_dict, interfaces)
781 # rspec.version.add_links(links)
783 if not options.get('list_leases') or options.get('list_leases') \
784 and options['list_leases'] != 'resources':
785 leases = self.get_all_leases(ldap_username)
786 rspec.version.add_leases(leases)
791 def describe(self, urns, version=None, options=None):
793 Retrieve a manifest RSpec describing the resources contained by the
794 named entities, e.g. a single slice or a set of the slivers in a slice.
795 This listing and description should be sufficiently descriptive to allow
796 experimenters to use the resources.
798 :param urns: If a slice urn is supplied and there are no slivers in the
799 given slice at this aggregate, then geni_rspec shall be a valid
800 manifest RSpec, containing no node elements - no resources.
801 :type urns: list or strings
802 :param options: various options. the valid options are: {boolean
803 geni_compressed <optional>; struct geni_rspec_version { string type;
804 #case insensitive , string version; # case insensitive}}
805 :type options: dictionary
807 :returns: On success returns the following dictionary {geni_rspec:
808 <geni.rspec, a Manifest RSpec>, geni_urn: <string slice urn of the
809 containing slice>, geni_slivers:{ geni_sliver_urn:
810 <string sliver urn>, geni_expires: <dateTime.rfc3339 allocation
811 expiration string, as in geni_expires from SliversStatus>,
812 geni_allocation_status: <string sliver state - e.g. geni_allocated
813 or geni_provisioned >, geni_operational_status:
814 <string sliver operational state>, geni_error: <optional string.
815 The field may be omitted entirely but may not be null/None,
816 explaining any failure for a sliver.>}
818 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3#Describe
819 .. seealso:: http://groups.geni.net/geni/wiki/GAPI_AM_API_V3/CommonConcepts#urns
821 if options is None: options={}
822 version_manager = VersionManager()
823 version = version_manager.get_version(version)
824 rspec_version = version_manager._get_version(
825 version.type, version.version, 'manifest')
826 rspec = RSpec(version=rspec_version, user_options=options)
830 slivers = self.get_slivers(urns, options)
831 logger.debug("SLIVERS=%r" % slivers)
833 rspec_expires = datetime_to_string(utcparse(slivers[0]['expires']))
835 rspec_expires = datetime_to_string(utcparse(time.time()))
836 rspec.xml.set('expires', rspec_expires)
838 # lookup the sliver allocations
840 sliver_ids = [sliver['sliver_id'] for sliver in slivers]
841 constraint = SliverAllocation.sliver_id.in_(sliver_ids)
842 query = self.driver.api.dbsession().query(SliverAllocation)
843 sliver_allocations = query.filter((constraint)).all()
844 sliver_allocation_dict = {}
845 for sliver_allocation in sliver_allocations:
846 geni_urn = sliver_allocation.slice_urn
847 sliver_allocation_dict[sliver_allocation.sliver_id] = \
849 show_leases = options.get('list_leases')
850 if show_leases in ['resources', 'all']:
851 #if not options.get('list_leases') or options['list_leases'] != 'leases':
854 for sliver in slivers:
855 nodes_dict[sliver['node_id']] = sliver
857 for sliver in slivers:
858 rspec_node = self.sliver_to_rspec_node(sliver,
859 sliver_allocation_dict)
860 rspec_nodes.append(rspec_node)
861 geni_sliver = self.rspec_node_to_geni_sliver(rspec_node,
862 sliver_allocation_dict)
863 geni_slivers.append(geni_sliver)
864 rspec.version.add_nodes(rspec_nodes)
866 logger.debug("SHOW LEASES = %r" % show_leases)
867 if show_leases in ['leases', 'all']:
868 #if not options.get('list_leases') or options['list_leases'] == 'resources':
870 leases = self.get_leases(slice=slivers[0])
871 logger.debug("JORDAN: getting leases from slice: %r" % slivers[0])
872 rspec.version.add_leases(leases)
874 return {'geni_urn': geni_urn,
875 'geni_rspec': rspec.toxml(),
876 'geni_slivers': geni_slivers}