1# Copyright (c) 2014 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
5import logging
6
7from autotest_lib.client.common_lib import error
8from autotest_lib.server.cros.update_engine import update_engine_test
9
10POWERWASH_COUNT = '/mnt/stateful_partition/unencrypted/preserve/powerwash_count'
11POWERWASH_MARKER_FILE = '/mnt/stateful_partition/factory_install_reset'
12POWERWASH_COMMAND = 'safe fast keepimg'
13
14STATEFUL_MARKER_FILE = '/mnt/stateful_partition/platform_Powerwash_flag'
15
16# Log files to help debugging what happened during last clobbering (powerwash).
17CLOBBER_STATE_LOG_FILE = '/mnt/stateful_partition/unencrypted/clobber-state.log'
18CLOBBER_LOG_FILE = '/mnt/stateful_partition/unencrypted/clobber.log'
19
20
21class platform_Powerwash(update_engine_test.UpdateEngineTest):
22    """Powerwash a device."""
23    version = 1
24
25    def cleanup(self):
26        """Restore stateful so the DUT is usable by other tests."""
27        self._restore_stateful()
28
29    def run_once(self, job_repo_url=None):
30        """
31        Main function for the test.
32
33        @param job_repo_url: String used to allow the test to figure out a
34                             devserver and stateful payload to use.
35
36        """
37        # Setup the job_repo_url for this test run.
38        self._job_repo_url = self._get_job_repo_url(job_repo_url)
39
40        count_before = self._powerwash_count()
41
42        # We create a file on the stateful partition to test if it is deleted
43        # during the powerwash.
44        self._host.run('echo car > %s' % STATEFUL_MARKER_FILE)
45
46        logging.debug('Signaling powerwash on the device.')
47        self._mark_powerwash()
48        self._host.reboot()
49
50        # Check if the marker file still exists on the stateful partition.
51        # The powerwash cycle should remove it.
52        marker = self._host.run('[ -e %s ]' % STATEFUL_MARKER_FILE,
53                                ignore_status=True, ignore_timeout=True)
54
55        # If "[ -e file ]" finishes with status 0, the file is present.
56        if marker is None or marker.exit_status == 0:
57            raise error.TestFail("Powerwash cycle didn't remove the marker "
58                                 "file on the stateful partition.")
59
60        # Capture powerwash logs.
61        logging.debug('Powerwash logs: %r', self._host.run(
62                'cat %s %s 2>/dev/null' % (CLOBBER_LOG_FILE,
63                                           CLOBBER_STATE_LOG_FILE),
64                ignore_status=True).stdout.strip())
65
66        # Check the powerwash counter before and after the powerwash to verify
67        # it was incremented. This file should be preserved by the powerwash.
68        count_after = self._powerwash_count()
69        if count_after != count_before + 1:
70            raise error.TestFail("Powerwash count didn't increase after "
71                                 "powerwash cycle.")
72
73
74    def _mark_powerwash(self, command=None):
75        """Creates the Powerwash marker file on the host with the given command.
76
77        @param command: The text to include on the marker file, *not* including
78                        the '\n' at the end.
79        """
80        if command is None:
81            command = POWERWASH_COMMAND
82        self._host.run("echo '%s' > %s" % (command, POWERWASH_MARKER_FILE))
83
84
85    def _powerwash_count(self):
86        """Return the powerwash count from the DUT."""
87        count = self._host.run('test -e %s && cat %s || true' %
88                               (POWERWASH_COUNT,
89                                POWERWASH_COUNT)).stdout.strip()
90        logging.debug('Powerwash count is: %r', count)
91        if count:
92            return int(count)
93        return 0
94