manila/manila/tests/test_network.py
Rodrigo Barbieri d877b61c5e Add manage/unmanage of shares in DHSS=True
This patch adds Manage/Unmanage of share servers in
Manila. It also updates the Manage Share API to accept
a "share_server_id" parameter, and updates Unmanage
of Share and Snapshots API to allow unmanaging of
shares and snapshots in DHSS=True.

Managed share servers are not deleted automatically
by manila, and if a single share is unmanaged in
DHSS=True, the respective share server will not be
deleted automatically as well.

Managing share servers require that the driver
implements 2 functions:
- get_share_server_network_info: obtain IPs from
  share server.
- manage_server: perform required operations to
  manage and return dict of backend_details.

Unmanaging share servers require that the driver
overrides unmanage_server function.

The IPs obtained from the backend are validated
by the Network plugin, so ports with the exact
IPs must exist in the subnet and admin subnet
associated with the share network specified
when managing the share server (unless
StandaloneNetworkPlugin is used).

It is recommended to rename the backend resource
if possible when managing the share server, to
prevent issues with re-managing a share server
that has already been managed.

This patch bumps the API microversion to 2.49.

APIImpact
DocImpact

Depends-On: I17c74b2aa242918188eeff368232c762a4b31093
Partially-implements: bp manage-unmanage-with-share-servers
Change-Id: I108961e7436ba13550ef2b8f02079c6e599a6166
2019-03-05 16:03:29 -03:00

206 lines
6.9 KiB
Python

# Copyright 2015 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.
import ddt
from oslo_config import cfg
from oslo_utils import importutils
from manila import exception
from manila import network
from manila import test
CONF = cfg.CONF
@ddt.ddt
class APITestCase(test.TestCase):
def setUp(self):
super(APITestCase, self).setUp()
self.mock_object(importutils, 'import_class')
def test_init_api_with_default_config_group_name(self):
network.API()
importutils.import_class.assert_called_once_with(
CONF.network_api_class)
importutils.import_class.return_value.assert_called_once_with(
config_group_name=None, label='user')
def test_init_api_with_custom_config_group_name(self):
group_name = 'FOO_GROUP_NAME'
network.API(config_group_name=group_name)
importutils.import_class.assert_called_once_with(
getattr(CONF, group_name).network_api_class)
importutils.import_class.return_value.assert_called_once_with(
config_group_name=group_name, label='user')
def test_init_api_with_custom_config_group_name_and_label(self):
group_name = 'FOO_GROUP_NAME'
label = 'custom_label'
network.API(config_group_name=group_name, label=label)
importutils.import_class.assert_called_once_with(
getattr(CONF, group_name).network_api_class)
importutils.import_class.return_value.assert_called_once_with(
config_group_name=group_name, label=label)
@ddt.ddt
class NetworkBaseAPITestCase(test.TestCase):
def setUp(self):
super(NetworkBaseAPITestCase, self).setUp()
self.db_driver = 'fake_driver'
self.mock_object(importutils, 'import_module')
def test_inherit_network_base_api_no_redefinitions(self):
class FakeNetworkAPI(network.NetworkBaseAPI):
pass
self.assertRaises(TypeError, FakeNetworkAPI)
def test_inherit_network_base_api_deallocate_not_redefined(self):
class FakeNetworkAPI(network.NetworkBaseAPI):
def allocate_network(self, *args, **kwargs):
pass
def manage_network_allocations(
self, context, allocations, share_server,
share_network=None):
pass
def unmanage_network_allocations(self, context, share_server_id):
pass
self.assertRaises(TypeError, FakeNetworkAPI)
def test_inherit_network_base_api_allocate_not_redefined(self):
class FakeNetworkAPI(network.NetworkBaseAPI):
def deallocate_network(self, *args, **kwargs):
pass
def manage_network_allocations(
self, context, allocations, share_server,
share_network=None):
pass
def unmanage_network_allocations(self, context, share_server_id):
pass
self.assertRaises(TypeError, FakeNetworkAPI)
def test_inherit_network_base_api(self):
class FakeNetworkAPI(network.NetworkBaseAPI):
def allocate_network(self, *args, **kwargs):
pass
def deallocate_network(self, *args, **kwargs):
pass
def manage_network_allocations(
self, context, allocations, share_server,
share_network=None):
pass
def unmanage_network_allocations(self, context, share_server_id):
pass
result = FakeNetworkAPI()
self.assertTrue(hasattr(result, '_verify_share_network'))
self.assertTrue(hasattr(result, 'allocate_network'))
self.assertTrue(hasattr(result, 'deallocate_network'))
def test__verify_share_network_ok(self):
class FakeNetworkAPI(network.NetworkBaseAPI):
def allocate_network(self, *args, **kwargs):
pass
def deallocate_network(self, *args, **kwargs):
pass
def manage_network_allocations(
self, context, allocations, share_server,
share_network=None):
pass
def unmanage_network_allocations(self, context, share_server_id):
pass
result = FakeNetworkAPI()
result._verify_share_network('foo_id', {'id': 'bar_id'})
def test__verify_share_network_fail(self):
class FakeNetworkAPI(network.NetworkBaseAPI):
def allocate_network(self, *args, **kwargs):
pass
def deallocate_network(self, *args, **kwargs):
pass
def manage_network_allocations(
self, context, allocations, share_server,
share_network=None):
pass
def unmanage_network_allocations(self, context, share_server_id):
pass
result = FakeNetworkAPI()
self.assertRaises(
exception.NetworkBadConfigurationException,
result._verify_share_network, 'foo_id', None)
@ddt.data((True, False, set([6])), (False, True, set([4])),
(True, True, set([4, 6])), (False, False, set()))
@ddt.unpack
def test_enabled_ip_versions(self, network_plugin_ipv6_enabled,
network_plugin_ipv4_enabled,
enable_ip_versions):
class FakeNetworkAPI(network.NetworkBaseAPI):
def allocate_network(self, *args, **kwargs):
pass
def deallocate_network(self, *args, **kwargs):
pass
def manage_network_allocations(
self, context, allocations, share_server,
share_network=None):
pass
def unmanage_network_allocations(self, context, share_server_id):
pass
network.CONF.set_default('network_plugin_ipv6_enabled',
network_plugin_ipv6_enabled)
network.CONF.set_default('network_plugin_ipv4_enabled',
network_plugin_ipv4_enabled)
result = FakeNetworkAPI()
if enable_ip_versions:
self.assertTrue(hasattr(result, 'enabled_ip_versions'))
self.assertEqual(enable_ip_versions, result.enabled_ip_versions)
else:
self.assertRaises(exception.NetworkBadConfigurationException,
getattr, result, 'enabled_ip_versions')