[autotest] Update suite scheduler to support notation of <=

BUG=chromium:519612
TEST=unittest, local suite scheduler test
create an ini file with <= branch_specs, e.g.,
[WeeklyWiFi_MatFunc]
run_on: weekly
suite: wifi_matfunc
branch_specs: <=tot-1
pool: suites

Create a repo of manifest-versions
/usr/bin/git clone https://chrome-internal-review.googlesource.com/chromeos/manifest-versions.git /tmp/_autotmp_uhDTzf_suite_scheduler

run suite_scheduler to confirm suite is created:
/usr/local/autotest/site_utils/suite_scheduler/suite_scheduler.py -b \
 -d /usr/local/autotest/logs -f /usr/local/autotest/test_suite_scheduler.ini \
 -r /tmp/_autotmp_uhDTzf_suite_scheduler -e weekly \
 -i veyron_jerry-release/R45-7077.90.0

Change-Id: Ia1a55a30a58801f1e28ad86b430592bc607a126e
Reviewed-on: https://chromium-review.googlesource.com/294136
Trybot-Ready: Dan Shi <dshi@chromium.org>
Tested-by: Dan Shi <dshi@chromium.org>
Reviewed-by: Mungyung Ryu <mkryu@google.com>
Reviewed-by: Fang Deng <fdeng@chromium.org>
Commit-Queue: Dan Shi <dshi@chromium.org>
diff --git a/site_utils/suite_scheduler/task.py b/site_utils/suite_scheduler/task.py
index 0ef61d8..3fa0980 100644
--- a/site_utils/suite_scheduler/task.py
+++ b/site_utils/suite_scheduler/task.py
@@ -335,6 +335,8 @@
 
         self._bare_branches = []
         self._version_equal_constraint = False
+        self._version_gte_constraint = False
+        self._version_lte_constraint = False
         if not branch_specs:
             # Any milestone is OK.
             self._numeric_constraint = version.LooseVersion('0')
@@ -345,14 +347,19 @@
                     tot_str = spec[spec.index('tot'):]
                     spec = spec.replace(
                             tot_str, TotMilestoneManager().ConvertTotSpec(
-                                tot_str))
+                                    tot_str))
                 if spec.startswith('>='):
                     self._numeric_constraint = version.LooseVersion(
-                        spec.lstrip('>=R'))
+                            spec.lstrip('>=R'))
+                    self._version_gte_constraint = True
+                elif spec.startswith('<='):
+                    self._numeric_constraint = version.LooseVersion(
+                            spec.lstrip('<=R'))
+                    self._version_lte_constraint = True
                 elif spec.startswith('=='):
                     self._version_equal_constraint = True
                     self._numeric_constraint = version.LooseVersion(
-                        spec.lstrip('==R'))
+                            spec.lstrip('==R'))
                 else:
                     self._bare_branches.append(spec)
 
@@ -382,7 +389,8 @@
 
         When called on a branch name, will return whether that branch
         'fits' the specifications stored in self._bare_branches,
-        self._numeric_constraint and self._version_equal_constraint.
+        self._numeric_constraint, self._version_equal_constraint,
+        self._version_gte_constraint and self._version_lte_constraint.
 
         @param branch: the branch to check.
         @return True if b 'fits' with stored specs, False otherwise.
@@ -392,7 +400,12 @@
         if self._numeric_constraint:
             if self._version_equal_constraint:
                 return version.LooseVersion(branch) == self._numeric_constraint
+            elif self._version_gte_constraint:
+                return version.LooseVersion(branch) >= self._numeric_constraint
+            elif self._version_lte_constraint:
+                return version.LooseVersion(branch) <= self._numeric_constraint
             else:
+                # Default to great or equal constraint.
                 return version.LooseVersion(branch) >= self._numeric_constraint
         else:
             return False
@@ -637,7 +650,7 @@
             logging.info('Checking if %s fits spec %r',
                          branch, self.branch_specs)
             if self._FitsSpec(branch):
-                logging.debug('Build %s fits the spec.')
+                logging.debug('Build %s fits the spec.', build)
                 builds.extend(build)
         for build in builds:
             try: