[autotest] Parse RETRIES from control files

Parse the RETRIES variable from control files and insert into job/test
databased entry. This happens in suite.py before creation of suite sub-jobs,
and in test_importer when importing new tests into afe_autotests database.

BUG=chromium-os:37158
TEST=unit.
Ran utils/test_importer.py and verified that 2 tests name
flaky_test both had test_retry imported correctly with value 2 (in
afe_autotests table).
Kicked off a dummyflake suite and verified that its sub jobs were
created with test_retry=2.

Change-Id: I93eb0f4581120082a82c46b2be98286ede248c94
Reviewed-on: https://gerrit.chromium.org/gerrit/44435
Tested-by: Aviv Keshet <akeshet@chromium.org>
Reviewed-by: Alex Miller <milleral@chromium.org>
Commit-Queue: Scott Zawalski <scottz@chromium.org>
Reviewed-by: Scott Zawalski <scottz@chromium.org>
Tested-by: Scott Zawalski <scottz@chromium.org>
diff --git a/client/common_lib/control_data.py b/client/common_lib/control_data.py
index cbecaca..0b12bfd 100644
--- a/client/common_lib/control_data.py
+++ b/client/common_lib/control_data.py
@@ -1,4 +1,4 @@
-#
+# pylint: disable-msg=C0111
 # Copyright 2008 Google Inc. Released under the GPL v2
 
 import compiler, logging, textwrap
@@ -43,6 +43,7 @@
         self.test_parameters = set()
         self.test_category = ''
         self.test_class = ''
+        self.retries = 0
 
         diff = REQUIRED_VARS - set(vars)
         if len(diff) > 0:
@@ -167,6 +168,10 @@
         self._set_set('test_parameters', val)
 
 
+    def set_retries(self, val):
+        self._set_int('retries', val)
+
+
 def _extract_const(n):
     assert(n.__class__ == compiler.ast.Assign)
     assert(n.expr.__class__ == compiler.ast.Const)
diff --git a/client/common_lib/control_data_unittest.py b/client/common_lib/control_data_unittest.py
index b5c3551..aafb9f0 100755
--- a/client/common_lib/control_data_unittest.py
+++ b/client/common_lib/control_data_unittest.py
@@ -1,4 +1,5 @@
 #!/usr/bin/python
+# pylint: disable-msg=C0111
 
 import os, unittest
 
@@ -21,6 +22,7 @@
 TEST_CLASS=u'Kernel'
 TEST_CATEGORY='Stress'
 TEST_TYPE='client'
+RETRIES = 5
 """
 
 
@@ -48,6 +50,7 @@
         self.assertEquals(cd.test_class, "kernel")
         self.assertEquals(cd.test_category, "stress")
         self.assertEquals(cd.test_type, "client")
+        self.assertEquals(cd.retries, 5)
 
 
 class SetMethodTests(unittest.TestCase):
diff --git a/server/cros/dynamic_suite/fakes.py b/server/cros/dynamic_suite/fakes.py
index 7fded70..fe7d505 100644
--- a/server/cros/dynamic_suite/fakes.py
+++ b/server/cros/dynamic_suite/fakes.py
@@ -1,3 +1,4 @@
+#pylint: disable-msg=C0111
 # Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
@@ -17,6 +18,7 @@
         self.experimental = expr
         self.dependencies = []
         self.time = time
+        self.retries = 0
 
 
 class FakeJob(object):
diff --git a/server/cros/dynamic_suite/suite.py b/server/cros/dynamic_suite/suite.py
index 440e1a0..18e9838 100644
--- a/server/cros/dynamic_suite/suite.py
+++ b/server/cros/dynamic_suite/suite.py
@@ -298,7 +298,8 @@
             keyvals={constants.JOB_BUILD_KEY: self._build,
                      constants.JOB_SUITE_KEY: self._tag},
             max_runtime_mins=self._max_runtime_mins,
-            parent_job_id=self._suite_job_id)
+            parent_job_id=self._suite_job_id,
+            test_retry=test.retries)
 
         setattr(test_obj, 'test_name', test.name)
 
diff --git a/utils/test_importer.py b/utils/test_importer.py
index a7be755..5609064 100755
--- a/utils/test_importer.py
+++ b/utils/test_importer.py
@@ -28,6 +28,7 @@
 
 import common
 import logging, re, os, sys, optparse, compiler
+#pylint: disable-msg=W0611
 from autotest_lib.frontend import setup_django_environment
 from autotest_lib.frontend.afe import models
 from autotest_lib.client.common_lib import control_data, utils
@@ -35,6 +36,7 @@
 
 
 class TestImporterLoggingConfig(logging_config.LoggingConfig):
+    #pylint: disable-msg=C0111
     def configure_logging(self, results_dir=None, verbose=False):
         super(TestImporterLoggingConfig, self).configure_logging(
                                                                use_console=True,
@@ -294,6 +296,8 @@
     if not test.test_type and str == type(data.test_type):
         test.test_type = test_type[data.test_type.lower()]
 
+    test.test_retry = data.retries
+
 
 def add_label_dependencies(test):
     """
@@ -464,7 +468,9 @@
 
 
 def main(argv):
-    """Main function"""
+    """Main function
+    @param argv: List of command line parameters.
+    """
 
     global DRY_RUN
     parser = optparse.OptionParser()