Merge "Add functional tests for add multiple subnets feature"
This commit is contained in:
commit
822cba5b0c
|
@ -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)
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -1957,6 +1957,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(
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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'])
|
||||
|
|
|
@ -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'])
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'])
|
|
@ -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
|
||||
)
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue