Add in base host setup.

Add in base host setup task that will install base packages (ssvnc, lzop) and
make it separate from the CF packages since those are only needed for local
instances and base packages could be use for any situation.

Bug: 134582660
Test: atest acloud_test --host
acloud create --local-image (with no /usr/bin/lzop)
acloud setup --host-base
acloud setup

Change-Id: Ic725b546604fa5165efddcddb82209dc3f7c11a6
diff --git a/create/create.py b/create/create.py
index 9dfba02..e4bc76a 100644
--- a/create/create.py
+++ b/create/create.py
@@ -151,18 +151,17 @@
     Args:
         args: Namespace object from argparse.parse_args.
     """
-    run_setup = False
     # Need to set all these so if we need to run setup, it won't barf on us
     # because of some missing fields.
     args.gcp_init = False
     args.host = False
+    args.host_base = False
     args.force = False
     # Remote image/instance requires the GCP config setup.
     if not args.local_instance or args.local_image == "":
         gcp_setup = gcp_setup_runner.GcpTaskRunner(args.config_file)
         if gcp_setup.ShouldRun():
             args.gcp_init = True
-            run_setup = True
 
     # Local instance requires host to be setup. We'll assume that if the
     # packages were installed, then the user was added into the groups. This
@@ -174,7 +173,13 @@
         host_pkg_setup = host_setup_runner.AvdPkgInstaller()
         if host_pkg_setup.ShouldRun():
             args.host = True
-            run_setup = True
+
+    # Install base packages if we haven't already.
+    host_base_setup = host_setup_runner.HostBasePkgInstaller()
+    if host_base_setup.ShouldRun():
+        args.host_base = True
+
+    run_setup = args.force or args.gcp_init or args.host or args.host_base
 
     if run_setup:
         answer = utils.InteractWithQuestion("Missing necessary acloud setup, "
diff --git a/setup/host_setup_runner.py b/setup/host_setup_runner.py
index 6f6e2c3..f994eb1 100644
--- a/setup/host_setup_runner.py
+++ b/setup/host_setup_runner.py
@@ -33,23 +33,22 @@
 
 # Install cuttlefish-common will probably not work now.
 # TODO: update this to pull from the proper repo.
-_AVD_REQUIRED_PKGS = ["cuttlefish-common", "ssvnc",
+_AVD_REQUIRED_PKGS = ["cuttlefish-common",
                       # TODO(b/117613492): This is all qemu related, take this
                       # out once they are added back in as deps for
                       # cuttlefish-common.
                       "qemu-kvm", "qemu-system-common", "qemu-system-x86",
                       "qemu-utils", "libvirt-clients", "libvirt-daemon-system"]
+_BASE_REQUIRED_PKGS = ["ssvnc", "lzop"]
 _LIST_OF_MODULES = ["kvm_intel", "kvm"]
 _UPDATE_APT_GET_CMD = "sudo apt-get update"
 
 
-class AvdPkgInstaller(base_task_runner.BaseTaskRunner):
-    """Subtask runner class for installing required packages."""
+class BasePkgInstaller(base_task_runner.BaseTaskRunner):
+    """Subtask base runner class for installing 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 and vnc on your host.")
+    # List of packages for child classes to override.
+    PACKAGES = []
 
     def ShouldRun(self):
         """Check if required packages are all installed.
@@ -62,23 +61,43 @@
 
         # Any required package is not installed or not up-to-date will need to
         # run installation task.
-        for pkg_name in _AVD_REQUIRED_PKGS:
+        for pkg_name in self.PACKAGES:
             if not setup_common.PackageInstalled(pkg_name):
                 return True
 
         return False
 
     def _Run(self):
-        """Install Cuttlefish-common package."""
+        """Install specified packages."""
 
-        logger.info("Start to install required package: %s ",
-                    _AVD_REQUIRED_PKGS)
+        logger.info("Start to install package(s): %s ",
+                    self.PACKAGES)
 
         setup_common.CheckCmdOutput(_UPDATE_APT_GET_CMD, shell=True)
-        for pkg in _AVD_REQUIRED_PKGS:
+        for pkg in self.PACKAGES:
             setup_common.InstallPackage(pkg)
 
-        logger.info("All required package are installed now.")
+        logger.info("All package(s) installed now.")
+
+
+class AvdPkgInstaller(BasePkgInstaller):
+    """Subtask runner class for installing packages for local instances."""
+
+    WELCOME_MESSAGE_TITLE = ("Install required packages for host setup for "
+                             "local instances")
+    WELCOME_MESSAGE = ("This step will walk you through the required packages "
+                       "installation for running Android cuttlefish devices "
+                       "on your host.")
+    PACKAGES = _AVD_REQUIRED_PKGS
+
+
+class HostBasePkgInstaller(BasePkgInstaller):
+    """Subtask runner class for installing base host packages."""
+
+    WELCOME_MESSAGE_TITLE = "Install base packages on the host"
+    WELCOME_MESSAGE = ("This step will walk you through the base packages "
+                       "installation for your host.")
+    PACKAGES = _BASE_REQUIRED_PKGS
 
 
 class CuttlefishHostSetup(base_task_runner.BaseTaskRunner):
diff --git a/setup/setup.py b/setup/setup.py
index ad498f4..36b6ffd 100644
--- a/setup/setup.py
+++ b/setup/setup.py
@@ -46,15 +46,20 @@
     _PrintWelcomeMessage()
 
     # 2.Init all subtasks in queue and traverse them.
-    host_runner = host_setup_runner.AvdPkgInstaller()
+    host_base_runner = host_setup_runner.HostBasePkgInstaller()
+    host_avd_runner = host_setup_runner.AvdPkgInstaller()
     host_env_runner = host_setup_runner.CuttlefishHostSetup()
     gcp_runner = gcp_setup_runner.GcpTaskRunner(args.config_file)
     task_queue = []
-    # User must explicitly specify --host to install the host packages.
+    # User must explicitly specify --host to install the avd host packages.
     if args.host:
-        task_queue.append(host_runner)
+        task_queue.append(host_base_runner)
+        task_queue.append(host_avd_runner)
         task_queue.append(host_env_runner)
-    if args.gcp_init or not args.host:
+    # We should do these setup tasks if specified or if no args were used.
+    if args.host_base or (not args.host and not args.gcp_init):
+        task_queue.append(host_base_runner)
+    if args.gcp_init or (not args.host and not args.host_base):
         task_queue.append(gcp_runner)
 
     for subtask in task_queue:
diff --git a/setup/setup_args.py b/setup/setup_args.py
index 8a56c35..e3df4de 100644
--- a/setup/setup_args.py
+++ b/setup/setup_args.py
@@ -39,14 +39,21 @@
         dest="host",
         required=False,
         help="Setup host to run local instance of an Android Virtual Device. "
-             "Must explicitly set to kick off host setup.")
+        "Must explicitly set to kick off host setup. Automatically installs "
+        "host base packages as well")
+    setup_parser.add_argument(
+        "--host-base",
+        action="store_true",
+        dest="host_base",
+        required=False,
+        help="Install base packages on the host.")
     setup_parser.add_argument(
         "--gcp-init",
         action="store_true",
         dest="gcp_init",
         required=False,
         help="Setup Google Cloud project name and enable required GCP APIs."
-        "Ex: Google Cloud Storage/ Internal Android Build/ Compute Engine")
+        "E.G. Google Cloud Storage/ Internal Android Build/ Compute Engine")
     setup_parser.add_argument(
         "--force",
         action="store_true",