From 300531507b9a261ed1707b4b1da6dabac0112b88 Mon Sep 17 00:00:00 2001 From: Stephen Fromm Date: Wed, 9 Jan 2013 15:54:51 -0800 Subject: [PATCH] Add method run_command to module_common.py This adds a helper method that modules can call to execute a command via subproces. It takes two arguments: the command to run and keyword options that control how the process is executed. Supported options are: fail_on_rc_non_zero, close_fds, and executable. fail_on_rc_non_zero will call fail_json if the command fails. If args is a list, the command will be run with shell=False; otherwise, if a string, it will be run with shell=True. Otherwise, run_command() returns the returncode, stdout, and stderr. --- lib/ansible/module_common.py | 46 ++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/lib/ansible/module_common.py b/lib/ansible/module_common.py index 882e5cda7b1..d8e87a8bf4f 100644 --- a/lib/ansible/module_common.py +++ b/lib/ansible/module_common.py @@ -677,6 +677,52 @@ class AnsibleModule(object): self.set_context_if_different(src, context, False) os.rename(src, dest) + def run_command(self, args, **kwargs): + ''' + Execute a command, returns rc, stdout, and stderr. + args is the command to run + If args is a list, the command will be run with shell=False. + Otherwise, the command will be run with shell=True when args is a string. + kwargs is a dict of keyword arguments: + - fail_on_rc_non_zero (boolean) Whether to call fail_json in case of + non zero RC. Default is False. + - close_fds (boolean) See documentation for subprocess.Popen(). + Default is False. + - executable (string) See documentation for subprocess.Popen(). + Default is None. + ''' + if isinstance(args, list): + kwargs['shell'] = False + elif isinstance(args, basestring): + kwargs['shell'] = True + else: + msg = "Argument 'args' to run_command must be list or string" + self.fail_json(rc=257, cmd=args, msg=msg) + if 'fail_on_rc_non_zero' not in kwargs: + kwargs['fail_on_rc_non_zero'] = False + if 'close_fds' not in kwargs: + kwargs['close_fds'] = False + if 'executable' not in kwargs: + kwargs['executable'] = None + rc = 0 + msg = None + try: + cmd = subprocess.Popen(args, + executable=kwargs['executable'], + shell=kwargs['shell'], + close_fds=kwargs['close_fds'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = cmd.communicate() + rc = cmd.returncode + except (OSError, IOError), e: + self.fail_json(rc=e.errno, msg=str(e), cmd=args) + except: + self.fail_json(rc=257, msg=traceback.format_exc(), cmd=args) + if rc != 0 and kwargs['fail_on_rc_non_zero']: + msg = err.rstrip() + self.fail_json(cmd=args, rc=rc, stdout=out, stderr=err, msg=msg) + return (rc, out, err) + # == END DYNAMICALLY INSERTED CODE === """