Exemple #1
0
    def __init__(self,
                 local_instance_id,
                 avd_flavor=None,
                 create_time=None,
                 x_res=None,
                 y_res=None,
                 dpi=None):
        """Initialize a LocalGoldfishInstance object.

        Args:
            local_instance_id: Integer of instance id.
            avd_flavor: String, the flavor of the virtual device.
            create_time: String, the creation date and time.
            x_res: Integer of x dimension.
            y_res: Integer of y dimension.
            dpi: Integer of dpi.
        """
        self._id = local_instance_id
        adb_port = self.console_port + 1
        self._adb = AdbTools(adb_port=adb_port,
                             device_serial=self.device_serial)

        name = self._INSTANCE_NAME_FORMAT % {"id": local_instance_id}

        elapsed_time = _GetElapsedTime(create_time) if create_time else None

        fullname = _FULL_NAME_STRING % {
            "device_serial": self.device_serial,
            "instance_name": name,
            "elapsed_time": elapsed_time
        }

        if x_res and y_res and dpi:
            display = _DISPLAY_STRING % {
                "x_res": x_res,
                "y_res": y_res,
                "dpi": dpi
            }
        else:
            display = "unknown"

        device_information = (self._adb.device_information
                              if self._adb.device_information else None)

        super(LocalGoldfishInstance,
              self).__init__(name=name,
                             fullname=fullname,
                             display=display,
                             ip="127.0.0.1",
                             status=None,
                             adb_port=adb_port,
                             avd_type=constants.TYPE_GF,
                             createtime=create_time,
                             elapsed_time=elapsed_time,
                             avd_flavor=avd_flavor,
                             is_local=True,
                             device_information=device_information)
Exemple #2
0
    def __init__(self, cf_config_path):
        """Initialize a localInstance object.

        Args:
            cf_config_path: String, path to the cf runtime config.
        """
        self._cf_runtime_cfg = cvd_runtime_config.CvdRuntimeConfig(
            cf_config_path)
        self._instance_dir = self._cf_runtime_cfg.instance_dir
        self._virtual_disk_paths = self._cf_runtime_cfg.virtual_disk_paths
        self._local_instance_id = int(self._cf_runtime_cfg.instance_id)

        display = _DISPLAY_STRING % {
            "x_res": self._cf_runtime_cfg.x_res,
            "y_res": self._cf_runtime_cfg.y_res,
            "dpi": self._cf_runtime_cfg.dpi
        }
        # TODO(143063678), there's no createtime info in
        # cuttlefish_config.json so far.
        name = GetLocalInstanceName(self._local_instance_id)
        fullname = (_FULL_NAME_STRING % {
            "device_serial": "127.0.0.1:%s" % self._cf_runtime_cfg.adb_port,
            "instance_name": name,
            "elapsed_time": None
        })
        adb_device = AdbTools(self._cf_runtime_cfg.adb_port)
        device_information = None
        if adb_device.IsAdbConnected():
            device_information = adb_device.device_information

        super(LocalInstance,
              self).__init__(name=name,
                             fullname=fullname,
                             display=display,
                             ip="127.0.0.1",
                             status=constants.INS_STATUS_RUNNING,
                             adb_port=self._cf_runtime_cfg.adb_port,
                             vnc_port=self._cf_runtime_cfg.vnc_port,
                             createtime=None,
                             elapsed_time=None,
                             avd_type=constants.TYPE_CF,
                             is_local=True,
                             device_information=device_information,
                             zone=_LOCAL_ZONE)
Exemple #3
0
 def GetExistingInstances(cls):
     """Get the list of instances that adb can send emu commands to."""
     instances = []
     for serial in AdbTools.GetDeviceSerials():
         match = cls._DEVICE_SERIAL_PATTERN.match(serial)
         if not match:
             continue
         port = int(match.group("console_port"))
         instance_id = (port - cls._EMULATOR_DEFAULT_CONSOLE_PORT) // 2 + 1
         instances.append(LocalGoldfishInstance(instance_id))
     return instances
