webpages_playback.py: Support storing to local directories

Make webpages_playback support storing to local directories as an
alternative to Google Storage.

Rename argument --dest_gsbase to --data_store=<location>. Make this parameter
accept either gs:// url or directory for local file system storage.

Rename argument --upload_to_gs to --upload.

Implement file existence check, download and upload for the file
operation.
NOTREECHECKS=true
NOTRY=true

Review URL: https://codereview.chromium.org/737123005
This commit is contained in:
kkinnunen 2015-03-31 00:18:26 -07:00 committed by Commit bot
parent 005b84ec1c
commit b4ee7ea834
2 changed files with 109 additions and 49 deletions

View File

@ -57,7 +57,7 @@ def main(chrome_src_path, browser_executable):
'--page_sets', 'all',
'--browser_executable', browser_executable,
'--non-interactive',
'--upload_to_gs',
'--upload',
'--alternate_upload_dir', upload_dir,
'--chrome_src_path', chrome_src_path,
]

View File

@ -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()
@ -404,21 +467,10 @@ if '__main__' == __name__:
'', '--page_sets',
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. '
@ -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',