Merge pull request #658 from kierandoonan/master
Add encrypted attribute to Volumes/Snapshots
This commit is contained in:
		
						commit
						3e797d9c50
					
				| @ -1536,7 +1536,7 @@ class VolumeAttachment(object): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Volume(TaggedEC2Resource): | class Volume(TaggedEC2Resource): | ||||||
|     def __init__(self, ec2_backend, volume_id, size, zone, snapshot_id=None): |     def __init__(self, ec2_backend, volume_id, size, zone, snapshot_id=None, encrypted=False): | ||||||
|         self.id = volume_id |         self.id = volume_id | ||||||
|         self.size = size |         self.size = size | ||||||
|         self.zone = zone |         self.zone = zone | ||||||
| @ -1544,6 +1544,7 @@ class Volume(TaggedEC2Resource): | |||||||
|         self.attachment = None |         self.attachment = None | ||||||
|         self.snapshot_id = snapshot_id |         self.snapshot_id = snapshot_id | ||||||
|         self.ec2_backend = ec2_backend |         self.ec2_backend = ec2_backend | ||||||
|  |         self.encrypted = encrypted | ||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): |     def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name): | ||||||
| @ -1593,6 +1594,9 @@ class Volume(TaggedEC2Resource): | |||||||
|         if filter_name == 'volume-id': |         if filter_name == 'volume-id': | ||||||
|             return self.id |             return self.id | ||||||
| 
 | 
 | ||||||
|  |         if filter_name == 'encrypted': | ||||||
|  |             return str(self.encrypted).lower() | ||||||
|  | 
 | ||||||
|         filter_value = super(Volume, self).get_filter_value(filter_name) |         filter_value = super(Volume, self).get_filter_value(filter_name) | ||||||
| 
 | 
 | ||||||
|         if filter_value is None: |         if filter_value is None: | ||||||
| @ -1602,7 +1606,7 @@ class Volume(TaggedEC2Resource): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Snapshot(TaggedEC2Resource): | class Snapshot(TaggedEC2Resource): | ||||||
|     def __init__(self, ec2_backend, snapshot_id, volume, description): |     def __init__(self, ec2_backend, snapshot_id, volume, description, encrypted=False): | ||||||
|         self.id = snapshot_id |         self.id = snapshot_id | ||||||
|         self.volume = volume |         self.volume = volume | ||||||
|         self.description = description |         self.description = description | ||||||
| @ -1610,6 +1614,7 @@ class Snapshot(TaggedEC2Resource): | |||||||
|         self.create_volume_permission_groups = set() |         self.create_volume_permission_groups = set() | ||||||
|         self.ec2_backend = ec2_backend |         self.ec2_backend = ec2_backend | ||||||
|         self.status = 'completed' |         self.status = 'completed' | ||||||
|  |         self.encrypted = encrypted | ||||||
| 
 | 
 | ||||||
|     def get_filter_value(self, filter_name): |     def get_filter_value(self, filter_name): | ||||||
| 
 | 
 | ||||||
| @ -1628,6 +1633,9 @@ class Snapshot(TaggedEC2Resource): | |||||||
|         if filter_name == 'volume-size': |         if filter_name == 'volume-size': | ||||||
|             return self.volume.size |             return self.volume.size | ||||||
| 
 | 
 | ||||||
|  |         if filter_name == 'encrypted': | ||||||
|  |             return str(self.encrypted).lower() | ||||||
|  | 
 | ||||||
|         filter_value = super(Snapshot, self).get_filter_value(filter_name) |         filter_value = super(Snapshot, self).get_filter_value(filter_name) | ||||||
| 
 | 
 | ||||||
|         if filter_value is None: |         if filter_value is None: | ||||||
| @ -1643,14 +1651,16 @@ class EBSBackend(object): | |||||||
|         self.snapshots = {} |         self.snapshots = {} | ||||||
|         super(EBSBackend, self).__init__() |         super(EBSBackend, self).__init__() | ||||||
| 
 | 
 | ||||||
