Ejemplo n.º 1
0
 def verify(self, host):
     # Temporarily work around a problem caused by some old FSI
     # builds that don't have the power_supply_info command by
     # ignoring failures.  The repair triggers believe that this
     # verifier can't be fixed by re-installing, which means if a DUT
     # gets stuck with one of those old builds, it can't be repaired.
     #
     # TODO(jrbarnette): This is for crbug.com/599158; we need a
     # better solution.
     try:
         info = host.get_power_supply_info()
     except:
         logging.exception('get_power_supply_info() failed')
         return
     try:
         if info['Line Power']['online'] != 'yes':
             raise hosts.AutoservVerifyError('AC power is not plugged in')
     except KeyError:
         logging.info('Cannot determine AC power status - '
                      'skipping check.')
     try:
         if float(info['Battery']['percentage']) < 50.0:
             raise hosts.AutoservVerifyError('Battery is less than 50%')
     except KeyError:
         logging.info('Cannot determine battery status - '
                      'skipping check.')
Ejemplo n.º 2
0
    def verify(self, host):
        # Test 1 - The DUT is not excluded from updates.
        if not _is_firmware_update_supported(host):
            return
        # Test 2 - The DUT has an assigned stable firmware version.
        info = host.host_info_store.get()
        if info.model is None:
            raise hosts.AutoservVerifyError(
                    'Can not verify firmware version. '
                    'No model label value found')

        stable_firmware = afe_utils.get_stable_firmware_version(info.model)
        if stable_firmware is None:
            # This DUT doesn't have a firmware update target
            return

        # For tests 3 and 4:  If the output from `crossystem` or
        # `chromeos-firmwareupdate` isn't what we expect, we log an
        # error, but don't fail:  We don't want DUTs unable to test a
        # build merely because of a bug or change in either of those
        # commands.

        # Test 3 - The DUT is not running the target stable firmware.
        current_firmware = self._get_rw_firmware(host)
        if current_firmware is None:
            logging.error('DUT firmware version can\'t be determined.')
            return
        if current_firmware == stable_firmware:
            return
        # Test 4 - The firmware supplied in the running OS build is not
        # the assigned stable firmware.
        available_firmware = _get_available_firmware(host, info.model)
        if available_firmware is None:
            logging.error('Supplied firmware version in OS can\'t be '
                          'determined.')
            return
        if available_firmware != stable_firmware:
            raise hosts.AutoservVerifyError(
                    'DUT firmware requires update from %s to %s' %
                    (current_firmware, stable_firmware))
        # Time to update the firmware.
        logging.info('Updating firmware from %s to %s',
                     current_firmware, stable_firmware)
        self._check_hardware_match(current_firmware, stable_firmware)
        try:
            host.run('chromeos-firmwareupdate --mode=autoupdate')
            host.reboot()
        except Exception as e:
            message = ('chromeos-firmwareupdate failed: from '
                       '%s to %s')
            logging.exception(message, current_firmware, stable_firmware)
            raise hosts.AutoservVerifyError(
                    message % (current_firmware, stable_firmware))
        final_firmware = self._get_rw_firmware(host)
        if final_firmware != stable_firmware:
            message = ('chromeos-firmwareupdate failed: tried upgrade '
                       'to %s, now running %s instead')
            raise hosts.AutoservVerifyError(
                    message % (stable_firmware, final_firmware))
