def resource_setup(cls): super(ShareServersAdminTest, cls).resource_setup() # create share type cls.share_type = cls.create_share_type() cls.share_type_id = cls.share_type['id'] # create share in this new share network cls.share = cls.create_share( share_type_id=cls.share_type_id) cls.share_network = cls.shares_v2_client.get_share_network( cls.shares_v2_client.share_network_id)['share_network'] if not cls.share_network["name"]: sn_id = cls.share_network["id"] cls.share_network = cls.shares_v2_client.update_share_network( sn_id, name="sn_%s" % sn_id) cls.sn_name_and_id = [ cls.share_network["name"], cls.share_network["id"], ] cls.share_net_info = ( utils.share_network_get_default_subnet(cls.share_network) if utils.share_network_subnets_are_supported() else cls.share_network) # Date should be like '2014-13-12T11:10:09.000000' cls.date_re = re.compile("^([0-9]{4}-[0-9]{2}-[0-9]{2}[A-Z]{1}" "[0-9]{2}:[0-9]{2}:[0-9]{2}).*$")
def test_create_share_on_subnet_with_availability_zone(self): compatible_azs = self.get_availability_zones_matching_share_type( self.share_type) if len(compatible_azs) < 2: msg = ("This test needs at least two compatible storage " "availability zones.") raise self.skipException(msg) original_share_network = self.shares_v2_client.get_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( neutron_net_id=share_net_info['neutron_net_id'], neutron_subnet_id=share_net_info['neutron_subnet_id'], ) share_network = self.shares_v2_client.get_share_network( share_network['id'])['share_network'] default_subnet = share_network['share_network_subnets'][0] availability_zone = compatible_azs[0] data = { "neutron_net_id": share_net_info['neutron_net_id'], "neutron_subnet_id": share_net_info['neutron_subnet_id'], 'share_network_id': share_network['id'], 'availability_zone': availability_zone, } # Create a new share network subnet subnet = self.create_share_network_subnet(**data) # Create a new share in the select availability zone # The 'status' of the share returned by the create API must be share = self.create_share(share_type_id=self.share_type_id, share_network_id=share_network['id'], availability_zone=availability_zone) # Set and have value either 'creating' or # 'available' (if share creation is really fast as in # case of Dummy driver). 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'] # Default subnet was created during share network creation self.assertIsNone(default_subnet['availability_zone']) # Match new subnet content self.assertDictContainsSubset(data, subnet) # Match share server subnet self.assertEqual(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']) # Delete the subnets self.shares_v2_client.delete_subnet(share_network['id'], subnet['id'])
def resource_setup(cls): super(SecServicesMappingNegativeTest, cls).resource_setup() cls.sn = cls.create_share_network(cleanup_in_class=True, add_security_services=False) cls.share_net_info = (utils.share_network_get_default_subnet( cls.sn) if utils.share_network_subnets_are_supported() else cls.sn) cls.ss = cls.create_security_service(cleanup_in_class=True) cls.cl = cls.shares_client # create share type cls.share_type = cls.create_share_type() cls.share_type_id = cls.share_type['id']
def _create_secondary_share_network(self, old_share_network_id): old_share_network = self.shares_v2_client.get_share_network( old_share_network_id)['share_network'] share_net_info = ( utils.share_network_get_default_subnet(old_share_network) if utils.share_network_subnets_are_supported() else old_share_network) new_share_network = self.create_share_network( cleanup_in_class=True, neutron_net_id=share_net_info['neutron_net_id'], neutron_subnet_id=share_net_info['neutron_subnet_id']) return new_share_network['id']
def test_try_add_replica_nonexistent_subnet(self): # Create a new share network only for a specific az data = self.generate_share_network_data() subnet = utils.share_network_get_default_subnet(self.share_network) data['neutron_net_id'] = subnet['neutron_net_id'] data['neutron_subnet_id'] = subnet['neutron_subnet_id'] data['availability_zone'] = self.share_zone share_net = self.shares_v2_client.create_share_network( **data)['share_network'] share, instance_id = self._create_share_get_instance( share_network_id=share_net['id']) self.assertRaises(lib_exc.BadRequest, self.create_share_replica, share['id'], self.replica_zone)
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'])
def test_add_delete_share_replica_different_subnet(self): # Create new subnet in replica az subnet = utils.share_network_get_default_subnet(self.share_network) data = { 'neutron_net_id': subnet.get('neutron_net_id'), 'neutron_subnet_id': subnet.get('neutron_subnet_id'), 'share_network_id': self.sn_id, 'availability_zone': self.replica_zone, } subnet = self.create_share_network_subnet(**data) # Create the replica share_replica = self._verify_create_replica() # Delete the replica self.delete_share_replica(share_replica["id"]) # Delete subnet self.shares_v2_client.delete_subnet(self.sn_id, subnet['id'])
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)
def resource_setup(cls): super(ManageShareServersNegativeTest, cls).resource_setup() # create share type cls.st_name = data_utils.rand_name("manage-st-name") cls.extra_specs = { 'storage_protocol': CONF.share.capability_storage_protocol, 'driver_handles_share_servers': CONF.share.multitenancy_enabled, } cls.share_type = cls.create_share_type(name=cls.st_name, cleanup_in_class=True, extra_specs=cls.extra_specs) cls.original_share_network = cls.shares_v2_client.get_share_network( cls.shares_v2_client.share_network_id)['share_network'] cls.share_net_info = (utils.share_network_get_default_subnet( cls.original_share_network) if utils.share_network_subnets_are_supported() else cls.original_share_network)
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)
def test_gateway_mtu_neutron_net_id_with_neutron(self): self.create_share(share_type_id=self.share_type_id, cleanup_in_class=False) share_net_details = self.shares_v2_client.get_share_network( self.shares_v2_client.share_network_id)['share_network'] share_net_info = ( utils.share_network_get_default_subnet(share_net_details) if utils.share_network_subnets_are_supported() else share_net_details) if utils.is_microversion_supported('2.18'): subnet_details = self.subnets_client.show_subnet( share_net_info['neutron_subnet_id']) self.assertEqual(subnet_details['subnet']['gateway_ip'], share_net_info['gateway']) if utils.is_microversion_supported('2.20'): network_details = self.networks_client.show_network( share_net_info['neutron_net_id']) self.assertEqual(network_details['network']['mtu'], share_net_info['mtu']) self.assertEqual(network_details['network']['id'], share_net_info['neutron_net_id'])
def test_manage_share_server(self, add_subnet_field): # Starting from v2.51 share network spans to multiple subnets. if add_subnet_field and not utils.is_microversion_supported('2.51'): 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( self.shares_v2_client.share_network_id)['share_network'] share_net_info = ( utils.share_network_get_default_subnet(original_share_network) if utils.share_network_subnets_are_supported() else original_share_network) share_network = self.create_share_network( neutron_net_id=share_net_info['neutron_net_id'], neutron_subnet_id=share_net_info['neutron_subnet_id'], cleanup_in_class=True) az = params = None if add_subnet_field: # Get a compatible availability zone az = self.get_availability_zones_matching_share_type( self.share_type)[0] az_subnet = self.shares_v2_client.create_subnet( share_network['id'], neutron_net_id=share_network['neutron_net_id'], neutron_subnet_id=share_network['neutron_subnet_id'], availability_zone=az)['share_network_subnet'] params = {network_subnet: az_subnet['id']} # create share share = self.create_share(share_type_id=self.share_type['id'], share_network_id=share_network['id'], availability_zone=az) share = self.shares_v2_client.get_share(share['id'])['share'] el = self.shares_v2_client.list_share_export_locations( share['id'])['export_locations'] share['export_locations'] = el share_server = self.shares_v2_client.show_share_server( share['share_server_id'])['share_server'] keys = [ "id", "host", "project_id", "status", "share_network_name", "created_at", "updated_at", "backend_details", "is_auto_deletable", "identifier", ] if add_subnet_field: keys.append(network_subnet) # all expected keys are present for key in keys: self.assertIn(key, share_server) # 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 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) # Starting from microversion 2.49, any share server that has ever had # an unmanaged share will never be auto-deleted. share_server = self.shares_v2_client.show_share_server( share_server['id'])['share_server'] self.assertIs(False, share_server['is_auto_deletable']) # unmanage share server and manage it again self._unmanage_share_server_and_wait(share_server) managed_share_server = self._manage_share_server(share_server, fields=params) managed_share = self._manage_share( share, name="managed share that had ID %s" % share['id'], description="description for managed share", share_server_id=managed_share_server['id']) # check managed share server managed_share_server = self.shares_v2_client.show_share_server( managed_share_server['id'])['share_server'] # all expected keys are present in the managed share server for key in keys: self.assertIn(key, managed_share_server) # check that managed share server is used by the managed share self.assertEqual(managed_share['share_server_id'], managed_share_server['id']) # check that the managed share server is still not auto-deletable self.assertIs(False, managed_share_server["is_auto_deletable"]) # delete share self._delete_share_and_wait(managed_share) # delete share server self._delete_share_server_and_wait(managed_share_server['id']) if add_subnet_field: # delete the created subnet self.shares_v2_client.delete_subnet(share_network['id'], az_subnet['id'])
def test_share_server_migration_complete(self, new_share_network): """Test the share server migration complete.""" share_network_id = self.provide_share_network(self.shares_v2_client, self.networks_client) dest_share_network_id = share_network_id if new_share_network: src_share_network = self.shares_v2_client.get_share_network( share_network_id)['share_network'] share_net_info = ( utils.share_network_get_default_subnet(src_share_network)) dest_share_network_id = self.create_share_network( neutron_net_id=share_net_info['neutron_net_id'], neutron_subnet_id=share_net_info['neutron_subnet_id'], cleanup_in_class=False)['id'] share = self.create_share(share_protocol=self.protocol, share_type_id=self.share_type['id'], share_network_id=share_network_id, cleanup_in_class=False) share = self.shares_v2_client.get_share(share['id'])['share'] # Initial migration setup. share, src_server_id, dest_host, snapshot_id = self._setup_migration( share) preserve_snapshots = True if snapshot_id else False # Start share server migration. self.shares_v2_client.share_server_migration_start( src_server_id, dest_host, new_share_network_id=dest_share_network_id, preserve_snapshots=preserve_snapshots) expected_state = constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE waiters.wait_for_resource_status(self.shares_v2_client, src_server_id, expected_state, resource_name='share_server', status_attr='task_state') # Get for the destination share server. dest_server_id = self._get_share_server_destination_for_migration( src_server_id) dest_server = self.shares_v2_client.show_share_server( dest_server_id)['share_server'] self.assertEqual(dest_host, dest_server['host']) self.assertEqual(dest_share_network_id, dest_server['share_network_id']) expected_status = constants.STATUS_SERVER_MIGRATING self._validate_state_of_resources(share, expected_status, snapshot_id) # Share server migration complete. self.shares_v2_client.share_server_migration_complete(src_server_id) # It's necessary wait for the destination server went to active status. expected_status = constants.SERVER_STATE_ACTIVE waiters.wait_for_resource_status(self.shares_v2_client, dest_server_id, expected_status, resource_name='share_server') # Validate the share server migration complete. share = self.shares_v2_client.get_share(share['id'])['share'] self._validate_share_server_migration_complete( share, dest_host, dest_server_id, snapshot_id=snapshot_id, share_network_id=dest_share_network_id) # Source share server is only deleted after Wallaby release (2.63). if utils.is_microversion_gt(CONF.share.max_api_microversion, "2.63"): self.admin_shares_client.wait_for_resource_deletion( server_id=src_server_id)
def test_delete_contains_shares(self): # 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'] share_net_info = ( utils.share_network_get_default_subnet(original_share_network)) share_network = self.create_share_network( neutron_net_id=share_net_info['neutron_net_id'], neutron_subnet_id=share_net_info['neutron_subnet_id'], ) share_network = self.shares_v2_client.get_share_network( share_network['id'] )['share_network'] share_network_id = share_network['id'] default_subnet = share_network['share_network_subnets'][0] # Generate subnet data data = {'neutron_net_id': default_subnet['neutron_net_id'], 'neutron_subnet_id': default_subnet['neutron_subnet_id'], 'share_network_id': share_network_id, 'availability_zone': az} # Create a new subnet in the desired az subnet = self.create_share_network_subnet(**data) args = {'share_network_id': share_network_id, 'share_type_id': self.share_type['id'], 'availability_zone': az} # Create a share into the share network share = self.shares_v2_client.create_share(**args)['share'] waiters.wait_for_resource_status( self.shares_v2_client, share['id'], constants.STATUS_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'] # Match share server subnet 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, self.shares_v2_client.delete_subnet, share_network_id, subnet['id']) # Assert that the user cannot delete a share-network that contain # shares self.assertRaises(lib_exc.Conflict, self.shares_v2_client.delete_share_network, share_network_id) # Cleanups self.shares_client.delete_share(share['id']) self.shares_v2_client.wait_for_resource_deletion(share_id=share["id"]) self._delete_share_server_and_wait(share['share_server_id']) self.shares_v2_client.delete_subnet(share_network_id, subnet['id'])
def test_delete_contains_unmanaged_share_servers(self): # Get a compatible availability zone az = self.get_availability_zones_matching_share_type( self.share_type)[0] share_network = self.shares_v2_client.get_share_network( self.shares_v2_client.share_network_id )['share_network'] share_network_id = share_network['id'] subnet = utils.share_network_get_default_subnet(share_network) # Generate subnet data data = {'neutron_net_id': subnet['neutron_net_id'], 'neutron_subnet_id': subnet['neutron_subnet_id'], 'share_network_id': share_network_id, 'availability_zone': az} # Create a new subnet in the desired az subnet = self.create_share_network_subnet(**data) args = {'share_network_id': share_network_id, 'share_type_id': self.share_type['id'], 'availability_zone': az} # Create a share into the share network share = self.shares_v2_client.create_share(**args)['share'] waiters.wait_for_resource_status( self.shares_v2_client, share['id'], constants.STATUS_AVAILABLE) share = self.shares_v2_client.get_share(share['id'])['share'] # Gets the export locations to be used in the future el = self.shares_v2_client.list_share_export_locations( share['id'])['export_locations'] share['export_locations'] = el # Unmanages the share to make the share server become is_auto # deletable=False self._unmanage_share_and_wait(share) # Assert that the user cannot delete a subnet that contains share # servers which may have unmanaged stuff self.assertRaises(lib_exc.Conflict, self.shares_v2_client.delete_subnet, share_network_id, subnet['id']) # Manages the share again to start cleaning up the test stuff managed_share = self.shares_v2_client.manage_share( service_host=share['host'], export_path=share['export_locations'][0], protocol=share['share_proto'], share_type_id=self.share_type['id'], name='share_to_be_deleted', description='share managed to be deleted', share_server_id=share['share_server_id'] )['share'] # Do some necessary cleanup waiters.wait_for_resource_status( self.shares_v2_client, managed_share['id'], constants.STATUS_AVAILABLE) self.shares_client.delete_share(managed_share['id']) self.shares_v2_client.wait_for_resource_deletion( share_id=managed_share["id"]) self._delete_share_server_and_wait(share['share_server_id']) self.shares_v2_client.delete_subnet(share_network_id, subnet['id'])
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'])
def test_create_share_on_share_network_with_multiple_subnets( self, create_share_with_az): compatible_azs = self.get_availability_zones_matching_share_type( self.share_type) if len(compatible_azs) < 2: 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'] share_net_info = ( utils.share_network_get_default_subnet(original_share_network)) share_network = self.create_share_network( neutron_net_id=share_net_info['neutron_net_id'], neutron_subnet_id=share_net_info['neutron_subnet_id'], ) share_network = self.shares_v2_client.get_share_network( share_network['id'])['share_network'] default_subnet = share_network['share_network_subnets'][0] # Save one availability zone to remain associated with default subnet destination_az = compatible_azs.pop() if not create_share_with_az: destination_az = None new_subnets = [] data = { "neutron_net_id": share_net_info['neutron_net_id'], "neutron_subnet_id": share_net_info['neutron_subnet_id'], 'share_network_id': share_network['id'], } for availability_zone in compatible_azs: # update availability zone data['availability_zone'] = availability_zone # create a new share network subnet subnet = self.create_share_network_subnet(**data) new_subnets.append(subnet) # Create a new share in the selected availability zone share = self.create_share(share_type_id=self.share_type_id, share_network_id=share_network['id'], availability_zone=destination_az) # The 'status' of the share returned by the create API must be # set and have value either 'creating' or 'available' (if share # creation is really fast as in case of Dummy driver). 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'] # If no availability zone was provided during share creation, it is # expected that the Scheduler selects one of the compatible backends to # place the share. The destination availability zone may or may not # have an specific share network subnet. expected_subnet_id = (next( (subnet['id'] for subnet in new_subnets if subnet['availability_zone'] == share['availability_zone']), default_subnet['id'])) # Default subnet was created during share network creation self.assertIsNone(default_subnet['availability_zone']) # Match share server subnet 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']) # 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 for subnet in new_subnets: self.shares_v2_client.delete_subnet(share_network['id'], subnet['id'])