# 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
      # ratio of 50 IOPS per 1 GiB.
      block_device_mapping['Ebs']['Iops'] = boot_volume_size * 50
    return block_device_mapping

  def GenerateSSHKeyPair(self, vm_name: str) -> Tuple[str, str]:
    """Generate a SSH key pair and returns its name and private key.

    Args:
      vm_name (str): The VM name for which to generate the key pair.

    Returns:
      Tuple[str, str]: A tuple containing the key name and the private key for
          the generated SSH key pair.

    Raises:
      ValueError: If vm_name is None.
      ResourceCreationError: If the key could not be created.
    """

    if not vm_name:
      raise ValueError('Parameter vm_name must not be None.')

    # SSH key names need to be unique, therefore we add a random 10 chars hex
    # string.
    key_name = '{0:s}-{1:s}-ssh'.format(
        vm_name, binascii.b2a_hex(os.urandom(10)).decode('utf-8'))
    client = self.aws_account.ClientApi(common.EC2_SERVICE)
    try:
      key = client.create_key_pair(KeyName=key_name)
    except client.exceptions.ClientError as exception:

# 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

      # ratio of 50 IOPS per 1 GiB.
      block_device_mapping['Ebs']['Iops'] = boot_volume_size * 50
    return block_device_mapping

  def GenerateSSHKeyPair(self, vm_name: str) -> Tuple[str, str]:
    """Generate a SSH key pair and returns its name and private key.

    Args:
      vm_name (str): The VM name for which to generate the key pair.

    Returns:
      Tuple[str, str]: A tuple containing the key name and the private key for
          the generated SSH key pair.

    Raises:
      ValueError: If vm_name is None.
      ResourceCreationError: If the key could not be created.
    """

    if not vm_name:
      raise ValueError('Parameter vm_name must not be None.')

    # SSH key names need to be unique, therefore we add a random 10 chars hex
    # string.
    key_name = '{0:s}-{1:s}-ssh'.format(
        vm_name, binascii.b2a_hex(os.urandom(10)).decode('utf-8'))
    client = self.aws_account.ClientApi(common.EC2_SERVICE)
    try:
      key = client.create_key_pair(KeyName=key_name)
    except client.exceptions.ClientError as exception:

      raise errors.ResourceCreationError(