blob: 156ce4914d3884b2df85243237f7d460d8bb1933 [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
25import grp
26import logging
27import os
28import platform
29
30from acloud.internal import constants
31from acloud.internal.lib import utils
32from acloud.setup import base_task_runner
33from acloud.setup import setup_common
34
35logger = logging.getLogger(__name__)
36
37# Install cuttlefish-common will probably not work now.
38# TODO: update this to pull from the proper repo.
Kevin Chengf756bbd2018-10-11 13:50:00 -070039_AVD_REQUIRED_PKGS = ["cuttlefish-common", "ssvnc",
40 # TODO(b/117613492): This is all qemu related, take this
41 # out once they are added back in as deps for
42 # cuttlefish-common.
43 "qemu-kvm", "qemu-system-common", "qemu-system-x86",
44 "qemu-utils", "libvirt-clients", "libvirt-daemon-system"]
Sam Chiu81bdc652018-06-29 18:45:08 +080045# dict of supported system and their distributions.
46_SUPPORTED_SYSTEMS_AND_DISTS = {"Linux": ["Ubuntu", "Debian"]}
Sam Chiu81bdc652018-06-29 18:45:08 +080047_LIST_OF_MODULES = ["kvm_intel", "kvm"]
Kevin Chengf756bbd2018-10-11 13:50:00 -070048_UPDATE_APT_GET_CMD = "sudo apt-get update"
Sam Chiu81bdc652018-06-29 18:45:08 +080049
50
51def _IsSupportedPlatform():
52 """Check if user's os is the supported platform.
53
54 Returns:
55 Boolean, True if user is using supported platform.
56 """
57 system = platform.system()
58 dist = platform.linux_distribution()[0]
59 platform_supported = (system in _SUPPORTED_SYSTEMS_AND_DISTS and
60 dist in _SUPPORTED_SYSTEMS_AND_DISTS[system])
61
62 logger.info("supported system and dists: %s",
63 _SUPPORTED_SYSTEMS_AND_DISTS)
64 logger.info("%s[%s] %s supported platform",
65 system,
66 dist,
67 "is a" if platform_supported else "is not a")
68
69 return platform_supported
70
71
chojoyce1b818bb2018-10-03 16:34:57 +080072class AvdPkgInstaller(base_task_runner.BaseTaskRunner):
Sam Chiu81bdc652018-06-29 18:45:08 +080073 """Subtask runner class for installing required packages."""
74
75 WELCOME_MESSAGE_TITLE = "Install required package for host setup"
76 WELCOME_MESSAGE = (
77 "This step will walk you through the required packages installation for "
chojoyce1b818bb2018-10-03 16:34:57 +080078 "running Android cuttlefish devices and vnc on your host.")
Sam Chiu81bdc652018-06-29 18:45:08 +080079
80 def ShouldRun(self):
81 """Check if required packages are all installed.
82
83 Returns:
84 Boolean, True if required packages are not installed.
85 """
86 if not _IsSupportedPlatform():
87 return False
88
89 # Any required package is not installed or not up-to-date will need to
90 # run installation task.
chojoyce1b818bb2018-10-03 16:34:57 +080091 for pkg_name in _AVD_REQUIRED_PKGS:
Sam Chiu81bdc652018-06-29 18:45:08 +080092 if not setup_common.PackageInstalled(pkg_name):
93 return True
94
95 return False
96
97 def _Run(self):
98 """Install Cuttlefish-common package."""
99
100 logger.info("Start to install required package: %s ",
chojoyce1b818bb2018-10-03 16:34:57 +0800101 _AVD_REQUIRED_PKGS)
Sam Chiu81bdc652018-06-29 18:45:08 +0800102
Kevin Chengf756bbd2018-10-11 13:50:00 -0700103 setup_common.CheckCmdOutput(_UPDATE_APT_GET_CMD, shell=True)
chojoyce1b818bb2018-10-03 16:34:57 +0800104 for pkg in _AVD_REQUIRED_PKGS:
Sam Chiu81bdc652018-06-29 18:45:08 +0800105 setup_common.InstallPackage(pkg)
106
107 logger.info("All required package are installed now.")
108
109
110class CuttlefishHostSetup(base_task_runner.BaseTaskRunner):
111 """Subtask class that setup host for cuttlefish."""
112
113 WELCOME_MESSAGE_TITLE = "Host Enviornment Setup"
114 WELCOME_MESSAGE = (
115 "This step will help you to setup enviornment for running Android "
116 "cuttlefish devices on your host. That includes adding user to kvm "
117 "related groups and checking required linux modules."
118 )
119
120 def ShouldRun(self):
121 """Check host user groups and modules.
122
123 Returns:
124 Boolean: False if user is in all required groups and all modules
125 are reloaded.
126 """
127 if not _IsSupportedPlatform():
128 return False
129
Sam Chiuafbc6582018-09-04 20:47:13 +0800130 return not (self.CheckUserInGroups(constants.LIST_CF_USER_GROUPS)
Sam Chiu81bdc652018-06-29 18:45:08 +0800131 and self._CheckLoadedModules(_LIST_OF_MODULES))
132
133 @staticmethod
Sam Chiuafbc6582018-09-04 20:47:13 +0800134 def CheckUserInGroups(group_name_list):
Sam Chiu81bdc652018-06-29 18:45:08 +0800135 """Check if the current user is in the group.
136
137 Args:
138 group_name_list: The list of group name.
139 Returns:
140 True if current user is in all the groups.
141 """
142 logger.info("Checking if user is in following groups: %s", group_name_list)
143 current_groups = [grp.getgrgid(g).gr_name for g in os.getgroups()]
144 all_groups_present = True
145 for group in group_name_list:
146 if group not in current_groups:
147 all_groups_present = False
148 logger.info("missing group: %s", group)
149 return all_groups_present
150
151 @staticmethod
152 def _CheckLoadedModules(module_list):
153 """Check if the modules are all in use.
154
155 Args:
156 module_list: The list of module name.
157 Returns:
158 True if all modules are in use.
159 """
160 logger.info("Checking if modules are loaded: %s", module_list)
161 lsmod_output = setup_common.CheckCmdOutput("lsmod", print_cmd=False)
162 current_modules = [r.split()[0] for r in lsmod_output.splitlines()]
163 all_modules_present = True
164 for module in module_list:
165 if module not in current_modules:
166 logger.info("missing module: %s", module)
167 all_modules_present = False
168 return all_modules_present
169
170 def _Run(self):
171 """Setup host environment for local cuttlefish instance support."""
172 # TODO: provide --uid args to let user use prefered username
173 username = getpass.getuser()
174 setup_cmds = [
175 "sudo rmmod kvm_intel",
176 "sudo rmmod kvm",
177 "sudo modprobe kvm",
178 "sudo modprobe kvm_intel"]
Sam Chiuafbc6582018-09-04 20:47:13 +0800179 for group in constants.LIST_CF_USER_GROUPS:
Sam Chiu81bdc652018-06-29 18:45:08 +0800180 setup_cmds.append("sudo usermod -aG %s % s" % (group, username))
181
182 print("Below commands will be run:")
183 for setup_cmd in setup_cmds:
184 print(setup_cmd)
185
186 if self._ConfirmContinue():
187 for setup_cmd in setup_cmds:
188 setup_common.CheckCmdOutput(setup_cmd, shell=True)
189 print("Host environment setup has done!")
190
191 @staticmethod
192 def _ConfirmContinue():
193 """Ask user if they want to continue.
194
195 Returns:
196 True if user answer yes.
197 """
198 answer_client = utils.InteractWithQuestion(
199 "\nPress 'y' to continue or anything else to do it myself:[y]",
200 utils.TextColors.WARNING)
201 return answer_client in constants.USER_ANSWER_YES