diff options
Diffstat (limited to '')
-rw-r--r-- | utils/crm_script.py | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/utils/crm_script.py b/utils/crm_script.py new file mode 100644 index 0000000..2341539 --- /dev/null +++ b/utils/crm_script.py @@ -0,0 +1,190 @@ +import os +import sys +import getpass +import select +import subprocess as proc +try: + import json +except ImportError: + import simplejson as json + +_input = None + +# read stdin, if there's anything to read +_stdin_data = {} +while sys.stdin in select.select([sys.stdin], [], [], 0)[0]: + line = sys.stdin.readline() + if line: + d = line.split(':', 1) + if len(d) == 2: + _stdin_data[d[0].strip()] = d[1].strip() + else: + break + + +def decode_utf8(s): + """ + Convert the given byte sequence to a + utf8 string. + """ + if s is None or isinstance(s, str): + return s + return s.decode('utf-8', 'ignore') + + +def host(): + return os.uname()[1] + + +def get_input(): + global _input + if _input is None: + _input = json.load(open('./script.input')) + return _input + + +def parameters(): + return get_input()[0] + + +def param(name): + return parameters().get(name) + + +def output(step_idx): + if step_idx < len(get_input()): + return get_input()[step_idx] + return {} + + +def exit_fail(msg): + print(msg, file=sys.stderr) + sys.exit(1) + + +def exit_ok(data): + print(json.dumps(data)) + sys.exit(0) + + +def is_true(s): + if s in (True, False): + return s + return isinstance(s, str) and s.lower() in ('yes', 'true', '1', 'on') + + +_debug_enabled = None + + +def debug_enabled(): + global _debug_enabled + if _debug_enabled is None: + _debug_enabled = is_true(param('debug')) + return _debug_enabled + + +def info(msg): + "writes msg to log" + with open('./crm_script.debug', 'a') as dbglog: + dbglog.write('%s' % (msg)) + + +def debug(msg): + "writes msg to log and syslog if debug is enabled" + if debug_enabled(): + try: + with open('./crm_script.debug', 'a') as dbglog: + dbglog.write('%s\n' % (msg)) + import syslog + syslog.openlog("crmsh", 0, syslog.LOG_USER) + syslog.syslog(syslog.LOG_NOTICE, str(msg).encode('utf8')) + except: + pass + + +def call(cmd, shell=False): + debug("crm_script(call): %s" % (cmd)) + p = proc.Popen(cmd, shell=shell, stdin=None, stdout=proc.PIPE, stderr=proc.PIPE) + out, err = p.communicate() + return p.returncode, decode_utf8(out).strip(), decode_utf8(err).strip() + + +def use_sudo(): + return getpass.getuser() != 'root' and is_true(param('sudo')) and _stdin_data.get('sudo') + + +def sudo_call(cmd, shell=False): + if not use_sudo(): + return call(cmd, shell=shell) + debug("crm_script(sudo_call): %s" % (cmd)) + os.unsetenv('SSH_ASKPASS') + call(['sudo', '-k'], shell=False) + sudo_prompt = 'crm_script_sudo_prompt' + if isinstance(cmd, str): + cmd = "sudo -H -S -p '%s' %s" % (sudo_prompt, cmd) + else: + cmd = ['sudo', '-H', '-S', '-p', sudo_prompt] + cmd + p = proc.Popen(cmd, shell=shell, stdin=proc.PIPE, stdout=proc.PIPE, stderr=proc.PIPE) + sudo_pass = "%s\n" % (_stdin_data.get('sudo', 'linux')) + debug("CMD(SUDO): %s" % (str(cmd))) + out, err = p.communicate(input=sudo_pass) + return p.returncode, out.strip(), err.strip() + + +def service(name, action): + if action.startswith('is-'): + return call(['/usr/bin/systemctl', action, name + '.service']) + return sudo_call(['/usr/bin/systemctl', action, name + '.service']) + + +def package(name, state): + rc, out, err = sudo_call(['./crm_pkg.py', '-n', name, '-s', state]) + if rc != 0: + raise IOError("%s / %s" % (out, err)) + outp = json.loads(decode_utf8(out)) + if isinstance(outp, dict) and 'rc' in outp: + rc = int(outp['rc']) + if rc != 0: + raise IOError("(rc=%s) %s%s" % (rc, outp.get('stdout', ''), outp.get('stderr', ''))) + return outp + + +def check_package(name, state): + rc, out, err = call(['./crm_pkg.py', '--dry-run', '-n', name, '-s', state]) + if rc != 0: + raise IOError(err) + outp = json.loads(out) + if isinstance(outp, dict) and 'rc' in outp: + rc = int(outp['rc']) + if rc != 0: + raise IOError("(rc=%s) %s%s" % (rc, outp.get('stdout', ''), outp.get('stderr', ''))) + return outp + + +def rpmcheck(names): + rc, out, err = call(['./crm_rpmcheck.py'] + names) + if rc != 0: + raise IOError(err) + return json.loads(out) + + +def save_template(template, dest, **kwargs): + ''' + 1. Reads a template from <template>, + 2. Replaces all template variables with those in <kwargs> and + 3. writes the resulting file to <dest> + ''' + import re + tmpl = open(template).read() + keys = re.findall(r'%\((\w+)\)s', tmpl, re.MULTILINE) + missing_keys = set(keys) - set(kwargs.keys()) + if missing_keys: + raise ValueError("Missing template arguments: %s" % ', '.join(missing_keys)) + tmpl = tmpl % kwargs + try: + with open(dest, 'w') as f: + f.write(tmpl) + except Exception as e: + raise IOError("Failed to write %s from template %s: %s" % (dest, template, e)) + debug("crm_script(save_template): wrote %s" % (dest)) + |