Add functional tests for add multiple subnets feature

This change adds negative and positive functional tests
for the new feature add multiple subnets per az. Older
functional tests impacted by the feature are fixed. Finally,
the new flags `run_share_server_multiple_subnets_tests` and
`run_network_allocation_update_tests` are added and configured
in the community jobs for Dummy DHSS=True and Container Driver.

Partially-Implements: blueprint multiple-share-network-subnets
Change-Id: I99547e1873646fb1494a454f67b14c7293342beb
This commit is contained in:
Andre 2022-01-29 14:46:53 +00:00 committed by andrebeltrami
parent 88225a342c
commit c1a3c0e54e
14 changed files with 696 additions and 16 deletions

View File

@ -217,3 +217,31 @@ def wait_for_restore(client, share_id, version=LATEST_MICROVERSION):
'timeout': client.build_timeout,
})
raise exceptions.TimeoutException(message)
def wait_for_subnet_create_check(client, share_network_id,
neutron_net_id=None,
neutron_subnet_id=None,
availability_zone=None):
result = client.subnet_create_check(
share_network_id, neutron_net_id=neutron_net_id,
neutron_subnet_id=neutron_subnet_id,
availability_zone=availability_zone)
start = int(time.time())
while not result['compatible']:
time.sleep(client.build_interval)
result = client.subnet_create_check(
share_network_id, neutron_net_id=neutron_net_id,
neutron_subnet_id=neutron_subnet_id,
availability_zone=availability_zone)
if result['compatible']:
break
elif int(time.time()) - start >= client.build_timeout or (
result['compatible'] is False):
message = ('Subnet create check failed within the '
'required time %(timeout)s seconds for share network '
'%(share_network)s.' % {
'timeout': client.build_timeout,
'share_network': share_network_id,
})
raise exceptions.TimeoutException(message)

View File

