Enable Manila multi-SVM driver on NetApp cDOT 8.3

cDOT 8.3 includes numerous new networking features, at least one
of which (broadcast domains) must be used when creating network
interfaces.  This patch enables the multi-SVM driver on cDOT 8.3
by ensuring that each physical port selected to host share server
logical interfaces (LIFs) is a member of a broadcast domain.
A couple of other API tweaks are included that also impeded
operation on cDOT 8.3.

Closes-Bug: #1425754
Change-Id: Ibe92aee217462bce06485e195b930f2fdf43fcc0
This commit is contained in:
Clinton Knight 2015-03-20 17:31:42 -04:00
parent a778199f01
commit dab1e3bc14
8 changed files with 532 additions and 82 deletions

View File

@ -42,6 +42,7 @@ EVOLNOTCLONE = '13170'
EVOL_NOT_MOUNTED = '14716'
ESIS_CLONE_NOT_LICENSED = '14956'
EOBJECTNOTFOUND = '15661'
E_VIFMGR_PORT_ALREADY_ASSIGNED_TO_BROADCAST_DOMAIN = '18605'
class NaServer(object):

View File

@ -47,6 +47,10 @@ class NetAppBaseClient(object):
minor = res.get_child_content('minor-version')
return major, minor
def _init_features(self):
"""Set up the repository of available Data ONTAP features."""
self.features = Features()
def check_is_naelement(self, elem):
"""Checks if object is instance of NaElement."""
if not isinstance(elem, netapp_api.NaElement):
@ -74,3 +78,19 @@ class NetAppBaseClient(object):
def send_ems_log_message(self, message_dict):
"""Sends a message to the Data ONTAP EMS log."""
raise NotImplementedError()
class Features(object):
def __init__(self):
self.defined_features = set()
def add_feature(self, name, supported=True):
if not isinstance(supported, bool):
raise TypeError("Feature value must be a bool type.")
self.defined_features.add(name)
setattr(self, name, supported)
def __getattr__(self, name):
# NOTE(cknight): Needed to keep pylint happy.
raise AttributeError

View File

