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
10 from sqlalchemy.orm import joinedload
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, SenslabXP
32 from sfa.senslab.slabaggregate import SlabAggregate, slab_xrn_to_hostname, \
34 from sfa.senslab.slabslices import SlabSlices
39 # this inheritance scheme is so that the driver object can receive
40 # GetNodes or GetSites sorts of calls directly
41 # and thus minimize the differences in the managers with the pl version
42 class SlabDriver(Driver):
43 """ Senslab Driver class inherited from Driver generic class.
45 Contains methods compliant with the SFA standard and the testbed
46 infrastructure (calls to LDAP and OAR).
48 def __init__(self, config):
49 Driver.__init__ (self, config)
51 self.hrn = config.SFA_INTERFACE_HRN
52 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
84 for single_slice in slice_list:
85 for node in single_slice['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([(one_node['hostname'], one_node) \
92 for one_node in nodes_all])
96 for single_slice in slice_list:
99 top_level_status = 'empty'
102 ['geni_urn','pl_login','geni_status','geni_resources'], None)
103 result['pl_login'] = recuser.hrn
104 logger.debug("Slabdriver - sliver_status Sliver status \
105 urn %s hrn %s single_slice %s \r\n " \
106 %(slice_urn, slice_hrn, single_slice))
108 nodes_in_slice = single_slice['node_ids']
111 result['geni_status'] = top_level_status
112 result['geni_resources'] = []
115 top_level_status = 'ready'
117 #A job is running on Senslab for this slice
118 # report about the local nodes that are in the slice only
120 result['geni_urn'] = slice_urn
124 #timestamp = float(sl['startTime']) + float(sl['walltime'])
125 #result['pl_expires'] = strftime(self.time_format, \
126 #gmtime(float(timestamp)))
127 #result['slab_expires'] = strftime(self.time_format,\
128 #gmtime(float(timestamp)))
131 for node in single_slice['node_ids']:
133 #res['slab_hostname'] = node['hostname']
134 #res['slab_boot_state'] = node['boot_state']
136 res['pl_hostname'] = node['hostname']
137 res['pl_boot_state'] = \
138 nodeall_byhostname[node['hostname']]['boot_state']
139 #res['pl_last_contact'] = strftime(self.time_format, \
140 #gmtime(float(timestamp)))
141 sliver_id = Xrn(slice_urn, type='slice', \
142 id=nodeall_byhostname[node['hostname']]['node_id'], \
143 authority=self.hrn).urn
145 res['geni_urn'] = sliver_id
146 node_name = node['hostname']
147 if nodeall_byhostname[node_name]['boot_state'] == 'Alive':
149 res['geni_status'] = 'ready'
151 res['geni_status'] = 'failed'
152 top_level_status = 'failed'
154 res['geni_error'] = ''
156 resources.append(res)
158 result['geni_status'] = top_level_status
159 result['geni_resources'] = resources
160 logger.debug("SLABDRIVER \tsliver_statusresources %s res %s "\
164 def get_user(self, hrn):
165 return dbsession.query(RegRecord).filter_by(hrn = hrn).first()
168 def create_sliver (self, slice_urn, slice_hrn, creds, rspec_string, \
170 aggregate = SlabAggregate(self)
172 slices = SlabSlices(self)
173 peer = slices.get_peer(slice_hrn)
174 sfa_peer = slices.get_sfa_peer(slice_hrn)
177 if not isinstance(creds, list):
181 slice_record = users[0].get('slice_record', {})
182 logger.debug("SLABDRIVER.PY \t create_sliver \t\
183 slice_record %s \r\n \r\n users %s" \
184 %(slice_record, users))
185 slice_record['user'] = {'keys':users[0]['keys'], \
186 'email':users[0]['email'], \
187 'hrn':slice_record['reg-researchers'][0]}
189 rspec = RSpec(rspec_string)
190 logger.debug("SLABDRIVER.PY \t create_sliver \trspec.version \
191 %s slice_record %s users %s" \
192 %(rspec.version,slice_record, users))
195 # ensure site record exists?
196 # ensure slice record exists
197 #Removed options to verify_slice SA 14/08/12
198 sfa_slice = slices.verify_slice(slice_hrn, slice_record, peer, \
201 # ensure person records exists
202 #verify_persons returns added persons but since the return value
204 slices.verify_persons(slice_hrn, sfa_slice, users, peer, \
205 sfa_peer, options=options)
206 #requested_attributes returned by rspec.version.get_slice_attributes()
207 #unused, removed SA 13/08/12
208 rspec.version.get_slice_attributes()
210 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))
233 if not lease.get('lease_id'):
234 if get_authority(lease['component_id']) == self.root_auth:
235 single_requested_lease['hostname'] = \
236 slab_xrn_to_hostname(\
237 lease.get('component_id').strip())
238 single_requested_lease['start_time'] = \
239 lease.get('start_time')
240 single_requested_lease['duration'] = lease.get('duration')
242 requested_lease_list.append(single_requested_lease)
244 logger.debug("SLABDRIVER.PY \tcreate_sliver APRESLEASE" )
245 #dCreate dict of leases by start_time, regrouping nodes reserved
247 #time, for the same amount of time = one job on OAR
248 requested_job_dict = {}
249 for lease in requested_lease_list:
251 #In case it is an asap experiment start_time is empty
252 if lease['start_time'] == '':
253 lease['start_time'] = '0'
255 if lease['start_time'] not in requested_job_dict:
256 if isinstance(lease['hostname'], str):
257 lease['hostname'] = [lease['hostname']]
259 requested_job_dict[lease['start_time']] = lease
262 job_lease = requested_job_dict[lease['start_time']]
263 if lease['duration'] == job_lease['duration'] :
264 job_lease['hostname'].append(lease['hostname'])
269 logger.debug("SLABDRIVER.PY \tcreate_sliver requested_job_dict %s "\
270 %(requested_job_dict))
271 #verify_slice_leases returns the leases , but the return value is unused
272 #here. Removed SA 13/08/12
273 slices.verify_slice_leases(sfa_slice, \
274 requested_job_dict, peer)
276 return aggregate.get_rspec(slice_xrn=slice_urn, version=rspec.version)
279 def delete_sliver (self, slice_urn, slice_hrn, creds, options):
281 sfa_slice_list = self.GetSlices(slice_filter = slice_hrn, \
282 slice_filter_type = 'slice_hrn')
284 if not sfa_slice_list:
287 #Delete all in the slice
288 for sfa_slice in sfa_slice_list:
291 logger.debug("SLABDRIVER.PY delete_sliver slice %s" %(sfa_slice))
292 slices = SlabSlices(self)
293 # determine if this is a peer slice
295 peer = slices.get_peer(slice_hrn)
296 #TODO delete_sliver SA : UnBindObjectFromPeer should be
297 #used when there is another
298 #senslab testbed, which is not the case 14/08/12 .
300 logger.debug("SLABDRIVER.PY delete_sliver peer %s" %(peer))
303 self.UnBindObjectFromPeer('slice', \
304 sfa_slice['record_id_slice'], \
306 self.DeleteSliceFromNodes(sfa_slice)
309 self.BindObjectToPeer('slice', \
310 sfa_slice['record_id_slice'], \
311 peer, sfa_slice['peer_slice_id'])
315 def AddSlice(self, slice_record, user_record):
316 """Add slice to the sfa tables and senslab table only if the user
317 already exists in senslab database(user already registered in LDAP).
318 There is no way to separate adding the slice to the tesbed
319 and then importing it from the testbed to SFA because of
320 senslab's architecture. Therefore, sfa tables are updated here.
323 sfa_record = RegSlice(hrn=slice_record['slice_hrn'],
324 gid=slice_record['gid'],
325 pointer=slice_record['slice_id'],
326 authority=slice_record['authority'])
328 logger.debug("SLABDRIVER.PY AddSlice sfa_record %s user_record %s" \
329 %(sfa_record, user_record))
330 sfa_record.just_created()
331 dbsession.add(sfa_record)
333 #Update the reg-researcher dependance table
334 sfa_record.reg_researchers = [user_record]
337 #Update the senslab table with the new slice
338 #slab_slice = SenslabXP( slice_hrn = slice_record['slice_hrn'], \
339 #record_id_slice = sfa_record.record_id , \
340 #record_id_user = slice_record['record_id_user'], \
341 #peer_authority = slice_record['peer_authority'])
343 #logger.debug("SLABDRIVER.PY \tAddSlice slice_record %s \
344 #slab_slice %s sfa_record %s" \
345 #%(slice_record,slab_slice, sfa_record))
346 #slab_dbsession.add(slab_slice)
347 #slab_dbsession.commit()
350 # first 2 args are None in case of resource discovery
351 def list_resources (self, slice_urn, slice_hrn, creds, options):
352 #cached_requested = options.get('cached', True)
354 version_manager = VersionManager()
355 # get the rspec's return format from options
357 version_manager.get_version(options.get('geni_rspec_version'))
358 version_string = "rspec_%s" % (rspec_version)
360 #panos adding the info option to the caching key (can be improved)
361 if options.get('info'):
362 version_string = version_string + "_" + \
363 options.get('info', 'default')
365 # look in cache first
366 #if cached_requested and self.cache and not slice_hrn:
367 #rspec = self.cache.get(version_string)
369 #logger.debug("SlabDriver.ListResources: \
370 #returning cached advertisement")
373 #panos: passing user-defined options
374 aggregate = SlabAggregate(self)
375 #origin_hrn = Credential(string=creds[0]).get_gid_caller().get_hrn()
376 #options.update({'origin_hrn':origin_hrn})
377 rspec = aggregate.get_rspec(slice_xrn=slice_urn, \
378 version=rspec_version, options=options)
381 #if self.cache and not slice_hrn:
382 #logger.debug("Slab.ListResources: stores advertisement in cache")
383 #self.cache.add(version_string, rspec)
388 def list_slices (self, creds, options):
389 # look in cache first
391 #slices = self.cache.get('slices')
393 #logger.debug("PlDriver.list_slices returns from cache")
398 slices = self.GetSlices()
399 logger.debug("SLABDRIVER.PY \tlist_slices hrn %s \r\n \r\n" %(slices))
400 slice_hrns = [slab_slice['hrn'] for slab_slice in slices]
402 slice_urns = [hrn_to_urn(slice_hrn, 'slice') \
403 for slice_hrn in slice_hrns]
407 #logger.debug ("SlabDriver.list_slices stores value in cache")
408 #self.cache.add('slices', slice_urns)
413 def register (self, sfa_record, hrn, pub_key):
415 Adding new user, slice, node or site should not be handled
419 Adding users = LDAP Senslab
420 Adding slice = Import from LDAP users
426 def update (self, old_sfa_record, new_sfa_record, hrn, new_key):
427 """No site or node record update allowed in Senslab."""
429 pointer = old_sfa_record['pointer']
430 old_sfa_record_type = old_sfa_record['type']
432 # new_key implemented for users only
433 if new_key and old_sfa_record_type not in [ 'user' ]:
434 raise UnknownSfaType(old_sfa_record_type)
436 #if (type == "authority"):
437 #self.shell.UpdateSite(pointer, new_sfa_record)
439 if old_sfa_record_type == "slice":
440 slab_record = self.sfa_fields_to_slab_fields(old_sfa_record_type, \
442 if 'name' in slab_record:
443 slab_record.pop('name')
444 #Prototype should be UpdateSlice(self,
445 #auth, slice_id_or_name, slice_fields)
446 #Senslab cannot update slice since slice = job
447 #so we must delete and create another job
448 self.UpdateSlice(pointer, slab_record)
450 elif old_sfa_record_type == "user":
452 all_fields = new_sfa_record
453 for key in all_fields.keys():
454 if key in ['first_name', 'last_name', 'title', 'email',
455 'password', 'phone', 'url', 'bio', 'accepted_aup',
457 update_fields[key] = all_fields[key]
458 self.UpdatePerson(pointer, update_fields)
461 # must check this key against the previous one if it exists
462 persons = self.GetPersons([pointer], ['key_ids'])
464 keys = person['key_ids']
465 keys = self.GetKeys(person['key_ids'])
467 # Delete all stale keys
470 if new_key != key['key']:
471 self.DeleteKey(key['key_id'])
475 self.AddPersonKey(pointer, {'key_type': 'ssh', \
482 def remove (self, sfa_record):
483 sfa_record_type = sfa_record['type']
484 hrn = sfa_record['hrn']
485 if sfa_record_type == 'user':
487 #get user from senslab ldap
488 person = self.GetPersons(sfa_record)
489 #No registering at a given site in Senslab.
490 #Once registered to the LDAP, all senslab sites are
493 #Mark account as disabled in ldap
494 self.DeletePerson(sfa_record)
495 elif sfa_record_type == 'slice':
496 if self.GetSlices(slice_filter = hrn, \
497 slice_filter_type = 'slice_hrn'):
498 self.DeleteSlice(sfa_record)
500 #elif type == 'authority':
501 #if self.GetSites(pointer):
502 #self.DeleteSite(pointer)
508 #TODO clean GetPeers. 05/07/12SA
509 def GetPeers (self, auth = None, peer_filter=None, return_fields_list=None):
511 existing_records = {}
512 existing_hrns_by_types = {}
513 logger.debug("SLABDRIVER \tGetPeers auth = %s, peer_filter %s, \
514 return_field %s " %(auth , peer_filter, return_fields_list))
515 all_records = dbsession.query(RegRecord).filter(RegRecord.type.like('%authority%')).all()
517 for record in all_records:
518 existing_records[(record.hrn, record.type)] = record
519 if record.type not in existing_hrns_by_types:
520 existing_hrns_by_types[record.type] = [record.hrn]
522 existing_hrns_by_types[record.type].append(record.hrn)
525 logger.debug("SLABDRIVER \tGetPeer\texisting_hrns_by_types %s "\
526 %( existing_hrns_by_types))
531 records_list.append(existing_records[(peer_filter,'authority')])
533 for hrn in existing_hrns_by_types['authority']:
534 records_list.append(existing_records[(hrn,'authority')])
536 logger.debug("SLABDRIVER \tGetPeer \trecords_list %s " \
542 return_records = records_list
543 if not peer_filter and not return_fields_list:
547 logger.debug("SLABDRIVER \tGetPeer return_records %s " \
549 return return_records
552 #TODO : Handling OR request in make_ldap_filters_from_records
553 #instead of the for loop
554 #over the records' list
555 def GetPersons(self, person_filter=None):
557 person_filter should be a list of dictionnaries when not set to None.
558 Returns a list of users whose accounts are enabled found in ldap.
561 logger.debug("SLABDRIVER \tGetPersons person_filter %s" \
564 if person_filter and isinstance(person_filter, list):
565 #If we are looking for a list of users (list of dict records)
566 #Usually the list contains only one user record
567 for searched_attributes in person_filter:
569 #Get only enabled user accounts in senslab LDAP :
570 #add a filter for make_ldap_filters_from_record
571 person = self.ldap.LdapFindUser(searched_attributes, \
572 is_user_enabled=True)
573 #If a person was found, append it to the list
575 person_list.append(person)
577 #If the list is empty, return None
578 if len(person_list) is 0:
582 #Get only enabled user accounts in senslab LDAP :
583 #add a filter for make_ldap_filters_from_record
584 person_list = self.ldap.LdapFindUser(is_user_enabled=True)
588 def GetTimezone(self):
589 """ Get the OAR servier time and timezone.
590 Unused SA 16/11/12"""
591 server_timestamp, server_tz = self.oar.parser.\
592 SendRequest("GET_timezone")
593 return server_timestamp, server_tz
596 def DeleteJobs(self, job_id, slice_hrn):
597 if not job_id or job_id is -1:
599 username = slice_hrn.split(".")[-1].rstrip("_slice")
601 reqdict['method'] = "delete"
602 reqdict['strval'] = str(job_id)
605 answer = self.oar.POSTRequestToOARRestAPI('DELETE_jobs_id', \
607 logger.debug("SLABDRIVER \tDeleteJobs jobid %s \r\n answer %s \
608 username %s" %(job_id,answer, username))
613 ##TODO : Unused GetJobsId ? SA 05/07/12
614 #def GetJobsId(self, job_id, username = None ):
616 #Details about a specific job.
617 #Includes details about submission time, jot type, state, events,
618 #owner, assigned ressources, walltime etc...
622 #node_list_k = 'assigned_network_address'
623 ##Get job info from OAR
624 #job_info = self.oar.parser.SendRequest(req, job_id, username)
626 #logger.debug("SLABDRIVER \t GetJobsId %s " %(job_info))
628 #if job_info['state'] == 'Terminated':
629 #logger.debug("SLABDRIVER \t GetJobsId job %s TERMINATED"\
632 #if job_info['state'] == 'Error':
633 #logger.debug("SLABDRIVER \t GetJobsId ERROR message %s "\
638 #logger.error("SLABDRIVER \tGetJobsId KeyError")
641 #parsed_job_info = self.get_info_on_reserved_nodes(job_info, \
643 ##Replaces the previous entry
644 ##"assigned_network_address" / "reserved_resources"
646 #job_info.update({'node_ids':parsed_job_info[node_list_k]})
647 #del job_info[node_list_k]
648 #logger.debug(" \r\nSLABDRIVER \t GetJobsId job_info %s " %(job_info))
652 def GetJobsResources(self, job_id, username = None):
653 #job_resources=['reserved_resources', 'assigned_resources',\
654 #'job_id', 'job_uri', 'assigned_nodes',\
656 #assigned_res = ['resource_id', 'resource_uri']
657 #assigned_n = ['node', 'node_uri']
659 req = "GET_jobs_id_resources"
662 #Get job resources list from OAR
663 node_id_list = self.oar.parser.SendRequest(req, job_id, username)
664 logger.debug("SLABDRIVER \t GetJobsResources %s " %(node_id_list))
667 self.__get_hostnames_from_oar_node_ids(node_id_list)
670 #Replaces the previous entry "assigned_network_address" /
671 #"reserved_resources"
673 job_info = {'node_ids': hostname_list}
678 def get_info_on_reserved_nodes(self, job_info, node_list_name):
679 #Get the list of the testbed nodes records and make a
680 #dictionnary keyed on the hostname out of it
681 node_list_dict = self.GetNodes()
682 #node_hostname_list = []
683 node_hostname_list = [node['hostname'] for node in node_list_dict]
684 #for node in node_list_dict:
685 #node_hostname_list.append(node['hostname'])
686 node_dict = dict(zip(node_hostname_list, node_list_dict))
688 reserved_node_hostname_list = []
689 for index in range(len(job_info[node_list_name])):
690 #job_info[node_list_name][k] =
691 reserved_node_hostname_list[index] = \
692 node_dict[job_info[node_list_name][index]]['hostname']
694 logger.debug("SLABDRIVER \t get_info_on_reserved_nodes \
695 reserved_node_hostname_list %s" \
696 %(reserved_node_hostname_list))
698 logger.error("SLABDRIVER \t get_info_on_reserved_nodes KEYERROR " )
700 return reserved_node_hostname_list
702 def GetNodesCurrentlyInUse(self):
703 """Returns a list of all the nodes already involved in an oar job"""
704 return self.oar.parser.SendRequest("GET_running_jobs")
706 def __get_hostnames_from_oar_node_ids(self, resource_id_list ):
707 full_nodes_dict_list = self.GetNodes()
708 #Put the full node list into a dictionary keyed by oar node id
709 oar_id_node_dict = {}
710 for node in full_nodes_dict_list:
711 oar_id_node_dict[node['oar_id']] = node
713 #logger.debug("SLABDRIVER \t __get_hostnames_from_oar_node_ids\
714 #oar_id_node_dict %s" %(oar_id_node_dict))
716 hostname_dict_list = []
717 for resource_id in resource_id_list:
718 #Because jobs requested "asap" do not have defined resources
719 if resource_id is not "Undefined":
720 hostname_dict_list.append(\
721 oar_id_node_dict[resource_id]['hostname'])
723 #hostname_list.append(oar_id_node_dict[resource_id]['hostname'])
724 return hostname_dict_list
726 def GetReservedNodes(self,username = None):
727 #Get the nodes in use and the reserved nodes
728 reservation_dict_list = \
729 self.oar.parser.SendRequest("GET_reserved_nodes", \
733 for resa in reservation_dict_list:
734 logger.debug ("GetReservedNodes resa %s"%(resa))
735 #dict list of hostnames and their site
736 resa['reserved_nodes'] = \
737 self.__get_hostnames_from_oar_node_ids(resa['resource_ids'])
739 #del resa['resource_ids']
740 return reservation_dict_list
742 def GetNodes(self, node_filter_dict = None, return_fields_list = None):
744 node_filter_dict : dictionnary of lists
747 node_dict_by_id = self.oar.parser.SendRequest("GET_resources_full")
748 node_dict_list = node_dict_by_id.values()
749 logger.debug (" SLABDRIVER GetNodes node_filter_dict %s \
750 return_fields_list %s "%(node_filter_dict, return_fields_list))
751 #No filtering needed return the list directly
752 if not (node_filter_dict or return_fields_list):
753 return node_dict_list
755 return_node_list = []
757 for filter_key in node_filter_dict:
759 #Filter the node_dict_list by each value contained in the
760 #list node_filter_dict[filter_key]
761 for value in node_filter_dict[filter_key]:
762 for node in node_dict_list:
763 if node[filter_key] == value:
764 if return_fields_list :
766 for k in return_fields_list:
768 return_node_list.append(tmp)
770 return_node_list.append(node)
772 logger.log_exc("GetNodes KeyError")
776 return return_node_list
779 def GetSites(self, site_filter_name_list = None, return_fields_list = None):
780 site_dict = self.oar.parser.SendRequest("GET_sites")
781 #site_dict : dict where the key is the sit ename
782 return_site_list = []
783 if not ( site_filter_name_list or return_fields_list):
784 return_site_list = site_dict.values()
785 return return_site_list
787 for site_filter_name in site_filter_name_list:
788 if site_filter_name in site_dict:
789 if return_fields_list:
790 for field in return_fields_list:
793 tmp[field] = site_dict[site_filter_name][field]
795 logger.error("GetSites KeyError %s "%(field))
797 return_site_list.append(tmp)
799 return_site_list.append( site_dict[site_filter_name])
802 return return_site_list
806 def GetSlices(self, slice_filter = None, slice_filter_type = None):
807 """ Get the slice records from the slab db.
808 Returns a slice ditc if slice_filter and slice_filter_type
810 Returns a list of slice dictionnaries if there are no filters
815 authorized_filter_types_list = ['slice_hrn', 'record_id_user']
816 return_slicerec_dictlist = []
818 #First try to get information on the slice based on the filter provided
819 if slice_filter_type in authorized_filter_types_list:
822 def __get_slice_records(slice_filter = None, \
823 slice_filter_type = None):
826 #Get list of slices based on the slice hrn
827 if slice_filter_type == 'slice_hrn':
829 if get_authority(slice_filter) == self.root_auth:
830 login = slice_filter.split(".")[1].split("_")[0]
832 #DO NOT USE RegSlice - reg_researchers to get the hrn
833 #of the user otherwise will mess up the RegRecord in
834 #Resolve, don't know why - SA 08/08/2012
836 #Only one entry for one user = one slice in slab_xp table
837 slicerec = dbsession.query(RegRecord).filter_by(hrn = slice_filter).first()
838 #slicerec = slab_dbsession.query(SenslabXP).filter_by(slice_hrn = slice_filter).first()
843 #Get slice based on user id
844 if slice_filter_type == 'record_id_user':
845 slicerec = dbsession.query(RegRecord).filter_by(record_id = slice_filter).first()
846 #slicerec = slab_dbsession.query(SenslabXP).filter_by(record_id_user = slice_filter).first()
850 fixed_slicerec_dict = slicerec.__dict__
851 #At this point if the there is no login it means
852 #record_id_user filter has been used for filtering
854 #If theslice record is from senslab
855 if fixed_slicerec_dict['peer_authority'] is None:
856 login = fixed_slicerec_dict['hrn'].split(".")[1].split("_")[0]
857 return login, fixed_slicerec_dict
861 login, fixed_slicerec_dict = \
862 __get_slice_records(slice_filter, slice_filter_type)
863 logger.debug(" SLABDRIVER \tGetSlices login %s \
864 slice record %s slice_filter %s slice_filter_type %s "\
865 %(login, fixed_slicerec_dict,slice_filter, slice_filter_type))
868 #Now we have the slice record fixed_slicerec_dict, get the
869 #jobs associated to this slice
870 leases_list = self.GetReservedNodes(username = login)
872 #If no job is running or no job scheduled
873 #return only the slice record
874 if leases_list == [] and fixed_slicerec_dict:
875 return_slicerec_dictlist.append(fixed_slicerec_dict)
877 #If several jobs for one slice , put the slice record into
878 # each lease information dict
879 for lease in leases_list :
882 reserved_list = lease['reserved_nodes']
884 slicerec_dict['oar_job_id'] = lease['lease_id']
885 slicerec_dict.update({'list_node_ids':{'hostname':reserved_list}})
886 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
887 #Update lease dict with the slice record
888 if fixed_slicerec_dict:
889 slicerec_dict.update(fixed_slicerec_dict)
890 #slicerec_dict.update({'hrn':\
891 #str(fixed_slicerec_dict['slice_hrn'])})
894 return_slicerec_dictlist.append(slicerec_dict)
895 logger.debug("SLABDRIVER.PY \tGetSlices \
896 slicerec_dict %s return_slicerec_dictlist %s \
897 lease['reserved_nodes'] \
898 %s" %(slicerec_dict, return_slicerec_dictlist, \
899 lease['reserved_nodes'] ))
901 logger.debug("SLABDRIVER.PY \tGetSlices RETURN \
902 return_slicerec_dictlist %s" \
903 %(return_slicerec_dictlist))
905 return return_slicerec_dictlist
909 #Get all slices from the senslab sfa database ,
910 #put them in dict format
911 query_slice_list = dbsession.query(RegRecord).filter_by(type='slice').all()
912 #query_slice_list = slab_dbsession.query(SenslabXP).all()
913 return_slicerec_dictlist = []
914 for record in query_slice_list:
915 return_slicerec_dictlist.append(record.__dict__)
917 #Get all the jobs reserved nodes
918 leases_list = self.GetReservedNodes()
921 for fixed_slicerec_dict in return_slicerec_dictlist:
923 #Check if the slice belongs to a senslab user
924 if fixed_slicerec_dict['peer_authority'] is None:
925 owner = fixed_slicerec_dict['hrn'].split(".")[1].split("_")[0]
928 for lease in leases_list:
929 if owner == lease['user']:
930 slicerec_dict['oar_job_id'] = lease['lease_id']
932 #for reserved_node in lease['reserved_nodes']:
933 logger.debug("SLABDRIVER.PY \tGetSlices lease %s "\
936 reserved_list = lease['reserved_nodes']
938 slicerec_dict.update({'node_ids':lease['reserved_nodes']})
939 slicerec_dict.update({'list_node_ids':{'hostname':reserved_list}})
940 slicerec_dict.update(fixed_slicerec_dict)
941 #slicerec_dict.update({'hrn':\
942 #str(fixed_slicerec_dict['slice_hrn'])})
943 #return_slicerec_dictlist.append(slicerec_dict)
944 fixed_slicerec_dict.update(slicerec_dict)
946 logger.debug("SLABDRIVER.PY \tGetSlices RETURN \
947 return_slicerec_dictlist %s \slice_filter %s " \
948 %(return_slicerec_dictlist, slice_filter))
950 return return_slicerec_dictlist
953 def testbed_name (self): return self.hrn
955 # 'geni_request_rspec_versions' and 'geni_ad_rspec_versions' are mandatory
956 def aggregate_version (self):
957 version_manager = VersionManager()
958 ad_rspec_versions = []
959 request_rspec_versions = []
960 for rspec_version in version_manager.versions:
961 if rspec_version.content_type in ['*', 'ad']:
962 ad_rspec_versions.append(rspec_version.to_dict())
963 if rspec_version.content_type in ['*', 'request']:
964 request_rspec_versions.append(rspec_version.to_dict())
966 'testbed':self.testbed_name(),
967 'geni_request_rspec_versions': request_rspec_versions,
968 'geni_ad_rspec_versions': ad_rspec_versions,
974 # Convert SFA fields to PLC fields for use when registering up updating
975 # registry record in the PLC database
977 # @param type type of record (user, slice, ...)
978 # @param hrn human readable name
979 # @param sfa_fields dictionary of SFA fields
980 # @param slab_fields dictionary of PLC fields (output)
982 def sfa_fields_to_slab_fields(self, sfa_type, hrn, record):
986 #for field in record:
987 # slab_record[field] = record[field]
989 if sfa_type == "slice":
990 #instantion used in get_slivers ?
991 if not "instantiation" in slab_record:
992 slab_record["instantiation"] = "senslab-instantiated"
993 #slab_record["hrn"] = hrn_to_pl_slicename(hrn)
994 #Unused hrn_to_pl_slicename because Slab's hrn already
995 #in the appropriate form SA 23/07/12
996 slab_record["hrn"] = hrn
997 logger.debug("SLABDRIVER.PY sfa_fields_to_slab_fields \
998 slab_record %s " %(slab_record['hrn']))
1000 slab_record["url"] = record["url"]
1001 if "description" in record:
1002 slab_record["description"] = record["description"]
1003 if "expires" in record:
1004 slab_record["expires"] = int(record["expires"])
1006 #nodes added by OAR only and then imported to SFA
1007 #elif type == "node":
1008 #if not "hostname" in slab_record:
1009 #if not "hostname" in record:
1010 #raise MissingSfaInfo("hostname")
1011 #slab_record["hostname"] = record["hostname"]
1012 #if not "model" in slab_record:
1013 #slab_record["model"] = "geni"
1016 #elif type == "authority":
1017 #slab_record["login_base"] = hrn_to_slab_login_base(hrn)
1019 #if not "name" in slab_record:
1020 #slab_record["name"] = hrn
1022 #if not "abbreviated_name" in slab_record:
1023 #slab_record["abbreviated_name"] = hrn
1025 #if not "enabled" in slab_record:
1026 #slab_record["enabled"] = True
1028 #if not "is_public" in slab_record:
1029 #slab_record["is_public"] = True
1036 def __transforms_timestamp_into_date(self, xp_utc_timestamp = None):
1037 """ Transforms unix timestamp into valid OAR date format """
1039 #Used in case of a scheduled experiment (not immediate)
1040 #To run an XP immediately, don't specify date and time in RSpec
1041 #They will be set to None.
1042 if xp_utc_timestamp:
1043 #transform the xp_utc_timestamp into server readable time
1044 xp_server_readable_date = datetime.fromtimestamp(int(\
1045 xp_utc_timestamp)).strftime(self.time_format)
1047 return xp_server_readable_date
1055 def LaunchExperimentOnOAR(self, added_nodes, slice_name, \
1056 lease_start_time, lease_duration, slice_user=None):
1058 lease_dict['lease_start_time'] = lease_start_time
1059 lease_dict['lease_duration'] = lease_duration
1060 lease_dict['added_nodes'] = added_nodes
1061 lease_dict['slice_name'] = slice_name
1062 lease_dict['slice_user'] = slice_user
1063 lease_dict['grain'] = self.GetLeaseGranularity()
1064 lease_dict['time_format'] = self.time_format
1067 def __create_job_structure_request_for_OAR(lease_dict):
1068 """ Creates the structure needed for a correct POST on OAR.
1069 Makes the timestamp transformation into the appropriate format.
1070 Sends the POST request to create the job with the resources in
1079 reqdict['workdir'] = '/tmp'
1080 reqdict['resource'] = "{network_address in ("
1082 for node in lease_dict['added_nodes']:
1083 logger.debug("\r\n \r\n OARrestapi \t \
1084 __create_job_structure_request_for_OAR node %s" %(node))
1086 # Get the ID of the node
1088 reqdict['resource'] += "'" + nodeid + "', "
1089 nodeid_list.append(nodeid)
1091 custom_length = len(reqdict['resource'])- 2
1092 reqdict['resource'] = reqdict['resource'][0:custom_length] + \
1093 ")}/nodes=" + str(len(nodeid_list))
1095 def __process_walltime(duration):
1096 """ Calculates the walltime in seconds from the duration in H:M:S
1097 specified in the RSpec.
1101 # Fixing the walltime by adding a few delays.
1102 # First put the walltime in seconds oarAdditionalDelay = 20;
1103 # additional delay for /bin/sleep command to
1104 # take in account prologue and epilogue scripts execution
1105 # int walltimeAdditionalDelay = 240; additional delay
1106 desired_walltime = duration
1107 total_walltime = desired_walltime + 240 #+4 min Update SA 23/10/12
1108 sleep_walltime = desired_walltime # 0 sec added Update SA 23/10/12
1110 #Put the walltime back in str form
1111 #First get the hours
1112 walltime.append(str(total_walltime / 3600))
1113 total_walltime = total_walltime - 3600 * int(walltime[0])
1114 #Get the remaining minutes
1115 walltime.append(str(total_walltime / 60))
1116 total_walltime = total_walltime - 60 * int(walltime[1])
1118 walltime.append(str(total_walltime))
1121 logger.log_exc(" __process_walltime duration null")
1123 return walltime, sleep_walltime
1126 walltime, sleep_walltime = \
1127 __process_walltime(int(lease_dict['lease_duration'])*lease_dict['grain'])
1130 reqdict['resource'] += ",walltime=" + str(walltime[0]) + \
1131 ":" + str(walltime[1]) + ":" + str(walltime[2])
1132 reqdict['script_path'] = "/bin/sleep " + str(sleep_walltime)
1134 #In case of a scheduled experiment (not immediate)
1135 #To run an XP immediately, don't specify date and time in RSpec
1136 #They will be set to None.
1137 if lease_dict['lease_start_time'] is not '0':
1138 #Readable time accepted by OAR
1139 start_time = datetime.fromtimestamp(int(lease_dict['lease_start_time'])).\
1140 strftime(lease_dict['time_format'])
1141 reqdict['reservation'] = start_time
1142 #If there is not start time, Immediate XP. No need to add special
1146 reqdict['type'] = "deploy"
1147 reqdict['directory'] = ""
1148 reqdict['name'] = "SFA_" + lease_dict['slice_user']
1153 #Create the request for OAR
1154 reqdict = __create_job_structure_request_for_OAR(lease_dict)
1155 # first step : start the OAR job and update the job
1156 logger.debug("SLABDRIVER.PY \tLaunchExperimentOnOAR reqdict %s\
1159 answer = self.oar.POSTRequestToOARRestAPI('POST_job', \
1160 reqdict, slice_user)
1161 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s " %(answer))
1163 jobid = answer['id']
1165 logger.log_exc("SLABDRIVER \tLaunchExperimentOnOAR \
1166 Impossible to create job %s " %(answer))
1170 def __configure_experiment(jobid, added_nodes):
1171 # second step : configure the experiment
1172 # we need to store the nodes in a yaml (well...) file like this :
1173 # [1,56,23,14,45,75] with name /tmp/sfa<jobid>.json
1174 job_file = open('/tmp/sfa/'+ str(jobid) + '.json', 'w')
1176 job_file.write(str(added_nodes[0].strip('node')))
1177 for node in added_nodes[1:len(added_nodes)] :
1178 job_file.write(', '+ node.strip('node'))
1183 def __launch_senslab_experiment(jobid):
1184 # third step : call the senslab-experiment wrapper
1185 #command= "java -jar target/sfa-1.0-jar-with-dependencies.jar
1186 # "+str(jobid)+" "+slice_user
1187 javacmdline = "/usr/bin/java"
1189 "/opt/senslabexperimentwrapper/sfa-1.0-jar-with-dependencies.jar"
1191 output = subprocess.Popen([javacmdline, "-jar", jarname, str(jobid), \
1192 slice_user],stdout=subprocess.PIPE).communicate()[0]
1194 logger.debug("SLABDRIVER \t __configure_experiment wrapper returns%s " \
1201 logger.debug("SLABDRIVER \tLaunchExperimentOnOAR jobid %s \
1202 added_nodes %s slice_user %s" %(jobid, added_nodes, slice_user))
1205 __configure_experiment(jobid, added_nodes)
1206 __launch_senslab_experiment(jobid)
1211 def AddLeases(self, hostname_list, slice_record, \
1212 lease_start_time, lease_duration):
1213 logger.debug("SLABDRIVER \r\n \r\n \t AddLeases hostname_list %s \
1214 slice_record %s lease_start_time %s lease_duration %s "\
1215 %( hostname_list, slice_record , lease_start_time, \
1218 tmp = slice_record['reg-researchers'][0].split(".")
1219 username = tmp[(len(tmp)-1)]
1220 job_id = self.LaunchExperimentOnOAR(hostname_list, slice_record['hrn'], \
1221 lease_start_time, lease_duration, username)
1222 start_time = datetime.fromtimestamp(int(lease_start_time)).strftime(self.time_format)
1223 end_time = lease_start_time + lease_duration
1224 slab_ex_row = SenslabXP(slice_record['hrn'], job_id, end_time)
1225 logger.debug("SLABDRIVER \r\n \r\n \t slab_ex_row %s" %(slab_ex_row))
1226 slab_dbsession.add(slab_ex_row)
1227 slab_dbsession.commit()
1229 logger.debug("SLABDRIVER \t AddLeases hostname_list start_time %s " %(start_time))
1234 #Delete the jobs from job_senslab table
1235 def DeleteSliceFromNodes(self, slice_record):
1237 self.DeleteJobs(slice_record['oar_job_id'], slice_record['hrn'])
1241 def GetLeaseGranularity(self):
1242 """ Returns the granularity of Senslab testbed.
1243 OAR returns seconds for experiments duration.
1244 Defined in seconds. """
1249 def update_jobs_in_slabdb(self, job_oar_list):
1250 #Get all the entries in slab_xp table
1251 jobs_psql_query = slab_dbsession.query(SenslabXP).all()
1252 jobs_psql = [ row.job_id for row in jobs_psql_query ]
1253 jobs_psql = set(jobs_psql)
1254 kept_jobs = set(job_oar_list).intersection(jobs_psql)
1256 deleted_jobs = set(jobs_psql).difference(kept_jobs)
1257 deleted_jobs = list(deleted_jobs)
1259 slab_dbsession.query(SenslabXP).filter(SenslabXP.job_id.in_(deleted_jobs)).delete(synchronize_session='fetch')
1260 slab_dbsession.commit()
1266 def GetLeases(self, lease_filter_dict=None):
1269 unfiltered_reservation_list = self.GetReservedNodes()
1271 reservation_list = []
1272 #Find the slice associated with this user senslab ldap uid
1273 logger.debug(" SLABDRIVER.PY \tGetLeases unfiltered_reservation_list %s " %(unfiltered_reservation_list))
1274 #Create user dict first to avoid looking several times for
1275 #the same user in LDAP SA 27/07/12
1278 for resa in unfiltered_reservation_list:
1279 logger.debug("SLABDRIVER \tGetLeases USER %s"\
1281 #Cosntruct list of jobs (runing, waiting..) in oar
1282 job_oar_list.append(resa['lease_id'])
1283 if resa['user'] not in resa_user_dict:
1284 logger.debug("SLABDRIVER \tGetLeases userNOTIN ")
1285 ldap_info = self.ldap.LdapSearch('(uid='+resa['user']+')')
1287 ldap_info = ldap_info[0][1]
1288 #Get the backref :relationship table reg-researchers
1289 user = dbsession.query(RegUser).options(joinedload('reg_slices_as_researcher')).filter_by(email = \
1290 ldap_info['mail'][0])
1293 user = user.__dict__
1294 slice_info = user['reg_slices_as_researcher'][0].__dict__
1295 #Separated in case user not in database :
1296 #record_id not defined SA 17/07//12
1298 #query_slice_info = slab_dbsession.query(SenslabXP).filter_by(record_id_user = user.record_id)
1299 #if query_slice_info:
1300 #slice_info = query_slice_info.first()
1304 resa_user_dict[resa['user']] = {}
1305 resa_user_dict[resa['user']]['ldap_info'] = user
1306 resa_user_dict[resa['user']]['slice_info'] = slice_info
1308 resa['slice_hrn'] = resa_user_dict[resa['user']]['slice_info']['hrn']
1309 resa['slice_id'] = hrn_to_urn(resa['slice_hrn'], 'slice')
1311 #resa['slice_id'] = hrn_to_urn(slice_info.slice_hrn, 'slice')
1312 resa['component_id_list'] = []
1313 #Transform the hostnames into urns (component ids)
1314 for node in resa['reserved_nodes']:
1315 #resa['component_id_list'].append(hostname_to_urn(self.hrn, \
1316 #self.root_auth, node['hostname']))
1317 slab_xrn = slab_xrn_object(self.root_auth, node)
1318 resa['component_id_list'].append(slab_xrn.urn)
1320 if lease_filter_dict:
1321 if lease_filter_dict['name'] == resa['slice_hrn']:
1322 reservation_list.append(resa)
1324 if lease_filter_dict is None:
1325 reservation_list = unfiltered_reservation_list
1327 #del unfiltered_reservation_list[unfiltered_reservation_list.index(resa)]
1331 logger.debug("SLABDRIVER \tGetLeases resa_user_dict %s"\
1333 #for resa in unfiltered_reservation_list:
1337 #if resa['user'] in resa_user_dict:
1338 #resa['slice_hrn'] = resa_user_dict[resa['user']]['slice_info']['hrn']
1339 #resa['slice_id'] = hrn_to_urn(resa['slice_hrn'], 'slice')
1341 ##resa['slice_id'] = hrn_to_urn(slice_info.slice_hrn, 'slice')
1342 #resa['component_id_list'] = []
1343 ##Transform the hostnames into urns (component ids)
1344 #for node in resa['reserved_nodes']:
1345 ##resa['component_id_list'].append(hostname_to_urn(self.hrn, \
1346 ##self.root_auth, node['hostname']))
1347 #slab_xrn = slab_xrn_object(self.root_auth, node)
1348 #resa['component_id_list'].append(slab_xrn.urn)
1350 ##Filter the reservation list if necessary
1351 ##Returns all the leases associated with a given slice
1352 #if lease_filter_dict:
1353 #logger.debug("SLABDRIVER \tGetLeases lease_filter_dict %s"\
1354 #%(lease_filter_dict))
1355 #for resa in unfiltered_reservation_list:
1356 #if lease_filter_dict['name'] == resa['slice_hrn']:
1357 #reservation_list.append(resa)
1359 #reservation_list = unfiltered_reservation_list
1361 logger.debug(" SLABDRIVER.PY \tGetLeases reservation_list %s"\
1362 %(reservation_list))
1363 return reservation_list
1365 def augment_records_with_testbed_info (self, sfa_records):
1366 return self.fill_record_info (sfa_records)
1368 def fill_record_info(self, record_list):
1370 Given a SFA record, fill in the senslab specific and SFA specific
1371 fields in the record.
1374 logger.debug("SLABDRIVER \tfill_record_info records %s " %(record_list))
1375 if not isinstance(record_list, list):
1376 record_list = [record_list]
1379 for record in record_list:
1380 #If the record is a SFA slice record, then add information
1381 #about the user of this slice. This kind of
1382 #information is in the Senslab's DB.
1383 if str(record['type']) == 'slice':
1384 #Get slab slice record.
1385 recslice_list = self.GetSlices(slice_filter = \
1386 str(record['hrn']),\
1387 slice_filter_type = 'slice_hrn')
1389 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1390 recslice_list[0]['record_id_user']).first()
1391 logger.debug("SLABDRIVER \tfill_record_info TYPE SLICE RECUSER %s " %(recuser))
1392 record.update({'PI':[recuser.hrn],
1393 'researcher': [recuser.hrn],
1394 'name':record['hrn'],
1397 'person_ids':[recslice_list[0]['record_id_user']],
1398 'geni_urn':'', #For client_helper.py compatibility
1399 'keys':'', #For client_helper.py compatibility
1400 'key_ids':''}) #For client_helper.py compatibility
1403 for rec in recslice_list:
1404 record['oar_job_id'].append(rec['oar_job_id'])
1405 record['node_ids'] = [ self.root_auth + hostname for hostname in rec['node_ids']]
1409 logger.debug( "SLABDRIVER.PY \t fill_record_info SLICE \
1410 recslice_list %s \r\n \t RECORD %s \r\n \r\n" %(recslice_list,record))
1411 if str(record['type']) == 'user':
1412 #The record is a SFA user record.
1413 #Get the information about his slice from Senslab's DB
1414 #and add it to the user record.
1415 recslice_list = self.GetSlices(\
1416 slice_filter = record['record_id'],\
1417 slice_filter_type = 'record_id_user')
1419 logger.debug( "SLABDRIVER.PY \t fill_record_info TYPE USER \
1420 recslice_list %s \r\n \t RECORD %s \r\n" %(recslice_list , record))
1421 #Append slice record in records list,
1422 #therefore fetches user and slice info again(one more loop)
1423 #Will update PIs and researcher for the slice
1424 recuser = dbsession.query(RegRecord).filter_by(record_id = \
1425 recslice_list[0]['record_id_user']).first()
1426 logger.debug( "SLABDRIVER.PY \t fill_record_info USER \
1427 recuser %s \r\n \r\n" %(recuser))
1429 recslice = recslice_list[0]
1430 recslice.update({'PI':[recuser.hrn],
1431 'researcher': [recuser.hrn],
1432 'name':record['hrn'],
1435 'person_ids':[recslice_list[0]['record_id_user']]})
1437 for rec in recslice_list:
1438 recslice['oar_job_id'].append(rec['oar_job_id'])
1442 recslice.update({'type':'slice', \
1443 'hrn':recslice_list[0]['slice_hrn']})
1446 #GetPersons takes [] as filters
1447 #user_slab = self.GetPersons([{'hrn':recuser.hrn}])
1448 user_slab = self.GetPersons([record])
1451 record.update(user_slab[0])
1452 #For client_helper.py compatibility
1453 record.update( { 'geni_urn':'',
1456 record_list.append(recslice)
1458 logger.debug("SLABDRIVER.PY \tfill_record_info ADDING SLICE\
1459 INFO TO USER records %s" %(record_list))
1460 logger.debug("SLABDRIVER.PY \tfill_record_info END \
1461 #record %s \r\n \r\n " %(record))
1463 except TypeError, error:
1464 logger.log_exc("SLABDRIVER \t fill_record_info EXCEPTION %s"\
1466 #logger.debug("SLABDRIVER.PY \t fill_record_info ENDENDEND ")
1470 #self.fill_record_slab_info(records)
1476 #TODO Update membership? update_membership_list SA 05/07/12
1477 #def update_membership_list(self, oldRecord, record, listName, addFunc, \
1479 ## get a list of the HRNs tht are members of the old and new records
1481 #oldList = oldRecord.get(listName, [])
1484 #newList = record.get(listName, [])
1486 ## if the lists are the same, then we don't have to update anything
1487 #if (oldList == newList):
1490 ## build a list of the new person ids, by looking up each person to get
1494 #records = table.find({'type': 'user', 'hrn': newList})
1495 #for rec in records:
1496 #newIdList.append(rec['pointer'])
1498 ## build a list of the old person ids from the person_ids field
1500 #oldIdList = oldRecord.get("person_ids", [])
1501 #containerId = oldRecord.get_pointer()
1503 ## if oldRecord==None, then we are doing a Register, instead of an
1506 #containerId = record.get_pointer()
1508 ## add people who are in the new list, but not the oldList
1509 #for personId in newIdList:
1510 #if not (personId in oldIdList):
1511 #addFunc(self.plauth, personId, containerId)
1513 ## remove people who are in the old list, but not the new list
1514 #for personId in oldIdList:
1515 #if not (personId in newIdList):
1516 #delFunc(self.plauth, personId, containerId)
1518 #def update_membership(self, oldRecord, record):
1520 #if record.type == "slice":
1521 #self.update_membership_list(oldRecord, record, 'researcher',
1522 #self.users.AddPersonToSlice,
1523 #self.users.DeletePersonFromSlice)
1524 #elif record.type == "authority":
1529 # I don't think you plan on running a component manager at this point
1530 # let me clean up the mess of ComponentAPI that is deprecated anyways
1533 #TODO FUNCTIONS SECTION 04/07/2012 SA
1535 #TODO : Is UnBindObjectFromPeer still necessary ? Currently does nothing
1537 def UnBindObjectFromPeer(self, auth, object_type, object_id, shortname):
1538 """ This method is a hopefully temporary hack to let the sfa correctly
1539 detach the objects it creates from a remote peer object. This is
1540 needed so that the sfa federation link can work in parallel with
1541 RefreshPeer, as RefreshPeer depends on remote objects being correctly
1544 auth : struct, API authentication structure
1545 AuthMethod : string, Authentication method to use
1546 object_type : string, Object type, among 'site','person','slice',
1548 object_id : int, object_id
1549 shortname : string, peer shortname
1553 logger.warning("SLABDRIVER \tUnBindObjectFromPeer EMPTY-\
1557 #TODO Is BindObjectToPeer still necessary ? Currently does nothing
1559 def BindObjectToPeer(self, auth, object_type, object_id, shortname=None, \
1560 remote_object_id=None):
1561 """This method is a hopefully temporary hack to let the sfa correctly
1562 attach the objects it creates to a remote peer object. This is needed
1563 so that the sfa federation link can work in parallel with RefreshPeer,
1564 as RefreshPeer depends on remote objects being correctly marked.
1566 shortname : string, peer shortname
1567 remote_object_id : int, remote object_id, set to 0 if unknown
1571 logger.warning("SLABDRIVER \tBindObjectToPeer EMPTY - DO NOTHING \r\n ")
1574 #TODO UpdateSlice 04/07/2012 SA
1575 #Funciton should delete and create another job since oin senslab slice=job
1576 def UpdateSlice(self, auth, slice_id_or_name, slice_fields=None):
1577 """Updates the parameters of an existing slice with the values in
1579 Users may only update slices of which they are members.
1580 PIs may update any of the slices at their sites, or any slices of
1581 which they are members. Admins may update any slice.
1582 Only PIs and admins may update max_nodes. Slices cannot be renewed
1583 (by updating the expires parameter) more than 8 weeks into the future.
1584 Returns 1 if successful, faults otherwise.
1588 logger.warning("SLABDRIVER UpdateSlice EMPTY - DO NOTHING \r\n ")
1591 #TODO UpdatePerson 04/07/2012 SA
1592 def UpdatePerson(self, slab_hrn, federated_hrn, person_fields=None):
1593 """Updates a person. Only the fields specified in person_fields
1594 are updated, all other fields are left untouched.
1595 Users and techs can only update themselves. PIs can only update
1596 themselves and other non-PIs at their sites.
1597 Returns 1 if successful, faults otherwise.
1601 #new_row = FederatedToSenslab(slab_hrn, federated_hrn)
1602 #slab_dbsession.add(new_row)
1603 #slab_dbsession.commit()
1605 logger.debug("SLABDRIVER UpdatePerson EMPTY - DO NOTHING \r\n ")
1608 #TODO GetKeys 04/07/2012 SA
1609 def GetKeys(self, auth, key_filter=None, return_fields=None):
1610 """Returns an array of structs containing details about keys.
1611 If key_filter is specified and is an array of key identifiers,
1612 or a struct of key attributes, only keys matching the filter
1613 will be returned. If return_fields is specified, only the
1614 specified details will be returned.
1616 Admin may query all keys. Non-admins may only query their own keys.
1620 logger.warning("SLABDRIVER GetKeys EMPTY - DO NOTHING \r\n ")
1623 #TODO DeleteKey 04/07/2012 SA
1624 def DeleteKey(self, auth, key_id):
1626 Non-admins may only delete their own keys.
1627 Returns 1 if successful, faults otherwise.
1631 logger.warning("SLABDRIVER DeleteKey EMPTY - DO NOTHING \r\n ")
1635 #TODO : Check rights to delete person
1636 def DeletePerson(self, auth, person_record):
1637 """ Disable an existing account in senslab LDAP.
1638 Users and techs can only delete themselves. PIs can only
1639 delete themselves and other non-PIs at their sites.
1640 ins can delete anyone.
1641 Returns 1 if successful, faults otherwise.
1645 #Disable user account in senslab LDAP
1646 ret = self.ldap.LdapMarkUserAsDeleted(person_record)
1647 logger.warning("SLABDRIVER DeletePerson %s " %(person_record))
1650 #TODO Check DeleteSlice, check rights 05/07/2012 SA
1651 def DeleteSlice(self, auth, slice_record):
1652 """ Deletes the specified slice.
1653 Senslab : Kill the job associated with the slice if there is one
1654 using DeleteSliceFromNodes.
1655 Updates the slice record in slab db to remove the slice nodes.
1657 Users may only delete slices of which they are members. PIs may
1658 delete any of the slices at their sites, or any slices of which
1659 they are members. Admins may delete any slice.
1660 Returns 1 if successful, faults otherwise.
1664 self.DeleteSliceFromNodes(slice_record)
1665 logger.warning("SLABDRIVER DeleteSlice %s "%(slice_record))
1668 #TODO AddPerson 04/07/2012 SA
1669 #def AddPerson(self, auth, person_fields=None):
1670 def AddPerson(self, record):#TODO fixing 28/08//2012 SA
1671 """Adds a new account. Any fields specified in records are used,
1672 otherwise defaults are used.
1673 Accounts are disabled by default. To enable an account,
1675 Returns the new person_id (> 0) if successful, faults otherwise.
1679 ret = self.ldap.LdapAddUser(record)
1680 logger.debug("SLABDRIVER AddPerson return code %s \r\n "%(ret))
1683 #TODO AddPersonToSite 04/07/2012 SA
1684 def AddPersonToSite (self, auth, person_id_or_email, \
1685 site_id_or_login_base=None):
1686 """ Adds the specified person to the specified site. If the person is
1687 already a member of the site, no errors are returned. Does not change
1688 the person's primary site.
1689 Returns 1 if successful, faults otherwise.
1693 logger.warning("SLABDRIVER AddPersonToSite EMPTY - DO NOTHING \r\n ")
1696 #TODO AddRoleToPerson : Not sure if needed in senslab 04/07/2012 SA
1697 def AddRoleToPerson(self, auth, role_id_or_name, person_id_or_email):
1698 """Grants the specified role to the person.
1699 PIs can only grant the tech and user roles to users and techs at their
1700 sites. Admins can grant any role to any user.
1701 Returns 1 if successful, faults otherwise.
1705 logger.warning("SLABDRIVER AddRoleToPerson EMPTY - DO NOTHING \r\n ")
1708 #TODO AddPersonKey 04/07/2012 SA
1709 def AddPersonKey(self, auth, person_id_or_email, key_fields=None):
1710 """Adds a new key to the specified account.
1711 Non-admins can only modify their own keys.
1712 Returns the new key_id (> 0) if successful, faults otherwise.
1716 logger.warning("SLABDRIVER AddPersonKey EMPTY - DO NOTHING \r\n ")
1719 def DeleteLeases(self, leases_id_list, slice_hrn ):
1720 for job_id in leases_id_list:
1721 self.DeleteJobs(job_id, slice_hrn)
1723 logger.debug("SLABDRIVER DeleteLeases leases_id_list %s slice_hrn %s \
1724 \r\n " %(leases_id_list, slice_hrn))