summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cloudinit/config/cc_ubuntu_init_switch.py120
-rw-r--r--config/cloud.cfg1
2 files changed, 121 insertions, 0 deletions
diff --git a/cloudinit/config/cc_ubuntu_init_switch.py b/cloudinit/config/cc_ubuntu_init_switch.py
new file mode 100644
index 00000000..3a2015e5
--- /dev/null
+++ b/cloudinit/config/cc_ubuntu_init_switch.py
@@ -0,0 +1,120 @@
+# vi: ts=4 expandtab
+#
+# Copyright (C) 2014 Canonical Ltd.
+#
+# Author: Scott Moser <scott.moser@canonical.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 3, as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from cloudinit.settings import PER_INSTANCE
+from cloudinit import log as logging
+from cloudinit import util
+from cloudinit.distros import ubuntu
+
+import os
+import time
+
+frequency = PER_INSTANCE
+REBOOT_CMD = ["/sbin/reboot"]
+
+DEFAULT_CONFIG = {
+ 'init_switch': {'target': None}
+}
+
+SWITCH_INIT = """
+#!/bin/sh
+# switch_init: [upstart | systemd]
+
+is_systemd() {
+ [ "$(dpkg-divert --listpackage /sbin/init)" = "systemd-sysv" ]
+}
+debug() { echo "$@" 1>&2; }
+fail() { echo "$@" 1>&2; exit 1; }
+
+if [ "$1" = "systemd" ]; then
+ if is_systemd; then
+ debug "already systemd, nothing to do"
+ else
+ [ -f /lib/systemd/systemd ] || fail "no systemd available";
+ dpkg-divert --package systemd-sysv --divert /sbin/init.diverted \\
+ --rename /sbin/init
+ fi
+ [ -f /sbin/init ] || ln /lib/systemd/systemd /sbin/init
+elif [ "$1" = "upstart" ]; then
+ if is_systemd; then
+ rm -f /sbin/init
+ dpkg-divert --package systemd-sysv --rename --remove /sbin/init
+ else
+ debug "already upstart, nothing to do."
+ fi
+else
+ fail "Error. expect 'upstart' or 'systemd'"
+fi
+"""
+
+
+def handle(name, cfg, cloud, log, _args):
+
+ if not isinstance(cloud.distro, ubuntu.Distro):
+ log.debug("%s: distro is '%s', not ubuntu. returning",
+ name, cloud.distro.__class__)
+ return
+
+ cfg = util.mergemanydict(cfg, DEFAULT_CONFIG)
+ target = cfg['init_switch']['target']
+ if not target:
+ log.debug("%s: target=%s. nothing to do", name, target)
+ return
+
+ supported = ('upstart', 'systemd')
+ if target not in supported:
+ log.warn("%s: target set to %s, expected one of: %s",
+ name, target, str(supported))
+
+ if os.path.exists("/run/systemd/systemd"):
+ current = "systemd"
+ else:
+ current = "upstart"
+
+ if current == target:
+ log.debug("%s: current = target = %s. nothing to do", name, target)
+ return
+
+ try:
+ util.subp(['sh', '-c', SWITCH_INIT, '--', target])
+ except util.ProcessExecutionError as e:
+ log.warn("%s: Failed to switch to init '%s'. %s", name, target, e)
+ return
+
+ try:
+ log.warn("%s: rebooting from '%s' to '%s'", name, current, target)
+ logging.flushLoggers(log)
+ _fire_reboot(log, initial_sleep=4)
+ except Exception as e:
+ util.logexc(log, "Requested reboot did not happen!")
+ raise
+
+
+def _fire_reboot(log, wait_attempts=6, initial_sleep=1, backoff=2):
+ util.subp(REBOOT_CMD)
+ start = time.time()
+ wait_time = initial_sleep
+ for _i in range(0, wait_attempts):
+ time.sleep(wait_time)
+ wait_time *= backoff
+ elapsed = time.time() - start
+ log.debug("Rebooted, but still running after %s seconds", int(elapsed))
+ # If we got here, not good
+ elapsed = time.time() - start
+ raise RuntimeError(("Reboot did not happen"
+ " after %s seconds!") % (int(elapsed)))
diff --git a/config/cloud.cfg b/config/cloud.cfg
index b746e3db..200050d3 100644
--- a/config/cloud.cfg
+++ b/config/cloud.cfg
@@ -24,6 +24,7 @@ preserve_hostname: false
# The modules that run in the 'init' stage
cloud_init_modules:
- migrator
+ - ubuntu-init-switch
- seed_random
- bootcmd
- write-files