Implement downloading artifacts from Android builds.
BUG=chromium:512668
TEST=local run
download credential file from Cloud console
start devserver:
./devserver.py --static_dir=/usr/local/google/home/dshi/images \
--log=/tmp/devserver.log --port 8082
-a "/usr/local/google2/chromiumos/src/platform/dev/android_build_cred.json"
test download:
success:
curl http://127.0.0.1:8082/stage?target=shamu-userdebug\&build_id=2040953\&artifacts=test_zip\&branch=git_mnc-release
fail:
curl http://127.0.0.1:8082/stage?target=shamu-userdebug\&build_id=2040953\&artifacts=test_zip\&branch=none
cros flash a test device
Change-Id: I967d80ed3013f6085ae6d7e56e34b0f9dd9af10e
Reviewed-on: https://chromium-review.googlesource.com/304664
Commit-Ready: Dan Shi <dshi@chromium.org>
Tested-by: Dan Shi <dshi@chromium.org>
Reviewed-by: Simran Basi <sbasi@chromium.org>
diff --git a/downloader.py b/downloader.py
index 554ce33..3bd0d03 100755
--- a/downloader.py
+++ b/downloader.py
@@ -21,6 +21,15 @@
import gsutil_util
import log_util
+try:
+ import android_build
+except ImportError as e:
+ # Ignore android_build import failure. This is to support devserver running
+ # inside a ChromeOS device triggered by cros flash. Most ChromeOS test images
+ # do not have google-api-python-client module and they don't need to support
+ # Android updating, therefore, ignore the import failure here.
+ android_build = None
+
class DownloaderException(Exception):
"""Exception that aggregates all exceptions raised during async download.
@@ -51,7 +60,7 @@
"""Downloader of images to the devsever.
This is the base class for different types of downloaders, including
- GoogleStorageDownloader, LocalDownloader and LaunchControlDownloader.
+ GoogleStorageDownloader, LocalDownloader and AndroidBuildDownloader.
Given a URL to a build on the archive server:
- Caches that build and the given artifacts onto the devserver.
@@ -388,24 +397,27 @@
return self.source_path
-class LaunchControlDownloader(Downloader):
- """Downloader of images to the devserver from launch control."""
+class AndroidBuildDownloader(Downloader):
+ """Downloader of images to the devserver from Android's build server."""
- def __init__(self, static_dir, build_id, target):
- """Initialize LaunchControlDownloader.
+ def __init__(self, static_dir, branch, build_id, target):
+ """Initialize AndroidBuildDownloader.
Args:
static_dir: Root directory to store the build.
+ branch: Branch for the build. Download will always verify if the given
+ build id is for the branch.
build_id: Build id of the Android build, e.g., 2155602.
target: Target of the Android build, e.g., shamu-userdebug.
"""
- build = '%s/%s' % (target, build_id)
+ build = '%s/%s/%s' % (branch, target, build_id)
build_dir = os.path.join(static_dir, '', build)
+ self.branch = branch
self.build_id = build_id
self.target = target
- super(LaunchControlDownloader, self).__init__(static_dir, build_dir, build)
+ super(AndroidBuildDownloader, self).__init__(static_dir, build_dir, build)
def Wait(self, name, is_regex_name, timeout):
"""Verifies the local artifact exists and returns the appropriate names.
@@ -421,12 +433,31 @@
Raises:
ArtifactDownloadError: An error occurred when obtaining artifact.
"""
- raise NotImplementedError()
+ artifacts = android_build.BuildAccessor.GetArtifacts(
+ branch=self.branch, build_id=self.build_id, target=self.target)
+
+ names = []
+ for artifact_name in [a['name'] for a in artifacts]:
+ match = (re.match(name, artifact_name) if is_regex_name
+ else name == artifact_name)
+ if match:
+ names.append(artifact_name)
+
+ if not names:
+ raise build_artifact.ArtifactDownloadError(
+ 'No artifact found with given name: %s for %s-%s' %
+ (name, self.target, self.build_id))
+
+ return names
def Fetch(self, remote_name, local_path):
- """Downloads artifact from LaunchControl to a local directory."""
- install_path = os.path.join(local_path, remote_name)
- return install_path
+ """Downloads artifact from Android's build server to a local directory."""
+ dest_file = os.path.join(local_path, remote_name)
+ android_build.BuildAccessor.Download(
+ branch=self.branch, build_id=self.build_id, target=self.target,
+ resource_id=remote_name, dest_file=dest_file)
+ return dest_file
def DescribeSource(self):
- raise NotImplementedError()
+ return '%s/%s/%s/%s' % (android_build.DEFAULT_BUILDER, self.branch,
+ self.target, self.build_id)