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