def search_marker(self): """Return an Anchor that we can use to dedupe this exact bug.""" board = '' try: board = site_utils.ParseBuildName(self.build)[0] except site_utils.ParseBuildNameException as e: logging.error(str(e)) # Substitute the board name for a placeholder. We try both build and # release board name variants. reason = self.reason if board: for b in (board, board.replace('_', '-')): reason = reason.replace(b, 'BOARD_PLACEHOLDER') return "%s(%s,%s,%s)" % ('Test%s' % self.status, self.suite, self.name, reason)
def update_image(self, wait_for_update=False): """Update the image on the servo host, if needed. This method recognizes the following cases: * If the Host is not running Chrome OS, do nothing. * If a previously triggered update is now complete, reboot to the new version. * If the host is processing a previously triggered update, do nothing. * If the host is running a version of Chrome OS different from the default for servo Hosts, trigger an update, but don't wait for it to complete. @param wait_for_update If an update needs to be applied and this is true, then don't return until the update is downloaded and finalized, and the host rebooted. @raises dev_server.DevServerException: If all the devservers are down. @raises site_utils.ParseBuildNameException: If the devserver returns an invalid build name. @raises autoupdater.ChromiumOSError: If something goes wrong in the checking update engine client status or applying an update. @raises AutoservRunError: If the update_engine_client isn't present on the host, and the host is a cros_host. """ # servod could be running in a Ubuntu workstation. if not self.is_cros_host(): logging.info( 'Not attempting an update, either %s is not running ' 'chromeos or we cannot find enough information about ' 'the host.', self.hostname) return if lsbrelease_utils.is_moblab(): logging.info('Not attempting an update, %s is running moblab.', self.hostname) return target_build = afe_utils.get_stable_cros_image_name(self.get_board()) target_build_number = server_site_utils.ParseBuildName(target_build)[3] # For servo image staging, we want it as more widely distributed as # possible, so that devservers' load can be evenly distributed. So use # hostname instead of target_build as hash. ds = dev_server.ImageServer.resolve(self.hostname, hostname=self.hostname) url = ds.get_update_url(target_build) updater = autoupdater.ChromiumOSUpdater(update_url=url, host=self) status, current_build_number = self._check_for_reboot(updater) update_pending = True if status in autoupdater.UPDATER_PROCESSING_UPDATE: logging.info( 'servo host %s already processing an update, update ' 'engine client status=%s', self.hostname, status) elif current_build_number != target_build_number: logging.info( 'Using devserver url: %s to trigger update on ' 'servo host %s, from %s to %s', url, self.hostname, current_build_number, target_build_number) try: ds.stage_artifacts(target_build, artifacts=['full_payload']) except Exception as e: logging.error('Staging artifacts failed: %s', str(e)) logging.error('Abandoning update for this cycle.') else: try: # TODO(jrbarnette): This 'touch' is a gross hack # to get us past crbug.com/613603. Once that # bug is resolved, we should remove this code. self.run('touch /home/chronos/.oobe_completed') updater.trigger_update() except autoupdater.RootFSUpdateError as e: trigger_download_status = 'failed with %s' % str(e) metrics.Counter('chromeos/autotest/servo/' 'rootfs_update_failed').increment() else: trigger_download_status = 'passed' logging.info( 'Triggered download and update %s for %s, ' 'update engine currently in status %s', trigger_download_status, self.hostname, updater.check_update_status()) else: logging.info('servo host %s does not require an update.', self.hostname) update_pending = False if update_pending and wait_for_update: logging.info('Waiting for servo update to complete.') self.run('update_engine_client --follow', ignore_status=True)