Exemple #4
0
    def Delete(self):
        """Execute stop_cvd to stop local cuttlefish instance.

        - We should get the same host tool used to launch cvd to delete instance
        , So get stop_cvd bin from the cvd runtime config.
        - Add CUTTLEFISH_CONFIG_FILE env variable to tell stop_cvd which cvd
        need to be deleted.
        - Stop adb since local instance use the fixed adb port and could be
         reused again soon.
        """
        stop_cvd_cmd = os.path.join(self.cf_runtime_cfg.cvd_tools_path,
                                    constants.CMD_STOP_CVD)
        logger.debug("Running cmd[%s] to delete local cvd", stop_cvd_cmd)
        with open(os.devnull, "w") as dev_null:
            cvd_env = os.environ.copy()
            if self.instance_dir:
                cvd_env[
                    constants.
                    ENV_CUTTLEFISH_CONFIG_FILE] = self._cf_runtime_cfg.config_path
                cvd_env[constants.ENV_CVD_HOME] = GetLocalInstanceHomeDir(
                    self._local_instance_id)
                cvd_env[constants.ENV_CUTTLEFISH_INSTANCE] = str(
                    self._local_instance_id)
            else:
                logger.error(
                    "instance_dir is null!! instance[%d] might not be"
                    " deleted", self._local_instance_id)
            subprocess.check_call(utils.AddUserGroupsToCmd(
                stop_cvd_cmd, constants.LIST_CF_USER_GROUPS),
                                  stderr=dev_null,
                                  stdout=dev_null,
                                  shell=True,
                                  env=cvd_env)

        adb_cmd = AdbTools(self.adb_port)
        # When relaunch a local instance, we need to pass in retry=True to make
        # sure adb device is completely gone since it will use the same adb port
        adb_cmd.DisconnectAdb(retry=True)
Exemple #5
0
def CreateGCETypeAVD(cfg,
                     build_target=None,
                     build_id=None,
                     num=1,
                     gce_image=None,
                     local_disk_image=None,
                     cleanup=True,
                     serial_log_file=None,
                     autoconnect=False,
                     report_internal_ip=False,
                     avd_spec=None):
    """Creates one or multiple gce android devices.

    Args:
        cfg: An AcloudConfig instance.
        build_target: Target name, e.g. "aosp_cf_x86_phone-userdebug"
        build_id: Build id, a string, e.g. "2263051", "P2804227"
        num: Number of devices to create.
        gce_image: string, if given, will use this gce image
                   instead of creating a new one.
                   implies cleanup=False.
        local_disk_image: string, path to a local disk image, e.g.
                          /tmp/avd-system.tar.gz
        cleanup: boolean, if True clean up compute engine image and
                 disk image in storage after creating the instance.
        serial_log_file: A path to a file where serial output should
                         be saved to.
        autoconnect: Create ssh tunnel(s) and adb connect after device creation.
        report_internal_ip: Boolean to report the internal ip instead of
                            external ip.
        avd_spec: AVDSpec object for pass hw_property.

    Returns:
        A Report instance.
    """
    r = report.Report(command="create")
    credentials = auth.CreateCredentials(cfg)
    compute_client = android_compute_client.AndroidComputeClient(
        cfg, credentials)
    try:
        common_operations.CreateSshKeyPairIfNecessary(cfg)
        device_pool = AndroidVirtualDevicePool(cfg)
        device_pool.CreateDevices(
            num,
            build_target,
            build_id,
            gce_image,
            local_disk_image,
            cleanup,
            extra_data_disk_size_gb=cfg.extra_data_disk_size_gb,
            precreated_data_image=cfg.precreated_data_image_map.get(
                cfg.extra_data_disk_size_gb),
            avd_spec=avd_spec,
            extra_scopes=cfg.extra_scopes)
        failures = device_pool.WaitForBoot()
        # Write result to report.
        for device in device_pool.devices:
            ip = (device.ip.internal
                  if report_internal_ip else device.ip.external)
            device_dict = {"ip": ip, "instance_name": device.instance_name}
            if autoconnect:
                forwarded_ports = utils.AutoConnect(
                    ip_addr=ip,
                    rsa_key_file=cfg.ssh_private_key_path,
                    target_vnc_port=constants.GCE_VNC_PORT,
                    target_adb_port=constants.GCE_ADB_PORT,
                    ssh_user=_SSH_USER,
                    client_adb_port=avd_spec.client_adb_port,
                    extra_args_ssh_tunnel=cfg.extra_args_ssh_tunnel)
                device_dict[constants.VNC_PORT] = forwarded_ports.vnc_port
                device_dict[constants.ADB_PORT] = forwarded_ports.adb_port
                if avd_spec.unlock_screen:
                    AdbTools(forwarded_ports.adb_port).AutoUnlockScreen()
            if device.instance_name in failures:
                r.AddData(key="devices_failing_boot", value=device_dict)
                r.AddError(str(failures[device.instance_name]))
            else:
                r.AddData(key="devices", value=device_dict)
        if failures:
            r.SetStatus(report.Status.BOOT_FAIL)
        else:
            r.SetStatus(report.Status.SUCCESS)

        # Dump serial logs.
        if serial_log_file:
            _FetchSerialLogsFromDevices(
                compute_client,
                instance_names=[d.instance_name for d in device_pool.devices],
                port=constants.DEFAULT_SERIAL_PORT,
                output_file=serial_log_file)
    except errors.DriverError as e:
        r.AddError(str(e))
        r.SetStatus(report.Status.FAIL)
    return r
