3 from datetime import datetime
5 from sfa.util.faults import SliverDoesNotExist, UnknownSfaType
6 from sfa.util.sfalogging import logger
8 from sfa.storage.alchemy import dbsession
9 from sfa.storage.model import RegRecord, RegUser
11 from sfa.trust.credential import Credential
14 from sfa.managers.driver import Driver
15 from sfa.rspecs.version_manager import VersionManager
16 from sfa.rspecs.rspec import RSpec
18 from sfa.util.xrn import hrn_to_urn
21 ## thierry: everything that is API-related (i.e. handling incoming requests)
23 # SlabDriver should be really only about talking to the senslab testbed
26 from sfa.senslab.OARrestapi import OARrestapi
27 from sfa.senslab.LDAPapi import LDAPapi
29 from sfa.senslab.slabpostgres import SlabDB, slab_dbsession, SliceSenslab
31 from sfa.senslab.slabaggregate import SlabAggregate, slab_xrn_to_hostname, \
33 from sfa.senslab.slabslices import SlabSlices
40 # this inheritance scheme is so that the driver object can receive
41 # GetNodes or GetSites sorts of calls directly
42 # and thus minimize the differences in the managers with the pl version
43 class SlabDriver(Driver):
44 """ Senslab Driver class inherited from Driver generic class.
46 Contains methods compliant with the SFA standard and the testbed
47 infrastructure (calls to LDAP and OAR).
49 def __init__(self, config):
50 Driver.__init__ (self, config)
52 self.hrn = config.SFA_INTERFACE_HRN
53 self.root_auth = config.SFA_REGISTRY_ROOT_AUTH
54 self.oar = OARrestapi()
56 self.time_format = "%Y-%m-%d %H:%M:%S"
57 self.db = SlabDB(config, debug = True)
61 def sliver_status(self, slice_urn, slice_hrn):
62 """Receive a status request for slice named urn/hrn
63 urn:publicid:IDN+senslab+nturro_slice hrn senslab.nturro_slice
64 shall return a structure as described in
65 http://groups.geni.net/geni/wiki/GAPI_AM_API_V2#SliverStatus
66 NT : not sure if we should implement this or not, but used by sface.
70 #First get the slice with the slice hrn
71 slice_list = self.GetSlices(slice_filter = slice_hrn, \
72 slice_filter_type = 'slice_hrn')
74 if len(slice_list) is 0:
75 raise SliverDoesNotExist("%s slice_hrn" % (slice_hrn))
77 #Slice has the same slice hrn for each slice in the slice/lease list
78 #So fetch the info on the user once
79 one_slice = slice_list[0]
80 recuser = dbsession.query(RegRecord).filter_by(record_id = \
81 one_slice['record_id_user']).first()
83 #Make a list of all the nodes hostnames in use for this slice
86 for node in sl['node_ids']:
87 slice_nodes_list.append(node['hostname'])
89 #Get all the corresponding nodes details
90 nodes_all = self.GetNodes({'hostname':slice_nodes_list},
91 ['node_id', 'hostname','site','boot_state'])
92 nodeall_byhostname = dict([(n['hostname'], n) for n in nodes_all])
99 top_level_status = 'empty'
101 result.fromkeys(['geni_urn','pl_login','geni_status','geni_resources'],None)
102 result['pl_login'] = recuser.hrn
103 logger.debug("Slabdriver - sliver_status Sliver status urn %s hrn %s sl\
104 %s \r\n " %(slice_urn, slice_hrn, sl))
106 nodes_in_slice = sl['node_ids']
109 result['geni_status'] = top_level_status
110 result['geni_resources'] = []
113 top_level_status = 'ready'
115 #A job is running on Senslab for this slice
116 # report about the local nodes that are in the slice only
118 result['geni_urn'] = slice_urn
122 #timestamp = float(sl['startTime']) + float(sl['walltime'])
123 #result['pl_expires'] = strftime(self.time_format, \
124 #gmtime(float(timestamp)))
125 #result['slab_expires'] = strftime(self.time_format,\
126 #gmtime(float(timestamp)))
129 for node in sl['node_ids']:
131 #res['slab_hostname'] = node['hostname']
132 #res['slab_boot_state'] = node['boot_state']
134 res['pl_hostname'] = node['hostname']
135 res['pl_boot_state'] = nodeall_byhostname[node['hostname']]['boot_state']
136 #res['pl_last_contact'] = strftime(self.time_format, \
137 #gmtime(float(timestamp)))
138 sliver_id = Xrn(slice_urn, type='slice', \
139 id=nodeall_byhostname[node['hostname']]['node_id'], \
140 authority=self.hrn).urn
142 res['geni_urn'] = sliver_id
143 if nodeall_byhostname[node['hostname']]['boot_state'] == 'Alive':
145 res['geni_status'] = 'ready'
147 res['geni_status'] = 'failed'
148 top_level_status = 'failed'
150 res['geni_error'] = ''
152 resources.append(res)
154 result['geni_status'] = top_level_status
155 result['geni_resources'] = resources
156 logger.debug("SLABDRIVER \tsliver_statusresources %s res %s "\
161 def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, \
163 aggregate = SlabAggregate(self)
165 slices = SlabSlices(self)
166 peer = slices.get_peer(slice_hrn)
167 sfa_peer = slices.get_sfa_peer(slice_hrn)
170 if not isinstance(creds, list):
174 slice_record = users[0].get('slice_record', {})
177 rspec = RSpec(rspec_string)
178 logger.debug("SLABDRIVER.PY \t create_sliver \tr spec.version %s slice_record %s " \
179 %(rspec.version,slice_record))
181 #self.synchronize_oar_and_slice_table(slice_hrn)
182 # ensure site record exists?
183 # ensure slice record exists
184 #Removed options to verify_slice SA 14/08/12
185 sfa_slice = slices.verify_slice(slice_hrn, slice_record, peer, \
188 #requested_attributes returned by rspec.version.get_slice_attributes()
189 #unused, removed SA 13/08/12
190 rspec.version.get_slice_attributes()
192 logger.debug("SLABDRIVER.PY create_sliver slice %s " %(sfa_slice))
194 # ensure person records exists
195 #verify_persons returns added persons but since the return value
197 slices.verify_persons(slice_hrn, sfa_slice, users, peer, \
198 sfa_peer, options=options)
202 # add/remove slice from nodes
204 requested_slivers = [node.get('component_name') \
205 for node in rspec.version.get_nodes_with_slivers()]
206 l = [ node for node in rspec.version.get_nodes_with_slivers() ]
207 logger.debug("SLADRIVER \tcreate_sliver requested_slivers \
208 requested_slivers %s listnodes %s" \
209 %(requested_slivers,l))
210 #verify_slice_nodes returns nodes, but unused here. Removed SA 13/08/12.
211 slices.verify_slice_nodes(sfa_slice, requested_slivers, peer)
214 requested_lease_list = []
216 for lease in rspec.version.get_leases():
217 single_requested_lease = {}
218 logger.debug("SLABDRIVER.PY \tcreate_sliver lease %s " %(lease))
219 if not lease.get('lease_id'):
220 single_requested_lease['hostname'] = \
221 slab_xrn_to_hostname(lease.get('component_id').strip())
222 single_requested_lease['start_time'] = lease.get('start_time')
223 single_requested_lease['duration'] = lease.get('duration')
225 kept_leases.append(int(lease['lease_id']))
226 if single_requested_lease.get('hostname'):
227 requested_lease_list.append(single_requested_lease)
229 #dCreate dict of leases by start_time, regrouping nodes reserved
231 #time, for the same amount of time = one job on OAR
232 requested_job_dict = {}
233 for lease in requested_lease_list:
235 #In case it is an asap experiment start_time is empty
236 if lease['start_time'] == '':
237 lease['start_time'] = '0'
239 if lease['start_time'] not in requested_job_dict:
240 if isinstance(lease['hostname'], str):
241 lease['hostname'] = [lease['hostname']]
243 requested_job_dict[lease['start_time']] = lease
246 job_lease = requested_job_dict[lease['start_time']]
247 if lease['duration'] == job_lease['duration'] :
248 job_lease['hostname'].append(lease['hostname'])
253 logger.debug("SLABDRIVER.PY \tcreate_sliver requested_job_dict %s " %(requested_job_dict))
254 #verify_slice_leases returns the leases , but the return value is unused
255 #here. Removed SA 13/08/12
256 slices.verify_slice_leases(sfa_slice, \
257 requested_job_dict, kept_leases, peer)
259 return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
262 def delete_sliver (self, slice_urn, slice_hrn, creds, options):
264 sfa_slice_list = self.GetSlices(slice_filter = slice_hrn, \
265 slice_filter_type = 'slice_hrn')
267 if not sfa_slice_list:
270 #Delete all in the slice
271 for sfa_slice in sfa_slice_list:
274 logger.debug("SLABDRIVER.PY delete_sliver slice %s" %(sfa_slice))
275 slices = SlabSlices(self)
276 # determine if this is a peer slice
278 peer = slices.get_peer(slice_hrn)
279 #TODO delete_sliver SA : UnBindObjectFromPeer should be
280 #used when there is another
281 #senslab testbed, which is not the case 14/08/12 .
283 logger.debug("SLABDRIVER.PY delete_sliver peer %s" %(peer))
286 self.UnBindObjectFromPeer('slice', \
287 sfa_slice['record_id_slice'], peer,None)
288 self.DeleteSliceFromNodes(sfa_slice)
291 self.BindObjectToPeer('slice', sfa_slice['record_id_slice'], \
292 peer, sfa_slice['peer_slice_id'])
296 def AddSlice(self, slice_record):
297 slab_slice = SliceSenslab( slice_hrn = slice_record['slice_hrn'], \
298 record_id_slice= slice_record['record_id_slice'] , \
299 record_id_user= slice_record['record_id_user'], \
300 peer_authority = slice_record['peer_authority'])
301 logger.debug("SLABDRIVER.PY \tAddSlice slice_record %s slab_slice %s" \
302 %(slice_record,slab_slice))
303 slab_dbsession.add(slab_slice)
304 slab_dbsession.commit()
307 # first 2 args are None in case of resource discovery
308 def list_resources (self, slice_urn, slice_hrn, creds, options):
309 #cached_requested = options.get('cached', True)
311 version_manager = VersionManager()
312 # get the rspec's return format from options
314 version_manager.get_version(options.get('geni_rspec_version'))
315 version_string = "rspec_%s" % (rspec_version)
317 #panos adding the info option to the caching key (can be improved)
318 if options.get('info'):
319 version_string = version_string + "_" + \
320 options.get('info', 'default')
322 # look in cache first
323 #if cached_requested and self.cache and not slice_hrn:
324 #rspec = self.cache.get(version_string)
326 #logger.debug("SlabDriver.ListResources: \
327 #returning cached advertisement")
330 #panos: passing user-defined options
331 aggregate = SlabAggregate(self)
332 origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
333 options.update({'origin_hrn':origin_hrn})
334 rspec = aggregate.get_rspec(slice_xrn=slice_urn, \
335 version=rspec_version, options=options)
338 #if self.cache and not slice_hrn:
339 #logger.debug("Slab.ListResources: stores advertisement in cache")
340 #self.cache.add(version_string, rspec)
345 def list_slices (self, creds, options):
346 # look in cache first
348 #slices = self.cache.get('slices')
350 #logger.debug("PlDriver.list_slices returns from cache")
355 slices = self.GetSlices()
356 logger.debug("SLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n" %(slices))
357 slice_hrns = [slab_slice['slice_hrn'] for slab_slice in slices]
358 #slice_hrns = [slicename_to_hrn(self.hrn, slab_slice['slice_hrn']) \
359 #for slab_slice in slices]
360 slice_urns = [hrn_to_urn(slice_hrn, 'slice') \
361 for slice_hrn in slice_hrns]
365 #logger.debug ("SlabDriver.list_slices stores value in cache")
366 #self.cache.add('slices', slice_urns)
371 def register (self, sfa_record, hrn, pub_key):
373 Adding new user, slice, node or site should not be handled
377 Adding users = LDAP Senslab
378 Adding slice = Import from LDAP users
383 #No site or node record update allowed
384 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
385 pointer = old_sfa_record['pointer']
386 old_sfa_record_type = old_sfa_record['type']
388 # new_key implemented for users only
389 if new_key and old_sfa_record_type not in [ 'user' ]:
390 raise UnknownSfaType(old_sfa_record_type)
392 #if (type == "authority"):
393 #self.shell.UpdateSite(pointer, new_sfa_record)
395 if old_sfa_record_type == "slice":
396 slab_record = self.sfa_fields_to_slab_fields(old_sfa_record_type, \
398 if 'name' in slab_record:
399 slab_record.pop('name')
400 #Prototype should be UpdateSlice(self,
401 #auth, slice_id_or_name, slice_fields)
402 #Senslab cannot update slice since slice = job
403 #so we must delete and create another job
404 self.UpdateSlice(pointer, slab_record)
406 elif old_sfa_record_type == "user":
408 all_fields = new_sfa_record
409 for key in all_fields.keys():
410 if key in ['first_name', 'last_name', 'title', 'email',
411 'password', 'phone', 'url', 'bio', 'accepted_aup',
413 update_fields[key] = all_fields[key]
414 self.UpdatePerson(pointer, update_fields)
417 # must check this key against the previous one if it exists
418 persons = self.GetPersons([pointer], ['key_ids'])
420 keys = person['key_ids']
421 keys = self.GetKeys(person['key_ids'])
423 # Delete all stale keys
426 if new_key != key['key']:
427 self.DeleteKey(key['key_id'])
431 self.AddPersonKey(pointer, {'key_type': 'ssh', \
438 def remove (self, sfa_record):
439 sfa_record_type = sfa_record['type']
440 hrn = sfa_record['hrn']
441 if sfa_record_type == 'user':
443 #get user from senslab ldap
444 person = self.GetPersons(sfa_record)
445 #No registering at a given site in Senslab.
446 #Once registered to the LDAP, all senslab sites are
449 #Mark account as disabled in ldap
450 self.DeletePerson(sfa_record)
451 elif sfa_record_type == 'slice':
452 if self.GetSlices(slice_filter = hrn, \
453 slice_filter_type = 'slice_hrn'):
454 self.DeleteSlice(sfa_record)
456 #elif type == 'authority':
457 #if self.GetSites(pointer):
458 #self.DeleteSite(pointer)
464 #TODO clean GetPeers. 05/07/12SA
465 def GetPeers (self, auth = None, peer_filter=None, return_fields_list=None):
467 existing_records = {}
468 existing_hrns_by_types = {}
469 logger.debug("SLABDRIVER \tGetPeers auth = %s, peer_filter %s, \
470 return_field %s " %(auth , peer_filter, return_fields_list))
471 all_records = dbsession.query(RegRecord).filter(RegRecord.type.like('%authority%')).all()
472 for record in all_records:
473 existing_records[(record.hrn, record.type)] = record
474 if record.type not in existing_hrns_by_types:
475 existing_hrns_by_types[record.type] = [record.hrn]
476 logger.debug("SLABDRIVER \tGetPeer\t NOT IN \
477 existing_hrns_by_types %s " %( existing_hrns_by_types))
480 logger.debug("SLABDRIVER \tGetPeer\t \INNN type %s hrn %s " \
481 %(record.type,record.hrn))
482 existing_hrns_by_types[record.type].append(record.hrn)
485 logger.debug("SLABDRIVER \tGetPeer\texisting_hrns_by_types %s "\
486 %( existing_hrns_by_types))
491 records_list.append(existing_records[(peer_filter,'authority')])
493 for hrn in existing_hrns_by_types['authority']:
494 records_list.append(existing_records[(hrn,'authority')])
496 logger.debug("SLABDRIVER \tGetPeer \trecords_list %s " \
502 return_records = records_list
503 if not peer_filter and not return_fields_list:
507 logger.debug("SLABDRIVER \tGetPeer return_records %s " \
509 return return_records
512 #TODO : Handling OR request in make_ldap_filters_from_records
513 #instead of the for loop
514 #over the records' list
515 def GetPersons(self, person_filter=None):
517 person_filter should be a list of dictionnaries when not set to None.
518 Returns a list of users whose accounts are enabled found in ldap.
521 logger.debug("SLABDRIVER \tGetPersons person_filter %s" \
524 if person_filter and isinstance(person_filter, list):
525 #If we are looking for a list of users (list of dict records)
526 #Usually the list contains only one user record
527 for searched_attributes in person_filter:
529 #Get only enabled user accounts in senslab LDAP :
530 #add a filter for make_ldap_filters_from_record
531 person = self.ldap.LdapFindUser(searched_attributes, \
532 is_user_enabled=True)
533 person_list.append(person)
536 #Get only enabled user accounts in senslab LDAP :
537 #add a filter for make_ldap_filters_from_record
538 person_list = self.ldap.LdapFindUser(is_user_enabled=True)
542 def GetTimezone(self):
543 server_timestamp, server_tz = self.oar.parser.\
544 SendRequest("GET_timezone")
545 return server_timestamp, server_tz
548 def DeleteJobs(self, job_id, slice_hrn):
549 if not job_id or job_id is -1:
551 username = slice_hrn.split(".")[-1].rstrip("_slice")
553 reqdict['method'] = "delete"
554 reqdict['strval'] = str(job_id)
557 answer = self.oar.POSTRequestToOARRestAPI('DELETE_jobs_id', \
559 logger.debug("SLABDRIVER \tDeleteJobs jobid %s \r\n answer %s \
560 username %s" %(job_id,answer, username))
565 ##TODO : Unused GetJobsId ? SA 05/07/12
566 #def GetJobsId(self, job_id, username = None ):
568 #Details about a specific job.
569 #Includes details about submission time, jot type, state, events,
570 #owner, assigned ressources, walltime etc...
574 #node_list_k = 'assigned_network_address'
575 ##Get job info from OAR
576 #job_info = self.oar.parser.SendRequest(req, job_id, username)
578 #logger.debug("SLABDRIVER \t GetJobsId %s " %(job_info))
580 #if job_info['state'] == 'Terminated':
581 #logger.debug("SLABDRIVER \t GetJobsId job %s TERMINATED"\
584 #if job_info['state'] == 'Error':
585 #logger.debug("SLABDRIVER \t GetJobsId ERROR message %s "\
590 #logger.error("SLABDRIVER \tGetJobsId KeyError")
593 #parsed_job_info = self.get_info_on_reserved_nodes(job_info, \
595 ##Replaces the previous entry
596 ##"assigned_network_address" / "reserved_resources"
598 #job_info.update({'node_ids':parsed_job_info[node_list_k]})
599 #del job_info[node_list_k]
600 #logger.debug(" \r\nSLABDRIVER \t GetJobsId job_info %s " %(job_info))
604 def GetJobsResources(self, job_id, username = None):
605 #job_resources=['reserved_resources', 'assigned_resources',\
606 #'job_id', 'job_uri', 'assigned_nodes',\
608 #assigned_res = ['resource_id', 'resource_uri']
609 #assigned_n = ['node', 'node_uri']
611 req = "GET_jobs_id_resources"
614 #Get job resources list from OAR
615 node_id_list = self.oar.parser.SendRequest(req, job_id, username)
616 logger.debug("SLABDRIVER \t GetJobsResources %s " %(node_id_list))
619 self.__get_hostnames_from_oar_node_ids(node_id_list)
622 #Replaces the previous entry "assigned_network_address" /
623 #"reserved_resources"
625 job_info = {'node_ids': hostname_list}
630 def get_info_on_reserved_nodes(self, job_info, node_list_name):
631 #Get the list of the testbed nodes records and make a
632 #dictionnary keyed on the hostname out of it
633 node_list_dict = self.GetNodes()
634 #node_hostname_list = []
635 node_hostname_list = [node['hostname'] for node in node_list_dict]
636 #for node in node_list_dict:
637 #node_hostname_list.append(node['hostname'])
638 node_dict = dict(zip(node_hostname_list, node_list_dict))
640 reserved_node_hostname_list = []
641 for index in range(len(job_info[node_list_name])):
642 #job_info[node_list_name][k] =
643 reserved_node_hostname_list[index] = \
644 node_dict[job_info[node_list_name][index]]['hostname']
646 logger.debug("SLABDRIVER \t get_info_on_reserved_nodes \
647 reserved_node_hostname_list %s" \
648 %(reserved_node_hostname_list))
650 logger.error("SLABDRIVER \t get_info_on_reserved_nodes KEYERROR " )
652 return reserved_node_hostname_list
654 def GetNodesCurrentlyInUse(self):
655 """Returns a list of all the nodes already involved in an oar job"""
656 return self.oar.parser.SendRequest("GET_running_jobs")
658 def __get_hostnames_from_oar_node_ids(self, resource_id_list ):
659 full_nodes_dict_list = self.GetNodes()
660 #Put the full node list into a dictionary keyed by oar node id
661 oar_id_node_dict = {}
662 for node in full_nodes_dict_list:
663 oar_id_node_dict[node['oar_id']] = node
665 logger.debug("SLABDRIVER \t __get_hostnames_from_oar_node_ids\
666 oar_id_node_dict %s" %(oar_id_node_dict))
668 hostname_dict_list = []
669 for resource_id in resource_id_list:
670 #Because jobs requested "asap" do not have defined resources
671 if resource_id is not "Undefined":
672 hostname_dict_list.append({'hostname' : \
673 oar_id_node_dict[resource_id]['hostname'],
674 'site_id' : oar_id_node_dict[resource_id]['site']})
676 #hostname_list.append(oar_id_node_dict[resource_id]['hostname'])
677 return hostname_dict_list
679 def GetReservedNodes(self,username = None):
680 #Get the nodes in use and the reserved nodes
681 reservation_dict_list = \
682 self.oar.parser.SendRequest("GET_reserved_nodes", username = username)
685 for resa in reservation_dict_list:
686 logger.debug ("GetReservedNodes resa %s"%(resa))
687 #dict list of hostnames and their site
688 resa['reserved_nodes'] = \
689 self.__get_hostnames_from_oar_node_ids(resa['resource_ids'])
691 #del resa['resource_ids']
692 return reservation_dict_list
694 def GetNodes(self, node_filter_dict = None, return_fields_list = None):
696 node_filter_dict : dictionnary of lists
699 node_dict_by_id = self.oar.parser.SendRequest("GET_resources_full")
700 node_dict_list = node_dict_by_id.values()
702 #No filtering needed return the list directly
703 if not (node_filter_dict or return_fields_list):
704 return node_dict_list
706 return_node_list = []
708 for filter_key in node_filter_dict:
710 #Filter the node_dict_list by each value contained in the
711 #list node_filter_dict[filter_key]
712 for value in node_filter_dict[filter_key]:
713 for node in node_dict_list:
714 if node[filter_key] == value:
715 if return_fields_list :
717 for k in return_fields_list:
719 return_node_list.append(tmp)
721 return_node_list.append(node)
723 logger.log_exc("GetNodes KeyError")
727 return return_node_list
730 def GetSites(self, site_filter_name_list = None, return_fields_list = None):
731 site_dict = self.oar.parser.SendRequest("GET_sites")
732 #site_dict : dict where the key is the sit ename
733 return_site_list = []
734 if not ( site_filter_name_list or return_fields_list):
735 return_site_list = site_dict.values()
736 return return_site_list
738 for site_filter_name in site_filter_name_list:
739 if site_filter_name in site_dict:
740 if return_fields_list:
741 for field in return_fields_list:
744 tmp[field] = site_dict[site_filter_name][field]
746 logger.error("GetSites KeyError %s "%(field))
748 return_site_list.append(tmp)
750 return_site_list.append( site_dict[site_filter_name])
753 return return_site_list
757 def GetSlices(self, slice_filter = None, slice_filter_type = None):
758 #def GetSlices(self, slice_filter = None, slice_filter_type = None, \
759 #return_fields_list = None):
760 """ Get the slice records from the slab db.
761 Returns a slice ditc if slice_filter and slice_filter_type
763 Returns a list of slice dictionnaries if there are no filters
768 return_slice_list = []
771 authorized_filter_types_list = ['slice_hrn', 'record_id_user']
772 slicerec_dictlist = []
775 if slice_filter_type in authorized_filter_types_list:
778 def __get_slice_records(slice_filter = None, slice_filter_type = None):
781 #Get list of slices based on the slice hrn
782 if slice_filter_type == 'slice_hrn':
784 login = slice_filter.split(".")[1].split("_")[0]
786 #DO NOT USE RegSlice - reg_researchers to get the hrn of the user
787 #otherwise will mess up the RegRecord in Resolve, don't know
790 #Only one entry for one user = one slice in slice_senslab table
791 slicerec = slab_dbsession.query(SliceSenslab).filter_by(slice_hrn = slice_filter).first()
793 #Get slice based on user id
794 if slice_filter_type == 'record_id_user':
795 slicerec = slab_dbsession.query(SliceSenslab).filter_by(record_id_user = slice_filter).first()
800 fixed_slicerec_dict = slicerec.dump_sqlalchemyobj_to_dict()
803 login = fixed_slicerec_dict['slice_hrn'].split(".")[1].split("_")[0]
804 return login, fixed_slicerec_dict
809 login, fixed_slicerec_dict = __get_slice_records(slice_filter, slice_filter_type)
810 logger.debug(" SLABDRIVER \tGetSlices login %s \
812 %(login, fixed_slicerec_dict))
816 #One slice can have multiple jobs
818 leases_list = self.GetReservedNodes(username = login)
819 #If no job is running or no job scheduled
820 if leases_list == [] :
821 return [fixed_slicerec_dict]
823 #Several jobs for one slice
824 for lease in leases_list :
828 #Check with OAR the status of the job if a job id is in
833 slicerec_dict['oar_job_id'] = lease['lease_id']
834 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
835 slicerec_dict.update(fixed_slicerec_dict)
836 slicerec_dict.update({'hrn':\
837 str(fixed_slicerec_dict['slice_hrn'])})
840 slicerec_dictlist.append(slicerec_dict)
841 logger.debug("SLABDRIVER.PY \tGetSlices slicerec_dict %s slicerec_dictlist %s" %(slicerec_dict, slicerec_dictlist))
843 logger.debug("SLABDRIVER.PY \tGetSlices RETURN slicerec_dictlist %s"\
844 %(slicerec_dictlist))
846 return slicerec_dictlist
851 slice_list = slab_dbsession.query(SliceSenslab).all()
852 leases_list = self.GetReservedNodes()
855 slicerec_dictlist = []
856 return_slice_list = []
857 for record in slice_list:
858 return_slice_list.append(record.dump_sqlalchemyobj_to_dict())
860 for fixed_slicerec_dict in return_slice_list:
862 owner = fixed_slicerec_dict['slice_hrn'].split(".")[1].split("_")[0]
863 for lease in leases_list:
864 if owner == lease['user']:
865 slicerec_dict['oar_job_id'] = lease['lease_id']
866 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
867 slicerec_dict.update(fixed_slicerec_dict)
868 slicerec_dict.update({'hrn':\
869 str(fixed_slicerec_dict['slice_hrn'])})
870 slicerec_dictlist.append(slicerec_dict)
872 logger.debug("SLABDRIVER.PY \tGetSlices RETURN slices %s \
873 slice_filter %s " %(return_slice_list, slice_filter))
875 #if return_fields_list:
876 #return_slice_list = parse_filter(sliceslist, \
877 #slice_filter,'slice', return_fields_list)
879 return slicerec_dictlist
882 def testbed_name (self): return self.hrn
884 # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
885 def aggregate_version (self):
886 version_manager = VersionManager()
887 ad_rspec_versions = []
888 request_rspec_versions = []
889 for rspec_version in version_manager.versions:
890 if rspec_version.content_type in ['*', 'ad']:
891 ad_rspec_versions.append(rspec_version.to_dict())
892 if rspec_version.content_type in ['*', 'request']:
893 request_rspec_versions.append(rspec_version.to_dict())
895 'testbed':self.testbed_name(),
896 'geni_request_rspec_versions': request_rspec_versions,
897 'geni_ad_rspec_versions': ad_rspec_versions,
906 # Convert SFA fields to PLC fields for use when registering up updating
907 # registry record in the PLC database
909 # @param type type of record (user, slice, ...)
910 # @param hrn human readable name
911 # @param sfa_fields dictionary of SFA fields
912 # @param slab_fields dictionary of PLC fields (output)
914 def sfa_fields_to_slab_fields(self, sfa_type, hrn, record):
918 #for field in record:
919 # slab_record[field] = record[field]
921 if sfa_type == "slice":
922 #instantion used in get_slivers ?
923 if not "instantiation" in slab_record:
924 slab_record["instantiation"] = "senslab-instantiated"
925 #slab_record["hrn"] = hrn_to_pl_slicename(hrn)
926 #Unused hrn_to_pl_slicename because Slab's hrn already in the appropriate form SA 23/07/12
927 slab_record["hrn"] = hrn
928 logger.debug("SLABDRIVER.PY sfa_fields_to_slab_fields \
929 slab_record %s " %(slab_record['hrn']))
931 slab_record["url"] = record["url"]
932 if "description" in record:
933 slab_record["description"] = record["description"]
934 if "expires" in record:
935 slab_record["expires"] = int(record["expires"])
937 #nodes added by OAR only and then imported to SFA
938 #elif type == "node":
939 #if not "hostname" in slab_record:
940 #if not "hostname" in record:
941 #raise MissingSfaInfo("hostname")
942 #slab_record["hostname"] = record["hostname"]
943 #if not "model" in slab_record:
944 #slab_record["model"] = "geni"
947 #elif type == "authority":
948 #slab_record["login_base"] = hrn_to_slab_login_base(hrn)
950 #if not "name" in slab_record:
951 #slab_record["name"] = hrn
953 #if not "abbreviated_name" in slab_record:
954 #slab_record["abbreviated_name"] = hrn
956 #if not "enabled" in slab_record:
957 #slab_record["enabled"] = True
959 #if not "is_public" in slab_record:
960 #slab_record["is_public"] = True
967 def __transforms_timestamp_into_date(self, xp_utc_timestamp = None):
968 """ Transforms unix timestamp into valid OAR date format """
970 #Used in case of a scheduled experiment (not immediate)
971 #To run an XP immediately, don't specify date and time in RSpec
972 #They will be set to None.
974 #transform the xp_utc_timestamp into server readable time
975 xp_server_readable_date = datetime.fromtimestamp(int(\
976 xp_utc_timestamp)).strftime(self.time_format)
978 return xp_server_readable_date
986 def LaunchExperimentOnOAR(self, added_nodes, slice_name, \
987 lease_start_time, lease_duration, slice_user=None):
989 lease_dict['lease_start_time'] = lease_start_time
990 lease_dict['lease_duration'] = lease_duration
991 lease_dict['added_nodes'] = added_nodes
992 lease_dict['slice_name'] = slice_name
993 lease_dict['slice_user'] = slice_user
994 lease_dict['grain'] = self.GetLeaseGranularity()
995 lease_dict['time_format'] = self.time_format
997 def __create_job_structure_request_for_OAR(lease_dict):
998 """ Creates the structure needed for a correct POST on OAR.
999 Makes the timestamp transformation into the appropriate format.
1000 Sends the POST request to create the job with the resources in
1009 reqdict['workdir'] = '/tmp'
1010 reqdict['resource'] = "{network_address in ("
1012 for node in lease_dict['added_nodes']:
1013 logger.debug("\r\n \r\n OARrestapi \t __create_job_structure_request_for_OAR \
1016 # Get the ID of the node
1018 reqdict['resource'] += "'" + nodeid + "', "
1019 nodeid_list.append(nodeid)
1021 custom_length = len(reqdict['resource'])- 2
1022 reqdict['resource'] = reqdict['resource'][0:custom_length] + \
1023 ")}/nodes=" + str(len(nodeid_list))
1025 def __process_walltime(duration):
1026 """ Calculates the walltime in seconds from the duration in H:M:S
1027 specified in the RSpec.
1031 # Fixing the walltime by adding a few delays.
1032 # First put the walltime in seconds oarAdditionalDelay = 20;
1033 # additional delay for /bin/sleep command to
1034 # take in account prologue and epilogue scripts execution
1035 # int walltimeAdditionalDelay = 120; additional delay
1036 desired_walltime = duration
1037 total_walltime = desired_walltime + 140#+2 min 20
1038 sleep_walltime = desired_walltime + 20 #+20 sec
1040 #Put the walltime back in str form
1041 #First get the hours
1042 walltime.append(str(total_walltime / 3600))
1043 total_walltime = total_walltime - 3600 * int(walltime[0])
1044 #Get the remaining minutes
1045 walltime.append(str(total_walltime / 60))
1046 total_walltime = total_walltime - 60 * int(walltime[1])
1048 walltime.append(str(total_walltime))
1051 logger.log_exc(" __process_walltime duration null")
1053 return walltime, sleep_walltime
1056 walltime, sleep_walltime = \
1057 __process_walltime(int(lease_dict['lease_duration'])*lease_dict['grain'])
1060 reqdict['resource'] += ",walltime=" + str(walltime[0]) + \
1061 ":" + str(walltime[1]) + ":" + str(walltime[2])
1062 reqdict['script_path'] = "/bin/sleep " + str(sleep_walltime)
1064 #In case of a scheduled experiment (not immediate)
1065 #To run an XP immediately, don't specify date and time in RSpec
1066 #They will be set to None.
1067 if lease_dict['lease_start_time'] is not '0':
1068 #Readable time accepted by OAR
1069 start_time = datetime.fromtimestamp(int(lease_dict['lease_start_time'])).\
1070 strftime(lease_dict['time_format'])
1071 reqdict['reservation'] = start_time
1072 #If there is not start time, Immediate XP. No need to add special
1076 reqdict['type'] = "deploy"
1077 reqdict['directory'] = ""
1078 reqdict['name'] = "SFA_" + lease_dict['slice_user']
1083 #Create the request for OAR
1084 reqdict = __create_job_structure_request_for_OAR(lease_dict)
1085 # first step : start the OAR job and update the job
1086 logger.debug("SLABDRIVER.PY \tLaunchExperimentOnOAR reqdict %s\
1089 answer = self.oar.POSTRequestToOARRestAPI('POST_job', \
1090 reqdict, slice_user)
1091 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s " %(answer))
1093 jobid = answer['id']
1095 logger.log_exc("SLABDRIVER \tLaunchExperimentOnOAR \
1096 Impossible to create job %s " %(answer))
1100 def __configure_experiment(jobid, added_nodes):
1101 # second step : configure the experiment
1102 # we need to store the nodes in a yaml (well...) file like this :
1103 # [1,56,23,14,45,75] with name /tmp/sfa<jobid>.json
1104 job_file = open('/tmp/sfa/'+ str(jobid) + '.json', 'w')
1106 job_file.write(str(added_nodes[0].strip('node')))
1107 for node in added_nodes[1:len(added_nodes)] :
1108 job_file.write(', '+ node.strip('node'))
1113 def __launch_senslab_experiment(jobid):
1114 # third step : call the senslab-experiment wrapper
1115 #command= "java -jar target/sfa-1.0-jar-with-dependencies.jar
1116 # "+str(jobid)+" "+slice_user
1117 javacmdline = "/usr/bin/java"
1119 "/opt/senslabexperimentwrapper/sfa-1.0-jar-with-dependencies.jar"
1120 #ret=subprocess.check_output(["/usr/bin/java", "-jar", ", \
1121 #str(jobid), slice_user])
1122 output = subprocess.Popen([javacmdline, "-jar", jarname, str(jobid), \
1123 slice_user],stdout=subprocess.PIPE).communicate()[0]
1125 logger.debug("SLABDRIVER \t __configure_experiment wrapper returns%s " \
1132 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s \
1133 added_nodes %s slice_user %s" %(jobid, added_nodes, slice_user))
1136 __configure_experiment(jobid, added_nodes)
1137 __launch_senslab_experiment(jobid)
1141 def AddLeases(self, hostname_list, slice_record, lease_start_time, lease_duration):
1142 logger.debug("SLABDRIVER \r\n \r\n \t AddLeases hostname_list %s \
1143 slice_record %s lease_start_time %s lease_duration %s "\
1144 %( hostname_list, slice_record , lease_start_time, \
1147 tmp = slice_record['PI'][0].split(".")
1148 username = tmp[(len(tmp)-1)]
1149 self.LaunchExperimentOnOAR(hostname_list, slice_record['name'], lease_start_time, lease_duration, username)
1150 start_time = datetime.fromtimestamp(int(lease_start_time)).strftime(self.time_format)
1151 logger.debug("SLABDRIVER \t AddLeases hostname_list start_time %s " %(start_time))
1156 #Delete the jobs from job_senslab table
1157 def DeleteSliceFromNodes(self, slice_record):
1159 self.DeleteJobs(slice_record['oar_job_id'], slice_record['hrn'])
1163 def GetLeaseGranularity(self):
1164 """ Returns the granularity of Senslab testbed.
1165 Defined in seconds. """
1170 def GetLeases(self, lease_filter_dict=None):
1171 unfiltered_reservation_list = self.GetReservedNodes()
1173 ##Synchronize slice_table of sfa senslab db
1174 #self.synchronize_oar_and_slice_table(unfiltered_reservation_list)
1176 reservation_list = []
1177 #Find the slice associated with this user senslab ldap uid
1178 logger.debug(" SLABDRIVER.PY \tGetLeases ")
1179 #Create user dict first to avoir looking several times for
1180 #the same user in LDAP SA 27/07/12
1182 for resa in unfiltered_reservation_list:
1183 logger.debug("SLABDRIVER \tGetLeases USER %s"\
1185 if resa['user'] not in resa_user_dict:
1186 logger.debug("SLABDRIVER \tGetLeases userNOTIN ")
1187 ldap_info = self.ldap.LdapSearch('(uid='+resa['user']+')')
1188 ldap_info = ldap_info[0][1]
1189 user = dbsession.query(RegUser).filter_by(email = \
1190 ldap_info['mail'][0]).first()
1191 #Separated in case user not in database : record_id not defined SA 17/07//12
1192 query_slice_info = slab_dbsession.query(SliceSenslab).filter_by(record_id_user = user.record_id)
1193 if query_slice_info:
1194 slice_info = query_slice_info.first()
1198 resa_user_dict[resa['user']] = {}
1199 resa_user_dict[resa['user']]['ldap_info'] = user
1200 resa_user_dict[resa['user']]['slice_info'] = slice_info
1202 logger.debug("SLABDRIVER \tGetLeases resa_user_dict %s"\
1204 for resa in unfiltered_reservation_list:
1208 resa['slice_hrn'] = resa_user_dict[resa['user']]['slice_info'].slice_hrn
1209 resa['slice_id'] = hrn_to_urn(resa['slice_hrn'], 'slice')
1211 #resa['slice_id'] = hrn_to_urn(slice_info.slice_hrn, 'slice')
1212 resa['component_id_list'] = []
1213 #Transform the hostnames into urns (component ids)
1214 for node in resa['reserved_nodes']:
1215 #resa['component_id_list'].append(hostname_to_urn(self.hrn, \
1216 #self.root_auth, node['hostname']))
1217 slab_xrn = slab_xrn_object(self.root_auth, node['hostname'])
1218 resa['component_id_list'].append(slab_xrn.urn)
1220 #Filter the reservation list if necessary
1221 #Returns all the leases associated with a given slice
1222 if lease_filter_dict:
1223 logger.debug("SLABDRIVER \tGetLeases lease_filter_dict %s"\
1224 %(lease_filter_dict))
1225 for resa in unfiltered_reservation_list:
1226 if lease_filter_dict['name'] == resa['slice_hrn']:
1227 reservation_list.append(resa)
1229 reservation_list = unfiltered_reservation_list
1231 logger.debug(" SLABDRIVER.PY \tGetLeases reservation_list %s"\
1232 %(reservation_list))
1233 return reservation_list
1235 def augment_records_with_testbed_info (self, sfa_records):
1236 return self.fill_record_info (sfa_records)
1238 def fill_record_info(self, record_list):
1240 Given a SFA record, fill in the senslab specific and SFA specific
1241 fields in the record.
1244 logger.debug("SLABDRIVER \tfill_record_info records %s " %(record_list))
1245 if not isinstance(record_list, list):
1246 record_list = [record_list]
1249 for record in record_list:
1250 #If the record is a SFA slice record, then add information
1251 #about the user of this slice. This kind of
1252 #information is in the Senslab's DB.
1253 if str(record['type']) == 'slice':
1254 #Get slab slice record.
1255 recslice_list = self.GetSlices(slice_filter = \
1256 str(record['hrn']),\
1257 slice_filter_type = 'slice_hrn')
1259 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1260 recslice_list[0]['record_id_user']).first()
1261 logger.debug("SLABDRIVER \tfill_record_info TYPE SLICE RECUSER %s " %(recuser))
1262 record.update({'PI':[recuser.hrn],
1263 'researcher': [recuser.hrn],
1264 'name':record['hrn'],
1265 'oar_job_id':[rec['oar_job_id'] for rec in recslice_list],
1267 'person_ids':[recslice_list[0]['record_id_user']],
1268 'geni_urn':'', #For client_helper.py compatibility
1269 'keys':'', #For client_helper.py compatibility
1270 'key_ids':''}) #For client_helper.py compatibility
1272 #for rec in recslice_list:
1273 #record['oar_job_id'].append(rec['oar_job_id'])
1274 logger.debug( "SLABDRIVER.PY \t fill_record_info SLICE \
1275 recslice_list %s \r\n \t RECORD %s \r\n \r\n" %(recslice_list,record))
1276 if str(record['type']) == 'user':
1277 #The record is a SFA user record.
1278 #Get the information about his slice from Senslab's DB
1279 #and add it to the user record.
1280 recslice_list = self.GetSlices(\
1281 slice_filter = record['record_id'],\
1282 slice_filter_type = 'record_id_user')
1284 logger.debug( "SLABDRIVER.PY \t fill_record_info TYPE USER \
1285 recslice_list %s \r\n \t RECORD %s \r\n" %(recslice_list , record))
1286 #Append slice record in records list,
1287 #therefore fetches user and slice info again(one more loop)
1288 #Will update PIs and researcher for the slice
1289 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1290 recslice_list[0]['record_id_user']).first()
1291 logger.debug( "SLABDRIVER.PY \t fill_record_info USER \
1292 recuser %s \r\n \r\n" %(recuser))
1294 recslice = recslice_list[0]
1295 recslice.update({'PI':[recuser.hrn],
1296 'researcher': [recuser.hrn],
1297 'name':record['hrn'],
1299 'oar_job_id': [rec['oar_job_id'] for rec in recslice_list],
1300 'person_ids':[recslice_list[0]['record_id_user']]})
1301 recslice.update({'type':'slice', \
1302 'hrn':recslice_list[0]['slice_hrn']})
1303 #for rec in recslice_list:
1304 #recslice['oar_job_id'].append(rec['oar_job_id'])
1306 #GetPersons takes [] as filters
1307 #user_slab = self.GetPersons([{'hrn':recuser.hrn}])
1308 user_slab = self.GetPersons([record])
1311 record.update(user_slab[0])
1312 #For client_helper.py compatibility
1313 record.update( { 'geni_urn':'',
1316 record_list.append(recslice)
1318 logger.debug("SLABDRIVER.PY \tfill_record_info ADDING SLICE\
1319 INFO TO USER records %s" %(record_list))
1320 logger.debug("SLABDRIVER.PY \tfill_record_info END \
1321 #record %s \r\n \r\n " %(record))
1323 except TypeError, error:
1324 logger.log_exc("SLABDRIVER \t fill_record_info EXCEPTION %s"\
1326 #logger.debug("SLABDRIVER.PY \t fill_record_info ENDENDEND ")
1330 #self.fill_record_slab_info(records)
1336 #TODO Update membership? update_membership_list SA 05/07/12
1337 #def update_membership_list(self, oldRecord, record, listName, addFunc, \
1339 ## get a list of the HRNs tht are members of the old and new records
1341 #oldList = oldRecord.get(listName, [])
1344 #newList = record.get(listName, [])
1346 ## if the lists are the same, then we don't have to update anything
1347 #if (oldList == newList):
1350 ## build a list of the new person ids, by looking up each person to get
1354 #records = table.find({'type': 'user', 'hrn': newList})
1355 #for rec in records:
1356 #newIdList.append(rec['pointer'])
1358 ## build a list of the old person ids from the person_ids field
1360 #oldIdList = oldRecord.get("person_ids", [])
1361 #containerId = oldRecord.get_pointer()
1363 ## if oldRecord==None, then we are doing a Register, instead of an
1366 #containerId = record.get_pointer()
1368 ## add people who are in the new list, but not the oldList
1369 #for personId in newIdList:
1370 #if not (personId in oldIdList):
1371 #addFunc(self.plauth, personId, containerId)
1373 ## remove people who are in the old list, but not the new list
1374 #for personId in oldIdList:
1375 #if not (personId in newIdList):
1376 #delFunc(self.plauth, personId, containerId)
1378 #def update_membership(self, oldRecord, record):
1380 #if record.type == "slice":
1381 #self.update_membership_list(oldRecord, record, 'researcher',
1382 #self.users.AddPersonToSlice,
1383 #self.users.DeletePersonFromSlice)
1384 #elif record.type == "authority":
1389 # I don't think you plan on running a component manager at this point
1390 # let me clean up the mess of ComponentAPI that is deprecated anyways
1393 #TODO FUNCTIONS SECTION 04/07/2012 SA
1395 #TODO : Is UnBindObjectFromPeer still necessary ? Currently does nothing
1397 def UnBindObjectFromPeer(self, auth, object_type, object_id, shortname):
1398 """ This method is a hopefully temporary hack to let the sfa correctly
1399 detach the objects it creates from a remote peer object. This is
1400 needed so that the sfa federation link can work in parallel with
1401 RefreshPeer, as RefreshPeer depends on remote objects being correctly
1404 auth : struct, API authentication structure
1405 AuthMethod : string, Authentication method to use
1406 object_type : string, Object type, among 'site','person','slice',
1408 object_id : int, object_id
1409 shortname : string, peer shortname
1413 logger.warning("SLABDRIVER \tUnBindObjectFromPeer EMPTY-\
1417 #TODO Is BindObjectToPeer still necessary ? Currently does nothing
1419 def BindObjectToPeer(self, auth, object_type, object_id, shortname=None, \
1420 remote_object_id=None):
1421 """This method is a hopefully temporary hack to let the sfa correctly
1422 attach the objects it creates to a remote peer object. This is needed
1423 so that the sfa federation link can work in parallel with RefreshPeer,
1424 as RefreshPeer depends on remote objects being correctly marked.
1426 shortname : string, peer shortname
1427 remote_object_id : int, remote object_id, set to 0 if unknown
1431 logger.warning("SLABDRIVER \tBindObjectToPeer EMPTY - DO NOTHING \r\n ")
1434 #TODO UpdateSlice 04/07/2012 SA
1435 #Funciton should delete and create another job since oin senslab slice=job
1436 def UpdateSlice(self, auth, slice_id_or_name, slice_fields=None):
1437 """Updates the parameters of an existing slice with the values in
1439 Users may only update slices of which they are members.
1440 PIs may update any of the slices at their sites, or any slices of
1441 which they are members. Admins may update any slice.
1442 Only PIs and admins may update max_nodes. Slices cannot be renewed
1443 (by updating the expires parameter) more than 8 weeks into the future.
1444 Returns 1 if successful, faults otherwise.
1448 logger.warning("SLABDRIVER UpdateSlice EMPTY - DO NOTHING \r\n ")
1451 #TODO UpdatePerson 04/07/2012 SA
1452 def UpdatePerson(self, auth, person_id_or_email, person_fields=None):
1453 """Updates a person. Only the fields specified in person_fields
1454 are updated, all other fields are left untouched.
1455 Users and techs can only update themselves. PIs can only update
1456 themselves and other non-PIs at their sites.
1457 Returns 1 if successful, faults otherwise.
1461 logger.warning("SLABDRIVER UpdatePerson EMPTY - DO NOTHING \r\n ")
1464 #TODO GetKeys 04/07/2012 SA
1465 def GetKeys(self, auth, key_filter=None, return_fields=None):
1466 """Returns an array of structs containing details about keys.
1467 If key_filter is specified and is an array of key identifiers,
1468 or a struct of key attributes, only keys matching the filter
1469 will be returned. If return_fields is specified, only the
1470 specified details will be returned.
1472 Admin may query all keys. Non-admins may only query their own keys.
1476 logger.warning("SLABDRIVER GetKeys EMPTY - DO NOTHING \r\n ")
1479 #TODO DeleteKey 04/07/2012 SA
1480 def DeleteKey(self, auth, key_id):
1482 Non-admins may only delete their own keys.
1483 Returns 1 if successful, faults otherwise.
1487 logger.warning("SLABDRIVER DeleteKey EMPTY - DO NOTHING \r\n ")
1491 #TODO : Check rights to delete person
1492 def DeletePerson(self, auth, person_record):
1493 """ Disable an existing account in senslab LDAP.
1494 Users and techs can only delete themselves. PIs can only
1495 delete themselves and other non-PIs at their sites.
1496 ins can delete anyone.
1497 Returns 1 if successful, faults otherwise.
1501 #Disable user account in senslab LDAP
1502 ret = self.ldap.LdapMarkUserAsDeleted(person_record)
1503 logger.warning("SLABDRIVER DeletePerson %s " %(person_record))
1506 #TODO Check DeleteSlice, check rights 05/07/2012 SA
1507 def DeleteSlice(self, auth, slice_record):
1508 """ Deletes the specified slice.
1509 Senslab : Kill the job associated with the slice if there is one
1510 using DeleteSliceFromNodes.
1511 Updates the slice record in slab db to remove the slice nodes.
1513 Users may only delete slices of which they are members. PIs may
1514 delete any of the slices at their sites, or any slices of which
1515 they are members. Admins may delete any slice.
1516 Returns 1 if successful, faults otherwise.
1520 self.DeleteSliceFromNodes(slice_record)
1521 logger.warning("SLABDRIVER DeleteSlice %s "%(slice_record))
1524 #TODO AddPerson 04/07/2012 SA
1525 #def AddPerson(self, auth, person_fields=None):
1526 def AddPerson(self, record):#TODO fixing 28/08//2012 SA
1527 """Adds a new account. Any fields specified in records are used,
1528 otherwise defaults are used.
1529 Accounts are disabled by default. To enable an account,
1531 Returns the new person_id (> 0) if successful, faults otherwise.
1535 ret = self.ldap.LdapAddUser(record)
1536 logger.warning("SLABDRIVER AddPerson return code %s \r\n ", ret)
1539 #TODO AddPersonToSite 04/07/2012 SA
1540 def AddPersonToSite (self, auth, person_id_or_email, \
1541 site_id_or_login_base=None):
1542 """ Adds the specified person to the specified site. If the person is
1543 already a member of the site, no errors are returned. Does not change
1544 the person's primary site.
1545 Returns 1 if successful, faults otherwise.
1549 logger.warning("SLABDRIVER AddPersonToSite EMPTY - DO NOTHING \r\n ")
1552 #TODO AddRoleToPerson : Not sure if needed in senslab 04/07/2012 SA
1553 def AddRoleToPerson(self, auth, role_id_or_name, person_id_or_email):
1554 """Grants the specified role to the person.
1555 PIs can only grant the tech and user roles to users and techs at their
1556 sites. Admins can grant any role to any user.
1557 Returns 1 if successful, faults otherwise.
1561 logger.warning("SLABDRIVER AddRoleToPerson EMPTY - DO NOTHING \r\n ")
1564 #TODO AddPersonKey 04/07/2012 SA
1565 def AddPersonKey(self, auth, person_id_or_email, key_fields=None):
1566 """Adds a new key to the specified account.
1567 Non-admins can only modify their own keys.
1568 Returns the new key_id (> 0) if successful, faults otherwise.
1572 logger.warning("SLABDRIVER AddPersonKey EMPTY - DO NOTHING \r\n ")
1575 def DeleteLeases(self, leases_id_list, slice_hrn ):
1576 for job_id in leases_id_list:
1577 self.DeleteJobs(job_id, slice_hrn)
1579 logger.debug("SLABDRIVER DeleteLeases leases_id_list %s slice_hrn %s \
1580 \r\n " %(leases_id_list, slice_hrn))