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
83 for single_slice in slice_list:
84 for node in single_slice['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([(one_node['hostname'], one_node) \
91 for one_node in nodes_all])
95 for single_slice in slice_list:
98 top_level_status = 'empty'
101 ['geni_urn','pl_login','geni_status','geni_resources'], None)
102 result['pl_login'] = recuser.hrn
103 logger.debug("Slabdriver - sliver_status Sliver status \
104 urn %s hrn %s single_slice %s \r\n " \
105 %(slice_urn, slice_hrn, single_slice))
107 nodes_in_slice = single_slice['node_ids']
110 result['geni_status'] = top_level_status
111 result['geni_resources'] = []
114 top_level_status = 'ready'
116 #A job is running on Senslab for this slice
117 # report about the local nodes that are in the slice only
119 result['geni_urn'] = slice_urn
123 #timestamp = float(sl['startTime']) + float(sl['walltime'])
124 #result['pl_expires'] = strftime(self.time_format, \
125 #gmtime(float(timestamp)))
126 #result['slab_expires'] = strftime(self.time_format,\
127 #gmtime(float(timestamp)))
130 for node in single_slice['node_ids']:
132 #res['slab_hostname'] = node['hostname']
133 #res['slab_boot_state'] = node['boot_state']
135 res['pl_hostname'] = node['hostname']
136 res['pl_boot_state'] = \
137 nodeall_byhostname[node['hostname']]['boot_state']
138 #res['pl_last_contact'] = strftime(self.time_format, \
139 #gmtime(float(timestamp)))
140 sliver_id = Xrn(slice_urn, type='slice', \
141 id=nodeall_byhostname[node['hostname']]['node_id'], \
142 authority=self.hrn).urn
144 res['geni_urn'] = sliver_id
145 node_name = node['hostname']
146 if nodeall_byhostname[node_name]['boot_state'] == 'Alive':
148 res['geni_status'] = 'ready'
150 res['geni_status'] = 'failed'
151 top_level_status = 'failed'
153 res['geni_error'] = ''
155 resources.append(res)
157 result['geni_status'] = top_level_status
158 result['geni_resources'] = resources
159 logger.debug("SLABDRIVER \tsliver_statusresources %s res %s "\
163 def get_user(self, hrn):
164 return dbsession.query(RegRecord).filter_by(hrn = hrn).first()
167 def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, \
169 aggregate = SlabAggregate(self)
171 slices = SlabSlices(self)
172 peer = slices.get_peer(slice_hrn)
173 sfa_peer = slices.get_sfa_peer(slice_hrn)
176 if not isinstance(creds, list):
180 slice_record = users[0].get('slice_record', {})
181 logger.debug("SLABDRIVER.PY \t create_sliver \t\
182 slice_record %s \r\n \r\n users %s" \
183 %(slice_record, users))
184 slice_record['user'] = {'keys':users[0]['keys'], \
185 'email':users[0]['email'], \
186 'hrn':slice_record['reg-researchers'][0]}
188 rspec = RSpec(rspec_string)
189 logger.debug("SLABDRIVER.PY \t create_sliver \trspec.version \
190 %s slice_record %s users %s" \
191 %(rspec.version,slice_record, users))
194 # ensure site record exists?
195 # ensure slice record exists
196 #Removed options to verify_slice SA 14/08/12
197 sfa_slice = slices.verify_slice(slice_hrn, slice_record, peer, \
200 # ensure person records exists
201 #verify_persons returns added persons but since the return value
203 slices.verify_persons(slice_hrn, sfa_slice, users, peer, \
204 sfa_peer, options=options)
205 #requested_attributes returned by rspec.version.get_slice_attributes()
206 #unused, removed SA 13/08/12
207 rspec.version.get_slice_attributes()
209 logger.debug("SLABDRIVER.PY create_sliver slice %s " %(sfa_slice))
215 # add/remove slice from nodes
217 requested_slivers = [node.get('component_id') \
218 for node in rspec.version.get_nodes_with_slivers()\
219 if node.get('authority_id') is self.root_auth]
220 l = [ node for node in rspec.version.get_nodes_with_slivers() ]
221 logger.debug("SLADRIVER \tcreate_sliver requested_slivers \
222 requested_slivers %s listnodes %s" \
223 %(requested_slivers,l))
224 #verify_slice_nodes returns nodes, but unused here. Removed SA 13/08/12.
225 #slices.verify_slice_nodes(sfa_slice, requested_slivers, peer)
228 requested_lease_list = []
230 logger.debug("SLABDRIVER.PY \tcreate_sliver AVANTLEASE " )
231 rspec_requested_leases = rspec.version.get_leases()
232 for lease in rspec.version.get_leases():
233 single_requested_lease = {}
234 logger.debug("SLABDRIVER.PY \tcreate_sliver lease %s " %(lease))
236 if not lease.get('lease_id'):
237 if get_authority(lease['component_id']) == self.root_auth:
238 single_requested_lease['hostname'] = \
239 slab_xrn_to_hostname(\
240 lease.get('component_id').strip())
241 single_requested_lease['start_time'] = \
242 lease.get('start_time')
243 single_requested_lease['duration'] = lease.get('duration')
245 requested_lease_list.append(single_requested_lease)
247 logger.debug("SLABDRIVER.PY \tcreate_sliver APRESLEASE" )
248 #dCreate dict of leases by start_time, regrouping nodes reserved
250 #time, for the same amount of time = one job on OAR
251 requested_job_dict = {}
252 for lease in requested_lease_list:
254 #In case it is an asap experiment start_time is empty
255 if lease['start_time'] == '':
256 lease['start_time'] = '0'
258 if lease['start_time'] not in requested_job_dict:
259 if isinstance(lease['hostname'], str):
260 lease['hostname'] = [lease['hostname']]
262 requested_job_dict[lease['start_time']] = lease
265 job_lease = requested_job_dict[lease['start_time']]
266 if lease['duration'] == job_lease['duration'] :
267 job_lease['hostname'].append(lease['hostname'])
272 logger.debug("SLABDRIVER.PY \tcreate_sliver requested_job_dict %s "\
273 %(requested_job_dict))
274 #verify_slice_leases returns the leases , but the return value is unused
275 #here. Removed SA 13/08/12
276 slices.verify_slice_leases(sfa_slice, \
277 requested_job_dict, peer)
279 return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
282 def delete_sliver (self, slice_urn, slice_hrn, creds, options):
284 sfa_slice_list = self.GetSlices(slice_filter = slice_hrn, \
285 slice_filter_type = 'slice_hrn')
287 if not sfa_slice_list:
290 #Delete all in the slice
291 for sfa_slice in sfa_slice_list:
294 logger.debug("SLABDRIVER.PY delete_sliver slice %s" %(sfa_slice))
295 slices = SlabSlices(self)
296 # determine if this is a peer slice
298 peer = slices.get_peer(slice_hrn)
299 #TODO delete_sliver SA : UnBindObjectFromPeer should be
300 #used when there is another
301 #senslab testbed, which is not the case 14/08/12 .
303 logger.debug("SLABDRIVER.PY delete_sliver peer %s" %(peer))
306 self.UnBindObjectFromPeer('slice', \
307 sfa_slice['record_id_slice'], \
309 self.DeleteSliceFromNodes(sfa_slice)
312 self.BindObjectToPeer('slice', \
313 sfa_slice['record_id_slice'], \
314 peer, sfa_slice['peer_slice_id'])
318 def AddSlice(self, slice_record, user_record):
319 """Add slice to the sfa tables and senslab table only if the user
320 already exists in senslab database(user already registered in LDAP).
321 There is no way to separate adding the slice to the tesbed
322 and then importing it from the testbed to SFA because of
323 senslab's architecture. Therefore, sfa tables are updated here.
326 sfa_record = RegSlice(hrn=slice_record['slice_hrn'],
327 gid=slice_record['gid'],
328 pointer=slice_record['slice_id'],
329 authority=slice_record['authority'])
331 logger.debug("SLABDRIVER.PY AddSlice sfa_record %s user_record %s" \
332 %(sfa_record, user_record))
333 sfa_record.just_created()
334 dbsession.add(sfa_record)
336 #Update the reg-researcher dependance table
337 sfa_record.reg_researchers = [user_record]
340 #Update the senslab table with the new slice
341 slab_slice = SliceSenslab( slice_hrn = slice_record['slice_hrn'], \
342 record_id_slice = sfa_record.record_id , \
343 record_id_user = slice_record['record_id_user'], \
344 peer_authority = slice_record['peer_authority'])
346 logger.debug("SLABDRIVER.PY \tAddSlice slice_record %s \
347 slab_slice %s sfa_record %s" \
348 %(slice_record,slab_slice, sfa_record))
349 slab_dbsession.add(slab_slice)
350 slab_dbsession.commit()
353 # first 2 args are None in case of resource discovery
354 def list_resources (self, slice_urn, slice_hrn, creds, options):
355 #cached_requested = options.get('cached', True)
357 version_manager = VersionManager()
358 # get the rspec's return format from options
360 version_manager.get_version(options.get('geni_rspec_version'))
361 version_string = "rspec_%s" % (rspec_version)
363 #panos adding the info option to the caching key (can be improved)
364 if options.get('info'):
365 version_string = version_string + "_" + \
366 options.get('info', 'default')
368 # look in cache first
369 #if cached_requested and self.cache and not slice_hrn:
370 #rspec = self.cache.get(version_string)
372 #logger.debug("SlabDriver.ListResources: \
373 #returning cached advertisement")
376 #panos: passing user-defined options
377 aggregate = SlabAggregate(self)
378 origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
379 options.update({'origin_hrn':origin_hrn})
380 rspec = aggregate.get_rspec(slice_xrn=slice_urn, \
381 version=rspec_version, options=options)
384 #if self.cache and not slice_hrn:
385 #logger.debug("Slab.ListResources: stores advertisement in cache")
386 #self.cache.add(version_string, rspec)
391 def list_slices (self, creds, options):
392 # look in cache first
394 #slices = self.cache.get('slices')
396 #logger.debug("PlDriver.list_slices returns from cache")
401 slices = self.GetSlices()
402 logger.debug("SLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n" %(slices))
403 slice_hrns = [slab_slice['slice_hrn'] for slab_slice in slices]
405 slice_urns = [hrn_to_urn(slice_hrn, 'slice') \
406 for slice_hrn in slice_hrns]
410 #logger.debug ("SlabDriver.list_slices stores value in cache")
411 #self.cache.add('slices', slice_urns)
416 def register (self, sfa_record, hrn, pub_key):
418 Adding new user, slice, node or site should not be handled
422 Adding users = LDAP Senslab
423 Adding slice = Import from LDAP users
429 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
430 """No site or node record update allowed in Senslab."""
432 pointer = old_sfa_record['pointer']
433 old_sfa_record_type = old_sfa_record['type']
435 # new_key implemented for users only
436 if new_key and old_sfa_record_type not in [ 'user' ]:
437 raise UnknownSfaType(old_sfa_record_type)
439 #if (type == "authority"):
440 #self.shell.UpdateSite(pointer, new_sfa_record)
442 if old_sfa_record_type == "slice":
443 slab_record = self.sfa_fields_to_slab_fields(old_sfa_record_type, \
445 if 'name' in slab_record:
446 slab_record.pop('name')
447 #Prototype should be UpdateSlice(self,
448 #auth, slice_id_or_name, slice_fields)
449 #Senslab cannot update slice since slice = job
450 #so we must delete and create another job
451 self.UpdateSlice(pointer, slab_record)
453 elif old_sfa_record_type == "user":
455 all_fields = new_sfa_record
456 for key in all_fields.keys():
457 if key in ['first_name', 'last_name', 'title', 'email',
458 'password', 'phone', 'url', 'bio', 'accepted_aup',
460 update_fields[key] = all_fields[key]
461 self.UpdatePerson(pointer, update_fields)
464 # must check this key against the previous one if it exists
465 persons = self.GetPersons([pointer], ['key_ids'])
467 keys = person['key_ids']
468 keys = self.GetKeys(person['key_ids'])
470 # Delete all stale keys
473 if new_key != key['key']:
474 self.DeleteKey(key['key_id'])
478 self.AddPersonKey(pointer, {'key_type': 'ssh', \
485 def remove (self, sfa_record):
486 sfa_record_type = sfa_record['type']
487 hrn = sfa_record['hrn']
488 if sfa_record_type == 'user':
490 #get user from senslab ldap
491 person = self.GetPersons(sfa_record)
492 #No registering at a given site in Senslab.
493 #Once registered to the LDAP, all senslab sites are
496 #Mark account as disabled in ldap
497 self.DeletePerson(sfa_record)
498 elif sfa_record_type == 'slice':
499 if self.GetSlices(slice_filter = hrn, \
500 slice_filter_type = 'slice_hrn'):
501 self.DeleteSlice(sfa_record)
503 #elif type == 'authority':
504 #if self.GetSites(pointer):
505 #self.DeleteSite(pointer)
511 #TODO clean GetPeers. 05/07/12SA
512 def GetPeers (self, auth = None, peer_filter=None, return_fields_list=None):
514 existing_records = {}
515 existing_hrns_by_types = {}
516 logger.debug("SLABDRIVER \tGetPeers auth = %s, peer_filter %s, \
517 return_field %s " %(auth , peer_filter, return_fields_list))
518 all_records = dbsession.query(RegRecord).filter(RegRecord.type.like('%authority%')).all()
520 for record in all_records:
521 existing_records[(record.hrn, record.type)] = record
522 if record.type not in existing_hrns_by_types:
523 existing_hrns_by_types[record.type] = [record.hrn]
525 existing_hrns_by_types[record.type].append(record.hrn)
528 logger.debug("SLABDRIVER \tGetPeer\texisting_hrns_by_types %s "\
529 %( existing_hrns_by_types))
534 records_list.append(existing_records[(peer_filter,'authority')])
536 for hrn in existing_hrns_by_types['authority']:
537 records_list.append(existing_records[(hrn,'authority')])
539 logger.debug("SLABDRIVER \tGetPeer \trecords_list %s " \
545 return_records = records_list
546 if not peer_filter and not return_fields_list:
550 logger.debug("SLABDRIVER \tGetPeer return_records %s " \
552 return return_records
555 #TODO : Handling OR request in make_ldap_filters_from_records
556 #instead of the for loop
557 #over the records' list
558 def GetPersons(self, person_filter=None):
560 person_filter should be a list of dictionnaries when not set to None.
561 Returns a list of users whose accounts are enabled found in ldap.
564 logger.debug("SLABDRIVER \tGetPersons person_filter %s" \
567 if person_filter and isinstance(person_filter, list):
568 #If we are looking for a list of users (list of dict records)
569 #Usually the list contains only one user record
570 for searched_attributes in person_filter:
572 #Get only enabled user accounts in senslab LDAP :
573 #add a filter for make_ldap_filters_from_record
574 person = self.ldap.LdapFindUser(searched_attributes, \
575 is_user_enabled=True)
576 #If a person was found, append it to the list
578 person_list.append(person)
580 #If the list is empty, return None
581 if len(person_list) is 0:
585 #Get only enabled user accounts in senslab LDAP :
586 #add a filter for make_ldap_filters_from_record
587 person_list = self.ldap.LdapFindUser(is_user_enabled=True)
591 def GetTimezone(self):
592 """ Get the OAR servier time and timezone.
593 Unused SA 16/11/12"""
594 server_timestamp, server_tz = self.oar.parser.\
595 SendRequest("GET_timezone")
596 return server_timestamp, server_tz
599 def DeleteJobs(self, job_id, slice_hrn):
600 if not job_id or job_id is -1:
602 username = slice_hrn.split(".")[-1].rstrip("_slice")
604 reqdict['method'] = "delete"
605 reqdict['strval'] = str(job_id)
608 answer = self.oar.POSTRequestToOARRestAPI('DELETE_jobs_id', \
610 logger.debug("SLABDRIVER \tDeleteJobs jobid %s \r\n answer %s \
611 username %s" %(job_id,answer, username))
616 ##TODO : Unused GetJobsId ? SA 05/07/12
617 #def GetJobsId(self, job_id, username = None ):
619 #Details about a specific job.
620 #Includes details about submission time, jot type, state, events,
621 #owner, assigned ressources, walltime etc...
625 #node_list_k = 'assigned_network_address'
626 ##Get job info from OAR
627 #job_info = self.oar.parser.SendRequest(req, job_id, username)
629 #logger.debug("SLABDRIVER \t GetJobsId %s " %(job_info))
631 #if job_info['state'] == 'Terminated':
632 #logger.debug("SLABDRIVER \t GetJobsId job %s TERMINATED"\
635 #if job_info['state'] == 'Error':
636 #logger.debug("SLABDRIVER \t GetJobsId ERROR message %s "\
641 #logger.error("SLABDRIVER \tGetJobsId KeyError")
644 #parsed_job_info = self.get_info_on_reserved_nodes(job_info, \
646 ##Replaces the previous entry
647 ##"assigned_network_address" / "reserved_resources"
649 #job_info.update({'node_ids':parsed_job_info[node_list_k]})
650 #del job_info[node_list_k]
651 #logger.debug(" \r\nSLABDRIVER \t GetJobsId job_info %s " %(job_info))
655 def GetJobsResources(self, job_id, username = None):
656 #job_resources=['reserved_resources', 'assigned_resources',\
657 #'job_id', 'job_uri', 'assigned_nodes',\
659 #assigned_res = ['resource_id', 'resource_uri']
660 #assigned_n = ['node', 'node_uri']
662 req = "GET_jobs_id_resources"
665 #Get job resources list from OAR
666 node_id_list = self.oar.parser.SendRequest(req, job_id, username)
667 logger.debug("SLABDRIVER \t GetJobsResources %s " %(node_id_list))
670 self.__get_hostnames_from_oar_node_ids(node_id_list)
673 #Replaces the previous entry "assigned_network_address" /
674 #"reserved_resources"
676 job_info = {'node_ids': hostname_list}
681 def get_info_on_reserved_nodes(self, job_info, node_list_name):
682 #Get the list of the testbed nodes records and make a
683 #dictionnary keyed on the hostname out of it
684 node_list_dict = self.GetNodes()
685 #node_hostname_list = []
686 node_hostname_list = [node['hostname'] for node in node_list_dict]
687 #for node in node_list_dict:
688 #node_hostname_list.append(node['hostname'])
689 node_dict = dict(zip(node_hostname_list, node_list_dict))
691 reserved_node_hostname_list = []
692 for index in range(len(job_info[node_list_name])):
693 #job_info[node_list_name][k] =
694 reserved_node_hostname_list[index] = \
695 node_dict[job_info[node_list_name][index]]['hostname']
697 logger.debug("SLABDRIVER \t get_info_on_reserved_nodes \
698 reserved_node_hostname_list %s" \
699 %(reserved_node_hostname_list))
701 logger.error("SLABDRIVER \t get_info_on_reserved_nodes KEYERROR " )
703 return reserved_node_hostname_list
705 def GetNodesCurrentlyInUse(self):
706 """Returns a list of all the nodes already involved in an oar job"""
707 return self.oar.parser.SendRequest("GET_running_jobs")
709 def __get_hostnames_from_oar_node_ids(self, resource_id_list ):
710 full_nodes_dict_list = self.GetNodes()
711 #Put the full node list into a dictionary keyed by oar node id
712 oar_id_node_dict = {}
713 for node in full_nodes_dict_list:
714 oar_id_node_dict[node['oar_id']] = node
716 #logger.debug("SLABDRIVER \t __get_hostnames_from_oar_node_ids\
717 #oar_id_node_dict %s" %(oar_id_node_dict))
719 hostname_dict_list = []
720 for resource_id in resource_id_list:
721 #Because jobs requested "asap" do not have defined resources
722 if resource_id is not "Undefined":
723 hostname_dict_list.append(\
724 oar_id_node_dict[resource_id]['hostname'])
726 #hostname_list.append(oar_id_node_dict[resource_id]['hostname'])
727 return hostname_dict_list
729 def GetReservedNodes(self,username = None):
730 #Get the nodes in use and the reserved nodes
731 reservation_dict_list = \
732 self.oar.parser.SendRequest("GET_reserved_nodes", \
736 for resa in reservation_dict_list:
737 logger.debug ("GetReservedNodes resa %s"%(resa))
738 #dict list of hostnames and their site
739 resa['reserved_nodes'] = \
740 self.__get_hostnames_from_oar_node_ids(resa['resource_ids'])
742 #del resa['resource_ids']
743 return reservation_dict_list
745 def GetNodes(self, node_filter_dict = None, return_fields_list = None):
747 node_filter_dict : dictionnary of lists
750 node_dict_by_id = self.oar.parser.SendRequest("GET_resources_full")
751 node_dict_list = node_dict_by_id.values()
752 logger.debug (" SLABDRIVER GetNodes node_filter_dict %s \
753 return_fields_list %s "%(node_filter_dict, return_fields_list))
754 #No filtering needed return the list directly
755 if not (node_filter_dict or return_fields_list):
756 return node_dict_list
758 return_node_list = []
760 for filter_key in node_filter_dict:
762 #Filter the node_dict_list by each value contained in the
763 #list node_filter_dict[filter_key]
764 for value in node_filter_dict[filter_key]:
765 for node in node_dict_list:
766 if node[filter_key] == value:
767 if return_fields_list :
769 for k in return_fields_list:
771 return_node_list.append(tmp)
773 return_node_list.append(node)
775 logger.log_exc("GetNodes KeyError")
779 return return_node_list
782 def GetSites(self, site_filter_name_list = None, return_fields_list = None):
783 site_dict = self.oar.parser.SendRequest("GET_sites")
784 #site_dict : dict where the key is the sit ename
785 return_site_list = []
786 if not ( site_filter_name_list or return_fields_list):
787 return_site_list = site_dict.values()
788 return return_site_list
790 for site_filter_name in site_filter_name_list:
791 if site_filter_name in site_dict:
792 if return_fields_list:
793 for field in return_fields_list:
796 tmp[field] = site_dict[site_filter_name][field]
798 logger.error("GetSites KeyError %s "%(field))
800 return_site_list.append(tmp)
802 return_site_list.append( site_dict[site_filter_name])
805 return return_site_list
809 def GetSlices(self, slice_filter = None, slice_filter_type = None):
810 """ Get the slice records from the slab db.
811 Returns a slice ditc if slice_filter and slice_filter_type
813 Returns a list of slice dictionnaries if there are no filters
818 authorized_filter_types_list = ['slice_hrn', 'record_id_user']
819 return_slicerec_dictlist = []
821 #First try to get information on the slice based on the filter provided
822 if slice_filter_type in authorized_filter_types_list:
825 def __get_slice_records(slice_filter = None, \
826 slice_filter_type = None):
829 #Get list of slices based on the slice hrn
830 if slice_filter_type == 'slice_hrn':
832 login = slice_filter.split(".")[1].split("_")[0]
834 #DO NOT USE RegSlice - reg_researchers to get the hrn
835 #of the user otherwise will mess up the RegRecord in
836 #Resolve, don't know why - SA 08/08/2012
838 #Only one entry for one user = one slice in slice_senslab table
839 slicerec = slab_dbsession.query(SliceSenslab).filter_by(slice_hrn = slice_filter).first()
844 #Get slice based on user id
845 if slice_filter_type == 'record_id_user':
846 slicerec = slab_dbsession.query(SliceSenslab).filter_by(record_id_user = slice_filter).first()
850 fixed_slicerec_dict = slicerec.dump_sqlalchemyobj_to_dict()
851 #At this point if the there is no login it means
852 #record_id_user filter has been used for filtering
854 login = fixed_slicerec_dict['slice_hrn'].split(".")[1].split("_")[0]
855 return login, fixed_slicerec_dict
859 login, fixed_slicerec_dict = \
860 __get_slice_records(slice_filter, slice_filter_type)
861 logger.debug(" SLABDRIVER \tGetSlices login %s \
862 slice record %s slice_filter %s"\
863 %(login, fixed_slicerec_dict,slice_filter))
866 #Now we have the slice record fixed_slicerec_dict, get the
867 #jobs associated to this slice
868 leases_list = self.GetReservedNodes(username = login)
870 #If no job is running or no job scheduled
871 #return only the slice record
872 if leases_list == [] and fixed_slicerec_dict:
873 return_slicerec_dictlist.append(fixed_slicerec_dict)
875 #If several jobs for one slice , put the slice record into
876 # each lease information dict
877 for lease in leases_list :
880 reserved_list = lease['reserved_nodes']
882 slicerec_dict['oar_job_id'] = lease['lease_id']
883 slicerec_dict.update({'list_node_ids':{'hostname':reserved_list}})
884 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
885 #Update lease dict with the slice record
886 if fixed_slicerec_dict:
887 slicerec_dict.update(fixed_slicerec_dict)
888 slicerec_dict.update({'hrn':\
889 str(fixed_slicerec_dict['slice_hrn'])})
892 return_slicerec_dictlist.append(slicerec_dict)
893 logger.debug("SLABDRIVER.PY \tGetSlices \
894 slicerec_dict %s return_slicerec_dictlist %s \
895 lease['reserved_nodes'] \
896 %s" %(slicerec_dict, return_slicerec_dictlist, \
897 lease['reserved_nodes'] ))
899 logger.debug("SLABDRIVER.PY \tGetSlices RETURN \
900 return_slicerec_dictlist %s" \
901 %(return_slicerec_dictlist))
903 return return_slicerec_dictlist
907 #Get all slices from the senslab sfa database ,
908 #put them in dict format
909 query_slice_list = slab_dbsession.query(SliceSenslab).all()
910 return_slicerec_dictlist = []
911 for record in query_slice_list:
912 return_slicerec_dictlist.append(record.dump_sqlalchemyobj_to_dict())
914 #Get all the jobs reserved nodes
915 leases_list = self.GetReservedNodes()
918 for fixed_slicerec_dict in return_slicerec_dictlist:
920 owner = fixed_slicerec_dict['slice_hrn'].split(".")[1].split("_")[0]
921 for lease in leases_list:
922 if owner == lease['user']:
923 slicerec_dict['oar_job_id'] = lease['lease_id']
925 #for reserved_node in lease['reserved_nodes']:
926 logger.debug("SLABDRIVER.PY \tGetSlices lease %s "\
929 reserved_list = lease['reserved_nodes']
931 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
932 slicerec_dict.update({'list_node_ids':{'hostname':reserved_list}})
933 slicerec_dict.update(fixed_slicerec_dict)
934 slicerec_dict.update({'hrn':\
935 str(fixed_slicerec_dict['slice_hrn'])})
936 #return_slicerec_dictlist.append(slicerec_dict)
937 fixed_slicerec_dict.update(slicerec_dict)
939 logger.debug("SLABDRIVER.PY \tGetSlices RETURN \
940 return_slicerec_dictlist %s \slice_filter %s " \
941 %(return_slicerec_dictlist, slice_filter))
943 return return_slicerec_dictlist
946 def testbed_name (self): return self.hrn
948 # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
949 def aggregate_version (self):
950 version_manager = VersionManager()
951 ad_rspec_versions = []
952 request_rspec_versions = []
953 for rspec_version in version_manager.versions:
954 if rspec_version.content_type in ['*', 'ad']:
955 ad_rspec_versions.append(rspec_version.to_dict())
956 if rspec_version.content_type in ['*', 'request']:
957 request_rspec_versions.append(rspec_version.to_dict())
959 'testbed':self.testbed_name(),
960 'geni_request_rspec_versions': request_rspec_versions,
961 'geni_ad_rspec_versions': ad_rspec_versions,
967 # Convert SFA fields to PLC fields for use when registering up updating
968 # registry record in the PLC database
970 # @param type type of record (user, slice, ...)
971 # @param hrn human readable name
972 # @param sfa_fields dictionary of SFA fields
973 # @param slab_fields dictionary of PLC fields (output)
975 def sfa_fields_to_slab_fields(self, sfa_type, hrn, record):
979 #for field in record:
980 # slab_record[field] = record[field]
982 if sfa_type == "slice":
983 #instantion used in get_slivers ?
984 if not "instantiation" in slab_record:
985 slab_record["instantiation"] = "senslab-instantiated"
986 #slab_record["hrn"] = hrn_to_pl_slicename(hrn)
987 #Unused hrn_to_pl_slicename because Slab's hrn already
988 #in the appropriate form SA 23/07/12
989 slab_record["hrn"] = hrn
990 logger.debug("SLABDRIVER.PY sfa_fields_to_slab_fields \
991 slab_record %s " %(slab_record['hrn']))
993 slab_record["url"] = record["url"]
994 if "description" in record:
995 slab_record["description"] = record["description"]
996 if "expires" in record:
997 slab_record["expires"] = int(record["expires"])
999 #nodes added by OAR only and then imported to SFA
1000 #elif type == "node":
1001 #if not "hostname" in slab_record:
1002 #if not "hostname" in record:
1003 #raise MissingSfaInfo("hostname")
1004 #slab_record["hostname"] = record["hostname"]
1005 #if not "model" in slab_record:
1006 #slab_record["model"] = "geni"
1009 #elif type == "authority":
1010 #slab_record["login_base"] = hrn_to_slab_login_base(hrn)
1012 #if not "name" in slab_record:
1013 #slab_record["name"] = hrn
1015 #if not "abbreviated_name" in slab_record:
1016 #slab_record["abbreviated_name"] = hrn
1018 #if not "enabled" in slab_record:
1019 #slab_record["enabled"] = True
1021 #if not "is_public" in slab_record:
1022 #slab_record["is_public"] = True
1029 def __transforms_timestamp_into_date(self, xp_utc_timestamp = None):
1030 """ Transforms unix timestamp into valid OAR date format """
1032 #Used in case of a scheduled experiment (not immediate)
1033 #To run an XP immediately, don't specify date and time in RSpec
1034 #They will be set to None.
1035 if xp_utc_timestamp:
1036 #transform the xp_utc_timestamp into server readable time
1037 xp_server_readable_date = datetime.fromtimestamp(int(\
1038 xp_utc_timestamp)).strftime(self.time_format)
1040 return xp_server_readable_date
1048 def LaunchExperimentOnOAR(self, added_nodes, slice_name, \
1049 lease_start_time, lease_duration, slice_user=None):
1051 lease_dict['lease_start_time'] = lease_start_time
1052 lease_dict['lease_duration'] = lease_duration
1053 lease_dict['added_nodes'] = added_nodes
1054 lease_dict['slice_name'] = slice_name
1055 lease_dict['slice_user'] = slice_user
1056 lease_dict['grain'] = self.GetLeaseGranularity()
1057 lease_dict['time_format'] = self.time_format
1059 def __create_job_structure_request_for_OAR(lease_dict):
1060 """ Creates the structure needed for a correct POST on OAR.
1061 Makes the timestamp transformation into the appropriate format.
1062 Sends the POST request to create the job with the resources in
1071 reqdict['workdir'] = '/tmp'
1072 reqdict['resource'] = "{network_address in ("
1074 for node in lease_dict['added_nodes']:
1075 logger.debug("\r\n \r\n OARrestapi \t \
1076 __create_job_structure_request_for_OAR node %s" %(node))
1078 # Get the ID of the node
1080 reqdict['resource'] += "'" + nodeid + "', "
1081 nodeid_list.append(nodeid)
1083 custom_length = len(reqdict['resource'])- 2
1084 reqdict['resource'] = reqdict['resource'][0:custom_length] + \
1085 ")}/nodes=" + str(len(nodeid_list))
1087 def __process_walltime(duration):
1088 """ Calculates the walltime in seconds from the duration in H:M:S
1089 specified in the RSpec.
1093 # Fixing the walltime by adding a few delays.
1094 # First put the walltime in seconds oarAdditionalDelay = 20;
1095 # additional delay for /bin/sleep command to
1096 # take in account prologue and epilogue scripts execution
1097 # int walltimeAdditionalDelay = 240; additional delay
1098 desired_walltime = duration
1099 total_walltime = desired_walltime + 240 #+4 min Update SA 23/10/12
1100 sleep_walltime = desired_walltime # 0 sec added Update SA 23/10/12
1102 #Put the walltime back in str form
1103 #First get the hours
1104 walltime.append(str(total_walltime / 3600))
1105 total_walltime = total_walltime - 3600 * int(walltime[0])
1106 #Get the remaining minutes
1107 walltime.append(str(total_walltime / 60))
1108 total_walltime = total_walltime - 60 * int(walltime[1])
1110 walltime.append(str(total_walltime))
1113 logger.log_exc(" __process_walltime duration null")
1115 return walltime, sleep_walltime
1118 walltime, sleep_walltime = \
1119 __process_walltime(int(lease_dict['lease_duration'])*lease_dict['grain'])
1122 reqdict['resource'] += ",walltime=" + str(walltime[0]) + \
1123 ":" + str(walltime[1]) + ":" + str(walltime[2])
1124 reqdict['script_path'] = "/bin/sleep " + str(sleep_walltime)
1126 #In case of a scheduled experiment (not immediate)
1127 #To run an XP immediately, don't specify date and time in RSpec
1128 #They will be set to None.
1129 if lease_dict['lease_start_time'] is not '0':
1130 #Readable time accepted by OAR
1131 start_time = datetime.fromtimestamp(int(lease_dict['lease_start_time'])).\
1132 strftime(lease_dict['time_format'])
1133 reqdict['reservation'] = start_time
1134 #If there is not start time, Immediate XP. No need to add special
1138 reqdict['type'] = "deploy"
1139 reqdict['directory'] = ""
1140 reqdict['name'] = "SFA_" + lease_dict['slice_user']
1145 #Create the request for OAR
1146 reqdict = __create_job_structure_request_for_OAR(lease_dict)
1147 # first step : start the OAR job and update the job
1148 logger.debug("SLABDRIVER.PY \tLaunchExperimentOnOAR reqdict %s\
1151 answer = self.oar.POSTRequestToOARRestAPI('POST_job', \
1152 reqdict, slice_user)
1153 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s " %(answer))
1155 jobid = answer['id']
1157 logger.log_exc("SLABDRIVER \tLaunchExperimentOnOAR \
1158 Impossible to create job %s " %(answer))
1162 def __configure_experiment(jobid, added_nodes):
1163 # second step : configure the experiment
1164 # we need to store the nodes in a yaml (well...) file like this :
1165 # [1,56,23,14,45,75] with name /tmp/sfa<jobid>.json
1166 job_file = open('/tmp/sfa/'+ str(jobid) + '.json', 'w')
1168 job_file.write(str(added_nodes[0].strip('node')))
1169 for node in added_nodes[1:len(added_nodes)] :
1170 job_file.write(', '+ node.strip('node'))
1175 def __launch_senslab_experiment(jobid):
1176 # third step : call the senslab-experiment wrapper
1177 #command= "java -jar target/sfa-1.0-jar-with-dependencies.jar
1178 # "+str(jobid)+" "+slice_user
1179 javacmdline = "/usr/bin/java"
1181 "/opt/senslabexperimentwrapper/sfa-1.0-jar-with-dependencies.jar"
1183 output = subprocess.Popen([javacmdline, "-jar", jarname, str(jobid), \
1184 slice_user],stdout=subprocess.PIPE).communicate()[0]
1186 logger.debug("SLABDRIVER \t __configure_experiment wrapper returns%s " \
1193 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s \
1194 added_nodes %s slice_user %s" %(jobid, added_nodes, slice_user))
1197 __configure_experiment(jobid, added_nodes)
1198 __launch_senslab_experiment(jobid)
1202 def AddLeases(self, hostname_list, slice_record, \
1203 lease_start_time, lease_duration):
1204 logger.debug("SLABDRIVER \r\n \r\n \t AddLeases hostname_list %s \
1205 slice_record %s lease_start_time %s lease_duration %s "\
1206 %( hostname_list, slice_record , lease_start_time, \
1209 tmp = slice_record['reg-researchers'][0].split(".")
1210 username = tmp[(len(tmp)-1)]
1211 self.LaunchExperimentOnOAR(hostname_list, slice_record['slice_hrn'], \
1212 lease_start_time, lease_duration, username)
1213 start_time = datetime.fromtimestamp(int(lease_start_time)).strftime(self.time_format)
1214 logger.debug("SLABDRIVER \t AddLeases hostname_list start_time %s " %(start_time))
1219 #Delete the jobs from job_senslab table
1220 def DeleteSliceFromNodes(self, slice_record):
1222 self.DeleteJobs(slice_record['oar_job_id'], slice_record['hrn'])
1226 def GetLeaseGranularity(self):
1227 """ Returns the granularity of Senslab testbed.
1228 OAR returns seconds for experiments duration.
1229 Defined in seconds. """
1234 def GetLeases(self, lease_filter_dict=None):
1237 unfiltered_reservation_list = self.GetReservedNodes()
1239 reservation_list = []
1240 #Find the slice associated with this user senslab ldap uid
1241 logger.debug(" SLABDRIVER.PY \tGetLeases unfiltered_reservation_list %s " %(unfiltered_reservation_list))
1242 #Create user dict first to avoid looking several times for
1243 #the same user in LDAP SA 27/07/12
1245 for resa in unfiltered_reservation_list:
1246 logger.debug("SLABDRIVER \tGetLeases USER %s"\
1248 if resa['user'] not in resa_user_dict:
1249 logger.debug("SLABDRIVER \tGetLeases userNOTIN ")
1250 ldap_info = self.ldap.LdapSearch('(uid='+resa['user']+')')
1252 ldap_info = ldap_info[0][1]
1253 user = dbsession.query(RegUser).filter_by(email = \
1254 ldap_info['mail'][0]).first()
1255 #Separated in case user not in database :
1256 #record_id not defined SA 17/07//12
1257 query_slice_info = slab_dbsession.query(SliceSenslab).filter_by(record_id_user = user.record_id)
1258 if query_slice_info:
1259 slice_info = query_slice_info.first()
1263 resa_user_dict[resa['user']] = {}
1264 resa_user_dict[resa['user']]['ldap_info'] = user
1265 resa_user_dict[resa['user']]['slice_info'] = slice_info
1267 #del unfiltered_reservation_list[unfiltered_reservation_list.index(resa)]
1271 logger.debug("SLABDRIVER \tGetLeases resa_user_dict %s"\
1273 for resa in unfiltered_reservation_list:
1277 if resa['user'] in resa_user_dict:
1278 resa['slice_hrn'] = resa_user_dict[resa['user']]['slice_info'].slice_hrn
1279 resa['slice_id'] = hrn_to_urn(resa['slice_hrn'], 'slice')
1281 #resa['slice_id'] = hrn_to_urn(slice_info.slice_hrn, 'slice')
1282 resa['component_id_list'] = []
1283 #Transform the hostnames into urns (component ids)
1284 for node in resa['reserved_nodes']:
1285 #resa['component_id_list'].append(hostname_to_urn(self.hrn, \
1286 #self.root_auth, node['hostname']))
1287 slab_xrn = slab_xrn_object(self.root_auth, node)
1288 resa['component_id_list'].append(slab_xrn.urn)
1290 #Filter the reservation list if necessary
1291 #Returns all the leases associated with a given slice
1292 if lease_filter_dict:
1293 logger.debug("SLABDRIVER \tGetLeases lease_filter_dict %s"\
1294 %(lease_filter_dict))
1295 for resa in unfiltered_reservation_list:
1296 if lease_filter_dict['name'] == resa['slice_hrn']:
1297 reservation_list.append(resa)
1299 reservation_list = unfiltered_reservation_list
1301 logger.debug(" SLABDRIVER.PY \tGetLeases reservation_list %s"\
1302 %(reservation_list))
1303 return reservation_list
1305 def augment_records_with_testbed_info (self, sfa_records):
1306 return self.fill_record_info (sfa_records)
1308 def fill_record_info(self, record_list):
1310 Given a SFA record, fill in the senslab specific and SFA specific
1311 fields in the record.
1314 logger.debug("SLABDRIVER \tfill_record_info records %s " %(record_list))
1315 if not isinstance(record_list, list):
1316 record_list = [record_list]
1319 for record in record_list:
1320 #If the record is a SFA slice record, then add information
1321 #about the user of this slice. This kind of
1322 #information is in the Senslab's DB.
1323 if str(record['type']) == 'slice':
1324 #Get slab slice record.
1325 recslice_list = self.GetSlices(slice_filter = \
1326 str(record['hrn']),\
1327 slice_filter_type = 'slice_hrn')
1329 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1330 recslice_list[0]['record_id_user']).first()
1331 logger.debug("SLABDRIVER \tfill_record_info TYPE SLICE RECUSER %s " %(recuser))
1332 record.update({'PI':[recuser.hrn],
1333 'researcher': [recuser.hrn],
1334 'name':record['hrn'],
1337 'person_ids':[recslice_list[0]['record_id_user']],
1338 'geni_urn':'', #For client_helper.py compatibility
1339 'keys':'', #For client_helper.py compatibility
1340 'key_ids':''}) #For client_helper.py compatibility
1343 for rec in recslice_list:
1344 record['oar_job_id'].append(rec['oar_job_id'])
1345 record['node_ids'] = [ self.root_auth + hostname for hostname in rec['node_ids']]
1349 logger.debug( "SLABDRIVER.PY \t fill_record_info SLICE \
1350 recslice_list %s \r\n \t RECORD %s \r\n \r\n" %(recslice_list,record))
1351 if str(record['type']) == 'user':
1352 #The record is a SFA user record.
1353 #Get the information about his slice from Senslab's DB
1354 #and add it to the user record.
1355 recslice_list = self.GetSlices(\
1356 slice_filter = record['record_id'],\
1357 slice_filter_type = 'record_id_user')
1359 logger.debug( "SLABDRIVER.PY \t fill_record_info TYPE USER \
1360 recslice_list %s \r\n \t RECORD %s \r\n" %(recslice_list , record))
1361 #Append slice record in records list,
1362 #therefore fetches user and slice info again(one more loop)
1363 #Will update PIs and researcher for the slice
1364 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1365 recslice_list[0]['record_id_user']).first()
1366 logger.debug( "SLABDRIVER.PY \t fill_record_info USER \
1367 recuser %s \r\n \r\n" %(recuser))
1369 recslice = recslice_list[0]
1370 recslice.update({'PI':[recuser.hrn],
1371 'researcher': [recuser.hrn],
1372 'name':record['hrn'],
1375 'person_ids':[recslice_list[0]['record_id_user']]})
1377 for rec in recslice_list:
1378 recslice['oar_job_id'].append(rec['oar_job_id'])
1382 recslice.update({'type':'slice', \
1383 'hrn':recslice_list[0]['slice_hrn']})
1386 #GetPersons takes [] as filters
1387 #user_slab = self.GetPersons([{'hrn':recuser.hrn}])
1388 user_slab = self.GetPersons([record])
1391 record.update(user_slab[0])
1392 #For client_helper.py compatibility
1393 record.update( { 'geni_urn':'',
1396 record_list.append(recslice)
1398 logger.debug("SLABDRIVER.PY \tfill_record_info ADDING SLICE\
1399 INFO TO USER records %s" %(record_list))
1400 logger.debug("SLABDRIVER.PY \tfill_record_info END \
1401 #record %s \r\n \r\n " %(record))
1403 except TypeError, error:
1404 logger.log_exc("SLABDRIVER \t fill_record_info EXCEPTION %s"\
1406 #logger.debug("SLABDRIVER.PY \t fill_record_info ENDENDEND ")
1410 #self.fill_record_slab_info(records)
1416 #TODO Update membership? update_membership_list SA 05/07/12
1417 #def update_membership_list(self, oldRecord, record, listName, addFunc, \
1419 ## get a list of the HRNs tht are members of the old and new records
1421 #oldList = oldRecord.get(listName, [])
1424 #newList = record.get(listName, [])
1426 ## if the lists are the same, then we don't have to update anything
1427 #if (oldList == newList):
1430 ## build a list of the new person ids, by looking up each person to get
1434 #records = table.find({'type': 'user', 'hrn': newList})
1435 #for rec in records:
1436 #newIdList.append(rec['pointer'])
1438 ## build a list of the old person ids from the person_ids field
1440 #oldIdList = oldRecord.get("person_ids", [])
1441 #containerId = oldRecord.get_pointer()
1443 ## if oldRecord==None, then we are doing a Register, instead of an
1446 #containerId = record.get_pointer()
1448 ## add people who are in the new list, but not the oldList
1449 #for personId in newIdList:
1450 #if not (personId in oldIdList):
1451 #addFunc(self.plauth, personId, containerId)
1453 ## remove people who are in the old list, but not the new list
1454 #for personId in oldIdList:
1455 #if not (personId in newIdList):
1456 #delFunc(self.plauth, personId, containerId)
1458 #def update_membership(self, oldRecord, record):
1460 #if record.type == "slice":
1461 #self.update_membership_list(oldRecord, record, 'researcher',
1462 #self.users.AddPersonToSlice,
1463 #self.users.DeletePersonFromSlice)
1464 #elif record.type == "authority":
1469 # I don't think you plan on running a component manager at this point
1470 # let me clean up the mess of ComponentAPI that is deprecated anyways
1473 #TODO FUNCTIONS SECTION 04/07/2012 SA
1475 #TODO : Is UnBindObjectFromPeer still necessary ? Currently does nothing
1477 def UnBindObjectFromPeer(self, auth, object_type, object_id, shortname):
1478 """ This method is a hopefully temporary hack to let the sfa correctly
1479 detach the objects it creates from a remote peer object. This is
1480 needed so that the sfa federation link can work in parallel with
1481 RefreshPeer, as RefreshPeer depends on remote objects being correctly
1484 auth : struct, API authentication structure
1485 AuthMethod : string, Authentication method to use
1486 object_type : string, Object type, among 'site','person','slice',
1488 object_id : int, object_id
1489 shortname : string, peer shortname
1493 logger.warning("SLABDRIVER \tUnBindObjectFromPeer EMPTY-\
1497 #TODO Is BindObjectToPeer still necessary ? Currently does nothing
1499 def BindObjectToPeer(self, auth, object_type, object_id, shortname=None, \
1500 remote_object_id=None):
1501 """This method is a hopefully temporary hack to let the sfa correctly
1502 attach the objects it creates to a remote peer object. This is needed
1503 so that the sfa federation link can work in parallel with RefreshPeer,
1504 as RefreshPeer depends on remote objects being correctly marked.
1506 shortname : string, peer shortname
1507 remote_object_id : int, remote object_id, set to 0 if unknown
1511 logger.warning("SLABDRIVER \tBindObjectToPeer EMPTY - DO NOTHING \r\n ")
1514 #TODO UpdateSlice 04/07/2012 SA
1515 #Funciton should delete and create another job since oin senslab slice=job
1516 def UpdateSlice(self, auth, slice_id_or_name, slice_fields=None):
1517 """Updates the parameters of an existing slice with the values in
1519 Users may only update slices of which they are members.
1520 PIs may update any of the slices at their sites, or any slices of
1521 which they are members. Admins may update any slice.
1522 Only PIs and admins may update max_nodes. Slices cannot be renewed
1523 (by updating the expires parameter) more than 8 weeks into the future.
1524 Returns 1 if successful, faults otherwise.
1528 logger.warning("SLABDRIVER UpdateSlice EMPTY - DO NOTHING \r\n ")
1531 #TODO UpdatePerson 04/07/2012 SA
1532 def UpdatePerson(self, auth, person_id_or_email, person_fields=None):
1533 """Updates a person. Only the fields specified in person_fields
1534 are updated, all other fields are left untouched.
1535 Users and techs can only update themselves. PIs can only update
1536 themselves and other non-PIs at their sites.
1537 Returns 1 if successful, faults otherwise.
1541 logger.warning("SLABDRIVER UpdatePerson EMPTY - DO NOTHING \r\n ")
1544 #TODO GetKeys 04/07/2012 SA
1545 def GetKeys(self, auth, key_filter=None, return_fields=None):
1546 """Returns an array of structs containing details about keys.
1547 If key_filter is specified and is an array of key identifiers,
1548 or a struct of key attributes, only keys matching the filter
1549 will be returned. If return_fields is specified, only the
1550 specified details will be returned.
1552 Admin may query all keys. Non-admins may only query their own keys.
1556 logger.warning("SLABDRIVER GetKeys EMPTY - DO NOTHING \r\n ")
1559 #TODO DeleteKey 04/07/2012 SA
1560 def DeleteKey(self, auth, key_id):
1562 Non-admins may only delete their own keys.
1563 Returns 1 if successful, faults otherwise.
1567 logger.warning("SLABDRIVER DeleteKey EMPTY - DO NOTHING \r\n ")
1571 #TODO : Check rights to delete person
1572 def DeletePerson(self, auth, person_record):
1573 """ Disable an existing account in senslab LDAP.
1574 Users and techs can only delete themselves. PIs can only
1575 delete themselves and other non-PIs at their sites.
1576 ins can delete anyone.
1577 Returns 1 if successful, faults otherwise.
1581 #Disable user account in senslab LDAP
1582 ret = self.ldap.LdapMarkUserAsDeleted(person_record)
1583 logger.warning("SLABDRIVER DeletePerson %s " %(person_record))
1586 #TODO Check DeleteSlice, check rights 05/07/2012 SA
1587 def DeleteSlice(self, auth, slice_record):
1588 """ Deletes the specified slice.
1589 Senslab : Kill the job associated with the slice if there is one
1590 using DeleteSliceFromNodes.
1591 Updates the slice record in slab db to remove the slice nodes.
1593 Users may only delete slices of which they are members. PIs may
1594 delete any of the slices at their sites, or any slices of which
1595 they are members. Admins may delete any slice.
1596 Returns 1 if successful, faults otherwise.
1600 self.DeleteSliceFromNodes(slice_record)
1601 logger.warning("SLABDRIVER DeleteSlice %s "%(slice_record))
1604 #TODO AddPerson 04/07/2012 SA
1605 #def AddPerson(self, auth, person_fields=None):
1606 def AddPerson(self, record):#TODO fixing 28/08//2012 SA
1607 """Adds a new account. Any fields specified in records are used,
1608 otherwise defaults are used.
1609 Accounts are disabled by default. To enable an account,
1611 Returns the new person_id (> 0) if successful, faults otherwise.
1615 ret = self.ldap.LdapAddUser(record)
1616 logger.warning("SLABDRIVER AddPerson return code %s \r\n ", ret)
1619 #TODO AddPersonToSite 04/07/2012 SA
1620 def AddPersonToSite (self, auth, person_id_or_email, \
1621 site_id_or_login_base=None):
1622 """ Adds the specified person to the specified site. If the person is
1623 already a member of the site, no errors are returned. Does not change
1624 the person's primary site.
1625 Returns 1 if successful, faults otherwise.
1629 logger.warning("SLABDRIVER AddPersonToSite EMPTY - DO NOTHING \r\n ")
1632 #TODO AddRoleToPerson : Not sure if needed in senslab 04/07/2012 SA
1633 def AddRoleToPerson(self, auth, role_id_or_name, person_id_or_email):
1634 """Grants the specified role to the person.
1635 PIs can only grant the tech and user roles to users and techs at their
1636 sites. Admins can grant any role to any user.
1637 Returns 1 if successful, faults otherwise.
1641 logger.warning("SLABDRIVER AddRoleToPerson EMPTY - DO NOTHING \r\n ")
1644 #TODO AddPersonKey 04/07/2012 SA
1645 def AddPersonKey(self, auth, person_id_or_email, key_fields=None):
1646 """Adds a new key to the specified account.
1647 Non-admins can only modify their own keys.
1648 Returns the new key_id (> 0) if successful, faults otherwise.
1652 logger.warning("SLABDRIVER AddPersonKey EMPTY - DO NOTHING \r\n ")
1655 def DeleteLeases(self, leases_id_list, slice_hrn ):
1656 for job_id in leases_id_list:
1657 self.DeleteJobs(job_id, slice_hrn)
1659 logger.debug("SLABDRIVER DeleteLeases leases_id_list %s slice_hrn %s \
1660 \r\n " %(leases_id_list, slice_hrn))