3 from sfa.util.config import Config
4 from sfa.util.xrn import Xrn, get_authority, hrn_to_urn
6 from sfa.senslab.slabdriver import SlabDriver
8 from sfa.trust.certificate import Keypair, convert_public_key
9 from sfa.trust.gid import create_uuid
11 from sfa.storage.alchemy import dbsession
12 from sfa.storage.model import RegRecord, RegAuthority, RegSlice, RegNode, \
16 from sqlalchemy.exc import SQLAlchemyError
19 def _get_site_hrn(site):
25 def __init__ (self, auth_hierarchy, loc_logger):
26 self.auth_hierarchy = auth_hierarchy
27 self.logger = loc_logger
28 self.logger.setLevelDebug()
31 def hostname_to_hrn_escaped(root_auth, hostname):
32 return '.'.join( [root_auth, Xrn.escape(hostname)] )
36 def slicename_to_hrn(person_hrn):
37 return (person_hrn +'_slice')
39 def add_options (self, parser):
40 # we don't have any options for now
43 def find_record_by_type_hrn(self, record_type, hrn):
44 return self.records_by_type_hrn.get ( (record_type, hrn), None)
46 def locate_by_type_pointer (self, record_type, pointer):
47 ret = self.records_by_type_pointer.get ( (record_type, pointer), None)
50 def update_just_added_records_dict (self, record):
51 rec_tuple = (record.type, record.hrn)
52 if rec_tuple in self.records_by_type_hrn:
53 self.logger.warning ("SlabImporter.update_just_added_records_dict:\
54 duplicate (%s,%s)"%rec_tuple)
56 self.records_by_type_hrn [ rec_tuple ] = record
58 def import_sites(self) :
60 def run (self, options):
63 slabdriver = SlabDriver(config)
65 #Create special slice table for senslab
67 if not slabdriver.db.exists('slab_xp'):
68 slabdriver.db.createtable()
69 self.logger.info ("SlabImporter.run: slab_xp table created ")
71 #retrieve all existing SFA objects
72 all_records = dbsession.query(RegRecord).all()
74 # initialize record.stale to True by default,
75 # then mark stale=False on the ones that are in use
76 for record in all_records:
78 #create hash by (type,hrn)
79 #used to know if a given record is already known to SFA
81 self.records_by_type_hrn = \
82 dict([( (record.type,record.hrn), record) \
83 for record in all_records])
85 self.users_rec_by_email = \
86 dict([ (record.email, record) \
87 for record in all_records if record.type == 'user'])
89 # create hash by (type,pointer)
90 self.records_by_type_pointer = \
91 dict([ ( (str(record.type), record.pointer) , record) \
92 for record in all_records if record.pointer != -1])
95 nodes_listdict = slabdriver.slab_api.GetNodes()
96 nodes_by_id = dict([(node['node_id'],node) for node in nodes_listdict])
97 sites_listdict = slabdriver.slab_api.GetSites()
99 ldap_person_listdict = slabdriver.slab_api.GetPersons()
100 print>>sys.stderr,"\r\n SLABIMPORT \t ldap_person_listdict %s \r\n" \
101 %(ldap_person_listdict)
102 slices_listdict = slabdriver.slab_api.GetSlices()
104 #slices_by_userid = \
105 #dict([(one_slice['reg_researchers']['record_id'], one_slice ) \
106 #for one_slice in slices_listdict ])
108 #self.logger.log_exc("SlabImporter: failed to create list \
109 #of slices by user id.")
112 for site in sites_listdict:
113 site_hrn = _get_site_hrn(site)
114 site_record = self.find_record_by_type_hrn ('authority', site_hrn)
117 urn = hrn_to_urn(site_hrn, 'authority')
118 if not self.auth_hierarchy.auth_exists(urn):
119 self.auth_hierarchy.create_auth(urn)
121 auth_info = self.auth_hierarchy.get_auth_info(urn)
122 site_record = RegAuthority(hrn=site_hrn, \
123 gid=auth_info.get_gid_object(),
125 authority=get_authority(site_hrn))
126 site_record.just_created()
127 dbsession.add(site_record)
129 self.logger.info("SlabImporter: imported authority (site) \
131 self.update_just_added_records_dict(site_record)
132 except SQLAlchemyError:
133 # if the site import fails then there is no point in
134 # trying to import the
135 # site's child records (node, slices, persons), so skip them.
136 self.logger.log_exc("SlabImporter: failed to import site. \
137 Skipping child records")
140 # xxx update the record ...
142 site_record.stale = False
144 # import node records in site
145 for node_id in site['node_ids']:
147 node = nodes_by_id[node_id]
149 self.logger.warning ("SlabImporter: cannot find node_id %s \
150 - ignored" %(node_id))
153 self.hostname_to_hrn_escaped(slabdriver.slab_api.root_auth, \
155 print>>sys.stderr, "\r\n \r\n SLABIMPORTER node %s " %(node)
159 # xxx this sounds suspicious
160 if len(hrn) > 64: hrn = hrn[:64]
161 node_record = self.find_record_by_type_hrn( 'node', hrn )
163 pkey = Keypair(create=True)
164 urn = hrn_to_urn(escaped_hrn, 'node')
166 self.auth_hierarchy.create_gid(urn, \
169 def slab_get_authority(hrn):
170 return hrn.split(".")[0]
172 node_record = RegNode(hrn=hrn, gid=node_gid,
174 authority=slab_get_authority(hrn))
177 node_record.just_created()
178 dbsession.add(node_record)
180 self.logger.info("SlabImporter: imported node: %s" \
182 self.update_just_added_records_dict(node_record)
183 except SQLAlchemyError:
184 self.logger.log_exc("SlabImporter: \
185 failed to import node")
187 # xxx update the record ...
189 node_record.stale=False
193 for person in ldap_person_listdict :
195 self.logger.info("SlabImporter: person :" %(person))
196 if 'ssh-rsa' not in person['pkey']:
197 #people with invalid ssh key (ssh-dss, empty, bullshit keys...)
200 person_hrn = person['hrn']
201 slice_hrn = self.slicename_to_hrn(person['hrn'])
203 # xxx suspicious again
204 if len(person_hrn) > 64: person_hrn = person_hrn[:64]
205 person_urn = hrn_to_urn(person_hrn, 'user')
208 self.logger.info("SlabImporter: users_rec_by_email %s " \
209 %(self.users_rec_by_email))
211 #Check if user using person['email'] form LDAP is already registered
212 #in SFA. One email = one person. In this case, do not create another
213 #record for this person
214 #person_hrn returned by GetPerson based on senslab root auth + uid ldap
215 user_record = self.find_record_by_type_hrn('user', person_hrn)
217 if not user_record and person['email'] in self.users_rec_by_email:
218 user_record = self.users_rec_by_email[person['email']]
219 person_hrn = user_record.hrn
220 person_urn = hrn_to_urn(person_hrn, 'user')
223 slice_record = self.find_record_by_type_hrn ('slice', slice_hrn)
225 # return a tuple pubkey (a plc key object) and pkey (a Keypair object)
226 def init_person_key (person, slab_key):
229 # randomly pick first key in set
233 pkey = convert_public_key(pubkey)
235 #key not good. create another pkey
236 self.logger.warn('SlabImporter: \
237 unable to convert public \
238 key for %s' % person_hrn)
239 pkey = Keypair(create=True)
242 # the user has no keys.
243 #Creating a random keypair for the user's gid
244 self.logger.warn("SlabImporter: person %s does not have a \
245 public key" %(person_hrn))
246 pkey = Keypair(create=True)
247 return (pubkey, pkey)
251 slab_key = person['pkey']
254 (pubkey,pkey) = init_person_key (person, slab_key )
255 if pubkey is not None and pkey is not None :
257 self.auth_hierarchy.create_gid(person_urn, \
260 print>>sys.stderr, "\r\n \r\n SLAB IMPORTER \
261 PERSON EMAIL OK email %s " %(person['email'])
262 person_gid.set_email(person['email'])
263 user_record = RegUser(hrn=person_hrn, \
266 authority=get_authority(person_hrn),
267 email=person['email'])
269 user_record = RegUser(hrn=person_hrn, \
272 authority=get_authority(person_hrn))
275 user_record.reg_keys = [RegKey(pubkey)]
277 self.logger.warning("No key found for user %s" \
281 user_record.just_created()
282 dbsession.add (user_record)
284 self.logger.info("SlabImporter: imported person: %s"\
286 self.update_just_added_records_dict( user_record )
288 except SQLAlchemyError:
289 self.logger.log_exc("SlabImporter: \
290 failed to import person %s"%(person))
292 # update the record ?
293 # if user's primary key has changed then we need to update
294 # the users gid by forcing an update here
295 sfa_keys = user_record.reg_keys
298 if slab_key is not sfa_keys :
301 print>>sys.stderr,"SlabImporter: \t \t USER UPDATE \
302 person: %s" %(person['hrn'])
303 (pubkey,pkey) = init_person_key (person, slab_key)
305 self.auth_hierarchy.create_gid(person_urn, \
308 user_record.reg_keys = []
310 user_record.reg_keys = [RegKey(pubkey)]
311 self.logger.info("SlabImporter: updated person: %s" \
315 user_record.email = person['email']
319 user_record.stale = False
320 except SQLAlchemyError:
321 self.logger.log_exc("SlabImporter: \
322 failed to update person %s"%(person))
326 #single_slice = slices_by_userid[user_record.record_id]
328 #self.logger.warning ("SlabImporter: \
329 #cannot locate slices_by_userid[user_record.record_id] %s - \
330 #ignored" %(user_record))
332 if not slice_record :
334 pkey = Keypair(create=True)
335 urn = hrn_to_urn(slice_hrn, 'slice')
337 self.auth_hierarchy.create_gid(urn, \
339 slice_record = RegSlice (hrn=slice_hrn, gid=slice_gid,
341 authority=get_authority(slice_hrn))
343 slice_record.just_created()
344 dbsession.add(slice_record)
347 #Serial id created after commit
349 sl_rec = dbsession.query(RegSlice).filter(RegSlice.hrn.match(slice_hrn)).all()
352 self.update_just_added_records_dict ( slice_record )
354 except SQLAlchemyError:
355 self.logger.log_exc("SlabImporter: failed to import slice")
357 #No slice update upon import in senslab
359 # xxx update the record ...
360 self.logger.warning ("Slice update not yet implemented")
362 # record current users affiliated with the slice
365 slice_record.reg_researchers = [user_record]
368 slice_record.stale = False
369 except SQLAlchemyError:
370 self.logger.log_exc("SlabImporter: failed to update slice")
374 ### remove stale records
375 # special records must be preserved
376 system_hrns = [slabdriver.hrn, slabdriver.slab_api.root_auth, \
377 slabdriver.hrn+ '.slicemanager']
378 for record in all_records:
379 if record.hrn in system_hrns:
381 if record.peer_authority:
385 for record in all_records:
386 if record.type == 'user':
387 print>>sys.stderr,"SlabImporter: stale records: hrn %s %s" \
388 %(record.hrn,record.stale)
393 self.logger.warning("stale not found with %s"%record)
395 self.logger.info("SlabImporter: deleting stale record: %s" \
399 dbsession.delete(record)
401 except SQLAlchemyError:
402 self.logger.log_exc("SlabImporter: failed to delete stale \
403 record %s" %(record) )