Ejemplo n.º 3
0
    def verify(self, host):
        if _is_virual_machine(host):
            # We do not forward host TPM / emulated TPM to qemu VMs, so skip
            # this verification step.
            logging.debug('Skipped verification %s on VM', self)
            return

        # This cryptohome command emits status information in JSON format. It
        # looks something like this:
        # {
        #    "installattrs": {
        #       ...
        #    },
        #    "mounts": [ {
        #       ...
        #    } ],
        #    "tpm": {
        #       "being_owned": false,
        #       "can_connect": true,
        #       "can_decrypt": false,
        #       "can_encrypt": false,
        #       "can_load_srk": true,
        #       "can_load_srk_pubkey": true,
        #       "enabled": true,
        #       "has_context": true,
        #       "has_cryptohome_key": false,
        #       "has_key_handle": false,
        #       "last_error": 0,
        #       "owned": true
        #    }
        # }
        output = host.run('cryptohome --action=status').stdout.strip()
        try:
            status = json.loads(output)
        except ValueError:
            logging.info('Cannot determine the Crytohome valid status - '
                         'skipping check.')
            return
        try:
            tpm = status['tpm']
            if not tpm['enabled']:
                raise hosts.AutoservVerifyError(
                    'TPM is not enabled -- Hardware is not working.')
            if not tpm['can_connect']:
                raise hosts.AutoservVerifyError(
                    ('TPM connect failed -- '
                     'last_error=%d.' % tpm['last_error']))
            if tpm['owned'] and not tpm['can_load_srk']:
                raise hosts.AutoservVerifyError('Cannot load the TPM SRK')
            if tpm['can_load_srk'] and not tpm['can_load_srk_pubkey']:
                raise hosts.AutoservVerifyError(
                    'Cannot load the TPM SRK public key')
        except KeyError:
            logging.info('Cannot determine the Crytohome valid status - '
                         'skipping check.')
Ejemplo n.º 4
0
    def verify(self, host):
        try:
            if not host.upstart_status('ap-controller'):
                raise hosts.AutoservVerifyError(
                    'ap-controller service is not running')
        except error.AutoservRunError:
            raise hosts.AutoservVerifyError('ap-controller service not found')

        try:
            host.run('pgrep ap-controller')
        except error.AutoservRunError:
            raise hosts.AutoservVerifyError(
                'ap-controller process is not running')
Ejemplo n.º 5
0
    def verify(self, host):
        # pylint: disable=missing-docstring
        try:
            # This output is in text protobuf format.
            result = host.run('cryptohome --action=tpm_more_status')
            if 'attestation_prepared: true' not in result.stdout:
                raise hosts.AutoservVerifyError(
                    'Attestation has not been prepared')

            result = host.run('cryptohome --action=tpm_attestation_get_ek')
            if 'EK Certificate' not in result.stdout:
                raise hosts.AutoservVerifyError(
                    'Endorsement certificate not found')
        except error.AutoservRunError:
            raise hosts.AutoservVerifyError(
                'Unable to fetch endorsement certificate')
Ejemplo n.º 6
0
    def verify(self, host):
        """
        Test whether the `host` has a `SERIAL` setting configured.

        This tests the config file names used by the `servod` upstart
        job for a valid setting of the `SERIAL` variable.  The following
        conditions raise errors:
          * The SERIAL setting doesn't match the DUT's entry in the AFE
            database.
          * There is no config file.
        """
        if not host.is_cros_host():
            return
        # Not all servo hosts will have a servo serial so don't verify if it's
        # not set.
        if host.servo_serial is None:
            return
        for config in self._get_configs(host):
            serialval = self._get_config_val(host, config, self.ATTR)
            if serialval is not None:
                self._validate_attr(host, serialval, host.servo_serial,
                                    self.ATTR, config)
                return
        msg = 'Servo serial is unconfigured; should be %s' % host.servo_serial
        raise hosts.AutoservVerifyError(msg)
Ejemplo n.º 7
0
 def repair(self, host):
     host.get_servo().get_power_state_controller().reset()
     # Get the lid_open value which requires EC console.
     lid_open = host.get_servo().get('lid_open')
     if lid_open != 'yes' and lid_open != 'not_applicable':
         raise hosts.AutoservVerifyError(
             'Still fail to contact EC console after rebooting DUT')
