Added support to specify cmdline for the booted kernels for both the CLI 
and the frontend. For the CLI there is a new "--kernel-cmdline" option 
that will be used for all the kernels configured to be booted with the 
"-k" parameter. For the frontend there's a new textbox under the kernel 
version one where cmdline can be provided.

Signed-off-by: Mihai Rusu <dizzy@google.com>


git-svn-id: http://test.kernel.org/svn/autotest/trunk@3599 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/frontend/afe/control_file.py b/frontend/afe/control_file.py
index 3ce0686..355c65f 100644
--- a/frontend/afe/control_file.py
+++ b/frontend/afe/control_file.py
@@ -19,18 +19,23 @@
 kernel_list = %(client_kernel_list)s
 
 def step_init():
-    for kernel_version in kernel_list:
-        job.next_step(boot_kernel, kernel_version)
-        job.next_step(step_test, kernel_version)
+    for kernel_info in kernel_list:
+        job.next_step(boot_kernel, kernel_info)
+        job.next_step(step_test, kernel_info['version'])
     if len(kernel_list) > 1:
         job.set_run_number(1)  # Include run numbers in output directory names.
         job.show_kernel_in_test_tag(True)  # Include kernel in output dir name.
 
-def boot_kernel(kernel_version):
-    testkernel = job.kernel(kernel_version)
-    %(kernel_config_line)s
+
+def boot_kernel(kernel_info):
+    testkernel = job.kernel(kernel_info['version'])
+    if kernel_info['config_file']:
+        testkernel.config(kernel_info['config_file'])
     testkernel.install()
-    testkernel.boot(args='%(kernel_args)s')
+
+    cmdline = ' '.join((kernel_info.get('cmdline', ''), '%(kernel_args)s'))
+    testkernel.boot(args=cmdline)
+
 
 def step_test(kernel_version):
     global kernel
@@ -46,11 +51,12 @@
 from autotest_lib.client.common_lib import error
 
 at = autotest.Autotest()
-def install_kernel(machine, kernel_version):
+def install_kernel(machine, kernel_info):
     host = hosts.create_host(machine)
     at.install(host=host)
     at.run(kernel_install_control %%%%
-           {'client_kernel_list': repr([kernel_version])}, host=host)
+           {'client_kernel_list': repr([kernel_info])}, host=host)
+
 
 num_machines_required = len(machines)
 if len(machines) > 4:
@@ -60,6 +66,7 @@
     # within some control files and will end up inside of stepN functions below.
     num_machines_required = len(machines) - 2
 
+
 def step_init():
     # a host object we use solely for the purpose of finding out the booted
     # kernel version, we use machines[0] since we already check that the same
@@ -67,8 +74,8 @@
     if len(kernel_list) > 1:
         kernel_host = hosts.create_host(machines[0])
 
