Update multiattach tests

Multiattach tests use legacy format to create multiattach
volumes i.e. provide "multiattach=True" in request body of
a create volume operation.
This patch updates the multiattach tests to use multiattach
volume type, which is the standard and only way[1], to create
multiattach volumes.
Note that the old functionality will be changed by patch[2] and
passing multiattach=True in volume create request body will
error out with BadRequest.

Devstack will create the multiattach volume type, like an
operator will create in a real deployment, and set it as a
tempest config option (see depends on patch).

We are adding a new config option `volume_type_multiattach`
which is used as the multiattach volume type to create
multiattach volumes.

[1] https://docs.openstack.org/cinder/latest/admin/volume-multiattach.html#how-to-create-a-multiattach-volume
[2] https://review.opendev.org/c/openstack/cinder/+/874865

Depends-On: https://review.opendev.org/c/openstack/devstack/+/877337
Depends-On: https://review.opendev.org/c/openstack/devstack/+/877497
Depends-On: https://review.opendev.org/c/openstack/devstack/+/877548
Depends-On: https://review.opendev.org/c/openstack/devstack/+/877498
Depends-On: https://review.opendev.org/c/openstack/devstack/+/877499

Related-prod: PRODX-32154

Change-Id: I5f68ef56fcc55dfc636936dabb5e6ad761579519
diff --git a/tempest/api/compute/admin/test_volume_swap.py b/tempest/api/compute/admin/test_volume_swap.py
index 8bf1876..de2739c 100644
--- a/tempest/api/compute/admin/test_volume_swap.py
+++ b/tempest/api/compute/admin/test_volume_swap.py
@@ -146,6 +146,8 @@
         super(TestMultiAttachVolumeSwap, cls).skip_checks()
         if not CONF.compute_feature_enabled.volume_multiattach:
             raise cls.skipException('Volume multi-attach is not available.')
+        if not CONF.volume.volume_type_multiattach:
+            raise cls.skipException('Multi-attach volume type is not defined')
 
     @classmethod
     def setup_clients(cls):
@@ -168,11 +170,26 @@
                              condition=CONF.compute.min_compute_nodes > 1)
     @utils.services('volume')
     def test_volume_swap_with_multiattach(self):
+        """Test swapping volume attached to multiple servers
+
+        The following is the scenario outline:
+
+        1. Create a volume "volume1" with non-admin.
+        2. Create a volume "volume2" with non-admin.
+        3. Boot 2 instances "server1" and "server2" with non-admin.
+        4. Attach "volume1" to "server1" with non-admin.
+        5. Attach "volume1" to "server2" with non-admin.
+        6. Swap "volume1" to "volume2" on "server1"
+        7. Check "volume1" is attached to "server2" and not attached to
+           "server1"
+        8. Check "volume2" is attached to "server1".
+        """
+        multiattach_vol_type = CONF.volume.volume_type_multiattach
         # Create two volumes.
         # NOTE(gmann): Volumes are created before server creation so that
         # volumes cleanup can happen successfully irrespective of which volume
         # is attached to server.
-        volume1 = self.create_volume(multiattach=True)
+        volume1 = self.create_volume(volume_type=multiattach_vol_type)
         # Make volume1 read-only since you can't swap from a volume with
         # multiple read/write attachments, and you can't change the readonly
         # flag on an in-use volume so we have to do this before attaching
@@ -180,7 +197,7 @@
         # attach modes, then we can handle this differently.
         self.admin_volumes_client.update_volume_readonly(
             volume1['id'], readonly=True)
-        volume2 = self.create_volume(multiattach=True)
+        volume2 = self.create_volume(volume_type=multiattach_vol_type)
 
         # Create two servers and wait for them to be ACTIVE.
         reservation_id = self.create_test_server(
diff --git a/tempest/api/compute/admin/test_volumes_negative.py b/tempest/api/compute/admin/test_volumes_negative.py
index 7b0f48b..c3f9ac4 100644
--- a/tempest/api/compute/admin/test_volumes_negative.py
+++ b/tempest/api/compute/admin/test_volumes_negative.py
@@ -71,15 +71,28 @@
         super(UpdateMultiattachVolumeNegativeTest, cls).skip_checks()
         if not CONF.compute_feature_enabled.volume_multiattach:
             raise cls.skipException('Volume multi-attach is not available.')
+        if not CONF.volume.volume_type_multiattach:
+            raise cls.skipException('Multi-attach volume type is not defined')
 
     @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7576d497-b7c6-44bd-9cc5-c5b4e50fec71')
     @utils.services('volume')
     def test_multiattach_rw_volume_update_failure(self):
+        """Test swapping volume attached to multi-servers with read-write mode
+
+        1. Create two volumes "vol1" and "vol2"
+        2. Create two instances "server1" and "server2"
+        3. Attach "vol1" to both of these instances
+        4. By default both of these attachments should have an attach_mode of
+           read-write, so trying to swap "vol1" to "vol2" should fail
+        5. Check "vol1" is still attached to both servers
+        6. Check "vol2" is not attached to any server
+        """
+        multiattach_vol_type = CONF.volume.volume_type_multiattach
 
         # Create two multiattach capable volumes.
-        vol1 = self.create_volume(multiattach=True)
-        vol2 = self.create_volume(multiattach=True)
+        vol1 = self.create_volume(volume_type=multiattach_vol_type)
+        vol2 = self.create_volume(volume_type=multiattach_vol_type)
 
         # Create two instances.
         server1 = self.create_test_server(wait_until='ACTIVE')
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index 3cec4bf..ef97746 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -335,6 +335,8 @@
         super(AttachVolumeMultiAttachTest, cls).skip_checks()
         if not CONF.compute_feature_enabled.volume_multiattach:
             raise cls.skipException('Volume multi-attach is not available.')
+        if not CONF.volume.volume_type_multiattach:
+            raise cls.skipException('Multi-attach volume type is not defined')
 
     def _attach_volume_to_servers(self, volume, servers):
         """Attaches the given volume to the list of servers.
@@ -376,7 +378,9 @@
         kwargs = {}
         if bootable:
             kwargs['image_ref'] = CONF.compute.image_ref
-        return self.create_volume(multiattach=True, **kwargs)
+        multiattach_vol_type = CONF.volume.volume_type_multiattach
+        return self.create_volume(volume_type=multiattach_vol_type,
+                                  **kwargs)
 
     def _create_and_multiattach(self):
         """Creates two server instances and a volume and attaches to both.
diff --git a/tempest/config.py b/tempest/config.py
index 55a7c61..7daa81f 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -930,6 +930,10 @@
                 default=['BACKEND_1', 'BACKEND_2'],
                 help='A list of backend names separated by comma. '
                      'The backend name must be declared in cinder.conf'),
+    cfg.StrOpt('volume_type_multiattach',
+               default='',
+               help='Multiattach volume type used while creating multiattach '
+                    'volume. When empty multiattach tests are skipped'),
     cfg.StrOpt('storage_protocol',
                default='iSCSI',
                help='Backend protocol to target when creating volume types'),