Ejemplo n.º 8
0
    def verify(self, host):
        """
        Test whether the `host` has a `BOARD` setting configured.

        This tests the config file names used by the `servod` upstart
        job for a valid setting of the `BOARD` variable.  The following
        conditions raise errors:
          * A config file exists, but the content contains no setting
            for BOARD.
          * The BOARD setting doesn't match the DUT's entry in the AFE
            database.
          * There is no config file.
        """
        if not host.is_cros_host():
            return
        for config in self._get_configs(host):
            boardval = self._get_config_val(host, config, self.ATTR)
            if boardval is not None:
                self._validate_attr(host, boardval, host.servo_board,
                                    self.ATTR, config)
                return
        msg = 'Servo board is unconfigured'
        if host.servo_board is not None:
            msg += '; should be %s' % host.servo_board
        raise hosts.AutoservVerifyError(msg)
Ejemplo n.º 9
0
    def verify(self, host):
        if not _is_firmware_repair_supported(host):
            return
        try:
            # Read the AP firmware and dump the sections that we're
            # interested in.
            cmd = ('mkdir /tmp/verify_firmware; '
                   'cd /tmp/verify_firmware; '
                   'for section in VBLOCK_A VBLOCK_B FW_MAIN_A FW_MAIN_B; '
                   'do flashrom -r image.bin -i $section:$section; '
                   'done')
            host.run(cmd)

            # Verify the firmware blocks A and B.
            cmd = ('vbutil_firmware --verify /tmp/verify_firmware/VBLOCK_%c'
                   ' --signpubkey /usr/share/vboot/devkeys/root_key.vbpubk'
                   ' --fv /tmp/verify_firmware/FW_MAIN_%c')
            for c in ('A', 'B'):
                rv = host.run(cmd % (c, c), ignore_status=True)
                if rv.exit_status:
                    raise hosts.AutoservVerifyError(
                        'Firmware %c is in a bad state.' % c)
        finally:
            # Remove the temporary files.
            host.run('rm -rf /tmp/verify_firmware')
Ejemplo n.º 10
0
 def verify(self, host):
     if host.servo_board in self._BOARDS_WO_PWR_BUTTON:
         return
     button = host.get_servo().get('pwr_button')
     if button != 'release':
         raise hosts.AutoservVerifyError(
             'Check ribbon cable: \'pwr_button\' is stuck')
Ejemplo n.º 11
0
 def verify(self, host):
     if not host.is_cros_host():
         return
     status_cmd = 'status servod PORT=%d' % host.servo_port
     job_status = host.run(status_cmd, ignore_status=True).stdout
     if 'start/running' not in job_status:
         raise hosts.AutoservVerifyError(
             'servod not running on %s port %d' %
             (host.hostname, host.servo_port))
Ejemplo n.º 12
0
    def verify(self, host):
        # Some pools are allowed to be in dev mode
        info = host.host_info_store.get()
        if (bool(info.pools & _DEV_MODE_ALLOWED_POOLS)):
            return

        result = host.run('crossystem devsw_boot', ignore_status=True).stdout
        if result != '0':
            raise hosts.AutoservVerifyError('The host is in dev mode')
Ejemplo n.º 13
0
    def verify(self, host):
        # pylint: disable=missing-docstring
        try:
            info = host.get_power_supply_info()
        except error.AutoservRunError:
            raise hosts.AutoservVerifyError('Failed to get power supply info')

        try:
            if info['Line Power']['online'] != 'yes':
                raise hosts.AutoservVerifyError('AC power is not plugged in')
        except KeyError:
            raise hosts.AutoservVerifyError('Cannot determine AC power status')

        try:
            if float(info['Battery']['percentage']) < 50.0:
                raise hosts.AutoservVerifyError('Battery is less than 50%')
        except KeyError:
            logging.info('Cannot determine battery status - '
                         'skipping check.')
