Disable nova placement API

The placement project has split from nova into its own project
in Train. This patch disables the nova placement API as of Stein
when the placement charm relatation joins, and discontinues
nova placement installation as of Train for new installs.

Change-Id: If7c37ef8936e418b5afd21d83c9322563348cbcf
Needed-By: https://review.opendev.org/#/c/687915/
Partial-Bug: 1811681
This commit is contained in:
Corey Bryant 2019-10-08 18:03:47 +00:00
parent f7f6fa295c
commit 81860afeca
10 changed files with 108 additions and 13 deletions

View File

@ -218,7 +218,10 @@ class HAProxyContext(ch_context.HAProxyContext):
del port_mapping['nova-api-ec2']
del port_mapping['nova-objectstore']
if cmp_os_rel < 'ocata':
rids = hookenv.relation_ids('placement')
if (rids or
cmp_os_rel < 'ocata' or
cmp_os_rel > 'stein'):
del listen_ports['placement_listen_port']
del port_mapping['nova-placement-api']

View File

@ -1292,6 +1292,32 @@ def nova_cell_api_relation_changed(rid=None, unit=None):
restart_trigger=str(uuid.uuid4()))
@hooks.hook('placement-relation-joined')
def placement_relation_joined(rid=None, unit=None):
# For Stein->Train upgrades, operators must pause nova-cloud-controller
# while placement charm is added.
ncc_utils.disable_deprecated_nova_placement_apache_site()
hookenv.relation_set(nova_placement_disabled=True, relation_id=rid)
@hooks.hook('placement-relation-changed')
def placement_relation_changed(rid=None, unit=None):
data = hookenv.relation_get(rid=rid, unit=unit)
if not data.get('placement_enabled'):
return
CONFIGS.write_all()
# kick identity_joined() to publish endpoints without nova placement
for rid in hookenv.relation_ids('identity-service'):
identity_joined(rid)
# kick compute_joined() to restart services on nova compute
for rid in hookenv.relation_ids('cloud-compute'):
compute_joined(rid=rid, remote_restart=True)
# For Stein->Train upgrades, operators can resume nova-cloud-controller
# once the new placement endpoints are published.
for s in ncc_utils.services():
ch_host.service_restart(s)
@hooks.hook('update-status')
@ch_harden.harden()
def update_status():

View File

