| Index: infra/scripts/legacy/scripts/slave/slave_utils.py
|
| diff --git a/infra/scripts/legacy/scripts/slave/slave_utils.py b/infra/scripts/legacy/scripts/slave/slave_utils.py
|
| index 98435e16479e9b916c4e1a0e159b8689251151ef..76cf4e37b3ebef7028890c6e97477d71e9232eb6 100644
|
| --- a/infra/scripts/legacy/scripts/slave/slave_utils.py
|
| +++ b/infra/scripts/legacy/scripts/slave/slave_utils.py
|
| @@ -15,179 +15,12 @@ import tempfile
|
| import time
|
|
|
| from common import chromium_utils
|
| -from slave.bootstrap import ImportMasterConfigs # pylint: disable=W0611
|
| -from common.chromium_utils import GetActiveMaster # pylint: disable=W0611
|
|
|
| # These codes used to distinguish true errors from script warnings.
|
| ERROR_EXIT_CODE = 1
|
| WARNING_EXIT_CODE = 88
|
|
|
|
|
| -# Local errors.
|
| -class PageHeapError(Exception):
|
| - pass
|
| -
|
| -
|
| -# Cache the path to gflags.exe.
|
| -_gflags_exe = None
|
| -
|
| -
|
| -def SubversionExe():
|
| - # TODO(pamg): move this into platform_utils to support Mac and Linux.
|
| - if chromium_utils.IsWindows():
|
| - return 'svn.bat' # Find it in the user's path.
|
| - elif chromium_utils.IsLinux() or chromium_utils.IsMac():
|
| - return 'svn' # Find it in the user's path.
|
| - else:
|
| - raise NotImplementedError(
|
| - 'Platform "%s" is not currently supported.' % sys.platform)
|
| -
|
| -
|
| -def GitExe():
|
| - return 'git.bat' if chromium_utils.IsWindows() else 'git'
|
| -
|
| -
|
| -def SubversionCat(wc_dir):
|
| - """Output the content of specified files or URLs in SVN.
|
| - """
|
| - try:
|
| - return chromium_utils.GetCommandOutput([SubversionExe(), 'cat',
|
| - wc_dir])
|
| - except chromium_utils.ExternalError:
|
| - return None
|
| -
|
| -
|
| -class NotGitWorkingCopy(Exception): pass
|
| -class NotSVNWorkingCopy(Exception): pass
|
| -class NotAnyWorkingCopy(Exception): pass
|
| -class InvalidSVNRevision(Exception): pass
|
| -
|
| -
|
| -def ScrapeSVNInfoRevision(wc_dir, regexp):
|
| - """Runs 'svn info' on a working copy and applies the supplied regex and
|
| - returns the matched group as an int.
|
| - regexp can be either a compiled regex or a string regex.
|
| - throws NotSVNWorkingCopy if wc_dir is not in a working copy.
|
| - throws InvalidSVNRevision if matched group is not alphanumeric.
|
| - """
|
| - if isinstance(regexp, (str, unicode)):
|
| - regexp = re.compile(regexp)
|
| - retval, svn_info = chromium_utils.GetStatusOutput([SubversionExe(), 'info',
|
| - wc_dir])
|
| - if retval or 'is not a working copy' in svn_info:
|
| - raise NotSVNWorkingCopy(wc_dir)
|
| - match = regexp.search(svn_info)
|
| - if not match or not match.groups():
|
| - raise InvalidSVNRevision(
|
| - '%s did not match in svn info %s.' % (regexp.pattern, svn_info))
|
| - text = match.group(1)
|
| - if text.isalnum():
|
| - return int(text)
|
| - else:
|
| - raise InvalidSVNRevision(text)
|
| -
|
| -
|
| -def SubversionRevision(wc_dir):
|
| - """Finds the last svn revision of a working copy and returns it as an int."""
|
| - return ScrapeSVNInfoRevision(wc_dir, r'(?s).*Revision: (\d+).*')
|
| -
|
| -
|
| -def SubversionLastChangedRevision(wc_dir_or_file):
|
| - """Finds the last changed svn revision of a fs path returns it as an int."""
|
| - return ScrapeSVNInfoRevision(wc_dir_or_file,
|
| - r'(?s).*Last Changed Rev: (\d+).*')
|
| -
|
| -
|
| -def GitHash(wc_dir):
|
| - """Finds the current commit hash of the wc_dir."""
|
| - retval, text = chromium_utils.GetStatusOutput(
|
| - [GitExe(), 'rev-parse', 'HEAD'], cwd=wc_dir)
|
| - if retval or 'fatal: Not a git repository' in text:
|
| - raise NotGitWorkingCopy(wc_dir)
|
| - return text.strip()
|
| -
|
| -
|
| -def GetHashOrRevision(wc_dir):
|
| - """Gets the svn revision or git hash of wc_dir as a string. Throws
|
| - NotAnyWorkingCopy if neither are appropriate."""
|
| - try:
|
| - return str(SubversionRevision(wc_dir))
|
| - except NotSVNWorkingCopy:
|
| - pass
|
| - try:
|
| - return GitHash(wc_dir)
|
| - except NotGitWorkingCopy:
|
| - pass
|
| - raise NotAnyWorkingCopy(wc_dir)
|
| -
|
| -
|
| -def GitOrSubversion(wc_dir):
|
| - """Returns the VCS for the given directory.
|
| -
|
| - Returns:
|
| - 'svn' if the directory is a valid svn repo
|
| - 'git' if the directory is a valid git repo root
|
| - None otherwise
|
| - """
|
| - ret, out = chromium_utils.GetStatusOutput([SubversionExe(), 'info', wc_dir])
|
| - if not ret and 'is not a working copy' not in out:
|
| - return 'svn'
|
| -
|
| - ret, out = chromium_utils.GetStatusOutput(
|
| - [GitExe(), 'rev-parse', '--is-inside-work-tree'], cwd=wc_dir)
|
| - if not ret and 'fatal: Not a git repository' not in out:
|
| - return 'git'
|
| -
|
| - return None
|
| -
|
| -
|
| -def GetBuildRevisions(src_dir, webkit_dir=None, revision_dir=None):
|
| - """Parses build revisions out of the provided directories.
|
| -
|
| - Args:
|
| - src_dir: The source directory to be used to check the revision in.
|
| - webkit_dir: Optional WebKit directory, relative to src_dir.
|
| - revision_dir: If provided, this dir will be used for the build revision
|
| - instead of the mandatory src_dir.
|
| -
|
| - Returns a tuple of the build revision and (optional) WebKit revision.
|
| - NOTICE: These revisions are strings, since they can be both Subversion numbers
|
| - and Git hashes.
|
| - """
|
| - abs_src_dir = os.path.abspath(src_dir)
|
| - webkit_revision = None
|
| - if webkit_dir:
|
| - webkit_dir = os.path.join(abs_src_dir, webkit_dir)
|
| - webkit_revision = GetHashOrRevision(webkit_dir)
|
| -
|
| - if revision_dir:
|
| - revision_dir = os.path.join(abs_src_dir, revision_dir)
|
| - build_revision = GetHashOrRevision(revision_dir)
|
| - else:
|
| - build_revision = GetHashOrRevision(src_dir)
|
| - return (build_revision, webkit_revision)
|
| -
|
| -
|
| -def GetZipFileNames(build_properties, build_revision, webkit_revision=None,
|
| - extract=False, use_try_buildnumber=True):
|
| - base_name = 'full-build-%s' % chromium_utils.PlatformName()
|
| -
|
| - if 'try' in build_properties.get('mastername', '') and use_try_buildnumber:
|
| - if extract:
|
| - if not build_properties.get('parent_buildnumber'):
|
| - raise Exception('build_props does not have parent data: %s' %
|
| - build_properties)
|
| - version_suffix = '_%(parent_buildnumber)s' % build_properties
|
| - else:
|
| - version_suffix = '_%(buildnumber)s' % build_properties
|
| - elif webkit_revision:
|
| - version_suffix = '_wk%s_%s' % (webkit_revision, build_revision)
|
| - else:
|
| - version_suffix = '_%s' % build_revision
|
| -
|
| - return base_name, version_suffix
|
| -
|
| -
|
| def SlaveBuildName(chrome_dir):
|
| """Extracts the build name of this slave (e.g., 'chrome-release') from the
|
| leaf subdir of its build directory.
|
| @@ -221,96 +54,6 @@ def SlaveBaseDir(chrome_dir):
|
| return result
|
|
|
|
|
| -def GetStagingDir(start_dir):
|
| - """Creates a chrome_staging dir in the starting directory. and returns its
|
| - full path.
|
| - """
|
| - start_dir = os.path.abspath(start_dir)
|
| - staging_dir = os.path.join(SlaveBaseDir(start_dir), 'chrome_staging')
|
| - chromium_utils.MaybeMakeDirectory(staging_dir)
|
| - return staging_dir
|
| -
|
| -
|
| -def SetPageHeap(chrome_dir, exe, enable):
|
| - """Enables or disables page-heap checking in the given executable, depending
|
| - on the 'enable' parameter. gflags_exe should be the full path to gflags.exe.
|
| - """
|
| - global _gflags_exe
|
| - if _gflags_exe is None:
|
| - _gflags_exe = chromium_utils.FindUpward(chrome_dir,
|
| - 'tools', 'memory', 'gflags.exe')
|
| - command = [_gflags_exe]
|
| - if enable:
|
| - command.extend(['/p', '/enable', exe, '/full'])
|
| - else:
|
| - command.extend(['/p', '/disable', exe])
|
| - result = chromium_utils.RunCommand(command)
|
| - if result:
|
| - description = {True: 'enable', False: 'disable'}
|
| - raise PageHeapError('Unable to %s page heap for %s.' %
|
| - (description[enable], exe))
|
| -
|
| -
|
| -def LongSleep(secs):
|
| - """A sleep utility for long durations that avoids appearing hung.
|
| -
|
| - Sleeps for the specified duration. Prints output periodically so as not to
|
| - look hung in order to avoid being timed out. Since this function is meant
|
| - for long durations, it assumes that the caller does not care about losing a
|
| - small amount of precision.
|
| -
|
| - Args:
|
| - secs: The time to sleep, in seconds.
|
| - """
|
| - secs_per_iteration = 60
|
| - time_slept = 0
|
| -
|
| - # Make sure we are dealing with an integral duration, since this function is
|
| - # meant for long-lived sleeps we don't mind losing floating point precision.
|
| - secs = int(round(secs))
|
| -
|
| - remainder = secs % secs_per_iteration
|
| - if remainder > 0:
|
| - time.sleep(remainder)
|
| - time_slept += remainder
|
| - sys.stdout.write('.')
|
| - sys.stdout.flush()
|
| -
|
| - while time_slept < secs:
|
| - time.sleep(secs_per_iteration)
|
| - time_slept += secs_per_iteration
|
| - sys.stdout.write('.')
|
| - sys.stdout.flush()
|
| -
|
| - sys.stdout.write('\n')
|
| -
|
| -
|
| -def RunPythonCommandInBuildDir(build_dir, target, command_line_args,
|
| - server_dir=None, filter_obj=None):
|
| - if sys.platform == 'win32':
|
| - python_exe = 'python.exe'
|
| - else:
|
| - os.environ['PYTHONPATH'] = (chromium_utils.FindUpward(build_dir, 'tools',
|
| - 'python')
|
| - + ':' +os.environ.get('PYTHONPATH', ''))
|
| - python_exe = 'python'
|
| -
|
| - command = [python_exe] + command_line_args
|
| - return chromium_utils.RunCommand(command, filter_obj=filter_obj)
|
| -
|
| -
|
| -class RunCommandCaptureFilter(object):
|
| - lines = []
|
| -
|
| - def FilterLine(self, in_line):
|
| - self.lines.append(in_line)
|
| - return None
|
| -
|
| - def FilterDone(self, last_bits):
|
| - self.lines.append(last_bits)
|
| - return None
|
| -
|
| -
|
| def GypFlagIsOn(options, flag):
|
| value = GetGypFlag(options, flag, False)
|
| # The values we understand as Off are False and a text zero.
|
| @@ -329,220 +72,6 @@ def GetGypFlag(options, flag, default=None):
|
| return gypflags[flag]
|
|
|
|
|
| -def GSUtilSetup():
|
| - # Get the path to the gsutil script.
|
| - gsutil = os.path.join(os.path.dirname(__file__), 'gsutil')
|
| - gsutil = os.path.normpath(gsutil)
|
| - if chromium_utils.IsWindows():
|
| - gsutil += '.bat'
|
| -
|
| - # Get the path to the boto file containing the password.
|
| - boto_file = os.path.join(os.path.dirname(__file__), '..', '..', 'site_config',
|
| - '.boto')
|
| -
|
| - # Make sure gsutil uses this boto file if it exists.
|
| - if os.path.exists(boto_file):
|
| - os.environ['AWS_CREDENTIAL_FILE'] = boto_file
|
| - os.environ['BOTO_CONFIG'] = boto_file
|
| - return gsutil
|
| -
|
| -
|
| -def GSUtilGetMetadataField(name, provider_prefix=None):
|
| - """Returns: (str) the metadata field to use with Google Storage
|
| -
|
| - The Google Storage specification for metadata can be found at:
|
| - https://developers.google.com/storage/docs/gsutil/addlhelp/WorkingWithObjectMetadata
|
| - """
|
| - # Already contains custom provider prefix
|
| - if name.lower().startswith('x-'):
|
| - return name
|
| -
|
| - # See if it's innately supported by Google Storage
|
| - if name in (
|
| - 'Cache-Control',
|
| - 'Content-Disposition',
|
| - 'Content-Encoding',
|
| - 'Content-Language',
|
| - 'Content-MD5',
|
| - 'Content-Type',
|
| - ):
|
| - return name
|
| -
|
| - # Add provider prefix
|
| - if not provider_prefix:
|
| - provider_prefix = 'x-goog-meta'
|
| - return '%s-%s' % (provider_prefix, name)
|
| -
|
| -
|
| -def GSUtilCopy(source, dest, mimetype=None, gs_acl=None, cache_control=None,
|
| - metadata=None):
|
| - """Copy a file to Google Storage.
|
| -
|
| - Runs the following command:
|
| - gsutil -h Content-Type:<mimetype> \
|
| - -h Cache-Control:<cache_control> \
|
| - cp -a <gs_acl> file://<filename> <gs_base>/<subdir>/<filename w/o path>
|
| -
|
| - Args:
|
| - source: the source URI
|
| - dest: the destination URI
|
| - mimetype: optional value to add as a Content-Type header
|
| - gs_acl: optional value to add as a canned-acl
|
| - cache_control: optional value to set Cache-Control header
|
| - metadata: (dict) A dictionary of string key/value metadata entries to set
|
| - (see `gsutil cp' '-h' option)
|
| - Returns:
|
| - The status code returned from running the generated gsutil command.
|
| - """
|
| -
|
| - if not source.startswith('gs://') and not source.startswith('file://'):
|
| - source = 'file://' + source
|
| - if not dest.startswith('gs://') and not dest.startswith('file://'):
|
| - dest = 'file://' + dest
|
| - gsutil = GSUtilSetup()
|
| - # Run the gsutil command. gsutil internally calls command_wrapper, which
|
| - # will try to run the command 10 times if it fails.
|
| - command = [gsutil]
|
| -
|
| - if not metadata:
|
| - metadata = {}
|
| - if mimetype:
|
| - metadata['Content-Type'] = mimetype
|
| - if cache_control:
|
| - metadata['Cache-Control'] = cache_control
|
| - for k, v in sorted(metadata.iteritems(), key=lambda (k, _): k):
|
| - field = GSUtilGetMetadataField(k)
|
| - param = (field) if v is None else ('%s:%s' % (field, v))
|
| - command += ['-h', param]
|
| - command.extend(['cp'])
|
| - if gs_acl:
|
| - command.extend(['-a', gs_acl])
|
| - command.extend([source, dest])
|
| - return chromium_utils.RunCommand(command)
|
| -
|
| -
|
| -def GSUtilCopyFile(filename, gs_base, subdir=None, mimetype=None, gs_acl=None,
|
| - cache_control=None, metadata=None):
|
| - """Copy a file to Google Storage.
|
| -
|
| - Runs the following command:
|
| - gsutil -h Content-Type:<mimetype> \
|
| - -h Cache-Control:<cache_control> \
|
| - cp -a <gs_acl> file://<filename> <gs_base>/<subdir>/<filename w/o path>
|
| -
|
| - Args:
|
| - filename: the file to upload
|
| - gs_base: the bucket to upload the file to
|
| - subdir: optional subdirectory withing the bucket
|
| - mimetype: optional value to add as a Content-Type header
|
| - gs_acl: optional value to add as a canned-acl
|
| - Returns:
|
| - The status code returned from running the generated gsutil command.
|
| - """
|
| -
|
| - source = 'file://' + filename
|
| - dest = gs_base
|
| - if subdir:
|
| - # HACK(nsylvain): We can't use normpath here because it will break the
|
| - # slashes on Windows.
|
| - if subdir == '..':
|
| - dest = os.path.dirname(gs_base)
|
| - else:
|
| - dest = '/'.join([gs_base, subdir])
|
| - dest = '/'.join([dest, os.path.basename(filename)])
|
| - return GSUtilCopy(source, dest, mimetype, gs_acl, cache_control,
|
| - metadata=metadata)
|
| -
|
| -
|
| -def GSUtilCopyDir(src_dir, gs_base, dest_dir=None, gs_acl=None,
|
| - cache_control=None):
|
| - """Upload the directory and its contents to Google Storage."""
|
| -
|
| - if os.path.isfile(src_dir):
|
| - assert os.path.isdir(src_dir), '%s must be a directory' % src_dir
|
| -
|
| - gsutil = GSUtilSetup()
|
| - command = [gsutil, '-m']
|
| - if cache_control:
|
| - command.extend(['-h', 'Cache-Control:%s' % cache_control])
|
| - command.extend(['cp', '-R'])
|
| - if gs_acl:
|
| - command.extend(['-a', gs_acl])
|
| - if dest_dir:
|
| - command.extend([src_dir, gs_base + '/' + dest_dir])
|
| - else:
|
| - command.extend([src_dir, gs_base])
|
| - return chromium_utils.RunCommand(command)
|
| -
|
| -def GSUtilDownloadFile(src, dst):
|
| - """Copy a file from Google Storage."""
|
| - gsutil = GSUtilSetup()
|
| -
|
| - # Run the gsutil command. gsutil internally calls command_wrapper, which
|
| - # will try to run the command 10 times if it fails.
|
| - command = [gsutil]
|
| - command.extend(['cp', src, dst])
|
| - return chromium_utils.RunCommand(command)
|
| -
|
| -
|
| -def GSUtilMoveFile(source, dest, gs_acl=None):
|
| - """Move a file on Google Storage."""
|
| -
|
| - gsutil = GSUtilSetup()
|
| -
|
| - # Run the gsutil command. gsutil internally calls command_wrapper, which
|
| - # will try to run the command 10 times if it fails.
|
| - command = [gsutil]
|
| - command.extend(['mv', source, dest])
|
| - status = chromium_utils.RunCommand(command)
|
| -
|
| - if status:
|
| - return status
|
| -
|
| - if gs_acl:
|
| - command = [gsutil]
|
| - command.extend(['setacl', gs_acl, dest])
|
| - status = chromium_utils.RunCommand(command)
|
| -
|
| - return status
|
| -
|
| -
|
| -def GSUtilDeleteFile(filename):
|
| - """Delete a file on Google Storage."""
|
| -
|
| - gsutil = GSUtilSetup()
|
| -
|
| - # Run the gsutil command. gsutil internally calls command_wrapper, which
|
| - # will try to run the command 10 times if it fails.
|
| - command = [gsutil]
|
| - command.extend(['rm', filename])
|
| - return chromium_utils.RunCommand(command)
|
| -
|
| -
|
| -# Python doesn't support the type of variable scope in nested methods needed
|
| -# to avoid the global output variable. This variable should only ever be used
|
| -# by GSUtilListBucket.
|
| -command_output = ''
|
| -
|
| -
|
| -def GSUtilListBucket(gs_base, args):
|
| - """List the contents of a Google Storage bucket."""
|
| -
|
| - gsutil = GSUtilSetup()
|
| -
|
| - # Run the gsutil command. gsutil internally calls command_wrapper, which
|
| - # will try to run the command 10 times if it fails.
|
| - global command_output
|
| - command_output = ''
|
| -
|
| - def GatherOutput(line):
|
| - global command_output
|
| - command_output += line + '\n'
|
| - command = [gsutil, 'ls'] + args + [gs_base]
|
| - status = chromium_utils.RunCommand(command, parser_func=GatherOutput)
|
| - return (status, command_output)
|
| -
|
| -
|
| def LogAndRemoveFiles(temp_dir, regex_pattern):
|
| """Removes files in |temp_dir| that match |regex_pattern|.
|
| This function prints out the name of each directory or filename before
|
| @@ -706,30 +235,3 @@ def WriteLogLines(logname, lines, perf=None):
|
| print '@@@STEP_LOG_END_PERF@%s@%s@@@' % (logname, perf)
|
| else:
|
| print '@@@STEP_LOG_END@%s@@@' % logname
|
| -
|
| -
|
| -def ZipAndUpload(bucket, archive, *targets):
|
| - """Uploads a zipped archive to the specified Google Storage bucket.
|
| -
|
| - Args:
|
| - bucket: Google Storage bucket to upload to.
|
| - archive: Name of the .zip archive.
|
| - *targets: List of targets that should be included in the archive.
|
| -
|
| - Returns:
|
| - Path to the uploaded archive on Google Storage.
|
| - """
|
| - local_archive = os.path.join(tempfile.mkdtemp(archive), archive)
|
| - zip_cmd = [
|
| - 'zip',
|
| - '-9',
|
| - '--filesync',
|
| - '--recurse-paths',
|
| - '--symlinks',
|
| - local_archive,
|
| - ]
|
| - zip_cmd.extend(targets)
|
| -
|
| - chromium_utils.RunCommand(zip_cmd)
|
| - GSUtilCopy(local_archive, 'gs://%s/%s' % (bucket, archive))
|
| - return 'https://storage.cloud.google.com/%s/%s' % (bucket, archive)
|
|
|