Exemple #6
0
def ReconnectInstance(ssh_private_key_path,
                      instance,
                      reconnect_report,
                      extra_args_ssh_tunnel=None,
                      connect_vnc=True):
    """Reconnect to the specified instance.

    It will:
     - re-establish ssh tunnels for adb/vnc port forwarding
     - re-establish adb connection
     - restart vnc client
     - update device information in reconnect_report

    Args:
        ssh_private_key_path: Path to the private key file.
                              e.g. ~/.ssh/acloud_rsa
        instance: list.Instance() object.
        reconnect_report: Report object.
        extra_args_ssh_tunnel: String, extra args for ssh tunnel connection.
        connect_vnc: Boolean, True will launch vnc.

    Raises:
        errors.UnknownAvdType: Unable to reconnect to instance of unknown avd
                               type.
    """
    if instance.avd_type not in utils.AVD_PORT_DICT:
        raise errors.UnknownAvdType("Unable to reconnect to instance (%s) of "
                                    "unknown avd type: %s" %
                                    (instance.name, instance.avd_type))

    adb_cmd = AdbTools(instance.adb_port)
    vnc_port = instance.vnc_port
    adb_port = instance.adb_port
    # ssh tunnel is up but device is disconnected on adb
    if instance.ssh_tunnel_is_connected and not adb_cmd.IsAdbConnectionAlive():
        adb_cmd.DisconnectAdb()
        adb_cmd.ConnectAdb()
    # ssh tunnel is down and it's a remote instance
    elif not instance.ssh_tunnel_is_connected and not instance.islocal:
        adb_cmd.DisconnectAdb()
        forwarded_ports = utils.AutoConnect(
            ip_addr=instance.ip,
            rsa_key_file=ssh_private_key_path,
            target_vnc_port=utils.AVD_PORT_DICT[instance.avd_type].vnc_port,
            target_adb_port=utils.AVD_PORT_DICT[instance.avd_type].adb_port,
            ssh_user=constants.GCE_USER,
            extra_args_ssh_tunnel=extra_args_ssh_tunnel)
        vnc_port = forwarded_ports.vnc_port
        adb_port = forwarded_ports.adb_port
    if _IsWebrtcEnable(instance, constants.GCE_USER, ssh_private_key_path,
                       extra_args_ssh_tunnel):
        if instance.islocal:
            if _WebrtcPortOccupied():
                raise errors.PortOccupied(
                    "\nReconnect to a local webrtc instance "
                    "is not work because remote webrtc "
                    "instance has established ssh tunnel "
                    "which occupied local webrtc instance "
                    "port. If you want to connect to a "
                    "local-instance of webrtc. please run "
                    "'acloud create --local-instance "
                    "--autoconnect webrtc' directly.")
        else:
            utils.EstablishWebRTCSshTunnel(
                ip_addr=instance.ip,
                rsa_key_file=ssh_private_key_path,
                ssh_user=constants.GCE_USER,
                extra_args_ssh_tunnel=extra_args_ssh_tunnel)
        utils.LaunchBrowser(constants.WEBRTC_LOCAL_HOST,
                            constants.WEBRTC_LOCAL_PORT)
    elif (vnc_port and connect_vnc):
        StartVnc(vnc_port, instance.display)

    device_dict = {
        constants.IP: instance.ip,
        constants.INSTANCE_NAME: instance.name,
        constants.VNC_PORT: vnc_port,
        constants.ADB_PORT: adb_port
    }

    if vnc_port and adb_port:
        reconnect_report.AddData(key="devices", value=device_dict)
    else:
        # We use 'ps aux' to grep adb/vnc fowarding port from ssh tunnel
        # command. Therefore we report failure here if no vnc_port and
        # adb_port found.
        reconnect_report.AddData(key="device_failing_reconnect",
                                 value=device_dict)
        reconnect_report.AddError(instance.name)
