2 """ aggregate class management """
4 from sfa.util.xrn import Xrn, hrn_to_urn
5 from sfa.util.sfatime import utcparse, datetime_to_string
6 from sfa.util.sfalogging import logger
7 from sfa.rspecs.rspec import RSpec
8 from sfa.rspecs.elements.hardware_type import HardwareType
9 from sfa.rspecs.elements.lease import Lease
10 from sfa.rspecs.elements.granularity import Granularity
11 from sfa.rspecs.version_manager import VersionManager
12 from sfa.rspecs.elements.versions.iotlabv1Node import IotlabPosition
13 from sfa.rspecs.elements.versions.iotlabv1Node import IotlabNode
14 from sfa.rspecs.elements.versions.iotlabv1Node import IotlabLocation
15 from sfa.iotlab.iotlablease import LeaseTable
19 class IotLABAggregate(object):
21 SFA aggregate for Iot-LAB testbed
24 def __init__(self, driver):
28 def leases_to_rspec_leases(self, leases):
29 """ Get leases attributes list"""
32 for node in lease['resources']:
34 rspec_lease['lease_id'] = lease['id']
35 iotlab_xrn = Xrn('.'.join([self.driver.root_auth,
38 rspec_lease['component_id'] = iotlab_xrn.urn
39 rspec_lease['start_time'] = str(lease['date'])
40 duration = int(lease['duration'])/60 # duration in minutes
41 rspec_lease['duration'] = duration
42 rspec_lease['slice_id'] = lease['slice_id']
43 rspec_leases.append(rspec_lease)
47 def node_to_rspec_node(self, node):
48 """ Get node attributes """
49 rspec_node = IotlabNode()
50 rspec_node['mobile'] = node['mobile']
51 rspec_node['archi'] = node['archi']
52 rspec_node['radio'] = (node['archi'].split(':'))[1]
53 iotlab_xrn = Xrn('.'.join([self.driver.root_auth,
54 Xrn.escape(node['network_address'])]),
56 rspec_node['boot_state'] = 'true'
57 rspec_node['component_id'] = iotlab_xrn.urn
58 rspec_node['component_name'] = node['network_address']
59 rspec_node['component_manager_id'] = \
60 hrn_to_urn(self.driver.root_auth,
62 rspec_node['authority_id'] = rspec_node['component_manager_id']
63 rspec_node['exclusive'] = 'true'
64 rspec_node['hardware_types'] = [HardwareType({'name': \
66 location = IotlabLocation({'country':'France', 'site': \
68 rspec_node['location'] = location
69 position = IotlabPosition()
70 for field in position:
71 position[field] = node[field]
72 granularity = Granularity({'grain': 30})
73 rspec_node['granularity'] = granularity
74 rspec_node['tags'] = []
78 def sliver_to_rspec_node(self, sliver):
79 """ Get node and sliver attributes """
80 rspec_node = self.node_to_rspec_node(sliver)
81 rspec_node['expires'] = datetime_to_string(utcparse(sliver['expires']))
82 rspec_node['sliver_id'] = sliver['sliver_id']
87 def rspec_node_to_geni_sliver(cls, rspec_node):
88 """ Get sliver status """
89 geni_sliver = {'geni_sliver_urn': rspec_node['sliver_id'],
90 'geni_expires': rspec_node['expires'],
91 'geni_allocation_status' : 'geni_allocated',
92 'geni_operational_status': 'geni_pending_allocation',
98 def list_resources(self, version=None, options=None):
100 list_resources method sends a RSpec with all Iot-LAB testbed nodes
101 and leases (OAR job submission). For leases we get all OAR jobs with
102 state Waiting or Running. If we have an entry in SFA database
103 (lease table) with OAR job id this submission was launched by SFA
104 driver, otherwise it was launched by Iot-LAB Webportal or CLI-tools
109 <node component_manager_id="urn:publicid:IDN+iotlab+authority+sa"
111 "urn:publicid:IDN+iotlab+node+m3-10.devgrenoble.iot-lab.info"
112 exclusive="true" component_name="m3-10.devgrenoble.iot-lab.info">
113 <hardware_type name="iotlab-node"/>
114 <location country="France"/>
115 <granularity grain="60"/>
119 <lease slice_id="urn:publicid:IDN+onelab:inria+slice+test_iotlab"
120 start_time="1427792400" duration="30">
122 "urn:publicid:IDN+iotlab+node+m3-10.grenoble.iot-lab.info"/>
127 # pylint:disable=R0914,W0212
128 logger.warning("iotlabaggregate list_resources")
129 logger.warning("iotlabaggregate list_resources options %s" % options)
133 version_manager = VersionManager()
134 version = version_manager.get_version(version)
135 rspec_version = version_manager._get_version(version.type,
138 rspec = RSpec(version=rspec_version, user_options=options)
140 nodes = self.driver.shell.get_nodes()
141 reserved_nodes = self.driver.shell.get_reserved_nodes()
142 if not 'error' in nodes and not 'error' in reserved_nodes:
143 # convert nodes to rspec nodes
146 rspec_node = self.node_to_rspec_node(nodes[node])
147 rspec_nodes.append(rspec_node)
148 rspec.version.add_nodes(rspec_nodes)
152 # find OAR jobs id for all slices in SFA database
153 for lease in self.driver.api.dbsession().query(LeaseTable).all():
154 db_leases[lease.job_id] = lease.slice_hrn
156 for lease_id in reserved_nodes:
157 # onelab slice = job submission from OneLAB
158 if lease_id in db_leases:
159 reserved_nodes[lease_id]['slice_id'] = \
160 hrn_to_urn(db_leases[lease_id],
162 # iotlab slice = job submission from Iot-LAB
164 reserved_nodes[lease_id]['slice_id'] = \
165 hrn_to_urn(self.driver.root_auth+'.'+
166 reserved_nodes[lease_id]['owner']+"_slice",
168 leases.append(reserved_nodes[lease_id])
170 rspec_leases = self.leases_to_rspec_leases(leases)
171 logger.warning("iotlabaggregate list_resources rspec_leases %s" %
173 rspec.version.add_leases(rspec_leases)
177 def get_slivers(self, urns, leases, nodes):
178 """ Get slivers attributes list """
179 logger.warning("iotlabaggregate get_slivers")
180 logger.warning("iotlabaggregate get_slivers urns %s" % urns)
183 for node in lease['resources']:
184 sliver_node = nodes[node]
185 sliver_hrn = '%s.%s-%s' % (self.driver.hrn,
186 lease['id'], node.split(".")[0])
187 start_time = datetime.datetime.fromtimestamp(lease['date'])
188 duration = datetime.timedelta(seconds=int(lease['duration']))
189 sliver_node['expires'] = start_time + duration
190 sliver_node['sliver_id'] = Xrn(sliver_hrn,
192 slivers.append(sliver_node)
196 def _delete_db_lease(self, job_id):
197 """ Delete lease table row in SFA database """
198 logger.warning("iotlabdriver _delete_db_lease lease job_id : %s"
200 self.driver.api.dbsession().query(LeaseTable).filter(
201 LeaseTable.job_id == job_id).delete()
202 self.driver.api.dbsession().commit()
205 def describe(self, urns, version=None, options=None):
207 describe method returns slice slivers (allocated resources) and leases
208 (OAR job submission). We search in lease table of SFA database all OAR
209 jobs id for this slice and match OAR jobs with state Waiting or Running.
210 If OAR job id doesn't exist the experiment is terminated and we delete
211 the database table entry. Otherwise we add slivers and leases in the
215 geni_slivers : a list of allocated slivers with information about
216 their allocation and operational state
217 geni_urn : the URN of the slice in which the sliver has been
219 geni_rspec: a RSpec describing the allocated slivers and leases
225 <node component_manager_id="urn:publicid:IDN+iotlab+authority+sa"
227 "urn:publicid:IDN+iotlab+node+m3-10.grenoble.iot-lab.info"
228 client_id="m3-10.grenoble.iot-lab.info"
229 sliver_id="urn:publicid:IDN+iotlab+sliver+9953-m3-10"
230 exclusive="true" component_name="m3-10.grenoble.iot-lab.info">
231 <hardware_type name="iotlab-node"/>
232 <location country="France"/>
233 <granularity grain="30"/>
234 <sliver_type name="iotlab-exclusive"/>
236 <lease slice_id="urn:publicid:IDN+onelab:inria+slice+test_iotlab"
237 start_time="1427792428" duration="29">
239 "urn:publicid:IDN+iotlab+node+m3-10.grenoble.iot-lab.info"/>
245 # pylint:disable=R0914,W0212
246 logger.warning("iotlabaggregate describe")
247 logger.warning("iotlabaggregate describe urns : %s" % urns)
250 version_manager = VersionManager()
251 version = version_manager.get_version(version)
252 rspec_version = version_manager._get_version(version.type,
255 rspec = RSpec(version=rspec_version, user_options=options)
259 nodes = self.driver.shell.get_nodes()
260 reserved_nodes = self.driver.shell.get_reserved_nodes()
261 if not 'error' in nodes and not 'error' in reserved_nodes:
262 # find OAR jobs id for one slice in SFA database
263 db_leases = [(lease.job_id, lease.slice_hrn)
264 for lease in self.driver.api.dbsession()
266 .filter(LeaseTable.slice_hrn == xrn.hrn).all()]
269 for job_id, slice_hrn in db_leases:
270 # OAR job terminated, we delete entry in database
271 if not job_id in reserved_nodes:
272 self._delete_db_lease(job_id)
274 # onelab slice = job submission from OneLAB
275 lease = reserved_nodes[job_id]
276 lease['slice_id'] = hrn_to_urn(slice_hrn, 'slice')
280 slivers = self.get_slivers(urns, leases, nodes)
282 date = utcparse(slivers[0]['expires'])
283 rspec_expires = datetime_to_string(date)
285 rspec_expires = datetime_to_string(utcparse(time.time()))
286 rspec.xml.set('expires', rspec_expires)
290 for sliver in slivers:
291 rspec_node = self.sliver_to_rspec_node(sliver)
292 rspec_nodes.append(rspec_node)
293 geni_sliver = self.rspec_node_to_geni_sliver(rspec_node)
294 geni_slivers.append(geni_sliver)
295 logger.warning("iotlabaggregate describe geni_slivers %s" %
297 rspec.version.add_nodes(rspec_nodes)
299 rspec_leases = self.leases_to_rspec_leases(leases)
300 logger.warning("iotlabaggregate describe rspec_leases %s" %
302 rspec.version.add_leases(rspec_leases)
304 return {'geni_urn': urns[0],
305 'geni_rspec': rspec.toxml(),
306 'geni_slivers': geni_slivers}