Setup users host env for local instance support
- Setup flow controller in setup.py
- Define common method in base_task_runner.py
- Required package installer in host_setup_runner.py
- Host env configuration in host_setup_runner.py
Bug: 110388133
Test: ./run_tests.sh, m acloud && acloud setup.
Change-Id: Id8b988149d606553d31dfb466e0ae14883513553
diff --git a/setup/host_setup_runner.py b/setup/host_setup_runner.py
new file mode 100644
index 0000000..569a16d
--- /dev/null
+++ b/setup/host_setup_runner.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python
+#
+# Copyright 2018 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+r"""host setup runner
+
+A setup sub task runner to support setting up the local host for AVD local
+instance.
+"""
+
+from __future__ import print_function
+
+import getpass
+import grp
+import logging
+import os
+import platform
+
+from acloud.internal import constants
+from acloud.internal.lib import utils
+from acloud.setup import base_task_runner
+from acloud.setup import setup_common
+
+logger = logging.getLogger(__name__)
+
+# Install cuttlefish-common will probably not work now.
+# TODO: update this to pull from the proper repo.
+_CUTTLEFISH_REQUIRED_PKGS = ["cuttlefish-common"]
+# dict of supported system and their distributions.
+_SUPPORTED_SYSTEMS_AND_DISTS = {"Linux": ["Ubuntu", "Debian"]}
+_LIST_OF_GROUPS = ["kvm", "libvirt", "cvdnetwork"]
+_LIST_OF_MODULES = ["kvm_intel", "kvm"]
+
+
+def _IsSupportedPlatform():
+ """Check if user's os is the supported platform.
+
+ Returns:
+ Boolean, True if user is using supported platform.
+ """
+ system = platform.system()
+ dist = platform.linux_distribution()[0]
+ platform_supported = (system in _SUPPORTED_SYSTEMS_AND_DISTS and
+ dist in _SUPPORTED_SYSTEMS_AND_DISTS[system])
+
+ logger.info("supported system and dists: %s",
+ _SUPPORTED_SYSTEMS_AND_DISTS)
+ logger.info("%s[%s] %s supported platform",
+ system,
+ dist,
+ "is a" if platform_supported else "is not a")
+
+ return platform_supported
+
+
+class CuttlefishPkgInstaller(base_task_runner.BaseTaskRunner):
+ """Subtask runner class for installing required packages."""
+
+ WELCOME_MESSAGE_TITLE = "Install required package for host setup"
+ WELCOME_MESSAGE = (
+ "This step will walk you through the required packages installation for "
+ "running Android cuttlefish devices on your host.")
+
+ def ShouldRun(self):
+ """Check if required packages are all installed.
+
+ Returns:
+ Boolean, True if required packages are not installed.
+ """
+ if not _IsSupportedPlatform():
+ return False
+
+ # Any required package is not installed or not up-to-date will need to
+ # run installation task.
+ for pkg_name in _CUTTLEFISH_REQUIRED_PKGS:
+ if not setup_common.PackageInstalled(pkg_name):
+ return True
+
+ return False
+
+ def _Run(self):
+ """Install Cuttlefish-common package."""
+
+ logger.info("Start to install required package: %s ",
+ _CUTTLEFISH_REQUIRED_PKGS)
+
+ for pkg in _CUTTLEFISH_REQUIRED_PKGS:
+ setup_common.InstallPackage(pkg)
+
+ logger.info("All required package are installed now.")
+
+
+class CuttlefishHostSetup(base_task_runner.BaseTaskRunner):
+ """Subtask class that setup host for cuttlefish."""
+
+ WELCOME_MESSAGE_TITLE = "Host Enviornment Setup"
+ WELCOME_MESSAGE = (
+ "This step will help you to setup enviornment for running Android "
+ "cuttlefish devices on your host. That includes adding user to kvm "
+ "related groups and checking required linux modules."
+ )
+
+ def ShouldRun(self):
+ """Check host user groups and modules.
+
+ Returns:
+ Boolean: False if user is in all required groups and all modules
+ are reloaded.
+ """
+ if not _IsSupportedPlatform():
+ return False
+
+ return not (self._CheckUserInGroups(_LIST_OF_GROUPS)
+ and self._CheckLoadedModules(_LIST_OF_MODULES))
+
+ @staticmethod
+ def _CheckUserInGroups(group_name_list):
+ """Check if the current user is in the group.
+
+ Args:
+ group_name_list: The list of group name.
+ Returns:
+ True if current user is in all the groups.
+ """
+ logger.info("Checking if user is in following groups: %s", group_name_list)
+ current_groups = [grp.getgrgid(g).gr_name for g in os.getgroups()]
+ all_groups_present = True
+ for group in group_name_list:
+ if group not in current_groups:
+ all_groups_present = False
+ logger.info("missing group: %s", group)
+ return all_groups_present
+
+ @staticmethod
+ def _CheckLoadedModules(module_list):
+ """Check if the modules are all in use.
+
+ Args:
+ module_list: The list of module name.
+ Returns:
+ True if all modules are in use.
+ """
+ logger.info("Checking if modules are loaded: %s", module_list)
+ lsmod_output = setup_common.CheckCmdOutput("lsmod", print_cmd=False)
+ current_modules = [r.split()[0] for r in lsmod_output.splitlines()]
+ all_modules_present = True
+ for module in module_list:
+ if module not in current_modules:
+ logger.info("missing module: %s", module)
+ all_modules_present = False
+ return all_modules_present
+
+ def _Run(self):
+ """Setup host environment for local cuttlefish instance support."""
+ # TODO: provide --uid args to let user use prefered username
+ username = getpass.getuser()
+ setup_cmds = [
+ "sudo rmmod kvm_intel",
+ "sudo rmmod kvm",
+ "sudo modprobe kvm",
+ "sudo modprobe kvm_intel"]
+ for group in _LIST_OF_GROUPS:
+ setup_cmds.append("sudo usermod -aG %s % s" % (group, username))
+
+ print("Below commands will be run:")
+ for setup_cmd in setup_cmds:
+ print(setup_cmd)
+
+ if self._ConfirmContinue():
+ for setup_cmd in setup_cmds:
+ setup_common.CheckCmdOutput(setup_cmd, shell=True)
+ print("Host environment setup has done!")
+
+ @staticmethod
+ def _ConfirmContinue():
+ """Ask user if they want to continue.
+
+ Returns:
+ True if user answer yes.
+ """
+ answer_client = utils.InteractWithQuestion(
+ "\nPress 'y' to continue or anything else to do it myself:[y]",
+ utils.TextColors.WARNING)
+ return answer_client in constants.USER_ANSWER_YES