def StartAnalysisVm(
    vm_name: str,
    default_availability_zone: str,
    boot_volume_size: int,
    boot_volume_type: str = 'gp3',
    ami: Optional[str] = None,
    cpu_cores: int = 4,
    attach_volumes: Optional[List[Tuple[str, str]]] = None,
    dst_profile: Optional[str] = None,
    ssh_key_name: Optional[str] = None,
    tags: Optional[Dict[str, str]] = None,
    subnet_id: Optional[str] = None,
    security_group_id: Optional[str] = None,
    userdata_file: Optional[str] = None
    ) -> Tuple['ec2.AWSInstance', bool]:
  """Start a virtual machine for analysis purposes.

  Look for an existing AWS instance with tag name vm_name. If found,
  this instance will be started and used as analysis VM. If not found, then a
  new vm with that name will be created, started and returned.

  Args:
    vm_name (str): The name for the virtual machine.
    default_availability_zone (str): Default zone within the region to create
        new resources in.
    boot_volume_size (int): The size of the analysis VM boot volume (in GB).
    boot_volume_type (str): Optional. The volume type for the boot volume
        of the VM. Can be one of 'standard'|'io1'|'gp2'|'gp3'|'sc1'|'st1'. The
        default is 'gp3'.
    ami (str): Optional. The Amazon Machine Image ID to use to create the VM.
        Default is a version of Ubuntu 22.04.
    cpu_cores (int): Optional. The number of CPU cores to create the machine
        with. Default is 4.
    attach_volumes (List[Tuple[str, str]]): Optional. List of tuples
        containing the volume IDs (str) to attach and their respective device
        name (str, e.g. /dev/sdf). Note that it is mandatory to provide a
        unique device name per volume to attach.
    dst_profile (str): Optional. The AWS account in which to create the
        analysis VM. This is the profile name that is defined in your AWS
        credentials file.
    ssh_key_name (str): Optional. A SSH key pair name linked to the AWS
        account to associate with the VM. If none provided, the VM can only
        be accessed through in-browser SSH from the AWS management console
        with the EC2 client connection package (ec2-instance-connect). Note
        that if this package fails to install on the target VM, then the VM
        will not be accessible. It is therefore recommended to fill in this
        parameter.
    tags (Dict[str, str]): Optional. A dictionary of tags to add to the
        instance, for example {'TicketID': 'xxx'}. An entry for the instance
        name is added by default.
    subnet_id (str): Optional. The subnet to launch the instance in.
    security_group_id (str): Optional. Security group ID to attach.
    userdata_file (str): Optional. Filename to be read in as the userdata
        launch script.

  Returns:
    Tuple[AWSInstance, bool]: a tuple with a virtual machine object
        and a boolean indicating if the virtual machine was created or not.

  Raises:
    RuntimeError: When multiple AMI images are returned.
  """

  aws_account = account.AWSAccount(
      default_availability_zone, aws_profile=dst_profile)

  # If no AMI ID is given we use the default Ubuntu 22.04
  # in the region requested.
  if not ami:
    logger.info('No AMI provided, fetching one for Ubuntu 22.04')
    qfilter = [{'Name': 'name', 'Values': [UBUNTU_2204_FILTER]}]
    ami_list = aws_account.ec2.ListImages(qfilter)
    # We should only get 1 AMI image back, if we get multiple we
    # have no way of knowing which one to use.
    if len(ami_list) > 1:
      image_names = [image['Name'] for image in ami_list]
      raise RuntimeError('error - ListImages returns >1 AMI image: [{0:s}]'
                         .format(', '.join(image_names)))
    ami = ami_list[0]['ImageId']
  assert ami  # Mypy: assert that ami is not None

  if not userdata_file:
    userdata_file = utils.FORENSICS_STARTUP_SCRIPT_AWS
  userdata = utils.ReadStartupScript(userdata_file)

  logger.info('Starting analysis VM {0:s}'.format(vm_name))
  analysis_vm, created = aws_account.ec2.GetOrCreateVm(
      vm_name,
      boot_volume_size,
      ami,
      cpu_cores,
      boot_volume_type=boot_volume_type,
      ssh_key_name=ssh_key_name,
      tags=tags,
      subnet_id=subnet_id,
      security_group_id=security_group_id,
      userdata=userdata)
  logger.info('VM started.')
  for volume_id, device_name in (attach_volumes or []):
    logger.info('Attaching volume {0:s} to device {1:s}'.format(
        volume_id, device_name))
    analysis_vm.AttachVolume(
        aws_account.ebs.GetVolumeById(volume_id), device_name)
  logger.info('VM ready.')
  return analysis_vm, created
Start a virtual machine for analysis purposes.

Look for an existing AWS instance with tag name vm_name. If found,
this instance will be started and used as analysis VM. If not found, then a
new vm with that name will be created, started and returned.

Args:
vm_name (str): The name for the virtual machine.
default_availability_zone (str): Default zone within the region to create
new resources in.
boot_volume_size (int): The size of the analysis VM boot volume (in GB).
boot_volume_type (str): Optional. The volume type for the boot volume
of the VM. Can be one of 'standard'|'io1'|'gp2'|'gp3'|'sc1'|'st1'. The
default is 'gp3'.
ami (str): Optional. The Amazon Machine Image ID to use to create the VM.
Default is a version of Ubuntu 22.04.
cpu_cores (int): Optional. The number of CPU cores to create the machine
with. Default is 4.
attach_volumes (List[Tuple[str, str]]): Optional. List of tuples
containing the volume IDs (str) to attach and their respective device
name (str, e.g. /dev/sdf). Note that it is mandatory to provide a
unique device name per volume to attach.
dst_profile (str): Optional. The AWS account in which to create the
analysis VM. This is the profile name that is defined in your AWS
credentials file.
ssh_key_name (str): Optional. A SSH key pair name linked to the AWS
account to associate with the VM. If none provided, the VM can only
be accessed through in-browser SSH from the AWS management console
with the EC2 client connection package (ec2-instance-connect). Note
that if this package fails to install on the target VM, then the VM
will not be accessible. It is therefore recommended to fill in this
parameter.
tags (Dict[str, str]): Optional. A dictionary of tags to add to the
instance, for example {'TicketID': 'xxx'}. An entry for the instance
name is added by default.
subnet_id (str): Optional. The subnet to launch the instance in.
security_group_id (str): Optional. Security group ID to attach.
userdata_file (str): Optional. Filename to be read in as the userdata
launch script.

Returns:
Tuple[AWSInstance, bool]: a tuple with a virtual machine object
and a boolean indicating if the virtual machine was created or not.

Raises:
RuntimeError: When multiple AMI images are returned.
libcloudforensics/providers/aws/forensics.py