|     def create_volume(self, size, zone_name, snapshot_id=None): |     def create_volume(self, size, zone_name, snapshot_id=None, encrypted=False): | ||||||
|         volume_id = random_volume_id() |         volume_id = random_volume_id() | ||||||
|         zone = self.get_zone_by_name(zone_name) |         zone = self.get_zone_by_name(zone_name) | ||||||
|         if snapshot_id: |         if snapshot_id: | ||||||
|             snapshot = self.get_snapshot(snapshot_id) |             snapshot = self.get_snapshot(snapshot_id) | ||||||
|             if size is None: |             if size is None: | ||||||
|                 size = snapshot.volume.size |                 size = snapshot.volume.size | ||||||
|         volume = Volume(self, volume_id, size, zone, snapshot_id) |             if snapshot.encrypted: | ||||||
|  |                 encrypted = snapshot.encrypted | ||||||
|  |         volume = Volume(self, volume_id, size, zone, snapshot_id, encrypted) | ||||||
|         self.volumes[volume_id] = volume |         self.volumes[volume_id] = volume | ||||||
|         return volume |         return volume | ||||||
| 
 | 
 | ||||||
| @ -1699,7 +1709,7 @@ class EBSBackend(object): | |||||||
|     def create_snapshot(self, volume_id, description): |     def create_snapshot(self, volume_id, description): | ||||||
|         snapshot_id = random_snapshot_id() |         snapshot_id = random_snapshot_id() | ||||||
|         volume = self.get_volume(volume_id) |         volume = self.get_volume(volume_id) | ||||||
|         snapshot = Snapshot(self, snapshot_id, volume, description) |         snapshot = Snapshot(self, snapshot_id, volume, description, volume.encrypted) | ||||||
|         self.snapshots[snapshot_id] = snapshot |         self.snapshots[snapshot_id] = snapshot | ||||||
|         return snapshot |         return snapshot | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -29,7 +29,8 @@ class ElasticBlockStore(BaseResponse): | |||||||
|         size = self._get_param('Size') |         size = self._get_param('Size') | ||||||
|         zone = self._get_param('AvailabilityZone') |         zone = self._get_param('AvailabilityZone') | ||||||
|         snapshot_id = self._get_param('SnapshotId') |         snapshot_id = self._get_param('SnapshotId') | ||||||
|         volume = self.ec2_backend.create_volume(size, zone, snapshot_id) |         encrypted = self._get_param('Encrypted') or 'false' | ||||||
|  |         volume = self.ec2_backend.create_volume(size, zone, snapshot_id, encrypted) | ||||||
|         template = self.response_template(CREATE_VOLUME_RESPONSE) |         template = self.response_template(CREATE_VOLUME_RESPONSE) | ||||||
|         return template.render(volume=volume) |         return template.render(volume=volume) | ||||||
| 
 | 
 | ||||||
