[autotest] Add a utility module to interact with LXC binaries.
Add a module (lxc.py) to interact with LXC binaries.
lxc_functional_test.py is a test script to test the module. It will
1. Set up base container in a tmp directory.
2. Create a test container from the base container.
3. Test site-packages and results directory can be mounted and shared between
host and test container.
4. Run autoserv in test mode.
Also add a utility function in client/common_lib/site_utils.py to get the value
of the given argument for the function. It's used in decorator to check function
parameters.
BUG=chromium:453621
CQ-DEPEND=CL:251140
TEST=unittest,
sudo python site_utils/lxc_functional_test.py
sudo python site_utils/lxc.py -s -p /tmp/container_123
sudo python site_utils/lxc.py -s -p /tmp/container_123 -f
sudo python site_utils/lxc.py -p /tmp/container_123 -f
Change-Id: Id7b259c4bc03977974af44d6d88420b220706589
Reviewed-on: https://chromium-review.googlesource.com/247271
Reviewed-by: Dan Shi <dshi@chromium.org>
Commit-Queue: Dan Shi <dshi@chromium.org>
Trybot-Ready: Dan Shi <dshi@chromium.org>
Tested-by: Dan Shi <dshi@chromium.org>
diff --git a/client/common_lib/site_utils.py b/client/common_lib/site_utils.py
index b3a0b3a..b5e739c 100644
--- a/client/common_lib/site_utils.py
+++ b/client/common_lib/site_utils.py
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import inspect
import logging
import os
import re
@@ -326,13 +327,13 @@
return ver, milestone
-
def is_localhost(server):
"""Check if server is equivalent to localhost.
@param server: Name of the server to check.
@return: True if given server is equivalent to localhost.
+
@raise socket.gaierror: If server name failed to be resolved.
"""
if server in _LOCAL_HOST_LIST:
@@ -343,3 +344,35 @@
except socket.gaierror:
logging.error('Failed to resolve server name %s.', server)
return False
+
+
+def get_function_arg_value(func, arg_name, args, kwargs):
+ """Get the value of the given argument for the function.
+
+ @param func: Function being called with given arguments.
+ @param arg_name: Name of the argument to look for value.
+ @param args: arguments for function to be called.
+ @param kwargs: keyword arguments for function to be called.
+
+ @return: The value of the given argument for the function.
+
+ @raise ValueError: If the argument is not listed function arguemnts.
+ @raise KeyError: If no value is found for the given argument.
+ """
+ if arg_name in kwargs:
+ return kwargs[arg_name]
+
+ argspec = inspect.getargspec(func)
+ index = argspec.args.index(arg_name)
+ try:
+ return args[index]
+ except IndexError:
+ try:
+ # The argument can use a default value. Reverse the default value
+ # so argument with default value can be counted from the last to
+ # the first.
+ return argspec.defaults[::-1][len(argspec.args) - index - 1]
+ except IndexError:
+ raise KeyError('Argument %s is not given a value. argspec: %s, '
+ 'args:%s, kwargs:%s' %
+ (arg_name, argspec, args, kwargs))