From: Alexander Kanevskiy Date: Mon, 12 Aug 2013 21:45:32 +0000 (+0300) Subject: collection of useful functions X-Git-Tag: submit/devel/20190730.075356~21 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c3d21aa8c7ab8cd06ab62fed12b42739c1906d49;p=services%2Fgerrithooks.git collection of useful functions --- diff --git a/gerrithooks/misc.py b/gerrithooks/misc.py new file mode 100644 index 0000000..967cf86 --- /dev/null +++ b/gerrithooks/misc.py @@ -0,0 +1,163 @@ +#!/usr/bin/env +# -*- coding: UTF-8 -*- +# vim: sw=4 ts=4 expandtab ai +# +# Copyright (c) 2013 Intel, Inc. +# License: GPLv2 +# Author: Alexander Kanevskiy +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, +# 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. + +""" Misc functions to use in rest of gerrit hooks modules (e.g. logging) """ + +import os +import sys +import signal +import subprocess +import pwd + +import logging +import logging.config + + +def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): + """Daemonize process""" + try: + pid = os.fork() + if pid > 0: + sys.exit(0) # Exit first parent. + except OSError, err: + sys.stderr.write("First fork failed: (%d) %sn" % \ + (err.errno, err.strerror)) + sys.exit(1) + os.setsid() + signal.signal(signal.SIGHUP, signal.SIG_IGN) + os.chdir("/") + os.umask(0) + try: + pid = os.fork() + if pid > 0: + sys.exit(0) + except OSError, err: + sys.stderr.write("Second fork failed: (%d) %sn" % \ + (err.errno, err.strerror)) + sys.exit(1) + + for filed in sys.stdout, sys.stderr: + filed.flush() + + new_stdin = open(stdin, 'r') + new_stdout = open(stdout, 'a+', 0) + new_stderr = open(stderr, 'a+', 0) + os.dup2(new_stdin.fileno(), sys.stdin.fileno()) + os.dup2(new_stdout.fileno(), sys.stdout.fileno()) + os.dup2(new_stderr.fileno(), sys.stderr.fileno()) + sys.stdin, sys.stdout, sys.stderr = new_stdin, new_stdout, new_stderr + + +def cmd_inout(command, args, cmd_input=None, extra_env=None, cwd=None, + capture_stderr=False, output_f=None, filter_fn=None, + filter_kwargs={}, logger=None): + """ + Run command in subprocess + """ + env = os.environ.copy() + if extra_env is not None: + env.update(extra_env) + if not command: + return (None, None, -255) + cmd = [command] + args + debug_msg = " ".join(cmd) + if output_f: + debug_msg += " > %s" % output_f.name + if filter_fn: + debug_msg += ", filtering through %s()" % filter_fn.__name__ + if logger: + logger.debug(debug_msg) + + if not output_f: + output_f = subprocess.PIPE + stdout_arg = subprocess.PIPE if filter_fn else output_f + stderr_arg = subprocess.PIPE if capture_stderr else None + popen = subprocess.Popen(cmd, + stdin=subprocess.PIPE, + stdout=stdout_arg, + stderr=stderr_arg, + env=env, + cwd=cwd) + if filter_fn: + if filter_fn(popen.stdout, output_f, **filter_kwargs): + raise Exception("Filtering command output in failed!") + (stdout, stderr) = popen.communicate(cmd_input) + + return stdout, stderr, popen.returncode + +def parse_gitconfig(input_cfg=None): + """ + Read configuration data from git. + + This internal method populates the GitConfig cache. + + """ + cfg = {} + if input_cfg is None or not input_cfg: + return cfg + for line in input_cfg.rstrip('\0').split('\0'): # pylint: disable=W1401 + # Backslash is not anomalous + if '\n' in line: + key, val = line.split('\n', 1) + else: + key = line + val = None + if key in cfg: + cfg[key].append(val) + else: + cfg[key] = [val] + return cfg + +def find_config(name, dirs=None, subdir=None): + """Find readable configuration file in the list of dirs.""" + + if not dirs: + homedir = pwd.getpwuid(os.getuid()).pw_dir + dirs = [] + if subdir: + dirs.append(os.path.join(homedir,"."+subdir)) + dirs.append(os.path.join("/etc", subdir)) + else: + dirs.append(homedir) + dirs.append("/etc") + for dirname in dirs: + confpath = os.path.join(dirname, name) + if os.access(confpath, os.R_OK): + return confpath + return None + +def configure_logging(appname): + """Setup logging""" + homedir = pwd.getpwuid(os.getuid()).pw_dir + + log_confname = "gerrit-hooks-log.conf" + log_config = find_config(log_confname, subdir="gerrit-hooks") + if not log_config: + raise SystemExit("Log configuration file %s not found or not readable" \ + % log_confname) + + if sys.platform == 'darwin': + syslog_socket = "/var/run/syslog" + else: + syslog_socket = "/dev/log" + + # Configure logging + logging.config.fileConfig(log_config, {'syslog_socket': syslog_socket}) + logger = logging.getLogger(appname) + logger.debug("configure_logging: using logging config %s", log_config) + return logger +