Codebase list cinder-tempest-plugin / 5ab3fef
Encryption Test Scenario for clone volume Due to an error in the _setup_encryption_keys volume rekey code, a cloned encrypted volume that has been rekeyed will specify an encryption key different from the key used to format the volume, so it cannot be attached. This test scenario will cover this feature and also the case of source-vol feature. Related-Bug: #1904440 Depends-on: https://review.opendev.org/#/c/762884/ Change-Id: I846b96ef925c34162cf462da91d854ceacabe022 Sofia Enriquez 5 years ago
1 changed file(s) with 183 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 # Licensed under the Apache License, Version 2.0 (the "License"); you may
1 # not use this file except in compliance with the License. You may obtain
2 # a copy of the License at
3 #
4 # http://www.apache.org/licenses/LICENSE-2.0
5 #
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
8 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
9 # License for the specific language governing permissions and limitations
10 # under the License.
11
12 from tempest.common import utils
13 from tempest.common import waiters
14 from tempest import config
15 from tempest.lib.common.utils import data_utils
16 from tempest.lib import decorators
17 from tempest.scenario import manager
18
19 CONF = config.CONF
20
21
22 class TestEncryptedCinderVolumes(manager.EncryptionScenarioTest,
23 manager.ScenarioTest):
24
25 @classmethod
26 def skip_checks(cls):
27 super(TestEncryptedCinderVolumes, cls).skip_checks()
28 if not CONF.compute_feature_enabled.attach_encrypted_volume:
29 raise cls.skipException('Encrypted volume attach is not supported')
30
31 @classmethod
32 def resource_setup(cls):
33 super(TestEncryptedCinderVolumes, cls).resource_setup()
34
35 @classmethod
36 def resource_cleanup(cls):
37 super(TestEncryptedCinderVolumes, cls).resource_cleanup()
38
39 def launch_instance(self):
40 image = self.image_create()
41 keypair = self.create_keypair()
42
43 return self.create_server(image_id=image, key_name=keypair['name'])
44
45 def attach_detach_volume(self, server, volume):
46 attached_volume = self.nova_volume_attach(server, volume)
47 self.nova_volume_detach(server, attached_volume)
48
49 def _delete_server(self, server):
50 self.servers_client.delete_server(server['id'])
51 waiters.wait_for_server_termination(self.servers_client, server['id'])
52
53 def create_encrypted_volume_from_image(self, encryption_provider,
54 volume_type='luks',
55 key_size=256,
56 cipher='aes-xts-plain64',
57 control_location='front-end',
58 **kwargs):
59 """Create an encrypted volume from image.
60
61 :param image_id: ID of the image to create volume from,
62 CONF.compute.image_ref by default
63 :param name: name of the volume,
64 '$classname-volume-origin' by default
65 :param **kwargs: additional parameters
66 """
67 volume_type = self.create_volume_type(name=volume_type)
68 self.create_encryption_type(type_id=volume_type['id'],
69 provider=encryption_provider,
70 key_size=key_size,
71 cipher=cipher,
72 control_location=control_location)
73 image_id = kwargs.pop('image_id', CONF.compute.image_ref)
74 name = kwargs.pop('name', None)
75 if not name:
76 namestart = self.__class__.__name__ + '-volume-origin'
77 name = data_utils.rand_name(namestart)
78 return self.create_volume(volume_type=volume_type['name'],
79 name=name, imageRef=image_id,
80 **kwargs)
81
82 @decorators.idempotent_id('5bb622ab-5060-48a8-8840-d589a548b9e4')
83 @utils.services('volume')
84 @utils.services('compute')
85 def test_attach_cloned_encrypted_volume(self):
86
87 """This test case attempts to reproduce the following steps:
88
89 * Create an encrypted volume
90 * Create clone from volume
91 * Boot an instance and attach/dettach cloned volume
92
93 """
94
95 volume = self.create_encrypted_volume('luks', volume_type='luks')
96 kwargs = {
97 'display_name': data_utils.rand_name(self.__class__.__name__),
98 'source_volid': volume['id'],
99 'volume_type': volume['volume_type'],
100 'size': volume['size']
101 }
102 volume_s = self.volumes_client.create_volume(**kwargs)['volume']
103 self.addCleanup(self.volumes_client.wait_for_resource_deletion,
104 volume_s['id'])
105 self.addCleanup(self.volumes_client.delete_volume, volume_s['id'])
106 waiters.wait_for_volume_resource_status(
107 self.volumes_client, volume_s['id'], 'available')
108 volume_source = self.volumes_client.show_volume(
109 volume_s['id'])['volume']
110 server = self.launch_instance()
111 self.attach_detach_volume(server, volume_source)
112
113 @decorators.idempotent_id('5bb622ab-5060-48a8-8840-d589a548b7e4')
114 @utils.services('volume')
115 @utils.services('compute')
116 @utils.services('image')
117 def test_boot_cloned_encrypted_volume(self):
118
119 """This test case attempts to reproduce the following steps:
120
121 * Create an encrypted volume from image
122 * Boot an instance from the volume
123 * Write data to the volume
124 * Detach volume
125 * Create a clone from the first volume
126 * Create another encrypted volume from source_volumeid
127 * Boot an instance from cloned volume
128 * Verify the data
129 """
130
131 keypair = self.create_keypair()
132 security_group = self._create_security_group()
133
134 volume = self.create_encrypted_volume_from_image('luks')
135
136 # create an instance from volume
137 instance_1st = self.boot_instance_from_resource(
138 source_id=volume['id'],
139 source_type='volume',
140 keypair=keypair,
141 security_group=security_group)
142
143 # write content to volume on instance
144 ip_instance_1st = self.get_server_ip(instance_1st)
145 timestamp = self.create_timestamp(ip_instance_1st,
146 private_key=keypair['private_key'],
147 server=instance_1st)
148 # delete instance
149 self._delete_server(instance_1st)
150
151 # create clone
152 kwargs = {
153 'display_name': data_utils.rand_name(self.__class__.__name__),
154 'source_volid': volume['id'],
155 'volume_type': volume['volume_type'],
156 'size': volume['size']
157 }
158 volume_s = self.volumes_client.create_volume(**kwargs)['volume']
159
160 self.addCleanup(self.volumes_client.wait_for_resource_deletion,
161 volume_s['id'])
162 self.addCleanup(self.volumes_client.delete_volume, volume_s['id'])
163 waiters.wait_for_volume_resource_status(
164 self.volumes_client, volume_s['id'], 'available')
165
166 # create an instance from volume
167 instance_2nd = self.boot_instance_from_resource(
168 source_id=volume_s['id'],
169 source_type='volume',
170 keypair=keypair,
171 security_group=security_group)
172
173 # check the content of written file
174 ip_instance_2nd = self.get_server_ip(instance_2nd)
175 timestamp2 = self.get_timestamp(ip_instance_2nd,
176 private_key=keypair['private_key'],
177 server=instance_2nd)
178
179 self.assertEqual(timestamp, timestamp2)
180
181 # delete instance
182 self._delete_server(instance_2nd)