Parcourir la source

Update `systemd` unit path detection
On newer distros, `systemd` default configurations
have been moved from `/lib` to `/usr/lib`.

Signed-off-by: Mihaela Balutoiu <mbalutoiu@cloudbasesolutions.com>

Mihaela Balutoiu il y a 2 mois
Parent
commit
edf263c000
2 fichiers modifiés avec 63 ajouts et 20 suppressions
  1. 44 15
      coriolis/tests/test_utils.py
  2. 19 5
      coriolis/utils.py

+ 44 - 15
coriolis/tests/test_utils.py

@@ -915,14 +915,16 @@ class UtilsTestCase(test_base.CoriolisBaseTestCase):
     def test_write_systemd(self, mock_uuid, mock_test_ssh,
                            mock_write_ssh_file, mock_exec_ssh_cmd):
         mock_uuid.return_value = 'uuid'
-        mock_test_ssh.return_value = False
+        mock_test_ssh.side_effect = [True, False]
         mock_write_ssh_file.return_value = None
 
         utils._write_systemd(self.mock_ssh, 'cmdline', 'svc_name')
 
         mock_uuid.assert_called_once_with()
-        mock_test_ssh.assert_called_once_with(
-            self.mock_ssh, '/lib/systemd/system/svc_name.service')
+        mock_test_ssh.assert_has_calls([
+            mock.call(self.mock_ssh, '/lib/systemd/system'),
+            mock.call(self.mock_ssh,
+                      '/lib/systemd/system/svc_name.service')])
         mock_write_ssh_file.assert_called_once_with(self.mock_ssh,
                                                     '/tmp/uuid.service',
                                                     mock.ANY)
@@ -936,14 +938,37 @@ class UtilsTestCase(test_base.CoriolisBaseTestCase):
             mock.call(self.mock_ssh, 'sudo systemctl start svc_name',
                       get_pty=True)])
 
+    @mock.patch('coriolis.utils.exec_ssh_cmd')
+    @mock.patch('coriolis.utils.write_ssh_file')
+    @mock.patch('coriolis.utils.test_ssh_path')
+    @mock.patch.object(uuid, 'uuid4')
+    def test_write_systemd_usr_lib(self, mock_uuid, mock_test_ssh,
+                                   mock_write_ssh_file, mock_exec_ssh_cmd):
+        mock_uuid.return_value = 'uuid'
+        mock_test_ssh.side_effect = [False, False]
+        mock_write_ssh_file.return_value = None
+
+        utils._write_systemd(self.mock_ssh, 'cmdline', 'svc_name')
+
+        mock_test_ssh.assert_has_calls([
+            mock.call(self.mock_ssh, '/lib/systemd/system'),
+            mock.call(self.mock_ssh,
+                      '/usr/lib/systemd/system/svc_name.service')])
+        mock_exec_ssh_cmd.assert_has_calls([
+            mock.call(self.mock_ssh, 'sudo mv /tmp/uuid.service '
+                      '/usr/lib/systemd/system/svc_name.service',
+                      get_pty=True)])
+
     @mock.patch('coriolis.utils.test_ssh_path')
     def test_write_systemd_service_exists(self, mock_test_ssh):
         mock_test_ssh.return_value = True
 
         utils._write_systemd(self.mock_ssh, 'cmdline', 'svc_name')
 
-        mock_test_ssh.assert_called_once_with(
-            self.mock_ssh, '/lib/systemd/system/svc_name.service')
+        mock_test_ssh.assert_has_calls([
+            mock.call(self.mock_ssh, '/lib/systemd/system'),
+            mock.call(self.mock_ssh,
+                      '/lib/systemd/system/svc_name.service')])
 
     @mock.patch('coriolis.utils.exec_ssh_cmd')
     @mock.patch('coriolis.utils.write_ssh_file')
@@ -954,7 +979,7 @@ class UtilsTestCase(test_base.CoriolisBaseTestCase):
                                                      mock_write_ssh_file,
                                                      mock_exec_ssh_cmd):
         mock_uuid.return_value = 'uuid'
-        mock_test_ssh.return_value = False
+        mock_test_ssh.side_effect = [True, False]
         mock_write_ssh_file.return_value = None
         mock_exec_ssh_cmd.side_effect = [
             None, exception.CoriolisException(), None, None]
@@ -967,8 +992,10 @@ class UtilsTestCase(test_base.CoriolisBaseTestCase):
                                        start=True)
 
         mock_uuid.assert_called_once_with()
-        mock_test_ssh.assert_called_once_with(
-            self.mock_ssh, '/lib/systemd/system/svc_name.service')
+        mock_test_ssh.assert_has_calls([
+            mock.call(self.mock_ssh, '/lib/systemd/system'),
+            mock.call(self.mock_ssh,
+                      '/lib/systemd/system/svc_name.service')])
         mock_write_ssh_file.assert_called_once_with(self.mock_ssh,
                                                     '/tmp/uuid.service',
                                                     mock.ANY)
@@ -982,14 +1009,16 @@ class UtilsTestCase(test_base.CoriolisBaseTestCase):
                                             mock_exec_ssh_cmd):
 
         mock_uuid.return_value = 'uuid'
-        mock_test_ssh.return_value = False
+        mock_test_ssh.side_effect = [True, False]
 
         utils._write_systemd(self.mock_ssh, 'cmdline', 'svc_name',
                              run_as='test_user')
 
         mock_uuid.assert_called_once_with()
-        mock_test_ssh.assert_called_once_with(
-            self.mock_ssh, '/lib/systemd/system/svc_name.service')
+        mock_test_ssh.assert_has_calls([
+            mock.call(self.mock_ssh, '/lib/systemd/system'),
+            mock.call(self.mock_ssh,
+                      '/lib/systemd/system/svc_name.service')])
         mock_write_ssh_file.assert_called_once_with(
             self.mock_ssh, '/tmp/uuid.service',
             utils.SYSTEMD_TEMPLATE % {
@@ -1081,7 +1110,7 @@ class UtilsTestCase(test_base.CoriolisBaseTestCase):
     @mock.patch('coriolis.utils._write_upstart')
     @mock.patch('coriolis.utils.test_ssh_path')
     def test_create_service_upstart(self, mock_test_ssh, mock_write_upstart):
-        mock_test_ssh.side_effect = [False, True]
+        mock_test_ssh.side_effect = [False, False, True]
 
         utils.create_service(self.mock_ssh, 'cmdline', 'svc_name',
                              run_as='user', start=True)
@@ -1119,7 +1148,7 @@ class UtilsTestCase(test_base.CoriolisBaseTestCase):
     @mock.patch('coriolis.utils.test_ssh_path')
     def test_restart_service_with_upstart(self, mock_test_ssh,
                                           mock_exec_ssh_cmd):
-        mock_test_ssh.side_effect = [False, True]
+        mock_test_ssh.side_effect = [False, False, True]
 
         utils.restart_service(self.mock_ssh, 'svc_name')
 
@@ -1153,7 +1182,7 @@ class UtilsTestCase(test_base.CoriolisBaseTestCase):
     @mock.patch('coriolis.utils.test_ssh_path')
     def test_start_service_with_upstart(self, mock_test_ssh,
                                         mock_exec_ssh_cmd):
-        mock_test_ssh.side_effect = [False, True]
+        mock_test_ssh.side_effect = [False, False, True]
 
         utils.start_service(self.mock_ssh, 'svc_name')
 
@@ -1187,7 +1216,7 @@ class UtilsTestCase(test_base.CoriolisBaseTestCase):
     @mock.patch('coriolis.utils.test_ssh_path')
     def test_stop_service_with_upstart(self, mock_test_ssh,
                                        mock_exec_ssh_cmd):
-        mock_test_ssh.side_effect = [False, True]
+        mock_test_ssh.side_effect = [False, False, True]
 
         utils.stop_service(self.mock_ssh, 'svc_name')
 

+ 19 - 5
coriolis/utils.py

@@ -718,8 +718,16 @@ def read_ssh_ini_config_file(ssh, path, check_exists=False):
         return {}
 
 
+def _get_systemd_unit_path(ssh):
+    """Returns the systemd unit directory path on the remote system."""
+    if test_ssh_path(ssh, "/lib/systemd/system"):
+        return "/lib/systemd/system"
+    return "/usr/lib/systemd/system"
+
+
 def _write_systemd(ssh, cmdline, svcname, run_as=None, start=True):
-    serviceFilePath = "/lib/systemd/system/%s.service" % svcname
+    systemd_unit_dir = _get_systemd_unit_path(ssh)
+    serviceFilePath = "%s/%s.service" % (systemd_unit_dir, svcname)
 
     if test_ssh_path(ssh, serviceFilePath):
         return
@@ -787,6 +795,12 @@ def _write_upstart(ssh, cmdline, svcname, run_as=None, start=True):
         exec_ssh_cmd(ssh, "start %s" % svcname)
 
 
+def _has_systemd(ssh):
+    """Check if the remote system uses systemd as its init system."""
+    return (test_ssh_path(ssh, "/lib/systemd/system") or
+            test_ssh_path(ssh, "/usr/lib/systemd/system"))
+
+
 @retry_on_error()
 def create_service(ssh, cmdline, svcname, run_as=None, start=True):
     # Simplistic check for init system. We usually use official images,
@@ -794,7 +808,7 @@ def create_service(ssh, cmdline, svcname, run_as=None, start=True):
     # and systemd installed side by side. So if /lib/systemd/system
     # exists, it's usually systemd enabled. If not, but /etc/init
     # exists, it's upstart
-    if test_ssh_path(ssh, "/lib/systemd/system"):
+    if _has_systemd(ssh):
         _write_systemd(ssh, cmdline, svcname, run_as=run_as, start=start)
     elif test_ssh_path(ssh, "/etc/init"):
         _write_upstart(ssh, cmdline, svcname, run_as=run_as, start=start)
@@ -805,7 +819,7 @@ def create_service(ssh, cmdline, svcname, run_as=None, start=True):
 
 @retry_on_error()
 def restart_service(ssh, svcname):
-    if test_ssh_path(ssh, "/lib/systemd/system"):
+    if _has_systemd(ssh):
         exec_ssh_cmd(ssh, "sudo systemctl restart %s" % svcname, get_pty=True)
     elif test_ssh_path(ssh, "/etc/init"):
         exec_ssh_cmd(ssh, "restart %s" % svcname)
@@ -815,7 +829,7 @@ def restart_service(ssh, svcname):
 
 @retry_on_error()
 def start_service(ssh, svcname):
-    if test_ssh_path(ssh, "/lib/systemd/system"):
+    if _has_systemd(ssh):
         exec_ssh_cmd(ssh, "sudo systemctl start %s" % svcname, get_pty=True)
     elif test_ssh_path(ssh, "/etc/init"):
         exec_ssh_cmd(ssh, "start %s" % svcname)
@@ -825,7 +839,7 @@ def start_service(ssh, svcname):
 
 @retry_on_error()
 def stop_service(ssh, svcname):
-    if test_ssh_path(ssh, "/lib/systemd/system"):
+    if _has_systemd(ssh):
         exec_ssh_cmd(ssh, "sudo systemctl stop %s" % svcname, get_pty=True)
     elif test_ssh_path(ssh, "/etc/init"):
         exec_ssh_cmd(ssh, "stop %s" % svcname)