diff options
Diffstat (limited to 'crosperf/download_images.py')
-rw-r--r-- | crosperf/download_images.py | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/crosperf/download_images.py b/crosperf/download_images.py new file mode 100644 index 00000000..8ceaa874 --- /dev/null +++ b/crosperf/download_images.py @@ -0,0 +1,286 @@ +# Copyright (c) 2014-2015 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. +"""Download images from Cloud Storage.""" + +from __future__ import print_function + +import ast +import os + +import test_flag + +from cros_utils import command_executer + +GS_UTIL = 'chromium/tools/depot_tools/gsutil.py' + + +class MissingImage(Exception): + """Raised when the requested image does not exist in gs://""" + + +class MissingFile(Exception): + """Raised when the requested file does not exist in gs://""" + + +class RunCommandExceptionHandler(object): + """Handle Exceptions from calls to RunCommand""" + + def __init__(self, logger_to_use, log_level, cmd_exec, command): + self.logger = logger_to_use + self.log_level = log_level + self.ce = cmd_exec + self.cleanup_command = command + + def HandleException(self, _, e): + # Exception handler, Run specified command + if self.log_level != 'verbose' and self.cleanup_command is not None: + self.logger.LogOutput('CMD: %s' % self.cleanup_command) + if self.cleanup_command is not None: + _ = self.ce.RunCommand(self.cleanup_command) + # Raise exception again + raise e + + +class ImageDownloader(object): + """Download images from Cloud Storage.""" + + def __init__(self, logger_to_use=None, log_level='verbose', cmd_exec=None): + self._logger = logger_to_use + self.log_level = log_level + self._ce = cmd_exec or command_executer.GetCommandExecuter( + self._logger, log_level=self.log_level) + + def GetBuildID(self, chromeos_root, xbuddy_label): + # Get the translation of the xbuddy_label into the real Google Storage + # image name. + command = ('cd ~/trunk/src/third_party/toolchain-utils/crosperf; ' + "python translate_xbuddy.py '%s'" % xbuddy_label) + _, build_id_tuple_str, _ = self._ce.ChrootRunCommandWOutput(chromeos_root, + command) + if not build_id_tuple_str: + raise MissingImage("Unable to find image for '%s'" % xbuddy_label) + + build_id_tuple = ast.literal_eval(build_id_tuple_str) + build_id = build_id_tuple[0] + + return build_id + + def DownloadImage(self, chromeos_root, build_id, image_name): + if self.log_level == 'average': + self._logger.LogOutput('Preparing to download %s image to local ' + 'directory.' % build_id) + + # Make sure the directory for downloading the image exists. + download_path = os.path.join(chromeos_root, 'chroot/tmp', build_id) + image_path = os.path.join(download_path, 'chromiumos_test_image.bin') + if not os.path.exists(download_path): + os.makedirs(download_path) + + # Check to see if the image has already been downloaded. If not, + # download the image. + if not os.path.exists(image_path): + gsutil_cmd = os.path.join(chromeos_root, GS_UTIL) + command = '%s cp %s %s' % (gsutil_cmd, image_name, download_path) + + if self.log_level != 'verbose': + self._logger.LogOutput('CMD: %s' % command) + status = self._ce.RunCommand(command) + downloaded_image_name = os.path.join(download_path, + 'chromiumos_test_image.tar.xz') + if status != 0 or not os.path.exists(downloaded_image_name): + raise MissingImage('Cannot download image: %s.' % downloaded_image_name) + + return image_path + + def UncompressImage(self, chromeos_root, build_id): + # Check to see if the file has already been uncompresssed, etc. + if os.path.exists( + os.path.join(chromeos_root, 'chroot/tmp', build_id, + 'chromiumos_test_image.bin')): + return + + # Uncompress and untar the downloaded image. + download_path = os.path.join(chromeos_root, 'chroot/tmp', build_id) + command = ('cd %s ; tar -Jxf chromiumos_test_image.tar.xz ' % download_path) + # Cleanup command for exception handler + clean_cmd = ('cd %s ; rm -f chromiumos_test_image.bin ' % download_path) + exception_handler = RunCommandExceptionHandler(self._logger, self.log_level, + self._ce, clean_cmd) + if self.log_level != 'verbose': + self._logger.LogOutput('CMD: %s' % command) + print('(Uncompressing and un-tarring may take a couple of minutes...' + 'please be patient.)') + retval = self._ce.RunCommand( + command, except_handler=exception_handler.HandleException) + if retval != 0: + if self.log_level != 'verbose': + self._logger.LogOutput('CMD: %s' % clean_cmd) + print('(Removing file chromiumos_test_image.bin.)') + # Remove partially uncompressed file + _ = self._ce.RunCommand(clean_cmd) + # Raise exception for failure to uncompress + raise MissingImage('Cannot uncompress image: %s.' % build_id) + + # Remove compressed image + command = ('cd %s ; rm -f chromiumos_test_image.tar.xz; ' % download_path) + if self.log_level != 'verbose': + self._logger.LogOutput('CMD: %s' % command) + print('(Removing file chromiumos_test_image.tar.xz.)') + # try removing file, its ok to have an error, print if encountered + retval = self._ce.RunCommand(command) + if retval != 0: + print('(Warning: Could not remove file chromiumos_test_image.tar.xz .)') + + def DownloadSingleAutotestFile(self, chromeos_root, build_id, + package_file_name): + # Verify if package files exist + status = 0 + gs_package_name = ('gs://chromeos-image-archive/%s/%s' % + (build_id, package_file_name)) + gsutil_cmd = os.path.join(chromeos_root, GS_UTIL) + if not test_flag.GetTestMode(): + cmd = '%s ls %s' % (gsutil_cmd, gs_package_name) + status = self._ce.RunCommand(cmd) + if status != 0: + raise MissingFile('Cannot find autotest package file: %s.' % + package_file_name) + + if self.log_level == 'average': + self._logger.LogOutput('Preparing to download %s package to local ' + 'directory.' % package_file_name) + + # Make sure the directory for downloading the package exists. + download_path = os.path.join(chromeos_root, 'chroot/tmp', build_id) + package_path = os.path.join(download_path, package_file_name) + if not os.path.exists(download_path): + os.makedirs(download_path) + + # Check to see if the package file has already been downloaded. If not, + # download it. + if not os.path.exists(package_path): + command = '%s cp %s %s' % (gsutil_cmd, gs_package_name, download_path) + + if self.log_level != 'verbose': + self._logger.LogOutput('CMD: %s' % command) + status = self._ce.RunCommand(command) + if status != 0 or not os.path.exists(package_path): + raise MissingFile('Cannot download package: %s .' % package_path) + + def UncompressSingleAutotestFile(self, chromeos_root, build_id, + package_file_name, uncompress_cmd): + # Uncompress file + download_path = os.path.join(chromeos_root, 'chroot/tmp', build_id) + command = ('cd %s ; %s %s' % + (download_path, uncompress_cmd, package_file_name)) + + if self.log_level != 'verbose': + self._logger.LogOutput('CMD: %s' % command) + print('(Uncompressing autotest file %s .)' % package_file_name) + retval = self._ce.RunCommand(command) + if retval != 0: + raise MissingFile('Cannot uncompress file: %s.' % package_file_name) + # Remove uncompressed downloaded file + command = ('cd %s ; rm -f %s' % (download_path, package_file_name)) + if self.log_level != 'verbose': + self._logger.LogOutput('CMD: %s' % command) + print('(Removing processed autotest file %s .)' % package_file_name) + # try removing file, its ok to have an error, print if encountered + retval = self._ce.RunCommand(command) + if retval != 0: + print('(Warning: Could not remove file %s .)' % package_file_name) + + def VerifyAutotestFilesExist(self, chromeos_root, build_id, package_file): + # Quickly verify if the files are there + status = 0 + gs_package_name = ('gs://chromeos-image-archive/%s/%s' % + (build_id, package_file)) + gsutil_cmd = os.path.join(chromeos_root, GS_UTIL) + if not test_flag.GetTestMode(): + cmd = '%s ls %s' % (gsutil_cmd, gs_package_name) + if self.log_level != 'verbose': + self._logger.LogOutput('CMD: %s' % cmd) + status = self._ce.RunCommand(cmd) + if status != 0: + print('(Warning: Could not find file %s )' % gs_package_name) + return 1 + # Package exists on server + return 0 + + def DownloadAutotestFiles(self, chromeos_root, build_id): + # Download autest package files (3 files) + autotest_packages_name = ('autotest_packages.tar') + autotest_server_package_name = ('autotest_server_package.tar.bz2') + autotest_control_files_name = ('control_files.tar') + + download_path = os.path.join(chromeos_root, 'chroot/tmp', build_id) + # Autotest directory relative path wrt chroot + autotest_rel_path = os.path.join('/tmp', build_id, 'autotest_files') + # Absolute Path to download files + autotest_path = os.path.join(chromeos_root, 'chroot/tmp', build_id, + 'autotest_files') + + if not os.path.exists(autotest_path): + # Quickly verify if the files are present on server + # If not, just exit with warning + status = self.VerifyAutotestFilesExist(chromeos_root, build_id, + autotest_packages_name) + if status != 0: + default_autotest_dir = '~/trunk/src/third_party/autotest/files' + print('(Warning: Could not find autotest packages .)\n' + '(Warning: Defaulting autotest path to %s .' % + default_autotest_dir) + return default_autotest_dir + + # Files exist on server, download and uncompress them + self.DownloadSingleAutotestFile(chromeos_root, build_id, + autotest_packages_name) + self.DownloadSingleAutotestFile(chromeos_root, build_id, + autotest_server_package_name) + self.DownloadSingleAutotestFile(chromeos_root, build_id, + autotest_control_files_name) + + self.UncompressSingleAutotestFile(chromeos_root, build_id, + autotest_packages_name, 'tar -xvf ') + self.UncompressSingleAutotestFile(chromeos_root, build_id, + autotest_server_package_name, + 'tar -jxvf ') + self.UncompressSingleAutotestFile(chromeos_root, build_id, + autotest_control_files_name, + 'tar -xvf ') + # Rename created autotest directory to autotest_files + command = ('cd %s ; mv autotest autotest_files' % download_path) + if self.log_level != 'verbose': + self._logger.LogOutput('CMD: %s' % command) + print('(Moving downloaded autotest files to autotest_files)') + retval = self._ce.RunCommand(command) + if retval != 0: + raise MissingFile('Could not create directory autotest_files') + + return autotest_rel_path + + def Run(self, chromeos_root, xbuddy_label, autotest_path): + build_id = self.GetBuildID(chromeos_root, xbuddy_label) + image_name = ('gs://chromeos-image-archive/%s/chromiumos_test_image.tar.xz' + % build_id) + + # Verify that image exists for build_id, before attempting to + # download it. + status = 0 + if not test_flag.GetTestMode(): + gsutil_cmd = os.path.join(chromeos_root, GS_UTIL) + cmd = '%s ls %s' % (gsutil_cmd, image_name) + status = self._ce.RunCommand(cmd) + if status != 0: + raise MissingImage('Cannot find official image: %s.' % image_name) + + image_path = self.DownloadImage(chromeos_root, build_id, image_name) + self.UncompressImage(chromeos_root, build_id) + + if self.log_level != 'quiet': + self._logger.LogOutput('Using image from %s.' % image_path) + + if autotest_path == '': + autotest_path = self.DownloadAutotestFiles(chromeos_root, build_id) + + return image_path, autotest_path |