Extract the logging decorator used in kernel.py into a common library
and add it to Autotest.install to provide logging of autotest
installation failure (and success).
Signed-off-by: John Admanski <jadmanski@google.com>
git-svn-id: http://test.kernel.org/svn/autotest/trunk@937 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/client/bin/kernel.py b/client/bin/kernel.py
index d9d818a..f7b1528 100755
--- a/client/bin/kernel.py
+++ b/client/bin/kernel.py
@@ -2,33 +2,10 @@
import os,os.path,shutil,urllib,copy,pickle,re,glob,time
from autotest_utils import *
+from common import logging
import kernel_config, test, os_dep
-def record(fn):
- """ Decorator for logging calls to specific kernel methods.
- It also accepts a "logged=False" keyword argument to disable
- the logging for particular calls.
-
- Classes that make use of this dectorator will need to have job
- and subdir attributes for the logging to function correctly.
- """
- def recorded_func(self, *args, **dargs):
- logged = dargs.pop('logged', True)
- if not logged:
- return fn(self, *args, **dargs)
- # wrap the method call in success/failure logging
- name = "kernel.%s" % fn.__name__
- try:
- result = fn(self, *args, **dargs)
- self.job.record('GOOD', self.subdir, name)
- except Exception, detail:
- self.job.record('FAIL', self.subdir, name, str(detail))
- raise
- return result
- return recorded_func
-
-
class kernel:
""" Class for compiling kernels.
@@ -138,7 +115,7 @@
self.patch(*base_components)
- @record
+ @logging.record
def patch(self, *patches):
"""Apply a list of patches (in order)"""
if not patches:
@@ -147,7 +124,7 @@
self.apply_patches(self.get_patches(patches))
- @record
+ @logging.record
def config(self, config_file = '', config_list = None, defconfig = False):
self.job.stdout.tee_redirect(os.path.join(self.log_dir, 'stdout'))
self.set_cross_cc()
@@ -220,7 +197,7 @@
system('sed "%s" < Makefile.old > Makefile' % p)
- @record
+ @logging.record
def build(self, make_opts = '', logfile = '', extraversion='autotest'):
"""build the kernel
@@ -277,7 +254,7 @@
raise TestError("no vmlinux found, kernel build failed")
- @record
+ @logging.record
def clean(self):
"""make clean in the kernel tree"""
os.chdir(self.build_dir)
@@ -285,7 +262,7 @@
system('make clean > /dev/null 2> /dev/null')
- @record
+ @logging.record
def mkinitrd(self, version, image, system_map, initrd):
"""Build kernel initrd image.
Try to use distro specific way to build initrd image.
@@ -331,7 +308,7 @@
self.build_image = image
- @record
+ @logging.record
def install(self, tag='autotest', prefix = '/'):
"""make install in the kernel tree"""
@@ -626,7 +603,7 @@
self.changelist = None
- @record
+ @logging.record
def install(self, tag='autotest'):
self.installed_as = tag
diff --git a/client/common_lib/__init__.py b/client/common_lib/__init__.py
index faa7f2f..7fbaa6e 100644
--- a/client/common_lib/__init__.py
+++ b/client/common_lib/__init__.py
@@ -1,4 +1,4 @@
-__all__ = []
+__all__ = ['logging']
import site_libraries
__all__ += site_libraries.libraries
diff --git a/client/common_lib/logging.py b/client/common_lib/logging.py
new file mode 100644
index 0000000..ded9abc
--- /dev/null
+++ b/client/common_lib/logging.py
@@ -0,0 +1,35 @@
+def record(fn):
+ """
+ Generic method decorator for logging calls under the
+ assumption that return=GOOD, exception=FAIL. The method
+ determines parameters as:
+ subdir = self.subdir if it exists, or None
+ operation = "class name"."method name"
+ status = None on GOOD, str(exception) on FAIL
+ The object using this method must have a job attribute
+ for the logging to actually occur, otherwise the logging
+ will silently fail.
+
+ Logging can explicitly be disabled for a call by passing
+ a logged=False parameter
+ """
+ def recorded_func(self, *args, **dargs):
+ logged = dargs.pop('logged', True)
+ job = getattr(self, 'job', None)
+ # if logging is disabled/unavailable, just
+ # call the method
+ if not logged or job is None:
+ return fn(self, *args, **dargs)
+ # logging is available, so wrap the method call
+ # in success/failure logging
+ subdir = getattr(self, 'subdir', None)
+ operation = '%s.%s' % (self.__class__.__name__,
+ fn.__name__)
+ try:
+ result = fn(self, *args, **dargs)
+ job.record('GOOD', subdir, operation)
+ except Exception, detail:
+ job.record('FAIL', subdir, operation, str(detail))
+ raise
+ return result
+ return recorded_func
diff --git a/server/autotest.py b/server/autotest.py
index 481a147..48b638d 100644
--- a/server/autotest.py
+++ b/server/autotest.py
@@ -26,6 +26,7 @@
import installable_object
import errors
import utils
+from common import logging
AUTOTEST_SVN = 'svn://test.kernel.org/autotest/trunk/client'
@@ -56,6 +57,9 @@
This is a leaf class in an abstract class hierarchy, it must
implement the unimplemented methods in parent classes.
"""
+ job = None
+
+
def __init__(self, host = None):
self.host = host
self.got = False
@@ -64,6 +68,7 @@
super(Autotest, self).__init__()
+ @logging.record
def install(self, host = None):
"""
Install autotest. If get() was not called previously, an
diff --git a/server/server_job.py b/server/server_job.py
index 1e81e4c..f756a41 100755
--- a/server/server_job.py
+++ b/server/server_job.py
@@ -31,6 +31,7 @@
from subcommand import *
from utils import run, get_tmp_dir, sh_escape
+autotest.Autotest.job = job
hosts.SSHHost.job = job
"""