refactored sfalogging to be less awkward and more reliable
[sfa.git] / sfa / importer / openstackimporter.py
1 import os
2
3 from sfa.util.config import Config
4 from sfa.util.xrn import Xrn, get_leaf, get_authority, hrn_to_urn
5 from sfa.trust.gid import create_uuid
6 from sfa.trust.certificate import convert_public_key, Keypair
7 # using global alchemy.session() here is fine
8 # as importer is on standalone one-shot process
9 from sfa.storage.alchemy import global_dbsession
10 from sfa.storage.model import RegRecord, RegAuthority, RegUser, RegSlice, RegNode
11 from sfa.openstack.osxrn import OSXrn
12 from sfa.openstack.shell import Shell
13
14
15 def load_keys(filename):
16     keys = {}
17     tmp_dict = {}
18     try:
19         execfile(filename, tmp_dict)
20         if 'keys' in tmp_dict:
21             keys = tmp_dict['keys']
22         return keys
23     except:
24         return keys
25
26
27 def save_keys(filename, keys):
28     f = open(filename, 'w')
29     f.write("keys = %s" % str(keys))
30     f.close()
31
32
33 class OpenstackImporter:
34
35     def __init__(self, auth_hierarchy, logger):
36         self.auth_hierarchy = auth_hierarchy
37         self.logger = logger
38         self.config = Config()
39         self.interface_hrn = self.config.SFA_INTERFACE_HRN
40         self.root_auth = self.config.SFA_REGISTRY_ROOT_AUTH
41         self.shell = Shell(self.config)
42
43     def add_options(self, parser):
44         self.logger.debug("OpenstackImporter: no options yet")
45         pass
46
47     def import_users(self, existing_hrns, existing_records):
48         # Get all users
49         users = self.shell.auth_manager.users.list()
50         users_dict = {}
51         keys_filename = self.config.config_path + os.sep + 'person_keys.py'
52         old_user_keys = load_keys(keys_filename)
53         user_keys = {}
54         for user in users:
55             auth_hrn = self.config.SFA_INTERFACE_HRN
56             if user.tenantId is not None:
57                 tenant = self.shell.auth_manager.tenants.find(id=user.tenantId)
58                 auth_hrn = OSXrn(
59                     name=tenant.name, auth=self.config.SFA_INTERFACE_HRN, type='authority').get_hrn()
60             hrn = OSXrn(name=user.name, auth=auth_hrn, type='user').get_hrn()
61             users_dict[hrn] = user
62             old_keys = old_user_keys.get(hrn, [])
63             keyname = OSXrn(xrn=hrn, type='user').get_slicename()
64             keys = [
65                 k.public_key for k in self.shell.nova_manager.keypairs.findall(name=keyname)]
66             user_keys[hrn] = keys
67             update_record = False
68             if old_keys != keys:
69                 update_record = True
70             if hrn not in existing_hrns or \
71                     (hrn, 'user') not in existing_records or update_record:
72                 urn = OSXrn(xrn=hrn, type='user').get_urn()
73
74                 if keys:
75                     try:
76                         pkey = convert_public_key(keys[0])
77                     except:
78                         self.logger.log_exc(
79                             'unable to convert public key for %s' % hrn)
80                         pkey = Keypair(create=True)
81                 else:
82                     self.logger.warning(
83                         "OpenstackImporter: person %s does not have a PL public key" % hrn)
84                     pkey = Keypair(create=True)
85                 user_gid = self.auth_hierarchy.create_gid(
86                     urn, create_uuid(), pkey, email=user.email)
87                 user_record = RegUser()
88                 user_record.type = 'user'
89                 user_record.hrn = hrn
90                 user_record.gid = user_gid
91                 user_record.authority = get_authority(hrn)
92                 global_dbsession.add(user_record)
93                 global_dbsession.commit()
94                 self.logger.info(
95                     "OpenstackImporter: imported person %s" % user_record)
96
97         return users_dict, user_keys
98
99     def import_tenants(self, existing_hrns, existing_records):
100         # Get all tenants
101         # A tenant can represent an organizational group (site) or a
102         # slice. If a tenant's authorty/parent matches the root authority it is
103         # considered a group/site. All other tenants are considered slices.
104         tenants = self.shell.auth_manager.tenants.list()
105         tenants_dict = {}
106         for tenant in tenants:
107             hrn = self.config.SFA_INTERFACE_HRN + '.' + tenant.name
108             tenants_dict[hrn] = tenant
109             authority_hrn = OSXrn(
110                 xrn=hrn, type='authority').get_authority_hrn()
111
112             if hrn in existing_hrns:
113                 continue
114
115             if authority_hrn == self.config.SFA_INTERFACE_HRN:
116                 # import group/site
117                 record = RegAuthority()
118                 urn = OSXrn(xrn=hrn, type='authority').get_urn()
119                 if not self.auth_hierarchy.auth_exists(urn):
120                     self.auth_hierarchy.create_auth(urn)
121                 auth_info = self.auth_hierarchy.get_auth_info(urn)
122                 gid = auth_info.get_gid_object()
123                 record.type = 'authority'
124                 record.hrn = hrn
125                 record.gid = gid
126                 record.authority = get_authority(hrn)
127                 global_dbsession.add(record)
128                 global_dbsession.commit()
129                 self.logger.info(
130                     "OpenstackImporter: imported authority: %s" % record)
131
132             else:
133                 record = RegSlice()
134                 urn = OSXrn(xrn=hrn, type='slice').get_urn()
135                 pkey = Keypair(create=True)
136                 gid = self.auth_hierarchy.create_gid(urn, create_uuid(), pkey)
137                 record.type = 'slice'
138                 record.hrn = hrn
139                 record.gid = gid
140                 record.authority = get_authority(hrn)
141                 global_dbsession.add(record)
142                 global_dbsession.commit()
143                 self.logger.info(
144                     "OpenstackImporter: imported slice: %s" % record)
145
146         return tenants_dict
147
148     def run(self, options):
149         # we don't have any options for now
150         self.logger.info("OpenstackImporter.run : to do")
151
152         # create dict of all existing sfa records
153         existing_records = {}
154         existing_hrns = []
155         key_ids = []
156         for record in global_dbsession.query(RegRecord):
157             existing_records[(record.hrn, record.type,)] = record
158             existing_hrns.append(record.hrn)
159
160         tenants_dict = self.import_tenants(existing_hrns, existing_records)
161         users_dict, user_keys = self.import_users(
162             existing_hrns, existing_records)
163
164         # remove stale records
165         system_records = [self.interface_hrn, self.root_auth,
166                           self.interface_hrn + '.slicemanager']
167         for (record_hrn, type) in existing_records.keys():
168             if record_hrn in system_records:
169                 continue
170
171             record = existing_records[(record_hrn, type)]
172             if record.peer_authority:
173                 continue
174
175             if type == 'user':
176                 if record_hrn in users_dict:
177                     continue
178             elif type in['slice', 'authority']:
179                 if record_hrn in tenants_dict:
180                     continue
181             else:
182                 continue
183
184             record_object = existing_records[(record_hrn, type)]
185             self.logger.info("OpenstackImporter: removing %s " % record)
186             global_dbsession.delete(record_object)
187             global_dbsession.commit()
188
189         # save pub keys
190         self.logger.info('OpenstackImporter: saving current pub keys')
191         keys_filename = self.config.config_path + os.sep + 'person_keys.py'
192         save_keys(keys_filename, user_keys)