Codebase list cinder-tempest-plugin / 6dc9a2f
Add multiattach tests This patch adds multiattach tests and also a gate job to run those tests. Change-Id: Iaf4fc9ab84e5c45bd6f85d7186e2775bae107721 whoami-rajat 4 years ago
3 changed file(s) with 193 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
33 - tempest-plugin-jobs
44 check:
55 jobs:
6 - cinder-tempest-plugin-lvm-multiattach
67 - cinder-tempest-plugin-lvm-lio-barbican
78 - cinder-tempest-plugin-lvm-lio-barbican-centos-8-stream:
89 voting: false
5152 - cinder-tempest-plugin
5253
5354 - job:
55 name: cinder-tempest-plugin-lvm-multiattach
56 description: |
57 This enables multiattach tests along with standard tempest tests
58 parent: devstack-tempest
59 required-projects:
60 - opendev.org/openstack/tempest
61 - opendev.org/openstack/cinder-tempest-plugin
62 - opendev.org/openstack/cinder
63 vars:
64 tempest_test_regex: '(^tempest\.(api|scenario)|(^cinder_tempest_plugin))'
65 tempest_test_exclude_list: '{{ ansible_user_dir }}/{{ zuul.projects["opendev.org/openstack/tempest"].src_dir }}/tools/tempest-integrated-gate-storage-exclude-list.txt'
66 tox_envlist: all
67 devstack_localrc:
68 ENABLE_VOLUME_MULTIATTACH: true
69 tempest_plugins:
70 - cinder-tempest-plugin
71 irrelevant-files:
72 - ^.*\.rst$
73 - ^doc/.*$
74 - ^releasenotes/.*$
75
76 - job:
5477 name: cinder-tempest-plugin-lvm-barbican-base-abstract
5578 description: |
5679 This is a base job for lvm with lio & tgt targets
123123 private_key=self.keypair['private_key'],
124124 server=instance)
125125 return count, md5_sum
126
127 def write_data_to_device(self, ip_address, out_dev, in_dev='/dev/urandom',
128 bs=1024, count=100, private_key=None,
129 server=None, sha_sum=False):
130 ssh_client = self.get_remote_client(
131 ip_address, private_key=private_key, server=server)
132
133 # Write data to device
134 write_command = (
135 'sudo dd bs=%(bs)s count=%(count)s if=%(in_dev)s of=%(out_dev)s '
136 '&& sudo dd bs=%(bs)s count=%(count)s if=%(out_dev)s' %
137 {'bs': str(bs), 'count': str(count), 'in_dev': in_dev,
138 'out_dev': out_dev})
139 if sha_sum:
140 # If we want to read sha1sum instead of the device data
141 write_command += ' | sha1sum | head -c 40'
142 data = ssh_client.exec_command(write_command)
143
144 return data
145
146 def read_data_from_device(self, ip_address, in_dev, bs=1024, count=100,
147 private_key=None, server=None, sha_sum=False):
148 ssh_client = self.get_remote_client(
149 ip_address, private_key=private_key, server=server)
150
151 # Read data from device
152 read_command = ('sudo dd bs=%(bs)s count=%(count)s if=%(in_dev)s' %
153 {'bs': bs, 'count': count, 'in_dev': in_dev})
154 if sha_sum:
155 # If we want to read sha1sum instead of the device data
156 read_command += ' | sha1sum | head -c 40'
157 data = ssh_client.exec_command(read_command)
158
159 return data
126160
127161 def _attach_and_get_volume_device_name(self, server, volume, instance_ip,
128162 private_key):
0 # Copyright 2022 Red Hat, Inc.
1 # All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may
4 # not use this file except in compliance with the License. You may obtain
5 # a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations
13 # under the License.
14
15 from tempest import config
16 from tempest.lib import decorators
17 from tempest.lib import exceptions as lib_exc
18
19 from cinder_tempest_plugin.scenario import manager
20 from tempest.scenario import manager as tempest_manager
21
22 CONF = config.CONF
23
24
25 class VolumeMultiattachTests(manager.ScenarioTest,
26 tempest_manager.EncryptionScenarioTest):
27
28 compute_min_microversion = '2.60'
29 compute_max_microversion = 'latest'
30
31 def setUp(self):
32 super(VolumeMultiattachTests, self).setUp()
33 self.keypair = self.create_keypair()
34 self.security_group = self.create_security_group()
35
36 @classmethod
37 def skip_checks(cls):
38 super(VolumeMultiattachTests, cls).skip_checks()
39 if not CONF.compute_feature_enabled.volume_multiattach:
40 raise cls.skipException('Volume multi-attach is not available.')
41
42 def _verify_attachment(self, volume_id, server_id):
43 volume = self.volumes_client.show_volume(volume_id)['volume']
44 server_ids = (
45 [attachment['server_id'] for attachment in volume['attachments']])
46 self.assertIn(server_id, server_ids)
47
48 @decorators.idempotent_id('e6604b85-5280-4f7e-90b5-186248fd3423')
49 def test_multiattach_data_integrity(self):
50
51 # Create an instance
52 server_1 = self.create_server(
53 key_name=self.keypair['name'],
54 security_groups=[{'name': self.security_group['name']}])
55
56 # Create multiattach type
57 multiattach_vol_type = self.create_volume_type(
58 extra_specs={'multiattach': "<is> True"})
59
60 # Create a multiattach volume
61 volume = self.create_volume(volume_type=multiattach_vol_type['id'])
62
63 # Create encrypted volume
64 encrypted_volume = self.create_encrypted_volume(
65 'luks', volume_type='luks')
66
67 # Create a normal volume
68 simple_volume = self.create_volume()
69
70 # Attach normal and encrypted volumes (These volumes are not used in
71 # the current test but is used to emulate a real world scenario
72 # where different types of volumes will be attached to the server)
73 self.attach_volume(server_1, simple_volume)
74 self.attach_volume(server_1, encrypted_volume)
75
76 instance_ip = self.get_server_ip(server_1)
77
78 # Attach volume to instance and find it's device name (eg: /dev/vdb)
79 volume_device_name_inst_1, __ = (
80 self._attach_and_get_volume_device_name(
81 server_1, volume, instance_ip, self.keypair['private_key']))
82
83 out_device = '/dev/' + volume_device_name_inst_1
84
85 # This data is written from the first server and will be used to
86 # verify when reading data from second server
87 device_data_inst_1 = self.write_data_to_device(
88 instance_ip, out_device, private_key=self.keypair['private_key'],
89 server=server_1, sha_sum=True)
90
91 # Create another instance
92 server_2 = self.create_server(
93 key_name=self.keypair['name'],
94 security_groups=[{'name': self.security_group['name']}])
95
96 instance_2_ip = self.get_server_ip(server_2)
97
98 # Attach volume to instance and find it's device name (eg: /dev/vdc)
99 volume_device_name_inst_2, __ = (
100 self._attach_and_get_volume_device_name(
101 server_2, volume, instance_2_ip, self.keypair['private_key']))
102
103 in_device = '/dev/' + volume_device_name_inst_2
104
105 # Read data from volume device
106 device_data_inst_2 = self.read_data_from_device(
107 instance_2_ip, in_device, private_key=self.keypair['private_key'],
108 server=server_2, sha_sum=True)
109
110 self._verify_attachment(volume['id'], server_1['id'])
111 self._verify_attachment(volume['id'], server_2['id'])
112 self.assertEqual(device_data_inst_1, device_data_inst_2)
113
114 @decorators.idempotent_id('53514da8-f49c-4cda-8792-ff4a2fa69977')
115 def test_volume_multiattach_same_host_negative(self):
116 # Create an instance
117 server = self.create_server(
118 key_name=self.keypair['name'],
119 security_groups=[{'name': self.security_group['name']}])
120
121 # Create multiattach type
122 multiattach_vol_type = self.create_volume_type(
123 extra_specs={'multiattach': "<is> True"})
124
125 # Create an empty volume
126 volume = self.create_volume(volume_type=multiattach_vol_type['id'])
127
128 # Attach volume to instance
129 attachment = self.attach_volume(server, volume)
130
131 self.assertEqual(server['id'], attachment['serverId'])
132
133 # Try attaching the volume to the same instance
134 self.assertRaises(lib_exc.BadRequest, self.attach_volume, server,
135 volume)