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, RegSlice
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, get_authority
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
38 # this inheritance scheme is so that the driver object can receive
39 # GetNodes or GetSites sorts of calls directly
40 # and thus minimize the differences in the managers with the pl version
41 class SlabDriver(Driver):
42 """ Senslab Driver class inherited from Driver generic class.
44 Contains methods compliant with the SFA standard and the testbed
45 infrastructure (calls to LDAP and OAR).
47 def __init__(self, config):
48 Driver.__init__ (self, config)
50 self.hrn = config.SFA_INTERFACE_HRN
51 self.root_auth = config.SFA_REGISTRY_ROOT_AUTH
52 self.oar = OARrestapi()
54 self.time_format = "%Y-%m-%d %H:%M:%S"
55 self.db = SlabDB(config, debug = True)
59 def sliver_status(self, slice_urn, slice_hrn):
60 """Receive a status request for slice named urn/hrn
61 urn:publicid:IDN+senslab+nturro_slice hrn senslab.nturro_slice
62 shall return a structure as described in
63 http://groups.geni.net/geni/wiki/GAPI_AM_API_V2#SliverStatus
64 NT : not sure if we should implement this or not, but used by sface.
68 #First get the slice with the slice hrn
69 slice_list = self.GetSlices(slice_filter = slice_hrn, \
70 slice_filter_type = 'slice_hrn')
72 if len(slice_list) is 0:
73 raise SliverDoesNotExist("%s slice_hrn" % (slice_hrn))
75 #Slice has the same slice hrn for each slice in the slice/lease list
76 #So fetch the info on the user once
77 one_slice = slice_list[0]
78 recuser = dbsession.query(RegRecord).filter_by(record_id = \
79 one_slice['record_id_user']).first()
81 #Make a list of all the nodes hostnames in use for this slice
84 for node in sl['node_ids']:
85 slice_nodes_list.append(node['hostname'])
87 #Get all the corresponding nodes details
88 nodes_all = self.GetNodes({'hostname':slice_nodes_list},
89 ['node_id', 'hostname','site','boot_state'])
90 nodeall_byhostname = dict([(n['hostname'], n) for n in nodes_all])
97 top_level_status = 'empty'
100 ['geni_urn','pl_login','geni_status','geni_resources'], None)
101 result['pl_login'] = recuser.hrn
102 logger.debug("Slabdriver - sliver_status Sliver status \
103 urn %s hrn %s sl %s \r\n " \
104 %(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'] = \
136 nodeall_byhostname[node['hostname']]['boot_state']
137 #res['pl_last_contact'] = strftime(self.time_format, \
138 #gmtime(float(timestamp)))
139 sliver_id = Xrn(slice_urn, type='slice', \
140 id=nodeall_byhostname[node['hostname']]['node_id'], \
141 authority=self.hrn).urn
143 res['geni_urn'] = sliver_id
144 if nodeall_byhostname[node['hostname']]['boot_state'] == 'Alive':
146 res['geni_status'] = 'ready'
148 res['geni_status'] = 'failed'
149 top_level_status = 'failed'
151 res['geni_error'] = ''
153 resources.append(res)
155 result['geni_status'] = top_level_status
156 result['geni_resources'] = resources
157 logger.debug("SLABDRIVER \tsliver_statusresources %s res %s "\
161 def get_user(self, hrn):
162 return dbsession.query(RegRecord).filter_by(hrn = hrn).first()
165 def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, \
167 aggregate = SlabAggregate(self)
169 slices = SlabSlices(self)
170 peer = slices.get_peer(slice_hrn)
171 sfa_peer = slices.get_sfa_peer(slice_hrn)
174 if not isinstance(creds, list):
178 slice_record = users[0].get('slice_record', {})
179 logger.debug("SLABDRIVER.PY \t create_sliver \t\
180 slice_record %s \r\n \r\n users %s" \
181 %(slice_record, users))
182 slice_record['user'] = {'keys':users[0]['keys'], 'email':users[0]['email'], 'hrn':slice_record['reg-researchers'][0]}
184 rspec = RSpec(rspec_string)
185 logger.debug("SLABDRIVER.PY \t create_sliver \trspec.version \
186 %s slice_record %s users %s" \
187 %(rspec.version,slice_record, users))
190 # ensure site record exists?
191 # ensure slice record exists
192 #Removed options to verify_slice SA 14/08/12
193 sfa_slice = slices.verify_slice(slice_hrn, slice_record, peer, \
196 # ensure person records exists
197 #verify_persons returns added persons but since the return value
199 slices.verify_persons(slice_hrn, sfa_slice, users, peer, \
200 sfa_peer, options=options)
201 #requested_attributes returned by rspec.version.get_slice_attributes()
202 #unused, removed SA 13/08/12
203 rspec.version.get_slice_attributes()
205 logger.debug("SLABDRIVER.PY create_sliver slice %s " %(sfa_slice))
211 # add/remove slice from nodes
213 requested_slivers = [node.get('component_id') \
214 for node in rspec.version.get_nodes_with_slivers()\
215 if node.get('authority_id') is self.root_auth]
216 l = [ node for node in rspec.version.get_nodes_with_slivers() ]
217 logger.debug("SLADRIVER \tcreate_sliver requested_slivers \
218 requested_slivers %s listnodes %s" \
219 %(requested_slivers,l))
220 #verify_slice_nodes returns nodes, but unused here. Removed SA 13/08/12.
221 #slices.verify_slice_nodes(sfa_slice, requested_slivers, peer)
224 requested_lease_list = []
226 logger.debug("SLABDRIVER.PY \tcreate_sliver AVANTLEASE " )
227 rspec_requested_leases = rspec.version.get_leases()
228 for lease in rspec.version.get_leases():
229 single_requested_lease = {}
230 logger.debug("SLABDRIVER.PY \tcreate_sliver lease %s " %(lease))
231 if not lease.get('lease_id'):
232 if get_authority(lease['component_id']) == self.root_auth:
233 single_requested_lease['hostname'] = \
234 slab_xrn_to_hostname(\
235 lease.get('component_id').strip())
236 single_requested_lease['start_time'] = lease.get('start_time')
237 single_requested_lease['duration'] = lease.get('duration')
239 #if single_requested_lease.get('hostname'):
240 requested_lease_list.append(single_requested_lease)
242 logger.debug("SLABDRIVER.PY \tcreate_sliver APRESLEASE" )
243 #dCreate dict of leases by start_time, regrouping nodes reserved
245 #time, for the same amount of time = one job on OAR
246 requested_job_dict = {}
247 for lease in requested_lease_list:
249 #In case it is an asap experiment start_time is empty
250 if lease['start_time'] == '':
251 lease['start_time'] = '0'
253 if lease['start_time'] not in requested_job_dict:
254 if isinstance(lease['hostname'], str):
255 lease['hostname'] = [lease['hostname']]
257 requested_job_dict[lease['start_time']] = lease
260 job_lease = requested_job_dict[lease['start_time']]
261 if lease['duration'] == job_lease['duration'] :
262 job_lease['hostname'].append(lease['hostname'])
267 logger.debug("SLABDRIVER.PY \tcreate_sliver requested_job_dict %s "\
268 %(requested_job_dict))
269 #verify_slice_leases returns the leases , but the return value is unused
270 #here. Removed SA 13/08/12
271 slices.verify_slice_leases(sfa_slice, \
272 requested_job_dict, peer)
274 return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
277 def delete_sliver (self, slice_urn, slice_hrn, creds, options):
279 sfa_slice_list = self.GetSlices(slice_filter = slice_hrn, \
280 slice_filter_type = 'slice_hrn')
282 if not sfa_slice_list:
285 #Delete all in the slice
286 for sfa_slice in sfa_slice_list:
289 logger.debug("SLABDRIVER.PY delete_sliver slice %s" %(sfa_slice))
290 slices = SlabSlices(self)
291 # determine if this is a peer slice
293 peer = slices.get_peer(slice_hrn)
294 #TODO delete_sliver SA : UnBindObjectFromPeer should be
295 #used when there is another
296 #senslab testbed, which is not the case 14/08/12 .
298 logger.debug("SLABDRIVER.PY delete_sliver peer %s" %(peer))
301 self.UnBindObjectFromPeer('slice', \
302 sfa_slice['record_id_slice'], \
304 self.DeleteSliceFromNodes(sfa_slice)
307 self.BindObjectToPeer('slice', \
308 sfa_slice['record_id_slice'], \
309 peer, sfa_slice['peer_slice_id'])
313 def AddSlice(self, slice_record, user_record):
314 #Add slice to the sfa table
315 sfa_record = RegSlice (hrn=slice_record['slice_hrn'], gid=slice_record['gid'],
316 pointer=slice_record['slice_id'],
317 authority=slice_record['authority'])
318 logger.debug("SLABDRIVER.PY AddSlice sfa_record %s user_record %s" %(sfa_record, user_record))
319 #There is no way to separate-adding the slice to the tesbed
320 #nd then importing it from the testebd to SFA because of the senslab's architecture
321 sfa_record.just_created()
322 dbsession.add(sfa_record)
324 sfa_record.reg_researchers = [user_record]
326 #sl_rec = dbsession.query(RegSlice).filter(RegSlice.hrn.match(slice_hrn)).all()
329 slab_slice = SliceSenslab( slice_hrn = slice_record['slice_hrn'], \
330 record_id_slice = sfa_record.record_id , \
331 record_id_user = slice_record['record_id_user'], \
332 peer_authority = slice_record['peer_authority'])
333 logger.debug("SLABDRIVER.PY \tAddSlice slice_record %s slab_slice %s sfa_record %s" \
334 %(slice_record,slab_slice, sfa_record))
335 slab_dbsession.add(slab_slice)
336 slab_dbsession.commit()
339 # first 2 args are None in case of resource discovery
340 def list_resources (self, slice_urn, slice_hrn, creds, options):
341 #cached_requested = options.get('cached', True)
343 version_manager = VersionManager()
344 # get the rspec's return format from options
346 version_manager.get_version(options.get('geni_rspec_version'))
347 version_string = "rspec_%s" % (rspec_version)
349 #panos adding the info option to the caching key (can be improved)
350 if options.get('info'):
351 version_string = version_string + "_" + \
352 options.get('info', 'default')
354 # look in cache first
355 #if cached_requested and self.cache and not slice_hrn:
356 #rspec = self.cache.get(version_string)
358 #logger.debug("SlabDriver.ListResources: \
359 #returning cached advertisement")
362 #panos: passing user-defined options
363 aggregate = SlabAggregate(self)
364 origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
365 options.update({'origin_hrn':origin_hrn})
366 rspec = aggregate.get_rspec(slice_xrn=slice_urn, \
367 version=rspec_version, options=options)
370 #if self.cache and not slice_hrn:
371 #logger.debug("Slab.ListResources: stores advertisement in cache")
372 #self.cache.add(version_string, rspec)
377 def list_slices (self, creds, options):
378 # look in cache first
380 #slices = self.cache.get('slices')
382 #logger.debug("PlDriver.list_slices returns from cache")
387 slices = self.GetSlices()
388 logger.debug("SLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n" %(slices))
389 slice_hrns = [slab_slice['slice_hrn'] for slab_slice in slices]
390 #slice_hrns = [slicename_to_hrn(self.hrn, slab_slice['slice_hrn']) \
391 #for slab_slice in slices]
392 slice_urns = [hrn_to_urn(slice_hrn, 'slice') \
393 for slice_hrn in slice_hrns]
397 #logger.debug ("SlabDriver.list_slices stores value in cache")
398 #self.cache.add('slices', slice_urns)
403 def register (self, sfa_record, hrn, pub_key):
405 Adding new user, slice, node or site should not be handled
409 Adding users = LDAP Senslab
410 Adding slice = Import from LDAP users
415 #No site or node record update allowed
416 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
417 pointer = old_sfa_record['pointer']
418 old_sfa_record_type = old_sfa_record['type']
420 # new_key implemented for users only
421 if new_key and old_sfa_record_type not in [ 'user' ]:
422 raise UnknownSfaType(old_sfa_record_type)
424 #if (type == "authority"):
425 #self.shell.UpdateSite(pointer, new_sfa_record)
427 if old_sfa_record_type == "slice":
428 slab_record = self.sfa_fields_to_slab_fields(old_sfa_record_type, \
430 if 'name' in slab_record:
431 slab_record.pop('name')
432 #Prototype should be UpdateSlice(self,
433 #auth, slice_id_or_name, slice_fields)
434 #Senslab cannot update slice since slice = job
435 #so we must delete and create another job
436 self.UpdateSlice(pointer, slab_record)
438 elif old_sfa_record_type == "user":
440 all_fields = new_sfa_record
441 for key in all_fields.keys():
442 if key in ['first_name', 'last_name', 'title', 'email',
443 'password', 'phone', 'url', 'bio', 'accepted_aup',
445 update_fields[key] = all_fields[key]
446 self.UpdatePerson(pointer, update_fields)
449 # must check this key against the previous one if it exists
450 persons = self.GetPersons([pointer], ['key_ids'])
452 keys = person['key_ids']
453 keys = self.GetKeys(person['key_ids'])
455 # Delete all stale keys
458 if new_key != key['key']:
459 self.DeleteKey(key['key_id'])
463 self.AddPersonKey(pointer, {'key_type': 'ssh', \
470 def remove (self, sfa_record):
471 sfa_record_type = sfa_record['type']
472 hrn = sfa_record['hrn']
473 if sfa_record_type == 'user':
475 #get user from senslab ldap
476 person = self.GetPersons(sfa_record)
477 #No registering at a given site in Senslab.
478 #Once registered to the LDAP, all senslab sites are
481 #Mark account as disabled in ldap
482 self.DeletePerson(sfa_record)
483 elif sfa_record_type == 'slice':
484 if self.GetSlices(slice_filter = hrn, \
485 slice_filter_type = 'slice_hrn'):
486 self.DeleteSlice(sfa_record)
488 #elif type == 'authority':
489 #if self.GetSites(pointer):
490 #self.DeleteSite(pointer)
496 #TODO clean GetPeers. 05/07/12SA
497 def GetPeers (self, auth = None, peer_filter=None, return_fields_list=None):
499 existing_records = {}
500 existing_hrns_by_types = {}
501 logger.debug("SLABDRIVER \tGetPeers auth = %s, peer_filter %s, \
502 return_field %s " %(auth , peer_filter, return_fields_list))
503 all_records = dbsession.query(RegRecord).filter(RegRecord.type.like('%authority%')).all()
504 for record in all_records:
505 existing_records[(record.hrn, record.type)] = record
506 if record.type not in existing_hrns_by_types:
507 existing_hrns_by_types[record.type] = [record.hrn]
508 logger.debug("SLABDRIVER \tGetPeer\t NOT IN \
509 existing_hrns_by_types %s " %( existing_hrns_by_types))
512 logger.debug("SLABDRIVER \tGetPeer\t \INNN type %s hrn %s " \
513 %(record.type,record.hrn))
514 existing_hrns_by_types[record.type].append(record.hrn)
517 logger.debug("SLABDRIVER \tGetPeer\texisting_hrns_by_types %s "\
518 %( existing_hrns_by_types))
523 records_list.append(existing_records[(peer_filter,'authority')])
525 for hrn in existing_hrns_by_types['authority']:
526 records_list.append(existing_records[(hrn,'authority')])
528 logger.debug("SLABDRIVER \tGetPeer \trecords_list %s " \
534 return_records = records_list
535 if not peer_filter and not return_fields_list:
539 logger.debug("SLABDRIVER \tGetPeer return_records %s " \
541 return return_records
544 #TODO : Handling OR request in make_ldap_filters_from_records
545 #instead of the for loop
546 #over the records' list
547 def GetPersons(self, person_filter=None):
549 person_filter should be a list of dictionnaries when not set to None.
550 Returns a list of users whose accounts are enabled found in ldap.
553 logger.debug("SLABDRIVER \tGetPersons person_filter %s" \
556 if person_filter and isinstance(person_filter, list):
557 #If we are looking for a list of users (list of dict records)
558 #Usually the list contains only one user record
559 for searched_attributes in person_filter:
561 #Get only enabled user accounts in senslab LDAP :
562 #add a filter for make_ldap_filters_from_record
563 person = self.ldap.LdapFindUser(searched_attributes, \
564 is_user_enabled=True)
565 person_list.append(person)
568 #Get only enabled user accounts in senslab LDAP :
569 #add a filter for make_ldap_filters_from_record
570 person_list = self.ldap.LdapFindUser(is_user_enabled=True)
574 def GetTimezone(self):
575 server_timestamp, server_tz = self.oar.parser.\
576 SendRequest("GET_timezone")
577 return server_timestamp, server_tz
580 def DeleteJobs(self, job_id, slice_hrn):
581 if not job_id or job_id is -1:
583 username = slice_hrn.split(".")[-1].rstrip("_slice")
585 reqdict['method'] = "delete"
586 reqdict['strval'] = str(job_id)
589 answer = self.oar.POSTRequestToOARRestAPI('DELETE_jobs_id', \
591 logger.debug("SLABDRIVER \tDeleteJobs jobid %s \r\n answer %s \
592 username %s" %(job_id,answer, username))
597 ##TODO : Unused GetJobsId ? SA 05/07/12
598 #def GetJobsId(self, job_id, username = None ):
600 #Details about a specific job.
601 #Includes details about submission time, jot type, state, events,
602 #owner, assigned ressources, walltime etc...
606 #node_list_k = 'assigned_network_address'
607 ##Get job info from OAR
608 #job_info = self.oar.parser.SendRequest(req, job_id, username)
610 #logger.debug("SLABDRIVER \t GetJobsId %s " %(job_info))
612 #if job_info['state'] == 'Terminated':
613 #logger.debug("SLABDRIVER \t GetJobsId job %s TERMINATED"\
616 #if job_info['state'] == 'Error':
617 #logger.debug("SLABDRIVER \t GetJobsId ERROR message %s "\
622 #logger.error("SLABDRIVER \tGetJobsId KeyError")
625 #parsed_job_info = self.get_info_on_reserved_nodes(job_info, \
627 ##Replaces the previous entry
628 ##"assigned_network_address" / "reserved_resources"
630 #job_info.update({'node_ids':parsed_job_info[node_list_k]})
631 #del job_info[node_list_k]
632 #logger.debug(" \r\nSLABDRIVER \t GetJobsId job_info %s " %(job_info))
636 def GetJobsResources(self, job_id, username = None):
637 #job_resources=['reserved_resources', 'assigned_resources',\
638 #'job_id', 'job_uri', 'assigned_nodes',\
640 #assigned_res = ['resource_id', 'resource_uri']
641 #assigned_n = ['node', 'node_uri']
643 req = "GET_jobs_id_resources"
646 #Get job resources list from OAR
647 node_id_list = self.oar.parser.SendRequest(req, job_id, username)
648 logger.debug("SLABDRIVER \t GetJobsResources %s " %(node_id_list))
651 self.__get_hostnames_from_oar_node_ids(node_id_list)
654 #Replaces the previous entry "assigned_network_address" /
655 #"reserved_resources"
657 job_info = {'node_ids': hostname_list}
662 def get_info_on_reserved_nodes(self, job_info, node_list_name):
663 #Get the list of the testbed nodes records and make a
664 #dictionnary keyed on the hostname out of it
665 node_list_dict = self.GetNodes()
666 #node_hostname_list = []
667 node_hostname_list = [node['hostname'] for node in node_list_dict]
668 #for node in node_list_dict:
669 #node_hostname_list.append(node['hostname'])
670 node_dict = dict(zip(node_hostname_list, node_list_dict))
672 reserved_node_hostname_list = []
673 for index in range(len(job_info[node_list_name])):
674 #job_info[node_list_name][k] =
675 reserved_node_hostname_list[index] = \
676 node_dict[job_info[node_list_name][index]]['hostname']
678 logger.debug("SLABDRIVER \t get_info_on_reserved_nodes \
679 reserved_node_hostname_list %s" \
680 %(reserved_node_hostname_list))
682 logger.error("SLABDRIVER \t get_info_on_reserved_nodes KEYERROR " )
684 return reserved_node_hostname_list
686 def GetNodesCurrentlyInUse(self):
687 """Returns a list of all the nodes already involved in an oar job"""
688 return self.oar.parser.SendRequest("GET_running_jobs")
690 def __get_hostnames_from_oar_node_ids(self, resource_id_list ):
691 full_nodes_dict_list = self.GetNodes()
692 #Put the full node list into a dictionary keyed by oar node id
693 oar_id_node_dict = {}
694 for node in full_nodes_dict_list:
695 oar_id_node_dict[node['oar_id']] = node
697 #logger.debug("SLABDRIVER \t __get_hostnames_from_oar_node_ids\
698 #oar_id_node_dict %s" %(oar_id_node_dict))
700 hostname_dict_list = []
701 for resource_id in resource_id_list:
702 #Because jobs requested "asap" do not have defined resources
703 if resource_id is not "Undefined":
704 hostname_dict_list.append(\
705 oar_id_node_dict[resource_id]['hostname'])
707 #hostname_list.append(oar_id_node_dict[resource_id]['hostname'])
708 return hostname_dict_list
710 def GetReservedNodes(self,username = None):
711 #Get the nodes in use and the reserved nodes
712 reservation_dict_list = \
713 self.oar.parser.SendRequest("GET_reserved_nodes", username = username)
716 for resa in reservation_dict_list:
717 logger.debug ("GetReservedNodes resa %s"%(resa))
718 #dict list of hostnames and their site
719 resa['reserved_nodes'] = \
720 self.__get_hostnames_from_oar_node_ids(resa['resource_ids'])
722 #del resa['resource_ids']
723 return reservation_dict_list
725 def GetNodes(self, node_filter_dict = None, return_fields_list = None):
727 node_filter_dict : dictionnary of lists
730 node_dict_by_id = self.oar.parser.SendRequest("GET_resources_full")
731 node_dict_list = node_dict_by_id.values()
732 logger.debug (" SLABDRIVER GetNodes node_filter_dict %s return_fields_list %s "%(node_filter_dict,return_fields_list))
733 #No filtering needed return the list directly
734 if not (node_filter_dict or return_fields_list):
735 return node_dict_list
737 return_node_list = []
739 for filter_key in node_filter_dict:
741 #Filter the node_dict_list by each value contained in the
742 #list node_filter_dict[filter_key]
743 for value in node_filter_dict[filter_key]:
744 for node in node_dict_list:
745 if node[filter_key] == value:
746 if return_fields_list :
748 for k in return_fields_list:
750 return_node_list.append(tmp)
752 return_node_list.append(node)
754 logger.log_exc("GetNodes KeyError")
758 return return_node_list
761 def GetSites(self, site_filter_name_list = None, return_fields_list = None):
762 site_dict = self.oar.parser.SendRequest("GET_sites")
763 #site_dict : dict where the key is the sit ename
764 return_site_list = []
765 if not ( site_filter_name_list or return_fields_list):
766 return_site_list = site_dict.values()
767 return return_site_list
769 for site_filter_name in site_filter_name_list:
770 if site_filter_name in site_dict:
771 if return_fields_list:
772 for field in return_fields_list:
775 tmp[field] = site_dict[site_filter_name][field]
777 logger.error("GetSites KeyError %s "%(field))
779 return_site_list.append(tmp)
781 return_site_list.append( site_dict[site_filter_name])
784 return return_site_list
788 def GetSlices(self, slice_filter = None, slice_filter_type = None):
789 #def GetSlices(self, slice_filter = None, slice_filter_type = None, \
790 #return_fields_list = None):
791 """ Get the slice records from the slab db.
792 Returns a slice ditc if slice_filter and slice_filter_type
794 Returns a list of slice dictionnaries if there are no filters
799 return_slice_list = []
802 authorized_filter_types_list = ['slice_hrn', 'record_id_user']
803 slicerec_dictlist = []
806 if slice_filter_type in authorized_filter_types_list:
809 def __get_slice_records(slice_filter = None, slice_filter_type = None):
812 #Get list of slices based on the slice hrn
813 if slice_filter_type == 'slice_hrn':
815 login = slice_filter.split(".")[1].split("_")[0]
817 #DO NOT USE RegSlice - reg_researchers to get the hrn of the user
818 #otherwise will mess up the RegRecord in Resolve, don't know
821 #Only one entry for one user = one slice in slice_senslab table
822 slicerec = slab_dbsession.query(SliceSenslab).filter_by(slice_hrn = slice_filter).first()
824 #Get slice based on user id
825 if slice_filter_type == 'record_id_user':
826 slicerec = slab_dbsession.query(SliceSenslab).filter_by(record_id_user = slice_filter).first()
831 fixed_slicerec_dict = slicerec.dump_sqlalchemyobj_to_dict()
834 login = fixed_slicerec_dict['slice_hrn'].split(".")[1].split("_")[0]
835 return login, fixed_slicerec_dict
840 login, fixed_slicerec_dict = __get_slice_records(slice_filter, slice_filter_type)
841 logger.debug(" SLABDRIVER \tGetSlices login %s \
842 slice record %s slice_filter %s"\
843 %(login, fixed_slicerec_dict,slice_filter))
847 #One slice can have multiple jobs
849 leases_list = self.GetReservedNodes(username = login)
850 #If no job is running or no job scheduled
851 #if leases_list == [] :
852 #return [fixed_slicerec_dict]
853 if leases_list == [] and fixed_slicerec_dict:
854 slicerec_dictlist.append(fixed_slicerec_dict)
856 #Several jobs for one slice
857 for lease in leases_list :
861 #Check with OAR the status of the job if a job id is in
866 slicerec_dict['oar_job_id'] = lease['lease_id']
868 #for reserved_node in lease['reserved_nodes']:
869 #reserved_list.append(reserved_node['hostname'])
870 reserved_list = lease['reserved_nodes']
871 #slicerec_dict.update({'node_ids':[lease['reserved_nodes'][n]['hostname'] for n in lease['reserved_nodes']]})
872 slicerec_dict.update({'list_node_ids':{'hostname':reserved_list}})
873 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
874 #If the slice does not belong to senslab:
875 if fixed_slicerec_dict:
876 slicerec_dict.update(fixed_slicerec_dict)
877 slicerec_dict.update({'hrn':\
878 str(fixed_slicerec_dict['slice_hrn'])})
881 slicerec_dictlist.append(slicerec_dict)
882 logger.debug("SLABDRIVER.PY \tGetSlices slicerec_dict %s slicerec_dictlist %s lease['reserved_nodes'] %s" %(slicerec_dict, slicerec_dictlist,lease['reserved_nodes'] ))
884 logger.debug("SLABDRIVER.PY \tGetSlices RETURN slicerec_dictlist %s"\
885 %(slicerec_dictlist))
887 return slicerec_dictlist
892 slice_list = slab_dbsession.query(SliceSenslab).all()
893 leases_list = self.GetReservedNodes()
896 slicerec_dictlist = []
897 return_slice_list = []
898 for record in slice_list:
899 return_slice_list.append(record.dump_sqlalchemyobj_to_dict())
901 for fixed_slicerec_dict in return_slice_list:
903 owner = fixed_slicerec_dict['slice_hrn'].split(".")[1].split("_")[0]
904 for lease in leases_list:
905 if owner == lease['user']:
906 slicerec_dict['oar_job_id'] = lease['lease_id']
909 #for reserved_node in lease['reserved_nodes']:
910 logger.debug("SLABDRIVER.PY \tGetSlices lease %s " %(lease ))
912 reserved_list.extend(lease['reserved_nodes'])
914 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
915 slicerec_dict.update({'list_node_ids':{'hostname':reserved_list}})
916 slicerec_dict.update(fixed_slicerec_dict)
917 slicerec_dict.update({'hrn':\
918 str(fixed_slicerec_dict['slice_hrn'])})
919 slicerec_dictlist.append(slicerec_dict)
920 fixed_slicerec_dict.update(slicerec_dict)
921 logger.debug("SLABDRIVER.PY \tGetSlices RETURN slices %s \
922 slice_filter %s " %(return_slice_list, slice_filter))
924 #if return_fields_list:
925 #return_slice_list = parse_filter(sliceslist, \
926 #slice_filter,'slice', return_fields_list)
927 return return_slice_list
928 #return slicerec_dictlist
931 def testbed_name (self): return self.hrn
933 # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
934 def aggregate_version (self):
935 version_manager = VersionManager()
936 ad_rspec_versions = []
937 request_rspec_versions = []
938 for rspec_version in version_manager.versions:
939 if rspec_version.content_type in ['*', 'ad']:
940 ad_rspec_versions.append(rspec_version.to_dict())
941 if rspec_version.content_type in ['*', 'request']:
942 request_rspec_versions.append(rspec_version.to_dict())
944 'testbed':self.testbed_name(),
945 'geni_request_rspec_versions': request_rspec_versions,
946 'geni_ad_rspec_versions': ad_rspec_versions,
955 # Convert SFA fields to PLC fields for use when registering up updating
956 # registry record in the PLC database
958 # @param type type of record (user, slice, ...)
959 # @param hrn human readable name
960 # @param sfa_fields dictionary of SFA fields
961 # @param slab_fields dictionary of PLC fields (output)
963 def sfa_fields_to_slab_fields(self, sfa_type, hrn, record):
967 #for field in record:
968 # slab_record[field] = record[field]
970 if sfa_type == "slice":
971 #instantion used in get_slivers ?
972 if not "instantiation" in slab_record:
973 slab_record["instantiation"] = "senslab-instantiated"
974 #slab_record["hrn"] = hrn_to_pl_slicename(hrn)
975 #Unused hrn_to_pl_slicename because Slab's hrn already in the appropriate form SA 23/07/12
976 slab_record["hrn"] = hrn
977 logger.debug("SLABDRIVER.PY sfa_fields_to_slab_fields \
978 slab_record %s " %(slab_record['hrn']))
980 slab_record["url"] = record["url"]
981 if "description" in record:
982 slab_record["description"] = record["description"]
983 if "expires" in record:
984 slab_record["expires"] = int(record["expires"])
986 #nodes added by OAR only and then imported to SFA
987 #elif type == "node":
988 #if not "hostname" in slab_record:
989 #if not "hostname" in record:
990 #raise MissingSfaInfo("hostname")
991 #slab_record["hostname"] = record["hostname"]
992 #if not "model" in slab_record:
993 #slab_record["model"] = "geni"
996 #elif type == "authority":
997 #slab_record["login_base"] = hrn_to_slab_login_base(hrn)
999 #if not "name" in slab_record:
1000 #slab_record["name"] = hrn
1002 #if not "abbreviated_name" in slab_record:
1003 #slab_record["abbreviated_name"] = hrn
1005 #if not "enabled" in slab_record:
1006 #slab_record["enabled"] = True
1008 #if not "is_public" in slab_record:
1009 #slab_record["is_public"] = True
1016 def __transforms_timestamp_into_date(self, xp_utc_timestamp = None):
1017 """ Transforms unix timestamp into valid OAR date format """
1019 #Used in case of a scheduled experiment (not immediate)
1020 #To run an XP immediately, don't specify date and time in RSpec
1021 #They will be set to None.
1022 if xp_utc_timestamp:
1023 #transform the xp_utc_timestamp into server readable time
1024 xp_server_readable_date = datetime.fromtimestamp(int(\
1025 xp_utc_timestamp)).strftime(self.time_format)
1027 return xp_server_readable_date
1035 def LaunchExperimentOnOAR(self, added_nodes, slice_name, \
1036 lease_start_time, lease_duration, slice_user=None):
1038 lease_dict['lease_start_time'] = lease_start_time
1039 lease_dict['lease_duration'] = lease_duration
1040 lease_dict['added_nodes'] = added_nodes
1041 lease_dict['slice_name'] = slice_name
1042 lease_dict['slice_user'] = slice_user
1043 lease_dict['grain'] = self.GetLeaseGranularity()
1044 lease_dict['time_format'] = self.time_format
1046 def __create_job_structure_request_for_OAR(lease_dict):
1047 """ Creates the structure needed for a correct POST on OAR.
1048 Makes the timestamp transformation into the appropriate format.
1049 Sends the POST request to create the job with the resources in
1058 reqdict['workdir'] = '/tmp'
1059 reqdict['resource'] = "{network_address in ("
1061 for node in lease_dict['added_nodes']:
1062 logger.debug("\r\n \r\n OARrestapi \t __create_job_structure_request_for_OAR \
1065 # Get the ID of the node
1067 reqdict['resource'] += "'" + nodeid + "', "
1068 nodeid_list.append(nodeid)
1070 custom_length = len(reqdict['resource'])- 2
1071 reqdict['resource'] = reqdict['resource'][0:custom_length] + \
1072 ")}/nodes=" + str(len(nodeid_list))
1074 def __process_walltime(duration):
1075 """ Calculates the walltime in seconds from the duration in H:M:S
1076 specified in the RSpec.
1080 # Fixing the walltime by adding a few delays.
1081 # First put the walltime in seconds oarAdditionalDelay = 20;
1082 # additional delay for /bin/sleep command to
1083 # take in account prologue and epilogue scripts execution
1084 # int walltimeAdditionalDelay = 240; additional delay
1085 desired_walltime = duration
1086 total_walltime = desired_walltime + 240 #+4 min Update SA 23/10/12
1087 sleep_walltime = desired_walltime # 0 sec added Update SA 23/10/12
1089 #Put the walltime back in str form
1090 #First get the hours
1091 walltime.append(str(total_walltime / 3600))
1092 total_walltime = total_walltime - 3600 * int(walltime[0])
1093 #Get the remaining minutes
1094 walltime.append(str(total_walltime / 60))
1095 total_walltime = total_walltime - 60 * int(walltime[1])
1097 walltime.append(str(total_walltime))
1100 logger.log_exc(" __process_walltime duration null")
1102 return walltime, sleep_walltime
1105 walltime, sleep_walltime = \
1106 __process_walltime(int(lease_dict['lease_duration'])*lease_dict['grain'])
1109 reqdict['resource'] += ",walltime=" + str(walltime[0]) + \
1110 ":" + str(walltime[1]) + ":" + str(walltime[2])
1111 reqdict['script_path'] = "/bin/sleep " + str(sleep_walltime)
1113 #In case of a scheduled experiment (not immediate)
1114 #To run an XP immediately, don't specify date and time in RSpec
1115 #They will be set to None.
1116 if lease_dict['lease_start_time'] is not '0':
1117 #Readable time accepted by OAR
1118 start_time = datetime.fromtimestamp(int(lease_dict['lease_start_time'])).\
1119 strftime(lease_dict['time_format'])
1120 reqdict['reservation'] = start_time
1121 #If there is not start time, Immediate XP. No need to add special
1125 reqdict['type'] = "deploy"
1126 reqdict['directory'] = ""
1127 reqdict['name'] = "SFA_" + lease_dict['slice_user']
1132 #Create the request for OAR
1133 reqdict = __create_job_structure_request_for_OAR(lease_dict)
1134 # first step : start the OAR job and update the job
1135 logger.debug("SLABDRIVER.PY \tLaunchExperimentOnOAR reqdict %s\
1138 answer = self.oar.POSTRequestToOARRestAPI('POST_job', \
1139 reqdict, slice_user)
1140 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s " %(answer))
1142 jobid = answer['id']
1144 logger.log_exc("SLABDRIVER \tLaunchExperimentOnOAR \
1145 Impossible to create job %s " %(answer))
1149 def __configure_experiment(jobid, added_nodes):
1150 # second step : configure the experiment
1151 # we need to store the nodes in a yaml (well...) file like this :
1152 # [1,56,23,14,45,75] with name /tmp/sfa<jobid>.json
1153 job_file = open('/tmp/sfa/'+ str(jobid) + '.json', 'w')
1155 job_file.write(str(added_nodes[0].strip('node')))
1156 for node in added_nodes[1:len(added_nodes)] :
1157 job_file.write(', '+ node.strip('node'))
1162 def __launch_senslab_experiment(jobid):
1163 # third step : call the senslab-experiment wrapper
1164 #command= "java -jar target/sfa-1.0-jar-with-dependencies.jar
1165 # "+str(jobid)+" "+slice_user
1166 javacmdline = "/usr/bin/java"
1168 "/opt/senslabexperimentwrapper/sfa-1.0-jar-with-dependencies.jar"
1169 #ret=subprocess.check_output(["/usr/bin/java", "-jar", ", \
1170 #str(jobid), slice_user])
1171 output = subprocess.Popen([javacmdline, "-jar", jarname, str(jobid), \
1172 slice_user],stdout=subprocess.PIPE).communicate()[0]
1174 logger.debug("SLABDRIVER \t __configure_experiment wrapper returns%s " \
1181 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s \
1182 added_nodes %s slice_user %s" %(jobid, added_nodes, slice_user))
1185 __configure_experiment(jobid, added_nodes)
1186 __launch_senslab_experiment(jobid)
1190 def AddLeases(self, hostname_list, slice_record, lease_start_time, lease_duration):
1191 logger.debug("SLABDRIVER \r\n \r\n \t AddLeases hostname_list %s \
1192 slice_record %s lease_start_time %s lease_duration %s "\
1193 %( hostname_list, slice_record , lease_start_time, \
1196 tmp = slice_record['reg-researchers'][0].split(".")
1197 username = tmp[(len(tmp)-1)]
1198 self.LaunchExperimentOnOAR(hostname_list, slice_record['slice_hrn'], lease_start_time, lease_duration, username)
1199 start_time = datetime.fromtimestamp(int(lease_start_time)).strftime(self.time_format)
1200 logger.debug("SLABDRIVER \t AddLeases hostname_list start_time %s " %(start_time))
1205 #Delete the jobs from job_senslab table
1206 def DeleteSliceFromNodes(self, slice_record):
1208 self.DeleteJobs(slice_record['oar_job_id'], slice_record['hrn'])
1212 def GetLeaseGranularity(self):
1213 """ Returns the granularity of Senslab testbed.
1214 OAR returns seconds for experiments duration.
1215 Defined in seconds. """
1220 def GetLeases(self, lease_filter_dict=None):
1221 unfiltered_reservation_list = self.GetReservedNodes()
1223 ##Synchronize slice_table of sfa senslab db
1224 #self.synchronize_oar_and_slice_table(unfiltered_reservation_list)
1226 reservation_list = []
1227 #Find the slice associated with this user senslab ldap uid
1228 logger.debug(" SLABDRIVER.PY \tGetLeases ")
1229 #Create user dict first to avoir looking several times for
1230 #the same user in LDAP SA 27/07/12
1232 for resa in unfiltered_reservation_list:
1233 logger.debug("SLABDRIVER \tGetLeases USER %s"\
1235 if resa['user'] not in resa_user_dict:
1236 logger.debug("SLABDRIVER \tGetLeases userNOTIN ")
1237 ldap_info = self.ldap.LdapSearch('(uid='+resa['user']+')')
1238 ldap_info = ldap_info[0][1]
1239 user = dbsession.query(RegUser).filter_by(email = \
1240 ldap_info['mail'][0]).first()
1241 #Separated in case user not in database : record_id not defined SA 17/07//12
1242 query_slice_info = slab_dbsession.query(SliceSenslab).filter_by(record_id_user = user.record_id)
1243 if query_slice_info:
1244 slice_info = query_slice_info.first()
1248 resa_user_dict[resa['user']] = {}
1249 resa_user_dict[resa['user']]['ldap_info'] = user
1250 resa_user_dict[resa['user']]['slice_info'] = slice_info
1252 logger.debug("SLABDRIVER \tGetLeases resa_user_dict %s"\
1254 for resa in unfiltered_reservation_list:
1258 resa['slice_hrn'] = resa_user_dict[resa['user']]['slice_info'].slice_hrn
1259 resa['slice_id'] = hrn_to_urn(resa['slice_hrn'], 'slice')
1261 #resa['slice_id'] = hrn_to_urn(slice_info.slice_hrn, 'slice')
1262 resa['component_id_list'] = []
1263 #Transform the hostnames into urns (component ids)
1264 for node in resa['reserved_nodes']:
1265 #resa['component_id_list'].append(hostname_to_urn(self.hrn, \
1266 #self.root_auth, node['hostname']))
1267 slab_xrn = slab_xrn_object(self.root_auth, node)
1268 resa['component_id_list'].append(slab_xrn.urn)
1270 #Filter the reservation list if necessary
1271 #Returns all the leases associated with a given slice
1272 if lease_filter_dict:
1273 logger.debug("SLABDRIVER \tGetLeases lease_filter_dict %s"\
1274 %(lease_filter_dict))
1275 for resa in unfiltered_reservation_list:
1276 if lease_filter_dict['name'] == resa['slice_hrn']:
1277 reservation_list.append(resa)
1279 reservation_list = unfiltered_reservation_list
1281 logger.debug(" SLABDRIVER.PY \tGetLeases reservation_list %s"\
1282 %(reservation_list))
1283 return reservation_list
1285 def augment_records_with_testbed_info (self, sfa_records):
1286 return self.fill_record_info (sfa_records)
1288 def fill_record_info(self, record_list):
1290 Given a SFA record, fill in the senslab specific and SFA specific
1291 fields in the record.
1294 logger.debug("SLABDRIVER \tfill_record_info records %s " %(record_list))
1295 if not isinstance(record_list, list):
1296 record_list = [record_list]
1299 for record in record_list:
1300 #If the record is a SFA slice record, then add information
1301 #about the user of this slice. This kind of
1302 #information is in the Senslab's DB.
1303 if str(record['type']) == 'slice':
1304 #Get slab slice record.
1305 recslice_list = self.GetSlices(slice_filter = \
1306 str(record['hrn']),\
1307 slice_filter_type = 'slice_hrn')
1309 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1310 recslice_list[0]['record_id_user']).first()
1311 logger.debug("SLABDRIVER \tfill_record_info TYPE SLICE RECUSER %s " %(recuser))
1312 record.update({'PI':[recuser.hrn],
1313 'researcher': [recuser.hrn],
1314 'name':record['hrn'],
1317 'person_ids':[recslice_list[0]['record_id_user']],
1318 'geni_urn':'', #For client_helper.py compatibility
1319 'keys':'', #For client_helper.py compatibility
1320 'key_ids':''}) #For client_helper.py compatibility
1323 for rec in recslice_list:
1324 record['oar_job_id'].append(rec['oar_job_id'])
1325 record['node_ids'] = [ self.root_auth + hostname for hostname in rec['node_ids']]
1329 logger.debug( "SLABDRIVER.PY \t fill_record_info SLICE \
1330 recslice_list %s \r\n \t RECORD %s \r\n \r\n" %(recslice_list,record))
1331 if str(record['type']) == 'user':
1332 #The record is a SFA user record.
1333 #Get the information about his slice from Senslab's DB
1334 #and add it to the user record.
1335 recslice_list = self.GetSlices(\
1336 slice_filter = record['record_id'],\
1337 slice_filter_type = 'record_id_user')
1339 logger.debug( "SLABDRIVER.PY \t fill_record_info TYPE USER \
1340 recslice_list %s \r\n \t RECORD %s \r\n" %(recslice_list , record))
1341 #Append slice record in records list,
1342 #therefore fetches user and slice info again(one more loop)
1343 #Will update PIs and researcher for the slice
1344 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1345 recslice_list[0]['record_id_user']).first()
1346 logger.debug( "SLABDRIVER.PY \t fill_record_info USER \
1347 recuser %s \r\n \r\n" %(recuser))
1349 recslice = recslice_list[0]
1350 recslice.update({'PI':[recuser.hrn],
1351 'researcher': [recuser.hrn],
1352 'name':record['hrn'],
1355 'person_ids':[recslice_list[0]['record_id_user']]})
1357 for rec in recslice_list:
1358 recslice['oar_job_id'].append(rec['oar_job_id'])
1362 recslice.update({'type':'slice', \
1363 'hrn':recslice_list[0]['slice_hrn']})
1366 #GetPersons takes [] as filters
1367 #user_slab = self.GetPersons([{'hrn':recuser.hrn}])
1368 user_slab = self.GetPersons([record])
1371 record.update(user_slab[0])
1372 #For client_helper.py compatibility
1373 record.update( { 'geni_urn':'',
1376 record_list.append(recslice)
1378 logger.debug("SLABDRIVER.PY \tfill_record_info ADDING SLICE\
1379 INFO TO USER records %s" %(record_list))
1380 logger.debug("SLABDRIVER.PY \tfill_record_info END \
1381 #record %s \r\n \r\n " %(record))
1383 except TypeError, error:
1384 logger.log_exc("SLABDRIVER \t fill_record_info EXCEPTION %s"\
1386 #logger.debug("SLABDRIVER.PY \t fill_record_info ENDENDEND ")
1390 #self.fill_record_slab_info(records)
1396 #TODO Update membership? update_membership_list SA 05/07/12
1397 #def update_membership_list(self, oldRecord, record, listName, addFunc, \
1399 ## get a list of the HRNs tht are members of the old and new records
1401 #oldList = oldRecord.get(listName, [])
1404 #newList = record.get(listName, [])
1406 ## if the lists are the same, then we don't have to update anything
1407 #if (oldList == newList):
1410 ## build a list of the new person ids, by looking up each person to get
1414 #records = table.find({'type': 'user', 'hrn': newList})
1415 #for rec in records:
1416 #newIdList.append(rec['pointer'])
1418 ## build a list of the old person ids from the person_ids field
1420 #oldIdList = oldRecord.get("person_ids", [])
1421 #containerId = oldRecord.get_pointer()
1423 ## if oldRecord==None, then we are doing a Register, instead of an
1426 #containerId = record.get_pointer()
1428 ## add people who are in the new list, but not the oldList
1429 #for personId in newIdList:
1430 #if not (personId in oldIdList):
1431 #addFunc(self.plauth, personId, containerId)
1433 ## remove people who are in the old list, but not the new list
1434 #for personId in oldIdList:
1435 #if not (personId in newIdList):
1436 #delFunc(self.plauth, personId, containerId)
1438 #def update_membership(self, oldRecord, record):
1440 #if record.type == "slice":
1441 #self.update_membership_list(oldRecord, record, 'researcher',
1442 #self.users.AddPersonToSlice,
1443 #self.users.DeletePersonFromSlice)
1444 #elif record.type == "authority":
1449 # I don't think you plan on running a component manager at this point
1450 # let me clean up the mess of ComponentAPI that is deprecated anyways
1453 #TODO FUNCTIONS SECTION 04/07/2012 SA
1455 #TODO : Is UnBindObjectFromPeer still necessary ? Currently does nothing
1457 def UnBindObjectFromPeer(self, auth, object_type, object_id, shortname):
1458 """ This method is a hopefully temporary hack to let the sfa correctly
1459 detach the objects it creates from a remote peer object. This is
1460 needed so that the sfa federation link can work in parallel with
1461 RefreshPeer, as RefreshPeer depends on remote objects being correctly
1464 auth : struct, API authentication structure
1465 AuthMethod : string, Authentication method to use
1466 object_type : string, Object type, among 'site','person','slice',
1468 object_id : int, object_id
1469 shortname : string, peer shortname
1473 logger.warning("SLABDRIVER \tUnBindObjectFromPeer EMPTY-\
1477 #TODO Is BindObjectToPeer still necessary ? Currently does nothing
1479 def BindObjectToPeer(self, auth, object_type, object_id, shortname=None, \
1480 remote_object_id=None):
1481 """This method is a hopefully temporary hack to let the sfa correctly
1482 attach the objects it creates to a remote peer object. This is needed
1483 so that the sfa federation link can work in parallel with RefreshPeer,
1484 as RefreshPeer depends on remote objects being correctly marked.
1486 shortname : string, peer shortname
1487 remote_object_id : int, remote object_id, set to 0 if unknown
1491 logger.warning("SLABDRIVER \tBindObjectToPeer EMPTY - DO NOTHING \r\n ")
1494 #TODO UpdateSlice 04/07/2012 SA
1495 #Funciton should delete and create another job since oin senslab slice=job
1496 def UpdateSlice(self, auth, slice_id_or_name, slice_fields=None):
1497 """Updates the parameters of an existing slice with the values in
1499 Users may only update slices of which they are members.
1500 PIs may update any of the slices at their sites, or any slices of
1501 which they are members. Admins may update any slice.
1502 Only PIs and admins may update max_nodes. Slices cannot be renewed
1503 (by updating the expires parameter) more than 8 weeks into the future.
1504 Returns 1 if successful, faults otherwise.
1508 logger.warning("SLABDRIVER UpdateSlice EMPTY - DO NOTHING \r\n ")
1511 #TODO UpdatePerson 04/07/2012 SA
1512 def UpdatePerson(self, auth, person_id_or_email, person_fields=None):
1513 """Updates a person. Only the fields specified in person_fields
1514 are updated, all other fields are left untouched.
1515 Users and techs can only update themselves. PIs can only update
1516 themselves and other non-PIs at their sites.
1517 Returns 1 if successful, faults otherwise.
1521 logger.warning("SLABDRIVER UpdatePerson EMPTY - DO NOTHING \r\n ")
1524 #TODO GetKeys 04/07/2012 SA
1525 def GetKeys(self, auth, key_filter=None, return_fields=None):
1526 """Returns an array of structs containing details about keys.
1527 If key_filter is specified and is an array of key identifiers,
1528 or a struct of key attributes, only keys matching the filter
1529 will be returned. If return_fields is specified, only the
1530 specified details will be returned.
1532 Admin may query all keys. Non-admins may only query their own keys.
1536 logger.warning("SLABDRIVER GetKeys EMPTY - DO NOTHING \r\n ")
1539 #TODO DeleteKey 04/07/2012 SA
1540 def DeleteKey(self, auth, key_id):
1542 Non-admins may only delete their own keys.
1543 Returns 1 if successful, faults otherwise.
1547 logger.warning("SLABDRIVER DeleteKey EMPTY - DO NOTHING \r\n ")
1551 #TODO : Check rights to delete person
1552 def DeletePerson(self, auth, person_record):
1553 """ Disable an existing account in senslab LDAP.
1554 Users and techs can only delete themselves. PIs can only
1555 delete themselves and other non-PIs at their sites.
1556 ins can delete anyone.
1557 Returns 1 if successful, faults otherwise.
1561 #Disable user account in senslab LDAP
1562 ret = self.ldap.LdapMarkUserAsDeleted(person_record)
1563 logger.warning("SLABDRIVER DeletePerson %s " %(person_record))
1566 #TODO Check DeleteSlice, check rights 05/07/2012 SA
1567 def DeleteSlice(self, auth, slice_record):
1568 """ Deletes the specified slice.
1569 Senslab : Kill the job associated with the slice if there is one
1570 using DeleteSliceFromNodes.
1571 Updates the slice record in slab db to remove the slice nodes.
1573 Users may only delete slices of which they are members. PIs may
1574 delete any of the slices at their sites, or any slices of which
1575 they are members. Admins may delete any slice.
1576 Returns 1 if successful, faults otherwise.
1580 self.DeleteSliceFromNodes(slice_record)
1581 logger.warning("SLABDRIVER DeleteSlice %s "%(slice_record))
1584 #TODO AddPerson 04/07/2012 SA
1585 #def AddPerson(self, auth, person_fields=None):
1586 def AddPerson(self, record):#TODO fixing 28/08//2012 SA
1587 """Adds a new account. Any fields specified in records are used,
1588 otherwise defaults are used.
1589 Accounts are disabled by default. To enable an account,
1591 Returns the new person_id (> 0) if successful, faults otherwise.
1595 ret = self.ldap.LdapAddUser(record)
1596 logger.warning("SLABDRIVER AddPerson return code %s \r\n ", ret)
1599 #TODO AddPersonToSite 04/07/2012 SA
1600 def AddPersonToSite (self, auth, person_id_or_email, \
1601 site_id_or_login_base=None):
1602 """ Adds the specified person to the specified site. If the person is
1603 already a member of the site, no errors are returned. Does not change
1604 the person's primary site.
1605 Returns 1 if successful, faults otherwise.
1609 logger.warning("SLABDRIVER AddPersonToSite EMPTY - DO NOTHING \r\n ")
1612 #TODO AddRoleToPerson : Not sure if needed in senslab 04/07/2012 SA
1613 def AddRoleToPerson(self, auth, role_id_or_name, person_id_or_email):
1614 """Grants the specified role to the person.
1615 PIs can only grant the tech and user roles to users and techs at their
1616 sites. Admins can grant any role to any user.
1617 Returns 1 if successful, faults otherwise.
1621 logger.warning("SLABDRIVER AddRoleToPerson EMPTY - DO NOTHING \r\n ")
1624 #TODO AddPersonKey 04/07/2012 SA
1625 def AddPersonKey(self, auth, person_id_or_email, key_fields=None):
1626 """Adds a new key to the specified account.
1627 Non-admins can only modify their own keys.
1628 Returns the new key_id (> 0) if successful, faults otherwise.
1632 logger.warning("SLABDRIVER AddPersonKey EMPTY - DO NOTHING \r\n ")
1635 def DeleteLeases(self, leases_id_list, slice_hrn ):
1636 for job_id in leases_id_list:
1637 self.DeleteJobs(job_id, slice_hrn)
1639 logger.debug("SLABDRIVER DeleteLeases leases_id_list %s slice_hrn %s \
1640 \r\n " %(leases_id_list, slice_hrn))