This commit adds a Run() class that can invoke Python's Popen command. This class provides a static method, run(), that will execute the command via Python's subprocess module.
Example usages: # delete foo.conf Run.run(['rm', '-f', '/tmp/foo.conf']) # Use cgset to set SomeCgroup's cpu.shares to 500 cmd = ['cgset', '-r', 'cpu.shares=500', 'SomeCgroup'] Run.run(cmd) # get info on current user Run.run('id') # write to a file. Note that this must be run in a shell Run.run(['echo', 'some data', '>>', 'some_file'], shell_bool=True) Example output: Jun 27 12:34:18: DEBUG: run: command = sudo lxc-info --config=lxc.rootfs -n test_libcg ret = 0 stdout = lxc.rootfs = /container/test_libcg/rootfs stderr = Jun 27 12:34:18: DEBUG: run: command = sudo lxc-attach -n test_libcg -- /libcg/src/tools/.libs/cgget -n -v -r cpu.shares 001cgget ret = 0 stdout = 512 stderr = If the command fails, Run.run() throws a RunError exception which contains the return code, stdout, and stderr from the command. Signed-off-by: Tom Hromatka <tom.hroma...@oracle.com> Reviewed-by: Dhaval Giani <dhaval.gi...@oracle.com> --- tests/ftests/run.py | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tests/ftests/run.py diff --git a/tests/ftests/run.py b/tests/ftests/run.py new file mode 100644 index 0000000..80e5221 --- /dev/null +++ b/tests/ftests/run.py @@ -0,0 +1,74 @@ +# +# Run class for the libcgroup functional tests +# +# Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. +# Author: Tom Hromatka <tom.hroma...@oracle.com> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# This library 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 Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, see <http://www.gnu.org/licenses>. +# + +from log import Log +import subprocess +import time + +class Run(object): + @staticmethod + def run(command, shell_bool=False): + if shell_bool: + if isinstance(command, str): + # nothing to do. command is already formatted as a string + pass + elif isinstance(command, list): + command = ' '.join(command) + else: + raise ValueError('Unsupported command type') + + subproc = subprocess.Popen(command, shell=shell_bool, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = subproc.communicate() + ret = subproc.returncode + + out = out.strip() + err = err.strip() + + if shell_bool: + Log.log_debug( + "run:\n\tcommand = {}\n\tret = {}\n\tstdout = {}\n\tstderr = {}".format( + command, ret, out, err)) + else: + Log.log_debug( + "run:\n\tcommand = {}\n\tret = {}\n\tstdout = {}\n\tstderr = {}".format( + ''.join(command), ret, out, err)) + + if ret != 0: + raise RunError("Command '{}' failed".format(''.join(command), + command, ret, out, err)) + + return out + +class RunError(Exception): + def __init__(self, message, command, ret, stdout, stderr): + super(RunError, self).__init__(message) + + self.command = command + self.ret = ret + self.stdout = stdout + self.stderr = stderr + + def __str__(self): + out_str = "RunError:\n\tmessage = {}\n\tret = {}".format(self.message, self.ret) + out_str += "\n\tstdout = {}\n\tstderr = {}".format(self.stdout, self.stderr) + return out_str -- 1.8.3.1 _______________________________________________ Libcg-devel mailing list Libcg-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libcg-devel