[gnuoy,r=james-page] Conditional migration of neutron db in neutron-api for >=kilo
This commit is contained in:
commit
c0f642c0cd
|
@ -11,6 +11,7 @@ from charmhelpers.core.hookenv import (
|
||||||
UnregisteredHookError,
|
UnregisteredHookError,
|
||||||
config,
|
config,
|
||||||
is_relation_made,
|
is_relation_made,
|
||||||
|
local_unit,
|
||||||
log,
|
log,
|
||||||
ERROR,
|
ERROR,
|
||||||
relation_get,
|
relation_get,
|
||||||
|
@ -23,6 +24,7 @@ from charmhelpers.core.hookenv import (
|
||||||
from charmhelpers.core.host import (
|
from charmhelpers.core.host import (
|
||||||
restart_on_change,
|
restart_on_change,
|
||||||
service_reload,
|
service_reload,
|
||||||
|
service_restart,
|
||||||
)
|
)
|
||||||
|
|
||||||
from charmhelpers.fetch import (
|
from charmhelpers.fetch import (
|
||||||
|
@ -37,10 +39,12 @@ from charmhelpers.contrib.openstack.utils import (
|
||||||
git_install_requested,
|
git_install_requested,
|
||||||
openstack_upgrade_available,
|
openstack_upgrade_available,
|
||||||
os_requires_version,
|
os_requires_version,
|
||||||
|
os_release,
|
||||||
sync_db_with_multi_ipv6_addresses
|
sync_db_with_multi_ipv6_addresses
|
||||||
)
|
)
|
||||||
|
|
||||||
from neutron_api_utils import (
|
from neutron_api_utils import (
|
||||||
|
CLUSTER_RES,
|
||||||
NEUTRON_CONF,
|
NEUTRON_CONF,
|
||||||
api_port,
|
api_port,
|
||||||
determine_packages,
|
determine_packages,
|
||||||
|
@ -49,6 +53,7 @@ from neutron_api_utils import (
|
||||||
git_install,
|
git_install,
|
||||||
dvr_router_present,
|
dvr_router_present,
|
||||||
l3ha_router_present,
|
l3ha_router_present,
|
||||||
|
migrate_neutron_database,
|
||||||
neutron_ready,
|
neutron_ready,
|
||||||
register_configs,
|
register_configs,
|
||||||
restart_map,
|
restart_map,
|
||||||
|
@ -66,6 +71,7 @@ from neutron_api_context import (
|
||||||
|
|
||||||
from charmhelpers.contrib.hahelpers.cluster import (
|
from charmhelpers.contrib.hahelpers.cluster import (
|
||||||
get_hacluster_config,
|
get_hacluster_config,
|
||||||
|
is_elected_leader,
|
||||||
)
|
)
|
||||||
|
|
||||||
from charmhelpers.payload.execd import execd_preinstall
|
from charmhelpers.payload.execd import execd_preinstall
|
||||||
|
@ -91,6 +97,25 @@ hooks = Hooks()
|
||||||
CONFIGS = register_configs()
|
CONFIGS = register_configs()
|
||||||
|
|
||||||
|
|
||||||
|
def conditional_neutron_migration():
|
||||||
|
if os_release('neutron-server') < 'kilo':
|
||||||
|
log('Not running neutron database migration as migrations are handled '
|
||||||
|
'by the neutron-server process or nova-cloud-controller charm.')
|
||||||
|
return
|
||||||
|
|
||||||
|
if is_elected_leader(CLUSTER_RES):
|
||||||
|
allowed_units = relation_get('allowed_units')
|
||||||
|
if allowed_units and local_unit() in allowed_units.split():
|
||||||
|
migrate_neutron_database()
|
||||||
|
service_restart('neutron-server')
|
||||||
|
else:
|
||||||
|
log('Not running neutron database migration, either no'
|
||||||
|
' allowed_units or this unit is not present')
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
log('Not running neutron database migration, not leader')
|
||||||
|
|
||||||
|
|
||||||
def configure_https():
|
def configure_https():
|
||||||
'''
|
'''
|
||||||
Enables SSL API Apache config if appropriate and kicks identity-service
|
Enables SSL API Apache config if appropriate and kicks identity-service
|
||||||
|
@ -231,12 +256,14 @@ def db_changed():
|
||||||
log('shared-db relation incomplete. Peer not ready?')
|
log('shared-db relation incomplete. Peer not ready?')
|
||||||
return
|
return
|
||||||
CONFIGS.write_all()
|
CONFIGS.write_all()
|
||||||
|
conditional_neutron_migration()
|
||||||
|
|
||||||
|
|
||||||
@hooks.hook('pgsql-db-relation-changed')
|
@hooks.hook('pgsql-db-relation-changed')
|
||||||
@restart_on_change(restart_map())
|
@restart_on_change(restart_map())
|
||||||
def postgresql_neutron_db_changed():
|
def postgresql_neutron_db_changed():
|
||||||
CONFIGS.write(NEUTRON_CONF)
|
CONFIGS.write(NEUTRON_CONF)
|
||||||
|
conditional_neutron_migration()
|
||||||
|
|
||||||
|
|
||||||
@hooks.hook('amqp-relation-broken',
|
@hooks.hook('amqp-relation-broken',
|
||||||
|
|
|
@ -3,6 +3,7 @@ from copy import deepcopy
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
import subprocess
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
from charmhelpers.contrib.openstack import context, templating
|
from charmhelpers.contrib.openstack import context, templating
|
||||||
from charmhelpers.contrib.openstack.neutron import (
|
from charmhelpers.contrib.openstack.neutron import (
|
||||||
|
@ -258,6 +259,7 @@ def do_openstack_upgrade(configs):
|
||||||
|
|
||||||
:param configs: The charms main OSConfigRenderer object.
|
:param configs: The charms main OSConfigRenderer object.
|
||||||
"""
|
"""
|
||||||
|
cur_os_rel = os_release('neutron-server')
|
||||||
new_src = config('openstack-origin')
|
new_src = config('openstack-origin')
|
||||||
new_os_rel = get_os_codename_install_source(new_src)
|
new_os_rel = get_os_codename_install_source(new_src)
|
||||||
|
|
||||||
|
@ -279,6 +281,38 @@ def do_openstack_upgrade(configs):
|
||||||
|
|
||||||
# set CONFIGS to load templates from new release
|
# set CONFIGS to load templates from new release
|
||||||
configs.set_release(openstack_release=new_os_rel)
|
configs.set_release(openstack_release=new_os_rel)
|
||||||
|
# Before kilo it's nova-cloud-controllers job
|
||||||
|
if new_os_rel >= 'kilo':
|
||||||
|
stamp_neutron_database(cur_os_rel)
|
||||||
|
migrate_neutron_database()
|
||||||
|
|
||||||
|
|
||||||
|
def stamp_neutron_database(release):
|
||||||
|
'''Stamp the database with the current release before upgrade.'''
|
||||||
|
log('Stamping the neutron database with release %s.' % release)
|
||||||
|
plugin = config('neutron-plugin')
|
||||||
|
cmd = ['neutron-db-manage',
|
||||||
|
'--config-file', NEUTRON_CONF,
|
||||||
|
'--config-file', neutron_plugin_attribute(plugin,
|
||||||
|
'config',
|
||||||
|
'neutron'),
|
||||||
|
'stamp',
|
||||||
|
release]
|
||||||
|
subprocess.check_output(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def migrate_neutron_database():
|
||||||
|
'''Initializes a new database or upgrades an existing database.'''
|
||||||
|
log('Migrating the neutron database.')
|
||||||
|
plugin = config('neutron-plugin')
|
||||||
|
cmd = ['neutron-db-manage',
|
||||||
|
'--config-file', NEUTRON_CONF,
|
||||||
|
'--config-file', neutron_plugin_attribute(plugin,
|
||||||
|
'config',
|
||||||
|
'neutron'),
|
||||||
|
'upgrade',
|
||||||
|
'head']
|
||||||
|
subprocess.check_output(cmd)
|
||||||
|
|
||||||
|
|
||||||
def get_topics():
|
def get_topics():
|
||||||
|
|
|
@ -34,6 +34,7 @@ TO_PATCH = [
|
||||||
'determine_ports',
|
'determine_ports',
|
||||||
'do_openstack_upgrade',
|
'do_openstack_upgrade',
|
||||||
'dvr_router_present',
|
'dvr_router_present',
|
||||||
|
'local_unit',
|
||||||
'l3ha_router_present',
|
'l3ha_router_present',
|
||||||
'execd_preinstall',
|
'execd_preinstall',
|
||||||
'filter_installed_packages',
|
'filter_installed_packages',
|
||||||
|
@ -42,15 +43,19 @@ TO_PATCH = [
|
||||||
'get_l2population',
|
'get_l2population',
|
||||||
'get_overlay_network_type',
|
'get_overlay_network_type',
|
||||||
'git_install',
|
'git_install',
|
||||||
|
'is_elected_leader',
|
||||||
'is_relation_made',
|
'is_relation_made',
|
||||||
'log',
|
'log',
|
||||||
|
'migrate_neutron_database',
|
||||||
'neutron_ready',
|
'neutron_ready',
|
||||||
'open_port',
|
'open_port',
|
||||||
'openstack_upgrade_available',
|
'openstack_upgrade_available',
|
||||||
|
'os_release',
|
||||||
'os_requires_version',
|
'os_requires_version',
|
||||||
'relation_get',
|
'relation_get',
|
||||||
'relation_ids',
|
'relation_ids',
|
||||||
'relation_set',
|
'relation_set',
|
||||||
|
'service_restart',
|
||||||
'unit_get',
|
'unit_get',
|
||||||
'get_iface_for_address',
|
'get_iface_for_address',
|
||||||
'get_netmask_for_address',
|
'get_netmask_for_address',
|
||||||
|
@ -292,19 +297,23 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||||
'Attempting to associate a postgresql database when'
|
'Attempting to associate a postgresql database when'
|
||||||
' there is already associated a mysql one')
|
' there is already associated a mysql one')
|
||||||
|
|
||||||
def test_shared_db_changed(self):
|
@patch.object(hooks, 'conditional_neutron_migration')
|
||||||
|
def test_shared_db_changed(self, cond_neutron_mig):
|
||||||
self.CONFIGS.complete_contexts.return_value = ['shared-db']
|
self.CONFIGS.complete_contexts.return_value = ['shared-db']
|
||||||
self._call_hook('shared-db-relation-changed')
|
self._call_hook('shared-db-relation-changed')
|
||||||
self.assertTrue(self.CONFIGS.write_all.called)
|
self.assertTrue(self.CONFIGS.write_all.called)
|
||||||
|
cond_neutron_mig.assert_called_with()
|
||||||
|
|
||||||
def test_shared_db_changed_partial_ctxt(self):
|
def test_shared_db_changed_partial_ctxt(self):
|
||||||
self.CONFIGS.complete_contexts.return_value = []
|
self.CONFIGS.complete_contexts.return_value = []
|
||||||
self._call_hook('shared-db-relation-changed')
|
self._call_hook('shared-db-relation-changed')
|
||||||
self.assertFalse(self.CONFIGS.write_all.called)
|
self.assertFalse(self.CONFIGS.write_all.called)
|
||||||
|
|
||||||
def test_pgsql_db_changed(self):
|
@patch.object(hooks, 'conditional_neutron_migration')
|
||||||
|
def test_pgsql_db_changed(self, cond_neutron_mig):
|
||||||
self._call_hook('pgsql-db-relation-changed')
|
self._call_hook('pgsql-db-relation-changed')
|
||||||
self.assertTrue(self.CONFIGS.write.called)
|
self.assertTrue(self.CONFIGS.write.called)
|
||||||
|
cond_neutron_mig.assert_called_with()
|
||||||
|
|
||||||
def test_amqp_broken(self):
|
def test_amqp_broken(self):
|
||||||
self._call_hook('amqp-relation-broken')
|
self._call_hook('amqp-relation-broken')
|
||||||
|
@ -668,3 +677,46 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||||
call('service', 'apache2', 'reload')]
|
call('service', 'apache2', 'reload')]
|
||||||
self.check_call.assert_called_has_calls(calls)
|
self.check_call.assert_called_has_calls(calls)
|
||||||
self.assertTrue(_id_rel_joined.called)
|
self.assertTrue(_id_rel_joined.called)
|
||||||
|
|
||||||
|
def test_conditional_neutron_migration_icehouse(self):
|
||||||
|
self.os_release.return_value = 'icehouse'
|
||||||
|
hooks.conditional_neutron_migration()
|
||||||
|
self.log.assert_called_with(
|
||||||
|
'Not running neutron database migration as migrations are handled '
|
||||||
|
'by the neutron-server process or nova-cloud-controller charm.'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_conditional_neutron_migration_ncc_rel_leader_juno(self):
|
||||||
|
self.test_relation.set({
|
||||||
|
'allowed_units': 'neutron-api/0 neutron-api/1 neutron-api/4',
|
||||||
|
})
|
||||||
|
self.local_unit.return_value = 'neutron-api/1'
|
||||||
|
self.is_elected_leader.return_value = True
|
||||||
|
self.os_release.return_value = 'juno'
|
||||||
|
hooks.conditional_neutron_migration()
|
||||||
|
self.log.assert_called_with(
|
||||||
|
'Not running neutron database migration as migrations are handled'
|
||||||
|
' by the neutron-server process or nova-cloud-controller charm.'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_conditional_neutron_migration_ncc_rel_leader_kilo(self):
|
||||||
|
self.test_relation.set({
|
||||||
|
'allowed_units': 'neutron-api/0 neutron-api/1 neutron-api/4',
|
||||||
|
})
|
||||||
|
self.local_unit.return_value = 'neutron-api/1'
|
||||||
|
self.is_elected_leader.return_value = True
|
||||||
|
self.os_release.return_value = 'kilo'
|
||||||
|
hooks.conditional_neutron_migration()
|
||||||
|
self.migrate_neutron_database.assert_called_with()
|
||||||
|
self.service_restart.assert_called_with('neutron-server')
|
||||||
|
|
||||||
|
def test_conditional_neutron_migration_ncc_rel_notleader(self):
|
||||||
|
self.is_elected_leader.return_value = False
|
||||||
|
self.os_release.return_value = 'juno'
|
||||||
|
hooks.conditional_neutron_migration()
|
||||||
|
self.assertFalse(self.migrate_neutron_database.called)
|
||||||
|
self.assertFalse(self.service_restart.called)
|
||||||
|
self.log.assert_called_with(
|
||||||
|
'Not running neutron database migration as migrations are handled '
|
||||||
|
'by the neutron-server process or nova-cloud-controller charm.'
|
||||||
|
)
|
||||||
|
|
|
@ -3,6 +3,7 @@ from mock import MagicMock, patch, call
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
import charmhelpers.contrib.openstack.templating as templating
|
import charmhelpers.contrib.openstack.templating as templating
|
||||||
|
import charmhelpers.contrib.openstack.utils
|
||||||
import neutron_api_context as ncontext
|
import neutron_api_context as ncontext
|
||||||
|
|
||||||
templating.OSConfigRenderer = MagicMock()
|
templating.OSConfigRenderer = MagicMock()
|
||||||
|
@ -30,6 +31,7 @@ TO_PATCH = [
|
||||||
'log',
|
'log',
|
||||||
'neutron_plugin_attribute',
|
'neutron_plugin_attribute',
|
||||||
'os_release',
|
'os_release',
|
||||||
|
'subprocess',
|
||||||
]
|
]
|
||||||
|
|
||||||
openstack_origin_git = \
|
openstack_origin_git = \
|
||||||
|
@ -73,7 +75,6 @@ class TestNeutronAPIUtils(CharmTestCase):
|
||||||
self.config.side_effect = self.test_config.get
|
self.config.side_effect = self.test_config.get
|
||||||
self.test_config.set('region', 'region101')
|
self.test_config.set('region', 'region101')
|
||||||
self.neutron_plugin_attribute.side_effect = _mock_npa
|
self.neutron_plugin_attribute.side_effect = _mock_npa
|
||||||
self.os_release.side_effect = 'trusty'
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
# Reset cached cache
|
# Reset cached cache
|
||||||
|
@ -182,15 +183,19 @@ class TestNeutronAPIUtils(CharmTestCase):
|
||||||
nutils.keystone_ca_cert_b64()
|
nutils.keystone_ca_cert_b64()
|
||||||
self.assertTrue(self.b64encode.called)
|
self.assertTrue(self.b64encode.called)
|
||||||
|
|
||||||
|
@patch.object(nutils, 'migrate_neutron_database')
|
||||||
|
@patch.object(nutils, 'stamp_neutron_database')
|
||||||
@patch.object(nutils, 'git_install_requested')
|
@patch.object(nutils, 'git_install_requested')
|
||||||
def test_do_openstack_upgrade(self, git_requested):
|
def test_do_openstack_upgrade_juno(self, git_requested,
|
||||||
|
stamp_neutron_db, migrate_neutron_db):
|
||||||
git_requested.return_value = False
|
git_requested.return_value = False
|
||||||
self.config.side_effect = self.test_config.get
|
self.config.side_effect = self.test_config.get
|
||||||
self.test_config.set('openstack-origin', 'cloud:trusty-juno')
|
self.test_config.set('openstack-origin', 'cloud:trusty-juno')
|
||||||
self.os_release.side_effect = 'icehouse'
|
self.os_release.return_value = 'icehouse'
|
||||||
self.get_os_codename_install_source.return_value = 'juno'
|
self.get_os_codename_install_source.return_value = 'juno'
|
||||||
configs = MagicMock()
|
configs = MagicMock()
|
||||||
nutils.do_openstack_upgrade(configs)
|
nutils.do_openstack_upgrade(configs)
|
||||||
|
self.os_release.assert_called_with('neutron-server')
|
||||||
self.log.assert_called()
|
self.log.assert_called()
|
||||||
self.configure_installation_source.assert_called_with(
|
self.configure_installation_source.assert_called_with(
|
||||||
'cloud:trusty-juno'
|
'cloud:trusty-juno'
|
||||||
|
@ -209,6 +214,46 @@ class TestNeutronAPIUtils(CharmTestCase):
|
||||||
options=dpkg_opts,
|
options=dpkg_opts,
|
||||||
fatal=True)
|
fatal=True)
|
||||||
configs.set_release.assert_called_with(openstack_release='juno')
|
configs.set_release.assert_called_with(openstack_release='juno')
|
||||||
|
self.assertItemsEqual(stamp_neutron_db.call_args_list, [])
|
||||||
|
self.assertItemsEqual(migrate_neutron_db.call_args_list, [])
|
||||||
|
|
||||||
|
@patch.object(charmhelpers.contrib.openstack.utils,
|
||||||
|
'get_os_codename_install_source')
|
||||||
|
@patch.object(nutils, 'migrate_neutron_database')
|
||||||
|
@patch.object(nutils, 'stamp_neutron_database')
|
||||||
|
@patch.object(nutils, 'git_install_requested')
|
||||||
|
def test_do_openstack_upgrade_kilo(self, git_requested,
|
||||||
|
stamp_neutron_db, migrate_neutron_db,
|
||||||
|
gsrc):
|
||||||
|
git_requested.return_value = False
|
||||||
|
self.os_release.return_value = 'juno'
|
||||||
|
self.config.side_effect = self.test_config.get
|
||||||
|
self.test_config.set('openstack-origin', 'cloud:trusty-kilo')
|
||||||
|
gsrc.return_value = 'kilo'
|
||||||
|
self.get_os_codename_install_source.return_value = 'kilo'
|
||||||
|
configs = MagicMock()
|
||||||
|
nutils.do_openstack_upgrade(configs)
|
||||||
|
self.os_release.assert_called_with('neutron-server')
|
||||||
|
self.log.assert_called()
|
||||||
|
self.configure_installation_source.assert_called_with(
|
||||||
|
'cloud:trusty-kilo'
|
||||||
|
)
|
||||||
|
self.apt_update.assert_called_with(fatal=True)
|
||||||
|
dpkg_opts = [
|
||||||
|
'--option', 'Dpkg::Options::=--force-confnew',
|
||||||
|
'--option', 'Dpkg::Options::=--force-confdef',
|
||||||
|
]
|
||||||
|
self.apt_upgrade.assert_called_with(options=dpkg_opts,
|
||||||
|
fatal=True,
|
||||||
|
dist=True)
|
||||||
|
pkgs = nutils.determine_packages()
|
||||||
|
pkgs.sort()
|
||||||
|
self.apt_install.assert_called_with(packages=pkgs,
|
||||||
|
options=dpkg_opts,
|
||||||
|
fatal=True)
|
||||||
|
configs.set_release.assert_called_with(openstack_release='kilo')
|
||||||
|
stamp_neutron_db.assert_called_with('juno')
|
||||||
|
migrate_neutron_db.assert_called_with()
|
||||||
|
|
||||||
@patch.object(ncontext, 'IdentityServiceContext')
|
@patch.object(ncontext, 'IdentityServiceContext')
|
||||||
@patch('neutronclient.v2_0.client.Client')
|
@patch('neutronclient.v2_0.client.Client')
|
||||||
|
@ -402,3 +447,21 @@ class TestNeutronAPIUtils(CharmTestCase):
|
||||||
call('neutron-server'),
|
call('neutron-server'),
|
||||||
]
|
]
|
||||||
self.assertEquals(service_restart.call_args_list, expected)
|
self.assertEquals(service_restart.call_args_list, expected)
|
||||||
|
|
||||||
|
def test_stamp_neutron_database(self):
|
||||||
|
nutils.stamp_neutron_database('icehouse')
|
||||||
|
cmd = ['neutron-db-manage',
|
||||||
|
'--config-file', '/etc/neutron/neutron.conf',
|
||||||
|
'--config-file', '/etc/neutron/plugins/ml2/ml2_conf.ini',
|
||||||
|
'stamp',
|
||||||
|
'icehouse']
|
||||||
|
self.subprocess.check_output.assert_called_with(cmd)
|
||||||
|
|
||||||
|
def test_migrate_neutron_database(self):
|
||||||
|
nutils.migrate_neutron_database()
|
||||||
|
cmd = ['neutron-db-manage',
|
||||||
|
'--config-file', '/etc/neutron/neutron.conf',
|
||||||
|
'--config-file', '/etc/neutron/plugins/ml2/ml2_conf.ini',
|
||||||
|
'upgrade',
|
||||||
|
'head']
|
||||||
|
self.subprocess.check_output.assert_called_with(cmd)
|
||||||
|
|
Loading…
Reference in New Issue