SA bug hunt
[sfa.git] / sfa / iotlab / iotlabdriver.py
1 from sfa.util.faults import SliverDoesNotExist, UnknownSfaType
2 from sfa.util.sfalogging import logger
3 from sfa.storage.alchemy import dbsession
4 from sfa.storage.model import RegRecord
5
6
7
8 from sfa.managers.driver import Driver
9 from sfa.rspecs.version_manager import VersionManager
10 from sfa.rspecs.rspec import RSpec
11
12 from sfa.util.xrn import Xrn, hrn_to_urn, get_authority
13
14
15 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
16 from sfa.iotlab.iotlabpostgres import IotlabDB
17 =======
18 from sfa.senslab.slabpostgres import SlabDB
19
20
21 from sfa.senslab.slabaggregate import SlabAggregate, slab_xrn_to_hostname
22
23 from sfa.senslab.slabslices import SlabSlices
24 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
25
26
27 from sfa.iotlab.iotlabaggregate import IotlabAggregate, iotlab_xrn_to_hostname
28
29 from sfa.iotlab.iotlabslices import IotlabSlices
30
31
32 from sfa.iotlab.iotlabapi import IotlabTestbedAPI
33
34
35 class IotlabDriver(Driver):
36     """ Iotlab Driver class inherited from Driver generic class.
37
38 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
39 =======
40 class SlabDriver(Driver):
41     """ Senslab Driver class inherited from Driver generic class.
42
43 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
44     Contains methods compliant with the SFA standard and the testbed
45     infrastructure (calls to LDAP and OAR).
46
47     ..seealso:: Driver class
48
49     """
50     def __init__(self, config):
51         """
52
53 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
54         Sets the iotlab SFA config parameters ,
55         instanciates the testbed api and the iotlab database.
56
57         :param config: iotlab SFA configuration object
58 =======
59         Sets the senslab SFA config parameters ,
60         instanciates the testbed api and the senslab database.
61
62         :param config: senslab SFA configuration object
63 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
64         :type config: Config object
65         """
66         Driver.__init__ (self, config)
67         self.config = config
68
69         self.db = IotlabDB(config, debug = False)
70         self.iotlab_api = IotlabTestbedAPI(config)
71         self.cache = None
72
73     def augment_records_with_testbed_info (self, record_list ):
74         """
75
76         Adds specific testbed info to the records.
77
78         :param record_list: list of sfa dictionaries records
79         :type record_list: list
80         :return: list of records with extended information in each record
81         :rtype: list
82         """
83         return self.fill_record_info (record_list)
84
85     def fill_record_info(self, record_list):
86         """
87 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
88         For each SFA record, fill in the iotlab specific and SFA specific
89 =======
90         For each SFA record, fill in the senslab specific and SFA specific
91 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
92         fields in the record.
93
94         :param record_list: list of sfa dictionaries records
95         :type record_list: list
96         :return: list of records with extended information in each record
97         :rtype: list
98
99         .. warnings:: Should not be modifying record_list directly because modi
100         fication are kept outside the method's scope. Howerver, there is no
101         other way to do it given the way it's called in registry manager.
102         """
103
104 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
105         logger.debug("IOTLABDRIVER \tfill_record_info records %s " %(record_list))
106 =======
107         logger.debug("SLABDRIVER \tfill_record_info records %s " %(record_list))
108 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
109         if not isinstance(record_list, list):
110             record_list = [record_list]
111
112
113         try:
114             for record in record_list:
115                 #If the record is a SFA slice record, then add information
116                 #about the user of this slice. This kind of
117 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
118                 #information is in the Iotlab's DB.
119 =======
120                 #information is in the Senslab's DB.
121 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
122                 if str(record['type']) == 'slice':
123                     if 'reg_researchers' in record and \
124                     isinstance(record['reg_researchers'], list) :
125                         record['reg_researchers'] = \
126                             record['reg_researchers'][0].__dict__
127                         record.update({'PI':[record['reg_researchers']['hrn']],
128                             'researcher': [record['reg_researchers']['hrn']],
129                             'name':record['hrn'],
130                             'oar_job_id':[],
131                             'node_ids': [],
132                             'person_ids':[record['reg_researchers']['record_id']],
133                             'geni_urn':'',  #For client_helper.py compatibility
134                             'keys':'',  #For client_helper.py compatibility
135                             'key_ids':''})  #For client_helper.py compatibility
136
137
138 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
139                     #Get iotlab slice record and oar job id if any.
140                     recslice_list = self.iotlab_api.GetSlices(slice_filter = \
141 =======
142                     #Get slab slice record and oar job id if any.
143                     recslice_list = self.slab_api.GetSlices(slice_filter = \
144 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
145                                                 str(record['hrn']),\
146                                                 slice_filter_type = 'slice_hrn')
147
148
149 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
150                     logger.debug("IOTLABDRIVER \tfill_record_info \
151 =======
152                     logger.debug("SLABDRIVER \tfill_record_info \
153 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
154                         TYPE SLICE RECUSER record['hrn'] %s ecord['oar_job_id']\
155                          %s " %(record['hrn'], record['oar_job_id']))
156                     del record['reg_researchers']
157                     try:
158                         for rec in recslice_list:
159 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
160                             logger.debug("IOTLABDRIVER\r\n  \t  \
161                             fill_record_info oar_job_id %s " \
162                             %(rec['oar_job_id']))
163
164                             record['node_ids'] = [ self.iotlab_api.root_auth + \
165 =======
166                             logger.debug("SLABDRIVER\r\n  \t  \
167                             fill_record_info oar_job_id %s " \
168                             %(rec['oar_job_id']))
169
170                             record['node_ids'] = [ self.slab_api.root_auth + \
171 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
172                                     hostname for hostname in rec['node_ids']]
173                     except KeyError:
174                         pass
175
176
177 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
178                     logger.debug( "IOTLABDRIVER.PY \t fill_record_info SLICE \
179 =======
180                     logger.debug( "SLABDRIVER.PY \t fill_record_info SLICE \
181 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
182                                     recslice_list  %s \r\n \t RECORD %s \r\n \
183                                     \r\n" %(recslice_list, record))
184
185                 if str(record['type']) == 'user':
186                     #The record is a SFA user record.
187                     #Get the information about his slice from Iotlab's DB
188                     #and add it to the user record.
189                     recslice_list = self.iotlab_api.GetSlices(\
190                             slice_filter = record['record_id'],\
191                             slice_filter_type = 'record_id_user')
192
193 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
194                     logger.debug( "IOTLABDRIVER.PY \t fill_record_info TYPE USER \
195 =======
196                     logger.debug( "SLABDRIVER.PY \t fill_record_info TYPE USER \
197 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
198                                 recslice_list %s \r\n \t RECORD %s \r\n" \
199                                 %(recslice_list , record))
200                     #Append slice record in records list,
201                     #therefore fetches user and slice info again(one more loop)
202                     #Will update PIs and researcher for the slice
203
204                     recuser = recslice_list[0]['reg_researchers']
205 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
206                     logger.debug( "IOTLABDRIVER.PY \t fill_record_info USER  \
207 =======
208                     logger.debug( "SLABDRIVER.PY \t fill_record_info USER  \
209 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
210                                             recuser %s \r\n \r\n" %(recuser))
211                     recslice = {}
212                     recslice = recslice_list[0]
213                     recslice.update({'PI':[recuser['hrn']],
214                         'researcher': [recuser['hrn']],
215                         'name':record['hrn'],
216                         'node_ids': [],
217                         'oar_job_id': [],
218                         'person_ids':[recuser['record_id']]})
219                     try:
220                         for rec in recslice_list:
221                             recslice['oar_job_id'].append(rec['oar_job_id'])
222                     except KeyError:
223                         pass
224
225                     recslice.update({'type':'slice', \
226                                                 'hrn':recslice_list[0]['hrn']})
227
228
229                     #GetPersons takes [] as filters
230 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
231                     user_iotlab = self.iotlab_api.GetPersons([record])
232
233
234                     record.update(user_iotlab[0])
235 =======
236                     user_slab = self.slab_api.GetPersons([record])
237
238
239                     record.update(user_slab[0])
240 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
241                     #For client_helper.py compatibility
242                     record.update( { 'geni_urn':'',
243                     'keys':'',
244                     'key_ids':'' })
245                     record_list.append(recslice)
246
247 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
248                     logger.debug("IOTLABDRIVER.PY \tfill_record_info ADDING SLICE\
249 =======
250                     logger.debug("SLABDRIVER.PY \tfill_record_info ADDING SLICE\
251 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
252                                 INFO TO USER records %s" %(record_list))
253
254
255         except TypeError, error:
256             logger.log_exc("IOTLABDRIVER \t fill_record_info  EXCEPTION %s"\
257                                                                      %(error))
258
259         return record_list
260
261
262     def sliver_status(self, slice_urn, slice_hrn):
263         """
264         Receive a status request for slice named urn/hrn
265 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
266         urn:publicid:IDN+iotlab+nturro_slice hrn iotlab.nturro_slice
267 =======
268         urn:publicid:IDN+senslab+nturro_slice hrn senslab.nturro_slice
269 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
270         shall return a structure as described in
271         http://groups.geni.net/geni/wiki/GAPI_AM_API_V2#SliverStatus
272         NT : not sure if we should implement this or not, but used by sface.
273
274         :param slice_urn: slice urn
275         :type slice_urn: string
276         :param slice_hrn: slice hrn
277         :type slice_hrn: string
278
279         """
280
281
282         #First get the slice with the slice hrn
283         slice_list =  self.iotlab_api.GetSlices(slice_filter = slice_hrn, \
284                                     slice_filter_type = 'slice_hrn')
285
286         if len(slice_list) is 0:
287             raise SliverDoesNotExist("%s  slice_hrn" % (slice_hrn))
288
289         #Used for fetching the user info witch comes along the slice info
290         one_slice = slice_list[0]
291
292
293         #Make a list of all the nodes hostnames  in use for this slice
294         slice_nodes_list = []
295         #for single_slice in slice_list:
296             #for node in single_slice['node_ids']:
297                 #slice_nodes_list.append(node['hostname'])
298         #for node in one_slice:
299             #slice_nodes_list.append(node['hostname'])
300         slice_nodes_list = one_slice['node_ids']
301         #Get all the corresponding nodes details
302 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
303         nodes_all = self.iotlab_api.GetNodes({'hostname':slice_nodes_list},
304 =======
305         nodes_all = self.slab_api.GetNodes({'hostname':slice_nodes_list},
306 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
307                                 ['node_id', 'hostname','site','boot_state'])
308         nodeall_byhostname = dict([(one_node['hostname'], one_node) \
309                                             for one_node in nodes_all])
310
311
312
313         for single_slice in slice_list:
314
315               #For compatibility
316             top_level_status = 'empty'
317             result = {}
318             result.fromkeys(\
319                 ['geni_urn','geni_error', 'pl_login','geni_status','geni_resources'], None)
320             result['pl_login'] = one_slice['reg_researchers'][0].hrn
321             logger.debug("Slabdriver - sliver_status Sliver status \
322                                         urn %s hrn %s single_slice  %s \r\n " \
323                                         %(slice_urn, slice_hrn, single_slice))
324
325             if 'node_ids' not in single_slice:
326                 #No job in the slice
327                 result['geni_status'] = top_level_status
328                 result['geni_resources'] = []
329                 return result
330 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
331 =======
332
333             top_level_status = 'ready'
334 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
335
336             top_level_status = 'ready'
337
338             #A job is running on Iotlab for this slice
339             # report about the local nodes that are in the slice only
340
341             result['geni_urn'] = slice_urn
342
343             resources = []
344             for node_hostname in single_slice['node_ids']:
345                 res = {}
346 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
347                 res['iotlab_hostname'] = node_hostname
348                 res['iotlab_boot_state'] = nodeall_byhostname[node_hostname]['boot_state']
349 =======
350                 res['slab_hostname'] = node_hostname
351                 res['slab_boot_state'] = nodeall_byhostname[node_hostname]['boot_state']
352 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
353
354                 #res['pl_hostname'] = node['hostname']
355                 #res['pl_boot_state'] = \
356                             #nodeall_byhostname[node['hostname']]['boot_state']
357                 #res['pl_last_contact'] = strftime(self.time_format, \
358                                                     #gmtime(float(timestamp)))
359                 sliver_id =  Xrn(slice_urn, type='slice', \
360                         id=nodeall_byhostname[node_hostname]['node_id'], \
361                         authority=self.hrn).urn
362
363                 res['geni_urn'] = sliver_id
364                 #node_name  = node['hostname']
365                 if nodeall_byhostname[node_hostname]['boot_state'] == 'Alive':
366
367                     res['geni_status'] = 'ready'
368                 else:
369                     res['geni_status'] = 'failed'
370                     top_level_status = 'failed'
371
372                 res['geni_error'] = ''
373
374                 resources.append(res)
375
376             result['geni_status'] = top_level_status
377             result['geni_resources'] = resources
378 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
379             logger.debug("IOTLABDRIVER \tsliver_statusresources %s res %s "\
380 =======
381             logger.debug("SLABDRIVER \tsliver_statusresources %s res %s "\
382 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
383                                                     %(resources,res))
384             return result
385
386     @staticmethod
387     def get_user_record(hrn):
388         """
389         Returns the user record based on the hrn from the SFA DB .
390
391         :param hrn: user's hrn
392         :type hrn: string
393         :return : user record from SFA database
394         :rtype: RegUser
395
396         """
397         return dbsession.query(RegRecord).filter_by(hrn = hrn).first()
398
399
400     def testbed_name (self):
401         """
402         Returns testbed's name.
403
404         :rtype: string
405         """
406         return self.hrn
407
408     # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
409     def aggregate_version (self):
410         """
411
412         Returns the testbed's supported rspec advertisement and
413         request versions.
414
415         :rtype: dict
416         """
417         version_manager = VersionManager()
418         ad_rspec_versions = []
419         request_rspec_versions = []
420         for rspec_version in version_manager.versions:
421             if rspec_version.content_type in ['*', 'ad']:
422                 ad_rspec_versions.append(rspec_version.to_dict())
423             if rspec_version.content_type in ['*', 'request']:
424                 request_rspec_versions.append(rspec_version.to_dict())
425         return {
426             'testbed':self.testbed_name(),
427             'geni_request_rspec_versions': request_rspec_versions,
428             'geni_ad_rspec_versions': ad_rspec_versions,
429             }
430
431
432
433     def _get_requested_leases_list(self, rspec):
434         """
435         Process leases in rspec depending on the rspec version (format)
436         type. Find the lease requests in the rspec and creates
437         a lease request list with the mandatory information ( nodes,
438         start time and duration) of the valid leases (duration above or equal
439 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
440         to the iotlab experiment minimum duration).
441 =======
442         to the senslab experiment minimum duration).
443 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
444
445         :param rspec: rspec request received.
446         :type rspec: RSpec
447         :return: list of lease requests found in the rspec
448         :rtype: list
449         """
450         requested_lease_list = []
451         for lease in rspec.version.get_leases():
452             single_requested_lease = {}
453 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
454             logger.debug("IOTLABDRIVER.PY \t_get_requested_leases_list lease %s " %(lease))
455 =======
456             logger.debug("SLABDRIVER.PY \t_get_requested_leases_list lease %s " %(lease))
457 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
458
459             if not lease.get('lease_id'):
460                 if get_authority(lease['component_id']) == \
461                                             self.iotlab_api.root_auth:
462                     single_requested_lease['hostname'] = \
463                                         iotlab_xrn_to_hostname(\
464                                         lease.get('component_id').strip())
465                     single_requested_lease['start_time'] = \
466                                                         lease.get('start_time')
467                     single_requested_lease['duration'] = lease.get('duration')
468                     #Check the experiment's duration is valid before adding
469                     #the lease to the requested leases list
470                     duration_in_seconds = \
471                             int(single_requested_lease['duration'])
472 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
473                     if duration_in_seconds >= self.iotlab_api.GetMinExperimentDurationInSec() :
474 =======
475                     if duration_in_seconds >= self.slab_api.GetMinExperimentDurationInSec() :
476 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
477                         requested_lease_list.append(single_requested_lease)
478
479         return requested_lease_list
480
481     @staticmethod
482     def _group_leases_by_start_time(requested_lease_list):
483         """
484         Create dict of leases by start_time, regrouping nodes reserved
485         at the same time, for the same amount of time so as to
486         define one job on OAR.
487
488         :param requested_lease_list: list of leases
489         :type requested_lease_list: list
490         :return: Dictionary with key = start time, value = list of leases
491         with the same start time.
492         :rtype: dictionary
493         """
494
495         requested_job_dict = {}
496         for lease in requested_lease_list:
497
498             #In case it is an asap experiment start_time is empty
499             if lease['start_time'] == '':
500                 lease['start_time'] = '0'
501
502             if lease['start_time'] not in requested_job_dict:
503                 if isinstance(lease['hostname'], str):
504                     lease['hostname'] = [lease['hostname']]
505
506
507                 requested_job_dict[lease['start_time']] = lease
508
509             else :
510                 job_lease = requested_job_dict[lease['start_time']]
511                 if lease['duration'] == job_lease['duration'] :
512                     job_lease['hostname'].append(lease['hostname'])
513
514         return requested_job_dict
515
516     def _process_requested_jobs(self, rspec):
517         """
518         Turns the requested leases and information into a dictionary
519         of requested jobs, grouped by starting time.
520
521         :param rspec: RSpec received
522         :type rspec : RSpec
523         :rtype: dictionary
524         """
525         requested_lease_list = self._get_requested_leases_list(rspec)
526         logger.debug("IOTLABDRIVER _process_requested_jobs requested_lease_list \
527         %s"%(requested_lease_list))
528         job_dict =  self._group_leases_by_start_time(requested_lease_list)
529 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
530         logger.debug("IOTLABDRIVER _process_requested_jobs  job_dict\
531 =======
532         logger.debug("SLABDRIVER _process_requested_jobs  job_dict\
533 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
534         %s"%(job_dict))
535
536         return job_dict
537
538     def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, \
539                                                              users, options):
540         """
541         Answer to CreateSliver.
542         Creates the leases and slivers for the users from the information
543         found in the rspec string.
544         Launch experiment on OAR if the requested leases is valid. Delete
545         no longer requested leases.
546
547
548         :param creds: user's credentials
549         :type creds: string
550         :param users: user record list
551         :type users: list
552         :param options:
553         :type options:
554
555         :return: a valid Rspec for the slice which has just been
556         modified.
557         :rtype: RSpec
558
559
560         """
561 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
562         aggregate = IotlabAggregate(self)
563
564         slices = IotlabSlices(self)
565 =======
566         aggregate = SlabAggregate(self)
567
568         slices = SlabSlices(self)
569 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
570         peer = slices.get_peer(slice_hrn)
571         sfa_peer = slices.get_sfa_peer(slice_hrn)
572         slice_record = None
573
574         if not isinstance(creds, list):
575             creds = [creds]
576
577         if users:
578             slice_record = users[0].get('slice_record', {})
579 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
580             logger.debug("IOTLABDRIVER.PY \t ===============create_sliver \t\
581 =======
582             logger.debug("SLABDRIVER.PY \t ===============create_sliver \t\
583 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
584                                         creds %s \r\n \r\n users %s" \
585                                         %(creds, users))
586             slice_record['user'] = {'keys':users[0]['keys'], \
587                                     'email':users[0]['email'], \
588                                     'hrn':slice_record['reg-researchers'][0]}
589         # parse rspec
590         rspec = RSpec(rspec_string)
591         logger.debug("IOTLABDRIVER.PY \t create_sliver \trspec.version \
592                                         %s slice_record %s users %s" \
593                                         %(rspec.version,slice_record, users))
594
595
596         # ensure site record exists?
597         # ensure slice record exists
598         #Removed options to verify_slice SA 14/08/12
599         sfa_slice = slices.verify_slice(slice_hrn, slice_record, peer, \
600                                                     sfa_peer)
601
602         # ensure person records exists
603         #verify_persons returns added persons but since the return value
604         #is not used
605         slices.verify_persons(slice_hrn, sfa_slice, users, peer, \
606                                                     sfa_peer, options=options)
607         #requested_attributes returned by rspec.version.get_slice_attributes()
608         #unused, removed SA 13/08/12
609         #rspec.version.get_slice_attributes()
610
611         logger.debug("IOTLABDRIVER.PY create_sliver slice %s " %(sfa_slice))
612
613         # add/remove slice from nodes
614
615 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
616 =======
617         # add/remove slice from nodes
618
619 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
620         #requested_slivers = [node.get('component_id') \
621                             #for node in rspec.version.get_nodes_with_slivers()\
622                             #if node.get('authority_id') is self.iotlab_api.root_auth]
623         #l = [ node for node in rspec.version.get_nodes_with_slivers() ]
624         #logger.debug("SLADRIVER \tcreate_sliver requested_slivers \
625                                     #requested_slivers %s  listnodes %s" \
626                                     #%(requested_slivers,l))
627         #verify_slice_nodes returns nodes, but unused here. Removed SA 13/08/12.
628         #slices.verify_slice_nodes(sfa_slice, requested_slivers, peer)
629
630
631         requested_job_dict = self._process_requested_jobs(rspec)
632
633
634 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
635         logger.debug("IOTLABDRIVER.PY \tcreate_sliver  requested_job_dict %s "\
636 =======
637         logger.debug("SLABDRIVER.PY \tcreate_sliver  requested_job_dict %s "\
638 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
639                                                      %(requested_job_dict))
640         #verify_slice_leases returns the leases , but the return value is unused
641         #here. Removed SA 13/08/12
642         slices.verify_slice_leases(sfa_slice, \
643                                     requested_job_dict, peer)
644
645         return aggregate.get_rspec(slice_xrn=slice_urn, \
646                 login=sfa_slice['login'], version=rspec.version)
647
648
649     def delete_sliver (self, slice_urn, slice_hrn, creds, options):
650         """
651         Deletes the lease associated with the slice hrn and the credentials
652 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
653         if the slice belongs to iotlab. Answer to DeleteSliver.
654
655         :return: 1 if the slice to delete was not found on iotlab,
656         True if the deletion was successful, False otherwise otherwise.
657
658         .. note:: Should really be named delete_leases because iotlab does
659 =======
660         if the slice belongs to senslab. Answer to DeleteSliver.
661
662         :return: 1 if the slice to delete was not found on senslab,
663         True if the deletion was successful, False otherwise otherwise.
664
665         .. note:: Should really be named delete_leases because senslab does
666 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
667         not have any slivers, but only deals with leases. However, SFA api only
668         have delete_sliver define so far. SA 13.05/2013
669         """
670
671 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
672         sfa_slice_list  = self.iotlab_api.GetSlices(slice_filter = slice_hrn, \
673 =======
674         sfa_slice_list  = self.slab_api.GetSlices(slice_filter = slice_hrn, \
675 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
676                                             slice_filter_type = 'slice_hrn')
677
678         if not sfa_slice_list:
679             return 1
680
681         #Delete all leases in the slice
682         for sfa_slice in sfa_slice_list:
683
684
685 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
686             logger.debug("IOTLABDRIVER.PY delete_sliver slice %s" %(sfa_slice))
687             slices = IotlabSlices(self)
688             # determine if this is a peer slice
689 =======
690             logger.debug("SLABDRIVER.PY delete_sliver slice %s" %(sfa_slice))
691             slices = SlabSlices(self)
692             # determine if this is a peer slice
693
694             peer = slices.get_peer(slice_hrn)
695 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
696
697             peer = slices.get_peer(slice_hrn)
698
699             logger.debug("IOTLABDRIVER.PY delete_sliver peer %s \
700             \r\n \t sfa_slice %s " %(peer, sfa_slice))
701             try:
702
703 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
704                 self.iotlab_api.DeleteSliceFromNodes(sfa_slice)
705 =======
706                 self.slab_api.DeleteSliceFromNodes(sfa_slice)
707 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
708                 return True
709             except :
710                 return False
711
712
713     def list_resources (self, slice_urn, slice_hrn, creds, options):
714         """
715 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
716         List resources from the iotlab aggregate and returns a Rspec
717 =======
718         List resources from the senslab aggregate and returns a Rspec
719 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
720         advertisement with resources found when slice_urn and slice_hrn are None
721         (in case of resource discovery).
722         If a slice hrn and urn are provided, list experiment's slice
723         nodes in a rspec format. Answer to ListResources.
724         Caching unused.
725         :param options: options used when listing resources (list_leases, info,
726         geni_available)
727         :return: rspec string in xml
728         :rtype: string
729         """
730
731         #cached_requested = options.get('cached', True)
732
733         version_manager = VersionManager()
734         # get the rspec's return format from options
735         rspec_version = \
736                 version_manager.get_version(options.get('geni_rspec_version'))
737         version_string = "rspec_%s" % (rspec_version)
738
739         #panos adding the info option to the caching key (can be improved)
740         if options.get('info'):
741             version_string = version_string + "_" + \
742                                         options.get('info', 'default')
743
744         # Adding the list_leases option to the caching key
745         if options.get('list_leases'):
746             version_string = version_string + "_" + \
747             options.get('list_leases', 'default')
748
749         # Adding geni_available to caching key
750         if options.get('geni_available'):
751             version_string = version_string + "_" + \
752                 str(options.get('geni_available'))
753
754         # look in cache first
755         #if cached_requested and self.cache and not slice_hrn:
756             #rspec = self.cache.get(version_string)
757             #if rspec:
758                 #logger.debug("IotlabDriver.ListResources: \
759                                     #returning cached advertisement")
760                 #return rspec
761
762         #panos: passing user-defined options
763 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
764         aggregate = IotlabAggregate(self)
765 =======
766         aggregate = SlabAggregate(self)
767 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
768
769         rspec =  aggregate.get_rspec(slice_xrn=slice_urn, \
770                                         version=rspec_version, options=options)
771
772         # cache the result
773         #if self.cache and not slice_hrn:
774             #logger.debug("Slab.ListResources: stores advertisement in cache")
775             #self.cache.add(version_string, rspec)
776
777         return rspec
778
779
780     def list_slices (self, creds, options):
781         """
782         Answer to ListSlices.
783 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
784         List slices belonging to iotlab, returns slice urns list.
785 =======
786         List slices belonging to senslab, returns slice urns list.
787 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
788         No caching used. Options unused but are defined in the SFA method
789         api prototype.
790
791         :return: slice urns list
792         :rtype: list
793
794         """
795         # look in cache first
796         #if self.cache:
797             #slices = self.cache.get('slices')
798             #if slices:
799                 #logger.debug("PlDriver.list_slices returns from cache")
800                 #return slices
801
802         # get data from db
803
804 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
805         slices = self.iotlab_api.GetSlices()
806         logger.debug("IOTLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n" %(slices))
807         slice_hrns = [iotlab_slice['hrn'] for iotlab_slice in slices]
808 =======
809         slices = self.slab_api.GetSlices()
810         logger.debug("SLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n" %(slices))
811         slice_hrns = [slab_slice['hrn'] for slab_slice in slices]
812 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
813
814         slice_urns = [hrn_to_urn(slice_hrn, 'slice') \
815                                                 for slice_hrn in slice_hrns]
816
817         # cache the result
818         #if self.cache:
819 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
820             #logger.debug ("IotlabDriver.list_slices stores value in cache")
821 =======
822             #logger.debug ("SlabDriver.list_slices stores value in cache")
823 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
824             #self.cache.add('slices', slice_urns)
825
826         return slice_urns
827
828
829     def register (self, sfa_record, hrn, pub_key):
830         """
831         Adding new user, slice, node or site should not be handled
832         by SFA.
833
834         ..warnings:: should not be used. Different components are in charge of
835         doing this task. Adding nodes = OAR
836         Adding users = LDAP Iotlab
837         Adding slice = Import from LDAP users
838         Adding site = OAR
839
840         :param sfa_record: record provided by the client of the
841         Register API call.
842         :type sfa_record: dict
843         """
844         return -1
845
846
847     def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
848 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
849         """No site or node record update allowed in Iotlab.
850 =======
851         """No site or node record update allowed in Senslab.
852 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
853         The only modifications authorized here are key deletion/addition
854         on an existing user and password change.
855         On an existing user, CAN NOT BE MODIFIED:
856         'first_name', 'last_name', 'email'
857          DOES NOT EXIST IN SENSLAB:
858          'phone', 'url', 'bio','title', 'accepted_aup',
859         A slice is bound to its user, so modifying the user's ssh key should
860         modify the slice's GID after an import procedure.
861
862         :param old_sfa_record: what is in the db for this hrn
863         :param new_sfa_record: what was passed to the Update call
864
865         ..seealso:: update in driver.py.
866         """
867
868         pointer = old_sfa_record['pointer']
869         old_sfa_record_type = old_sfa_record['type']
870
871         # new_key implemented for users only
872         if new_key and old_sfa_record_type not in [ 'user' ]:
873             raise UnknownSfaType(old_sfa_record_type)
874
875
876         if old_sfa_record_type == "user":
877             update_fields = {}
878             all_fields = new_sfa_record
879             for key in all_fields.keys():
880                 if key in ['key', 'password']:
881                     update_fields[key] = all_fields[key]
882
883
884             if new_key:
885                 # must check this key against the previous one if it exists
886                 persons = self.iotlab_api.GetPersons([old_sfa_record])
887                 person = persons[0]
888                 keys = [person['pkey']]
889                 #Get all the person's keys
890 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
891                 keys_dict = self.iotlab_api.GetKeys(keys)
892 =======
893                 keys_dict = self.slab_api.GetKeys(keys)
894 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
895
896                 # Delete all stale keys, meaning the user has only one key
897                 #at a time
898                 #TODO: do we really want to delete all the other keys?
899                 #Is this a problem with the GID generation to have multiple
900                 #keys? SA 30/05/13
901                 key_exists = False
902                 if key in keys_dict:
903                     key_exists = True
904                 else:
905                     #remove all the other keys
906                     for key in keys_dict:
907                         self.iotlab_api.DeleteKey(person, key)
908                     self.iotlab_api.AddPersonKey(person, \
909                     {'sshPublicKey': person['pkey']},{'sshPublicKey': new_key} )
910                     #self.iotlab_api.AddPersonKey(person, {'key_type': 'ssh', \
911                                                     #'key': new_key})
912         return True
913
914
915     def remove (self, sfa_record):
916         """
917         Removes users only. Mark the user as disabled in
918         LDAP. The user and his slice are then deleted from the db by running an
919         import on the registry.
920
921
922
923         :param sfa_record: record is the existing sfa record in the db
924         :type sfa_record: dict
925
926         ..warning::As fas as the slice is concerned, here only the leases are
927         removed from the slice. The slice is record itself is not removed from
928         the db.
929         TODO : REMOVE SLICE FROM THE DB AS WELL? SA 14/05/2013,
930
931         TODO: return boolean for the slice part
932         """
933         sfa_record_type = sfa_record['type']
934         hrn = sfa_record['hrn']
935         if sfa_record_type == 'user':
936
937 <<<<<<< HEAD:sfa/iotlab/iotlabdriver.py
938             #get user from iotlab ldap
939             person = self.iotlab_api.GetPersons(sfa_record)
940             #No registering at a given site in Iotlab.
941             #Once registered to the LDAP, all iotlab sites are
942 =======
943             #get user from senslab ldap
944             person = self.slab_api.GetPersons(sfa_record)
945             #No registering at a given site in Senslab.
946             #Once registered to the LDAP, all senslab sites are
947 >>>>>>> 3fe7429... SA:sfa/senslab/slabdriver.py
948             #accesible.
949             if person :
950                 #Mark account as disabled in ldap
951                 return self.iotlab_api.DeletePerson(sfa_record)
952
953         elif sfa_record_type == 'slice':
954             if self.iotlab_api.GetSlices(slice_filter = hrn, \
955                                     slice_filter_type = 'slice_hrn'):
956                 ret = self.iotlab_api.DeleteSlice(sfa_record)
957
958
959
960             return True
961
962