def _GetImagePath(self): """Returns the image path to use.""" image_path = translated_path = None if os.path.isfile(self.image): if not self.yes and not _IsFilePathGPTDiskImage(self.image): # TODO(wnwen): Open the tarball and if there is just one file in it, # use that instead. Existing code in upload_symbols.py. if cros_build_lib.BooleanPrompt( prolog= 'The given image file is not a valid disk image. Perhaps ' 'you forgot to untar it.', prompt='Terminate the current flash process?'): raise FlashError('Update terminated by user.') image_path = self.image elif os.path.isdir(self.image): # Ask user which image (*.bin) in the folder to use. image_path = _ChooseImageFromDirectory(self.image) else: # Translate the xbuddy path to get the exact image to use. translated_path, _ = ds_wrapper.GetImagePathWithXbuddy( self.image, self.board, static_dir=DEVSERVER_STATIC_DIR) image_path = ds_wrapper.TranslatedPathToLocalPath( translated_path, DEVSERVER_STATIC_DIR) logging.info('Using image %s', translated_path or image_path) return image_path
def _ConfirmDeploy(num_updates): """Returns whether we can continue deployment.""" if num_updates > _MAX_UPDATES_NUM: logging.warning(_MAX_UPDATES_WARNING) return cros_build_lib.BooleanPrompt(default=False) return True
def main(argv): parser = GetParser() opts = parser.parse_args(argv) opts.Freeze() force_keysets = set(['%s-%s' % (TEST_KEYSET_PREFIX, x) for x in opts.test_sign]) # If we aren't using mock or test or dry run mode, then let's prompt the user # to make sure they actually want to do this. It's rare that people want to # run this directly and hit the release bucket. if not (opts.mock or force_keysets or opts.dry_run) and not opts.yes: prolog = '\n'.join(textwrap.wrap(textwrap.dedent( 'Uploading images for signing to the *release* bucket is not something ' 'you generally should be doing yourself.'), 80)).strip() if not cros_build_lib.BooleanPrompt( prompt='Are you sure you want to sign these images', default=False, prolog=prolog): cros_build_lib.Die('better safe than sorry') PushImage(opts.image_dir, opts.board, versionrev=opts.version, profile=opts.profile, priority=opts.priority, sign_types=opts.sign_types, dry_run=opts.dry_run, mock=opts.mock, force_keysets=force_keysets, force_channels=opts.channels, buildroot=opts.buildroot)
def _DisableRootfsVerification(self): if not self.options.force: logging.error( 'Detected that the device has rootfs verification enabled.') logging.info( 'This script can automatically remove the rootfs ' 'verification, which requires that it reboot the device.') logging.info('Make sure the device is in developer mode!') logging.info('Skip this prompt by specifying --force.') if not cros_build_lib.BooleanPrompt('Remove rootfs verification?', False): return False logging.info('Removing rootfs verification from %s', self.options.to) # Running in VM's cause make_dev_ssd's firmware sanity checks to fail. # Use --force to bypass the checks. cmd = ('/usr/share/vboot/bin/make_dev_ssd.sh --partitions %d ' '--remove_rootfs_verification --force') for partition in (KERNEL_A_PARTITION, KERNEL_B_PARTITION): self.device.RunCommand(cmd % partition, error_code_ok=True) self._Reboot() # Now that the machine has been rebooted, we need to kill Chrome again. self._KillProcsIfNeeded() # Make sure the rootfs is writable now. self._MountRootfsAsWritable(error_code_ok=False) return True
def _CheckOptions(options): """Vet the options.""" me = os.environ['USER'] if not options.email and not os.path.exists(options.cred_file): options.email = me oper.Notice('Assuming your chromium email is %[email protected].' ' Override with --email.' % options.email) if not options.team and not options.owner: oper.Notice('Without --owner or --team filters this will run for all' ' packages in the spreadsheet (same as --team=all).') if not cros_build_lib.BooleanPrompt( 'Are you sure you want to run for all packages?', False): sys.exit(0) if options.team and options.team == 'all': options.team = None if options.owner and options.owner == 'all': options.owner = None if options.owner and options.owner == 'me': options.owner = me oper.Notice('Using %r for owner filter (from $USER envvar)' % options.owner) if options.test_ss and not options.pretend: oper.Notice('Running in --pretend mode because of --test-spreadsheet') options.pretend = True
def _HandleCreate(self, checkout): """Sync to the version or file and create a branch. Args: checkout: The CrosCheckout to run commands in. """ # Start with quick, immediate validations. if self.options.name and self.options.descriptor: raise BranchError('--descriptor cannot be used with --custom.') if self.options.version and not self.options.version.endswith('0'): raise BranchError( 'Cannot branch version from nonzero patch number.') # Handle sync. Unfortunately, we cannot fully validate the version until # we have a copy of chromeos_version.sh. if self.options.file: checkout.SyncFile(self.options.file) else: checkout.SyncVersion(self.options.version) # Now to validate the version. First, double check that the checkout # has a zero patch number in case we synced from file. vinfo = checkout.ReadVersion() if int(vinfo.patch_number): raise BranchError( 'Cannot branch version with nonzero patch number.') # Second, check that we did not already branch from this version. # manifest-internal serves as the sentinel project. manifest_internal = checkout.manifest.GetUniqueProject( 'chromeos/manifest-internal') pattern = '.*-%s\\.B$' % '\\.'.join( str(comp) for comp in vinfo.VersionComponents() if comp) if (checkout.BranchExists(manifest_internal, pattern) and not self.options.force): raise BranchError( 'Already branched %s. Please rerun with --force if you wish to ' 'proceed.' % vinfo.VersionString()) # Determine if we are creating a custom branch or a standard branch. if self.options.cls: branch = self.options.cls(checkout, self.options.descriptor) else: branch = Branch(checkout, self.options.name) # Finally, double check the name with the user. proceed = self.options.yes or cros_build_lib.BooleanPrompt( prompt='New branch will be named %s. Continue?' % branch.name, default=False) if proceed: branch.Create(push=self.options.push, force=self.options.force) logging.notice('Successfully created branch %s.', branch.name) else: logging.notice('Aborted branch creation.')
def _CheckBoard(self): """Check that the Chrome build is targeted for the device board.""" if self.options.board == self.device.board: return logging.warning('Device board is %s whereas target board is %s.', self.device.board, self.options.board) if self.options.force: return if not cros_build_lib.BooleanPrompt('Continue despite board mismatch?', False): raise DeployFailure('Aborted.')
def main(argv): parser = commandline.ArgumentParser(description=__doc__) # The type of image_dir will strip off trailing slashes (makes later # processing simpler and the display prettier). parser.add_argument('image_dir', default=None, type='local_or_gs_path', help='full path of source artifacts to upload') parser.add_argument('--board', default=None, required=True, help='board to generate symbols for') parser.add_argument('--profile', default=None, help='board profile in use (e.g. "asan")') parser.add_argument('--version', default=None, help='version info (normally extracted from image_dir)') parser.add_argument('-n', '--dry-run', default=False, action='store_true', help='show what would be done, but do not upload') parser.add_argument('-M', '--mock', default=False, action='store_true', help='upload things to a testing bucket (dev testing)') parser.add_argument('--test-sign', default=[], action='append', choices=TEST_KEYSETS, help='mung signing behavior to sign w/ test keys') parser.add_argument('--priority', type=int, default=50, help='set signing priority (lower == higher prio)') parser.add_argument('--sign-types', default=None, nargs='+', choices=_SUPPORTED_IMAGE_TYPES, help='only sign specified image types') parser.add_argument('--yes', action='store_true', default=False, help='answer yes to all prompts') opts = parser.parse_args(argv) opts.Freeze() force_keysets = set(['%s-%s' % (TEST_KEYSET_PREFIX, x) for x in opts.test_sign]) # If we aren't using mock or test or dry run mode, then let's prompt the user # to make sure they actually want to do this. It's rare that people want to # run this directly and hit the release bucket. if not (opts.mock or force_keysets or opts.dry_run) and not opts.yes: prolog = '\n'.join(textwrap.wrap(textwrap.dedent( 'Uploading images for signing to the *release* bucket is not something ' 'you generally should be doing yourself.'), 80)).strip() if not cros_build_lib.BooleanPrompt( prompt='Are you sure you want to sign these images', default=False, prolog=prolog): cros_build_lib.Die('better safe than sorry') PushImage(opts.image_dir, opts.board, versionrev=opts.version, profile=opts.profile, priority=opts.priority, sign_types=opts.sign_types, dry_run=opts.dry_run, mock=opts.mock, force_keysets=force_keysets)
def _CheckRestoreStateful(self): """Check whether to restore stateful.""" restore_stateful = False if not self._CanRunDevserver() and self._do_rootfs_update: msg = ('Cannot start devserver! The stateful partition may be ' 'corrupted.') prompt = 'Attempt to restore the stateful partition?' restore_stateful = self._yes or cros_build_lib.BooleanPrompt( prompt=prompt, default=False, prolog=msg) if not restore_stateful: raise ChromiumOSUpdateError( 'Cannot continue to perform rootfs update!') return restore_stateful
def UploadComponent(component_dir, gsbucket): """Upload a component. Args: component_dir: (str) location for generated component. gsbucket: (str) gs bucket to upload. """ logger.info('upload %s to %s', component_dir, gsbucket) ctx = gs.GSContext() if cros_build_lib.BooleanPrompt( prompt='Are you sure you want to upload component to official gs bucket', default=False, prolog='Once component is uploaded, it can not be modified again.'): # Upload component to gs. ctx.Copy(component_dir, gsbucket, recursive=True)
def main(argv): """Main function.""" parser = _CreateOptParser() (options, _args) = parser.parse_args(argv) oper.verbose = options.verbose _CheckOptions(options) ss_key = ups.TEST_SS_KEY if options.test_ss else ups.REAL_SS_KEY # Prepare credentials for Docs and Tracker access. creds = PrepareCreds(options.cred_file, options.token_file, options.email) scomm = gdata_lib.SpreadsheetComm() scomm.Connect(creds, ss_key, PKGS_WS_NAME, source='Sync Package Status') tcomm = gdata_lib.TrackerComm() tcomm.Connect(creds, PROJECT_NAME, source='Sync Package Status') oper.Notice('Syncing between Tracker and spreadsheet %s' % ss_key) syncer = Syncer(tcomm, scomm, pretend=options.pretend, verbose=options.verbose) if options.team: syncer.SetTeamFilter(options.team) if options.owner: syncer.SetOwnerFilter(options.owner) if options.default_owner: syncer.SetDefaultOwner(options.default_owner) try: syncer.Sync() except SyncError as ex: oper.Die(str(ex)) # If --email, which is only effective when run interactively (because the # password must be entered), give the option of saving to a creds file for # next time. if options.email and options.cred_file: prompt = ('Do you want to save credentials for next time to %r?' % options.cred_file) if cros_build_lib.BooleanPrompt(prompt, False): creds.StoreCreds(options.cred_file) oper.Notice('Be sure to save the creds file to the same location' ' outside your chroot so it will also be used with' ' future chroots.')
def testBooleanPrompt(self): self.mox.StubOutWithMock(cros_build_lib, 'GetInput') for value in ('', '', 'yes', 'ye', 'y', 'no', 'n'): cros_build_lib.GetInput(mox.IgnoreArg()).AndReturn(value) self.mox.ReplayAll() self.assertTrue(cros_build_lib.BooleanPrompt()) self.assertFalse(cros_build_lib.BooleanPrompt(default=False)) self.assertTrue(cros_build_lib.BooleanPrompt()) self.assertTrue(cros_build_lib.BooleanPrompt()) self.assertTrue(cros_build_lib.BooleanPrompt()) self.assertFalse(cros_build_lib.BooleanPrompt()) self.assertFalse(cros_build_lib.BooleanPrompt()) self.mox.VerifyAll()
def Evaluate(self, unused_remote, build_label, unused_repeat=1): """Prompts user if the build is good or bad. Args: unused_remote: Unused args. build_label: Build label used for part of report filename and log message. unused_repeat: Unused args. Returns: Score([1.0]) if it is a good build. Otherwise, Score([0.0]). """ report_path = self.GetReportPath(build_label) prompt = 'Is %s a good build on the DUT?' % build_label is_good = cros_build_lib.BooleanPrompt(prompt=prompt) score = 1.0 if is_good else 0.0 osutils.WriteFile(report_path, '%d' % score) return common.Score([score])
def CreateBuildrootIfNeeded(buildroot): """Create the buildroot is it doesn't exist with confirmation prompt. Args: buildroot: The buildroot path to create as a string. Returns: boolean: Does the buildroot now exist? """ if os.path.exists(buildroot): return True prompt = 'Create %s as buildroot' % buildroot if not cros_build_lib.BooleanPrompt(prompt=prompt, default=False): print('Please specify a different buildroot via the --buildroot option.') return False os.makedirs(buildroot) return True
def testBooleanPrompt(self): """Verify BooleanPrompt() full behavior.""" m = self.PatchObject(cros_build_lib, 'GetInput') m.return_value = '' self.assertTrue(cros_build_lib.BooleanPrompt()) self.assertFalse(cros_build_lib.BooleanPrompt(default=False)) m.return_value = 'yes' self.assertTrue(cros_build_lib.BooleanPrompt()) m.return_value = 'ye' self.assertTrue(cros_build_lib.BooleanPrompt()) m.return_value = 'y' self.assertTrue(cros_build_lib.BooleanPrompt()) m.return_value = 'no' self.assertFalse(cros_build_lib.BooleanPrompt()) m.return_value = 'n' self.assertFalse(cros_build_lib.BooleanPrompt())
def CheckRestoreStateful(self): """Check whether to restore stateful.""" logging.debug('Checking whether to restore stateful...') restore_stateful = False try: self._CheckNebraskaCanRun() return restore_stateful except nebraska_wrapper.NebraskaStartupError as e: if self._do_rootfs_update: msg = ('Cannot start nebraska! The stateful partition may be ' 'corrupted: %s' % e) prompt = 'Attempt to restore the stateful partition?' restore_stateful = self._yes or cros_build_lib.BooleanPrompt( prompt=prompt, default=False, prolog=msg) if not restore_stateful: raise ChromiumOSUpdateError( 'Cannot continue to perform rootfs update!') logging.debug('Restore stateful partition is%s required.', ('' if restore_stateful else ' not')) return restore_stateful
def _UserConfirmKeyChange(self): """Asks the user whether it's OK that a host key has changed. A changed key can be fairly common during Chrome OS development, so instead of outright rejecting a modified key like SSH does, this provides some common reasons a key may have changed to help the user decide whether it was legitimate or not. _StartSsh() must have been called before this function so that |self.device| is valid. Returns: True if the user is OK with a changed host key. """ return cros_build_lib.BooleanPrompt( prolog='The host ID for "%s" has changed since last connect.\n' 'Some common reasons for this are:\n' ' - Device powerwash.\n' ' - Device flash from a USB stick.\n' ' - Device flash using "--clobber-stateful".\n' 'Otherwise, please verify that this is the correct device' ' before continuing.' % self.device.hostname)
def Run(self): """Image the removable device.""" devices = self.ListAllRemovableDevices() if self.device: # If user specified a device path, check if it exists. if not os.path.exists(self.device): raise FlashError('Device path %s does not exist.' % self.device) # Then check if it is removable. if self.device not in [self.DeviceNameToPath(x) for x in devices]: msg = '%s is not a removable device.' % self.device if not (self.yes or cros_build_lib.BooleanPrompt(default=False, prolog=msg)): raise FlashError( 'You can specify usb:// to choose from a list of ' 'removable devices.') target = None if self.device: # Get device name from path (e.g. sdc in /dev/sdc). target = self.device.rsplit(os.path.sep, 1)[-1] elif devices: # Ask user to choose from the list. target = self.ChooseRemovableDevice(devices) else: raise FlashError('No removable devices detected.') image_path = self._GetImagePath() try: device = self.DeviceNameToPath(target) if self.install: self.InstallImageToDevice(image_path, device) else: self.CopyImageToDevice(image_path, device) except cros_build_lib.RunCommandError: logging.error('Failed copying image to device %s', self.DeviceNameToPath(target))
def _DisableRootfsVerification(self): if not self.options.force: logging.error( 'Detected that the device has rootfs verification enabled.') logging.info( 'This script can automatically remove the rootfs ' 'verification, which requires that it reboot the device.') logging.info('Make sure the device is in developer mode!') logging.info('Skip this prompt by specifying --force.') if not cros_build_lib.BooleanPrompt('Remove roots verification?', False): # Since we stopped Chrome earlier, it's good form to start it up again. if self.options.startui: logging.info('Starting Chrome...') self.device.RunCommand('start ui') raise DeployFailure('Need rootfs verification to be disabled. ' 'Aborting.') logging.info('Removing rootfs verification from %s', self.options.to) # Running in VM's cause make_dev_ssd's firmware sanity checks to fail. # Use --force to bypass the checks. cmd = ('/usr/share/vboot/bin/make_dev_ssd.sh --partitions %d ' '--remove_rootfs_verification --force') for partition in (KERNEL_A_PARTITION, KERNEL_B_PARTITION): self.device.RunCommand(cmd % partition, error_code_ok=True) # A reboot in developer mode takes a while (and has delays), so the user # will have time to read and act on the USB boot instructions below. logging.info( 'Please remember to press Ctrl-U if you are booting from USB.') self.device.Reboot() # Now that the machine has been rebooted, we need to kill Chrome again. self._KillProcsIfNeeded() # Make sure the rootfs is writable now. self._MountRootfsAsWritable(error_code_ok=False)
def VerifyOptions(options, site_config): """Verify that our command line options make sense. Args: options: Parsed cros tryjob tryjob arguments. site_config: config_lib.SiteConfig containing all config info. """ # Handle --list before checking that everything else is valid. if options.list: PrintKnownConfigs(site_config, options.production, options.build_configs) raise cros_build_lib.DieSystemExit(0) # Exit with success code. # Validate specified build_configs. if not options.build_configs: cros_build_lib.Die('At least one build_config is required.') on_branch = options.branch != 'master' if not (options.yes or on_branch): unknown_build_configs = [b for b in options.build_configs if b not in site_config] if unknown_build_configs: prompt = ('Unknown build configs; are you sure you want to schedule ' 'for %s?' % ', '.join(unknown_build_configs)) if not cros_build_lib.BooleanPrompt(prompt=prompt, default=False): cros_build_lib.Die('No confirmation.') # Ensure that production configs are only run with --production. if not (on_branch or options.production or options.where == CBUILDBOT): # We can't know if branched configs are tryjob safe. # It should always be safe to run a tryjob config with --production. prod_configs = [] for b in options.build_configs: if b in site_config and not config_lib.isTryjobConfig(site_config[b]): prod_configs.append(b) if prod_configs: # Die, and explain why. alternative_configs = ['%s-tryjob' % b for b in prod_configs] msg = ('These configs are not tryjob safe:\n' ' %s\n' 'Consider these configs instead:\n' ' %s\n' 'See go/cros-explicit-tryjob-build-configs-psa.' % (', '.join(prod_configs), ', '.join(alternative_configs))) if options.branch == 'master': # On master branch, we know the status of configs for sure. cros_build_lib.Die(msg) elif not options.yes: # On branches, we are just guessing. Let people override. prompt = '%s\nAre you sure you want to continue?' % msg if not cros_build_lib.BooleanPrompt(prompt=prompt, default=False): cros_build_lib.Die('No confirmation.') patches_given = options.gerrit_patches or options.local_patches if options.production: # Make sure production builds don't have patches. if patches_given and not options.debug: cros_build_lib.Die('Patches cannot be included in production builds.') elif options.where != CBUILDBOT: # Ask for confirmation if there are no patches to test. if not patches_given and not options.yes: prompt = ('No patches were provided; are you sure you want to just ' 'run a build of %s?' % ( options.branch if options.branch else 'ToT')) if not cros_build_lib.BooleanPrompt(prompt=prompt, default=False): cros_build_lib.Die('No confirmation.') if options.where in (REMOTE, INFRA_TESTING): if options.buildroot: cros_build_lib.Die('--buildroot is not used for remote tryjobs.') if options.git_cache_dir: cros_build_lib.Die('--git-cache-dir is not used for remote tryjobs.') else: if options.json: cros_build_lib.Die('--json can only be used for remote tryjobs.')
def main(argv): parser = commandline.ArgumentParser(description=__doc__) parser.add_argument('sym_files', type='path', nargs='*', default=None) parser.add_argument('--board', default=None, help='board to build packages for') parser.add_argument('--breakpad_root', type='path', default=None, help='root directory for breakpad symbols') parser.add_argument('--official_build', action='store_true', default=False, help='point to official symbol server') parser.add_argument('--regenerate', action='store_true', default=False, help='regenerate all symbols') parser.add_argument('--upload-count', type=int, default=None, help='only upload # number of symbols') parser.add_argument('--strip_cfi', type=int, default=CRASH_SERVER_FILE_LIMIT - (10 * 1024 * 1024), help='strip CFI data for files above this size') parser.add_argument('--testing', action='store_true', default=False, help='run in testing mode') parser.add_argument('--yes', action='store_true', default=False, help='answer yes to all prompts') opts = parser.parse_args(argv) if opts.sym_files: if opts.regenerate: cros_build_lib.Die( '--regenerate may not be used with specific files') else: if opts.board is None: cros_build_lib.Die('--board is required') if opts.breakpad_root and opts.regenerate: cros_build_lib.Die('--regenerate may not be used with --breakpad_root') if opts.testing: # TODO(build): Kill off --testing mode once unittests are up-to-snuff. cros_build_lib.Info('running in testing mode') # pylint: disable=W0601,W0603 global INITIAL_RETRY_DELAY, SymUpload, DEFAULT_SLEEP_DELAY INITIAL_RETRY_DELAY = DEFAULT_SLEEP_DELAY = 0 SymUpload = TestingSymUpload if not opts.yes: query = textwrap.wrap( textwrap.dedent(""" Uploading symbols for an entire Chromium OS build is really only necessary for release builds and in a few cases for developers to debug problems. It will take considerable time to run. For developer debugging purposes, consider instead passing specific files to upload. """), 80) cros_build_lib.Warning('\n%s', '\n'.join(query)) if not cros_build_lib.BooleanPrompt( prompt='Are you sure you want to upload all build symbols', default=False): cros_build_lib.Die('better safe than sorry') ret = 0 if opts.regenerate: ret += cros_generate_breakpad_symbols.GenerateBreakpadSymbols( opts.board, breakpad_dir=opts.breakpad_root) ret += UploadSymbols(opts.board, official=opts.official_build, breakpad_dir=opts.breakpad_root, file_limit=opts.strip_cfi, sleep=DEFAULT_SLEEP_DELAY, upload_count=opts.upload_count, sym_files=opts.sym_files) if ret: cros_build_lib.Error('encountered %i problem(s)', ret) # Since exit(status) gets masked, clamp it to 1 so we don't inadvertently # return 0 in case we are a multiple of the mask. ret = 1 return ret
def main(argv): parser = commandline.ArgumentParser(description=__doc__) # TODO: Make sym_paths, breakpad_root, and root exclusive. parser.add_argument('sym_paths', type='path_or_uri', nargs='*', default=None, help='symbol file or directory or URL or tarball') parser.add_argument('--board', default=None, help='Used to find default breakpad_root.') parser.add_argument('--breakpad_root', type='path', default=None, help='full path to the breakpad symbol directory') parser.add_argument('--root', type='path', default=None, help='full path to the chroot dir') parser.add_argument('--official_build', action='store_true', default=False, help='point to official symbol server') parser.add_argument('--server', type=str, default=None, help='URI for custom symbol server') parser.add_argument('--regenerate', action='store_true', default=False, help='regenerate all symbols') parser.add_argument('--upload-limit', type=int, help='only upload # number of symbols') parser.add_argument('--strip_cfi', type=int, default=DEFAULT_FILE_LIMIT, help='strip CFI data for files above this size') parser.add_argument('--failed-list', type='path', help='where to save a list of failed symbols') parser.add_argument('--dedupe', action='store_true', default=False, help='use the swarming service to avoid re-uploading') parser.add_argument('--yes', action='store_true', default=False, help='answer yes to all prompts') parser.add_argument('--product_name', type=str, default='ChromeOS', help='Produce Name for breakpad stats.') opts = parser.parse_args(argv) opts.Freeze() # Figure out the symbol files/directories to upload. if opts.sym_paths: sym_paths = opts.sym_paths elif opts.breakpad_root: sym_paths = [opts.breakpad_root] elif opts.root: if not opts.board: raise ValueError('--board must be set if --root is used.') breakpad_dir = cros_generate_breakpad_symbols.FindBreakpadDir( opts.board) sym_paths = [os.path.join(opts.root, breakpad_dir.lstrip('/'))] else: raise ValueError( '--sym_paths, --breakpad_root, or --root must be set.') if opts.sym_paths or opts.breakpad_root: if opts.regenerate: cros_build_lib.Die( '--regenerate may not be used with specific files, ' 'or breakpad_root') else: if opts.board is None: cros_build_lib.Die('--board is required') # Figure out the dedupe namespace. dedupe_namespace = None if opts.dedupe: if opts.official_build: dedupe_namespace = OFFICIAL_DEDUPE_NAMESPACE_TMPL % opts.product_name else: dedupe_namespace = STAGING_DEDUPE_NAMESPACE_TMPL % opts.product_name # Figure out which crash server to upload too. upload_url = opts.server if not upload_url: if opts.official_build: upload_url = OFFICIAL_UPLOAD_URL else: logging.warning('unofficial builds upload to the staging server') upload_url = STAGING_UPLOAD_URL # Confirm we really want the long upload. if not opts.yes: prolog = '\n'.join( textwrap.wrap( textwrap.dedent(""" Uploading symbols for an entire Chromium OS build is really only necessary for release builds and in a few cases for developers to debug problems. It will take considerable time to run. For developer debugging purposes, consider instead passing specific files to upload. """), 80)).strip() if not cros_build_lib.BooleanPrompt( prompt='Are you sure you want to upload all build symbols', default=False, prolog=prolog): cros_build_lib.Die('better safe than sorry') ret = 0 # Regenerate symbols from binaries. if opts.regenerate: ret += cros_generate_breakpad_symbols.GenerateBreakpadSymbols( opts.board, breakpad_dir=opts.breakpad_root) # Do the upload. ret += UploadSymbols(sym_paths=sym_paths, upload_url=upload_url, product_name=opts.product_name, dedupe_namespace=dedupe_namespace, failed_list=opts.failed_list, upload_limit=opts.upload_limit, strip_cfi=opts.strip_cfi) if ret: logging.error('encountered %i problem(s)', ret) # Since exit(status) gets masked, clamp it to 1 so we don't inadvertently # return 0 in case we are a multiple of the mask. return 1
def VerifyAndFinishInitialization(self, device): """Verify files/processes exist and flags are correct.""" if not self.board: if self.remote: self.board = cros_build_lib.GetBoard(device_board=device.board, override_board=self.board) else: raise GdbCannotDetectBoardError( 'Cannot determine which board to use. ' 'Please specify the with --board flag.') self.sysroot = cros_build_lib.GetSysroot(board=self.board) self.prompt = '(%s-gdb) ' % self.board self.inf_cmd = self.RemoveSysrootPrefix(self.inf_cmd) self.cross_gdb = self.GetCrossGdb() if self.remote: # If given remote process name, find pid & inf_cmd on remote device. if self.remote_process_name or self.pid: self._FindRemoteProcess(device) # Verify that sysroot is valid (exists). if not os.path.isdir(self.sysroot): raise GdbMissingSysrootError('Sysroot does not exist: %s' % self.sysroot) self.device = device sysroot_inf_cmd = '' if self.inf_cmd: sysroot_inf_cmd = os.path.join(self.sysroot, self.inf_cmd.lstrip('/')) # Verify that inf_cmd, if given, exists. if sysroot_inf_cmd and not os.path.exists(sysroot_inf_cmd): raise GdbMissingInferiorError('Cannot find file %s (in sysroot).' % sysroot_inf_cmd) # Check to see if inf_cmd is stripped, and if so, check to see if debug file # exists. If not, tell user and give them the option of quitting & getting # the debug info. if sysroot_inf_cmd: stripped_info = cros_build_lib.RunCommand( ['file', sysroot_inf_cmd], capture_output=True).output if not ' not stripped' in stripped_info: debug_file = os.path.join(self.sysroot, 'usr/lib/debug', self.inf_cmd.lstrip('/')) debug_file += '.debug' if not os.path.exists(debug_file): equery = 'equery-%s' % self.board package = cros_build_lib.RunCommand( [equery, '-q', 'b', self.inf_cmd], capture_output=True).output logging.info( self._MISSING_DEBUG_INFO_MSG % { 'board': self.board, 'inf_cmd': self.inf_cmd, 'package': package, 'debug_file': debug_file }) answer = cros_build_lib.BooleanPrompt() if not answer: raise GdbEarlyExitError( 'Exiting early, at user request.') # Set up qemu, if appropriate. qemu_arch = qemu.Qemu.DetectArch(self._GDB, self.sysroot) if qemu_arch is None: self.framework = 'ldso' else: self.framework = 'qemu' self.qemu = qemu.Qemu(self.sysroot, arch=qemu_arch) if self.remote: # Verify cgdb flag info. if self.cgdb: if osutils.Which('cgdb') is None: raise GdbMissingDebuggerError( 'Cannot find cgdb. Please install ' 'cgdb first.')
def main(argv): parser = commandline.ArgumentParser(description=__doc__) parser.add_argument('sym_paths', type='path_or_uri', nargs='*', default=None, help='symbol file or directory or URL or tarball') parser.add_argument('--board', default=None, help='Used to find default breakpad_root.') parser.add_argument('--breakpad_root', type='path', default=None, help='full path to the breakpad symbol directory') parser.add_argument('--root', type='path', default=None, help='full path to the chroot dir') parser.add_argument('--official_build', action='store_true', default=False, help='point to official symbol server') parser.add_argument('--server', type=str, default=None, help='URI for custom symbol server') parser.add_argument('--regenerate', action='store_true', default=False, help='regenerate all symbols') parser.add_argument('--upload-limit', type=int, default=None, help='only upload # number of symbols') parser.add_argument('--strip_cfi', type=int, default=CRASH_SERVER_FILE_LIMIT - (10 * 1024 * 1024), help='strip CFI data for files above this size') parser.add_argument('--failed-list', type='path', help='where to save a list of failed symbols') parser.add_argument('--dedupe', action='store_true', default=False, help='use the swarming service to avoid re-uploading') parser.add_argument('--testing', action='store_true', default=False, help='run in testing mode') parser.add_argument('--yes', action='store_true', default=False, help='answer yes to all prompts') parser.add_argument('--product_name', type=str, default='ChromeOS', help='Produce Name for breakpad stats.') opts = parser.parse_args(argv) opts.Freeze() if opts.sym_paths or opts.breakpad_root: if opts.regenerate: cros_build_lib.Die( '--regenerate may not be used with specific files, ' 'or breakpad_root') else: if opts.board is None: cros_build_lib.Die('--board is required') if opts.testing: # TODO(build): Kill off --testing mode once unittests are up-to-snuff. logging.info('running in testing mode') # pylint: disable=W0601,W0603 global INITIAL_RETRY_DELAY, SymUpload, DEFAULT_SLEEP_DELAY INITIAL_RETRY_DELAY = DEFAULT_SLEEP_DELAY = 0 SymUpload = TestingSymUpload dedupe_namespace = None if opts.dedupe: if opts.official_build and not opts.testing: dedupe_namespace = OFFICIAL_DEDUPE_NAMESPACE_TMPL % opts.product_name else: dedupe_namespace = STAGING_DEDUPE_NAMESPACE_TMPL % opts.product_name if not opts.yes: prolog = '\n'.join( textwrap.wrap( textwrap.dedent(""" Uploading symbols for an entire Chromium OS build is really only necessary for release builds and in a few cases for developers to debug problems. It will take considerable time to run. For developer debugging purposes, consider instead passing specific files to upload. """), 80)).strip() if not cros_build_lib.BooleanPrompt( prompt='Are you sure you want to upload all build symbols', default=False, prolog=prolog): cros_build_lib.Die('better safe than sorry') ret = 0 if opts.regenerate: ret += cros_generate_breakpad_symbols.GenerateBreakpadSymbols( opts.board, breakpad_dir=opts.breakpad_root) ret += UploadSymbols(opts.board, official=opts.official_build, server=opts.server, breakpad_dir=opts.breakpad_root, file_limit=opts.strip_cfi, sleep=DEFAULT_SLEEP_DELAY, upload_limit=opts.upload_limit, sym_paths=opts.sym_paths, failed_list=opts.failed_list, root=opts.root, dedupe_namespace=dedupe_namespace, product_name=opts.product_name) if ret: logging.error('encountered %i problem(s)', ret) # Since exit(status) gets masked, clamp it to 1 so we don't inadvertently # return 0 in case we are a multiple of the mask. ret = 1 return ret