1# Copyright 2021 - The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""This module implements the classes and functions needed for the common 16creation flow.""" 17 18import re 19 20from acloud.internal import constants 21from acloud.internal.lib import ssh 22from acloud.public import config 23 24 25_INSTANCE_NAME_FORMAT = ("host-goldfish-%(ip_addr)s-%(console_port)s-" 26 "%(build_id)s-%(build_target)s") 27_INSTANCE_NAME_PATTERN = re.compile( 28 r"host-goldfish-(?P<ip_addr>[\d.]+)-(?P<console_port>\d+)-.+") 29# Report keys 30_VERSION = "version" 31 32 33def FormatInstanceName(ip_addr, console_port, build_info): 34 """Convert address and build info to an instance name. 35 36 Args: 37 ip_addr: A string, the IP address of the host. 38 console_port: An integer, the emulator console port. 39 build_info: A dict containing the build ID and target. 40 41 Returns: 42 A string, the instance name. 43 """ 44 return _INSTANCE_NAME_FORMAT % { 45 "ip_addr": ip_addr, 46 "console_port": console_port, 47 "build_id": build_info.get(constants.BUILD_ID), 48 "build_target": build_info.get(constants.BUILD_TARGET)} 49 50 51def ParseEmulatorConsoleAddress(instance_name): 52 """Parse emulator console address from an instance name. 53 54 Args: 55 instance_name: A string, the instance name. 56 57 Returns: 58 The IP address as a string and the console port as an integer. 59 None if the name does not represent a goldfish instance on remote host. 60 """ 61 match = _INSTANCE_NAME_PATTERN.fullmatch(instance_name) 62 return ((match.group("ip_addr"), int(match.group("console_port"))) 63 if match else None) 64 65 66class GoldfishRemoteHostClient: 67 """A client that manages goldfish instance on a remote host.""" 68 69 @staticmethod 70 def GetInstanceIP(instance_name): 71 """Parse the IP address from an instance name.""" 72 ip_and_port = ParseEmulatorConsoleAddress(instance_name) 73 if not ip_and_port: 74 raise ValueError("Cannot parse instance name: %s" % instance_name) 75 return ssh.IP(ip=ip_and_port[0]) 76 77 @staticmethod 78 def WaitForBoot(_instance_name, _boot_timeout_secs): 79 """Should not be called in the common creation flow.""" 80 raise NotImplementedError("The common creation flow should call " 81 "GetFailures instead of this method.") 82 83 @staticmethod 84 def GetSerialPortOutput(): 85 """Remote hosts do not support serial log.""" 86 return "" 87 88 @property 89 def dict_report(self): 90 """Return the key-value pairs to be written to the report.""" 91 return {_VERSION: config.GetVersion()} 92