普通文本  |  118行  |  4.19 KB

# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Update event types.
EVENT_TYPE_DOWNLOAD_COMPLETE = '1'
EVENT_TYPE_INSTALL_COMPLETE = '2'
EVENT_TYPE_UPDATE_COMPLETE = '3'
EVENT_TYPE_DOWNLOAD_STARTED = '13'
EVENT_TYPE_DOWNLOAD_FINISHED = '14'
EVENT_TYPE_REBOOTED_AFTER_UPDATE = '54'

# Update event results.
EVENT_RESULT_ERROR = '0'
EVENT_RESULT_SUCCESS = '1'
EVENT_RESULT_UPDATE_DEFERRED = '9'

# Omaha event types/results, from update_engine/omaha_request_action.h
# These are stored in dict form in order to easily print out the keys.
EVENT_TYPE_DICT = {
    EVENT_TYPE_DOWNLOAD_COMPLETE: 'download_complete',
    EVENT_TYPE_INSTALL_COMPLETE: 'install_complete',
    EVENT_TYPE_UPDATE_COMPLETE: 'update_complete',
    EVENT_TYPE_DOWNLOAD_STARTED: 'download_started',
    EVENT_TYPE_DOWNLOAD_FINISHED: 'download_finished',
    EVENT_TYPE_REBOOTED_AFTER_UPDATE: 'rebooted_after_update'
}

EVENT_RESULT_DICT = {
    EVENT_RESULT_ERROR: 'error',
    EVENT_RESULT_SUCCESS: 'success',
    EVENT_RESULT_UPDATE_DEFERRED: 'update_deferred'
}


def get_event_type(event_type_code):
    """Utility to look up the different event type codes."""
    return EVENT_TYPE_DICT[event_type_code]


def get_event_result(event_result_code):
    """Utility to look up the different event result codes."""
    return EVENT_RESULT_DICT[event_result_code]


class UpdateEngineEvent(object):
    """This class represents a single EXPECTED update engine event.

    This class's data will be compared against an ACTUAL event returned by
    update_engine.
    """

    def __init__(self, event_type=None, event_result=None, version=None,
                 previous_version=None, on_error=None):
        """Initializes an event.

        @param event_type: Expected event type.
        @param event_result: Expected event result code.
        @param version: Expected reported image version.
        @param previous_version: Expected reported previous image version.
        @param on_error: a function to call when the event's data is invalid.
        """
        self._expected_attrs = {
            'event_type': event_type,
            'event_result': event_result,
            'version': version,
            'previous_version': previous_version,
        }
        self._on_error = on_error


    def _verify_event_attribute(self, attr_name, expected_attr_val,
                                actual_attr_val):
        """Compares a single attribute to ensure expected matches actual.

        @param attr_name: name of the attribute to verify.
        @param expected_attr_val: expected attribute value.
        @param actual_attr_val: actual attribute value.

        @return True if actual value is present and matches, False otherwise.
        """
        # None values are assumed to be missing and non-matching.
        if actual_attr_val is None:
            return False

        # We allow expected version numbers (e.g. 2940.0.0) to be contained in
        # actual values (2940.0.0-a1) for developer images.
        if (actual_attr_val == expected_attr_val or
           ('version' in attr_name and expected_attr_val in actual_attr_val)):
            return True

        return False


    def __str__(self):
        """Returns a comma separated list of the event data."""
        return '{%s}' % ', '.join(['%s:%s' % (k, v) for k, v in
                                   self._expected_attrs.iteritems()])

    def equals(self, actual_event):
        """Compares this expected event with an actual event from the update.

        @param actual_event: a dictionary containing event attributes.

        @return An error message, or None if all attributes as expected.
        """
        mismatched_attrs = [
            attr_name for attr_name, expected_attr_val
            in self._expected_attrs.iteritems()
            if (expected_attr_val and
                not self._verify_event_attribute(attr_name, expected_attr_val,
                                                 actual_event.get(attr_name)))]

        if not mismatched_attrs:
            return None

        return self._on_error(self._expected_attrs, actual_event,
                              mismatched_attrs)