xref: /aosp_15_r20/tools/acloud/hostcleanup/host_cleanup_runner.py (revision 800a58d989c669b8eb8a71d8df53b1ba3d411444)
1*800a58d9SAndroid Build Coastguard Worker# Copyright 2021 - The Android Open Source Project
2*800a58d9SAndroid Build Coastguard Worker#
3*800a58d9SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*800a58d9SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*800a58d9SAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*800a58d9SAndroid Build Coastguard Worker#
7*800a58d9SAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*800a58d9SAndroid Build Coastguard Worker#
9*800a58d9SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*800a58d9SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*800a58d9SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*800a58d9SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*800a58d9SAndroid Build Coastguard Worker# limitations under the License.
14*800a58d9SAndroid Build Coastguard Workerr"""host cleanup runner
15*800a58d9SAndroid Build Coastguard Worker
16*800a58d9SAndroid Build Coastguard WorkerA host cleanup sub task runner will cleanup host to a pristine state.
17*800a58d9SAndroid Build Coastguard Worker"""
18*800a58d9SAndroid Build Coastguard Worker
19*800a58d9SAndroid Build Coastguard Workerfrom __future__ import print_function
20*800a58d9SAndroid Build Coastguard Worker
21*800a58d9SAndroid Build Coastguard Workerimport logging
22*800a58d9SAndroid Build Coastguard Workerimport os
23*800a58d9SAndroid Build Coastguard Workerimport subprocess
24*800a58d9SAndroid Build Coastguard Workerimport textwrap
25*800a58d9SAndroid Build Coastguard Worker
26*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal import constants
27*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import utils
28*800a58d9SAndroid Build Coastguard Workerfrom acloud.setup import base_task_runner
29*800a58d9SAndroid Build Coastguard Workerfrom acloud.setup import setup_common
30*800a58d9SAndroid Build Coastguard Worker
31*800a58d9SAndroid Build Coastguard Workerlogger = logging.getLogger(__name__)
32*800a58d9SAndroid Build Coastguard Worker
33*800a58d9SAndroid Build Coastguard Worker_PARAGRAPH_BREAK = "="
34*800a58d9SAndroid Build Coastguard Worker_PURGE_PACKAGE_CMD = "sudo apt-get purge --assume-yes %s"
35*800a58d9SAndroid Build Coastguard Worker_UNINSTALL_SUCCESS_MSG = "Package(s) [%s] have uninstalled."
36*800a58d9SAndroid Build Coastguard Worker
37*800a58d9SAndroid Build Coastguard Worker
38*800a58d9SAndroid Build Coastguard Workerclass BasePurger(base_task_runner.BaseTaskRunner):
39*800a58d9SAndroid Build Coastguard Worker    """Subtask base runner class for hostcleanup."""
40*800a58d9SAndroid Build Coastguard Worker
41*800a58d9SAndroid Build Coastguard Worker    PURGE_MESSAGE_TITLE = ""
42*800a58d9SAndroid Build Coastguard Worker    PURGE_MESSAGE = ""
43*800a58d9SAndroid Build Coastguard Worker
44*800a58d9SAndroid Build Coastguard Worker    cmds = []
45*800a58d9SAndroid Build Coastguard Worker    purge_packages = []
46*800a58d9SAndroid Build Coastguard Worker
47*800a58d9SAndroid Build Coastguard Worker    def ShouldRun(self):
48*800a58d9SAndroid Build Coastguard Worker        """Check if required packages are all uninstalled.
49*800a58d9SAndroid Build Coastguard Worker
50*800a58d9SAndroid Build Coastguard Worker        Returns:
51*800a58d9SAndroid Build Coastguard Worker            Boolean, True if command list not null.
52*800a58d9SAndroid Build Coastguard Worker        """
53*800a58d9SAndroid Build Coastguard Worker        if not utils.IsSupportedPlatform():
54*800a58d9SAndroid Build Coastguard Worker            return False
55*800a58d9SAndroid Build Coastguard Worker
56*800a58d9SAndroid Build Coastguard Worker        if self.cmds:
57*800a58d9SAndroid Build Coastguard Worker            return True
58*800a58d9SAndroid Build Coastguard Worker
59*800a58d9SAndroid Build Coastguard Worker        utils.PrintColorString(
60*800a58d9SAndroid Build Coastguard Worker            "[%s]: don't have to process." % self.PURGE_MESSAGE_TITLE,
61*800a58d9SAndroid Build Coastguard Worker            utils.TextColors.WARNING)
62*800a58d9SAndroid Build Coastguard Worker        return False
63*800a58d9SAndroid Build Coastguard Worker
64*800a58d9SAndroid Build Coastguard Worker    def _Run(self):
65*800a58d9SAndroid Build Coastguard Worker        """Run purge commands."""
66*800a58d9SAndroid Build Coastguard Worker        utils.PrintColorString("Below commands will be run: \n%s" %
67*800a58d9SAndroid Build Coastguard Worker                               "\n".join(self.cmds))
68*800a58d9SAndroid Build Coastguard Worker
69*800a58d9SAndroid Build Coastguard Worker        answer_client = utils.InteractWithQuestion(
70*800a58d9SAndroid Build Coastguard Worker            "\nPress 'y' to continue or anything else to do it myself[y/N]: ",
71*800a58d9SAndroid Build Coastguard Worker            utils.TextColors.WARNING)
72*800a58d9SAndroid Build Coastguard Worker        if answer_client not in constants.USER_ANSWER_YES:
73*800a58d9SAndroid Build Coastguard Worker            return
74*800a58d9SAndroid Build Coastguard Worker
75*800a58d9SAndroid Build Coastguard Worker        for cmd in self.cmds:
76*800a58d9SAndroid Build Coastguard Worker            try:
77*800a58d9SAndroid Build Coastguard Worker                setup_common.CheckCmdOutput(cmd,
78*800a58d9SAndroid Build Coastguard Worker                                            shell=True,
79*800a58d9SAndroid Build Coastguard Worker                                            stderr=subprocess.STDOUT)
80*800a58d9SAndroid Build Coastguard Worker            except subprocess.CalledProcessError as cpe:
81*800a58d9SAndroid Build Coastguard Worker                logger.error("Run command [%s] failed: %s",
82*800a58d9SAndroid Build Coastguard Worker                             cmd, cpe.output)
83*800a58d9SAndroid Build Coastguard Worker
84*800a58d9SAndroid Build Coastguard Worker        utils.PrintColorString((_UNINSTALL_SUCCESS_MSG %
85*800a58d9SAndroid Build Coastguard Worker                                ",".join(self.purge_packages)),
86*800a58d9SAndroid Build Coastguard Worker                               utils.TextColors.OKGREEN)
87*800a58d9SAndroid Build Coastguard Worker
88*800a58d9SAndroid Build Coastguard Worker    def PrintPurgeMessage(self):
89*800a58d9SAndroid Build Coastguard Worker        """Print purge message"""
90*800a58d9SAndroid Build Coastguard Worker        # define the layout of message.
91*800a58d9SAndroid Build Coastguard Worker        console_width = int(os.popen('stty size', 'r').read().split()[1])
92*800a58d9SAndroid Build Coastguard Worker        break_width = int(console_width / 2)
93*800a58d9SAndroid Build Coastguard Worker
94*800a58d9SAndroid Build Coastguard Worker        # start to print purge message.
95*800a58d9SAndroid Build Coastguard Worker        print("\n" + _PARAGRAPH_BREAK * break_width)
96*800a58d9SAndroid Build Coastguard Worker        print(" [%s] " % self.PURGE_MESSAGE_TITLE)
97*800a58d9SAndroid Build Coastguard Worker        print(textwrap.fill(
98*800a58d9SAndroid Build Coastguard Worker            self.PURGE_MESSAGE,
99*800a58d9SAndroid Build Coastguard Worker            break_width - 2,
100*800a58d9SAndroid Build Coastguard Worker            initial_indent=" ",
101*800a58d9SAndroid Build Coastguard Worker            subsequent_indent=" "))
102*800a58d9SAndroid Build Coastguard Worker        print(_PARAGRAPH_BREAK * break_width + "\n")
103*800a58d9SAndroid Build Coastguard Worker
104*800a58d9SAndroid Build Coastguard Worker
105*800a58d9SAndroid Build Coastguard Workerclass PackagesUninstaller(BasePurger):
106*800a58d9SAndroid Build Coastguard Worker    """Subtask base runner class for uninstalling packages."""
107*800a58d9SAndroid Build Coastguard Worker
108*800a58d9SAndroid Build Coastguard Worker    PURGE_MESSAGE_TITLE = "Uninstalling packages"
109*800a58d9SAndroid Build Coastguard Worker    PURGE_MESSAGE = ("This will uninstall packages installed previously "
110*800a58d9SAndroid Build Coastguard Worker                     "through \"acloud setup --host-setup\"")
111*800a58d9SAndroid Build Coastguard Worker
112*800a58d9SAndroid Build Coastguard Worker    def __init__(self):
113*800a58d9SAndroid Build Coastguard Worker        """Initialize."""
114*800a58d9SAndroid Build Coastguard Worker        packages = []
115*800a58d9SAndroid Build Coastguard Worker        packages.extend(constants.AVD_REQUIRED_PKGS)
116*800a58d9SAndroid Build Coastguard Worker        packages.extend(constants.BASE_REQUIRED_PKGS)
117*800a58d9SAndroid Build Coastguard Worker        packages.append(constants.CUTTLEFISH_COMMOM_PKG)
118*800a58d9SAndroid Build Coastguard Worker
119*800a58d9SAndroid Build Coastguard Worker        self.purge_packages = [pkg for pkg in packages
120*800a58d9SAndroid Build Coastguard Worker                               if setup_common.PackageInstalled(pkg)]
121*800a58d9SAndroid Build Coastguard Worker
122*800a58d9SAndroid Build Coastguard Worker        self.cmds = [
123*800a58d9SAndroid Build Coastguard Worker            _PURGE_PACKAGE_CMD % pkg for pkg in self.purge_packages]
124*800a58d9SAndroid Build Coastguard Worker
125*800a58d9SAndroid Build Coastguard Worker        self.PrintPurgeMessage()
126