diff options
author | Scott Moser <smoser@ubuntu.com> | 2016-08-10 09:06:15 -0600 |
---|---|---|
committer | Scott Moser <smoser@ubuntu.com> | 2016-08-10 09:06:15 -0600 |
commit | c3c3dc693c14175e110b5fe125d4d5f98ace9700 (patch) | |
tree | 8858702c2c8a6ad4bf1bb861a4565e0a9c28e588 /cloudinit/config/cc_power_state_change.py | |
parent | 5bd3493d732e5b1902872958e8681f17cbc81ce5 (diff) | |
download | cloud-init-trunk.tar.gz |
cloud-init development has moved its revision control to git.
It is available at
https://code.launchpad.net/cloud-init
Clone with
git clone https://git.launchpad.net/cloud-init
or
git clone git+ssh://git.launchpad.net/cloud-init
For more information see
https://git.launchpad.net/cloud-init/tree/HACKING.rst
Diffstat (limited to 'cloudinit/config/cc_power_state_change.py')
-rw-r--r-- | cloudinit/config/cc_power_state_change.py | 223 |
1 files changed, 0 insertions, 223 deletions
diff --git a/cloudinit/config/cc_power_state_change.py b/cloudinit/config/cc_power_state_change.py deleted file mode 100644 index cc3f7f70..00000000 --- a/cloudinit/config/cc_power_state_change.py +++ /dev/null @@ -1,223 +0,0 @@ -# vi: ts=4 expandtab -# -# Copyright (C) 2011 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 util - -import errno -import os -import re -import six -import subprocess -import time - -frequency = PER_INSTANCE - -EXIT_FAIL = 254 - - -def givecmdline(pid): - # Returns the cmdline for the given process id. In Linux we can use procfs - # for this but on BSD there is /usr/bin/procstat. - try: - # Example output from procstat -c 1 - # PID COMM ARGS - # 1 init /bin/init -- - if util.system_info()["platform"].startswith('FreeBSD'): - (output, _err) = util.subp(['procstat', '-c', str(pid)]) - line = output.splitlines()[1] - m = re.search('\d+ (\w|\.|-)+\s+(/\w.+)', line) - return m.group(2) - else: - return util.load_file("/proc/%s/cmdline" % pid) - except IOError: - return None - - -def check_condition(cond, log=None): - if isinstance(cond, bool): - if log: - log.debug("Static Condition: %s" % cond) - return cond - - pre = "check_condition command (%s): " % cond - try: - proc = subprocess.Popen(cond, shell=not isinstance(cond, list)) - proc.communicate() - ret = proc.returncode - if ret == 0: - if log: - log.debug(pre + "exited 0. condition met.") - return True - elif ret == 1: - if log: - log.debug(pre + "exited 1. condition not met.") - return False - else: - if log: - log.warn(pre + "unexpected exit %s. " % ret + - "do not apply change.") - return False - except Exception as e: - if log: - log.warn(pre + "Unexpected error: %s" % e) - return False - - -def handle(_name, cfg, _cloud, log, _args): - - try: - (args, timeout, condition) = load_power_state(cfg) - if args is None: - log.debug("no power_state provided. doing nothing") - return - except Exception as e: - log.warn("%s Not performing power state change!" % str(e)) - return - - if condition is False: - log.debug("Condition was false. Will not perform state change.") - return - - mypid = os.getpid() - - cmdline = givecmdline(mypid) - if not cmdline: - log.warn("power_state: failed to get cmdline of current process") - return - - devnull_fp = open(os.devnull, "w") - - log.debug("After pid %s ends, will execute: %s" % (mypid, ' '.join(args))) - - util.fork_cb(run_after_pid_gone, mypid, cmdline, timeout, log, - condition, execmd, [args, devnull_fp]) - - -def load_power_state(cfg): - # returns a tuple of shutdown_command, timeout - # shutdown_command is None if no config found - pstate = cfg.get('power_state') - - if pstate is None: - return (None, None, None) - - if not isinstance(pstate, dict): - raise TypeError("power_state is not a dict.") - - opt_map = {'halt': '-H', 'poweroff': '-P', 'reboot': '-r'} - - mode = pstate.get("mode") - if mode not in opt_map: - raise TypeError( - "power_state[mode] required, must be one of: %s. found: '%s'." % - (','.join(opt_map.keys()), mode)) - - delay = pstate.get("delay", "now") - # convert integer 30 or string '30' to '+30' - try: - delay = "+%s" % int(delay) - except ValueError: - pass - - if delay != "now" and not re.match(r"\+[0-9]+", delay): - raise TypeError( - "power_state[delay] must be 'now' or '+m' (minutes)." - " found '%s'." % delay) - - args = ["shutdown", opt_map[mode], delay] - if pstate.get("message"): - args.append(pstate.get("message")) - - try: - timeout = float(pstate.get('timeout', 30.0)) - except ValueError: - raise ValueError("failed to convert timeout '%s' to float." % - pstate['timeout']) - - condition = pstate.get("condition", True) - if not isinstance(condition, six.string_types + (list, bool)): - raise TypeError("condition type %s invalid. must be list, bool, str") - return (args, timeout, condition) - - -def doexit(sysexit): - os._exit(sysexit) - - -def execmd(exe_args, output=None, data_in=None): - try: - proc = subprocess.Popen(exe_args, stdin=subprocess.PIPE, - stdout=output, stderr=subprocess.STDOUT) - proc.communicate(data_in) - ret = proc.returncode - except Exception: - doexit(EXIT_FAIL) - doexit(ret) - - -def run_after_pid_gone(pid, pidcmdline, timeout, log, condition, func, args): - # wait until pid, with /proc/pid/cmdline contents of pidcmdline - # is no longer alive. After it is gone, or timeout has passed - # execute func(args) - msg = None - end_time = time.time() + timeout - - def fatal(msg): - if log: - log.warn(msg) - doexit(EXIT_FAIL) - - known_errnos = (errno.ENOENT, errno.ESRCH) - - while True: - if time.time() > end_time: - msg = "timeout reached before %s ended" % pid - break - - try: - cmdline = givecmdline(pid) - if cmdline != pidcmdline: - msg = "cmdline changed for %s [now: %s]" % (pid, cmdline) - break - - except IOError as ioerr: - if ioerr.errno in known_errnos: - msg = "pidfile gone [%d]" % ioerr.errno - else: - fatal("IOError during wait: %s" % ioerr) - break - - except Exception as e: - fatal("Unexpected Exception: %s" % e) - - time.sleep(.25) - - if not msg: - fatal("Unexpected error in run_after_pid_gone") - - if log: - log.debug(msg) - - try: - if not check_condition(condition, log): - return - except Exception as e: - fatal("Unexpected Exception when checking condition: %s" % e) - - func(*args) |