blob: 392fc34a20e46f0cc51d762c7f2bb962d13738b2 [file] [log] [blame]
Kevin Cheng3087af52018-08-13 13:26:50 -07001#!/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"""Create entry point.
17
18Create will handle all the logic related to creating a local/remote instance
19an Android Virtual Device and the logic related to prepping the local/remote
20image artifacts.
21"""
22
Kevin Chengcc6bf0d2018-10-10 14:18:47 -070023from __future__ import print_function
24
Kevin Cheng835a4152018-10-11 10:46:57 -070025import os
26import subprocess
Kevin Chengcc6bf0d2018-10-10 14:18:47 -070027import sys
28
Kevin Cheng3ce4b452018-08-23 14:47:22 -070029from acloud import errors
Kevin Chengc3d0d5e2018-08-14 14:22:44 -070030from acloud.create import avd_spec
Richard Fung97503b22019-02-06 13:43:38 -080031from acloud.create import cheeps_remote_image_remote_instance
chojoyce7a361732018-11-26 16:26:13 +080032from acloud.create import gce_local_image_remote_instance
33from acloud.create import gce_remote_image_remote_instance
Hsin-Yi Chen7ba49962019-09-25 18:58:56 +080034from acloud.create import goldfish_local_image_local_instance
Hsin-Yi Chen36e2d762021-07-30 14:26:42 +080035from acloud.create import goldfish_remote_image_remote_host
herbertxue494891e2019-01-19 13:50:53 +080036from acloud.create import goldfish_remote_image_remote_instance
Kevin Cheng3ce4b452018-08-23 14:47:22 -070037from acloud.create import local_image_local_instance
38from acloud.create import local_image_remote_instance
cyland43f2932019-11-26 17:37:28 +080039from acloud.create import local_image_remote_host
herbertxuedf01c422018-09-06 19:52:52 +080040from acloud.create import remote_image_remote_instance
chojoycecd004bc2018-09-13 10:39:00 +080041from acloud.create import remote_image_local_instance
cyland43f2932019-11-26 17:37:28 +080042from acloud.create import remote_image_remote_host
Kevin Cheng3ce4b452018-08-23 14:47:22 -070043from acloud.internal import constants
Kevin Chengcc6bf0d2018-10-10 14:18:47 -070044from acloud.internal.lib import utils
45from acloud.setup import setup
46from acloud.setup import gcp_setup_runner
47from acloud.setup import host_setup_runner
Kevin Cheng3ce4b452018-08-23 14:47:22 -070048
herbertxue1512f8a2019-06-27 13:56:23 +080049
Kevin Cheng835a4152018-10-11 10:46:57 -070050_MAKE_CMD = "build/soong/soong_ui.bash"
51_MAKE_ARG = "--make-mode"
Sam Chiua8ef70d2020-07-21 12:03:50 +080052_YES = "y"
Kevin Cheng835a4152018-10-11 10:46:57 -070053
chojoyce7a361732018-11-26 16:26:13 +080054_CREATOR_CLASS_DICT = {
55 # GCE types
56 (constants.TYPE_GCE, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_REMOTE):
57 gce_local_image_remote_instance.GceLocalImageRemoteInstance,
58 (constants.TYPE_GCE, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_REMOTE):
59 gce_remote_image_remote_instance.GceRemoteImageRemoteInstance,
60 # CF types
61 (constants.TYPE_CF, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_LOCAL):
62 local_image_local_instance.LocalImageLocalInstance,
63 (constants.TYPE_CF, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_REMOTE):
64 local_image_remote_instance.LocalImageRemoteInstance,
cyland43f2932019-11-26 17:37:28 +080065 (constants.TYPE_CF, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_HOST):
66 local_image_remote_host.LocalImageRemoteHost,
chojoyce7a361732018-11-26 16:26:13 +080067 (constants.TYPE_CF, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_REMOTE):
68 remote_image_remote_instance.RemoteImageRemoteInstance,
69 (constants.TYPE_CF, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_LOCAL):
70 remote_image_local_instance.RemoteImageLocalInstance,
cyland43f2932019-11-26 17:37:28 +080071 (constants.TYPE_CF, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_HOST):
72 remote_image_remote_host.RemoteImageRemoteHost,
Richard Fung97503b22019-02-06 13:43:38 -080073 # Cheeps types
74 (constants.TYPE_CHEEPS, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_REMOTE):
75 cheeps_remote_image_remote_instance.CheepsRemoteImageRemoteInstance,
herbertxue494891e2019-01-19 13:50:53 +080076 # GF types
77 (constants.TYPE_GF, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_REMOTE):
78 goldfish_remote_image_remote_instance.GoldfishRemoteImageRemoteInstance,
Hsin-Yi Chen7ba49962019-09-25 18:58:56 +080079 (constants.TYPE_GF, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_LOCAL):
80 goldfish_local_image_local_instance.GoldfishLocalImageLocalInstance,
Hsin-Yi Chen36e2d762021-07-30 14:26:42 +080081 (constants.TYPE_GF, constants.IMAGE_SRC_REMOTE, constants.INSTANCE_TYPE_HOST):
82 goldfish_remote_image_remote_host.GoldfishRemoteImageRemoteHost,
Peter Collingbournedce6d722020-05-07 15:29:21 -070083 # FVP types
84 (constants.TYPE_FVP, constants.IMAGE_SRC_LOCAL, constants.INSTANCE_TYPE_REMOTE):
85 local_image_remote_instance.LocalImageRemoteInstance,
chojoyce7a361732018-11-26 16:26:13 +080086}
Kevin Cheng3ce4b452018-08-23 14:47:22 -070087
chojoyce7a361732018-11-26 16:26:13 +080088
89def GetAvdCreatorClass(avd_type, instance_type, image_source):
Kevin Cheng3ce4b452018-08-23 14:47:22 -070090 """Return the creator class for the specified spec.
91
92 Based on the image source and the instance type, return the proper
93 creator class.
94
95 Args:
chojoyce7a361732018-11-26 16:26:13 +080096 avd_type: String, the AVD type(cuttlefish, gce).
Kevin Cheng3ce4b452018-08-23 14:47:22 -070097 instance_type: String, the AVD instance type (local or remote).
98 image_source: String, the source of the image (local or remote).
99
100 Returns:
101 An AVD creator class (e.g. LocalImageRemoteInstance).
chojoyce7a361732018-11-26 16:26:13 +0800102
103 Raises:
104 UnsupportedInstanceImageType if argments didn't match _CREATOR_CLASS_DICT.
Kevin Cheng3ce4b452018-08-23 14:47:22 -0700105 """
chojoyce7a361732018-11-26 16:26:13 +0800106 creator_class = _CREATOR_CLASS_DICT.get(
107 (avd_type, image_source, instance_type))
Kevin Cheng3ce4b452018-08-23 14:47:22 -0700108
chojoyce7a361732018-11-26 16:26:13 +0800109 if not creator_class:
110 raise errors.UnsupportedInstanceImageType(
111 "unsupported creation of avd type: %s, instance type: %s, "
112 "image source: %s" % (avd_type, instance_type, image_source))
113 return creator_class
Kevin Cheng3087af52018-08-13 13:26:50 -0700114
Kevin Cheng835a4152018-10-11 10:46:57 -0700115def _CheckForAutoconnect(args):
116 """Check that we have all prerequisites for autoconnect.
117
118 Autoconnect requires adb and ssh, we'll just check for adb for now and
119 assume ssh is everywhere. If adb isn't around, ask the user if they want us
120 to build it, if not we'll disable autoconnect.
121
122 Args:
123 args: Namespace object from argparse.parse_args.
124 """
chojoyce6e30cc52019-11-04 16:18:09 +0800125 if not args.autoconnect or utils.FindExecutable(constants.ADB_BIN):
Kevin Cheng835a4152018-10-11 10:46:57 -0700126 return
127
128 disable_autoconnect = False
Sam Chiua8ef70d2020-07-21 12:03:50 +0800129 answer = _YES if args.no_prompt else utils.InteractWithQuestion(
Kevin Cheng835a4152018-10-11 10:46:57 -0700130 "adb is required for autoconnect, without it autoconnect will be "
Sam Chiu705b9012019-01-19 12:11:35 +0800131 "disabled, would you like acloud to build it[y/N]? ")
Kevin Cheng835a4152018-10-11 10:46:57 -0700132 if answer in constants.USER_ANSWER_YES:
133 utils.PrintColorString("Building adb ... ", end="")
134 android_build_top = os.environ.get(
135 constants.ENV_ANDROID_BUILD_TOP)
136 if not android_build_top:
137 utils.PrintColorString("Fail! (Not in a lunch'd env)",
138 utils.TextColors.FAIL)
139 disable_autoconnect = True
140 else:
141 make_cmd = os.path.join(android_build_top, _MAKE_CMD)
142 build_adb_cmd = [make_cmd, _MAKE_ARG, "adb"]
143 try:
144 with open(os.devnull, "w") as dev_null:
145 subprocess.check_call(build_adb_cmd, stderr=dev_null,
146 stdout=dev_null)
147 utils.PrintColorString("OK!", utils.TextColors.OKGREEN)
148 except subprocess.CalledProcessError:
149 utils.PrintColorString("Fail! (build failed)",
150 utils.TextColors.FAIL)
151 disable_autoconnect = True
152 else:
153 disable_autoconnect = True
154
155 if disable_autoconnect:
156 utils.PrintColorString("Disabling autoconnect",
157 utils.TextColors.WARNING)
158 args.autoconnect = False
159
160
161def _CheckForSetup(args):
Kevin Chengcc6bf0d2018-10-10 14:18:47 -0700162 """Check that host is setup to run the create commands.
163
164 We'll check we have the necessary bits setup to do what the user wants, and
165 if not, tell them what they need to do before running create again.
166
167 Args:
168 args: Namespace object from argparse.parse_args.
169 """
Kevin Chengcc6bf0d2018-10-10 14:18:47 -0700170 # Need to set all these so if we need to run setup, it won't barf on us
171 # because of some missing fields.
172 args.gcp_init = False
173 args.host = False
Kevin Chengeb997272019-06-05 14:53:18 -0700174 args.host_base = False
Kevin Chengcc6bf0d2018-10-10 14:18:47 -0700175 args.force = False
herbertxue4815ca22020-05-31 13:31:53 +0800176 args.update_config = None
Kevin Chengcc6bf0d2018-10-10 14:18:47 -0700177 # Remote image/instance requires the GCP config setup.
chojoyce8a63f1e2021-03-24 16:10:40 +0800178 if args.local_instance is None or args.local_image is None:
Kevin Chengcc6bf0d2018-10-10 14:18:47 -0700179 gcp_setup = gcp_setup_runner.GcpTaskRunner(args.config_file)
180 if gcp_setup.ShouldRun():
181 args.gcp_init = True
Kevin Chengcc6bf0d2018-10-10 14:18:47 -0700182
Kevin Cheng2aa41da2018-10-11 15:00:48 -0700183 # Local instance requires host to be setup. We'll assume that if the
184 # packages were installed, then the user was added into the groups. This
185 # avoids the scenario where a user runs setup and creates a local instance.
186 # The following local instance create will trigger this if statment and go
187 # through the whole setup again even though it's already done because the
188 # user groups aren't set until the user logs out and back in.
chojoyce8a63f1e2021-03-24 16:10:40 +0800189 if args.local_instance is not None:
Kevin Chengcc6bf0d2018-10-10 14:18:47 -0700190 host_pkg_setup = host_setup_runner.AvdPkgInstaller()
Kevin Cheng2aa41da2018-10-11 15:00:48 -0700191 if host_pkg_setup.ShouldRun():
Kevin Chengcc6bf0d2018-10-10 14:18:47 -0700192 args.host = True
Kevin Chengeb997272019-06-05 14:53:18 -0700193
chojoyce574f8f02021-10-27 12:21:03 +0800194 setup_mkcert = False
chojoyce7cac62f2021-06-29 16:03:36 +0800195 if args.autoconnect == constants.INS_KEY_WEBRTC:
196 mkcert_pkg_setup = host_setup_runner.MkcertPkgInstaller()
197 if mkcert_pkg_setup.ShouldRun():
chojoyce574f8f02021-10-27 12:21:03 +0800198 setup_mkcert = True
chojoyce7cac62f2021-06-29 16:03:36 +0800199
Kevin Chengeb997272019-06-05 14:53:18 -0700200 # Install base packages if we haven't already.
201 host_base_setup = host_setup_runner.HostBasePkgInstaller()
202 if host_base_setup.ShouldRun():
203 args.host_base = True
204
chojoyce574f8f02021-10-27 12:21:03 +0800205 run_setup = (args.force or args.gcp_init or args.host or args.host_base
206 or setup_mkcert)
Kevin Chengcc6bf0d2018-10-10 14:18:47 -0700207
208 if run_setup:
209 answer = utils.InteractWithQuestion("Missing necessary acloud setup, "
Sam Chiu705b9012019-01-19 12:11:35 +0800210 "would you like to run setup[y/N]?")
Kevin Chengcc6bf0d2018-10-10 14:18:47 -0700211 if answer in constants.USER_ANSWER_YES:
212 setup.Run(args)
213 else:
214 print("Please run '#acloud setup' so we can get your host setup")
Sam Chiue791f602019-05-03 15:18:10 +0800215 sys.exit(constants.EXIT_BY_USER)
Kevin Chengcc6bf0d2018-10-10 14:18:47 -0700216
217
Kevin Cheng835a4152018-10-11 10:46:57 -0700218def PreRunCheck(args):
219 """Do some pre-run checks to ensure a smooth create experience.
220
221 Args:
222 args: Namespace object from argparse.parse_args.
223 """
224 _CheckForSetup(args)
225 _CheckForAutoconnect(args)
226
227
Kevin Chengc3d0d5e2018-08-14 14:22:44 -0700228def Run(args):
Kevin Cheng3087af52018-08-13 13:26:50 -0700229 """Run create.
230
231 Args:
232 args: Namespace object from argparse.parse_args.
herbertxue48bba082019-12-31 12:12:16 +0800233
234 Returns:
235 A Report instance.
Kevin Cheng3087af52018-08-13 13:26:50 -0700236 """
Kevin Chengfab8cfc2019-06-27 14:01:37 -0700237 if not args.skip_pre_run_check:
238 PreRunCheck(args)
Kevin Chengc3d0d5e2018-08-14 14:22:44 -0700239 spec = avd_spec.AVDSpec(args)
chojoyce7a361732018-11-26 16:26:13 +0800240 avd_creator_class = GetAvdCreatorClass(spec.avd_type,
241 spec.instance_type,
Kevin Cheng3ce4b452018-08-23 14:47:22 -0700242 spec.image_source)
243 avd_creator = avd_creator_class()
herbertxue7ef23b22019-02-27 09:34:24 +0800244 report = avd_creator.Create(spec, args.no_prompt)
herbertxue48bba082019-12-31 12:12:16 +0800245 return report