EC2: create_volume(): support Throughput-parameter (#6379)
This commit is contained in:
parent
08e509506a
commit
681873d177
@ -23,6 +23,7 @@ from ..utils import (
|
|||||||
|
|
||||||
IOPS_REQUIRED_VOLUME_TYPES = ["io1", "io2"]
|
IOPS_REQUIRED_VOLUME_TYPES = ["io1", "io2"]
|
||||||
IOPS_SUPPORTED_VOLUME_TYPES = ["gp3", "io1", "io2"]
|
IOPS_SUPPORTED_VOLUME_TYPES = ["gp3", "io1", "io2"]
|
||||||
|
THROUGHPUT_SUPPORTED_VOLUME_TYPES = ["gp3"]
|
||||||
GP3_DEFAULT_IOPS = 3000
|
GP3_DEFAULT_IOPS = 3000
|
||||||
|
|
||||||
|
|
||||||
@ -114,6 +115,7 @@ class Volume(TaggedEC2Resource, CloudFormationModel):
|
|||||||
kms_key_id: Optional[str] = None,
|
kms_key_id: Optional[str] = None,
|
||||||
volume_type: Optional[str] = None,
|
volume_type: Optional[str] = None,
|
||||||
iops: Optional[int] = None,
|
iops: Optional[int] = None,
|
||||||
|
throughput: Optional[int] = None,
|
||||||
):
|
):
|
||||||
self.id = volume_id
|
self.id = volume_id
|
||||||
self.volume_type = volume_type or "gp2"
|
self.volume_type = volume_type or "gp2"
|
||||||
@ -127,6 +129,7 @@ class Volume(TaggedEC2Resource, CloudFormationModel):
|
|||||||
self.kms_key_id = kms_key_id
|
self.kms_key_id = kms_key_id
|
||||||
self.modifications: List[VolumeModification] = []
|
self.modifications: List[VolumeModification] = []
|
||||||
self.iops = iops
|
self.iops = iops
|
||||||
|
self.throughput = throughput
|
||||||
|
|
||||||
def modify(
|
def modify(
|
||||||
self,
|
self,
|
||||||
@ -272,6 +275,7 @@ class EBSBackend:
|
|||||||
kms_key_id: Optional[str] = None,
|
kms_key_id: Optional[str] = None,
|
||||||
volume_type: Optional[str] = None,
|
volume_type: Optional[str] = None,
|
||||||
iops: Optional[int] = None,
|
iops: Optional[int] = None,
|
||||||
|
throughput: Optional[int] = None,
|
||||||
) -> Volume:
|
) -> Volume:
|
||||||
if kms_key_id and not encrypted:
|
if kms_key_id and not encrypted:
|
||||||
raise InvalidParameterDependency("KmsKeyId", "Encrypted")
|
raise InvalidParameterDependency("KmsKeyId", "Encrypted")
|
||||||
@ -283,6 +287,8 @@ class EBSBackend:
|
|||||||
iops = GP3_DEFAULT_IOPS
|
iops = GP3_DEFAULT_IOPS
|
||||||
elif volume_type not in IOPS_SUPPORTED_VOLUME_TYPES and iops:
|
elif volume_type not in IOPS_SUPPORTED_VOLUME_TYPES and iops:
|
||||||
raise InvalidParameterDependency("VolumeType", "Iops")
|
raise InvalidParameterDependency("VolumeType", "Iops")
|
||||||
|
if volume_type not in THROUGHPUT_SUPPORTED_VOLUME_TYPES and throughput:
|
||||||
|
raise InvalidParameterDependency("VolumeType", "Throughput")
|
||||||
|
|
||||||
volume_id = random_volume_id()
|
volume_id = random_volume_id()
|
||||||
zone = self.get_zone_by_name(zone_name) # type: ignore[attr-defined]
|
zone = self.get_zone_by_name(zone_name) # type: ignore[attr-defined]
|
||||||
@ -302,6 +308,7 @@ class EBSBackend:
|
|||||||
kms_key_id=kms_key_id,
|
kms_key_id=kms_key_id,
|
||||||
volume_type=volume_type,
|
volume_type=volume_type,
|
||||||
iops=iops,
|
iops=iops,
|
||||||
|
throughput=throughput,
|
||||||
)
|
)
|
||||||
self.volumes[volume_id] = volume
|
self.volumes[volume_id] = volume
|
||||||
return volume
|
return volume
|
||||||
|
@ -67,6 +67,7 @@ class ElasticBlockStore(EC2BaseResponse):
|
|||||||
encrypted = self._get_bool_param("Encrypted", if_none=False)
|
encrypted = self._get_bool_param("Encrypted", if_none=False)
|
||||||
kms_key_id = self._get_param("KmsKeyId")
|
kms_key_id = self._get_param("KmsKeyId")
|
||||||
iops = self._get_param("Iops")
|
iops = self._get_param("Iops")
|
||||||
|
throughput = self._get_param("Throughput")
|
||||||
|
|
||||||
self.error_on_dryrun()
|
self.error_on_dryrun()
|
||||||
|
|
||||||
@ -78,6 +79,7 @@ class ElasticBlockStore(EC2BaseResponse):
|
|||||||
kms_key_id=kms_key_id,
|
kms_key_id=kms_key_id,
|
||||||
volume_type=volume_type,
|
volume_type=volume_type,
|
||||||
iops=iops,
|
iops=iops,
|
||||||
|
throughput=throughput,
|
||||||
)
|
)
|
||||||
volume.add_tags(volume_tags)
|
volume.add_tags(volume_tags)
|
||||||
template = self.response_template(CREATE_VOLUME_RESPONSE)
|
template = self.response_template(CREATE_VOLUME_RESPONSE)
|
||||||
@ -246,6 +248,9 @@ CREATE_VOLUME_RESPONSE = """<CreateVolumeResponse xmlns="http://ec2.amazonaws.co
|
|||||||
{% if volume.iops %}
|
{% if volume.iops %}
|
||||||
<iops>{{ volume.iops }}</iops>
|
<iops>{{ volume.iops }}</iops>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if volume.throughput %}
|
||||||
|
<throughput>{{ volume.throughput }}</throughput>
|
||||||
|
{% endif %}
|
||||||
</CreateVolumeResponse>"""
|
</CreateVolumeResponse>"""
|
||||||
|
|
||||||
DESCRIBE_VOLUMES_RESPONSE = """<DescribeVolumesResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
|
DESCRIBE_VOLUMES_RESPONSE = """<DescribeVolumesResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
|
||||||
@ -295,6 +300,9 @@ DESCRIBE_VOLUMES_RESPONSE = """<DescribeVolumesResponse xmlns="http://ec2.amazon
|
|||||||
{% if volume.iops %}
|
{% if volume.iops %}
|
||||||
<iops>{{ volume.iops }}</iops>
|
<iops>{{ volume.iops }}</iops>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if volume.throughput %}
|
||||||
|
<throughput>{{ volume.throughput }}</throughput>
|
||||||
|
{% endif %}
|
||||||
</item>
|
</item>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</volumeSet>
|
</volumeSet>
|
||||||
|
@ -1101,3 +1101,26 @@ def test_create_volume_with_iops():
|
|||||||
|
|
||||||
volume = ec2.describe_volumes(VolumeIds=[volume["VolumeId"]])["Volumes"][0]
|
volume = ec2.describe_volumes(VolumeIds=[volume["VolumeId"]])["Volumes"][0]
|
||||||
volume["Iops"].should.equal(4000)
|
volume["Iops"].should.equal(4000)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_create_volume_with_throughput():
|
||||||
|
ec2 = boto3.client("ec2", region_name="us-east-1")
|
||||||
|
volume = ec2.create_volume(
|
||||||
|
AvailabilityZone="us-east-1a", Size=10, VolumeType="gp3", Throughput=200
|
||||||
|
)
|
||||||
|
volume["Throughput"].should.equal(200)
|
||||||
|
|
||||||
|
volume = ec2.describe_volumes(VolumeIds=[volume["VolumeId"]])["Volumes"][0]
|
||||||
|
volume["Throughput"].should.equal(200)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_create_volume_with_throughput_fails():
|
||||||
|
resource = boto3.resource("ec2", region_name="us-east-1")
|
||||||
|
with pytest.raises(ClientError) as ex:
|
||||||
|
resource.create_volume(
|
||||||
|
AvailabilityZone="us-east-1a", Size=10, VolumeType="gp2", Throughput=200
|
||||||
|
)
|
||||||
|
ex.value.response["Error"]["Code"].should.equal("InvalidParameterDependency")
|
||||||
|
ex.value.response["Error"]["Message"].should.contain("Throughput")
|
||||||
|
Loading…
Reference in New Issue
Block a user