• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2017 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5# Update event types.
6EVENT_TYPE_DOWNLOAD_COMPLETE = '1'
7EVENT_TYPE_INSTALL_COMPLETE = '2'
8EVENT_TYPE_UPDATE_COMPLETE = '3'
9EVENT_TYPE_DOWNLOAD_STARTED = '13'
10EVENT_TYPE_DOWNLOAD_FINISHED = '14'
11EVENT_TYPE_REBOOTED_AFTER_UPDATE = '54'
12
13# Update event results.
14EVENT_RESULT_ERROR = '0'
15EVENT_RESULT_SUCCESS = '1'
16EVENT_RESULT_UPDATE_DEFERRED = '9'
17
18# Omaha event types/results, from update_engine/omaha_request_action.h
19# These are stored in dict form in order to easily print out the keys.
20EVENT_TYPE_DICT = {
21    EVENT_TYPE_DOWNLOAD_COMPLETE: 'download_complete',
22    EVENT_TYPE_INSTALL_COMPLETE: 'install_complete',
23    EVENT_TYPE_UPDATE_COMPLETE: 'update_complete',
24    EVENT_TYPE_DOWNLOAD_STARTED: 'download_started',
25    EVENT_TYPE_DOWNLOAD_FINISHED: 'download_finished',
26    EVENT_TYPE_REBOOTED_AFTER_UPDATE: 'rebooted_after_update'
27}
28
29EVENT_RESULT_DICT = {
30    EVENT_RESULT_ERROR: 'error',
31    EVENT_RESULT_SUCCESS: 'success',
32    EVENT_RESULT_UPDATE_DEFERRED: 'update_deferred'
33}
34
35
36def get_event_type(event_type_code):
37    """Utility to look up the different event type codes."""
38    return EVENT_TYPE_DICT[event_type_code]
39
40
41def get_event_result(event_result_code):
42    """Utility to look up the different event result codes."""
43    return EVENT_RESULT_DICT[event_result_code]
44
45
46class UpdateEngineEvent(object):
47    """This class represents a single EXPECTED update engine event.
48
49    This class's data will be compared against an ACTUAL event returned by
50    update_engine.
51    """
52
53    def __init__(self, event_type=None, event_result=None, version=None,
54                 previous_version=None, on_error=None):
55        """Initializes an event.
56
57        @param event_type: Expected event type.
58        @param event_result: Expected event result code.
59        @param version: Expected reported image version.
60        @param previous_version: Expected reported previous image version.
61        @param on_error: a function to call when the event's data is invalid.
62        """
63        self._expected_attrs = {
64            'event_type': event_type,
65            'event_result': event_result,
66            'version': version,
67            'previous_version': previous_version,
68        }
69        self._on_error = on_error
70
71
72    def _verify_event_attribute(self, attr_name, expected_attr_val,
73                                actual_attr_val):
74        """Compares a single attribute to ensure expected matches actual.
75
76        @param attr_name: name of the attribute to verify.
77        @param expected_attr_val: expected attribute value.
78        @param actual_attr_val: actual attribute value.
79
80        @return True if actual value is present and matches, False otherwise.
81        """
82        # None values are assumed to be missing and non-matching.
83        if actual_attr_val is None:
84            return False
85
86        # We allow expected version numbers (e.g. 2940.0.0) to be contained in
87        # actual values (2940.0.0-a1) for developer images.
88        if (actual_attr_val == expected_attr_val or
89           ('version' in attr_name and expected_attr_val in actual_attr_val)):
90            return True
91
92        return False
93
94
95    def __str__(self):
96        """Returns a comma separated list of the event data."""
97        return '{%s}' % ', '.join(['%s:%s' % (k, v) for k, v in
98                                   self._expected_attrs.iteritems()])
99
100    def equals(self, actual_event):
101        """Compares this expected event with an actual event from the update.
102
103        @param actual_event: a dictionary containing event attributes.
104
105        @return An error message, or None if all attributes as expected.
106        """
107        mismatched_attrs = [
108            attr_name for attr_name, expected_attr_val
109            in self._expected_attrs.iteritems()
110            if (expected_attr_val and
111                not self._verify_event_attribute(attr_name, expected_attr_val,
112                                                 actual_event.get(attr_name)))]
113
114        if not mismatched_attrs:
115            return None
116
117        return self._on_error(self._expected_attrs, actual_event,
118                              mismatched_attrs)