xref: /aosp_15_r20/external/autotest/server/site_tests/autoupdate_Rollback/autoupdate_Rollback.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Lint as: python2, python3
2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import logging
7import os
8
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.common_lib.cros import kernel_utils
11from autotest_lib.server.cros.update_engine import update_engine_test
12
13POWERWASH_COMMAND = 'safe fast keepimg'
14POWERWASH_MARKER_FILE = '/mnt/stateful_partition/factory_install_reset'
15STATEFUL_MARKER_FILE = '/mnt/stateful_partition/autoupdate_Rollback_flag'
16
17class autoupdate_Rollback(update_engine_test.UpdateEngineTest):
18    """Test that updates the machine and performs rollback."""
19    version = 1
20
21    def _powerwash(self):
22        """Powerwashes DUT."""
23        logging.info('Powerwashing device before rollback.')
24        self._host.run(['echo', 'car', '>', STATEFUL_MARKER_FILE])
25        self._host.run(['echo', "'%s'" % POWERWASH_COMMAND, '>',
26                        POWERWASH_MARKER_FILE])
27        self._host.reboot()
28        marker = self._host.run(['test', '-e', STATEFUL_MARKER_FILE],
29                                ignore_status=True, ignore_timeout=True)
30        if marker is None or marker.exit_status == 0:
31            raise error.TestFail("Powerwash cycle didn't remove the marker "
32                                 "file on the stateful partition.")
33
34
35    def cleanup(self):
36        """Clean up test state."""
37        # Save update_engine logs for the update, rollback, and post-reboot.
38        self._save_extra_update_engine_logs(number_of_logs=3)
39
40        # Restore the stateful partition so tests can still use this DUT.
41        if self._powerwash_attempted:
42            self._restore_stateful()
43
44        # Delete rollback-version and rollback-happened pref which are
45        # generated during Rollback and Enterprise Rollback.
46        # rollback-version is written when update_engine Rollback D-Bus API is
47        # called. The existence of rollback-version prevents update_engine to
48        # apply payload whose version is the same as rollback-version.
49        # rollback-happened is written when update_engine finished Enterprise
50        # Rollback operation.
51        preserved_prefs_path = ('/mnt/stateful_partition/unencrypted/preserve'
52                                '/update_engine/prefs/')
53        self._host.run(
54            ['rm', os.path.join(preserved_prefs_path, 'rollback-version'),
55             os.path.join(preserved_prefs_path, 'rollback-happened')],
56            ignore_status=True)
57        # Restart update-engine to pick up new prefs.
58        self._restart_update_engine(ignore_status=True)
59
60
61    def run_once(self, job_repo_url=None, powerwash_before_rollback=False):
62        """Runs the test.
63
64        @param job_repo_url: URL to get the image.
65        @param powerwash_before_rollback: True if we should rollback before
66                                          powerwashing.
67
68        @raise error.TestError if anything went wrong with setting up the test;
69               error.TestFail if any part of the test has failed.
70
71        """
72        self._powerwash_attempted = False
73        payload_url = self.get_payload_for_nebraska(job_repo_url)
74        active, inactive = kernel_utils.get_kernel_state(self._host)
75        logging.info('Initial device state: active kernel %s, '
76                     'inactive kernel %s.', active, inactive)
77
78        logging.info('Performing an update.')
79        self._run_client_test_and_check_result('autoupdate_CannedOmahaUpdate',
80                                               payload_url=payload_url)
81        self._host.reboot()
82        # Ensure the update completed successfully.
83        rootfs_hostlog, _ = self._create_hostlog_files()
84        self.verify_update_events(self._FORCED_UPDATE, rootfs_hostlog)
85        # We should be booting from the new partition.
86        error_msg = 'Failed to set up test by updating DUT.'
87        kernel_utils.verify_boot_expectations(inactive, error_msg, self._host)
88
89        if powerwash_before_rollback:
90            self._powerwash_attempted = True
91            self._powerwash()
92
93        logging.info('Update verified, initiating rollback.')
94        # Powerwash is tested separately from rollback.
95        self._rollback(powerwash=False)
96        self._host.reboot()
97
98        # We should be back on our initial partition.
99        error_msg = ('Autoupdate reported that rollback succeeded but we '
100                         'did not boot into the correct partition.')
101        kernel_utils.verify_boot_expectations(active, error_msg, self._host)
102        logging.info('We successfully rolled back to initial kernel.')
103