acloud create: If setup was skipped, tell the user to do it, nicely.

We can tell if the user needs a config file or host setup based on the
create action they specified so instead of raising an exception
somewhere and confusing them, point them to run acloud setup.

Bug: 110383583
Test: acloud create with no ~/.config/acloud/acloud.config
Change-Id: Id0aabbea821f9d9f6f5fc3c5d0ea277284e5bdd7
diff --git a/create/create.py b/create/create.py
index 81710f4..d7ae932 100644
--- a/create/create.py
+++ b/create/create.py
@@ -20,6 +20,10 @@
 image artifacts.
 """
 
+from __future__ import print_function
+
+import sys
+
 from acloud import errors
 from acloud.create import avd_spec
 from acloud.create import local_image_local_instance
@@ -27,6 +31,10 @@
 from acloud.create import remote_image_remote_instance
 from acloud.create import remote_image_local_instance
 from acloud.internal import constants
+from acloud.internal.lib import utils
+from acloud.setup import setup
+from acloud.setup import gcp_setup_runner
+from acloud.setup import host_setup_runner
 
 
 def GetAvdCreatorClass(instance_type, image_source):
@@ -60,12 +68,53 @@
         (instance_type, image_source))
 
 
+def PreRunCheck(args):
+    """Check that host is setup to run the create commands.
+
+    We'll check we have the necessary bits setup to do what the user wants, and
+    if not, tell them what they need to do before running create again.
+
+    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.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.
+    if args.local_instance:
+        host_pkg_setup = host_setup_runner.AvdPkgInstaller()
+        host_env_setup = host_setup_runner.CuttlefishHostSetup()
+        if host_pkg_setup.ShouldRun() or host_env_setup.ShouldRun():
+            args.host = True
+            run_setup = True
+
+    if run_setup:
+        answer = utils.InteractWithQuestion("Missing necessary acloud setup, "
+                                            "would you like to run setup[y]?")
+        if answer in constants.USER_ANSWER_YES:
+            setup.Run(args)
+        else:
+            print("Please run '#acloud setup' so we can get your host setup")
+            sys.exit()
+
+
 def Run(args):
     """Run create.
 
     Args:
         args: Namespace object from argparse.parse_args.
     """
+    PreRunCheck(args)
     spec = avd_spec.AVDSpec(args)
     avd_creator_class = GetAvdCreatorClass(spec.instance_type,
                                            spec.image_source)
diff --git a/setup/gcp_setup_runner.py b/setup/gcp_setup_runner.py
index f50b2c0..30074a5 100644
--- a/setup/gcp_setup_runner.py
+++ b/setup/gcp_setup_runner.py
@@ -198,11 +198,7 @@
         self.storage_bucket_name = cfg.storage_bucket_name
         self.ssh_private_key_path = cfg.ssh_private_key_path
         self.ssh_public_key_path = cfg.ssh_public_key_path
-
-        # Write default stable_host_image_name with dummy value.
-        # TODO(113091773): An additional step to create the host image.
-        if not cfg.stable_host_image_name:
-            UpdateConfigFile(self.config_path, "stable_host_image_name", "")
+        self.stable_host_image_name = cfg.stable_host_image_name
 
     def ShouldRun(self):
         """Check if we actually need to run GCP setup.
@@ -236,9 +232,18 @@
             google_sdk_runner = GoogleSDKBins(google_sdk_init.GetSDKBinPath())
             self._SetupProject(google_sdk_runner)
             self._EnableGcloudServices(google_sdk_runner)
+            self._CreateStableHostImage()
         finally:
             google_sdk_init.CleanUp()
 
+    def _CreateStableHostImage(self):
+        """Create the stable host image."""
+        # Write default stable_host_image_name with dummy value.
+        # TODO(113091773): An additional step to create the host image.
+        if not self.stable_host_image_name:
+            UpdateConfigFile(self.config_path, "stable_host_image_name", "")
+
+
     def _NeedProjectSetup(self):
         """Confirm project setup should run or not.