devserver: Add functionality to stage artifacts from a local directory.
This change updates the devserver so that local build and
test artifacts can be staged onto the devserver.
The devserver stage function will now also accept a local_path
as an argument. local_path specifies a subdirectory of the
devserver's static directory that contains build artifacts we
want to stage. It's restricted to a subdirectory of the static
directory in order to not allow callers access to the whole
file system of the devserver.
This functionality will be used in supporting custom image
staging for the new 'cros stage-on-moblab' command.
BUG=chromium:370909
TEST=devserver_integration_test, unittests, & local moblab test run.
Change-Id: I617a61066e644657cdbfddee9762691c495d26b5
Reviewed-on: https://chromium-review.googlesource.com/239321
Reviewed-by: Simran Basi <sbasi@chromium.org>
Tested-by: Simran Basi <sbasi@chromium.org>
Commit-Queue: Simran Basi <sbasi@chromium.org>
diff --git a/devserver.py b/devserver.py
index c398c9e..16e895e 100755
--- a/devserver.py
+++ b/devserver.py
@@ -446,6 +446,22 @@
else:
raise DevServerError("Must specify an archive_url in the request")
+ @staticmethod
+ def _canonicalize_local_path(local_path):
+ """Canonicalizes |local_path| strings.
+
+ Raises:
+ DevserverError: if |local_path| is not set.
+ """
+ # Restrict staging of local content to only files within the static
+ # directory.
+ local_path = os.path.abspath(local_path)
+ if not local_path.startswith(updater.static_dir):
+ raise DevServerError('Local path %s must be a subdirectory of the static'
+ ' directory: %s' % (local_path, updater.static_dir))
+
+ return local_path.rstrip('/')
+
@cherrypy.expose
def is_staged(self, **kwargs):
"""Check if artifacts have been downloaded.
@@ -511,6 +527,7 @@
Args:
archive_url: Google Storage URL for the build.
+ local_path: Local path for the build.
async: True to return without waiting for download to complete.
artifacts: Comma separated list of named artifacts to download.
These are defined in artifact_info and have their implementation
@@ -542,14 +559,26 @@
http://devserver_url:<port>/static/x86-mario-release/R26-3920.0.0
"""
- archive_url = self._canonicalize_archive_url(kwargs.get('archive_url'))
+ archive_url = kwargs.get('archive_url')
+ local_path = kwargs.get('local_path')
+ if not archive_url and not local_path:
+ raise DevServerError('Requires archive_url or local_path to be '
+ 'specified.')
+ if archive_url and local_path:
+ raise DevServerError('archive_url and local_path can not both be '
+ 'specified.')
+ if archive_url:
+ archive_url = self._canonicalize_archive_url(archive_url)
+ if local_path:
+ local_path = self._canonicalize_local_path(local_path)
async = kwargs.get('async', False)
artifacts, files = self._get_artifacts(kwargs)
with DevServerRoot._staging_thread_count_lock:
DevServerRoot._staging_thread_count += 1
try:
- downloader.Downloader(updater.static_dir, archive_url).Download(
- artifacts, files, async=async)
+ downloader.Downloader(
+ updater.static_dir, (archive_url or local_path)).Download(
+ artifacts, files, async=async)
finally:
with DevServerRoot._staging_thread_count_lock:
DevServerRoot._staging_thread_count -= 1