Index: tools/skp/webpages_playback.py |
diff --git a/tools/skp/webpages_playback.py b/tools/skp/webpages_playback.py |
index d9635b6960fedf08b37d7ebf5c75aa642d04d891..a3bff696da3c7d1bd3f8ad099f561d9543d8f115 100644 |
--- a/tools/skp/webpages_playback.py |
+++ b/tools/skp/webpages_playback.py |
@@ -8,16 +8,17 @@ |
To archive webpages and store SKP files (archives should be rarely updated): |
cd skia |
-python tools/skp/webpages_playback.py --dest_gsbase=gs://rmistry --record \ |
+python tools/skp/webpages_playback.py --data_store=gs://rmistry --record \ |
--page_sets=all --skia_tools=/home/default/trunk/out/Debug/ \ |
--browser_executable=/tmp/chromium/out/Release/chrome |
+The above command uses Google Storage bucket 'rmistry' to download needed files. |
To replay archived webpages and re-generate SKP files (should be run whenever |
SkPicture.PICTURE_VERSION changes): |
cd skia |
-python tools/skp/webpages_playback.py --dest_gsbase=gs://rmistry \ |
+python tools/skp/webpages_playback.py --data_store=gs://rmistry \ |
--page_sets=all --skia_tools=/home/default/trunk/out/Debug/ \ |
--browser_executable=/tmp/chromium/out/Release/chrome |
@@ -32,8 +33,15 @@ The --browser_executable flag should point to the browser binary you want to use |
to capture archives and/or capture SKP files. Majority of the time it should be |
a newly built chrome binary. |
-The --upload_to_gs flag controls whether generated artifacts will be uploaded |
-to Google Storage (default value is False if not specified). |
+The --data_store flag controls where the needed artifacts, such as |
+credential files, are downloaded from. It also controls where the |
+generated artifacts, such as recorded webpages and resulting skp renderings, |
+are uploaded to. URLs with scheme 'gs://' use Google Storage. Otherwise |
+use local filesystem. |
+ |
+The --upload=True flag means generated artifacts will be |
+uploaded or copied to the location specified by --data_store. (default value is |
+False if not specified). |
The --non-interactive flag controls whether the script will prompt the user |
(default value is False if not specified). |
@@ -123,13 +131,16 @@ class SkPicturePlayback(object): |
self._all_page_sets_specified = parse_options.page_sets == 'all' |
self._page_sets = self._ParsePageSets(parse_options.page_sets) |
- self._dest_gsbase = parse_options.dest_gsbase |
self._record = parse_options.record |
self._skia_tools = parse_options.skia_tools |
self._non_interactive = parse_options.non_interactive |
- self._upload_to_gs = parse_options.upload_to_gs |
+ self._upload = parse_options.upload |
+ data_store_location = parse_options.data_store |
+ if data_store_location.startswith(gs_utils.GS_PREFIX): |
+ self.gs = GoogleStorageDataStore(data_store_location) |
+ else: |
+ self.gs = LocalFileSystemDataStore(data_store_location) |
self._alternate_upload_dir = parse_options.alternate_upload_dir |
- self._skip_all_gs_access = parse_options.skip_all_gs_access |
self._telemetry_binaries_dir = os.path.join(parse_options.chrome_src_path, |
'tools', 'perf') |
@@ -164,8 +175,13 @@ class SkPicturePlayback(object): |
"""Run the SkPicturePlayback BuildStep.""" |
# Download the credentials file if it was not previously downloaded. |
- if self._skip_all_gs_access: |
- print """\n\nPlease create a %s file that contains: |
+ if not os.path.isfile(CREDENTIALS_FILE_PATH): |
+ # Download the credentials.json file from Google Storage. |
+ self.gs.download_file(CREDENTIALS_GS_PATH, CREDENTIALS_FILE_PATH) |
+ |
+ if not os.path.isfile(CREDENTIALS_FILE_PATH): |
+ print """\n\nCould not locate credentials file in the storage. |
+ Please create a %s file that contains: |
{ |
"google": { |
"username": "google_testing_account_username", |
@@ -177,11 +193,6 @@ class SkPicturePlayback(object): |
} |
}\n\n""" % CREDENTIALS_FILE_PATH |
raw_input("Please press a key when you are ready to proceed...") |
- elif not os.path.isfile(CREDENTIALS_FILE_PATH): |
- # Download the credentials.json file from Google Storage. |
- gs_bucket = remove_prefix(self._dest_gsbase.lstrip(), gs_utils.GS_PREFIX) |
- gs_utils.GSUtils().download_file(gs_bucket, CREDENTIALS_GS_PATH, |
- CREDENTIALS_FILE_PATH) |
# Delete any left over data files in the data directory. |
for archive_file in glob.glob( |
@@ -244,9 +255,8 @@ class SkPicturePlayback(object): |
raise Exception('record_wpr failed for page_set: %s' % page_set) |
else: |
- if not self._skip_all_gs_access: |
- # Get the webpages archive so that it can be replayed. |
- self._DownloadWebpagesArchive(wpr_data_file, page_set_json_name) |
+ # Get the webpages archive so that it can be replayed. |
+ self._DownloadWebpagesArchive(wpr_data_file, page_set_json_name) |
run_benchmark_cmd = ( |
'PYTHONPATH=%s:$PYTHONPATH' % page_set_dir, |
@@ -314,24 +324,24 @@ class SkPicturePlayback(object): |
print '\n\n' |
- if not self._skip_all_gs_access and self._upload_to_gs: |
- print '\n\n=======Uploading to Google Storage=======\n\n' |
+ if self._upload: |
+ print '\n\n=======Uploading to %s=======\n\n' % self.gs.target_type() |
# Copy the directory structure in the root directory into Google Storage. |
dest_dir_name = ROOT_PLAYBACK_DIR_NAME |
if self._alternate_upload_dir: |
dest_dir_name = self._alternate_upload_dir |
- gs_bucket = remove_prefix(self._dest_gsbase.lstrip(), gs_utils.GS_PREFIX) |
- gs_utils.GSUtils().upload_dir_contents( |
- LOCAL_PLAYBACK_ROOT_DIR, gs_bucket, dest_dir_name, |
+ self.gs.upload_dir_contents( |
+ LOCAL_PLAYBACK_ROOT_DIR, dest_dir_name, |
upload_if=gs_utils.GSUtils.UploadIf.IF_MODIFIED, |
predefined_acl=GS_PREDEFINED_ACL, |
fine_grained_acl_list=GS_FINE_GRAINED_ACL_LIST) |
print '\n\n=======New SKPs have been uploaded to %s =======\n\n' % ( |
- posixpath.join(self._dest_gsbase, dest_dir_name, SKPICTURES_DIR_NAME)) |
+ posixpath.join(self.gs.target_name(), dest_dir_name, |
+ SKPICTURES_DIR_NAME)) |
else: |
- print '\n\n=======Not Uploading to Google Storage=======\n\n' |
+ print '\n\n=======Not Uploading to %s=======\n\n' % self.gs.target_type() |
print 'Generated resources are available in %s\n\n' % ( |
LOCAL_PLAYBACK_ROOT_DIR) |
@@ -383,20 +393,73 @@ class SkPicturePlayback(object): |
page_set_source = posixpath.join(ROOT_PLAYBACK_DIR_NAME, |
'webpages_archive', |
page_set_json_name) |
- gs = gs_utils.GSUtils() |
- gs_bucket = remove_prefix(self._dest_gsbase.lstrip(), gs_utils.GS_PREFIX) |
- if (gs.does_storage_object_exist(gs_bucket, wpr_source) and |
- gs.does_storage_object_exist(gs_bucket, page_set_source)): |
- gs.download_file(gs_bucket, wpr_source, |
+ gs = self.gs |
+ if (gs.does_storage_object_exist(wpr_source) and |
+ gs.does_storage_object_exist(page_set_source)): |
+ gs.download_file(wpr_source, |
os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, |
wpr_data_file)) |
- gs.download_file(gs_bucket, page_set_source, |
+ gs.download_file(page_set_source, |
os.path.join(LOCAL_REPLAY_WEBPAGES_ARCHIVE_DIR, |
page_set_json_name)) |
else: |
- raise Exception('%s and %s do not exist in Google Storage!' % ( |
- wpr_source, page_set_source)) |
- |
+ raise Exception('%s and %s do not exist in %s!' % (gs.target_type(), |
+ wpr_source, page_set_source)) |
+ |
+class DataStore: |
+ """An abstract base class for uploading recordings to a data storage. |
+ The interface emulates the google storage api.""" |
+ def target_name(self): |
+ raise NotImplementedError() |
+ def target_type(self): |
+ raise NotImplementedError() |
+ def does_storage_object_exist(self, *args): |
+ raise NotImplementedError() |
+ def download_file(self, *args): |
+ raise NotImplementedError() |
+ def upload_dir_contents(self, source_dir, **kwargs): |
+ raise NotImplementedError() |
+ |
+class GoogleStorageDataStore(DataStore): |
+ def __init__(self, data_store_url): |
+ self._data_store_url = data_store_url |
+ self._bucket = remove_prefix(self._data_store_url.lstrip(), |
+ gs_utils.GS_PREFIX) |
+ self.gs = gs_utils.GSUtils() |
+ def target_name(self): |
+ return self._data_store_url |
+ def target_type(self): |
+ return 'Google Storage' |
+ def does_storage_object_exist(self, *args): |
+ return self.gs.does_storage_object_exist(self._bucket, *args) |
+ def download_file(self, *args): |
+ self.gs.download_file(self._bucket, *args) |
+ def upload_dir_contents(self, source_dir, **kwargs): |
+ self.gs.upload_dir_contents(source_dir, self._bucket, **kwargs) |
+ |
+class LocalFileSystemDataStore(DataStore): |
+ def __init__(self, data_store_location): |
+ self._base_dir = data_store_location |
+ def target_name(self): |
+ return self._base_dir |
+ def target_type(self): |
+ return self._base_dir |
+ def does_storage_object_exist(self, name, *args): |
+ return os.path.isfile(os.path.join(self._base_dir, name)) |
+ def download_file(self, name, local_path, *args): |
+ shutil.copyfile(os.path.join(self._base_dir, name), local_path) |
+ def upload_dir_contents(self, source_dir, dest_dir, **kwargs): |
+ def copytree(source_dir, dest_dir): |
+ if not os.path.exists(dest_dir): |
+ os.makedirs(dest_dir) |
+ for item in os.listdir(source_dir): |
+ source = os.path.join(source_dir, item) |
+ dest = os.path.join(dest_dir, item) |
+ if os.path.isdir(source): |
+ copytree(source, dest) |
+ else: |
+ shutil.copy2(source, dest) |
+ copytree(source_dir, os.path.join(self._base_dir, dest_dir)) |
if '__main__' == __name__: |
option_parser = optparse.OptionParser() |
@@ -405,21 +468,10 @@ if '__main__' == __name__: |
help='Specifies the page sets to use to archive. Supports globs.', |
default='all') |
option_parser.add_option( |
- '', '--skip_all_gs_access', action='store_true', |
- help='All Google Storage interactions will be skipped if this flag is ' |
- 'specified. This is useful for cases where the user does not have ' |
- 'the required .boto file but would like to generate webpage ' |
- 'archives and SKPs from the Skia page sets.', |
- default=False) |
- option_parser.add_option( |
'', '--record', action='store_true', |
help='Specifies whether a new website archive should be created.', |
default=False) |
option_parser.add_option( |
- '', '--dest_gsbase', |
- help='gs:// bucket_name, the bucket to upload the file to.', |
- default='gs://chromium-skia-gm') |
- option_parser.add_option( |
'', '--skia_tools', |
help=('Path to compiled Skia executable tools. ' |
'render_pictures/render_pdfs is run on the set ' |
@@ -429,17 +481,25 @@ if '__main__' == __name__: |
'than Release builds.'), |
default=None) |
option_parser.add_option( |
- '', '--upload_to_gs', action='store_true', |
- help='Does not upload to Google Storage if this is False.', |
+ '', '--upload', action='store_true', |
+ help=('Uploads to Google Storage or copies to local filesystem storage ' |
+ ' if this is True.'), |
default=False) |
option_parser.add_option( |
+ '', '--data_store', |
+ help=('The location of the file storage to use to download and upload ' |
+ 'files. Can be \'gs://<bucket>\' for Google Storage, or ' |
+ 'a directory for local filesystem storage'), |
+ default='gs://chromium-skia-gm') |
+ option_parser.add_option( |
'', '--alternate_upload_dir', |
- help='Uploads to a different directory in Google Storage if this flag is ' |
- 'specified', |
+ help= ('Uploads to a different directory in Google Storage or local ' |
+ 'storage if this flag is specified'), |
default=None) |
option_parser.add_option( |
'', '--output_dir', |
- help='Directory where SKPs and webpage archives will be outputted to.', |
+ help=('Temporary directory where SKPs and webpage archives will be ' |
+ 'outputted to.'), |
default=tempfile.gettempdir()) |
option_parser.add_option( |
'', '--browser_executable', |