Purge old packages on upgrade-charm

On charm upgrade the charm may switch to py3 packages. If so, ensure
the old py2 packages are purged. If the purge occurs then restore
the glance-api-paste.ini from packages and restart services.

Closes-Bug: 1803451
Change-Id: Ib258873fb2be95821e8f8c22fd1f3d19666b3181
This commit is contained in:
Liam Young 2018-11-15 09:45:05 +00:00
parent aadc2ce8dd
commit 9ddaa45565
4 changed files with 93 additions and 11 deletions

View File

@ -56,6 +56,7 @@ from glance_utils import (
update_image_location_policy,
pause_unit_helper,
resume_unit_helper,
remove_old_packages,
)
from charmhelpers.core.hookenv import (
charm_dir,
@ -419,11 +420,16 @@ def cluster_changed():
@harden()
def upgrade_charm():
apt_install(filter_installed_packages(determine_packages()), fatal=True)
reinstall_paste_ini()
packages_removed = remove_old_packages()
reinstall_paste_ini(force_reinstall=packages_removed)
configure_https()
update_nrpe_config()
update_image_location_policy()
CONFIGS.write_all()
if packages_removed:
juju_log("Package purge detected, restarting services", "INFO")
for s in services():
service_restart(s)
@hooks.hook('ha-relation-joined')

View File

@ -273,7 +273,7 @@ def determine_purge_packages():
:returns: list of package names
'''
if CompareOpenStackReleases(os_release('cinder')) >= 'rocky':
if CompareOpenStackReleases(os_release('glance')) >= 'rocky':
pkgs = [p for p in PACKAGES if p.startswith('python-')]
pkgs.append('python-glance')
pkgs.append('python-memcache')
@ -295,6 +295,18 @@ def migrate_database():
subprocess.check_call(cmd)
def remove_old_packages():
'''Purge any packages that need ot be removed.
:returns: bool Whether packages were removed.
'''
installed_packages = filter_missing_packages(determine_purge_packages())
if installed_packages:
apt_purge(installed_packages, fatal=True)
apt_autoremove(purge=True, fatal=True)
return bool(installed_packages)
def do_openstack_upgrade(configs):
"""Perform an upgrade of glance. Takes care of upgrading
packages, rewriting configs + database migration and potentially
@ -318,10 +330,7 @@ def do_openstack_upgrade(configs):
reset_os_release()
apt_install(determine_packages(), fatal=True)
installed_packages = filter_missing_packages(determine_purge_packages())
if installed_packages:
apt_purge(installed_packages, fatal=True)
apt_autoremove(purge=True, fatal=True)
remove_old_packages()
# set CONFIGS to load templates from new release and regenerate config
configs.set_release(openstack_release=new_os_rel)
@ -547,7 +556,7 @@ REINSTALL_OPTIONS = [
]
def reinstall_paste_ini():
def reinstall_paste_ini(force_reinstall=False):
'''
Re-install glance-{api,registry}-paste.ini file from packages
@ -555,15 +564,25 @@ def reinstall_paste_ini():
and the original files provided by the packages will be
re-installed.
This will only ever be performed once per unit.
This will only be performed once per unit unless force_reinstall
is set to True.
'''
db = kv()
if not db.get(PASTE_INI_MARKER):
if not db.get(PASTE_INI_MARKER) or force_reinstall:
for paste_file in [GLANCE_REGISTRY_PASTE,
GLANCE_API_PASTE]:
if os.path.exists(paste_file):
os.remove(paste_file)
apt_install(packages=['glance-api', 'glance-registry'],
cmp_release = CompareOpenStackReleases(os_release('glance-common'))
if cmp_release < 'queens':
pkg_list = ['glance-api', 'glance-registry']
# glance-registry is deprecated in Queens
elif cmp_release < 'rocky':
pkg_list = ['glance-api']
# File is in glance-common for py3 packages.
else:
pkg_list = ['glance-common']
apt_install(packages=pkg_list,
options=REINSTALL_OPTIONS,
fatal=True)
db.set(PASTE_INI_MARKER, True)

View File

@ -91,6 +91,8 @@ TO_PATCH = [
'update_nrpe_config',
'reinstall_paste_ini',
'determine_packages',
'remove_old_packages',
'services',
# other
'call',
'check_call',
@ -572,12 +574,29 @@ class GlanceRelationTests(CharmTestCase):
@patch.object(relations, 'update_image_location_policy')
@patch.object(relations, 'CONFIGS')
def test_upgrade_charm(self, configs, mock_update_image_location_policy):
self.remove_old_packages.return_value = False
self.filter_installed_packages.return_value = ['test']
relations.upgrade_charm()
self.apt_install.assert_called_with(['test'], fatal=True)
self.assertTrue(configs.write_all.called)
self.assertTrue(self.reinstall_paste_ini.called)
self.assertTrue(mock_update_image_location_policy.called)
self.assertTrue(self.remove_old_packages.called)
@patch.object(relations, 'update_image_location_policy')
@patch.object(relations, 'CONFIGS')
def test_upgrade_charm_purge(self, configs,
mock_update_image_location_policy):
self.services.return_value = ['glance-api']
self.remove_old_packages.return_value = True
self.filter_installed_packages.return_value = ['test']
relations.upgrade_charm()
self.apt_install.assert_called_with(['test'], fatal=True)
self.assertTrue(configs.write_all.called)
self.reinstall_paste_ini.assert_called_once_with(force_reinstall=True)
self.assertTrue(mock_update_image_location_policy.called)
self.assertTrue(self.remove_old_packages.called)
self.service_restart.assert_called_once_with('glance-api')
def test_ha_relation_joined(self):
self.get_hacluster_config.return_value = {

View File

@ -276,10 +276,12 @@ class TestGlanceUtils(CharmTestCase):
# ports=None whilst port checks are disabled.
f.assert_called_once_with('assessor', services='s1', ports=None)
@patch.object(utils, 'os_release')
@patch.object(utils, 'os')
@patch.object(utils, 'kv')
def test_reinstall_paste_ini(self, kv, _os):
def test_reinstall_paste_ini(self, kv, _os, mock_os_release):
"""Ensure that paste.ini files are re-installed"""
mock_os_release.return_value = 'pike'
_os.path.exists.return_value = True
test_kv = SimpleKV()
kv.return_value = test_kv
@ -300,6 +302,42 @@ class TestGlanceUtils(CharmTestCase):
self.assertTrue(test_kv.get(utils.PASTE_INI_MARKER))
self.assertTrue(test_kv.flushed)
@patch.object(utils, 'os_release')
@patch.object(utils, 'os')
@patch.object(utils, 'kv')
def test_reinstall_paste_ini_queens(self, kv, _os, mock_os_release):
"""Ensure that paste.ini files are re-installed"""
mock_os_release.return_value = 'queens'
_os.path.exists.return_value = True
test_kv = SimpleKV()
kv.return_value = test_kv
utils.reinstall_paste_ini()
self.apt_install.assert_called_with(
packages=['glance-api'],
options=utils.REINSTALL_OPTIONS,
fatal=True
)
@patch.object(utils, 'os_release')
@patch.object(utils, 'os')
@patch.object(utils, 'kv')
def test_reinstall_paste_ini_rocky(self, kv, _os, mock_os_release):
"""Ensure that paste.ini files are re-installed"""
mock_os_release.return_value = 'queens'
_os.path.exists.return_value = True
test_kv = SimpleKV()
kv.return_value = test_kv
self.apt_install.reset_mock()
mock_os_release.return_value = 'rocky'
utils.reinstall_paste_ini()
self.apt_install.assert_called_with(
packages=['glance-common'],
options=utils.REINSTALL_OPTIONS,
fatal=True
)
@patch.object(utils, 'kv')
def test_reinstall_paste_ini_idempotent(self, kv):
"""Ensure that re-running does not re-install files"""