3 from datetime import datetime
4 from time import gmtime
6 from sfa.util.faults import SliverDoesNotExist, UnknownSfaType
7 from sfa.util.sfalogging import logger
9 from sfa.storage.alchemy import dbsession
10 from sfa.storage.model import RegRecord, RegUser
12 from sfa.trust.credential import Credential
15 from sfa.managers.driver import Driver
16 from sfa.rspecs.version_manager import VersionManager
17 from sfa.rspecs.rspec import RSpec
19 from sfa.util.xrn import hrn_to_urn, urn_to_sliver_id, get_leaf
22 ## thierry: everything that is API-related (i.e. handling incoming requests)
24 # SlabDriver should be really only about talking to the senslab testbed
27 from sfa.senslab.OARrestapi import OARrestapi
28 from sfa.senslab.LDAPapi import LDAPapi
30 from sfa.senslab.slabpostgres import SlabDB, slab_dbsession, SliceSenslab
32 from sfa.senslab.slabaggregate import SlabAggregate, slab_xrn_to_hostname, \
34 from sfa.senslab.slabslices import SlabSlices
41 # this inheritance scheme is so that the driver object can receive
42 # GetNodes or GetSites sorts of calls directly
43 # and thus minimize the differences in the managers with the pl version
44 class SlabDriver(Driver):
46 def __init__(self, config):
47 Driver.__init__ (self, config)
49 self.hrn = config.SFA_INTERFACE_HRN
51 self.root_auth = config.SFA_REGISTRY_ROOT_AUTH
53 self.oar = OARrestapi()
55 self.time_format = "%Y-%m-%d %H:%M:%S"
56 self.db = SlabDB(config,debug = True)
60 def sliver_status(self, slice_urn, slice_hrn):
61 """Receive a status request for slice named urn/hrn
62 urn:publicid:IDN+senslab+nturro_slice hrn senslab.nturro_slice
63 shall return a structure as described in
64 http://groups.geni.net/geni/wiki/GAPI_AM_API_V2#SliverStatus
65 NT : not sure if we should implement this or not, but used by sface.
69 #First get the slice with the slice hrn
70 slice_list = self.GetSlices(slice_filter = slice_hrn, \
71 slice_filter_type = 'slice_hrn')
73 if len(slice_list) is 0:
74 raise SliverDoesNotExist("%s slice_hrn" % (slice_hrn))
76 #Slice has the same slice hrn for each slice in the slice/lease list
77 #So fetch the info on the user once
78 one_slice = slice_list[0]
79 recuser = dbsession.query(RegRecord).filter_by(record_id = \
80 one_slice['record_id_user']).first()
82 #Make a list of all the nodes hostnames in use for this slice
85 for node in sl['node_ids']:
86 slice_nodes_list.append(node['hostname'])
88 #Get all the corresponding nodes details
89 nodes_all = self.GetNodes({'hostname':slice_nodes_list},
90 ['node_id', 'hostname','site','boot_state'])
91 nodeall_byhostname = dict([(n['hostname'], n) for n in nodes_all])
98 top_level_status = 'empty'
100 result.fromkeys(['geni_urn','pl_login','geni_status','geni_resources'],None)
101 result['pl_login'] = recuser.hrn
102 logger.debug("Slabdriver - sliver_status Sliver status urn %s hrn %s sl\
103 %s \r\n " %(slice_urn, slice_hrn, sl))
105 nodes_in_slice = sl['node_ids']
108 result['geni_status'] = top_level_status
109 result['geni_resources'] = []
112 top_level_status = 'ready'
114 #A job is running on Senslab for this slice
115 # report about the local nodes that are in the slice only
117 result['geni_urn'] = slice_urn
121 #timestamp = float(sl['startTime']) + float(sl['walltime'])
122 #result['pl_expires'] = strftime(self.time_format, \
123 #gmtime(float(timestamp)))
124 #result['slab_expires'] = strftime(self.time_format,\
125 #gmtime(float(timestamp)))
128 for node in sl['node_ids']:
130 #res['slab_hostname'] = node['hostname']
131 #res['slab_boot_state'] = node['boot_state']
133 res['pl_hostname'] = node['hostname']
134 res['pl_boot_state'] = nodeall_byhostname[node['hostname']]['boot_state']
135 #res['pl_last_contact'] = strftime(self.time_format, \
136 #gmtime(float(timestamp)))
137 sliver_id = urn_to_sliver_id(slice_urn, sl['record_id_slice'], \
138 nodeall_byhostname[node['hostname']]['node_id'])
139 res['geni_urn'] = sliver_id
140 if nodeall_byhostname[node['hostname']]['boot_state'] == 'Alive':
142 res['geni_status'] = 'ready'
144 res['geni_status'] = 'failed'
145 top_level_status = 'failed'
147 res['geni_error'] = ''
149 resources.append(res)
151 result['geni_status'] = top_level_status
152 result['geni_resources'] = resources
153 logger.debug("SLABDRIVER \tsliver_statusresources %s res %s "\
158 def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, \
160 aggregate = SlabAggregate(self)
162 slices = SlabSlices(self)
163 peer = slices.get_peer(slice_hrn)
164 sfa_peer = slices.get_sfa_peer(slice_hrn)
167 if not isinstance(creds, list):
171 slice_record = users[0].get('slice_record', {})
174 rspec = RSpec(rspec_string)
175 logger.debug("SLABDRIVER.PY \t create_sliver \tr spec.version %s slice_record %s " \
176 %(rspec.version,slice_record))
178 #self.synchronize_oar_and_slice_table(slice_hrn)
179 # ensure site record exists?
180 # ensure slice record exists
181 #Removed options to verify_slice SA 14/08/12
182 sfa_slice = slices.verify_slice(slice_hrn, slice_record, peer, \
185 #requested_attributes returned by rspec.version.get_slice_attributes()
186 #unused, removed SA 13/08/12
187 rspec.version.get_slice_attributes()
189 logger.debug("SLABDRIVER.PY create_sliver slice %s " %(sfa_slice))
191 # ensure person records exists
192 #verify_persons returns added persons but since the return value
194 slices.verify_persons(slice_hrn, sfa_slice, users, peer, \
195 sfa_peer, options=options)
199 # add/remove slice from nodes
201 requested_slivers = [node.get('component_name') \
202 for node in rspec.version.get_nodes_with_slivers()]
203 l = [ node for node in rspec.version.get_nodes_with_slivers() ]
204 logger.debug("SLADRIVER \tcreate_sliver requested_slivers \
205 requested_slivers %s listnodes %s" \
206 %(requested_slivers,l))
207 #verify_slice_nodes returns nodes, but unused here. Removed SA 13/08/12.
208 slices.verify_slice_nodes(sfa_slice, requested_slivers, peer)
211 requested_lease_list = []
213 for lease in rspec.version.get_leases():
214 single_requested_lease = {}
215 logger.debug("SLABDRIVER.PY \tcreate_sliver lease %s " %(lease))
216 if not lease.get('lease_id'):
217 single_requested_lease['hostname'] = \
218 slab_xrn_to_hostname(lease.get('component_id').strip())
219 single_requested_lease['start_time'] = lease.get('start_time')
220 single_requested_lease['duration'] = lease.get('duration')
222 kept_leases.append(int(lease['lease_id']))
223 if single_requested_lease.get('hostname'):
224 requested_lease_list.append(single_requested_lease)
226 #dCreate dict of leases by start_time, regrouping nodes reserved
228 #time, for the same amount of time = one job on OAR
229 requested_job_dict = {}
230 for lease in requested_lease_list:
232 #In case it is an asap experiment start_time is empty
233 if lease['start_time'] == '':
234 lease['start_time'] = '0'
236 if lease['start_time'] not in requested_job_dict:
237 if isinstance(lease['hostname'], str):
238 lease['hostname'] = [lease['hostname']]
240 requested_job_dict[lease['start_time']] = lease
243 job_lease = requested_job_dict[lease['start_time']]
244 if lease['duration'] == job_lease['duration'] :
245 job_lease['hostname'].append(lease['hostname'])
250 logger.debug("SLABDRIVER.PY \tcreate_sliver requested_job_dict %s " %(requested_job_dict))
251 #verify_slice_leases returns the leases , but the return value is unused
252 #here. Removed SA 13/08/12
253 slices.verify_slice_leases(sfa_slice, \
254 requested_job_dict, kept_leases, peer)
256 return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
259 def delete_sliver (self, slice_urn, slice_hrn, creds, options):
261 sfa_slice_list = self.GetSlices(slice_filter = slice_hrn, \
262 slice_filter_type = 'slice_hrn')
264 if not sfa_slice_list:
267 #Delete all in the slice
268 for sfa_slice in sfa_slice_list:
271 logger.debug("SLABDRIVER.PY delete_sliver slice %s" %(sfa_slice))
272 slices = SlabSlices(self)
273 # determine if this is a peer slice
275 peer = slices.get_peer(slice_hrn)
276 #TODO delete_sliver SA : UnBindObjectFromPeer should be
277 #used when there is another
278 #senslab testbed, which is not the case 14/08/12 .
280 logger.debug("SLABDRIVER.PY delete_sliver peer %s" %(peer))
283 self.UnBindObjectFromPeer('slice', \
284 sfa_slice['record_id_slice'], peer,None)
285 self.DeleteSliceFromNodes(sfa_slice)
288 self.BindObjectToPeer('slice', sfa_slice['record_id_slice'], \
289 peer, sfa_slice['peer_slice_id'])
293 def AddSlice(self, slice_record):
294 slab_slice = SliceSenslab( slice_hrn = slice_record['slice_hrn'], \
295 record_id_slice= slice_record['record_id_slice'] , \
296 record_id_user= slice_record['record_id_user'], \
297 peer_authority = slice_record['peer_authority'])
298 logger.debug("SLABDRIVER.PY \tAddSlice slice_record %s slab_slice %s" \
299 %(slice_record,slab_slice))
300 slab_dbsession.add(slab_slice)
301 slab_dbsession.commit()
304 # first 2 args are None in case of resource discovery
305 def list_resources (self, slice_urn, slice_hrn, creds, options):
306 #cached_requested = options.get('cached', True)
308 version_manager = VersionManager()
309 # get the rspec's return format from options
311 version_manager.get_version(options.get('geni_rspec_version'))
312 version_string = "rspec_%s" % (rspec_version)
314 #panos adding the info option to the caching key (can be improved)
315 if options.get('info'):
316 version_string = version_string + "_" + \
317 options.get('info', 'default')
319 # look in cache first
320 #if cached_requested and self.cache and not slice_hrn:
321 #rspec = self.cache.get(version_string)
323 #logger.debug("SlabDriver.ListResources: \
324 #returning cached advertisement")
327 #panos: passing user-defined options
328 aggregate = SlabAggregate(self)
329 origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
330 options.update({'origin_hrn':origin_hrn})
331 rspec = aggregate.get_rspec(slice_xrn=slice_urn, \
332 version=rspec_version, options=options)
335 #if self.cache and not slice_hrn:
336 #logger.debug("Slab.ListResources: stores advertisement in cache")
337 #self.cache.add(version_string, rspec)
342 def list_slices (self, creds, options):
343 # look in cache first
345 #slices = self.cache.get('slices')
347 #logger.debug("PlDriver.list_slices returns from cache")
352 slices = self.GetSlices()
353 logger.debug("SLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n" %(slices))
354 slice_hrns = [slab_slice['slice_hrn'] for slab_slice in slices]
355 #slice_hrns = [slicename_to_hrn(self.hrn, slab_slice['slice_hrn']) \
356 #for slab_slice in slices]
357 slice_urns = [hrn_to_urn(slice_hrn, 'slice') \
358 for slice_hrn in slice_hrns]
362 #logger.debug ("SlabDriver.list_slices stores value in cache")
363 #self.cache.add('slices', slice_urns)
367 #No site or node register supported
368 def register (self, sfa_record, hrn, pub_key):
369 record_type = sfa_record['type']
370 slab_record = self.sfa_fields_to_slab_fields(record_type, hrn, \
374 if record_type == 'slice':
375 acceptable_fields = ['url', 'instantiation', 'name', 'description']
376 for key in slab_record.keys():
377 if key not in acceptable_fields:
379 logger.debug("SLABDRIVER.PY register")
380 slices = self.GetSlices(slice_filter =slab_record['hrn'], \
381 slice_filter_type = 'slice_hrn')
383 pointer = self.AddSlice(slab_record)
385 pointer = slices[0]['slice_id']
387 elif record_type == 'user':
388 persons = self.GetPersons([sfa_record])
389 #persons = self.GetPersons([sfa_record['hrn']])
391 pointer = self.AddPerson(dict(sfa_record))
394 pointer = persons[0]['person_id']
396 #Does this make sense to senslab ?
397 #if 'enabled' in sfa_record and sfa_record['enabled']:
398 #self.UpdatePerson(pointer, \
399 #{'enabled': sfa_record['enabled']})
401 #TODO register Change this AddPersonToSite stuff 05/07/2012 SA
402 # add this person to the site only if
403 # she is being added for the first
404 # time by sfa and doesnt already exist in plc
405 if not persons or not persons[0]['site_ids']:
406 login_base = get_leaf(sfa_record['authority'])
407 self.AddPersonToSite(pointer, login_base)
409 # What roles should this user have?
410 #TODO : DElete this AddRoleToPerson 04/07/2012 SA
411 #Function prototype is :
412 #AddRoleToPerson(self, auth, role_id_or_name, person_id_or_email)
413 #what's the pointer doing here?
414 self.AddRoleToPerson('user', pointer)
417 self.AddPersonKey(pointer, {'key_type' : 'ssh', \
420 #No node adding outside OAR
424 #No site or node record update allowed
425 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
426 pointer = old_sfa_record['pointer']
427 old_sfa_record_type = old_sfa_record['type']
429 # new_key implemented for users only
430 if new_key and old_sfa_record_type not in [ 'user' ]:
431 raise UnknownSfaType(old_sfa_record_type)
433 #if (type == "authority"):
434 #self.shell.UpdateSite(pointer, new_sfa_record)
436 if old_sfa_record_type == "slice":
437 slab_record = self.sfa_fields_to_slab_fields(old_sfa_record_type, \
439 if 'name' in slab_record:
440 slab_record.pop('name')
441 #Prototype should be UpdateSlice(self,
442 #auth, slice_id_or_name, slice_fields)
443 #Senslab cannot update slice since slice = job
444 #so we must delete and create another job
445 self.UpdateSlice(pointer, slab_record)
447 elif old_sfa_record_type == "user":
449 all_fields = new_sfa_record
450 for key in all_fields.keys():
451 if key in ['first_name', 'last_name', 'title', 'email',
452 'password', 'phone', 'url', 'bio', 'accepted_aup',
454 update_fields[key] = all_fields[key]
455 self.UpdatePerson(pointer, update_fields)
458 # must check this key against the previous one if it exists
459 persons = self.GetPersons([pointer], ['key_ids'])
461 keys = person['key_ids']
462 keys = self.GetKeys(person['key_ids'])
464 # Delete all stale keys
467 if new_key != key['key']:
468 self.DeleteKey(key['key_id'])
472 self.AddPersonKey(pointer, {'key_type': 'ssh', \
479 def remove (self, sfa_record):
480 sfa_record_type = sfa_record['type']
481 hrn = sfa_record['hrn']
482 if sfa_record_type == 'user':
484 #get user from senslab ldap
485 person = self.GetPersons(sfa_record)
486 #No registering at a given site in Senslab.
487 #Once registered to the LDAP, all senslab sites are
490 #Mark account as disabled in ldap
491 self.DeletePerson(sfa_record)
492 elif sfa_record_type == 'slice':
493 if self.GetSlices(slice_filter = hrn, \
494 slice_filter_type = 'slice_hrn'):
495 self.DeleteSlice(sfa_record)
497 #elif type == 'authority':
498 #if self.GetSites(pointer):
499 #self.DeleteSite(pointer)
505 #TODO clean GetPeers. 05/07/12SA
506 def GetPeers (self, auth = None, peer_filter=None, return_fields_list=None):
508 existing_records = {}
509 existing_hrns_by_types = {}
510 logger.debug("SLABDRIVER \tGetPeers auth = %s, peer_filter %s, \
511 return_field %s " %(auth , peer_filter, return_fields_list))
512 all_records = dbsession.query(RegRecord).filter(RegRecord.type.like('%authority%')).all()
513 for record in all_records:
514 existing_records[(record.hrn, record.type)] = record
515 if record.type not in existing_hrns_by_types:
516 existing_hrns_by_types[record.type] = [record.hrn]
517 logger.debug("SLABDRIVER \tGetPeer\t NOT IN \
518 existing_hrns_by_types %s " %( existing_hrns_by_types))
521 logger.debug("SLABDRIVER \tGetPeer\t \INNN type %s hrn %s " \
522 %(record.type,record.hrn))
523 existing_hrns_by_types[record.type].append(record.hrn)
526 logger.debug("SLABDRIVER \tGetPeer\texisting_hrns_by_types %s "\
527 %( existing_hrns_by_types))
532 records_list.append(existing_records[(peer_filter,'authority')])
534 for hrn in existing_hrns_by_types['authority']:
535 records_list.append(existing_records[(hrn,'authority')])
537 logger.debug("SLABDRIVER \tGetPeer \trecords_list %s " \
543 return_records = records_list
544 if not peer_filter and not return_fields_list:
548 logger.debug("SLABDRIVER \tGetPeer return_records %s " \
550 return return_records
553 #TODO : Handling OR request in make_ldap_filters_from_records
554 #instead of the for loop
555 #over the records' list
556 def GetPersons(self, person_filter=None):
558 person_filter should be a list of dictionnaries when not set to None.
559 Returns a list of users whose accounts are enabled found in ldap.
562 logger.debug("SLABDRIVER \tGetPersons person_filter %s" \
565 if person_filter and isinstance(person_filter, list):
566 #If we are looking for a list of users (list of dict records)
567 #Usually the list contains only one user record
568 for searched_attributes in person_filter:
570 #Get only enabled user accounts in senslab LDAP :
571 #add a filter for make_ldap_filters_from_record
572 person = self.ldap.LdapFindUser(searched_attributes, \
573 is_user_enabled=True)
574 person_list.append(person)
577 #Get only enabled user accounts in senslab LDAP :
578 #add a filter for make_ldap_filters_from_record
579 person_list = self.ldap.LdapFindUser(is_user_enabled=True)
583 def GetTimezone(self):
584 server_timestamp, server_tz = self.oar.parser.\
585 SendRequest("GET_timezone")
586 return server_timestamp, server_tz
589 def DeleteJobs(self, job_id, slice_hrn):
590 if not job_id or job_id is -1:
592 username = slice_hrn.split(".")[-1].rstrip("_slice")
594 reqdict['method'] = "delete"
595 reqdict['strval'] = str(job_id)
598 answer = self.oar.POSTRequestToOARRestAPI('DELETE_jobs_id', \
600 logger.debug("SLABDRIVER \tDeleteJobs jobid %s \r\n answer %s \
601 username %s" %(job_id,answer, username))
606 ##TODO : Unused GetJobsId ? SA 05/07/12
607 #def GetJobsId(self, job_id, username = None ):
609 #Details about a specific job.
610 #Includes details about submission time, jot type, state, events,
611 #owner, assigned ressources, walltime etc...
615 #node_list_k = 'assigned_network_address'
616 ##Get job info from OAR
617 #job_info = self.oar.parser.SendRequest(req, job_id, username)
619 #logger.debug("SLABDRIVER \t GetJobsId %s " %(job_info))
621 #if job_info['state'] == 'Terminated':
622 #logger.debug("SLABDRIVER \t GetJobsId job %s TERMINATED"\
625 #if job_info['state'] == 'Error':
626 #logger.debug("SLABDRIVER \t GetJobsId ERROR message %s "\
631 #logger.error("SLABDRIVER \tGetJobsId KeyError")
634 #parsed_job_info = self.get_info_on_reserved_nodes(job_info, \
636 ##Replaces the previous entry
637 ##"assigned_network_address" / "reserved_resources"
639 #job_info.update({'node_ids':parsed_job_info[node_list_k]})
640 #del job_info[node_list_k]
641 #logger.debug(" \r\nSLABDRIVER \t GetJobsId job_info %s " %(job_info))
645 def GetJobsResources(self, job_id, username = None):
646 #job_resources=['reserved_resources', 'assigned_resources',\
647 #'job_id', 'job_uri', 'assigned_nodes',\
649 #assigned_res = ['resource_id', 'resource_uri']
650 #assigned_n = ['node', 'node_uri']
652 req = "GET_jobs_id_resources"
655 #Get job resources list from OAR
656 node_id_list = self.oar.parser.SendRequest(req, job_id, username)
657 logger.debug("SLABDRIVER \t GetJobsResources %s " %(node_id_list))
660 self.__get_hostnames_from_oar_node_ids(node_id_list)
663 #Replaces the previous entry "assigned_network_address" /
664 #"reserved_resources"
666 job_info = {'node_ids': hostname_list}
671 def get_info_on_reserved_nodes(self, job_info, node_list_name):
672 #Get the list of the testbed nodes records and make a
673 #dictionnary keyed on the hostname out of it
674 node_list_dict = self.GetNodes()
675 #node_hostname_list = []
676 node_hostname_list = [node['hostname'] for node in node_list_dict]
677 #for node in node_list_dict:
678 #node_hostname_list.append(node['hostname'])
679 node_dict = dict(zip(node_hostname_list, node_list_dict))
681 reserved_node_hostname_list = []
682 for index in range(len(job_info[node_list_name])):
683 #job_info[node_list_name][k] =
684 reserved_node_hostname_list[index] = \
685 node_dict[job_info[node_list_name][index]]['hostname']
687 logger.debug("SLABDRIVER \t get_info_on_reserved_nodes \
688 reserved_node_hostname_list %s" \
689 %(reserved_node_hostname_list))
691 logger.error("SLABDRIVER \t get_info_on_reserved_nodes KEYERROR " )
693 return reserved_node_hostname_list
695 def GetNodesCurrentlyInUse(self):
696 """Returns a list of all the nodes already involved in an oar job"""
697 return self.oar.parser.SendRequest("GET_running_jobs")
699 def __get_hostnames_from_oar_node_ids(self, resource_id_list ):
700 full_nodes_dict_list = self.GetNodes()
701 #Put the full node list into a dictionary keyed by oar node id
702 oar_id_node_dict = {}
703 for node in full_nodes_dict_list:
704 oar_id_node_dict[node['oar_id']] = node
706 logger.debug("SLABDRIVER \t __get_hostnames_from_oar_node_ids\
707 oar_id_node_dict %s" %(oar_id_node_dict))
709 hostname_dict_list = []
710 for resource_id in resource_id_list:
711 #Because jobs requested "asap" do not have defined resources
712 if resource_id is not "Undefined":
713 hostname_dict_list.append({'hostname' : \
714 oar_id_node_dict[resource_id]['hostname'],
715 'site_id' : oar_id_node_dict[resource_id]['site']})
717 #hostname_list.append(oar_id_node_dict[resource_id]['hostname'])
718 return hostname_dict_list
720 def GetReservedNodes(self,username = None):
721 #Get the nodes in use and the reserved nodes
722 reservation_dict_list = \
723 self.oar.parser.SendRequest("GET_reserved_nodes", username = username)
726 for resa in reservation_dict_list:
727 logger.debug ("GetReservedNodes resa %s"%(resa))
728 #dict list of hostnames and their site
729 resa['reserved_nodes'] = \
730 self.__get_hostnames_from_oar_node_ids(resa['resource_ids'])
732 #del resa['resource_ids']
733 return reservation_dict_list
735 def GetNodes(self, node_filter_dict = None, return_fields_list = None):
737 node_filter_dict : dictionnary of lists
740 node_dict_by_id = self.oar.parser.SendRequest("GET_resources_full")
741 node_dict_list = node_dict_by_id.values()
743 #No filtering needed return the list directly
744 if not (node_filter_dict or return_fields_list):
745 return node_dict_list
747 return_node_list = []
749 for filter_key in node_filter_dict:
751 #Filter the node_dict_list by each value contained in the
752 #list node_filter_dict[filter_key]
753 for value in node_filter_dict[filter_key]:
754 for node in node_dict_list:
755 if node[filter_key] == value:
756 if return_fields_list :
758 for k in return_fields_list:
760 return_node_list.append(tmp)
762 return_node_list.append(node)
764 logger.log_exc("GetNodes KeyError")
768 return return_node_list
771 def GetSites(self, site_filter_name_list = None, return_fields_list = None):
772 site_dict = self.oar.parser.SendRequest("GET_sites")
773 #site_dict : dict where the key is the sit ename
774 return_site_list = []
775 if not ( site_filter_name_list or return_fields_list):
776 return_site_list = site_dict.values()
777 return return_site_list
779 for site_filter_name in site_filter_name_list:
780 if site_filter_name in site_dict:
781 if return_fields_list:
782 for field in return_fields_list:
785 tmp[field] = site_dict[site_filter_name][field]
787 logger.error("GetSites KeyError %s "%(field))
789 return_site_list.append(tmp)
791 return_site_list.append( site_dict[site_filter_name])
794 return return_site_list
798 def GetSlices(self, slice_filter = None, slice_filter_type = None):
799 #def GetSlices(self, slice_filter = None, slice_filter_type = None, \
800 #return_fields_list = None):
801 """ Get the slice records from the slab db.
802 Returns a slice ditc if slice_filter and slice_filter_type
804 Returns a list of slice dictionnaries if there are no filters
809 return_slice_list = []
812 authorized_filter_types_list = ['slice_hrn', 'record_id_user']
813 slicerec_dictlist = []
816 if slice_filter_type in authorized_filter_types_list:
819 def __get_slice_records(slice_filter = None, slice_filter_type = None):
822 #Get list of slices based on the slice hrn
823 if slice_filter_type == 'slice_hrn':
825 login = slice_filter.split(".")[1].split("_")[0]
827 #DO NOT USE RegSlice - reg_researchers to get the hrn of the user
828 #otherwise will mess up the RegRecord in Resolve, don't know
831 #Only one entry for one user = one slice in slice_senslab table
832 slicerec = slab_dbsession.query(SliceSenslab).filter_by(slice_hrn = slice_filter).first()
834 #Get slice based on user id
835 if slice_filter_type == 'record_id_user':
836 slicerec = slab_dbsession.query(SliceSenslab).filter_by(record_id_user = slice_filter).first()
841 fixed_slicerec_dict = slicerec.dump_sqlalchemyobj_to_dict()
844 login = fixed_slicerec_dict['slice_hrn'].split(".")[1].split("_")[0]
845 return login, fixed_slicerec_dict
850 login, fixed_slicerec_dict = __get_slice_records(slice_filter, slice_filter_type)
851 logger.debug(" SLABDRIVER \tGetSlices login %s \
853 %(login, fixed_slicerec_dict))
857 #One slice can have multiple jobs
859 leases_list = self.GetReservedNodes(username = login)
860 #If no job is running or no job scheduled
861 if leases_list == [] :
862 return [fixed_slicerec_dict]
864 #Several jobs for one slice
865 for lease in leases_list :
869 #Check with OAR the status of the job if a job id is in
874 slicerec_dict['oar_job_id'] = lease['lease_id']
875 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
876 slicerec_dict.update(fixed_slicerec_dict)
877 slicerec_dict.update({'hrn':\
878 str(fixed_slicerec_dict['slice_hrn'])})
881 slicerec_dictlist.append(slicerec_dict)
882 logger.debug("SLABDRIVER.PY \tGetSlices slicerec_dict %s slicerec_dictlist %s" %(slicerec_dict, slicerec_dictlist))
884 logger.debug("SLABDRIVER.PY \tGetSlices RETURN slicerec_dictlist %s"\
885 %(slicerec_dictlist))
887 return slicerec_dictlist
892 slice_list = slab_dbsession.query(SliceSenslab).all()
893 leases_list = self.GetReservedNodes()
896 slicerec_dictlist = []
897 return_slice_list = []
898 for record in slice_list:
899 return_slice_list.append(record.dump_sqlalchemyobj_to_dict())
901 for fixed_slicerec_dict in return_slice_list:
903 owner = fixed_slicerec_dict['slice_hrn'].split(".")[1].split("_")[0]
904 for lease in leases_list:
905 if owner == lease['user']:
906 slicerec_dict['oar_job_id'] = lease['lease_id']
907 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
908 slicerec_dict.update(fixed_slicerec_dict)
909 slicerec_dict.update({'hrn':\
910 str(fixed_slicerec_dict['slice_hrn'])})
911 slicerec_dictlist.append(slicerec_dict)
913 logger.debug("SLABDRIVER.PY \tGetSlices RETURN slices %s \
914 slice_filter %s " %(return_slice_list, slice_filter))
916 #if return_fields_list:
917 #return_slice_list = parse_filter(sliceslist, \
918 #slice_filter,'slice', return_fields_list)
920 return slicerec_dictlist
923 def testbed_name (self): return self.hrn
925 # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
926 def aggregate_version (self):
927 version_manager = VersionManager()
928 ad_rspec_versions = []
929 request_rspec_versions = []
930 for rspec_version in version_manager.versions:
931 if rspec_version.content_type in ['*', 'ad']:
932 ad_rspec_versions.append(rspec_version.to_dict())
933 if rspec_version.content_type in ['*', 'request']:
934 request_rspec_versions.append(rspec_version.to_dict())
936 'testbed':self.testbed_name(),
937 'geni_request_rspec_versions': request_rspec_versions,
938 'geni_ad_rspec_versions': ad_rspec_versions,
947 # Convert SFA fields to PLC fields for use when registering up updating
948 # registry record in the PLC database
950 # @param type type of record (user, slice, ...)
951 # @param hrn human readable name
952 # @param sfa_fields dictionary of SFA fields
953 # @param slab_fields dictionary of PLC fields (output)
955 def sfa_fields_to_slab_fields(self, sfa_type, hrn, record):
959 #for field in record:
960 # slab_record[field] = record[field]
962 if sfa_type == "slice":
963 #instantion used in get_slivers ?
964 if not "instantiation" in slab_record:
965 slab_record["instantiation"] = "senslab-instantiated"
966 #slab_record["hrn"] = hrn_to_pl_slicename(hrn)
967 #Unused hrn_to_pl_slicename because Slab's hrn already in the appropriate form SA 23/07/12
968 slab_record["hrn"] = hrn
969 logger.debug("SLABDRIVER.PY sfa_fields_to_slab_fields \
970 slab_record %s " %(slab_record['hrn']))
972 slab_record["url"] = record["url"]
973 if "description" in record:
974 slab_record["description"] = record["description"]
975 if "expires" in record:
976 slab_record["expires"] = int(record["expires"])
978 #nodes added by OAR only and then imported to SFA
979 #elif type == "node":
980 #if not "hostname" in slab_record:
981 #if not "hostname" in record:
982 #raise MissingSfaInfo("hostname")
983 #slab_record["hostname"] = record["hostname"]
984 #if not "model" in slab_record:
985 #slab_record["model"] = "geni"
988 #elif type == "authority":
989 #slab_record["login_base"] = hrn_to_slab_login_base(hrn)
991 #if not "name" in slab_record:
992 #slab_record["name"] = hrn
994 #if not "abbreviated_name" in slab_record:
995 #slab_record["abbreviated_name"] = hrn
997 #if not "enabled" in slab_record:
998 #slab_record["enabled"] = True
1000 #if not "is_public" in slab_record:
1001 #slab_record["is_public"] = True
1008 def __transforms_timestamp_into_date(self, xp_utc_timestamp = None):
1009 """ Transforms unix timestamp into valid OAR date format """
1011 #Used in case of a scheduled experiment (not immediate)
1012 #To run an XP immediately, don't specify date and time in RSpec
1013 #They will be set to None.
1014 if xp_utc_timestamp:
1015 #transform the xp_utc_timestamp into server readable time
1016 xp_server_readable_date = datetime.fromtimestamp(int(\
1017 xp_utc_timestamp)).strftime(self.time_format)
1019 return xp_server_readable_date
1027 def LaunchExperimentOnOAR(self, added_nodes, slice_name, \
1028 lease_start_time, lease_duration, slice_user=None):
1030 lease_dict['lease_start_time'] = lease_start_time
1031 lease_dict['lease_duration'] = lease_duration
1032 lease_dict['added_nodes'] = added_nodes
1033 lease_dict['slice_name'] = slice_name
1034 lease_dict['slice_user'] = slice_user
1035 lease_dict['grain'] = self.GetLeaseGranularity()
1036 lease_dict['time_format'] = self.time_format
1038 def __create_job_structure_request_for_OAR(lease_dict):
1039 """ Creates the structure needed for a correct POST on OAR.
1040 Makes the timestamp transformation into the appropriate format.
1041 Sends the POST request to create the job with the resources in
1050 reqdict['workdir'] = '/tmp'
1051 reqdict['resource'] = "{network_address in ("
1053 for node in lease_dict['added_nodes']:
1054 logger.debug("\r\n \r\n OARrestapi \t __create_job_structure_request_for_OAR \
1057 # Get the ID of the node
1059 reqdict['resource'] += "'" + nodeid + "', "
1060 nodeid_list.append(nodeid)
1062 custom_length = len(reqdict['resource'])- 2
1063 reqdict['resource'] = reqdict['resource'][0:custom_length] + \
1064 ")}/nodes=" + str(len(nodeid_list))
1066 def __process_walltime(duration):
1067 """ Calculates the walltime in seconds from the duration in H:M:S
1068 specified in the RSpec.
1072 # Fixing the walltime by adding a few delays.
1073 # First put the walltime in seconds oarAdditionalDelay = 20;
1074 # additional delay for /bin/sleep command to
1075 # take in account prologue and epilogue scripts execution
1076 # int walltimeAdditionalDelay = 120; additional delay
1077 desired_walltime = duration
1078 total_walltime = desired_walltime + 140#+2 min 20
1079 sleep_walltime = desired_walltime + 20 #+20 sec
1081 #Put the walltime back in str form
1082 #First get the hours
1083 walltime.append(str(total_walltime / 3600))
1084 total_walltime = total_walltime - 3600 * int(walltime[0])
1085 #Get the remaining minutes
1086 walltime.append(str(total_walltime / 60))
1087 total_walltime = total_walltime - 60 * int(walltime[1])
1089 walltime.append(str(total_walltime))
1092 logger.log_exc(" __process_walltime duration null")
1094 return walltime, sleep_walltime
1097 walltime, sleep_walltime = \
1098 __process_walltime(int(lease_dict['lease_duration'])*lease_dict['grain'])
1101 reqdict['resource'] += ",walltime=" + str(walltime[0]) + \
1102 ":" + str(walltime[1]) + ":" + str(walltime[2])
1103 reqdict['script_path'] = "/bin/sleep " + str(sleep_walltime)
1105 #In case of a scheduled experiment (not immediate)
1106 #To run an XP immediately, don't specify date and time in RSpec
1107 #They will be set to None.
1108 if lease_dict['lease_start_time'] is not '0':
1109 #Readable time accepted by OAR
1110 start_time = datetime.fromtimestamp(int(lease_dict['lease_start_time'])).\
1111 strftime(lease_dict['time_format'])
1112 reqdict['reservation'] = start_time
1113 #If there is not start time, Immediate XP. No need to add special
1117 reqdict['type'] = "deploy"
1118 reqdict['directory'] = ""
1119 reqdict['name'] = "SFA_" + lease_dict['slice_user']
1124 #Create the request for OAR
1125 reqdict = __create_job_structure_request_for_OAR(lease_dict)
1126 # first step : start the OAR job and update the job
1127 logger.debug("SLABDRIVER.PY \tLaunchExperimentOnOAR reqdict %s\
1130 answer = self.oar.POSTRequestToOARRestAPI('POST_job', \
1131 reqdict, slice_user)
1132 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s " %(answer))
1134 jobid = answer['id']
1136 logger.log_exc("SLABDRIVER \tLaunchExperimentOnOAR \
1137 Impossible to create job %s " %(answer))
1141 def __configure_experiment(jobid, added_nodes):
1142 # second step : configure the experiment
1143 # we need to store the nodes in a yaml (well...) file like this :
1144 # [1,56,23,14,45,75] with name /tmp/sfa<jobid>.json
1145 job_file = open('/tmp/sfa/'+ str(jobid) + '.json', 'w')
1147 job_file.write(str(added_nodes[0].strip('node')))
1148 for node in added_nodes[1:len(added_nodes)] :
1149 job_file.write(', '+ node.strip('node'))
1154 def __launch_senslab_experiment(jobid):
1155 # third step : call the senslab-experiment wrapper
1156 #command= "java -jar target/sfa-1.0-jar-with-dependencies.jar
1157 # "+str(jobid)+" "+slice_user
1158 javacmdline = "/usr/bin/java"
1160 "/opt/senslabexperimentwrapper/sfa-1.0-jar-with-dependencies.jar"
1161 #ret=subprocess.check_output(["/usr/bin/java", "-jar", ", \
1162 #str(jobid), slice_user])
1163 output = subprocess.Popen([javacmdline, "-jar", jarname, str(jobid), \
1164 slice_user],stdout=subprocess.PIPE).communicate()[0]
1166 logger.debug("SLABDRIVER \t __configure_experiment wrapper returns%s " \
1173 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s \
1174 added_nodes %s slice_user %s" %(jobid, added_nodes, slice_user))
1177 __configure_experiment(jobid, added_nodes)
1178 __launch_senslab_experiment(jobid)
1182 def AddLeases(self, hostname_list, slice_record, lease_start_time, lease_duration):
1183 logger.debug("SLABDRIVER \r\n \r\n \t AddLeases hostname_list %s \
1184 slice_record %s lease_start_time %s lease_duration %s "\
1185 %( hostname_list, slice_record , lease_start_time, \
1188 tmp = slice_record['PI'][0].split(".")
1189 username = tmp[(len(tmp)-1)]
1190 self.LaunchExperimentOnOAR(hostname_list, slice_record['name'], lease_start_time, lease_duration, username)
1191 start_time = datetime.fromtimestamp(int(lease_start_time)).strftime(self.time_format)
1192 logger.debug("SLABDRIVER \t AddLeases hostname_list start_time %s " %(start_time))
1197 #Delete the jobs from job_senslab table
1198 def DeleteSliceFromNodes(self, slice_record):
1200 self.DeleteJobs(slice_record['oar_job_id'], slice_record['hrn'])
1204 def GetLeaseGranularity(self):
1205 """ Returns the granularity of Senslab testbed.
1206 Defined in seconds. """
1211 def GetLeases(self, lease_filter_dict=None):
1212 unfiltered_reservation_list = self.GetReservedNodes()
1214 ##Synchronize slice_table of sfa senslab db
1215 #self.synchronize_oar_and_slice_table(unfiltered_reservation_list)
1217 reservation_list = []
1218 #Find the slice associated with this user senslab ldap uid
1219 logger.debug(" SLABDRIVER.PY \tGetLeases ")
1220 #Create user dict first to avoir looking several times for
1221 #the same user in LDAP SA 27/07/12
1223 for resa in unfiltered_reservation_list:
1224 logger.debug("SLABDRIVER \tGetLeases USER %s"\
1226 if resa['user'] not in resa_user_dict:
1227 logger.debug("SLABDRIVER \tGetLeases userNOTIN ")
1228 ldap_info = self.ldap.LdapSearch('(uid='+resa['user']+')')
1229 ldap_info = ldap_info[0][1]
1230 user = dbsession.query(RegUser).filter_by(email = \
1231 ldap_info['mail'][0]).first()
1232 #Separated in case user not in database : record_id not defined SA 17/07//12
1233 query_slice_info = slab_dbsession.query(SliceSenslab).filter_by(record_id_user = user.record_id)
1234 if query_slice_info:
1235 slice_info = query_slice_info.first()
1239 resa_user_dict[resa['user']] = {}
1240 resa_user_dict[resa['user']]['ldap_info'] = user
1241 resa_user_dict[resa['user']]['slice_info'] = slice_info
1243 logger.debug("SLABDRIVER \tGetLeases resa_user_dict %s"\
1245 for resa in unfiltered_reservation_list:
1249 resa['slice_hrn'] = resa_user_dict[resa['user']]['slice_info'].slice_hrn
1250 resa['slice_id'] = hrn_to_urn(resa['slice_hrn'], 'slice')
1252 #resa['slice_id'] = hrn_to_urn(slice_info.slice_hrn, 'slice')
1253 resa['component_id_list'] = []
1254 #Transform the hostnames into urns (component ids)
1255 for node in resa['reserved_nodes']:
1256 #resa['component_id_list'].append(hostname_to_urn(self.hrn, \
1257 #self.root_auth, node['hostname']))
1258 slab_xrn = slab_xrn_object(self.root_auth, node['hostname'])
1259 resa['component_id_list'].append(slab_xrn.urn)
1261 #Filter the reservation list if necessary
1262 #Returns all the leases associated with a given slice
1263 if lease_filter_dict:
1264 logger.debug("SLABDRIVER \tGetLeases lease_filter_dict %s"\
1265 %(lease_filter_dict))
1266 for resa in unfiltered_reservation_list:
1267 if lease_filter_dict['name'] == resa['slice_hrn']:
1268 reservation_list.append(resa)
1270 reservation_list = unfiltered_reservation_list
1272 logger.debug(" SLABDRIVER.PY \tGetLeases reservation_list %s"\
1273 %(reservation_list))
1274 return reservation_list
1276 def augment_records_with_testbed_info (self, sfa_records):
1277 return self.fill_record_info (sfa_records)
1279 def fill_record_info(self, record_list):
1281 Given a SFA record, fill in the senslab specific and SFA specific
1282 fields in the record.
1285 logger.debug("SLABDRIVER \tfill_record_info records %s " %(record_list))
1286 if not isinstance(record_list, list):
1287 record_list = [record_list]
1290 for record in record_list:
1291 #If the record is a SFA slice record, then add information
1292 #about the user of this slice. This kind of
1293 #information is in the Senslab's DB.
1294 if str(record['type']) == 'slice':
1295 #Get slab slice record.
1296 recslice_list = self.GetSlices(slice_filter = \
1297 str(record['hrn']),\
1298 slice_filter_type = 'slice_hrn')
1300 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1301 recslice_list[0]['record_id_user']).first()
1302 logger.debug("SLABDRIVER \tfill_record_info TYPE SLICE RECUSER %s " %(recuser))
1303 record.update({'PI':[recuser.hrn],
1304 'researcher': [recuser.hrn],
1305 'name':record['hrn'],
1306 'oar_job_id':[rec['oar_job_id'] for rec in recslice_list],
1308 'person_ids':[recslice_list[0]['record_id_user']],
1309 'geni_urn':'', #For client_helper.py compatibility
1310 'keys':'', #For client_helper.py compatibility
1311 'key_ids':''}) #For client_helper.py compatibility
1313 #for rec in recslice_list:
1314 #record['oar_job_id'].append(rec['oar_job_id'])
1315 logger.debug( "SLABDRIVER.PY \t fill_record_info SLICE \
1316 recslice_list %s \r\n \t RECORD %s \r\n \r\n" %(recslice_list,record))
1317 if str(record['type']) == 'user':
1318 #The record is a SFA user record.
1319 #Get the information about his slice from Senslab's DB
1320 #and add it to the user record.
1321 recslice_list = self.GetSlices(\
1322 slice_filter = record['record_id'],\
1323 slice_filter_type = 'record_id_user')
1325 logger.debug( "SLABDRIVER.PY \t fill_record_info TYPE USER \
1326 recslice_list %s \r\n \t RECORD %s \r\n" %(recslice_list , record))
1327 #Append slice record in records list,
1328 #therefore fetches user and slice info again(one more loop)
1329 #Will update PIs and researcher for the slice
1330 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1331 recslice_list[0]['record_id_user']).first()
1332 logger.debug( "SLABDRIVER.PY \t fill_record_info USER \
1333 recuser %s \r\n \r\n" %(recuser))
1335 recslice = recslice_list[0]
1336 recslice.update({'PI':[recuser.hrn],
1337 'researcher': [recuser.hrn],
1338 'name':record['hrn'],
1340 'oar_job_id': [rec['oar_job_id'] for rec in recslice_list],
1341 'person_ids':[recslice_list[0]['record_id_user']]})
1342 recslice.update({'type':'slice', \
1343 'hrn':recslice_list[0]['slice_hrn']})
1344 #for rec in recslice_list:
1345 #recslice['oar_job_id'].append(rec['oar_job_id'])
1347 #GetPersons takes [] as filters
1348 #user_slab = self.GetPersons([{'hrn':recuser.hrn}])
1349 user_slab = self.GetPersons([record])
1352 record.update(user_slab[0])
1353 #For client_helper.py compatibility
1354 record.update( { 'geni_urn':'',
1357 record_list.append(recslice)
1359 logger.debug("SLABDRIVER.PY \tfill_record_info ADDING SLICE\
1360 INFO TO USER records %s" %(record_list))
1361 logger.debug("SLABDRIVER.PY \tfill_record_info END \
1362 #record %s \r\n \r\n " %(record))
1364 except TypeError, error:
1365 logger.log_exc("SLABDRIVER \t fill_record_info EXCEPTION %s"\
1367 #logger.debug("SLABDRIVER.PY \t fill_record_info ENDENDEND ")
1371 #self.fill_record_slab_info(records)
1377 #TODO Update membership? update_membership_list SA 05/07/12
1378 #def update_membership_list(self, oldRecord, record, listName, addFunc, \
1380 ## get a list of the HRNs tht are members of the old and new records
1382 #oldList = oldRecord.get(listName, [])
1385 #newList = record.get(listName, [])
1387 ## if the lists are the same, then we don't have to update anything
1388 #if (oldList == newList):
1391 ## build a list of the new person ids, by looking up each person to get
1395 #records = table.find({'type': 'user', 'hrn': newList})
1396 #for rec in records:
1397 #newIdList.append(rec['pointer'])
1399 ## build a list of the old person ids from the person_ids field
1401 #oldIdList = oldRecord.get("person_ids", [])
1402 #containerId = oldRecord.get_pointer()
1404 ## if oldRecord==None, then we are doing a Register, instead of an
1407 #containerId = record.get_pointer()
1409 ## add people who are in the new list, but not the oldList
1410 #for personId in newIdList:
1411 #if not (personId in oldIdList):
1412 #addFunc(self.plauth, personId, containerId)
1414 ## remove people who are in the old list, but not the new list
1415 #for personId in oldIdList:
1416 #if not (personId in newIdList):
1417 #delFunc(self.plauth, personId, containerId)
1419 #def update_membership(self, oldRecord, record):
1421 #if record.type == "slice":
1422 #self.update_membership_list(oldRecord, record, 'researcher',
1423 #self.users.AddPersonToSlice,
1424 #self.users.DeletePersonFromSlice)
1425 #elif record.type == "authority":
1430 # I don't think you plan on running a component manager at this point
1431 # let me clean up the mess of ComponentAPI that is deprecated anyways
1434 #TODO FUNCTIONS SECTION 04/07/2012 SA
1436 #TODO : Is UnBindObjectFromPeer still necessary ? Currently does nothing
1438 def UnBindObjectFromPeer(self, auth, object_type, object_id, shortname):
1439 """ This method is a hopefully temporary hack to let the sfa correctly
1440 detach the objects it creates from a remote peer object. This is
1441 needed so that the sfa federation link can work in parallel with
1442 RefreshPeer, as RefreshPeer depends on remote objects being correctly
1445 auth : struct, API authentication structure
1446 AuthMethod : string, Authentication method to use
1447 object_type : string, Object type, among 'site','person','slice',
1449 object_id : int, object_id
1450 shortname : string, peer shortname
1454 logger.warning("SLABDRIVER \tUnBindObjectFromPeer EMPTY-\
1458 #TODO Is BindObjectToPeer still necessary ? Currently does nothing
1460 def BindObjectToPeer(self, auth, object_type, object_id, shortname=None, \
1461 remote_object_id=None):
1462 """This method is a hopefully temporary hack to let the sfa correctly
1463 attach the objects it creates to a remote peer object. This is needed
1464 so that the sfa federation link can work in parallel with RefreshPeer,
1465 as RefreshPeer depends on remote objects being correctly marked.
1467 shortname : string, peer shortname
1468 remote_object_id : int, remote object_id, set to 0 if unknown
1472 logger.warning("SLABDRIVER \tBindObjectToPeer EMPTY - DO NOTHING \r\n ")
1475 #TODO UpdateSlice 04/07/2012 SA
1476 #Funciton should delete and create another job since oin senslab slice=job
1477 def UpdateSlice(self, auth, slice_id_or_name, slice_fields=None):
1478 """Updates the parameters of an existing slice with the values in
1480 Users may only update slices of which they are members.
1481 PIs may update any of the slices at their sites, or any slices of
1482 which they are members. Admins may update any slice.
1483 Only PIs and admins may update max_nodes. Slices cannot be renewed
1484 (by updating the expires parameter) more than 8 weeks into the future.
1485 Returns 1 if successful, faults otherwise.
1489 logger.warning("SLABDRIVER UpdateSlice EMPTY - DO NOTHING \r\n ")
1492 #TODO UpdatePerson 04/07/2012 SA
1493 def UpdatePerson(self, auth, person_id_or_email, person_fields=None):
1494 """Updates a person. Only the fields specified in person_fields
1495 are updated, all other fields are left untouched.
1496 Users and techs can only update themselves. PIs can only update
1497 themselves and other non-PIs at their sites.
1498 Returns 1 if successful, faults otherwise.
1502 logger.warning("SLABDRIVER UpdatePerson EMPTY - DO NOTHING \r\n ")
1505 #TODO GetKeys 04/07/2012 SA
1506 def GetKeys(self, auth, key_filter=None, return_fields=None):
1507 """Returns an array of structs containing details about keys.
1508 If key_filter is specified and is an array of key identifiers,
1509 or a struct of key attributes, only keys matching the filter
1510 will be returned. If return_fields is specified, only the
1511 specified details will be returned.
1513 Admin may query all keys. Non-admins may only query their own keys.
1517 logger.warning("SLABDRIVER GetKeys EMPTY - DO NOTHING \r\n ")
1520 #TODO DeleteKey 04/07/2012 SA
1521 def DeleteKey(self, auth, key_id):
1523 Non-admins may only delete their own keys.
1524 Returns 1 if successful, faults otherwise.
1528 logger.warning("SLABDRIVER DeleteKey EMPTY - DO NOTHING \r\n ")
1532 #TODO : Check rights to delete person
1533 def DeletePerson(self, auth, person_record):
1534 """ Disable an existing account in senslab LDAP.
1535 Users and techs can only delete themselves. PIs can only
1536 delete themselves and other non-PIs at their sites.
1537 ins can delete anyone.
1538 Returns 1 if successful, faults otherwise.
1542 #Disable user account in senslab LDAP
1543 ret = self.ldap.LdapMarkUserAsDeleted(person_record)
1544 logger.warning("SLABDRIVER DeletePerson %s " %(person_record))
1547 #TODO Check DeleteSlice, check rights 05/07/2012 SA
1548 def DeleteSlice(self, auth, slice_record):
1549 """ Deletes the specified slice.
1550 Senslab : Kill the job associated with the slice if there is one
1551 using DeleteSliceFromNodes.
1552 Updates the slice record in slab db to remove the slice nodes.
1554 Users may only delete slices of which they are members. PIs may
1555 delete any of the slices at their sites, or any slices of which
1556 they are members. Admins may delete any slice.
1557 Returns 1 if successful, faults otherwise.
1561 self.DeleteSliceFromNodes(slice_record)
1562 logger.warning("SLABDRIVER DeleteSlice %s "%(slice_record))
1565 #TODO AddPerson 04/07/2012 SA
1566 def AddPerson(self, auth, person_fields=None):
1567 """Adds a new account. Any fields specified in person_fields are used,
1568 otherwise defaults are used.
1569 Accounts are disabled by default. To enable an account,
1571 Returns the new person_id (> 0) if successful, faults otherwise.
1575 logger.warning("SLABDRIVER AddPerson EMPTY - DO NOTHING \r\n ")
1578 #TODO AddPersonToSite 04/07/2012 SA
1579 def AddPersonToSite (self, auth, person_id_or_email, \
1580 site_id_or_login_base=None):
1581 """ Adds the specified person to the specified site. If the person is
1582 already a member of the site, no errors are returned. Does not change
1583 the person's primary site.
1584 Returns 1 if successful, faults otherwise.
1588 logger.warning("SLABDRIVER AddPersonToSite EMPTY - DO NOTHING \r\n ")
1591 #TODO AddRoleToPerson : Not sure if needed in senslab 04/07/2012 SA
1592 def AddRoleToPerson(self, auth, role_id_or_name, person_id_or_email):
1593 """Grants the specified role to the person.
1594 PIs can only grant the tech and user roles to users and techs at their
1595 sites. Admins can grant any role to any user.
1596 Returns 1 if successful, faults otherwise.
1600 logger.warning("SLABDRIVER AddRoleToPerson EMPTY - DO NOTHING \r\n ")
1603 #TODO AddPersonKey 04/07/2012 SA
1604 def AddPersonKey(self, auth, person_id_or_email, key_fields=None):
1605 """Adds a new key to the specified account.
1606 Non-admins can only modify their own keys.
1607 Returns the new key_id (> 0) if successful, faults otherwise.
1611 logger.warning("SLABDRIVER AddPersonKey EMPTY - DO NOTHING \r\n ")
1614 def DeleteLeases(self, leases_id_list, slice_hrn ):
1615 for job_id in leases_id_list:
1616 self.DeleteJobs(job_id, slice_hrn)
1618 logger.debug("SLABDRIVER DeleteLeases leases_id_list %s slice_hrn %s \
1619 \r\n " %(leases_id_list, slice_hrn))