Просмотр исходного кода

Merge pull request #46 from gabriel-samfira/add-system-startup-functions

Add system startup creation functions
Nashwan Azhari 6 лет назад
Родитель
Сommit
4b4249a1e8
1 измененных файлов с 109 добавлено и 1 удалено
  1. 109 1
      coriolis/utils.py

+ 109 - 1
coriolis/utils.py

@@ -1,5 +1,6 @@
 # Copyright 2016 Cloudbase Solutions Srl
 # All Rights Reserved.
+# pylint: disable=anomalous-backslash-in-string
 
 import base64
 import binascii
@@ -15,6 +16,7 @@ import socket
 import subprocess
 import time
 import traceback
+import uuid
 
 import OpenSSL
 from oslo_config import cfg
@@ -40,6 +42,37 @@ CONF.register_opts(opts)
 
 LOG = logging.getLogger(__name__)
 
+SYSTEMD_TEMPLATE = """
+[Unit]
+Description=Coriolis %(svc_name)s
+After=network-online.target
+
+[Service]
+Type=simple
+ExecStart=%(cmdline)s
+Restart=always
+RestartSec=5s
+User=%(username)s
+
+[Install]
+WantedBy=multi-user.target
+"""
+
+UPSTART_TEMPLATE = """
+# %(svc_name)s - Coriolis %(svc_name)s service
+#
+
+description     "%(svc_name)s service"
+
+start on runlevel [2345]
+stop on runlevel [!2345]
+
+respawn
+umask 022
+
+exec %(cmdline)s
+"""
+
 
 def setup_logging():
     logging.setup(CONF, 'coriolis')
@@ -178,7 +211,7 @@ def list_ssh_dir(ssh, remote_path):
 def exec_ssh_cmd(ssh, cmd, environment=None, get_pty=False):
     LOG.debug("Executing SSH command: %s", cmd)
     LOG.debug("SSH command environment: %s", environment)
-    stdin, stdout, stderr = ssh.exec_command(
+    _, stdout, stderr = ssh.exec_command(
         cmd, environment=environment, get_pty=get_pty)
     exit_code = stdout.channel.recv_exit_status()
     std_out = stdout.read()
@@ -498,3 +531,78 @@ def filter_chunking_info_for_task(task_info):
             vol["replica_state"]["chunks"] = "<redacted>"
 
     return cpy
+
+
+def _write_systemd(ssh, cmdline, svcname, run_as=None, start=True):
+    serviceFilePath = "/lib/systemd/system/%s.service" % svcname
+
+    if test_ssh_path(ssh, serviceFilePath):
+        return
+
+    def _reload_and_start(start=True):
+        exec_ssh_cmd(
+            ssh, "sudo systemctl daemon-reload",
+            get_pty=True)
+        if start:
+            exec_ssh_cmd(
+                ssh, "sudo systemctl start %s" % svcname,
+                get_pty=True)
+
+    systemd_args = {
+        "cmdline": cmdline,
+        "username": "root",
+        "svc_name": svcname,
+    }
+    if run_as:
+        systemd_args["username"] = run_as
+
+    systemdService = SYSTEMD_TEMPLATE % systemd_args
+
+    name = str(uuid.uuid4())
+    write_ssh_file(
+        ssh, '/tmp/%s.service' % name, systemdService)
+    exec_ssh_cmd(
+        ssh,
+        "sudo mv /tmp/%s.service %s" % (name, serviceFilePath),
+        get_pty=True)
+    _reload_and_start(start=start)
+
+
+def _write_upstart(ssh, cmdline, svcname, run_as=None, start=True):
+    serviceFilePath = "/etc/init/%s.conf" % svcname
+
+    if test_ssh_path(ssh, serviceFilePath):
+        return
+
+    if run_as:
+        cmdline = "sudo -u %s -- %s" % (run_as, cmdline)
+
+    upstartService = UPSTART_TEMPLATE % {
+        "cmdline": cmdline,
+        "svc_name": svcname,
+    }
+    name = str(uuid.uuid4())
+    write_ssh_file(
+        ssh, '/tmp/%s.conf' % name, upstartService)
+    exec_ssh_cmd(
+        ssh,
+        "sudo mv /tmp/%s.conf %s" % (name, serviceFilePath),
+        get_pty=True)
+    if start:
+        exec_ssh_cmd(ssh, "start %s" % svcname)
+
+
+@retry_on_error()
+def create_service(ssh, cmdline, svcname, run_as=None, start=True):
+    # Simplistic check for init system. We usually use official images,
+    # and none of the supported operating systems come with both upstart
+    # 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"):
+        _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)
+    else:
+        raise exception.CoriolisException(
+            "could not determine init system")