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 if nodeall_byhostname[node['hostname']]['boot_state'] == 'Alive':
147 res['geni_status'] = 'ready'
149 res['geni_status'] = 'failed'
150 top_level_status = 'failed'
152 res['geni_error'] = ''
154 resources.append(res)
156 result['geni_status'] = top_level_status
157 result['geni_resources'] = resources
158 logger.debug("SLABDRIVER \tsliver_statusresources %s res %s "\
162 def get_user(self, hrn):
163 return dbsession.query(RegRecord).filter_by(hrn = hrn).first()
166 def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, \
168 aggregate = SlabAggregate(self)
170 slices = SlabSlices(self)
171 peer = slices.get_peer(slice_hrn)
172 sfa_peer = slices.get_sfa_peer(slice_hrn)
175 if not isinstance(creds, list):
179 slice_record = users[0].get('slice_record', {})
180 logger.debug("SLABDRIVER.PY \t create_sliver \t\
181 slice_record %s \r\n \r\n users %s" \
182 %(slice_record, users))
183 slice_record['user'] = {'keys':users[0]['keys'], 'email':users[0]['email'], 'hrn':slice_record['reg-researchers'][0]}
185 rspec = RSpec(rspec_string)
186 logger.debug("SLABDRIVER.PY \t create_sliver \trspec.version \
187 %s slice_record %s users %s" \
188 %(rspec.version,slice_record, users))
191 # ensure site record exists?
192 # ensure slice record exists
193 #Removed options to verify_slice SA 14/08/12
194 sfa_slice = slices.verify_slice(slice_hrn, slice_record, peer, \
197 # ensure person records exists
198 #verify_persons returns added persons but since the return value
200 slices.verify_persons(slice_hrn, sfa_slice, users, peer, \
201 sfa_peer, options=options)
202 #requested_attributes returned by rspec.version.get_slice_attributes()
203 #unused, removed SA 13/08/12
204 rspec.version.get_slice_attributes()
206 logger.debug("SLABDRIVER.PY create_sliver slice %s " %(sfa_slice))
212 # add/remove slice from nodes
214 requested_slivers = [node.get('component_id') \
215 for node in rspec.version.get_nodes_with_slivers()\
216 if node.get('authority_id') is self.root_auth]
217 l = [ node for node in rspec.version.get_nodes_with_slivers() ]
218 logger.debug("SLADRIVER \tcreate_sliver requested_slivers \
219 requested_slivers %s listnodes %s" \
220 %(requested_slivers,l))
221 #verify_slice_nodes returns nodes, but unused here. Removed SA 13/08/12.
222 #slices.verify_slice_nodes(sfa_slice, requested_slivers, peer)
225 requested_lease_list = []
227 logger.debug("SLABDRIVER.PY \tcreate_sliver AVANTLEASE " )
228 rspec_requested_leases = rspec.version.get_leases()
229 for lease in rspec.version.get_leases():
230 single_requested_lease = {}
231 logger.debug("SLABDRIVER.PY \tcreate_sliver lease %s " %(lease))
232 if not lease.get('lease_id'):
233 if get_authority(lease['component_id']) == self.root_auth:
234 single_requested_lease['hostname'] = \
235 slab_xrn_to_hostname(\
236 lease.get('component_id').strip())
237 single_requested_lease['start_time'] = lease.get('start_time')
238 single_requested_lease['duration'] = lease.get('duration')
240 #if single_requested_lease.get('hostname'):
241 requested_lease_list.append(single_requested_lease)
243 logger.debug("SLABDRIVER.PY \tcreate_sliver APRESLEASE" )
244 #dCreate dict of leases by start_time, regrouping nodes reserved
246 #time, for the same amount of time = one job on OAR
247 requested_job_dict = {}
248 for lease in requested_lease_list:
250 #In case it is an asap experiment start_time is empty
251 if lease['start_time'] == '':
252 lease['start_time'] = '0'
254 if lease['start_time'] not in requested_job_dict:
255 if isinstance(lease['hostname'], str):
256 lease['hostname'] = [lease['hostname']]
258 requested_job_dict[lease['start_time']] = lease
261 job_lease = requested_job_dict[lease['start_time']]
262 if lease['duration'] == job_lease['duration'] :
263 job_lease['hostname'].append(lease['hostname'])
268 logger.debug("SLABDRIVER.PY \tcreate_sliver requested_job_dict %s "\
269 %(requested_job_dict))
270 #verify_slice_leases returns the leases , but the return value is unused
271 #here. Removed SA 13/08/12
272 slices.verify_slice_leases(sfa_slice, \
273 requested_job_dict, peer)
275 return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
278 def delete_sliver (self, slice_urn, slice_hrn, creds, options):
280 sfa_slice_list = self.GetSlices(slice_filter = slice_hrn, \
281 slice_filter_type = 'slice_hrn')
283 if not sfa_slice_list:
286 #Delete all in the slice
287 for sfa_slice in sfa_slice_list:
290 logger.debug("SLABDRIVER.PY delete_sliver slice %s" %(sfa_slice))
291 slices = SlabSlices(self)
292 # determine if this is a peer slice
294 peer = slices.get_peer(slice_hrn)
295 #TODO delete_sliver SA : UnBindObjectFromPeer should be
296 #used when there is another
297 #senslab testbed, which is not the case 14/08/12 .
299 logger.debug("SLABDRIVER.PY delete_sliver peer %s" %(peer))
302 self.UnBindObjectFromPeer('slice', \
303 sfa_slice['record_id_slice'], \
305 self.DeleteSliceFromNodes(sfa_slice)
308 self.BindObjectToPeer('slice', \
309 sfa_slice['record_id_slice'], \
310 peer, sfa_slice['peer_slice_id'])
314 def AddSlice(self, slice_record, user_record):
315 #Add slice to the sfa table
316 sfa_record = RegSlice (hrn=slice_record['slice_hrn'], gid=slice_record['gid'],
317 pointer=slice_record['slice_id'],
318 authority=slice_record['authority'])
319 logger.debug("SLABDRIVER.PY AddSlice sfa_record %s user_record %s" %(sfa_record, user_record))
320 #There is no way to separate-adding the slice to the tesbed
321 #nd then importing it from the testebd to SFA because of the senslab's architecture
322 sfa_record.just_created()
323 dbsession.add(sfa_record)
325 sfa_record.reg_researchers = [user_record]
327 #sl_rec = dbsession.query(RegSlice).filter(RegSlice.hrn.match(slice_hrn)).all()
330 slab_slice = SliceSenslab( slice_hrn = slice_record['slice_hrn'], \
331 record_id_slice = sfa_record.record_id , \
332 record_id_user = slice_record['record_id_user'], \
333 peer_authority = slice_record['peer_authority'])
334 logger.debug("SLABDRIVER.PY \tAddSlice slice_record %s slab_slice %s sfa_record %s" \
335 %(slice_record,slab_slice, sfa_record))
336 slab_dbsession.add(slab_slice)
337 slab_dbsession.commit()
340 # first 2 args are None in case of resource discovery
341 def list_resources (self, slice_urn, slice_hrn, creds, options):
342 #cached_requested = options.get('cached', True)
344 version_manager = VersionManager()
345 # get the rspec's return format from options
347 version_manager.get_version(options.get('geni_rspec_version'))
348 version_string = "rspec_%s" % (rspec_version)
350 #panos adding the info option to the caching key (can be improved)
351 if options.get('info'):
352 version_string = version_string + "_" + \
353 options.get('info', 'default')
355 # look in cache first
356 #if cached_requested and self.cache and not slice_hrn:
357 #rspec = self.cache.get(version_string)
359 #logger.debug("SlabDriver.ListResources: \
360 #returning cached advertisement")
363 #panos: passing user-defined options
364 aggregate = SlabAggregate(self)
365 origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
366 options.update({'origin_hrn':origin_hrn})
367 rspec = aggregate.get_rspec(slice_xrn=slice_urn, \
368 version=rspec_version, options=options)
371 #if self.cache and not slice_hrn:
372 #logger.debug("Slab.ListResources: stores advertisement in cache")
373 #self.cache.add(version_string, rspec)
378 def list_slices (self, creds, options):
379 # look in cache first
381 #slices = self.cache.get('slices')
383 #logger.debug("PlDriver.list_slices returns from cache")
388 slices = self.GetSlices()
389 logger.debug("SLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n" %(slices))
390 slice_hrns = [slab_slice['slice_hrn'] for slab_slice in slices]
391 #slice_hrns = [slicename_to_hrn(self.hrn, slab_slice['slice_hrn']) \
392 #for slab_slice in slices]
393 slice_urns = [hrn_to_urn(slice_hrn, 'slice') \
394 for slice_hrn in slice_hrns]
398 #logger.debug ("SlabDriver.list_slices stores value in cache")
399 #self.cache.add('slices', slice_urns)
404 def register (self, sfa_record, hrn, pub_key):
406 Adding new user, slice, node or site should not be handled
410 Adding users = LDAP Senslab
411 Adding slice = Import from LDAP users
416 #No site or node record update allowed
417 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
418 pointer = old_sfa_record['pointer']
419 old_sfa_record_type = old_sfa_record['type']
421 # new_key implemented for users only
422 if new_key and old_sfa_record_type not in [ 'user' ]:
423 raise UnknownSfaType(old_sfa_record_type)
425 #if (type == "authority"):
426 #self.shell.UpdateSite(pointer, new_sfa_record)
428 if old_sfa_record_type == "slice":
429 slab_record = self.sfa_fields_to_slab_fields(old_sfa_record_type, \
431 if 'name' in slab_record:
432 slab_record.pop('name')
433 #Prototype should be UpdateSlice(self,
434 #auth, slice_id_or_name, slice_fields)
435 #Senslab cannot update slice since slice = job
436 #so we must delete and create another job
437 self.UpdateSlice(pointer, slab_record)
439 elif old_sfa_record_type == "user":
441 all_fields = new_sfa_record
442 for key in all_fields.keys():
443 if key in ['first_name', 'last_name', 'title', 'email',
444 'password', 'phone', 'url', 'bio', 'accepted_aup',
446 update_fields[key] = all_fields[key]
447 self.UpdatePerson(pointer, update_fields)
450 # must check this key against the previous one if it exists
451 persons = self.GetPersons([pointer], ['key_ids'])
453 keys = person['key_ids']
454 keys = self.GetKeys(person['key_ids'])
456 # Delete all stale keys
459 if new_key != key['key']:
460 self.DeleteKey(key['key_id'])
464 self.AddPersonKey(pointer, {'key_type': 'ssh', \
471 def remove (self, sfa_record):
472 sfa_record_type = sfa_record['type']
473 hrn = sfa_record['hrn']
474 if sfa_record_type == 'user':
476 #get user from senslab ldap
477 person = self.GetPersons(sfa_record)
478 #No registering at a given site in Senslab.
479 #Once registered to the LDAP, all senslab sites are
482 #Mark account as disabled in ldap
483 self.DeletePerson(sfa_record)
484 elif sfa_record_type == 'slice':
485 if self.GetSlices(slice_filter = hrn, \
486 slice_filter_type = 'slice_hrn'):
487 self.DeleteSlice(sfa_record)
489 #elif type == 'authority':
490 #if self.GetSites(pointer):
491 #self.DeleteSite(pointer)
497 #TODO clean GetPeers. 05/07/12SA
498 def GetPeers (self, auth = None, peer_filter=None, return_fields_list=None):
500 existing_records = {}
501 existing_hrns_by_types = {}
502 logger.debug("SLABDRIVER \tGetPeers auth = %s, peer_filter %s, \
503 return_field %s " %(auth , peer_filter, return_fields_list))
504 all_records = dbsession.query(RegRecord).filter(RegRecord.type.like('%authority%')).all()
505 for record in all_records:
506 existing_records[(record.hrn, record.type)] = record
507 if record.type not in existing_hrns_by_types:
508 existing_hrns_by_types[record.type] = [record.hrn]
509 logger.debug("SLABDRIVER \tGetPeer\t NOT IN \
510 existing_hrns_by_types %s " %( existing_hrns_by_types))
513 logger.debug("SLABDRIVER \tGetPeer\t \INNN type %s hrn %s " \
514 %(record.type,record.hrn))
515 existing_hrns_by_types[record.type].append(record.hrn)
518 logger.debug("SLABDRIVER \tGetPeer\texisting_hrns_by_types %s "\
519 %( existing_hrns_by_types))
524 records_list.append(existing_records[(peer_filter,'authority')])
526 for hrn in existing_hrns_by_types['authority']:
527 records_list.append(existing_records[(hrn,'authority')])
529 logger.debug("SLABDRIVER \tGetPeer \trecords_list %s " \
535 return_records = records_list
536 if not peer_filter and not return_fields_list:
540 logger.debug("SLABDRIVER \tGetPeer return_records %s " \
542 return return_records
545 #TODO : Handling OR request in make_ldap_filters_from_records
546 #instead of the for loop
547 #over the records' list
548 def GetPersons(self, person_filter=None):
550 person_filter should be a list of dictionnaries when not set to None.
551 Returns a list of users whose accounts are enabled found in ldap.
554 logger.debug("SLABDRIVER \tGetPersons person_filter %s" \
557 if person_filter and isinstance(person_filter, list):
558 #If we are looking for a list of users (list of dict records)
559 #Usually the list contains only one user record
560 for searched_attributes in person_filter:
562 #Get only enabled user accounts in senslab LDAP :
563 #add a filter for make_ldap_filters_from_record
564 person = self.ldap.LdapFindUser(searched_attributes, \
565 is_user_enabled=True)
566 person_list.append(person)
569 #Get only enabled user accounts in senslab LDAP :
570 #add a filter for make_ldap_filters_from_record
571 person_list = self.ldap.LdapFindUser(is_user_enabled=True)
575 def GetTimezone(self):
576 server_timestamp, server_tz = self.oar.parser.\
577 SendRequest("GET_timezone")
578 return server_timestamp, server_tz
581 def DeleteJobs(self, job_id, slice_hrn):
582 if not job_id or job_id is -1:
584 username = slice_hrn.split(".")[-1].rstrip("_slice")
586 reqdict['method'] = "delete"
587 reqdict['strval'] = str(job_id)
590 answer = self.oar.POSTRequestToOARRestAPI('DELETE_jobs_id', \
592 logger.debug("SLABDRIVER \tDeleteJobs jobid %s \r\n answer %s \
593 username %s" %(job_id,answer, username))
598 ##TODO : Unused GetJobsId ? SA 05/07/12
599 #def GetJobsId(self, job_id, username = None ):
601 #Details about a specific job.
602 #Includes details about submission time, jot type, state, events,
603 #owner, assigned ressources, walltime etc...
607 #node_list_k = 'assigned_network_address'
608 ##Get job info from OAR
609 #job_info = self.oar.parser.SendRequest(req, job_id, username)
611 #logger.debug("SLABDRIVER \t GetJobsId %s " %(job_info))
613 #if job_info['state'] == 'Terminated':
614 #logger.debug("SLABDRIVER \t GetJobsId job %s TERMINATED"\
617 #if job_info['state'] == 'Error':
618 #logger.debug("SLABDRIVER \t GetJobsId ERROR message %s "\
623 #logger.error("SLABDRIVER \tGetJobsId KeyError")
626 #parsed_job_info = self.get_info_on_reserved_nodes(job_info, \
628 ##Replaces the previous entry
629 ##"assigned_network_address" / "reserved_resources"
631 #job_info.update({'node_ids':parsed_job_info[node_list_k]})
632 #del job_info[node_list_k]
633 #logger.debug(" \r\nSLABDRIVER \t GetJobsId job_info %s " %(job_info))
637 def GetJobsResources(self, job_id, username = None):
638 #job_resources=['reserved_resources', 'assigned_resources',\
639 #'job_id', 'job_uri', 'assigned_nodes',\
641 #assigned_res = ['resource_id', 'resource_uri']
642 #assigned_n = ['node', 'node_uri']
644 req = "GET_jobs_id_resources"
647 #Get job resources list from OAR
648 node_id_list = self.oar.parser.SendRequest(req, job_id, username)
649 logger.debug("SLABDRIVER \t GetJobsResources %s " %(node_id_list))
652 self.__get_hostnames_from_oar_node_ids(node_id_list)
655 #Replaces the previous entry "assigned_network_address" /
656 #"reserved_resources"
658 job_info = {'node_ids': hostname_list}
663 def get_info_on_reserved_nodes(self, job_info, node_list_name):
664 #Get the list of the testbed nodes records and make a
665 #dictionnary keyed on the hostname out of it
666 node_list_dict = self.GetNodes()
667 #node_hostname_list = []
668 node_hostname_list = [node['hostname'] for node in node_list_dict]
669 #for node in node_list_dict:
670 #node_hostname_list.append(node['hostname'])
671 node_dict = dict(zip(node_hostname_list, node_list_dict))
673 reserved_node_hostname_list = []
674 for index in range(len(job_info[node_list_name])):
675 #job_info[node_list_name][k] =
676 reserved_node_hostname_list[index] = \
677 node_dict[job_info[node_list_name][index]]['hostname']
679 logger.debug("SLABDRIVER \t get_info_on_reserved_nodes \
680 reserved_node_hostname_list %s" \
681 %(reserved_node_hostname_list))
683 logger.error("SLABDRIVER \t get_info_on_reserved_nodes KEYERROR " )
685 return reserved_node_hostname_list
687 def GetNodesCurrentlyInUse(self):
688 """Returns a list of all the nodes already involved in an oar job"""
689 return self.oar.parser.SendRequest("GET_running_jobs")
691 def __get_hostnames_from_oar_node_ids(self, resource_id_list ):
692 full_nodes_dict_list = self.GetNodes()
693 #Put the full node list into a dictionary keyed by oar node id
694 oar_id_node_dict = {}
695 for node in full_nodes_dict_list:
696 oar_id_node_dict[node['oar_id']] = node
698 #logger.debug("SLABDRIVER \t __get_hostnames_from_oar_node_ids\
699 #oar_id_node_dict %s" %(oar_id_node_dict))
701 hostname_dict_list = []
702 for resource_id in resource_id_list:
703 #Because jobs requested "asap" do not have defined resources
704 if resource_id is not "Undefined":
705 hostname_dict_list.append(\
706 oar_id_node_dict[resource_id]['hostname'])
708 #hostname_list.append(oar_id_node_dict[resource_id]['hostname'])
709 return hostname_dict_list
711 def GetReservedNodes(self,username = None):
712 #Get the nodes in use and the reserved nodes
713 reservation_dict_list = \
714 self.oar.parser.SendRequest("GET_reserved_nodes", \
718 for resa in reservation_dict_list:
719 logger.debug ("GetReservedNodes resa %s"%(resa))
720 #dict list of hostnames and their site
721 resa['reserved_nodes'] = \
722 self.__get_hostnames_from_oar_node_ids(resa['resource_ids'])
724 #del resa['resource_ids']
725 return reservation_dict_list
727 def GetNodes(self, node_filter_dict = None, return_fields_list = None):
729 node_filter_dict : dictionnary of lists
732 node_dict_by_id = self.oar.parser.SendRequest("GET_resources_full")
733 node_dict_list = node_dict_by_id.values()
734 logger.debug (" SLABDRIVER GetNodes node_filter_dict %s return_fields_list %s "%(node_filter_dict,return_fields_list))
735 #No filtering needed return the list directly
736 if not (node_filter_dict or return_fields_list):
737 return node_dict_list
739 return_node_list = []
741 for filter_key in node_filter_dict:
743 #Filter the node_dict_list by each value contained in the
744 #list node_filter_dict[filter_key]
745 for value in node_filter_dict[filter_key]:
746 for node in node_dict_list:
747 if node[filter_key] == value:
748 if return_fields_list :
750 for k in return_fields_list:
752 return_node_list.append(tmp)
754 return_node_list.append(node)
756 logger.log_exc("GetNodes KeyError")
760 return return_node_list
763 def GetSites(self, site_filter_name_list = None, return_fields_list = None):
764 site_dict = self.oar.parser.SendRequest("GET_sites")
765 #site_dict : dict where the key is the sit ename
766 return_site_list = []
767 if not ( site_filter_name_list or return_fields_list):
768 return_site_list = site_dict.values()
769 return return_site_list
771 for site_filter_name in site_filter_name_list:
772 if site_filter_name in site_dict:
773 if return_fields_list:
774 for field in return_fields_list:
777 tmp[field] = site_dict[site_filter_name][field]
779 logger.error("GetSites KeyError %s "%(field))
781 return_site_list.append(tmp)
783 return_site_list.append( site_dict[site_filter_name])
786 return return_site_list
790 def GetSlices(self, slice_filter = None, slice_filter_type = None):
791 #def GetSlices(self, slice_filter = None, slice_filter_type = None, \
792 #return_fields_list = None):
793 """ Get the slice records from the slab db.
794 Returns a slice ditc if slice_filter and slice_filter_type
796 Returns a list of slice dictionnaries if there are no filters
801 authorized_filter_types_list = ['slice_hrn', 'record_id_user']
802 return_slicerec_dictlist = []
804 #First try to get information on the slice based on the filter provided
805 if slice_filter_type in authorized_filter_types_list:
808 def __get_slice_records(slice_filter = None, slice_filter_type = None):
811 #Get list of slices based on the slice hrn
812 if slice_filter_type == 'slice_hrn':
814 login = slice_filter.split(".")[1].split("_")[0]
816 #DO NOT USE RegSlice - reg_researchers to get the hrn of the user
817 #otherwise will mess up the RegRecord in Resolve, don't know
820 #Only one entry for one user = one slice in slice_senslab table
821 slicerec = slab_dbsession.query(SliceSenslab).filter_by(slice_hrn = slice_filter).first()
825 #Get slice based on user id
826 if slice_filter_type == 'record_id_user':
827 slicerec = slab_dbsession.query(SliceSenslab).filter_by(record_id_user = slice_filter).first()
831 fixed_slicerec_dict = slicerec.dump_sqlalchemyobj_to_dict()
832 #At this point if the there is no login it means
833 #record_id_user filter has been used for filtering
835 login = fixed_slicerec_dict['slice_hrn'].split(".")[1].split("_")[0]
836 return login, fixed_slicerec_dict
840 login, fixed_slicerec_dict = \
841 __get_slice_records(slice_filter, slice_filter_type)
842 logger.debug(" SLABDRIVER \tGetSlices login %s \
843 slice record %s slice_filter %s"\
844 %(login, fixed_slicerec_dict,slice_filter))
847 #Now we have the slice record fixed_slicerec_dict, get the
848 #jobs associated to this slice
849 leases_list = self.GetReservedNodes(username = login)
851 #If no job is running or no job scheduled
852 #return only the slice record
853 if leases_list == [] and fixed_slicerec_dict:
854 return_slicerec_dictlist.append(fixed_slicerec_dict)
856 #If several jobs for one slice , put the slice record into
857 # each lease information dict
858 for lease in leases_list :
861 reserved_list = lease['reserved_nodes']
863 slicerec_dict['oar_job_id'] = lease['lease_id']
864 slicerec_dict.update({'list_node_ids':{'hostname':reserved_list}})
865 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
866 #Update lease dict with the slice record
867 if fixed_slicerec_dict:
868 slicerec_dict.update(fixed_slicerec_dict)
869 slicerec_dict.update({'hrn':\
870 str(fixed_slicerec_dict['slice_hrn'])})
873 return_slicerec_dictlist.append(slicerec_dict)
874 logger.debug("SLABDRIVER.PY \tGetSlices \
875 slicerec_dict %s return_slicerec_dictlist %s \
876 lease['reserved_nodes'] \
877 %s" %(slicerec_dict, return_slicerec_dictlist,\
878 lease['reserved_nodes'] ))
880 logger.debug("SLABDRIVER.PY \tGetSlices RETURN \
881 return_slicerec_dictlist %s" %(return_slicerec_dictlist))
883 return return_slicerec_dictlist
887 #Get all slices from the senslab sfa database ,
888 #put them in dict format
889 query_slice_list = slab_dbsession.query(SliceSenslab).all()
890 return_slicerec_dictlist = []
891 for record in query_slice_list:
892 return_slicerec_dictlist.append(record.dump_sqlalchemyobj_to_dict())
894 #Get all the jobs reserved nodes
895 leases_list = self.GetReservedNodes()
900 for fixed_slicerec_dict in return_slicerec_dictlist:
902 owner = fixed_slicerec_dict['slice_hrn'].split(".")[1].split("_")[0]
903 for lease in leases_list:
904 if owner == lease['user']:
905 slicerec_dict['oar_job_id'] = lease['lease_id']
907 #for reserved_node in lease['reserved_nodes']:
908 logger.debug("SLABDRIVER.PY \tGetSlices lease %s "\
911 reserved_list = lease['reserved_nodes']
913 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
914 slicerec_dict.update({'list_node_ids':{'hostname':reserved_list}})
915 slicerec_dict.update(fixed_slicerec_dict)
916 slicerec_dict.update({'hrn':\
917 str(fixed_slicerec_dict['slice_hrn'])})
918 #return_slicerec_dictlist.append(slicerec_dict)
919 fixed_slicerec_dict.update(slicerec_dict)
921 logger.debug("SLABDRIVER.PY \tGetSlices RETURN return_slicerec_dictlist %s \
922 slice_filter %s " %(return_slicerec_dictlist, slice_filter))
924 return return_slicerec_dictlist
927 def testbed_name (self): return self.hrn
929 # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
930 def aggregate_version (self):
931 version_manager = VersionManager()
932 ad_rspec_versions = []
933 request_rspec_versions = []
934 for rspec_version in version_manager.versions:
935 if rspec_version.content_type in ['*', 'ad']:
936 ad_rspec_versions.append(rspec_version.to_dict())
937 if rspec_version.content_type in ['*', 'request']:
938 request_rspec_versions.append(rspec_version.to_dict())
940 'testbed':self.testbed_name(),
941 'geni_request_rspec_versions': request_rspec_versions,
942 'geni_ad_rspec_versions': ad_rspec_versions,
951 # Convert SFA fields to PLC fields for use when registering up updating
952 # registry record in the PLC database
954 # @param type type of record (user, slice, ...)
955 # @param hrn human readable name
956 # @param sfa_fields dictionary of SFA fields
957 # @param slab_fields dictionary of PLC fields (output)
959 def sfa_fields_to_slab_fields(self, sfa_type, hrn, record):
963 #for field in record:
964 # slab_record[field] = record[field]
966 if sfa_type == "slice":
967 #instantion used in get_slivers ?
968 if not "instantiation" in slab_record:
969 slab_record["instantiation"] = "senslab-instantiated"
970 #slab_record["hrn"] = hrn_to_pl_slicename(hrn)
971 #Unused hrn_to_pl_slicename because Slab's hrn already in the appropriate form SA 23/07/12
972 slab_record["hrn"] = hrn
973 logger.debug("SLABDRIVER.PY sfa_fields_to_slab_fields \
974 slab_record %s " %(slab_record['hrn']))
976 slab_record["url"] = record["url"]
977 if "description" in record:
978 slab_record["description"] = record["description"]
979 if "expires" in record:
980 slab_record["expires"] = int(record["expires"])
982 #nodes added by OAR only and then imported to SFA
983 #elif type == "node":
984 #if not "hostname" in slab_record:
985 #if not "hostname" in record:
986 #raise MissingSfaInfo("hostname")
987 #slab_record["hostname"] = record["hostname"]
988 #if not "model" in slab_record:
989 #slab_record["model"] = "geni"
992 #elif type == "authority":
993 #slab_record["login_base"] = hrn_to_slab_login_base(hrn)
995 #if not "name" in slab_record:
996 #slab_record["name"] = hrn
998 #if not "abbreviated_name" in slab_record:
999 #slab_record["abbreviated_name"] = hrn
1001 #if not "enabled" in slab_record:
1002 #slab_record["enabled"] = True
1004 #if not "is_public" in slab_record:
1005 #slab_record["is_public"] = True
1012 def __transforms_timestamp_into_date(self, xp_utc_timestamp = None):
1013 """ Transforms unix timestamp into valid OAR date format """
1015 #Used in case of a scheduled experiment (not immediate)
1016 #To run an XP immediately, don't specify date and time in RSpec
1017 #They will be set to None.
1018 if xp_utc_timestamp:
1019 #transform the xp_utc_timestamp into server readable time
1020 xp_server_readable_date = datetime.fromtimestamp(int(\
1021 xp_utc_timestamp)).strftime(self.time_format)
1023 return xp_server_readable_date
1031 def LaunchExperimentOnOAR(self, added_nodes, slice_name, \
1032 lease_start_time, lease_duration, slice_user=None):
1034 lease_dict['lease_start_time'] = lease_start_time
1035 lease_dict['lease_duration'] = lease_duration
1036 lease_dict['added_nodes'] = added_nodes
1037 lease_dict['slice_name'] = slice_name
1038 lease_dict['slice_user'] = slice_user
1039 lease_dict['grain'] = self.GetLeaseGranularity()
1040 lease_dict['time_format'] = self.time_format
1042 def __create_job_structure_request_for_OAR(lease_dict):
1043 """ Creates the structure needed for a correct POST on OAR.
1044 Makes the timestamp transformation into the appropriate format.
1045 Sends the POST request to create the job with the resources in
1054 reqdict['workdir'] = '/tmp'
1055 reqdict['resource'] = "{network_address in ("
1057 for node in lease_dict['added_nodes']:
1058 logger.debug("\r\n \r\n OARrestapi \t __create_job_structure_request_for_OAR \
1061 # Get the ID of the node
1063 reqdict['resource'] += "'" + nodeid + "', "
1064 nodeid_list.append(nodeid)
1066 custom_length = len(reqdict['resource'])- 2
1067 reqdict['resource'] = reqdict['resource'][0:custom_length] + \
1068 ")}/nodes=" + str(len(nodeid_list))
1070 def __process_walltime(duration):
1071 """ Calculates the walltime in seconds from the duration in H:M:S
1072 specified in the RSpec.
1076 # Fixing the walltime by adding a few delays.
1077 # First put the walltime in seconds oarAdditionalDelay = 20;
1078 # additional delay for /bin/sleep command to
1079 # take in account prologue and epilogue scripts execution
1080 # int walltimeAdditionalDelay = 240; additional delay
1081 desired_walltime = duration
1082 total_walltime = desired_walltime + 240 #+4 min Update SA 23/10/12
1083 sleep_walltime = desired_walltime # 0 sec added Update SA 23/10/12
1085 #Put the walltime back in str form
1086 #First get the hours
1087 walltime.append(str(total_walltime / 3600))
1088 total_walltime = total_walltime - 3600 * int(walltime[0])
1089 #Get the remaining minutes
1090 walltime.append(str(total_walltime / 60))
1091 total_walltime = total_walltime - 60 * int(walltime[1])
1093 walltime.append(str(total_walltime))
1096 logger.log_exc(" __process_walltime duration null")
1098 return walltime, sleep_walltime
1101 walltime, sleep_walltime = \
1102 __process_walltime(int(lease_dict['lease_duration'])*lease_dict['grain'])
1105 reqdict['resource'] += ",walltime=" + str(walltime[0]) + \
1106 ":" + str(walltime[1]) + ":" + str(walltime[2])
1107 reqdict['script_path'] = "/bin/sleep " + str(sleep_walltime)
1109 #In case of a scheduled experiment (not immediate)
1110 #To run an XP immediately, don't specify date and time in RSpec
1111 #They will be set to None.
1112 if lease_dict['lease_start_time'] is not '0':
1113 #Readable time accepted by OAR
1114 start_time = datetime.fromtimestamp(int(lease_dict['lease_start_time'])).\
1115 strftime(lease_dict['time_format'])
1116 reqdict['reservation'] = start_time
1117 #If there is not start time, Immediate XP. No need to add special
1121 reqdict['type'] = "deploy"
1122 reqdict['directory'] = ""
1123 reqdict['name'] = "SFA_" + lease_dict['slice_user']
1128 #Create the request for OAR
1129 reqdict = __create_job_structure_request_for_OAR(lease_dict)
1130 # first step : start the OAR job and update the job
1131 logger.debug("SLABDRIVER.PY \tLaunchExperimentOnOAR reqdict %s\
1134 answer = self.oar.POSTRequestToOARRestAPI('POST_job', \
1135 reqdict, slice_user)
1136 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s " %(answer))
1138 jobid = answer['id']
1140 logger.log_exc("SLABDRIVER \tLaunchExperimentOnOAR \
1141 Impossible to create job %s " %(answer))
1145 def __configure_experiment(jobid, added_nodes):
1146 # second step : configure the experiment
1147 # we need to store the nodes in a yaml (well...) file like this :
1148 # [1,56,23,14,45,75] with name /tmp/sfa<jobid>.json
1149 job_file = open('/tmp/sfa/'+ str(jobid) + '.json', 'w')
1151 job_file.write(str(added_nodes[0].strip('node')))
1152 for node in added_nodes[1:len(added_nodes)] :
1153 job_file.write(', '+ node.strip('node'))
1158 def __launch_senslab_experiment(jobid):
1159 # third step : call the senslab-experiment wrapper
1160 #command= "java -jar target/sfa-1.0-jar-with-dependencies.jar
1161 # "+str(jobid)+" "+slice_user
1162 javacmdline = "/usr/bin/java"
1164 "/opt/senslabexperimentwrapper/sfa-1.0-jar-with-dependencies.jar"
1165 #ret=subprocess.check_output(["/usr/bin/java", "-jar", ", \
1166 #str(jobid), slice_user])
1167 output = subprocess.Popen([javacmdline, "-jar", jarname, str(jobid), \
1168 slice_user],stdout=subprocess.PIPE).communicate()[0]
1170 logger.debug("SLABDRIVER \t __configure_experiment wrapper returns%s " \
1177 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s \
1178 added_nodes %s slice_user %s" %(jobid, added_nodes, slice_user))
1181 __configure_experiment(jobid, added_nodes)
1182 __launch_senslab_experiment(jobid)
1186 def AddLeases(self, hostname_list, slice_record, lease_start_time, lease_duration):
1187 logger.debug("SLABDRIVER \r\n \r\n \t AddLeases hostname_list %s \
1188 slice_record %s lease_start_time %s lease_duration %s "\
1189 %( hostname_list, slice_record , lease_start_time, \
1192 tmp = slice_record['reg-researchers'][0].split(".")
1193 username = tmp[(len(tmp)-1)]
1194 self.LaunchExperimentOnOAR(hostname_list, slice_record['slice_hrn'], lease_start_time, lease_duration, username)
1195 start_time = datetime.fromtimestamp(int(lease_start_time)).strftime(self.time_format)
1196 logger.debug("SLABDRIVER \t AddLeases hostname_list start_time %s " %(start_time))
1201 #Delete the jobs from job_senslab table
1202 def DeleteSliceFromNodes(self, slice_record):
1204 self.DeleteJobs(slice_record['oar_job_id'], slice_record['hrn'])
1208 def GetLeaseGranularity(self):
1209 """ Returns the granularity of Senslab testbed.
1210 OAR returns seconds for experiments duration.
1211 Defined in seconds. """
1216 def GetLeases(self, lease_filter_dict=None):
1219 unfiltered_reservation_list = self.GetReservedNodes()
1221 reservation_list = []
1222 #Find the slice associated with this user senslab ldap uid
1223 logger.debug(" SLABDRIVER.PY \tGetLeases ")
1224 #Create user dict first to avoid looking several times for
1225 #the same user in LDAP SA 27/07/12
1227 for resa in unfiltered_reservation_list:
1228 logger.debug("SLABDRIVER \tGetLeases USER %s"\
1230 if resa['user'] not in resa_user_dict:
1231 logger.debug("SLABDRIVER \tGetLeases userNOTIN ")
1232 ldap_info = self.ldap.LdapSearch('(uid='+resa['user']+')')
1233 ldap_info = ldap_info[0][1]
1234 user = dbsession.query(RegUser).filter_by(email = \
1235 ldap_info['mail'][0]).first()
1236 #Separated in case user not in database :
1237 #record_id not defined SA 17/07//12
1238 query_slice_info = slab_dbsession.query(SliceSenslab).filter_by(record_id_user = user.record_id)
1239 if query_slice_info:
1240 slice_info = query_slice_info.first()
1244 resa_user_dict[resa['user']] = {}
1245 resa_user_dict[resa['user']]['ldap_info'] = user
1246 resa_user_dict[resa['user']]['slice_info'] = slice_info
1248 logger.debug("SLABDRIVER \tGetLeases resa_user_dict %s"\
1250 for resa in unfiltered_reservation_list:
1254 resa['slice_hrn'] = resa_user_dict[resa['user']]['slice_info'].slice_hrn
1255 resa['slice_id'] = hrn_to_urn(resa['slice_hrn'], 'slice')
1257 #resa['slice_id'] = hrn_to_urn(slice_info.slice_hrn, 'slice')
1258 resa['component_id_list'] = []
1259 #Transform the hostnames into urns (component ids)
1260 for node in resa['reserved_nodes']:
1261 #resa['component_id_list'].append(hostname_to_urn(self.hrn, \
1262 #self.root_auth, node['hostname']))
1263 slab_xrn = slab_xrn_object(self.root_auth, node)
1264 resa['component_id_list'].append(slab_xrn.urn)
1266 #Filter the reservation list if necessary
1267 #Returns all the leases associated with a given slice
1268 if lease_filter_dict:
1269 logger.debug("SLABDRIVER \tGetLeases lease_filter_dict %s"\
1270 %(lease_filter_dict))
1271 for resa in unfiltered_reservation_list:
1272 if lease_filter_dict['name'] == resa['slice_hrn']:
1273 reservation_list.append(resa)
1275 reservation_list = unfiltered_reservation_list
1277 logger.debug(" SLABDRIVER.PY \tGetLeases reservation_list %s"\
1278 %(reservation_list))
1279 return reservation_list
1281 def augment_records_with_testbed_info (self, sfa_records):
1282 return self.fill_record_info (sfa_records)
1284 def fill_record_info(self, record_list):
1286 Given a SFA record, fill in the senslab specific and SFA specific
1287 fields in the record.
1290 logger.debug("SLABDRIVER \tfill_record_info records %s " %(record_list))
1291 if not isinstance(record_list, list):
1292 record_list = [record_list]
1295 for record in record_list:
1296 #If the record is a SFA slice record, then add information
1297 #about the user of this slice. This kind of
1298 #information is in the Senslab's DB.
1299 if str(record['type']) == 'slice':
1300 #Get slab slice record.
1301 recslice_list = self.GetSlices(slice_filter = \
1302 str(record['hrn']),\
1303 slice_filter_type = 'slice_hrn')
1305 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1306 recslice_list[0]['record_id_user']).first()
1307 logger.debug("SLABDRIVER \tfill_record_info TYPE SLICE RECUSER %s " %(recuser))
1308 record.update({'PI':[recuser.hrn],
1309 'researcher': [recuser.hrn],
1310 'name':record['hrn'],
1313 'person_ids':[recslice_list[0]['record_id_user']],
1314 'geni_urn':'', #For client_helper.py compatibility
1315 'keys':'', #For client_helper.py compatibility
1316 'key_ids':''}) #For client_helper.py compatibility
1319 for rec in recslice_list:
1320 record['oar_job_id'].append(rec['oar_job_id'])
1321 record['node_ids'] = [ self.root_auth + hostname for hostname in rec['node_ids']]
1325 logger.debug( "SLABDRIVER.PY \t fill_record_info SLICE \
1326 recslice_list %s \r\n \t RECORD %s \r\n \r\n" %(recslice_list,record))
1327 if str(record['type']) == 'user':
1328 #The record is a SFA user record.
1329 #Get the information about his slice from Senslab's DB
1330 #and add it to the user record.
1331 recslice_list = self.GetSlices(\
1332 slice_filter = record['record_id'],\
1333 slice_filter_type = 'record_id_user')
1335 logger.debug( "SLABDRIVER.PY \t fill_record_info TYPE USER \
1336 recslice_list %s \r\n \t RECORD %s \r\n" %(recslice_list , record))
1337 #Append slice record in records list,
1338 #therefore fetches user and slice info again(one more loop)
1339 #Will update PIs and researcher for the slice
1340 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1341 recslice_list[0]['record_id_user']).first()
1342 logger.debug( "SLABDRIVER.PY \t fill_record_info USER \
1343 recuser %s \r\n \r\n" %(recuser))
1345 recslice = recslice_list[0]
1346 recslice.update({'PI':[recuser.hrn],
1347 'researcher': [recuser.hrn],
1348 'name':record['hrn'],
1351 'person_ids':[recslice_list[0]['record_id_user']]})
1353 for rec in recslice_list:
1354 recslice['oar_job_id'].append(rec['oar_job_id'])
1358 recslice.update({'type':'slice', \
1359 'hrn':recslice_list[0]['slice_hrn']})
1362 #GetPersons takes [] as filters
1363 #user_slab = self.GetPersons([{'hrn':recuser.hrn}])
1364 user_slab = self.GetPersons([record])
1367 record.update(user_slab[0])
1368 #For client_helper.py compatibility
1369 record.update( { 'geni_urn':'',
1372 record_list.append(recslice)
1374 logger.debug("SLABDRIVER.PY \tfill_record_info ADDING SLICE\
1375 INFO TO USER records %s" %(record_list))
1376 logger.debug("SLABDRIVER.PY \tfill_record_info END \
1377 #record %s \r\n \r\n " %(record))
1379 except TypeError, error:
1380 logger.log_exc("SLABDRIVER \t fill_record_info EXCEPTION %s"\
1382 #logger.debug("SLABDRIVER.PY \t fill_record_info ENDENDEND ")
1386 #self.fill_record_slab_info(records)
1392 #TODO Update membership? update_membership_list SA 05/07/12
1393 #def update_membership_list(self, oldRecord, record, listName, addFunc, \
1395 ## get a list of the HRNs tht are members of the old and new records
1397 #oldList = oldRecord.get(listName, [])
1400 #newList = record.get(listName, [])
1402 ## if the lists are the same, then we don't have to update anything
1403 #if (oldList == newList):
1406 ## build a list of the new person ids, by looking up each person to get
1410 #records = table.find({'type': 'user', 'hrn': newList})
1411 #for rec in records:
1412 #newIdList.append(rec['pointer'])
1414 ## build a list of the old person ids from the person_ids field
1416 #oldIdList = oldRecord.get("person_ids", [])
1417 #containerId = oldRecord.get_pointer()
1419 ## if oldRecord==None, then we are doing a Register, instead of an
1422 #containerId = record.get_pointer()
1424 ## add people who are in the new list, but not the oldList
1425 #for personId in newIdList:
1426 #if not (personId in oldIdList):
1427 #addFunc(self.plauth, personId, containerId)
1429 ## remove people who are in the old list, but not the new list
1430 #for personId in oldIdList:
1431 #if not (personId in newIdList):
1432 #delFunc(self.plauth, personId, containerId)
1434 #def update_membership(self, oldRecord, record):
1436 #if record.type == "slice":
1437 #self.update_membership_list(oldRecord, record, 'researcher',
1438 #self.users.AddPersonToSlice,
1439 #self.users.DeletePersonFromSlice)
1440 #elif record.type == "authority":
1445 # I don't think you plan on running a component manager at this point
1446 # let me clean up the mess of ComponentAPI that is deprecated anyways
1449 #TODO FUNCTIONS SECTION 04/07/2012 SA
1451 #TODO : Is UnBindObjectFromPeer still necessary ? Currently does nothing
1453 def UnBindObjectFromPeer(self, auth, object_type, object_id, shortname):
1454 """ This method is a hopefully temporary hack to let the sfa correctly
1455 detach the objects it creates from a remote peer object. This is
1456 needed so that the sfa federation link can work in parallel with
1457 RefreshPeer, as RefreshPeer depends on remote objects being correctly
1460 auth : struct, API authentication structure
1461 AuthMethod : string, Authentication method to use
1462 object_type : string, Object type, among 'site','person','slice',
1464 object_id : int, object_id
1465 shortname : string, peer shortname
1469 logger.warning("SLABDRIVER \tUnBindObjectFromPeer EMPTY-\
1473 #TODO Is BindObjectToPeer still necessary ? Currently does nothing
1475 def BindObjectToPeer(self, auth, object_type, object_id, shortname=None, \
1476 remote_object_id=None):
1477 """This method is a hopefully temporary hack to let the sfa correctly
1478 attach the objects it creates to a remote peer object. This is needed
1479 so that the sfa federation link can work in parallel with RefreshPeer,
1480 as RefreshPeer depends on remote objects being correctly marked.
1482 shortname : string, peer shortname
1483 remote_object_id : int, remote object_id, set to 0 if unknown
1487 logger.warning("SLABDRIVER \tBindObjectToPeer EMPTY - DO NOTHING \r\n ")
1490 #TODO UpdateSlice 04/07/2012 SA
1491 #Funciton should delete and create another job since oin senslab slice=job
1492 def UpdateSlice(self, auth, slice_id_or_name, slice_fields=None):
1493 """Updates the parameters of an existing slice with the values in
1495 Users may only update slices of which they are members.
1496 PIs may update any of the slices at their sites, or any slices of
1497 which they are members. Admins may update any slice.
1498 Only PIs and admins may update max_nodes. Slices cannot be renewed
1499 (by updating the expires parameter) more than 8 weeks into the future.
1500 Returns 1 if successful, faults otherwise.
1504 logger.warning("SLABDRIVER UpdateSlice EMPTY - DO NOTHING \r\n ")
1507 #TODO UpdatePerson 04/07/2012 SA
1508 def UpdatePerson(self, auth, person_id_or_email, person_fields=None):
1509 """Updates a person. Only the fields specified in person_fields
1510 are updated, all other fields are left untouched.
1511 Users and techs can only update themselves. PIs can only update
1512 themselves and other non-PIs at their sites.
1513 Returns 1 if successful, faults otherwise.
1517 logger.warning("SLABDRIVER UpdatePerson EMPTY - DO NOTHING \r\n ")
1520 #TODO GetKeys 04/07/2012 SA
1521 def GetKeys(self, auth, key_filter=None, return_fields=None):
1522 """Returns an array of structs containing details about keys.
1523 If key_filter is specified and is an array of key identifiers,
1524 or a struct of key attributes, only keys matching the filter
1525 will be returned. If return_fields is specified, only the
1526 specified details will be returned.
1528 Admin may query all keys. Non-admins may only query their own keys.
1532 logger.warning("SLABDRIVER GetKeys EMPTY - DO NOTHING \r\n ")
1535 #TODO DeleteKey 04/07/2012 SA
1536 def DeleteKey(self, auth, key_id):
1538 Non-admins may only delete their own keys.
1539 Returns 1 if successful, faults otherwise.
1543 logger.warning("SLABDRIVER DeleteKey EMPTY - DO NOTHING \r\n ")
1547 #TODO : Check rights to delete person
1548 def DeletePerson(self, auth, person_record):
1549 """ Disable an existing account in senslab LDAP.
1550 Users and techs can only delete themselves. PIs can only
1551 delete themselves and other non-PIs at their sites.
1552 ins can delete anyone.
1553 Returns 1 if successful, faults otherwise.
1557 #Disable user account in senslab LDAP
1558 ret = self.ldap.LdapMarkUserAsDeleted(person_record)
1559 logger.warning("SLABDRIVER DeletePerson %s " %(person_record))
1562 #TODO Check DeleteSlice, check rights 05/07/2012 SA
1563 def DeleteSlice(self, auth, slice_record):
1564 """ Deletes the specified slice.
1565 Senslab : Kill the job associated with the slice if there is one
1566 using DeleteSliceFromNodes.
1567 Updates the slice record in slab db to remove the slice nodes.
1569 Users may only delete slices of which they are members. PIs may
1570 delete any of the slices at their sites, or any slices of which
1571 they are members. Admins may delete any slice.
1572 Returns 1 if successful, faults otherwise.
1576 self.DeleteSliceFromNodes(slice_record)
1577 logger.warning("SLABDRIVER DeleteSlice %s "%(slice_record))
1580 #TODO AddPerson 04/07/2012 SA
1581 #def AddPerson(self, auth, person_fields=None):
1582 def AddPerson(self, record):#TODO fixing 28/08//2012 SA
1583 """Adds a new account. Any fields specified in records are used,
1584 otherwise defaults are used.
1585 Accounts are disabled by default. To enable an account,
1587 Returns the new person_id (> 0) if successful, faults otherwise.
1591 ret = self.ldap.LdapAddUser(record)
1592 logger.warning("SLABDRIVER AddPerson return code %s \r\n ", ret)
1595 #TODO AddPersonToSite 04/07/2012 SA
1596 def AddPersonToSite (self, auth, person_id_or_email, \
1597 site_id_or_login_base=None):
1598 """ Adds the specified person to the specified site. If the person is
1599 already a member of the site, no errors are returned. Does not change
1600 the person's primary site.
1601 Returns 1 if successful, faults otherwise.
1605 logger.warning("SLABDRIVER AddPersonToSite EMPTY - DO NOTHING \r\n ")
1608 #TODO AddRoleToPerson : Not sure if needed in senslab 04/07/2012 SA
1609 def AddRoleToPerson(self, auth, role_id_or_name, person_id_or_email):
1610 """Grants the specified role to the person.
1611 PIs can only grant the tech and user roles to users and techs at their
1612 sites. Admins can grant any role to any user.
1613 Returns 1 if successful, faults otherwise.
1617 logger.warning("SLABDRIVER AddRoleToPerson EMPTY - DO NOTHING \r\n ")
1620 #TODO AddPersonKey 04/07/2012 SA
1621 def AddPersonKey(self, auth, person_id_or_email, key_fields=None):
1622 """Adds a new key to the specified account.
1623 Non-admins can only modify their own keys.
1624 Returns the new key_id (> 0) if successful, faults otherwise.
1628 logger.warning("SLABDRIVER AddPersonKey EMPTY - DO NOTHING \r\n ")
1631 def DeleteLeases(self, leases_id_list, slice_hrn ):
1632 for job_id in leases_id_list:
1633 self.DeleteJobs(job_id, slice_hrn)
1635 logger.debug("SLABDRIVER DeleteLeases leases_id_list %s slice_hrn %s \
1636 \r\n " %(leases_id_list, slice_hrn))