示例#1
0
    def testWaitUntilComplete(self):
        """Test WaitUntilComplete returns False if background task isn't complete.

    As the background task is not started in this test, we expect it not to
    complete.
    """
        op = operation.ProgressBarOperation()
        self.assertFalse(op.WaitUntilComplete(0))
示例#2
0
    def testCaptureOutputInBackground(self):
        """Test CaptureOutputInBackground puts finished in reasonable time."""
        def func():
            print('hi')

        op = operation.ProgressBarOperation()
        op.CaptureOutputInBackground(func)

        # This function should really finish in < 1 sec. However, we wait for a
        # longer time so the test does not fail on highly loaded builders.
        self.assertTrue(op.WaitUntilComplete(10))
示例#3
0
    def _VerifyProgressBar(self, width, percent, expected_shaded,
                           expected_unshaded):
        """Helper to test progress bar with different percentages and lengths."""
        terminal_width = width + (
            operation.ProgressBarOperation._PROGRESS_BAR_BORDER_SIZE)
        self._terminal.return_value = operation._TerminalSize(
            100, terminal_width)
        op = operation.ProgressBarOperation()
        with self.OutputCapturer() as output:
            op.ProgressBar(percent)
        stdout = output.GetStdout()

        # Check that the shaded and unshaded regions are the expected size.
        self.assertEqual(stdout.count('#'), expected_shaded)
        self.assertEqual(stdout.count('-'), expected_unshaded)
示例#4
0
    def UpdateRootfs(self):
        """Update the rootfs partition of the device (utilizing nebraska)."""
        logging.notice('Updating rootfs partition...')
        nebraska_bin = os.path.join(self.device_dev_dir,
                                    self.REMOTE_NEBRASKA_FILENAME)

        nebraska = nebraska_wrapper.RemoteNebraskaWrapper(
            self.device,
            nebraska_bin=nebraska_bin,
            update_payloads_address='file://' + self.device_payload_dir,
            update_metadata_dir=self.device_payload_dir)

        try:
            nebraska.Start()

            # Use the localhost IP address (default) to ensure that update engine
            # client can connect to the nebraska.
            nebraska_url = nebraska.GetURL(critical_update=True)
            cmd = [
                self.REMOTE_UPDATE_ENGINE_BIN_FILENAME, '--check_for_update',
                '--omaha_url="%s"' % nebraska_url
            ]

            self.device.run(cmd, **self._cmd_kwargs)

            # If we are using a progress bar, update it every 0.5s instead of 10s.
            if command.UseProgressBar():
                update_check_interval = self.UPDATE_CHECK_INTERVAL_PROGRESSBAR
                oper = operation.ProgressBarOperation()
            else:
                update_check_interval = self.UPDATE_CHECK_INTERVAL_NORMAL
                oper = None
            end_message_not_printed = True

            # Loop until update is complete.
            while True:
                # Number of times to retry `update_engine_client --status`. See
                # crbug.com/744212.
                update_engine_status_retry = 30
                op, progress = retry_util.RetryException(
                    cros_build_lib.RunCommandError,
                    update_engine_status_retry,
                    self.GetUpdateStatus,
                    self.device, ['CURRENT_OP', 'PROGRESS'],
                    delay_sec=DELAY_SEC_FOR_RETRY)[0:2]
                logging.info('Waiting for update...status: %s at progress %s',
                             op, progress)

                if op == UPDATE_STATUS_UPDATED_NEED_REBOOT:
                    logging.info('Update completed.')
                    break

                if op == UPDATE_STATUS_IDLE:
                    # Something went wrong. Try to get last error code.
                    cmd = ['cat', self.REMOTE_UPDATE_ENGINE_LOGFILE_PATH]
                    log = self.device.run(cmd).stdout.strip().splitlines()
                    err_str = 'Updating payload state for error code: '
                    targets = [line for line in log if err_str in line]
                    logging.debug('Error lines found: %s', targets)
                    if not targets:
                        raise RootfsUpdateError(
                            'Update failed with unexpected update status: %s' %
                            op)
                    else:
                        # e.g 20 (ErrorCode::kDownloadStateInitializationError)
                        raise RootfsUpdateError(
                            targets[-1].rpartition(err_str)[2])

                if oper is not None:
                    if op == UPDATE_STATUS_DOWNLOADING:
                        oper.ProgressBar(float(progress))
                    elif end_message_not_printed and op == UPDATE_STATUS_FINALIZING:
                        oper.Cleanup()
                        logging.info('Finalizing image.')
                        end_message_not_printed = False

                time.sleep(update_check_interval)
        # TODO(ahassani): Scope the Exception to finer levels. For example we don't
        # need to revert the boot partition if the Nebraska fails to start, etc.
        except Exception as e:
            logging.error('Rootfs update failed %s', e)
            self.RevertBootPartition()
            logging.warning(nebraska.PrintLog()
                            or 'No nebraska log is available.')
            raise RootfsUpdateError('Failed to perform rootfs update: %r' % e)
        finally:
            nebraska.Stop()

            nebraska.CollectLogs(
                os.path.join(self.tempdir, self.LOCAL_NEBRASKA_LOG_FILENAME))
            self.device.CopyFromDevice(
                self.REMOTE_UPDATE_ENGINE_LOGFILE_PATH,
                os.path.join(
                    self.tempdir,
                    os.path.basename(self.REMOTE_UPDATE_ENGINE_LOGFILE_PATH)),
                follow_symlinks=True,
                **self._cmd_kwargs_omit_error)
