xref: /aosp_15_r20/tools/acloud/list/list.py (revision 800a58d989c669b8eb8a71d8df53b1ba3d411444)
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"""List entry point.
15*800a58d9SAndroid Build Coastguard Worker
16*800a58d9SAndroid Build Coastguard WorkerList will handle all the logic related to list 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 Workerimport getpass
22*800a58d9SAndroid Build Coastguard Workerimport logging
23*800a58d9SAndroid Build Coastguard Workerimport os
24*800a58d9SAndroid Build Coastguard Worker
25*800a58d9SAndroid Build Coastguard Workerfrom acloud import errors
26*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal import constants
27*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import auth
28*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import gcompute_client
29*800a58d9SAndroid Build Coastguard Workerfrom acloud.internal.lib import utils
30*800a58d9SAndroid Build Coastguard Workerfrom acloud.list import instance
31*800a58d9SAndroid Build Coastguard Workerfrom acloud.public import config
32*800a58d9SAndroid Build Coastguard Worker
33*800a58d9SAndroid Build Coastguard Worker
34*800a58d9SAndroid Build Coastguard Workerlogger = logging.getLogger(__name__)
35*800a58d9SAndroid Build Coastguard Worker
36*800a58d9SAndroid Build Coastguard Worker_COMMAND_PS_LAUNCH_CVD = ["ps", "-wweo", "lstart,cmd"]
37*800a58d9SAndroid Build Coastguard Worker_NOT_CONNECTED_DEVICE_HINT = (
38*800a58d9SAndroid Build Coastguard Worker    "\nFor not connected device, you can try \"$ acloud reconnect\" or "
39*800a58d9SAndroid Build Coastguard Worker    "\"$ acloud restart\" to get the device back.")
40*800a58d9SAndroid Build Coastguard Worker
41*800a58d9SAndroid Build Coastguard Worker
42*800a58d9SAndroid Build Coastguard Workerdef _ProcessInstances(instance_list):
43*800a58d9SAndroid Build Coastguard Worker    """Get more details of remote instances.
44*800a58d9SAndroid Build Coastguard Worker
45*800a58d9SAndroid Build Coastguard Worker    Args:
46*800a58d9SAndroid Build Coastguard Worker        instance_list: List of dicts which contain info about the remote instances,
47*800a58d9SAndroid Build Coastguard Worker                       they're the response from the GCP GCE api.
48*800a58d9SAndroid Build Coastguard Worker
49*800a58d9SAndroid Build Coastguard Worker    Returns:
50*800a58d9SAndroid Build Coastguard Worker        instance_detail_list: List of instance.Instance() with detail info.
51*800a58d9SAndroid Build Coastguard Worker    """
52*800a58d9SAndroid Build Coastguard Worker    return [instance.RemoteInstance(gce_instance) for gce_instance in instance_list]
53*800a58d9SAndroid Build Coastguard Worker
54*800a58d9SAndroid Build Coastguard Worker
55*800a58d9SAndroid Build Coastguard Workerdef _SortInstancesForDisplay(instances):
56*800a58d9SAndroid Build Coastguard Worker    """Sort the instances by connected first and then by age.
57*800a58d9SAndroid Build Coastguard Worker
58*800a58d9SAndroid Build Coastguard Worker    Args:
59*800a58d9SAndroid Build Coastguard Worker        instances: List of instance.Instance()
60*800a58d9SAndroid Build Coastguard Worker
61*800a58d9SAndroid Build Coastguard Worker    Returns:
62*800a58d9SAndroid Build Coastguard Worker        List of instance.Instance() after sorted.
63*800a58d9SAndroid Build Coastguard Worker    """
64*800a58d9SAndroid Build Coastguard Worker    instances.sort(key=lambda ins: ins.createtime, reverse=True)
65*800a58d9SAndroid Build Coastguard Worker    instances.sort(key=lambda ins: ins.AdbConnected(), reverse=True)
66*800a58d9SAndroid Build Coastguard Worker    return instances
67*800a58d9SAndroid Build Coastguard Worker
68*800a58d9SAndroid Build Coastguard Worker
69*800a58d9SAndroid Build Coastguard Workerdef PrintInstancesDetails(instance_list, verbose=False):
70*800a58d9SAndroid Build Coastguard Worker    """Display instances information.
71*800a58d9SAndroid Build Coastguard Worker
72*800a58d9SAndroid Build Coastguard Worker    Example of non-verbose case:
73*800a58d9SAndroid Build Coastguard Worker    [1]device serial: 127.0.0.1:55685 (ins-1ff036dc-5128057-cf-x86-phone-userdebug)
74*800a58d9SAndroid Build Coastguard Worker    [2]device serial: 127.0.0.1:60979 (ins-80952669-5128057-cf-x86-phone-userdebug)
75*800a58d9SAndroid Build Coastguard Worker    [3]device serial: 127.0.0.1:6520 (local-instance)
76*800a58d9SAndroid Build Coastguard Worker
77*800a58d9SAndroid Build Coastguard Worker    Example of verbose case:
78*800a58d9SAndroid Build Coastguard Worker    [1] name: ins-244710f0-5091715-aosp-cf-x86-phone-userdebug
79*800a58d9SAndroid Build Coastguard Worker        IP: None
80*800a58d9SAndroid Build Coastguard Worker        create time: 2018-10-25T06:32:08.182-07:00
81*800a58d9SAndroid Build Coastguard Worker        status: TERMINATED
82*800a58d9SAndroid Build Coastguard Worker        avd type: cuttlefish
83*800a58d9SAndroid Build Coastguard Worker        display: 1080x1920 (240)
84*800a58d9SAndroid Build Coastguard Worker
85*800a58d9SAndroid Build Coastguard Worker    [2] name: ins-82979192-5091715-aosp-cf-x86-phone-userdebug
86*800a58d9SAndroid Build Coastguard Worker        IP: 35.232.77.15
87*800a58d9SAndroid Build Coastguard Worker        adb serial: 127.0.0.1:33537
88*800a58d9SAndroid Build Coastguard Worker        create time: 2018-10-25T06:34:22.716-07:00
89*800a58d9SAndroid Build Coastguard Worker        status: RUNNING
90*800a58d9SAndroid Build Coastguard Worker        avd type: cuttlefish
91*800a58d9SAndroid Build Coastguard Worker        display: 1080x1920 (240)
92*800a58d9SAndroid Build Coastguard Worker
93*800a58d9SAndroid Build Coastguard Worker    Args:
94*800a58d9SAndroid Build Coastguard Worker        verbose: Boolean, True to print all details and only full name if False.
95*800a58d9SAndroid Build Coastguard Worker        instance_list: List of instances.
96*800a58d9SAndroid Build Coastguard Worker    """
97*800a58d9SAndroid Build Coastguard Worker    not_any_connected_device = False
98*800a58d9SAndroid Build Coastguard Worker    if not instance_list:
99*800a58d9SAndroid Build Coastguard Worker        print("No remote or local instances found")
100*800a58d9SAndroid Build Coastguard Worker
101*800a58d9SAndroid Build Coastguard Worker    for num, instance_info in enumerate(instance_list, 1):
102*800a58d9SAndroid Build Coastguard Worker        idx_str = f"[{num}]"
103*800a58d9SAndroid Build Coastguard Worker        utils.PrintColorString(idx_str, end="")
104*800a58d9SAndroid Build Coastguard Worker        if verbose:
105*800a58d9SAndroid Build Coastguard Worker            print(instance_info.Summary())
106*800a58d9SAndroid Build Coastguard Worker            # add space between instances in verbose mode.
107*800a58d9SAndroid Build Coastguard Worker            print("")
108*800a58d9SAndroid Build Coastguard Worker        else:
109*800a58d9SAndroid Build Coastguard Worker            print(instance_info)
110*800a58d9SAndroid Build Coastguard Worker
111*800a58d9SAndroid Build Coastguard Worker        if not instance_info.AdbConnected():
112*800a58d9SAndroid Build Coastguard Worker            not_any_connected_device = True
113*800a58d9SAndroid Build Coastguard Worker    if not_any_connected_device:
114*800a58d9SAndroid Build Coastguard Worker        utils.PrintColorString(_NOT_CONNECTED_DEVICE_HINT)
115*800a58d9SAndroid Build Coastguard Worker
116*800a58d9SAndroid Build Coastguard Worker
117*800a58d9SAndroid Build Coastguard Workerdef GetRemoteInstances(cfg):
118*800a58d9SAndroid Build Coastguard Worker    """Look for remote instances.
119*800a58d9SAndroid Build Coastguard Worker
120*800a58d9SAndroid Build Coastguard Worker    We're going to query the GCP project for all instances that created by user.
121*800a58d9SAndroid Build Coastguard Worker
122*800a58d9SAndroid Build Coastguard Worker    Args:
123*800a58d9SAndroid Build Coastguard Worker        cfg: AcloudConfig object.
124*800a58d9SAndroid Build Coastguard Worker
125*800a58d9SAndroid Build Coastguard Worker    Returns:
126*800a58d9SAndroid Build Coastguard Worker        instance_list: List of remote instances.
127*800a58d9SAndroid Build Coastguard Worker    """
128*800a58d9SAndroid Build Coastguard Worker    credentials = auth.CreateCredentials(cfg)
129*800a58d9SAndroid Build Coastguard Worker    compute_client = gcompute_client.ComputeClient(cfg, credentials)
130*800a58d9SAndroid Build Coastguard Worker    filter_item = f"labels.{constants.LABEL_CREATE_BY}={getpass.getuser()}"
131*800a58d9SAndroid Build Coastguard Worker    all_instances = compute_client.ListInstances(instance_filter=filter_item)
132*800a58d9SAndroid Build Coastguard Worker
133*800a58d9SAndroid Build Coastguard Worker    logger.debug("Instance list from: (filter: %s\n%s):",
134*800a58d9SAndroid Build Coastguard Worker                 filter_item, all_instances)
135*800a58d9SAndroid Build Coastguard Worker
136*800a58d9SAndroid Build Coastguard Worker    return _SortInstancesForDisplay(_ProcessInstances(all_instances))
137*800a58d9SAndroid Build Coastguard Worker
138*800a58d9SAndroid Build Coastguard Worker
139*800a58d9SAndroid Build Coastguard Workerdef _GetLocalCuttlefishInstances(id_cfg_pairs):
140*800a58d9SAndroid Build Coastguard Worker    """Look for local cuttelfish instances.
141*800a58d9SAndroid Build Coastguard Worker
142*800a58d9SAndroid Build Coastguard Worker    Gather local instances information from cuttlefish runtime config.
143*800a58d9SAndroid Build Coastguard Worker
144*800a58d9SAndroid Build Coastguard Worker    Args:
145*800a58d9SAndroid Build Coastguard Worker        id_cfg_pairs: List of tuples. Each tuple consists of an instance id and
146*800a58d9SAndroid Build Coastguard Worker                      a config path.
147*800a58d9SAndroid Build Coastguard Worker
148*800a58d9SAndroid Build Coastguard Worker    Returns:
149*800a58d9SAndroid Build Coastguard Worker        instance_list: List of local instances.
150*800a58d9SAndroid Build Coastguard Worker    """
151*800a58d9SAndroid Build Coastguard Worker    local_instance_list = []
152*800a58d9SAndroid Build Coastguard Worker    for ins_id, cfg_path in id_cfg_pairs:
153*800a58d9SAndroid Build Coastguard Worker        ins_lock = instance.GetLocalInstanceLock(ins_id)
154*800a58d9SAndroid Build Coastguard Worker        if not ins_lock.Lock():
155*800a58d9SAndroid Build Coastguard Worker            logger.warning("Cuttlefish Instance %d is locked by another "
156*800a58d9SAndroid Build Coastguard Worker                           "process.", ins_id)
157*800a58d9SAndroid Build Coastguard Worker            continue
158*800a58d9SAndroid Build Coastguard Worker        try:
159*800a58d9SAndroid Build Coastguard Worker            if not os.path.isfile(cfg_path):
160*800a58d9SAndroid Build Coastguard Worker                continue
161*800a58d9SAndroid Build Coastguard Worker            instances = instance.GetCuttleFishLocalInstances(cfg_path)
162*800a58d9SAndroid Build Coastguard Worker            for ins in instances:
163*800a58d9SAndroid Build Coastguard Worker                if ins.CvdStatus():
164*800a58d9SAndroid Build Coastguard Worker                    local_instance_list.append(ins)
165*800a58d9SAndroid Build Coastguard Worker                else:
166*800a58d9SAndroid Build Coastguard Worker                    logger.info("Cvd runtime config is found at %s but instance "
167*800a58d9SAndroid Build Coastguard Worker                                "%d is not active.", cfg_path, ins_id)
168*800a58d9SAndroid Build Coastguard Worker        finally:
169*800a58d9SAndroid Build Coastguard Worker            ins_lock.Unlock()
170*800a58d9SAndroid Build Coastguard Worker    return local_instance_list
171*800a58d9SAndroid Build Coastguard Worker
172*800a58d9SAndroid Build Coastguard Worker
173*800a58d9SAndroid Build Coastguard Workerdef GetActiveCVD(local_instance_id):
174*800a58d9SAndroid Build Coastguard Worker    """Check if the local AVD with specific instance id is running
175*800a58d9SAndroid Build Coastguard Worker
176*800a58d9SAndroid Build Coastguard Worker    This function does not lock the instance.
177*800a58d9SAndroid Build Coastguard Worker
178*800a58d9SAndroid Build Coastguard Worker    Args:
179*800a58d9SAndroid Build Coastguard Worker        local_instance_id: Integer of instance id.
180*800a58d9SAndroid Build Coastguard Worker
181*800a58d9SAndroid Build Coastguard Worker    Return:
182*800a58d9SAndroid Build Coastguard Worker        LocalInstance object.
183*800a58d9SAndroid Build Coastguard Worker    """
184*800a58d9SAndroid Build Coastguard Worker    cfg_path = instance.GetLocalInstanceConfig(local_instance_id)
185*800a58d9SAndroid Build Coastguard Worker    if cfg_path:
186*800a58d9SAndroid Build Coastguard Worker        ins = instance.LocalInstance(cfg_path)
187*800a58d9SAndroid Build Coastguard Worker        if ins.CvdStatus():
188*800a58d9SAndroid Build Coastguard Worker            return ins
189*800a58d9SAndroid Build Coastguard Worker    cfg_path = instance.GetDefaultCuttlefishConfig()
190*800a58d9SAndroid Build Coastguard Worker    if local_instance_id == 1 and cfg_path:
191*800a58d9SAndroid Build Coastguard Worker        ins = instance.LocalInstance(cfg_path)
192*800a58d9SAndroid Build Coastguard Worker        if ins.CvdStatus():
193*800a58d9SAndroid Build Coastguard Worker            return ins
194*800a58d9SAndroid Build Coastguard Worker    return None
195*800a58d9SAndroid Build Coastguard Worker
196*800a58d9SAndroid Build Coastguard Worker
197*800a58d9SAndroid Build Coastguard Workerdef GetLocalInstances():
198*800a58d9SAndroid Build Coastguard Worker    """Look for local cuttleifsh and goldfish instances.
199*800a58d9SAndroid Build Coastguard Worker
200*800a58d9SAndroid Build Coastguard Worker    Returns:
201*800a58d9SAndroid Build Coastguard Worker        List of local instances.
202*800a58d9SAndroid Build Coastguard Worker    """
203*800a58d9SAndroid Build Coastguard Worker    # Running instances on local is not supported on all OS.
204*800a58d9SAndroid Build Coastguard Worker    if not utils.IsSupportedPlatform():
205*800a58d9SAndroid Build Coastguard Worker        return []
206*800a58d9SAndroid Build Coastguard Worker
207*800a58d9SAndroid Build Coastguard Worker    id_cfg_pairs = instance.GetAllLocalInstanceConfigs()
208*800a58d9SAndroid Build Coastguard Worker    return (_GetLocalCuttlefishInstances(id_cfg_pairs) +
209*800a58d9SAndroid Build Coastguard Worker            instance.LocalGoldfishInstance.GetExistingInstances())
210*800a58d9SAndroid Build Coastguard Worker
211*800a58d9SAndroid Build Coastguard Worker
212*800a58d9SAndroid Build Coastguard Workerdef GetInstances(cfg):
213*800a58d9SAndroid Build Coastguard Worker    """Look for remote/local instances.
214*800a58d9SAndroid Build Coastguard Worker
215*800a58d9SAndroid Build Coastguard Worker    Args:
216*800a58d9SAndroid Build Coastguard Worker        cfg: AcloudConfig object.
217*800a58d9SAndroid Build Coastguard Worker
218*800a58d9SAndroid Build Coastguard Worker    Returns:
219*800a58d9SAndroid Build Coastguard Worker        instance_list: List of instances.
220*800a58d9SAndroid Build Coastguard Worker    """
221*800a58d9SAndroid Build Coastguard Worker    return GetRemoteInstances(cfg) + GetLocalInstances()
222*800a58d9SAndroid Build Coastguard Worker
223*800a58d9SAndroid Build Coastguard Worker
224*800a58d9SAndroid Build Coastguard Workerdef ChooseInstancesFromList(instances):
225*800a58d9SAndroid Build Coastguard Worker    """Let user choose instances from a list.
226*800a58d9SAndroid Build Coastguard Worker
227*800a58d9SAndroid Build Coastguard Worker    Args:
228*800a58d9SAndroid Build Coastguard Worker        instances: List of Instance objects.
229*800a58d9SAndroid Build Coastguard Worker
230*800a58d9SAndroid Build Coastguard Worker    Returns:
231*800a58d9SAndroid Build Coastguard Worker         List of Instance objects.
232*800a58d9SAndroid Build Coastguard Worker    """
233*800a58d9SAndroid Build Coastguard Worker    if len(instances) > 1:
234*800a58d9SAndroid Build Coastguard Worker        print("Multiple instances detected, choose any one to proceed:")
235*800a58d9SAndroid Build Coastguard Worker        return utils.GetAnswerFromList(instances, enable_choose_all=True)
236*800a58d9SAndroid Build Coastguard Worker    return instances
237*800a58d9SAndroid Build Coastguard Worker
238*800a58d9SAndroid Build Coastguard Worker
239*800a58d9SAndroid Build Coastguard Workerdef ChooseInstances(cfg, select_all_instances=False):
240*800a58d9SAndroid Build Coastguard Worker    """Get instances.
241*800a58d9SAndroid Build Coastguard Worker
242*800a58d9SAndroid Build Coastguard Worker    Retrieve all remote/local instances and if there is more than 1 instance
243*800a58d9SAndroid Build Coastguard Worker    found, ask user which instance they'd like.
244*800a58d9SAndroid Build Coastguard Worker
245*800a58d9SAndroid Build Coastguard Worker    Args:
246*800a58d9SAndroid Build Coastguard Worker        cfg: AcloudConfig object.
247*800a58d9SAndroid Build Coastguard Worker        select_all_instances: True if select all instances by default and no
248*800a58d9SAndroid Build Coastguard Worker                              need to ask user to choose.
249*800a58d9SAndroid Build Coastguard Worker
250*800a58d9SAndroid Build Coastguard Worker    Returns:
251*800a58d9SAndroid Build Coastguard Worker        List of Instance() object.
252*800a58d9SAndroid Build Coastguard Worker    """
253*800a58d9SAndroid Build Coastguard Worker    instances = GetInstances(cfg)
254*800a58d9SAndroid Build Coastguard Worker    if not select_all_instances:
255*800a58d9SAndroid Build Coastguard Worker        return ChooseInstancesFromList(instances)
256*800a58d9SAndroid Build Coastguard Worker    return instances
257*800a58d9SAndroid Build Coastguard Worker
258*800a58d9SAndroid Build Coastguard Worker
259*800a58d9SAndroid Build Coastguard Workerdef ChooseOneRemoteInstance(cfg):
260*800a58d9SAndroid Build Coastguard Worker    """Get one remote cuttlefish instance.
261*800a58d9SAndroid Build Coastguard Worker
262*800a58d9SAndroid Build Coastguard Worker    Retrieve all remote cuttlefish instances and if there is more than 1 instance
263*800a58d9SAndroid Build Coastguard Worker    found, ask user which instance they'd like.
264*800a58d9SAndroid Build Coastguard Worker
265*800a58d9SAndroid Build Coastguard Worker    Args:
266*800a58d9SAndroid Build Coastguard Worker        cfg: AcloudConfig object.
267*800a58d9SAndroid Build Coastguard Worker
268*800a58d9SAndroid Build Coastguard Worker    Raises:
269*800a58d9SAndroid Build Coastguard Worker        errors.NoInstancesFound: No cuttlefish remote instance found.
270*800a58d9SAndroid Build Coastguard Worker
271*800a58d9SAndroid Build Coastguard Worker    Returns:
272*800a58d9SAndroid Build Coastguard Worker        list.Instance() object.
273*800a58d9SAndroid Build Coastguard Worker    """
274*800a58d9SAndroid Build Coastguard Worker    instances_list = GetCFRemoteInstances(cfg)
275*800a58d9SAndroid Build Coastguard Worker    if not instances_list:
276*800a58d9SAndroid Build Coastguard Worker        raise errors.NoInstancesFound(
277*800a58d9SAndroid Build Coastguard Worker            "Can't find any cuttlefish remote instances, please try "
278*800a58d9SAndroid Build Coastguard Worker            "'$acloud create' to create instances")
279*800a58d9SAndroid Build Coastguard Worker    if len(instances_list) > 1:
280*800a58d9SAndroid Build Coastguard Worker        print("Multiple instances detected, choose any one to proceed:")
281*800a58d9SAndroid Build Coastguard Worker        instances = utils.GetAnswerFromList(instances_list,
282*800a58d9SAndroid Build Coastguard Worker                                            enable_choose_all=False)
283*800a58d9SAndroid Build Coastguard Worker        return instances[0]
284*800a58d9SAndroid Build Coastguard Worker
285*800a58d9SAndroid Build Coastguard Worker    return instances_list[0]
286*800a58d9SAndroid Build Coastguard Worker
287*800a58d9SAndroid Build Coastguard Worker
288*800a58d9SAndroid Build Coastguard Workerdef _FilterInstancesByNames(instances, names):
289*800a58d9SAndroid Build Coastguard Worker    """Find instances by names.
290*800a58d9SAndroid Build Coastguard Worker
291*800a58d9SAndroid Build Coastguard Worker    Args:
292*800a58d9SAndroid Build Coastguard Worker        instances: Collection of Instance objects.
293*800a58d9SAndroid Build Coastguard Worker        names: Collection of strings, the names of the instances to search for.
294*800a58d9SAndroid Build Coastguard Worker
295*800a58d9SAndroid Build Coastguard Worker    Returns:
296*800a58d9SAndroid Build Coastguard Worker        List of Instance objects.
297*800a58d9SAndroid Build Coastguard Worker
298*800a58d9SAndroid Build Coastguard Worker    Raises:
299*800a58d9SAndroid Build Coastguard Worker        errors.NoInstancesFound if any instance is not found.
300*800a58d9SAndroid Build Coastguard Worker    """
301*800a58d9SAndroid Build Coastguard Worker    instance_map = {inst.name: inst for inst in instances}
302*800a58d9SAndroid Build Coastguard Worker    found_instances = []
303*800a58d9SAndroid Build Coastguard Worker    missing_instance_names = []
304*800a58d9SAndroid Build Coastguard Worker    for name in names:
305*800a58d9SAndroid Build Coastguard Worker        if name in instance_map:
306*800a58d9SAndroid Build Coastguard Worker            found_instances.append(instance_map[name])
307*800a58d9SAndroid Build Coastguard Worker        else:
308*800a58d9SAndroid Build Coastguard Worker            missing_instance_names.append(name)
309*800a58d9SAndroid Build Coastguard Worker
310*800a58d9SAndroid Build Coastguard Worker    if missing_instance_names:
311*800a58d9SAndroid Build Coastguard Worker        raise errors.NoInstancesFound("Did not find the following instances: %s" %
312*800a58d9SAndroid Build Coastguard Worker                                      " ".join(missing_instance_names))
313*800a58d9SAndroid Build Coastguard Worker    return found_instances
314*800a58d9SAndroid Build Coastguard Worker
315*800a58d9SAndroid Build Coastguard Worker
316*800a58d9SAndroid Build Coastguard Workerdef GetLocalInstanceLockByName(name):
317*800a58d9SAndroid Build Coastguard Worker    """Get the lock of a local cuttelfish or goldfish instance.
318*800a58d9SAndroid Build Coastguard Worker
319*800a58d9SAndroid Build Coastguard Worker    Args:
320*800a58d9SAndroid Build Coastguard Worker        name: The instance name.
321*800a58d9SAndroid Build Coastguard Worker
322*800a58d9SAndroid Build Coastguard Worker    Returns:
323*800a58d9SAndroid Build Coastguard Worker        LocalInstanceLock object. None if the name is invalid.
324*800a58d9SAndroid Build Coastguard Worker    """
325*800a58d9SAndroid Build Coastguard Worker    cf_id = instance.GetLocalInstanceIdByName(name)
326*800a58d9SAndroid Build Coastguard Worker    if cf_id is not None:
327*800a58d9SAndroid Build Coastguard Worker        return instance.GetLocalInstanceLock(cf_id)
328*800a58d9SAndroid Build Coastguard Worker
329*800a58d9SAndroid Build Coastguard Worker    gf_id = instance.LocalGoldfishInstance.GetIdByName(name)
330*800a58d9SAndroid Build Coastguard Worker    if gf_id is not None:
331*800a58d9SAndroid Build Coastguard Worker        return instance.LocalGoldfishInstance.GetLockById(gf_id)
332*800a58d9SAndroid Build Coastguard Worker
333*800a58d9SAndroid Build Coastguard Worker    return None
334*800a58d9SAndroid Build Coastguard Worker
335*800a58d9SAndroid Build Coastguard Worker
336*800a58d9SAndroid Build Coastguard Workerdef GetLocalInstancesByNames(names):
337*800a58d9SAndroid Build Coastguard Worker    """Get local cuttlefish and goldfish instances by names.
338*800a58d9SAndroid Build Coastguard Worker
339*800a58d9SAndroid Build Coastguard Worker    This method does not raise an error if it cannot find all instances.
340*800a58d9SAndroid Build Coastguard Worker
341*800a58d9SAndroid Build Coastguard Worker    Args:
342*800a58d9SAndroid Build Coastguard Worker        names: Collection of instance names.
343*800a58d9SAndroid Build Coastguard Worker
344*800a58d9SAndroid Build Coastguard Worker    Returns:
345*800a58d9SAndroid Build Coastguard Worker        List consisting of LocalInstance and LocalGoldfishInstance objects.
346*800a58d9SAndroid Build Coastguard Worker    """
347*800a58d9SAndroid Build Coastguard Worker    id_cfg_pairs = []
348*800a58d9SAndroid Build Coastguard Worker    for name in names:
349*800a58d9SAndroid Build Coastguard Worker        ins_id = instance.GetLocalInstanceIdByName(name)
350*800a58d9SAndroid Build Coastguard Worker        if ins_id is None:
351*800a58d9SAndroid Build Coastguard Worker            continue
352*800a58d9SAndroid Build Coastguard Worker        cfg_path = instance.GetLocalInstanceConfig(ins_id)
353*800a58d9SAndroid Build Coastguard Worker        if cfg_path:
354*800a58d9SAndroid Build Coastguard Worker            id_cfg_pairs.append((ins_id, cfg_path))
355*800a58d9SAndroid Build Coastguard Worker        if ins_id == 1:
356*800a58d9SAndroid Build Coastguard Worker            cfg_path = instance.GetDefaultCuttlefishConfig()
357*800a58d9SAndroid Build Coastguard Worker            if cfg_path:
358*800a58d9SAndroid Build Coastguard Worker                id_cfg_pairs.append((ins_id, cfg_path))
359*800a58d9SAndroid Build Coastguard Worker
360*800a58d9SAndroid Build Coastguard Worker    gf_instances = [ins for ins in
361*800a58d9SAndroid Build Coastguard Worker                    instance.LocalGoldfishInstance.GetExistingInstances()
362*800a58d9SAndroid Build Coastguard Worker                    if ins.name in names]
363*800a58d9SAndroid Build Coastguard Worker
364*800a58d9SAndroid Build Coastguard Worker    return _GetLocalCuttlefishInstances(id_cfg_pairs) + gf_instances
365*800a58d9SAndroid Build Coastguard Worker
366*800a58d9SAndroid Build Coastguard Worker
367*800a58d9SAndroid Build Coastguard Workerdef GetInstancesFromInstanceNames(cfg, instance_names):
368*800a58d9SAndroid Build Coastguard Worker    """Get instances from instance names.
369*800a58d9SAndroid Build Coastguard Worker
370*800a58d9SAndroid Build Coastguard Worker    Turn a list of instance names into a list of Instance().
371*800a58d9SAndroid Build Coastguard Worker
372*800a58d9SAndroid Build Coastguard Worker    Args:
373*800a58d9SAndroid Build Coastguard Worker        cfg: AcloudConfig object.
374*800a58d9SAndroid Build Coastguard Worker        instance_names: list of instance name.
375*800a58d9SAndroid Build Coastguard Worker
376*800a58d9SAndroid Build Coastguard Worker    Returns:
377*800a58d9SAndroid Build Coastguard Worker        List of Instance() objects.
378*800a58d9SAndroid Build Coastguard Worker
379*800a58d9SAndroid Build Coastguard Worker    Raises:
380*800a58d9SAndroid Build Coastguard Worker        errors.NoInstancesFound: No instances found.
381*800a58d9SAndroid Build Coastguard Worker    """
382*800a58d9SAndroid Build Coastguard Worker    return _FilterInstancesByNames(
383*800a58d9SAndroid Build Coastguard Worker        GetLocalInstancesByNames(instance_names) + GetRemoteInstances(cfg),
384*800a58d9SAndroid Build Coastguard Worker        instance_names)
385*800a58d9SAndroid Build Coastguard Worker
386*800a58d9SAndroid Build Coastguard Worker
387*800a58d9SAndroid Build Coastguard Workerdef FilterInstancesByAdbPort(instances, adb_port):
388*800a58d9SAndroid Build Coastguard Worker    """Find an instance by adb port.
389*800a58d9SAndroid Build Coastguard Worker
390*800a58d9SAndroid Build Coastguard Worker    Args:
391*800a58d9SAndroid Build Coastguard Worker        instances: Collection of Instance objects.
392*800a58d9SAndroid Build Coastguard Worker        adb_port: int, adb port of the instance to search for.
393*800a58d9SAndroid Build Coastguard Worker
394*800a58d9SAndroid Build Coastguard Worker    Returns:
395*800a58d9SAndroid Build Coastguard Worker        List of Instance() objects.
396*800a58d9SAndroid Build Coastguard Worker
397*800a58d9SAndroid Build Coastguard Worker    Raises:
398*800a58d9SAndroid Build Coastguard Worker        errors.NoInstancesFound: No instances found.
399*800a58d9SAndroid Build Coastguard Worker    """
400*800a58d9SAndroid Build Coastguard Worker    all_instance_info = []
401*800a58d9SAndroid Build Coastguard Worker    for instance_object in instances:
402*800a58d9SAndroid Build Coastguard Worker        if instance_object.adb_port == adb_port:
403*800a58d9SAndroid Build Coastguard Worker            return [instance_object]
404*800a58d9SAndroid Build Coastguard Worker        all_instance_info.append(instance_object.fullname)
405*800a58d9SAndroid Build Coastguard Worker
406*800a58d9SAndroid Build Coastguard Worker    # Show devices information to user when user provides wrong adb port.
407*800a58d9SAndroid Build Coastguard Worker    if all_instance_info:
408*800a58d9SAndroid Build Coastguard Worker        hint_message = ("No instance with adb port %d, available instances:\n%s"
409*800a58d9SAndroid Build Coastguard Worker                        % (adb_port, "\n".join(all_instance_info)))
410*800a58d9SAndroid Build Coastguard Worker    else:
411*800a58d9SAndroid Build Coastguard Worker        hint_message = "No instances to delete."
412*800a58d9SAndroid Build Coastguard Worker    raise errors.NoInstancesFound(hint_message)
413*800a58d9SAndroid Build Coastguard Worker
414*800a58d9SAndroid Build Coastguard Worker
415*800a58d9SAndroid Build Coastguard Workerdef GetCFRemoteInstances(cfg):
416*800a58d9SAndroid Build Coastguard Worker    """Look for cuttlefish remote instances.
417*800a58d9SAndroid Build Coastguard Worker
418*800a58d9SAndroid Build Coastguard Worker    Args:
419*800a58d9SAndroid Build Coastguard Worker        cfg: AcloudConfig object.
420*800a58d9SAndroid Build Coastguard Worker
421*800a58d9SAndroid Build Coastguard Worker    Returns:
422*800a58d9SAndroid Build Coastguard Worker        instance_list: List of instance names.
423*800a58d9SAndroid Build Coastguard Worker    """
424*800a58d9SAndroid Build Coastguard Worker    instances = GetRemoteInstances(cfg)
425*800a58d9SAndroid Build Coastguard Worker    return [ins for ins in instances if ins.avd_type == constants.TYPE_CF]
426*800a58d9SAndroid Build Coastguard Worker
427*800a58d9SAndroid Build Coastguard Worker
428*800a58d9SAndroid Build Coastguard Workerdef Run(args):
429*800a58d9SAndroid Build Coastguard Worker    """Run list.
430*800a58d9SAndroid Build Coastguard Worker
431*800a58d9SAndroid Build Coastguard Worker    Args:
432*800a58d9SAndroid Build Coastguard Worker        args: Namespace object from argparse.parse_args.
433*800a58d9SAndroid Build Coastguard Worker    """
434*800a58d9SAndroid Build Coastguard Worker    instances = GetLocalInstances()
435*800a58d9SAndroid Build Coastguard Worker    cfg = config.GetAcloudConfig(args)
436*800a58d9SAndroid Build Coastguard Worker    if not args.local_only and cfg.SupportRemoteInstance():
437*800a58d9SAndroid Build Coastguard Worker        instances.extend(GetRemoteInstances(cfg))
438*800a58d9SAndroid Build Coastguard Worker
439*800a58d9SAndroid Build Coastguard Worker    PrintInstancesDetails(instances, args.verbose)
440