blob: a334c2c0964667b2ec086d19ba78d2c820ceb159 [file] [log] [blame]
Sam Chiu81bdc652018-06-29 18:45:08 +08001#!/usr/bin/env python
2#
3# Copyright 2018 - The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16r"""host setup runner
17
18A setup sub task runner to support setting up the local host for AVD local
19instance.
20"""
21
22from __future__ import print_function
23
24import getpass
Sam Chiu81bdc652018-06-29 18:45:08 +080025import logging
Sam Chiuaa703b62019-10-04 19:47:43 +080026import sys
Sam Chiu81bdc652018-06-29 18:45:08 +080027
28from acloud.internal import constants
29from acloud.internal.lib import utils
30from acloud.setup import base_task_runner
31from acloud.setup import setup_common
32
herbertxue1512f8a2019-06-27 13:56:23 +080033
Sam Chiu81bdc652018-06-29 18:45:08 +080034logger = logging.getLogger(__name__)
35
36# Install cuttlefish-common will probably not work now.
37# TODO: update this to pull from the proper repo.
Kevin Chengeb997272019-06-05 14:53:18 -070038_AVD_REQUIRED_PKGS = ["cuttlefish-common",
Kevin Chengf756bbd2018-10-11 13:50:00 -070039 # TODO(b/117613492): This is all qemu related, take this
40 # out once they are added back in as deps for
41 # cuttlefish-common.
42 "qemu-kvm", "qemu-system-common", "qemu-system-x86",
43 "qemu-utils", "libvirt-clients", "libvirt-daemon-system"]
Kevin Chengeb997272019-06-05 14:53:18 -070044_BASE_REQUIRED_PKGS = ["ssvnc", "lzop"]
Sam Chiu81bdc652018-06-29 18:45:08 +080045_LIST_OF_MODULES = ["kvm_intel", "kvm"]
Kevin Chengf756bbd2018-10-11 13:50:00 -070046_UPDATE_APT_GET_CMD = "sudo apt-get update"
Sam Chiu81bdc652018-06-29 18:45:08 +080047
48
Kevin Chengeb997272019-06-05 14:53:18 -070049class BasePkgInstaller(base_task_runner.BaseTaskRunner):
50 """Subtask base runner class for installing packages."""
Sam Chiu81bdc652018-06-29 18:45:08 +080051
Kevin Chengeb997272019-06-05 14:53:18 -070052 # List of packages for child classes to override.
53 PACKAGES = []
Sam Chiu81bdc652018-06-29 18:45:08 +080054
55 def ShouldRun(self):
56 """Check if required packages are all installed.
57
58 Returns:
59 Boolean, True if required packages are not installed.
60 """
Sam Chiu6c738d62018-12-04 10:29:02 +080061 if not utils.IsSupportedPlatform():
Sam Chiu81bdc652018-06-29 18:45:08 +080062 return False
63
64 # Any required package is not installed or not up-to-date will need to
65 # run installation task.
Kevin Chengeb997272019-06-05 14:53:18 -070066 for pkg_name in self.PACKAGES:
Sam Chiu81bdc652018-06-29 18:45:08 +080067 if not setup_common.PackageInstalled(pkg_name):
68 return True
69
70 return False
71
72 def _Run(self):
Kevin Chengeb997272019-06-05 14:53:18 -070073 """Install specified packages."""
Sam Chiuaa703b62019-10-04 19:47:43 +080074 cmd = "\n".join(
75 [setup_common.PKG_INSTALL_CMD % pkg
76 for pkg in self.PACKAGES
77 if not setup_common.PackageInstalled(pkg)])
Sam Chiu81bdc652018-06-29 18:45:08 +080078
Sam Chiuaa703b62019-10-04 19:47:43 +080079 if not utils.GetUserAnswerYes("\nStart to install package(s):\n%s"
80 "\nPress 'y' to continue or anything "
81 "else to do it myself and run acloud "
82 "again[y/N]: " % cmd):
83 sys.exit(constants.EXIT_BY_USER)
Sam Chiu81bdc652018-06-29 18:45:08 +080084
Kevin Chengf756bbd2018-10-11 13:50:00 -070085 setup_common.CheckCmdOutput(_UPDATE_APT_GET_CMD, shell=True)
Kevin Chengeb997272019-06-05 14:53:18 -070086 for pkg in self.PACKAGES:
Sam Chiu81bdc652018-06-29 18:45:08 +080087 setup_common.InstallPackage(pkg)
88
Kevin Chengeb997272019-06-05 14:53:18 -070089 logger.info("All package(s) installed now.")
90
91
92class AvdPkgInstaller(BasePkgInstaller):
93 """Subtask runner class for installing packages for local instances."""
94
95 WELCOME_MESSAGE_TITLE = ("Install required packages for host setup for "
96 "local instances")
97 WELCOME_MESSAGE = ("This step will walk you through the required packages "
98 "installation for running Android cuttlefish devices "
99 "on your host.")
100 PACKAGES = _AVD_REQUIRED_PKGS
101
102
103class HostBasePkgInstaller(BasePkgInstaller):
104 """Subtask runner class for installing base host packages."""
105
106 WELCOME_MESSAGE_TITLE = "Install base packages on the host"
107 WELCOME_MESSAGE = ("This step will walk you through the base packages "
108 "installation for your host.")
109 PACKAGES = _BASE_REQUIRED_PKGS
Sam Chiu81bdc652018-06-29 18:45:08 +0800110
111
112class CuttlefishHostSetup(base_task_runner.BaseTaskRunner):
113 """Subtask class that setup host for cuttlefish."""
114
115 WELCOME_MESSAGE_TITLE = "Host Enviornment Setup"
116 WELCOME_MESSAGE = (
117 "This step will help you to setup enviornment for running Android "
118 "cuttlefish devices on your host. That includes adding user to kvm "
119 "related groups and checking required linux modules."
120 )
121
122 def ShouldRun(self):
123 """Check host user groups and modules.
124
125 Returns:
126 Boolean: False if user is in all required groups and all modules
127 are reloaded.
128 """
Sam Chiu6c738d62018-12-04 10:29:02 +0800129 if not utils.IsSupportedPlatform():
Sam Chiu81bdc652018-06-29 18:45:08 +0800130 return False
131
herbertxue07293a32018-11-05 20:40:11 +0800132 return not (utils.CheckUserInGroups(constants.LIST_CF_USER_GROUPS)
Sam Chiu81bdc652018-06-29 18:45:08 +0800133 and self._CheckLoadedModules(_LIST_OF_MODULES))
134
135 @staticmethod
Sam Chiu81bdc652018-06-29 18:45:08 +0800136 def _CheckLoadedModules(module_list):
137 """Check if the modules are all in use.
138
139 Args:
140 module_list: The list of module name.
141 Returns:
142 True if all modules are in use.
143 """
144 logger.info("Checking if modules are loaded: %s", module_list)
145 lsmod_output = setup_common.CheckCmdOutput("lsmod", print_cmd=False)
146 current_modules = [r.split()[0] for r in lsmod_output.splitlines()]
147 all_modules_present = True
148 for module in module_list:
149 if module not in current_modules:
150 logger.info("missing module: %s", module)
151 all_modules_present = False
152 return all_modules_present
153
154 def _Run(self):
155 """Setup host environment for local cuttlefish instance support."""
156 # TODO: provide --uid args to let user use prefered username
157 username = getpass.getuser()
158 setup_cmds = [
159 "sudo rmmod kvm_intel",
160 "sudo rmmod kvm",
161 "sudo modprobe kvm",
162 "sudo modprobe kvm_intel"]
Sam Chiuafbc6582018-09-04 20:47:13 +0800163 for group in constants.LIST_CF_USER_GROUPS:
Sam Chiu81bdc652018-06-29 18:45:08 +0800164 setup_cmds.append("sudo usermod -aG %s % s" % (group, username))
165
166 print("Below commands will be run:")
167 for setup_cmd in setup_cmds:
168 print(setup_cmd)
169
170 if self._ConfirmContinue():
171 for setup_cmd in setup_cmds:
172 setup_common.CheckCmdOutput(setup_cmd, shell=True)
173 print("Host environment setup has done!")
174
175 @staticmethod
176 def _ConfirmContinue():
177 """Ask user if they want to continue.
178
179 Returns:
180 True if user answer yes.
181 """
182 answer_client = utils.InteractWithQuestion(
Sam Chiu705b9012019-01-19 12:11:35 +0800183 "\nPress 'y' to continue or anything else to do it myself[y/N]: ",
Sam Chiu81bdc652018-06-29 18:45:08 +0800184 utils.TextColors.WARNING)
185 return answer_client in constants.USER_ANSWER_YES