36c8ef8cfb1f996860cad027163c9143147d5fde
[sfa.git] / sfa / senslab / slabdriver.py
1 import subprocess
2 import os
3
4 from datetime import datetime
5
6 from sfa.util.faults import SliverDoesNotExist, UnknownSfaType
7 from sfa.util.sfalogging import logger
8 from sfa.storage.alchemy import dbsession
9 from sfa.storage.model import RegRecord, RegUser, RegSlice
10 from sqlalchemy.orm import joinedload
11
12
13 from sfa.managers.driver import Driver
14 from sfa.rspecs.version_manager import VersionManager
15 from sfa.rspecs.rspec import RSpec
16
17 from sfa.util.xrn import Xrn, hrn_to_urn, get_authority
18
19
20 ## thierry: everything that is API-related (i.e. handling incoming requests) 
21 # is taken care of 
22 # SlabDriver should be really only about talking to the senslab testbed
23
24
25 from sfa.senslab.OARrestapi import  OARrestapi
26 from sfa.senslab.LDAPapi import LDAPapi
27
28 from sfa.senslab.slabpostgres import SlabDB, slab_dbsession, SenslabXP
29                                                      
30                                                                 
31 from sfa.senslab.slabaggregate import SlabAggregate, slab_xrn_to_hostname, \
32                                                             slab_xrn_object
33 from sfa.senslab.slabslices import SlabSlices
34
35
36
37 # thierry : note
38 # this inheritance scheme is so that the driver object can receive
39 # GetNodes or GetSites sorts of calls directly
40 # and thus minimize the differences in the managers with the pl version
41
42
43
44 class SlabDriver(Driver):
45     """ Senslab Driver class inherited from Driver generic class.
46     
47     Contains methods compliant with the SFA standard and the testbed
48     infrastructure (calls to LDAP and OAR).
49     """
50     def __init__(self, config):
51         Driver.__init__ (self, config)
52         self.config = config
53         self.hrn = config.SFA_INTERFACE_HRN
54         self.root_auth = config.SFA_REGISTRY_ROOT_AUTH
55         self.oar = OARrestapi()
56         self.ldap = LDAPapi()
57         self.time_format = "%Y-%m-%d %H:%M:%S"
58         self.db = SlabDB(config, debug = False)
59         self.cache = None
60         
61     
62     def sliver_status(self, slice_urn, slice_hrn):
63         """Receive a status request for slice named urn/hrn 
64         urn:publicid:IDN+senslab+nturro_slice hrn senslab.nturro_slice
65         shall return a structure as described in
66         http://groups.geni.net/geni/wiki/GAPI_AM_API_V2#SliverStatus
67         NT : not sure if we should implement this or not, but used by sface.
68         
69         """
70         
71         #First get the slice with the slice hrn
72         slice_list =  self.GetSlices(slice_filter = slice_hrn, \
73                                     slice_filter_type = 'slice_hrn')
74         
75         if len(slice_list) is 0:
76             raise SliverDoesNotExist("%s  slice_hrn" % (slice_hrn))
77         
78         #Slice has the same slice hrn for each slice in the slice/lease list
79         #So fetch the info on the user once 
80         one_slice = slice_list[0] 
81         #recuser = dbsession.query(RegRecord).filter_by(record_id = \
82                                             #one_slice['record_id_user']).first()
83         
84         #Make a list of all the nodes hostnames  in use for this slice
85         slice_nodes_list = []
86         for single_slice in slice_list:
87             for node in single_slice['node_ids']:
88                 slice_nodes_list.append(node['hostname'])
89             
90         #Get all the corresponding nodes details    
91         nodes_all = self.GetNodes({'hostname':slice_nodes_list},
92                                 ['node_id', 'hostname','site','boot_state'])
93         nodeall_byhostname = dict([(one_node['hostname'], one_node) \
94                                             for one_node in nodes_all])  
95           
96           
97           
98         for single_slice in slice_list:
99
100               #For compatibility
101             top_level_status = 'empty' 
102             result = {}
103             result.fromkeys(\
104                 ['geni_urn','pl_login','geni_status','geni_resources'], None)
105             result['pl_login'] = one_slice['reg_researchers']['hrn']
106             logger.debug("Slabdriver - sliver_status Sliver status \
107                                         urn %s hrn %s single_slice  %s \r\n " \
108                                         %(slice_urn, slice_hrn, single_slice))
109             try:
110                 nodes_in_slice = single_slice['node_ids']
111             except KeyError:
112                 #No job in the slice
113                 result['geni_status'] = top_level_status
114                 result['geni_resources'] = [] 
115                 return result
116            
117             top_level_status = 'ready' 
118
119             #A job is running on Senslab for this slice
120             # report about the local nodes that are in the slice only
121          
122             result['geni_urn'] = slice_urn
123             
124
125             
126             #timestamp = float(sl['startTime']) + float(sl['walltime']) 
127             #result['pl_expires'] = strftime(self.time_format, \
128                                                     #gmtime(float(timestamp)))
129             #result['slab_expires'] = strftime(self.time_format,\
130                                                     #gmtime(float(timestamp)))
131             
132             resources = []
133             for node in single_slice['node_ids']:
134                 res = {}
135                 #res['slab_hostname'] = node['hostname']
136                 #res['slab_boot_state'] = node['boot_state']
137                 
138                 res['pl_hostname'] = node['hostname']
139                 res['pl_boot_state'] = \
140                             nodeall_byhostname[node['hostname']]['boot_state']
141                 #res['pl_last_contact'] = strftime(self.time_format, \
142                                                     #gmtime(float(timestamp)))
143                 sliver_id =  Xrn(slice_urn, type='slice', \
144                         id=nodeall_byhostname[node['hostname']]['node_id'], \
145                         authority=self.hrn).urn
146     
147                 res['geni_urn'] = sliver_id 
148                 node_name  = node['hostname']
149                 if nodeall_byhostname[node_name]['boot_state'] == 'Alive':
150
151                     res['geni_status'] = 'ready'
152                 else:
153                     res['geni_status'] = 'failed'
154                     top_level_status = 'failed' 
155                     
156                 res['geni_error'] = ''
157         
158                 resources.append(res)
159                 
160             result['geni_status'] = top_level_status
161             result['geni_resources'] = resources 
162             logger.debug("SLABDRIVER \tsliver_statusresources %s res %s "\
163                                                     %(resources,res))
164             return result        
165             
166     def get_user(self, hrn):
167         return dbsession.query(RegRecord).filter_by(hrn = hrn).first() 
168          
169          
170     def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, \
171                                                              users, options):
172         aggregate = SlabAggregate(self)
173         
174         slices = SlabSlices(self)
175         peer = slices.get_peer(slice_hrn)
176         sfa_peer = slices.get_sfa_peer(slice_hrn)
177         slice_record = None 
178  
179         if not isinstance(creds, list):
180             creds = [creds]
181     
182         if users:
183             slice_record = users[0].get('slice_record', {}) 
184             logger.debug("SLABDRIVER.PY \t ===============create_sliver \t\
185                                         creds %s \r\n \r\n users %s" \
186                                         %(creds, users))
187             slice_record['user'] = {'keys':users[0]['keys'], \
188                                     'email':users[0]['email'], \
189                                     'hrn':slice_record['reg-researchers'][0]}
190         # parse rspec
191         rspec = RSpec(rspec_string)
192         logger.debug("SLABDRIVER.PY \t create_sliver \trspec.version \
193                                         %s slice_record %s users %s" \
194                                         %(rspec.version,slice_record, users))
195                                             
196
197         # ensure site record exists?
198         # ensure slice record exists
199         #Removed options to verify_slice SA 14/08/12
200         sfa_slice = slices.verify_slice(slice_hrn, slice_record, peer, \
201                                                     sfa_peer)
202                                                     
203         # ensure person records exists
204         #verify_persons returns added persons but since the return value
205         #is not used 
206         slices.verify_persons(slice_hrn, sfa_slice, users, peer, \
207                                                     sfa_peer, options=options)                                           
208         #requested_attributes returned by rspec.version.get_slice_attributes() 
209         #unused, removed SA 13/08/12
210         rspec.version.get_slice_attributes()
211
212         logger.debug("SLABDRIVER.PY create_sliver slice %s " %(sfa_slice))
213
214         # add/remove slice from nodes 
215        
216         requested_slivers = [node.get('component_id') \
217                             for node in rspec.version.get_nodes_with_slivers()\
218                             if node.get('authority_id') is self.root_auth]
219         l = [ node for node in rspec.version.get_nodes_with_slivers() ]
220         logger.debug("SLADRIVER \tcreate_sliver requested_slivers \
221                                     requested_slivers %s  listnodes %s" \
222                                     %(requested_slivers,l))
223         #verify_slice_nodes returns nodes, but unused here. Removed SA 13/08/12.
224         #slices.verify_slice_nodes(sfa_slice, requested_slivers, peer) 
225         
226         # add/remove leases
227         requested_lease_list = []
228
229         logger.debug("SLABDRIVER.PY \tcreate_sliver AVANTLEASE " )
230         rspec_requested_leases = rspec.version.get_leases()
231         for lease in rspec.version.get_leases():
232             single_requested_lease = {}
233             logger.debug("SLABDRIVER.PY \tcreate_sliver lease %s " %(lease))
234             
235             if not lease.get('lease_id'):
236                 if get_authority(lease['component_id']) == self.root_auth:
237                     single_requested_lease['hostname'] = \
238                                         slab_xrn_to_hostname(\
239                                         lease.get('component_id').strip())
240                     single_requested_lease['start_time'] = \
241                                                         lease.get('start_time')
242                     single_requested_lease['duration'] = lease.get('duration')
243
244                     requested_lease_list.append(single_requested_lease)
245                 
246         logger.debug("SLABDRIVER.PY \tcreate_sliver APRESLEASE" )       
247         #Create dict of leases by start_time, regrouping nodes reserved
248         #at the same
249         #time, for the same amount of time = one job on OAR
250         requested_job_dict = {}
251         for lease in requested_lease_list:
252             
253             #In case it is an asap experiment start_time is empty
254             if lease['start_time'] == '':
255                 lease['start_time'] = '0' 
256                 
257             if lease['start_time'] not in requested_job_dict:
258                 if isinstance(lease['hostname'], str):
259                     lease['hostname'] =  [lease['hostname']]
260                     
261                 requested_job_dict[lease['start_time']] = lease
262                 
263             else :
264                 job_lease = requested_job_dict[lease['start_time']]
265                 if lease['duration'] == job_lease['duration'] :
266                     job_lease['hostname'].append(lease['hostname'])
267                     
268           
269                 
270                         
271         logger.debug("SLABDRIVER.PY \tcreate_sliver  requested_job_dict %s "\
272                                                      %(requested_job_dict))    
273         #verify_slice_leases returns the leases , but the return value is unused
274         #here. Removed SA 13/08/12           
275         slices.verify_slice_leases(sfa_slice, \
276                                     requested_job_dict, peer)
277         
278         return aggregate.get_rspec(slice_xrn=slice_urn, login=sfa_slice['login'],version=rspec.version)
279         
280         
281     def delete_sliver (self, slice_urn, slice_hrn, creds, options):
282         
283         sfa_slice_list  = self.GetSlices(slice_filter = slice_hrn, \
284                                             slice_filter_type = 'slice_hrn')
285         
286         if not sfa_slice_list:
287             return 1
288         
289         #Delete all in the slice
290         for sfa_slice in sfa_slice_list:
291
292         
293             logger.debug("SLABDRIVER.PY delete_sliver slice %s" %(sfa_slice))
294             slices = SlabSlices(self)
295             # determine if this is a peer slice
296         
297             peer = slices.get_peer(slice_hrn) 
298             #TODO delete_sliver SA : UnBindObjectFromPeer should be 
299             #used when there is another 
300             #senslab testbed, which is not the case 14/08/12 . 
301             
302             logger.debug("SLABDRIVER.PY delete_sliver peer %s" %(peer))
303             try:
304                 if peer:
305                     self.UnBindObjectFromPeer('slice', \
306                                             sfa_slice['record_id_slice'], \
307                                             peer, None)
308                 self.DeleteSliceFromNodes(sfa_slice)
309             finally:
310                 if peer:
311                     self.BindObjectToPeer('slice', \
312                                             sfa_slice['record_id_slice'], \
313                                             peer, sfa_slice['peer_slice_id'])
314             return 1
315             
316             
317     def AddSlice(self, slice_record, user_record):
318         """Add slice to the sfa tables and senslab table only if the user
319         already exists in senslab database(user already registered in LDAP).
320         There is no way to separate adding the slice to the tesbed 
321         and then importing it from the testbed to SFA because of
322         senslab's architecture. Therefore, sfa tables are updated here.
323         """
324  
325         sfa_record = RegSlice(hrn=slice_record['slice_hrn'], 
326                                 gid=slice_record['gid'], 
327                                 pointer=slice_record['slice_id'],
328                                 authority=slice_record['authority'])
329                                 
330         logger.debug("SLABDRIVER.PY AddSlice  sfa_record %s user_record %s" \
331                                                     %(sfa_record, user_record))
332         sfa_record.just_created()
333         dbsession.add(sfa_record)
334         dbsession.commit() 
335         #Update the reg-researcher dependance table
336         sfa_record.reg_researchers =  [user_record]
337         dbsession.commit()       
338      
339         #Update the senslab table with the new slice                     
340         #slab_slice = SenslabXP( slice_hrn = slice_record['slice_hrn'], \
341                         #record_id_slice = sfa_record.record_id , \
342                         #record_id_user = slice_record['record_id_user'], \
343                         #peer_authority = slice_record['peer_authority'])
344                         
345         #logger.debug("SLABDRIVER.PY \tAddSlice slice_record %s \
346                                     #slab_slice %s sfa_record %s" \
347                                     #%(slice_record,slab_slice, sfa_record))
348         #slab_dbsession.add(slab_slice)
349         #slab_dbsession.commit()
350         return
351         
352     # first 2 args are None in case of resource discovery
353     def list_resources (self, slice_urn, slice_hrn, creds, options):
354         #cached_requested = options.get('cached', True) 
355     
356         version_manager = VersionManager()
357         # get the rspec's return format from options
358         rspec_version = \
359                 version_manager.get_version(options.get('geni_rspec_version'))
360         version_string = "rspec_%s" % (rspec_version)
361     
362         #panos adding the info option to the caching key (can be improved)
363         if options.get('info'):
364             version_string = version_string + "_" + \
365                                         options.get('info', 'default')
366                                         
367         # Adding the list_leases option to the caching key
368         if options.get('list_leases'):
369             version_string = version_string + "_"+options.get('list_leases', 'default')
370             
371         # Adding geni_available to caching key
372         if options.get('geni_available'):
373             version_string = version_string + "_" + str(options.get('geni_available'))
374     
375         # look in cache first
376         #if cached_requested and self.cache and not slice_hrn:
377             #rspec = self.cache.get(version_string)
378             #if rspec:
379                 #logger.debug("SlabDriver.ListResources: \
380                                     #returning cached advertisement")
381                 #return rspec 
382     
383         #panos: passing user-defined options
384         aggregate = SlabAggregate(self)
385         #origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
386         #options.update({'origin_hrn':origin_hrn})
387         rspec =  aggregate.get_rspec(slice_xrn=slice_urn, \
388                                         version=rspec_version, options=options)
389        
390         # cache the result
391         #if self.cache and not slice_hrn:
392             #logger.debug("Slab.ListResources: stores advertisement in cache")
393             #self.cache.add(version_string, rspec)
394     
395         return rspec
396         
397         
398     def list_slices (self, creds, options):
399         # look in cache first
400         #if self.cache:
401             #slices = self.cache.get('slices')
402             #if slices:
403                 #logger.debug("PlDriver.list_slices returns from cache")
404                 #return slices
405     
406         # get data from db 
407
408         slices = self.GetSlices()        
409         logger.debug("SLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n" %(slices))        
410         slice_hrns = [slab_slice['hrn'] for slab_slice in slices]
411
412         slice_urns = [hrn_to_urn(slice_hrn, 'slice') \
413                                                 for slice_hrn in slice_hrns]
414
415         # cache the result
416         #if self.cache:
417             #logger.debug ("SlabDriver.list_slices stores value in cache")
418             #self.cache.add('slices', slice_urns) 
419     
420         return slice_urns
421     
422    
423     def register (self, sfa_record, hrn, pub_key):
424         """ 
425         Adding new user, slice, node or site should not be handled
426         by SFA.
427         
428         Adding nodes = OAR
429         Adding users = LDAP Senslab
430         Adding slice = Import from LDAP users
431         Adding site = OAR
432         """
433         return -1
434             
435       
436     def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
437         """No site or node record update allowed in Senslab."""
438         
439         pointer = old_sfa_record['pointer']
440         old_sfa_record_type = old_sfa_record['type']
441
442         # new_key implemented for users only
443         if new_key and old_sfa_record_type not in [ 'user' ]:
444             raise UnknownSfaType(old_sfa_record_type)
445         
446         #if (type == "authority"):
447             #self.shell.UpdateSite(pointer, new_sfa_record)
448     
449         if old_sfa_record_type == "slice":
450             slab_record = self.sfa_fields_to_slab_fields(old_sfa_record_type, \
451                                                 hrn, new_sfa_record)
452             if 'name' in slab_record:
453                 slab_record.pop('name')
454                 #Prototype should be UpdateSlice(self,
455                 #auth, slice_id_or_name, slice_fields)
456                 #Senslab cannot update slice since slice = job
457                 #so we must delete and create another job
458                 self.UpdateSlice(pointer, slab_record)
459     
460         elif old_sfa_record_type == "user":
461             update_fields = {}
462             all_fields = new_sfa_record
463             for key in all_fields.keys():
464                 if key in ['first_name', 'last_name', 'title', 'email',
465                            'password', 'phone', 'url', 'bio', 'accepted_aup',
466                            'enabled']:
467                     update_fields[key] = all_fields[key]
468             self.UpdatePerson(pointer, update_fields)
469     
470             if new_key:
471                 # must check this key against the previous one if it exists
472                 persons = self.GetPersons([pointer], ['key_ids'])
473                 person = persons[0]
474                 keys = person['key_ids']
475                 keys = self.GetKeys(person['key_ids'])
476                 
477                 # Delete all stale keys
478                 key_exists = False
479                 for key in keys:
480                     if new_key != key['key']:
481                         self.DeleteKey(key['key_id'])
482                     else:
483                         key_exists = True
484                 if not key_exists:
485                     self.AddPersonKey(pointer, {'key_type': 'ssh', \
486                                                     'key': new_key})
487
488
489         return True
490         
491
492     def remove (self, sfa_record):
493         sfa_record_type = sfa_record['type']
494         hrn = sfa_record['hrn']
495         if sfa_record_type == 'user':
496
497             #get user from senslab ldap  
498             person = self.GetPersons(sfa_record)
499             #No registering at a given site in Senslab.
500             #Once registered to the LDAP, all senslab sites are
501             #accesible.
502             if person :
503                 #Mark account as disabled in ldap
504                 self.DeletePerson(sfa_record)
505         elif sfa_record_type == 'slice':
506             if self.GetSlices(slice_filter = hrn, \
507                                     slice_filter_type = 'slice_hrn'):
508                 self.DeleteSlice(sfa_record)
509
510         #elif type == 'authority':
511             #if self.GetSites(pointer):
512                 #self.DeleteSite(pointer)
513
514         return True
515             
516             
517             
518     #TODO clean GetPeers. 05/07/12SA        
519     def GetPeers (self, auth = None, peer_filter=None, return_fields_list=None):
520
521         existing_records = {}
522         existing_hrns_by_types = {}
523         logger.debug("SLABDRIVER \tGetPeers auth = %s, peer_filter %s, \
524                     return_field %s " %(auth , peer_filter, return_fields_list))
525         all_records = dbsession.query(RegRecord).filter(RegRecord.type.like('%authority%')).all()
526         
527         for record in all_records:
528             existing_records[(record.hrn, record.type)] = record
529             if record.type not in existing_hrns_by_types:
530                 existing_hrns_by_types[record.type] = [record.hrn]
531             else:
532                 existing_hrns_by_types[record.type].append(record.hrn)
533
534                         
535         logger.debug("SLABDRIVER \tGetPeer\texisting_hrns_by_types %s "\
536                                              %( existing_hrns_by_types))
537         records_list = [] 
538       
539         try: 
540             if peer_filter:
541                 records_list.append(existing_records[(peer_filter,'authority')])
542             else :
543                 for hrn in existing_hrns_by_types['authority']:
544                     records_list.append(existing_records[(hrn,'authority')])
545                     
546             logger.debug("SLABDRIVER \tGetPeer \trecords_list  %s " \
547                                             %(records_list))
548
549         except KeyError:
550             pass
551                 
552         return_records = records_list
553         if not peer_filter and not return_fields_list:
554             return records_list
555
556        
557         logger.debug("SLABDRIVER \tGetPeer return_records %s " \
558                                                     %(return_records))
559         return return_records
560         
561      
562     #TODO  : Handling OR request in make_ldap_filters_from_records 
563     #instead of the for loop 
564     #over the records' list
565     def GetPersons(self, person_filter=None):
566         """
567         person_filter should be a list of dictionnaries when not set to None.
568         Returns a list of users whose accounts are enabled found in ldap.
569        
570         """
571         logger.debug("SLABDRIVER \tGetPersons person_filter %s" \
572                                                     %(person_filter))
573         person_list = []
574         if person_filter and isinstance(person_filter, list):
575         #If we are looking for a list of users (list of dict records)
576         #Usually the list contains only one user record
577             for searched_attributes in person_filter:
578                 
579                 #Get only enabled user accounts in senslab LDAP : 
580                 #add a filter for make_ldap_filters_from_record
581                 person = self.ldap.LdapFindUser(searched_attributes, \
582                                 is_user_enabled=True)
583                 #If a person was found, append it to the list
584                 if person:
585                     person_list.append(person)
586                     
587             #If the list is empty, return None
588             if len(person_list) is 0:
589                 person_list = None
590           
591         else:
592             #Get only enabled user accounts in senslab LDAP : 
593             #add a filter for make_ldap_filters_from_record
594             person_list  = self.ldap.LdapFindUser(is_user_enabled=True)  
595
596         return person_list
597
598     def GetTimezone(self):
599         """ Get the OAR servier time and timezone.
600         Unused SA 16/11/12"""
601         server_timestamp, server_tz = self.oar.parser.\
602                                             SendRequest("GET_timezone")
603         return server_timestamp, server_tz
604     
605
606     def DeleteJobs(self, job_id, slice_hrn):
607         if not job_id or job_id is -1:
608             return
609         username  = slice_hrn.split(".")[-1].rstrip("_slice")
610         reqdict = {}
611         reqdict['method'] = "delete"
612         reqdict['strval'] = str(job_id)
613        
614
615         answer = self.oar.POSTRequestToOARRestAPI('DELETE_jobs_id', \
616                                                     reqdict,username)
617         logger.debug("SLABDRIVER \tDeleteJobs jobid  %s \r\n answer %s \
618                                 username %s" %(job_id,answer, username))
619         return answer
620
621             
622         
623         ##TODO : Unused GetJobsId ? SA 05/07/12
624     #def GetJobsId(self, job_id, username = None ):
625         #"""
626         #Details about a specific job. 
627         #Includes details about submission time, jot type, state, events, 
628         #owner, assigned ressources, walltime etc...
629             
630         #"""
631         #req = "GET_jobs_id"
632         #node_list_k = 'assigned_network_address'
633         ##Get job info from OAR    
634         #job_info = self.oar.parser.SendRequest(req, job_id, username)
635
636         #logger.debug("SLABDRIVER \t GetJobsId  %s " %(job_info))
637         #try:
638             #if job_info['state'] == 'Terminated':
639                 #logger.debug("SLABDRIVER \t GetJobsId job %s TERMINATED"\
640                                                             #%(job_id))
641                 #return None
642             #if job_info['state'] == 'Error':
643                 #logger.debug("SLABDRIVER \t GetJobsId ERROR message %s "\
644                                                             #%(job_info))
645                 #return None
646                                                             
647         #except KeyError:
648             #logger.error("SLABDRIVER \tGetJobsId KeyError")
649             #return None 
650         
651         #parsed_job_info  = self.get_info_on_reserved_nodes(job_info, \
652                                                             #node_list_k)
653         ##Replaces the previous entry 
654         ##"assigned_network_address" / "reserved_resources"
655         ##with "node_ids"
656         #job_info.update({'node_ids':parsed_job_info[node_list_k]})
657         #del job_info[node_list_k]
658         #logger.debug(" \r\nSLABDRIVER \t GetJobsId job_info %s " %(job_info))
659         #return job_info
660
661         
662     def GetJobsResources(self, job_id, username = None):
663         #job_resources=['reserved_resources', 'assigned_resources',\
664                             #'job_id', 'job_uri', 'assigned_nodes',\
665                              #'api_timestamp']
666         #assigned_res = ['resource_id', 'resource_uri']
667         #assigned_n = ['node', 'node_uri']
668
669         req = "GET_jobs_id_resources"
670        
671                
672         #Get job resources list from OAR    
673         node_id_list = self.oar.parser.SendRequest(req, job_id, username)
674         logger.debug("SLABDRIVER \t GetJobsResources  %s " %(node_id_list))
675         
676         hostname_list = \
677             self.__get_hostnames_from_oar_node_ids(node_id_list)
678         
679
680         #Replaces the previous entry "assigned_network_address" / 
681         #"reserved_resources"
682         #with "node_ids"
683         job_info = {'node_ids': hostname_list}
684
685         return job_info
686
687             
688     def get_info_on_reserved_nodes(self, job_info, node_list_name):
689         #Get the list of the testbed nodes records and make a 
690         #dictionnary keyed on the hostname out of it
691         node_list_dict = self.GetNodes() 
692         #node_hostname_list = []
693         node_hostname_list = [node['hostname'] for node in node_list_dict] 
694         #for node in node_list_dict:
695             #node_hostname_list.append(node['hostname'])
696         node_dict = dict(zip(node_hostname_list, node_list_dict))
697         try :
698             reserved_node_hostname_list = []
699             for index in range(len(job_info[node_list_name])):
700                #job_info[node_list_name][k] = 
701                 reserved_node_hostname_list[index] = \
702                         node_dict[job_info[node_list_name][index]]['hostname']
703                             
704             logger.debug("SLABDRIVER \t get_info_on_reserved_nodes \
705                         reserved_node_hostname_list %s" \
706                         %(reserved_node_hostname_list))
707         except KeyError:
708             logger.error("SLABDRIVER \t get_info_on_reserved_nodes KEYERROR " )
709             
710         return reserved_node_hostname_list  
711             
712     def GetNodesCurrentlyInUse(self):
713         """Returns a list of all the nodes already involved in an oar job"""
714         return self.oar.parser.SendRequest("GET_running_jobs") 
715     
716     def __get_hostnames_from_oar_node_ids(self, resource_id_list ):
717         full_nodes_dict_list = self.GetNodes()
718         #Put the full node list into a dictionary keyed by oar node id
719         oar_id_node_dict = {}
720         for node in full_nodes_dict_list:
721             oar_id_node_dict[node['oar_id']] = node
722             
723         #logger.debug("SLABDRIVER \t  __get_hostnames_from_oar_node_ids\
724                         #oar_id_node_dict %s" %(oar_id_node_dict))
725
726         hostname_dict_list = [] 
727         for resource_id in resource_id_list:
728             #Because jobs requested "asap" do not have defined resources
729             if resource_id is not "Undefined":
730                 hostname_dict_list.append(\
731                         oar_id_node_dict[resource_id]['hostname'])
732                 
733             #hostname_list.append(oar_id_node_dict[resource_id]['hostname'])
734         return hostname_dict_list 
735         
736     def GetReservedNodes(self,username = None):
737         #Get the nodes in use and the reserved nodes
738         reservation_dict_list = \
739                         self.oar.parser.SendRequest("GET_reserved_nodes", \
740                         username = username)
741         
742         
743         for resa in reservation_dict_list:
744             logger.debug ("GetReservedNodes resa %s"%(resa))
745             #dict list of hostnames and their site
746             resa['reserved_nodes'] = \
747                 self.__get_hostnames_from_oar_node_ids(resa['resource_ids'])
748                 
749         #del resa['resource_ids']
750         return reservation_dict_list
751      
752     def GetNodes(self, node_filter_dict = None, return_fields_list = None):
753         """
754         node_filter_dict : dictionnary of lists
755         
756         """
757         node_dict_by_id = self.oar.parser.SendRequest("GET_resources_full")
758         node_dict_list = node_dict_by_id.values()
759         logger.debug (" SLABDRIVER GetNodes  node_filter_dict %s \
760             return_fields_list %s "%(node_filter_dict, return_fields_list))
761         #No  filtering needed return the list directly
762         if not (node_filter_dict or return_fields_list):
763             return node_dict_list
764         
765         return_node_list = []
766         if node_filter_dict:
767             for filter_key in node_filter_dict:
768                 try:
769                     #Filter the node_dict_list by each value contained in the 
770                     #list node_filter_dict[filter_key]
771                     for value in node_filter_dict[filter_key]:
772                         for node in node_dict_list:
773                             if node[filter_key] == value:
774                                 if return_fields_list :
775                                     tmp = {}
776                                     for k in return_fields_list:
777                                         tmp[k] = node[k]     
778                                     return_node_list.append(tmp)
779                                 else:
780                                     return_node_list.append(node)
781                 except KeyError:
782                     logger.log_exc("GetNodes KeyError")
783                     return
784
785
786         return return_node_list
787     
788   
789     def GetSites(self, site_filter_name_list = None, return_fields_list = None):
790         site_dict = self.oar.parser.SendRequest("GET_sites")
791         #site_dict : dict where the key is the sit ename
792         return_site_list = []
793         if not ( site_filter_name_list or return_fields_list):
794             return_site_list = site_dict.values()
795             return return_site_list
796         
797         for site_filter_name in site_filter_name_list:
798             if site_filter_name in site_dict:
799                 if return_fields_list:
800                     for field in return_fields_list:
801                         tmp = {}
802                         try:
803                             tmp[field] = site_dict[site_filter_name][field]
804                         except KeyError:
805                             logger.error("GetSites KeyError %s "%(field))
806                             return None
807                     return_site_list.append(tmp)
808                 else:
809                     return_site_list.append( site_dict[site_filter_name])
810             
811
812         return return_site_list
813                 
814                 
815     def _sql_get_slice_info( self, slice_filter ):
816         #DO NOT USE RegSlice - reg_researchers to get the hrn 
817         #of the user otherwise will mess up the RegRecord in 
818         #Resolve, don't know why - SA 08/08/2012
819         
820         #Only one entry for one user  = one slice in slab_xp table
821         #slicerec = dbsession.query(RegRecord).filter_by(hrn = slice_filter).first()
822         raw_slicerec = dbsession.query(RegSlice).options(joinedload('reg_researchers')).filter_by(hrn = slice_filter).first()
823         #raw_slicerec = dbsession.query(RegRecord).filter_by(hrn = slice_filter).first()
824         if raw_slicerec: 
825             #load_reg_researcher
826             #raw_slicerec.reg_researchers
827             raw_slicerec = raw_slicerec.__dict__
828             logger.debug(" SLABDRIVER \t  get_slice_info slice_filter %s  raw_slicerec %s"%(slice_filter,raw_slicerec))
829             slicerec = raw_slicerec
830             #only one researcher per slice so take the first one
831             #slicerec['reg_researchers'] = raw_slicerec['reg_researchers']
832             #del slicerec['reg_researchers']['_sa_instance_state']
833             return slicerec
834         
835         else :
836             return None
837             
838             
839     def _sql_get_slice_info_from_user( self, slice_filter ): 
840         #slicerec = dbsession.query(RegRecord).filter_by(record_id = slice_filter).first()
841         raw_slicerec = dbsession.query(RegUser).options(joinedload('reg_slices_as_researcher')).filter_by(record_id = slice_filter).first()
842         #raw_slicerec = dbsession.query(RegRecord).filter_by(record_id = slice_filter).first()
843         #Put it in correct order 
844         user_needed_fields = ['peer_authority', 'hrn', 'last_updated', 'classtype', 'authority', 'gid', 'record_id', 'date_created', 'type', 'email', 'pointer']
845         slice_needed_fields = ['peer_authority', 'hrn', 'last_updated', 'classtype', 'authority', 'gid', 'record_id', 'date_created', 'type', 'pointer']
846         if raw_slicerec:
847             #raw_slicerec.reg_slices_as_researcher
848             raw_slicerec = raw_slicerec.__dict__
849             slicerec = {}
850             slicerec = dict([(k,raw_slicerec['reg_slices_as_researcher'][0].__dict__[k]) for k in slice_needed_fields])
851             slicerec['reg_researchers'] = dict([(k, raw_slicerec[k]) for k in user_needed_fields])
852              #TODO Handle multiple slices for one user SA 10/12/12
853                         #for now only take the first slice record associated to the rec user
854                         ##slicerec  = raw_slicerec['reg_slices_as_researcher'][0].__dict__
855                         #del raw_slicerec['reg_slices_as_researcher']
856                         #slicerec['reg_researchers'] = raw_slicerec
857                         ##del slicerec['_sa_instance_state']
858                                    
859             return slicerec
860         
861         else:
862             return None
863             
864     def _get_slice_records(self, slice_filter = None, \
865                     slice_filter_type = None):
866        
867         #login = None
868         
869         #Get list of slices based on the slice hrn
870         if slice_filter_type == 'slice_hrn':
871             
872             #if get_authority(slice_filter) == self.root_auth:
873                 #login = slice_filter.split(".")[1].split("_")[0] 
874             
875             slicerec = self._sql_get_slice_info(slice_filter)
876             
877             if slicerec is None:
878                 return  None                        
879                 #return login, None    
880             
881         #Get slice based on user id                             
882         if slice_filter_type == 'record_id_user': 
883             
884             slicerec = self._sql_get_slice_info_from_user(slice_filter)
885                 
886         if slicerec:
887             fixed_slicerec_dict = slicerec
888             #At this point if the there is no login it means 
889             #record_id_user filter has been used for filtering
890             #if login is None :
891                 ##If theslice record is from senslab
892                 #if fixed_slicerec_dict['peer_authority'] is None:
893                     #login = fixed_slicerec_dict['hrn'].split(".")[1].split("_")[0] 
894             #return login, fixed_slicerec_dict
895             return fixed_slicerec_dict                  
896                   
897     def GetSlices(self, slice_filter = None, slice_filter_type = None, login=None):
898         """ Get the slice records from the slab db. 
899         Returns a slice ditc if slice_filter  and slice_filter_type 
900         are specified.
901         Returns a list of slice dictionnaries if there are no filters
902         specified. 
903        
904         """
905         #login = None
906         authorized_filter_types_list = ['slice_hrn', 'record_id_user']
907         return_slicerec_dictlist = []
908         
909         #First try to get information on the slice based on the filter provided     
910         if slice_filter_type in authorized_filter_types_list:
911             fixed_slicerec_dict = \
912                             self._get_slice_records(slice_filter, slice_filter_type)
913             #login, fixed_slicerec_dict = \
914                             #self._get_slice_records(slice_filter, slice_filter_type)
915             logger.debug(" SLABDRIVER \tGetSlices login %s \
916                             slice record %s slice_filter %s slice_filter_type %s "\
917                             %(login, fixed_slicerec_dict,slice_filter, slice_filter_type))
918     
919             
920             #Now we have the slice record fixed_slicerec_dict, get the 
921             #jobs associated to this slice
922             #leases_list = self.GetReservedNodes(username = login)
923             leases_list = self.GetLeases(login = login)
924             #If no job is running or no job scheduled 
925             #return only the slice record           
926             if leases_list == [] and fixed_slicerec_dict:
927                 return_slicerec_dictlist.append(fixed_slicerec_dict)
928                 
929             #If several jobs for one slice , put the slice record into 
930             # each lease information dict
931             for lease in leases_list : 
932                 slicerec_dict = {} 
933                 
934                 reserved_list = lease['reserved_nodes']
935                 
936                 slicerec_dict['oar_job_id']= lease['lease_id']
937                 slicerec_dict.update({'list_node_ids':{'hostname':reserved_list}})   
938                 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
939                 
940                 #Update lease dict with the slice record
941                 if fixed_slicerec_dict:
942                     fixed_slicerec_dict['oar_job_id'] = []
943                     fixed_slicerec_dict['oar_job_id'].append(slicerec_dict['oar_job_id'])
944                     slicerec_dict.update(fixed_slicerec_dict)
945                     #slicerec_dict.update({'hrn':\
946                                     #str(fixed_slicerec_dict['slice_hrn'])})
947                     
948     
949                 return_slicerec_dictlist.append(slicerec_dict)
950                 logger.debug("SLABDRIVER.PY  \tGetSlices  \
951                         slicerec_dict %s return_slicerec_dictlist %s \
952                         lease['reserved_nodes'] \
953                         %s" %(slicerec_dict, return_slicerec_dictlist, \
954                         lease['reserved_nodes'] ))
955                 
956             logger.debug("SLABDRIVER.PY  \tGetSlices  RETURN \
957                         return_slicerec_dictlist  %s" \
958                         %(return_slicerec_dictlist))
959                             
960             return return_slicerec_dictlist
961                 
962                 
963         else:
964             #Get all slices from the senslab sfa database ,
965             #put them in dict format 
966             #query_slice_list = dbsession.query(RegRecord).all()           
967             query_slice_list = dbsession.query(RegSlice).options(joinedload('reg_researchers')).all()          
968             #query_slice_list = dbsession.query(RegRecord).filter_by(type='slice').all()
969             #query_slice_list = slab_dbsession.query(SenslabXP).all()
970             return_slicerec_dictlist = []
971             for record in query_slice_list: 
972                 tmp = record.__dict__
973                 tmp['reg_researchers'] = tmp['reg_researchers'][0].__dict__
974                 #del tmp['reg_researchers']['_sa_instance_state']
975                 return_slicerec_dictlist.append(tmp)
976                 #return_slicerec_dictlist.append(record.__dict__)
977                 
978             #Get all the jobs reserved nodes
979             leases_list = self.GetReservedNodes()
980             
981                
982             for fixed_slicerec_dict in return_slicerec_dictlist:
983                 slicerec_dict = {} 
984                 #Check if the slice belongs to a senslab user
985                 if fixed_slicerec_dict['peer_authority'] is None:
986                     owner = fixed_slicerec_dict['hrn'].split(".")[1].split("_")[0] 
987                 else:
988                     owner = None
989                 for lease in leases_list:   
990                     if owner == lease['user']:
991                         slicerec_dict['oar_job_id'] = lease['lease_id']
992
993                         #for reserved_node in lease['reserved_nodes']:
994                         logger.debug("SLABDRIVER.PY  \tGetSlices lease %s "\
995                                                                  %(lease ))
996
997                         reserved_list = lease['reserved_nodes']
998
999                         slicerec_dict.update({'node_ids':lease['reserved_nodes']})
1000                         slicerec_dict.update({'list_node_ids':{'hostname':reserved_list}}) 
1001                         slicerec_dict.update(fixed_slicerec_dict)
1002                         #slicerec_dict.update({'hrn':\
1003                                     #str(fixed_slicerec_dict['slice_hrn'])})
1004                         #return_slicerec_dictlist.append(slicerec_dict)
1005                         fixed_slicerec_dict.update(slicerec_dict)
1006                         
1007             logger.debug("SLABDRIVER.PY  \tGetSlices RETURN \
1008                         return_slicerec_dictlist %s \slice_filter %s " \
1009                         %(return_slicerec_dictlist, slice_filter))
1010
1011         return return_slicerec_dictlist
1012         
1013     
1014     def testbed_name (self): return self.hrn
1015          
1016     # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
1017     def aggregate_version (self):
1018         version_manager = VersionManager()
1019         ad_rspec_versions = []
1020         request_rspec_versions = []
1021         for rspec_version in version_manager.versions:
1022             if rspec_version.content_type in ['*', 'ad']:
1023                 ad_rspec_versions.append(rspec_version.to_dict())
1024             if rspec_version.content_type in ['*', 'request']:
1025                 request_rspec_versions.append(rspec_version.to_dict()) 
1026         return {
1027             'testbed':self.testbed_name(),
1028             'geni_request_rspec_versions': request_rspec_versions,
1029             'geni_ad_rspec_versions': ad_rspec_versions,
1030             }
1031           
1032
1033           
1034     ##
1035     # Convert SFA fields to PLC fields for use when registering up updating
1036     # registry record in the PLC database
1037     #
1038     # @param type type of record (user, slice, ...)
1039     # @param hrn human readable name
1040     # @param sfa_fields dictionary of SFA fields
1041     # @param slab_fields dictionary of PLC fields (output)
1042
1043     def sfa_fields_to_slab_fields(self, sfa_type, hrn, record):
1044
1045
1046         slab_record = {}
1047         #for field in record:
1048         #    slab_record[field] = record[field]
1049  
1050         if sfa_type == "slice":
1051             #instantion used in get_slivers ? 
1052             if not "instantiation" in slab_record:
1053                 slab_record["instantiation"] = "senslab-instantiated"
1054             #slab_record["hrn"] = hrn_to_pl_slicename(hrn)     
1055             #Unused hrn_to_pl_slicename because Slab's hrn already 
1056             #in the appropriate form SA 23/07/12
1057             slab_record["hrn"] = hrn 
1058             logger.debug("SLABDRIVER.PY sfa_fields_to_slab_fields \
1059                         slab_record %s  " %(slab_record['hrn']))
1060             if "url" in record:
1061                 slab_record["url"] = record["url"]
1062             if "description" in record:
1063                 slab_record["description"] = record["description"]
1064             if "expires" in record:
1065                 slab_record["expires"] = int(record["expires"])
1066                 
1067         #nodes added by OAR only and then imported to SFA
1068         #elif type == "node":
1069             #if not "hostname" in slab_record:
1070                 #if not "hostname" in record:
1071                     #raise MissingSfaInfo("hostname")
1072                 #slab_record["hostname"] = record["hostname"]
1073             #if not "model" in slab_record:
1074                 #slab_record["model"] = "geni"
1075                 
1076         #One authority only 
1077         #elif type == "authority":
1078             #slab_record["login_base"] = hrn_to_slab_login_base(hrn)
1079
1080             #if not "name" in slab_record:
1081                 #slab_record["name"] = hrn
1082
1083             #if not "abbreviated_name" in slab_record:
1084                 #slab_record["abbreviated_name"] = hrn
1085
1086             #if not "enabled" in slab_record:
1087                 #slab_record["enabled"] = True
1088
1089             #if not "is_public" in slab_record:
1090                 #slab_record["is_public"] = True
1091
1092         return slab_record
1093
1094     
1095
1096             
1097     def __transforms_timestamp_into_date(self, xp_utc_timestamp = None):
1098         """ Transforms unix timestamp into valid OAR date format """
1099         
1100         #Used in case of a scheduled experiment (not immediate)
1101         #To run an XP immediately, don't specify date and time in RSpec 
1102         #They will be set to None. 
1103         if xp_utc_timestamp:
1104             #transform the xp_utc_timestamp into server readable time  
1105             xp_server_readable_date = datetime.fromtimestamp(int(\
1106                                 xp_utc_timestamp)).strftime(self.time_format)
1107
1108             return xp_server_readable_date
1109             
1110         else:
1111             return None
1112         
1113    
1114
1115              
1116     def LaunchExperimentOnOAR(self, added_nodes, slice_name, \
1117                         lease_start_time, lease_duration, slice_user=None):
1118         lease_dict = {}
1119         lease_dict['lease_start_time'] = lease_start_time
1120         lease_dict['lease_duration'] = lease_duration
1121         lease_dict['added_nodes'] = added_nodes
1122         lease_dict['slice_name'] = slice_name
1123         lease_dict['slice_user'] = slice_user
1124         lease_dict['grain'] = self.GetLeaseGranularity()
1125         lease_dict['time_format'] = self.time_format
1126
1127         
1128         def __create_job_structure_request_for_OAR(lease_dict):
1129             """ Creates the structure needed for a correct POST on OAR.
1130             Makes the timestamp transformation into the appropriate format.
1131             Sends the POST request to create the job with the resources in 
1132             added_nodes.
1133             
1134             """
1135
1136             nodeid_list = []
1137             reqdict = {}
1138     
1139             
1140             reqdict['workdir'] = '/tmp'   
1141             reqdict['resource'] = "{network_address in ("   
1142     
1143             for node in lease_dict['added_nodes']: 
1144                 logger.debug("\r\n \r\n OARrestapi \t \
1145                 __create_job_structure_request_for_OAR node %s" %(node))
1146     
1147                 # Get the ID of the node 
1148                 nodeid = node
1149                 reqdict['resource'] += "'" + nodeid + "', "
1150                 nodeid_list.append(nodeid)
1151     
1152             custom_length = len(reqdict['resource'])- 2
1153             reqdict['resource'] = reqdict['resource'][0:custom_length] + \
1154                                                 ")}/nodes=" + str(len(nodeid_list))
1155     
1156             def __process_walltime(duration):
1157                 """ Calculates the walltime in seconds from the duration in H:M:S
1158                     specified in the RSpec.
1159                     
1160                 """
1161                 if duration:
1162                     # Fixing the walltime by adding a few delays. 
1163                     # First put the walltime in seconds oarAdditionalDelay = 20;
1164                     #  additional delay for /bin/sleep command to
1165                     # take in account  prologue and epilogue scripts execution
1166                     # int walltimeAdditionalDelay = 240;  additional delay
1167                     desired_walltime = duration 
1168                     total_walltime = desired_walltime + 240 #+4 min Update SA 23/10/12
1169                     sleep_walltime = desired_walltime  # 0 sec added Update SA 23/10/12
1170                     walltime = []
1171                     #Put the walltime back in str form
1172                     #First get the hours
1173                     walltime.append(str(total_walltime / 3600))
1174                     total_walltime = total_walltime - 3600 * int(walltime[0])
1175                     #Get the remaining minutes
1176                     walltime.append(str(total_walltime / 60))
1177                     total_walltime = total_walltime - 60 * int(walltime[1])
1178                     #Get the seconds
1179                     walltime.append(str(total_walltime))
1180     
1181                 else:
1182                     logger.log_exc(" __process_walltime duration null")
1183                     
1184                 return walltime, sleep_walltime
1185                     
1186
1187             walltime, sleep_walltime = \
1188                         __process_walltime(int(lease_dict['lease_duration'])*lease_dict['grain'])
1189     
1190     
1191             reqdict['resource'] += ",walltime=" + str(walltime[0]) + \
1192                                 ":" + str(walltime[1]) + ":" + str(walltime[2])
1193             reqdict['script_path'] = "/bin/sleep " + str(sleep_walltime)
1194     
1195             #In case of a scheduled experiment (not immediate)
1196             #To run an XP immediately, don't specify date and time in RSpec 
1197             #They will be set to None.
1198             if lease_dict['lease_start_time'] is not '0':
1199                 #Readable time accepted by OAR
1200                 start_time = datetime.fromtimestamp(int(lease_dict['lease_start_time'])).\
1201                                                         strftime(lease_dict['time_format'])
1202                 reqdict['reservation'] = start_time
1203             #If there is not start time, Immediate XP. No need to add special 
1204             # OAR parameters
1205     
1206     
1207             reqdict['type'] = "deploy" 
1208             reqdict['directory'] = ""
1209             reqdict['name'] = "SFA_" + lease_dict['slice_user']
1210     
1211             return reqdict
1212         
1213         logger.debug("SLABDRIVER.PY \tLaunchExperimentOnOAR slice_user %s\
1214                              \r\n "  %(slice_user))                             
1215         #Create the request for OAR
1216         reqdict = __create_job_structure_request_for_OAR(lease_dict)
1217          # first step : start the OAR job and update the job 
1218         logger.debug("SLABDRIVER.PY \tLaunchExperimentOnOAR reqdict %s\
1219                              \r\n "  %(reqdict))  
1220        
1221         answer = self.oar.POSTRequestToOARRestAPI('POST_job', \
1222                                                             reqdict, slice_user)
1223         logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid   %s " %(answer))
1224         try:       
1225             jobid = answer['id']
1226         except KeyError:
1227             logger.log_exc("SLABDRIVER \tLaunchExperimentOnOAR \
1228                                 Impossible to create job  %s "  %(answer))
1229             return None
1230         
1231         
1232         def __configure_experiment(jobid, added_nodes):
1233             # second step : configure the experiment
1234             # we need to store the nodes in a yaml (well...) file like this :
1235             # [1,56,23,14,45,75] with name /tmp/sfa<jobid>.json
1236             tmp_dir = '/tmp/sfa/'
1237             if not os.path.exists(tmp_dir):
1238                 os.makedirs(tmp_dir)
1239             job_file = open(tmp_dir + str(jobid) + '.json', 'w')
1240             job_file.write('[')
1241             job_file.write(str(added_nodes[0].strip('node')))
1242             for node in added_nodes[1:len(added_nodes)] :
1243                 job_file.write(', '+ node.strip('node'))
1244             job_file.write(']')
1245             job_file.close()
1246             return 
1247         
1248         def __launch_senslab_experiment(jobid):   
1249             # third step : call the senslab-experiment wrapper
1250             #command= "java -jar target/sfa-1.0-jar-with-dependencies.jar 
1251             # "+str(jobid)+" "+slice_user
1252             javacmdline = "/usr/bin/java"
1253             jarname = \
1254                 "/opt/senslabexperimentwrapper/sfa-1.0-jar-with-dependencies.jar"
1255
1256             output = subprocess.Popen([javacmdline, "-jar", jarname, str(jobid), \
1257                                 slice_user],stdout=subprocess.PIPE).communicate()[0]
1258     
1259             logger.debug("SLABDRIVER \t __configure_experiment wrapper returns%s " \
1260                                                                     %(output))
1261             return 
1262         
1263         
1264         
1265         if jobid :
1266             logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s \
1267                     added_nodes %s slice_user %s" %(jobid, added_nodes, slice_user))
1268             
1269         
1270             __configure_experiment(jobid, added_nodes)
1271             __launch_senslab_experiment(jobid) 
1272             
1273         return jobid
1274         
1275         
1276     def AddLeases(self, hostname_list, slice_record, \
1277                                         lease_start_time, lease_duration):
1278         logger.debug("SLABDRIVER \r\n \r\n \t AddLeases hostname_list %s  \
1279                 slice_record %s lease_start_time %s lease_duration %s  "\
1280                  %( hostname_list, slice_record , lease_start_time, \
1281                  lease_duration))
1282
1283         #tmp = slice_record['reg-researchers'][0].split(".")
1284         username = slice_record['login']
1285         #username = tmp[(len(tmp)-1)]
1286         job_id = self.LaunchExperimentOnOAR(hostname_list, slice_record['hrn'], \
1287                                     lease_start_time, lease_duration, username)
1288         start_time = datetime.fromtimestamp(int(lease_start_time)).strftime(self.time_format)
1289         end_time = lease_start_time + lease_duration
1290
1291         import logging, logging.handlers
1292         from sfa.util.sfalogging import _SfaLogger
1293         logger.debug("SLABDRIVER \r\n \r\n \t AddLeases TURN ON LOGGING SQL %s %s %s "%(slice_record['hrn'], job_id, end_time))
1294         sql_logger = _SfaLogger(loggername = 'sqlalchemy.engine', level=logging.DEBUG)
1295         logger.debug("SLABDRIVER \r\n \r\n \t AddLeases %s %s %s " %(type(slice_record['hrn']), type(job_id), type(end_time)))
1296         slab_ex_row = SenslabXP(slice_hrn = slice_record['hrn'], job_id = job_id,end_time= end_time)
1297         logger.debug("SLABDRIVER \r\n \r\n \t AddLeases slab_ex_row %s" %(slab_ex_row))
1298         slab_dbsession.add(slab_ex_row)
1299         slab_dbsession.commit()
1300         
1301         logger.debug("SLABDRIVER \t AddLeases hostname_list start_time %s " %(start_time))
1302         
1303         return
1304     
1305     
1306     #Delete the jobs from job_senslab table
1307     def DeleteSliceFromNodes(self, slice_record):
1308         for job_id in slice_record['oar_job_id']:
1309             self.DeleteJobs(job_id, slice_record['hrn'])
1310         return   
1311     
1312  
1313     def GetLeaseGranularity(self):
1314         """ Returns the granularity of Senslab testbed.
1315         OAR returns seconds for experiments duration.
1316         Defined in seconds. """
1317         
1318         grain = 60 
1319         return grain
1320     
1321     def update_jobs_in_slabdb(self, job_oar_list, jobs_psql):
1322         #Get all the entries in slab_xp table
1323         
1324
1325         jobs_psql = set(jobs_psql)
1326         kept_jobs = set(job_oar_list).intersection(jobs_psql)
1327         logger.debug ( "\r\n \t\tt update_jobs_in_slabdb jobs_psql %s \r\n \t job_oar_list %s \
1328         kept_jobs %s " %(jobs_psql,job_oar_list,kept_jobs))
1329         deleted_jobs = set(jobs_psql).difference(kept_jobs)
1330         deleted_jobs = list(deleted_jobs)
1331         if len(deleted_jobs) > 0:
1332             slab_dbsession.query(SenslabXP).filter(SenslabXP.job_id.in_(deleted_jobs)).delete(synchronize_session='fetch')
1333             slab_dbsession.commit()
1334         
1335         return
1336
1337         
1338     
1339     def GetLeases(self, lease_filter_dict=None, login=None):
1340         
1341         
1342         unfiltered_reservation_list = self.GetReservedNodes(login)
1343
1344         reservation_list = []
1345         #Find the slice associated with this user senslab ldap uid
1346         logger.debug(" SLABDRIVER.PY \tGetLeases  login %s unfiltered_reservation_list %s " %(login ,unfiltered_reservation_list))
1347         #Create user dict first to avoid looking several times for
1348         #the same user in LDAP SA 27/07/12
1349         resa_user_dict = {}
1350         job_oar_list = []
1351         
1352         jobs_psql_query = slab_dbsession.query(SenslabXP).all()
1353         jobs_psql_dict =  [ (row.job_id, row.__dict__ )for row in jobs_psql_query ]
1354         jobs_psql_dict = dict(jobs_psql_dict)
1355         logger.debug("SLABDRIVER \tGetLeases jobs_psql_dict %s"\
1356                                             %(jobs_psql_dict))
1357         jobs_psql_id_list =  [ row.job_id for row in jobs_psql_query ]
1358         
1359         
1360         
1361         for resa in unfiltered_reservation_list:
1362             logger.debug("SLABDRIVER \tGetLeases USER %s"\
1363                                             %(resa['user']))   
1364             #Cosntruct list of jobs (runing, waiting..) in oar 
1365             job_oar_list.append(resa['lease_id'])  
1366             #If there is information on the job in SLAB DB (slice used and job id) 
1367             if resa['lease_id'] in jobs_psql_dict:
1368                 job_info = jobs_psql_dict[resa['lease_id']]
1369                 logger.debug("SLABDRIVER \tGetLeases resa_user_dict %s"\
1370                                             %(resa_user_dict))        
1371                 resa['slice_hrn'] = job_info['slice_hrn']
1372                 resa['slice_id'] = hrn_to_urn(resa['slice_hrn'], 'slice')
1373                 
1374              #Assume it is a senslab slice:   
1375             else:
1376                 resa['slice_id'] =  hrn_to_urn(self.root_auth+'.'+ resa['user'] +"_slice"  , 'slice')            
1377             #if resa['user'] not in resa_user_dict: 
1378                 #logger.debug("SLABDRIVER \tGetLeases userNOTIN ")
1379                 #ldap_info = self.ldap.LdapSearch('(uid='+resa['user']+')')
1380                 #if ldap_info:
1381                     #ldap_info = ldap_info[0][1]
1382                     ##Get the backref :relationship table reg-researchers 
1383                     #user = dbsession.query(RegUser).options(joinedload('reg_slices_as_researcher')).filter_by(email = \
1384                                                     #ldap_info['mail'][0])
1385                     #if user:
1386                         #user = user.first()
1387                         #user = user.__dict__
1388                         #slice_info =  user['reg_slices_as_researcher'][0].__dict__
1389                     ##Separated in case user not in database : 
1390                     ##record_id not defined SA 17/07//12
1391                     
1392                     ##query_slice_info = slab_dbsession.query(SenslabXP).filter_by(record_id_user = user.record_id)
1393                     ##if query_slice_info:
1394                         ##slice_info = query_slice_info.first()
1395                     ##else:
1396                         ##slice_info = None
1397                         
1398                     #resa_user_dict[resa['user']] = {}
1399                     #resa_user_dict[resa['user']]['ldap_info'] = user
1400                     #resa_user_dict[resa['user']]['slice_info'] = slice_info
1401                     
1402                     #resa['slice_hrn'] = resa_user_dict[resa['user']]['slice_info']['hrn']
1403                     #resa['slice_id'] = hrn_to_urn(resa['slice_hrn'], 'slice')
1404                 
1405     
1406                 resa['component_id_list'] = []
1407                 resa['hrn'] = Xrn(resa['slice_id']).get_hrn()
1408                 #Transform the hostnames into urns (component ids)
1409                 for node in resa['reserved_nodes']:
1410                     #resa['component_id_list'].append(hostname_to_urn(self.hrn, \
1411                             #self.root_auth, node['hostname']))
1412                     slab_xrn = slab_xrn_object(self.root_auth, node)
1413                     resa['component_id_list'].append(slab_xrn.urn)
1414                     
1415                 if lease_filter_dict:
1416                     logger.debug("SLABDRIVER \tGetLeases resa_ %s \r\n leasefilter %s"\
1417                                             %(resa,lease_filter_dict)) 
1418                         
1419                     if lease_filter_dict['name'] == resa['hrn']:
1420                         reservation_list.append(resa)
1421                         
1422         if lease_filter_dict is None:
1423             reservation_list = unfiltered_reservation_list
1424                 #else:
1425                     #del unfiltered_reservation_list[unfiltered_reservation_list.index(resa)]
1426
1427                     
1428         self.update_jobs_in_slabdb(job_oar_list, jobs_psql_id_list)
1429                 
1430         #for resa in unfiltered_reservation_list:
1431             
1432             
1433             ##Put the slice_urn  
1434             #if resa['user'] in resa_user_dict:
1435                 #resa['slice_hrn'] = resa_user_dict[resa['user']]['slice_info']['hrn']
1436                 #resa['slice_id'] = hrn_to_urn(resa['slice_hrn'], 'slice')    
1437                 ##Put the slice_urn 
1438                 ##resa['slice_id'] = hrn_to_urn(slice_info.slice_hrn, 'slice')
1439                 #resa['component_id_list'] = []
1440                 ##Transform the hostnames into urns (component ids)
1441                 #for node in resa['reserved_nodes']:
1442                     ##resa['component_id_list'].append(hostname_to_urn(self.hrn, \
1443                             ##self.root_auth, node['hostname']))
1444                     #slab_xrn = slab_xrn_object(self.root_auth, node)
1445                     #resa['component_id_list'].append(slab_xrn.urn)
1446         
1447         ##Filter the reservation list if necessary
1448         ##Returns all the leases associated with a given slice
1449         #if lease_filter_dict:
1450             #logger.debug("SLABDRIVER \tGetLeases lease_filter_dict %s"\
1451                                             #%(lease_filter_dict))
1452             #for resa in unfiltered_reservation_list:
1453                 #if lease_filter_dict['name'] == resa['slice_hrn']:
1454                     #reservation_list.append(resa)
1455         #else:
1456             #reservation_list = unfiltered_reservation_list
1457             
1458         logger.debug(" SLABDRIVER.PY \tGetLeases reservation_list %s"\
1459                                                     %(reservation_list))
1460         return reservation_list
1461             
1462     def augment_records_with_testbed_info (self, sfa_records):
1463         return self.fill_record_info (sfa_records)
1464     
1465     def fill_record_info(self, record_list):
1466         """
1467         Given a SFA record, fill in the senslab specific and SFA specific
1468         fields in the record. 
1469         """
1470                     
1471         logger.debug("SLABDRIVER \tfill_record_info records %s " %(record_list))
1472         if not isinstance(record_list, list):
1473             record_list = [record_list]
1474             
1475         try:
1476             for record in record_list:
1477                 #If the record is a SFA slice record, then add information 
1478                 #about the user of this slice. This kind of 
1479                 #information is in the Senslab's DB.
1480                 if str(record['type']) == 'slice':
1481                     if 'reg_researchers' in record and isinstance(record['reg_researchers'],list) :
1482                         record['reg_researchers'] = record['reg_researchers'][0].__dict__
1483                         record.update({'PI':[record['reg_researchers']['hrn']],
1484                                 'researcher': [record['reg_researchers']['hrn']],
1485                                 'name':record['hrn'], 
1486                                 'oar_job_id':[],
1487                                 'node_ids': [],
1488                                 'person_ids':[record['reg_researchers']['record_id']],
1489                                 'geni_urn':'',  #For client_helper.py compatibility
1490                                 'keys':'',  #For client_helper.py compatibility
1491                                 'key_ids':''})  #For client_helper.py compatibility
1492                         
1493                         
1494                     #Get slab slice record.
1495                     recslice_list = self.GetSlices(slice_filter = \
1496                                                 str(record['hrn']),\
1497                                                 slice_filter_type = 'slice_hrn')
1498                     
1499                     #recuser = recslice_list[0]['reg_researchers']
1500                     ##recuser = dbsession.query(RegRecord).filter_by(record_id = \
1501                                             ##recslice_list[0]['record_id_user']).first()
1502                    
1503                     #record.update({'PI':[recuser['hrn']],
1504                                 #'researcher': [recuser['hrn']],
1505                                 #'name':record['hrn'], 
1506                                 #'oar_job_id':[],
1507                                 #'node_ids': [],
1508                                 #'person_ids':[recslice_list[0]['reg_researchers']['record_id']],
1509                                 #'geni_urn':'',  #For client_helper.py compatibility
1510                                 #'keys':'',  #For client_helper.py compatibility
1511                                 #'key_ids':''})  #For client_helper.py compatibility
1512                     logger.debug("SLABDRIVER \tfill_record_info TYPE SLICE RECUSER record['hrn'] %s ecord['oar_job_id'] %s " %(record['hrn'],record['oar_job_id']))
1513                     try:
1514                         for rec in recslice_list: 
1515                             logger.debug("SLABDRIVER\r\n  \t \t fill_record_info oar_job_id %s " %(rec['oar_job_id']))
1516                             #record['oar_job_id'].append(rec['oar_job_id'])
1517                             #del record['_sa_instance_state']
1518                             del record['reg_researchers']
1519                             record['node_ids'] = [ self.root_auth + hostname for hostname in rec['node_ids']]
1520                     except KeyError:
1521                         pass
1522
1523                     logger.debug( "SLABDRIVER.PY \t fill_record_info SLICE \
1524                                                     recslice_list  %s \r\n \t RECORD %s \r\n \r\n" %(recslice_list,record)) 
1525                 if str(record['type']) == 'user':
1526                     #The record is a SFA user record.
1527                     #Get the information about his slice from Senslab's DB
1528                     #and add it to the user record.
1529                     recslice_list = self.GetSlices(\
1530                             slice_filter = record['record_id'],\
1531                             slice_filter_type = 'record_id_user')
1532                                             
1533                     logger.debug( "SLABDRIVER.PY \t fill_record_info TYPE USER \
1534                                                 recslice_list %s \r\n \t RECORD %s \r\n" %(recslice_list , record)) 
1535                     #Append slice record in records list, 
1536                     #therefore fetches user and slice info again(one more loop)
1537                     #Will update PIs and researcher for the slice
1538                     #recuser = dbsession.query(RegRecord).filter_by(record_id = \
1539                                                 #recslice_list[0]['record_id_user']).first()
1540                     recuser = recslice_list[0]['reg_researchers']
1541                     logger.debug( "SLABDRIVER.PY \t fill_record_info USER  \
1542                                                 recuser %s \r\n \r\n" %(recuser)) 
1543                     recslice = {}
1544                     recslice = recslice_list[0]
1545                     recslice.update({'PI':[recuser['hrn']],
1546                         'researcher': [recuser['hrn']],
1547                         'name':record['hrn'], 
1548                         'node_ids': [],
1549                         'oar_job_id': [],
1550                         'person_ids':[recuser['record_id']]}) 
1551                     try:
1552                         for rec in recslice_list:
1553                             recslice['oar_job_id'].append(rec['oar_job_id'])
1554                     except KeyError:
1555                         pass
1556                             
1557                     recslice.update({'type':'slice', \
1558                                                 'hrn':recslice_list[0]['hrn']})
1559
1560
1561                     #GetPersons takes [] as filters 
1562                     #user_slab = self.GetPersons([{'hrn':recuser.hrn}])
1563                     user_slab = self.GetPersons([record])
1564     
1565                     
1566                     record.update(user_slab[0])
1567                     #For client_helper.py compatibility
1568                     record.update( { 'geni_urn':'',
1569                     'keys':'',
1570                     'key_ids':'' })                
1571                     record_list.append(recslice)
1572                     
1573                     logger.debug("SLABDRIVER.PY \tfill_record_info ADDING SLICE\
1574                                 INFO TO USER records %s" %(record_list)) 
1575                 
1576                 logger.debug("SLABDRIVER.PY \tfill_record_info END \
1577                                 record %s \r\n \r\n " %(record))     
1578
1579         except TypeError, error:
1580             logger.log_exc("SLABDRIVER \t fill_record_info  EXCEPTION %s"\
1581                                                                      %(error))
1582         #logger.debug("SLABDRIVER.PY \t fill_record_info ENDENDEND ")
1583                               
1584         return
1585         
1586         #self.fill_record_slab_info(records)
1587     
1588     
1589         
1590
1591     
1592     #TODO Update membership?    update_membership_list SA 05/07/12
1593     #def update_membership_list(self, oldRecord, record, listName, addFunc, \
1594                                                                 #delFunc):
1595         ## get a list of the HRNs tht are members of the old and new records
1596         #if oldRecord:
1597             #oldList = oldRecord.get(listName, [])
1598         #else:
1599             #oldList = []     
1600         #newList = record.get(listName, [])
1601
1602         ## if the lists are the same, then we don't have to update anything
1603         #if (oldList == newList):
1604             #return
1605
1606         ## build a list of the new person ids, by looking up each person to get
1607         ## their pointer
1608         #newIdList = []
1609         #table = SfaTable()
1610         #records = table.find({'type': 'user', 'hrn': newList})
1611         #for rec in records:
1612             #newIdList.append(rec['pointer'])
1613
1614         ## build a list of the old person ids from the person_ids field 
1615         #if oldRecord:
1616             #oldIdList = oldRecord.get("person_ids", [])
1617             #containerId = oldRecord.get_pointer()
1618         #else:
1619             ## if oldRecord==None, then we are doing a Register, instead of an
1620             ## update.
1621             #oldIdList = []
1622             #containerId = record.get_pointer()
1623
1624     ## add people who are in the new list, but not the oldList
1625         #for personId in newIdList:
1626             #if not (personId in oldIdList):
1627                 #addFunc(self.plauth, personId, containerId)
1628
1629         ## remove people who are in the old list, but not the new list
1630         #for personId in oldIdList:
1631             #if not (personId in newIdList):
1632                 #delFunc(self.plauth, personId, containerId)
1633
1634     #def update_membership(self, oldRecord, record):
1635        
1636         #if record.type == "slice":
1637             #self.update_membership_list(oldRecord, record, 'researcher',
1638                                         #self.users.AddPersonToSlice,
1639                                         #self.users.DeletePersonFromSlice)
1640         #elif record.type == "authority":
1641             ## xxx TODO
1642             #pass
1643
1644 ### thierry
1645 # I don't think you plan on running a component manager at this point
1646 # let me clean up the mess of ComponentAPI that is deprecated anyways
1647
1648
1649 #TODO FUNCTIONS SECTION 04/07/2012 SA
1650
1651     #TODO : Is UnBindObjectFromPeer still necessary ? Currently does nothing
1652     #04/07/2012 SA
1653     def UnBindObjectFromPeer(self, auth, object_type, object_id, shortname):
1654         """ This method is a hopefully temporary hack to let the sfa correctly
1655         detach the objects it creates from a remote peer object. This is 
1656         needed so that the sfa federation link can work in parallel with 
1657         RefreshPeer, as RefreshPeer depends on remote objects being correctly 
1658         marked.
1659         Parameters:
1660         auth : struct, API authentication structure
1661             AuthMethod : string, Authentication method to use 
1662         object_type : string, Object type, among 'site','person','slice',
1663         'node','key'
1664         object_id : int, object_id
1665         shortname : string, peer shortname 
1666         FROM PLC DOC
1667         
1668         """
1669         logger.warning("SLABDRIVER \tUnBindObjectFromPeer EMPTY-\
1670                         DO NOTHING \r\n ")
1671         return 
1672     
1673     #TODO Is BindObjectToPeer still necessary ? Currently does nothing 
1674     #04/07/2012 SA
1675     def BindObjectToPeer(self, auth, object_type, object_id, shortname=None, \
1676                                                     remote_object_id=None):
1677         """This method is a hopefully temporary hack to let the sfa correctly 
1678         attach the objects it creates to a remote peer object. This is needed 
1679         so that the sfa federation link can work in parallel with RefreshPeer, 
1680         as RefreshPeer depends on remote objects being correctly marked.
1681         Parameters:
1682         shortname : string, peer shortname 
1683         remote_object_id : int, remote object_id, set to 0 if unknown 
1684         FROM PLC API DOC
1685         
1686         """
1687         logger.warning("SLABDRIVER \tBindObjectToPeer EMPTY - DO NOTHING \r\n ")
1688         return
1689     
1690     #TODO UpdateSlice 04/07/2012 SA
1691     #Funciton should delete and create another job since oin senslab slice=job
1692     def UpdateSlice(self, auth, slice_id_or_name, slice_fields=None):    
1693         """Updates the parameters of an existing slice with the values in 
1694         slice_fields.
1695         Users may only update slices of which they are members. 
1696         PIs may update any of the slices at their sites, or any slices of 
1697         which they are members. Admins may update any slice.
1698         Only PIs and admins may update max_nodes. Slices cannot be renewed
1699         (by updating the expires parameter) more than 8 weeks into the future.
1700          Returns 1 if successful, faults otherwise.
1701         FROM PLC API DOC
1702         
1703         """  
1704         logger.warning("SLABDRIVER UpdateSlice EMPTY - DO NOTHING \r\n ")
1705         return
1706     
1707     #TODO UpdatePerson 04/07/2012 SA
1708     def UpdatePerson(self, slab_hrn, federated_hrn, person_fields=None):
1709         """Updates a person. Only the fields specified in person_fields 
1710         are updated, all other fields are left untouched.
1711         Users and techs can only update themselves. PIs can only update
1712         themselves and other non-PIs at their sites.
1713         Returns 1 if successful, faults otherwise.
1714         FROM PLC API DOC
1715          
1716         """
1717         #new_row = FederatedToSenslab(slab_hrn, federated_hrn)
1718         #slab_dbsession.add(new_row)
1719         #slab_dbsession.commit()
1720         
1721         logger.debug("SLABDRIVER UpdatePerson EMPTY - DO NOTHING \r\n ")
1722         return
1723     
1724     #TODO GetKeys 04/07/2012 SA
1725     def GetKeys(self, auth, key_filter=None, return_fields=None):
1726         """Returns an array of structs containing details about keys. 
1727         If key_filter is specified and is an array of key identifiers, 
1728         or a struct of key attributes, only keys matching the filter 
1729         will be returned. If return_fields is specified, only the 
1730         specified details will be returned.
1731
1732         Admin may query all keys. Non-admins may only query their own keys.
1733         FROM PLC API DOC
1734         
1735         """
1736         logger.warning("SLABDRIVER  GetKeys EMPTY - DO NOTHING \r\n ")
1737         return
1738     
1739     #TODO DeleteKey 04/07/2012 SA
1740     def DeleteKey(self, auth, key_id):
1741         """  Deletes a key.
1742          Non-admins may only delete their own keys.
1743          Returns 1 if successful, faults otherwise.
1744          FROM PLC API DOC
1745          
1746         """
1747         logger.warning("SLABDRIVER  DeleteKey EMPTY - DO NOTHING \r\n ")
1748         return
1749
1750     
1751     #TODO : Check rights to delete person 
1752     def DeletePerson(self, auth, person_record):
1753         """ Disable an existing account in senslab LDAP.
1754         Users and techs can only delete themselves. PIs can only 
1755         delete themselves and other non-PIs at their sites. 
1756         ins can delete anyone.
1757         Returns 1 if successful, faults otherwise.
1758         FROM PLC API DOC
1759         
1760         """
1761         #Disable user account in senslab LDAP
1762         ret = self.ldap.LdapMarkUserAsDeleted(person_record)
1763         logger.warning("SLABDRIVER DeletePerson %s " %(person_record))
1764         return ret
1765     
1766     #TODO Check DeleteSlice, check rights 05/07/2012 SA
1767     def DeleteSlice(self, auth, slice_record):
1768         """ Deletes the specified slice.
1769          Senslab : Kill the job associated with the slice if there is one
1770          using DeleteSliceFromNodes.
1771          Updates the slice record in slab db to remove the slice nodes.
1772          
1773          Users may only delete slices of which they are members. PIs may 
1774          delete any of the slices at their sites, or any slices of which 
1775          they are members. Admins may delete any slice.
1776          Returns 1 if successful, faults otherwise.
1777          FROM PLC API DOC
1778         
1779         """
1780         self.DeleteSliceFromNodes(slice_record)
1781         logger.warning("SLABDRIVER DeleteSlice %s "%(slice_record))
1782         return
1783     
1784     def __add_person_to_db(self, user_dict):
1785
1786         check_if_exists = dbsession.query(RegUser).filter_by(email = user_dict['email']).first()
1787         #user doesn't exists
1788         if not check_if_exists:
1789             logger.debug("__add_person_to_db \t Adding %s \r\n \r\n \
1790             _________________________________________________________________________\
1791             " %(user_dict['hrn']))
1792             user_record = RegUser(hrn =user_dict['hrn'] , pointer= '-1', authority=get_authority(hrn), \
1793                                                     email= user_dict['email'], gid = None)
1794             user_record.reg_keys = [RegKey(user_dict['pkey'])]
1795             user_record.just_created()
1796             dbsession.add (user_record)
1797             dbsession.commit()
1798         return 
1799         
1800     #TODO AddPerson 04/07/2012 SA
1801     #def AddPerson(self, auth,  person_fields=None): 
1802     def AddPerson(self, record):#TODO fixing 28/08//2012 SA
1803         """Adds a new account. Any fields specified in records are used, 
1804         otherwise defaults are used.
1805         Accounts are disabled by default. To enable an account, 
1806         use UpdatePerson().
1807         Returns the new person_id (> 0) if successful, faults otherwise. 
1808         FROM PLC API DOC
1809         
1810         """
1811         ret = self.ldap.LdapAddUser(record)
1812         logger.debug("SLABDRIVER AddPerson return code %s \r\n "%(ret))
1813         self.__add_person_to_db(record)
1814         return ret['uid']
1815     
1816     #TODO AddPersonToSite 04/07/2012 SA
1817     def AddPersonToSite (self, auth, person_id_or_email, \
1818                                                 site_id_or_login_base=None):
1819         """  Adds the specified person to the specified site. If the person is 
1820         already a member of the site, no errors are returned. Does not change 
1821         the person's primary site.
1822         Returns 1 if successful, faults otherwise.
1823         FROM PLC API DOC
1824         
1825         """
1826         logger.warning("SLABDRIVER AddPersonToSite EMPTY - DO NOTHING \r\n ")
1827         return
1828     
1829     #TODO AddRoleToPerson : Not sure if needed in senslab 04/07/2012 SA
1830     def AddRoleToPerson(self, auth, role_id_or_name, person_id_or_email):
1831         """Grants the specified role to the person.
1832         PIs can only grant the tech and user roles to users and techs at their 
1833         sites. Admins can grant any role to any user.
1834         Returns 1 if successful, faults otherwise.
1835         FROM PLC API DOC
1836         
1837         """
1838         logger.warning("SLABDRIVER AddRoleToPerson EMPTY - DO NOTHING \r\n ")
1839         return
1840     
1841     #TODO AddPersonKey 04/07/2012 SA
1842     def AddPersonKey(self, auth, person_id_or_email, key_fields=None):
1843         """Adds a new key to the specified account.
1844         Non-admins can only modify their own keys.
1845         Returns the new key_id (> 0) if successful, faults otherwise.
1846         FROM PLC API DOC
1847         
1848         """
1849         logger.warning("SLABDRIVER AddPersonKey EMPTY - DO NOTHING \r\n ")
1850         return
1851     
1852     def DeleteLeases(self, leases_id_list, slice_hrn ):        
1853         logger.debug("SLABDRIVER DeleteLeases leases_id_list %s slice_hrn %s \
1854                 \r\n " %(leases_id_list, slice_hrn))
1855         for job_id in leases_id_list:
1856             self.DeleteJobs(job_id, slice_hrn)
1857         
1858
1859         return