def ListVolumes( self, region: Optional[str] = None, # pylint: disable=line-too-long filters: Optional[List[Dict[str, Any]]] = None ) -> Dict[str, ebs.AWSVolume]: # pylint: enable=line-too-long """List volumes of an AWS account. Example usage: # List volumes attached to the instance 'some-instance-id' ListVolumes(filters=[ {'Name':'attachment.instance-id', 'Values':['some-instance-id']}]) Args: region (str): Optional. The region from which to list the volumes. If none provided, the default_region associated to the AWSAccount object will be used. filters (List[Dict]): Optional. Filters for the query. Filters are given as a list of dictionaries, e.g.: {'Name': 'someFilter', 'Values': ['value1', 'value2']}. Returns: Dict[str, AWSVolume]: Dictionary mapping volume IDs (str) to their respective AWSVolume object. Raises: RuntimeError: If volumes can't be listed. """ if not filters: filters = [] volumes = {} client = self.ClientApi(common.EC2_SERVICE, region=region) responses = common.ExecuteRequest(client, 'describe_volumes', {'Filters': filters}) for response in responses: for volume in response['Volumes']: volume_id = volume['VolumeId'] aws_volume = ebs.AWSVolume(volume_id, self, self.default_region, volume['AvailabilityZone'], volume['Encrypted']) for tag in volume.get('Tags', []): if tag.get('Key') == 'Name': aws_volume.name = tag.get('Value') break for attachment in volume.get('Attachments', []): if attachment.get('State') == 'attached': aws_volume.device_name = attachment.get('Device') break volumes[volume_id] = aws_volume return volumes
import mock from libcloudforensics.providers.aws.internal import account, common, ebs, ec2 from libcloudforensics.providers.aws.internal import log as aws_log from libcloudforensics.providers.aws import forensics FAKE_AWS_ACCOUNT = account.AWSAccount(default_availability_zone='fake-zone-2b') FAKE_INSTANCE = ec2.AWSInstance(FAKE_AWS_ACCOUNT, 'fake-instance-id', 'fake-zone-2', 'fake-zone-2b') FAKE_INSTANCE_WITH_NAME = ec2.AWSInstance(FAKE_AWS_ACCOUNT, 'fake-instance-with-name-id', 'fake-zone-2', 'fake-zone-2b', name='fake-instance') FAKE_VOLUME = ebs.AWSVolume('fake-volume-id', FAKE_AWS_ACCOUNT, 'fake-zone-2', 'fake-zone-2b', False) FAKE_BOOT_VOLUME = ebs.AWSVolume('fake-boot-volume-id', FAKE_AWS_ACCOUNT, 'fake-zone-2', 'fake-zone-2b', False, name='fake-boot-volume', device_name='/dev/spf') FAKE_SNAPSHOT = ebs.AWSSnapshot('fake-snapshot-id', FAKE_AWS_ACCOUNT, 'fake-zone-2', 'fake-zone-2b', FAKE_VOLUME, name='fake-snapshot') FAKE_CLOUDTRAIL = aws_log.AWSCloudTrail(FAKE_AWS_ACCOUNT) FAKE_EVENT_LIST = [
def CreateVolumeFromSnapshot( self, snapshot: ebs.AWSSnapshot, volume_name: Optional[str] = None, volume_name_prefix: str = '', kms_key_id: Optional[str] = None) -> ebs.AWSVolume: """Create a new volume based on a snapshot. Args: snapshot (AWSSnapshot): Snapshot to use. volume_name (str): Optional. String to use as new volume name. volume_name_prefix (str): Optional. String to prefix the volume name with. kms_key_id (str): Optional. A KMS key id to encrypt the volume with. Returns: AWSVolume: An AWS EBS Volume. Raises: ValueError: If the volume name does not comply with the RegEx. RuntimeError: If the volume could not be created. """ if not volume_name: volume_name = self._GenerateVolumeName( snapshot, volume_name_prefix=volume_name_prefix) if not common.REGEX_TAG_VALUE.match(volume_name): raise ValueError('Volume name {0:s} does not comply with ' '{1:s}'.format(volume_name, common.REGEX_TAG_VALUE.pattern)) client = self.ClientApi(common.EC2_SERVICE) create_volume_args = { 'AvailabilityZone': snapshot.availability_zone, 'SnapshotId': snapshot.snapshot_id, 'TagSpecifications': [common.GetTagForResourceType('volume', volume_name)] } if kms_key_id: create_volume_args['Encrypted'] = True create_volume_args['KmsKeyId'] = kms_key_id try: volume = client.create_volume(**create_volume_args) volume_id = volume['VolumeId'] # Wait for volume creation completion client.get_waiter('volume_available').wait(VolumeIds=[volume_id]) except (client.exceptions.ClientError, botocore.exceptions.WaiterError) as exception: raise RuntimeError('Could not create volume {0:s} from snapshot ' '{1:s}: {2:s}'.format(volume_name, snapshot.name, str(exception))) zone = volume['AvailabilityZone'] encrypted = volume['Encrypted'] return ebs.AWSVolume(volume_id, self, self.default_region, zone, encrypted, name=volume_name)
def CreateVolumeFromSnapshot( self, snapshot: ebs.AWSSnapshot, volume_name: Optional[str] = None, volume_name_prefix: Optional[str] = None, kms_key_id: Optional[str] = None, tags: Optional[Dict[str, str]] = None) -> ebs.AWSVolume: """Create a new volume based on a snapshot. Args: snapshot (AWSSnapshot): Snapshot to use. volume_name (str): Optional. String to use as new volume name. volume_name_prefix (str): Optional. String to prefix the volume name with. kms_key_id (str): Optional. A KMS key id to encrypt the volume with. tags (Dict[str, str]): Optional. A dictionary of tags to add to the volume, for example {'TicketID': 'xxx'}. An entry for the volume name is added by default. Returns: AWSVolume: An AWS EBS Volume. Raises: ValueError: If the volume name does not comply with the RegEx. RuntimeError: If the volume could not be created. """ if not volume_name: volume_name = self._GenerateVolumeName( snapshot, volume_name_prefix=volume_name_prefix) if len(volume_name) > 255: raise ValueError( 'Volume name {0:s} is too long (>255 chars)'.format( volume_name)) if not tags: tags = {} tags['Name'] = volume_name client = self.ClientApi(common.EC2_SERVICE) create_volume_args = { 'AvailabilityZone': snapshot.availability_zone, 'SnapshotId': snapshot.snapshot_id, 'TagSpecifications': [common.CreateTags(common.VOLUME, tags)] } if kms_key_id: create_volume_args['Encrypted'] = True create_volume_args['KmsKeyId'] = kms_key_id try: volume = client.create_volume(**create_volume_args) volume_id = volume['VolumeId'] # Wait for volume creation completion client.get_waiter('volume_available').wait(VolumeIds=[volume_id]) except (client.exceptions.ClientError, botocore.exceptions.WaiterError) as exception: raise RuntimeError('Could not create volume {0:s} from snapshot ' '{1:s}: {2:s}'.format(volume_name, snapshot.name, str(exception))) zone = volume['AvailabilityZone'] encrypted = volume['Encrypted'] return ebs.AWSVolume(volume_id, self, self.default_region, zone, encrypted, name=volume_name)
def CreateVolumeFromSnapshot( self, snapshot: ebs.AWSSnapshot, volume_name: Optional[str] = None, volume_name_prefix: Optional[str] = None, volume_type: str = 'gp2', kms_key_id: Optional[str] = None, tags: Optional[Dict[str, str]] = None) -> ebs.AWSVolume: """Create a new volume based on a snapshot. Args: snapshot (AWSSnapshot): Snapshot to use. volume_name (str): Optional. String to use as new volume name. volume_name_prefix (str): Optional. String to prefix the volume name with. volume_type (str): Optional. The volume type for the volume to create. Can be one of 'standard'|'io1'|'gp2'|'sc1'|'st1'. The default is 'gp2'. kms_key_id (str): Optional. A KMS key id to encrypt the volume with. tags (Dict[str, str]): Optional. A dictionary of tags to add to the volume, for example {'TicketID': 'xxx'}. An entry for the volume name is added by default. Returns: AWSVolume: An AWS EBS Volume. Raises: ValueError: If the volume name does not comply with the RegEx, or if the volume type is invalid. RuntimeError: If the volume could not be created. """ if volume_type not in ['standard', 'io1', 'gp2', 'sc1', 'st1']: raise ValueError( 'Volume type must be one of [standard, io1, gp2, sc1, ' 'st1]. Got: {0:s}'.format(volume_type)) if not volume_name: volume_name = self._GenerateVolumeName( snapshot, volume_name_prefix=volume_name_prefix) if len(volume_name) > 255: raise ValueError( 'Volume name {0:s} is too long (>255 chars)'.format( volume_name)) if not tags: tags = {} tags['Name'] = volume_name client = self.ClientApi(common.EC2_SERVICE) create_volume_args = { 'AvailabilityZone': snapshot.availability_zone, 'SnapshotId': snapshot.snapshot_id, 'TagSpecifications': [common.CreateTags(common.VOLUME, tags)], 'VolumeType': volume_type } if kms_key_id: create_volume_args['Encrypted'] = True create_volume_args['KmsKeyId'] = kms_key_id if volume_type == 'io1': # If using the io1 volume type, we must specify Iops, see # https://boto3.amazonaws.com/v1/documentation/api/latest/reference/ # services/ec2.html#EC2.Client.create_volume. io1 volumes allow for a # ratio of 50 IOPS per 1 GiB. create_volume_args['Iops'] = self.ResourceApi( common.EC2_SERVICE).Snapshot( snapshot.snapshot_id).volume_size * 50 try: volume = client.create_volume(**create_volume_args) volume_id = volume['VolumeId'] # Wait for volume creation completion client.get_waiter('volume_available').wait(VolumeIds=[volume_id]) except (client.exceptions.ClientError, botocore.exceptions.WaiterError) as exception: raise RuntimeError('Could not create volume {0:s} from snapshot ' '{1:s}: {2:s}'.format(volume_name, snapshot.name, str(exception))) zone = volume['AvailabilityZone'] encrypted = volume['Encrypted'] return ebs.AWSVolume(volume_id, self, self.default_region, zone, encrypted, name=volume_name)