c8b625
From 8e539e045371769a63f3b33fc53eed568d644695 Mon Sep 17 00:00:00 2001
c8b625
From: Emanuele Giuseppe Esposito <eesposit@redhat.com>
c8b625
Date: Tue, 31 May 2022 09:33:08 +0200
c8b625
Subject: [PATCH] Leave the details of service management to the distro (#1074)
c8b625
c8b625
RH-Author: Emanuele Giuseppe Esposito <eesposit@redhat.com>
c8b625
RH-MergeRequest: 73: Leave the details of service management to the distro (#1074)
c8b625
RH-Commit: [1/1] d33e0976d8811a6cb2755eb08fd3a4c811be53f5 (eesposit/cloud-init)
c8b625
RH-Bugzilla: 2091935
c8b625
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
c8b625
RH-Acked-by: Mohamed Gamal Morsy <mmorsy@redhat.com>
c8b625
c8b625
commit 8c89009e75c7cf6c2f87635b82656f07f58095e1
c8b625
Author: Andy Fiddaman <omnios@citrus-it.co.uk>
c8b625
Date:   Wed Oct 20 20:58:27 2021 +0000
c8b625
c8b625
    Leave the details of service management to the distro (#1074)
c8b625
c8b625
    Various modules restart services and they all have logic to try and
c8b625
    detect if they are running on a system that needs 'systemctl' or
c8b625
    'service', and then have code to decide which order the arguments
c8b625
    need to be etc. On top of that, not all modules do this in the same way.
c8b625
c8b625
    The duplication and different approaches are not ideal but this also
c8b625
    makes it hard to add support for a new distribution that does not use
c8b625
    either 'systemctl' or 'service'.
c8b625
c8b625
    This change adds a new manage_service() method to the distro class
c8b625
    and updates several modules to use it.
c8b625
c8b625
Signed-off-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
c8b625
---
c8b625
 cloudinit/config/cc_fan.py                    | 42 ++++++++-----------
c8b625
 cloudinit/config/cc_ntp.py                    | 20 ++-------
c8b625
 cloudinit/config/cc_rsyslog.py                | 17 +++-----
c8b625
 cloudinit/config/cc_set_passwords.py          | 17 ++------
c8b625
 cloudinit/config/tests/test_set_passwords.py  | 41 ++++++++----------
c8b625
 cloudinit/distros/__init__.py                 | 28 +++++++++++++
c8b625
 .../test_distros/test_manage_service.py       | 38 +++++++++++++++++
c8b625
 .../test_handler/test_handler_ntp.py          | 29 +++----------
c8b625
 8 files changed, 119 insertions(+), 113 deletions(-)
c8b625
 create mode 100644 tests/unittests/test_distros/test_manage_service.py
c8b625
c8b625
diff --git a/cloudinit/config/cc_fan.py b/cloudinit/config/cc_fan.py
c8b625
index 77984bca..91f50e22 100644
c8b625
--- a/cloudinit/config/cc_fan.py
c8b625
+++ b/cloudinit/config/cc_fan.py
c8b625
@@ -52,35 +52,26 @@ BUILTIN_CFG = {
c8b625
 }
c8b625
 
c8b625
 
c8b625
-def stop_update_start(service, config_file, content, systemd=False):
c8b625
-    if systemd:
c8b625
-        cmds = {'stop': ['systemctl', 'stop', service],
c8b625
-                'start': ['systemctl', 'start', service],
c8b625
-                'enable': ['systemctl', 'enable', service]}
c8b625
-    else:
c8b625
-        cmds = {'stop': ['service', 'stop'],
c8b625
-                'start': ['service', 'start']}
c8b625
-
c8b625
-    def run(cmd, msg):
c8b625
-        try:
c8b625
-            return subp.subp(cmd, capture=True)
c8b625
-        except subp.ProcessExecutionError as e:
c8b625
-            LOG.warning("failed: %s (%s): %s", service, cmd, e)
c8b625
-            return False
c8b625
-
c8b625
-    stop_failed = not run(cmds['stop'], msg='stop %s' % service)
c8b625
+def stop_update_start(distro, service, config_file, content):
c8b625
+    try:
c8b625
+        distro.manage_service('stop', service)
c8b625
+        stop_failed = False
c8b625
+    except subp.ProcessExecutionError as e:
c8b625
+        stop_failed = True
c8b625
+        LOG.warning("failed to stop %s: %s", service, e)
c8b625
+
c8b625
     if not content.endswith('\n'):
c8b625
         content += '\n'
c8b625
     util.write_file(config_file, content, omode="w")
c8b625
 
c8b625
-    ret = run(cmds['start'], msg='start %s' % service)
c8b625
-    if ret and stop_failed:
c8b625
-        LOG.warning("success: %s started", service)
c8b625
-
c8b625
-    if 'enable' in cmds:
c8b625
-        ret = run(cmds['enable'], msg='enable %s' % service)
c8b625
+    try:
c8b625
+        distro.manage_service('start', service)
c8b625
+        if stop_failed:
c8b625
+            LOG.warning("success: %s started", service)
c8b625
+    except subp.ProcessExecutionError as e:
c8b625
+        LOG.warning("failed to start %s: %s", service, e)
c8b625
 
c8b625
-    return ret
c8b625
+    distro.manage_service('enable', service)
c8b625
 
c8b625
 
c8b625
 def handle(name, cfg, cloud, log, args):
c8b625
@@ -99,7 +90,8 @@ def handle(name, cfg, cloud, log, args):
c8b625
         distro.install_packages(['ubuntu-fan'])
c8b625
 
c8b625
     stop_update_start(
c8b625
+        distro,
c8b625
         service='ubuntu-fan', config_file=mycfg.get('config_path'),
c8b625
-        content=mycfg.get('config'), systemd=distro.uses_systemd())
c8b625
+        content=mycfg.get('config'))
c8b625
 
c8b625
 # vi: ts=4 expandtab
c8b625
diff --git a/cloudinit/config/cc_ntp.py b/cloudinit/config/cc_ntp.py
c8b625
index e183993f..4f358c8a 100644
c8b625
--- a/cloudinit/config/cc_ntp.py
c8b625
+++ b/cloudinit/config/cc_ntp.py
c8b625
@@ -459,21 +459,6 @@ def write_ntp_config_template(distro_name, service_name=None, servers=None,
c8b625
         util.del_file(template_fn)
c8b625
 
c8b625
 
c8b625
-def reload_ntp(service, systemd=False):
c8b625
-    """Restart or reload an ntp system service.
c8b625
-
c8b625
-    @param service: A string specifying the name of the service to be affected.
c8b625
-    @param systemd: A boolean indicating if the distro uses systemd, defaults
c8b625
-    to False.
c8b625
-    @returns: A tuple of stdout, stderr results from executing the action.
c8b625
-    """
c8b625
-    if systemd:
c8b625
-        cmd = ['systemctl', 'reload-or-restart', service]
c8b625
-    else:
c8b625
-        cmd = ['service', service, 'restart']
c8b625
-    subp.subp(cmd, capture=True)
c8b625
-
c8b625
-
c8b625
 def supplemental_schema_validation(ntp_config):
c8b625
     """Validate user-provided ntp:config option values.
c8b625
 
c8b625
@@ -583,10 +568,11 @@ def handle(name, cfg, cloud, log, _args):
c8b625
                        packages=ntp_client_config['packages'],
c8b625
                        check_exe=ntp_client_config['check_exe'])
c8b625
     try:
c8b625
-        reload_ntp(ntp_client_config['service_name'],
c8b625
-                   systemd=cloud.distro.uses_systemd())
c8b625
+        cloud.distro.manage_service('reload',
c8b625
+                                    ntp_client_config.get('service_name'))
c8b625
     except subp.ProcessExecutionError as e:
c8b625
         LOG.exception("Failed to reload/start ntp service: %s", e)
c8b625
         raise
c8b625
 
c8b625
+
c8b625
 # vi: ts=4 expandtab
c8b625
diff --git a/cloudinit/config/cc_rsyslog.py b/cloudinit/config/cc_rsyslog.py
c8b625
index 2a2bc931..dd2bbd00 100644
c8b625
--- a/cloudinit/config/cc_rsyslog.py
c8b625
+++ b/cloudinit/config/cc_rsyslog.py
c8b625
@@ -207,16 +207,11 @@ HOST_PORT_RE = re.compile(
c8b625
     r'([:](?P<port>[0-9]+))?$')
c8b625
 
c8b625
 
c8b625
-def reload_syslog(command=DEF_RELOAD, systemd=False):
c8b625
-    service = 'rsyslog'
c8b625
+def reload_syslog(distro, command=DEF_RELOAD):
c8b625
     if command == DEF_RELOAD:
c8b625
-        if systemd:
c8b625
-            cmd = ['systemctl', 'reload-or-try-restart', service]
c8b625
-        else:
c8b625
-            cmd = ['service', service, 'restart']
c8b625
-    else:
c8b625
-        cmd = command
c8b625
-    subp.subp(cmd, capture=True)
c8b625
+        service = distro.get_option('rsyslog_svcname', 'rsyslog')
c8b625
+        return distro.manage_service('try-reload', service)
c8b625
+    return subp.subp(command, capture=True)
c8b625
 
c8b625
 
c8b625
 def load_config(cfg):
c8b625
@@ -429,9 +424,7 @@ def handle(name, cfg, cloud, log, _args):
c8b625
         return
c8b625
 
c8b625
     try:
c8b625
-        restarted = reload_syslog(
c8b625
-            command=mycfg[KEYNAME_RELOAD],
c8b625
-            systemd=cloud.distro.uses_systemd()),
c8b625
+        restarted = reload_syslog(cloud.distro, command=mycfg[KEYNAME_RELOAD])
c8b625
     except subp.ProcessExecutionError as e:
c8b625
         restarted = False
c8b625
         log.warning("Failed to reload syslog", e)
c8b625
diff --git a/cloudinit/config/cc_set_passwords.py b/cloudinit/config/cc_set_passwords.py
c8b625
index 433de751..9efbf61f 100755
c8b625
--- a/cloudinit/config/cc_set_passwords.py
c8b625
+++ b/cloudinit/config/cc_set_passwords.py
c8b625
@@ -94,18 +94,15 @@ PW_SET = (''.join([x for x in ascii_letters + digits
c8b625
                    if x not in 'loLOI01']))
c8b625
 
c8b625
 
c8b625
-def handle_ssh_pwauth(pw_auth, service_cmd=None, service_name="ssh"):
c8b625
+def handle_ssh_pwauth(pw_auth, distro):
c8b625
     """Apply sshd PasswordAuthentication changes.
c8b625
 
c8b625
     @param pw_auth: config setting from 'pw_auth'.
c8b625
                     Best given as True, False, or "unchanged".
c8b625
-    @param service_cmd: The service command list (['service'])
c8b625
-    @param service_name: The name of the sshd service for the system.
c8b625
+    @param distro: an instance of the distro class for the target distribution
c8b625
 
c8b625
     @return: None"""
c8b625
     cfg_name = "PasswordAuthentication"
c8b625
-    if service_cmd is None:
c8b625
-        service_cmd = ["service"]
c8b625
 
c8b625
     if util.is_true(pw_auth):
c8b625
         cfg_val = 'yes'
c8b625
@@ -124,11 +121,7 @@ def handle_ssh_pwauth(pw_auth, service_cmd=None, service_name="ssh"):
c8b625
         LOG.debug("No need to restart SSH service, %s not updated.", cfg_name)
c8b625
         return
c8b625
 
c8b625
-    if 'systemctl' in service_cmd:
c8b625
-        cmd = list(service_cmd) + ["restart", service_name]
c8b625
-    else:
c8b625
-        cmd = list(service_cmd) + [service_name, "restart"]
c8b625
-    subp.subp(cmd)
c8b625
+    distro.manage_service('restart', distro.get_option('ssh_svcname', 'ssh'))
c8b625
     LOG.debug("Restarted the SSH daemon.")
c8b625
 
c8b625
 
c8b625
@@ -229,9 +222,7 @@ def handle(_name, cfg, cloud, log, args):
c8b625
             if expired_users:
c8b625
                 log.debug("Expired passwords for: %s users", expired_users)
c8b625
 
c8b625
-    handle_ssh_pwauth(
c8b625
-        cfg.get('ssh_pwauth'), service_cmd=cloud.distro.init_cmd,
c8b625
-        service_name=cloud.distro.get_option('ssh_svcname', 'ssh'))
c8b625
+    handle_ssh_pwauth(cfg.get('ssh_pwauth'), cloud.distro)
c8b625
 
c8b625
     if len(errors):
c8b625
         log.debug("%s errors occured, re-raising the last one", len(errors))
c8b625
diff --git a/cloudinit/config/tests/test_set_passwords.py b/cloudinit/config/tests/test_set_passwords.py
c8b625
index bbe2ee8f..79118a12 100644
c8b625
--- a/cloudinit/config/tests/test_set_passwords.py
c8b625
+++ b/cloudinit/config/tests/test_set_passwords.py
c8b625
@@ -14,57 +14,52 @@ class TestHandleSshPwauth(CiTestCase):
c8b625
 
c8b625
     with_logs = True
c8b625
 
c8b625
-    @mock.patch(MODPATH + "subp.subp")
c8b625
+    @mock.patch("cloudinit.distros.subp.subp")
c8b625
     def test_unknown_value_logs_warning(self, m_subp):
c8b625
-        setpass.handle_ssh_pwauth("floo")
c8b625
+        cloud = self.tmp_cloud(distro='ubuntu')
c8b625
+        setpass.handle_ssh_pwauth("floo", cloud.distro)
c8b625
         self.assertIn("Unrecognized value: ssh_pwauth=floo",
c8b625
                       self.logs.getvalue())
c8b625
         m_subp.assert_not_called()
c8b625
 
c8b625
     @mock.patch(MODPATH + "update_ssh_config", return_value=True)
c8b625
-    @mock.patch(MODPATH + "subp.subp")
c8b625
+    @mock.patch("cloudinit.distros.subp.subp")
c8b625
     def test_systemctl_as_service_cmd(self, m_subp, m_update_ssh_config):
c8b625
         """If systemctl in service cmd: systemctl restart name."""
c8b625
-        setpass.handle_ssh_pwauth(
c8b625
-            True, service_cmd=["systemctl"], service_name="myssh")
c8b625
-        self.assertEqual(mock.call(["systemctl", "restart", "myssh"]),
c8b625
-                         m_subp.call_args)
c8b625
-
c8b625
-    @mock.patch(MODPATH + "update_ssh_config", return_value=True)
c8b625
-    @mock.patch(MODPATH + "subp.subp")
c8b625
-    def test_service_as_service_cmd(self, m_subp, m_update_ssh_config):
c8b625
-        """If systemctl in service cmd: systemctl restart name."""
c8b625
-        setpass.handle_ssh_pwauth(
c8b625
-            True, service_cmd=["service"], service_name="myssh")
c8b625
-        self.assertEqual(mock.call(["service", "myssh", "restart"]),
c8b625
-                         m_subp.call_args)
c8b625
+        cloud = self.tmp_cloud(distro='ubuntu')
c8b625
+        cloud.distro.init_cmd = ['systemctl']
c8b625
+        setpass.handle_ssh_pwauth(True, cloud.distro)
c8b625
+        m_subp.assert_called_with(
c8b625
+            ["systemctl", "restart", "ssh"], capture=True)
c8b625
 
c8b625
     @mock.patch(MODPATH + "update_ssh_config", return_value=False)
c8b625
-    @mock.patch(MODPATH + "subp.subp")
c8b625
+    @mock.patch("cloudinit.distros.subp.subp")
c8b625
     def test_not_restarted_if_not_updated(self, m_subp, m_update_ssh_config):
c8b625
         """If config is not updated, then no system restart should be done."""
c8b625
-        setpass.handle_ssh_pwauth(True)
c8b625
+        cloud = self.tmp_cloud(distro='ubuntu')
c8b625
+        setpass.handle_ssh_pwauth(True, cloud.distro)
c8b625
         m_subp.assert_not_called()
c8b625
         self.assertIn("No need to restart SSH", self.logs.getvalue())
c8b625
 
c8b625
     @mock.patch(MODPATH + "update_ssh_config", return_value=True)
c8b625
-    @mock.patch(MODPATH + "subp.subp")
c8b625
+    @mock.patch("cloudinit.distros.subp.subp")
c8b625
     def test_unchanged_does_nothing(self, m_subp, m_update_ssh_config):
c8b625
         """If 'unchanged', then no updates to config and no restart."""
c8b625
-        setpass.handle_ssh_pwauth(
c8b625
-            "unchanged", service_cmd=["systemctl"], service_name="myssh")
c8b625
+        cloud = self.tmp_cloud(distro='ubuntu')
c8b625
+        setpass.handle_ssh_pwauth("unchanged", cloud.distro)
c8b625
         m_update_ssh_config.assert_not_called()
c8b625
         m_subp.assert_not_called()
c8b625
 
c8b625
-    @mock.patch(MODPATH + "subp.subp")
c8b625
+    @mock.patch("cloudinit.distros.subp.subp")
c8b625
     def test_valid_change_values(self, m_subp):
c8b625
         """If value is a valid changen value, then update should be called."""
c8b625
+        cloud = self.tmp_cloud(distro='ubuntu')
c8b625
         upname = MODPATH + "update_ssh_config"
c8b625
         optname = "PasswordAuthentication"
c8b625
         for value in util.FALSE_STRINGS + util.TRUE_STRINGS:
c8b625
             optval = "yes" if value in util.TRUE_STRINGS else "no"
c8b625
             with mock.patch(upname, return_value=False) as m_update:
c8b625
-                setpass.handle_ssh_pwauth(value)
c8b625
+                setpass.handle_ssh_pwauth(value, cloud.distro)
c8b625
                 m_update.assert_called_with({optname: optval})
c8b625
         m_subp.assert_not_called()
c8b625
 
c8b625
diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py
c8b625
index 220bd11f..a8c57cb8 100755
c8b625
--- a/cloudinit/distros/__init__.py
c8b625
+++ b/cloudinit/distros/__init__.py
c8b625
@@ -784,6 +784,34 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta):
c8b625
             args.append(message)
c8b625
         return args
c8b625
 
c8b625
+    def manage_service(self, action, service):
c8b625
+        """
c8b625
+        Perform the requested action on a service. This handles the common
c8b625
+        'systemctl' and 'service' cases and may be overridden in subclasses
c8b625
+        as necessary.
c8b625
+        May raise ProcessExecutionError
c8b625
+        """
c8b625
+        init_cmd = self.init_cmd
c8b625
+        if self.uses_systemd() or 'systemctl' in init_cmd:
c8b625
+            init_cmd = ['systemctl']
c8b625
+            cmds = {'stop': ['stop', service],
c8b625
+                    'start': ['start', service],
c8b625
+                    'enable': ['enable', service],
c8b625
+                    'restart': ['restart', service],
c8b625
+                    'reload': ['reload-or-restart', service],
c8b625
+                    'try-reload': ['reload-or-try-restart', service],
c8b625
+                    }
c8b625
+        else:
c8b625
+            cmds = {'stop': [service, 'stop'],
c8b625
+                    'start': [service, 'start'],
c8b625
+                    'enable': [service, 'start'],
c8b625
+                    'restart': [service, 'restart'],
c8b625
+                    'reload': [service, 'restart'],
c8b625
+                    'try-reload': [service, 'restart'],
c8b625
+                    }
c8b625
+        cmd = list(init_cmd) + list(cmds[action])
c8b625
+        return subp.subp(cmd, capture=True)
c8b625
+
c8b625
 
c8b625
 def _apply_hostname_transformations_to_url(url: str, transformations: list):
c8b625
     """
c8b625
diff --git a/tests/unittests/test_distros/test_manage_service.py b/tests/unittests/test_distros/test_manage_service.py
c8b625
new file mode 100644
c8b625
index 00000000..47e7cfb0
c8b625
--- /dev/null
c8b625
+++ b/tests/unittests/test_distros/test_manage_service.py
c8b625
@@ -0,0 +1,38 @@
c8b625
+# This file is part of cloud-init. See LICENSE file for license information.
c8b625
+
c8b625
+from cloudinit.tests.helpers import (CiTestCase, mock)
c8b625
+from tests.unittests.util import TestingDistro
c8b625
+
c8b625
+
c8b625
+class TestManageService(CiTestCase):
c8b625
+
c8b625
+    with_logs = True
c8b625
+
c8b625
+    def setUp(self):
c8b625
+        super(TestManageService, self).setUp()
c8b625
+        self.dist = TestingDistro()
c8b625
+
c8b625
+    @mock.patch.object(TestingDistro, 'uses_systemd', return_value=False)
c8b625
+    @mock.patch("cloudinit.distros.subp.subp")
c8b625
+    def test_manage_service_systemctl_initcmd(self, m_subp, m_sysd):
c8b625
+        self.dist.init_cmd = ['systemctl']
c8b625
+        self.dist.manage_service('start', 'myssh')
c8b625
+        m_subp.assert_called_with(['systemctl', 'start', 'myssh'],
c8b625
+                                  capture=True)
c8b625
+
c8b625
+    @mock.patch.object(TestingDistro, 'uses_systemd', return_value=False)
c8b625
+    @mock.patch("cloudinit.distros.subp.subp")
c8b625
+    def test_manage_service_service_initcmd(self, m_subp, m_sysd):
c8b625
+        self.dist.init_cmd = ['service']
c8b625
+        self.dist.manage_service('start', 'myssh')
c8b625
+        m_subp.assert_called_with(['service', 'myssh', 'start'], capture=True)
c8b625
+
c8b625
+    @mock.patch.object(TestingDistro, 'uses_systemd', return_value=True)
c8b625
+    @mock.patch("cloudinit.distros.subp.subp")
c8b625
+    def test_manage_service_systemctl(self, m_subp, m_sysd):
c8b625
+        self.dist.init_cmd = ['ignore']
c8b625
+        self.dist.manage_service('start', 'myssh')
c8b625
+        m_subp.assert_called_with(['systemctl', 'start', 'myssh'],
c8b625
+                                  capture=True)
c8b625
+
c8b625
+# vi: ts=4 sw=4 expandtab
c8b625
diff --git a/tests/unittests/test_handler/test_handler_ntp.py b/tests/unittests/test_handler/test_handler_ntp.py
c8b625
index 6b9c8377..c059e2e6 100644
c8b625
--- a/tests/unittests/test_handler/test_handler_ntp.py
c8b625
+++ b/tests/unittests/test_handler/test_handler_ntp.py
c8b625
@@ -112,22 +112,6 @@ class TestNtp(FilesystemMockingTestCase):
c8b625
                                   check_exe='timesyncd')
c8b625
         install_func.assert_called_once_with([])
c8b625
 
c8b625
-    @mock.patch("cloudinit.config.cc_ntp.subp")
c8b625
-    def test_reload_ntp_defaults(self, mock_subp):
c8b625
-        """Test service is restarted/reloaded (defaults)"""
c8b625
-        service = 'ntp_service_name'
c8b625
-        cmd = ['service', service, 'restart']
c8b625
-        cc_ntp.reload_ntp(service)
c8b625
-        mock_subp.subp.assert_called_with(cmd, capture=True)
c8b625
-
c8b625
-    @mock.patch("cloudinit.config.cc_ntp.subp")
c8b625
-    def test_reload_ntp_systemd(self, mock_subp):
c8b625
-        """Test service is restarted/reloaded (systemd)"""
c8b625
-        service = 'ntp_service_name'
c8b625
-        cc_ntp.reload_ntp(service, systemd=True)
c8b625
-        cmd = ['systemctl', 'reload-or-restart', service]
c8b625
-        mock_subp.subp.assert_called_with(cmd, capture=True)
c8b625
-
c8b625
     def test_ntp_rename_ntp_conf(self):
c8b625
         """When NTP_CONF exists, rename_ntp moves it."""
c8b625
         ntpconf = self.tmp_path("ntp.conf", self.new_root)
c8b625
@@ -488,10 +472,11 @@ class TestNtp(FilesystemMockingTestCase):
c8b625
             cc_ntp.handle('notimportant', cfg, mycloud, None, None)
c8b625
             self.assertEqual(0, m_select.call_count)
c8b625
 
c8b625
+    @mock.patch("cloudinit.distros.subp")
c8b625
     @mock.patch("cloudinit.config.cc_ntp.subp")
c8b625
     @mock.patch('cloudinit.config.cc_ntp.select_ntp_client')
c8b625
     @mock.patch("cloudinit.distros.Distro.uses_systemd")
c8b625
-    def test_ntp_the_whole_package(self, m_sysd, m_select, m_subp):
c8b625
+    def test_ntp_the_whole_package(self, m_sysd, m_select, m_subp, m_dsubp):
c8b625
         """Test enabled config renders template, and restarts service """
c8b625
         cfg = {'ntp': {'enabled': True}}
c8b625
         for distro in cc_ntp.distros:
c8b625
@@ -509,7 +494,7 @@ class TestNtp(FilesystemMockingTestCase):
c8b625
 
c8b625
             if distro == 'alpine':
c8b625
                 uses_systemd = False
c8b625
-                expected_service_call = ['service', service_name, 'restart']
c8b625
+                expected_service_call = ['rc-service', service_name, 'restart']
c8b625
                 # _mock_ntp_client_config call above did not specify a client
c8b625
                 # value and so it defaults to "ntp" which on Alpine Linux only
c8b625
                 # supports servers and not pools.
c8b625
@@ -525,7 +510,7 @@ class TestNtp(FilesystemMockingTestCase):
c8b625
                 m_util.is_false.return_value = util.is_false(
c8b625
                     cfg['ntp']['enabled'])
c8b625
                 cc_ntp.handle('notimportant', cfg, mycloud, None, None)
c8b625
-                m_subp.subp.assert_called_with(
c8b625
+                m_dsubp.subp.assert_called_with(
c8b625
                     expected_service_call, capture=True)
c8b625
 
c8b625
             self.assertEqual(expected_content, util.load_file(confpath))
c8b625
@@ -673,9 +658,8 @@ class TestNtp(FilesystemMockingTestCase):
c8b625
             self.assertEqual(sorted(expected_cfg), sorted(result))
c8b625
             m_which.assert_has_calls([])
c8b625
 
c8b625
-    @mock.patch('cloudinit.config.cc_ntp.reload_ntp')
c8b625
     @mock.patch('cloudinit.config.cc_ntp.install_ntp_client')
c8b625
-    def test_ntp_user_provided_config_with_template(self, m_install, m_reload):
c8b625
+    def test_ntp_user_provided_config_with_template(self, m_install):
c8b625
         custom = r'\n#MyCustomTemplate'
c8b625
         user_template = NTP_TEMPLATE + custom
c8b625
         confpath = os.path.join(self.new_root, 'etc/myntp/myntp.conf')
c8b625
@@ -702,11 +686,10 @@ class TestNtp(FilesystemMockingTestCase):
c8b625
                 util.load_file(confpath))
c8b625
 
c8b625
     @mock.patch('cloudinit.config.cc_ntp.supplemental_schema_validation')
c8b625
-    @mock.patch('cloudinit.config.cc_ntp.reload_ntp')
c8b625
     @mock.patch('cloudinit.config.cc_ntp.install_ntp_client')
c8b625
     @mock.patch('cloudinit.config.cc_ntp.select_ntp_client')
c8b625
     def test_ntp_user_provided_config_template_only(self, m_select, m_install,
c8b625
-                                                    m_reload, m_schema):
c8b625
+                                                    m_schema):
c8b625
         """Test custom template for default client"""
c8b625
         custom = r'\n#MyCustomTemplate'
c8b625
         user_template = NTP_TEMPLATE + custom
c8b625
-- 
c8b625
2.31.1
c8b625