47 ('DEFAULT', 'cinder_http_retries'): ('cinder', 'http_retries'), |
45 ('DEFAULT', 'cinder_http_retries'): ('cinder', 'http_retries'), |
48 ('DEFAULT', 'cinder_http_timeout'): ('cinder', 'http_timeout'), |
46 ('DEFAULT', 'cinder_http_timeout'): ('cinder', 'http_timeout'), |
49 ('DEFAULT', 'cinder_api_insecure'): ('cinder', 'api_insecure'), |
47 ('DEFAULT', 'cinder_api_insecure'): ('cinder', 'api_insecure'), |
50 ('DEFAULT', 'cinder_cross_az_attach'): ('cinder', 'cross_az_attach'), |
48 ('DEFAULT', 'cinder_cross_az_attach'): ('cinder', 'cross_az_attach'), |
51 ('DEFAULT', 'db_backend'): ('database', 'backend'), |
49 ('DEFAULT', 'db_backend'): ('database', 'backend'), |
52 ('DEFAULT', 'sql_connection'): ('database', 'connection'), |
|
53 ('DEFAULT', 'sql_connection'): ('database', 'connection'), |
50 ('DEFAULT', 'sql_connection'): ('database', 'connection'), |
54 ('sql', 'connection'): ('database', 'connection'), |
51 ('sql', 'connection'): ('database', 'connection'), |
55 ('DEFAULT', 'sql_idle_timeout'): ('database', 'idle_timeout'), |
52 ('DEFAULT', 'sql_idle_timeout'): ('database', 'idle_timeout'), |
56 ('DATABASE', 'sql_idle_timeout'): ('database', 'idle_timeout'), |
53 ('DATABASE', 'sql_idle_timeout'): ('database', 'idle_timeout'), |
57 ('sql', 'idle_timeout'): ('database', 'idle_timeout'), |
54 ('sql', 'idle_timeout'): ('database', 'idle_timeout'), |
96 ('neutron', 'extension_sync_interval'), |
93 ('neutron', 'extension_sync_interval'), |
97 ('DEFAULT', 'neutron_ca_certificates_file'): |
94 ('DEFAULT', 'neutron_ca_certificates_file'): |
98 ('neutron', 'ca_certificates_file'), |
95 ('neutron', 'ca_certificates_file'), |
99 ('DEFAULT', 'spicehtml5proxy_host'): ('spice', 'html5proxy_host'), |
96 ('DEFAULT', 'spicehtml5proxy_host'): ('spice', 'html5proxy_host'), |
100 ('DEFAULT', 'spicehtml5proxy_port'): ('spice', 'html5proxy_port'), |
97 ('DEFAULT', 'spicehtml5proxy_port'): ('spice', 'html5proxy_port'), |
101 # No longer referenced by the service |
|
102 ('DEFAULT', 'sql_connection'): (None, None), |
|
103 } |
98 } |
104 |
99 |
105 |
100 NOVA_CONF_EXCEPTIONS = [ |
106 def update_mapping(section, key, mapping): |
101 ('DEFAULT', 'ec2_workers'), |
107 """ look for deprecated variables and, if found, convert it to the new |
102 ('DEFAULT', 'osapi_compute_workers'), |
108 section/key. |
103 ('DEFAULT', 'metadata_workers'), |
109 """ |
104 ('DEFAULT', 'lock_path'), |
110 |
105 ('DEFAULT', 'novncproxy_base_url'), |
111 if (section, key) in mapping: |
106 ('conductor', 'workers'), |
112 print "Deprecated value found: [%s] %s" % (section, key) |
107 ('database', 'connection'), |
113 section, key = mapping[(section, key)] |
108 ('keystone_authtoken', 'auth_uri'), |
114 if section is None and key is None: |
109 ('keystone_authtoken', 'signing_dir'), |
115 print "Removing from configuration" |
110 ('keystone_authtoken', 'identity_uri'), |
116 else: |
111 ('keystone_authtoken', 'admin_user'), |
117 print "Updating to: [%s] %s" % (section, key) |
112 ('keystone_authtoken', 'admin_password'), |
118 return section, key |
113 ('keystone_authtoken', 'admin_tenant_name'), |
119 |
114 ('neutron', 'service_metadata_proxy'), |
120 |
115 ] |
121 def alter_mysql_tables(engine): |
116 |
122 """ Convert MySQL tables to use utf8 |
117 NOVA_MOVE_CONFIG = { |
123 """ |
118 ('filter:authtoken', 'auth_uri'): ('keystone_authtoken', 'auth_uri'), |
124 |
119 ('filter:authtoken', 'identity_uri'): |
125 import MySQLdb |
120 ('keystone_authtoken', 'identity_uri'), |
126 |
121 ('filter:authtoken', 'admin_tenant_name'): |
127 for _none in range(5): |
122 ('keystone_authtoken', 'admin_tenant_name'), |
128 try: |
123 ('filter:authtoken', 'admin_user'): ('keystone_authtoken', 'admin_user'), |
129 db = MySQLdb.connect(host=engine.url.host, |
124 ('filter:authtoken', 'admin_password'): |
130 user=engine.url.username, |
125 ('keystone_authtoken', 'admin_password'), |
131 passwd=engine.url.password, |
126 ('filter:authtoken', 'signing_dir'): ('keystone_authtoken', 'signing_dir'), |
132 db=engine.url.database) |
127 ('filter:authtoken', 'auth_version'): |
133 break |
128 ('keystone_authtoken', 'auth_version'), |
134 except MySQLdb.OperationalError as err: |
129 } |
135 # mysql is not ready. sleep for 2 more seconds |
|
136 time.sleep(2) |
|
137 else: |
|
138 print "Unable to connect to MySQL: %s" % err |
|
139 print ("Please verify MySQL is properly configured and online " |
|
140 "before using svcadm(1M) to clear this service.") |
|
141 sys.exit(smf_include.SMF_EXIT_ERR_FATAL) |
|
142 |
|
143 cursor = db.cursor() |
|
144 cursor.execute("ALTER DATABASE %s CHARACTER SET = 'utf8'" % |
|
145 engine.url.database) |
|
146 cursor.execute("ALTER DATABASE %s COLLATE = 'utf8_general_ci'" % |
|
147 engine.url.database) |
|
148 cursor.execute("SHOW tables") |
|
149 res = cursor.fetchall() |
|
150 if res: |
|
151 cursor.execute("SET foreign_key_checks = 0") |
|
152 for item in res: |
|
153 cursor.execute("ALTER TABLE %s.%s CONVERT TO " |
|
154 "CHARACTER SET 'utf8', COLLATE 'utf8_general_ci'" |
|
155 % (engine.url.database, item[0])) |
|
156 cursor.execute("SET foreign_key_checks = 1") |
|
157 db.commit() |
|
158 db.close() |
|
159 |
|
160 |
|
161 def modify_conf(old_file, mapping=None): |
|
162 """ Copy over all uncommented options from the old configuration file. In |
|
163 addition, look for deprecated section/keys and convert them to the new |
|
164 section/key. |
|
165 """ |
|
166 |
|
167 new_file = old_file + '.new' |
|
168 |
|
169 # open the previous version |
|
170 old = iniparse.ConfigParser() |
|
171 old.readfp(open(old_file)) |
|
172 |
|
173 # open the new version |
|
174 new = iniparse.ConfigParser() |
|
175 try: |
|
176 new.readfp(open(new_file)) |
|
177 except IOError as err: |
|
178 if err.errno == errno.ENOENT: |
|
179 # The upgrade did not deliver a .new file so, return |
|
180 print "%s not found - continuing with %s" % (new_file, old_file) |
|
181 return |
|
182 else: |
|
183 raise |
|
184 print "\nupdating %s" % old_file |
|
185 |
|
186 # It's possible that nova.conf has database.connection commented out (to |
|
187 # use the default value). If it is, and none of other deprecated values |
|
188 # are set, manually set database.connection in the new conf file. |
|
189 if 'nova.conf' in old_file: |
|
190 options = [ |
|
191 ('database', 'sql_connection'), |
|
192 ('sql', 'connection'), |
|
193 ('database', 'connection'), |
|
194 ('DEFAULT', 'sql_connection') |
|
195 ] |
|
196 test = lambda x: old.has_section(x[0]) and old.has_option(x[0], x[1]) |
|
197 if not any(map(test, options)): |
|
198 if old.has_option('DEFAULT', 'state_path'): |
|
199 state_path = old.get('DEFAULT', 'state_path') |
|
200 else: |
|
201 state_path = '/var/lib/nova' |
|
202 |
|
203 if old.has_option('DEFAULT', 'sqlite_db'): |
|
204 sqlite_db = old.get('DEFAULT', 'sqlite_db') |
|
205 else: |
|
206 sqlite_db = 'nova.sqlite' |
|
207 |
|
208 new.set('database', 'connection', |
|
209 'sqlite:///%s/%s' % (state_path, sqlite_db)) |
|
210 |
|
211 # walk every single section for uncommented options |
|
212 default_items = set(old.items('DEFAULT')) |
|
213 for section in old.sections() + ['DEFAULT']: |
|
214 |
|
215 # DEFAULT items show up in every section so remove them |
|
216 if section != 'DEFAULT': |
|
217 section_items = set(old.items(section)) - default_items |
|
218 else: |
|
219 section_items = default_items |
|
220 |
|
221 for key, value in section_items: |
|
222 # keep a copy of the old value |
|
223 oldvalue = value |
|
224 oldsection = section |
|
225 |
|
226 if mapping is not None: |
|
227 section, key = update_mapping(section, key, mapping) |
|
228 |
|
229 if section is None and key is None: |
|
230 # option is deprecated so continue |
|
231 continue |
|
232 |
|
233 if not new.has_section(section): |
|
234 if section != 'DEFAULT': |
|
235 new.add_section(section) |
|
236 |
|
237 # print to the log when a value for the same section.key is |
|
238 # changing to a new value |
|
239 try: |
|
240 new_value = new.get(section, key) |
|
241 if new_value != value and '%SERVICE' not in new_value: |
|
242 print "Changing [%s] %s:\n- %s\n+ %s" % \ |
|
243 (section, key, oldvalue, new_value) |
|
244 print |
|
245 except NoOptionError: |
|
246 # the new configuration file does not have this option set so |
|
247 # just continue |
|
248 pass |
|
249 |
|
250 # Only copy the old value to the new conf file if the entry doesn't |
|
251 # exist or if it contains '%SERVICE' |
|
252 if not new.has_option(section, key) or \ |
|
253 '%SERVICE' in new.get(section, key): |
|
254 new.set(section, key, value) |
|
255 section = oldsection |
|
256 |
|
257 # copy the old conf file to a backup |
|
258 today = datetime.now().strftime("%Y%m%d%H%M%S") |
|
259 shutil.copy2(old_file, old_file + '.' + today) |
|
260 |
|
261 # copy the new conf file in place |
|
262 with open(old_file, 'wb+') as fh: |
|
263 new.write(fh) |
|
264 |
130 |
265 |
131 |
266 def start(): |
132 def start(): |
267 # pull out the current version of config/upgrade-id |
133 # pull out the current version of config/upgrade-id |
268 p = Popen(['/usr/bin/svcprop', '-p', 'config/upgrade-id', |
134 p = Popen(['/usr/bin/svcprop', '-p', 'config/upgrade-id', |
283 |
149 |
284 # look for any .new files |
150 # look for any .new files |
285 if glob.glob('/etc/nova/*.new'): |
151 if glob.glob('/etc/nova/*.new'): |
286 # the versions are different, so perform an upgrade |
152 # the versions are different, so perform an upgrade |
287 # modify the configuration files |
153 # modify the configuration files |
|
154 |
|
155 # backup all the old configuration files |
|
156 create_backups('/etc/nova') |
|
157 |
288 modify_conf('/etc/nova/api-paste.ini') |
158 modify_conf('/etc/nova/api-paste.ini') |
289 modify_conf('/etc/nova/logging.conf') |
159 modify_conf('/etc/nova/logging.conf') |
290 modify_conf('/etc/nova/nova.conf', NOVA_CONF_MAPPINGS) |
160 |
|
161 # It's possible that nova.conf has database.connection commented out |
|
162 # (to use the default value). If it is, and none of other deprecated |
|
163 # values are set, manually set database.connection in the new conf |
|
164 # file. |
|
165 if os.path.exists('/etc/nova/nova.conf.new'): |
|
166 |
|
167 # open the previous version |
|
168 old = iniparse.ConfigParser() |
|
169 old.readfp(open('/etc/nova/nova.conf')) |
|
170 |
|
171 # open the new version |
|
172 new = iniparse.ConfigParser() |
|
173 new.readfp(open('/etc/nova/nova.conf.new')) |
|
174 |
|
175 options = [ |
|
176 ('database', 'sql_connection'), |
|
177 ('sql', 'connection'), |
|
178 ('database', 'connection'), |
|
179 ('DEFAULT', 'sql_connection') |
|
180 ] |
|
181 test = lambda x: old.has_section(x[0]) and \ |
|
182 old.has_option(x[0], x[1]) |
|
183 |
|
184 if not any(map(test, options)): |
|
185 if old.has_option('DEFAULT', 'state_path'): |
|
186 state_path = old.get('DEFAULT', 'state_path') |
|
187 else: |
|
188 state_path = '/var/lib/nova' |
|
189 |
|
190 if old.has_option('DEFAULT', 'sqlite_db'): |
|
191 sqlite_db = old.get('DEFAULT', 'sqlite_db') |
|
192 else: |
|
193 sqlite_db = 'nova.sqlite' |
|
194 |
|
195 new.set('database', 'connection', |
|
196 'sqlite:///%s/%s' % (state_path, sqlite_db)) |
|
197 |
|
198 with open('/etc/nova/nova.conf.new', 'w+') as fh: |
|
199 new.write(fh) |
|
200 |
|
201 # before modifying nova.conf, move the [filter:authtoken] entries from |
|
202 # the updated api-paste.ini to the old nova.conf |
|
203 move_conf('/etc/nova/api-paste.ini', '/etc/nova/nova.conf', |
|
204 NOVA_MOVE_CONFIG) |
|
205 |
|
206 modify_conf('/etc/nova/nova.conf', NOVA_CONF_MAPPINGS, |
|
207 NOVA_CONF_EXCEPTIONS) |
291 |
208 |
292 config = iniparse.RawConfigParser() |
209 config = iniparse.RawConfigParser() |
293 config.read('/etc/nova/nova.conf') |
210 config.read('/etc/nova/nova.conf') |
294 # In certain cases the database section does not exist and the |
211 # In certain cases the database section does not exist and the |
295 # default database chosen is sqlite. |
212 # default database chosen is sqlite. |