@ -91,6 +91,7 @@ AWS_COMPAT_SERVICES = ['nova-api-ec2', 'nova-objectstore']
SERVICE_BLACKLIST = {
'liberty': AWS_COMPAT_SERVICES,
'newton': ['nova-cert'],
'train': ['nova-placement-api'],
}
# API_PORTS is now in nova_cc_common.py to break the circular dependency
@ -1447,7 +1448,7 @@ def determine_endpoints(public_url, internal_url, admin_url):
common.api_port('nova-objectstore'))
s3_admin_url = '%s:%s' % (admin_url, common.api_port('nova-objectstore'))
if cmp_os_rel >= 'ocata':
if placement_api_enabled():
placement_public_url = '%s:%s' % (
public_url, common.api_port('nova-placement-api'))
placement_internal_url = '%s:%s' % (
@ -1491,7 +1492,7 @@ def determine_endpoints(public_url, internal_url, admin_url):
's3_internal_url': None,
})
if cmp_os_rel >= 'ocata':
if placement_api_enabled():
endpoints.update({
'placement_service': 'placement',
'placement_region': region,
@ -1755,8 +1756,12 @@ def serial_console_settings():
def placement_api_enabled():
"""Return true if nova-placement-api is enabled in this release"""
return ch_utils.CompareOpenStackReleases(
ch_utils.os_release('nova-common')) >= 'ocata'
rids = hookenv.relation_ids('placement')
release = ch_utils.os_release('nova-common')
return (
not rids and
ch_utils.CompareOpenStackReleases(release) >= 'ocata' and
ch_utils.CompareOpenStackReleases(release) <= 'stein')
def enable_metadata_api(release=None):
@ -1808,6 +1813,14 @@ def stop_deprecated_services():
ch_host.service_pause('nova-api-os-compute')
def disable_deprecated_nova_placement_apache_site():
"""Disable deprecated nova placement apache2 configuration"""
release = ch_utils.os_release('nova-common')
if ch_utils.CompareOpenStackReleases(release) >= 'stein':
if os.path.exists(WSGI_NOVA_PLACEMENT_API_CONF):
os.remove(WSGI_NOVA_PLACEMENT_API_CONF)
def get_shared_metadatasecret():
"""Return the shared metadata secret."""
return hookenv.leader_get(SHARED_METADATA_SECRET_KEY)

View File

@ -0,0 +1 @@
nova_cc_hooks.py

View File

@ -0,0 +1 @@
nova_cc_hooks.py

View File

@ -64,6 +64,8 @@ requires:
interface: mysql-shared
amqp-cell:
interface: rabbitmq
placement:
interface: placement
peers:
cluster:
interface: nova-ha

View File

@ -504,7 +504,8 @@ class NovaCCBasicDeployment(OpenStackAmuletDeployment):
expected['ec2_region'] = 'RegionOne'
expected['ec2_service'] = 'ec2'
if self._get_openstack_release() >= self.xenial_ocata:
if (self._get_openstack_release() >= self.xenial_ocata and
self._get_openstack_release() <= self.disco_stein):
expected['placement_service'] = 'placement'
expected['placement_internal_url'] = u.valid_url
expected['placement_public_url'] = u.valid_url
@ -539,7 +540,8 @@ class NovaCCBasicDeployment(OpenStackAmuletDeployment):
if self._get_openstack_release() >= self.trusty_kilo:
expected['service_username'] = 'nova'
if self._get_openstack_release() >= self.xenial_ocata:
if (self._get_openstack_release() >= self.xenial_ocata and
self._get_openstack_release() <= self.disco_stein):
expected['service_username'] = 'nova_placement'
ret = u.validate_relation_data(unit, relation, expected)
@ -903,7 +905,8 @@ class NovaCCBasicDeployment(OpenStackAmuletDeployment):
del services['nova-api-os-compute']
services['apache2'] = conf_file
if self._get_openstack_release() >= self.xenial_ocata:
if (self._get_openstack_release() >= self.xenial_ocata and
self._get_openstack_release() <= self.disco_stein):
# nova-placement-api is run under apache2 with mod_wsgi
services['apache2'] = conf_file

View File

@ -132,6 +132,7 @@ class NovaComputeContextTests(CharmTestCase):
self.assertEqual(ctxt['nova_url'], 'http://10.0.1.1:8774/v2')
self.assertFalse('neutron_url' in ctxt)
@mock.patch('charmhelpers.core.hookenv.relation_ids')
@mock.patch('charmhelpers.contrib.openstack.context.config')
@mock.patch('charmhelpers.contrib.openstack.context.get_relation_ip')
@mock.patch('charmhelpers.contrib.openstack.context.mkdir')
@ -150,12 +151,13 @@ class NovaComputeContextTests(CharmTestCase):
mock_local_unit, mock_get_netmask_for_address,
mock_get_address_in_network, mock_kv, mock_https,
mock_unit_get, mock_network_manager, mock_mkdir,
mock_get_relation_ip, mock_config):
mock_get_relation_ip, mock_config, mock_rids):
self.os_release.return_value = 'ocata'
mock_config.side_effect = self.test_config.get
mock_https.return_value = False
mock_unit_get.return_value = '127.0.0.1'
mock_network_manager.return_value = 'neutron'
mock_rids.return_value = []
ctxt = context.HAProxyContext()()
self.assertEqual(ctxt['service_ports']['nova-api-os-compute'],
[8774, 8764])

View File

@ -57,6 +57,7 @@ TO_PATCH = [
'charmhelpers.core.hookenv.unit_get',
'charmhelpers.core.host.service_pause',
'charmhelpers.core.host.service_reload',
'charmhelpers.core.host.service_restart',
'charmhelpers.core.host.service_resume',
'charmhelpers.fetch.apt_install',
'charmhelpers.fetch.apt_update',
@ -1060,6 +1061,28 @@ class NovaCCHooksTests(CharmTestCase):
ha='settings',
relation_id=None)
@patch('hooks.nova_cc_utils.disable_deprecated_nova_placement_apache_site')
def test_placement_joined(self, disable_nova_placement):
hooks.placement_relation_joined()
self.assertTrue(disable_nova_placement.called)
self.relation_set.assert_called_with(nova_placement_disabled=True,
relation_id=None)
@patch.object(hooks, 'compute_joined')
@patch.object(hooks, 'identity_joined')
@patch.object(hooks, 'CONFIGS')
def test_placement_changed(self, configs, identity_joined, compute_joined):
self.test_relation.set({
'placement_enabled': True,
})
self.services.return_value = ['dummy-service']
self.relation_ids.return_value = ['generic_rid']
hooks.placement_relation_changed()
self.assertTrue(self.service_restart.called)
self.assertTrue(configs.write_all.called)
self.assertTrue(identity_joined.called)
self.assertTrue(compute_joined.called)
@patch.object(hooks, 'memcached_common')
def test_memcache_joined(self, _memcached_common):
self.get_relation_ip.return_value = 'foo'