Exemple #7
0
def CreateDevices(command,
                  cfg,
                  device_factory,
                  num,
                  avd_type,
                  report_internal_ip=False,
                  autoconnect=False,
                  serial_log_file=None,
                  client_adb_port=None,
                  boot_timeout_secs=None,
                  unlock_screen=False,
                  wait_for_boot=True,
                  connect_webrtc=False):
    """Create a set of devices using the given factory.

    Main jobs in create devices.
        1. Create GCE instance: Launch instance in GCP(Google Cloud Platform).
        2. Starting up AVD: Wait device boot up.

    Args:
        command: The name of the command, used for reporting.
        cfg: An AcloudConfig instance.
        device_factory: A factory capable of producing a single device.
        num: The number of devices to create.
        avd_type: String, the AVD type(cuttlefish, goldfish...).
        report_internal_ip: Boolean to report the internal ip instead of
                            external ip.
        serial_log_file: String, the file path to tar the serial logs.
        autoconnect: Boolean, whether to auto connect to device.
        client_adb_port: Integer, Specify port for adb forwarding.
        boot_timeout_secs: Integer, boot timeout secs.
        unlock_screen: Boolean, whether to unlock screen after invoke vnc client.
        wait_for_boot: Boolean, True to check serial log include boot up
                       message.
        connect_webrtc: Boolean, whether to auto connect webrtc to device.

    Raises:
        errors: Create instance fail.

    Returns:
        A Report instance.
    """
    reporter = report.Report(command=command)
    try:
        CreateSshKeyPairIfNecessary(cfg)
        device_pool = DevicePool(device_factory)
        device_pool.CreateDevices(num)
        device_pool.SetDeviceBuildInfo()
        if wait_for_boot:
            failures = device_pool.WaitForBoot(boot_timeout_secs)
        else:
            failures = device_factory.GetFailures()

        if failures:
            reporter.SetStatus(report.Status.BOOT_FAIL)
        else:
            reporter.SetStatus(report.Status.SUCCESS)

        # Collect logs
        if serial_log_file:
            device_pool.CollectSerialPortLogs(
                serial_log_file, port=constants.DEFAULT_SERIAL_PORT)

        device_pool.UpdateReport(reporter)
        # Write result to report.
        for device in device_pool.devices:
            ip = (device.ip.internal
                  if report_internal_ip else device.ip.external)
            device_dict = {"ip": ip, "instance_name": device.instance_name}
            if device.build_info:
                device_dict.update(device.build_info)
            if device.time_info:
                device_dict.update(device.time_info)
            if autoconnect:
                forwarded_ports = utils.AutoConnect(
                    ip_addr=ip,
                    rsa_key_file=cfg.ssh_private_key_path,
                    target_vnc_port=utils.AVD_PORT_DICT[avd_type].vnc_port,
                    target_adb_port=utils.AVD_PORT_DICT[avd_type].adb_port,
                    ssh_user=constants.GCE_USER,
                    client_adb_port=client_adb_port,
                    extra_args_ssh_tunnel=cfg.extra_args_ssh_tunnel)
                device_dict[constants.VNC_PORT] = forwarded_ports.vnc_port
                device_dict[constants.ADB_PORT] = forwarded_ports.adb_port
                if unlock_screen:
                    AdbTools(forwarded_ports.adb_port).AutoUnlockScreen()
            if connect_webrtc:
                utils.EstablishWebRTCSshTunnel(
                    ip_addr=ip,
                    rsa_key_file=cfg.ssh_private_key_path,
                    ssh_user=constants.GCE_USER,
                    extra_args_ssh_tunnel=cfg.extra_args_ssh_tunnel)
            if device.instance_name in failures:
                device_dict[_ERROR_TYPE] = _DICT_ERROR_TYPE[device.stage]
                reporter.AddData(key="devices_failing_boot", value=device_dict)
                reporter.AddError(str(failures[device.instance_name]))
            else:
                reporter.AddData(key="devices", value=device_dict)
    except errors.DriverError as e:
        reporter.AddError(str(e))
        reporter.SetStatus(report.Status.FAIL)
    return reporter
