3 from datetime import datetime
4 from time import gmtime
6 from sfa.util.faults import SliverDoesNotExist, UnknownSfaType
7 from sfa.util.sfalogging import logger
9 from sfa.storage.alchemy import dbsession
10 from sfa.storage.model import RegRecord, RegUser
12 from sfa.trust.credential import Credential
15 from sfa.managers.driver import Driver
16 from sfa.rspecs.version_manager import VersionManager
17 from sfa.rspecs.rspec import RSpec
19 from sfa.util.xrn import hrn_to_urn, urn_to_sliver_id, get_leaf
22 ## thierry: everything that is API-related (i.e. handling incoming requests)
24 # SlabDriver should be really only about talking to the senslab testbed
27 from sfa.senslab.OARrestapi import OARrestapi
28 from sfa.senslab.LDAPapi import LDAPapi
30 from sfa.senslab.slabpostgres import SlabDB, slab_dbsession, SliceSenslab
32 from sfa.senslab.slabaggregate import SlabAggregate, slab_xrn_to_hostname, \
34 from sfa.senslab.slabslices import SlabSlices
41 # this inheritance scheme is so that the driver object can receive
42 # GetNodes or GetSites sorts of calls directly
43 # and thus minimize the differences in the managers with the pl version
44 class SlabDriver(Driver):
46 def __init__(self, config):
47 Driver.__init__ (self, config)
49 self.hrn = config.SFA_INTERFACE_HRN
51 self.root_auth = config.SFA_REGISTRY_ROOT_AUTH
53 self.oar = OARrestapi()
55 self.time_format = "%Y-%m-%d %H:%M:%S"
56 self.db = SlabDB(config,debug = True)
60 def sliver_status(self, slice_urn, slice_hrn):
61 """Receive a status request for slice named urn/hrn
62 urn:publicid:IDN+senslab+nturro_slice hrn senslab.nturro_slice
63 shall return a structure as described in
64 http://groups.geni.net/geni/wiki/GAPI_AM_API_V2#SliverStatus
65 NT : not sure if we should implement this or not, but used by sface.
69 #First get the slice with the slice hrn
70 sl = self.GetSlices(slice_filter = slice_hrn, \
71 slice_filter_type = 'slice_hrn')
74 raise SliverDoesNotExist("%s slice_hrn" % (slice_hrn))
76 if isinstance(sl,list):
80 top_level_status = 'unknown'
81 nodes_in_slice = sl['node_ids']
82 recuser = dbsession.query(RegRecord).filter_by(record_id = \
83 sl['record_id_user']).first()
84 sl.update({'user':recuser.hrn})
85 if len(nodes_in_slice) is 0:
86 raise SliverDoesNotExist("No slivers allocated ")
88 top_level_status = 'ready'
90 logger.debug("Slabdriver - sliver_status Sliver status urn %s hrn %s sl\
91 %s \r\n " %(slice_urn, slice_hrn, sl))
93 if sl['oar_job_id'] is not []:
94 #A job is running on Senslab for this slice
95 # report about the local nodes that are in the slice only
97 nodes_all = self.GetNodes({'hostname':nodes_in_slice},
98 ['node_id', 'hostname','site','boot_state'])
99 nodeall_byhostname = dict([(n['hostname'], n) for n in nodes_all])
103 result['geni_urn'] = slice_urn
104 result['pl_login'] = sl['user'] #For compatibility
107 #timestamp = float(sl['startTime']) + float(sl['walltime'])
108 #result['pl_expires'] = strftime(self.time_format, \
109 #gmtime(float(timestamp)))
110 #result['slab_expires'] = strftime(self.time_format,\
111 #gmtime(float(timestamp)))
114 for node in nodeall_byhostname:
116 #res['slab_hostname'] = node['hostname']
117 #res['slab_boot_state'] = node['boot_state']
119 res['pl_hostname'] = nodeall_byhostname[node]['hostname']
120 res['pl_boot_state'] = nodeall_byhostname[node]['boot_state']
121 #res['pl_last_contact'] = strftime(self.time_format, \
122 #gmtime(float(timestamp)))
123 sliver_id = urn_to_sliver_id(slice_urn, sl['record_id_slice'], \
124 nodeall_byhostname[node]['node_id'])
125 res['geni_urn'] = sliver_id
126 if nodeall_byhostname[node]['boot_state'] == 'Alive':
128 res['geni_status'] = 'ready'
130 res['geni_status'] = 'failed'
131 top_level_status = 'failed'
133 res['geni_error'] = ''
135 resources.append(res)
137 result['geni_status'] = top_level_status
138 result['geni_resources'] = resources
139 logger.debug("SLABDRIVER \tsliver_statusresources %s res %s "\
144 def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, \
146 aggregate = SlabAggregate(self)
148 slices = SlabSlices(self)
149 peer = slices.get_peer(slice_hrn)
150 sfa_peer = slices.get_sfa_peer(slice_hrn)
153 if not isinstance(creds, list):
157 slice_record = users[0].get('slice_record', {})
160 rspec = RSpec(rspec_string)
161 logger.debug("SLABDRIVER.PY \t create_sliver \tr spec.version %s slice_record %s " \
162 %(rspec.version,slice_record))
164 #self.synchronize_oar_and_slice_table(slice_hrn)
165 # ensure site record exists?
166 # ensure slice record exists
167 #Removed options to verify_slice SA 14/08/12
168 sfa_slice = slices.verify_slice(slice_hrn, slice_record, peer, \
171 #requested_attributes returned by rspec.version.get_slice_attributes()
172 #unused, removed SA 13/08/12
173 rspec.version.get_slice_attributes()
175 logger.debug("SLABDRIVER.PY create_sliver slice %s " %(sfa_slice))
177 # ensure person records exists
178 #verify_persons returns added persons but since the return value
180 slices.verify_persons(slice_hrn, sfa_slice, users, peer, \
181 sfa_peer, options=options)
185 # add/remove slice from nodes
187 requested_slivers = [node.get('component_name') \
188 for node in rspec.version.get_nodes_with_slivers()]
189 l = [ node for node in rspec.version.get_nodes_with_slivers() ]
190 logger.debug("SLADRIVER \tcreate_sliver requested_slivers \
191 requested_slivers %s listnodes %s" \
192 %(requested_slivers,l))
193 #verify_slice_nodes returns nodes, but unused here. Removed SA 13/08/12.
194 slices.verify_slice_nodes(sfa_slice, requested_slivers, peer)
197 requested_lease_list = []
199 for lease in rspec.version.get_leases():
200 single_requested_lease = {}
201 logger.debug("SLABDRIVER.PY \tcreate_sliver lease %s " %(lease))
202 if not lease.get('lease_id'):
203 single_requested_lease['hostname'] = \
204 slab_xrn_to_hostname(lease.get('component_id').strip())
205 single_requested_lease['start_time'] = lease.get('start_time')
206 single_requested_lease['duration'] = lease.get('duration')
208 kept_leases.append(int(lease['lease_id']))
209 if single_requested_lease.get('hostname'):
210 requested_lease_list.append(single_requested_lease)
212 #dCreate dict of leases by start_time, regrouping nodes reserved
214 #time, for the same amount of time = one job on OAR
215 requested_job_dict = {}
216 for lease in requested_lease_list:
218 #In case it is an asap experiment start_time is empty
219 if lease['start_time'] == '':
220 lease['start_time'] = '0'
222 if lease['start_time'] not in requested_job_dict:
223 if isinstance(lease['hostname'], str):
224 lease['hostname'] = [lease['hostname']]
226 requested_job_dict[lease['start_time']] = lease
229 job_lease = requested_job_dict[lease['start_time']]
230 if lease['duration'] == job_lease['duration'] :
231 job_lease['hostname'].append(lease['hostname'])
236 logger.debug("SLABDRIVER.PY \tcreate_sliver requested_job_dict %s " %(requested_job_dict))
237 #verify_slice_leases returns the leases , but the return value is unused
238 #here. Removed SA 13/08/12
239 slices.verify_slice_leases(sfa_slice, \
240 requested_job_dict, kept_leases, peer)
242 return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
245 def delete_sliver (self, slice_urn, slice_hrn, creds, options):
247 sfa_slice_list = self.GetSlices(slice_filter = slice_hrn, \
248 slice_filter_type = 'slice_hrn')
250 if not sfa_slice_list:
253 #Delete all in the slice
254 for sfa_slice in sfa_slice_list:
257 logger.debug("SLABDRIVER.PY delete_sliver slice %s" %(sfa_slice))
258 slices = SlabSlices(self)
259 # determine if this is a peer slice
261 peer = slices.get_peer(slice_hrn)
262 #TODO delete_sliver SA : UnBindObjectFromPeer should be
263 #used when there is another
264 #senslab testbed, which is not the case 14/08/12 .
266 logger.debug("SLABDRIVER.PY delete_sliver peer %s" %(peer))
269 self.UnBindObjectFromPeer('slice', \
270 sfa_slice['record_id_slice'], peer,None)
271 self.DeleteSliceFromNodes(sfa_slice)
274 self.BindObjectToPeer('slice', sfa_slice['record_id_slice'], \
275 peer, sfa_slice['peer_slice_id'])
279 def AddSlice(self, slice_record):
280 slab_slice = SliceSenslab( slice_hrn = slice_record['slice_hrn'], \
281 record_id_slice= slice_record['record_id_slice'] , \
282 record_id_user= slice_record['record_id_user'], \
283 peer_authority = slice_record['peer_authority'])
284 logger.debug("SLABDRIVER.PY \tAddSlice slice_record %s slab_slice %s" \
285 %(slice_record,slab_slice))
286 slab_dbsession.add(slab_slice)
287 slab_dbsession.commit()
290 # first 2 args are None in case of resource discovery
291 def list_resources (self, slice_urn, slice_hrn, creds, options):
292 #cached_requested = options.get('cached', True)
294 version_manager = VersionManager()
295 # get the rspec's return format from options
297 version_manager.get_version(options.get('geni_rspec_version'))
298 version_string = "rspec_%s" % (rspec_version)
300 #panos adding the info option to the caching key (can be improved)
301 if options.get('info'):
302 version_string = version_string + "_" + \
303 options.get('info', 'default')
305 # look in cache first
306 #if cached_requested and self.cache and not slice_hrn:
307 #rspec = self.cache.get(version_string)
309 #logger.debug("SlabDriver.ListResources: \
310 #returning cached advertisement")
313 #panos: passing user-defined options
314 aggregate = SlabAggregate(self)
315 origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
316 options.update({'origin_hrn':origin_hrn})
317 rspec = aggregate.get_rspec(slice_xrn=slice_urn, \
318 version=rspec_version, options=options)
321 #if self.cache and not slice_hrn:
322 #logger.debug("Slab.ListResources: stores advertisement in cache")
323 #self.cache.add(version_string, rspec)
328 def list_slices (self, creds, options):
329 # look in cache first
331 #slices = self.cache.get('slices')
333 #logger.debug("PlDriver.list_slices returns from cache")
338 slices = self.GetSlices()
339 logger.debug("SLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n" %(slices))
340 slice_hrns = [slab_slice['slice_hrn'] for slab_slice in slices]
341 #slice_hrns = [slicename_to_hrn(self.hrn, slab_slice['slice_hrn']) \
342 #for slab_slice in slices]
343 slice_urns = [hrn_to_urn(slice_hrn, 'slice') \
344 for slice_hrn in slice_hrns]
348 #logger.debug ("SlabDriver.list_slices stores value in cache")
349 #self.cache.add('slices', slice_urns)
353 #No site or node register supported
354 def register (self, sfa_record, hrn, pub_key):
355 record_type = sfa_record['type']
356 slab_record = self.sfa_fields_to_slab_fields(record_type, hrn, \
360 if record_type == 'slice':
361 acceptable_fields = ['url', 'instantiation', 'name', 'description']
362 for key in slab_record.keys():
363 if key not in acceptable_fields:
365 logger.debug("SLABDRIVER.PY register")
366 slices = self.GetSlices(slice_filter =slab_record['hrn'], \
367 slice_filter_type = 'slice_hrn')
369 pointer = self.AddSlice(slab_record)
371 pointer = slices[0]['slice_id']
373 elif record_type == 'user':
374 persons = self.GetPersons([sfa_record])
375 #persons = self.GetPersons([sfa_record['hrn']])
377 pointer = self.AddPerson(dict(sfa_record))
380 pointer = persons[0]['person_id']
382 #Does this make sense to senslab ?
383 #if 'enabled' in sfa_record and sfa_record['enabled']:
384 #self.UpdatePerson(pointer, \
385 #{'enabled': sfa_record['enabled']})
387 #TODO register Change this AddPersonToSite stuff 05/07/2012 SA
388 # add this person to the site only if
389 # she is being added for the first
390 # time by sfa and doesnt already exist in plc
391 if not persons or not persons[0]['site_ids']:
392 login_base = get_leaf(sfa_record['authority'])
393 self.AddPersonToSite(pointer, login_base)
395 # What roles should this user have?
396 #TODO : DElete this AddRoleToPerson 04/07/2012 SA
397 #Function prototype is :
398 #AddRoleToPerson(self, auth, role_id_or_name, person_id_or_email)
399 #what's the pointer doing here?
400 self.AddRoleToPerson('user', pointer)
403 self.AddPersonKey(pointer, {'key_type' : 'ssh', \
406 #No node adding outside OAR
410 #No site or node record update allowed
411 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
412 pointer = old_sfa_record['pointer']
413 old_sfa_record_type = old_sfa_record['type']
415 # new_key implemented for users only
416 if new_key and old_sfa_record_type not in [ 'user' ]:
417 raise UnknownSfaType(old_sfa_record_type)
419 #if (type == "authority"):
420 #self.shell.UpdateSite(pointer, new_sfa_record)
422 if old_sfa_record_type == "slice":
423 slab_record = self.sfa_fields_to_slab_fields(old_sfa_record_type, \
425 if 'name' in slab_record:
426 slab_record.pop('name')
427 #Prototype should be UpdateSlice(self,
428 #auth, slice_id_or_name, slice_fields)
429 #Senslab cannot update slice since slice = job
430 #so we must delete and create another job
431 self.UpdateSlice(pointer, slab_record)
433 elif old_sfa_record_type == "user":
435 all_fields = new_sfa_record
436 for key in all_fields.keys():
437 if key in ['first_name', 'last_name', 'title', 'email',
438 'password', 'phone', 'url', 'bio', 'accepted_aup',
440 update_fields[key] = all_fields[key]
441 self.UpdatePerson(pointer, update_fields)
444 # must check this key against the previous one if it exists
445 persons = self.GetPersons([pointer], ['key_ids'])
447 keys = person['key_ids']
448 keys = self.GetKeys(person['key_ids'])
450 # Delete all stale keys
453 if new_key != key['key']:
454 self.DeleteKey(key['key_id'])
458 self.AddPersonKey(pointer, {'key_type': 'ssh', \
465 def remove (self, sfa_record):
466 sfa_record_type = sfa_record['type']
467 hrn = sfa_record['hrn']
468 if sfa_record_type == 'user':
470 #get user from senslab ldap
471 person = self.GetPersons(sfa_record)
472 #No registering at a given site in Senslab.
473 #Once registered to the LDAP, all senslab sites are
476 #Mark account as disabled in ldap
477 self.DeletePerson(sfa_record)
478 elif sfa_record_type == 'slice':
479 if self.GetSlices(slice_filter = hrn, \
480 slice_filter_type = 'slice_hrn'):
481 self.DeleteSlice(sfa_record)
483 #elif type == 'authority':
484 #if self.GetSites(pointer):
485 #self.DeleteSite(pointer)
491 #TODO clean GetPeers. 05/07/12SA
492 def GetPeers (self, auth = None, peer_filter=None, return_fields_list=None):
494 existing_records = {}
495 existing_hrns_by_types = {}
496 logger.debug("SLABDRIVER \tGetPeers auth = %s, peer_filter %s, \
497 return_field %s " %(auth , peer_filter, return_fields_list))
498 all_records = dbsession.query(RegRecord).filter(RegRecord.type.like('%authority%')).all()
499 for record in all_records:
500 existing_records[(record.hrn, record.type)] = record
501 if record.type not in existing_hrns_by_types:
502 existing_hrns_by_types[record.type] = [record.hrn]
503 logger.debug("SLABDRIVER \tGetPeer\t NOT IN \
504 existing_hrns_by_types %s " %( existing_hrns_by_types))
507 logger.debug("SLABDRIVER \tGetPeer\t \INNN type %s hrn %s " \
508 %(record.type,record.hrn))
509 existing_hrns_by_types[record.type].append(record.hrn)
512 logger.debug("SLABDRIVER \tGetPeer\texisting_hrns_by_types %s "\
513 %( existing_hrns_by_types))
518 records_list.append(existing_records[(peer_filter,'authority')])
520 for hrn in existing_hrns_by_types['authority']:
521 records_list.append(existing_records[(hrn,'authority')])
523 logger.debug("SLABDRIVER \tGetPeer \trecords_list %s " \
529 return_records = records_list
530 if not peer_filter and not return_fields_list:
534 logger.debug("SLABDRIVER \tGetPeer return_records %s " \
536 return return_records
539 #TODO : Handling OR request in make_ldap_filters_from_records
540 #instead of the for loop
541 #over the records' list
542 def GetPersons(self, person_filter=None):
544 person_filter should be a list of dictionnaries when not set to None.
545 Returns a list of users whose accounts are enabled found in ldap.
548 logger.debug("SLABDRIVER \tGetPersons person_filter %s" \
551 if person_filter and isinstance(person_filter, list):
552 #If we are looking for a list of users (list of dict records)
553 #Usually the list contains only one user record
554 for searched_attributes in person_filter:
556 #Get only enabled user accounts in senslab LDAP :
557 #add a filter for make_ldap_filters_from_record
558 person = self.ldap.LdapFindUser(searched_attributes, \
559 is_user_enabled=True)
560 person_list.append(person)
563 #Get only enabled user accounts in senslab LDAP :
564 #add a filter for make_ldap_filters_from_record
565 person_list = self.ldap.LdapFindUser(is_user_enabled=True)
569 def GetTimezone(self):
570 server_timestamp, server_tz = self.oar.parser.\
571 SendRequest("GET_timezone")
572 return server_timestamp, server_tz
575 def DeleteJobs(self, job_id, slice_hrn):
576 if not job_id or job_id is -1:
578 username = slice_hrn.split(".")[-1].rstrip("_slice")
580 reqdict['method'] = "delete"
581 reqdict['strval'] = str(job_id)
583 self.db.delete_job(slice_hrn, job_id)
584 answer = self.oar.POSTRequestToOARRestAPI('DELETE_jobs_id', \
586 logger.debug("SLABDRIVER \tDeleteJobs jobid %s \r\n answer %s \
587 username %s" %(job_id,answer, username))
592 ##TODO : Unused GetJobsId ? SA 05/07/12
593 #def GetJobsId(self, job_id, username = None ):
595 #Details about a specific job.
596 #Includes details about submission time, jot type, state, events,
597 #owner, assigned ressources, walltime etc...
601 #node_list_k = 'assigned_network_address'
602 ##Get job info from OAR
603 #job_info = self.oar.parser.SendRequest(req, job_id, username)
605 #logger.debug("SLABDRIVER \t GetJobsId %s " %(job_info))
607 #if job_info['state'] == 'Terminated':
608 #logger.debug("SLABDRIVER \t GetJobsId job %s TERMINATED"\
611 #if job_info['state'] == 'Error':
612 #logger.debug("SLABDRIVER \t GetJobsId ERROR message %s "\
617 #logger.error("SLABDRIVER \tGetJobsId KeyError")
620 #parsed_job_info = self.get_info_on_reserved_nodes(job_info, \
622 ##Replaces the previous entry
623 ##"assigned_network_address" / "reserved_resources"
625 #job_info.update({'node_ids':parsed_job_info[node_list_k]})
626 #del job_info[node_list_k]
627 #logger.debug(" \r\nSLABDRIVER \t GetJobsId job_info %s " %(job_info))
631 def GetJobsResources(self, job_id, username = None):
632 #job_resources=['reserved_resources', 'assigned_resources',\
633 #'job_id', 'job_uri', 'assigned_nodes',\
635 #assigned_res = ['resource_id', 'resource_uri']
636 #assigned_n = ['node', 'node_uri']
638 req = "GET_jobs_id_resources"
641 #Get job resources list from OAR
642 node_id_list = self.oar.parser.SendRequest(req, job_id, username)
643 logger.debug("SLABDRIVER \t GetJobsResources %s " %(node_id_list))
646 self.__get_hostnames_from_oar_node_ids(node_id_list)
649 #Replaces the previous entry "assigned_network_address" /
650 #"reserved_resources"
652 job_info = {'node_ids': hostname_list}
657 def get_info_on_reserved_nodes(self, job_info, node_list_name):
658 #Get the list of the testbed nodes records and make a
659 #dictionnary keyed on the hostname out of it
660 node_list_dict = self.GetNodes()
661 #node_hostname_list = []
662 node_hostname_list = [node['hostname'] for node in node_list_dict]
663 #for node in node_list_dict:
664 #node_hostname_list.append(node['hostname'])
665 node_dict = dict(zip(node_hostname_list, node_list_dict))
667 reserved_node_hostname_list = []
668 for index in range(len(job_info[node_list_name])):
669 #job_info[node_list_name][k] =
670 reserved_node_hostname_list[index] = \
671 node_dict[job_info[node_list_name][index]]['hostname']
673 logger.debug("SLABDRIVER \t get_info_on_reserved_nodes \
674 reserved_node_hostname_list %s" \
675 %(reserved_node_hostname_list))
677 logger.error("SLABDRIVER \t get_info_on_reserved_nodes KEYERROR " )
679 return reserved_node_hostname_list
681 def GetNodesCurrentlyInUse(self):
682 """Returns a list of all the nodes already involved in an oar job"""
683 return self.oar.parser.SendRequest("GET_running_jobs")
685 def __get_hostnames_from_oar_node_ids(self, resource_id_list ):
686 full_nodes_dict_list = self.GetNodes()
687 #Put the full node list into a dictionary keyed by oar node id
688 oar_id_node_dict = {}
689 for node in full_nodes_dict_list:
690 oar_id_node_dict[node['oar_id']] = node
692 logger.debug("SLABDRIVER \t __get_hostnames_from_oar_node_ids\
693 oar_id_node_dict %s" %(oar_id_node_dict))
695 hostname_dict_list = []
696 for resource_id in resource_id_list:
697 #Because jobs requested "asap" do not have defined resources
698 if resource_id is not "Undefined":
699 hostname_dict_list.append({'hostname' : \
700 oar_id_node_dict[resource_id]['hostname'],
701 'site_id' : oar_id_node_dict[resource_id]['site']})
703 #hostname_list.append(oar_id_node_dict[resource_id]['hostname'])
704 return hostname_dict_list
706 def GetReservedNodes(self,username = None):
707 #Get the nodes in use and the reserved nodes
708 reservation_dict_list = \
709 self.oar.parser.SendRequest("GET_reserved_nodes", username = username)
712 for resa in reservation_dict_list:
713 logger.debug ("GetReservedNodes resa %s"%(resa))
714 #dict list of hostnames and their site
715 resa['reserved_nodes'] = \
716 self.__get_hostnames_from_oar_node_ids(resa['resource_ids'])
718 #del resa['resource_ids']
719 return reservation_dict_list
721 def GetNodes(self, node_filter_dict = None, return_fields_list = None):
723 node_filter_dict : dictionnary of lists
726 node_dict_by_id = self.oar.parser.SendRequest("GET_resources_full")
727 node_dict_list = node_dict_by_id.values()
729 #No filtering needed return the list directly
730 if not (node_filter_dict or return_fields_list):
731 return node_dict_list
733 return_node_list = []
735 for filter_key in node_filter_dict:
737 #Filter the node_dict_list by each value contained in the
738 #list node_filter_dict[filter_key]
739 for value in node_filter_dict[filter_key]:
740 for node in node_dict_list:
741 if node[filter_key] == value:
742 if return_fields_list :
744 for k in return_fields_list:
746 return_node_list.append(tmp)
748 return_node_list.append(node)
750 logger.log_exc("GetNodes KeyError")
754 return return_node_list
757 def GetSites(self, site_filter_name_list = None, return_fields_list = None):
758 site_dict = self.oar.parser.SendRequest("GET_sites")
759 #site_dict : dict where the key is the sit ename
760 return_site_list = []
761 if not ( site_filter_name_list or return_fields_list):
762 return_site_list = site_dict.values()
763 return return_site_list
765 for site_filter_name in site_filter_name_list:
766 if site_filter_name in site_dict:
767 if return_fields_list:
768 for field in return_fields_list:
771 tmp[field] = site_dict[site_filter_name][field]
773 logger.error("GetSites KeyError %s "%(field))
775 return_site_list.append(tmp)
777 return_site_list.append( site_dict[site_filter_name])
780 return return_site_list
784 def GetSlices(self, slice_filter = None, slice_filter_type = None):
785 #def GetSlices(self, slice_filter = None, slice_filter_type = None, \
786 #return_fields_list = None):
787 """ Get the slice records from the slab db.
788 Returns a slice ditc if slice_filter and slice_filter_type
790 Returns a list of slice dictionnaries if there are no filters
795 return_slice_list = []
798 authorized_filter_types_list = ['slice_hrn', 'record_id_user']
799 slicerec_dictlist = []
802 if slice_filter_type in authorized_filter_types_list:
805 def __get_slice_records(slice_filter = None, slice_filter_type = None):
808 #Get list of slices based on the slice hrn
809 if slice_filter_type == 'slice_hrn':
811 login = slice_filter.split(".")[1].split("_")[0]
813 #DO NOT USE RegSlice - reg_researchers to get the hrn of the user
814 #otherwise will mess up the RegRecord in Resolve, don't know
817 #Only one entry for one user = one slice in slice_senslab table
818 slicerec = slab_dbsession.query(SliceSenslab).filter_by(slice_hrn = slice_filter).first()
820 #Get slice based on user id
821 if slice_filter_type == 'record_id_user':
822 slicerec = slab_dbsession.query(SliceSenslab).filter_by(record_id_user = slice_filter).first()
827 fixed_slicerec_dict = slicerec.dump_sqlalchemyobj_to_dict()
830 login = fixed_slicerec_dict['slice_hrn'].split(".")[1].split("_")[0]
831 return login, fixed_slicerec_dict
836 login, fixed_slicerec_dict = __get_slice_records(slice_filter, slice_filter_type)
837 logger.debug(" SLABDRIVER \tGetSlices login %s \
839 %(login, fixed_slicerec_dict))
843 #One slice can have multiple jobs
845 leases_list = self.GetReservedNodes(username = login)
847 #Several jobs for one slice
849 for lease in leases_list :
853 #Check with OAR the status of the job if a job id is in
858 slicerec_dict['oar_job_id'] = lease['lease_id']
859 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
860 slicerec_dict.update(fixed_slicerec_dict)
861 slicerec_dict.update({'hrn':\
862 str(fixed_slicerec_dict['slice_hrn'])})
865 slicerec_dictlist.append(slicerec_dict)
866 logger.debug("SLABDRIVER.PY \tGetSlices slicerec_dict %s slicerec_dictlist %s" %(slicerec_dict, slicerec_dictlist))
868 logger.debug("SLABDRIVER.PY \tGetSlices RETURN slicerec_dictlist %s"\
869 %(slicerec_dictlist))
871 return slicerec_dictlist
876 slice_list = slab_dbsession.query(SliceSenslab).all()
877 leases_list = self.GetReservedNodes()
880 slicerec_dictlist = []
881 return_slice_list = []
882 for record in slice_list:
883 return_slice_list.append(record.dump_sqlalchemyobj_to_dict())
885 for fixed_slicerec_dict in return_slice_list:
887 owner = fixed_slicerec_dict['slice_hrn'].split(".")[1].split("_")[0]
888 for lease in leases_list:
889 if owner == lease['user']:
890 slicerec_dict['oar_job_id'] = lease['lease_id']
891 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
892 slicerec_dict.update(fixed_slicerec_dict)
893 slicerec_dict.update({'hrn':\
894 str(fixed_slicerec_dict['slice_hrn'])})
895 slicerec_dictlist.append(slicerec_dict)
897 logger.debug("SLABDRIVER.PY \tGetSlices RETURN slices %s \
898 slice_filter %s " %(return_slice_list, slice_filter))
900 #if return_fields_list:
901 #return_slice_list = parse_filter(sliceslist, \
902 #slice_filter,'slice', return_fields_list)
904 return slicerec_dictlist
907 def testbed_name (self): return self.hrn
909 # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
910 def aggregate_version (self):
911 version_manager = VersionManager()
912 ad_rspec_versions = []
913 request_rspec_versions = []
914 for rspec_version in version_manager.versions:
915 if rspec_version.content_type in ['*', 'ad']:
916 ad_rspec_versions.append(rspec_version.to_dict())
917 if rspec_version.content_type in ['*', 'request']:
918 request_rspec_versions.append(rspec_version.to_dict())
920 'testbed':self.testbed_name(),
921 'geni_request_rspec_versions': request_rspec_versions,
922 'geni_ad_rspec_versions': ad_rspec_versions,
931 # Convert SFA fields to PLC fields for use when registering up updating
932 # registry record in the PLC database
934 # @param type type of record (user, slice, ...)
935 # @param hrn human readable name
936 # @param sfa_fields dictionary of SFA fields
937 # @param slab_fields dictionary of PLC fields (output)
939 def sfa_fields_to_slab_fields(self, sfa_type, hrn, record):
943 #for field in record:
944 # slab_record[field] = record[field]
946 if sfa_type == "slice":
947 #instantion used in get_slivers ?
948 if not "instantiation" in slab_record:
949 slab_record["instantiation"] = "senslab-instantiated"
950 #slab_record["hrn"] = hrn_to_pl_slicename(hrn)
951 #Unused hrn_to_pl_slicename because Slab's hrn already in the appropriate form SA 23/07/12
952 slab_record["hrn"] = hrn
953 logger.debug("SLABDRIVER.PY sfa_fields_to_slab_fields \
954 slab_record %s " %(slab_record['hrn']))
956 slab_record["url"] = record["url"]
957 if "description" in record:
958 slab_record["description"] = record["description"]
959 if "expires" in record:
960 slab_record["expires"] = int(record["expires"])
962 #nodes added by OAR only and then imported to SFA
963 #elif type == "node":
964 #if not "hostname" in slab_record:
965 #if not "hostname" in record:
966 #raise MissingSfaInfo("hostname")
967 #slab_record["hostname"] = record["hostname"]
968 #if not "model" in slab_record:
969 #slab_record["model"] = "geni"
972 #elif type == "authority":
973 #slab_record["login_base"] = hrn_to_slab_login_base(hrn)
975 #if not "name" in slab_record:
976 #slab_record["name"] = hrn
978 #if not "abbreviated_name" in slab_record:
979 #slab_record["abbreviated_name"] = hrn
981 #if not "enabled" in slab_record:
982 #slab_record["enabled"] = True
984 #if not "is_public" in slab_record:
985 #slab_record["is_public"] = True
992 def __transforms_timestamp_into_date(self, xp_utc_timestamp = None):
993 """ Transforms unix timestamp into valid OAR date format """
995 #Used in case of a scheduled experiment (not immediate)
996 #To run an XP immediately, don't specify date and time in RSpec
997 #They will be set to None.
999 #transform the xp_utc_timestamp into server readable time
1000 xp_server_readable_date = datetime.fromtimestamp(int(\
1001 xp_utc_timestamp)).strftime(self.time_format)
1003 return xp_server_readable_date
1011 def LaunchExperimentOnOAR(self, added_nodes, slice_name, \
1012 lease_start_time, lease_duration, slice_user=None):
1014 lease_dict['lease_start_time'] = lease_start_time
1015 lease_dict['lease_duration'] = lease_duration
1016 lease_dict['added_nodes'] = added_nodes
1017 lease_dict['slice_name'] = slice_name
1018 lease_dict['slice_user'] = slice_user
1019 lease_dict['grain'] = self.GetLeaseGranularity()
1020 lease_dict['time_format'] = self.time_format
1022 def __create_job_structure_request_for_OAR(lease_dict):
1023 """ Creates the structure needed for a correct POST on OAR.
1024 Makes the timestamp transformation into the appropriate format.
1025 Sends the POST request to create the job with the resources in
1034 reqdict['workdir'] = '/tmp'
1035 reqdict['resource'] = "{network_address in ("
1037 for node in lease_dict['added_nodes']:
1038 logger.debug("\r\n \r\n OARrestapi \t __create_job_structure_request_for_OAR \
1041 # Get the ID of the node
1043 reqdict['resource'] += "'" + nodeid + "', "
1044 nodeid_list.append(nodeid)
1046 custom_length = len(reqdict['resource'])- 2
1047 reqdict['resource'] = reqdict['resource'][0:custom_length] + \
1048 ")}/nodes=" + str(len(nodeid_list))
1050 def __process_walltime(duration):
1051 """ Calculates the walltime in seconds from the duration in H:M:S
1052 specified in the RSpec.
1056 # Fixing the walltime by adding a few delays.
1057 # First put the walltime in seconds oarAdditionalDelay = 20;
1058 # additional delay for /bin/sleep command to
1059 # take in account prologue and epilogue scripts execution
1060 # int walltimeAdditionalDelay = 120; additional delay
1061 desired_walltime = duration
1062 total_walltime = desired_walltime + 140#+2 min 20
1063 sleep_walltime = desired_walltime + 20 #+20 sec
1065 #Put the walltime back in str form
1066 #First get the hours
1067 walltime.append(str(total_walltime / 3600))
1068 total_walltime = total_walltime - 3600 * int(walltime[0])
1069 #Get the remaining minutes
1070 walltime.append(str(total_walltime / 60))
1071 total_walltime = total_walltime - 60 * int(walltime[1])
1073 walltime.append(str(total_walltime))
1076 logger.log_exc(" __process_walltime duration null")
1078 return walltime, sleep_walltime
1081 walltime, sleep_walltime = \
1082 __process_walltime(int(lease_dict['lease_duration'])*lease_dict['grain'])
1085 reqdict['resource'] += ",walltime=" + str(walltime[0]) + \
1086 ":" + str(walltime[1]) + ":" + str(walltime[2])
1087 reqdict['script_path'] = "/bin/sleep " + str(sleep_walltime)
1089 #In case of a scheduled experiment (not immediate)
1090 #To run an XP immediately, don't specify date and time in RSpec
1091 #They will be set to None.
1092 if lease_dict['lease_start_time'] is not '0':
1093 #Readable time accepted by OAR
1094 start_time = datetime.fromtimestamp(int(lease_dict['lease_start_time'])).\
1095 strftime(lease_dict['time_format'])
1096 reqdict['reservation'] = start_time
1097 #If there is not start time, Immediate XP. No need to add special
1101 reqdict['type'] = "deploy"
1102 reqdict['directory'] = ""
1103 reqdict['name'] = "SFA_" + lease_dict['slice_user']
1108 #Create the request for OAR
1109 reqdict = __create_job_structure_request_for_OAR(lease_dict)
1110 # first step : start the OAR job and update the job
1111 logger.debug("SLABDRIVER.PY \tLaunchExperimentOnOAR reqdict %s\
1114 answer = self.oar.POSTRequestToOARRestAPI('POST_job', \
1115 reqdict, slice_user)
1116 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s " %(answer))
1118 jobid = answer['id']
1120 logger.log_exc("SLABDRIVER \tLaunchExperimentOnOAR \
1121 Impossible to create job %s " %(answer))
1125 def __configure_experiment(jobid, added_nodes):
1126 # second step : configure the experiment
1127 # we need to store the nodes in a yaml (well...) file like this :
1128 # [1,56,23,14,45,75] with name /tmp/sfa<jobid>.json
1129 job_file = open('/tmp/sfa/'+ str(jobid) + '.json', 'w')
1131 job_file.write(str(added_nodes[0].strip('node')))
1132 for node in added_nodes[1:len(added_nodes)] :
1133 job_file.write(', '+ node.strip('node'))
1138 def __launch_senslab_experiment(jobid):
1139 # third step : call the senslab-experiment wrapper
1140 #command= "java -jar target/sfa-1.0-jar-with-dependencies.jar
1141 # "+str(jobid)+" "+slice_user
1142 javacmdline = "/usr/bin/java"
1144 "/opt/senslabexperimentwrapper/sfa-1.0-jar-with-dependencies.jar"
1145 #ret=subprocess.check_output(["/usr/bin/java", "-jar", ", \
1146 #str(jobid), slice_user])
1147 output = subprocess.Popen([javacmdline, "-jar", jarname, str(jobid), \
1148 slice_user],stdout=subprocess.PIPE).communicate()[0]
1150 logger.debug("SLABDRIVER \t __configure_experiment wrapper returns%s " \
1157 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s \
1158 added_nodes %s slice_user %s" %(jobid, added_nodes, slice_user))
1159 self.db.add_job( slice_name, jobid, added_nodes)
1161 __configure_experiment(jobid, added_nodes)
1162 __launch_senslab_experiment(jobid)
1166 def AddLeases(self, hostname_list, slice_record, lease_start_time, lease_duration):
1167 logger.debug("SLABDRIVER \r\n \r\n \t AddLeases hostname_list %s \
1168 slice_record %s lease_start_time %s lease_duration %s "\
1169 %( hostname_list, slice_record , lease_start_time, \
1172 tmp = slice_record['PI'][0].split(".")
1173 username = tmp[(len(tmp)-1)]
1174 self.LaunchExperimentOnOAR(hostname_list, slice_record['name'], lease_start_time, lease_duration, username)
1175 start_time = datetime.fromtimestamp(int(lease_start_time)).strftime(self.time_format)
1176 logger.debug("SLABDRIVER \t AddLeases hostname_list start_time %s " %(start_time))
1181 #Delete the jobs from job_senslab table
1182 def DeleteSliceFromNodes(self, slice_record):
1184 self.DeleteJobs(slice_record['oar_job_id'], slice_record['hrn'])
1188 def GetLeaseGranularity(self):
1189 """ Returns the granularity of Senslab testbed.
1190 Defined in seconds. """
1195 def GetLeases(self, lease_filter_dict=None):
1196 unfiltered_reservation_list = self.GetReservedNodes()
1198 ##Synchronize slice_table of sfa senslab db
1199 #self.synchronize_oar_and_slice_table(unfiltered_reservation_list)
1201 reservation_list = []
1202 #Find the slice associated with this user senslab ldap uid
1203 logger.debug(" SLABDRIVER.PY \tGetLeases ")
1204 #Create user dict first to avoir looking several times for
1205 #the same user in LDAP SA 27/07/12
1207 for resa in unfiltered_reservation_list:
1208 logger.debug("SLABDRIVER \tGetLeases USER %s"\
1210 if resa['user'] not in resa_user_dict:
1211 logger.debug("SLABDRIVER \tGetLeases userNOTIN ")
1212 ldap_info = self.ldap.LdapSearch('(uid='+resa['user']+')')
1213 ldap_info = ldap_info[0][1]
1214 user = dbsession.query(RegUser).filter_by(email = \
1215 ldap_info['mail'][0]).first()
1216 #Separated in case user not in database : record_id not defined SA 17/07//12
1217 query_slice_info = slab_dbsession.query(SliceSenslab).filter_by(record_id_user = user.record_id)
1218 if query_slice_info:
1219 slice_info = query_slice_info.first()
1223 resa_user_dict[resa['user']] = {}
1224 resa_user_dict[resa['user']]['ldap_info'] = user
1225 resa_user_dict[resa['user']]['slice_info'] = slice_info
1227 logger.debug("SLABDRIVER \tGetLeases resa_user_dict %s"\
1229 for resa in unfiltered_reservation_list:
1233 resa['slice_hrn'] = resa_user_dict[resa['user']]['slice_info'].slice_hrn
1234 resa['slice_id'] = hrn_to_urn(resa['slice_hrn'], 'slice')
1236 #resa['slice_id'] = hrn_to_urn(slice_info.slice_hrn, 'slice')
1237 resa['component_id_list'] = []
1238 #Transform the hostnames into urns (component ids)
1239 for node in resa['reserved_nodes']:
1240 #resa['component_id_list'].append(hostname_to_urn(self.hrn, \
1241 #self.root_auth, node['hostname']))
1242 slab_xrn = slab_xrn_object(self.root_auth, node['hostname'])
1243 resa['component_id_list'].append(slab_xrn.urn)
1245 #Filter the reservation list if necessary
1246 #Returns all the leases associated with a given slice
1247 if lease_filter_dict:
1248 logger.debug("SLABDRIVER \tGetLeases lease_filter_dict %s"\
1249 %(lease_filter_dict))
1250 for resa in unfiltered_reservation_list:
1251 if lease_filter_dict['name'] == resa['slice_hrn']:
1252 reservation_list.append(resa)
1254 reservation_list = unfiltered_reservation_list
1256 logger.debug(" SLABDRIVER.PY \tGetLeases reservation_list %s"\
1257 %(reservation_list))
1258 return reservation_list
1260 def augment_records_with_testbed_info (self, sfa_records):
1261 return self.fill_record_info (sfa_records)
1263 def fill_record_info(self, record_list):
1265 Given a SFA record, fill in the senslab specific and SFA specific
1266 fields in the record.
1269 logger.debug("SLABDRIVER \tfill_record_info records %s " %(record_list))
1270 if not isinstance(record_list, list):
1271 record_list = [record_list]
1274 for record in record_list:
1275 #If the record is a SFA slice record, then add information
1276 #about the user of this slice. This kind of
1277 #information is in the Senslab's DB.
1278 if str(record['type']) == 'slice':
1279 #Get slab slice record.
1280 recslice_list = self.GetSlices(slice_filter = \
1281 str(record['hrn']),\
1282 slice_filter_type = 'slice_hrn')
1284 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1285 recslice_list[0]['record_id_user']).first()
1286 logger.debug("SLABDRIVER \tfill_record_info TYPE SLICE RECUSER %s " %(recuser))
1287 record.update({'PI':[recuser.hrn],
1288 'researcher': [recuser.hrn],
1289 'name':record['hrn'],
1290 'oar_job_id':[rec['oar_job_id'] for rec in recslice_list],
1292 'person_ids':[recslice_list[0]['record_id_user']],
1293 'geni_urn':'', #For client_helper.py compatibility
1294 'keys':'', #For client_helper.py compatibility
1295 'key_ids':''}) #For client_helper.py compatibility
1297 #for rec in recslice_list:
1298 #record['oar_job_id'].append(rec['oar_job_id'])
1299 logger.debug( "SLABDRIVER.PY \t fill_record_info SLICE \
1300 recslice_list %s \r\n \t RECORD %s \r\n \r\n" %(recslice_list,record))
1301 if str(record['type']) == 'user':
1302 #The record is a SFA user record.
1303 #Get the information about his slice from Senslab's DB
1304 #and add it to the user record.
1305 recslice_list = self.GetSlices(\
1306 slice_filter = record['record_id'],\
1307 slice_filter_type = 'record_id_user')
1309 logger.debug( "SLABDRIVER.PY \t fill_record_info TYPE USER \
1310 recslice_list %s \r\n \t RECORD %s \r\n" %(recslice_list , record))
1311 #Append slice record in records list,
1312 #therefore fetches user and slice info again(one more loop)
1313 #Will update PIs and researcher for the slice
1314 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1315 recslice_list[0]['record_id_user']).first()
1316 logger.debug( "SLABDRIVER.PY \t fill_record_info USER \
1317 recuser %s \r\n \r\n" %(recuser))
1319 recslice = recslice_list[0]
1320 recslice.update({'PI':[recuser.hrn],
1321 'researcher': [recuser.hrn],
1322 'name':record['hrn'],
1324 'oar_job_id': [rec['oar_job_id'] for rec in recslice_list],
1325 'person_ids':[recslice_list[0]['record_id_user']]})
1326 recslice.update({'type':'slice', \
1327 'hrn':recslice_list[0]['slice_hrn']})
1328 #for rec in recslice_list:
1329 #recslice['oar_job_id'].append(rec['oar_job_id'])
1331 #GetPersons takes [] as filters
1332 #user_slab = self.GetPersons([{'hrn':recuser.hrn}])
1333 user_slab = self.GetPersons([record])
1336 record.update(user_slab[0])
1337 #For client_helper.py compatibility
1338 record.update( { 'geni_urn':'',
1341 record_list.append(recslice)
1343 logger.debug("SLABDRIVER.PY \tfill_record_info ADDING SLICE\
1344 INFO TO USER records %s" %(record_list))
1345 logger.debug("SLABDRIVER.PY \tfill_record_info END \
1346 #record %s \r\n \r\n " %(record))
1348 except TypeError, error:
1349 logger.log_exc("SLABDRIVER \t fill_record_info EXCEPTION %s"\
1351 #logger.debug("SLABDRIVER.PY \t fill_record_info ENDENDEND ")
1355 #self.fill_record_slab_info(records)
1361 #TODO Update membership? update_membership_list SA 05/07/12
1362 #def update_membership_list(self, oldRecord, record, listName, addFunc, \
1364 ## get a list of the HRNs tht are members of the old and new records
1366 #oldList = oldRecord.get(listName, [])
1369 #newList = record.get(listName, [])
1371 ## if the lists are the same, then we don't have to update anything
1372 #if (oldList == newList):
1375 ## build a list of the new person ids, by looking up each person to get
1379 #records = table.find({'type': 'user', 'hrn': newList})
1380 #for rec in records:
1381 #newIdList.append(rec['pointer'])
1383 ## build a list of the old person ids from the person_ids field
1385 #oldIdList = oldRecord.get("person_ids", [])
1386 #containerId = oldRecord.get_pointer()
1388 ## if oldRecord==None, then we are doing a Register, instead of an
1391 #containerId = record.get_pointer()
1393 ## add people who are in the new list, but not the oldList
1394 #for personId in newIdList:
1395 #if not (personId in oldIdList):
1396 #addFunc(self.plauth, personId, containerId)
1398 ## remove people who are in the old list, but not the new list
1399 #for personId in oldIdList:
1400 #if not (personId in newIdList):
1401 #delFunc(self.plauth, personId, containerId)
1403 #def update_membership(self, oldRecord, record):
1405 #if record.type == "slice":
1406 #self.update_membership_list(oldRecord, record, 'researcher',
1407 #self.users.AddPersonToSlice,
1408 #self.users.DeletePersonFromSlice)
1409 #elif record.type == "authority":
1414 # I don't think you plan on running a component manager at this point
1415 # let me clean up the mess of ComponentAPI that is deprecated anyways
1418 #TODO FUNCTIONS SECTION 04/07/2012 SA
1420 #TODO : Is UnBindObjectFromPeer still necessary ? Currently does nothing
1422 def UnBindObjectFromPeer(self, auth, object_type, object_id, shortname):
1423 """ This method is a hopefully temporary hack to let the sfa correctly
1424 detach the objects it creates from a remote peer object. This is
1425 needed so that the sfa federation link can work in parallel with
1426 RefreshPeer, as RefreshPeer depends on remote objects being correctly
1429 auth : struct, API authentication structure
1430 AuthMethod : string, Authentication method to use
1431 object_type : string, Object type, among 'site','person','slice',
1433 object_id : int, object_id
1434 shortname : string, peer shortname
1438 logger.warning("SLABDRIVER \tUnBindObjectFromPeer EMPTY-\
1442 #TODO Is BindObjectToPeer still necessary ? Currently does nothing
1444 def BindObjectToPeer(self, auth, object_type, object_id, shortname=None, \
1445 remote_object_id=None):
1446 """This method is a hopefully temporary hack to let the sfa correctly
1447 attach the objects it creates to a remote peer object. This is needed
1448 so that the sfa federation link can work in parallel with RefreshPeer,
1449 as RefreshPeer depends on remote objects being correctly marked.
1451 shortname : string, peer shortname
1452 remote_object_id : int, remote object_id, set to 0 if unknown
1456 logger.warning("SLABDRIVER \tBindObjectToPeer EMPTY - DO NOTHING \r\n ")
1459 #TODO UpdateSlice 04/07/2012 SA
1460 #Funciton should delete and create another job since oin senslab slice=job
1461 def UpdateSlice(self, auth, slice_id_or_name, slice_fields=None):
1462 """Updates the parameters of an existing slice with the values in
1464 Users may only update slices of which they are members.
1465 PIs may update any of the slices at their sites, or any slices of
1466 which they are members. Admins may update any slice.
1467 Only PIs and admins may update max_nodes. Slices cannot be renewed
1468 (by updating the expires parameter) more than 8 weeks into the future.
1469 Returns 1 if successful, faults otherwise.
1473 logger.warning("SLABDRIVER UpdateSlice EMPTY - DO NOTHING \r\n ")
1476 #TODO UpdatePerson 04/07/2012 SA
1477 def UpdatePerson(self, auth, person_id_or_email, person_fields=None):
1478 """Updates a person. Only the fields specified in person_fields
1479 are updated, all other fields are left untouched.
1480 Users and techs can only update themselves. PIs can only update
1481 themselves and other non-PIs at their sites.
1482 Returns 1 if successful, faults otherwise.
1486 logger.warning("SLABDRIVER UpdatePerson EMPTY - DO NOTHING \r\n ")
1489 #TODO GetKeys 04/07/2012 SA
1490 def GetKeys(self, auth, key_filter=None, return_fields=None):
1491 """Returns an array of structs containing details about keys.
1492 If key_filter is specified and is an array of key identifiers,
1493 or a struct of key attributes, only keys matching the filter
1494 will be returned. If return_fields is specified, only the
1495 specified details will be returned.
1497 Admin may query all keys. Non-admins may only query their own keys.
1501 logger.warning("SLABDRIVER GetKeys EMPTY - DO NOTHING \r\n ")
1504 #TODO DeleteKey 04/07/2012 SA
1505 def DeleteKey(self, auth, key_id):
1507 Non-admins may only delete their own keys.
1508 Returns 1 if successful, faults otherwise.
1512 logger.warning("SLABDRIVER DeleteKey EMPTY - DO NOTHING \r\n ")
1516 #TODO : Check rights to delete person
1517 def DeletePerson(self, auth, person_record):
1518 """ Disable an existing account in senslab LDAP.
1519 Users and techs can only delete themselves. PIs can only
1520 delete themselves and other non-PIs at their sites.
1521 ins can delete anyone.
1522 Returns 1 if successful, faults otherwise.
1526 #Disable user account in senslab LDAP
1527 ret = self.ldap.LdapMarkUserAsDeleted(person_record)
1528 logger.warning("SLABDRIVER DeletePerson %s " %(person_record))
1531 #TODO Check DeleteSlice, check rights 05/07/2012 SA
1532 def DeleteSlice(self, auth, slice_record):
1533 """ Deletes the specified slice.
1534 Senslab : Kill the job associated with the slice if there is one
1535 using DeleteSliceFromNodes.
1536 Updates the slice record in slab db to remove the slice nodes.
1538 Users may only delete slices of which they are members. PIs may
1539 delete any of the slices at their sites, or any slices of which
1540 they are members. Admins may delete any slice.
1541 Returns 1 if successful, faults otherwise.
1545 self.DeleteSliceFromNodes(slice_record)
1546 logger.warning("SLABDRIVER DeleteSlice %s "%(slice_record))
1549 #TODO AddPerson 04/07/2012 SA
1550 def AddPerson(self, auth, person_fields=None):
1551 """Adds a new account. Any fields specified in person_fields are used,
1552 otherwise defaults are used.
1553 Accounts are disabled by default. To enable an account,
1555 Returns the new person_id (> 0) if successful, faults otherwise.
1559 logger.warning("SLABDRIVER AddPerson EMPTY - DO NOTHING \r\n ")
1562 #TODO AddPersonToSite 04/07/2012 SA
1563 def AddPersonToSite (self, auth, person_id_or_email, \
1564 site_id_or_login_base=None):
1565 """ Adds the specified person to the specified site. If the person is
1566 already a member of the site, no errors are returned. Does not change
1567 the person's primary site.
1568 Returns 1 if successful, faults otherwise.
1572 logger.warning("SLABDRIVER AddPersonToSite EMPTY - DO NOTHING \r\n ")
1575 #TODO AddRoleToPerson : Not sure if needed in senslab 04/07/2012 SA
1576 def AddRoleToPerson(self, auth, role_id_or_name, person_id_or_email):
1577 """Grants the specified role to the person.
1578 PIs can only grant the tech and user roles to users and techs at their
1579 sites. Admins can grant any role to any user.
1580 Returns 1 if successful, faults otherwise.
1584 logger.warning("SLABDRIVER AddRoleToPerson EMPTY - DO NOTHING \r\n ")
1587 #TODO AddPersonKey 04/07/2012 SA
1588 def AddPersonKey(self, auth, person_id_or_email, key_fields=None):
1589 """Adds a new key to the specified account.
1590 Non-admins can only modify their own keys.
1591 Returns the new key_id (> 0) if successful, faults otherwise.
1595 logger.warning("SLABDRIVER AddPersonKey EMPTY - DO NOTHING \r\n ")
1598 def DeleteLeases(self, leases_id_list, slice_hrn ):
1599 for job_id in leases_id_list:
1600 self.DeleteJobs(job_id, slice_hrn)
1602 logger.debug("SLABDRIVER DeleteLeases leases_id_list %s slice_hrn %s \
1603 \r\n " %(leases_id_list, slice_hrn))