From c4188808201eef9119f9106c3d0580327c0ab50e Mon Sep 17 00:00:00 2001
From: Liam Young <liam.young@canonical.com>
Date: Thu, 15 Nov 2018 15:37:54 +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: I473ed1da342b2294f0f66f836b40387c1f831f5c
Closes-Bug: 1803451
---
 hooks/horizon_hooks.py           |  7 +++++++
 hooks/horizon_utils.py           | 17 +++++++++++++----
 unit_tests/test_horizon_hooks.py | 25 +++++++++++++++++++++++++
 3 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/hooks/horizon_hooks.py b/hooks/horizon_hooks.py
index d6e1390..9221afc 100755
--- a/hooks/horizon_hooks.py
+++ b/hooks/horizon_hooks.py
@@ -55,6 +55,7 @@ from charmhelpers.fetch import (
 from charmhelpers.core.host import (
     lsb_release,
     service_reload,
+    service_restart,
 )
 from charmhelpers.contrib.openstack.utils import (
     configure_installation_source,
@@ -101,6 +102,7 @@ from hooks.horizon_utils import (
     check_custom_theme,
     pause_unit_helper,
     resume_unit_helper,
+    remove_old_packages,
 )
 
 hooks = Hooks()
@@ -133,8 +135,13 @@ def install():
 def upgrade_charm():
     execd_preinstall()
     apt_install(filter_installed_packages(determine_packages()), fatal=True)
+    packages_removed = remove_old_packages()
     update_nrpe_config()
     CONFIGS.write_all()
+    if packages_removed:
+        log("Package purge detected, restarting services", "INFO")
+        for s in services():
+            service_restart(s)
     check_custom_theme()
 
 
diff --git a/hooks/horizon_utils.py b/hooks/horizon_utils.py
index bc2b244..5043a39 100644
--- a/hooks/horizon_utils.py
+++ b/hooks/horizon_utils.py
@@ -296,6 +296,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 do_openstack_upgrade(configs):
     """
     Perform an upgrade.  Takes care of upgrading packages, rewriting
@@ -319,10 +331,7 @@ def do_openstack_upgrade(configs):
     reset_os_release()
     apt_install(determine_packages(), fatal=True)
 
-    installed_pkgs = filter_missing_packages(determine_purge_packages())
-    if installed_pkgs:
-        apt_purge(installed_pkgs, 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)
diff --git a/unit_tests/test_horizon_hooks.py b/unit_tests/test_horizon_hooks.py
index 222045e..13fc34a 100644
--- a/unit_tests/test_horizon_hooks.py
+++ b/unit_tests/test_horizon_hooks.py
@@ -64,6 +64,9 @@ TO_PATCH = [
     'lsb_release',
     'status_set',
     'update_dns_ha_resource_params',
+    'services',
+    'service_restart',
+    'remove_old_packages',
 ]
 
 
@@ -141,6 +144,7 @@ class TestHorizonHooks(CharmTestCase):
                                 _determine_packages,
                                 _custom_theme,
                                 _sleep):
+        self.remove_old_packages.return_value = False
         _determine_packages.return_value = []
         side_effects = []
         [side_effects.append(None) for f in RESTART_MAP.keys()]
@@ -164,6 +168,27 @@ class TestHorizonHooks(CharmTestCase):
         # restart_on_change actually sleeps for 9 seconds,
         _sleep.assert_called()
 
+    @patch('time.sleep')
+    @patch('hooks.horizon_hooks.check_custom_theme')
+    @patch.object(hooks, 'determine_packages')
+    @patch.object(utils, 'path_hash')
+    @patch.object(utils, 'service')
+    def test_upgrade_charm_hook_purge(self, _service, _hash,
+                                      _determine_packages,
+                                      _custom_theme,
+                                      _sleep):
+        self.remove_old_packages.return_value = True
+        self.services.return_value = ['apache2']
+        _determine_packages.return_value = []
+        side_effects = []
+        [side_effects.append(None) for f in RESTART_MAP.keys()]
+        [side_effects.append('bar') for f in RESTART_MAP.keys()]
+        _hash.side_effect = side_effects
+        self.filter_installed_packages.return_value = ['foo']
+        self._call_hook('upgrade-charm')
+        self.remove_old_packages.assert_called_once_with()
+        self.service_restart.assert_called_once_with('apache2')
+
     def test_ha_joined_complete_config(self):
         conf = {
             'ha-bindiface': 'eth100',
-- 
GitLab