diff --git a/contrib/ci/common.sh b/contrib/ci/common.sh index df85a3b9af..f7652c9f2d 100755 --- a/contrib/ci/common.sh +++ b/contrib/ci/common.sh @@ -74,3 +74,62 @@ function manila_wait_for_drivers_init { # its capabilities on time. sleep 10 } + +function archive_file { + # First argument is expected to be filename + local filename=$1 + + sudo gzip -9 $filename + sudo chown jenkins:jenkins $filename.gz + sudo chmod a+r $filename.gz +} + +function save_tempest_results { + # First argument is expected to be number or tempest run + + local src_dirname + local dst_dirname + + src_dirname="$BASE/new/tempest" + dst_dirname="$BASE/logs/tempest_$1" + + # 1. Create destination directory + sudo mkdir $dst_dirname + sudo chown jenkins:jenkins $dst_dirname + sudo chmod 755 $dst_dirname + + # 2. Save tempest configuration file + sudo cp $src_dirname/etc/tempest.conf $dst_dirname/tempest_conf.txt + + # 3. Save tempest log file + cp $src_dirname/tempest.log $src_dirname/tempest.txt + echo '' > $src_dirname/tempest.log + archive_file $src_dirname/tempest.txt + sudo mv $src_dirname/tempest.txt.gz $dst_dirname/tempest.txt.gz + + # 4. Save tempest testr results + + # Check for an interrupted run first + if [ -f $src_dirname/.testrepository/tmp* ]; then + sudo cat $src_dirname/.testrepository/tmp* >> $src_dirname/tempest.subunit + elif [ -f $src_dirname/.testrepository/0 ]; then + pushd $src_dirname + sudo testr last --subunit > $src_dirname/tempest.subunit + popd + fi + + if [ -f $src_dirname/tempest.subunit ]; then + sudo /usr/os-testr-env/bin/subunit2html \ + $src_dirname/tempest.subunit $src_dirname/testr_results.html + archive_file $src_dirname/tempest.subunit + sudo mv $src_dirname/tempest.subunit.gz $dst_dirname/tempest.subunit.gz + + archive_file $src_dirname/testr_results.html + sudo mv $src_dirname/testr_results.html.gz $dst_dirname/testr_results.html.gz + + # 5. Cleanup + sudo rm -rf $src_dirname/.testrepository + else + echo "No 'testr' results available for saving. File '$src_dirname/tempest.subunit' is absent." + fi +} diff --git a/contrib/ci/post_test_hook.sh b/contrib/ci/post_test_hook.sh index f37cecd2f2..7171cf4f8c 100755 --- a/contrib/ci/post_test_hook.sh +++ b/contrib/ci/post_test_hook.sh @@ -43,7 +43,9 @@ TEST_TYPE=$3 POSTGRES_ENABLED=$4 POSTGRES_ENABLED=$(trueorfalse True POSTGRES_ENABLED) -if [[ "$BACK_END_TYPE" == "multibackend" ]]; then +if [[ "$DRIVER" == "dummy" ]]; then + export BACKENDS_NAMES="ALPHA,BETA" +elif [[ "$BACK_END_TYPE" == "multibackend" ]]; then iniset $TEMPEST_CONFIG share multi_backend True iniset $TEMPEST_CONFIG share run_migration_tests $(trueorfalse True RUN_MANILA_MIGRATION_TESTS) @@ -185,6 +187,26 @@ elif [[ "$DRIVER" == "zfsonlinux" ]]; then iniset $TEMPEST_CONFIG share multitenancy_enabled False iniset $TEMPEST_CONFIG share multi_backend True iniset $TEMPEST_CONFIG share backend_replication_type 'readable' +elif [[ "$DRIVER" == "dummy" ]]; then + MANILA_TEMPEST_CONCURRENCY=24 + RUN_MANILA_CG_TESTS=True + RUN_MANILA_MANAGE_TESTS=False + iniset $TEMPEST_CONFIG share run_migration_tests False + iniset $TEMPEST_CONFIG share run_quota_tests True + iniset $TEMPEST_CONFIG share run_replication_tests False + iniset $TEMPEST_CONFIG share run_shrink_tests True + iniset $TEMPEST_CONFIG share enable_ip_rules_for_protocols 'nfs' + iniset $TEMPEST_CONFIG share enable_user_rules_for_protocols 'cifs' + iniset $TEMPEST_CONFIG share enable_cert_rules_for_protocols '' + iniset $TEMPEST_CONFIG share enable_ro_access_level_for_protocols 'nfs,cifs' + iniset $TEMPEST_CONFIG share build_timeout 180 + iniset $TEMPEST_CONFIG share share_creation_retry_number 0 + iniset $TEMPEST_CONFIG share capability_storage_protocol 'NFS_CIFS' + iniset $TEMPEST_CONFIG share enable_protocols 'nfs,cifs' + iniset $TEMPEST_CONFIG share suppress_errors_in_cleanup False + iniset $TEMPEST_CONFIG share multitenancy_enabled True + iniset $TEMPEST_CONFIG share create_networks_when_multitenancy_enabled False + iniset $TEMPEST_CONFIG share multi_backend True fi # Enable consistency group tests @@ -213,3 +235,37 @@ manila_wait_for_drivers_init $MANILA_CONF echo "Running tempest manila test suites" sudo -H -u jenkins tox -eall-plugin $MANILA_TESTS -- --concurrency=$MANILA_TEMPEST_CONCURRENCY +RETVAL=$? + +if [[ "$DRIVER" == "dummy" ]]; then + save_tempest_results 1 + echo "First tempest run (DHSS=True) returned '$RETVAL'" + iniset $TEMPEST_CONFIG share backend_names "GAMMA,DELTA" + + # NOTE(vponomaryov): enable migration tests when its support added to + # dummy driver. + iniset $TEMPEST_CONFIG share run_migration_tests False + iniset $TEMPEST_CONFIG share run_manage_unmanage_tests True + iniset $TEMPEST_CONFIG share run_manage_unmanage_snapshot_tests True + iniset $TEMPEST_CONFIG share run_replication_tests True + iniset $TEMPEST_CONFIG share multitenancy_enabled False + iniset $TEMPEST_CONFIG share backend_replication_type 'readable' + + # Change driver mode for default share type to make tempest use + # DHSS=False backends. + source $BASE/new/devstack/openrc admin demo + manila type-key default set driver_handles_share_servers=False + + echo "Running tempest manila test suites for DHSS=False mode" + sudo -H -u jenkins tox -eall-plugin $MANILA_TESTS -- --concurrency=$MANILA_TEMPEST_CONCURRENCY + RETVAL2=$? + save_tempest_results 2 + + # Exit with last code if first succeeded else exit with first error code + if [[ "$RETVAL" == "0" ]]; then + RETVAL=$RETVAL2 + fi + + echo "Second tempest run (DHSS=False) returned '$RETVAL2'" +fi +exit $RETVAL diff --git a/contrib/ci/pre_test_hook.sh b/contrib/ci/pre_test_hook.sh index 111a515757..f30406b9e7 100755 --- a/contrib/ci/pre_test_hook.sh +++ b/contrib/ci/pre_test_hook.sh @@ -75,6 +75,55 @@ if [[ "$DRIVER" == "generic" ]]; then elif [[ "$DRIVER" == "windows" ]]; then MANILA_SERVICE_IMAGE_ENABLED=True echo "SHARE_DRIVER=manila.share.drivers.windows.windows_smb_driver.WindowsSMBDriver" >> $localrc_path +elif [[ "$DRIVER" == "dummy" ]]; then + driver_path="manila.tests.share.drivers.dummy.DummyDriver" + echo "MANILA_SERVICE_IMAGE_ENABLED=False" >> $localrc_path + echo "SHARE_DRIVER=$driver_path" >> $localrc_path + echo "SUPPRESS_ERRORS_IN_CLEANUP=False" >> $localrc_path + echo "MANILA_REPLICA_STATE_UPDATE_INTERVAL=10" >> $localrc_path + echo "MANILA_ENABLED_BACKENDS=alpha,beta,gamma,delta" >> $localrc_path + echo "MANILA_CONFIGURE_GROUPS=alpha,beta,gamma,delta,membernet,adminnet" >> $localrc_path + + echo "MANILA_OPTGROUP_alpha_share_driver=$driver_path" >> $localrc_path + echo "MANILA_OPTGROUP_alpha_driver_handles_share_servers=True" >> $localrc_path + echo "MANILA_OPTGROUP_alpha_share_backend_name=ALPHA" >> $localrc_path + echo "MANILA_OPTGROUP_alpha_network_config_group=membernet" >> $localrc_path + echo "MANILA_OPTGROUP_alpha_admin_network_config_group=adminnet" >> $localrc_path + + echo "MANILA_OPTGROUP_beta_share_driver=$driver_path" >> $localrc_path + echo "MANILA_OPTGROUP_beta_driver_handles_share_servers=True" >> $localrc_path + echo "MANILA_OPTGROUP_beta_share_backend_name=BETA" >> $localrc_path + echo "MANILA_OPTGROUP_beta_network_config_group=membernet" >> $localrc_path + echo "MANILA_OPTGROUP_beta_admin_network_config_group=adminnet" >> $localrc_path + + echo "MANILA_OPTGROUP_gamma_share_driver=$driver_path" >> $localrc_path + echo "MANILA_OPTGROUP_gamma_driver_handles_share_servers=False" >> $localrc_path + echo "MANILA_OPTGROUP_gamma_share_backend_name=GAMMA" >> $localrc_path + echo "MANILA_OPTGROUP_gamma_replication_domain=DUMMY_DOMAIN" >> $localrc_path + + echo "MANILA_OPTGROUP_delta_share_driver=$driver_path" >> $localrc_path + echo "MANILA_OPTGROUP_delta_driver_handles_share_servers=False" >> $localrc_path + echo "MANILA_OPTGROUP_delta_share_backend_name=DELTA" >> $localrc_path + echo "MANILA_OPTGROUP_delta_replication_domain=DUMMY_DOMAIN" >> $localrc_path + + echo "MANILA_OPTGROUP_membernet_network_api_class=manila.network.standalone_network_plugin.StandaloneNetworkPlugin" >> $localrc_path + echo "MANILA_OPTGROUP_membernet_standalone_network_plugin_gateway=10.0.0.1" >> $localrc_path + echo "MANILA_OPTGROUP_membernet_standalone_network_plugin_mask=24" >> $localrc_path + echo "MANILA_OPTGROUP_membernet_standalone_network_plugin_network_type=vlan" >> $localrc_path + echo "MANILA_OPTGROUP_membernet_standalone_network_plugin_segmentation_id=1010" >> $localrc_path + echo "MANILA_OPTGROUP_membernet_standalone_network_plugin_allowed_ip_ranges=10.0.0.10-10.0.0.209" >> $localrc_path + echo "MANILA_OPTGROUP_membernet_standalone_network_plugin_ip_version=4" >> $localrc_path + + echo "MANILA_OPTGROUP_adminnet_network_api_class=manila.network.standalone_network_plugin.StandaloneNetworkPlugin" >> $localrc_path + echo "MANILA_OPTGROUP_adminnet_standalone_network_plugin_gateway=11.0.0.1" >> $localrc_path + echo "MANILA_OPTGROUP_adminnet_standalone_network_plugin_mask=24" >> $localrc_path + echo "MANILA_OPTGROUP_adminnet_standalone_network_plugin_network_type=vlan" >> $localrc_path + echo "MANILA_OPTGROUP_adminnet_standalone_network_plugin_segmentation_id=1011" >> $localrc_path + echo "MANILA_OPTGROUP_adminnet_standalone_network_plugin_allowed_ip_ranges=11.0.0.10-11.0.0.19,11.0.0.30-11.0.0.39,11.0.0.50-11.0.0.199" >> $localrc_path + echo "MANILA_OPTGROUP_adminnet_standalone_network_plugin_ip_version=4" >> $localrc_path + + export MANILA_TEMPEST_CONCURRENCY=24 + elif [[ "$DRIVER" == "lvm" ]]; then echo "SHARE_DRIVER=manila.share.drivers.lvm.LVMShareDriver" >> $localrc_path echo "SHARE_BACKING_FILE_SIZE=32000M" >> $localrc_path @@ -98,7 +147,7 @@ echo 'ENABLE_ISOLATED_METADATA=True' >> $localrc_path echo "TEMPEST_USE_TEST_ACCOUNTS=True" >> $localrc_path echo "TEMPEST_ALLOW_TENANT_ISOLATION=False" >> $localrc_path -echo "TEMPEST_CONCURRENCY=8" >> $localrc_path +echo "TEMPEST_CONCURRENCY=${MANILA_TEMPEST_CONCURRENCY:-8}" >> $localrc_path # Go to Tempest dir and checkout stable commit to avoid possible # incompatibilities for plugin stored in Manila repo. diff --git a/manila/tests/share/drivers/dummy.py b/manila/tests/share/drivers/dummy.py new file mode 100644 index 0000000000..4d1b0a8e24 --- /dev/null +++ b/manila/tests/share/drivers/dummy.py @@ -0,0 +1,330 @@ +# Copyright 2016 Mirantis 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. + +""" +Dummy share driver for testing Manila APIs and other interfaces. + +This driver simulates support of: +- Both available driver modes: DHSS=True/False +- NFS and CIFS protocols +- IP access for NFS shares and USER access for CIFS shares +- CIFS shares in DHSS=True driver mode +- Creation and deletion of share snapshots +- Share replication (readable) +- Consistency groups +- Resize of a share (extend/shrink) + +""" + +from oslo_log import log + +from manila.common import constants +from manila import exception +from manila.i18n import _ +from manila.share import driver +from manila.share import utils as share_utils + +LOG = log.getLogger(__name__) + + +class DummyDriver(driver.ShareDriver): + """Dummy share driver that implements all share driver interfaces.""" + + def __init__(self, *args, **kwargs): + """Do initialization.""" + super(self.__class__, self).__init__([False, True], *args, **kwargs) + self.private_storage = kwargs.get('private_storage') + self.backend_name = self.configuration.safe_get( + "share_backend_name") or "DummyDriver" + + def _get_share_name(self, share): + return "share_%(s_id)s_%(si_id)s" % { + "s_id": share["share_id"].replace("-", "_"), + "si_id": share["id"].replace("-", "_")} + + def _get_snapshot_name(self, snapshot): + return "snapshot_%(s_id)s_%(si_id)s" % { + "s_id": snapshot["snapshot_id"].replace("-", "_"), + "si_id": snapshot["id"].replace("-", "_")} + + def _generate_export_locations(self, mountpoint, share_server=None): + details = share_server["backend_details"] if share_server else { + "primary_public_ip": "10.0.0.10", + "secondary_public_ip": "10.0.0.20", + "service_ip": "11.0.0.11", + } + return [ + { + "path": "%(ip)s:%(mp)s" % {"ip": ip, "mp": mountpoint}, + "metadata": { + "preferred": preferred, + }, + "is_admin_only": is_admin_only, + } for ip, is_admin_only, preferred in ( + (details["primary_public_ip"], False, True), + (details["secondary_public_ip"], False, False), + (details["service_ip"], True, False)) + ] + + def _create_share(self, share, share_server=None): + share_proto = share["share_proto"] + if share_proto not in ("NFS", "CIFS"): + msg = _("Unsupported share protocol provided - %s.") % share_proto + raise exception.InvalidShareAccess(reason=msg) + + share_name = self._get_share_name(share) + mountpoint = "/path/to/fake/share/%s" % share_name + self.private_storage.update( + share["id"], { + "fake_provider_share_name": share_name, + "fake_provider_location": mountpoint, + } + ) + return self._generate_export_locations( + mountpoint, share_server=share_server) + + def create_share(self, context, share, share_server=None): + """Is called to create share.""" + return self._create_share(share, share_server=share_server) + + def create_share_from_snapshot(self, context, share, snapshot, + share_server=None): + """Is called to create share from snapshot.""" + return self._create_share(share, share_server=share_server) + + def _create_snapshot(self, snapshot): + snapshot_name = self._get_snapshot_name(snapshot) + self.private_storage.update( + snapshot["id"], { + "fake_provider_snapshot_name": snapshot_name, + } + ) + return {"provider_location": snapshot_name} + + def create_snapshot(self, context, snapshot, share_server=None): + """Is called to create snapshot.""" + return self._create_snapshot(snapshot) + + def delete_share(self, context, share, share_server=None): + """Is called to remove share.""" + self.private_storage.delete(share["id"]) + + def delete_snapshot(self, context, snapshot, share_server=None): + """Is called to remove snapshot.""" + self.private_storage.delete(snapshot["id"]) + + def get_pool(self, share): + """Return pool name where the share resides on.""" + pool_name = share_utils.extract_host(share["host"], level="pool") + return pool_name + + def ensure_share(self, context, share, share_server=None): + """Invoked to ensure that share is exported.""" + + def update_access(self, context, share, access_rules, add_rules, + delete_rules, share_server=None): + """Update access rules for given share.""" + for rule in add_rules + access_rules: + share_proto = share["share_proto"].lower() + access_type = rule["access_type"].lower() + if not ( + (share_proto == "nfs" and access_type == "ip") or + (share_proto == "cifs" and access_type == "user")): + msg = _("Unsupported '%(access_type)s' access type provided " + "for '%(share_proto)s' share protocol.") % { + "access_type": access_type, "share_proto": share_proto} + raise exception.InvalidShareAccess(reason=msg) + + def do_setup(self, context): + """Any initialization the share driver does while starting.""" + + def manage_existing(self, share, driver_options): + """Brings an existing share under Manila management.""" + return {"size": 1, "export_locations": self._create_share(share)} + + def unmanage(self, share): + """Removes the specified share from Manila management.""" + + def manage_existing_snapshot(self, snapshot, driver_options): + """Brings an existing snapshot under Manila management.""" + self._create_snapshot(snapshot) + return {"size": 1, "provider_location": snapshot["provider_location"]} + + def unmanage_snapshot(self, snapshot): + """Removes the specified snapshot from Manila management.""" + + def extend_share(self, share, new_size, share_server=None): + """Extends size of existing share.""" + + def shrink_share(self, share, new_size, share_server=None): + """Shrinks size of existing share.""" + + def get_network_allocations_number(self): + """Returns number of network allocations for creating VIFs.""" + return 2 + + def get_admin_network_allocations_number(self): + return 1 + + def _setup_server(self, network_info, metadata=None): + """Sets up and configures share server with given network parameters. + + Redefine it within share driver when it is going to handle share + servers. + """ + server_details = { + "primary_public_ip": network_info[ + "network_allocations"][0]["ip_address"], + "secondary_public_ip": network_info[ + "network_allocations"][1]["ip_address"], + "service_ip": network_info[ + "admin_network_allocations"][0]["ip_address"], + "username": "fake_username", + } + return server_details + + def _teardown_server(self, server_details, security_services=None): + """Tears down share server.""" + + def _get_pools_info(self): + pools = [{ + "pool_name": "fake_pool_for_%s" % self.backend_name, + "total_capacity_gb": 1230.0, + "free_capacity_gb": 1210.0, + "reserved_percentage": self.configuration.reserved_share_percentage + }] + if self.configuration.replication_domain: + pools[0]["replication_type"] = "readable" + return pools + + def _update_share_stats(self, data=None): + """Retrieve stats info from share group.""" + data = { + "share_backend_name": self.backend_name, + "storage_protocol": "NFS_CIFS", + "reserved_percentage": + self.configuration.reserved_share_percentage, + "consistency_group_support": "pool", + "snapshot_support": True, + "driver_name": "Dummy", + "pools": self._get_pools_info(), + } + if self.configuration.replication_domain: + data["replication_type"] = "readable" + super(self.__class__, self)._update_share_stats(data) + + def get_share_server_pools(self, share_server): + """Return list of pools related to a particular share server.""" + return [] + + def create_consistency_group(self, context, cg_dict, share_server=None): + """Create a consistency group.""" + LOG.debug( + "Successfully created dummy Consistency Group with ID: %s.", + cg_dict["id"]) + + def delete_consistency_group(self, context, cg_dict, share_server=None): + """Delete a consistency group.""" + LOG.debug( + "Successfully deleted dummy consistency group with ID %s.", + cg_dict["id"]) + + def create_cgsnapshot(self, context, snap_dict, share_server=None): + """Create a consistency group snapshot.""" + LOG.debug("Successfully created CG snapshot %s." % snap_dict["id"]) + return None, None + + def delete_cgsnapshot(self, context, snap_dict, share_server=None): + """Delete a consistency group snapshot.""" + LOG.debug("Successfully deleted CG snapshot %s." % snap_dict["id"]) + return None, None + + def create_consistency_group_from_cgsnapshot( + self, context, cg_dict, cgsnapshot_dict, share_server=None): + """Create a consistency group from a cgsnapshot.""" + LOG.debug( + ("Successfully created dummy Consistency Group (%(cg_id)s) " + "from CG snapshot (%(cg_snap_id)s)."), + {"cg_id": cg_dict["id"], "cg_snap_id": cgsnapshot_dict["id"]}) + return None, [] + + def create_replica(self, context, replica_list, new_replica, + access_rules, replica_snapshots, share_server=None): + """Replicate the active replica to a new replica on this backend.""" + replica_name = self._get_share_name(new_replica) + mountpoint = "/path/to/fake/share/%s" % replica_name + self.private_storage.update( + new_replica["id"], { + "fake_provider_replica_name": replica_name, + "fake_provider_location": mountpoint, + } + ) + return { + "export_locations": self._generate_export_locations( + mountpoint, share_server=share_server), + "replica_state": constants.REPLICA_STATE_IN_SYNC, + "access_rules_status": constants.STATUS_ACTIVE, + } + + def delete_replica(self, context, replica_list, replica_snapshots, + replica, share_server=None): + """Delete a replica.""" + self.private_storage.delete(replica["id"]) + + def promote_replica(self, context, replica_list, replica, access_rules, + share_server=None): + """Promote a replica to 'active' replica state.""" + return_replica_list = [] + for r in replica_list: + if r["id"] == replica["id"]: + replica_state = constants.REPLICA_STATE_ACTIVE + else: + replica_state = constants.REPLICA_STATE_IN_SYNC + return_replica_list.append( + {"id": r["id"], "replica_state": replica_state}) + return return_replica_list + + def update_replica_state(self, context, replica_list, replica, + access_rules, replica_snapshots, + share_server=None): + """Update the replica_state of a replica.""" + return constants.REPLICA_STATE_IN_SYNC + + def create_replicated_snapshot(self, context, replica_list, + replica_snapshots, share_server=None): + """Create a snapshot on active instance and update across the replicas. + + """ + return_replica_snapshots = [] + for r in replica_snapshots: + return_replica_snapshots.append( + {"id": r["id"], "status": constants.STATUS_AVAILABLE}) + return return_replica_snapshots + + def delete_replicated_snapshot(self, context, replica_list, + replica_snapshots, share_server=None): + """Delete a snapshot by deleting its instances across the replicas.""" + return_replica_snapshots = [] + for r in replica_snapshots: + return_replica_snapshots.append( + {"id": r["id"], "status": constants.STATUS_DELETED}) + return return_replica_snapshots + + def update_replicated_snapshot(self, context, replica_list, + share_replica, replica_snapshots, + replica_snapshot, share_server=None): + """Update the status of a snapshot instance that lives on a replica.""" + return { + "id": replica_snapshot["id"], "status": constants.STATUS_AVAILABLE} diff --git a/manila_tempest_tests/config.py b/manila_tempest_tests/config.py index 7a7ee6f211..4b394c64f6 100644 --- a/manila_tempest_tests/config.py +++ b/manila_tempest_tests/config.py @@ -56,6 +56,15 @@ ShareGroup = [ help="This option used to determine backend driver type, " "multitenant driver uses share-networks, but " "single-tenant doesn't."), + cfg.BoolOpt("create_networks_when_multitenancy_enabled", + default=True, + help="This option is used only when other " + "'multitenancy_enabled' option is set to 'True'. " + "If this one is set to True, then tempest will create " + "neutron networks for each new manila share-network " + "it creates. Else it will use manila share-networks with " + "empty values (case of StandAloneNetworkPlugin and " + "NeutronSingleNetworkPlugin)."), cfg.ListOpt("enable_protocols", default=["nfs", "cifs"], help="First value of list is protocol by default, " diff --git a/manila_tempest_tests/tests/api/base.py b/manila_tempest_tests/tests/api/base.py index a599196cee..79c8673cc1 100644 --- a/manila_tempest_tests/tests/api/base.py +++ b/manila_tempest_tests/tests/api/base.py @@ -203,7 +203,8 @@ class BaseSharesTest(test.BaseTestCase): # Provide share network if CONF.share.multitenancy_enabled: - if not CONF.service_available.neutron: + if (not CONF.service_available.neutron and + CONF.share.create_networks_when_multitenancy_enabled): raise cls.skipException("Neutron support is required") nc = os.networks_client share_network_id = cls.provide_share_network(client, nc, ic) @@ -235,7 +236,8 @@ class BaseSharesTest(test.BaseTestCase): os.auth_provider) cls.shares_v2_client = os.shares_v2_client if CONF.share.multitenancy_enabled: - if not CONF.service_available.neutron: + if (not CONF.service_available.neutron and + CONF.share.create_networks_when_multitenancy_enabled): raise cls.skipException("Neutron support is required") share_network_id = cls.provide_share_network( cls.shares_v2_client, os.networks_client) @@ -282,6 +284,8 @@ class BaseSharesTest(test.BaseTestCase): """ sc = shares_client + search_word = "reusable" + sn_name = "autogenerated_by_tempest_%s" % search_word if not CONF.share.multitenancy_enabled: # Assumed usage of a single-tenant driver @@ -289,13 +293,28 @@ class BaseSharesTest(test.BaseTestCase): elif sc.share_network_id: # Share-network already exists, use it share_network_id = sc.share_network_id + elif not CONF.share.create_networks_when_multitenancy_enabled: + share_network_id = None + + # Try get suitable share-network + share_networks = sc.list_share_networks_with_detail() + for sn in share_networks: + if (sn["neutron_net_id"] is None and + sn["neutron_subnet_id"] is None and + sn["name"] and search_word in sn["name"]): + share_network_id = sn["id"] + break + + # Create new share-network if one was not found + if share_network_id is None: + sn_desc = "This share-network was created by tempest" + sn = sc.create_share_network(name=sn_name, description=sn_desc) + share_network_id = sn["id"] else: net_id = subnet_id = share_network_id = None if not isolated_creds_client: # Search for networks, created in previous runs - search_word = "reusable" - sn_name = "autogenerated_by_tempest_%s" % search_word service_net_name = "share-service" networks = networks_client.list_networks() if "networks" in networks.keys(): diff --git a/manila_tempest_tests/tests/api/test_shares.py b/manila_tempest_tests/tests/api/test_shares.py index 2acd81a8e1..f7ff194f64 100644 --- a/manila_tempest_tests/tests/api/test_shares.py +++ b/manila_tempest_tests/tests/api/test_shares.py @@ -146,8 +146,10 @@ class SharesNFSTest(base.BaseSharesTest): self.protocol, snapshot_id=snap["id"], cleanup_in_class=False) # The 'status' of the share returned by the create API must be - # the default value - 'creating'. - self.assertEqual('creating', s2['status']) + # set and have value either 'creating' or + # 'available' (if share creation is really fast as in + # case of Dummy driver). + self.assertIn(s2['status'], ('creating', 'available')) # verify share, created from snapshot get = self.shares_client.get_share(s2["id"])