Ejemplo n.º 14
0
 def verify(self, host):
     # grep for stateful FS errors of the type "EXT4-fs error (device sda1):"
     command = ("dmesg | grep -E \"EXT4-fs error \(device "
                "$(cut -d ' ' -f 5,9 /proc/$$/mountinfo | "
                "grep -e '^/mnt/stateful_partition ' | "
                "cut -d ' ' -f 2 | cut -d '/' -f 3)\):\"")
     output = host.run(command=command, ignore_status=True).stdout
     if output:
         sample = output.splitlines()[0]
         message = 'Saw file system error: %s' % sample
         raise hosts.AutoservVerifyError(message)
     # Check for other critical FS errors.
     command = 'dmesg | grep "This should not happen!!  Data will be lost"'
     output = host.run(command=command, ignore_status=True).stdout
     if output:
         message = 'Saw file system error: Data will be lost'
         raise hosts.AutoservVerifyError(message)
     else:
         logging.error('Could not determine stateful mount.')
Ejemplo n.º 15
0
 def verify(self, host):
     result = host.run('python -c "import cPickle"', ignore_status=True)
     if result.exit_status != 0:
         message = 'The python interpreter is broken'
         if result.exit_status == 127:
             search = host.run('which python', ignore_status=True)
             if search.exit_status != 0 or not search.stdout:
                 message = ('Python is missing; may be caused by '
                            'powerwash')
         raise hosts.AutoservVerifyError(message)
Ejemplo n.º 16
0
 def verify(self, host):
     # This deliberately stops looking after the first error.
     # See above for the details.
     for testdir in self._TEST_DIRECTORIES:
         filename = os.path.join(testdir, 'writable_test')
         command = 'touch %s && rm %s' % (filename, filename)
         rv = host.run(command=command, ignore_status=True)
         if rv.exit_status != 0:
             msg = 'Can\'t create a file in %s' % testdir
             raise hosts.AutoservVerifyError(msg)
Ejemplo n.º 17
0
def _get_cryptohome_status(host):
    """Returns a dictionary containing the cryptohome status.

    @param host: a hosts.Host object.
    @returns A dictionary containing the cryptohome status.
    @raises AutoservVerifyError: if the output could not be parsed or the TPM
       status is missing.
    @raises hosts.AutoservRunError: if the cryptohome command failed.
    """
    # This cryptohome command emits status information in JSON format. It
    # looks something like this:
    # {
    #    "installattrs": {
    #       ...
    #    },
    #    "mounts": [ {
    #       ...
    #    } ],
    #    "tpm": {
    #       "being_owned": false,
    #       "can_connect": true,
    #       "can_decrypt": false,
    #       "can_encrypt": false,
    #       "can_load_srk": true,
    #       "can_load_srk_pubkey": true,
    #       "enabled": true,
    #       "has_context": true,
    #       "has_cryptohome_key": false,
    #       "has_key_handle": false,
    #       "last_error": 0,
    #       "owned": true
    #    }
    # }
    try:
        output = host.run('cryptohome --action=status').stdout.strip()
        status = json.loads(output)
        if 'tpm' not in status:
            raise hosts.AutoservVerifyError('TPM status is missing')
        return status
    except ValueError:
        raise hosts.AutoservVerifyError('Unable to parse cryptohome status')
Ejemplo n.º 18
0
 def verify(self, host):
     if host.is_up():
         return
     msg = 'No answer to ssh from %s'
     try:
         socket.gethostbyname(host.hostname)
     except Exception as e:
         logging.exception('DNS lookup failure')
         msg = 'Unable to look up %%s in DNS: %s' % e
     else:
         if utils.ping(host.hostname, tries=1, deadline=1) != 0:
             msg = 'No answer to ping from %s'
     raise hosts.AutoservVerifyError(msg % host.hostname)
Ejemplo n.º 19
0
    def _validate_attr(host, val, expected_val, attr, config_file):
        """
        Check that the attr setting is valid for the host.

        This presupposes that a valid config file was found.  Raise an
        execption if:
          * There was no attr setting from the file (i.e. the setting
            is an empty string), or
          * The attr setting is valid, the attr is known,
            and the setting doesn't match the DUT.

        @param host         Host to be checked for `config_file`.
        @param val          Value to be tested.
        @param expected_val Expected value.
        @param attr         Attribute we're validating.
        @param config_file  Path to the config file to be tested.
        """
        if not val:
            raise hosts.AutoservVerifyError('config file %s exists, but %s '
                                            'is not set' % (attr, config_file))
        if expected_val is not None and val != expected_val:
            raise hosts.AutoservVerifyError('%s is %s; it should be %s' %
                                            (attr, val, expected_val))