@ -32,6 +32,8 @@ from manila.share.drivers.netapp import utils as na_utils
LOG = log.getLogger(__name__)
DELETED_PREFIX = 'deleted_manila_'
DEFAULT_IPSPACE = 'Default'
DEFAULT_BROADCAST_DOMAIN = 'OpenStack'
class NetAppCmodeClient(client_base.NetAppBaseClient):
@ -46,6 +48,19 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
(major, minor) = self.get_ontapi_version(cached=False)
self.connection.set_api_version(major, minor)
self._init_features()
def _init_features(self):
"""Initialize cDOT feature support map."""
super(NetAppCmodeClient, self)._init_features()
ontapi_version = self.get_ontapi_version(cached=True)
ontapi_1_30 = ontapi_version >= (1, 30)
self.features.add_feature('BROADCAST_DOMAINS', supported=ontapi_1_30)
self.features.add_feature('IPSPACES', supported=ontapi_1_30)
self.features.add_feature('SUBNETS', supported=ontapi_1_30)
def _invoke_vserver_api(self, na_element, vserver):
server = copy.copy(self.connection)
server.set_vserver(vserver)
@ -265,7 +280,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
},
},
'desired-attributes': {
'node-details-info': {
'net-port-info': {
'port': None,
'node': None,
'operational-speed': None,
@ -350,6 +365,9 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
self._create_vlan(node, port, vlan)
home_port_name = '%(port)s-%(tag)s' % {'port': port, 'tag': vlan}
if self.features.BROADCAST_DOMAINS:
self._ensure_broadcast_domain_for_port(node, home_port_name)
interface_name = (lif_name_template %
{'node': node, 'net_allocation_id': allocation_id})
@ -393,6 +411,104 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
msg_args = {'vlan': vlan, 'port': port, 'err_msg': e.message}
raise exception.NetAppException(msg % msg_args)
@na_utils.trace
def _ensure_broadcast_domain_for_port(self, node, port,
domain=DEFAULT_BROADCAST_DOMAIN,
ipspace=DEFAULT_IPSPACE):
"""Ensure a port is in a broadcast domain. Create one if necessary."""
if self._get_broadcast_domain_for_port(node, port):
return
if not self._broadcast_domain_exists(domain, ipspace):
self._create_broadcast_domain(domain, ipspace)
self._add_port_to_broadcast_domain(node, port, domain, ipspace)
@na_utils.trace
def _get_broadcast_domain_for_port(self, node, port):
"""Get broadcast domain for a specific port."""
api_args = {
'query': {
'net-port-info': {
'node': node,
'port': port,
},
},
'desired-attributes': {
'net-port-info': {
'broadcast-domain': None,
},
},
}
result = self.send_request('net-port-get-iter', api_args)
net_port_info_list = result.get_child_by_name(
'attributes-list') or netapp_api.NaElement('none')
port_info = net_port_info_list.get_children()
if not port_info:
msg = _('Could not find port %(port)s on node %(node)s.')
msg_args = {'port': port, 'node': node}
raise exception.NetAppException(msg % msg_args)
return port_info[0].get_child_content('broadcast-domain')
@na_utils.trace
def _broadcast_domain_exists(self, domain, ipspace):
"""Check if a broadcast domain exists."""
api_args = {
'query': {
'net-port-broadcast-domain-info': {
'ipspace': ipspace,
'broadcast-domain': domain,
},
},
'desired-attributes': {
'net-port-broadcast-domain-info': None,
},
}
result = self.send_request('net-port-broadcast-domain-get-iter',
api_args)
return self._has_records(result)
@na_utils.trace
def _create_broadcast_domain(self, domain, ipspace, mtu=1500):
"""Create a broadcast domain."""
api_args = {
'ipspace': ipspace,
'broadcast-domain': domain,
'mtu': mtu,
}
self.send_request('net-port-broadcast-domain-create', api_args)
@na_utils.trace
def _add_port_to_broadcast_domain(self, node, port, domain, ipspace):
qualified_port_name = ':'.join([node, port])
try:
api_args = {
'ipspace': ipspace,
'broadcast-domain': domain,
'ports': {
'net-qualified-port-name': qualified_port_name,
}
}
self.send_request('net-port-broadcast-domain-add-ports', api_args)
except netapp_api.NaApiError as e:
if e.code == (netapp_api.
E_VIFMGR_PORT_ALREADY_ASSIGNED_TO_BROADCAST_DOMAIN):
LOG.debug('Port %(port)s already exists in broadcast domain '
'%(domain)s', {'port': port, 'domain': domain})
else:
msg = _('Failed to add port %(port)s to broadcast domain '
'%(domain)s. %(err_msg)s')
msg_args = {
'port': qualified_port_name,
'domain': domain,
'err_msg': e.message,
}
raise exception.NetAppException(msg % msg_args)
@na_utils.trace
def network_interface_exists(self, vserver_name, node, port, ip, netmask,
vlan):
@ -595,12 +711,14 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
def setup_security_services(self, security_services, vserver_client,
vserver_name):
api_args = {
'name-mapping-switch': {
'nmswitch': 'ldap,file',
},
'name-server-switch': {
'nsswitch': 'ldap,file',
},
'name-mapping-switch': [
{'nmswitch': 'ldap'},
{'nmswitch': 'file'}
],
'name-server-switch': [
{'nsswitch': 'ldap'},
{'nsswitch': 'file'}
],
'vserver-name': vserver_name,
}
self.send_request('vserver-modify', api_args)

View File

@ -42,8 +42,6 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
@na_utils.trace
def check_for_setup_error(self):
self._check_data_ontap_version()
if self._have_cluster_creds:
if self.configuration.netapp_vserver:
msg = _LW('Vserver is specified in the configuration. This is '
@ -65,17 +63,6 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
super(NetAppCmodeMultiSVMFileStorageLibrary, self).\
check_for_setup_error()
def _check_data_ontap_version(self):
# Temporary check to indicate that the Kilo multi-SVM driver does not
# support cDOT 8.3 or higher.
ontapi_version = self._client.get_ontapi_version()
if ontapi_version >= (1, 30):
msg = _('Clustered Data ONTAP 8.3.0 or higher is not '
'supported by this version of the driver when the '
'configuration option driver_handles_share_servers '
'is set to True.')
raise exception.NetAppException(msg)
@na_utils.trace
def _get_vserver(self, share_server=None):

View File

@ -60,6 +60,9 @@ NETMASK = '255.255.255.0'
NET_ALLOCATION_ID = 'fake_allocation_id'
LIF_NAME_TEMPLATE = 'os_%(net_allocation_id)s'
LIF_NAME = LIF_NAME_TEMPLATE % {'net_allocation_id': NET_ALLOCATION_ID}
IPSPACE = 'fake_ipspace'
BROADCAST_DOMAIN = 'fake_domain'
MTU = 9000
EMS_MESSAGE = {
'computer-name': 'fake_host',
@ -431,6 +434,43 @@ SORTED_PORTS_ALL_SPEEDS = (
{'node': NODE_NAME, 'port': 'port7'},
)
NET_PORT_GET_ITER_BROADCAST_DOMAIN_RESPONSE = etree.XML("""
<results status="passed">
<attributes-list>
<net-port-info>
<broadcast-domain>%(domain)s</broadcast-domain>
<node>%(node)s</node>
<port>%(port)s</port>
</net-port-info>
</attributes-list>
<num-records>1</num-records>
</results>
""" % {'domain': BROADCAST_DOMAIN, 'node': NODE_NAME, 'port': PORT})
NET_PORT_GET_ITER_BROADCAST_DOMAIN_MISSING_RESPONSE = etree.XML("""
<results status="passed">
<attributes-list>
<net-port-info>
<node>%(node)s</node>
<port>%(port)s</port>
</net-port-info>
</attributes-list>
<num-records>1</num-records>
</results>
""" % {'node': NODE_NAME, 'port': PORT})
NET_PORT_BROADCAST_DOMAIN_GET_ITER_RESPONSE = etree.XML("""
<results status="passed">
<attributes-list>
<net-port-broadcast-domain-info>
<broadcast-domain>%(domain)s</broadcast-domain>
<ipspace>%(ipspace)s</ipspace>
</net-port-broadcast-domain-info>
</attributes-list>
<num-records>1</num-records>
</results>
""" % {'domain': BROADCAST_DOMAIN, 'ipspace': IPSPACE})
NET_INTERFACE_GET_ITER_RESPONSE = etree.XML("""
<results status="passed">
<attributes-list>

View File

@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import ddt
import mock
from oslo_log import log
@ -56,6 +57,12 @@ class NetAppBaseClientTestCase(test.TestCase):
self.assertEqual(1, major)
self.assertEqual(20, minor)
def test_init_features(self):
self.client._init_features()
self.assertSetEqual(set(), self.client.features.defined_features)
def test_check_is_naelement(self):
element = netapp_api.NaElement('name')
@ -121,4 +128,39 @@ class NetAppBaseClientTestCase(test.TestCase):
self.assertRaises(NotImplementedError,
self.client.send_ems_log_message,
{})
{})
@ddt.ddt
class FeaturesTestCase(test.TestCase):
def setUp(self):
super(FeaturesTestCase, self).setUp()
self.features = client_base.Features()
def test_init(self):
self.assertSetEqual(set(), self.features.defined_features)
def test_add_feature_default(self):
self.features.add_feature('FEATURE_1')
self.assertTrue(self.features.FEATURE_1)
self.assertIn('FEATURE_1', self.features.defined_features)
@ddt.data(True, False)
def test_add_feature(self, value):
self.features.add_feature('FEATURE_2', value)
self.assertEqual(value, self.features.FEATURE_2)
self.assertIn('FEATURE_2', self.features.defined_features)
@ddt.data('True', 'False', 0, 1, 1.0, None, [], {}, (True,))
def test_add_feature_type_error(self, value):
self.assertRaises(TypeError,
self.features.add_feature,
'FEATURE_3',
value)
self.assertNotIn('FEATURE_3', self.features.defined_features)
def test_get_attr_missing(self):
self.assertRaises(AttributeError, getattr, self.features, 'FEATURE_4')

View File

@ -63,6 +63,31 @@ class NetAppClientCmodeTestCase(test.TestCase):
def _mock_api_error(self, code='fake'):
return mock.Mock(side_effect=netapp_api.NaApiError(code=code))
def test_init_features_ontapi_1_21(self):
self.mock_object(client_base.NetAppBaseClient,
'get_ontapi_version',
mock.Mock(return_value=(1, 21)))
self.client._init_features()
self.assertFalse(self.client.features.BROADCAST_DOMAINS)
self.assertFalse(self.client.features.IPSPACES)
self.assertFalse(self.client.features.SUBNETS)
@ddt.data((1, 30), (1, 40), (2, 0))
def test_init_features_ontapi_1_30(self, ontapi_version):
self.mock_object(client_base.NetAppBaseClient,
'get_ontapi_version',
mock.Mock(return_value=ontapi_version))
self.client._init_features()
self.assertTrue(self.client.features.BROADCAST_DOMAINS)
self.assertTrue(self.client.features.IPSPACES)
self.assertTrue(self.client.features.SUBNETS)
def test_invoke_vserver_api(self):
self.client._invoke_vserver_api('fake-api', 'fake_vserver')
@ -487,7 +512,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
},
},
'desired-attributes': {
'node-details-info': {
'net-port-info': {
'port': None,
'node': None,
'operational-speed': None,
@ -559,8 +584,14 @@ class NetAppClientCmodeTestCase(test.TestCase):
self.assertListEqual([], result)
def test_create_network_interface(self):
@ddt.data((True, True), (True, False), (False, True), (False, False))
@ddt.unpack
def test_create_network_interface(self, broadcast_domains_supported,
use_vlans):
self.client.features.add_feature('BROADCAST_DOMAINS',
broadcast_domains_supported)
self.mock_object(self.client, '_ensure_broadcast_domain_for_port')
self.mock_object(self.client, '_create_vlan')
self.mock_object(self.client, 'send_request')
@ -572,50 +603,32 @@ class NetAppClientCmodeTestCase(test.TestCase):
{'data-protocol': 'cifs'}
],
'home-node': fake.NODE_NAME,
'home-port': fake.VLAN_PORT,
'home-port': fake.VLAN_PORT if use_vlans else fake.PORT,
'netmask': fake.NETMASK,
'interface-name': fake.LIF_NAME,
'role': 'data',
'vserver': fake.VSERVER_NAME,
}
self.client.create_network_interface(fake.IP_ADDRESS, fake.NETMASK,
fake.VLAN, fake.NODE_NAME,
fake.PORT, fake.VSERVER_NAME,
fake.VLAN if use_vlans else None,
fake.NODE_NAME, fake.PORT,
fake.VSERVER_NAME,
fake.NET_ALLOCATION_ID,
fake.LIF_NAME_TEMPLATE)
self.client._create_vlan.assert_called_with(fake.NODE_NAME, fake.PORT,
fake.VLAN)
if use_vlans:
self.client._create_vlan.assert_called_with(
fake.NODE_NAME, fake.PORT, fake.VLAN)
else:
self.assertFalse(self.client._create_vlan.called)
self.client.send_request.assert_has_calls([
mock.call('net-interface-create', lif_create_args)])
if broadcast_domains_supported:
self.client._ensure_broadcast_domain_for_port.assert_called_with(
fake.NODE_NAME, fake.VLAN_PORT if use_vlans else fake.PORT)
else:
self.assertFalse(
self.client._ensure_broadcast_domain_for_port.called)
def test_create_network_interface_no_vlan(self):
self.mock_object(self.client, '_create_vlan')
self.mock_object(self.client, 'send_request')
lif_create_args = {
'address': fake.IP_ADDRESS,
'administrative-status': 'up',
'data-protocols': [
{'data-protocol': 'nfs'},
{'data-protocol': 'cifs'}
],
'home-node': fake.NODE_NAME,
'home-port': fake.PORT,
'netmask': fake.NETMASK,
'interface-name': fake.LIF_NAME,
'role': 'data',
'vserver': fake.VSERVER_NAME,
}
self.client.create_network_interface(fake.IP_ADDRESS, fake.NETMASK,
None, fake.NODE_NAME,
fake.PORT, fake.VSERVER_NAME,
fake.NET_ALLOCATION_ID,
fake.LIF_NAME_TEMPLATE)
self.assertFalse(self.client._create_vlan.called)
self.client.send_request.assert_has_calls([
mock.call('net-interface-create', lif_create_args)])
@ -665,6 +678,229 @@ class NetAppClientCmodeTestCase(test.TestCase):
fake.PORT,
fake.VLAN)
def test_ensure_broadcast_domain_for_port_has_domain(self):
self.mock_object(self.client,
'_get_broadcast_domain_for_port',
mock.Mock(return_value=fake.BROADCAST_DOMAIN))
self.mock_object(self.client, '_broadcast_domain_exists')
self.mock_object(self.client, '_create_broadcast_domain')
self.mock_object(self.client, '_add_port_to_broadcast_domain')
self.client._ensure_broadcast_domain_for_port(fake.NODE_NAME,
fake.PORT)
self.client._get_broadcast_domain_for_port.assert_has_calls([
mock.call(fake.NODE_NAME, fake.PORT)])
self.assertFalse(self.client._broadcast_domain_exists.called)
self.assertFalse(self.client._create_broadcast_domain.called)
self.assertFalse(self.client._add_port_to_broadcast_domain.called)
def test_ensure_broadcast_domain_for_port_domain_not_found(self):
self.mock_object(self.client,
'_get_broadcast_domain_for_port',
mock.Mock(return_value=None))
self.mock_object(self.client,
'_broadcast_domain_exists',
mock.Mock(return_value=False))
self.mock_object(self.client, '_create_broadcast_domain')
self.mock_object(self.client, '_add_port_to_broadcast_domain')
self.client._ensure_broadcast_domain_for_port(
fake.NODE_NAME, fake.PORT, domain=fake.BROADCAST_DOMAIN,
ipspace=fake.IPSPACE)
self.client._get_broadcast_domain_for_port.assert_has_calls([
mock.call(fake.NODE_NAME, fake.PORT)])
self.client._broadcast_domain_exists.assert_has_calls([
mock.call(fake.BROADCAST_DOMAIN, fake.IPSPACE)])
self.client._create_broadcast_domain.assert_has_calls([
mock.call(fake.BROADCAST_DOMAIN, fake.IPSPACE)])
self.client._add_port_to_broadcast_domain.assert_has_calls([
mock.call(fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN,
fake.IPSPACE)])
def test_ensure_broadcast_domain_for_port_domain_found(self):
self.mock_object(self.client,
'_get_broadcast_domain_for_port',
mock.Mock(return_value=None))
self.mock_object(self.client,
'_broadcast_domain_exists',
mock.Mock(return_value=True))
self.mock_object(self.client, '_create_broadcast_domain')
self.mock_object(self.client, '_add_port_to_broadcast_domain')
self.client._ensure_broadcast_domain_for_port(
fake.NODE_NAME, fake.PORT, domain=fake.BROADCAST_DOMAIN,
ipspace=fake.IPSPACE)
self.client._get_broadcast_domain_for_port.assert_has_calls([
mock.call(fake.NODE_NAME, fake.PORT)])
self.client._broadcast_domain_exists.assert_has_calls([
mock.call(fake.BROADCAST_DOMAIN, fake.IPSPACE)])
self.assertFalse(self.client._create_broadcast_domain.called)
self.client._add_port_to_broadcast_domain.assert_has_calls([
mock.call(fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN,
fake.IPSPACE)])
def test_get_broadcast_domain_for_port(self):
api_response = netapp_api.NaElement(
fake.NET_PORT_GET_ITER_BROADCAST_DOMAIN_RESPONSE)
self.mock_object(self.client,
'send_request',
mock.Mock(return_value=api_response))
net_port_get_iter_args = {
'query': {
'net-port-info': {
'node': fake.NODE_NAME,
'port': fake.PORT,
},
},
'desired-attributes': {
'net-port-info': {
'broadcast-domain': None,
},
},
}
result = self.client._get_broadcast_domain_for_port(fake.NODE_NAME,
fake.PORT)
self.client.send_request.assert_has_calls([
mock.call('net-port-get-iter', net_port_get_iter_args)])
self.assertEqual(fake.BROADCAST_DOMAIN, result)
def test_get_broadcast_domain_for_port_port_not_found(self):
api_response = netapp_api.NaElement(
fake.NO_RECORDS_RESPONSE)
self.mock_object(self.client,
'send_request',
mock.Mock(return_value=api_response))
self.assertRaises(exception.NetAppException,
self.client._get_broadcast_domain_for_port,
fake.NODE_NAME,
fake.PORT)
def test_get_broadcast_domain_for_port_domain_not_found(self):
api_response = netapp_api.NaElement(
fake.NET_PORT_GET_ITER_BROADCAST_DOMAIN_MISSING_RESPONSE)
self.mock_object(self.client,
'send_request',
mock.Mock(return_value=api_response))
result = self.client._get_broadcast_domain_for_port(fake.NODE_NAME,
fake.PORT)
self.assertIsNone(result)
def test_broadcast_domain_exists(self):
api_response = netapp_api.NaElement(
fake.NET_PORT_BROADCAST_DOMAIN_GET_ITER_RESPONSE)
self.mock_object(self.client,
'send_request',
mock.Mock(return_value=api_response))
result = self.client._broadcast_domain_exists(fake.BROADCAST_DOMAIN,
fake.IPSPACE)
net_port_broadcast_domain_get_iter_args = {
'query': {
'net-port-broadcast-domain-info': {
'ipspace': fake.IPSPACE,
'broadcast-domain': fake.BROADCAST_DOMAIN,
},
},
'desired-attributes': {
'net-port-broadcast-domain-info': None,
},
}
self.client.send_request.assert_has_calls([
mock.call('net-port-broadcast-domain-get-iter',
net_port_broadcast_domain_get_iter_args)])
self.assertTrue(result)
def test_broadcast_domain_exists_not_found(self):
api_response = netapp_api.NaElement(
fake.NO_RECORDS_RESPONSE)
self.mock_object(self.client,
'send_request',
mock.Mock(return_value=api_response))
result = self.client._broadcast_domain_exists(fake.BROADCAST_DOMAIN,
fake.IPSPACE)
self.assertFalse(result)
def test_create_broadcast_domain(self):
self.mock_object(self.client, 'send_request')
result = self.client._create_broadcast_domain(fake.BROADCAST_DOMAIN,
fake.IPSPACE,
mtu=fake.MTU)
net_port_broadcast_domain_create_args = {
'ipspace': fake.IPSPACE,
'broadcast-domain': fake.BROADCAST_DOMAIN,
'mtu': fake.MTU,
}
self.assertIsNone(result)
self.client.send_request.assert_has_calls([
mock.call('net-port-broadcast-domain-create',
net_port_broadcast_domain_create_args)])
def test_add_port_to_broadcast_domain(self):
self.mock_object(self.client, 'send_request')
add_port_to_broadcast_domain_args = {
'ipspace': fake.IPSPACE,
'broadcast-domain': fake.BROADCAST_DOMAIN,
'ports': {
'net-qualified-port-name': ':'.join([fake.NODE_NAME,
fake.VLAN_PORT])
}
}
result = self.client._add_port_to_broadcast_domain(
fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN,
fake.IPSPACE)
self.assertIsNone(result)
self.client.send_request.assert_has_calls([
mock.call('net-port-broadcast-domain-add-ports',
add_port_to_broadcast_domain_args)])
def test_add_port_to_broadcast_domain_already_present(self):
self.mock_object(self.client, 'send_request', self._mock_api_error(
code=netapp_api.
E_VIFMGR_PORT_ALREADY_ASSIGNED_TO_BROADCAST_DOMAIN))
result = self.client._add_port_to_broadcast_domain(
fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN,
fake.IPSPACE)
self.assertIsNone(result)
def test_add_port_to_broadcast_domain_api_error(self):
self.mock_object(self.client, 'send_request', self._mock_api_error())
self.assertRaises(exception.NetAppException,
self.client._add_port_to_broadcast_domain,
fake.NODE_NAME,
fake.VLAN_PORT,
fake.BROADCAST_DOMAIN,
fake.IPSPACE)
def test_network_interface_exists(self):
api_response = netapp_api.NaElement(
@ -1029,11 +1265,16 @@ class NetAppClientCmodeTestCase(test.TestCase):
fake.VSERVER_NAME)
vserver_modify_args = {
'name-mapping-switch': {'nmswitch': 'ldap,file'},
'name-server-switch': {'nsswitch': 'ldap,file'},
'name-mapping-switch': [
{'nmswitch': 'ldap'},
{'nmswitch': 'file'},
],
'name-server-switch': [
{'nsswitch': 'ldap'},
{'nsswitch': 'file'},
],
'vserver-name': fake.VSERVER_NAME
}
self.client.send_request.assert_has_calls([
mock.call('vserver-modify', vserver_modify_args)])
self.vserver_client.configure_ldap.assert_has_calls([
@ -1049,11 +1290,16 @@ class NetAppClientCmodeTestCase(test.TestCase):
fake.VSERVER_NAME)
vserver_modify_args = {
'name-mapping-switch': {'nmswitch': 'ldap,file'},
'name-server-switch': {'nsswitch': 'ldap,file'},
'name-mapping-switch': [
{'nmswitch': 'ldap'},
{'nmswitch': 'file'},
],
'name-server-switch': [
{'nsswitch': 'ldap'},
{'nsswitch': 'file'},
],
'vserver-name': fake.VSERVER_NAME
}
self.client.send_request.assert_has_calls([
mock.call('vserver-modify', vserver_modify_args)])
self.vserver_client.configure_active_directory.assert_has_calls([
@ -1070,11 +1316,16 @@ class NetAppClientCmodeTestCase(test.TestCase):
fake.VSERVER_NAME)
vserver_modify_args = {
'name-mapping-switch': {'nmswitch': 'ldap,file'},
'name-server-switch': {'nsswitch': 'ldap,file'},
'name-mapping-switch': [
{'nmswitch': 'ldap'},
{'nmswitch': 'file'},
],
'name-server-switch': [
{'nsswitch': 'ldap'},
{'nsswitch': 'file'},
],
'vserver-name': fake.VSERVER_NAME
}
self.client.send_request.assert_has_calls([
mock.call('vserver-modify', vserver_modify_args)])
self.client.create_kerberos_realm.assert_has_calls([
@ -1093,11 +1344,16 @@ class NetAppClientCmodeTestCase(test.TestCase):
fake.VSERVER_NAME)
vserver_modify_args = {
'name-mapping-switch': {'nmswitch': 'ldap,file'},
'name-server-switch': {'nsswitch': 'ldap,file'},
'name-mapping-switch': [
{'nmswitch': 'ldap'},
{'nmswitch': 'file'},
],
'name-server-switch': [
{'nsswitch': 'ldap'},
{'nsswitch': 'file'},
],
'vserver-name': fake.VSERVER_NAME
}
self.client.send_request.assert_has_calls([
mock.call('vserver-modify', vserver_modify_args)])

View File

@ -65,14 +65,11 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
self.mock_object(self.library,
'_find_matching_aggregates',
mock.Mock(return_value=fake.AGGREGATES))
mock_check_data_ontap_version = self.mock_object(
self.library, '_check_data_ontap_version')
mock_super = self.mock_object(lib_base.NetAppCmodeFileStorageLibrary,
'check_for_setup_error')
self.library.check_for_setup_error()
self.assertTrue(mock_check_data_ontap_version.called)
self.assertTrue(self.library._find_matching_aggregates.called)
mock_super.assert_called_once_with()
@ -107,17 +104,6 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
self.library.check_for_setup_error)
self.assertTrue(self.library._find_matching_aggregates.called)
@ddt.data((1, 20), (1, 21))
def test_check_data_ontap_version(self, version):
self.library._client.get_ontapi_version.return_value = version
self.assertIsNone(self.library._check_data_ontap_version())
@ddt.data((1, 30), (1, 31), (1, 40), (2, 0))
def test_check_data_ontap_version_too_new(self, version):
self.library._client.get_ontapi_version.return_value = version
self.assertRaises(exception.NetAppException,
self.library._check_data_ontap_version)
def test_get_vserver_no_share_server(self):
self.assertRaises(exception.InvalidInput,