From 8cde93e515cb39aaeb6cc1ecf7fd45c55c50e6ee Mon Sep 17 00:00:00 2001
From: Liam Young <liam.young@canonical.com>
Date: Thu, 15 Nov 2018 13:57:21 +0000
Subject: [PATCH] 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 restart
services.

Change-Id: I23812e518d5d0ba64dff33ac8d704b8b0f829b7e
Closes-Bug: 1803451
---
 hooks/ceilometer_hooks.py           |  6 ++++++
 lib/ceilometer_utils.py             | 17 +++++++++++++----
 unit_tests/test_ceilometer_hooks.py | 15 +++++++++++++++
 3 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/hooks/ceilometer_hooks.py b/hooks/ceilometer_hooks.py
index fee6822..ace6f63 100755
--- a/hooks/ceilometer_hooks.py
+++ b/hooks/ceilometer_hooks.py
@@ -80,6 +80,7 @@ from ceilometer_utils import (
     reload_systemd,
     pause_unit_helper,
     resume_unit_helper,
+    remove_old_packages,
 )
 from ceilometer_contexts import CEILOMETER_PORT
 from charmhelpers.contrib.openstack.ip import (
@@ -262,6 +263,11 @@ def install_event_pipeline_setting():
 @harden()
 def upgrade_charm():
     install()
+    packages_removed = remove_old_packages()
+    if packages_removed and not is_unit_paused_set():
+        log("Package purge detected, restarting services", "INFO")
+        for s in services():
+            service_restart(s)
     update_nrpe_config()
     any_changed()
     for rid in relation_ids('cluster'):
diff --git a/lib/ceilometer_utils.py b/lib/ceilometer_utils.py
index e146293..e9a12f9 100644
--- a/lib/ceilometer_utils.py
+++ b/lib/ceilometer_utils.py
@@ -380,10 +380,7 @@ def do_openstack_upgrade(configs):
                 options=dpkg_opts,
                 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
     configs.set_release(openstack_release=new_os_rel)
@@ -448,6 +445,18 @@ def determine_purge_packages():
     return []
 
 
+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 get_shared_secret():
     """
     Returns the current shared secret for the ceilometer node. If the shared
diff --git a/unit_tests/test_ceilometer_hooks.py b/unit_tests/test_ceilometer_hooks.py
index 6a31adc..6126200 100644
--- a/unit_tests/test_ceilometer_hooks.py
+++ b/unit_tests/test_ceilometer_hooks.py
@@ -71,6 +71,8 @@ TO_PATCH = [
     'get_relation_ip',
     'is_clustered',
     'get_os_codename_install_source',
+    'services',
+    'remove_old_packages',
 ]
 
 
@@ -151,10 +153,23 @@ class CeilometerHooksTest(CharmTestCase):
     @patch.object(hooks, 'install')
     @patch.object(hooks, 'any_changed')
     def test_upgrade_charm(self, changed, install, mock_config):
+        self.remove_old_packages.return_value = False
         hooks.hooks.execute(['hooks/upgrade-charm'])
         self.assertTrue(changed.called)
         self.assertTrue(install.called)
 
+    @patch('charmhelpers.core.hookenv.config')
+    @patch.object(hooks, 'install')
+    @patch.object(hooks, 'any_changed')
+    def test_upgrade_charm_purge(self, changed, install, mock_config):
+        self.remove_old_packages.return_value = True
+        self.services.return_value = ['ceilometer-important-service']
+        hooks.hooks.execute(['hooks/upgrade-charm'])
+        self.assertTrue(changed.called)
+        self.assertTrue(install.called)
+        self.service_restart.assert_called_once_with(
+            'ceilometer-important-service')
+
     @patch.object(hooks, 'any_changed')
     @patch('charmhelpers.core.hookenv.config')
     @patch.object(hooks, 'cluster_joined')
-- 
GitLab