示例#5
0
    def UpdateRootfs(self):
        """Update the rootfs partition of the device."""
        devserver_bin = os.path.join(self.device_dev_dir,
                                     self.DEVSERVER_FILENAME)
        ds = ds_wrapper.RemoteDevServerWrapper(
            self.device,
            devserver_bin,
            static_dir=self.device_static_dir,
            log_dir=self.device.work_dir)

        logging.info('Updating rootfs partition')
        try:
            ds.Start()
            # Use the localhost IP address to ensure that update engine
            # client can connect to the devserver.
            omaha_url = ds.GetDevServerURL(ip='127.0.0.1',
                                           port=ds.port,
                                           sub_dir='update/pregenerated')
            cmd = [
                self.UPDATE_ENGINE_BIN, '-check_for_update',
                '-omaha_url=%s' % omaha_url
            ]
            self.device.RunCommand(cmd)

            # If we are using a progress bar, update it every 0.5s instead of 10s.
            if command.UseProgressBar():
                update_check_interval = self.UPDATE_CHECK_INTERVAL_PROGRESSBAR
                oper = operation.ProgressBarOperation()
            else:
                update_check_interval = self.UPDATE_CHECK_INTERVAL_NORMAL
                oper = None
            end_message_not_printed = True

            # Loop until update is complete.
            while True:
                op, progress = self.GetUpdateStatus(self.device,
                                                    ['CURRENT_OP', 'PROGRESS'])
                logging.info('Waiting for update...status: %s at progress %s',
                             op, progress)

                if op == UPDATE_STATUS_UPDATED_NEED_REBOOT:
                    logging.notice('Update completed.')
                    break

                if op == UPDATE_STATUS_IDLE:
                    raise RootfsUpdateError(
                        'Update failed with unexpected update status: %s' % op)

                if oper is not None:
                    if op == UPDATE_STATUS_DOWNLOADING:
                        oper.ProgressBar(float(progress))
                    elif end_message_not_printed and op == UPDATE_STATUS_FINALIZING:
                        oper.Cleanup()
                        logging.notice('Finalizing image.')
                        end_message_not_printed = False

                time.sleep(update_check_interval)

            ds.Stop()
        except Exception as e:
            logging.error('Rootfs update failed.')
            logging.warning(ds.TailLog() or 'No devserver log is available.')
            error_msg = 'Failed to perform rootfs update: %r'
            raise RootfsUpdateError(error_msg % e)
        finally:
            ds.Stop()
            self.device.CopyFromDevice(ds.log_file,
                                       os.path.join(self.tempdir,
                                                    self.DEVSERVER_LOG),
                                       error_code_ok=True)
            self.device.CopyFromDevice(self.UPDATE_ENGINE_LOG,
                                       self.tempdir,
                                       follow_symlinks=True,
                                       error_code_ok=True)