Publish releases packages map to principal charm
For principal - subordinate plugin type relations where the
principal Python payload imports code from packages managed by a
subordinate, upgrades can be problematic.
This change will allow a subordinate charm that have opted into the
feature to inform its principal about all implemented release -
packages combinations ahead of time. With this information in place
the principal can do the upgrade in one operation without risk of
charm relation RPC type processing at a critical moment.
This is similar to
https://review.opendev.org/c/openstack/charm-interface-keystone-domain-backend/+/781658
https://review.opendev.org/c/openstack/charm-layer-openstack/+/781624
Change-Id: Ibd5bdcb141fc3103ee97123ff284fb2957802eba
Closes-Bug: #1927277
(cherry picked from commit be45f77945
)
This commit is contained in:
parent
32ff18a775
commit
5e97b3c92a
|
@ -59,6 +59,7 @@ from ceilometer_utils import (
|
||||||
NOVA_SETTINGS,
|
NOVA_SETTINGS,
|
||||||
assess_status,
|
assess_status,
|
||||||
get_packages,
|
get_packages,
|
||||||
|
releases_packages_map,
|
||||||
pause_unit_helper,
|
pause_unit_helper,
|
||||||
resume_unit_helper,
|
resume_unit_helper,
|
||||||
remove_old_packages,
|
remove_old_packages,
|
||||||
|
@ -83,8 +84,14 @@ def install():
|
||||||
|
|
||||||
@hooks.hook('nova-ceilometer-relation-joined')
|
@hooks.hook('nova-ceilometer-relation-joined')
|
||||||
def nova_ceilometer_joined(relation_id=None):
|
def nova_ceilometer_joined(relation_id=None):
|
||||||
relation_set(relation_id=relation_id,
|
relation_set(
|
||||||
subordinate_configuration=json.dumps(NOVA_SETTINGS))
|
relation_id=relation_id,
|
||||||
|
relation_settings={
|
||||||
|
'subordinate_configuration': json.dumps(NOVA_SETTINGS),
|
||||||
|
'releases-packages-map': json.dumps(
|
||||||
|
releases_packages_map(), sort_keys=True),
|
||||||
|
'services': json.dumps(services())
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@hooks.hook("ceilometer-service-relation-changed")
|
@hooks.hook("ceilometer-service-relation-changed")
|
||||||
|
|
|
@ -115,8 +115,7 @@ def register_configs():
|
||||||
# if called without anything installed (eg during install hook)
|
# if called without anything installed (eg during install hook)
|
||||||
# just default to earliest supported release. configs dont get touched
|
# just default to earliest supported release. configs dont get touched
|
||||||
# till post-install, anyway.
|
# till post-install, anyway.
|
||||||
release = get_os_codename_package('ceilometer-common', fatal=False) \
|
release = _get_current_release()
|
||||||
or 'icehouse'
|
|
||||||
configs = templating.OSConfigRenderer(templates_dir=TEMPLATES,
|
configs = templating.OSConfigRenderer(templates_dir=TEMPLATES,
|
||||||
openstack_release=release)
|
openstack_release=release)
|
||||||
|
|
||||||
|
@ -137,8 +136,7 @@ def register_configs():
|
||||||
|
|
||||||
|
|
||||||
def get_packages():
|
def get_packages():
|
||||||
release = CompareOpenStackReleases(get_os_codename_package(
|
release = _get_current_release()
|
||||||
'ceilometer-common', fatal=False) or 'icehouse')
|
|
||||||
|
|
||||||
packages = deepcopy(CEILOMETER_AGENT_PACKAGES)
|
packages = deepcopy(CEILOMETER_AGENT_PACKAGES)
|
||||||
packages.extend(token_cache_pkgs(release=release))
|
packages.extend(token_cache_pkgs(release=release))
|
||||||
|
@ -157,8 +155,7 @@ def determine_purge_packages():
|
||||||
|
|
||||||
:returns: list of package names
|
:returns: list of package names
|
||||||
'''
|
'''
|
||||||
release = CompareOpenStackReleases(get_os_codename_package(
|
release = _get_current_release()
|
||||||
'ceilometer-common', fatal=False) or 'icehouse')
|
|
||||||
if release >= 'rocky':
|
if release >= 'rocky':
|
||||||
pkgs = [p for p in CEILOMETER_AGENT_PACKAGES
|
pkgs = [p for p in CEILOMETER_AGENT_PACKAGES
|
||||||
if p.startswith('python-')]
|
if p.startswith('python-')]
|
||||||
|
@ -166,6 +163,40 @@ def determine_purge_packages():
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def releases_packages_map():
|
||||||
|
'''Provide a map of all supported releases and their packages.
|
||||||
|
|
||||||
|
NOTE(lourot): this is a simplified version of a more generic
|
||||||
|
implementation:
|
||||||
|
https://github.com/openstack/charms.openstack/blob/master/charms_openstack/charm/core.py
|
||||||
|
|
||||||
|
:returns: Map of release, package type and install / purge packages.
|
||||||
|
Example:
|
||||||
|
{
|
||||||
|
'mitaka': {
|
||||||
|
'deb': {
|
||||||
|
'install': ['python-ldappool'],
|
||||||
|
'purge': []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'rocky': {
|
||||||
|
'deb': {
|
||||||
|
'install': ['python3-ldap', 'python3-ldappool'],
|
||||||
|
'purge': ['python-ldap', 'python-ldappool']}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:rtype: Dict[str,Dict[str,List[str]]]
|
||||||
|
'''
|
||||||
|
return {
|
||||||
|
_get_current_release(): {
|
||||||
|
'deb': {
|
||||||
|
'install': get_packages(),
|
||||||
|
'purge': determine_purge_packages(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def remove_old_packages():
|
def remove_old_packages():
|
||||||
'''Purge any packages that need ot be removed.
|
'''Purge any packages that need ot be removed.
|
||||||
|
|
||||||
|
@ -183,8 +214,7 @@ def remove_old_packages():
|
||||||
def determine_held_packages():
|
def determine_held_packages():
|
||||||
'''Return a list of packages to mark as candidates for removal
|
'''Return a list of packages to mark as candidates for removal
|
||||||
for the current OS release'''
|
for the current OS release'''
|
||||||
release = CompareOpenStackReleases(get_os_codename_package(
|
release = _get_current_release()
|
||||||
'ceilometer-common', fatal=False) or 'icehouse')
|
|
||||||
if release >= 'rocky':
|
if release >= 'rocky':
|
||||||
return HELD_PACKAGES
|
return HELD_PACKAGES
|
||||||
return []
|
return []
|
||||||
|
@ -198,8 +228,7 @@ def restart_map():
|
||||||
:returns: dict: A dictionary mapping config file to lists of services
|
:returns: dict: A dictionary mapping config file to lists of services
|
||||||
that should be restarted when file changes.
|
that should be restarted when file changes.
|
||||||
'''
|
'''
|
||||||
release = (get_os_codename_package('ceilometer-common', fatal=False) or
|
release = _get_current_release()
|
||||||
'icehouse')
|
|
||||||
|
|
||||||
if CompareOpenStackReleases(release) >= 'queens':
|
if CompareOpenStackReleases(release) >= 'queens':
|
||||||
_config_files = QUEENS_CONFIG_FILES
|
_config_files = QUEENS_CONFIG_FILES
|
||||||
|
@ -291,3 +320,8 @@ def _pause_resume_helper(f, configs):
|
||||||
f(assess_status_func(configs),
|
f(assess_status_func(configs),
|
||||||
services=services(),
|
services=services(),
|
||||||
ports=None)
|
ports=None)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_current_release():
|
||||||
|
return (get_os_codename_package('ceilometer-common', fatal=False)
|
||||||
|
or 'icehouse')
|
||||||
|
|
|
@ -29,6 +29,8 @@ TO_PATCH = [
|
||||||
'apt_update',
|
'apt_update',
|
||||||
'filter_installed_packages',
|
'filter_installed_packages',
|
||||||
'get_packages',
|
'get_packages',
|
||||||
|
'releases_packages_map',
|
||||||
|
'services',
|
||||||
'is_relation_made',
|
'is_relation_made',
|
||||||
'is_unit_paused_set',
|
'is_unit_paused_set',
|
||||||
'relation_set',
|
'relation_set',
|
||||||
|
@ -65,11 +67,27 @@ class CeilometerHooksTest(CharmTestCase):
|
||||||
|
|
||||||
@patch('charmhelpers.core.hookenv.config')
|
@patch('charmhelpers.core.hookenv.config')
|
||||||
def test_nova_ceilometer_joined(self, mock_config):
|
def test_nova_ceilometer_joined(self, mock_config):
|
||||||
|
mocked_releases_packages_map = {
|
||||||
|
'ussuri': {
|
||||||
|
'deb': {
|
||||||
|
'install': [
|
||||||
|
'ceilometer-common', 'ceilometer-agent-compute',
|
||||||
|
'python3-ceilometer', 'python3-memcache'],
|
||||||
|
'purge': ['python-ceilometer'],
|
||||||
|
}}}
|
||||||
|
mocked_services = ['ceilometer-agent-compute']
|
||||||
|
|
||||||
|
self.releases_packages_map.return_value = mocked_releases_packages_map
|
||||||
|
self.services.return_value = mocked_services
|
||||||
hooks.hooks.execute(['hooks/nova-ceilometer-relation-joined'])
|
hooks.hooks.execute(['hooks/nova-ceilometer-relation-joined'])
|
||||||
self.relation_set.assert_called_with(
|
self.relation_set.assert_called_with(
|
||||||
relation_id=None,
|
relation_id=None,
|
||||||
subordinate_configuration=json.dumps(
|
relation_settings={
|
||||||
ceilometer_utils.NOVA_SETTINGS))
|
'subordinate_configuration': json.dumps(
|
||||||
|
ceilometer_utils.NOVA_SETTINGS),
|
||||||
|
'releases-packages-map': json.dumps(
|
||||||
|
mocked_releases_packages_map, sort_keys=True),
|
||||||
|
'services': json.dumps(mocked_services)})
|
||||||
|
|
||||||
@patch('charmhelpers.core.hookenv.config')
|
@patch('charmhelpers.core.hookenv.config')
|
||||||
def test_config_changed(self, mock_config):
|
def test_config_changed(self, mock_config):
|
||||||
|
|
|
@ -157,3 +157,15 @@ class CeilometerUtilsTest(CharmTestCase):
|
||||||
sorted([p for p in utils.CEILOMETER_AGENT_PACKAGES
|
sorted([p for p in utils.CEILOMETER_AGENT_PACKAGES
|
||||||
if not p.startswith('python-')] +
|
if not p.startswith('python-')] +
|
||||||
['python3-ceilometer', 'python3-memcache']))
|
['python3-ceilometer', 'python3-memcache']))
|
||||||
|
|
||||||
|
def test_releases_packages_map(self):
|
||||||
|
self.get_os_codename_package.return_value = 'ussuri'
|
||||||
|
self.token_cache_pkgs.return_value = []
|
||||||
|
self.assertEqual(utils.releases_packages_map(), {
|
||||||
|
'ussuri': {
|
||||||
|
'deb': {
|
||||||
|
'install': [
|
||||||
|
'ceilometer-common', 'ceilometer-agent-compute',
|
||||||
|
'python3-ceilometer', 'python3-memcache'],
|
||||||
|
'purge': ['python-ceilometer'],
|
||||||
|
}}})
|
||||||
|
|
Loading…
Reference in New Issue