-    for kernel_version in kernel_list:
-        func = lambda machine: install_kernel(machine, kernel_version)
+    for kernel_info in kernel_list:
+        func = lambda machine: install_kernel(machine, kernel_info)
         good_machines = job.parallel_on_machines(func, machines)
         if len(good_machines) < num_machines_required:
             raise error.TestError(
@@ -86,6 +93,7 @@
             job.set_test_tag_prefix(kernel_host.get_kernel_ver())
         step_test()
 
+
 def step_test():
 """ % CLIENT_KERNEL_TEMPLATE
 
@@ -93,11 +101,11 @@
 SERVER_STEP_TEMPLATE = '    step%d()\n'
 
 
-def kernel_config_line(kernel, platform):
+def kernel_config_file(kernel, platform):
     if (not kernel.endswith('.rpm') and platform and
         platform.kernel_config):
-        return "testkernel.config('%s')" % platform.kernel_config
-    return ''
+        return platform.kernel_config
+    return None
 
 
 def read_control_file(test):
@@ -110,20 +118,23 @@
 def get_kernel_stanza(kernel_list, platform=None, kernel_args='',
                       is_server=False):
 
-    template_args = {
-        # XXX This always looks up the config line using the first kernel
-        # in the list rather than doing it for each kernel.
-        'kernel_config_line' : kernel_config_line(kernel_list[0], platform),
-        'kernel_args' : kernel_args}
+    template_args = {'kernel_args' : kernel_args}
+
+    # add 'config_file' keys to the kernel_info dictionaries
+    new_kernel_list = []
+    for kernel_info in kernel_list:
+        config_file = kernel_config_file(kernel_info['version'], platform)
+        new_kernel_info = dict(kernel_info, config_file=config_file)
+        new_kernel_list.append(new_kernel_info)
 
     if is_server:
         template = SERVER_KERNEL_TEMPLATE
         # leave client_kernel_list as a placeholder
         template_args['client_kernel_list'] = '%(client_kernel_list)s'
-        template_args['server_kernel_list'] = repr(kernel_list)
+        template_args['server_kernel_list'] = repr(new_kernel_list)
     else:
         template = CLIENT_KERNEL_TEMPLATE
-        template_args['client_kernel_list'] = repr(kernel_list)
+        template_args['client_kernel_list'] = repr(new_kernel_list)
 
     return template % template_args
 
@@ -246,15 +257,7 @@
     return prepend, append
 
 
-def split_kernel_list(kernel_string):
-    """Split the kernel(s) string from the user into a list of kernels.
-
-    We allow multiple kernels to be listed separated by a space or comma.
-    """
-    return re.split('[\s,]+', kernel_string.strip())
-
-
-def _sanity_check_generate_control(is_server, client_control_file, kernel):
+def _sanity_check_generate_control(is_server, client_control_file, kernels):
     """
     Sanity check some of the parameters to generate_control().
 
@@ -268,30 +271,45 @@
                 {'tests' : 'You cannot run server tests at the same time '
                  'as directly supplying a client-side control file.'})
 
+    if kernels:
+        # make sure that kernel is a list of dictionarions with at least
+        # the 'version' key in them
+        kernel_error = model_logic.ValidationError(
+                {'kernel': 'The kernel parameter must be a sequence of '
+                 'dictionaries containing at least the "version" key '
+                 '(got: %r)' % kernels})
+        try:
+            iter(kernels)
+        except TypeError:
+            raise kernel_error
+        for kernel_info in kernels:
+            if (not isinstance(kernel_info, dict) or
+                    'version' not in kernel_info):
+                raise kernel_error
 
-def generate_control(tests, kernel=None, platform=None, is_server=False,
+
+def generate_control(tests, kernels=None, platform=None, is_server=False,
                      profilers=(), client_control_file=''):
     """
     Generate a control file for a sequence of tests.
 
     @param tests A sequence of test control files to run.
-    @param kernel A string listing one or more kernel versions to test
-        separated by spaces or commas.
+    @param kernels A sequence of kernel info dictionaries configuring which
+            kernels to boot for this job and other options for them
     @param platform A platform object with a kernel_config attribute.
     @param is_server bool, Is this a server control file rather than a client?
     @param profilers A list of profiler objects to enable during the tests.
     @param client_control_file Contents of a client control file to run as the
-        last test after everything in tests.  Requires is_server=False.
+            last test after everything in tests.  Requires is_server=False.
 
     @returns The control file text as a string.
     """
-    _sanity_check_generate_control(is_server=is_server, kernel=kernel,
+    _sanity_check_generate_control(is_server=is_server, kernels=kernels,
                                    client_control_file=client_control_file)
 
     control_file_text = ''
-    if kernel:
-        kernel_list = split_kernel_list(kernel)
-        control_file_text = get_kernel_stanza(kernel_list, platform,
+    if kernels:
+        control_file_text = get_kernel_stanza(kernels, platform,
                                               is_server=is_server)
     else:
         control_file_text = EMPTY_TEMPLATE