Run nova-manage db online_data_migrations on upgrades

In mitaka an extra operation called online_data_migrations was added to
assist rolling upgrades.

This patch runs this before and after, this is to make sure the old
upgrades where this migration was not being performed are run before
installing a newer release.

References:
- https://git.openstack.org/cgit/openstack/nova/commit/?id=7d5069ce20ec0d792a3974b2c53d01ae005cde98
- https://docs.openstack.org/nova/latest/user/upgrade.html

Change-Id: Ic4bc2c5ae86c99c3af2a1d0ee08badb09835d932
Closes-Bug: 1711209
This commit is contained in:
Felipe Reyes 2017-08-25 15:11:39 -03:00
parent 024a34e52a
commit eacd234ed5
3 changed files with 60 additions and 9 deletions

View File

@ -526,6 +526,7 @@ def get_step_upgrade_source(new_src):
'precise-icehouse/proposed': ('precise-proposed/grizzly',
'cloud:precise-havana/proposed'),
'trusty-liberty': ('*', 'cloud:trusty-kilo'),
'xenial-ocata': ('*', 'cloud:xenial-newton'), # LP: #1711209
}
try:
os_codename = get_os_codename_install_source(new_src)
@ -551,12 +552,12 @@ def get_step_upgrade_source(new_src):
continue
with open(fpath, 'r') as f:
line = f.readline()
for target_src, (cur_pocket, step_src) in sources.items():
if target_src != new_src:
continue
if cur_pocket in line:
return step_src
for line in f.readlines():
for target_src, (cur_pocket, step_src) in sources.items():
if target_src != new_src:
continue
if cur_pocket in line:
return step_src
return None
@ -611,6 +612,12 @@ def _do_openstack_upgrade(new_src):
if (CompareOpenStackReleases(os_release('nova-common')) == 'kilo' and
is_leader()):
migrate_nova_flavors()
# 'nova-manage db online_data_migrations' needs to be run before moving to
# the next release for environments upgraded using old charms where this
# step was not being executed (LP: #1711209).
online_data_migrations_if_needed()
new_os_rel = get_os_codename_install_source(new_src)
cmp_new_os_rel = CompareOpenStackReleases(new_os_rel)
log('Performing OpenStack upgrade to %s.' % (new_os_rel))
@ -655,6 +662,7 @@ def _do_openstack_upgrade(new_src):
if is_leader():
status_set('maintenance', 'Running nova db migration')
migrate_nova_databases()
if not is_unit_paused_set():
[service_start(s) for s in services()]
@ -695,6 +703,16 @@ def migrate_nova_flavors():
subprocess.check_output(cmd)
@retry_on_exception(5, base_delay=3, exc_type=subprocess.CalledProcessError)
def online_data_migrations_if_needed():
'''Runs nova-manage to run online data migrations available since Mitaka'''
if (is_leader() and
CompareOpenStackReleases(os_release('nova-common')) >= 'mitaka'):
log('Running online_data_migrations', level=INFO)
subprocess.check_output(['nova-manage', 'db',
'online_data_migrations'])
def migrate_nova_api_database():
'''Initialize or migrate the nova_api database'''
if CompareOpenStackReleases(os_release('nova-common')) >= 'mitaka':
@ -793,6 +811,7 @@ def migrate_nova_databases():
if CompareOpenStackReleases(os_release('nova-common')) < 'ocata':
migrate_nova_api_database()
migrate_nova_database()
online_data_migrations_if_needed()
finalize_migrate_nova_databases()
# TODO: Replace the following checks with a Cellsv2 context check.
@ -805,6 +824,7 @@ def migrate_nova_databases():
migrate_nova_api_database()
initialize_cell_databases()
migrate_nova_database()
online_data_migrations_if_needed()
add_hosts_to_cell()
finalize_migrate_nova_databases()

View File