@ -40,7 +40,7 @@ ShareGroup = [
"This value is only used to validate the versions "
"response from Manila."),
cfg.StrOpt("max_api_microversion",
default="2.69",
default="2.70",
help="The maximum api microversion is configured to be the "
"value of the latest microversion supported by Manila."),
cfg.StrOpt("region",
@ -287,6 +287,16 @@ ShareGroup = [
default=False,
help="Defines whether to run share servers migration tests. "
"Enable this option if the used driver supports it."),
cfg.BoolOpt("run_share_server_multiple_subnet_tests",
default=False,
help="Defines whether to run the share server multiple "
"subnets tests. Enable this option if the used driver "
"supports it."),
cfg.BoolOpt("run_network_allocation_update_tests",
default=False,
help="Defines whether to run the network allocation update "
"tests. Enable this option if the used driver "
"supports it."),
cfg.StrOpt("image_with_share_tools",
default="manila-service-image-master",

View File

@ -1953,6 +1953,29 @@ class SharesV2Client(shares_client.SharesClient):
self.expected_success(202, resp.status)
return rest_client.ResponseBody(resp, body)
def subnet_create_check(
self, share_network_id, neutron_net_id=None,
neutron_subnet_id=None, availability_zone=None,
reset=False, version=LATEST_MICROVERSION):
body = {
'share_network_subnet_create_check': {
'neutron_net_id': neutron_net_id,
'neutron_subnet_id': neutron_subnet_id,
'availability_zone': availability_zone,
'reset': reset,
}
}
body = json.dumps(body)
resp, body = self.post(
f'share-networks/{share_network_id}/action',
body, headers=EXPERIMENTAL, extra_headers=True,
version=version)
self.expected_success(202, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
###############
def share_server_migration_check(

View File

@ -196,8 +196,13 @@ class ShareServersAdminTest(base.BaseSharesAdminTest):
if utils.is_microversion_ge(CONF.share.max_api_microversion, "2.49"):
keys.append("is_auto_deletable")
keys.append("identifier")
if utils.is_microversion_ge(CONF.share.max_api_microversion, "2.51"):
if utils.is_microversion_ge(
CONF.share.max_api_microversion, "2.51") and (
utils.is_microversion_lt(
CONF.share.max_api_microversion, "2.70")):
keys.append("share_network_subnet_id")
if utils.is_microversion_ge(CONF.share.max_api_microversion, "2.70"):
keys.append("share_network_subnet_ids")
# all expected keys are present
for key in keys:
self.assertIn(key, server.keys())

View File

@ -66,6 +66,12 @@ class ManageShareServersTest(base.BaseSharesAdminTest):
msg = ("Manage share server with share network subnet is "
"supported starting from microversion '2.51'.")
raise self.skipException(msg)
check_multiple_subnet = utils.is_microversion_ge(
CONF.share.max_api_microversion, '2.70')
if check_multiple_subnet:
network_subnet = 'share_network_subnet_ids'
else:
network_subnet = 'share_network_subnet_id'
# create a new share network to make sure that a new share server
# will be created
original_share_network = self.shares_v2_client.get_share_network(
@ -91,7 +97,7 @@ class ManageShareServersTest(base.BaseSharesAdminTest):
neutron_subnet_id=share_network['neutron_subnet_id'],
availability_zone=az
)['share_network_subnet']
params = {'share_network_subnet_id': az_subnet['id']}
params = {network_subnet: az_subnet['id']}
# create share
share = self.create_share(
@ -119,7 +125,7 @@ class ManageShareServersTest(base.BaseSharesAdminTest):
"identifier",
]
if add_subnet_field:
keys.append('share_network_subnet_id')
keys.append(network_subnet)
# all expected keys are present
for key in keys:
self.assertIn(key, share_server)
@ -127,9 +133,10 @@ class ManageShareServersTest(base.BaseSharesAdminTest):
# check that the share server is initially auto-deletable
self.assertIs(True, share_server["is_auto_deletable"])
self.assertIsNotNone(share_server["identifier"])
if add_subnet_field:
self.assertEqual(az_subnet["id"],
share_server["share_network_subnet_id"])
if add_subnet_field and check_multiple_subnet:
self.assertIn(az_subnet["id"], share_server[network_subnet])
elif add_subnet_field and not check_multiple_subnet:
self.assertEqual(az_subnet["id"], share_server[network_subnet])
self._unmanage_share_and_wait(share)

View File

@ -187,6 +187,145 @@ class ReplicationTest(base.BaseSharesMixedTest):
# Delete subnet
self.shares_v2_client.delete_subnet(self.sn_id, subnet['id'])
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@testtools.skipIf(
not CONF.share.run_share_server_multiple_subnet_tests,
"Share server multiple subnet tests are disabled.")
@testtools.skipIf(CONF.share.share_network_id != "",
"This test is not suitable for pre-existing "
"share networks.")
@utils.skip_if_microversion_not_supported("2.70")
@decorators.idempotent_id('4235e789-dbd6-47a8-8f2e-d70edf78e532')
def test_add_delete_share_replica_multiple_subnets(self):
extra_specs = {
"replication_type": self.replication_type,
"driver_handles_share_servers": CONF.share.multitenancy_enabled,
"share_server_multiple_subnet_support": True,
}
share_type = self.create_share_type(
extra_specs=extra_specs, client=self.admin_client)
default_subnet = utils.share_network_get_default_subnet(
self.share_network)
new_share_network_id = self.create_share_network(
cleanup_in_class=False)['id']
subnet_data = {
'neutron_net_id': default_subnet.get('neutron_net_id'),
'neutron_subnet_id': default_subnet.get('neutron_subnet_id'),
'share_network_id': new_share_network_id,
'availability_zone': self.replica_zone,
}
subnet1 = self.create_share_network_subnet(**subnet_data)
subnet2 = self.create_share_network_subnet(**subnet_data)
# Creating a third subnet in share replica az
subnet_data.update({'availability_zone': self.share_zone})
subnet3 = self.create_share_network_subnet(**subnet_data)
# Create the share and share replica
share = self.create_share(
share_type_id=share_type['id'], cleanup_in_class=False,
availability_zone=self.share_zone,
share_network_id=new_share_network_id)
share = self.admin_client.get_share(share['id'])['share']
replica = self.create_share_replica(share['id'], self.replica_zone)
replica = self.admin_client.get_share_replica(
replica['id'])['share_replica']
share_server = self.admin_client.show_share_server(
replica['share_server_id'])['share_server']
self.assertIn(subnet1['id'],
share_server['share_network_subnet_ids'])
self.assertIn(subnet2['id'],
share_server['share_network_subnet_ids'])
# Delete the replica
self.delete_share_replica(replica['id'])
# Delete share
self.shares_v2_client.delete_share(share['id'])
self.shares_v2_client.wait_for_resource_deletion(share_id=share['id'])
# Delete subnets
self.shares_v2_client.delete_subnet(
new_share_network_id, subnet1['id'])
self.shares_v2_client.delete_subnet(
new_share_network_id, subnet2['id'])
self.shares_v2_client.delete_subnet(
new_share_network_id, subnet3['id'])
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@testtools.skipIf(
not CONF.share.run_network_allocation_update_tests,
"Share server network allocation update tests are disabled.")
@testtools.skipIf(CONF.share.share_network_id != "",
"This test is not suitable for pre-existing "
"share_network.")
@utils.skip_if_microversion_not_supported("2.70")
@decorators.idempotent_id('26694947-d4a0-46c8-99e8-2e0eca1b6a08')
def test_add_delete_share_replica_network_allocation_update(self):
extra_specs = {
"replication_type": self.replication_type,
"driver_handles_share_servers": CONF.share.multitenancy_enabled,
"network_allocation_update_support": True,
}
share_type = self.create_share_type(extra_specs=extra_specs)
default_subnet = utils.share_network_get_default_subnet(
self.share_network)
new_share_network_id = self.create_share_network(
cleanup_in_class=False)['id']
subnet_data = {
'neutron_net_id': default_subnet.get('neutron_net_id'),
'neutron_subnet_id': default_subnet.get('neutron_subnet_id'),
'share_network_id': new_share_network_id,
'availability_zone': self.share_zone,
}
subnet1 = self.create_share_network_subnet(**subnet_data)
subnet_data.update({'availability_zone': self.replica_zone})
subnet2 = self.create_share_network_subnet(**subnet_data)
# Create the share and share replica
share = self.create_share(
share_type_id=share_type['id'], cleanup_in_class=False,
availability_zone=self.share_zone,
share_network_id=new_share_network_id)
share = self.admin_client.get_share(share['id'])['share']
replica = self.create_share_replica(share['id'], self.replica_zone)
replica = self.admin_client.get_share_replica(
replica['id'])['share_replica']
# Waits until the check is completed and positive
waiters.wait_for_subnet_create_check(
self.shares_v2_client, new_share_network_id,
neutron_net_id=subnet_data['neutron_net_id'],
neutron_subnet_id=subnet_data['neutron_subnet_id'],
availability_zone=self.replica_zone)
# Creating a third subnet in replica zone to trigger the network
# allocation update
subnet3 = self.create_share_network_subnet(**subnet_data)
waiters.wait_for_resource_status(
self.admin_client, replica['share_server_id'],
constants.SERVER_STATE_ACTIVE,
resource_name="share_server",
status_attr="status")
share_server = self.admin_client.show_share_server(
replica['share_server_id']
)['share_server']
self.assertIn(subnet2['id'],
share_server['share_network_subnet_ids'])
self.assertIn(subnet3['id'],
share_server['share_network_subnet_ids'])
# Delete the replica
self.delete_share_replica(replica['id'])
# Delete share
self.shares_v2_client.delete_share(share['id'])
self.shares_v2_client.wait_for_resource_deletion(share_id=share['id'])
# Delete subnets
self.shares_v2_client.delete_subnet(
new_share_network_id, subnet1['id'])
self.shares_v2_client.delete_subnet(
new_share_network_id, subnet2['id'])
self.shares_v2_client.delete_subnet(
new_share_network_id, subnet3['id'])
@decorators.idempotent_id('00e12b41-b95d-494a-99be-e584aae10f5c')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_add_access_rule_create_replica_delete_rule(self):

View File

@ -15,12 +15,14 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
from manila_tempest_tests.common import constants
from manila_tempest_tests.common import waiters
from manila_tempest_tests.tests.api import base
from manila_tempest_tests import utils
@ -263,3 +265,130 @@ class ShareGroupsTest(base.BaseSharesMixedTest):
# Verify that share always has the same AZ as share group does
self.assertEqual(
share_group['availability_zone'], share['availability_zone'])
@utils.skip_if_microversion_not_supported("2.70")
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.multitenancy_enabled,
"Multitenancy is disabled.")
@testtools.skipUnless(CONF.share.run_share_server_multiple_subnet_tests,
"Share server multiple subnet tests are disabled.")
@testtools.skipIf(CONF.share.share_network_id != "",
"This test is not suitable for pre-existing "
"share networks.")
@ddt.data(False, True)
@decorators.idempotent_id('17fd1867-03a3-43d0-9be3-daf90b6c5e02')
def test_create_sg_and_share_with_multiple_subnets(
self, network_allocation_update):
if network_allocation_update and not (
CONF.share.run_network_allocation_update_tests):
raise self.skipException(
'Network allocation update tests are disabled.')
extra_specs = {
'driver_handles_share_servers': CONF.share.multitenancy_enabled,
'share_server_multiple_subnet_support': True,
}
if network_allocation_update:
extra_specs['network_allocation_update_support'] = True
share_type = self.create_share_type(extra_specs=extra_specs)
sg_type_name = data_utils.rand_name("tempest-manila")
sg_type = self.create_share_group_type(
name=sg_type_name, share_types=share_type['id'],
client=self.admin_shares_v2_client)
# Get list of existing availability zones, at least one always
# should exist
azs = self.get_availability_zones_matching_share_type(share_type)
if len(azs) == 0:
raise self.skipException(
"No AZs were found. Make sure there is at least one "
"configured.")
share_network = self.shares_v2_client.get_share_network(
self.shares_v2_client.share_network_id)['share_network']
new_share_network_id = self.create_share_network(
cleanup_in_class=False)['id']
default_subnet = utils.share_network_get_default_subnet(
share_network)
subnet_data = {
'neutron_net_id': default_subnet.get('neutron_net_id'),
'neutron_subnet_id': default_subnet.get('neutron_subnet_id'),
'share_network_id': new_share_network_id,
'availability_zone': azs[0]
}
subnet1 = self.create_share_network_subnet(**subnet_data)
if not network_allocation_update:
subnet2 = self.create_share_network_subnet(**subnet_data)
sg_kwargs = {
'share_group_type_id': sg_type['id'],
'share_type_ids': [share_type['id']],
'share_network_id': new_share_network_id,
'availability_zone': azs[0],
'version': constants.MIN_SHARE_GROUP_MICROVERSION,
'cleanup_in_class': False,
}
# Create share group
share_group = self.create_share_group(**sg_kwargs)
# Get latest share group info
share_group = self.shares_v2_client.get_share_group(
share_group['id'])['share_group']
self.assertIn('availability_zone', share_group)
self.assertEqual(azs[0], share_group['availability_zone'])
# Test 'consistent_snapshot_support' as part of 2.33 API change
self.assertIn('consistent_snapshot_support', share_group)
self.assertIn(
share_group['consistent_snapshot_support'], ('host', 'pool', None))
share_data = {
'share_type_id': share_type['id'],
'share_group_id': share_group['id'],
'share_network_id': new_share_network_id,
'availability_zone': azs[0],
'cleanup_in_class': False,
}
# Create share in share group
share = self.create_share(**share_data)
# Get latest share info
share = self.admin_shares_v2_client.get_share(share['id'])['share']
# Verify that share always has the same AZ as share group does
self.assertEqual(
share_group['availability_zone'], share['availability_zone'])
# Get share server info
share_server = self.admin_shares_v2_client.show_share_server(
share['share_server_id'])['share_server']
if network_allocation_update:
waiters.wait_for_subnet_create_check(
self.shares_v2_client, new_share_network_id,
neutron_net_id=subnet_data['neutron_net_id'],
neutron_subnet_id=subnet_data['neutron_subnet_id'],
availability_zone=azs[0])
subnet2 = self.create_share_network_subnet(**subnet_data)
waiters.wait_for_resource_status(
self.admin_shares_v2_client, share['share_server_id'],
constants.SERVER_STATE_ACTIVE,
resource_name="share_server",
status_attr="status")
share_server = self.admin_shares_v2_client.show_share_server(
share['share_server_id'])['share_server']
# Check if share server has multiple subnets
self.assertIn(subnet1['id'], share_server['share_network_subnet_ids'])
self.assertIn(subnet2['id'], share_server['share_network_subnet_ids'])
# Delete share
params = {"share_group_id": share_group['id']}
self.shares_v2_client.delete_share(
share['id'],
params=params,
version=constants.MIN_SHARE_GROUP_MICROVERSION)
self.shares_client.wait_for_resource_deletion(share_id=share['id'])
# Delete subnet
self.shares_v2_client.delete_subnet(
new_share_network_id, subnet1['id'])
self.shares_v2_client.delete_subnet(
new_share_network_id, subnet2['id'])

View File

@ -127,6 +127,8 @@ class ShareNetworkSubnetsTest(base.BaseSharesMixedTest):
msg = ("This test needs at least two compatible storage "
"availability zones.")
raise self.skipException(msg)
check_multiple_subnet = utils.is_microversion_ge(
CONF.share.max_api_microversion, '2.70')
original_share_network = self.shares_v2_client.get_share_network(
self.shares_v2_client.share_network_id
@ -173,8 +175,12 @@ class ShareNetworkSubnetsTest(base.BaseSharesMixedTest):
# Match new subnet content
self.assertDictContainsSubset(data, subnet)
# Match share server subnet
self.assertEqual(subnet['id'],
share_server['share_network_subnet_id'])
if check_multiple_subnet:
self.assertIn(subnet['id'],
share_server['share_network_subnet_ids'])
else:
self.assertIn(subnet['id'],
share_server['share_network_subnet_id'])
# Delete share
self.shares_v2_client.delete_share(share['id'])
self.shares_v2_client.wait_for_resource_deletion(share_id=share['id'])
@ -197,10 +203,11 @@ class ShareNetworkSubnetsTest(base.BaseSharesMixedTest):
msg = ("This test needs at least two compatible storage "
"availability zones.")
raise self.skipException(msg)
check_multiple_subnet = utils.is_microversion_ge(
CONF.share.max_api_microversion, '2.70')
original_share_network = self.shares_v2_client.get_share_network(
self.shares_v2_client.share_network_id
)['share_network']
self.shares_v2_client.share_network_id)['share_network']
share_net_info = (
utils.share_network_get_default_subnet(original_share_network))
share_network = self.create_share_network(
@ -254,8 +261,12 @@ class ShareNetworkSubnetsTest(base.BaseSharesMixedTest):
# Default subnet was created during share network creation
self.assertIsNone(default_subnet['availability_zone'])
# Match share server subnet
self.assertEqual(expected_subnet_id,
share_server['share_network_subnet_id'])
if not check_multiple_subnet:
self.assertEqual(
expected_subnet_id, share_server['share_network_subnet_id'])
else:
self.assertIn(
expected_subnet_id, share_server['share_network_subnet_ids'])
if create_share_with_az:
self.assertEqual(destination_az,
share['availability_zone'])

View File

@ -27,6 +27,7 @@ from manila_tempest_tests import utils
CONF = config.CONF
LATEST_MICROVERSION = CONF.share.max_api_microversion
@ddt.ddt
@ -72,6 +73,7 @@ class ShareNetworkSubnetsNegativeTest(base.BaseSharesAdminTest):
@decorators.idempotent_id('13f397bf-5e3a-42b0-b4f9-9cd2dbbb0955')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@ddt.data(True, False)
@utils.skip_if_is_microversion_ge(LATEST_MICROVERSION, "2.70")
def test_add_share_network_subnet_in_same_az_exists(self, is_default):
share_network = self.shares_v2_client.create_share_network(
)['share_network']
@ -231,7 +233,8 @@ class ShareNetworkSubnetsNegativeTest(base.BaseSharesAdminTest):
# Get a compatible availability zone
az = self.get_availability_zones_matching_share_type(
self.share_type)[0]
check_multiple_subnets = utils.is_microversion_ge(
CONF.share.max_api_microversion, '2.70')
original_share_network = self.shares_v2_client.get_share_network(
self.shares_v2_client.share_network_id
)['share_network']
@ -269,8 +272,12 @@ class ShareNetworkSubnetsNegativeTest(base.BaseSharesAdminTest):
share['share_server_id']
)['share_server']
# Match share server subnet
self.assertEqual(subnet['id'],
share_server['share_network_subnet_id'])
if check_multiple_subnets:
self.assertIn(subnet['id'],
share_server['share_network_subnet_ids'])
else:
self.assertEqual(subnet['id'],
share_server['share_network_subnet_id'])
# Assert that the user cannot delete a subnet that contain shares
self.assertRaises(lib_exc.Conflict,

View File

@ -195,3 +195,24 @@ class ShareNetworksNegativeTest(base.BaseSharesMixedTest):
self.shares_v2_client.create_share_network,
availability_zone='inexistent-availability-zone',
)
@utils.skip_if_microversion_not_supported("2.70")
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@decorators.idempotent_id('f6f47c64-6821-4d4a-aa7d-3b0244158197')
def test_check_add_share_network_subnet_share_network_not_found(self):
data = self.generate_subnet_data()
self.assertRaises(lib_exc.NotFound,
self.shares_v2_client.subnet_create_check,
'fake_inexistent_id',
**data)
@utils.skip_if_microversion_not_supported("2.70")
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@decorators.idempotent_id('d9a487fb-6638-4f93-8b69-3e1a85bfbc7d')
def test_check_add_share_network_subnet_az_not_found(self):
share_network = self.create_share_network()
data = {'availability_zone': 'non-existent-az'}
self.assertRaises(lib_exc.BadRequest,
self.shares_v2_client.subnet_create_check,
share_network['id'], **data)

View File

@ -0,0 +1,196 @@
# Copyright 2022 NetApp 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
import testtools
from testtools import testcase as tc
from manila_tempest_tests.common import constants
from manila_tempest_tests.common import waiters
from manila_tempest_tests.tests.api import base
from manila_tempest_tests import utils
CONF = config.CONF
class ShareServerMultipleSubnetTest(base.BaseSharesMixedTest):
@classmethod
def skip_checks(cls):
super(ShareServerMultipleSubnetTest, cls).skip_checks()
if not CONF.share.multitenancy_enabled:
raise cls.skipException('Multitenancy tests are disabled.')
if not CONF.share.run_share_server_multiple_subnet_tests and not (
CONF.share.run_network_allocation_update_tests):
raise cls.skipException(
'Share server multiple subnets and network allocation '
'update tests are disabled.')
if CONF.share.share_network_id != "":
raise cls.skipException(
'These tests are not suitable for pre-existing '
'share_network.')
utils.check_skip_if_microversion_not_supported("2.70")
@classmethod
def resource_setup(cls):
super(ShareServerMultipleSubnetTest, cls).resource_setup()
cls.extra_specs = {
'driver_handles_share_servers': CONF.share.multitenancy_enabled,
}
if CONF.share.run_share_server_multiple_subnet_tests:
cls.extra_specs['share_server_multiple_subnet_support'] = True
if CONF.share.run_network_allocation_update_tests:
cls.extra_specs['network_allocation_update_support'] = True
share_type = cls.create_share_type(extra_specs=cls.extra_specs)
cls.share_type_id = share_type['id']
cls.zones = cls.get_availability_zones_matching_share_type(
share_type)
if len(cls.zones) == 0:
msg = ("These tests need at least one compatible "
"availability zone.")
raise cls.skipException(msg)
cls.share_network = cls.alt_shares_v2_client.get_share_network(
cls.alt_shares_v2_client.share_network_id)['share_network']
cls.default_subnet = utils.share_network_get_default_subnet(
cls.share_network)
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipIf(
not CONF.share.run_share_server_multiple_subnet_tests,
"Share network multiple subnets tests are disabled.")
@decorators.idempotent_id('5600bd52-ecb4-47d3-a4e8-3e6565cb0b80')
def test_create_share_on_multiple_subnets_same_az(self):
share_network_id = self.create_share_network(
cleanup_in_class=False)["id"]
subnet_data = {
'neutron_net_id': self.default_subnet.get('neutron_net_id'),
'neutron_subnet_id': self.default_subnet.get('neutron_subnet_id'),
'share_network_id': share_network_id,
'availability_zone': self.zones[0],
}
subnet1 = self.create_share_network_subnet(**subnet_data)
subnet2 = self.create_share_network_subnet(**subnet_data)
share = self.create_share(
share_type_id=self.share_type_id,
share_network_id=share_network_id,
availability_zone=self.zones[0])
self.assertIn(share['status'], ('creating', 'available'))
share = self.admin_shares_v2_client.get_share(share['id'])['share']
share_server = self.admin_shares_v2_client.show_share_server(
share['share_server_id']
)['share_server']
self.assertIn(subnet1['id'],
share_server['share_network_subnet_ids'])
self.assertIn(subnet2['id'],
share_server['share_network_subnet_ids'])
# Delete share
self.shares_v2_client.delete_share(share['id'])
self.shares_v2_client.wait_for_resource_deletion(share_id=share['id'])
# Delete the subnets
self.shares_v2_client.delete_subnet(share_network_id, subnet1['id'])
self.shares_v2_client.delete_subnet(share_network_id, subnet2['id'])
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipIf(
not CONF.share.run_network_allocation_update_tests,
"Share server network allocation update are disabled.")
@decorators.idempotent_id('2a9debd5-47a3-42cc-823b-2b9de435a5e4')
def test_create_share_with_network_allocation_update(self):
share_network_id = self.create_share_network(
cleanup_in_class=False)["id"]
subnet_data = {
'neutron_net_id': self.default_subnet.get('neutron_net_id'),
'neutron_subnet_id': self.default_subnet.get('neutron_subnet_id'),
'share_network_id': share_network_id,
'availability_zone': self.zones[0],
}
subnet1 = self.create_share_network_subnet(**subnet_data)
share = self.create_share(
share_type_id=self.share_type_id,
share_network_id=share_network_id,
availability_zone=self.zones[0])
self.assertIn(share['status'], ('creating', 'available'))
share = self.admin_shares_v2_client.get_share(share['id'])['share']
waiters.wait_for_subnet_create_check(
self.shares_v2_client, share_network_id,
neutron_net_id=subnet_data['neutron_net_id'],
neutron_subnet_id=subnet_data['neutron_subnet_id'],
availability_zone=self.zones[0])
subnet2 = self.create_share_network_subnet(**subnet_data)
waiters.wait_for_resource_status(
self.admin_shares_v2_client, share['share_server_id'],
constants.SERVER_STATE_ACTIVE,
resource_name="share_server",
status_attr="status")
share_server = self.admin_shares_v2_client.show_share_server(
share['share_server_id']
)['share_server']
self.assertIn(subnet1['id'],
share_server['share_network_subnet_ids'])
self.assertIn(subnet2['id'],
share_server['share_network_subnet_ids'])
# Delete share
self.shares_v2_client.delete_share(share['id'])
self.shares_v2_client.wait_for_resource_deletion(share_id=share['id'])
# Delete subnets
self.shares_v2_client.delete_subnet(share_network_id, subnet1['id'])
self.shares_v2_client.delete_subnet(share_network_id, subnet2['id'])
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipIf(
not CONF.share.run_network_allocation_update_tests,
"Share server network allocation update are disabled.")
@decorators.idempotent_id('2624f9a7-660b-4f91-89b8-c026b3bb8d1f')
def test_share_network_subnet_create_check(self):
"""The share network subnet create check compatibility test."""
share_network_id = self.create_share_network(
cleanup_in_class=False)["id"]
subnet_data = {
'neutron_net_id': self.default_subnet.get('neutron_net_id'),
'neutron_subnet_id': self.default_subnet.get('neutron_subnet_id'),
'share_network_id': share_network_id,
'availability_zone': self.zones[0],
}
subnet1 = self.create_share_network_subnet(**subnet_data)
share = self.create_share(
share_type_id=self.share_type_id,
share_network_id=share_network_id,
availability_zone=self.zones[0]
)
self.assertIn(share['status'], ('creating', 'available'))
waiters.wait_for_subnet_create_check(
self.shares_v2_client, share_network_id,
neutron_net_id=subnet_data['neutron_net_id'],
neutron_subnet_id=subnet_data['neutron_subnet_id'],
availability_zone=self.zones[0])
# Delete share
self.shares_v2_client.delete_share(share['id'])
self.shares_v2_client.wait_for_resource_deletion(share_id=share['id'])
# Delete subnets
self.shares_v2_client.delete_subnet(share_network_id, subnet1['id'])

View File

@ -0,0 +1,90 @@
# Copyright 2022 NetApp 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.common.utils import test_utils
from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests import share_exceptions
from manila_tempest_tests.tests.api import base
from manila_tempest_tests import utils
CONF = config.CONF
class ShareServerMultipleSubNegativeTest(base.BaseSharesMixedTest):
@classmethod
def skip_checks(cls):
super(ShareServerMultipleSubNegativeTest, cls).skip_checks()
if not CONF.share.multitenancy_enabled:
raise cls.skipException('Multitenancy tests are disabled.')
utils.check_skip_if_microversion_not_supported("2.70")
@classmethod
def resource_setup(cls):
super(ShareServerMultipleSubNegativeTest, cls).resource_setup()
cls.share_network = cls.alt_shares_v2_client.get_share_network(
cls.alt_shares_v2_client.share_network_id)['share_network']
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@decorators.idempotent_id('1e2a9415-b02f-4c02-812d-bedc361f92ce')
def test_create_share_multiple_subnets_to_unsupported_backend(self):
extra_specs = {
'driver_handles_share_servers': CONF.share.multitenancy_enabled,
'share_server_multiple_subnet_support': False
}
share_type = self.create_share_type(extra_specs=extra_specs)
pools = self.get_pools_matching_share_type(
share_type, client=self.admin_shares_v2_client)
zones = self.get_availability_zones_matching_share_type(
share_type)
if not pools or not zones:
raise self.skipException("At least one backend that supports "
"adding multiple subnets into a share "
"network is needed for this test.")
extra_specs = {'pool_name': pools[0]['pool'],
'availability_zone': zones[0]}
self.admin_shares_v2_client.update_share_type_extra_specs(
share_type['id'], extra_specs)
share_network_id = self.create_share_network(
cleanup_in_class=True)["id"]
default_subnet = utils.share_network_get_default_subnet(
self.share_network)
subnet_data = {
'neutron_net_id': default_subnet.get('neutron_net_id'),
'neutron_subnet_id': default_subnet.get('neutron_subnet_id'),
'share_network_id': share_network_id,
'availability_zone': zones[0],
'cleanup_in_class': False
}
subnet1 = self.create_share_network_subnet(**subnet_data)
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.shares_v2_client.delete_subnet,
share_network_id, subnet1['id'])
subnet2 = self.create_share_network_subnet(**subnet_data)
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.shares_v2_client.delete_subnet,
share_network_id, subnet2['id'])
self.assertRaises(
share_exceptions.ShareBuildErrorException,
self.create_share,
share_type_id=share_type['id'],
share_network_id=share_network_id,
availability_zone=zones[0],
cleanup_in_class=False
)

View File

@ -94,6 +94,16 @@ def skip_if_microversion_not_supported(microversion):
return lambda f: f
def skip_if_is_microversion_ge(left, right):
"""Skip if version for left is greater than or equal to the right one."""
if is_microversion_ge(left, right):
reason = ("Skipped. Test requires microversion "
"< than '%s'." % right)
return testtools.skip(reason)
return lambda f: f
def check_skip_if_microversion_not_supported(microversion):
"""Callable method for tests that are microversion-specific."""
if not is_microversion_supported(microversion):

View File

@ -246,6 +246,8 @@
backend_names: LONDON,PARIS
multi_backend: true
run_share_server_migration_tests: true
run_share_server_multiple_subnet_tests: true
run_network_allocation_update_tests: true
- job:
name: manila-tempest-plugin-generic
@ -490,6 +492,8 @@
run_replication_tests: true
run_revert_to_snapshot_tests: true
run_share_server_migration_tests: true
run_share_server_multiple_subnet_tests: true
run_network_allocation_update_tests: true
- job:
name: manila-tempest-plugin-glusterfs-native