SA bug hunt
[sfa.git] / sfa / iotlab / iotlabaggregate.py
1 #import time
2 from sfa.util.xrn import hrn_to_urn, urn_to_hrn, get_authority
3
4 from sfa.rspecs.rspec import RSpec
5 #from sfa.rspecs.elements.location import Location
6 from sfa.rspecs.elements.hardware_type import HardwareType
7 from sfa.rspecs.elements.login import Login
8 from sfa.rspecs.elements.services import ServicesElement
9 from sfa.rspecs.elements.sliver import Sliver
10 from sfa.rspecs.elements.lease import Lease
11 from sfa.rspecs.elements.granularity import Granularity
12 from sfa.rspecs.version_manager import VersionManager
13
14
15 from sfa.rspecs.elements.versions.iotlabv1Node import IotlabPosition, IotlabNode, \
16                                                             IotlabLocation
17 from sfa.util.sfalogging import logger
18
19 from sfa.util.xrn import Xrn
20
21 def iotlab_xrn_to_hostname(xrn):
22     return Xrn.unescape(Xrn(xrn=xrn, type='node').get_leaf())
23
24 def iotlab_xrn_object(root_auth, hostname):
25     """Attributes are urn and hrn.
26 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
27     Get the hostname using iotlab_xrn_to_hostname on the urn.
28
29     :return: the iotlab node's xrn
30 =======
31     Get the hostname using slab_xrn_to_hostname on the urn.
32
33     :return: the senslab node's xrn
34 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
35     :rtype: Xrn
36     """
37     return Xrn('.'.join( [root_auth, Xrn.escape(hostname)]), type='node')
38
39 class IotlabAggregate:
40
41     sites = {}
42     nodes = {}
43     api = None
44     interfaces = {}
45     links = {}
46     node_tags = {}
47
48     prepared = False
49
50     user_options = {}
51
52     def __init__(self, driver):
53         self.driver = driver
54
55     def get_slice_and_slivers(self, slice_xrn, login=None):
56         """
57         Get the slices and the associated leases if any from the iotlab
58         testbed. For each slice, get the nodes in the  associated lease
59         and create a sliver with the necessary info and insertinto the sliver
60         dictionary, keyed on the node hostnames.
61         Returns a dict of slivers based on the sliver's node_id.
62         Called by get_rspec.
63
64
65         :param slice_xrn: xrn of the slice
66 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
67         :param login: user's login on iotlab ldap
68 =======
69         :param login: user's login on senslab ldap
70 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
71
72         :type slice_xrn: string
73         :type login: string
74         :reutnr : a list of slices dict and a dictionary of Sliver object
75         :rtype: (list, dict)
76
77 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
78         ..note: There is no slivers in iotlab, only leases.
79 =======
80         ..note: There is no slivers in senslab, only leases.
81 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
82
83         """
84         slivers = {}
85         sfa_slice = None
86         if slice_xrn is None:
87             return (sfa_slice, slivers)
88         slice_urn = hrn_to_urn(slice_xrn, 'slice')
89         slice_hrn, _ = urn_to_hrn(slice_xrn)
90         slice_name = slice_hrn
91
92         slices = self.driver.iotlab_api.GetSlices(slice_filter= str(slice_name), \
93                                             slice_filter_type = 'slice_hrn', \
94                                             login=login)
95
96         logger.debug("Slabaggregate api \tget_slice_and_slivers \
97                         sfa_slice %s \r\n slices %s self.driver.hrn %s" \
98                         %(sfa_slice, slices, self.driver.hrn))
99         if slices ==  []:
100             return (sfa_slice, slivers)
101
102
103         # sort slivers by node id , if there is a job
104         #and therefore, node allocated to this slice
105         for sfa_slice in slices:
106             try:
107                 node_ids_list =  sfa_slice['node_ids']
108             except KeyError:
109                 logger.log_exc("SLABAGGREGATE \t \
110                                         get_slice_and_slivers No nodes in the slice - KeyError ")
111                 continue
112
113             for node in node_ids_list:
114                 sliver_xrn = Xrn(slice_urn, type='sliver', id=node)
115                 sliver_xrn.set_authority(self.driver.hrn)
116                 sliver = Sliver({'sliver_id':sliver_xrn.urn,
117                                 'name': sfa_slice['hrn'],
118 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
119                                 'type': 'iotlab-node',
120 =======
121                                 'type': 'slab-node',
122 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
123                                 'tags': []})
124
125                 slivers[node] = sliver
126
127
128         #Add default sliver attribute :
129 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
130         #connection information for iotlab
131         if get_authority (sfa_slice['hrn']) == self.driver.iotlab_api.root_auth:
132 =======
133         #connection information for senslab
134         if get_authority (sfa_slice['hrn']) == self.driver.slab_api.root_auth:
135 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
136             tmp = sfa_slice['hrn'].split('.')
137             ldap_username = tmp[1].split('_')[0]
138             ssh_access = None
139             slivers['default_sliver'] =  {'ssh': ssh_access , \
140                                         'login': ldap_username}
141
142         #TODO get_slice_and_slivers Find the login of the external user
143
144         logger.debug("SLABAGGREGATE api get_slice_and_slivers  slivers %s "\
145                                                              %(slivers))
146         return (slices, slivers)
147
148
149
150     def get_nodes(self, slices=None, slivers=[], options=None):
151         # NT: the semantic of this function is not clear to me :
152         # if slice is not defined, then all the nodes should be returned
153         # if slice is defined, we should return only the nodes that
154         # are part of this slice
155         # but what is the role of the slivers parameter ?
156         # So i assume that slice['node_ids'] will be the same as slivers for us
157         #filter_dict = {}
158         #if slice_xrn:
159             #if not slices or not slices['node_ids']:
160                 #return ([],[])
161         #tags_filter = {}
162
163         # get the granularity in second for the reservation system
164 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
165         grain = self.driver.iotlab_api.GetLeaseGranularity()
166
167
168         nodes = self.driver.iotlab_api.GetNodes()
169 =======
170         grain = self.driver.slab_api.GetLeaseGranularity()
171
172
173         nodes = self.driver.slab_api.GetNodes()
174 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
175         #geni_available = options.get('geni_available')
176         #if geni_available:
177             #filter['boot_state'] = 'boot'
178
179         #filter.update({'peer_id': None})
180 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
181         #nodes = self.driver.iotlab_api.GetNodes(filter['hostname'])
182 =======
183         #nodes = self.driver.slab_api.GetNodes(filter['hostname'])
184 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
185
186         #site_ids = []
187         #interface_ids = []
188         #tag_ids = []
189         nodes_dict = {}
190
191         #for node in nodes:
192
193             #nodes_dict[node['node_id']] = node
194         #logger.debug("SLABAGGREGATE api get_nodes nodes  %s "\
195                                                              #%(nodes ))
196         # get sites
197         #sites_dict  = self.get_sites({'site_id': site_ids})
198         # get interfaces
199         #interfaces = self.get_interfaces({'interface_id':interface_ids})
200         # get tags
201         #node_tags = self.get_node_tags(tags_filter)
202
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
205         #attributes
206         rspec_nodes = []
207         slice_nodes_list = []
208         logger.debug("SLABAGGREGATE api get_nodes slice_nodes_list  %s "\
209                                                              %(slices ))
210         if slices is not None:
211             for one_slice in slices:
212                 try:
213                     slice_nodes_list = one_slice['node_ids']
214                 except KeyError:
215                     pass
216                 #for node in one_slice['node_ids']:
217                     #slice_nodes_list.append(node)
218
219 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
220         reserved_nodes = self.driver.iotlab_api.GetNodesCurrentlyInUse()
221 =======
222         reserved_nodes = self.driver.slab_api.GetNodesCurrentlyInUse()
223 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
224         logger.debug("SLABAGGREGATE api get_nodes slice_nodes_list  %s "\
225                                                         %(slice_nodes_list))
226         for node in nodes:
227             nodes_dict[node['node_id']] = node
228             if slice_nodes_list == [] or node['hostname'] in slice_nodes_list:
229
230 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
231                 rspec_node = IotlabNode()
232 =======
233                 rspec_node = SlabNode()
234 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
235                 # xxx how to retrieve site['login_base']
236                 #site_id=node['site_id']
237                 #site=sites_dict[site_id]
238
239                 rspec_node['mobile'] = node['mobile']
240                 rspec_node['archi'] = node['archi']
241                 rspec_node['radio'] = node['radio']
242
243 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
244                 iotlab_xrn = iotlab_xrn_object(self.driver.iotlab_api.root_auth, \
245                                                     node['hostname'])
246                 rspec_node['component_id'] = iotlab_xrn.urn
247 =======
248                 slab_xrn = slab_xrn_object(self.driver.slab_api.root_auth, \
249                                                     node['hostname'])
250                 rspec_node['component_id'] = slab_xrn.urn
251 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
252                 rspec_node['component_name'] = node['hostname']
253                 rspec_node['component_manager_id'] = \
254                                 hrn_to_urn(self.driver.iotlab_api.root_auth, \
255                                 'authority+sa')
256
257 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
258                 # Iotlab's nodes are federated : there is only one authority
259                 # for all Iotlab sites, registered in SFA.
260 =======
261                 # Senslab's nodes are federated : there is only one authority
262                 # for all Senslab sites, registered in SFA.
263 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
264                 # Removing the part including the site
265                 # in authority_id SA 27/07/12
266                 rspec_node['authority_id'] = rspec_node['component_manager_id']
267
268                 # do not include boot state (<available> element)
269                 #in the manifest rspec
270
271
272                 rspec_node['boot_state'] = node['boot_state']
273                 if node['hostname'] in reserved_nodes:
274                     rspec_node['boot_state'] = "Reserved"
275                 rspec_node['exclusive'] = 'true'
276                 rspec_node['hardware_types'] = [HardwareType({'name': \
277                                                 'iotlab-node'})]
278
279
280                 location = IotlabLocation({'country':'France', 'site': \
281                                             node['site']})
282                 rspec_node['location'] = location
283
284
285 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
286                 position = IotlabPosition()
287 =======
288                 position = SlabPosition()
289 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
290                 for field in position :
291                     try:
292                         position[field] = node[field]
293                     except KeyError, error :
294                         logger.log_exc("SLABAGGREGATE\t get_nodes \
295                                                         position %s "%(error))
296
297                 rspec_node['position'] = position
298                 #rspec_node['interfaces'] = []
299
300                 # Granularity
301                 granularity = Granularity({'grain': grain})
302                 rspec_node['granularity'] = granularity
303                 rspec_node['tags'] = []
304                 if node['hostname'] in slivers:
305                     # add sliver info
306                     sliver = slivers[node['hostname']]
307                     rspec_node['sliver_id'] = sliver['sliver_id']
308                     rspec_node['client_id'] = node['hostname']
309                     rspec_node['slivers'] = [sliver]
310
311                     # slivers always provide the ssh service
312                     login = Login({'authentication': 'ssh-keys', \
313                             'hostname': node['hostname'], 'port':'22', \
314                             'username': sliver['name']})
315                     service = Services({'login': login})
316                     rspec_node['services'] = [service]
317                 rspec_nodes.append(rspec_node)
318
319         return (rspec_nodes)
320     #def get_all_leases(self, slice_record = None):
321     def get_all_leases(self):
322         """
323         Get list of lease dictionaries which all have the mandatory keys
324         ('lease_id', 'hostname', 'site_id', 'name', 'start_time', 'duration').
325         All the leases running or scheduled are returned.
326
327
328         ..note::There is no filtering of leases within a given time frame.
329         All the running or scheduled leases are returned. options
330         removed SA 15/05/2013
331
332
333         """
334
335         #now = int(time.time())
336         #lease_filter = {'clip': now }
337
338         #if slice_record:
339             #lease_filter.update({'name': slice_record['name']})
340
341         #leases = self.driver.iotlab_api.GetLeases(lease_filter)
342         leases = self.driver.iotlab_api.GetLeases()
343         grain = self.driver.iotlab_api.GetLeaseGranularity()
344         site_ids = []
345         rspec_leases = []
346         for lease in leases:
347             #as many leases as there are nodes in the job
348             for node in lease['reserved_nodes']:
349                 rspec_lease = Lease()
350                 rspec_lease['lease_id'] = lease['lease_id']
351                 #site = node['site_id']
352                 iotlab_xrn = iotlab_xrn_object(self.driver.iotlab_api.root_auth, node)
353                 rspec_lease['component_id'] = iotlab_xrn.urn
354                 #rspec_lease['component_id'] = hostname_to_urn(self.driver.hrn,\
355                                         #site, node['hostname'])
356                 try:
357                     rspec_lease['slice_id'] = lease['slice_id']
358                 except KeyError:
359                     #No info on the slice used in iotlab_xp table
360                     pass
361                 rspec_lease['start_time'] = lease['t_from']
362                 rspec_lease['duration'] = (lease['t_until'] - lease['t_from']) \
363                                                                     / grain
364                 rspec_leases.append(rspec_lease)
365         return rspec_leases
366
367
368
369 #from plc/aggregate.py
370     def get_rspec(self, slice_xrn=None, login=None, version = None, \
371                 options=None):
372
373         rspec = None
374         version_manager = VersionManager()
375         version = version_manager.get_version(version)
376         logger.debug("IotlabAggregate \t get_rspec ***version %s \
377                     version.type %s  version.version %s options %s \r\n" \
378                     %(version,version.type,version.version,options))
379
380         if slice_xrn is None:
381             rspec_version = version_manager._get_version(version.type, \
382                                                     version.version, 'ad')
383
384         else:
385             rspec_version = version_manager._get_version(version.type, \
386                                                 version.version, 'manifest')
387
388         slices, slivers = self.get_slice_and_slivers(slice_xrn, login)
389 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
390         #at this point sliver may be empty if no iotlab job
391 =======
392         #at this point sliver may be empty if no senslab job
393 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
394         #is running for this user/slice.
395         rspec = RSpec(version=rspec_version, user_options=options)
396
397
398         #if slice and 'expires' in slice:
399            #rspec.xml.set('expires',\
400                 #datetime_to_string(utcparse(slice['expires']))
401          # add sliver defaults
402         #nodes, links = self.get_nodes(slice, slivers)
403         logger.debug("\r\n \r\n IotlabAggregate \tget_rspec *** \
404                                         slice_xrn %s slices  %s\r\n \r\n"\
405                                             %(slice_xrn, slices))
406
407         if options is not None:
408             lease_option = options['list_leases']
409         else:
410             #If no options are specified, at least print the resources
411             lease_option = 'all'
412            #if slice_xrn :
413                #lease_option = 'all'
414
415
416         if lease_option in ['all', 'resources']:
417         #if not options.get('list_leases') or options.get('list_leases')
418         #and options['list_leases'] != 'leases':
419             nodes = self.get_nodes(slices, slivers)
420 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
421             logger.debug("\r\n \r\n IotlabAggregate \ lease_option %s \
422 =======
423             logger.debug("\r\n \r\n SlabAggregate \ lease_option %s \
424 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
425                                         get rspec  ******* nodes %s"\
426                                             %(lease_option, nodes[0]))
427
428             sites_set = set([node['location']['site'] for node in nodes] )
429
430             #In case creating a job,  slice_xrn is not set to None
431             rspec.version.add_nodes(nodes)
432             if slice_xrn :
433                 #Get user associated with this slice
434                 #user = dbsession.query(RegRecord).filter_by(record_id = \
435                                             #slices['record_id_user']).first()
436
437                 #ldap_username = (user.hrn).split('.')[1]
438
439
440                 #for one_slice in slices :
441                 ldap_username = slices[0]['hrn']
442                 tmp = ldap_username.split('.')
443                 ldap_username = tmp[1].split('_')[0]
444
445                 if version.type == "Slab":
446                     rspec.version.add_connection_information(ldap_username, \
447                                                         sites_set)
448
449             default_sliver = slivers.get('default_sliver', [])
450             if default_sliver:
451                 #default_sliver_attribs = default_sliver.get('tags', [])
452                 logger.debug("IotlabAggregate \tget_rspec **** \
453                         default_sliver%s \r\n" %(default_sliver))
454                 for attrib in default_sliver:
455                     rspec.version.add_default_sliver_attribute(attrib, \
456                                                         default_sliver[attrib])
457         if lease_option in ['all','leases']:
458             #leases = self.get_all_leases(slices)
459             leases = self.get_all_leases()
460             rspec.version.add_leases(leases)
461
462 <<<<<<< HEAD:sfa/iotlab/iotlabaggregate.py
463         #logger.debug("IotlabAggregate \tget_rspec ******* rspec_toxml %s \r\n"\
464 =======
465         #logger.debug("SlabAggregate \tget_rspec ******* rspec_toxml %s \r\n"\
466 >>>>>>> 3fe7429... SA:sfa/senslab/slabaggregate.py
467                                             #%(rspec.toxml()))
468         return rspec.toxml()