Browse Source

Merge "Add multiattach tests"

changes/66/729766/21 1.7.0
Zuul 2 months ago committed by Gerrit Code Review
parent
commit
5960fa4ed7
  1. 23
      .zuul.yaml
  2. 34
      cinder_tempest_plugin/scenario/manager.py
  3. 136
      cinder_tempest_plugin/scenario/test_volume_multiattach.py

23
.zuul.yaml

@ -4,6 +4,7 @@
- tempest-plugin-jobs
check:
jobs:
- cinder-tempest-plugin-lvm-multiattach
- cinder-tempest-plugin-lvm-lio-barbican
- cinder-tempest-plugin-lvm-lio-barbican-centos-9-stream:
voting: false
@ -54,6 +55,28 @@
tempest_plugins:
- cinder-tempest-plugin
- job:
name: cinder-tempest-plugin-lvm-multiattach
description: |
This enables multiattach tests along with standard tempest tests
parent: devstack-tempest
required-projects:
- opendev.org/openstack/tempest
- opendev.org/openstack/cinder-tempest-plugin
- opendev.org/openstack/cinder
vars:
tempest_test_regex: '(^tempest\.(api|scenario)|(^cinder_tempest_plugin))'
tempest_test_exclude_list: '{{ ansible_user_dir }}/{{ zuul.projects["opendev.org/openstack/tempest"].src_dir }}/tools/tempest-integrated-gate-storage-exclude-list.txt'
tox_envlist: all
devstack_localrc:
ENABLE_VOLUME_MULTIATTACH: true
tempest_plugins:
- cinder-tempest-plugin
irrelevant-files:
- ^.*\.rst$
- ^doc/.*$
- ^releasenotes/.*$
- job:
name: cinder-tempest-plugin-lvm-barbican-base-abstract
description: |

34
cinder_tempest_plugin/scenario/manager.py

@ -125,6 +125,40 @@ class ScenarioTest(manager.ScenarioTest):
server=instance)
return count, md5_sum
def write_data_to_device(self, ip_address, out_dev, in_dev='/dev/urandom',
bs=1024, count=100, private_key=None,
server=None, sha_sum=False):
ssh_client = self.get_remote_client(
ip_address, private_key=private_key, server=server)
# Write data to device
write_command = (
'sudo dd bs=%(bs)s count=%(count)s if=%(in_dev)s of=%(out_dev)s '
'&& sudo dd bs=%(bs)s count=%(count)s if=%(out_dev)s' %
{'bs': str(bs), 'count': str(count), 'in_dev': in_dev,
'out_dev': out_dev})
if sha_sum:
# If we want to read sha1sum instead of the device data
write_command += ' | sha1sum | head -c 40'
data = ssh_client.exec_command(write_command)
return data
def read_data_from_device(self, ip_address, in_dev, bs=1024, count=100,
private_key=None, server=None, sha_sum=False):
ssh_client = self.get_remote_client(
ip_address, private_key=private_key, server=server)
# Read data from device
read_command = ('sudo dd bs=%(bs)s count=%(count)s if=%(in_dev)s' %
{'bs': bs, 'count': count, 'in_dev': in_dev})
if sha_sum:
# If we want to read sha1sum instead of the device data
read_command += ' | sha1sum | head -c 40'
data = ssh_client.exec_command(read_command)
return data
def _attach_and_get_volume_device_name(self, server, volume, instance_ip,
private_key):
ssh_client = self.get_remote_client(

136
cinder_tempest_plugin/scenario/test_volume_multiattach.py

@ -0,0 +1,136 @@
# Copyright 2022 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from tempest import config
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from cinder_tempest_plugin.scenario import manager
from tempest.scenario import manager as tempest_manager
CONF = config.CONF
class VolumeMultiattachTests(manager.ScenarioTest,
tempest_manager.EncryptionScenarioTest):
compute_min_microversion = '2.60'
compute_max_microversion = 'latest'
def setUp(self):
super(VolumeMultiattachTests, self).setUp()
self.keypair = self.create_keypair()
self.security_group = self.create_security_group()
@classmethod
def skip_checks(cls):
super(VolumeMultiattachTests, cls).skip_checks()
if not CONF.compute_feature_enabled.volume_multiattach:
raise cls.skipException('Volume multi-attach is not available.')
def _verify_attachment(self, volume_id, server_id):
volume = self.volumes_client.show_volume(volume_id)['volume']
server_ids = (
[attachment['server_id'] for attachment in volume['attachments']])
self.assertIn(server_id, server_ids)
@decorators.idempotent_id('e6604b85-5280-4f7e-90b5-186248fd3423')
def test_multiattach_data_integrity(self):
# Create an instance
server_1 = self.create_server(
key_name=self.keypair['name'],
security_groups=[{'name': self.security_group['name']}])
# Create multiattach type
multiattach_vol_type = self.create_volume_type(
extra_specs={'multiattach': "<is> True"})
# Create a multiattach volume
volume = self.create_volume(volume_type=multiattach_vol_type['id'])
# Create encrypted volume
encrypted_volume = self.create_encrypted_volume(
'luks', volume_type='luks')
# Create a normal volume
simple_volume = self.create_volume()
# Attach normal and encrypted volumes (These volumes are not used in
# the current test but is used to emulate a real world scenario
# where different types of volumes will be attached to the server)
self.attach_volume(server_1, simple_volume)
self.attach_volume(server_1, encrypted_volume)
instance_ip = self.get_server_ip(server_1)
# Attach volume to instance and find it's device name (eg: /dev/vdb)
volume_device_name_inst_1, __ = (
self._attach_and_get_volume_device_name(
server_1, volume, instance_ip, self.keypair['private_key']))
out_device = '/dev/' + volume_device_name_inst_1
# This data is written from the first server and will be used to
# verify when reading data from second server
device_data_inst_1 = self.write_data_to_device(
instance_ip, out_device, private_key=self.keypair['private_key'],
server=server_1, sha_sum=True)
# Create another instance
server_2 = self.create_server(
key_name=self.keypair['name'],
security_groups=[{'name': self.security_group['name']}])
instance_2_ip = self.get_server_ip(server_2)
# Attach volume to instance and find it's device name (eg: /dev/vdc)
volume_device_name_inst_2, __ = (
self._attach_and_get_volume_device_name(
server_2, volume, instance_2_ip, self.keypair['private_key']))
in_device = '/dev/' + volume_device_name_inst_2
# Read data from volume device
device_data_inst_2 = self.read_data_from_device(
instance_2_ip, in_device, private_key=self.keypair['private_key'],
server=server_2, sha_sum=True)
self._verify_attachment(volume['id'], server_1['id'])
self._verify_attachment(volume['id'], server_2['id'])
self.assertEqual(device_data_inst_1, device_data_inst_2)
@decorators.idempotent_id('53514da8-f49c-4cda-8792-ff4a2fa69977')
def test_volume_multiattach_same_host_negative(self):
# Create an instance
server = self.create_server(
key_name=self.keypair['name'],
security_groups=[{'name': self.security_group['name']}])
# Create multiattach type
multiattach_vol_type = self.create_volume_type(
extra_specs={'multiattach': "<is> True"})
# Create an empty volume
volume = self.create_volume(volume_type=multiattach_vol_type['id'])
# Attach volume to instance
attachment = self.attach_volume(server, volume)
self.assertEqual(server['id'], attachment['serverId'])
# Try attaching the volume to the same instance
self.assertRaises(lib_exc.BadRequest, self.attach_volume, server,
volume)
Loading…
Cancel
Save