diff --git a/hooks/nova_cc_hooks.py b/hooks/nova_cc_hooks.py index f1d4d2c5..0639f8ad 100755 --- a/hooks/nova_cc_hooks.py +++ b/hooks/nova_cc_hooks.py @@ -898,6 +898,12 @@ def upgrade_charm(): for s in ncc_utils.services(): ch_host.service_restart(s) + # For users already using bionic-rocky which are upgrading their + # charm only we need ensure to not end-up with the old + # 'wsgi-openstack-api' and the new 'wsgi-placement-api' apache + # configurations installed at the same time. + ncc_utils.disable_package_apache_site(service_reload=True) + for r_id in hookenv.relation_ids('amqp'): amqp_joined(relation_id=r_id) for r_id in hookenv.relation_ids('identity-service'): diff --git a/hooks/nova_cc_utils.py b/hooks/nova_cc_utils.py index b285e6bb..87322c12 100644 --- a/hooks/nova_cc_utils.py +++ b/hooks/nova_cc_utils.py @@ -106,9 +106,11 @@ APACHE_CONF = '/etc/apache2/sites-available/openstack_https_frontend' APACHE_24_CONF = '/etc/apache2/sites-available/openstack_https_frontend.conf' MEMCACHED_CONF = '/etc/memcached.conf' WSGI_NOVA_PLACEMENT_API_CONF = \ - '/etc/apache2/sites-enabled/wsgi-openstack-api.conf' + '/etc/apache2/sites-enabled/wsgi-placement-api.conf' PACKAGE_NOVA_PLACEMENT_API_CONF = \ '/etc/apache2/sites-enabled/nova-placement-api.conf' +OLD_WSGI_NOVA_PLACEMENT_API_CONF = \ + '/etc/apache2/sites-enabled/wsgi-openstack-api.conf' WSGI_NOVA_METADATA_API_CONF = \ '/etc/apache2/sites-enabled/wsgi-openstack-metadata.conf' VENDORDATA_FILE = '/etc/nova/vendor_data.json' @@ -562,6 +564,7 @@ def _do_openstack_upgrade(new_src): ch_fetch.apt_install(determine_packages(), fatal=True) remove_old_packages() + disable_package_apache_site() disable_policy_rcd() @@ -1453,12 +1456,30 @@ def enable_metadata_api(release=None): return ch_utils.CompareOpenStackReleases(release) >= 'rocky' -def disable_package_apache_site(): - """Ensure that the package-provided apache configuration is disabled to - prevent it from conflicting with the charm-provided version. +def disable_package_apache_site(service_reload=False): + """Ensure the package-provided apache2 configuration is disabled. + + This ensures the package-provided apache2 configuration doesn't + conflict with the charm-provided version. + + :param service_reload: Boolean that indicates the service should + be reloaded if a change occurred in sites-enabled. + """ - if os.path.exists(PACKAGE_NOVA_PLACEMENT_API_CONF): - subprocess.check_call(['a2dissite', 'nova-placement-api']) + site_changed = False + if placement_api_enabled(): + if os.path.exists(PACKAGE_NOVA_PLACEMENT_API_CONF): + subprocess.check_call(['a2dissite', 'nova-placement-api']) + site_changed = True + if os.path.exists(OLD_WSGI_NOVA_PLACEMENT_API_CONF): + # wsgi-openstack-api.conf is generated is copied as a plain + # text to sites-enables. a2dissite does not accept to remove + # "file" that is not symlink from sites-available. + os.remove(OLD_WSGI_NOVA_PLACEMENT_API_CONF) + site_changed = True + + if site_changed and service_reload: + ch_host.service_reload('apache2', restart_on_failure=True) def get_shared_metadatasecret(): diff --git a/templates/wsgi-placement-api.conf b/templates/wsgi-placement-api.conf new file mode 120000 index 00000000..c9067c89 --- /dev/null +++ b/templates/wsgi-placement-api.conf @@ -0,0 +1 @@ +../charmhelpers/contrib/openstack/templates/wsgi-openstack-api.conf \ No newline at end of file diff --git a/unit_tests/test_nova_cc_utils.py b/unit_tests/test_nova_cc_utils.py index 72573c5c..b08b3dd2 100644 --- a/unit_tests/test_nova_cc_utils.py +++ b/unit_tests/test_nova_cc_utils.py @@ -140,7 +140,7 @@ RESTART_MAP_OCATA_ACTUAL = OrderedDict([ ('/etc/nova/api-paste.ini', ['nova-api-os-compute', 'apache2']), ('/etc/haproxy/haproxy.cfg', ['haproxy']), ('/etc/apache2/sites-available/openstack_https_frontend', ['apache2']), - ('/etc/apache2/sites-enabled/wsgi-openstack-api.conf', ['apache2']), + ('/etc/apache2/sites-enabled/wsgi-placement-api.conf', ['apache2']), ]) RESTART_MAP_OCATA_BASE = OrderedDict([ ('/etc/nova/nova.conf', [ @@ -969,6 +969,37 @@ class NovaCCUtilsTests(CharmTestCase): self.assertFalse(migrate_nova_databases.called) database_setup.assert_called_with(prefix='novaapi') + @patch.object(utils, 'online_data_migrations_if_needed') + @patch.object(utils, 'disable_package_apache_site') + @patch.object(utils, 'database_setup') + @patch.object(utils, 'get_step_upgrade_source') + @patch.object(utils, 'migrate_nova_databases') + @patch.object(utils, 'determine_packages') + def test_upgrade_queens_rocky(self, determine_packages, + migrate_nova_databases, + get_step_upgrade_source, + database_setup, + disable_package_apache_site, + online_data_migrations_if_needed): + "Simulate a call to do_openstack_upgrade() for queens->rocky" + self.test_config.set('openstack-origin', 'cloud:bionic-queens') + get_step_upgrade_source.return_value = None + self.os_release.return_value = 'queens' + self.get_os_codename_install_source.return_value = 'rocky' + self.is_leader.return_value = True + self.relation_ids.return_value = [] + database_setup.return_value = False + utils.do_openstack_upgrade(self.register_configs()) + self.apt_update.assert_called_with(fatal=True) + self.apt_upgrade.assert_called_with(options=DPKG_OPTS, fatal=True, + dist=True) + self.apt_install.assert_called_with(determine_packages(), fatal=True) + self.register_configs.assert_called_with(release='rocky') + self.assertFalse(migrate_nova_databases.called) + database_setup.assert_called_with(prefix='novaapi') + online_data_migrations_if_needed.assert_called_once() + disable_package_apache_site.assert_called_once() + def test_guard_map_nova(self): self.relation_ids.return_value = [] self.os_release.return_value = 'icehouse'