Ejemplo n.º 20
0
    def connect_servo(self):
        """Establish a connection to the servod server on this host.

        Initializes `self._servo` and then verifies that all network
        connections are working.  This will create an ssh tunnel if
        it's required.

        As a side effect of testing the connection, all signals on the
        target servo are reset to default values, and the USB stick is
        set to the neutral (off) position.
        """
        servo_obj = servo.Servo(servo_host=self,
                                servo_serial=self.servo_serial)
        timeout, _ = retry.timeout(
            servo_obj.initialize_dut,
            timeout_sec=self.INITIALIZE_SERVO_TIMEOUT_SECS)
        if timeout:
            raise hosts.AutoservVerifyError('Servo initialize timed out.')
        self._servo = servo_obj
Ejemplo n.º 21
0
    def _check_hardware_match(version_a, version_b):
        """
        Check that two firmware versions identify the same hardware.

        Firmware version strings look like this:
            Google_Gnawty.5216.239.34
        The part before the numbers identifies the hardware for which
        the firmware was built.  This function checks that the hardware
        identified by `version_a` and `version_b` is the same.

        This is a sanity check to protect us from installing the wrong
        firmware on a DUT when a board label has somehow gone astray.

        @param version_a  First firmware version for the comparison.
        @param version_b  Second firmware version for the comparison.
        """
        hardware_a = version_a.split('.')[0]
        hardware_b = version_b.split('.')[0]
        if hardware_a != hardware_b:
            message = 'Hardware/Firmware mismatch updating %s to %s'
            raise hosts.AutoservVerifyError(message % (version_a, version_b))
Ejemplo n.º 22
0
    def verify(self, host):
        # pylint: disable=missing-docstring
        try:
            status = CryptohomeStatus(host)
            if not status.tpm_enabled:
                raise hosts.AutoservVerifyError('TPM is not enabled')
            if not status.tpm_owned:
                raise hosts.AutoservVerifyError('TPM is not owned')
            if not status.tpm_can_load_srk:
                raise hosts.AutoservVerifyError('TPM cannot load SRK')
            if not status.tpm_can_load_srk_pubkey:
                raise hosts.AutoservVerifyError('TPM cannot load SRK pubkey')

            # Check that the TPM is fully initialized. The output of this
            # command is line-oriented property/value pairs.
            result = host.run('cryptohome --action=tpm_status')
            if 'TPM Ready: true' not in result.stdout:
                raise hosts.AutoservVerifyError('TPM is not ready')
        except error.AutoservRunError:
            raise hosts.AutoservVerifyError('Could not determine TPM status')
Ejemplo n.º 23
0
 def verify(self, host):
     # pylint: disable=missing-docstring
     result = host.run('[ ! -e /dev/kvm -a -f /usr/bin/vm_concierge ]',
                       ignore_status=True)
     if result.exit_status == 0:
         raise hosts.AutoservVerifyError('/dev/kvm is missing')
Ejemplo n.º 24
0
 def verify(self, host):
     # pylint: disable=missing-docstring
     result = host.run('test -f %s' % autoupdater.PROVISION_FAILED,
                       ignore_status=True)
     if result.exit_status == 0:
         raise hosts.AutoservVerifyError('Last AU on this DUT failed')
Ejemplo n.º 25
0
 def verify(self, host):
     result = host.run('test -f %s' % host.PROVISION_FAILED,
                       ignore_status=True)
     if result.exit_status == 0:
         raise hosts.AutoservVerifyError('Last AU on this DUT failed')
Ejemplo n.º 26
0
 def verify(self, host):
     lid_open = host.get_servo().get('lid_open')
     if lid_open != 'yes' and lid_open != 'not_applicable':
         raise hosts.AutoservVerifyError(
             'Check lid switch: lid_open is %s' % lid_open)