1*800a58d9SAndroid Build Coastguard Worker# Copyright 2018 - The Android Open Source Project 2*800a58d9SAndroid Build Coastguard Worker# 3*800a58d9SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*800a58d9SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*800a58d9SAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*800a58d9SAndroid Build Coastguard Worker# 7*800a58d9SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*800a58d9SAndroid Build Coastguard Worker# 9*800a58d9SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*800a58d9SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*800a58d9SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*800a58d9SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*800a58d9SAndroid Build Coastguard Worker# limitations under the License. 14*800a58d9SAndroid Build Coastguard Workerr"""Delete entry point. 15*800a58d9SAndroid Build Coastguard Worker 16*800a58d9SAndroid Build Coastguard WorkerDelete will handle all the logic related to deleting a local/remote instance 17*800a58d9SAndroid Build Coastguard Workerof an Android Virtual Device. 18*800a58d9SAndroid Build Coastguard Worker""" 19*800a58d9SAndroid Build Coastguard Worker 20*800a58d9SAndroid Build Coastguard Workerfrom __future__ import print_function 21*800a58d9SAndroid Build Coastguard Worker 22*800a58d9SAndroid Build Coastguard Workerimport logging 23*800a58d9SAndroid Build Coastguard Workerimport re 24*800a58d9SAndroid Build Coastguard Workerimport subprocess 25*800a58d9SAndroid Build Coastguard Worker 26*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors 27*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal import constants 28*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import cvd_utils 29*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import emulator_console 30*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import goldfish_utils 31*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import oxygen_client 32*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import ssh 33*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import utils 34*800a58d9SAndroid Build Coastguard Workerfrom acloud.list import list as list_instances 35*800a58d9SAndroid Build Coastguard Workerfrom acloud.public import config 36*800a58d9SAndroid Build Coastguard Workerfrom acloud.public import device_driver 37*800a58d9SAndroid Build Coastguard Workerfrom acloud.public import report 38*800a58d9SAndroid Build Coastguard Worker 39*800a58d9SAndroid Build Coastguard Worker 40*800a58d9SAndroid Build Coastguard Workerlogger = logging.getLogger(__name__) 41*800a58d9SAndroid Build Coastguard Worker 42*800a58d9SAndroid Build Coastguard Worker_COMMAND_GET_PROCESS_ID = ["pgrep", "run_cvd"] 43*800a58d9SAndroid Build Coastguard Worker_COMMAND_GET_PROCESS_COMMAND = ["ps", "-o", "command", "-p"] 44*800a58d9SAndroid Build Coastguard Worker_RE_RUN_CVD = re.compile(r"^(?P<run_cvd>.+run_cvd)") 45*800a58d9SAndroid Build Coastguard Worker_LOCAL_INSTANCE_PREFIX = "local-" 46*800a58d9SAndroid Build Coastguard Worker_RE_OXYGEN_RELEASE_ERROR = re.compile( 47*800a58d9SAndroid Build Coastguard Worker r".*Error received while trying to release device: (?P<error>.*)$", re.DOTALL) 48*800a58d9SAndroid Build Coastguard Worker 49*800a58d9SAndroid Build Coastguard Worker 50*800a58d9SAndroid Build Coastguard Workerdef DeleteInstances(cfg, instances_to_delete): 51*800a58d9SAndroid Build Coastguard Worker """Delete instances according to instances_to_delete. 52*800a58d9SAndroid Build Coastguard Worker 53*800a58d9SAndroid Build Coastguard Worker Args: 54*800a58d9SAndroid Build Coastguard Worker cfg: AcloudConfig object. 55*800a58d9SAndroid Build Coastguard Worker instances_to_delete: List of list.Instance() object. 56*800a58d9SAndroid Build Coastguard Worker 57*800a58d9SAndroid Build Coastguard Worker Returns: 58*800a58d9SAndroid Build Coastguard Worker Report object. 59*800a58d9SAndroid Build Coastguard Worker """ 60*800a58d9SAndroid Build Coastguard Worker delete_report = report.Report(command="delete") 61*800a58d9SAndroid Build Coastguard Worker remote_instance_list = [] 62*800a58d9SAndroid Build Coastguard Worker for instance in instances_to_delete: 63*800a58d9SAndroid Build Coastguard Worker if instance.islocal: 64*800a58d9SAndroid Build Coastguard Worker if instance.avd_type == constants.TYPE_GF: 65*800a58d9SAndroid Build Coastguard Worker DeleteLocalGoldfishInstance(instance, delete_report) 66*800a58d9SAndroid Build Coastguard Worker elif instance.avd_type == constants.TYPE_CF: 67*800a58d9SAndroid Build Coastguard Worker DeleteLocalCuttlefishInstance(instance, delete_report) 68*800a58d9SAndroid Build Coastguard Worker else: 69*800a58d9SAndroid Build Coastguard Worker delete_report.AddError("Deleting %s is not supported." % 70*800a58d9SAndroid Build Coastguard Worker instance.avd_type) 71*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.FAIL) 72*800a58d9SAndroid Build Coastguard Worker else: 73*800a58d9SAndroid Build Coastguard Worker remote_instance_list.append(instance.name) 74*800a58d9SAndroid Build Coastguard Worker # Delete ssvnc viewer 75*800a58d9SAndroid Build Coastguard Worker if instance.vnc_port: 76*800a58d9SAndroid Build Coastguard Worker utils.CleanupSSVncviewer(instance.vnc_port) 77*800a58d9SAndroid Build Coastguard Worker 78*800a58d9SAndroid Build Coastguard Worker if remote_instance_list: 79*800a58d9SAndroid Build Coastguard Worker # TODO(119283708): We should move DeleteAndroidVirtualDevices into 80*800a58d9SAndroid Build Coastguard Worker # delete.py after gce is deprecated. 81*800a58d9SAndroid Build Coastguard Worker # Stop remote instances. 82*800a58d9SAndroid Build Coastguard Worker return DeleteRemoteInstances(cfg, remote_instance_list, delete_report) 83*800a58d9SAndroid Build Coastguard Worker 84*800a58d9SAndroid Build Coastguard Worker return delete_report 85*800a58d9SAndroid Build Coastguard Worker 86*800a58d9SAndroid Build Coastguard Worker 87*800a58d9SAndroid Build Coastguard Worker@utils.TimeExecute(function_description="Deleting remote instances", 88*800a58d9SAndroid Build Coastguard Worker result_evaluator=utils.ReportEvaluator, 89*800a58d9SAndroid Build Coastguard Worker display_waiting_dots=False) 90*800a58d9SAndroid Build Coastguard Workerdef DeleteRemoteInstances(cfg, instances_to_delete, delete_report=None): 91*800a58d9SAndroid Build Coastguard Worker """Delete remote instances. 92*800a58d9SAndroid Build Coastguard Worker 93*800a58d9SAndroid Build Coastguard Worker Args: 94*800a58d9SAndroid Build Coastguard Worker cfg: AcloudConfig object. 95*800a58d9SAndroid Build Coastguard Worker instances_to_delete: List of instance names(string). 96*800a58d9SAndroid Build Coastguard Worker delete_report: Report object. 97*800a58d9SAndroid Build Coastguard Worker 98*800a58d9SAndroid Build Coastguard Worker Returns: 99*800a58d9SAndroid Build Coastguard Worker Report instance if there are instances to delete, None otherwise. 100*800a58d9SAndroid Build Coastguard Worker 101*800a58d9SAndroid Build Coastguard Worker Raises: 102*800a58d9SAndroid Build Coastguard Worker error.ConfigError: when config doesn't support remote instances. 103*800a58d9SAndroid Build Coastguard Worker """ 104*800a58d9SAndroid Build Coastguard Worker if not cfg.SupportRemoteInstance(): 105*800a58d9SAndroid Build Coastguard Worker raise errors.ConfigError("No gcp project info found in config! " 106*800a58d9SAndroid Build Coastguard Worker "The execution of deleting remote instances " 107*800a58d9SAndroid Build Coastguard Worker "has been aborted.") 108*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString("") 109*800a58d9SAndroid Build Coastguard Worker for instance in instances_to_delete: 110*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString(" - %s" % instance, utils.TextColors.WARNING) 111*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString("") 112*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString("status: waiting...", end="") 113*800a58d9SAndroid Build Coastguard Worker 114*800a58d9SAndroid Build Coastguard Worker # TODO(119283708): We should move DeleteAndroidVirtualDevices into 115*800a58d9SAndroid Build Coastguard Worker # delete.py after gce is deprecated. 116*800a58d9SAndroid Build Coastguard Worker # Stop remote instances. 117*800a58d9SAndroid Build Coastguard Worker delete_report = device_driver.DeleteAndroidVirtualDevices( 118*800a58d9SAndroid Build Coastguard Worker cfg, instances_to_delete, delete_report) 119*800a58d9SAndroid Build Coastguard Worker 120*800a58d9SAndroid Build Coastguard Worker return delete_report 121*800a58d9SAndroid Build Coastguard Worker 122*800a58d9SAndroid Build Coastguard Worker 123*800a58d9SAndroid Build Coastguard Worker@utils.TimeExecute(function_description="Deleting local cuttlefish instances", 124*800a58d9SAndroid Build Coastguard Worker result_evaluator=utils.ReportEvaluator) 125*800a58d9SAndroid Build Coastguard Workerdef DeleteLocalCuttlefishInstance(instance, delete_report): 126*800a58d9SAndroid Build Coastguard Worker """Delete a local cuttlefish instance. 127*800a58d9SAndroid Build Coastguard Worker 128*800a58d9SAndroid Build Coastguard Worker Delete local instance and write delete instance 129*800a58d9SAndroid Build Coastguard Worker information to report. 130*800a58d9SAndroid Build Coastguard Worker 131*800a58d9SAndroid Build Coastguard Worker Args: 132*800a58d9SAndroid Build Coastguard Worker instance: instance.LocalInstance object. 133*800a58d9SAndroid Build Coastguard Worker delete_report: Report object. 134*800a58d9SAndroid Build Coastguard Worker 135*800a58d9SAndroid Build Coastguard Worker Returns: 136*800a58d9SAndroid Build Coastguard Worker delete_report. 137*800a58d9SAndroid Build Coastguard Worker """ 138*800a58d9SAndroid Build Coastguard Worker ins_lock = instance.GetLock() 139*800a58d9SAndroid Build Coastguard Worker if not ins_lock.Lock(): 140*800a58d9SAndroid Build Coastguard Worker delete_report.AddError("%s is locked by another process." % 141*800a58d9SAndroid Build Coastguard Worker instance.name) 142*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.FAIL) 143*800a58d9SAndroid Build Coastguard Worker return delete_report 144*800a58d9SAndroid Build Coastguard Worker 145*800a58d9SAndroid Build Coastguard Worker try: 146*800a58d9SAndroid Build Coastguard Worker ins_lock.SetInUse(False) 147*800a58d9SAndroid Build Coastguard Worker instance.Delete() 148*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.SUCCESS) 149*800a58d9SAndroid Build Coastguard Worker device_driver.AddDeletionResultToReport( 150*800a58d9SAndroid Build Coastguard Worker delete_report, [instance.name], failed=[], 151*800a58d9SAndroid Build Coastguard Worker error_msgs=[], 152*800a58d9SAndroid Build Coastguard Worker resource_name="instance") 153*800a58d9SAndroid Build Coastguard Worker except subprocess.CalledProcessError as e: 154*800a58d9SAndroid Build Coastguard Worker delete_report.AddError(str(e)) 155*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.FAIL) 156*800a58d9SAndroid Build Coastguard Worker finally: 157*800a58d9SAndroid Build Coastguard Worker ins_lock.Unlock() 158*800a58d9SAndroid Build Coastguard Worker 159*800a58d9SAndroid Build Coastguard Worker return delete_report 160*800a58d9SAndroid Build Coastguard Worker 161*800a58d9SAndroid Build Coastguard Worker 162*800a58d9SAndroid Build Coastguard Worker@utils.TimeExecute(function_description="Deleting local goldfish instances", 163*800a58d9SAndroid Build Coastguard Worker result_evaluator=utils.ReportEvaluator) 164*800a58d9SAndroid Build Coastguard Workerdef DeleteLocalGoldfishInstance(instance, delete_report): 165*800a58d9SAndroid Build Coastguard Worker """Delete a local goldfish instance. 166*800a58d9SAndroid Build Coastguard Worker 167*800a58d9SAndroid Build Coastguard Worker Args: 168*800a58d9SAndroid Build Coastguard Worker instance: LocalGoldfishInstance object. 169*800a58d9SAndroid Build Coastguard Worker delete_report: Report object. 170*800a58d9SAndroid Build Coastguard Worker 171*800a58d9SAndroid Build Coastguard Worker Returns: 172*800a58d9SAndroid Build Coastguard Worker delete_report. 173*800a58d9SAndroid Build Coastguard Worker """ 174*800a58d9SAndroid Build Coastguard Worker lock = instance.GetLock() 175*800a58d9SAndroid Build Coastguard Worker if not lock.Lock(): 176*800a58d9SAndroid Build Coastguard Worker delete_report.AddError("%s is locked by another process." % 177*800a58d9SAndroid Build Coastguard Worker instance.name) 178*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.FAIL) 179*800a58d9SAndroid Build Coastguard Worker return delete_report 180*800a58d9SAndroid Build Coastguard Worker 181*800a58d9SAndroid Build Coastguard Worker try: 182*800a58d9SAndroid Build Coastguard Worker lock.SetInUse(False) 183*800a58d9SAndroid Build Coastguard Worker if instance.adb.EmuCommand("kill") == 0: 184*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.SUCCESS) 185*800a58d9SAndroid Build Coastguard Worker device_driver.AddDeletionResultToReport( 186*800a58d9SAndroid Build Coastguard Worker delete_report, [instance.name], failed=[], 187*800a58d9SAndroid Build Coastguard Worker error_msgs=[], 188*800a58d9SAndroid Build Coastguard Worker resource_name="instance") 189*800a58d9SAndroid Build Coastguard Worker else: 190*800a58d9SAndroid Build Coastguard Worker delete_report.AddError("Cannot kill %s." % instance.device_serial) 191*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.FAIL) 192*800a58d9SAndroid Build Coastguard Worker finally: 193*800a58d9SAndroid Build Coastguard Worker lock.Unlock() 194*800a58d9SAndroid Build Coastguard Worker 195*800a58d9SAndroid Build Coastguard Worker return delete_report 196*800a58d9SAndroid Build Coastguard Worker 197*800a58d9SAndroid Build Coastguard Worker 198*800a58d9SAndroid Build Coastguard Workerdef ResetLocalInstanceLockByName(name, delete_report): 199*800a58d9SAndroid Build Coastguard Worker """Set the lock state of a local instance to be not in use. 200*800a58d9SAndroid Build Coastguard Worker 201*800a58d9SAndroid Build Coastguard Worker Args: 202*800a58d9SAndroid Build Coastguard Worker name: The instance name. 203*800a58d9SAndroid Build Coastguard Worker delete_report: Report object. 204*800a58d9SAndroid Build Coastguard Worker """ 205*800a58d9SAndroid Build Coastguard Worker ins_lock = list_instances.GetLocalInstanceLockByName(name) 206*800a58d9SAndroid Build Coastguard Worker if not ins_lock: 207*800a58d9SAndroid Build Coastguard Worker delete_report.AddError("%s is not a valid local instance name." % name) 208*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.FAIL) 209*800a58d9SAndroid Build Coastguard Worker return 210*800a58d9SAndroid Build Coastguard Worker 211*800a58d9SAndroid Build Coastguard Worker if not ins_lock.Lock(): 212*800a58d9SAndroid Build Coastguard Worker delete_report.AddError("%s is locked by another process." % name) 213*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.FAIL) 214*800a58d9SAndroid Build Coastguard Worker return 215*800a58d9SAndroid Build Coastguard Worker 216*800a58d9SAndroid Build Coastguard Worker try: 217*800a58d9SAndroid Build Coastguard Worker ins_lock.SetInUse(False) 218*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.SUCCESS) 219*800a58d9SAndroid Build Coastguard Worker device_driver.AddDeletionResultToReport( 220*800a58d9SAndroid Build Coastguard Worker delete_report, [name], failed=[], error_msgs=[], 221*800a58d9SAndroid Build Coastguard Worker resource_name="instance") 222*800a58d9SAndroid Build Coastguard Worker finally: 223*800a58d9SAndroid Build Coastguard Worker ins_lock.Unlock() 224*800a58d9SAndroid Build Coastguard Worker 225*800a58d9SAndroid Build Coastguard Worker 226*800a58d9SAndroid Build Coastguard Worker@utils.TimeExecute(function_description=("Deleting remote host goldfish " 227*800a58d9SAndroid Build Coastguard Worker "instance"), 228*800a58d9SAndroid Build Coastguard Worker result_evaluator=utils.ReportEvaluator) 229*800a58d9SAndroid Build Coastguard Workerdef DeleteHostGoldfishInstance(cfg, name, ssh_user, 230*800a58d9SAndroid Build Coastguard Worker ssh_private_key_path, delete_report): 231*800a58d9SAndroid Build Coastguard Worker """Delete a goldfish instance on a remote host by console command. 232*800a58d9SAndroid Build Coastguard Worker 233*800a58d9SAndroid Build Coastguard Worker Args: 234*800a58d9SAndroid Build Coastguard Worker cfg: An AcloudConfig object. 235*800a58d9SAndroid Build Coastguard Worker name: String, the instance name. 236*800a58d9SAndroid Build Coastguard Worker remote_host : String, the IP address of the host. 237*800a58d9SAndroid Build Coastguard Worker ssh_user: String or None, the ssh user for the host. 238*800a58d9SAndroid Build Coastguard Worker ssh_private_key_path: String or None, the ssh private key for the host. 239*800a58d9SAndroid Build Coastguard Worker delete_report: A Report object. 240*800a58d9SAndroid Build Coastguard Worker 241*800a58d9SAndroid Build Coastguard Worker Returns: 242*800a58d9SAndroid Build Coastguard Worker delete_report. 243*800a58d9SAndroid Build Coastguard Worker """ 244*800a58d9SAndroid Build Coastguard Worker ip_addr, port = goldfish_utils.ParseRemoteHostConsoleAddress(name) 245*800a58d9SAndroid Build Coastguard Worker try: 246*800a58d9SAndroid Build Coastguard Worker with emulator_console.RemoteEmulatorConsole( 247*800a58d9SAndroid Build Coastguard Worker ip_addr, port, 248*800a58d9SAndroid Build Coastguard Worker (ssh_user or constants.GCE_USER), 249*800a58d9SAndroid Build Coastguard Worker (ssh_private_key_path or cfg.ssh_private_key_path), 250*800a58d9SAndroid Build Coastguard Worker cfg.extra_args_ssh_tunnel) as console: 251*800a58d9SAndroid Build Coastguard Worker console.Kill() 252*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.SUCCESS) 253*800a58d9SAndroid Build Coastguard Worker device_driver.AddDeletionResultToReport( 254*800a58d9SAndroid Build Coastguard Worker delete_report, [name], failed=[], error_msgs=[], 255*800a58d9SAndroid Build Coastguard Worker resource_name="instance") 256*800a58d9SAndroid Build Coastguard Worker except errors.DeviceConnectionError as e: 257*800a58d9SAndroid Build Coastguard Worker delete_report.AddError("%s is not deleted: %s" % (name, str(e))) 258*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.FAIL) 259*800a58d9SAndroid Build Coastguard Worker return delete_report 260*800a58d9SAndroid Build Coastguard Worker 261*800a58d9SAndroid Build Coastguard Worker 262*800a58d9SAndroid Build Coastguard Worker@utils.TimeExecute(function_description=("Deleting remote host cuttlefish " 263*800a58d9SAndroid Build Coastguard Worker "instance"), 264*800a58d9SAndroid Build Coastguard Worker result_evaluator=utils.ReportEvaluator) 265*800a58d9SAndroid Build Coastguard Workerdef CleanUpRemoteHost(cfg, remote_host, host_user, host_ssh_private_key_path, 266*800a58d9SAndroid Build Coastguard Worker base_dir, delete_report): 267*800a58d9SAndroid Build Coastguard Worker """Clean up the remote host. 268*800a58d9SAndroid Build Coastguard Worker 269*800a58d9SAndroid Build Coastguard Worker Args: 270*800a58d9SAndroid Build Coastguard Worker cfg: An AcloudConfig instance. 271*800a58d9SAndroid Build Coastguard Worker remote_host : String, ip address or host name of the remote host. 272*800a58d9SAndroid Build Coastguard Worker host_user: String of user login into the instance. 273*800a58d9SAndroid Build Coastguard Worker host_ssh_private_key_path: String of host key for logging in to the 274*800a58d9SAndroid Build Coastguard Worker host. 275*800a58d9SAndroid Build Coastguard Worker base_dir: String, the base directory on the remote host. 276*800a58d9SAndroid Build Coastguard Worker delete_report: A Report object. 277*800a58d9SAndroid Build Coastguard Worker 278*800a58d9SAndroid Build Coastguard Worker Returns: 279*800a58d9SAndroid Build Coastguard Worker delete_report. 280*800a58d9SAndroid Build Coastguard Worker """ 281*800a58d9SAndroid Build Coastguard Worker ssh_obj = ssh.Ssh( 282*800a58d9SAndroid Build Coastguard Worker ip=ssh.IP(ip=remote_host), 283*800a58d9SAndroid Build Coastguard Worker user=host_user, 284*800a58d9SAndroid Build Coastguard Worker ssh_private_key_path=( 285*800a58d9SAndroid Build Coastguard Worker host_ssh_private_key_path or cfg.ssh_private_key_path)) 286*800a58d9SAndroid Build Coastguard Worker try: 287*800a58d9SAndroid Build Coastguard Worker cvd_utils.CleanUpRemoteCvd(ssh_obj, base_dir, raise_error=True) 288*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.SUCCESS) 289*800a58d9SAndroid Build Coastguard Worker device_driver.AddDeletionResultToReport( 290*800a58d9SAndroid Build Coastguard Worker delete_report, [remote_host], failed=[], 291*800a58d9SAndroid Build Coastguard Worker error_msgs=[], 292*800a58d9SAndroid Build Coastguard Worker resource_name="remote host") 293*800a58d9SAndroid Build Coastguard Worker except subprocess.CalledProcessError as e: 294*800a58d9SAndroid Build Coastguard Worker delete_report.AddError(str(e)) 295*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.FAIL) 296*800a58d9SAndroid Build Coastguard Worker return delete_report 297*800a58d9SAndroid Build Coastguard Worker 298*800a58d9SAndroid Build Coastguard Worker 299*800a58d9SAndroid Build Coastguard Workerdef DeleteInstanceByNames(cfg, instances, host_user, 300*800a58d9SAndroid Build Coastguard Worker host_ssh_private_key_path): 301*800a58d9SAndroid Build Coastguard Worker """Delete instances by the given instance names. 302*800a58d9SAndroid Build Coastguard Worker 303*800a58d9SAndroid Build Coastguard Worker This method can identify the following types of instance names: 304*800a58d9SAndroid Build Coastguard Worker local cuttlefish instance: local-instance-<id> 305*800a58d9SAndroid Build Coastguard Worker local goldfish instance: local-goldfish-instance-<id> 306*800a58d9SAndroid Build Coastguard Worker remote host cuttlefish instance: host-<ip_addr>-<build_info> 307*800a58d9SAndroid Build Coastguard Worker remote host goldfish instance: host-goldfish-<ip_addr>-<port>-<build_info> 308*800a58d9SAndroid Build Coastguard Worker remote instance: ins-<uuid>-<build_info> 309*800a58d9SAndroid Build Coastguard Worker 310*800a58d9SAndroid Build Coastguard Worker Args: 311*800a58d9SAndroid Build Coastguard Worker cfg: AcloudConfig object. 312*800a58d9SAndroid Build Coastguard Worker instances: List of instance name. 313*800a58d9SAndroid Build Coastguard Worker host_user: String or None, the ssh user for remote hosts. 314*800a58d9SAndroid Build Coastguard Worker host_ssh_private_key_path: String or None, the ssh private key for 315*800a58d9SAndroid Build Coastguard Worker remote hosts. 316*800a58d9SAndroid Build Coastguard Worker 317*800a58d9SAndroid Build Coastguard Worker Returns: 318*800a58d9SAndroid Build Coastguard Worker A Report instance. 319*800a58d9SAndroid Build Coastguard Worker """ 320*800a58d9SAndroid Build Coastguard Worker delete_report = report.Report(command="delete") 321*800a58d9SAndroid Build Coastguard Worker local_names = set(name for name in instances if 322*800a58d9SAndroid Build Coastguard Worker name.startswith(_LOCAL_INSTANCE_PREFIX)) 323*800a58d9SAndroid Build Coastguard Worker remote_host_cf_names = set( 324*800a58d9SAndroid Build Coastguard Worker name for name in instances if cvd_utils.ParseRemoteHostAddress(name)) 325*800a58d9SAndroid Build Coastguard Worker remote_host_gf_names = set( 326*800a58d9SAndroid Build Coastguard Worker name for name in instances if 327*800a58d9SAndroid Build Coastguard Worker goldfish_utils.ParseRemoteHostConsoleAddress(name)) 328*800a58d9SAndroid Build Coastguard Worker remote_names = list(set(instances) - local_names - remote_host_cf_names - 329*800a58d9SAndroid Build Coastguard Worker remote_host_gf_names) 330*800a58d9SAndroid Build Coastguard Worker 331*800a58d9SAndroid Build Coastguard Worker if local_names: 332*800a58d9SAndroid Build Coastguard Worker active_instances = list_instances.GetLocalInstancesByNames(local_names) 333*800a58d9SAndroid Build Coastguard Worker inactive_names = local_names.difference(ins.name for ins in 334*800a58d9SAndroid Build Coastguard Worker active_instances) 335*800a58d9SAndroid Build Coastguard Worker if active_instances: 336*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString("Deleting local instances") 337*800a58d9SAndroid Build Coastguard Worker delete_report = DeleteInstances(cfg, active_instances) 338*800a58d9SAndroid Build Coastguard Worker if inactive_names: 339*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString("Unlocking local instances") 340*800a58d9SAndroid Build Coastguard Worker for name in inactive_names: 341*800a58d9SAndroid Build Coastguard Worker ResetLocalInstanceLockByName(name, delete_report) 342*800a58d9SAndroid Build Coastguard Worker 343*800a58d9SAndroid Build Coastguard Worker if remote_host_cf_names: 344*800a58d9SAndroid Build Coastguard Worker for name in remote_host_cf_names: 345*800a58d9SAndroid Build Coastguard Worker ip_addr, base_dir = cvd_utils.ParseRemoteHostAddress(name) 346*800a58d9SAndroid Build Coastguard Worker CleanUpRemoteHost(cfg, ip_addr, host_user, 347*800a58d9SAndroid Build Coastguard Worker host_ssh_private_key_path, base_dir, 348*800a58d9SAndroid Build Coastguard Worker delete_report) 349*800a58d9SAndroid Build Coastguard Worker 350*800a58d9SAndroid Build Coastguard Worker if remote_host_gf_names: 351*800a58d9SAndroid Build Coastguard Worker for name in remote_host_gf_names: 352*800a58d9SAndroid Build Coastguard Worker DeleteHostGoldfishInstance( 353*800a58d9SAndroid Build Coastguard Worker cfg, name, host_user, host_ssh_private_key_path, delete_report) 354*800a58d9SAndroid Build Coastguard Worker 355*800a58d9SAndroid Build Coastguard Worker if remote_names: 356*800a58d9SAndroid Build Coastguard Worker delete_report = DeleteRemoteInstances(cfg, remote_names, delete_report) 357*800a58d9SAndroid Build Coastguard Worker return delete_report 358*800a58d9SAndroid Build Coastguard Worker 359*800a58d9SAndroid Build Coastguard Worker 360*800a58d9SAndroid Build Coastguard Workerdef _ReleaseOxygenDevice(cfg, instances, ip): 361*800a58d9SAndroid Build Coastguard Worker """ Release one Oxygen device. 362*800a58d9SAndroid Build Coastguard Worker 363*800a58d9SAndroid Build Coastguard Worker Args: 364*800a58d9SAndroid Build Coastguard Worker cfg: AcloudConfig object. 365*800a58d9SAndroid Build Coastguard Worker instances: List of instance name. 366*800a58d9SAndroid Build Coastguard Worker ip: String of device ip. 367*800a58d9SAndroid Build Coastguard Worker 368*800a58d9SAndroid Build Coastguard Worker Returns: 369*800a58d9SAndroid Build Coastguard Worker A Report instance. 370*800a58d9SAndroid Build Coastguard Worker """ 371*800a58d9SAndroid Build Coastguard Worker if len(instances) != 1: 372*800a58d9SAndroid Build Coastguard Worker raise errors.CommandArgError( 373*800a58d9SAndroid Build Coastguard Worker "The release device function doesn't support multiple instances. " 374*800a58d9SAndroid Build Coastguard Worker "Please check the specified instance names: %s" % instances) 375*800a58d9SAndroid Build Coastguard Worker instance_name = instances[0] 376*800a58d9SAndroid Build Coastguard Worker delete_report = report.Report(command="delete") 377*800a58d9SAndroid Build Coastguard Worker try: 378*800a58d9SAndroid Build Coastguard Worker oxygen_client.OxygenClient.ReleaseDevice(instance_name, ip, 379*800a58d9SAndroid Build Coastguard Worker cfg.oxygen_client) 380*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.SUCCESS) 381*800a58d9SAndroid Build Coastguard Worker device_driver.AddDeletionResultToReport( 382*800a58d9SAndroid Build Coastguard Worker delete_report, [instance_name], failed=[], 383*800a58d9SAndroid Build Coastguard Worker error_msgs=[], 384*800a58d9SAndroid Build Coastguard Worker resource_name="instance") 385*800a58d9SAndroid Build Coastguard Worker except subprocess.CalledProcessError as e: 386*800a58d9SAndroid Build Coastguard Worker logger.error("Failed to release device from Oxygen, error: %s", 387*800a58d9SAndroid Build Coastguard Worker e.output) 388*800a58d9SAndroid Build Coastguard Worker error = str(e) 389*800a58d9SAndroid Build Coastguard Worker match = _RE_OXYGEN_RELEASE_ERROR.match(e.output) 390*800a58d9SAndroid Build Coastguard Worker if match: 391*800a58d9SAndroid Build Coastguard Worker error = match.group("error").strip() 392*800a58d9SAndroid Build Coastguard Worker delete_report.AddError(error) 393*800a58d9SAndroid Build Coastguard Worker delete_report.SetErrorType(constants.ACLOUD_OXYGEN_RELEASE_ERROR) 394*800a58d9SAndroid Build Coastguard Worker delete_report.SetStatus(report.Status.FAIL) 395*800a58d9SAndroid Build Coastguard Worker return delete_report 396*800a58d9SAndroid Build Coastguard Worker 397*800a58d9SAndroid Build Coastguard Worker 398*800a58d9SAndroid Build Coastguard Workerdef Run(args): 399*800a58d9SAndroid Build Coastguard Worker """Run delete. 400*800a58d9SAndroid Build Coastguard Worker 401*800a58d9SAndroid Build Coastguard Worker After delete command executed, tool will return one Report instance. 402*800a58d9SAndroid Build Coastguard Worker If there is no instance to delete, just reutrn empty Report. 403*800a58d9SAndroid Build Coastguard Worker 404*800a58d9SAndroid Build Coastguard Worker Args: 405*800a58d9SAndroid Build Coastguard Worker args: Namespace object from argparse.parse_args. 406*800a58d9SAndroid Build Coastguard Worker 407*800a58d9SAndroid Build Coastguard Worker Returns: 408*800a58d9SAndroid Build Coastguard Worker A Report instance. 409*800a58d9SAndroid Build Coastguard Worker """ 410*800a58d9SAndroid Build Coastguard Worker # Prioritize delete instances by names without query all instance info from 411*800a58d9SAndroid Build Coastguard Worker # GCP project. 412*800a58d9SAndroid Build Coastguard Worker cfg = config.GetAcloudConfig(args) 413*800a58d9SAndroid Build Coastguard Worker if args.oxygen: 414*800a58d9SAndroid Build Coastguard Worker return _ReleaseOxygenDevice(cfg, args.instance_names, args.ip) 415*800a58d9SAndroid Build Coastguard Worker if args.instance_names: 416*800a58d9SAndroid Build Coastguard Worker return DeleteInstanceByNames(cfg, 417*800a58d9SAndroid Build Coastguard Worker args.instance_names, 418*800a58d9SAndroid Build Coastguard Worker args.host_user, 419*800a58d9SAndroid Build Coastguard Worker args.host_ssh_private_key_path) 420*800a58d9SAndroid Build Coastguard Worker if args.remote_host: 421*800a58d9SAndroid Build Coastguard Worker delete_report = report.Report(command="delete") 422*800a58d9SAndroid Build Coastguard Worker CleanUpRemoteHost(cfg, args.remote_host, args.host_user, 423*800a58d9SAndroid Build Coastguard Worker args.host_ssh_private_key_path, 424*800a58d9SAndroid Build Coastguard Worker cvd_utils.GetRemoteHostBaseDir(1), 425*800a58d9SAndroid Build Coastguard Worker delete_report) 426*800a58d9SAndroid Build Coastguard Worker return delete_report 427*800a58d9SAndroid Build Coastguard Worker 428*800a58d9SAndroid Build Coastguard Worker instances = list_instances.GetLocalInstances() 429*800a58d9SAndroid Build Coastguard Worker if not args.local_only and cfg.SupportRemoteInstance(): 430*800a58d9SAndroid Build Coastguard Worker instances.extend(list_instances.GetRemoteInstances(cfg)) 431*800a58d9SAndroid Build Coastguard Worker 432*800a58d9SAndroid Build Coastguard Worker if args.adb_port: 433*800a58d9SAndroid Build Coastguard Worker instances = list_instances.FilterInstancesByAdbPort(instances, 434*800a58d9SAndroid Build Coastguard Worker args.adb_port) 435*800a58d9SAndroid Build Coastguard Worker elif not args.all: 436*800a58d9SAndroid Build Coastguard Worker # Provide instances list to user and let user choose what to delete if 437*800a58d9SAndroid Build Coastguard Worker # user didn't specify instances in args. 438*800a58d9SAndroid Build Coastguard Worker instances = list_instances.ChooseInstancesFromList(instances) 439*800a58d9SAndroid Build Coastguard Worker 440*800a58d9SAndroid Build Coastguard Worker if not instances: 441*800a58d9SAndroid Build Coastguard Worker utils.PrintColorString("No instances to delete") 442*800a58d9SAndroid Build Coastguard Worker return DeleteInstances(cfg, instances) 443