# Path: libcloudforensics/errors.py
# class LCFError(Exception):
# class CredentialsConfigurationError(LCFError):
# class InvalidFileFormatError(LCFError):
# class InvalidNameError(LCFError):
# class ResourceNotFoundError(LCFError):
# class ResourceCreationError(LCFError):
# class ResourceDeletionError(LCFError):
# class InstanceStateChangeError(LCFError):
# class ServiceAccountRemovalError(LCFError):
# class InstanceProfileCreationError(LCFError):
# class OperationFailedError(LCFError):
# class TransferCreationError(LCFError):
# class TransferExecutionError(LCFError):
# class ResourceAlreadyExistsError(LCFError):
#   def __init__(self,
#                message: str,
#                name: str) -> None:
# 
# Path: libcloudforensics/providers/aws/internal/common.py
# EC2_SERVICE = 'ec2'
# ACCOUNT_SERVICE = 'sts'
# KMS_SERVICE = 'kms'
# CLOUDTRAIL_SERVICE = 'cloudtrail'
# S3_SERVICE = 's3'
# IAM_SERVICE = 'iam'
# INSTANCE = 'instance'
# VOLUME = 'volume'
# SNAPSHOT = 'snapshot'
# UBUNTU_1804_FILTER = 'ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-20200611'  # pylint: disable=line-too-long
# ALINUX2_BASE_FILTER = 'amzn2-ami-hvm-2*-x86_64-gp2'
# def CreateTags(resource: str, tags: Dict[str, str]) -> Dict[str, Any]:
# def GetInstanceTypeByCPU(cpu_cores: int) -> str:
# def ExecuteRequest(client: 'botocore.client.EC2',
#                    func: str,
#                    kwargs: Dict[str, Any]) -> List[Dict[str, Any]]:


import binascii
import ipaddress
import os
import random
import botocore
from typing import TYPE_CHECKING, Dict, Optional, List, Any, Tuple
from libcloudforensics import errors
from libcloudforensics.providers.aws.internal import common
  from libcloudforensics.providers.aws.internal import account  # pylint: disable=cyclic-import
  from libcloudforensics.providers.aws.internal import ebs  # pylint: disable=cyclic-import

    Raises:
      RuntimeError: If the volume could not be attached.
    """

    client = self.aws_account.ClientApi(common.EC2_SERVICE)
    try:
      client.attach_volume(Device=device_name,
                           InstanceId=self.instance_id,
                           VolumeId=volume.volume_id)
    except client.exceptions.ClientError as exception:
      raise RuntimeError('Could not attach volume {0:s}: {1:s}'.format(
          volume.volume_id, str(exception))) from exception

    volume.device_name = device_name

  def Delete(self, force_delete: bool = False) -> None:
    """Delete an instance.

    Args:
      force_delete (bool): Optional. True if the instance should be deleted
          despite disableApiTermination being set to True on the instance.

    Raises:
      ResourceDeletionError: If the instance could not be deleted.
    """

    client = self.aws_account.ClientApi(common.EC2_SERVICE)
    if force_delete:
      try:

# Path: libcloudforensics/errors.py
# class LCFError(Exception):
# class CredentialsConfigurationError(LCFError):
# class InvalidFileFormatError(LCFError):
# class InvalidNameError(LCFError):
# class ResourceNotFoundError(LCFError):
# class ResourceCreationError(LCFError):
# class ResourceDeletionError(LCFError):
# class InstanceStateChangeError(LCFError):
# class ServiceAccountRemovalError(LCFError):
# class InstanceProfileCreationError(LCFError):
# class OperationFailedError(LCFError):
# class TransferCreationError(LCFError):
# class TransferExecutionError(LCFError):
# class ResourceAlreadyExistsError(LCFError):
#   def __init__(self,
#                message: str,
#                name: str) -> None:
# 
# Path: libcloudforensics/providers/aws/internal/common.py
# EC2_SERVICE = 'ec2'
# ACCOUNT_SERVICE = 'sts'
# KMS_SERVICE = 'kms'
# CLOUDTRAIL_SERVICE = 'cloudtrail'
# S3_SERVICE = 's3'
# IAM_SERVICE = 'iam'
# INSTANCE = 'instance'
# VOLUME = 'volume'
# SNAPSHOT = 'snapshot'
# UBUNTU_1804_FILTER = 'ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-20200611'  # pylint: disable=line-too-long
# ALINUX2_BASE_FILTER = 'amzn2-ami-hvm-2*-x86_64-gp2'
# def CreateTags(resource: str, tags: Dict[str, str]) -> Dict[str, Any]:
# def GetInstanceTypeByCPU(cpu_cores: int) -> str:
# def ExecuteRequest(client: 'botocore.client.EC2',
#                    func: str,
#                    kwargs: Dict[str, Any]) -> List[Dict[str, Any]]:


# Path: libcloudforensics/providers/aws/internal/ec2.py
import binascii
import ipaddress
import os
import random
import botocore
from typing import TYPE_CHECKING, Dict, Optional, List, Any, Tuple
from libcloudforensics import errors
from libcloudforensics.providers.aws.internal import common
  from libcloudforensics.providers.aws.internal import account  # pylint: disable=cyclic-import
  from libcloudforensics.providers.aws.internal import ebs  # pylint: disable=cyclic-import


    Raises:
      RuntimeError: If the volume could not be attached.
    """

    client = self.aws_account.ClientApi(common.EC2_SERVICE)
    try:
      client.attach_volume(Device=device_name,
                           InstanceId=self.instance_id,
                           VolumeId=volume.volume_id)
    except client.exceptions.ClientError as exception:
      raise RuntimeError('Could not attach volume {0:s}: {1:s}'.format(
          volume.volume_id, str(exception))) from exception

    volume.device_name = device_name

  def Delete(self, force_delete: bool = False) -> None:
    """Delete an instance.

    Args:
      force_delete (bool): Optional. True if the instance should be deleted
          despite disableApiTermination being set to True on the instance.

    Raises:
      ResourceDeletionError: If the instance could not be deleted.
    """

    client = self.aws_account.ClientApi(common.EC2_SERVICE)
    if force_delete:
      try:

        common.ExecuteRequest(