@ -566,9 +566,12 @@ class NovaCCHooksTests(CharmTestCase):
self.assertFalse(self.migrate_nova_databases.called)
api_joined.asert_called_with(rid='nova-api/0')
@patch.object(utils, 'is_leader')
@patch.object(utils, 'os_release')
@patch.object(hooks, 'is_db_initialised')
@patch.object(hooks, 'CONFIGS')
def test_db_changed_allowed(self, configs, mock_is_db_initialised):
def test_db_changed_allowed(self, configs, mock_is_db_initialised,
utils_os_release, utils_is_leader):
mock_is_db_initialised.return_value = False
allowed_units = 'nova-cloud-controller/0 nova-cloud-controller/3'
self.test_relation.set({
@ -576,6 +579,8 @@ class NovaCCHooksTests(CharmTestCase):
})
self.local_unit.return_value = 'nova-cloud-controller/3'
self.os_release.return_value = 'diablo'
utils_os_release.return_value = 'diablo'
utils_is_leader.return_value = False
self._shared_db_test(configs)
self.assertTrue(configs.write_all.called)
self.migrate_nova_databases.assert_called_with()
@ -594,23 +599,30 @@ class NovaCCHooksTests(CharmTestCase):
self.assertTrue(configs.write_all.called)
self.assertFalse(self.migrate_nova_databases.called)
@patch.object(utils, 'is_leader')
@patch.object(utils, 'os_release')
@patch.object(hooks, 'quantum_joined')
@patch.object(hooks, 'nova_api_relation_joined')
@patch.object(hooks, 'is_db_initialised')
@patch.object(hooks, 'CONFIGS')
def test_postgresql_db_changed(self, configs, mock_is_db_initialised,
api_joined, quantum_joined):
api_joined, quantum_joined,
utils_os_release, utils_is_leader):
self.relation_ids.side_effect = [
[],
['neutron-gateway/0'],
['nova-api/0']]
mock_is_db_initialised.return_value = False
self.os_release.return_value = 'diablo'
utils_os_release.return_value = 'diablo'
utils_is_leader.return_value = True
self._postgresql_db_test(configs)
self.assertTrue(configs.write_all.called)
self.migrate_nova_databases.assert_called_with()
api_joined.assert_called_with(rid='nova-api/0')
@patch.object(utils, 'is_leader')
@patch.object(utils, 'os_release')
@patch.object(hooks, 'quantum_joined')
@patch.object(hooks, 'is_db_initialised')
@patch.object(hooks, 'nova_cell_relation_joined')
@ -618,7 +630,8 @@ class NovaCCHooksTests(CharmTestCase):
@patch.object(hooks, 'CONFIGS')
def test_db_changed_remote_restarts(self, configs, comp_joined,
cell_joined, mock_is_db_initialised,
quantum_joined):
quantum_joined, utils_os_release,
utils_is_leader):
mock_is_db_initialised.return_value = False
def _relation_ids(rel):
@ -636,6 +649,8 @@ class NovaCCHooksTests(CharmTestCase):
})
self.local_unit.return_value = 'nova-cloud-controller/0'
self.os_release.return_value = 'diablo'
utils_os_release.return_value = 'diablo'
utils_is_leader.return_value = False
self._shared_db_test(configs)
comp_joined.assert_called_with(remote_restart=True,
rid='nova-compute/0')

View File

@ -505,6 +505,18 @@ class NovaCCUtilsTests(CharmTestCase):
step_src = utils.get_step_upgrade_source(OS_ORIGIN_NEWTON_STAGING)
self.assertEqual(step_src, None)
@patch('charmhelpers.contrib.openstack.utils.lsb_release')
def test_get_setup_upgrade_source_target_ocata(self, lsb_release):
# mitaka -> ocata
self.lsb_release.return_value = {'DISTRIB_CODENAME': 'xenial'}
lsb_release.return_value = {'DISTRIB_CODENAME': 'xenial'}
self.os_release.return_value = 'mitaka'
self.get_os_codename_install_source.side_effect = self.originals[
'get_os_codename_install_source']
step_src = utils.get_step_upgrade_source("cloud:xenial-ocata")
self.assertEqual(step_src, "cloud:xenial-newton")
@patch('charmhelpers.contrib.openstack.utils.lsb_release')
def test_get_setup_upgrade_source_target_liberty_with_mirror(self,
lsb_release):
@ -691,6 +703,8 @@ class NovaCCUtilsTests(CharmTestCase):
self.os_release.return_value = 'diablo'
utils.migrate_nova_databases()
check_output.assert_called_with(['nova-manage', 'db', 'sync'])
self.assertNotIn(call(['nova-manage', 'db', 'online_data_migrations']),
check_output.mock_calls)
self.peer_store.assert_called_with('dbsync_state', 'complete')
self.assertTrue(self.enable_services.called)
self.cmd_all_services.assert_called_with('start')
@ -704,6 +718,7 @@ class NovaCCUtilsTests(CharmTestCase):
check_output.assert_has_calls([
call(['nova-manage', 'api_db', 'sync']),
call(['nova-manage', 'db', 'sync']),
call(['nova-manage', 'db', 'online_data_migrations']),
])
self.peer_store.assert_called_with('dbsync_state', 'complete')
self.assertTrue(self.enable_services.called)
@ -724,6 +739,7 @@ class NovaCCUtilsTests(CharmTestCase):
call(['nova-manage', 'api_db', 'sync']),
call(['nova-manage', 'cell_v2', 'map_cell0']),
call(['nova-manage', 'db', 'sync']),
call(['nova-manage', 'db', 'online_data_migrations']),
call(['nova-manage', 'cell_v2', 'list_cells']),
ANY,
])