View File

@ -340,41 +340,47 @@ class NovaCCUtilsTests(CharmTestCase):
self.assertIsInstance(_map, OrderedDict)
self.assertEqual(_map, RESTART_MAP_ICEHOUSE)
@patch('charmhelpers.core.hookenv.relation_ids')
@patch('charmhelpers.contrib.openstack.neutron.os_release')
@patch('os.path.exists')
@patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext')
def test_restart_map_api_actual_ocata(
self, subcontext, _exists, _os_release):
self, subcontext, _exists, _os_release, rids):
_os_release.return_value = 'ocata'
self.os_release.return_value = 'ocata'
_exists.return_value = False
self.enable_memcache.return_value = False
rids.return_value = []
_map = utils.restart_map()
self.assertIsInstance(_map, OrderedDict)
self.assertEqual(_map, RESTART_MAP_OCATA_ACTUAL)
@patch('charmhelpers.core.hookenv.relation_ids')
@patch('charmhelpers.contrib.openstack.neutron.os_release')
@patch('os.path.exists')
@patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext')
def test_restart_map_api_actual_rocky(
self, subcontext, _exists, _os_release):
self, subcontext, _exists, _os_release, rids):
_os_release.return_value = 'rocky'
self.os_release.return_value = 'rocky'
_exists.return_value = False
self.enable_memcache.return_value = False
rids.return_value = []
_map = utils.restart_map()
self.assertIsInstance(_map, OrderedDict)
self.assertEqual(_map, RESTART_MAP_ROCKY_ACTUAL)
@patch('charmhelpers.core.hookenv.relation_ids')
@patch('charmhelpers.contrib.openstack.neutron.os_release')
@patch('os.path.exists')
@patch('charmhelpers.contrib.openstack.context.SubordinateConfigContext')
def test_restart_map_api_ocata_base(
self, subcontext, _exists, _os_release):
self, subcontext, _exists, _os_release, rids):
_os_release.return_value = 'ocata'
self.os_release.return_value = 'ocata'
_exists.return_value = False
self.enable_memcache.return_value = False
rids.return_value = []
_map = utils.restart_map(actual_services=False)
self.assertIsInstance(_map, OrderedDict)
self.assertEqual(_map, RESTART_MAP_OCATA_BASE)
@ -1456,10 +1462,16 @@ class NovaCCUtilsTests(CharmTestCase):
shared_db.assert_called_once()
self.log.assert_not_called()
def test_placement_api_enabled(self):
@patch('charmhelpers.core.hookenv.relation_ids')
def test_placement_api_enabled(self, rids):
self.os_release.return_value = 'ocata'
rids.return_value = []
self.assertTrue(utils.placement_api_enabled())
self.os_release.return_value = 'mitaka'
rids.return_value = []
self.assertFalse(utils.placement_api_enabled())
self.os_release.return_value = 'train'
rids.return_value = ['placement:1']
self.assertFalse(utils.placement_api_enabled())
def test_enable_metadata_api(self):
@ -1635,3 +1647,12 @@ class NovaCCUtilsTests(CharmTestCase):
utils.update_child_cell('cell2', 'mysql-cell2', 'amqp-cell2')
self.assertFalse(mock_check_output.called)
self.assertFalse(self.service_restart.called)
@patch('os.remove')
@patch('os.path.exists')
def test_disable_deprecated_nova_placement_apache_site(self, exists,
remove):
self.os_release.return_value = 'stein'
exists.return_value = True
utils.disable_deprecated_nova_placement_apache_site()
self.assertTrue(remove.called)