blob: 243556fa94b653fa586600223fcc28af4f42b25d [file] [log] [blame]
# 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)