Exemple #8
0
    def __init__(self, gce_instance):
        """Process the args into class vars.

        RemoteInstace initialized by gce dict object. We parse the required data
        from gce_instance to local variables.
        Reference:
        https://cloud.google.com/compute/docs/reference/rest/v1/instances/get

        We also gather more details on client side including the forwarding adb
        port and vnc port which will be used to determine the status of ssh
        tunnel connection.

        The status of gce instance will be displayed in _fullname property:
        - Connected: If gce instance and ssh tunnel and adb connection are all
         active.
        - No connected: If ssh tunnel or adb connection is not found.
        - Terminated: If we can't retrieve the public ip from gce instance.

        Args:
            gce_instance: dict object queried from gce.
        """
        name = gce_instance.get(constants.INS_KEY_NAME)

        create_time = gce_instance.get(constants.INS_KEY_CREATETIME)
        elapsed_time = _GetElapsedTime(create_time)
        status = gce_instance.get(constants.INS_KEY_STATUS)
        zone = self._GetZoneName(gce_instance.get(constants.INS_KEY_ZONE))

        ip = None
        for network_interface in gce_instance.get("networkInterfaces"):
            for access_config in network_interface.get("accessConfigs"):
                ip = access_config.get("natIP")

        # Get metadata
        display = None
        avd_type = None
        avd_flavor = None
        for metadata in gce_instance.get("metadata", {}).get("items", []):
            key = metadata["key"]
            value = metadata["value"]
            if key == constants.INS_KEY_DISPLAY:
                display = value
            elif key == constants.INS_KEY_AVD_TYPE:
                avd_type = value
            elif key == constants.INS_KEY_AVD_FLAVOR:
                avd_flavor = value

        # Find ssl tunnel info.
        adb_port = None
        vnc_port = None
        device_information = None
        if ip:
            forwarded_ports = self.GetAdbVncPortFromSSHTunnel(ip, avd_type)
            adb_port = forwarded_ports.adb_port
            vnc_port = forwarded_ports.vnc_port
            ssh_tunnel_is_connected = adb_port is not None

            adb_device = AdbTools(adb_port)
            if adb_device.IsAdbConnected():
                device_information = adb_device.device_information
                fullname = (_FULL_NAME_STRING % {
                    "device_serial": "127.0.0.1:%d" % adb_port,
                    "instance_name": name,
                    "elapsed_time": elapsed_time
                })
            else:
                fullname = (_FULL_NAME_STRING % {
                    "device_serial": "not connected",
                    "instance_name": name,
                    "elapsed_time": elapsed_time
                })
        # If instance is terminated, its ip is None.
        else:
            ssh_tunnel_is_connected = False
            fullname = (_FULL_NAME_STRING % {
                "device_serial": "terminated",
                "instance_name": name,
                "elapsed_time": elapsed_time
            })

        super(RemoteInstance,
              self).__init__(name=name,
                             fullname=fullname,
                             display=display,
                             ip=ip,
                             status=status,
                             adb_port=adb_port,
                             vnc_port=vnc_port,
                             ssh_tunnel_is_connected=ssh_tunnel_is_connected,
                             createtime=create_time,
                             elapsed_time=elapsed_time,
                             avd_type=avd_type,
                             avd_flavor=avd_flavor,
                             is_local=False,
                             device_information=device_information,
                             zone=zone)
    def _CreateInstance(self, local_instance_id, local_image_path,
                        host_bins_path, avd_spec, no_prompts):
        """Create a CVD instance.

        Args:
            local_instance_id: Integer of instance id.
            local_image_path: String of local image directory.
            host_bins_path: String of host package directory.
            avd_spec: AVDSpec for the instance.
            no_prompts: Boolean, True to skip all prompts.

        Returns:
            A Report instance.
        """
        if avd_spec.connect_webrtc:
            utils.ReleasePort(constants.WEBRTC_LOCAL_PORT)

        launch_cvd_path = os.path.join(host_bins_path, "bin",
                                       constants.CMD_LAUNCH_CVD)
        cmd = self.PrepareLaunchCVDCmd(launch_cvd_path, avd_spec.hw_property,
                                       avd_spec.connect_adb, local_image_path,
                                       local_instance_id,
                                       avd_spec.connect_webrtc, avd_spec.gpu)

        result_report = report.Report(command="create")
        instance_name = instance.GetLocalInstanceName(local_instance_id)
        try:
            self._LaunchCvd(cmd, local_instance_id, host_bins_path,
                            (avd_spec.boot_timeout_secs
                             or constants.DEFAULT_CF_BOOT_TIMEOUT))
        except errors.LaunchCVDFail as launch_error:
            result_report.SetStatus(report.Status.BOOT_FAIL)
            result_report.AddDeviceBootFailure(instance_name,
                                               constants.LOCALHOST,
                                               None,
                                               None,
                                               error=str(launch_error))
            return result_report

        active_ins = list_instance.GetActiveCVD(local_instance_id)
        if active_ins:
            result_report.SetStatus(report.Status.SUCCESS)
            result_report.AddDevice(instance_name, constants.LOCALHOST,
                                    active_ins.adb_port, active_ins.vnc_port)
            # Launch vnc client if we're auto-connecting.
            if avd_spec.connect_vnc:
                utils.LaunchVNCFromReport(result_report, avd_spec, no_prompts)
            if avd_spec.connect_webrtc:
                utils.LaunchBrowserFromReport(result_report)
            if avd_spec.unlock_screen:
                AdbTools(active_ins.adb_port).AutoUnlockScreen()
        else:
            err_msg = "cvd_status return non-zero after launch_cvd"
            logger.error(err_msg)
            result_report.SetStatus(report.Status.BOOT_FAIL)
            result_report.AddDeviceBootFailure(instance_name,
                                               constants.LOCALHOST,
                                               None,
                                               None,
                                               error=err_msg)
        return result_report