NetApp cDOT multi-SVM driver can't handle duplicate addresses
When operating in DHSS==True mode, the cDOT driver can receive separate Neutron subnets for different tenants with overlapping IP address ranges. This is typically seen in Tempest testing, and it is likely to occur for production clouds as well. VLAN segmentation is insufficient by itself to resolve the problem. Starting with 8.3, clustered Data ONTAP supports IPspaces, which allow different storage virtual machines (i.e. share servers) to utilize overlapping address spaces. This commit resolves the issue on cDOT 8.3 by creating a new IPspace for each unique tenant network segment (i.e., each Neutron subnet) it encounters while creating share servers. It also includes some minor improvements to error handling when vservers aren't created and configured successfully plus some trivial refactoring in the vserver creation path. Closes-Bug: #1491384 Change-Id: I808547c7d38e6bb61ae10ecdb174d3ab52b1443a
This commit is contained in:
parent
7049a9aac9
commit
6369e3f9c8
|
@ -81,7 +81,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||
|
||||
@na_utils.trace
|
||||
def create_vserver(self, vserver_name, root_volume_aggregate_name,
|
||||
root_volume_name, aggregate_names):
|
||||
root_volume_name, aggregate_names, ipspace_name):
|
||||
"""Creates new vserver and assigns aggregates."""
|
||||
create_args = {
|
||||
'vserver-name': vserver_name,
|
||||
|
@ -92,6 +92,14 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||
'nsswitch': 'file',
|
||||
},
|
||||
}
|
||||
|
||||
if ipspace_name:
|
||||
if not self.features.IPSPACES:
|
||||
msg = 'IPSpaces are not supported on this backend.'
|
||||
raise exception.NetAppException(msg)
|
||||
else:
|
||||
create_args['ipspace'] = ipspace_name
|
||||
|
||||
self.send_request('vserver-create', create_args)
|
||||
|
||||
aggr_list = [{'aggr-name': aggr_name} for aggr_name in aggregate_names]
|
||||
|
@ -148,6 +156,57 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||
raise exception.NetAppException(msg)
|
||||
return root_volume_name
|
||||
|
||||
@na_utils.trace
|
||||
def get_vserver_ipspace(self, vserver_name):
|
||||
"""Get the IPspace of the vserver, or None if not supported."""
|
||||
if not self.features.IPSPACES:
|
||||
return None
|
||||
|
||||
api_args = {
|
||||
'query': {
|
||||
'vserver-info': {
|
||||
'vserver-name': vserver_name,
|
||||
},
|
||||
},
|
||||
'desired-attributes': {
|
||||
'vserver-info': {
|
||||
'ipspace': None,
|
||||
},
|
||||
},
|
||||
}
|
||||
vserver_info = self.send_request('vserver-get-iter', api_args)
|
||||
|
||||
try:
|
||||
ipspace = vserver_info.get_child_by_name(
|
||||
'attributes-list').get_child_by_name(
|
||||
'vserver-info').get_child_content('ipspace')
|
||||
except AttributeError:
|
||||
msg = _('Could not determine IPspace for Vserver %s.')
|
||||
raise exception.NetAppException(msg % vserver_name)
|
||||
return ipspace
|
||||
|
||||
@na_utils.trace
|
||||
def ipspace_has_data_vservers(self, ipspace_name):
|
||||
"""Check whether an IPspace has any data Vservers assigned to it."""
|
||||
if not self.features.IPSPACES:
|
||||
return False
|
||||
|
||||
api_args = {
|
||||
'query': {
|
||||
'vserver-info': {
|
||||
'ipspace': ipspace_name,
|
||||
'vserver-type': 'data'
|
||||
},
|
||||
},
|
||||
'desired-attributes': {
|
||||
'vserver-info': {
|
||||
'vserver-name': None,
|
||||
},
|
||||
},
|
||||
}
|
||||
result = self.send_request('vserver-get-iter', api_args)
|
||||
return self._has_records(result)
|
||||
|
||||
@na_utils.trace
|
||||
def list_vservers(self, vserver_type='data'):
|
||||
"""Get the names of vservers present, optionally filtered by type."""
|
||||
|
@ -358,7 +417,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||
@na_utils.trace
|
||||
def create_network_interface(self, ip, netmask, vlan, node, port,
|
||||
vserver_name, allocation_id,
|
||||
lif_name_template):
|
||||
lif_name_template, ipspace_name):
|
||||
"""Creates LIF on VLAN port."""
|
||||
|
||||
home_port_name = port
|
||||
|
@ -367,7 +426,8 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||
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)
|
||||
self._ensure_broadcast_domain_for_port(node, home_port_name,
|
||||
ipspace=ipspace_name)
|
||||
|
||||
interface_name = (lif_name_template %
|
||||
{'node': node, 'net_allocation_id': allocation_id})
|
||||
|
@ -416,14 +476,34 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||
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."""
|
||||
"""Ensure a port is in a broadcast domain. Create one if necessary.
|
||||
|
||||
if self._get_broadcast_domain_for_port(node, port):
|
||||
If the IPspace:domain pair match for the given port, which commonly
|
||||
happens in multi-node clusters, then there isn't anything to do.
|
||||
Otherwise, we can assume the IPspace is correct and extant by this
|
||||
point, so the remaining task is to remove the port from any domain it
|
||||
is already in, create the desired domain if it doesn't exist, and add
|
||||
the port to the desired domain.
|
||||
"""
|
||||
|
||||
port_info = self._get_broadcast_domain_for_port(node, port)
|
||||
|
||||
# Port already in desired ipspace and broadcast domain.
|
||||
if (port_info['ipspace'] == ipspace
|
||||
and port_info['broadcast-domain'] == domain):
|
||||
return
|
||||
|
||||
# If in another broadcast domain, remove port from it.
|
||||
if port_info['broadcast-domain']:
|
||||
self._remove_port_from_broadcast_domain(
|
||||
node, port, port_info['broadcast-domain'],
|
||||
port_info['ipspace'])
|
||||
|
||||
# If desired broadcast domain doesn't exist, create it.
|
||||
if not self._broadcast_domain_exists(domain, ipspace):
|
||||
self._create_broadcast_domain(domain, ipspace)
|
||||
|
||||
# Move the port into the broadcast domain where it is needed.
|
||||
self._add_port_to_broadcast_domain(node, port, domain, ipspace)
|
||||
|
||||
@na_utils.trace
|
||||
|
@ -439,6 +519,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||
'desired-attributes': {
|
||||
'net-port-info': {
|
||||
'broadcast-domain': None,
|
||||
'ipspace': None,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -452,7 +533,12 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||
msg_args = {'port': port, 'node': node}
|
||||
raise exception.NetAppException(msg % msg_args)
|
||||
|
||||
return port_info[0].get_child_content('broadcast-domain')
|
||||
port = {
|
||||
'broadcast-domain':
|
||||
port_info[0].get_child_content('broadcast-domain'),
|
||||
'ipspace': port_info[0].get_child_content('ipspace')
|
||||
}
|
||||
return port
|
||||
|
||||
@na_utils.trace
|
||||
def _broadcast_domain_exists(self, domain, ipspace):
|
||||
|
@ -482,6 +568,25 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||
}
|
||||
self.send_request('net-port-broadcast-domain-create', api_args)
|
||||
|
||||
@na_utils.trace
|
||||
def _delete_broadcast_domain(self, domain, ipspace):
|
||||
"""Delete a broadcast domain."""
|
||||
api_args = {
|
||||
'ipspace': ipspace,
|
||||
'broadcast-domain': domain,
|
||||
}
|
||||
self.send_request('net-port-broadcast-domain-destroy', api_args)
|
||||
|
||||
def _delete_broadcast_domains_for_ipspace(self, ipspace_name):
|
||||
"""Deletes all broadcast domains in an IPspace."""
|
||||
ipspaces = self.get_ipspaces(ipspace_name=ipspace_name)
|
||||
if not ipspaces:
|
||||
return
|
||||
|
||||
ipspace = ipspaces[0]
|
||||
for broadcast_domain_name in ipspace['broadcast-domains']:
|
||||
self._delete_broadcast_domain(broadcast_domain_name, ipspace_name)
|
||||
|
||||
@na_utils.trace
|
||||
def _add_port_to_broadcast_domain(self, node, port, domain, ipspace):
|
||||
|
||||
|
@ -510,6 +615,19 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||
}
|
||||
raise exception.NetAppException(msg % msg_args)
|
||||
|
||||
@na_utils.trace
|
||||
def _remove_port_from_broadcast_domain(self, node, port, domain, ipspace):
|
||||
|
||||
qualified_port_name = ':'.join([node, port])
|
||||
api_args = {
|
||||
'ipspace': ipspace,
|
||||
'broadcast-domain': domain,
|
||||
'ports': {
|
||||
'net-qualified-port-name': qualified_port_name,
|
||||
}
|
||||
}
|
||||
self.send_request('net-port-broadcast-domain-remove-ports', api_args)
|
||||
|
||||
@na_utils.trace
|
||||
def network_interface_exists(self, vserver_name, node, port, ip, netmask,
|
||||
vlan):
|
||||
|
@ -594,6 +712,103 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||
api_args = {'vserver': None, 'interface-name': interface_name}
|
||||
self.send_request('net-interface-delete', api_args)
|
||||
|
||||
@na_utils.trace
|
||||
def get_ipspaces(self, ipspace_name=None, max_records=1000):
|
||||
"""Gets one or more IPSpaces."""
|
||||
|
||||
if not self.features.IPSPACES:
|
||||
return []
|
||||
|
||||
api_args = {'max-records': max_records}
|
||||
if ipspace_name:
|
||||
api_args['query'] = {
|
||||
'net-ipspaces-info': {
|
||||
'ipspace': ipspace_name,
|
||||
}
|
||||
}
|
||||
|
||||
result = self.send_request('net-ipspaces-get-iter', api_args)
|
||||
if not self._has_records(result):
|
||||
return []
|
||||
|
||||
ipspaces = []
|
||||
|
||||
for net_ipspaces_info in result.get_child_by_name(
|
||||
'attributes-list').get_children():
|
||||
|
||||
ipspace = {
|
||||
'ports': [],
|
||||
'vservers': [],
|
||||
'broadcast-domains': [],
|
||||
}
|
||||
|
||||
ports = net_ipspaces_info.get_child_by_name(
|
||||
'ports') or netapp_api.NaElement('none')
|
||||
for port in ports.get_children():
|
||||
ipspace['ports'].append(port.get_content())
|
||||
|
||||
vservers = net_ipspaces_info.get_child_by_name(
|
||||
'vservers') or netapp_api.NaElement('none')
|
||||
for vserver in vservers.get_children():
|
||||
ipspace['vservers'].append(vserver.get_content())
|
||||
|
||||
broadcast_domains = net_ipspaces_info.get_child_by_name(
|
||||
'broadcast-domains') or netapp_api.NaElement('none')
|
||||
for broadcast_domain in broadcast_domains.get_children():
|
||||
ipspace['broadcast-domains'].append(
|
||||
broadcast_domain.get_content())
|
||||
|
||||
ipspace['ipspace'] = net_ipspaces_info.get_child_content('ipspace')
|
||||
ipspace['id'] = net_ipspaces_info.get_child_content('id')
|
||||
ipspace['uuid'] = net_ipspaces_info.get_child_content('uuid')
|
||||
|
||||
ipspaces.append(ipspace)
|
||||
|
||||
return ipspaces
|
||||
|
||||
@na_utils.trace
|
||||
def ipspace_exists(self, ipspace_name):
|
||||
"""Checks if IPspace exists."""
|
||||
|
||||
if not self.features.IPSPACES:
|
||||
return False
|
||||
|
||||
api_args = {
|
||||
'query': {
|
||||
'net-ipspaces-info': {
|
||||
'ipspace': ipspace_name,
|
||||
},
|
||||
},
|
||||
'desired-attributes': {
|
||||
'net-ipspaces-info': {
|
||||
'ipspace': None,
|
||||
},
|
||||
},
|
||||
}
|
||||
result = self.send_request('net-ipspaces-get-iter', api_args)
|
||||
return self._has_records(result)
|
||||
|
||||
@na_utils.trace
|
||||
def create_ipspace(self, ipspace_name):
|
||||
"""Creates an IPspace."""
|
||||
api_args = {'ipspace': ipspace_name}
|
||||
self.send_request('net-ipspaces-create', api_args)
|
||||
|
||||
@na_utils.trace
|
||||
def delete_ipspace(self, ipspace_name):
|
||||
"""Deletes an IPspace."""
|
||||
|
||||
self._delete_broadcast_domains_for_ipspace(ipspace_name)
|
||||
|
||||
api_args = {'ipspace': ipspace_name}
|
||||
self.send_request('net-ipspaces-destroy', api_args)
|
||||
|
||||
@na_utils.trace
|
||||
def add_vserver_to_ipspace(self, ipspace_name, vserver_name):
|
||||
"""Assigns a vserver to an IPspace."""
|
||||
api_args = {'ipspace': ipspace_name, 'vserver': vserver_name}
|
||||
self.send_request('net-ipspaces-assign-vserver', api_args)
|
||||
|
||||
@na_utils.trace
|
||||
def get_node_for_aggregate(self, aggregate_name):
|
||||
"""Get home node for the specified aggregate.
|
||||
|
|
|
@ -27,6 +27,7 @@ from oslo_utils import excutils
|
|||
|
||||
from manila import exception
|
||||
from manila.i18n import _, _LE, _LW
|
||||
from manila.share.drivers.netapp.dataontap.client import client_cmode
|
||||
from manila.share.drivers.netapp.dataontap.cluster_mode import lib_base
|
||||
from manila.share.drivers.netapp import utils as na_utils
|
||||
from manila import utils
|
||||
|
@ -34,6 +35,7 @@ from manila import utils
|
|||
|
||||
LOG = log.getLogger(__name__)
|
||||
SUPPORTED_NETWORK_TYPES = (None, 'flat', 'vlan')
|
||||
SEGMENTED_NETWORK_TYPES = ('vlan',)
|
||||
|
||||
|
||||
class NetAppCmodeMultiSVMFileStorageLibrary(
|
||||
|
@ -111,7 +113,7 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
|
|||
server_details = {'vserver_name': vserver_name}
|
||||
|
||||
try:
|
||||
self._create_vserver_if_nonexistent(vserver_name, network_info)
|
||||
self._create_vserver(vserver_name, network_info)
|
||||
except Exception as e:
|
||||
e.detail_data = {'server_details': server_details}
|
||||
raise
|
||||
|
@ -132,41 +134,74 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
|
|||
return self.configuration.netapp_vserver_name_template % server_id
|
||||
|
||||
@na_utils.trace
|
||||
def _create_vserver_if_nonexistent(self, vserver_name, network_info):
|
||||
def _create_vserver(self, vserver_name, network_info):
|
||||
"""Creates Vserver with given parameters if it doesn't exist."""
|
||||
|
||||
if self._client.vserver_exists(vserver_name):
|
||||
msg = _('Vserver %s already exists.')
|
||||
raise exception.NetAppException(msg % vserver_name)
|
||||
|
||||
ipspace_name = self._create_ipspace(network_info)
|
||||
|
||||
LOG.debug('Vserver %s does not exist, creating.', vserver_name)
|
||||
self._client.create_vserver(
|
||||
vserver_name,
|
||||
self.configuration.netapp_root_volume_aggregate,
|
||||
self.configuration.netapp_root_volume,
|
||||
self._find_matching_aggregates())
|
||||
self._find_matching_aggregates(),
|
||||
ipspace_name)
|
||||
|
||||
vserver_client = self._get_api_client(vserver=vserver_name)
|
||||
security_services = None
|
||||
try:
|
||||
self._create_vserver_lifs(vserver_name,
|
||||
vserver_client,
|
||||
network_info)
|
||||
network_info,
|
||||
ipspace_name)
|
||||
|
||||
vserver_client.enable_nfs()
|
||||
|
||||
security_services = network_info.get('security_services')
|
||||
if security_services:
|
||||
self._client.setup_security_services(security_services,
|
||||
vserver_client,
|
||||
vserver_name)
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE("Failed to create network interface(s)."))
|
||||
self._client.delete_vserver(vserver_name, vserver_client)
|
||||
LOG.error(_LE("Failed to configure Vserver."))
|
||||
self._delete_vserver(vserver_name,
|
||||
security_services=security_services)
|
||||
|
||||
vserver_client.enable_nfs()
|
||||
def _get_valid_ipspace_name(self, network_id):
|
||||
"""Get IPspace name according to network id."""
|
||||
return 'ipspace_' + network_id.replace('-', '_')
|
||||
|
||||
security_services = network_info.get('security_services')
|
||||
if security_services:
|
||||
self._client.setup_security_services(security_services,
|
||||
vserver_client,
|
||||
vserver_name)
|
||||
@na_utils.trace
|
||||
def _create_ipspace(self, network_info):
|
||||
"""If supported, create an IPspace for a new Vserver."""
|
||||
|
||||
if not self._client.features.IPSPACES:
|
||||
return None
|
||||
|
||||
if network_info['network_type'] not in SEGMENTED_NETWORK_TYPES:
|
||||
return client_cmode.DEFAULT_IPSPACE
|
||||
|
||||
# NOTE(cknight): Neutron needs cDOT IP spaces because it can provide
|
||||
# overlapping IP address ranges for different subnets. That is not
|
||||
# believed to be an issue for any of Manila's other network plugins.
|
||||
ipspace_id = network_info.get('neutron_subnet_id')
|
||||
if not ipspace_id:
|
||||
return client_cmode.DEFAULT_IPSPACE
|
||||
|
||||
ipspace_name = self._get_valid_ipspace_name(ipspace_id)
|
||||
if not self._client.ipspace_exists(ipspace_name):
|
||||
self._client.create_ipspace(ipspace_name)
|
||||
|
||||
return ipspace_name
|
||||
|
||||
@na_utils.trace
|
||||
def _create_vserver_lifs(self, vserver_name, vserver_client,
|
||||
network_info):
|
||||
network_info, ipspace_name):
|
||||
|
||||
nodes = self._client.list_cluster_nodes()
|
||||
node_network_info = zip(nodes, network_info['network_allocations'])
|
||||
|
@ -183,6 +218,7 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
|
|||
port,
|
||||
ip,
|
||||
netmask,
|
||||
ipspace_name,
|
||||
vserver_client)
|
||||
|
||||
@na_utils.trace
|
||||
|
@ -199,14 +235,15 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
|
|||
|
||||
@na_utils.trace
|
||||
def _create_lif_if_nonexistent(self, vserver_name, allocation_id, vlan,
|
||||
node, port, ip, netmask, vserver_client):
|
||||
node, port, ip, netmask, ipspace_name,
|
||||
vserver_client):
|
||||
"""Creates LIF for Vserver."""
|
||||
if not vserver_client.network_interface_exists(vserver_name, node,
|
||||
port, ip, netmask,
|
||||
vlan):
|
||||
self._client.create_network_interface(
|
||||
ip, netmask, vlan, node, port, vserver_name, allocation_id,
|
||||
self.configuration.netapp_lif_name_template)
|
||||
self.configuration.netapp_lif_name_template, ipspace_name)
|
||||
|
||||
@na_utils.trace
|
||||
def get_network_allocations_number(self):
|
||||
|
@ -231,7 +268,19 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
|
|||
"record will proceed anyway."), vserver)
|
||||
return
|
||||
|
||||
self._delete_vserver(vserver, security_services=security_services)
|
||||
|
||||
@na_utils.trace
|
||||
def _delete_vserver(self, vserver, security_services=None):
|
||||
"""Delete a Vserver plus IPspace and security services as needed."""
|
||||
|
||||
ipspace_name = self._client.get_vserver_ipspace(vserver)
|
||||
|
||||
vserver_client = self._get_api_client(vserver=vserver)
|
||||
self._client.delete_vserver(vserver,
|
||||
vserver_client,
|
||||
security_services=security_services)
|
||||
|
||||
if ipspace_name and not self._client.ipspace_has_data_vservers(
|
||||
ipspace_name):
|
||||
self._client.delete_ipspace(ipspace_name)
|
||||
|
|
|
@ -65,10 +65,22 @@ 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'
|
||||
IPSPACE_NAME = 'fake_ipspace'
|
||||
BROADCAST_DOMAIN = 'fake_domain'
|
||||
MTU = 9000
|
||||
|
||||
IPSPACES = [{
|
||||
'uuid': 'fake_uuid',
|
||||
'ipspace': IPSPACE_NAME,
|
||||
'id': 'fake_id',
|
||||
'broadcast-domains': ['OpenStack'],
|
||||
'ports': [NODE_NAME + ':' + VLAN_PORT],
|
||||
'vservers': [
|
||||
IPSPACE_NAME,
|
||||
VSERVER_NAME,
|
||||
]
|
||||
}]
|
||||
|
||||
EMS_MESSAGE = {
|
||||
'computer-name': 'fake_host',
|
||||
'event-id': '0',
|
||||
|
@ -113,6 +125,18 @@ VSERVER_GET_ROOT_VOLUME_NAME_RESPONSE = etree.XML("""
|
|||
</results>
|
||||
""" % {'root_volume': ROOT_VOLUME_NAME, 'fake_vserver': VSERVER_NAME})
|
||||
|
||||
VSERVER_GET_IPSPACE_NAME_RESPONSE = etree.XML("""
|
||||
<results status="passed">
|
||||
<attributes-list>
|
||||
<vserver-info>
|
||||
<ipspace>%(ipspace)s</ipspace>
|
||||
<vserver-name>%(fake_vserver)s</vserver-name>
|
||||
</vserver-info>
|
||||
</attributes-list>
|
||||
<num-records>1</num-records>
|
||||
</results>
|
||||
""" % {'ipspace': IPSPACE_NAME, 'fake_vserver': VSERVER_NAME})
|
||||
|
||||
VSERVER_GET_RESPONSE = etree.XML("""
|
||||
<results status="passed">
|
||||
<attributes>
|
||||
|
@ -447,6 +471,7 @@ NET_PORT_GET_ITER_BROADCAST_DOMAIN_RESPONSE = etree.XML("""
|
|||
<results status="passed">
|
||||
<attributes-list>
|
||||
<net-port-info>
|
||||
<ipspace>%(ipspace)s</ipspace>
|
||||
<broadcast-domain>%(domain)s</broadcast-domain>
|
||||
<node>%(node)s</node>
|
||||
<port>%(port)s</port>
|
||||
|
@ -454,19 +479,25 @@ NET_PORT_GET_ITER_BROADCAST_DOMAIN_RESPONSE = etree.XML("""
|
|||
</attributes-list>
|
||||
<num-records>1</num-records>
|
||||
</results>
|
||||
""" % {'domain': BROADCAST_DOMAIN, 'node': NODE_NAME, 'port': PORT})
|
||||
""" % {
|
||||
'domain': BROADCAST_DOMAIN,
|
||||
'node': NODE_NAME,
|
||||
'port': PORT,
|
||||
'ipspace': IPSPACE_NAME,
|
||||
})
|
||||
|
||||
NET_PORT_GET_ITER_BROADCAST_DOMAIN_MISSING_RESPONSE = etree.XML("""
|
||||
<results status="passed">
|
||||
<attributes-list>
|
||||
<net-port-info>
|
||||
<ipspace>%(ipspace)s</ipspace>
|
||||
<node>%(node)s</node>
|
||||
<port>%(port)s</port>
|
||||
</net-port-info>
|
||||
</attributes-list>
|
||||
<num-records>1</num-records>
|
||||
</results>
|
||||
""" % {'node': NODE_NAME, 'port': PORT})
|
||||
""" % {'node': NODE_NAME, 'port': PORT, 'ipspace': IPSPACE_NAME})
|
||||
|
||||
NET_PORT_BROADCAST_DOMAIN_GET_ITER_RESPONSE = etree.XML("""
|
||||
<results status="passed">
|
||||
|
@ -478,7 +509,35 @@ NET_PORT_BROADCAST_DOMAIN_GET_ITER_RESPONSE = etree.XML("""
|
|||
</attributes-list>
|
||||
<num-records>1</num-records>
|
||||
</results>
|
||||
""" % {'domain': BROADCAST_DOMAIN, 'ipspace': IPSPACE})
|
||||
""" % {'domain': BROADCAST_DOMAIN, 'ipspace': IPSPACE_NAME})
|
||||
|
||||
NET_IPSPACES_GET_ITER_RESPONSE = etree.XML("""
|
||||
<results status="passed">
|
||||
<attributes-list>
|
||||
<net-ipspaces-info>
|
||||
<broadcast-domains>
|
||||
<broadcast-domain-name>OpenStack</broadcast-domain-name>
|
||||
</broadcast-domains>
|
||||
<id>fake_id</id>
|
||||
<ipspace>%(ipspace)s</ipspace>
|
||||
<ports>
|
||||
<net-qualified-port-name>%(node)s:%(port)s</net-qualified-port-name>
|
||||
</ports>
|
||||
<uuid>fake_uuid</uuid>
|
||||
<vservers>
|
||||
<vserver-name>%(ipspace)s</vserver-name>
|
||||
<vserver-name>%(vserver)s</vserver-name>
|
||||
</vservers>
|
||||
</net-ipspaces-info>
|
||||
</attributes-list>
|
||||
<num-records>1</num-records>
|
||||
</results>
|
||||
""" % {
|
||||
'ipspace': IPSPACE_NAME,
|
||||
'node': NODE_NAME,
|
||||
'port': VLAN_PORT,
|
||||
'vserver': VSERVER_NAME
|
||||
})
|
||||
|
||||
NET_INTERFACE_GET_ITER_RESPONSE = etree.XML("""
|
||||
<results status="passed">
|
||||
|
|
|
@ -140,7 +140,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_create_vserver(self):
|
||||
def test_create_vserver_no_ipspace(self):
|
||||
|
||||
self.mock_object(self.client, 'send_request')
|
||||
|
||||
|
@ -160,12 +160,52 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
self.client.create_vserver(fake.VSERVER_NAME,
|
||||
fake.ROOT_VOLUME_AGGREGATE_NAME,
|
||||
fake.ROOT_VOLUME_NAME,
|
||||
fake.SHARE_AGGREGATE_NAMES)
|
||||
fake.SHARE_AGGREGATE_NAMES,
|
||||
None)
|
||||
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('vserver-create', vserver_create_args),
|
||||
mock.call('vserver-modify', vserver_modify_args)])
|
||||
|
||||
def test_create_vserver_with_ipspace(self):
|
||||
|
||||
self.client.features.add_feature('IPSPACES')
|
||||
self.mock_object(self.client, 'send_request')
|
||||
|
||||
vserver_create_args = {
|
||||
'vserver-name': fake.VSERVER_NAME,
|
||||
'root-volume-security-style': 'unix',
|
||||
'root-volume-aggregate': fake.ROOT_VOLUME_AGGREGATE_NAME,
|
||||
'root-volume': fake.ROOT_VOLUME_NAME,
|
||||
'name-server-switch': {'nsswitch': 'file'},
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
}
|
||||
vserver_modify_args = {
|
||||
'aggr-list': [{'aggr-name': aggr_name} for aggr_name
|
||||
in fake.SHARE_AGGREGATE_NAMES],
|
||||
'vserver-name': fake.VSERVER_NAME
|
||||
}
|
||||
|
||||
self.client.create_vserver(fake.VSERVER_NAME,
|
||||
fake.ROOT_VOLUME_AGGREGATE_NAME,
|
||||
fake.ROOT_VOLUME_NAME,
|
||||
fake.SHARE_AGGREGATE_NAMES,
|
||||
fake.IPSPACE_NAME)
|
||||
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('vserver-create', vserver_create_args),
|
||||
mock.call('vserver-modify', vserver_modify_args)])
|
||||
|
||||
def test_create_vserver_ipspaces_not_supported(self):
|
||||
|
||||
self.assertRaises(exception.NetAppException,
|
||||
self.client.create_vserver,
|
||||
fake.VSERVER_NAME,
|
||||
fake.ROOT_VOLUME_AGGREGATE_NAME,
|
||||
fake.ROOT_VOLUME_NAME,
|
||||
fake.SHARE_AGGREGATE_NAMES,
|
||||
fake.IPSPACE_NAME)
|
||||
|
||||
def test_get_vserver_root_volume_name(self):
|
||||
|
||||
api_response = netapp_api.NaElement(
|
||||
|
@ -187,8 +227,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
|
||||
def test_get_vserver_root_volume_name_not_found(self):
|
||||
|
||||
api_response = netapp_api.NaElement(
|
||||
fake.NO_RECORDS_RESPONSE)
|
||||
api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
|
||||
self.mock_object(self.client,
|
||||
'send_request',
|
||||
mock.Mock(return_value=api_response))
|
||||
|
@ -197,6 +236,96 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
self.client.get_vserver_root_volume_name,
|
||||
fake.VSERVER_NAME)
|
||||
|
||||
def test_get_vserver_ipspace(self):
|
||||
|
||||
self.client.features.add_feature('IPSPACES')
|
||||
api_response = netapp_api.NaElement(
|
||||
fake.VSERVER_GET_IPSPACE_NAME_RESPONSE)
|
||||
self.mock_object(self.client,
|
||||
'send_request',
|
||||
mock.Mock(return_value=api_response))
|
||||
|
||||
result = self.client.get_vserver_ipspace(fake.VSERVER_NAME)
|
||||
|
||||
vserver_get_iter_args = {
|
||||
'query': {
|
||||
'vserver-info': {
|
||||
'vserver-name': fake.VSERVER_NAME,
|
||||
},
|
||||
},
|
||||
'desired-attributes': {
|
||||
'vserver-info': {
|
||||
'ipspace': None,
|
||||
},
|
||||
},
|
||||
}
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('vserver-get-iter', vserver_get_iter_args)])
|
||||
self.assertEqual(fake.IPSPACE_NAME, result)
|
||||
|
||||
def test_get_vserver_ipspace_not_supported(self):
|
||||
|
||||
result = self.client.get_vserver_ipspace(fake.IPSPACE_NAME)
|
||||
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_get_vserver_ipspace_not_found(self):
|
||||
|
||||
self.client.features.add_feature('IPSPACES')
|
||||
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_vserver_ipspace,
|
||||
fake.IPSPACE_NAME)
|
||||
|
||||
def test_ipspace_has_data_vservers(self):
|
||||
|
||||
self.client.features.add_feature('IPSPACES')
|
||||
api_response = netapp_api.NaElement(fake.VSERVER_GET_ITER_RESPONSE)
|
||||
self.mock_object(self.client,
|
||||
'send_request',
|
||||
mock.Mock(return_value=api_response))
|
||||
|
||||
result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME)
|
||||
|
||||
vserver_get_iter_args = {
|
||||
'query': {
|
||||
'vserver-info': {
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
'vserver-type': 'data'
|
||||
},
|
||||
},
|
||||
'desired-attributes': {
|
||||
'vserver-info': {
|
||||
'vserver-name': None,
|
||||
},
|
||||
},
|
||||
}
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('vserver-get-iter', vserver_get_iter_args)])
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_ipspace_has_data_vservers_not_supported(self):
|
||||
|
||||
result = self.client.ipspace_has_data_vservers(fake.IPSPACE_NAME)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_ipspace_has_data_vservers_not_found(self):
|
||||
|
||||
self.client.features.add_feature('IPSPACES')
|
||||
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.ipspace_has_data_vservers(fake.IPSPACE_NAME)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_list_vservers(self):
|
||||
|
||||
api_response = netapp_api.NaElement(
|
||||
|
@ -615,7 +744,8 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
fake.NODE_NAME, fake.PORT,
|
||||
fake.VSERVER_NAME,
|
||||
fake.NET_ALLOCATION_ID,
|
||||
fake.LIF_NAME_TEMPLATE)
|
||||
fake.LIF_NAME_TEMPLATE,
|
||||
fake.IPSPACE_NAME)
|
||||
|
||||
if use_vlans:
|
||||
self.client._create_vlan.assert_called_with(
|
||||
|
@ -625,7 +755,8 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
|
||||
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)
|
||||
fake.NODE_NAME, fake.VLAN_PORT if use_vlans else fake.PORT,
|
||||
ipspace=fake.IPSPACE_NAME)
|
||||
else:
|
||||
self.assertFalse(
|
||||
self.client._ensure_broadcast_domain_for_port.called)
|
||||
|
@ -678,54 +809,15 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
fake.PORT,
|
||||
fake.VLAN)
|
||||
|
||||
def test_ensure_broadcast_domain_for_port_has_domain(self):
|
||||
def test_ensure_broadcast_domain_for_port_domain_match(self):
|
||||
|
||||
port_info = {
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
'broadcast-domain': fake.BROADCAST_DOMAIN,
|
||||
}
|
||||
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))
|
||||
mock.Mock(return_value=port_info))
|
||||
self.mock_object(self.client,
|
||||
'_broadcast_domain_exists',
|
||||
mock.Mock(return_value=True))
|
||||
|
@ -734,16 +826,76 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
|
||||
self.client._ensure_broadcast_domain_for_port(
|
||||
fake.NODE_NAME, fake.PORT, domain=fake.BROADCAST_DOMAIN,
|
||||
ipspace=fake.IPSPACE)
|
||||
ipspace=fake.IPSPACE_NAME)
|
||||
|
||||
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_other_domain(self):
|
||||
|
||||
port_info = {
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
'broadcast-domain': 'other_domain',
|
||||
}
|
||||
self.mock_object(self.client,
|
||||
'_get_broadcast_domain_for_port',
|
||||
mock.Mock(return_value=port_info))
|
||||
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, '_remove_port_from_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_NAME)
|
||||
|
||||
self.client._get_broadcast_domain_for_port.assert_has_calls([
|
||||
mock.call(fake.NODE_NAME, fake.PORT)])
|
||||
self.client._remove_port_from_broadcast_domain.assert_has_calls([
|
||||
mock.call(fake.NODE_NAME, fake.PORT, 'other_domain',
|
||||
fake.IPSPACE_NAME)])
|
||||
self.client._broadcast_domain_exists.assert_has_calls([
|
||||
mock.call(fake.BROADCAST_DOMAIN, fake.IPSPACE)])
|
||||
mock.call(fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)])
|
||||
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)])
|
||||
fake.IPSPACE_NAME)])
|
||||
|
||||
def test_ensure_broadcast_domain_for_port_no_domain(self):
|
||||
|
||||
port_info = {
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
'broadcast-domain': None,
|
||||
}
|
||||
self.mock_object(self.client,
|
||||
'_get_broadcast_domain_for_port',
|
||||
mock.Mock(return_value=port_info))
|
||||
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, '_remove_port_from_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_NAME)
|
||||
|
||||
self.client._get_broadcast_domain_for_port.assert_has_calls([
|
||||
mock.call(fake.NODE_NAME, fake.PORT)])
|
||||
self.assertFalse(self.client._remove_port_from_broadcast_domain.called)
|
||||
self.client._broadcast_domain_exists.assert_has_calls([
|
||||
mock.call(fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)])
|
||||
self.client._create_broadcast_domain.assert_has_calls([
|
||||
mock.call(fake.BROADCAST_DOMAIN, fake.IPSPACE_NAME)])
|
||||
self.client._add_port_to_broadcast_domain.assert_has_calls([
|
||||
mock.call(fake.NODE_NAME, fake.PORT, fake.BROADCAST_DOMAIN,
|
||||
fake.IPSPACE_NAME)])
|
||||
|
||||
def test_get_broadcast_domain_for_port(self):
|
||||
|
||||
|
@ -763,15 +915,20 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
'desired-attributes': {
|
||||
'net-port-info': {
|
||||
'broadcast-domain': None,
|
||||
'ipspace': None,
|
||||
},
|
||||
},
|
||||
}
|
||||
result = self.client._get_broadcast_domain_for_port(fake.NODE_NAME,
|
||||
fake.PORT)
|
||||
|
||||
expected = {
|
||||
'broadcast-domain': fake.BROADCAST_DOMAIN,
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
}
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('net-port-get-iter', net_port_get_iter_args)])
|
||||
self.assertEqual(fake.BROADCAST_DOMAIN, result)
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_get_broadcast_domain_for_port_port_not_found(self):
|
||||
|
||||
|
@ -797,7 +954,11 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
result = self.client._get_broadcast_domain_for_port(fake.NODE_NAME,
|
||||
fake.PORT)
|
||||
|
||||
self.assertIsNone(result)
|
||||
expected = {
|
||||
'broadcast-domain': None,
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
}
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_broadcast_domain_exists(self):
|
||||
|
||||
|
@ -808,12 +969,12 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
mock.Mock(return_value=api_response))
|
||||
|
||||
result = self.client._broadcast_domain_exists(fake.BROADCAST_DOMAIN,
|
||||
fake.IPSPACE)
|
||||
fake.IPSPACE_NAME)
|
||||
|
||||
net_port_broadcast_domain_get_iter_args = {
|
||||
'query': {
|
||||
'net-port-broadcast-domain-info': {
|
||||
'ipspace': fake.IPSPACE,
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
'broadcast-domain': fake.BROADCAST_DOMAIN,
|
||||
},
|
||||
},
|
||||
|
@ -835,7 +996,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
mock.Mock(return_value=api_response))
|
||||
|
||||
result = self.client._broadcast_domain_exists(fake.BROADCAST_DOMAIN,
|
||||
fake.IPSPACE)
|
||||
fake.IPSPACE_NAME)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
|
@ -844,11 +1005,11 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
self.mock_object(self.client, 'send_request')
|
||||
|
||||
result = self.client._create_broadcast_domain(fake.BROADCAST_DOMAIN,
|
||||
fake.IPSPACE,
|
||||
fake.IPSPACE_NAME,
|
||||
mtu=fake.MTU)
|
||||
|
||||
net_port_broadcast_domain_create_args = {
|
||||
'ipspace': fake.IPSPACE,
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
'broadcast-domain': fake.BROADCAST_DOMAIN,
|
||||
'mtu': fake.MTU,
|
||||
}
|
||||
|
@ -857,12 +1018,55 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
mock.call('net-port-broadcast-domain-create',
|
||||
net_port_broadcast_domain_create_args)])
|
||||
|
||||
def test_delete_broadcast_domain(self):
|
||||
|
||||
self.mock_object(self.client, 'send_request')
|
||||
|
||||
result = self.client._delete_broadcast_domain(fake.BROADCAST_DOMAIN,
|
||||
fake.IPSPACE_NAME)
|
||||
|
||||
net_port_broadcast_domain_delete_args = {
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
'broadcast-domain': fake.BROADCAST_DOMAIN,
|
||||
}
|
||||
self.assertIsNone(result)
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('net-port-broadcast-domain-destroy',
|
||||
net_port_broadcast_domain_delete_args)])
|
||||
|
||||
def test_delete_broadcast_domains_for_ipspace_not_found(self):
|
||||
|
||||
self.mock_object(self.client,
|
||||
'get_ipspaces',
|
||||
mock.Mock(return_value=[]))
|
||||
self.mock_object(self.client, '_delete_broadcast_domain')
|
||||
|
||||
self.client._delete_broadcast_domains_for_ipspace(fake.IPSPACE_NAME)
|
||||
|
||||
self.client.get_ipspaces.assert_called_once_with(
|
||||
ipspace_name=fake.IPSPACE_NAME)
|
||||
self.assertFalse(self.client._delete_broadcast_domain.called)
|
||||
|
||||
def test_delete_broadcast_domains_for_ipspace(self):
|
||||
|
||||
self.mock_object(self.client,
|
||||
'get_ipspaces',
|
||||
mock.Mock(return_value=fake.IPSPACES))
|
||||
self.mock_object(self.client, '_delete_broadcast_domain')
|
||||
|
||||
self.client._delete_broadcast_domains_for_ipspace(fake.IPSPACE_NAME)
|
||||
|
||||
self.client.get_ipspaces.assert_called_once_with(
|
||||
ipspace_name=fake.IPSPACE_NAME)
|
||||
self.client._delete_broadcast_domain.assert_called_once_with(
|
||||
fake.IPSPACES[0]['broadcast-domains'][0], fake.IPSPACE_NAME)
|
||||
|
||||
def test_add_port_to_broadcast_domain(self):
|
||||
|
||||
self.mock_object(self.client, 'send_request')
|
||||
|
||||
add_port_to_broadcast_domain_args = {
|
||||
'ipspace': fake.IPSPACE,
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
'broadcast-domain': fake.BROADCAST_DOMAIN,
|
||||
'ports': {
|
||||
'net-qualified-port-name': ':'.join([fake.NODE_NAME,
|
||||
|
@ -871,7 +1075,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
}
|
||||
result = self.client._add_port_to_broadcast_domain(
|
||||
fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN,
|
||||
fake.IPSPACE)
|
||||
fake.IPSPACE_NAME)
|
||||
|
||||
self.assertIsNone(result)
|
||||
self.client.send_request.assert_has_calls([
|
||||
|
@ -886,7 +1090,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
|
||||
result = self.client._add_port_to_broadcast_domain(
|
||||
fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN,
|
||||
fake.IPSPACE)
|
||||
fake.IPSPACE_NAME)
|
||||
|
||||
self.assertIsNone(result)
|
||||
|
||||
|
@ -899,7 +1103,28 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
fake.NODE_NAME,
|
||||
fake.VLAN_PORT,
|
||||
fake.BROADCAST_DOMAIN,
|
||||
fake.IPSPACE)
|
||||
fake.IPSPACE_NAME)
|
||||
|
||||
def test_remove_port_from_broadcast_domain(self):
|
||||
|
||||
self.mock_object(self.client, 'send_request')
|
||||
|
||||
result = self.client._remove_port_from_broadcast_domain(
|
||||
fake.NODE_NAME, fake.VLAN_PORT, fake.BROADCAST_DOMAIN,
|
||||
fake.IPSPACE_NAME)
|
||||
|
||||
net_port_broadcast_domain_remove_ports_args = {
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
'broadcast-domain': fake.BROADCAST_DOMAIN,
|
||||
'ports': {
|
||||
'net-qualified-port-name': ':'.join([fake.NODE_NAME,
|
||||
fake.VLAN_PORT])
|
||||
}
|
||||
}
|
||||
self.assertIsNone(result)
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('net-port-broadcast-domain-remove-ports',
|
||||
net_port_broadcast_domain_remove_ports_args)])
|
||||
|
||||
def test_network_interface_exists(self):
|
||||
|
||||
|
@ -1059,6 +1284,128 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||
self.client.send_request.assert_has_calls([
|
||||
mock.call('net-interface-delete', net_interface_delete_args)])
|
||||
|
||||
def test_get_ipspaces(self):
|
||||
|
||||
self.client.features.add_feature('IPSPACES')
|
||||
api_response = netapp_api.NaElement(
|
||||
fake.NET_IPSPACES_GET_ITER_RESPONSE)
|
||||
self.mock_object(self.client,
|
||||
'send_request',
|
||||
mock.Mock(return_value=api_response))
|
||||
|
||||
result = self.client.get_ipspaces(ipspace_name=fake.IPSPACE_NAME,
|
||||
max_records=500)
|
||||
|
||||
net_ipspaces_get_iter_args = {
|
||||
'max-records': 500,
|
||||
'query': {
|
||||
'net-ipspaces-info': {
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
},
|
||||
},
|
||||
}
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('net-ipspaces-get-iter', net_ipspaces_get_iter_args)])
|
||||
self.assertEqual(fake.IPSPACES, result)
|
||||
|
||||
def test_get_ipspaces_not_found(self):
|
||||
|
||||
self.client.features.add_feature('IPSPACES')
|
||||
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.get_ipspaces()
|
||||
|
||||
net_ipspaces_get_iter_args = {'max-records': 1000}
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('net-ipspaces-get-iter', net_ipspaces_get_iter_args)])
|
||||
self.assertEqual([], result)
|
||||
|
||||
def test_get_ipspaces_not_supported(self):
|
||||
|
||||
self.mock_object(self.client, 'send_request')
|
||||
|
||||
result = self.client.get_ipspaces()
|
||||
|
||||
self.assertFalse(self.client.send_request.called)
|
||||
self.assertEqual([], result)
|
||||
|
||||
@ddt.data((fake.NET_IPSPACES_GET_ITER_RESPONSE, True),
|
||||
(fake.NO_RECORDS_RESPONSE, False))
|
||||
@ddt.unpack
|
||||
def test_ipspace_exists(self, api_response, expected):
|
||||
|
||||
self.client.features.add_feature('IPSPACES')
|
||||
api_response = netapp_api.NaElement(api_response)
|
||||
self.mock_object(self.client,
|
||||
'send_request',
|
||||
mock.Mock(return_value=api_response))
|
||||
|
||||
result = self.client.ipspace_exists(fake.IPSPACE_NAME)
|
||||
|
||||
net_ipspaces_get_iter_args = {
|
||||
'query': {
|
||||
'net-ipspaces-info': {
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
},
|
||||
},
|
||||
'desired-attributes': {
|
||||
'net-ipspaces-info': {
|
||||
'ipspace': None,
|
||||
},
|
||||
},
|
||||
}
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('net-ipspaces-get-iter', net_ipspaces_get_iter_args)])
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_ipspace_exists_not_supported(self):
|
||||
|
||||
result = self.client.ipspace_exists(fake.IPSPACE_NAME)
|
||||
|
||||
self.assertFalse(result)
|
||||
|
||||
def test_create_ipspace(self):
|
||||
|
||||
self.mock_object(self.client, 'send_request')
|
||||
|
||||
self.client.create_ipspace(fake.IPSPACE_NAME)
|
||||
|
||||
net_ipspaces_create_args = {'ipspace': fake.IPSPACE_NAME}
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('net-ipspaces-create', net_ipspaces_create_args)])
|
||||
|
||||
def test_delete_ipspace(self):
|
||||
|
||||
mock_delete_broadcast_domains_for_ipspace = self.mock_object(
|
||||
self.client, '_delete_broadcast_domains_for_ipspace')
|
||||
self.mock_object(self.client, 'send_request')
|
||||
|
||||
self.client.delete_ipspace(fake.IPSPACE_NAME)
|
||||
|
||||
net_ipspaces_destroy_args = {'ipspace': fake.IPSPACE_NAME}
|
||||
mock_delete_broadcast_domains_for_ipspace.assert_called_once_with(
|
||||
fake.IPSPACE_NAME)
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('net-ipspaces-destroy', net_ipspaces_destroy_args)])
|
||||
|
||||
def test_add_vserver_to_ipspace(self):
|
||||
|
||||
self.mock_object(self.client, 'send_request')
|
||||
|
||||
self.client.add_vserver_to_ipspace(fake.IPSPACE_NAME,
|
||||
fake.VSERVER_NAME)
|
||||
|
||||
net_ipspaces_assign_vserver_args = {
|
||||
'ipspace': fake.IPSPACE_NAME,
|
||||
'vserver': fake.VSERVER_NAME
|
||||
}
|
||||
self.client.send_request.assert_has_calls([
|
||||
mock.call('net-ipspaces-assign-vserver',
|
||||
net_ipspaces_assign_vserver_args)])
|
||||
|
||||
def test_get_node_for_aggregate(self):
|
||||
|
||||
api_response = netapp_api.NaElement(
|
||||
|
|
|
@ -199,9 +199,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
'_get_vserver_name',
|
||||
mock.Mock(return_value=fake.VSERVER1))
|
||||
|
||||
mock_create_vserver = self.mock_object(
|
||||
self.library,
|
||||
'_create_vserver_if_nonexistent')
|
||||
mock_create_vserver = self.mock_object(self.library, '_create_vserver')
|
||||
|
||||
mock_validate_network_type = self.mock_object(
|
||||
self.library,
|
||||
|
@ -224,7 +222,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
fake_exception = exception.ManilaException("fake")
|
||||
mock_create_vserver = self.mock_object(
|
||||
self.library,
|
||||
'_create_vserver_if_nonexistent',
|
||||
'_create_vserver',
|
||||
mock.Mock(side_effect=fake_exception))
|
||||
|
||||
mock_validate_network_type = self.mock_object(
|
||||
|
@ -270,7 +268,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
|
||||
self.assertEqual(vserver_name, actual_result)
|
||||
|
||||
def test_create_vserver_if_nonexistent(self):
|
||||
def test_create_vserver(self):
|
||||
|
||||
vserver_id = fake.NETWORK_INFO['server_id']
|
||||
vserver_name = fake.VSERVER_NAME_TEMPLATE % vserver_id
|
||||
|
@ -288,27 +286,26 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
self.mock_object(self.library,
|
||||
'_find_matching_aggregates',
|
||||
mock.Mock(return_value=fake.AGGREGATES))
|
||||
self.mock_object(self.library,
|
||||
'_create_ipspace',
|
||||
mock.Mock(return_value=fake.IPSPACE))
|
||||
self.mock_object(self.library, '_create_vserver_lifs')
|
||||
|
||||
self.library._create_vserver_if_nonexistent(vserver_name,
|
||||
fake.NETWORK_INFO)
|
||||
self.library._get_api_client.assert_called_with(vserver=vserver_name)
|
||||
self.library._create_vserver(vserver_name, fake.NETWORK_INFO)
|
||||
|
||||
self.library._create_ipspace.assert_called_with(fake.NETWORK_INFO)
|
||||
self.library._client.create_vserver.assert_called_with(
|
||||
vserver_name,
|
||||
fake.ROOT_VOLUME_AGGREGATE,
|
||||
fake.ROOT_VOLUME,
|
||||
fake.AGGREGATES)
|
||||
vserver_name, fake.ROOT_VOLUME_AGGREGATE, fake.ROOT_VOLUME,
|
||||
fake.AGGREGATES, fake.IPSPACE)
|
||||
self.library._get_api_client.assert_called_with(vserver=vserver_name)
|
||||
self.library._create_vserver_lifs.assert_called_with(
|
||||
vserver_name,
|
||||
vserver_client,
|
||||
fake.NETWORK_INFO)
|
||||
vserver_name, vserver_client, fake.NETWORK_INFO, fake.IPSPACE)
|
||||
self.assertTrue(vserver_client.enable_nfs.called)
|
||||
self.library._client.setup_security_services.assert_called_with(
|
||||
fake.NETWORK_INFO['security_services'],
|
||||
vserver_client,
|
||||
fake.NETWORK_INFO['security_services'], vserver_client,
|
||||
vserver_name)
|
||||
|
||||
def test_create_vserver_if_nonexistent_already_present(self):
|
||||
def test_create_vserver_already_present(self):
|
||||
|
||||
vserver_id = fake.NETWORK_INFO['server_id']
|
||||
vserver_name = fake.VSERVER_NAME_TEMPLATE % vserver_id
|
||||
|
@ -321,13 +318,12 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
mock.Mock(return_value=True))
|
||||
|
||||
self.assertRaises(exception.NetAppException,
|
||||
self.library._create_vserver_if_nonexistent,
|
||||
self.library._create_vserver,
|
||||
vserver_name,
|
||||
fake.NETWORK_INFO)
|
||||
|
||||
@ddt.data(netapp_api.NaApiError, exception.NetAppException)
|
||||
def test_create_vserver_if_nonexistent_lif_creation_failure(self,
|
||||
lif_exception):
|
||||
def test_create_vserver_lif_creation_failure(self, lif_exception):
|
||||
|
||||
vserver_id = fake.NETWORK_INFO['server_id']
|
||||
vserver_name = fake.VSERVER_NAME_TEMPLATE % vserver_id
|
||||
|
@ -345,12 +341,16 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
self.mock_object(self.library,
|
||||
'_find_matching_aggregates',
|
||||
mock.Mock(return_value=fake.AGGREGATES))
|
||||
self.mock_object(self.library,
|
||||
'_create_ipspace',
|
||||
mock.Mock(return_value=fake.IPSPACE))
|
||||
self.mock_object(self.library,
|
||||
'_create_vserver_lifs',
|
||||
mock.Mock(side_effect=lif_exception))
|
||||
self.mock_object(self.library, '_delete_vserver')
|
||||
|
||||
self.assertRaises(lif_exception,
|
||||
self.library._create_vserver_if_nonexistent,
|
||||
self.library._create_vserver,
|
||||
vserver_name,
|
||||
fake.NETWORK_INFO)
|
||||
|
||||
|
@ -359,13 +359,85 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
self.library._create_vserver_lifs.assert_called_with(
|
||||
vserver_name,
|
||||
vserver_client,
|
||||
fake.NETWORK_INFO)
|
||||
self.library._client.delete_vserver.assert_called_once_with(
|
||||
fake.NETWORK_INFO,
|
||||
fake.IPSPACE)
|
||||
self.library._delete_vserver.assert_called_once_with(
|
||||
vserver_name,
|
||||
vserver_client)
|
||||
security_services=None)
|
||||
self.assertFalse(vserver_client.enable_nfs.called)
|
||||
self.assertEqual(1, lib_multi_svm.LOG.error.call_count)
|
||||
|
||||
def test_get_valid_ipspace_name(self):
|
||||
|
||||
result = self.library._get_valid_ipspace_name(fake.IPSPACE_ID)
|
||||
|
||||
expected = 'ipspace_' + fake.IPSPACE_ID.replace('-', '_')
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_create_ipspace_not_supported(self):
|
||||
|
||||
self.library._client.features.IPSPACES = False
|
||||
|
||||
result = self.library._create_ipspace(fake.NETWORK_INFO)
|
||||
|
||||
self.assertIsNone(result)
|
||||
|
||||
@ddt.data(None, 'flat')
|
||||
def test_create_ipspace_not_vlan(self, network_type):
|
||||
|
||||
self.library._client.features.IPSPACES = True
|
||||
network_info = copy.deepcopy(fake.NETWORK_INFO)
|
||||
network_info['segmentation_id'] = None
|
||||
network_info['network_type'] = network_type
|
||||
|
||||
result = self.library._create_ipspace(network_info)
|
||||
|
||||
self.assertEqual('Default', result)
|
||||
|
||||
def test_create_ipspace_not_neutron(self):
|
||||
|
||||
self.library._client.features.IPSPACES = True
|
||||
network_info = copy.deepcopy(fake.NETWORK_INFO)
|
||||
network_info['neutron_subnet_id'] = None
|
||||
network_info['nova_net_id'] = 'fake_nova_net_id'
|
||||
|
||||
result = self.library._create_ipspace(network_info)
|
||||
|
||||
self.assertEqual('Default', result)
|
||||
|
||||
def test_create_ipspace_already_present(self):
|
||||
|
||||
self.library._client.features.IPSPACES = True
|
||||
self.mock_object(self.library._client,
|
||||
'ipspace_exists',
|
||||
mock.Mock(return_value=True))
|
||||
|
||||
result = self.library._create_ipspace(fake.NETWORK_INFO)
|
||||
|
||||
expected = self.library._get_valid_ipspace_name(
|
||||
fake.NETWORK_INFO['neutron_subnet_id'])
|
||||
self.assertEqual(expected, result)
|
||||
self.library._client.ipspace_exists.assert_has_calls([
|
||||
mock.call(expected)])
|
||||
self.assertFalse(self.library._client.create_ipspace.called)
|
||||
|
||||
def test_create_ipspace(self):
|
||||
|
||||
self.library._client.features.IPSPACES = True
|
||||
self.mock_object(self.library._client,
|
||||
'ipspace_exists',
|
||||
mock.Mock(return_value=False))
|
||||
|
||||
result = self.library._create_ipspace(fake.NETWORK_INFO)
|
||||
|
||||
expected = self.library._get_valid_ipspace_name(
|
||||
fake.NETWORK_INFO['neutron_subnet_id'])
|
||||
self.assertEqual(expected, result)
|
||||
self.library._client.ipspace_exists.assert_has_calls([
|
||||
mock.call(expected)])
|
||||
self.library._client.create_ipspace.assert_has_calls([
|
||||
mock.call(expected)])
|
||||
|
||||
def test_create_vserver_lifs(self):
|
||||
|
||||
self.mock_object(self.library._client,
|
||||
|
@ -378,7 +450,8 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
|
||||
self.library._create_vserver_lifs(fake.VSERVER1,
|
||||
'fake_vserver_client',
|
||||
fake.NETWORK_INFO)
|
||||
fake.NETWORK_INFO,
|
||||
fake.IPSPACE)
|
||||
|
||||
self.library._create_lif_if_nonexistent.assert_has_calls([
|
||||
mock.call(
|
||||
|
@ -389,6 +462,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
fake.NODE_DATA_PORT,
|
||||
fake.NETWORK_INFO['network_allocations'][0]['ip_address'],
|
||||
fake.NETWORK_INFO_NETMASK,
|
||||
fake.IPSPACE,
|
||||
'fake_vserver_client'),
|
||||
mock.call(
|
||||
fake.VSERVER1,
|
||||
|
@ -398,6 +472,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
fake.NODE_DATA_PORT,
|
||||
fake.NETWORK_INFO['network_allocations'][1]['ip_address'],
|
||||
fake.NETWORK_INFO_NETMASK,
|
||||
fake.IPSPACE,
|
||||
'fake_vserver_client')])
|
||||
|
||||
def test_get_node_data_port(self):
|
||||
|
@ -437,6 +512,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
'fake_port',
|
||||
'fake_ip',
|
||||
'fake_netmask',
|
||||
fake.IPSPACE,
|
||||
vserver_client)
|
||||
|
||||
self.library._client.create_network_interface.assert_has_calls([
|
||||
|
@ -448,7 +524,8 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
'fake_port',
|
||||
'fake_vserver',
|
||||
'fake_allocation_id',
|
||||
fake.LIF_NAME_TEMPLATE)])
|
||||
fake.LIF_NAME_TEMPLATE,
|
||||
fake.IPSPACE)])
|
||||
|
||||
def test_create_lif_if_nonexistent_already_present(self):
|
||||
|
||||
|
@ -463,6 +540,7 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
'fake_port',
|
||||
'fake_ip',
|
||||
'fake_netmask',
|
||||
fake.IPSPACE,
|
||||
vserver_client)
|
||||
|
||||
self.assertFalse(self.library._client.create_network_interface.called)
|
||||
|
@ -478,11 +556,9 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
|
||||
def test_teardown_server(self):
|
||||
|
||||
vserver_client = mock.Mock()
|
||||
self.mock_object(self.library,
|
||||
'_get_api_client',
|
||||
mock.Mock(return_value=vserver_client))
|
||||
self.library._client.vserver_exists.return_value = True
|
||||
mock_delete_vserver = self.mock_object(self.library,
|
||||
'_delete_vserver')
|
||||
|
||||
self.library.teardown_server(
|
||||
fake.SHARE_SERVER['backend_details'],
|
||||
|
@ -490,22 +566,26 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
|
||||
self.library._client.vserver_exists.assert_called_once_with(
|
||||
fake.VSERVER1)
|
||||
self.library._client.delete_vserver.assert_called_once_with(
|
||||
mock_delete_vserver.assert_called_once_with(
|
||||
fake.VSERVER1,
|
||||
vserver_client,
|
||||
security_services=fake.NETWORK_INFO['security_services'])
|
||||
|
||||
@ddt.data(None, {}, {'vserver_name': None})
|
||||
def test_teardown_server_no_share_server(self, server_details):
|
||||
|
||||
mock_delete_vserver = self.mock_object(self.library,
|
||||
'_delete_vserver')
|
||||
|
||||
self.library.teardown_server(server_details)
|
||||
|
||||
self.assertFalse(self.library._client.delete_vserver.called)
|
||||
self.assertFalse(mock_delete_vserver.called)
|
||||
self.assertTrue(lib_multi_svm.LOG.warning.called)
|
||||
|
||||
def test_teardown_server_no_vserver(self):
|
||||
|
||||
self.library._client.vserver_exists.return_value = False
|
||||
mock_delete_vserver = self.mock_object(self.library,
|
||||
'_delete_vserver')
|
||||
|
||||
self.library.teardown_server(
|
||||
fake.SHARE_SERVER['backend_details'],
|
||||
|
@ -513,5 +593,72 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||
|
||||
self.library._client.vserver_exists.assert_called_once_with(
|
||||
fake.VSERVER1)
|
||||
self.assertFalse(self.library._client.delete_vserver.called)
|
||||
self.assertFalse(mock_delete_vserver.called)
|
||||
self.assertTrue(lib_multi_svm.LOG.warning.called)
|
||||
|
||||
def test_delete_vserver_no_ipspace(self):
|
||||
|
||||
self.mock_object(self.library._client,
|
||||
'get_vserver_ipspace',
|
||||
mock.Mock(return_value=None))
|
||||
vserver_client = mock.Mock()
|
||||
self.mock_object(self.library,
|
||||
'_get_api_client',
|
||||
mock.Mock(return_value=vserver_client))
|
||||
security_services = fake.NETWORK_INFO['security_services']
|
||||
|
||||
self.library._delete_vserver(fake.VSERVER1,
|
||||
security_services=security_services)
|
||||
|
||||
self.library._client.get_vserver_ipspace.assert_called_once_with(
|
||||
fake.VSERVER1)
|
||||
self.library._client.delete_vserver.assert_called_once_with(
|
||||
fake.VSERVER1, vserver_client, security_services=security_services)
|
||||
self.assertFalse(self.library._client.delete_ipspace.called)
|
||||
|
||||
def test_delete_vserver_ipspace_has_data_vservers(self):
|
||||
|
||||
self.mock_object(self.library._client,
|
||||
'get_vserver_ipspace',
|
||||
mock.Mock(return_value=fake.IPSPACE))
|
||||
vserver_client = mock.Mock()
|
||||
self.mock_object(self.library,
|
||||
'_get_api_client',
|
||||
mock.Mock(return_value=vserver_client))
|
||||
self.mock_object(self.library._client,
|
||||
'ipspace_has_data_vservers',
|
||||
mock.Mock(return_value=True))
|
||||
security_services = fake.NETWORK_INFO['security_services']
|
||||
|
||||
self.library._delete_vserver(fake.VSERVER1,
|
||||
security_services=security_services)
|
||||
|
||||
self.library._client.get_vserver_ipspace.assert_called_once_with(
|
||||
fake.VSERVER1)
|
||||
self.library._client.delete_vserver.assert_called_once_with(
|
||||
fake.VSERVER1, vserver_client, security_services=security_services)
|
||||
self.assertFalse(self.library._client.delete_ipspace.called)
|
||||
|
||||
def test_delete_vserver_with_ipspace(self):
|
||||
|
||||
self.mock_object(self.library._client,
|
||||
'get_vserver_ipspace',
|
||||
mock.Mock(return_value=fake.IPSPACE))
|
||||
vserver_client = mock.Mock()
|
||||
self.mock_object(self.library,
|
||||
'_get_api_client',
|
||||
mock.Mock(return_value=vserver_client))
|
||||
self.mock_object(self.library._client,
|
||||
'ipspace_has_data_vservers',
|
||||
mock.Mock(return_value=False))
|
||||
security_services = fake.NETWORK_INFO['security_services']
|
||||
|
||||
self.library._delete_vserver(fake.VSERVER1,
|
||||
security_services=security_services)
|
||||
|
||||
self.library._client.get_vserver_ipspace.assert_called_once_with(
|
||||
fake.VSERVER1)
|
||||
self.library._client.delete_vserver.assert_called_once_with(
|
||||
fake.VSERVER1, vserver_client, security_services=security_services)
|
||||
self.library._client.delete_ipspace.assert_called_once_with(
|
||||
fake.IPSPACE)
|
||||
|
|
|
@ -62,6 +62,8 @@ NODE_DATA_PORTS = ('e0c', 'e0d')
|
|||
LIF_NAME_TEMPLATE = 'os_%(net_allocation_id)s'
|
||||
SHARE_TYPE_ID = '26e89a5b-960b-46bb-a8cf-0778e653098f'
|
||||
SHARE_TYPE_NAME = 'fake_share_type'
|
||||
IPSPACE = 'fake_ipspace'
|
||||
IPSPACE_ID = '27d38c27-3e8b-4d7d-9d91-fcf295e3ac8f'
|
||||
|
||||
CLIENT_KWARGS = {
|
||||
'username': 'admin',
|
||||
|
@ -203,7 +205,8 @@ NETWORK_INFO = {
|
|||
'ip_address': '10.10.10.10'},
|
||||
{'id': '7eabdeed-bad2-46ea-bd0f-a33884c869e0',
|
||||
'ip_address': '10.10.10.20'}
|
||||
]
|
||||
],
|
||||
'neutron_subnet_id': '62bf1c2c-18eb-421b-8983-48a6d39aafe0',
|
||||
}
|
||||
NETWORK_INFO_NETMASK = '255.255.255.0'
|
||||
|
||||
|
|
Loading…
Reference in New Issue