| @ -117,6 +118,7 @@ CREATE_VOLUME_RESPONSE = """<CreateVolumeResponse xmlns="http://ec2.amazonaws.co | |||||||
|   {% else %} |   {% else %} | ||||||
|     <snapshotId/> |     <snapshotId/> | ||||||
|   {% endif %} |   {% endif %} | ||||||
|  |   <encrypted>{{ volume.encrypted }}</encrypted> | ||||||
|   <availabilityZone>{{ volume.zone.name }}</availabilityZone> |   <availabilityZone>{{ volume.zone.name }}</availabilityZone> | ||||||
|   <status>creating</status> |   <status>creating</status> | ||||||
|   <createTime>{{ volume.create_time}}</createTime> |   <createTime>{{ volume.create_time}}</createTime> | ||||||
| @ -135,6 +137,7 @@ DESCRIBE_VOLUMES_RESPONSE = """<DescribeVolumesResponse xmlns="http://ec2.amazon | |||||||
|              {% else %} |              {% else %} | ||||||
|                <snapshotId/> |                <snapshotId/> | ||||||
|              {% endif %} |              {% endif %} | ||||||
|  |              <encrypted>{{ volume.encrypted }}</encrypted> | ||||||
|              <availabilityZone>{{ volume.zone.name }}</availabilityZone> |              <availabilityZone>{{ volume.zone.name }}</availabilityZone> | ||||||
|              <status>{{ volume.status }}</status> |              <status>{{ volume.status }}</status> | ||||||
|              <createTime>{{ volume.create_time}}</createTime> |              <createTime>{{ volume.create_time}}</createTime> | ||||||
| @ -199,6 +202,7 @@ CREATE_SNAPSHOT_RESPONSE = """<CreateSnapshotResponse xmlns="http://ec2.amazonaw | |||||||
|   <ownerId>111122223333</ownerId> |   <ownerId>111122223333</ownerId> | ||||||
|   <volumeSize>{{ snapshot.volume.size }}</volumeSize> |   <volumeSize>{{ snapshot.volume.size }}</volumeSize> | ||||||
|   <description>{{ snapshot.description }}</description> |   <description>{{ snapshot.description }}</description> | ||||||
|  |   <encrypted>{{ snapshot.encrypted }}</encrypted> | ||||||
| </CreateSnapshotResponse>""" | </CreateSnapshotResponse>""" | ||||||
| 
 | 
 | ||||||
| DESCRIBE_SNAPSHOTS_RESPONSE = """<DescribeSnapshotsResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/"> | DESCRIBE_SNAPSHOTS_RESPONSE = """<DescribeSnapshotsResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/"> | ||||||
| @ -214,6 +218,7 @@ DESCRIBE_SNAPSHOTS_RESPONSE = """<DescribeSnapshotsResponse xmlns="http://ec2.am | |||||||
|              <ownerId>111122223333</ownerId> |              <ownerId>111122223333</ownerId> | ||||||
|              <volumeSize>{{ snapshot.volume.size }}</volumeSize> |              <volumeSize>{{ snapshot.volume.size }}</volumeSize> | ||||||
|              <description>{{ snapshot.description }}</description> |              <description>{{ snapshot.description }}</description> | ||||||
|  |              <encrypted>{{ snapshot.encrypted }}</encrypted> | ||||||
|              <tagSet> |              <tagSet> | ||||||
|                {% for tag in snapshot.get_tags() %} |                {% for tag in snapshot.get_tags() %} | ||||||
|                  <item> |                  <item> | ||||||
|  | |||||||
| @ -20,6 +20,7 @@ def test_create_and_delete_volume(): | |||||||
|     all_volumes.should.have.length_of(1) |     all_volumes.should.have.length_of(1) | ||||||
|     all_volumes[0].size.should.equal(80) |     all_volumes[0].size.should.equal(80) | ||||||
|     all_volumes[0].zone.should.equal("us-east-1a") |     all_volumes[0].zone.should.equal("us-east-1a") | ||||||
|  |     all_volumes[0].encrypted.should.be(False) | ||||||
| 
 | 
 | ||||||
|     volume = all_volumes[0] |     volume = all_volumes[0] | ||||||
|     volume.delete() |     volume.delete() | ||||||
| @ -34,6 +35,15 @@ def test_create_and_delete_volume(): | |||||||
|     cm.exception.request_id.should_not.be.none |     cm.exception.request_id.should_not.be.none | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @mock_ec2 | ||||||
|  | def test_create_encrypted_volume(): | ||||||
|  |     conn = boto.connect_ec2('the_key', 'the_secret') | ||||||
|  |     conn.create_volume(80, "us-east-1a", encrypted=True) | ||||||
|  | 
 | ||||||
|  |     all_volumes = conn.get_all_volumes() | ||||||
|  |     all_volumes[0].encrypted.should.be(True) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @mock_ec2 | @mock_ec2 | ||||||
| def test_filter_volume_by_id(): | def test_filter_volume_by_id(): | ||||||
|     conn = boto.connect_ec2('the_key', 'the_secret') |     conn = boto.connect_ec2('the_key', 'the_secret') | ||||||
| @ -57,9 +67,9 @@ def test_volume_filters(): | |||||||
| 
 | 
 | ||||||
|     instance.update() |     instance.update() | ||||||
| 
 | 
 | ||||||
|     volume1 = conn.create_volume(80, "us-east-1a") |     volume1 = conn.create_volume(80, "us-east-1a", encrypted=True) | ||||||
|     volume2 = conn.create_volume(36, "us-east-1b") |     volume2 = conn.create_volume(36, "us-east-1b", encrypted=False) | ||||||
|     volume3 = conn.create_volume(20, "us-east-1c") |     volume3 = conn.create_volume(20, "us-east-1c", encrypted=True) | ||||||
| 
 | 
 | ||||||
|     snapshot = volume3.create_snapshot(description='testsnap') |     snapshot = volume3.create_snapshot(description='testsnap') | ||||||
|     volume4 = conn.create_volume(25, "us-east-1a", snapshot=snapshot) |     volume4 = conn.create_volume(25, "us-east-1a", snapshot=snapshot) | ||||||
| @ -107,6 +117,16 @@ def test_volume_filters(): | |||||||
|     volumes_by_tag = conn.get_all_volumes(filters={'tag:testkey1': 'testvalue1'}) |     volumes_by_tag = conn.get_all_volumes(filters={'tag:testkey1': 'testvalue1'}) | ||||||
|     set([vol.id for vol in volumes_by_tag]).should.equal(set([volume1.id])) |     set([vol.id for vol in volumes_by_tag]).should.equal(set([volume1.id])) | ||||||
| 
 | 
 | ||||||
|  |     volumes_by_unencrypted = conn.get_all_volumes(filters={'encrypted': 'false'}) | ||||||
|  |     set([vol.id for vol in volumes_by_unencrypted]).should.equal( | ||||||
|  |         set([block_mapping.volume_id, volume2.id]) | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     volumes_by_encrypted = conn.get_all_volumes(filters={'encrypted': 'true'}) | ||||||
|  |     set([vol.id for vol in volumes_by_encrypted]).should.equal( | ||||||
|  |         set([volume1.id, volume3.id, volume4.id]) | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| @mock_ec2 | @mock_ec2 | ||||||
| def test_volume_attach_and_detach(): | def test_volume_attach_and_detach(): | ||||||
| @ -162,6 +182,7 @@ def test_create_snapshot(): | |||||||
|     snapshots.should.have.length_of(1) |     snapshots.should.have.length_of(1) | ||||||
|     snapshots[0].description.should.equal('a test snapshot') |     snapshots[0].description.should.equal('a test snapshot') | ||||||
|     snapshots[0].start_time.should_not.be.none |     snapshots[0].start_time.should_not.be.none | ||||||
|  |     snapshots[0].encrypted.should.be(False) | ||||||
| 
 | 
 | ||||||
|     # Create snapshot without description |     # Create snapshot without description | ||||||
|     snapshot = volume.create_snapshot() |     snapshot = volume.create_snapshot() | ||||||
| @ -178,6 +199,21 @@ def test_create_snapshot(): | |||||||
|     cm.exception.request_id.should_not.be.none |     cm.exception.request_id.should_not.be.none | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @mock_ec2 | ||||||
|  | def test_create_encrypted_snapshot(): | ||||||
|  |     conn = boto.connect_ec2('the_key', 'the_secret') | ||||||
|  |     volume = conn.create_volume(80, "us-east-1a", encrypted=True) | ||||||
|  |     snapshot = volume.create_snapshot('a test snapshot') | ||||||
|  |     snapshot.update() | ||||||
|  |     snapshot.status.should.equal('completed') | ||||||
|  | 
 | ||||||
|  |     snapshots = conn.get_all_snapshots() | ||||||
|  |     snapshots.should.have.length_of(1) | ||||||
|  |     snapshots[0].description.should.equal('a test snapshot') | ||||||
|  |     snapshots[0].start_time.should_not.be.none | ||||||
|  |     snapshots[0].encrypted.should.be(True) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @mock_ec2 | @mock_ec2 | ||||||
| def test_filter_snapshot_by_id(): | def test_filter_snapshot_by_id(): | ||||||
|     conn = boto.connect_ec2('the_key', 'the_secret') |     conn = boto.connect_ec2('the_key', 'the_secret') | ||||||
| @ -202,8 +238,8 @@ def test_filter_snapshot_by_id(): | |||||||
| @mock_ec2 | @mock_ec2 | ||||||
| def test_snapshot_filters(): | def test_snapshot_filters(): | ||||||
|     conn = boto.connect_ec2('the_key', 'the_secret') |     conn = boto.connect_ec2('the_key', 'the_secret') | ||||||
|     volume1 = conn.create_volume(20, "us-east-1a") |     volume1 = conn.create_volume(20, "us-east-1a", encrypted=False) | ||||||
|     volume2 = conn.create_volume(25, "us-east-1a") |     volume2 = conn.create_volume(25, "us-east-1a", encrypted=True) | ||||||
| 
 | 
 | ||||||
|     snapshot1 = volume1.create_snapshot(description='testsnapshot1') |     snapshot1 = volume1.create_snapshot(description='testsnapshot1') | ||||||
|     snapshot2 = volume1.create_snapshot(description='testsnapshot2') |     snapshot2 = volume1.create_snapshot(description='testsnapshot2') | ||||||
| @ -236,6 +272,9 @@ def test_snapshot_filters(): | |||||||
|     snapshots_by_tag = conn.get_all_snapshots(filters={'tag:testkey1': 'testvalue1'}) |     snapshots_by_tag = conn.get_all_snapshots(filters={'tag:testkey1': 'testvalue1'}) | ||||||
|     set([snap.id for snap in snapshots_by_tag]).should.equal(set([snapshot1.id])) |     set([snap.id for snap in snapshots_by_tag]).should.equal(set([snapshot1.id])) | ||||||
| 
 | 
 | ||||||
|  |     snapshots_by_encrypted = conn.get_all_snapshots(filters={'encrypted': 'true'}) | ||||||
|  |     set([snap.id for snap in snapshots_by_encrypted]).should.equal(set([snapshot3.id])) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| @mock_ec2 | @mock_ec2 | ||||||
| def test_snapshot_attribute(): | def test_snapshot_attribute(): | ||||||
| @ -332,6 +371,21 @@ def test_create_volume_from_snapshot(): | |||||||
|     new_volume.snapshot_id.should.equal(snapshot.id) |     new_volume.snapshot_id.should.equal(snapshot.id) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @mock_ec2 | ||||||
|  | def test_create_volume_from_encrypted_snapshot(): | ||||||
|  |     conn = boto.connect_ec2('the_key', 'the_secret') | ||||||
|  |     volume = conn.create_volume(80, "us-east-1a", encrypted=True) | ||||||
|  | 
 | ||||||
|  |     snapshot = volume.create_snapshot('a test snapshot') | ||||||
|  |     snapshot.update() | ||||||
|  |     snapshot.status.should.equal('completed') | ||||||
|  | 
 | ||||||
|  |     new_volume = snapshot.create_volume('us-east-1a') | ||||||
|  |     new_volume.size.should.equal(80) | ||||||
|  |     new_volume.snapshot_id.should.equal(snapshot.id) | ||||||
|  |     new_volume.encrypted.should.be(True) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @mock_ec2 | @mock_ec2 | ||||||
| def test_modify_attribute_blockDeviceMapping(): | def test_modify_attribute_blockDeviceMapping(): | ||||||
|     """ |     """ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user