blob: 7869caec551f574c773a8dba5d92b61f7a652f6f [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.
chojoyce1b818bb2018-10-03 16:34:57 +080039_AVD_REQUIRED_PKGS = ["cuttlefish-common", "ssvnc"]
Sam Chiu81bdc652018-06-29 18:45:08 +080040# dict of supported system and their distributions.
41_SUPPORTED_SYSTEMS_AND_DISTS = {"Linux": ["Ubuntu", "Debian"]}
42_LIST_OF_GROUPS = ["kvm", "libvirt", "cvdnetwork"]
43_LIST_OF_MODULES = ["kvm_intel", "kvm"]
44
45
46def _IsSupportedPlatform():
47 """Check if user's os is the supported platform.
48
49 Returns:
50 Boolean, True if user is using supported platform.
51 """
52 system = platform.system()
53 dist = platform.linux_distribution()[0]
54 platform_supported = (system in _SUPPORTED_SYSTEMS_AND_DISTS and
55 dist in _SUPPORTED_SYSTEMS_AND_DISTS[system])
56
57 logger.info("supported system and dists: %s",
58 _SUPPORTED_SYSTEMS_AND_DISTS)
59 logger.info("%s[%s] %s supported platform",
60 system,
61 dist,
62 "is a" if platform_supported else "is not a")
63
64 return platform_supported
65
66
chojoyce1b818bb2018-10-03 16:34:57 +080067class AvdPkgInstaller(base_task_runner.BaseTaskRunner):
Sam Chiu81bdc652018-06-29 18:45:08 +080068 """Subtask runner class for installing required packages."""
69
70 WELCOME_MESSAGE_TITLE = "Install required package for host setup"
71 WELCOME_MESSAGE = (
72 "This step will walk you through the required packages installation for "
chojoyce1b818bb2018-10-03 16:34:57 +080073 "running Android cuttlefish devices and vnc on your host.")
Sam Chiu81bdc652018-06-29 18:45:08 +080074
75 def ShouldRun(self):
76 """Check if required packages are all installed.
77
78 Returns:
79 Boolean, True if required packages are not installed.
80 """
81 if not _IsSupportedPlatform():
82 return False
83
84 # Any required package is not installed or not up-to-date will need to
85 # run installation task.
chojoyce1b818bb2018-10-03 16:34:57 +080086 for pkg_name in _AVD_REQUIRED_PKGS:
Sam Chiu81bdc652018-06-29 18:45:08 +080087 if not setup_common.PackageInstalled(pkg_name):
88 return True
89
90 return False
91
92 def _Run(self):
93 """Install Cuttlefish-common package."""
94
95 logger.info("Start to install required package: %s ",
chojoyce1b818bb2018-10-03 16:34:57 +080096 _AVD_REQUIRED_PKGS)
Sam Chiu81bdc652018-06-29 18:45:08 +080097
chojoyce1b818bb2018-10-03 16:34:57 +080098 for pkg in _AVD_REQUIRED_PKGS:
Sam Chiu81bdc652018-06-29 18:45:08 +080099 setup_common.InstallPackage(pkg)
100
101 logger.info("All required package are installed now.")
102
103
104class CuttlefishHostSetup(base_task_runner.BaseTaskRunner):
105 """Subtask class that setup host for cuttlefish."""
106
107 WELCOME_MESSAGE_TITLE = "Host Enviornment Setup"
108 WELCOME_MESSAGE = (
109 "This step will help you to setup enviornment for running Android "
110 "cuttlefish devices on your host. That includes adding user to kvm "
111 "related groups and checking required linux modules."
112 )
113
114 def ShouldRun(self):
115 """Check host user groups and modules.
116
117 Returns:
118 Boolean: False if user is in all required groups and all modules
119 are reloaded.
120 """
121 if not _IsSupportedPlatform():
122 return False
123
124 return not (self._CheckUserInGroups(_LIST_OF_GROUPS)
125 and self._CheckLoadedModules(_LIST_OF_MODULES))
126
127 @staticmethod
128 def _CheckUserInGroups(group_name_list):
129 """Check if the current user is in the group.
130
131 Args:
132 group_name_list: The list of group name.
133 Returns:
134 True if current user is in all the groups.
135 """
136 logger.info("Checking if user is in following groups: %s", group_name_list)
137 current_groups = [grp.getgrgid(g).gr_name for g in os.getgroups()]
138 all_groups_present = True
139 for group in group_name_list:
140 if group not in current_groups:
141 all_groups_present = False
142 logger.info("missing group: %s", group)
143 return all_groups_present
144
145 @staticmethod
146 def _CheckLoadedModules(module_list):
147 """Check if the modules are all in use.
148
149 Args:
150 module_list: The list of module name.
151 Returns:
152 True if all modules are in use.
153 """
154 logger.info("Checking if modules are loaded: %s", module_list)
155 lsmod_output = setup_common.CheckCmdOutput("lsmod", print_cmd=False)
156 current_modules = [r.split()[0] for r in lsmod_output.splitlines()]
157 all_modules_present = True
158 for module in module_list:
159 if module not in current_modules:
160 logger.info("missing module: %s", module)
161 all_modules_present = False
162 return all_modules_present
163
164 def _Run(self):
165 """Setup host environment for local cuttlefish instance support."""
166 # TODO: provide --uid args to let user use prefered username
167 username = getpass.getuser()
168 setup_cmds = [
169 "sudo rmmod kvm_intel",
170 "sudo rmmod kvm",
171 "sudo modprobe kvm",
172 "sudo modprobe kvm_intel"]
173 for group in _LIST_OF_GROUPS:
174 setup_cmds.append("sudo usermod -aG %s % s" % (group, username))
175
176 print("Below commands will be run:")
177 for setup_cmd in setup_cmds:
178 print(setup_cmd)
179
180 if self._ConfirmContinue():
181 for setup_cmd in setup_cmds:
182 setup_common.CheckCmdOutput(setup_cmd, shell=True)
183 print("Host environment setup has done!")
184
185 @staticmethod
186 def _ConfirmContinue():
187 """Ask user if they want to continue.
188
189 Returns:
190 True if user answer yes.
191 """
192 answer_client = utils.InteractWithQuestion(
193 "\nPress 'y' to continue or anything else to do it myself:[y]",
194 utils.TextColors.WARNING)
195 return answer_client in constants.USER_ANSWER_YES