aboutsummaryrefslogtreecommitdiff
path: root/cros_utils/buildbot_utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'cros_utils/buildbot_utils.py')
-rw-r--r--cros_utils/buildbot_utils.py485
1 files changed, 250 insertions, 235 deletions
diff --git a/cros_utils/buildbot_utils.py b/cros_utils/buildbot_utils.py
index b600c6aa..8f0ce5e0 100644
--- a/cros_utils/buildbot_utils.py
+++ b/cros_utils/buildbot_utils.py
@@ -1,12 +1,10 @@
# -*- coding: utf-8 -*-
-# Copyright 2017 The Chromium OS Authors. All rights reserved.
+# Copyright 2017 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Utilities for launching and accessing ChromeOS buildbots."""
-from __future__ import division
-from __future__ import print_function
import ast
import json
@@ -17,6 +15,7 @@ import time
from cros_utils import command_executer
from cros_utils import logger
+
INITIAL_SLEEP_TIME = 7200 # 2 hours; wait time before polling buildbot.
SLEEP_TIME = 600 # 10 minutes; time between polling of buildbot.
@@ -26,267 +25,283 @@ TIME_OUT = 15 * 60 * 60 # Decide the build is dead or will never finish
class BuildbotTimeout(Exception):
- """Exception to throw when a buildbot operation timesout."""
+ """Exception to throw when a buildbot operation timesout."""
def RunCommandInPath(path, cmd):
- ce = command_executer.GetCommandExecuter()
- cwd = os.getcwd()
- os.chdir(path)
- status, stdout, stderr = ce.RunCommandWOutput(cmd, print_to_console=False)
- os.chdir(cwd)
- return status, stdout, stderr
+ ce = command_executer.GetCommandExecuter()
+ cwd = os.getcwd()
+ os.chdir(path)
+ status, stdout, stderr = ce.RunCommandWOutput(cmd, print_to_console=False)
+ os.chdir(cwd)
+ return status, stdout, stderr
def PeekTrybotImage(chromeos_root, buildbucket_id):
- """Get the artifact URL of a given tryjob.
+ """Get the artifact URL of a given tryjob.
- Args:
- buildbucket_id: buildbucket-id
- chromeos_root: root dir of chrome os checkout
+ Args:
+ buildbucket_id: buildbucket-id
+ chromeos_root: root dir of chrome os checkout
- Returns:
- (status, url) where status can be 'pass', 'fail', 'running',
- and url looks like:
- gs://chromeos-image-archive/trybot-elm-release-tryjob/R67-10468.0.0-b20789
- """
- command = ('cros buildresult --report json --buildbucket-id %s' %
- buildbucket_id)
- rc, out, _ = RunCommandInPath(chromeos_root, command)
+ Returns:
+ (status, url) where status can be 'pass', 'fail', 'running',
+ and url looks like:
+ gs://chromeos-image-archive/trybot-elm-release-tryjob/R67-10468.0.0-b20789
+ """
+ command = (
+ "cros buildresult --report json --buildbucket-id %s" % buildbucket_id
+ )
+ rc, out, _ = RunCommandInPath(chromeos_root, command)
- # Current implementation of cros buildresult returns fail when a job is still
- # running.
- if rc != 0:
- return ('running', None)
+ # Current implementation of cros buildresult returns fail when a job is still
+ # running.
+ if rc != 0:
+ return ("running", None)
- results = json.loads(out)[buildbucket_id]
+ results = json.loads(out)[buildbucket_id]
- # Handle the case where the tryjob failed to launch correctly.
- if results['artifacts_url'] is None:
- return (results['status'], '')
+ # Handle the case where the tryjob failed to launch correctly.
+ if results["artifacts_url"] is None:
+ return (results["status"], "")
- return (results['status'], results['artifacts_url'].rstrip('/'))
+ return (results["status"], results["artifacts_url"].rstrip("/"))
def ParseTryjobBuildbucketId(msg):
- """Find the buildbucket-id in the messages from `cros tryjob`.
-
- Args:
- msg: messages from `cros tryjob`
-
- Returns:
- buildbucket-id, which will be passed to `cros buildresult`
- """
- output_list = ast.literal_eval(msg)
- output_dict = output_list[0]
- if 'buildbucket_id' in output_dict:
- return output_dict['buildbucket_id']
- return None
-
-
-def SubmitTryjob(chromeos_root,
- buildbot_name,
- patch_list,
- tryjob_flags=None,
- build_toolchain=False):
- """Calls `cros tryjob ...`
-
- Args:
- chromeos_root: the path to the ChromeOS root, needed for finding chromite
- and launching the buildbot.
- buildbot_name: the name of the buildbot queue, such as lumpy-release or
- daisy-paladin.
- patch_list: a python list of the patches, if any, for the buildbot to use.
- tryjob_flags: See cros tryjob --help for available options.
- build_toolchain: builds and uses the latest toolchain, rather than the
- prebuilt one in SDK.
-
- Returns:
- buildbucket id
- """
- patch_arg = ''
- if patch_list:
- for p in patch_list:
- patch_arg = patch_arg + ' -g ' + repr(p)
- if not tryjob_flags:
- tryjob_flags = []
- if build_toolchain:
- tryjob_flags.append('--latest-toolchain')
- tryjob_flags = ' '.join(tryjob_flags)
-
- # Launch buildbot with appropriate flags.
- build = buildbot_name
- command = ('cros_sdk -- cros tryjob --yes --json --nochromesdk %s %s %s' %
- (tryjob_flags, patch_arg, build))
- print('CMD: %s' % command)
- _, out, _ = RunCommandInPath(chromeos_root, command)
- buildbucket_id = ParseTryjobBuildbucketId(out)
- print('buildbucket_id: %s' % repr(buildbucket_id))
- if not buildbucket_id:
- logger.GetLogger().LogFatal('Error occurred while launching trybot job: '
- '%s' % command)
- return buildbucket_id
-
-
-def GetTrybotImage(chromeos_root,
- buildbot_name,
- patch_list,
- tryjob_flags=None,
- build_toolchain=False,
- asynchronous=False):
- """Launch buildbot and get resulting trybot artifact name.
-
- This function launches a buildbot with the appropriate flags to
- build the test ChromeOS image, with the current ToT mobile compiler. It
- checks every 10 minutes to see if the trybot has finished. When the trybot
- has finished, it parses the resulting report logs to find the trybot
- artifact (if one was created), and returns that artifact name.
-
- Args:
- chromeos_root: the path to the ChromeOS root, needed for finding chromite
- and launching the buildbot.
- buildbot_name: the name of the buildbot queue, such as lumpy-release or
- daisy-paladin.
- patch_list: a python list of the patches, if any, for the buildbot to use.
- tryjob_flags: See cros tryjob --help for available options.
- build_toolchain: builds and uses the latest toolchain, rather than the
- prebuilt one in SDK.
- asynchronous: don't wait for artifacts; just return the buildbucket id
-
- Returns:
- (buildbucket id, partial image url) e.g.
- (8952271933586980528, trybot-elm-release-tryjob/R67-10480.0.0-b2373596)
- """
- buildbucket_id = SubmitTryjob(chromeos_root, buildbot_name, patch_list,
- tryjob_flags, build_toolchain)
- if asynchronous:
- return buildbucket_id, ' '
-
- # The trybot generally takes more than 2 hours to finish.
- # Wait two hours before polling the status.
- time.sleep(INITIAL_SLEEP_TIME)
- elapsed = INITIAL_SLEEP_TIME
- status = 'running'
- image = ''
- while True:
- status, image = PeekTrybotImage(chromeos_root, buildbucket_id)
- if status == 'running':
- if elapsed > TIME_OUT:
+ """Find the buildbucket-id in the messages from `cros tryjob`.
+
+ Args:
+ msg: messages from `cros tryjob`
+
+ Returns:
+ buildbucket-id, which will be passed to `cros buildresult`
+ """
+ output_list = ast.literal_eval(msg)
+ output_dict = output_list[0]
+ if "buildbucket_id" in output_dict:
+ return output_dict["buildbucket_id"]
+ return None
+
+
+def SubmitTryjob(
+ chromeos_root,
+ buildbot_name,
+ patch_list,
+ tryjob_flags=None,
+ build_toolchain=False,
+):
+ """Calls `cros tryjob ...`
+
+ Args:
+ chromeos_root: the path to the ChromeOS root, needed for finding chromite
+ and launching the buildbot.
+ buildbot_name: the name of the buildbot queue, such as lumpy-release or
+ daisy-paladin.
+ patch_list: a python list of the patches, if any, for the buildbot to use.
+ tryjob_flags: See cros tryjob --help for available options.
+ build_toolchain: builds and uses the latest toolchain, rather than the
+ prebuilt one in SDK.
+
+ Returns:
+ buildbucket id
+ """
+ patch_arg = ""
+ if patch_list:
+ for p in patch_list:
+ patch_arg = patch_arg + " -g " + repr(p)
+ if not tryjob_flags:
+ tryjob_flags = []
+ if build_toolchain:
+ tryjob_flags.append("--latest-toolchain")
+ tryjob_flags = " ".join(tryjob_flags)
+
+ # Launch buildbot with appropriate flags.
+ build = buildbot_name
+ command = "cros_sdk -- cros tryjob --yes --json --nochromesdk %s %s %s" % (
+ tryjob_flags,
+ patch_arg,
+ build,
+ )
+ print("CMD: %s" % command)
+ _, out, _ = RunCommandInPath(chromeos_root, command)
+ buildbucket_id = ParseTryjobBuildbucketId(out)
+ print("buildbucket_id: %s" % repr(buildbucket_id))
+ if not buildbucket_id:
logger.GetLogger().LogFatal(
- 'Unable to get build result for target %s.' % buildbot_name)
- else:
- wait_msg = 'Unable to find build result; job may be running.'
- logger.GetLogger().LogOutput(wait_msg)
- logger.GetLogger().LogOutput('{0} minutes elapsed.'.format(elapsed / 60))
- logger.GetLogger().LogOutput('Sleeping {0} seconds.'.format(SLEEP_TIME))
- time.sleep(SLEEP_TIME)
- elapsed += SLEEP_TIME
+ "Error occurred while launching trybot job: " "%s" % command
+ )
+ return buildbucket_id
+
+
+def GetTrybotImage(
+ chromeos_root,
+ buildbot_name,
+ patch_list,
+ tryjob_flags=None,
+ build_toolchain=False,
+ asynchronous=False,
+):
+ """Launch buildbot and get resulting trybot artifact name.
+
+ This function launches a buildbot with the appropriate flags to
+ build the test ChromeOS image, with the current ToT mobile compiler. It
+ checks every 10 minutes to see if the trybot has finished. When the trybot
+ has finished, it parses the resulting report logs to find the trybot
+ artifact (if one was created), and returns that artifact name.
+
+ Args:
+ chromeos_root: the path to the ChromeOS root, needed for finding chromite
+ and launching the buildbot.
+ buildbot_name: the name of the buildbot queue, such as lumpy-release or
+ daisy-paladin.
+ patch_list: a python list of the patches, if any, for the buildbot to use.
+ tryjob_flags: See cros tryjob --help for available options.
+ build_toolchain: builds and uses the latest toolchain, rather than the
+ prebuilt one in SDK.
+ asynchronous: don't wait for artifacts; just return the buildbucket id
+
+ Returns:
+ (buildbucket id, partial image url) e.g.
+ (8952271933586980528, trybot-elm-release-tryjob/R67-10480.0.0-b2373596)
+ """
+ buildbucket_id = SubmitTryjob(
+ chromeos_root, buildbot_name, patch_list, tryjob_flags, build_toolchain
+ )
+ if asynchronous:
+ return buildbucket_id, " "
+
+ # The trybot generally takes more than 2 hours to finish.
+ # Wait two hours before polling the status.
+ time.sleep(INITIAL_SLEEP_TIME)
+ elapsed = INITIAL_SLEEP_TIME
+ status = "running"
+ image = ""
+ while True:
+ status, image = PeekTrybotImage(chromeos_root, buildbucket_id)
+ if status == "running":
+ if elapsed > TIME_OUT:
+ logger.GetLogger().LogFatal(
+ "Unable to get build result for target %s." % buildbot_name
+ )
+ else:
+ wait_msg = "Unable to find build result; job may be running."
+ logger.GetLogger().LogOutput(wait_msg)
+ logger.GetLogger().LogOutput(f"{elapsed / 60} minutes elapsed.")
+ logger.GetLogger().LogOutput(f"Sleeping {SLEEP_TIME} seconds.")
+ time.sleep(SLEEP_TIME)
+ elapsed += SLEEP_TIME
+ else:
+ break
+
+ if not buildbot_name.endswith("-toolchain") and status == "fail":
+ # For rotating testers, we don't care about their status
+ # result, because if any HWTest failed it will be non-zero.
+ #
+ # The nightly performance tests do not run HWTests, so if
+ # their status is non-zero, we do care. In this case
+ # non-zero means the image itself probably did not build.
+ image = ""
+
+ if not image:
+ logger.GetLogger().LogError(
+ "Trybot job (buildbucket id: %s) failed with"
+ "status %s; no trybot image generated. " % (buildbucket_id, status)
+ )
else:
- break
-
- if not buildbot_name.endswith('-toolchain') and status == 'fail':
- # For rotating testers, we don't care about their status
- # result, because if any HWTest failed it will be non-zero.
- #
- # The nightly performance tests do not run HWTests, so if
- # their status is non-zero, we do care. In this case
- # non-zero means the image itself probably did not build.
- image = ''
-
- if not image:
- logger.GetLogger().LogError('Trybot job (buildbucket id: %s) failed with'
- 'status %s; no trybot image generated. ' %
- (buildbucket_id, status))
- else:
- # Convert full gs path to what crosperf expects. For example, convert
- # gs://chromeos-image-archive/trybot-elm-release-tryjob/R67-10468.0.0-b20789
- # to
- # trybot-elm-release-tryjob/R67-10468.0.0-b20789
- image = '/'.join(image.split('/')[-2:])
-
- logger.GetLogger().LogOutput("image is '%s'" % image)
- logger.GetLogger().LogOutput('status is %s' % status)
- return buildbucket_id, image
+ # Convert full gs path to what crosperf expects. For example, convert
+ # gs://chromeos-image-archive/trybot-elm-release-tryjob/R67-10468.0.0-b20789
+ # to
+ # trybot-elm-release-tryjob/R67-10468.0.0-b20789
+ image = "/".join(image.split("/")[-2:])
+
+ logger.GetLogger().LogOutput("image is '%s'" % image)
+ logger.GetLogger().LogOutput("status is %s" % status)
+ return buildbucket_id, image
def DoesImageExist(chromeos_root, build):
- """Check if the image for the given build exists."""
+ """Check if the image for the given build exists."""
- ce = command_executer.GetCommandExecuter()
- command = ('gsutil ls gs://chromeos-image-archive/%s'
- '/chromiumos_test_image.tar.xz' % (build))
- ret = ce.ChrootRunCommand(chromeos_root, command, print_to_console=False)
- return not ret
+ ce = command_executer.GetCommandExecuter()
+ command = (
+ "gsutil ls gs://chromeos-image-archive/%s"
+ "/chromiumos_test_image.tar.xz" % (build)
+ )
+ ret = ce.ChrootRunCommand(chromeos_root, command, print_to_console=False)
+ return not ret
def WaitForImage(chromeos_root, build):
- """Wait for an image to be ready."""
+ """Wait for an image to be ready."""
- elapsed_time = 0
- while elapsed_time < TIME_OUT:
- if DoesImageExist(chromeos_root, build):
- return
- logger.GetLogger().LogOutput('Image %s not ready, waiting for 10 minutes' %
- build)
- time.sleep(SLEEP_TIME)
- elapsed_time += SLEEP_TIME
+ elapsed_time = 0
+ while elapsed_time < TIME_OUT:
+ if DoesImageExist(chromeos_root, build):
+ return
+ logger.GetLogger().LogOutput(
+ "Image %s not ready, waiting for 10 minutes" % build
+ )
+ time.sleep(SLEEP_TIME)
+ elapsed_time += SLEEP_TIME
- logger.GetLogger().LogOutput('Image %s not found, waited for %d hours' %
- (build, (TIME_OUT / 3600)))
- raise BuildbotTimeout('Timeout while waiting for image %s' % build)
+ logger.GetLogger().LogOutput(
+ "Image %s not found, waited for %d hours" % (build, (TIME_OUT / 3600))
+ )
+ raise BuildbotTimeout("Timeout while waiting for image %s" % build)
def GetLatestImage(chromeos_root, path):
- """Get latest image"""
-
- fmt = re.compile(r'R([0-9]+)-([0-9]+).([0-9]+).([0-9]+)')
-
- ce = command_executer.GetCommandExecuter()
- command = ('gsutil ls gs://chromeos-image-archive/%s' % path)
- ret, out, _ = ce.ChrootRunCommandWOutput(
- chromeos_root, command, print_to_console=False)
- if ret != 0:
- raise RuntimeError('Failed to list buckets with command: %s.' % command)
- candidates = [l.split('/')[-2] for l in out.split()]
- candidates = [fmt.match(c) for c in candidates]
- candidates = [[int(r) for r in m.group(1, 2, 3, 4)] for m in candidates if m]
- candidates.sort(reverse=True)
- for c in candidates:
- build = '%s/R%d-%d.%d.%d' % (path, c[0], c[1], c[2], c[3])
- # Denylist "R79-12384.0.0" image released by mistake.
- # TODO(crbug.com/992242): Remove the filter by 2019-09-05.
- if c == [79, 12384, 0, 0]:
- continue
-
- if DoesImageExist(chromeos_root, build):
- return build
+ """Get latest image"""
+
+ fmt = re.compile(r"R([0-9]+)-([0-9]+).([0-9]+).([0-9]+)")
+
+ ce = command_executer.GetCommandExecuter()
+ command = "gsutil ls gs://chromeos-image-archive/%s" % path
+ ret, out, _ = ce.ChrootRunCommandWOutput(
+ chromeos_root, command, print_to_console=False
+ )
+ if ret != 0:
+ raise RuntimeError("Failed to list buckets with command: %s." % command)
+ candidates = [l.split("/")[-2] for l in out.split()]
+ candidates = [fmt.match(c) for c in candidates]
+ candidates = [
+ [int(r) for r in m.group(1, 2, 3, 4)] for m in candidates if m
+ ]
+ candidates.sort(reverse=True)
+ for c in candidates:
+ build = "%s/R%d-%d.%d.%d" % (path, c[0], c[1], c[2], c[3])
+ if DoesImageExist(chromeos_root, build):
+ return build
def GetLatestRecipeImage(chromeos_root, path):
- """Get latest nightly test image from recipe bucket.
-
- Image location example:
- $ARCHIVE/lulu-llvm-next-nightly/R84-13037.0.0-31011-8883172717979984032
- """
-
- fmt = re.compile(r'R([0-9]+)-([0-9]+).([0-9]+).([0-9]+)-([0-9]+)')
-
- ce = command_executer.GetCommandExecuter()
- command = ('gsutil ls gs://chromeos-image-archive/%s' % path)
- ret, out, _ = ce.ChrootRunCommandWOutput(
- chromeos_root, command, print_to_console=False)
- if ret != 0:
- raise RuntimeError('Failed to list buckets with command: %s.' % command)
- candidates = [l.split('/')[-2] for l in out.split()]
- candidates = [(fmt.match(c), c) for c in candidates]
- candidates = [([int(r)
- for r in m[0].group(1, 2, 3, 4, 5)], m[1])
- for m in candidates
- if m]
- candidates.sort(key=lambda x: x[0], reverse=True)
- # Try to get ony last two days of images since nightly tests are run once
- # another day.
- for c in candidates[:2]:
- build = '%s/%s' % (path, c[1])
- if DoesImageExist(chromeos_root, build):
- return build
+ """Get latest nightly test image from recipe bucket.
+
+ Image location example:
+ $ARCHIVE/lulu-llvm-next-nightly/R84-13037.0.0-31011-8883172717979984032
+ """
+
+ fmt = re.compile(r"R([0-9]+)-([0-9]+).([0-9]+).([0-9]+)-([0-9]+)")
+
+ ce = command_executer.GetCommandExecuter()
+ command = "gsutil ls gs://chromeos-image-archive/%s" % path
+ ret, out, _ = ce.ChrootRunCommandWOutput(
+ chromeos_root, command, print_to_console=False
+ )
+ if ret != 0:
+ raise RuntimeError("Failed to list buckets with command: %s." % command)
+ candidates = [l.split("/")[-2] for l in out.split()]
+ candidates = [(fmt.match(c), c) for c in candidates]
+ candidates = [
+ ([int(r) for r in m[0].group(1, 2, 3, 4, 5)], m[1])
+ for m in candidates
+ if m
+ ]
+ candidates.sort(key=lambda x: x[0], reverse=True)
+ # Try to get ony last two days of images since nightly tests are run once
+ # another day.
+ for c in candidates[:2]:
+ build = "%s/%s" % (path, c[1])
+ if DoesImageExist(chromeos_root, build):
+ return build