[WIP] NSXV, TVD test removal
Change-Id: I8d227670e268825a343b6c9474a059a1a866d5bb
This commit is contained in:
parent
fb953367e0
commit
d6c1bc15e5
20
.pylintrc
20
.pylintrc
@ -25,21 +25,21 @@ disable=
|
||||
abstract-class-instantiated,
|
||||
arguments-differ,
|
||||
attribute-defined-outside-init,
|
||||
bad-builtin,
|
||||
#bad-builtin,
|
||||
broad-except,
|
||||
dangerous-default-value,
|
||||
deprecated-lambda,
|
||||
#deprecated-lambda,
|
||||
expression-not-assigned,
|
||||
fixme,
|
||||
global-statement,
|
||||
no-init,
|
||||
#no-init,
|
||||
non-parent-init-called,
|
||||
protected-access,
|
||||
redefined-builtin,
|
||||
signature-differs,
|
||||
star-args,
|
||||
#star-args,
|
||||
super-init-not-called,
|
||||
super-on-old-class,
|
||||
#super-on-old-class,
|
||||
unpacking-non-sequence,
|
||||
unspecified-encoding,
|
||||
unused-argument,
|
||||
@ -48,7 +48,7 @@ disable=
|
||||
unsubscriptable-object,
|
||||
useless-super-delegation,
|
||||
# TODO(dougwig) - disable nonstandard-exception while we have neutron_lib shims
|
||||
nonstandard-exception,
|
||||
#nonstandard-exception,
|
||||
# "C" Coding convention violations
|
||||
# bad-continuation,
|
||||
consider-iterating-dictionary,
|
||||
@ -64,13 +64,13 @@ disable=
|
||||
wrong-import-order,
|
||||
wrong-import-position,
|
||||
# "R" Refactor recommendations
|
||||
abstract-class-little-used,
|
||||
abstract-class-not-used,
|
||||
#abstract-class-little-used,
|
||||
#abstract-class-not-used,
|
||||
consider-merging-isinstance,
|
||||
consider-using-ternary,
|
||||
duplicate-code,
|
||||
interface-not-implemented,
|
||||
no-self-use,
|
||||
#interface-not-implemented,
|
||||
#no-self-use,
|
||||
redefined-argument-from-local,
|
||||
too-few-public-methods,
|
||||
too-many-ancestors,
|
||||
|
@ -28,7 +28,6 @@ oslo.vmware>=2.17.0 # Apache-2.0
|
||||
paramiko>=2.4.0 # LGPLv2.1+
|
||||
tooz>=2.7.1 # Apache-2.0
|
||||
decorator>=4.4.1 # BSD
|
||||
|
||||
# These repos are installed from git in OpenStack CI if the job
|
||||
# configures them as required-projects:
|
||||
neutron>=20.0.0.0 # Apache-2.0
|
||||
|
@ -10,6 +10,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from neutron.common import eventlet_utils
|
||||
|
||||
eventlet_utils.monkey_patch()
|
||||
@ -24,3 +26,4 @@ orig_threading.current_thread.__globals__['_active'] = threading._active
|
||||
import os # noqa
|
||||
|
||||
NSX_EXT_PATH = os.path.join(os.path.dirname(__file__), 'extensions')
|
||||
mock.patch('neutron.common.utils.transaction_guard', lambda x: x).start()
|
||||
|
@ -16,7 +16,6 @@
|
||||
import inspect
|
||||
import re
|
||||
|
||||
from distutils import version
|
||||
import functools
|
||||
import hashlib
|
||||
import xml.etree.ElementTree as et
|
||||
@ -33,6 +32,7 @@ from neutron_lib import constants
|
||||
from neutron_lib import exceptions as n_exc
|
||||
from oslo_context import context as common_context
|
||||
from oslo_log import log
|
||||
from packaging import version
|
||||
|
||||
from vmware_nsxlib.v3 import nsx_constants as v3_const
|
||||
|
||||
@ -74,72 +74,72 @@ class NsxV3NetworkTypes(object):
|
||||
|
||||
|
||||
def is_nsx_version_1_1_0(nsx_version):
|
||||
return (version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion(v3_const.NSX_VERSION_1_1_0))
|
||||
return (version.parse(nsx_version) >=
|
||||
version.parse(v3_const.NSX_VERSION_1_1_0))
|
||||
|
||||
|
||||
def is_nsx_version_2_0_0(nsx_version):
|
||||
return (version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion(v3_const.NSX_VERSION_2_0_0))
|
||||
return (version.parse(nsx_version) >=
|
||||
version.parse(v3_const.NSX_VERSION_2_0_0))
|
||||
|
||||
|
||||
def is_nsx_version_2_1_0(nsx_version):
|
||||
return (version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion(v3_const.NSX_VERSION_2_1_0))
|
||||
return (version.parse(nsx_version) >=
|
||||
version.parse(v3_const.NSX_VERSION_2_1_0))
|
||||
|
||||
|
||||
def is_nsx_version_2_4_0(nsx_version):
|
||||
return (version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion(v3_const.NSX_VERSION_2_4_0))
|
||||
return (version.parse(nsx_version) >=
|
||||
version.parse(v3_const.NSX_VERSION_2_4_0))
|
||||
|
||||
|
||||
def is_nsx_version_2_5_0(nsx_version):
|
||||
return (version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion(v3_const.NSX_VERSION_2_5_0))
|
||||
return (version.parse(nsx_version) >=
|
||||
version.parse(v3_const.NSX_VERSION_2_5_0))
|
||||
|
||||
|
||||
def is_nsx_version_3_0_0(nsx_version):
|
||||
return (version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion(v3_const.NSX_VERSION_3_0_0))
|
||||
return (version.parse(nsx_version) >=
|
||||
version.parse(v3_const.NSX_VERSION_3_0_0))
|
||||
|
||||
|
||||
def is_nsx_version_3_1_0(nsx_version):
|
||||
return (version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion(v3_const.NSX_VERSION_3_1_0))
|
||||
return (version.parse(nsx_version) >=
|
||||
version.parse(v3_const.NSX_VERSION_3_1_0))
|
||||
|
||||
|
||||
def is_nsx_version_3_2_0(nsx_version):
|
||||
return (version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion(v3_const.NSX_VERSION_3_2_0))
|
||||
return (version.parse(nsx_version) >=
|
||||
version.parse(v3_const.NSX_VERSION_3_2_0))
|
||||
|
||||
|
||||
def is_nsxv_version_6_2(nsx_version):
|
||||
return (version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion('6.2'))
|
||||
return (version.parse(nsx_version) >=
|
||||
version.parse('6.2'))
|
||||
|
||||
|
||||
def is_nsxv_version_6_3(nsx_version):
|
||||
return (version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion('6.3'))
|
||||
return (version.parse(nsx_version) >=
|
||||
version.parse('6.3'))
|
||||
|
||||
|
||||
def is_nsxv_version_6_4_6(nsx_version):
|
||||
return (version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion('6.4.6'))
|
||||
return (version.parse(nsx_version) >=
|
||||
version.parse('6.4.6'))
|
||||
|
||||
|
||||
def is_nsxv_version_6_4_9(nsx_version):
|
||||
return (version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion('6.4.9'))
|
||||
return (version.parse(nsx_version) >=
|
||||
version.parse('6.4.9'))
|
||||
|
||||
|
||||
def is_nsxv_dhcp_binding_supported(nsx_version):
|
||||
return ((version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion('6.3.3')) or
|
||||
(version.LooseVersion(nsx_version) >=
|
||||
version.LooseVersion('6.2.8') and
|
||||
version.LooseVersion(nsx_version) <
|
||||
version.LooseVersion('6.3')))
|
||||
return ((version.parse(nsx_version) >=
|
||||
version.parse('6.3.3')) or
|
||||
(version.parse(nsx_version) >=
|
||||
version.parse('6.2.8') and
|
||||
version.parse(nsx_version) <
|
||||
version.parse('6.3')))
|
||||
|
||||
|
||||
def get_tags(**kwargs):
|
||||
|
@ -13,7 +13,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from distutils import version
|
||||
import xml.etree.ElementTree as et
|
||||
|
||||
import netaddr
|
||||
@ -69,6 +68,7 @@ from oslo_serialization import jsonutils
|
||||
from oslo_utils import excutils
|
||||
from oslo_utils import netutils
|
||||
from oslo_utils import uuidutils
|
||||
from packaging import version
|
||||
from sqlalchemy.orm import exc as sa_exc
|
||||
|
||||
from neutron.api import extensions as neutron_extensions
|
||||
@ -452,7 +452,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
|
||||
def _validate_nsx_version(self):
|
||||
ver = self.nsx_v.vcns.get_version()
|
||||
if version.LooseVersion(ver) < version.LooseVersion('6.2.3'):
|
||||
if version.parse(ver) < version.parse('6.2.3'):
|
||||
error = _("Plugin version doesn't support NSX version %s.") % ver
|
||||
raise nsx_exc.NsxPluginException(err_msg=error)
|
||||
|
||||
@ -2280,8 +2280,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
LOG.info("Add VM %(dev)s to exclude list on behalf of "
|
||||
"port %(port)s: VM already in list",
|
||||
{"dev": device_id, "port": port_id})
|
||||
loose_ver = version.LooseVersion(self.nsx_v.vcns.get_version())
|
||||
if loose_ver < version.LooseVersion('6.3.3'):
|
||||
loose_ver = version.parse(self.nsx_v.vcns.get_version())
|
||||
if loose_ver < version.parse('6.3.3'):
|
||||
LOG.info("Syncing firewall")
|
||||
self.nsx_v.vcns.sync_firewall()
|
||||
|
||||
@ -3270,8 +3270,8 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
|
||||
def setup_dhcp_edge_fw_rules(self, context, plugin, router_id):
|
||||
rules = []
|
||||
loose_ver = version.LooseVersion(self.nsx_v.vcns.get_version())
|
||||
if loose_ver < version.LooseVersion('6.3.2'):
|
||||
loose_ver = version.parse(self.nsx_v.vcns.get_version())
|
||||
if loose_ver < version.parse('6.3.2'):
|
||||
# For these versions the raw icmp rule will not work due to
|
||||
# backend bug. Workaround: use applications, but since
|
||||
# application ids can change, we look them up by application name
|
||||
@ -4985,7 +4985,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
|
||||
def _configure_reservations(self):
|
||||
ver = self.nsx_v.vcns.get_version()
|
||||
if version.LooseVersion(ver) < version.LooseVersion('6.2.3'):
|
||||
if version.parse(ver) < version.parse('6.2.3'):
|
||||
LOG.debug("Skipping reservation configuration. "
|
||||
"Not supported by version - %s.", ver)
|
||||
return
|
||||
@ -5064,7 +5064,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
||||
res_name='mgt_net_moid', res_id=mgmt_net)
|
||||
|
||||
ver = self.nsx_v.vcns.get_version()
|
||||
if version.LooseVersion(ver) < version.LooseVersion('6.2.0'):
|
||||
if version.parse(ver) < version.parse('6.2.0'):
|
||||
LOG.warning("Skipping validations. Not supported by version.")
|
||||
return
|
||||
|
||||
|
@ -12,7 +12,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from distutils import version
|
||||
import random
|
||||
import time
|
||||
|
||||
@ -22,6 +21,7 @@ from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import excutils
|
||||
from packaging import version
|
||||
from sqlalchemy.orm import exc as sa_exc
|
||||
|
||||
from vmware_nsx._i18n import _
|
||||
@ -519,7 +519,7 @@ class EdgeApplianceDriver(object):
|
||||
edge_id, size)
|
||||
return
|
||||
ver = self.vcns.get_version()
|
||||
if version.LooseVersion(ver) < version.LooseVersion('6.2.3'):
|
||||
if version.parse(ver) < version.parse('6.2.3'):
|
||||
# remove some data that will make the update fail
|
||||
edge_utils.remove_irrelevant_keys_from_edge_request(edge)
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from distutils import version
|
||||
import os
|
||||
import random
|
||||
import time
|
||||
@ -34,6 +33,7 @@ from oslo_serialization import jsonutils
|
||||
from oslo_utils import excutils
|
||||
from oslo_utils import timeutils
|
||||
from oslo_utils import uuidutils
|
||||
from packaging import version
|
||||
from sqlalchemy import exc as db_base_exc
|
||||
from sqlalchemy.orm import exc as sa_exc
|
||||
|
||||
@ -227,7 +227,7 @@ class EdgeManager(object):
|
||||
|
||||
def _get_per_edge_rp_filter_state(self):
|
||||
ver = self.nsxv_manager.vcns.get_version()
|
||||
if version.LooseVersion(ver) < version.LooseVersion('6.2.0'):
|
||||
if version.parse(ver) < version.parse('6.2.0'):
|
||||
return False
|
||||
return True
|
||||
|
||||
@ -2428,7 +2428,7 @@ def update_nat_rules(nsxv_manager, context, router_id, snat, dnat, az=None):
|
||||
# from 6.2.4 onwards, unspecified vnic will result
|
||||
# in binding the rule to all interfaces
|
||||
ver = nsxv_manager.vcns.get_version()
|
||||
if version.LooseVersion(ver) < version.LooseVersion('6.2.4'):
|
||||
if version.parse(ver) < version.parse('6.2.4'):
|
||||
LOG.debug("NSX version %s requires explicit nat rule "
|
||||
"for each interface", ver)
|
||||
edge_id = binding['edge_id']
|
||||
|
@ -16,9 +16,10 @@
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from neutron_dynamic_routing.db import bgp_db # noqa
|
||||
|
||||
from vmware_nsx.api_client import client as nsx_client
|
||||
from vmware_nsx.api_client import eventlet_client
|
||||
from vmware_nsx import extensions
|
||||
|
@ -19,7 +19,6 @@ from neutron_lib.plugins import directory
|
||||
from oslo_config import cfg
|
||||
|
||||
from vmware_nsx.extension_drivers import dns_integration
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin as test_v_plugin
|
||||
from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_v3_plugin
|
||||
|
||||
|
||||
@ -84,15 +83,6 @@ class NsxDNSIntegrationTestCase(object):
|
||||
dns_assignment['fqdn'])
|
||||
|
||||
|
||||
class NsxVDNSIntegrationTestCase(NsxDNSIntegrationTestCase,
|
||||
test_v_plugin.NsxVPluginV2TestCase):
|
||||
|
||||
def setUp(self):
|
||||
cfg.CONF.set_override('nsx_extension_drivers', ['vmware_nsxv_dns'])
|
||||
cfg.CONF.set_override('dns_domain', self._domain)
|
||||
super(NsxVDNSIntegrationTestCase, self).setUp()
|
||||
|
||||
|
||||
class NsxV3DNSIntegrationTestCase(NsxDNSIntegrationTestCase,
|
||||
test_v3_plugin.NsxV3PluginTestCaseMixin):
|
||||
|
||||
|
@ -14,13 +14,11 @@
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef
|
||||
from neutron_lib.api.definitions import port_security as psec
|
||||
from oslo_config import cfg
|
||||
|
||||
from neutron.tests.unit.db import test_allowedaddresspairs_db as ext_pairs
|
||||
|
||||
from vmware_nsx.tests.unit.nsx_p import test_plugin as test_p_plugin
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin as test_nsx_v_plugin
|
||||
from vmware_nsx.tests.unit.nsx_v3 import test_constants as v3_constants
|
||||
from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_v3_plugin
|
||||
|
||||
@ -321,106 +319,3 @@ class TestAllowedAddressPairsNSXv3(test_v3_plugin.NsxV3PluginTestCaseMixin,
|
||||
|
||||
def test_create_port_security_false_allowed_address_pairs(self):
|
||||
self.skipTest('TBD')
|
||||
|
||||
|
||||
class TestAllowedAddressPairsNSXv(test_nsx_v_plugin.NsxVPluginV2TestCase,
|
||||
ext_pairs.TestAllowedAddressPairs):
|
||||
|
||||
def setUp(self, plugin='vmware_nsx.plugin.NsxVPlugin',
|
||||
ext_mgr=None,
|
||||
service_plugins=None):
|
||||
super(TestAllowedAddressPairsNSXv, self).setUp(
|
||||
plugin=plugin, ext_mgr=ext_mgr, service_plugins=service_plugins)
|
||||
|
||||
def test_create_port_security_false_allowed_address_pairs(self):
|
||||
self.skipTest('TBD')
|
||||
|
||||
def test_update_port_security_off_address_pairs(self):
|
||||
self.skipTest('Not supported')
|
||||
|
||||
def test_create_overlap_with_fixed_ip(self):
|
||||
address_pairs = [{'ip_address': '10.0.0.2'}]
|
||||
with self.network() as network:
|
||||
with self.subnet(network=network, cidr='10.0.0.0/24',
|
||||
enable_dhcp=False) as subnet:
|
||||
fixed_ips = [{'subnet_id': subnet['subnet']['id'],
|
||||
'ip_address': '10.0.0.2'}]
|
||||
res = self._create_port(self.fmt, network['network']['id'],
|
||||
arg_list=(addr_apidef.ADDRESS_PAIRS,
|
||||
'fixed_ips'),
|
||||
allowed_address_pairs=address_pairs,
|
||||
fixed_ips=fixed_ips)
|
||||
self.assertEqual(res.status_int, 201)
|
||||
port = self.deserialize(self.fmt, res)
|
||||
self._delete('ports', port['port']['id'])
|
||||
|
||||
def test_create_port_allowed_address_pairs(self):
|
||||
with self.network() as net:
|
||||
address_pairs = [{'ip_address': '10.0.0.1'}]
|
||||
res = self._create_port(self.fmt, net['network']['id'],
|
||||
arg_list=(addr_apidef.ADDRESS_PAIRS,),
|
||||
allowed_address_pairs=address_pairs)
|
||||
port = self.deserialize(self.fmt, res)
|
||||
address_pairs[0]['mac_address'] = port['port']['mac_address']
|
||||
self.assertEqual(port['port'][addr_apidef.ADDRESS_PAIRS],
|
||||
address_pairs)
|
||||
self._delete('ports', port['port']['id'])
|
||||
|
||||
def _test_create_port_remove_allowed_address_pairs(self, update_value):
|
||||
with self.network() as net:
|
||||
address_pairs = [{'ip_address': '10.0.0.1'}]
|
||||
res = self._create_port(self.fmt, net['network']['id'],
|
||||
arg_list=(addr_apidef.ADDRESS_PAIRS,),
|
||||
allowed_address_pairs=address_pairs)
|
||||
port = self.deserialize(self.fmt, res)
|
||||
update_port = {'port': {addr_apidef.ADDRESS_PAIRS: []}}
|
||||
req = self.new_update_request('ports', update_port,
|
||||
port['port']['id'])
|
||||
port = self.deserialize(self.fmt, req.get_response(self.api))
|
||||
self.assertEqual(port['port'][addr_apidef.ADDRESS_PAIRS], [])
|
||||
self._delete('ports', port['port']['id'])
|
||||
|
||||
def test_update_add_address_pairs(self):
|
||||
with self.network() as net:
|
||||
res = self._create_port(self.fmt, net['network']['id'])
|
||||
port = self.deserialize(self.fmt, res)
|
||||
address_pairs = [{'ip_address': '10.0.0.1'}]
|
||||
update_port = {'port': {addr_apidef.ADDRESS_PAIRS:
|
||||
address_pairs}}
|
||||
req = self.new_update_request('ports', update_port,
|
||||
port['port']['id'])
|
||||
port = self.deserialize(self.fmt, req.get_response(self.api))
|
||||
address_pairs[0]['mac_address'] = port['port']['mac_address']
|
||||
self.assertEqual(port['port'][addr_apidef.ADDRESS_PAIRS],
|
||||
address_pairs)
|
||||
self._delete('ports', port['port']['id'])
|
||||
|
||||
def test_mac_configuration(self):
|
||||
address_pairs = [{'mac_address': '00:00:00:00:00:01',
|
||||
'ip_address': '10.0.0.1'}]
|
||||
self._create_port_with_address_pairs(address_pairs, 400)
|
||||
|
||||
def test_equal_to_max_allowed_address_pair(self):
|
||||
cfg.CONF.set_default('max_allowed_address_pair', 3)
|
||||
address_pairs = [{'ip_address': '10.0.0.1'},
|
||||
{'ip_address': '10.0.0.2'},
|
||||
{'ip_address': '10.0.0.3'}]
|
||||
self._create_port_with_address_pairs(address_pairs, 201)
|
||||
|
||||
def test_create_port_security_true_allowed_address_pairs(self):
|
||||
if self._skip_port_security:
|
||||
self.skipTest("Plugin does not implement port-security extension")
|
||||
|
||||
with self.network() as net:
|
||||
address_pairs = [{'ip_address': '10.0.0.1'}]
|
||||
res = self._create_port(self.fmt, net['network']['id'],
|
||||
arg_list=('port_security_enabled',
|
||||
addr_apidef.ADDRESS_PAIRS,),
|
||||
port_security_enabled=True,
|
||||
allowed_address_pairs=address_pairs)
|
||||
port = self.deserialize(self.fmt, res)
|
||||
self.assertTrue(port['port'][psec.PORTSECURITY])
|
||||
address_pairs[0]['mac_address'] = port['port']['mac_address']
|
||||
self.assertEqual(port['port'][addr_apidef.ADDRESS_PAIRS],
|
||||
address_pairs)
|
||||
self._delete('ports', port['port']['id'])
|
||||
|
@ -12,16 +12,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_db
|
||||
from neutron_lib.db import api as db_api
|
||||
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.extensions import dhcp_mtu as ext_dhcp_mtu
|
||||
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin
|
||||
from vmware_nsx.tests.unit.nsx_v.vshield import fake_vcns
|
||||
|
||||
PLUGIN_NAME = 'vmware_nsx.plugin.NsxVPlugin'
|
||||
|
||||
@ -41,87 +36,6 @@ class DhcpMtuExtensionManager(object):
|
||||
return ext_dhcp_mtu.get_extended_resources(version)
|
||||
|
||||
|
||||
class DhcpMtuExtensionTestCase(test_plugin.NsxVPluginV2TestCase):
|
||||
"""Test API extension dhcp-mtu attribute of subnets."""
|
||||
|
||||
@mock.patch.object(edge_utils.EdgeManager, '_deploy_edge')
|
||||
def setUp(self, plugin=PLUGIN_NAME):
|
||||
ext_mgr = DhcpMtuExtensionManager()
|
||||
# This feature is enabled only since 6.2.3
|
||||
with mock.patch.object(fake_vcns.FakeVcns,
|
||||
'get_version',
|
||||
return_value="6.2.3"):
|
||||
super(DhcpMtuExtensionTestCase, self).setUp(ext_mgr=ext_mgr)
|
||||
|
||||
def _create_subnet_with_dhcp_mtu(self, dhcp_mtu):
|
||||
with self.network() as net:
|
||||
tenant_id = net['network']['tenant_id']
|
||||
net_id = net['network']['id']
|
||||
data = {'subnet': {'network_id': net_id,
|
||||
'cidr': '10.0.0.0/24',
|
||||
'ip_version': 4,
|
||||
'name': 'test-mtu-subnet',
|
||||
'tenant_id': tenant_id,
|
||||
'dhcp_mtu': dhcp_mtu}}
|
||||
subnet_req = self.new_create_request('subnets', data)
|
||||
res = subnet_req.get_response(self.api)
|
||||
return res
|
||||
|
||||
def test_subnet_create_with_dhcp_mtu(self):
|
||||
for mtu in (68, 2000, 65535):
|
||||
res = self._create_subnet_with_dhcp_mtu(mtu)
|
||||
sub = self.deserialize(self.fmt, res)
|
||||
self.assertEqual(mtu, sub['subnet']['dhcp_mtu'])
|
||||
|
||||
def test_subnet_create_with_invalid_dhcp_mtu_fail(self):
|
||||
res = self._create_subnet_with_dhcp_mtu(67)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
res = self._create_subnet_with_dhcp_mtu(100000)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
def test_subnet_update_with_dhcp_mtu(self):
|
||||
res = self._create_subnet_with_dhcp_mtu(2000)
|
||||
sub = self.deserialize(self.fmt, res)
|
||||
data = {'subnet': {'dhcp_mtu': 3000}}
|
||||
req = self.new_update_request('subnets', data, sub['subnet']['id'])
|
||||
updated_sub = self.deserialize(self.fmt, req.get_response(self.api))
|
||||
self.assertEqual(3000, updated_sub['subnet']['dhcp_mtu'])
|
||||
|
||||
def _create_subnet_with_dhcp_mtu_and_dns(self, dhcp_mtu,
|
||||
dns_search_domain):
|
||||
with self.network() as net:
|
||||
tenant_id = net['network']['tenant_id']
|
||||
net_id = net['network']['id']
|
||||
data = {'subnet': {'network_id': net_id,
|
||||
'cidr': '10.0.0.0/24',
|
||||
'ip_version': 4,
|
||||
'name': 'test-mtu-subnet',
|
||||
'tenant_id': tenant_id,
|
||||
'dhcp_mtu': dhcp_mtu,
|
||||
'dns_search_domain': dns_search_domain}}
|
||||
subnet_req = self.new_create_request('subnets', data)
|
||||
res = subnet_req.get_response(self.api)
|
||||
return res
|
||||
|
||||
def test_subnet_create_with_dhcp_mtu_and_dns(self):
|
||||
res = self._create_subnet_with_dhcp_mtu_and_dns(2000, 'vmware.com')
|
||||
sub = self.deserialize(self.fmt, res)
|
||||
self.assertEqual(2000, sub['subnet']['dhcp_mtu'])
|
||||
self.assertEqual('vmware.com', sub['subnet']['dns_search_domain'])
|
||||
|
||||
def test_subnet_update_with_dhcp_mtu_and_dns(self):
|
||||
res = self._create_subnet_with_dhcp_mtu_and_dns(2000, 'vmware.com')
|
||||
sub = self.deserialize(self.fmt, res)
|
||||
data = {'subnet': {'dhcp_mtu': 3000,
|
||||
'dns_search_domain': 'eng.vmware.com'}}
|
||||
req = self.new_update_request('subnets', data, sub['subnet']['id'])
|
||||
updated_sub = self.deserialize(self.fmt, req.get_response(self.api))
|
||||
self.assertEqual(3000, updated_sub['subnet']['dhcp_mtu'])
|
||||
self.assertEqual('eng.vmware.com',
|
||||
updated_sub['subnet']['dns_search_domain'])
|
||||
|
||||
|
||||
class DhcpMtuDBTestCase(test_db.NeutronDbPluginV2TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -12,15 +12,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_db
|
||||
from neutron_lib.db import api as db_api
|
||||
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.extensions import dns_search_domain as ext_dns_search_domain
|
||||
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin
|
||||
|
||||
PLUGIN_NAME = 'vmware_nsx.plugin.NsxVPlugin'
|
||||
|
||||
@ -40,47 +36,6 @@ class DnsSearchDomainExtensionManager(object):
|
||||
return ext_dns_search_domain.get_extended_resources(version)
|
||||
|
||||
|
||||
class DnsSearchDomainExtensionTestCase(test_plugin.NsxVPluginV2TestCase):
|
||||
"""Test API extension dns-search-domain attribute."""
|
||||
|
||||
@mock.patch.object(edge_utils.EdgeManager, '_deploy_edge')
|
||||
def setUp(self, plugin=PLUGIN_NAME):
|
||||
ext_mgr = DnsSearchDomainExtensionManager()
|
||||
super(DnsSearchDomainExtensionTestCase, self).setUp(ext_mgr=ext_mgr)
|
||||
|
||||
def _create_subnet_with_dns_search_domain(self, dns_search_domain):
|
||||
with self.network() as net:
|
||||
tenant_id = net['network']['tenant_id']
|
||||
net_id = net['network']['id']
|
||||
data = {'subnet': {'network_id': net_id,
|
||||
'cidr': '10.0.0.0/24',
|
||||
'ip_version': 4,
|
||||
'name': 'test-dns-search-domain-subnet',
|
||||
'tenant_id': tenant_id,
|
||||
'dns_search_domain': dns_search_domain}}
|
||||
subnet_req = self.new_create_request('subnets', data)
|
||||
res = subnet_req.get_response(self.api)
|
||||
return res
|
||||
|
||||
def test_subnet_create_with_dns_search_domain(self):
|
||||
res = self._create_subnet_with_dns_search_domain('vmware.com')
|
||||
sub = self.deserialize(self.fmt, res)
|
||||
self.assertEqual('vmware.com', sub['subnet']['dns_search_domain'])
|
||||
|
||||
def test_subnet_create_with_invalid_dns_search_domain_fail(self):
|
||||
res = self._create_subnet_with_dns_search_domain('vmw@re.com')
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
def test_subnet_update_with_dns_search_domain(self):
|
||||
res = self._create_subnet_with_dns_search_domain('vmware.com')
|
||||
sub = self.deserialize(self.fmt, res)
|
||||
data = {'subnet': {'dns_search_domain': 'eng.vmware.com'}}
|
||||
req = self.new_update_request('subnets', data, sub['subnet']['id'])
|
||||
updated_sub = self.deserialize(self.fmt, req.get_response(self.api))
|
||||
self.assertEqual('eng.vmware.com',
|
||||
updated_sub['subnet']['dns_search_domain'])
|
||||
|
||||
|
||||
class DnsSearchDomainDBTestCase(test_db.NeutronDbPluginV2TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -26,7 +26,6 @@ import webob.exc
|
||||
from vmware_nsx.db import extended_security_group
|
||||
from vmware_nsx.extensions import providersecuritygroup as provider_sg
|
||||
from vmware_nsx.tests.unit.nsx_p import test_plugin as test_nsxp_plugin
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin as test_nsxv_plugin
|
||||
from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_nsxv3_plugin
|
||||
|
||||
|
||||
@ -362,38 +361,6 @@ class TestNSXv3ProviderSecurityGrp(test_nsxv3_plugin.NsxV3PluginTestCaseMixin,
|
||||
port['port']['security_groups'])
|
||||
|
||||
|
||||
class TestNSXvProviderSecurityGroup(test_nsxv_plugin.NsxVPluginV2TestCase,
|
||||
ProviderSecurityGroupExtTestCase):
|
||||
def test_create_provider_security_group(self):
|
||||
_create_section_tmp = self.fc2.create_section
|
||||
|
||||
def _create_section(*args, **kwargs):
|
||||
return _create_section_tmp(*args, **kwargs)
|
||||
|
||||
with mock.patch.object(self.fc2, 'create_section',
|
||||
side_effect=_create_section) as create_sec_mock:
|
||||
super(TestNSXvProviderSecurityGroup,
|
||||
self).test_create_provider_security_group()
|
||||
create_sec_mock.assert_called_with('ip', mock.ANY,
|
||||
insert_top=True,
|
||||
insert_before=mock.ANY)
|
||||
|
||||
def test_create_provider_security_group_rule(self):
|
||||
provider_secgroup = self._create_provider_security_group()
|
||||
sg_id = provider_secgroup['security_group']['id']
|
||||
_create_nsx_rule_tmp = self.plugin._create_nsx_rule
|
||||
|
||||
def m_create_nsx_rule(*args, **kwargs):
|
||||
return _create_nsx_rule_tmp(*args, **kwargs)
|
||||
|
||||
with mock.patch.object(self.plugin, '_create_nsx_rule',
|
||||
side_effect=m_create_nsx_rule) as create_rule_m:
|
||||
with self.security_group_rule(security_group_id=sg_id):
|
||||
create_rule_m.assert_called_with(mock.ANY, mock.ANY,
|
||||
logged=mock.ANY,
|
||||
action='deny')
|
||||
|
||||
|
||||
class TestNSXpProviderSecurityGrp(test_nsxp_plugin.NsxPPluginTestCaseMixin,
|
||||
ProviderSecurityGroupExtTestCase):
|
||||
|
||||
|
@ -1,180 +0,0 @@
|
||||
# Copyright (c) 2014 OpenStack Foundation.
|
||||
# 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.
|
||||
|
||||
from oslo_config import cfg
|
||||
import webob.exc
|
||||
|
||||
from neutron_lib.api.definitions import multiprovidernet as mpnet_apidef
|
||||
from neutron_lib.api.definitions import provider_net as pnet
|
||||
from vmware_nsx.tests import unit as vmware
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin as test_nsxv
|
||||
|
||||
|
||||
class TestProvidernet(test_nsxv.NsxVPluginV2TestCase):
|
||||
|
||||
def test_create_delete_provider_network_default_physical_net(self):
|
||||
'''Leaves physical_net unspecified'''
|
||||
data = {'network': {'name': 'net1',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'admin',
|
||||
pnet.NETWORK_TYPE: 'vlan',
|
||||
pnet.SEGMENTATION_ID: 411}}
|
||||
network_req = self.new_create_request('networks', data, self.fmt)
|
||||
net = self.deserialize(self.fmt, network_req.get_response(self.api))
|
||||
self.assertEqual(net['network'][pnet.NETWORK_TYPE], 'vlan')
|
||||
self.assertEqual(net['network'][pnet.SEGMENTATION_ID], 411)
|
||||
req = self.new_delete_request('networks', net['network']['id'])
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code)
|
||||
|
||||
def test_create_delete_provider_network_default_physical_net_2(self):
|
||||
'''Uses the 'default' keyword as physical_net'''
|
||||
data = {'network': {'name': 'net1',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'admin',
|
||||
pnet.NETWORK_TYPE: 'vlan',
|
||||
pnet.SEGMENTATION_ID: 411,
|
||||
pnet.PHYSICAL_NETWORK: 'default'}}
|
||||
network_req = self.new_create_request('networks', data, self.fmt)
|
||||
net = self.deserialize(self.fmt, network_req.get_response(self.api))
|
||||
self.assertEqual(net['network'][pnet.NETWORK_TYPE], 'vlan')
|
||||
self.assertEqual(net['network'][pnet.SEGMENTATION_ID], 411)
|
||||
req = self.new_delete_request('networks', net['network']['id'])
|
||||
res = req.get_response(self.api)
|
||||
self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code)
|
||||
|
||||
def test_create_provider_network(self):
|
||||
data = {'network': {'name': 'net1',
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'admin',
|
||||
pnet.NETWORK_TYPE: 'vlan',
|
||||
pnet.SEGMENTATION_ID: 411,
|
||||
pnet.PHYSICAL_NETWORK: 'physnet1'}}
|
||||
network_req = self.new_create_request('networks', data, self.fmt)
|
||||
net = self.deserialize(self.fmt, network_req.get_response(self.api))
|
||||
self.assertEqual(net['network'][pnet.NETWORK_TYPE], 'vlan')
|
||||
self.assertEqual(net['network'][pnet.SEGMENTATION_ID], 411)
|
||||
self.assertEqual(net['network'][pnet.PHYSICAL_NETWORK], 'physnet1')
|
||||
|
||||
# Test that we can create another provider network using the same
|
||||
# vlan_id on another physical network.
|
||||
data['network'][pnet.PHYSICAL_NETWORK] = 'physnet2'
|
||||
network_req = self.new_create_request('networks', data, self.fmt)
|
||||
net = self.deserialize(self.fmt, network_req.get_response(self.api))
|
||||
self.assertEqual(net['network'][pnet.NETWORK_TYPE], 'vlan')
|
||||
self.assertEqual(net['network'][pnet.SEGMENTATION_ID], 411)
|
||||
self.assertEqual(net['network'][pnet.PHYSICAL_NETWORK], 'physnet2')
|
||||
|
||||
|
||||
class TestMultiProviderNetworks(test_nsxv.NsxVPluginV2TestCase):
|
||||
|
||||
def setUp(self, plugin=None):
|
||||
cfg.CONF.set_override('api_extensions_path', vmware.NSXEXT_PATH)
|
||||
super(TestMultiProviderNetworks, self).setUp()
|
||||
|
||||
def test_create_network_provider(self):
|
||||
data = {'network': {'name': 'net1',
|
||||
pnet.NETWORK_TYPE: 'vlan',
|
||||
pnet.PHYSICAL_NETWORK: 'physnet1',
|
||||
pnet.SEGMENTATION_ID: 1,
|
||||
'tenant_id': 'tenant_one'}}
|
||||
network_req = self.new_create_request('networks', data)
|
||||
network = self.deserialize(self.fmt,
|
||||
network_req.get_response(self.api))
|
||||
self.assertEqual(network['network'][pnet.NETWORK_TYPE], 'vlan')
|
||||
self.assertEqual(network['network'][pnet.PHYSICAL_NETWORK], 'physnet1')
|
||||
self.assertEqual(network['network'][pnet.SEGMENTATION_ID], 1)
|
||||
self.assertNotIn(mpnet_apidef.SEGMENTS, network['network'])
|
||||
|
||||
def test_create_network_provider_flat(self):
|
||||
data = {'network': {'name': 'net1',
|
||||
pnet.NETWORK_TYPE: 'flat',
|
||||
pnet.PHYSICAL_NETWORK: 'physnet1',
|
||||
'tenant_id': 'tenant_one'}}
|
||||
network_req = self.new_create_request('networks', data)
|
||||
network = self.deserialize(self.fmt,
|
||||
network_req.get_response(self.api))
|
||||
self.assertEqual('flat', network['network'][pnet.NETWORK_TYPE])
|
||||
self.assertEqual('physnet1', network['network'][pnet.PHYSICAL_NETWORK])
|
||||
self.assertEqual(0, network['network'][pnet.SEGMENTATION_ID])
|
||||
self.assertNotIn(mpnet_apidef.SEGMENTS, network['network'])
|
||||
|
||||
def test_create_network_single_multiple_provider(self):
|
||||
data = {'network': {'name': 'net1',
|
||||
mpnet_apidef.SEGMENTS:
|
||||
[{pnet.NETWORK_TYPE: 'vlan',
|
||||
pnet.PHYSICAL_NETWORK: 'physnet1',
|
||||
pnet.SEGMENTATION_ID: 1}],
|
||||
'tenant_id': 'tenant_one'}}
|
||||
net_req = self.new_create_request('networks', data)
|
||||
network = self.deserialize(self.fmt, net_req.get_response(self.api))
|
||||
for provider_field in [pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK,
|
||||
pnet.SEGMENTATION_ID]:
|
||||
self.assertNotIn(provider_field, network['network'])
|
||||
tz = network['network'][mpnet_apidef.SEGMENTS][0]
|
||||
self.assertEqual(tz[pnet.NETWORK_TYPE], 'vlan')
|
||||
self.assertEqual(tz[pnet.PHYSICAL_NETWORK], 'physnet1')
|
||||
self.assertEqual(tz[pnet.SEGMENTATION_ID], 1)
|
||||
|
||||
# Tests get_network()
|
||||
net_req = self.new_show_request('networks', network['network']['id'])
|
||||
network = self.deserialize(self.fmt, net_req.get_response(self.api))
|
||||
tz = network['network'][mpnet_apidef.SEGMENTS][0]
|
||||
self.assertEqual(tz[pnet.NETWORK_TYPE], 'vlan')
|
||||
self.assertEqual(tz[pnet.PHYSICAL_NETWORK], 'physnet1')
|
||||
self.assertEqual(tz[pnet.SEGMENTATION_ID], 1)
|
||||
|
||||
def test_create_network_multprovider(self):
|
||||
data = {'network': {'name': 'net1',
|
||||
mpnet_apidef.SEGMENTS:
|
||||
[{pnet.NETWORK_TYPE: 'vlan',
|
||||
pnet.PHYSICAL_NETWORK: 'physnet1',
|
||||
pnet.SEGMENTATION_ID: 1},
|
||||
{pnet.NETWORK_TYPE: 'vlan',
|
||||
pnet.PHYSICAL_NETWORK: 'physnet2',
|
||||
pnet.SEGMENTATION_ID: 2}],
|
||||
'tenant_id': 'tenant_one'}}
|
||||
network_req = self.new_create_request('networks', data)
|
||||
network = self.deserialize(self.fmt,
|
||||
network_req.get_response(self.api))
|
||||
tz = network['network'][mpnet_apidef.SEGMENTS]
|
||||
for tz in data['network'][mpnet_apidef.SEGMENTS]:
|
||||
for field in [pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK,
|
||||
pnet.SEGMENTATION_ID]:
|
||||
self.assertEqual(tz.get(field), tz.get(field))
|
||||
|
||||
# Tests get_network()
|
||||
net_req = self.new_show_request('networks', network['network']['id'])
|
||||
network = self.deserialize(self.fmt, net_req.get_response(self.api))
|
||||
tz = network['network'][mpnet_apidef.SEGMENTS]
|
||||
for tz in data['network'][mpnet_apidef.SEGMENTS]:
|
||||
for field in [pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK,
|
||||
pnet.SEGMENTATION_ID]:
|
||||
self.assertEqual(tz.get(field), tz.get(field))
|
||||
|
||||
def test_create_network_with_provider_and_multiprovider_fail(self):
|
||||
data = {'network': {'name': 'net1',
|
||||
mpnet_apidef.SEGMENTS:
|
||||
[{pnet.NETWORK_TYPE: 'vlan',
|
||||
pnet.PHYSICAL_NETWORK: 'physnet1',
|
||||
pnet.SEGMENTATION_ID: 1}],
|
||||
pnet.NETWORK_TYPE: 'vlan',
|
||||
pnet.PHYSICAL_NETWORK: 'physnet1',
|
||||
pnet.SEGMENTATION_ID: 1,
|
||||
'tenant_id': 'tenant_one'}}
|
||||
|
||||
network_req = self.new_create_request('networks', data)
|
||||
res = network_req.get_response(self.api)
|
||||
self.assertEqual(res.status_int, 400)
|
@ -21,15 +21,12 @@ from neutron.extensions import securitygroup as ext_sg
|
||||
from neutron.tests.unit.extensions import test_securitygroup
|
||||
from neutron_lib import constants as const
|
||||
from neutron_lib.db import api as db_api
|
||||
from neutron_lib.plugins import directory
|
||||
from oslo_utils import uuidutils
|
||||
import webob.exc
|
||||
|
||||
from vmware_nsx.db import extended_security_group_rule as ext_rule_db
|
||||
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix as ext_loip
|
||||
from vmware_nsx.plugins.nsx_v.vshield import securitygroup_utils
|
||||
from vmware_nsx.tests.unit.nsx_p import test_plugin as test_nsxp_plugin
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin as test_nsxv_plugin
|
||||
from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_nsxv3_plugin
|
||||
|
||||
|
||||
@ -95,24 +92,6 @@ class LocalIPPrefixExtTestCase(test_securitygroup.SecurityGroupDBTestCase):
|
||||
res['security_group_rule']['local_ip_prefix'])
|
||||
|
||||
|
||||
class TestNsxVExtendedSGRule(test_nsxv_plugin.NsxVSecurityGroupsTestCase,
|
||||
LocalIPPrefixExtTestCase):
|
||||
def test_create_rule_with_local_ip_prefix(self):
|
||||
sg_utils = securitygroup_utils.NsxSecurityGroupUtils(None)
|
||||
local_ip_prefix = '239.255.0.0/16'
|
||||
plugin = directory.get_plugin()
|
||||
dest = {'type': 'Ipv4Address', 'value': local_ip_prefix}
|
||||
|
||||
plugin.nsx_sg_utils.get_rule_config = mock.Mock(
|
||||
side_effect=sg_utils.get_rule_config)
|
||||
super(TestNsxVExtendedSGRule,
|
||||
self).test_create_rule_with_local_ip_prefix()
|
||||
plugin.nsx_sg_utils.get_rule_config.assert_called_with(
|
||||
source=mock.ANY, destination=dest, services=mock.ANY,
|
||||
name=mock.ANY, applied_to_ids=mock.ANY, flags=mock.ANY,
|
||||
logged=mock.ANY, action=mock.ANY, tag=mock.ANY, notes=mock.ANY)
|
||||
|
||||
|
||||
class TestNSXv3ExtendedSGRule(test_nsxv3_plugin.NsxV3PluginTestCaseMixin,
|
||||
LocalIPPrefixExtTestCase):
|
||||
def test_create_rule_with_local_ip_prefix(self):
|
||||
|
@ -1,254 +0,0 @@
|
||||
# Copyright 2016 VMware, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from oslo_config import cfg
|
||||
import webob.exc
|
||||
|
||||
from neutron.extensions import securitygroup as ext_sg
|
||||
from neutron.tests.unit.api import test_extensions
|
||||
from neutron.tests.unit.db import test_db_base_plugin_v2
|
||||
from neutron.tests.unit.extensions import test_securitygroup
|
||||
from neutron_lib import constants
|
||||
from neutron_lib import context
|
||||
from neutron_lib import exceptions as n_exc
|
||||
|
||||
from vmware_nsx.extensions import nsxpolicy
|
||||
from vmware_nsx.extensions import securitygrouplogging as ext_logging
|
||||
from vmware_nsx.extensions import securitygrouppolicy as ext_policy
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin
|
||||
from vmware_nsx.tests.unit.nsx_v.vshield import fake_vcns
|
||||
|
||||
PLUGIN_NAME = 'vmware_nsx.plugin.NsxVPlugin'
|
||||
|
||||
|
||||
class SecGroupPolicyExtensionTestCase(
|
||||
test_plugin.NsxVPluginV2TestCase,
|
||||
test_securitygroup.SecurityGroupDBTestCase):
|
||||
def setUp(self, plugin=PLUGIN_NAME, ext_mgr=None):
|
||||
cfg.CONF.set_override('use_nsx_policies', True, group='nsxv')
|
||||
cfg.CONF.set_override('default_policy_id', 'policy-1', group='nsxv')
|
||||
# This feature is enabled only since 6.2
|
||||
with mock.patch.object(fake_vcns.FakeVcns,
|
||||
'get_version',
|
||||
return_value="6.2.3"):
|
||||
super(SecGroupPolicyExtensionTestCase, self).setUp(
|
||||
plugin=plugin, ext_mgr=ext_mgr)
|
||||
self._tenant_id = test_db_base_plugin_v2.TEST_TENANT_ID
|
||||
# add policy & logging security group attribute
|
||||
ext_sg.Securitygroup().update_attributes_map(
|
||||
ext_policy.RESOURCE_ATTRIBUTE_MAP)
|
||||
ext_sg.Securitygroup().update_attributes_map(
|
||||
ext_logging.RESOURCE_ATTRIBUTE_MAP)
|
||||
|
||||
def _create_secgroup_with_policy(self, policy_id, description=None,
|
||||
logging=False):
|
||||
body = {'security_group':
|
||||
{'name': 'sg-policy',
|
||||
'tenant_id': self._tenant_id,
|
||||
'policy': policy_id,
|
||||
'description': description if description else '',
|
||||
'logging': logging}}
|
||||
return self._create_security_group_response(self.fmt, body)
|
||||
|
||||
def _get_secgroup_with_policy(self):
|
||||
policy_id = 'policy-5'
|
||||
res = self._create_secgroup_with_policy(policy_id)
|
||||
return self.deserialize(self.fmt, res)
|
||||
|
||||
def test_secgroup_create_with_policy(self):
|
||||
policy_id = 'policy-5'
|
||||
res = self._create_secgroup_with_policy(policy_id)
|
||||
sg = self.deserialize(self.fmt, res)
|
||||
self.assertEqual(policy_id, sg['security_group']['policy'])
|
||||
self.assertEqual('dummy', sg['security_group']['description'])
|
||||
|
||||
def test_secgroup_create_with_policyand_desc(self):
|
||||
policy_id = 'policy-5'
|
||||
desc = 'test'
|
||||
res = self._create_secgroup_with_policy(policy_id, description=desc)
|
||||
sg = self.deserialize(self.fmt, res)
|
||||
self.assertEqual(policy_id, sg['security_group']['policy'])
|
||||
self.assertEqual(desc, sg['security_group']['description'])
|
||||
|
||||
def test_secgroup_create_without_policy(self):
|
||||
res = self._create_secgroup_with_policy(None)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
def test_secgroup_create_with_illegal_policy(self):
|
||||
policy_id = 'bad-policy'
|
||||
with mock.patch(PLUGIN_NAME + '.get_nsx_policy',
|
||||
side_effect=n_exc.ObjectNotFound(id=policy_id)):
|
||||
res = self._create_secgroup_with_policy(policy_id)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
def test_secgroup_create_with_policy_and_logging(self):
|
||||
# We do not support policy & logging together
|
||||
policy_id = 'policy-5'
|
||||
res = self._create_secgroup_with_policy(policy_id, logging=True)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
def test_secgroup_update_with_policy(self):
|
||||
# Test that updating the policy is allowed
|
||||
old_policy = 'policy-5'
|
||||
new_policy = 'policy-6'
|
||||
res = self._create_secgroup_with_policy(old_policy)
|
||||
sg = self.deserialize(self.fmt, res)
|
||||
data = {'security_group': {'policy': new_policy}}
|
||||
req = self.new_update_request('security-groups', data,
|
||||
sg['security_group']['id'])
|
||||
updated_sg = self.deserialize(self.fmt, req.get_response(self.ext_api))
|
||||
self.assertEqual(new_policy, updated_sg['security_group']['policy'])
|
||||
# Verify the same result in 'get'
|
||||
req = self.new_show_request('security-groups',
|
||||
sg['security_group']['id'])
|
||||
shown_sg = self.deserialize(self.fmt, req.get_response(self.ext_api))
|
||||
self.assertEqual(new_policy, shown_sg['security_group']['policy'])
|
||||
|
||||
def test_secgroup_update_no_policy_change(self):
|
||||
# Test updating without changing the policy
|
||||
old_policy = 'policy-5'
|
||||
desc = 'abc'
|
||||
res = self._create_secgroup_with_policy(old_policy)
|
||||
sg = self.deserialize(self.fmt, res)
|
||||
data = {'security_group': {'description': desc}}
|
||||
req = self.new_update_request('security-groups', data,
|
||||
sg['security_group']['id'])
|
||||
updated_sg = self.deserialize(self.fmt, req.get_response(self.ext_api))
|
||||
self.assertEqual(old_policy, updated_sg['security_group']['policy'])
|
||||
self.assertEqual(desc, updated_sg['security_group']['description'])
|
||||
|
||||
def test_secgroup_update_remove_policy(self):
|
||||
# removing the policy is not allowed
|
||||
sg = self._get_secgroup_with_policy()
|
||||
data = {'security_group': {'policy': None}}
|
||||
req = self.new_update_request('security-groups', data,
|
||||
sg['security_group']['id'])
|
||||
res = req.get_response(self.ext_api)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
def test_secgroup_update_add_logging(self):
|
||||
# We do not support policy & logging together
|
||||
sg = self._get_secgroup_with_policy()
|
||||
data = {'security_group': {'logging': True}}
|
||||
req = self.new_update_request('security-groups', data,
|
||||
sg['security_group']['id'])
|
||||
res = req.get_response(self.ext_api)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
def test_non_admin_cannot_delete_policy_sg_and_admin_can(self):
|
||||
sg = self._get_secgroup_with_policy()
|
||||
sg_id = sg['security_group']['id']
|
||||
|
||||
# Try deleting the request as a normal user returns forbidden
|
||||
# as a tenant is not allowed to delete this.
|
||||
ctx = context.Context('', self._tenant_id)
|
||||
self._delete('security-groups', sg_id,
|
||||
expected_code=webob.exc.HTTPForbidden.code,
|
||||
neutron_context=ctx)
|
||||
# can be deleted though as admin
|
||||
self._delete('security-groups', sg_id,
|
||||
expected_code=webob.exc.HTTPNoContent.code)
|
||||
|
||||
def test_create_rule(self):
|
||||
sg = self._get_secgroup_with_policy()
|
||||
rule = self._build_security_group_rule(
|
||||
sg['security_group']['id'], 'ingress',
|
||||
constants.PROTO_NAME_TCP, '22', '22')
|
||||
res = self._create_security_group_rule(self.fmt, rule)
|
||||
self.deserialize(self.fmt, res)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
|
||||
class SecGroupPolicyExtensionTestCaseWithRules(
|
||||
SecGroupPolicyExtensionTestCase):
|
||||
|
||||
def setUp(self, plugin=PLUGIN_NAME, ext_mgr=None):
|
||||
cfg.CONF.set_override('allow_tenant_rules_with_policy',
|
||||
True, group='nsxv')
|
||||
super(SecGroupPolicyExtensionTestCaseWithRules, self).setUp(
|
||||
plugin=plugin, ext_mgr=ext_mgr)
|
||||
|
||||
def test_secgroup_create_without_policy(self):
|
||||
# in case allow_tenant_rules_with_policy is True, it is allowed to
|
||||
# create a regular sg
|
||||
desc = 'test'
|
||||
res = self._create_secgroup_with_policy(None, description=desc)
|
||||
sg = self.deserialize(self.fmt, res)
|
||||
self.assertIsNone(sg['security_group']['policy'])
|
||||
self.assertEqual(desc, sg['security_group']['description'])
|
||||
|
||||
def test_secgroup_create_without_policy_update_policy(self):
|
||||
# Create a regular security group. adding the policy later should fail
|
||||
res = self._create_secgroup_with_policy(None)
|
||||
sg = self.deserialize(self.fmt, res)
|
||||
data = {'security_group': {'policy': 'policy-1'}}
|
||||
req = self.new_update_request('security-groups', data,
|
||||
sg['security_group']['id'])
|
||||
res = req.get_response(self.ext_api)
|
||||
self.assertEqual(400, res.status_int)
|
||||
|
||||
def test_secgroup_create_without_policy_and_rule(self):
|
||||
# Test that regular security groups can have rules
|
||||
res = self._create_secgroup_with_policy(None)
|
||||
sg = self.deserialize(self.fmt, res)
|
||||
self.assertIsNone(sg['security_group']['policy'])
|
||||
|
||||
rule = self._build_security_group_rule(
|
||||
sg['security_group']['id'], 'ingress',
|
||||
constants.PROTO_NAME_TCP, '22', '22')
|
||||
res = self._create_security_group_rule(self.fmt, rule)
|
||||
rule_data = self.deserialize(self.fmt, res)
|
||||
self.assertEqual(
|
||||
sg['security_group']['id'],
|
||||
rule_data['security_group_rule']['security_group_id'])
|
||||
|
||||
|
||||
class NsxPolExtensionManager(object):
|
||||
|
||||
def get_resources(self):
|
||||
return nsxpolicy.Nsxpolicy.get_resources()
|
||||
|
||||
def get_actions(self):
|
||||
return []
|
||||
|
||||
def get_request_extensions(self):
|
||||
return []
|
||||
|
||||
|
||||
class TestNsxPolicies(test_plugin.NsxVPluginV2TestCase):
|
||||
|
||||
def setUp(self, plugin=None):
|
||||
super(TestNsxPolicies, self).setUp()
|
||||
ext_mgr = NsxPolExtensionManager()
|
||||
self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr)
|
||||
|
||||
def test_get_policy(self):
|
||||
id = 'policy-1'
|
||||
req = self.new_show_request('nsx-policies', id)
|
||||
res = self.deserialize(
|
||||
self.fmt, req.get_response(self.ext_api)
|
||||
)
|
||||
policy = res['nsx_policy']
|
||||
self.assertEqual(id, policy['id'])
|
||||
|
||||
def test_list_policies(self):
|
||||
req = self.new_list_request('nsx-policies')
|
||||
res = self.deserialize(
|
||||
self.fmt, req.get_response(self.ext_api)
|
||||
)
|
||||
self.assertIn('nsx_policies', res)
|
||||
# the fake_vcns api returns 3 policies
|
||||
self.assertEqual(3, len(res['nsx_policies']))
|
@ -1,443 +0,0 @@
|
||||
# Copyright (c) 2017 OpenStack Foundation.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from neutron.objects import subnet as subnet_obj
|
||||
from neutron_lib import context
|
||||
from neutron_lib import exceptions as n_exc
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from vmware_nsx.tests.unit.dvs import test_plugin as dvs_tests
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin as v_tests
|
||||
from vmware_nsx.tests.unit.nsx_v3 import test_plugin as t_tests
|
||||
|
||||
PLUGIN_NAME = 'vmware_nsx.plugin.NsxTVDPlugin'
|
||||
_uuid = uuidutils.generate_uuid
|
||||
|
||||
|
||||
class NsxTVDPluginTestCase(v_tests.NsxVPluginV2TestCase,
|
||||
t_tests.NsxV3PluginTestCaseMixin,
|
||||
dvs_tests.NeutronSimpleDvsTestCase):
|
||||
|
||||
def setUp(self,
|
||||
plugin=PLUGIN_NAME,
|
||||
ext_mgr=None,
|
||||
service_plugins=None):
|
||||
|
||||
# set the default plugin
|
||||
if self.plugin_type:
|
||||
cfg.CONF.set_override('default_plugin', self.plugin_type,
|
||||
group="nsx_tvd")
|
||||
|
||||
# set the default availability zones
|
||||
cfg.CONF.set_override('nsx_v_default_availability_zones',
|
||||
['default'],
|
||||
group="nsx_tvd")
|
||||
cfg.CONF.set_override('nsx_v3_default_availability_zones',
|
||||
['defaultv3'],
|
||||
group="nsx_tvd")
|
||||
|
||||
super(NsxTVDPluginTestCase, self).setUp(
|
||||
plugin=plugin,
|
||||
ext_mgr=ext_mgr,
|
||||
with_md_proxy=False)
|
||||
self._project_id = _uuid()
|
||||
self.core_plugin = directory.get_plugin()
|
||||
|
||||
# create a context with this tenant
|
||||
self.context = context.get_admin_context()
|
||||
self.context.tenant_id = self.project_id
|
||||
|
||||
# create a default user for this plugin
|
||||
self.core_plugin.create_project_plugin_map(self.context,
|
||||
{'project_plugin_map': {'plugin': self.plugin_type,
|
||||
'project': self.project_id}})
|
||||
self.sub_plugin = self.core_plugin.get_plugin_by_type(self.plugin_type)
|
||||
|
||||
@property
|
||||
def project_id(self):
|
||||
return self._project_id
|
||||
|
||||
@property
|
||||
def plugin_type(self):
|
||||
pass
|
||||
|
||||
def _test_plugin_initialized(self):
|
||||
self.assertTrue(self.core_plugin.is_tvd_plugin())
|
||||
self.assertIsNotNone(self.sub_plugin)
|
||||
|
||||
def _test_call_create(self, obj_name, calls_count=1, project_id=None,
|
||||
is_bulk=False):
|
||||
method_name = single_name = 'create_%s' % obj_name
|
||||
if is_bulk:
|
||||
method_name = method_name + '_bulk'
|
||||
func_to_call = getattr(self.core_plugin, method_name)
|
||||
if not project_id:
|
||||
project_id = self.project_id
|
||||
with mock.patch.object(self.sub_plugin, method_name) as sub_func,\
|
||||
mock.patch.object(self.sub_plugin, single_name) as single_func:
|
||||
if is_bulk:
|
||||
func_to_call(self.context,
|
||||
{obj_name + 's': [{obj_name:
|
||||
{'tenant_id': project_id}}]})
|
||||
else:
|
||||
func_to_call(self.context,
|
||||
{obj_name: {'tenant_id': project_id}})
|
||||
self.assertEqual(calls_count,
|
||||
sub_func.call_count or single_func.call_count)
|
||||
|
||||
def _test_call_create_with_net_id(self, obj_name, field_name='network_id',
|
||||
calls_count=1, is_bulk=False):
|
||||
method_name = 'create_%s' % obj_name
|
||||
if is_bulk:
|
||||
method_name = method_name + '_bulk'
|
||||
func_to_call = getattr(self.core_plugin, method_name)
|
||||
net_id = _uuid()
|
||||
|
||||
with mock.patch.object(self.sub_plugin, method_name) as sub_func,\
|
||||
mock.patch.object(self.core_plugin, '_get_network',
|
||||
return_value={'tenant_id': self.project_id}):
|
||||
if is_bulk:
|
||||
func_to_call(self.context,
|
||||
{obj_name + 's': [{obj_name:
|
||||
{'tenant_id': self.project_id,
|
||||
field_name: net_id}}]})
|
||||
else:
|
||||
func_to_call(self.context,
|
||||
{obj_name: {'tenant_id': self.project_id,
|
||||
field_name: net_id}})
|
||||
self.assertEqual(calls_count, sub_func.call_count)
|
||||
|
||||
def _test_call_delete(self, obj_name):
|
||||
method_name = 'delete_%s' % obj_name
|
||||
func_to_call = getattr(self.core_plugin, method_name)
|
||||
obj_id = _uuid()
|
||||
with mock.patch.object(self.sub_plugin, method_name) as sub_func,\
|
||||
mock.patch.object(self.core_plugin, '_get_%s' % obj_name,
|
||||
return_value={'tenant_id': self.project_id}):
|
||||
func_to_call(self.context, obj_id)
|
||||
sub_func.assert_called_once()
|
||||
|
||||
def _test_call_delete_with_net(self, obj_name, field_name='network_id'):
|
||||
method_name = 'delete_%s' % obj_name
|
||||
func_to_call = getattr(self.core_plugin, method_name)
|
||||
obj_id = _uuid()
|
||||
net_id = _uuid()
|
||||
if obj_name == 'subnet':
|
||||
mock_name = '_get_subnet_object'
|
||||
ret_val = subnet_obj.Subnet(network_id=net_id)
|
||||
else:
|
||||
mock_name = '_get_%s' % obj_name
|
||||
ret_val = {field_name: net_id}
|
||||
with mock.patch.object(self.sub_plugin, method_name) as sub_func,\
|
||||
mock.patch.object(self.core_plugin, mock_name,
|
||||
return_value=ret_val),\
|
||||
mock.patch.object(self.core_plugin, '_get_network',
|
||||
return_value={'tenant_id': self.project_id}):
|
||||
func_to_call(self.context, obj_id)
|
||||
sub_func.assert_called_once()
|
||||
|
||||
def _test_call_update(self, obj_name):
|
||||
method_name = 'update_%s' % obj_name
|
||||
func_to_call = getattr(self.core_plugin, method_name)
|
||||
obj_id = _uuid()
|
||||
with mock.patch.object(self.sub_plugin, method_name) as sub_func,\
|
||||
mock.patch.object(self.core_plugin, '_get_%s' % obj_name,
|
||||
return_value={'tenant_id': self.project_id}):
|
||||
func_to_call(self.context, obj_id, {obj_name: {}})
|
||||
sub_func.assert_called_once()
|
||||
|
||||
def _test_call_update_with_net(self, obj_name, field_name='network_id'):
|
||||
method_name = 'update_%s' % obj_name
|
||||
func_to_call = getattr(self.core_plugin, method_name)
|
||||
obj_id = _uuid()
|
||||
net_id = _uuid()
|
||||
if obj_name == 'subnet':
|
||||
mock_name = '_get_subnet_object'
|
||||
ret_val = subnet_obj.Subnet(network_id=net_id)
|
||||
else:
|
||||
mock_name = '_get_%s' % obj_name
|
||||
ret_val = {field_name: net_id}
|
||||
with mock.patch.object(self.sub_plugin, method_name) as sub_func,\
|
||||
mock.patch.object(self.core_plugin, mock_name,
|
||||
return_value=ret_val),\
|
||||
mock.patch.object(self.core_plugin, '_get_network',
|
||||
return_value={'tenant_id': self.project_id}):
|
||||
func_to_call(self.context, obj_id, {obj_name: {}})
|
||||
sub_func.assert_called_once()
|
||||
|
||||
def _test_call_get(self, obj_name):
|
||||
method_name = 'get_%s' % obj_name
|
||||
func_to_call = getattr(self.core_plugin, method_name)
|
||||
obj_id = _uuid()
|
||||
with mock.patch.object(self.sub_plugin, method_name) as sub_func,\
|
||||
mock.patch.object(self.core_plugin, '_get_%s' % obj_name,
|
||||
return_value={'tenant_id': self.project_id}):
|
||||
func_to_call(self.context, obj_id)
|
||||
sub_func.assert_called_once()
|
||||
|
||||
def _test_call_get_with_net(self, obj_name, field_name='network_id'):
|
||||
method_name = 'get_%s' % obj_name
|
||||
func_to_call = getattr(self.core_plugin, method_name)
|
||||
obj_id = _uuid()
|
||||
net_id = _uuid()
|
||||
if obj_name == 'subnet':
|
||||
mock_name = '_get_subnet_object'
|
||||
ret_val = subnet_obj.Subnet(network_id=net_id)
|
||||
else:
|
||||
mock_name = '_get_%s' % obj_name
|
||||
ret_val = {field_name: net_id}
|
||||
with mock.patch.object(self.sub_plugin, method_name) as sub_func,\
|
||||
mock.patch.object(self.core_plugin, mock_name,
|
||||
return_value=ret_val),\
|
||||
mock.patch.object(self.core_plugin, '_get_network',
|
||||
return_value={'tenant_id': self.project_id}):
|
||||
func_to_call(self.context, obj_id)
|
||||
sub_func.assert_called_once()
|
||||
|
||||
|
||||
class TestPluginWithDefaultPlugin(NsxTVDPluginTestCase):
|
||||
"""Test TVD plugin with the NSX-T (default) sub plugin"""
|
||||
|
||||
@property
|
||||
def plugin_type(self):
|
||||
return 'nsx-t'
|
||||
|
||||
def test_plugin_initialized(self):
|
||||
self._test_plugin_initialized()
|
||||
|
||||
# no unsupported extensions for the nsx_t plugin
|
||||
self.assertCountEqual(
|
||||
['router_type', 'router_size'],
|
||||
self.core_plugin._unsupported_fields[self.plugin_type]['router'])
|
||||
self.assertEqual(
|
||||
[],
|
||||
self.core_plugin._unsupported_fields[self.plugin_type]['port'])
|
||||
|
||||
def test_create_network(self):
|
||||
self._test_call_create('network')
|
||||
|
||||
def test_create_subnet(self):
|
||||
self._test_call_create_with_net_id('subnet')
|
||||
|
||||
def test_create_port(self):
|
||||
self._test_call_create_with_net_id('port')
|
||||
|
||||
def test_create_router(self):
|
||||
self._test_call_create('router')
|
||||
|
||||
def test_create_floatingip(self):
|
||||
self._test_call_create_with_net_id(
|
||||
'floatingip', field_name='floating_network_id')
|
||||
|
||||
def test_create_security_group(self):
|
||||
# plugin will be called twice because of the default sg
|
||||
self._test_call_create('security_group', calls_count=2)
|
||||
|
||||
def test_create_security_group_rule(self):
|
||||
self._test_call_create('security_group_rule')
|
||||
|
||||
def test_create_network_bulk(self):
|
||||
self._test_call_create('network', is_bulk=True)
|
||||
|
||||
def test_create_subnet_bulk(self):
|
||||
self._test_call_create_with_net_id('subnet', is_bulk=True)
|
||||
|
||||
def test_create_security_group_rule_bulk(self):
|
||||
self._test_call_create('security_group_rule', is_bulk=True)
|
||||
|
||||
def test_delete_network(self):
|
||||
self._test_call_delete('network')
|
||||
|
||||
def test_delete_subnet(self):
|
||||
self._test_call_delete_with_net('subnet')
|
||||
|
||||
def test_delete_port(self):
|
||||
self._test_call_delete_with_net('port')
|
||||
|
||||
def test_delete_router(self):
|
||||
self._test_call_delete('router')
|
||||
|
||||
def test_delete_floatingip(self):
|
||||
self._test_call_delete_with_net(
|
||||
'floatingip', field_name='floating_network_id')
|
||||
|
||||
def test_delete_security_group(self):
|
||||
self._test_call_delete('security_group')
|
||||
|
||||
def test_update_network(self):
|
||||
self._test_call_update('network')
|
||||
|
||||
def test_update_subnet(self):
|
||||
self._test_call_update_with_net('subnet')
|
||||
|
||||
def test_update_port(self):
|
||||
self._test_call_update_with_net('port')
|
||||
|
||||
def test_update_router(self):
|
||||
self._test_call_update('router')
|
||||
|
||||
def test_update_floatingip(self):
|
||||
self._test_call_update_with_net(
|
||||
'floatingip', field_name='floating_network_id')
|
||||
|
||||
def test_update_security_group(self):
|
||||
self._test_call_update('security_group')
|
||||
|
||||
def test_unsupported_extensions(self):
|
||||
self.assertRaises(n_exc.InvalidInput,
|
||||
self.core_plugin.create_router,
|
||||
self.context,
|
||||
{'router': {'tenant_id': self.project_id,
|
||||
'router_type': 'exclusive'}})
|
||||
|
||||
def test_get_network(self):
|
||||
self._test_call_get('network')
|
||||
|
||||
def test_get_subnet(self):
|
||||
self._test_call_get_with_net('subnet')
|
||||
|
||||
def test_get_port(self):
|
||||
self._test_call_get_with_net('port')
|
||||
|
||||
def test_get_router(self):
|
||||
self._test_call_get('router')
|
||||
|
||||
def test_get_floatingip(self):
|
||||
self._test_call_get_with_net(
|
||||
'floatingip', field_name='floating_network_id')
|
||||
|
||||
def test_get_security_group(self):
|
||||
self._test_call_get('security_group')
|
||||
|
||||
def test_add_router_interface(self):
|
||||
rtr_id = _uuid()
|
||||
port_id = _uuid()
|
||||
net_id = _uuid()
|
||||
with mock.patch.object(self.sub_plugin,
|
||||
'add_router_interface') as sub_func,\
|
||||
mock.patch.object(self.core_plugin, '_get_router',
|
||||
return_value={'tenant_id': self.project_id}),\
|
||||
mock.patch.object(self.core_plugin, '_get_port',
|
||||
return_value={'network_id': net_id}),\
|
||||
mock.patch.object(self.core_plugin, '_get_network',
|
||||
return_value={'tenant_id': self.project_id}),\
|
||||
mock.patch.object(self.core_plugin, '_validate_interface_info',
|
||||
return_value=(True, False)):
|
||||
self.core_plugin.add_router_interface(self.context, rtr_id,
|
||||
{'port_id': port_id})
|
||||
sub_func.assert_called_once()
|
||||
|
||||
def test_add_invalid_router_interface(self):
|
||||
# Test that the plugin prevents adding interface from one plugin
|
||||
# to a router of another plugin
|
||||
rtr_id = _uuid()
|
||||
port_id = _uuid()
|
||||
net_id = _uuid()
|
||||
another_tenant_id = _uuid()
|
||||
another_plugin = 'nsx-v' if self.plugin_type == 'nsx-t' else 'nsx-t'
|
||||
self.core_plugin.create_project_plugin_map(self.context,
|
||||
{'project_plugin_map': {'plugin': another_plugin,
|
||||
'project': another_tenant_id}})
|
||||
|
||||
with mock.patch.object(self.core_plugin, '_get_router',
|
||||
return_value={'tenant_id': self.project_id}),\
|
||||
mock.patch.object(self.core_plugin, '_get_port',
|
||||
return_value={'network_id': net_id}),\
|
||||
mock.patch.object(self.core_plugin, '_get_network',
|
||||
return_value={'tenant_id': another_tenant_id}),\
|
||||
mock.patch.object(self.core_plugin, '_validate_interface_info',
|
||||
return_value=(True, False)):
|
||||
self.assertRaises(n_exc.InvalidInput,
|
||||
self.core_plugin.add_router_interface,
|
||||
self.context, rtr_id, {'port_id': port_id})
|
||||
|
||||
def test_remove_router_interface(self):
|
||||
rtr_id = _uuid()
|
||||
with mock.patch.object(self.sub_plugin,
|
||||
'remove_router_interface') as sub_func,\
|
||||
mock.patch.object(self.core_plugin, '_get_router',
|
||||
return_value={'tenant_id': self.project_id}):
|
||||
self.core_plugin.remove_router_interface(self.context, rtr_id, {})
|
||||
sub_func.assert_called_once()
|
||||
|
||||
def test_disassociate_floatingips(self):
|
||||
port_id = _uuid()
|
||||
net_id = _uuid()
|
||||
with mock.patch.object(self.sub_plugin,
|
||||
'disassociate_floatingips') as sub_func,\
|
||||
mock.patch.object(self.core_plugin, '_get_port',
|
||||
return_value={'network_id': net_id}),\
|
||||
mock.patch.object(self.core_plugin, '_get_network',
|
||||
return_value={'tenant_id': self.project_id}):
|
||||
self.core_plugin.disassociate_floatingips(self.context, port_id)
|
||||
sub_func.assert_called_once()
|
||||
|
||||
def test_new_user(self):
|
||||
project_id = _uuid()
|
||||
self._test_call_create('network', project_id=project_id)
|
||||
|
||||
|
||||
class TestPluginWithNsxv(TestPluginWithDefaultPlugin):
|
||||
"""Test TVD plugin with the NSX-V sub plugin"""
|
||||
|
||||
@property
|
||||
def plugin_type(self):
|
||||
return 'nsx-v'
|
||||
|
||||
def test_plugin_initialized(self):
|
||||
self._test_plugin_initialized()
|
||||
|
||||
# no unsupported extensions for the nsx_v plugin
|
||||
self.assertEqual(
|
||||
[],
|
||||
self.core_plugin._unsupported_fields[self.plugin_type]['router'])
|
||||
self.assertEqual(
|
||||
[],
|
||||
self.core_plugin._unsupported_fields[self.plugin_type]['port'])
|
||||
|
||||
def test_unsupported_extensions(self):
|
||||
self.skipTest('No unsupported extensions in this plugin')
|
||||
|
||||
|
||||
class TestPluginWithDvs(TestPluginWithDefaultPlugin):
|
||||
"""Test TVD plugin with the DVS sub plugin"""
|
||||
|
||||
@property
|
||||
def plugin_type(self):
|
||||
return 'dvs'
|
||||
|
||||
def test_plugin_initialized(self):
|
||||
self._test_plugin_initialized()
|
||||
|
||||
# no unsupported extensions for the dvs plugin
|
||||
self.assertCountEqual(
|
||||
['mac_learning_enabled', 'provider_security_groups'],
|
||||
self.core_plugin._unsupported_fields[self.plugin_type]['port'])
|
||||
|
||||
def test_unsupported_extensions(self):
|
||||
net_id = _uuid()
|
||||
with mock.patch.object(self.core_plugin, '_get_network',
|
||||
return_value={'tenant_id': self.project_id}):
|
||||
self.assertRaises(n_exc.InvalidInput,
|
||||
self.core_plugin.create_port,
|
||||
self.context,
|
||||
{'port': {'tenant_id': self.project_id,
|
||||
'network_id': net_id,
|
||||
'mac_learning_enabled': True}})
|
@ -1,84 +0,0 @@
|
||||
# Copyright 2017 VMware, 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.
|
||||
from unittest import mock
|
||||
|
||||
from neutron.tests import base
|
||||
from neutron_lib.plugins import constants
|
||||
|
||||
from vmware_nsx.plugins.common.housekeeper import base_job
|
||||
from vmware_nsx.plugins.nsx_v.housekeeper import error_backup_edge
|
||||
|
||||
FAKE_ROUTER_BINDINGS = [
|
||||
{
|
||||
'router_id': 'backup-3b0b1fe1-c984', 'status': 'ERROR',
|
||||
'availability_zone': 'default', 'edge_id': 'edge-782',
|
||||
'edge_type': 'service', 'appliance_size': 'compact'}]
|
||||
|
||||
|
||||
class ErrorBackupEdgeTestCaseReadOnly(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
def get_plugin_mock(alias=constants.CORE):
|
||||
if alias in (constants.CORE, constants.L3):
|
||||
return self.plugin
|
||||
|
||||
super(ErrorBackupEdgeTestCaseReadOnly, self).setUp()
|
||||
self.plugin = mock.Mock()
|
||||
self.context = mock.Mock()
|
||||
self.context.session = mock.Mock()
|
||||
mock.patch('neutron_lib.plugins.directory.get_plugin',
|
||||
side_effect=get_plugin_mock).start()
|
||||
self.log = mock.Mock()
|
||||
base_job.LOG = self.log
|
||||
self.job = error_backup_edge.ErrorBackupEdgeJob(True, [])
|
||||
|
||||
def run_job(self):
|
||||
self.job.run(self.context, readonly=True)
|
||||
|
||||
def test_clean_run(self):
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings',
|
||||
return_value=[]).start()
|
||||
self.run_job()
|
||||
self.log.warning.assert_not_called()
|
||||
|
||||
def test_broken_backup_edge(self):
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings',
|
||||
return_value=FAKE_ROUTER_BINDINGS).start()
|
||||
|
||||
self.run_job()
|
||||
self.log.warning.assert_called_once()
|
||||
|
||||
|
||||
class ErrorBackupEdgeTestCaseReadWrite(ErrorBackupEdgeTestCaseReadOnly):
|
||||
def run_job(self):
|
||||
self.job.run(self.context, readonly=False)
|
||||
|
||||
def test_broken_backup_edge(self):
|
||||
upd_binding = mock.patch(
|
||||
'vmware_nsx.db.nsxv_db.update_nsxv_router_binding').start()
|
||||
upd_edge = mock.patch.object(self.plugin.nsx_v, 'update_edge').start()
|
||||
self.job.azs = mock.Mock()
|
||||
az = mock.Mock()
|
||||
mock.patch.object(self.job.azs, 'get_availability_zone',
|
||||
return_value=az).start()
|
||||
super(ErrorBackupEdgeTestCaseReadWrite, self
|
||||
).test_broken_backup_edge()
|
||||
upd_binding.assert_has_calls(
|
||||
[mock.call(mock.ANY, r['router_id'], status='ACTIVE')
|
||||
for r in FAKE_ROUTER_BINDINGS])
|
||||
upd_edge.assert_called_with(
|
||||
self.context, 'backup-3b0b1fe1-c984', 'edge-782',
|
||||
'backup-3b0b1fe1-c984', None, appliance_size='compact',
|
||||
availability_zone=az, dist=False)
|
@ -1,489 +0,0 @@
|
||||
# Copyright 2017 VMware, 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 copy
|
||||
import datetime
|
||||
from unittest import mock
|
||||
|
||||
from neutron.tests import base
|
||||
from neutron_lib.plugins import constants
|
||||
|
||||
from vmware_nsx.plugins.common.housekeeper import base_job
|
||||
from vmware_nsx.plugins.nsx_v.housekeeper import error_dhcp_edge
|
||||
|
||||
FAKE_ROUTER_BINDINGS = [
|
||||
{
|
||||
'router_id': 'dhcp-16c224dd-7c2b-4241-a447-4fc07a3', 'status': 'ERROR',
|
||||
'availability_zone': 'default', 'edge_id': 'edge-752'},
|
||||
{
|
||||
'router_id': 'dhcp-31341032-6911-4596-8b64-afce92f', 'status': 'ERROR',
|
||||
'availability_zone': 'default', 'edge_id': 'edge-752'},
|
||||
{
|
||||
'router_id': 'dhcp-51c97abb-8ac9-4f24-b914-cc30cf8', 'status': 'ERROR',
|
||||
'availability_zone': 'default', 'edge_id': 'edge-752'},
|
||||
{
|
||||
'router_id': 'dhcp-5d01cea4-58f8-4a16-9be0-11012ca', 'status': 'ERROR',
|
||||
'availability_zone': 'default', 'edge_id': 'edge-752'},
|
||||
{
|
||||
'router_id': 'dhcp-65a5335c-4c72-4721-920e-5abdc9e', 'status': 'ERROR',
|
||||
'availability_zone': 'default', 'edge_id': 'edge-752'},
|
||||
{
|
||||
'router_id': 'dhcp-83bce421-b72c-4744-9285-a0fcc25', 'status': 'ERROR',
|
||||
'availability_zone': 'default', 'edge_id': 'edge-752'},
|
||||
{
|
||||
'router_id': 'dhcp-9d2f5b66-c252-4681-86af-9460484', 'status': 'ERROR',
|
||||
'availability_zone': 'default', 'edge_id': 'edge-752'},
|
||||
{
|
||||
'router_id': 'dhcp-aea44408-0448-42dd-9ae6-ed940da', 'status': 'ERROR',
|
||||
'availability_zone': 'default', 'edge_id': 'edge-752'}]
|
||||
|
||||
BAD_ROUTER_BINDING = {
|
||||
'router_id': 'dhcp-11111111-1111-1111-aaaa-aaaaaaa', 'status': 'ERROR',
|
||||
'availability_zone': 'default', 'edge_id': 'edge-752'}
|
||||
|
||||
FAKE_EDGE_VNIC_BINDS = [
|
||||
{
|
||||
'network_id': '7c0b6fb5-d86c-4e5e-a2af-9ce36971764b',
|
||||
'vnic_index': 1, 'edge_id': 'edge-752', 'tunnel_index': 1},
|
||||
{
|
||||
'network_id': '16c224dd-7c2b-4241-a447-4fc07a38dc80',
|
||||
'vnic_index': 2, 'edge_id': 'edge-752', 'tunnel_index': 4},
|
||||
{
|
||||
'network_id': '65a5335c-4c72-4721-920e-5abdc9e09ba4',
|
||||
'vnic_index': 2, 'edge_id': 'edge-752', 'tunnel_index': 6},
|
||||
{
|
||||
'network_id': 'aea44408-0448-42dd-9ae6-ed940dac564a',
|
||||
'vnic_index': 4, 'edge_id': 'edge-752', 'tunnel_index': 10},
|
||||
{
|
||||
'network_id': '5d01cea4-58f8-4a16-9be0-11012cadbf55',
|
||||
'vnic_index': 4, 'edge_id': 'edge-752', 'tunnel_index': 12},
|
||||
{
|
||||
'network_id': '51c97abb-8ac9-4f24-b914-cc30cf8e856a',
|
||||
'vnic_index': 6, 'edge_id': 'edge-752', 'tunnel_index': 16},
|
||||
{
|
||||
'network_id': '31341032-6911-4596-8b64-afce92f46bf4',
|
||||
'vnic_index': 6, 'edge_id': 'edge-752', 'tunnel_index': 18},
|
||||
{
|
||||
'network_id': '9d2f5b66-c252-4681-86af-946048414a1f',
|
||||
'vnic_index': 8, 'edge_id': 'edge-752', 'tunnel_index': 22},
|
||||
{
|
||||
'network_id': '83bce421-b72c-4744-9285-a0fcc25b001a',
|
||||
'vnic_index': 8, 'edge_id': 'edge-752', 'tunnel_index': 24}]
|
||||
|
||||
BAD_VNIC_BINDING = {
|
||||
'network_id': '11111111-1111-1111-aaaa-aaaaaaabbaac',
|
||||
'vnic_index': 8, 'edge_id': 'edge-752', 'tunnel_index': 21}
|
||||
|
||||
FAKE_INTERNAL_NETWORKS = [
|
||||
{'availability_zone': u'default',
|
||||
'network_id': u'7c0b6fb5-d86c-4e5e-a2af-9ce36971764b',
|
||||
'network_purpose': 'inter_edge_net', 'updated_at': None,
|
||||
'_rev_bumped': False,
|
||||
'created_at': datetime.datetime(2017, 12, 13, 12, 28, 18)}]
|
||||
|
||||
FAKE_NETWORK_RESULTS = [{'id': 'e3a02b46-b9c9-4f2f-bcea-7978355a7dca'},
|
||||
{'id': '031eaf4b-49b8-4003-9369-8a0dd5d7a163'},
|
||||
{'id': '16c224dd-7c2b-4241-a447-4fc07a38dc80'},
|
||||
{'id': '1a3b570c-c8b5-411e-8e13-d4dc0b3e56b2'},
|
||||
{'id': '24b31d2c-fcec-45e5-bdcb-aa089d3713ae'},
|
||||
{'id': '31341032-6911-4596-8b64-afce92f46bf4'},
|
||||
{'id': '51c97abb-8ac9-4f24-b914-cc30cf8e856a'},
|
||||
{'id': '5484b39b-ec6e-43f4-b900-fc1b2c49c71a'},
|
||||
{'id': '54eae237-3516-4f82-b46f-f955e91c989c'},
|
||||
{'id': '5a859fa0-bea0-41be-843a-9f9bf39e2509'},
|
||||
{'id': '5d01cea4-58f8-4a16-9be0-11012cadbf55'},
|
||||
{'id': '65a5335c-4c72-4721-920e-5abdc9e09ba4'},
|
||||
{'id': '708f11d4-00d0-48ea-836f-01273cbf36cc'},
|
||||
{'id': '7c0b6fb5-d86c-4e5e-a2af-9ce36971764b'},
|
||||
{'id': '83bce421-b72c-4744-9285-a0fcc25b001a'},
|
||||
{'id': '9d2f5b66-c252-4681-86af-946048414a1f'},
|
||||
{'id': 'aea44408-0448-42dd-9ae6-ed940dac564a'},
|
||||
{'id': 'b0cee4e3-266b-48d3-a651-04f1985fe4b0'},
|
||||
{'id': 'be82b8c5-96a9-4e08-a965-bb09d48ec161'},
|
||||
{'id': 'e69279c6-9a1e-4f7b-b421-b8b3eb92c54b'}]
|
||||
|
||||
BACKEND_EDGE_VNICS = {'vnics': [
|
||||
{'label': 'vNic_0', 'name': 'external',
|
||||
'addressGroups': {'addressGroups': []}, 'mtu': 1500, 'type': 'uplink',
|
||||
'isConnected': True, 'index': 0, 'portgroupId': 'network-13',
|
||||
'fenceParameters': [], 'enableProxyArp': False,
|
||||
'enableSendRedirects': True},
|
||||
{'label': 'vNic_1', 'name': 'internal1', 'addressGroups': {
|
||||
'addressGroups': [
|
||||
{'primaryAddress': '169.254.128.14',
|
||||
'secondaryAddresses': {
|
||||
'type': 'secondary_addresses',
|
||||
'ipAddress': ['169.254.169.254']},
|
||||
'subnetMask': '255.255.128.0',
|
||||
'subnetPrefixLength': '17'}]}, 'mtu': 1500,
|
||||
'type': 'internal', 'isConnected': True, 'index': 1,
|
||||
'portgroupId': 'virtualwire-472',
|
||||
'fenceParameters': [], 'enableProxyArp': False,
|
||||
'enableSendRedirects': True},
|
||||
{'label': 'vNic_2', 'name': 'internal2',
|
||||
'addressGroups': {'addressGroups': []}, 'mtu': 1500, 'type': 'trunk',
|
||||
'subInterfaces': {'subInterfaces': [
|
||||
{'isConnected': True, 'label': 'vNic_10',
|
||||
'name': '1639ff40-8137-4803-a29f-dcf0efc35b34', 'index': 10,
|
||||
'tunnelId': 4, 'logicalSwitchId': 'virtualwire-497',
|
||||
'logicalSwitchName': '16c224dd-7c2b-4241-a447-4fc07a38dc80',
|
||||
'enableSendRedirects': True, 'mtu': 1500,
|
||||
'addressGroups': {'addressGroups': [{
|
||||
'primaryAddress': '10.24.0.2', 'subnetMask': '255.255.255.0',
|
||||
'subnetPrefixLength': '24'}]}, 'virtualNetworkId': 5025,
|
||||
'subInterfaceBackingType': 'NETWORK'},
|
||||
{'isConnected': True, 'label': 'vNic_12',
|
||||
'name': 'd1515746-a21a-442d-8347-62b36f5791d6', 'index': 12,
|
||||
'tunnelId': 6, 'logicalSwitchId': 'virtualwire-499',
|
||||
'logicalSwitchName': '65a5335c-4c72-4721-920e-5abdc9e09ba4',
|
||||
'enableSendRedirects': True, 'mtu': 1500,
|
||||
'addressGroups': {'addressGroups': [
|
||||
{'primaryAddress': '10.26.0.2', 'subnetMask': '255.255.255.0',
|
||||
'subnetPrefixLength': '24'}]}, 'virtualNetworkId': 5027,
|
||||
'subInterfaceBackingType': 'NETWORK'}]}, 'isConnected': True,
|
||||
'index': 2, 'portgroupId': 'dvportgroup-1550',
|
||||
'fenceParameters': [], 'enableProxyArp': False,
|
||||
'enableSendRedirects': True},
|
||||
{'label': 'vNic_3', 'name': 'vnic3',
|
||||
'addressGroups': {'addressGroups': []},
|
||||
'mtu': 1500, 'type': 'internal', 'isConnected': False, 'index': 3,
|
||||
'fenceParameters': [], 'enableProxyArp': False,
|
||||
'enableSendRedirects': True},
|
||||
{'label': 'vNic_4', 'name': 'internal4',
|
||||
'addressGroups': {'addressGroups': []}, 'mtu': 1500, 'type': 'trunk',
|
||||
'subInterfaces': {'subInterfaces': [
|
||||
{'isConnected': True, 'label': 'vNic_16',
|
||||
'name': 'e2405dc6-21d7-4421-a70c-3eecf675b286', 'index': 16,
|
||||
'tunnelId': 10, 'logicalSwitchId': 'virtualwire-503',
|
||||
'logicalSwitchName': 'aea44408-0448-42dd-9ae6-ed940dac564a',
|
||||
'enableSendRedirects': True, 'mtu': 1500,
|
||||
'addressGroups': {'addressGroups': [
|
||||
{'primaryAddress': '10.30.0.2', 'subnetMask': '255.255.255.0',
|
||||
'subnetPrefixLength': '24'}]}, 'virtualNetworkId': 5031,
|
||||
'subInterfaceBackingType': 'NETWORK'},
|
||||
{'isConnected': True, 'label': 'vNic_18',
|
||||
'name': 'a10fb348-30e4-477f-817f-bb3c9c9fd3f5', 'index': 18,
|
||||
'tunnelId': 12, 'logicalSwitchId': 'virtualwire-505',
|
||||
'logicalSwitchName': '5d01cea4-58f8-4a16-9be0-11012cadbf55',
|
||||
'enableSendRedirects': True, 'mtu': 1500,
|
||||
'addressGroups': {'addressGroups': [
|
||||
{'primaryAddress': '10.32.0.2', 'subnetMask': '255.255.255.0',
|
||||
'subnetPrefixLength': '24'}]}, 'virtualNetworkId': 5033,
|
||||
'subInterfaceBackingType': 'NETWORK'}]}, 'isConnected': True,
|
||||
'index': 4, 'portgroupId': 'dvportgroup-1559',
|
||||
'fenceParameters': [], 'enableProxyArp': False,
|
||||
'enableSendRedirects': True},
|
||||
{'label': 'vNic_5', 'name': 'vnic5',
|
||||
'addressGroups': {'addressGroups': []},
|
||||
'mtu': 1500, 'type': 'internal', 'isConnected': False, 'index': 5,
|
||||
'fenceParameters': [], 'enableProxyArp': False,
|
||||
'enableSendRedirects': True},
|
||||
{'label': 'vNic_6', 'name': 'internal6',
|
||||
'addressGroups': {'addressGroups': []}, 'mtu': 1500, 'type': 'trunk',
|
||||
'subInterfaces': {'subInterfaces': [
|
||||
{'isConnected': True, 'label': 'vNic_22',
|
||||
'name': '2da534c8-3d9b-4677-aa14-2e66efd09e3f', 'index': 22,
|
||||
'tunnelId': 16, 'logicalSwitchId': 'virtualwire-509',
|
||||
'logicalSwitchName': '51c97abb-8ac9-4f24-b914-cc30cf8e856a',
|
||||
'enableSendRedirects': True, 'mtu': 1500,
|
||||
'addressGroups': {'addressGroups': [
|
||||
{'primaryAddress': '10.36.0.2', 'subnetMask': '255.255.255.0',
|
||||
'subnetPrefixLength': '24'}]}, 'virtualNetworkId': 5037,
|
||||
'subInterfaceBackingType': 'NETWORK'},
|
||||
{'isConnected': True, 'label': 'vNic_24',
|
||||
'name': 'd25f00c2-eb82-455c-87b9-d2d510d42917', 'index': 24,
|
||||
'tunnelId': 18, 'logicalSwitchId': 'virtualwire-511',
|
||||
'logicalSwitchName': '31341032-6911-4596-8b64-afce92f46bf4',
|
||||
'enableSendRedirects': True, 'mtu': 1500,
|
||||
'addressGroups': {'addressGroups': [
|
||||
{'primaryAddress': '10.38.0.2', 'subnetMask': '255.255.255.0',
|
||||
'subnetPrefixLength': '24'}]}, 'virtualNetworkId': 5039,
|
||||
'subInterfaceBackingType': 'NETWORK'}]}, 'isConnected': True,
|
||||
'index': 6, 'portgroupId': 'dvportgroup-1567',
|
||||
|
||||
'fenceParameters': [], 'enableProxyArp': False,
|
||||
'enableSendRedirects': True},
|
||||
{'label': 'vNic_7', 'name': 'vnic7',
|
||||
'addressGroups': {'addressGroups': []},
|
||||
'mtu': 1500, 'type': 'internal', 'isConnected': False, 'index': 7,
|
||||
'fenceParameters': [], 'enableProxyArp': False,
|
||||
'enableSendRedirects': True},
|
||||
{'label': 'vNic_8', 'name': 'internal8',
|
||||
'addressGroups': {'addressGroups': []}, 'mtu': 1500, 'type': 'trunk',
|
||||
'subInterfaces': {'subInterfaces': [
|
||||
{'isConnected': True, 'label': 'vNic_28',
|
||||
'name': 'cf4cc867-e958-4f86-acea-d8a52a4c26c8', 'index': 28,
|
||||
'tunnelId': 22, 'logicalSwitchId': 'virtualwire-515',
|
||||
'logicalSwitchName': '9d2f5b66-c252-4681-86af-946048414a1f',
|
||||
'enableSendRedirects': True, 'mtu': 1500,
|
||||
'addressGroups': {'addressGroups': [
|
||||
{'primaryAddress': '10.42.0.2', 'subnetMask': '255.255.255.0',
|
||||
'subnetPrefixLength': '24'}]}, 'virtualNetworkId': 5043,
|
||||
'subInterfaceBackingType': 'NETWORK'},
|
||||
{'isConnected': True, 'label': 'vNic_30',
|
||||
'name': 'ceab3d83-3ee2-4372-b5d7-f1d47be76e9d', 'index': 30,
|
||||
'tunnelId': 24, 'logicalSwitchId': 'virtualwire-517',
|
||||
'logicalSwitchName': '83bce421-b72c-4744-9285-a0fcc25b001a',
|
||||
'enableSendRedirects': True, 'mtu': 1500,
|
||||
'addressGroups': {'addressGroups': [
|
||||
{'primaryAddress': '10.44.0.2', 'subnetMask': '255.255.255.0',
|
||||
'subnetPrefixLength': '24'}]}, 'virtualNetworkId': 5045,
|
||||
'subInterfaceBackingType': 'NETWORK'}]}, 'isConnected': True,
|
||||
'index': 8, 'portgroupId': 'dvportgroup-1575',
|
||||
'fenceParameters': [], 'enableProxyArp': False,
|
||||
'enableSendRedirects': True},
|
||||
{'label': 'vNic_9', 'name': 'vnic9',
|
||||
'addressGroups': {'addressGroups': []},
|
||||
'mtu': 1500, 'type': 'internal', 'isConnected': False, 'index': 9,
|
||||
'fenceParameters': [], 'enableProxyArp': False,
|
||||
'enableSendRedirects': True}]}
|
||||
|
||||
BAD_SUBINTERFACE = {
|
||||
'isConnected': True, 'label': 'vNic_31',
|
||||
'name': '11111111-2222-3333-4444-555555555555', 'index': 31,
|
||||
'tunnelId': 25, 'logicalSwitchId': 'virtualwire-518',
|
||||
'logicalSwitchName': '55555555-4444-3333-2222-111111111111',
|
||||
'enableSendRedirects': True, 'mtu': 1500, 'addressGroups': {
|
||||
'addressGroups': [
|
||||
{'primaryAddress': '10.99.0.2', 'subnetMask': '255.255.255.0',
|
||||
'subnetPrefixLength': '24'}]}, 'virtualNetworkId': 5045,
|
||||
'subInterfaceBackingType': 'NETWORK'}
|
||||
|
||||
BAD_INTERFACE = {
|
||||
'label': 'vNic_8', 'name': 'vnic8',
|
||||
'addressGroups': {'addressGroups': []},
|
||||
'mtu': 1500, 'type': 'internal', 'isConnected': False, 'index': 8,
|
||||
'fenceParameters': [], 'enableProxyArp': False,
|
||||
'enableSendRedirects': True}
|
||||
|
||||
|
||||
class ErrorDhcpEdgeTestCaseReadOnly(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
def get_plugin_mock(alias=constants.CORE):
|
||||
if alias in (constants.CORE, constants.L3):
|
||||
return self.plugin
|
||||
|
||||
super(ErrorDhcpEdgeTestCaseReadOnly, self).setUp()
|
||||
self.plugin = mock.Mock()
|
||||
self.context = mock.Mock()
|
||||
self.context.session = mock.Mock()
|
||||
mock.patch('neutron_lib.plugins.directory.get_plugin',
|
||||
side_effect=get_plugin_mock).start()
|
||||
self.plugin.edge_manager = mock.Mock()
|
||||
self.plugin.nsx_v = mock.Mock()
|
||||
self.plugin.nsx_v.vcns = mock.Mock()
|
||||
mock.patch.object(self.plugin, 'get_availability_zone_name_by_edge',
|
||||
return_value='default').start()
|
||||
self.log = mock.Mock()
|
||||
base_job.LOG = self.log
|
||||
self.job = error_dhcp_edge.ErrorDhcpEdgeJob(True, [])
|
||||
|
||||
def run_job(self):
|
||||
self.job.run(self.context, readonly=True)
|
||||
|
||||
def test_clean_run(self):
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings',
|
||||
return_value=[]).start()
|
||||
self.run_job()
|
||||
self.log.warning.assert_not_called()
|
||||
|
||||
def test_invalid_router_binding(self):
|
||||
router_binds = copy.deepcopy(FAKE_ROUTER_BINDINGS)
|
||||
router_binds.append(BAD_ROUTER_BINDING)
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings',
|
||||
return_value=router_binds).start()
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_edge_vnic_bindings_by_edge',
|
||||
return_value=FAKE_EDGE_VNIC_BINDS).start()
|
||||
mock.patch.object(self.plugin, 'get_networks',
|
||||
return_value=FAKE_NETWORK_RESULTS).start()
|
||||
mock.patch.object(self.plugin.nsx_v.vcns, 'get_interfaces',
|
||||
return_value=(None, BACKEND_EDGE_VNICS)).start()
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_internal_networks',
|
||||
return_value=FAKE_INTERNAL_NETWORKS).start()
|
||||
self.run_job()
|
||||
self.log.warning.assert_called_once()
|
||||
|
||||
def test_invalid_edge_vnic_bindings(self):
|
||||
def fake_vnic_bind(*args, **kwargs):
|
||||
# The DB content is manipulated by the housekeeper. Therefore
|
||||
# get_edge_vnic_bindings_by_edge() output should be altered
|
||||
if fake_vnic_bind.ctr < 2:
|
||||
ret = fake_vnic_bind.vnic_binds
|
||||
else:
|
||||
ret = FAKE_EDGE_VNIC_BINDS
|
||||
fake_vnic_bind.ctr += 1
|
||||
return ret
|
||||
|
||||
fake_vnic_bind.ctr = 0
|
||||
fake_vnic_bind.vnic_binds = copy.deepcopy(FAKE_EDGE_VNIC_BINDS)
|
||||
fake_vnic_bind.vnic_binds.append(BAD_VNIC_BINDING)
|
||||
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings',
|
||||
return_value=FAKE_ROUTER_BINDINGS).start()
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_edge_vnic_bindings_by_edge',
|
||||
side_effect=fake_vnic_bind).start()
|
||||
mock.patch.object(self.plugin, 'get_networks',
|
||||
return_value=FAKE_NETWORK_RESULTS).start()
|
||||
mock.patch.object(self.plugin.nsx_v.vcns, 'get_interfaces',
|
||||
return_value=(None, BACKEND_EDGE_VNICS)).start()
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_internal_networks',
|
||||
return_value=FAKE_INTERNAL_NETWORKS).start()
|
||||
self.run_job()
|
||||
self.log.warning.assert_called_once()
|
||||
|
||||
def test_invalid_edge_sub_if(self):
|
||||
backend_vnics = copy.deepcopy(BACKEND_EDGE_VNICS)
|
||||
backend_vnics['vnics'][8]['subInterfaces']['subInterfaces'].append(
|
||||
BAD_SUBINTERFACE)
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings',
|
||||
return_value=FAKE_ROUTER_BINDINGS).start()
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_edge_vnic_bindings_by_edge',
|
||||
return_value=FAKE_EDGE_VNIC_BINDS).start()
|
||||
mock.patch.object(self.plugin, 'get_networks',
|
||||
return_value=FAKE_NETWORK_RESULTS).start()
|
||||
mock.patch.object(self.plugin.nsx_v.vcns, 'get_interfaces',
|
||||
return_value=(None, backend_vnics)).start()
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_internal_networks',
|
||||
return_value=FAKE_INTERNAL_NETWORKS).start()
|
||||
self.run_job()
|
||||
self.log.warning.assert_called_once()
|
||||
|
||||
def test_missing_edge_sub_if(self):
|
||||
backend_vnics = copy.deepcopy(BACKEND_EDGE_VNICS)
|
||||
del backend_vnics['vnics'][8]['subInterfaces']['subInterfaces'][1]
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings',
|
||||
return_value=FAKE_ROUTER_BINDINGS).start()
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_edge_vnic_bindings_by_edge',
|
||||
return_value=FAKE_EDGE_VNIC_BINDS).start()
|
||||
mock.patch.object(self.plugin, 'get_networks',
|
||||
return_value=FAKE_NETWORK_RESULTS).start()
|
||||
mock.patch.object(self.plugin.nsx_v.vcns, 'get_interfaces',
|
||||
return_value=(None, backend_vnics)).start()
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_internal_networks',
|
||||
return_value=FAKE_INTERNAL_NETWORKS).start()
|
||||
self.run_job()
|
||||
self.log.warning.assert_called_once()
|
||||
|
||||
def test_missing_edge_interface(self):
|
||||
backend_vnics = copy.deepcopy(BACKEND_EDGE_VNICS)
|
||||
backend_vnics['vnics'][8] = BAD_INTERFACE
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings',
|
||||
return_value=FAKE_ROUTER_BINDINGS).start()
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_edge_vnic_bindings_by_edge',
|
||||
return_value=FAKE_EDGE_VNIC_BINDS).start()
|
||||
mock.patch.object(self.plugin, 'get_networks',
|
||||
return_value=FAKE_NETWORK_RESULTS).start()
|
||||
mock.patch.object(self.plugin.nsx_v.vcns, 'get_interfaces',
|
||||
return_value=(None, backend_vnics)).start()
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_internal_networks',
|
||||
return_value=FAKE_INTERNAL_NETWORKS).start()
|
||||
self.run_job()
|
||||
self.assertEqual(2, self.log.warning.call_count)
|
||||
|
||||
|
||||
class ErrorDhcpEdgeTestCaseReadWrite(ErrorDhcpEdgeTestCaseReadOnly):
|
||||
|
||||
def run_job(self):
|
||||
self.job.run(self.context, readonly=False)
|
||||
|
||||
def test_invalid_router_binding(self):
|
||||
del_binding = mock.patch(
|
||||
'vmware_nsx.db.nsxv_db.delete_nsxv_router_binding').start()
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings_by_edge',
|
||||
return_value=FAKE_ROUTER_BINDINGS).start()
|
||||
upd_binding = mock.patch(
|
||||
'vmware_nsx.db.nsxv_db.update_nsxv_router_binding').start()
|
||||
super(ErrorDhcpEdgeTestCaseReadWrite, self
|
||||
).test_invalid_router_binding()
|
||||
del_binding.assert_called_with(mock.ANY,
|
||||
BAD_ROUTER_BINDING['router_id'])
|
||||
upd_binding.assert_has_calls(
|
||||
[mock.call(mock.ANY, r['router_id'], status='ACTIVE')
|
||||
for r in FAKE_ROUTER_BINDINGS])
|
||||
|
||||
def test_invalid_edge_vnic_bindings(self):
|
||||
del_binding = mock.patch(
|
||||
'vmware_nsx.db.nsxv_db.free_edge_vnic_by_network').start()
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings_by_edge',
|
||||
return_value=FAKE_ROUTER_BINDINGS).start()
|
||||
upd_binding = mock.patch(
|
||||
'vmware_nsx.db.nsxv_db.update_nsxv_router_binding').start()
|
||||
super(ErrorDhcpEdgeTestCaseReadWrite, self
|
||||
).test_invalid_edge_vnic_bindings()
|
||||
del_binding.assert_called_with(mock.ANY, BAD_VNIC_BINDING['edge_id'],
|
||||
BAD_VNIC_BINDING['network_id'])
|
||||
upd_binding.assert_has_calls(
|
||||
[mock.call(mock.ANY, r['router_id'], status='ACTIVE')
|
||||
for r in FAKE_ROUTER_BINDINGS])
|
||||
|
||||
def test_invalid_edge_sub_if(self):
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings_by_edge',
|
||||
return_value=FAKE_ROUTER_BINDINGS).start()
|
||||
upd_binding = mock.patch(
|
||||
'vmware_nsx.db.nsxv_db.update_nsxv_router_binding').start()
|
||||
upd_if = mock.patch.object(self.plugin.nsx_v.vcns,
|
||||
'update_interface').start()
|
||||
super(ErrorDhcpEdgeTestCaseReadWrite, self
|
||||
).test_invalid_edge_sub_if()
|
||||
upd_binding.assert_has_calls(
|
||||
[mock.call(mock.ANY, r['router_id'], status='ACTIVE')
|
||||
for r in FAKE_ROUTER_BINDINGS])
|
||||
upd_if.assert_called_with('edge-752', BACKEND_EDGE_VNICS['vnics'][8])
|
||||
|
||||
def test_missing_edge_sub_if(self):
|
||||
deleted_sub_if = BACKEND_EDGE_VNICS['vnics'][8]['subInterfaces'][
|
||||
'subInterfaces'][1]
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings_by_edge',
|
||||
return_value=FAKE_ROUTER_BINDINGS).start()
|
||||
mock.patch.object(
|
||||
self.plugin.edge_manager, '_create_sub_interface',
|
||||
return_value=('dvportgroup-1575', deleted_sub_if)).start()
|
||||
upd_binding = mock.patch(
|
||||
'vmware_nsx.db.nsxv_db.update_nsxv_router_binding').start()
|
||||
upd_if = mock.patch.object(self.plugin.nsx_v.vcns,
|
||||
'update_interface').start()
|
||||
super(ErrorDhcpEdgeTestCaseReadWrite, self
|
||||
).test_missing_edge_sub_if()
|
||||
upd_binding.assert_has_calls(
|
||||
[mock.call(mock.ANY, r['router_id'], status='ACTIVE')
|
||||
for r in FAKE_ROUTER_BINDINGS])
|
||||
upd_if.assert_called_with('edge-752', BACKEND_EDGE_VNICS['vnics'][8])
|
||||
|
||||
def test_missing_edge_interface(self):
|
||||
def fake_create_subif(*args, **kwargs):
|
||||
deleted_sub_if = BACKEND_EDGE_VNICS['vnics'][8]['subInterfaces'][
|
||||
'subInterfaces'][fake_create_subif.ctr]
|
||||
fake_create_subif.ctr += 1
|
||||
return (BACKEND_EDGE_VNICS['vnics'][8]['portgroupId'],
|
||||
deleted_sub_if)
|
||||
|
||||
fake_create_subif.ctr = 0
|
||||
|
||||
mock.patch('vmware_nsx.db.nsxv_db.get_nsxv_router_bindings_by_edge',
|
||||
return_value=FAKE_ROUTER_BINDINGS).start()
|
||||
mock.patch.object(
|
||||
self.plugin.edge_manager, '_create_sub_interface',
|
||||
side_effect=fake_create_subif).start()
|
||||
upd_binding = mock.patch(
|
||||
'vmware_nsx.db.nsxv_db.update_nsxv_router_binding').start()
|
||||
upd_if = mock.patch.object(self.plugin.nsx_v.vcns,
|
||||
'update_interface').start()
|
||||
super(ErrorDhcpEdgeTestCaseReadWrite, self
|
||||
).test_missing_edge_interface()
|
||||
upd_binding.assert_has_calls(
|
||||
[mock.call(mock.ANY, r['router_id'], status='ACTIVE')
|
||||
for r in FAKE_ROUTER_BINDINGS])
|
||||
upd_if.assert_called_with('edge-752', BACKEND_EDGE_VNICS['vnics'][8])
|
@ -1,288 +0,0 @@
|
||||
# Copyright 2016 VMware, 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.
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from neutron.tests import base
|
||||
|
||||
from vmware_nsx.common import config
|
||||
from vmware_nsx.common import exceptions as nsx_exc
|
||||
from vmware_nsx.plugins.nsx_v import availability_zones as nsx_az
|
||||
|
||||
|
||||
DEF_AZ_POOL = ['service:compact:1:2', 'vdr:compact:1:2']
|
||||
DEF_GLOBAL_POOL = ['service:compact:4:10', 'vdr:compact:4:10']
|
||||
|
||||
|
||||
class NsxvAvailabilityZonesTestCase(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(NsxvAvailabilityZonesTestCase, self).setUp()
|
||||
self.az_name = 'zone1'
|
||||
self.group_name = 'az:%s' % self.az_name
|
||||
config.register_nsxv_azs(cfg.CONF, [self.az_name])
|
||||
cfg.CONF.set_override("ha_placement_random", True, group="nsxv")
|
||||
cfg.CONF.set_override("mgt_net_proxy_ips", ["2.2.2.2"], group="nsxv")
|
||||
cfg.CONF.set_override("dvs_id", "dvs-1", group="nsxv")
|
||||
|
||||
def _config_az(self,
|
||||
resource_pool_id="respool",
|
||||
datastore_id="datastore",
|
||||
edge_ha=True,
|
||||
ha_datastore_id="hastore",
|
||||
backup_edge_pool=DEF_AZ_POOL,
|
||||
ha_placement_random=False,
|
||||
datacenter_moid="datacenter",
|
||||
mgt_net_moid="portgroup-407",
|
||||
mgt_net_proxy_ips=["1.1.1.1"],
|
||||
mgt_net_proxy_netmask="255.255.255.0",
|
||||
mgt_net_default_gateway="2.2.2.2",
|
||||
external_network="network-17",
|
||||
vdn_scope_id="vdnscope-1",
|
||||
dvs_id="dvs-2"):
|
||||
cfg.CONF.set_override("resource_pool_id", resource_pool_id,
|
||||
group=self.group_name)
|
||||
cfg.CONF.set_override("datastore_id", datastore_id,
|
||||
group=self.group_name)
|
||||
if edge_ha is not None:
|
||||
cfg.CONF.set_override("edge_ha", edge_ha,
|
||||
group=self.group_name)
|
||||
cfg.CONF.set_override("ha_datastore_id", ha_datastore_id,
|
||||
group=self.group_name)
|
||||
if ha_placement_random is not None:
|
||||
cfg.CONF.set_override("ha_placement_random",
|
||||
ha_placement_random,
|
||||
group=self.group_name)
|
||||
if datacenter_moid is not None:
|
||||
cfg.CONF.set_override("datacenter_moid",
|
||||
datacenter_moid,
|
||||
group=self.group_name)
|
||||
if backup_edge_pool is not None:
|
||||
cfg.CONF.set_override("backup_edge_pool", backup_edge_pool,
|
||||
group=self.group_name)
|
||||
if mgt_net_moid is not None:
|
||||
cfg.CONF.set_override("mgt_net_moid", mgt_net_moid,
|
||||
group=self.group_name)
|
||||
if mgt_net_proxy_ips is not None:
|
||||
cfg.CONF.set_override("mgt_net_proxy_ips", mgt_net_proxy_ips,
|
||||
group=self.group_name)
|
||||
if mgt_net_proxy_netmask is not None:
|
||||
cfg.CONF.set_override("mgt_net_proxy_netmask",
|
||||
mgt_net_proxy_netmask,
|
||||
group=self.group_name)
|
||||
if mgt_net_default_gateway is not None:
|
||||
cfg.CONF.set_override("mgt_net_default_gateway",
|
||||
mgt_net_default_gateway,
|
||||
group=self.group_name)
|
||||
if external_network is not None:
|
||||
cfg.CONF.set_override("external_network", external_network,
|
||||
group=self.group_name)
|
||||
if vdn_scope_id is not None:
|
||||
cfg.CONF.set_override("vdn_scope_id", vdn_scope_id,
|
||||
group=self.group_name)
|
||||
if dvs_id is not None:
|
||||
cfg.CONF.set_override("dvs_id", dvs_id,
|
||||
group=self.group_name)
|
||||
|
||||
def test_simple_availability_zone(self):
|
||||
self._config_az()
|
||||
az = nsx_az.NsxVAvailabilityZone(self.az_name)
|
||||
self.assertEqual(self.az_name, az.name)
|
||||
self.assertEqual("respool", az.resource_pool)
|
||||
self.assertEqual("datastore", az.datastore_id)
|
||||
self.assertTrue(az.edge_ha)
|
||||
self.assertEqual("hastore", az.ha_datastore_id)
|
||||
self.assertFalse(az.ha_placement_random)
|
||||
self.assertEqual("datacenter", az.datacenter_moid)
|
||||
self.assertEqual(DEF_AZ_POOL, az.backup_edge_pool)
|
||||
self.assertEqual("portgroup-407", az.mgt_net_moid)
|
||||
self.assertEqual(["1.1.1.1"], az.mgt_net_proxy_ips)
|
||||
self.assertEqual("255.255.255.0", az.mgt_net_proxy_netmask)
|
||||
self.assertEqual("2.2.2.2", az.mgt_net_default_gateway)
|
||||
self.assertEqual("network-17", az.external_network)
|
||||
self.assertEqual("vdnscope-1", az.vdn_scope_id)
|
||||
self.assertEqual("dvs-2", az.dvs_id)
|
||||
self.assertTrue(az.az_metadata_support)
|
||||
|
||||
def test_availability_zone_no_edge_ha(self):
|
||||
self._config_az(edge_ha=False)
|
||||
az = nsx_az.NsxVAvailabilityZone(self.az_name)
|
||||
self.assertEqual(self.az_name, az.name)
|
||||
self.assertEqual("respool", az.resource_pool)
|
||||
self.assertEqual("datastore", az.datastore_id)
|
||||
self.assertFalse(az.edge_ha)
|
||||
self.assertIsNone(az.ha_datastore_id)
|
||||
self.assertFalse(az.ha_placement_random)
|
||||
|
||||
def test_availability_zone_no_ha_datastore(self):
|
||||
self._config_az(ha_datastore_id=None)
|
||||
az = nsx_az.NsxVAvailabilityZone(self.az_name)
|
||||
self.assertEqual(self.az_name, az.name)
|
||||
self.assertEqual("respool", az.resource_pool)
|
||||
self.assertEqual("datastore", az.datastore_id)
|
||||
self.assertTrue(az.edge_ha)
|
||||
self.assertIsNone(az.ha_datastore_id)
|
||||
self.assertFalse(az.ha_placement_random)
|
||||
|
||||
def test_missing_group_section(self):
|
||||
self.assertRaises(
|
||||
nsx_exc.NsxInvalidConfiguration,
|
||||
nsx_az.NsxVAvailabilityZone,
|
||||
"doesnt_exist")
|
||||
|
||||
def test_availability_zone_missing_respool(self):
|
||||
self._config_az(resource_pool_id=None)
|
||||
self.assertRaises(
|
||||
nsx_exc.NsxInvalidConfiguration,
|
||||
nsx_az.NsxVAvailabilityZone,
|
||||
self.az_name)
|
||||
|
||||
def test_availability_zone_missing_datastore(self):
|
||||
self._config_az(datastore_id=None)
|
||||
self.assertRaises(
|
||||
nsx_exc.NsxInvalidConfiguration,
|
||||
nsx_az.NsxVAvailabilityZone,
|
||||
self.az_name)
|
||||
|
||||
def test_availability_zone_missing_edge_ha(self):
|
||||
self._config_az(edge_ha=None)
|
||||
az = nsx_az.NsxVAvailabilityZone(self.az_name)
|
||||
self.assertEqual(self.az_name, az.name)
|
||||
self.assertEqual("respool", az.resource_pool)
|
||||
self.assertEqual("datastore", az.datastore_id)
|
||||
self.assertFalse(az.edge_ha)
|
||||
self.assertIsNone(az.ha_datastore_id)
|
||||
self.assertFalse(az.ha_placement_random)
|
||||
|
||||
def test_availability_zone_missing_edge_placement(self):
|
||||
self._config_az(ha_placement_random=None)
|
||||
az = nsx_az.NsxVAvailabilityZone(self.az_name)
|
||||
self.assertEqual(self.az_name, az.name)
|
||||
self.assertEqual("respool", az.resource_pool)
|
||||
self.assertEqual("datastore", az.datastore_id)
|
||||
self.assertTrue(az.edge_ha)
|
||||
self.assertEqual("hastore", az.ha_datastore_id)
|
||||
# ha_placement_random should have the global value
|
||||
self.assertTrue(az.ha_placement_random)
|
||||
|
||||
def test_availability_zone_missing_backup_pool(self):
|
||||
self._config_az(backup_edge_pool=None)
|
||||
az = nsx_az.NsxVAvailabilityZone(self.az_name)
|
||||
self.assertEqual(self.az_name, az.name)
|
||||
# Should use the global configuration instead
|
||||
self.assertEqual(DEF_GLOBAL_POOL, az.backup_edge_pool)
|
||||
|
||||
def test_availability_zone_missing_metadata(self):
|
||||
self._config_az(mgt_net_proxy_ips=None, dvs_id=None)
|
||||
az = nsx_az.NsxVAvailabilityZone(self.az_name)
|
||||
self.assertIsNone(az.mgt_net_moid)
|
||||
self.assertEqual([], az.mgt_net_proxy_ips)
|
||||
self.assertIsNone(az.mgt_net_proxy_netmask)
|
||||
self.assertIsNone(az.mgt_net_default_gateway)
|
||||
self.assertFalse(az.az_metadata_support)
|
||||
|
||||
def test_availability_zone_same_metadata(self):
|
||||
self._config_az(mgt_net_proxy_ips=["2.2.2.2"])
|
||||
self.assertRaises(
|
||||
nsx_exc.NsxInvalidConfiguration,
|
||||
nsx_az.NsxVAvailabilityZone,
|
||||
self.az_name)
|
||||
|
||||
self._config_az(mgt_net_proxy_ips=["2.2.2.2", "3.3.3.3"])
|
||||
self.assertRaises(
|
||||
nsx_exc.NsxInvalidConfiguration,
|
||||
nsx_az.NsxVAvailabilityZone,
|
||||
self.az_name)
|
||||
|
||||
|
||||
class NsxvAvailabilityZonesOldTestCase(base.BaseTestCase):
|
||||
"""Test old way of configuring the availability zones
|
||||
|
||||
using a one-line configuration instead of different dynamic sections
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(NsxvAvailabilityZonesOldTestCase, self).setUp()
|
||||
cfg.CONF.set_override("mgt_net_proxy_ips", ["2.2.2.2"], group="nsxv")
|
||||
cfg.CONF.set_override("dvs_id", "dvs-1", group="nsxv")
|
||||
|
||||
def test_simple_availability_zone(self):
|
||||
az = nsx_az.NsxVAvailabilityZone(
|
||||
"name:respool:datastore:true:hastore")
|
||||
self.assertEqual("name", az.name)
|
||||
self.assertEqual("respool", az.resource_pool)
|
||||
self.assertEqual("datastore", az.datastore_id)
|
||||
self.assertTrue(az.edge_ha)
|
||||
self.assertEqual("hastore", az.ha_datastore_id)
|
||||
self.assertFalse(az.ha_placement_random)
|
||||
self.assertEqual(DEF_GLOBAL_POOL, az.backup_edge_pool)
|
||||
# should get the global configuration (which is empty now)
|
||||
self.assertIsNone(az.external_network)
|
||||
self.assertIsNone(az.vdn_scope_id)
|
||||
self.assertEqual("dvs-1", az.dvs_id)
|
||||
# no metadata per az support
|
||||
self.assertFalse(az.az_metadata_support)
|
||||
self.assertIsNone(az.mgt_net_moid)
|
||||
self.assertEqual([], az.mgt_net_proxy_ips)
|
||||
self.assertIsNone(az.mgt_net_proxy_netmask)
|
||||
self.assertIsNone(az.mgt_net_default_gateway)
|
||||
|
||||
def test_availability_zone_without_ha_datastore(self):
|
||||
az = nsx_az.NsxVAvailabilityZone(
|
||||
"name:respool:datastore:true")
|
||||
self.assertEqual("name", az.name)
|
||||
self.assertEqual("respool", az.resource_pool)
|
||||
self.assertEqual("datastore", az.datastore_id)
|
||||
self.assertTrue(az.edge_ha)
|
||||
self.assertIsNone(az.ha_datastore_id)
|
||||
|
||||
def test_availability_zone_without_edge_ha(self):
|
||||
az = nsx_az.NsxVAvailabilityZone(
|
||||
"name:respool:datastore:FALSE")
|
||||
self.assertEqual("name", az.name)
|
||||
self.assertEqual("respool", az.resource_pool)
|
||||
self.assertEqual("datastore", az.datastore_id)
|
||||
self.assertFalse(az.edge_ha)
|
||||
self.assertIsNone(az.ha_datastore_id)
|
||||
|
||||
def test_availability_fail_long_name(self):
|
||||
self.assertRaises(
|
||||
nsx_exc.NsxInvalidConfiguration,
|
||||
nsx_az.NsxVAvailabilityZone,
|
||||
"very-very-very-very-very-longest-name:respool:da:true:ha")
|
||||
|
||||
def test_availability_fail_few_args(self):
|
||||
self.assertRaises(
|
||||
nsx_exc.NsxInvalidConfiguration,
|
||||
nsx_az.NsxVAvailabilityZone,
|
||||
"name:respool")
|
||||
|
||||
def test_availability_fail_many_args(self):
|
||||
self.assertRaises(
|
||||
nsx_exc.NsxInvalidConfiguration,
|
||||
nsx_az.NsxVAvailabilityZone,
|
||||
"name:1:2:3:4:5:6")
|
||||
|
||||
def test_availability_fail_bad_edge_ha(self):
|
||||
self.assertRaises(
|
||||
nsx_exc.NsxInvalidConfiguration,
|
||||
nsx_az.NsxVAvailabilityZone,
|
||||
"name:respool:datastore:truex:hastore")
|
||||
|
||||
def test_availability_fail_no_ha_datastore(self):
|
||||
self.assertRaises(
|
||||
nsx_exc.NsxInvalidConfiguration,
|
||||
nsx_az.NsxVAvailabilityZone,
|
||||
"name:respool:datastore:false:hastore")
|
File diff suppressed because it is too large
Load Diff
@ -1,402 +0,0 @@
|
||||
# Copyright 2018 VMware, 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 copy
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from vmware_nsx.db import nsxv_models
|
||||
from vmware_nsx.plugins.nsx_v.vshield import edge_firewall_driver
|
||||
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
|
||||
from vmware_nsx.services.fwaas.nsx_v import edge_fwaas_driver_v2
|
||||
from vmware_nsx.services.fwaas.nsx_v import fwaas_callbacks_v2
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin as test_v_plugin
|
||||
|
||||
FAKE_FW_ID = 'fake_fw_uuid'
|
||||
FAKE_ROUTER_ID = 'fake_rtr_uuid'
|
||||
FAKE_PORT_ID = 'fake_port_uuid'
|
||||
FAKE_NET_ID = 'fake_net_uuid'
|
||||
FAKE_DB_OBJ = nsxv_models.NsxvEdgeVnicBinding(vnic_index='1')
|
||||
|
||||
|
||||
class NsxvFwaasTestCase(test_v_plugin.NsxVPluginV2TestCase):
|
||||
def setUp(self):
|
||||
super(NsxvFwaasTestCase, self).setUp()
|
||||
self.firewall = edge_fwaas_driver_v2.EdgeFwaasVDriverV2()
|
||||
|
||||
self.plugin = directory.get_plugin()
|
||||
self.plugin.fwaas_callbacks = fwaas_callbacks_v2.\
|
||||
NsxvFwaasCallbacksV2(False)
|
||||
self.plugin.fwaas_callbacks.fwaas_enabled = True
|
||||
self.plugin.fwaas_callbacks.fwaas_driver = self.firewall
|
||||
self.plugin.fwaas_callbacks.internal_driver = self.firewall
|
||||
self.plugin.init_is_complete = True
|
||||
self.plugin.metadata_proxy_handler = None
|
||||
|
||||
# Start some mocks
|
||||
self.router = {'id': FAKE_ROUTER_ID,
|
||||
'external_gateway_info': {'network_id': 'external'},
|
||||
'nsx_attributes': {'distributed': False,
|
||||
'router_type': 'exclusive'}}
|
||||
self.distributed_router = {'id': FAKE_ROUTER_ID,
|
||||
'external_gateway_info': {'network_id': 'external'},
|
||||
'nsx_attributes': {'distributed': True,
|
||||
'router_type': 'exclusive'}}
|
||||
mock.patch.object(self.plugin, '_get_router',
|
||||
return_value=self.router).start()
|
||||
mock.patch.object(self.plugin, 'get_router',
|
||||
return_value=self.router).start()
|
||||
self.port = {'id': FAKE_PORT_ID, 'network_id': FAKE_NET_ID}
|
||||
mock.patch.object(self.plugin, '_get_router_interfaces',
|
||||
return_value=[self.port]).start()
|
||||
mock.patch.object(self.plugin, 'get_port',
|
||||
return_value=self.port).start()
|
||||
mock.patch.object(self.plugin, '_get_subnet_fw_rules',
|
||||
return_value=[]).start()
|
||||
mock.patch.object(self.plugin, '_get_firewall_icmpv6_rules',
|
||||
return_value=[]).start()
|
||||
mock.patch.object(self.plugin, '_get_dnat_fw_rule',
|
||||
return_value=[]).start()
|
||||
mock.patch.object(self.plugin, '_get_allocation_pools_fw_rule',
|
||||
return_value=[]).start()
|
||||
mock.patch.object(self.plugin, '_get_nosnat_subnets_fw_rules',
|
||||
return_value=[]).start()
|
||||
|
||||
def _fake_rules_v4(self, is_ingress=True, is_conflict=False,
|
||||
cidr='10.24.4.0/24'):
|
||||
rule1 = {'enabled': True,
|
||||
'action': 'allow',
|
||||
'ip_version': 4,
|
||||
'protocol': 'tcp',
|
||||
'destination_port': '80',
|
||||
'id': 'fake-fw-rule1',
|
||||
'description': 'first rule',
|
||||
'position': '0'}
|
||||
rule2 = {'enabled': True,
|
||||
'action': 'reject',
|
||||
'ip_version': 4,
|
||||
'protocol': 'tcp',
|
||||
'destination_port': '22:24',
|
||||
'source_port': '1:65535',
|
||||
'id': 'fake-fw-rule2',
|
||||
'position': '1'}
|
||||
rule3 = {'enabled': True,
|
||||
'action': 'deny',
|
||||
'ip_version': 4,
|
||||
'protocol': 'icmp',
|
||||
'id': 'fake-fw-rule3',
|
||||
'position': '2'}
|
||||
rule4 = {'enabled': True,
|
||||
'action': 'deny',
|
||||
'ip_version': 4,
|
||||
'id': 'fake-fw-rule4',
|
||||
'position': '3'}
|
||||
if is_ingress:
|
||||
if not is_conflict:
|
||||
rule1['source_ip_address'] = cidr
|
||||
else:
|
||||
rule1['destination_ip_address'] = cidr
|
||||
else:
|
||||
if not is_conflict:
|
||||
rule1['destination_ip_address'] = cidr
|
||||
else:
|
||||
rule1['source_ip_address'] = cidr
|
||||
|
||||
return [rule1, rule2, rule3, rule4]
|
||||
|
||||
def _fake_translated_rules(self, rules_list,
|
||||
nsx_port_id,
|
||||
is_ingress=True,
|
||||
logged=False, fwg_id=None):
|
||||
translated_rules = copy.copy(rules_list)
|
||||
for rule in translated_rules:
|
||||
if logged:
|
||||
rule['logged'] = True
|
||||
if is_ingress:
|
||||
if (not rule.get('destination_ip_address') or
|
||||
rule['destination_ip_address'].startswith('0.0.0.0')):
|
||||
if nsx_port_id:
|
||||
rule['destination_vnic_groups'] = [nsx_port_id]
|
||||
else:
|
||||
if (not rule.get('source_ip_address') or
|
||||
rule['source_ip_address'].startswith('0.0.0.0')):
|
||||
if nsx_port_id:
|
||||
rule['source_vnic_groups'] = [nsx_port_id]
|
||||
if rule.get('destination_ip_address'):
|
||||
if rule['destination_ip_address'].startswith('0.0.0.0'):
|
||||
del rule['destination_ip_address']
|
||||
else:
|
||||
rule['destination_ip_address'] = [
|
||||
rule['destination_ip_address']]
|
||||
if rule.get('source_ip_address'):
|
||||
if rule['source_ip_address'].startswith('0.0.0.0'):
|
||||
del rule['source_ip_address']
|
||||
else:
|
||||
rule['source_ip_address'] = [
|
||||
rule['source_ip_address']]
|
||||
rule['name'] = (fwaas_callbacks_v2.RULE_NAME_PREFIX +
|
||||
(rule.get('name') or rule['id']))[:30]
|
||||
if rule.get('id'):
|
||||
if is_ingress:
|
||||
rule['id'] = ('ingress-%s-%s' % (nsx_port_id or fwg_id,
|
||||
rule['id']))[:36]
|
||||
else:
|
||||
rule['id'] = ('egress-%s-%s' % (nsx_port_id or fwg_id,
|
||||
rule['id']))[:36]
|
||||
|
||||
return translated_rules
|
||||
|
||||
def _fake_empty_firewall_group(self):
|
||||
fw_inst = {'id': FAKE_FW_ID,
|
||||
'admin_state_up': True,
|
||||
'tenant_id': 'tenant-uuid',
|
||||
'ingress_rule_list': [],
|
||||
'egress_rule_list': []}
|
||||
return fw_inst
|
||||
|
||||
def _fake_firewall_group(self, rule_list, is_ingress=True,
|
||||
admin_state_up=True):
|
||||
_rule_list = copy.deepcopy(rule_list)
|
||||
for rule in _rule_list:
|
||||
rule['position'] = str(_rule_list.index(rule))
|
||||
fw_inst = {'id': FAKE_FW_ID,
|
||||
'admin_state_up': admin_state_up,
|
||||
'tenant_id': 'tenant-uuid',
|
||||
'ingress_rule_list': [],
|
||||
'egress_rule_list': []}
|
||||
if is_ingress:
|
||||
fw_inst['ingress_rule_list'] = _rule_list
|
||||
else:
|
||||
fw_inst['egress_rule_list'] = _rule_list
|
||||
return fw_inst
|
||||
|
||||
def _fake_firewall_group_with_admin_down(self, rule_list,
|
||||
is_ingress=True):
|
||||
return self._fake_firewall_group(
|
||||
rule_list, is_ingress=is_ingress, admin_state_up=False)
|
||||
|
||||
def _fake_apply_list_template(self, router):
|
||||
router_inst = router
|
||||
router_info_inst = mock.Mock()
|
||||
router_info_inst.router = router_inst
|
||||
router_info_inst.router_id = FAKE_ROUTER_ID
|
||||
apply_list = [(router_info_inst, FAKE_PORT_ID)]
|
||||
return apply_list
|
||||
|
||||
def _fake_apply_list(self):
|
||||
return self._fake_apply_list_template(self.router)
|
||||
|
||||
def _fake_distributed_apply_list(self):
|
||||
return self._fake_apply_list_template(self.distributed_router)
|
||||
|
||||
def test_create_firewall_no_rules(self):
|
||||
apply_list = self._fake_apply_list()
|
||||
firewall = self._fake_empty_firewall_group()
|
||||
with mock.patch.object(self.plugin.fwaas_callbacks, 'get_port_fwg',
|
||||
return_value=firewall),\
|
||||
mock.patch.object(self.plugin.fwaas_callbacks,
|
||||
'_get_port_firewall_group_id',
|
||||
return_value=FAKE_FW_ID),\
|
||||
mock.patch.object(self.plugin.fwaas_callbacks,
|
||||
'_get_fw_group_from_plugin',
|
||||
return_value=firewall),\
|
||||
mock.patch("vmware_nsx.db.nsxv_db.get_edge_vnic_binding",
|
||||
return_value=FAKE_DB_OBJ),\
|
||||
mock.patch.object(edge_utils, "update_firewall") as update_fw,\
|
||||
mock.patch.object(edge_utils, 'get_router_edge_id',
|
||||
return_value='edge-1'):
|
||||
self.firewall.create_firewall_group('nsx', apply_list, firewall)
|
||||
# expecting 2 block rules for the logical port (egress & ingress)
|
||||
# and last default allow all rule
|
||||
expected_rules = [
|
||||
{'name': "Block port ingress",
|
||||
'action': edge_firewall_driver.FWAAS_DENY,
|
||||
'destination_vnic_groups': ['vnic-index-1'],
|
||||
'logged': False},
|
||||
{'name': "Block port egress",
|
||||
'action': edge_firewall_driver.FWAAS_DENY,
|
||||
'source_vnic_groups': ['vnic-index-1'],
|
||||
'logged': False}]
|
||||
update_fw.assert_called_once_with(
|
||||
self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID,
|
||||
{'firewall_rule_list': expected_rules})
|
||||
|
||||
def _setup_firewall_with_rules(self, func, is_ingress=True,
|
||||
is_conflict=False, cidr='10.24.4.0/24'):
|
||||
apply_list = self._fake_apply_list()
|
||||
rule_list = self._fake_rules_v4(is_ingress=is_ingress,
|
||||
is_conflict=is_conflict, cidr=cidr)
|
||||
firewall = self._fake_firewall_group(rule_list, is_ingress=is_ingress)
|
||||
with mock.patch.object(self.plugin.fwaas_callbacks, 'get_port_fwg',
|
||||
return_value=firewall),\
|
||||
mock.patch.object(self.plugin.fwaas_callbacks,
|
||||
'_get_port_firewall_group_id',
|
||||
return_value=FAKE_FW_ID),\
|
||||
mock.patch.object(self.plugin.fwaas_callbacks,
|
||||
'_get_fw_group_from_plugin',
|
||||
return_value=firewall),\
|
||||
mock.patch("vmware_nsx.db.nsxv_db.get_edge_vnic_binding",
|
||||
return_value=FAKE_DB_OBJ),\
|
||||
mock.patch.object(edge_utils, "update_firewall") as update_fw,\
|
||||
mock.patch.object(edge_utils, 'get_router_edge_id',
|
||||
return_value='edge-1'):
|
||||
func('nsx', apply_list, firewall)
|
||||
expected_rules = self._fake_translated_rules(
|
||||
rule_list,
|
||||
'vnic-index-1', is_ingress=is_ingress) + [
|
||||
{'name': "Block port ingress",
|
||||
'action': edge_firewall_driver.FWAAS_DENY,
|
||||
'destination_vnic_groups': ['vnic-index-1'],
|
||||
'logged': False},
|
||||
{'name': "Block port egress",
|
||||
'action': edge_firewall_driver.FWAAS_DENY,
|
||||
'source_vnic_groups': ['vnic-index-1'],
|
||||
'logged': False}]
|
||||
|
||||
update_fw.assert_called_once_with(
|
||||
self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID,
|
||||
{'firewall_rule_list': expected_rules})
|
||||
|
||||
def test_create_firewall_with_ingress_rules(self):
|
||||
self._setup_firewall_with_rules(self.firewall.create_firewall_group)
|
||||
|
||||
def test_update_firewall_with_ingress_rules(self):
|
||||
self._setup_firewall_with_rules(self.firewall.update_firewall_group)
|
||||
|
||||
def test_create_firewall_with_egress_rules(self):
|
||||
self._setup_firewall_with_rules(self.firewall.create_firewall_group,
|
||||
is_ingress=False)
|
||||
|
||||
def test_create_firewall_with_illegal_cidr(self):
|
||||
self._setup_firewall_with_rules(self.firewall.create_firewall_group,
|
||||
cidr='0.0.0.0/24')
|
||||
|
||||
def test_update_firewall_with_egress_rules(self):
|
||||
self._setup_firewall_with_rules(self.firewall.update_firewall_group,
|
||||
is_ingress=False)
|
||||
|
||||
def test_update_firewall_with_egress_conflicting_rules(self):
|
||||
self._setup_firewall_with_rules(self.firewall.update_firewall_group,
|
||||
is_ingress=False, is_conflict=True)
|
||||
|
||||
def test_update_firewall_with_ingress_conflicting_rules(self):
|
||||
self._setup_firewall_with_rules(self.firewall.update_firewall_group,
|
||||
is_ingress=True, is_conflict=True)
|
||||
|
||||
def test_delete_firewall(self):
|
||||
apply_list = self._fake_apply_list()
|
||||
firewall = self._fake_empty_firewall_group()
|
||||
with mock.patch.object(self.plugin.fwaas_callbacks, 'get_port_fwg',
|
||||
return_value=None),\
|
||||
mock.patch("vmware_nsx.db.db.get_nsx_switch_and_port_id",
|
||||
return_value=('vnic-index-1', 0)),\
|
||||
mock.patch.object(edge_utils, "update_firewall") as update_fw,\
|
||||
mock.patch.object(self.plugin.fwaas_callbacks,
|
||||
'_get_port_firewall_group_id',
|
||||
return_value=None),\
|
||||
mock.patch.object(edge_utils, 'get_router_edge_id',
|
||||
return_value='edge-1'):
|
||||
self.firewall.delete_firewall_group('nsx', apply_list, firewall)
|
||||
update_fw.assert_called_once_with(
|
||||
self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID,
|
||||
{'firewall_rule_list': []})
|
||||
|
||||
def test_create_firewall_with_admin_down(self):
|
||||
apply_list = self._fake_apply_list()
|
||||
rule_list = self._fake_rules_v4()
|
||||
firewall = self._fake_firewall_group_with_admin_down(rule_list)
|
||||
with mock.patch.object(edge_utils, "update_firewall") as update_fw,\
|
||||
mock.patch.object(self.plugin.fwaas_callbacks,
|
||||
'_get_port_firewall_group_id',
|
||||
return_value=None),\
|
||||
mock.patch.object(edge_utils, 'get_router_edge_id',
|
||||
return_value='edge-1'):
|
||||
self.firewall.create_firewall_group('nsx', apply_list, firewall)
|
||||
update_fw.assert_called_once_with(
|
||||
self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID,
|
||||
{'firewall_rule_list': []})
|
||||
|
||||
def _setup_dist_router_firewall_with_rules(self, func, is_ingress=True,
|
||||
is_conflict=False,
|
||||
cidr='10.24.4.0/24'):
|
||||
apply_list = self._fake_distributed_apply_list()
|
||||
rule_list = self._fake_rules_v4(is_ingress=is_ingress,
|
||||
is_conflict=is_conflict, cidr=cidr)
|
||||
firewall = self._fake_firewall_group(rule_list, is_ingress=is_ingress)
|
||||
with mock.patch.object(self.plugin.fwaas_callbacks, 'get_port_fwg',
|
||||
return_value=firewall),\
|
||||
mock.patch.object(self.plugin.fwaas_callbacks,
|
||||
'_get_port_firewall_group_id',
|
||||
return_value=FAKE_FW_ID),\
|
||||
mock.patch.object(self.plugin.fwaas_callbacks,
|
||||
'_get_fw_group_from_plugin',
|
||||
return_value=firewall),\
|
||||
mock.patch.object(edge_utils, "update_firewall") as update_fw,\
|
||||
mock.patch.object(edge_utils, 'get_router_edge_id',
|
||||
return_value='edge-1'),\
|
||||
mock.patch.object(self.plugin.edge_manager, 'get_plr_by_tlr_id',
|
||||
return_value=FAKE_ROUTER_ID),\
|
||||
mock.patch.object(self.plugin, '_get_router',
|
||||
return_value=self.distributed_router),\
|
||||
mock.patch.object(self.plugin, 'get_router',
|
||||
return_value=self.distributed_router):
|
||||
func('nsx', apply_list, firewall)
|
||||
expected_rules = self._fake_translated_rules(
|
||||
rule_list, None, is_ingress=is_ingress, fwg_id=FAKE_FW_ID) + [
|
||||
{'name': "Block port ingress",
|
||||
'action': edge_firewall_driver.FWAAS_DENY,
|
||||
'logged': False},
|
||||
{'name': "Block port egress",
|
||||
'action': edge_firewall_driver.FWAAS_DENY,
|
||||
'logged': False}]
|
||||
|
||||
update_fw.assert_called_once_with(
|
||||
self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID,
|
||||
{'firewall_rule_list': expected_rules})
|
||||
|
||||
def test_create_dist_router_firewall_with_ingress_rules(self):
|
||||
self._setup_dist_router_firewall_with_rules(
|
||||
self.firewall.create_firewall_group)
|
||||
|
||||
def test_update_dist_router_firewall_with_ingress_rules(self):
|
||||
self._setup_dist_router_firewall_with_rules(
|
||||
self.firewall.update_firewall_group)
|
||||
|
||||
def test_create_dist_router_firewall_with_egress_rules(self):
|
||||
self._setup_dist_router_firewall_with_rules(
|
||||
self.firewall.create_firewall_group,
|
||||
is_ingress=False)
|
||||
|
||||
def test_create_dist_router_firewall_with_illegal_cidr(self):
|
||||
self._setup_dist_router_firewall_with_rules(
|
||||
self.firewall.create_firewall_group,
|
||||
cidr='0.0.0.0/24')
|
||||
|
||||
def test_update_dist_router_firewall_with_egress_rules(self):
|
||||
self._setup_dist_router_firewall_with_rules(
|
||||
self.firewall.update_firewall_group,
|
||||
is_ingress=False)
|
||||
|
||||
def test_update_dist_router_firewall_with_egress_conflicting_rules(self):
|
||||
self._setup_dist_router_firewall_with_rules(
|
||||
self.firewall.update_firewall_group,
|
||||
is_ingress=False, is_conflict=True)
|
||||
|
||||
def test_update_dist_router_firewall_with_ingress_conflicting_rules(self):
|
||||
self._setup_dist_router_firewall_with_rules(
|
||||
self.firewall.update_firewall_group,
|
||||
is_ingress=True, is_conflict=True)
|
@ -1,128 +0,0 @@
|
||||
# Copyright 2015 VMware, 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.
|
||||
from unittest import mock
|
||||
|
||||
from neutron.tests import base
|
||||
|
||||
from vmware_nsx.plugins.nsx_v.vshield import vcns_driver
|
||||
from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common
|
||||
|
||||
|
||||
EDGE_ID = 'edge-x'
|
||||
POOL_ID = 'b3dfb476-6fdf-4ddd-b6bd-e86ae78dc30b'
|
||||
|
||||
|
||||
def firewall_section_maker(if_ip_list, vip_ip_list):
|
||||
return (
|
||||
'<section id="1132" name="LBaaS FW Rules"><rule><name>' + POOL_ID +
|
||||
'</name><action>allow</action><sources excluded="false"><source>'
|
||||
'<type>Ipv4Address</type><value>' + ','.join(if_ip_list) +
|
||||
'</value></source></sources><destinations excluded="false">'
|
||||
'<destination><type>Ipv4Address</type><value>' +
|
||||
','.join(vip_ip_list) + '</value></destination></destinations></rule>'
|
||||
'</section>')
|
||||
|
||||
|
||||
def if_maker(ip_list):
|
||||
intf = {
|
||||
'index': 1, 'name': 'internal1', 'addressGroups': {
|
||||
'addressGroups': [
|
||||
{'subnetPrefixLength': '24',
|
||||
'secondaryAddresses': {
|
||||
'ipAddress': ip_list,
|
||||
'type': 'secondary_addresses'},
|
||||
'primaryAddress': '10.0.0.1',
|
||||
'subnetMask': '255.255.255.0'}]},
|
||||
'portgroupName': 'pg1234', 'label': 'vNic_1',
|
||||
'type': 'internal', 'portgroupId': 'virtualwire-31'}
|
||||
return intf
|
||||
|
||||
|
||||
def if_list_maker(ip_list):
|
||||
if_list = {
|
||||
'vnics': [
|
||||
{'index': 0, 'name': 'external', 'addressGroups': {
|
||||
'addressGroups': [
|
||||
{'subnetMask': '255.255.255.0',
|
||||
'primaryAddress': '172.24.4.2',
|
||||
'subnetPrefixLength': '24'}]},
|
||||
'portgroupName': 'VM Network', 'label': 'vNic_0',
|
||||
'type': 'uplink', 'portgroupId': 'network-13'},
|
||||
{'index': 1, 'name': 'internal1', 'addressGroups': {
|
||||
'addressGroups': [
|
||||
{'subnetPrefixLength': '24',
|
||||
'secondaryAddresses': {
|
||||
'ipAddress': ip_list,
|
||||
'type': 'secondary_addresses'},
|
||||
'primaryAddress': '10.0.0.1',
|
||||
'subnetMask': '255.255.255.0'}]},
|
||||
'portgroupName': 'pg1234',
|
||||
'label': 'vNic_1', 'type': 'internal',
|
||||
'portgroupId': 'virtualwire-31'},
|
||||
{'index': 2, 'name': 'vnic2',
|
||||
'addressGroups': {'addressGroups': []},
|
||||
'label': 'vNic_2', 'type': 'internal'},
|
||||
{'index': 3, 'name': 'vnic3',
|
||||
'addressGroups': {'addressGroups': []},
|
||||
'label': 'vNic_3', 'type': 'internal'}]}
|
||||
return if_list
|
||||
|
||||
|
||||
class TestLbaasCommon(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestLbaasCommon, self).setUp()
|
||||
callbacks = mock.Mock()
|
||||
callbacks.plugin = mock.Mock()
|
||||
self.edge_driver = vcns_driver.VcnsDriver(callbacks)
|
||||
self.edge_driver._lb_driver_prop = mock.Mock()
|
||||
|
||||
def _mock_edge_driver_vcns(self, attr):
|
||||
return mock.patch.object(self.edge_driver.vcns, attr)
|
||||
|
||||
def test_add_vip_as_secondary_ip(self):
|
||||
update_if = if_maker(['10.0.0.6', '10.0.0.8'])
|
||||
|
||||
with self._mock_edge_driver_vcns('get_interfaces') as mock_get_if,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_interface') as mock_update_if:
|
||||
|
||||
mock_get_if.return_value = (None, if_list_maker(['10.0.0.6']))
|
||||
|
||||
lb_common.add_vip_as_secondary_ip(
|
||||
self.edge_driver.vcns, EDGE_ID, '10.0.0.8')
|
||||
mock_update_if.assert_called_with(EDGE_ID, update_if)
|
||||
|
||||
def test_del_vip_as_secondary_ip(self):
|
||||
update_if = if_maker(['10.0.0.6'])
|
||||
|
||||
with self._mock_edge_driver_vcns('get_interfaces') as mock_get_if,\
|
||||
self._mock_edge_driver_vcns(
|
||||
'update_interface') as mock_update_if:
|
||||
|
||||
mock_get_if.return_value = (None, if_list_maker(['10.0.0.6',
|
||||
'10.0.0.8']))
|
||||
|
||||
lb_common.del_vip_as_secondary_ip(
|
||||
self.edge_driver.vcns, EDGE_ID, '10.0.0.8')
|
||||
mock_update_if.assert_called_with(EDGE_ID, update_if)
|
||||
|
||||
def test_get_edge_ip_addresses(self):
|
||||
get_if_list = if_list_maker(['10.0.0.6'])
|
||||
|
||||
with mock.patch.object(self.edge_driver.vcns, 'get_interfaces',
|
||||
return_value=(None, get_if_list)):
|
||||
ip_list = lb_common.get_edge_ip_addresses(self.edge_driver.vcns,
|
||||
EDGE_ID)
|
||||
self.assertEqual(['172.24.4.2', '10.0.0.1'], ip_list)
|
@ -1,79 +0,0 @@
|
||||
# Copyright (c) 2014 VMware.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from neutron.tests import base
|
||||
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions
|
||||
from vmware_nsx.plugins.nsx_v.vshield import vcns
|
||||
|
||||
|
||||
def raise_until_attempt(attempt, exception):
|
||||
def raises_until():
|
||||
if raises_until.current_attempt < attempt:
|
||||
raises_until.current_attempt += 1
|
||||
raise exception
|
||||
else:
|
||||
return raises_until.current_attempt
|
||||
raises_until.current_attempt = 1
|
||||
return raises_until
|
||||
|
||||
|
||||
class TestMisc(base.BaseTestCase):
|
||||
response = """
|
||||
<error><details>Dummy</details><errorCode>1</errorCode>
|
||||
<moduleName>core-services</moduleName></error>
|
||||
"""
|
||||
|
||||
def test_retry_on_exception_one_attempt(self):
|
||||
success_on_first_attempt = raise_until_attempt(
|
||||
1, exceptions.RequestBad(uri='', response=''))
|
||||
should_return_one = vcns.retry_upon_exception(
|
||||
exceptions.RequestBad,
|
||||
max_attempts=1)(success_on_first_attempt)
|
||||
self.assertEqual(1, should_return_one())
|
||||
|
||||
def test_retry_on_exception_five_attempts(self):
|
||||
success_on_fifth_attempt = raise_until_attempt(
|
||||
5, exceptions.RequestBad(uri='', response=''))
|
||||
should_return_five = vcns.retry_upon_exception(
|
||||
exceptions.RequestBad,
|
||||
max_attempts=10)(success_on_fifth_attempt)
|
||||
self.assertEqual(5, should_return_five())
|
||||
|
||||
def test_retry_on_exception_exceed_attempts(self):
|
||||
success_on_fifth_attempt = raise_until_attempt(
|
||||
5, exceptions.RequestBad(uri='', response=''))
|
||||
should_raise = vcns.retry_upon_exception(
|
||||
exceptions.RequestBad,
|
||||
max_attempts=4)(success_on_fifth_attempt)
|
||||
self.assertRaises(exceptions.RequestBad, should_raise)
|
||||
|
||||
def test_retry_on_exception_exclude_error_codes_retry(self):
|
||||
success_on_fifth_attempt = raise_until_attempt(
|
||||
5, exceptions.RequestBad(uri='', response=self.response))
|
||||
# excluding another error code, so should retry
|
||||
should_return_five = vcns.retry_upon_exception_exclude_error_codes(
|
||||
exceptions.RequestBad, [2],
|
||||
max_attempts=10)(success_on_fifth_attempt)
|
||||
self.assertEqual(5, should_return_five())
|
||||
|
||||
def test_retry_on_exception_exclude_error_codes_raise(self):
|
||||
success_on_fifth_attempt = raise_until_attempt(
|
||||
5, exceptions.RequestBad(uri='', response=self.response))
|
||||
# excluding the returned error code, so no retries are expected
|
||||
should_raise = vcns.retry_upon_exception_exclude_error_codes(
|
||||
exceptions.RequestBad, [1],
|
||||
max_attempts=10)(success_on_fifth_attempt)
|
||||
self.assertRaises(exceptions.RequestBad, should_raise)
|
@ -1,94 +0,0 @@
|
||||
# Copyright 2014 VMware, 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.
|
||||
from unittest import mock
|
||||
|
||||
from neutron.tests import base
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from vmware_nsx.plugins.nsx_v.vshield import nsxv_loadbalancer
|
||||
from vmware_nsx.plugins.nsx_v.vshield import vcns
|
||||
|
||||
|
||||
class NsxvLoadbalancerTestCase(base.BaseTestCase):
|
||||
|
||||
EDGE_OBJ_JSON = (
|
||||
'{"accelerationEnabled":false,"applicationProfile":[{'
|
||||
'"applicationProfileId":"applicationProfile-1","insertXForwardedFor":'
|
||||
'false,"name":"MDSrvProxy","persistence":{"cookieMode":"insert",'
|
||||
'"cookieName":"JSESSIONID","expire":"30","method":"cookie"},'
|
||||
'"serverSslEnabled":false,"sslPassthrough":false,"template":"HTTP"}],'
|
||||
'"applicationRule":[],"enableServiceInsertion":false,"enabled":true,'
|
||||
'"featureType":"loadbalancer_4.0","logging":{"enable":false,'
|
||||
'"logLevel":"info"},"monitor":[{"interval":10,"maxRetries":3,"method":'
|
||||
'"GET","monitorId":"monitor-1","name":"MDSrvMon","timeout":15,"type":'
|
||||
'"http","url":"/"}],"pool":[{"algorithm":"round-robin",'
|
||||
'"applicationRuleId":[],"member":[{"condition":"enabled","ipAddress":'
|
||||
'"192.168.0.39","maxConn":0,"memberId":"member-1","minConn":0,'
|
||||
'"monitorPort":8775,"name":"Member-1","port":8775,"weight":1}],'
|
||||
'"monitorId":["monitor-1"],"name":"MDSrvPool","poolId":"pool-1",'
|
||||
'"transparent":false}],"version":6,"virtualServer":[{'
|
||||
'"accelerationEnabled":false,"applicationProfileId":'
|
||||
'"applicationProfile-1","applicationRuleId":[],"connectionLimit":0,'
|
||||
'"defaultPoolId":"pool-1","enableServiceInsertion":false,'
|
||||
'"enabled":true,"ipAddress":"169.254.0.3","name":"MdSrv",'
|
||||
'"port":"8775","protocol":"http","virtualServerId":'
|
||||
'"virtualServer-1"}]}')
|
||||
|
||||
OUT_OBJ_JSON = (
|
||||
'{"accelerationEnabled": false, "applicationProfile": [{'
|
||||
'"applicationProfileId": "applicationProfile-1", '
|
||||
'"insertXForwardedFor": false, "name": "MDSrvProxy", "persistence": '
|
||||
'{"expire": "30", "method": "cookie"}, "serverSslEnabled": false, '
|
||||
'"sslPassthrough": false, "template": "HTTP"}],'
|
||||
' "enableServiceInsertion": false, "enabled": true, "featureType": '
|
||||
'"loadbalancer_4.0", "monitor": [{"interval": 10, "maxRetries": 3, '
|
||||
'"method": "GET", "monitorId": "monitor-1", "name": "MDSrvMon", '
|
||||
'"timeout": 15, "type": "http", "url": "/"}], "pool": [{"algorithm":'
|
||||
' "round-robin", "member": [{"condition": "enabled", "ipAddress": '
|
||||
'"192.168.0.39", "maxConn": 0, "memberId": "member-1", "minConn": 0, '
|
||||
'"monitorPort": 8775, "name": "Member-1", "port": 8775, "weight": 1}],'
|
||||
' "monitorId": ["monitor-1"], "name": "MDSrvPool", "poolId": "pool-1",'
|
||||
' "transparent": false}], "virtualServer": [{"accelerationEnabled": '
|
||||
'false, "applicationProfileId": "applicationProfile-1", '
|
||||
'"connectionLimit": 0, "defaultPoolId": "pool-1", '
|
||||
'"enableServiceInsertion": false, "enabled": true, "ipAddress": '
|
||||
'"169.254.0.3", "name": "MdSrv", "port": "8775", "protocol": '
|
||||
'"http", "virtualServerId": "virtualServer-1"}]}')
|
||||
|
||||
LB_URI = '/api/4.0/edges/%s/loadbalancer/config'
|
||||
EDGE_1 = 'edge-x'
|
||||
EDGE_2 = 'edge-y'
|
||||
|
||||
def setUp(self):
|
||||
super(NsxvLoadbalancerTestCase, self).setUp()
|
||||
self._lb = nsxv_loadbalancer.NsxvLoadbalancer()
|
||||
self._vcns = vcns.Vcns(None, None, None, None, True)
|
||||
|
||||
def test_get_edge_loadbalancer(self):
|
||||
h = None
|
||||
v = jsonutils.loads(self.EDGE_OBJ_JSON)
|
||||
|
||||
with mock.patch.object(self._vcns, 'do_request',
|
||||
return_value=(h, v)) as mock_do_request:
|
||||
lb = nsxv_loadbalancer.NsxvLoadbalancer.get_loadbalancer(
|
||||
self._vcns, self.EDGE_1)
|
||||
lb.submit_to_backend(self._vcns, self.EDGE_2)
|
||||
|
||||
mock_do_request.assert_called_with(
|
||||
vcns.HTTP_PUT,
|
||||
self.LB_URI % self.EDGE_2,
|
||||
self.OUT_OBJ_JSON,
|
||||
format='json',
|
||||
encode=False)
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,840 +0,0 @@
|
||||
# Copyright 2014 VMware, Inc
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
from unittest import mock
|
||||
|
||||
from neutron.tests.unit import testlib_api
|
||||
from neutron_lib import constants
|
||||
from neutron_lib import context
|
||||
from neutron_lib import exceptions as n_exc
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from vmware_nsx.common import config as conf
|
||||
from vmware_nsx.common import exceptions as nsx_exc
|
||||
from vmware_nsx.common import nsxv_constants
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.plugins.nsx_v import availability_zones as nsx_az
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import (
|
||||
constants as vcns_const)
|
||||
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
|
||||
from vmware_nsx.tests import unit as vmware
|
||||
|
||||
_uuid = uuidutils.generate_uuid
|
||||
|
||||
#Four types of backup edge with different status
|
||||
EDGE_AVAIL = 'available-'
|
||||
EDGE_CREATING = 'creating-'
|
||||
EDGE_ERROR1 = 'error1-'
|
||||
EDGE_ERROR2 = 'error2-'
|
||||
EDGE_DELETING = 'deleting-'
|
||||
DEFAULT_AZ = 'default'
|
||||
|
||||
|
||||
class EdgeUtilsTestCaseMixin(testlib_api.SqlTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(EdgeUtilsTestCaseMixin, self).setUp()
|
||||
nsxv_manager_p = mock.patch(vmware.VCNS_DRIVER_NAME, autospec=True)
|
||||
self.nsxv_manager = nsxv_manager_p.start()
|
||||
task = mock.Mock()
|
||||
nsxv_manager_p.return_value = task
|
||||
self.nsxv_manager.callbacks = mock.Mock()
|
||||
self.nsxv_manager.vcns = mock.Mock()
|
||||
get_ver = mock.patch.object(self.nsxv_manager.vcns,
|
||||
'get_version').start()
|
||||
get_ver.return_value = '6.1.4'
|
||||
self.ctx = context.get_admin_context()
|
||||
self.addCleanup(nsxv_manager_p.stop)
|
||||
self.az = (nsx_az.NsxVAvailabilityZones().
|
||||
get_default_availability_zone())
|
||||
|
||||
def _create_router(self, name='router1'):
|
||||
return {'name': name,
|
||||
'id': _uuid()}
|
||||
|
||||
def _create_network(self, name='network'):
|
||||
return {'name': name,
|
||||
'id': _uuid()}
|
||||
|
||||
def _create_subnet(self, name='subnet'):
|
||||
return {'name': name,
|
||||
'id': _uuid()}
|
||||
|
||||
def _populate_vcns_router_binding(self, bindings):
|
||||
for binding in bindings:
|
||||
nsxv_db.init_edge_vnic_binding(self.ctx.session,
|
||||
binding['edge_id'])
|
||||
nsxv_db.add_nsxv_router_binding(
|
||||
self.ctx.session, binding['router_id'],
|
||||
binding['edge_id'], None, binding['status'],
|
||||
appliance_size=binding['appliance_size'],
|
||||
edge_type=binding['edge_type'],
|
||||
availability_zone=binding['availability_zone'])
|
||||
|
||||
|
||||
class DummyPlugin(object):
|
||||
def get_network_az_by_net_id(self, context, network_id):
|
||||
return (nsx_az.NsxVAvailabilityZones().
|
||||
get_default_availability_zone())
|
||||
|
||||
|
||||
class EdgeDHCPManagerTestCase(EdgeUtilsTestCaseMixin):
|
||||
|
||||
def setUp(self):
|
||||
super(EdgeDHCPManagerTestCase, self).setUp()
|
||||
self.edge_manager = edge_utils.EdgeManager(self.nsxv_manager, None)
|
||||
self.check = mock.patch.object(self.edge_manager,
|
||||
'check_edge_active_at_backend').start()
|
||||
self.check.return_value = True
|
||||
|
||||
def test_create_dhcp_edge_service(self):
|
||||
fake_edge_pool = [{'status': constants.ACTIVE,
|
||||
'edge_id': 'edge-1',
|
||||
'router_id': 'backup-11111111-1111',
|
||||
'appliance_size': 'compact',
|
||||
'edge_type': 'service',
|
||||
'availability_zone': DEFAULT_AZ},
|
||||
{'status': constants.PENDING_DELETE,
|
||||
'edge_id': 'edge-2',
|
||||
'router_id': 'dhcp-22222222-2222',
|
||||
'appliance_size': 'compact',
|
||||
'edge_type': 'service',
|
||||
'availability_zone': DEFAULT_AZ},
|
||||
{'status': constants.PENDING_DELETE,
|
||||
'edge_id': 'edge-3',
|
||||
'router_id': 'backup-33333333-3333',
|
||||
'appliance_size': 'compact',
|
||||
'edge_type': 'service',
|
||||
'availability_zone': DEFAULT_AZ}]
|
||||
self._populate_vcns_router_binding(fake_edge_pool)
|
||||
fake_network = self._create_network()
|
||||
fake_subnet = self._create_subnet(fake_network['id'])
|
||||
self.edge_manager.plugin = DummyPlugin()
|
||||
with mock.patch.object(self.edge_manager,
|
||||
'_get_used_edges', return_value=([], [])):
|
||||
self.edge_manager.create_dhcp_edge_service(self.ctx,
|
||||
fake_network['id'],
|
||||
fake_subnet)
|
||||
self.nsxv_manager.rename_edge.assert_called_once_with('edge-1',
|
||||
mock.ANY)
|
||||
|
||||
def test_get_random_available_edge(self):
|
||||
available_edge_ids = ['edge-1', 'edge-2']
|
||||
selected_edge_id = self.edge_manager._get_random_available_edge(
|
||||
available_edge_ids)
|
||||
self.assertIn(selected_edge_id, available_edge_ids)
|
||||
|
||||
def test_get_random_available_edge_missing_edges_returns_none(self):
|
||||
available_edge_ids = ['edge-1', 'edge-2']
|
||||
# Always return inactive(False) while checking whether the edge
|
||||
# exists on the backend.
|
||||
with mock.patch.object(self.edge_manager,
|
||||
'check_edge_active_at_backend',
|
||||
return_value=False):
|
||||
selected_edge_id = self.edge_manager._get_random_available_edge(
|
||||
available_edge_ids)
|
||||
# If no active edges are found on the backend, return None so that
|
||||
# a new DHCP edge is created.
|
||||
self.assertIsNone(selected_edge_id)
|
||||
|
||||
|
||||
class EdgeUtilsTestCase(EdgeUtilsTestCaseMixin):
|
||||
|
||||
def setUp(self):
|
||||
super(EdgeUtilsTestCase, self).setUp()
|
||||
self.edge_manager = edge_utils.EdgeManager(self.nsxv_manager, None)
|
||||
|
||||
# Args for vcns interface configuration
|
||||
self.internal_ip = '10.0.0.1'
|
||||
self.uplink_ip = '192.168.111.30'
|
||||
self.subnet_mask = '255.255.255.0'
|
||||
self.pref_len = '24'
|
||||
self.edge_id = 'dummy'
|
||||
self.orig_vnics = ({},
|
||||
{'vnics': [
|
||||
{'addressGroups':
|
||||
{'addressGroups': [
|
||||
{'subnetMask': self.subnet_mask,
|
||||
'subnetPrefixLength': self.pref_len,
|
||||
'primaryAddress': self.uplink_ip}]},
|
||||
'type': 'uplink',
|
||||
'index': 1},
|
||||
{'addressGroups':
|
||||
{'addressGroups': [
|
||||
{'subnetMask': self.subnet_mask,
|
||||
'subnetPrefixLength': self.pref_len,
|
||||
'primaryAddress': self.internal_ip}]},
|
||||
'type': 'internal',
|
||||
'index': 2}]}
|
||||
)
|
||||
|
||||
# Args for vcns vdr interface configuration
|
||||
self.vdr_ip = '10.0.0.1'
|
||||
self.vnic = 1
|
||||
self.orig_vdr = ({},
|
||||
{'index': 2,
|
||||
'addressGroups': {'addressGroups':
|
||||
[{'subnetMask': self.subnet_mask,
|
||||
'subnetPrefixLength': self.pref_len,
|
||||
'primaryAddress': self.vdr_ip}]},
|
||||
'type': 'internal'})
|
||||
|
||||
def test_create_lrouter(self):
|
||||
lrouter = self._create_router()
|
||||
self.nsxv_manager.deploy_edge.reset_mock()
|
||||
edge_utils.create_lrouter(self.nsxv_manager, self.ctx, lrouter,
|
||||
lswitch=None, dist=False,
|
||||
availability_zone=self.az)
|
||||
self.nsxv_manager.deploy_edge.assert_called_once_with(self.ctx,
|
||||
lrouter['id'], (lrouter['name'] + '-' + lrouter['id']),
|
||||
internal_network=None, dist=False, availability_zone=self.az,
|
||||
appliance_size=vcns_const.SERVICE_SIZE_MAPPING['router'])
|
||||
|
||||
def _test_update_intereface_primary_addr(self, old_ip, new_ip, isUplink):
|
||||
fixed_vnic = {'addressGroups':
|
||||
{'addressGroups': [
|
||||
{'subnetMask': self.subnet_mask,
|
||||
'subnetPrefixLength': self.pref_len,
|
||||
'primaryAddress': new_ip}] if new_ip else []},
|
||||
'type': 'uplink' if isUplink else 'internal',
|
||||
'index': 1 if isUplink else 2}
|
||||
|
||||
with mock.patch.object(self.nsxv_manager.vcns,
|
||||
'get_interfaces', return_value=self.orig_vnics):
|
||||
self.edge_manager.update_interface_addr(
|
||||
self.ctx, self.edge_id, old_ip, new_ip,
|
||||
self.subnet_mask, is_uplink=isUplink)
|
||||
self.nsxv_manager.vcns.update_interface.assert_called_once_with(
|
||||
self.edge_id, fixed_vnic)
|
||||
|
||||
def test_update_interface_addr_intrernal(self):
|
||||
self._test_update_intereface_primary_addr(
|
||||
self.internal_ip, '10.0.0.2', False)
|
||||
|
||||
def test_remove_interface_primary_addr_intrernal(self):
|
||||
self._test_update_intereface_primary_addr(
|
||||
self.internal_ip, None, False)
|
||||
|
||||
def test_update_interface_addr_uplink(self):
|
||||
self._test_update_intereface_primary_addr(
|
||||
self.uplink_ip, '192.168.111.31', True)
|
||||
|
||||
def test_remove_interface_primary_addr_uplink(self):
|
||||
self._test_update_intereface_primary_addr(
|
||||
self.uplink_ip, None, True)
|
||||
|
||||
def _test_update_intereface_secondary_addr(self, old_ip, new_ip):
|
||||
addr_group = {'subnetMask': self.subnet_mask,
|
||||
'subnetPrefixLength': self.pref_len,
|
||||
'primaryAddress': self.uplink_ip,
|
||||
'secondaryAddresses': {'type': 'secondary_addresses',
|
||||
'ipAddress': [new_ip]}}
|
||||
fixed_vnic = {'addressGroups': {'addressGroups': [addr_group]},
|
||||
'type': 'uplink',
|
||||
'index': 1}
|
||||
|
||||
with mock.patch.object(self.nsxv_manager.vcns,
|
||||
'get_interfaces', return_value=self.orig_vnics):
|
||||
self.edge_manager.update_interface_addr(
|
||||
self.ctx, self.edge_id, old_ip, new_ip,
|
||||
self.subnet_mask, is_uplink=True)
|
||||
self.nsxv_manager.vcns.update_interface.assert_called_once_with(
|
||||
self.edge_id, fixed_vnic)
|
||||
|
||||
def test_add_secondary_interface_addr(self):
|
||||
self._test_update_intereface_secondary_addr(
|
||||
None, '192.168.111.31')
|
||||
|
||||
def test_update_interface_addr_fail(self):
|
||||
# Old ip is not configured on the interface, so we should fail
|
||||
old_ip = '192.168.111.32'
|
||||
new_ip = '192.168.111.31'
|
||||
|
||||
with mock.patch.object(self.nsxv_manager.vcns,
|
||||
'get_interfaces', return_value=self.orig_vnics):
|
||||
self.assertRaises(
|
||||
nsx_exc.NsxPluginException,
|
||||
self.edge_manager.update_interface_addr,
|
||||
self.ctx, self.edge_id, old_ip, new_ip,
|
||||
self.subnet_mask, is_uplink=True)
|
||||
|
||||
def _test_update_vdr_intereface_primary_addr(self, old_ip,
|
||||
new_ip):
|
||||
fixed_vnic = {'addressGroups':
|
||||
{'addressGroups': [
|
||||
{'subnetMask': self.subnet_mask,
|
||||
'subnetPrefixLength': self.pref_len,
|
||||
'primaryAddress': new_ip}] if new_ip else []},
|
||||
'type': 'internal',
|
||||
'index': 2}
|
||||
|
||||
with mock.patch.object(self.nsxv_manager.vcns,
|
||||
'get_vdr_internal_interface', return_value=self.orig_vdr):
|
||||
with mock.patch.object(self.nsxv_manager.vcns,
|
||||
'update_vdr_internal_interface') as vcns_update:
|
||||
self.edge_manager.update_vdr_interface_addr(
|
||||
self.ctx, self.edge_id, self.vnic, old_ip, new_ip,
|
||||
self.subnet_mask)
|
||||
vcns_update.assert_called_once_with(self.edge_id,
|
||||
self.vnic,
|
||||
{'interface': fixed_vnic})
|
||||
|
||||
def test_update_vdr_interface_addr_intrernal(self):
|
||||
self._test_update_vdr_intereface_primary_addr(
|
||||
self.vdr_ip, '20.0.0.2')
|
||||
|
||||
def test_remove_vdr_interface_primary_addr_intrernal(self):
|
||||
self._test_update_vdr_intereface_primary_addr(
|
||||
self.vdr_ip, None)
|
||||
|
||||
def test_update_vdr_interface_addr_fail(self):
|
||||
# Old ip is not configured on the vdr interface, so we should fail
|
||||
old_ip = '192.168.111.32'
|
||||
new_ip = '192.168.111.31'
|
||||
|
||||
with mock.patch.object(self.nsxv_manager.vcns,
|
||||
'get_vdr_internal_interface', return_value=self.orig_vdr):
|
||||
self.assertRaises(
|
||||
nsx_exc.NsxPluginException,
|
||||
self.edge_manager.update_vdr_interface_addr,
|
||||
self.ctx, self.edge_id, self.vnic, old_ip, new_ip,
|
||||
self.subnet_mask)
|
||||
|
||||
|
||||
class EdgeManagerTestCase(EdgeUtilsTestCaseMixin):
|
||||
|
||||
def setUp(self):
|
||||
super(EdgeManagerTestCase, self).setUp()
|
||||
cfg.CONF.set_override('backup_edge_pool', [], 'nsxv')
|
||||
self.edge_manager = edge_utils.EdgeManager(self.nsxv_manager, None)
|
||||
self.check = mock.patch.object(self.edge_manager,
|
||||
'check_edge_active_at_backend').start()
|
||||
self.check.side_effect = self.check_edge_active_at_backend
|
||||
self.default_edge_pool_dicts = {'default': {
|
||||
nsxv_constants.SERVICE_EDGE: {
|
||||
nsxv_constants.LARGE: {'minimum_pooled_edges': 1,
|
||||
'maximum_pooled_edges': 3},
|
||||
nsxv_constants.COMPACT: {'minimum_pooled_edges': 1,
|
||||
'maximum_pooled_edges': 3}},
|
||||
nsxv_constants.VDR_EDGE: {}}}
|
||||
self.vdr_edge_pool_dicts = {'default': {
|
||||
nsxv_constants.SERVICE_EDGE: {},
|
||||
nsxv_constants.VDR_EDGE: {
|
||||
nsxv_constants.LARGE: {'minimum_pooled_edges': 1,
|
||||
'maximum_pooled_edges': 3}}}}
|
||||
|
||||
def check_edge_active_at_backend(self, edge_id):
|
||||
# workaround to let edge_id None pass since we wrapped router binding
|
||||
# db update op.
|
||||
if edge_id is None:
|
||||
edge_id = ""
|
||||
return not (edge_id.startswith(EDGE_ERROR1) or
|
||||
edge_id.startswith(EDGE_ERROR2))
|
||||
|
||||
def test_backup_edge_pool_with_default(self):
|
||||
cfg.CONF.set_override('backup_edge_pool',
|
||||
['service:large:1:3', 'service:compact:1:3'],
|
||||
'nsxv')
|
||||
az = nsx_az.NsxVAvailabilityZone(None)
|
||||
edge_pool_dicts = edge_utils.parse_backup_edge_pool_opt_per_az(az)
|
||||
self.assertEqual(self.default_edge_pool_dicts['default'],
|
||||
edge_pool_dicts)
|
||||
|
||||
def test_backup_edge_pool_with_empty_conf(self):
|
||||
cfg.CONF.set_override('backup_edge_pool', [], 'nsxv')
|
||||
az = nsx_az.NsxVAvailabilityZone(None)
|
||||
edge_pool_dicts = edge_utils.parse_backup_edge_pool_opt_per_az(az)
|
||||
expect_edge_pool_dicts = {
|
||||
nsxv_constants.SERVICE_EDGE: {},
|
||||
nsxv_constants.VDR_EDGE: {}}
|
||||
self.assertEqual(expect_edge_pool_dicts, edge_pool_dicts)
|
||||
|
||||
def test_backup_edge_pool_with_vdr_conf(self):
|
||||
cfg.CONF.set_override('backup_edge_pool', ['vdr:large:1:3'], 'nsxv')
|
||||
az = nsx_az.NsxVAvailabilityZone(None)
|
||||
edge_pool_dicts = edge_utils.parse_backup_edge_pool_opt_per_az(az)
|
||||
expect_edge_pool_dicts = self.vdr_edge_pool_dicts['default']
|
||||
self.assertEqual(expect_edge_pool_dicts, edge_pool_dicts)
|
||||
|
||||
def test_backup_edge_pool_with_duplicate_conf(self):
|
||||
cfg.CONF.set_override('backup_edge_pool',
|
||||
['service:compact:1:3', 'service::3:4'],
|
||||
'nsxv')
|
||||
az = nsx_az.NsxVAvailabilityZone(None)
|
||||
self.assertRaises(n_exc.Invalid,
|
||||
edge_utils.parse_backup_edge_pool_opt_per_az, az)
|
||||
|
||||
def _create_router_bindings(self, num, status, id_prefix, size,
|
||||
edge_type, availability_zone):
|
||||
if not availability_zone:
|
||||
availability_zone = self.az
|
||||
return [{'status': status,
|
||||
'edge_id': id_prefix + '-edge-' + str(i),
|
||||
'router_id': (vcns_const.BACKUP_ROUTER_PREFIX +
|
||||
id_prefix + str(i)),
|
||||
'appliance_size': size,
|
||||
'edge_type': edge_type,
|
||||
'availability_zone': availability_zone.name}
|
||||
for i in range(num)]
|
||||
|
||||
def _create_available_router_bindings(
|
||||
self, num, size=nsxv_constants.LARGE,
|
||||
edge_type=nsxv_constants.SERVICE_EDGE,
|
||||
availability_zone=None):
|
||||
status = constants.ACTIVE
|
||||
id_prefix = EDGE_AVAIL + size + '-' + edge_type
|
||||
return self._create_router_bindings(
|
||||
num, status, id_prefix, size, edge_type,
|
||||
availability_zone)
|
||||
|
||||
def _create_creating_router_bindings(
|
||||
self, num, size=nsxv_constants.LARGE,
|
||||
edge_type=nsxv_constants.SERVICE_EDGE,
|
||||
availability_zone=None):
|
||||
status = constants.PENDING_CREATE
|
||||
id_prefix = EDGE_CREATING + size + '-' + edge_type
|
||||
return self._create_router_bindings(
|
||||
num, status, id_prefix, size, edge_type,
|
||||
availability_zone)
|
||||
|
||||
def _create_error_router_bindings(
|
||||
self, num, status=constants.ERROR,
|
||||
size=nsxv_constants.LARGE,
|
||||
edge_type=nsxv_constants.SERVICE_EDGE,
|
||||
availability_zone=None):
|
||||
id_prefix = EDGE_ERROR1 + size + '-' + edge_type
|
||||
return self._create_router_bindings(
|
||||
num, status, id_prefix, size, edge_type,
|
||||
availability_zone)
|
||||
|
||||
def _create_error_router_bindings_at_backend(
|
||||
self, num, status=constants.ACTIVE,
|
||||
size=nsxv_constants.LARGE,
|
||||
edge_type=nsxv_constants.SERVICE_EDGE,
|
||||
availability_zone=None):
|
||||
id_prefix = EDGE_ERROR2 + size + '-' + edge_type
|
||||
return self._create_router_bindings(
|
||||
num, status, id_prefix, size, edge_type,
|
||||
availability_zone)
|
||||
|
||||
def _create_deleting_router_bindings(
|
||||
self, num, size=nsxv_constants.LARGE,
|
||||
edge_type=nsxv_constants.SERVICE_EDGE,
|
||||
availability_zone=None):
|
||||
status = constants.PENDING_DELETE
|
||||
id_prefix = EDGE_DELETING + size + '-' + edge_type
|
||||
return self._create_router_bindings(
|
||||
num, status, id_prefix, size, edge_type,
|
||||
availability_zone)
|
||||
|
||||
def _create_edge_pools(self, avail, creating, error,
|
||||
error_at_backend, deleting,
|
||||
size=nsxv_constants.LARGE,
|
||||
edge_type=nsxv_constants.SERVICE_EDGE):
|
||||
"""Create a backup edge pool with different status of edges.
|
||||
|
||||
Backup edges would be edges with avail, creating and error_at_backend,
|
||||
while available edges would only be edges with avail status.
|
||||
"""
|
||||
availability_zone = self.az
|
||||
return (
|
||||
self._create_error_router_bindings(
|
||||
error, size=size, edge_type=edge_type,
|
||||
availability_zone=availability_zone) +
|
||||
self._create_deleting_router_bindings(
|
||||
deleting, size=size, edge_type=edge_type,
|
||||
availability_zone=availability_zone) +
|
||||
self._create_error_router_bindings_at_backend(
|
||||
error_at_backend, size=size, edge_type=edge_type,
|
||||
availability_zone=availability_zone) +
|
||||
self._create_creating_router_bindings(
|
||||
creating, size=size, edge_type=edge_type,
|
||||
availability_zone=availability_zone) +
|
||||
self._create_available_router_bindings(
|
||||
avail, size=size, edge_type=edge_type,
|
||||
availability_zone=availability_zone))
|
||||
|
||||
def _create_backup_router_bindings(
|
||||
self, avail, creating, error, error_at_backend, deleting,
|
||||
error_status=constants.PENDING_DELETE,
|
||||
error_at_backend_status=constants.PENDING_DELETE,
|
||||
size=nsxv_constants.LARGE,
|
||||
edge_type=nsxv_constants.SERVICE_EDGE,
|
||||
availability_zone=None):
|
||||
if not availability_zone:
|
||||
availability_zone = self.az
|
||||
return (
|
||||
self._create_error_router_bindings(
|
||||
error, status=error_status, size=size, edge_type=edge_type,
|
||||
availability_zone=availability_zone) +
|
||||
self._create_error_router_bindings_at_backend(
|
||||
error_at_backend, status=error_at_backend_status,
|
||||
size=size, edge_type=edge_type,
|
||||
availability_zone=availability_zone) +
|
||||
self._create_creating_router_bindings(
|
||||
creating, size=size, edge_type=edge_type,
|
||||
availability_zone=availability_zone) +
|
||||
self._create_available_router_bindings(
|
||||
avail, size=size, edge_type=edge_type,
|
||||
availability_zone=availability_zone) +
|
||||
self._create_deleting_router_bindings(
|
||||
deleting, size=size, edge_type=edge_type,
|
||||
availability_zone=availability_zone))
|
||||
|
||||
def _verify_router_bindings(self, exp_bindings, act_db_bindings):
|
||||
exp_dict = dict(zip([binding['router_id']
|
||||
for binding in exp_bindings], exp_bindings))
|
||||
act_bindings = [{'router_id': binding['router_id'],
|
||||
'edge_id': binding['edge_id'],
|
||||
'status': binding['status'],
|
||||
'appliance_size': binding['appliance_size'],
|
||||
'edge_type': binding['edge_type'],
|
||||
'availability_zone': binding['availability_zone']}
|
||||
for binding in act_db_bindings]
|
||||
act_dict = dict(zip([binding['router_id']
|
||||
for binding in act_bindings], act_bindings))
|
||||
self.assertEqual(exp_dict, act_dict)
|
||||
|
||||
def test_get_backup_edge_bindings(self):
|
||||
"""Test get backup edges filtering out deleting and error edges."""
|
||||
pool_edges = (self._create_edge_pools(1, 2, 3, 4, 5) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, size=nsxv_constants.COMPACT))
|
||||
self._populate_vcns_router_binding(pool_edges)
|
||||
expect_backup_bindings = self._create_backup_router_bindings(
|
||||
1, 2, 0, 4, 0,
|
||||
error_at_backend_status=constants.ACTIVE,
|
||||
size=nsxv_constants.LARGE)
|
||||
backup_bindings = self.edge_manager._get_backup_edge_bindings(self.ctx,
|
||||
appliance_size=nsxv_constants.LARGE, availability_zone=self.az)
|
||||
self._verify_router_bindings(expect_backup_bindings, backup_bindings)
|
||||
|
||||
def test_get_available_router_bindings(self):
|
||||
appliance_size = nsxv_constants.LARGE
|
||||
edge_type = nsxv_constants.SERVICE_EDGE
|
||||
pool_edges = (self._create_edge_pools(1, 2, 3, 0, 5) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 0, 5, size=nsxv_constants.COMPACT))
|
||||
self._populate_vcns_router_binding(pool_edges)
|
||||
expect_backup_bindings = self._create_backup_router_bindings(
|
||||
1, 2, 3, 0, 5, error_status=constants.ERROR)
|
||||
binding = self.edge_manager._get_available_router_binding(
|
||||
self.ctx, appliance_size=appliance_size, edge_type=edge_type,
|
||||
availability_zone=self.az)
|
||||
router_bindings = [
|
||||
binding_db
|
||||
for binding_db in nsxv_db.get_nsxv_router_bindings(
|
||||
self.ctx.session)
|
||||
if (binding_db['appliance_size'] == appliance_size and
|
||||
binding_db['edge_type'] == edge_type and
|
||||
binding_db['availability_zone'] == 'default')]
|
||||
self._verify_router_bindings(expect_backup_bindings, router_bindings)
|
||||
edge_id = (EDGE_AVAIL + appliance_size + '-' +
|
||||
edge_type + '-edge-' + str(0))
|
||||
self.assertEqual(edge_id, binding['edge_id'])
|
||||
|
||||
def test_check_backup_edge_pool_with_max(self):
|
||||
appliance_size = nsxv_constants.LARGE
|
||||
edge_type = nsxv_constants.SERVICE_EDGE
|
||||
pool_edges = (self._create_edge_pools(1, 2, 3, 4, 5) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, size=nsxv_constants.COMPACT))
|
||||
self._populate_vcns_router_binding(pool_edges)
|
||||
expect_pool_bindings = self._create_backup_router_bindings(
|
||||
1, 2, 3, 4, 5,
|
||||
error_status=constants.ERROR,
|
||||
error_at_backend_status=constants.PENDING_DELETE)
|
||||
self.edge_manager._check_backup_edge_pool(
|
||||
0, 3,
|
||||
appliance_size=appliance_size, edge_type=edge_type,
|
||||
availability_zone=self.az)
|
||||
router_bindings = [
|
||||
binding
|
||||
for binding in nsxv_db.get_nsxv_router_bindings(self.ctx.session)
|
||||
if (binding['appliance_size'] == appliance_size and
|
||||
binding['edge_type'] == edge_type)]
|
||||
self._verify_router_bindings(expect_pool_bindings, router_bindings)
|
||||
|
||||
def test_check_backup_edge_pool_with_min(self):
|
||||
appliance_size = nsxv_constants.LARGE
|
||||
edge_type = nsxv_constants.SERVICE_EDGE
|
||||
pool_edges = (self._create_edge_pools(1, 2, 3, 0, 5) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, size=nsxv_constants.COMPACT))
|
||||
self._populate_vcns_router_binding(pool_edges)
|
||||
|
||||
edge_utils.eventlet = mock.Mock()
|
||||
edge_utils.eventlet.spawn_n.return_value = None
|
||||
|
||||
self.edge_manager._check_backup_edge_pool(
|
||||
5, 10, appliance_size=appliance_size, edge_type=edge_type,
|
||||
availability_zone=self.az)
|
||||
router_bindings = [
|
||||
binding
|
||||
for binding in nsxv_db.get_nsxv_router_bindings(self.ctx.session)
|
||||
if binding['edge_id'] is None and
|
||||
binding['status'] == constants.PENDING_CREATE]
|
||||
|
||||
binding_ids = [bind.router_id for bind in router_bindings]
|
||||
self.assertEqual(2, len(router_bindings))
|
||||
edge_utils.eventlet.spawn_n.assert_called_with(
|
||||
mock.ANY, binding_ids, appliance_size, edge_type, self.az)
|
||||
|
||||
def test_check_backup_edge_pools_with_empty_conf(self):
|
||||
pool_edges = (self._create_edge_pools(1, 2, 3, 4, 5) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, size=nsxv_constants.COMPACT) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, edge_type=nsxv_constants.VDR_EDGE))
|
||||
self._populate_vcns_router_binding(pool_edges)
|
||||
self.edge_manager._check_backup_edge_pools()
|
||||
router_bindings = nsxv_db.get_nsxv_router_bindings(self.ctx.session)
|
||||
for binding in router_bindings:
|
||||
self.assertEqual(constants.PENDING_DELETE, binding['status'])
|
||||
|
||||
def test_check_backup_edge_pools_with_default(self):
|
||||
self.edge_manager.edge_pool_dicts = self.default_edge_pool_dicts
|
||||
pool_edges = (self._create_edge_pools(1, 2, 3, 4, 5) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, size=nsxv_constants.COMPACT) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, edge_type=nsxv_constants.VDR_EDGE))
|
||||
self._populate_vcns_router_binding(pool_edges)
|
||||
self.edge_manager._check_backup_edge_pools()
|
||||
router_bindings = nsxv_db.get_nsxv_router_bindings(self.ctx.session)
|
||||
|
||||
expect_large_bindings = self._create_backup_router_bindings(
|
||||
1, 2, 3, 4, 5,
|
||||
error_status=constants.PENDING_DELETE,
|
||||
error_at_backend_status=constants.PENDING_DELETE)
|
||||
large_bindings = [
|
||||
binding
|
||||
for binding in router_bindings
|
||||
if (binding['appliance_size'] == nsxv_constants.LARGE and
|
||||
binding['edge_type'] == nsxv_constants.SERVICE_EDGE)]
|
||||
self._verify_router_bindings(expect_large_bindings, large_bindings)
|
||||
|
||||
expect_compact_bindings = self._create_backup_router_bindings(
|
||||
1, 2, 3, 4, 5,
|
||||
error_status=constants.PENDING_DELETE,
|
||||
error_at_backend_status=constants.PENDING_DELETE,
|
||||
size=nsxv_constants.COMPACT)
|
||||
compact_bindings = [
|
||||
binding
|
||||
for binding in router_bindings
|
||||
if (binding['appliance_size'] == nsxv_constants.COMPACT and
|
||||
binding['edge_type'] == nsxv_constants.SERVICE_EDGE)]
|
||||
self._verify_router_bindings(expect_compact_bindings, compact_bindings)
|
||||
|
||||
vdr_bindings = [
|
||||
binding
|
||||
for binding in router_bindings
|
||||
if (binding['appliance_size'] == nsxv_constants.LARGE and
|
||||
binding['edge_type'] == nsxv_constants.VDR_EDGE)]
|
||||
for binding in vdr_bindings:
|
||||
self.assertEqual(constants.PENDING_DELETE, binding['status'])
|
||||
|
||||
def test_check_backup_edge_pools_with_vdr(self):
|
||||
self.edge_manager.edge_pool_dicts = self.vdr_edge_pool_dicts
|
||||
pool_edges = (self._create_edge_pools(1, 2, 3, 4, 5) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, size=nsxv_constants.COMPACT) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, edge_type=nsxv_constants.VDR_EDGE))
|
||||
self._populate_vcns_router_binding(pool_edges)
|
||||
self.edge_manager._check_backup_edge_pools()
|
||||
router_bindings = nsxv_db.get_nsxv_router_bindings(self.ctx.session)
|
||||
expect_vdr_bindings = self._create_backup_router_bindings(
|
||||
1, 2, 3, 4, 5,
|
||||
error_status=constants.PENDING_DELETE,
|
||||
error_at_backend_status=constants.PENDING_DELETE,
|
||||
edge_type=nsxv_constants.VDR_EDGE)
|
||||
vdr_bindings = [
|
||||
binding
|
||||
for binding in router_bindings
|
||||
if (binding['appliance_size'] == nsxv_constants.LARGE and
|
||||
binding['edge_type'] == nsxv_constants.VDR_EDGE)]
|
||||
self._verify_router_bindings(expect_vdr_bindings, vdr_bindings)
|
||||
service_bindings = [
|
||||
binding
|
||||
for binding in router_bindings
|
||||
if binding['edge_type'] == nsxv_constants.SERVICE_EDGE]
|
||||
for binding in service_bindings:
|
||||
self.assertEqual(constants.PENDING_DELETE, binding['status'])
|
||||
|
||||
def test_allocate_edge_appliance_with_empty(self):
|
||||
self.edge_manager._clean_all_error_edge_bindings = mock.Mock()
|
||||
self.edge_manager._allocate_edge_appliance(
|
||||
self.ctx, 'fake_id', 'fake_name',
|
||||
availability_zone=self.az)
|
||||
assert not self.edge_manager._clean_all_error_edge_bindings.called
|
||||
|
||||
def test_allocate_large_edge_appliance_with_default(self):
|
||||
self.edge_manager.edge_pool_dicts = self.default_edge_pool_dicts
|
||||
pool_edges = (self._create_edge_pools(1, 2, 3, 4, 5) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, size=nsxv_constants.COMPACT) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, edge_type=nsxv_constants.VDR_EDGE))
|
||||
self._populate_vcns_router_binding(pool_edges)
|
||||
self.edge_manager._allocate_edge_appliance(
|
||||
self.ctx, 'fake_id', 'fake_name',
|
||||
appliance_size=nsxv_constants.LARGE,
|
||||
availability_zone=self.az)
|
||||
edge_id = (EDGE_AVAIL + nsxv_constants.LARGE + '-' +
|
||||
nsxv_constants.SERVICE_EDGE + '-edge-' + str(0))
|
||||
self.nsxv_manager.rename_edge.assert_has_calls(
|
||||
[mock.call(edge_id, 'fake_name')])
|
||||
|
||||
def test_allocate_compact_edge_appliance_with_default(self):
|
||||
self.edge_manager.edge_pool_dicts = self.default_edge_pool_dicts
|
||||
pool_edges = (self._create_edge_pools(1, 2, 3, 4, 5) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, size=nsxv_constants.COMPACT) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, edge_type=nsxv_constants.VDR_EDGE))
|
||||
self._populate_vcns_router_binding(pool_edges)
|
||||
self.edge_manager._allocate_edge_appliance(
|
||||
self.ctx, 'fake_id', 'fake_name',
|
||||
appliance_size=nsxv_constants.COMPACT,
|
||||
availability_zone=self.az)
|
||||
edge_id = (EDGE_AVAIL + nsxv_constants.COMPACT + '-' +
|
||||
nsxv_constants.SERVICE_EDGE + '-edge-' + str(0))
|
||||
self.nsxv_manager.rename_edge.assert_has_calls(
|
||||
[mock.call(edge_id, 'fake_name')])
|
||||
|
||||
def test_allocate_large_edge_appliance_with_vdr(self):
|
||||
self.edge_manager.edge_pool_dicts = self.vdr_edge_pool_dicts
|
||||
pool_edges = (self._create_edge_pools(1, 2, 3, 4, 5) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, size=nsxv_constants.COMPACT) +
|
||||
self._create_edge_pools(
|
||||
1, 2, 3, 4, 5, edge_type=nsxv_constants.VDR_EDGE))
|
||||
self._populate_vcns_router_binding(pool_edges)
|
||||
self.edge_manager._allocate_edge_appliance(
|
||||
self.ctx, 'fake_id', 'fake_name', dist=True,
|
||||
appliance_size=nsxv_constants.LARGE,
|
||||
availability_zone=self.az)
|
||||
edge_id = (EDGE_AVAIL + nsxv_constants.LARGE + '-' +
|
||||
nsxv_constants.VDR_EDGE + '-edge-' + str(0))
|
||||
self.nsxv_manager.rename_edge.assert_has_calls(
|
||||
[mock.call(edge_id, 'fake_name')])
|
||||
|
||||
def test_free_edge_appliance_with_empty(self):
|
||||
self.edge_manager._clean_all_error_edge_bindings = mock.Mock()
|
||||
self.edge_manager._allocate_edge_appliance(
|
||||
self.ctx, 'fake_id', 'fake_name',
|
||||
availability_zone=self.az)
|
||||
self.edge_manager._free_edge_appliance(
|
||||
self.ctx, 'fake_id')
|
||||
assert not self.edge_manager._clean_all_error_edge_bindings.called
|
||||
|
||||
def test_free_edge_appliance_with_default(self):
|
||||
self.edge_manager.edge_pool_dicts = self.default_edge_pool_dicts
|
||||
self.edge_manager._allocate_edge_appliance(
|
||||
self.ctx, 'fake_id', 'fake_name',
|
||||
availability_zone=self.az)
|
||||
self.edge_manager._free_edge_appliance(
|
||||
self.ctx, 'fake_id')
|
||||
assert not self.nsxv_manager.delete_edge.called
|
||||
self.nsxv_manager.update_edge.assert_has_calls(
|
||||
[mock.call(mock.ANY, mock.ANY, mock.ANY, mock.ANY, None,
|
||||
appliance_size=nsxv_constants.COMPACT, dist=False,
|
||||
availability_zone=mock.ANY)])
|
||||
|
||||
def test_free_edge_appliance_with_default_with_full(self):
|
||||
self.edge_pool_dicts = {
|
||||
nsxv_constants.SERVICE_EDGE: {
|
||||
nsxv_constants.LARGE: {'minimum_pooled_edges': 1,
|
||||
'maximum_pooled_edges': 1},
|
||||
nsxv_constants.COMPACT: {'minimum_pooled_edges': 1,
|
||||
'maximum_pooled_edges': 3}},
|
||||
nsxv_constants.VDR_EDGE: {}}
|
||||
# Avoid use of eventlet greenpool as this breaks the UT
|
||||
with mock.patch.object(self.edge_manager, '_get_worker_pool'):
|
||||
self.edge_manager._allocate_edge_appliance(
|
||||
self.ctx, 'fake_id', 'fake_name',
|
||||
availability_zone=self.az)
|
||||
self.edge_manager._free_edge_appliance(
|
||||
self.ctx, 'fake_id')
|
||||
|
||||
|
||||
class VdrTransitNetUtilDefaultTestCase(EdgeUtilsTestCaseMixin):
|
||||
EXPECTED_NETMASK = '255.255.255.240'
|
||||
EXPECTED_TLR_IP = '169.254.2.1'
|
||||
EXPECTED_PLR_IP = conf.DEFAULT_PLR_ADDRESS
|
||||
|
||||
def setUp(self):
|
||||
super(VdrTransitNetUtilDefaultTestCase, self).setUp()
|
||||
|
||||
def test_get_vdr_transit_network_netmask(self):
|
||||
self.assertEqual(edge_utils.get_vdr_transit_network_netmask(),
|
||||
self.EXPECTED_NETMASK)
|
||||
|
||||
def test_get_vdr_transit_network_tlr_address(self):
|
||||
self.assertEqual(edge_utils.get_vdr_transit_network_tlr_address(),
|
||||
self.EXPECTED_TLR_IP)
|
||||
|
||||
def test_get_vdr_transit_network_plr_address(self):
|
||||
self.assertEqual(edge_utils.get_vdr_transit_network_plr_address(),
|
||||
self.EXPECTED_PLR_IP)
|
||||
|
||||
def test_is_overlapping_reserved_subnets(self):
|
||||
self.assertTrue(
|
||||
edge_utils.is_overlapping_reserved_subnets('169.254.1.0/24',
|
||||
['169.254.0.0/16']))
|
||||
self.assertTrue(
|
||||
edge_utils.is_overlapping_reserved_subnets('169.254.1.0/24',
|
||||
['192.168.2.0/24',
|
||||
'169.254.0.0/16']))
|
||||
self.assertFalse(
|
||||
edge_utils.is_overlapping_reserved_subnets('169.254.1.0/24',
|
||||
['169.253.0.0/16']))
|
||||
self.assertFalse(
|
||||
edge_utils.is_overlapping_reserved_subnets('169.254.1.0/24',
|
||||
['192.168.2.0/24',
|
||||
'169.253.0.0/16']))
|
||||
|
||||
|
||||
class VdrTransitNetUtilTestCase(EdgeUtilsTestCaseMixin):
|
||||
EXPECTED_NETMASK = '255.255.255.0'
|
||||
EXPECTED_TLR_IP = '192.168.1.1'
|
||||
EXPECTED_PLR_IP = '192.168.1.2'
|
||||
|
||||
def setUp(self):
|
||||
super(VdrTransitNetUtilTestCase, self).setUp()
|
||||
|
||||
|
||||
class VdrTransitNetValidatorTestCase(EdgeUtilsTestCaseMixin):
|
||||
def setUp(self):
|
||||
super(VdrTransitNetValidatorTestCase, self).setUp()
|
||||
|
||||
def _test_validator(self, cidr):
|
||||
cfg.CONF.set_override('vdr_transit_network', cidr, 'nsxv')
|
||||
return edge_utils.validate_vdr_transit_network()
|
||||
|
||||
def test_vdr_transit_net_validator_success(self):
|
||||
self.assertIsNone(self._test_validator('192.168.253.0/24'))
|
||||
|
||||
def test_vdr_transit_net_validator_junk_cidr(self):
|
||||
self.assertRaises(n_exc.Invalid, self._test_validator, 'not_a_subnet')
|
||||
|
||||
def test_vdr_transit_net_validator_too_small_cidr(self):
|
||||
self.assertRaises(
|
||||
n_exc.Invalid, self._test_validator, '169.254.2.0/31')
|
||||
|
||||
def test_vdr_transit_net_validator_overlap_cidr(self):
|
||||
self.assertRaises(
|
||||
n_exc.Invalid, self._test_validator, '169.254.0.0/16')
|
@ -1,589 +0,0 @@
|
||||
# Copyright 2013 OpenStack Foundation.
|
||||
#
|
||||
# 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.
|
||||
from unittest import mock
|
||||
|
||||
from eventlet import greenthread
|
||||
|
||||
from neutron.tests import base
|
||||
from neutron_lib import context as neutron_context
|
||||
from oslo_config import cfg
|
||||
|
||||
from vmware_nsx.common import exceptions as nsxv_exc
|
||||
from vmware_nsx.plugins.nsx_v import availability_zones as nsx_az
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import (
|
||||
constants as vcns_const)
|
||||
from vmware_nsx.plugins.nsx_v.vshield import edge_appliance_driver as e_drv
|
||||
from vmware_nsx.plugins.nsx_v.vshield.tasks import (
|
||||
constants as ts_const)
|
||||
from vmware_nsx.plugins.nsx_v.vshield.tasks import tasks as ts
|
||||
from vmware_nsx.plugins.nsx_v.vshield import vcns_driver
|
||||
from vmware_nsx.tests import unit as vmware
|
||||
from vmware_nsx.tests.unit.nsx_v.vshield import fake_vcns
|
||||
|
||||
VCNS_CONFIG_FILE = vmware.get_fake_conf("vcns.ini.test")
|
||||
|
||||
ts.TaskManager.set_default_interval(100)
|
||||
|
||||
|
||||
class VcnsDriverTaskManagerTestCase(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(VcnsDriverTaskManagerTestCase, self).setUp()
|
||||
self.manager = ts.TaskManager()
|
||||
self.manager.start(100)
|
||||
|
||||
def tearDown(self):
|
||||
self.manager.stop()
|
||||
# Task manager should not leave running threads around
|
||||
# if _thread is None it means it was killed in stop()
|
||||
self.assertIsNone(self.manager._thread)
|
||||
super(VcnsDriverTaskManagerTestCase, self).tearDown()
|
||||
|
||||
def _test_task_manager_task_process_state(self, sync_exec=False):
|
||||
def _task_failed(task, reason):
|
||||
task.userdata['result'] = False
|
||||
task.userdata['error'] = reason
|
||||
|
||||
def _check_state(task, exp_state):
|
||||
if not task.userdata.get('result', True):
|
||||
return False
|
||||
|
||||
state = task.userdata['state']
|
||||
if state != exp_state:
|
||||
msg = "state %d expect %d" % (
|
||||
state, exp_state)
|
||||
_task_failed(task, msg)
|
||||
return False
|
||||
|
||||
task.userdata['state'] = state + 1
|
||||
return True
|
||||
|
||||
def _exec(task):
|
||||
if not _check_state(task, 1):
|
||||
return ts_const.TaskStatus.ERROR
|
||||
|
||||
if task.userdata['sync_exec']:
|
||||
return ts_const.TaskStatus.COMPLETED
|
||||
else:
|
||||
return ts_const.TaskStatus.PENDING
|
||||
|
||||
def _status(task):
|
||||
if task.userdata['sync_exec']:
|
||||
_task_failed(task, "_status callback triggered")
|
||||
|
||||
state = task.userdata['state']
|
||||
if state == 3:
|
||||
_check_state(task, 3)
|
||||
return ts_const.TaskStatus.PENDING
|
||||
else:
|
||||
_check_state(task, 4)
|
||||
return ts_const.TaskStatus.COMPLETED
|
||||
|
||||
def _result(task):
|
||||
if task.userdata['sync_exec']:
|
||||
exp_state = 3
|
||||
else:
|
||||
exp_state = 5
|
||||
|
||||
_check_state(task, exp_state)
|
||||
|
||||
def _start_monitor(task):
|
||||
_check_state(task, 0)
|
||||
|
||||
def _executed_monitor(task):
|
||||
_check_state(task, 2)
|
||||
|
||||
def _result_monitor(task):
|
||||
if task.userdata['sync_exec']:
|
||||
exp_state = 4
|
||||
else:
|
||||
exp_state = 6
|
||||
|
||||
if _check_state(task, exp_state):
|
||||
task.userdata['result'] = True
|
||||
else:
|
||||
task.userdata['result'] = False
|
||||
|
||||
userdata = {
|
||||
'state': 0,
|
||||
'sync_exec': sync_exec
|
||||
}
|
||||
task = ts.Task('name', 'res', _exec, _status, _result, userdata)
|
||||
task.add_start_monitor(_start_monitor)
|
||||
task.add_executed_monitor(_executed_monitor)
|
||||
task.add_result_monitor(_result_monitor)
|
||||
|
||||
self.manager.add(task)
|
||||
|
||||
task.wait(ts_const.TaskState.RESULT)
|
||||
|
||||
self.assertTrue(userdata['result'])
|
||||
|
||||
def test_task_manager_task_sync_exec_process_state(self):
|
||||
self._test_task_manager_task_process_state(sync_exec=True)
|
||||
|
||||
def test_task_manager_task_async_exec_process_state(self):
|
||||
self._test_task_manager_task_process_state(sync_exec=False)
|
||||
|
||||
def test_task_manager_task_ordered_process(self):
|
||||
def _task_failed(task, reason):
|
||||
task.userdata['result'] = False
|
||||
task.userdata['error'] = reason
|
||||
|
||||
def _exec(task):
|
||||
task.userdata['executed'] = True
|
||||
return ts_const.TaskStatus.PENDING
|
||||
|
||||
def _status(task):
|
||||
return ts_const.TaskStatus.COMPLETED
|
||||
|
||||
def _result(task):
|
||||
next_task = task.userdata.get('next')
|
||||
if next_task:
|
||||
if next_task.userdata.get('executed'):
|
||||
_task_failed(next_task, "executed premature")
|
||||
if task.userdata.get('result', True):
|
||||
task.userdata['result'] = True
|
||||
|
||||
tasks = []
|
||||
prev = None
|
||||
last_task = None
|
||||
for i in range(5):
|
||||
name = "name-%d" % i
|
||||
task = ts.Task(name, 'res', _exec, _status, _result, {})
|
||||
tasks.append(task)
|
||||
if prev:
|
||||
prev.userdata['next'] = task
|
||||
prev = task
|
||||
last_task = task
|
||||
|
||||
for task in tasks:
|
||||
self.manager.add(task)
|
||||
|
||||
last_task.wait(ts_const.TaskState.RESULT)
|
||||
|
||||
for task in tasks:
|
||||
self.assertTrue(task.userdata['result'])
|
||||
|
||||
def test_task_manager_task_parallel_process(self):
|
||||
tasks = []
|
||||
|
||||
def _exec(task):
|
||||
task.userdata['executed'] = True
|
||||
return ts_const.TaskStatus.PENDING
|
||||
|
||||
def _status(task):
|
||||
for t in tasks:
|
||||
if not t.userdata.get('executed'):
|
||||
t.userdata['resut'] = False
|
||||
return ts_const.TaskStatus.COMPLETED
|
||||
|
||||
def _result(task):
|
||||
if (task.userdata.get('result') is None and
|
||||
task.status == ts_const.TaskStatus.COMPLETED):
|
||||
task.userdata['result'] = True
|
||||
else:
|
||||
task.userdata['result'] = False
|
||||
|
||||
for i in range(5):
|
||||
name = "name-%d" % i
|
||||
res = 'resource-%d' % i
|
||||
task = ts.Task(name, res, _exec, _status, _result, {})
|
||||
tasks.append(task)
|
||||
self.manager.add(task)
|
||||
|
||||
for task in tasks:
|
||||
task.wait(ts_const.TaskState.RESULT)
|
||||
self.assertTrue(task.userdata['result'])
|
||||
|
||||
def _test_task_manager_stop(self, exec_wait=False, result_wait=False,
|
||||
stop_wait=0):
|
||||
def _exec(task):
|
||||
if exec_wait:
|
||||
greenthread.sleep(0.01)
|
||||
return ts_const.TaskStatus.PENDING
|
||||
|
||||
def _status(task):
|
||||
greenthread.sleep(0.01)
|
||||
return ts_const.TaskStatus.PENDING
|
||||
|
||||
def _result(task):
|
||||
if result_wait:
|
||||
greenthread.sleep(0)
|
||||
|
||||
manager = ts.TaskManager().start(100)
|
||||
manager.stop()
|
||||
# Task manager should not leave running threads around
|
||||
# if _thread is None it means it was killed in stop()
|
||||
self.assertIsNone(manager._thread)
|
||||
manager.start(100)
|
||||
|
||||
alltasks = {}
|
||||
for i in range(100):
|
||||
res = 'res-%d' % i
|
||||
tasks = []
|
||||
for i in range(100):
|
||||
task = ts.Task('name', res, _exec, _status, _result)
|
||||
manager.add(task)
|
||||
tasks.append(task)
|
||||
alltasks[res] = tasks
|
||||
|
||||
greenthread.sleep(stop_wait)
|
||||
manager.stop()
|
||||
# Task manager should not leave running threads around
|
||||
# if _thread is None it means it was killed in stop()
|
||||
self.assertIsNone(manager._thread)
|
||||
|
||||
for res, tasks in alltasks.items():
|
||||
for task in tasks:
|
||||
self.assertEqual(ts_const.TaskStatus.ABORT, task.status)
|
||||
|
||||
def test_task_manager_stop_1(self):
|
||||
self._test_task_manager_stop(True, True, 0)
|
||||
|
||||
def test_task_manager_stop_2(self):
|
||||
self._test_task_manager_stop(True, True, 1)
|
||||
|
||||
def test_task_manager_stop_3(self):
|
||||
self._test_task_manager_stop(False, False, 0)
|
||||
|
||||
def test_task_manager_stop_4(self):
|
||||
self._test_task_manager_stop(False, False, 1)
|
||||
|
||||
def test_task_pending_task(self):
|
||||
def _exec(task):
|
||||
task.userdata['executing'] = True
|
||||
while not task.userdata['tested']:
|
||||
greenthread.sleep(0)
|
||||
task.userdata['executing'] = False
|
||||
return ts_const.TaskStatus.COMPLETED
|
||||
|
||||
userdata = {
|
||||
'executing': False,
|
||||
'tested': False
|
||||
}
|
||||
manager = ts.TaskManager().start(100)
|
||||
task = ts.Task('name', 'res', _exec, userdata=userdata)
|
||||
manager.add(task)
|
||||
|
||||
while not userdata['executing']:
|
||||
greenthread.sleep(0)
|
||||
self.assertTrue(manager.has_pending_task())
|
||||
|
||||
userdata['tested'] = True
|
||||
while userdata['executing']:
|
||||
greenthread.sleep(0)
|
||||
self.assertFalse(manager.has_pending_task())
|
||||
|
||||
|
||||
class VcnsDriverTestCase(base.BaseTestCase):
|
||||
|
||||
def vcns_patch(self):
|
||||
instance = self.mock_vcns.start()
|
||||
instance.return_value.deploy_edge.side_effect = self.fc.deploy_edge
|
||||
instance.return_value.get_edge_id.side_effect = self.fc.get_edge_id
|
||||
instance.return_value.delete_edge.side_effect = self.fc.delete_edge
|
||||
instance.return_value.update_interface.side_effect = (
|
||||
self.fc.update_interface)
|
||||
instance.return_value.get_nat_config.side_effect = (
|
||||
self.fc.get_nat_config)
|
||||
instance.return_value.update_nat_config.side_effect = (
|
||||
self.fc.update_nat_config)
|
||||
instance.return_value.delete_nat_rule.side_effect = (
|
||||
self.fc.delete_nat_rule)
|
||||
instance.return_value.get_edge_status.side_effect = (
|
||||
self.fc.get_edge_status)
|
||||
instance.return_value.get_edges.side_effect = self.fc.get_edges
|
||||
instance.return_value.update_routes.side_effect = (
|
||||
self.fc.update_routes)
|
||||
instance.return_value.create_lswitch.side_effect = (
|
||||
self.fc.create_lswitch)
|
||||
instance.return_value.delete_lswitch.side_effect = (
|
||||
self.fc.delete_lswitch)
|
||||
|
||||
def setUp(self):
|
||||
super(VcnsDriverTestCase, self).setUp()
|
||||
|
||||
self.ctx = neutron_context.get_admin_context()
|
||||
self.temp_e_drv_nsxv_db = e_drv.nsxv_db
|
||||
e_drv.nsxv_db = mock.MagicMock()
|
||||
self.config_parse(args=['--config-file', VCNS_CONFIG_FILE])
|
||||
|
||||
self.fc = fake_vcns.FakeVcns()
|
||||
self.mock_vcns = mock.patch(vmware.VCNS_NAME, autospec=True)
|
||||
self.vcns_patch()
|
||||
|
||||
self.addCleanup(self.fc.reset_all)
|
||||
|
||||
self.vcns_driver = vcns_driver.VcnsDriver(self)
|
||||
|
||||
self.az = (nsx_az.NsxVAvailabilityZones().
|
||||
get_default_availability_zone())
|
||||
self.edge_id = None
|
||||
self.result = None
|
||||
|
||||
def tearDown(self):
|
||||
e_drv.nsxv_db = self.temp_e_drv_nsxv_db
|
||||
self.vcns_driver.task_manager.stop()
|
||||
# Task manager should not leave running threads around
|
||||
# if _thread is None it means it was killed in stop()
|
||||
self.assertIsNone(self.vcns_driver.task_manager._thread)
|
||||
super(VcnsDriverTestCase, self).tearDown()
|
||||
|
||||
def complete_edge_creation(
|
||||
self, context, edge_id, name, router_id, dist, deploy_successful,
|
||||
availability_zone=None, deploy_metadata=False):
|
||||
pass
|
||||
|
||||
def _deploy_edge(self):
|
||||
self.edge_id = self.vcns_driver.deploy_edge(
|
||||
self.ctx, 'router-id', 'myedge', 'internal-network',
|
||||
availability_zone=self.az)
|
||||
self.assertEqual('edge-1', self.edge_id)
|
||||
|
||||
def test_deploy_edge_with(self):
|
||||
self.vcns_driver.deploy_edge(
|
||||
self.ctx, 'router-id', 'myedge', 'internal-network',
|
||||
availability_zone=self.az)
|
||||
status = self.vcns_driver.get_edge_status('edge-1')
|
||||
self.assertEqual(vcns_const.RouterStatus.ROUTER_STATUS_ACTIVE, status)
|
||||
|
||||
def test_deploy_edge_fail(self):
|
||||
self.vcns_driver.deploy_edge(
|
||||
self.ctx, 'router-1', 'myedge', 'internal-network',
|
||||
availability_zone=self.az)
|
||||
# self.vcns_driver.deploy_edge(
|
||||
# self.ctx, 'router-2', 'myedge', 'internal-network',
|
||||
# availability_zone=self.az)
|
||||
self.assertRaises(
|
||||
nsxv_exc.NsxPluginException, self.vcns_driver.deploy_edge,
|
||||
self.ctx, 'router-2', 'myedge', 'internal-network',
|
||||
availability_zone=self.az)
|
||||
|
||||
def test_get_edge_status(self):
|
||||
self._deploy_edge()
|
||||
status = self.vcns_driver.get_edge_status(self.edge_id)
|
||||
self.assertEqual(vcns_const.RouterStatus.ROUTER_STATUS_ACTIVE, status)
|
||||
|
||||
def test_update_nat_rules(self):
|
||||
self._deploy_edge()
|
||||
snats = [{
|
||||
'src': '192.168.1.0/24',
|
||||
'translated': '10.0.0.1'
|
||||
}, {
|
||||
'src': '192.168.2.0/24',
|
||||
'translated': '10.0.0.2'
|
||||
}, {
|
||||
'src': '192.168.3.0/24',
|
||||
'translated': '10.0.0.3'
|
||||
}
|
||||
]
|
||||
dnats = [{
|
||||
'dst': '100.0.0.4',
|
||||
'translated': '192.168.1.1'
|
||||
}, {
|
||||
'dst': '100.0.0.5',
|
||||
'translated': '192.168.2.1'
|
||||
}
|
||||
]
|
||||
|
||||
result = self.vcns_driver.update_nat_rules(self.edge_id, snats, dnats)
|
||||
self.assertTrue(result)
|
||||
|
||||
natcfg = self.vcns_driver.get_nat_config(self.edge_id)
|
||||
rules = natcfg['rules']['natRulesDtos']
|
||||
self.assertEqual(2 * len(dnats) + len(snats), len(rules))
|
||||
self.natEquals(rules[0], dnats[0])
|
||||
self.natEquals(rules[1], self.snat_for_dnat(dnats[0]))
|
||||
self.natEquals(rules[2], dnats[1])
|
||||
self.natEquals(rules[3], self.snat_for_dnat(dnats[1]))
|
||||
self.natEquals(rules[4], snats[0])
|
||||
self.natEquals(rules[5], snats[1])
|
||||
self.natEquals(rules[6], snats[2])
|
||||
|
||||
def test_update_nat_rules_for_all_vnics(self):
|
||||
self._deploy_edge()
|
||||
snats = [{
|
||||
'src': '192.168.1.0/24',
|
||||
'translated': '10.0.0.1'
|
||||
}, {
|
||||
'src': '192.168.2.0/24',
|
||||
'translated': '10.0.0.2'
|
||||
}, {
|
||||
'src': '192.168.3.0/24',
|
||||
'translated': '10.0.0.3'
|
||||
}
|
||||
]
|
||||
dnats = [{
|
||||
'dst': '100.0.0.4',
|
||||
'translated': '192.168.1.1'
|
||||
}, {
|
||||
'dst': '100.0.0.5',
|
||||
'translated': '192.168.2.1'
|
||||
}
|
||||
]
|
||||
|
||||
indices = [0, 1, 2, 3]
|
||||
result = self.vcns_driver.update_nat_rules(self.edge_id,
|
||||
snats, dnats, indices)
|
||||
self.assertTrue(result)
|
||||
|
||||
natcfg = self.vcns_driver.get_nat_config(self.edge_id)
|
||||
rules = natcfg['rules']['natRulesDtos']
|
||||
|
||||
self.assertEqual(2 * len(indices) * len(dnats) +
|
||||
len(indices) * len(snats), len(rules))
|
||||
|
||||
sorted_rules = sorted(rules, key=lambda k: k['vnic'])
|
||||
for i in range(0, len(sorted_rules), 7):
|
||||
self.natEquals(sorted_rules[i], dnats[0])
|
||||
self.natEquals(sorted_rules[i + 1], self.snat_for_dnat(dnats[0]))
|
||||
self.natEquals(sorted_rules[i + 2], dnats[1])
|
||||
self.natEquals(sorted_rules[i + 3], self.snat_for_dnat(dnats[1]))
|
||||
self.natEquals(sorted_rules[i + 4], snats[0])
|
||||
self.natEquals(sorted_rules[i + 5], snats[1])
|
||||
self.natEquals(sorted_rules[i + 6], snats[2])
|
||||
|
||||
def test_update_nat_rules_for_specific_vnics(self):
|
||||
self._deploy_edge()
|
||||
snats = [{
|
||||
'src': '192.168.1.0/24',
|
||||
'translated': '10.0.0.1',
|
||||
'vnic_index': 5
|
||||
}, {
|
||||
'src': '192.168.2.0/24',
|
||||
'translated': '10.0.0.2'
|
||||
}, {
|
||||
'src': '192.168.3.0/24',
|
||||
'translated': '10.0.0.3'
|
||||
}
|
||||
]
|
||||
dnats = [{
|
||||
'dst': '100.0.0.4',
|
||||
'translated': '192.168.1.1',
|
||||
'vnic_index': 2
|
||||
}, {
|
||||
'dst': '100.0.0.5',
|
||||
'translated': '192.168.2.1'
|
||||
}
|
||||
]
|
||||
|
||||
result = self.vcns_driver.update_nat_rules(self.edge_id, snats, dnats)
|
||||
self.assertTrue(result)
|
||||
|
||||
natcfg = self.vcns_driver.get_nat_config(self.edge_id)
|
||||
|
||||
rules = natcfg['rules']['natRulesDtos']
|
||||
|
||||
self.assertEqual(2 * len(dnats) + len(snats), len(rules))
|
||||
|
||||
self.natEquals(rules[0], dnats[0])
|
||||
self.assertEqual(2, rules[0]['vnic'])
|
||||
self.natEquals(rules[1], self.snat_for_dnat(dnats[0]))
|
||||
self.assertEqual(2, rules[1]['vnic'])
|
||||
self.natEquals(rules[2], dnats[1])
|
||||
self.assertNotIn('vnic', rules[2])
|
||||
self.natEquals(rules[3], self.snat_for_dnat(dnats[1]))
|
||||
self.assertNotIn('vnic', rules[3])
|
||||
self.natEquals(rules[4], snats[0])
|
||||
self.assertEqual(5, rules[4]['vnic'])
|
||||
self.natEquals(rules[5], snats[1])
|
||||
self.assertNotIn('vnic', rules[5])
|
||||
self.natEquals(rules[6], snats[2])
|
||||
self.assertNotIn('vnic', rules[6])
|
||||
|
||||
def snat_for_dnat(self, dnat):
|
||||
return {
|
||||
'src': dnat['translated'],
|
||||
'translated': dnat['dst']
|
||||
}
|
||||
|
||||
def natEquals(self, rule, exp):
|
||||
addr = exp.get('src')
|
||||
if not addr:
|
||||
addr = exp.get('dst')
|
||||
|
||||
self.assertEqual(addr, rule['originalAddress'])
|
||||
self.assertEqual(exp['translated'], rule['translatedAddress'])
|
||||
|
||||
def test_update_routes(self):
|
||||
self._deploy_edge()
|
||||
routes = [{
|
||||
'cidr': '192.168.1.0/24',
|
||||
'nexthop': '169.254.2.1'
|
||||
}, {
|
||||
'cidr': '192.168.2.0/24',
|
||||
'nexthop': '169.254.2.1'
|
||||
}, {
|
||||
'cidr': '192.168.3.0/24',
|
||||
'nexthop': '169.254.2.1'
|
||||
}
|
||||
]
|
||||
result = self.vcns_driver.update_routes(
|
||||
self.edge_id, '10.0.0.1', routes)
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_update_interface(self):
|
||||
self._deploy_edge()
|
||||
self.vcns_driver.update_interface(
|
||||
'router-id', self.edge_id, vcns_const.EXTERNAL_VNIC_INDEX,
|
||||
'network-id', address='100.0.0.3', netmask='255.255.255.0')
|
||||
|
||||
def test_delete_edge(self):
|
||||
self._deploy_edge()
|
||||
result = self.vcns_driver.delete_edge(
|
||||
self.ctx, 'router-id', self.edge_id)
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_create_lswitch(self):
|
||||
tz_config = [{
|
||||
'transport_zone_uuid': 'tz-uuid'
|
||||
}]
|
||||
lswitch = self.vcns_driver.create_lswitch('lswitch', tz_config)
|
||||
self.assertEqual('lswitch', lswitch['display_name'])
|
||||
self.assertEqual('LogicalSwitchConfig', lswitch['type'])
|
||||
self.assertIn('uuid', lswitch)
|
||||
|
||||
def test_delete_lswitch(self):
|
||||
tz_config = {
|
||||
'transport_zone_uuid': 'tz-uuid'
|
||||
}
|
||||
lswitch = self.vcns_driver.create_lswitch('lswitch', tz_config)
|
||||
self.vcns_driver.delete_lswitch(lswitch['uuid'])
|
||||
|
||||
|
||||
class VcnsDriverHATestCase(VcnsDriverTestCase):
|
||||
|
||||
def setUp(self):
|
||||
# add edge_ha and ha_datastore to the pre-defined configuration
|
||||
self._data_store = 'fake-datastore'
|
||||
self._ha_data_store = 'fake-datastore-2'
|
||||
cfg.CONF.set_override('ha_datastore_id', self._ha_data_store,
|
||||
group="nsxv")
|
||||
cfg.CONF.set_override('edge_ha', True, group="nsxv")
|
||||
|
||||
super(VcnsDriverHATestCase, self).setUp()
|
||||
|
||||
self.vcns_driver.vcns.orig_deploy = self.vcns_driver.vcns.deploy_edge
|
||||
self.vcns_driver.vcns.deploy_edge = self._fake_deploy_edge
|
||||
|
||||
def _fake_deploy_edge(self, request):
|
||||
# validate the appliance structure in the request,
|
||||
# and return the regular (fake) response
|
||||
found_app = request['appliances']['appliances']
|
||||
self.assertEqual(2, len(found_app))
|
||||
self.assertEqual(self._data_store, found_app[0]['datastoreId'])
|
||||
self.assertEqual(self._ha_data_store, found_app[1]['datastoreId'])
|
||||
return self.vcns_driver.vcns.orig_deploy(request)
|
@ -1,307 +0,0 @@
|
||||
# Copyright 2017 VMware, 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 contextlib
|
||||
from unittest import mock
|
||||
|
||||
from neutron.api import extensions
|
||||
from neutron_dynamic_routing.db import bgp_db # noqa
|
||||
from neutron_dynamic_routing import extensions as dr_extensions
|
||||
from neutron_dynamic_routing.extensions import bgp as ext_bgp
|
||||
from neutron_dynamic_routing.tests.unit.db import test_bgp_db
|
||||
from neutron_lib.api.definitions import address_scope
|
||||
from neutron_lib import context
|
||||
from neutron_lib import exceptions as n_exc
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from vmware_nsx.common import exceptions as exc
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.plugins.nsx_v.drivers import (
|
||||
shared_router_driver as router_driver)
|
||||
from vmware_nsx.services.dynamic_routing import bgp_plugin
|
||||
from vmware_nsx.services.dynamic_routing.nsx_v import driver as bgp_driver
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin
|
||||
|
||||
BGP_PLUGIN = 'vmware_nsx.services.dynamic_routing.bgp_plugin.NSXvBgpPlugin'
|
||||
|
||||
|
||||
class TestNSXvBgpPlugin(test_plugin.NsxVPluginV2TestCase,
|
||||
test_bgp_db.BgpTests):
|
||||
def setUp(self):
|
||||
extensions.append_api_extensions_path(dr_extensions.__path__)
|
||||
service_plugins = {'bgp': BGP_PLUGIN}
|
||||
super(TestNSXvBgpPlugin, self).setUp(service_plugins=service_plugins)
|
||||
self.bgp_plugin = bgp_plugin.NSXvBgpPlugin()
|
||||
self.nsxv_driver = self.bgp_plugin.drivers['nsx-v']
|
||||
self.nsxv_driver._validate_gateway_network = mock.Mock()
|
||||
self.nsxv_driver._validate_bgp_configuration_on_peer_esg = (
|
||||
mock.Mock())
|
||||
self.plugin = directory.get_plugin()
|
||||
self.l3plugin = self.plugin
|
||||
self.plugin.init_is_complete = True
|
||||
self.context = context.get_admin_context()
|
||||
self.project_id = 'dummy_project'
|
||||
|
||||
@contextlib.contextmanager
|
||||
def gw_network(self, external=True, **kwargs):
|
||||
with super(TestNSXvBgpPlugin, self).gw_network(external=external,
|
||||
**kwargs) as gw_net:
|
||||
if external:
|
||||
gw_net['network']['router:external'] = True
|
||||
gw_net['network'][address_scope.IPV4_ADDRESS_SCOPE] = True
|
||||
yield gw_net
|
||||
|
||||
@contextlib.contextmanager
|
||||
def subnet(self, network=None, **kwargs):
|
||||
if network and network['network'].get('router:external'):
|
||||
kwargs['gateway_ip'] = None
|
||||
kwargs['enable_dhcp'] = False
|
||||
|
||||
with super(TestNSXvBgpPlugin, self).subnet(network=network,
|
||||
**kwargs) as sub:
|
||||
yield sub
|
||||
|
||||
@contextlib.contextmanager
|
||||
def router(self, **kwargs):
|
||||
if 'external_gateway_info' in kwargs:
|
||||
kwargs['external_gateway_info']['enable_snat'] = False
|
||||
with super(TestNSXvBgpPlugin, self).router(**kwargs) as r:
|
||||
yield r
|
||||
|
||||
@contextlib.contextmanager
|
||||
def esg_bgp_peer(self, esg_id):
|
||||
data = {'name': '',
|
||||
'peer_ip': '192.168.1.10',
|
||||
'remote_as': '65000',
|
||||
'esg_id': esg_id,
|
||||
'auth_type': 'none',
|
||||
'password': '',
|
||||
'tenant_id': self.project_id}
|
||||
bgp_peer = self.bgp_plugin.create_bgp_peer(self.context,
|
||||
{'bgp_peer': data})
|
||||
yield bgp_peer
|
||||
self.bgp_plugin.delete_bgp_peer(self.context, bgp_peer['id'])
|
||||
|
||||
@contextlib.contextmanager
|
||||
def bgp_speaker(self, ip_version, local_as, name='my-speaker',
|
||||
advertise_fip_host_routes=True,
|
||||
advertise_tenant_networks=True,
|
||||
networks=None, peers=None):
|
||||
data = {'ip_version': ip_version,
|
||||
test_bgp_db.ADVERTISE_FIPS_KEY: advertise_fip_host_routes,
|
||||
'advertise_tenant_networks': advertise_tenant_networks,
|
||||
'local_as': local_as, 'name': name,
|
||||
'tenant_id': self.project_id}
|
||||
bgp_speaker = self.bgp_plugin.create_bgp_speaker(self.context,
|
||||
{'bgp_speaker': data})
|
||||
bgp_speaker_id = bgp_speaker['id']
|
||||
|
||||
if networks:
|
||||
for network_id in networks:
|
||||
self.bgp_plugin.add_gateway_network(
|
||||
self.context,
|
||||
bgp_speaker_id,
|
||||
{'network_id': network_id})
|
||||
if peers:
|
||||
for peer_id in peers:
|
||||
self.bgp_plugin.add_bgp_peer(self.context, bgp_speaker_id,
|
||||
{'bgp_peer_id': peer_id})
|
||||
|
||||
yield self.bgp_plugin.get_bgp_speaker(self.context, bgp_speaker_id)
|
||||
|
||||
def test_get_external_networks_for_port_same_address_scope_v6(self):
|
||||
self.skipTest("IPv6 not supported by this plugin.")
|
||||
|
||||
def test_get_external_networks_for_port_different_address_scope_v6(self):
|
||||
self.skipTest("IPv6 not supported by this plugin.")
|
||||
|
||||
def test__get_dvr_fixed_ip_routes_by_bgp_speaker_same_scope(self):
|
||||
self.skipTest("DVR specific.")
|
||||
|
||||
def test_get_external_networks_for_port_different_address_scope_v4(self):
|
||||
self.skipTest("DVR specific.")
|
||||
|
||||
def test__get_dvr_fixed_ip_routes_by_bgp_speaker_different_scope(self):
|
||||
self.skipTest("DVR specific.")
|
||||
|
||||
def test__get_dvr_fixed_ip_routes_by_bgp_speaker_no_scope(self):
|
||||
self.skipTest("DVR specific.")
|
||||
|
||||
def test_create_v6_bgp_speaker(self):
|
||||
fake_bgp_speaker = {
|
||||
"bgp_speaker": {
|
||||
"ip_version": 6,
|
||||
"local_as": "1000",
|
||||
"name": "bgp-speaker",
|
||||
"tenant_id": self.project_id
|
||||
}
|
||||
}
|
||||
self.assertRaises(n_exc.InvalidInput,
|
||||
self.bgp_plugin.create_bgp_speaker,
|
||||
self.context, fake_bgp_speaker)
|
||||
|
||||
def test_create_v6_bgp_peer(self):
|
||||
fake_bgp_peer = {
|
||||
"bgp_peer": {
|
||||
"auth_type": "none",
|
||||
"remote_as": "1000",
|
||||
"name": "bgp-peer",
|
||||
"peer_ip": "fc00::/7",
|
||||
"tenant_id": self.project_id
|
||||
}
|
||||
}
|
||||
self.assertRaises(n_exc.InvalidInput,
|
||||
self.bgp_plugin.create_bgp_peer,
|
||||
self.context, fake_bgp_peer)
|
||||
|
||||
def test_bgp_peer_esg_id(self):
|
||||
edge_id = 'edge-123'
|
||||
with self.esg_bgp_peer(esg_id='edge-123') as esg_peer:
|
||||
self.assertEqual(edge_id, esg_peer['esg_id'])
|
||||
|
||||
peer_id = esg_peer['id']
|
||||
bgp_peer = self.bgp_plugin.get_bgp_peer(self.context, peer_id)
|
||||
self.assertEqual(edge_id, bgp_peer['esg_id'])
|
||||
|
||||
def test_create_bgp_peer_md5_auth_no_password(self):
|
||||
bgp_peer = {'bgp_peer':
|
||||
{'auth_type': 'md5', 'password': None,
|
||||
'peer_ip': '10.0.0.3',
|
||||
'tenant_id': self.project_id}}
|
||||
self.assertRaises(ext_bgp.InvalidBgpPeerMd5Authentication,
|
||||
self.bgp_plugin.create_bgp_peer,
|
||||
self.context, bgp_peer)
|
||||
|
||||
def test_add_non_external_gateway_network(self):
|
||||
self.nsxv_driver._validate_gateway_network = (
|
||||
bgp_driver.NSXvBgpDriver(
|
||||
self.bgp_plugin)._validate_gateway_network)
|
||||
with self.gw_network(external=False) as net,\
|
||||
self.subnetpool_with_address_scope(4,
|
||||
prefixes=['8.0.0.0/8']) as sp:
|
||||
network_id = net['network']['id']
|
||||
with self.bgp_speaker(sp['ip_version'], 1234) as speaker:
|
||||
self.assertRaises(exc.NsxBgpNetworkNotExternal,
|
||||
self.bgp_plugin.add_gateway_network,
|
||||
self.context, speaker['id'],
|
||||
{'network_id': network_id})
|
||||
|
||||
@mock.patch.object(nsxv_db, 'get_nsxv_bgp_speaker_binding',
|
||||
return_value={'bgp_identifier': '10.0.0.11'})
|
||||
def test_shared_router_on_gateway_clear(self, m1):
|
||||
with self.gw_network(external=True) as net,\
|
||||
self.subnetpool_with_address_scope(4,
|
||||
prefixes=['10.0.0.0/24']) as sp:
|
||||
with self.subnet(network=net,
|
||||
subnetpool_id=sp['id']) as s1,\
|
||||
self.bgp_speaker(sp['ip_version'], 1234,
|
||||
networks=[net['network']['id']]):
|
||||
subnet_id = s1['subnet']['id']
|
||||
gw_info1 = {'network_id': net['network']['id'],
|
||||
'external_fixed_ips': [{'ip_address': '10.0.0.11',
|
||||
'subnet_id': subnet_id}]}
|
||||
gw_info2 = {'network_id': net['network']['id'],
|
||||
'external_fixed_ips': [{'ip_address': '10.0.0.12',
|
||||
'subnet_id': subnet_id}]}
|
||||
router_obj = router_driver.RouterSharedDriver(self.plugin)
|
||||
with mock.patch.object(self.plugin, '_find_router_driver',
|
||||
return_value=router_obj):
|
||||
with self.router(external_gateway_info=gw_info1) as rtr1,\
|
||||
self.router(external_gateway_info=gw_info2) as rtr2,\
|
||||
mock.patch.object(
|
||||
self.nsxv_driver, '_get_router_edge_info',
|
||||
return_value=('edge-1', False)),\
|
||||
mock.patch.object(
|
||||
self.plugin.edge_manager,
|
||||
'get_routers_on_same_edge',
|
||||
return_value=[rtr1['id'], rtr2['id']]),\
|
||||
mock.patch.object(
|
||||
self.nsxv_driver,
|
||||
'_update_edge_bgp_identifier') as up_bgp:
|
||||
gw_clear = {u'router': {u'external_gateway_info': {}}}
|
||||
self.plugin.update_router(self.context,
|
||||
rtr1['id'],
|
||||
gw_clear)
|
||||
up_bgp.assert_called_once_with(mock.ANY,
|
||||
mock.ANY,
|
||||
mock.ANY,
|
||||
'10.0.0.12')
|
||||
|
||||
def test__bgp_speakers_for_gateway_network_by_ip_version(self):
|
||||
# REVISIT(roeyc): Base class test use ipv6 which is not supported.
|
||||
pass
|
||||
|
||||
def test__bgp_speakers_for_gateway_network_by_ip_version_no_binding(self):
|
||||
# REVISIT(roeyc): Base class test use ipv6 which is not supported.
|
||||
pass
|
||||
|
||||
def test__tenant_prefixes_by_router_no_gateway_port(self):
|
||||
# REVISIT(roeyc): Base class test use ipv6 which is not supported.
|
||||
pass
|
||||
|
||||
def test_all_routes_by_bgp_speaker_different_tenant_address_scope(self):
|
||||
# REVISIT(roeyc): Base class test use ipv6 which is not supported.
|
||||
pass
|
||||
|
||||
def test__get_address_scope_ids_for_bgp_speaker(self):
|
||||
pass
|
||||
|
||||
def test__get_dvr_fip_host_routes_by_binding(self):
|
||||
pass
|
||||
|
||||
def test__get_dvr_fip_host_routes_by_router(self):
|
||||
pass
|
||||
|
||||
def test__get_fip_next_hop_dvr(self):
|
||||
pass
|
||||
|
||||
def test__get_fip_next_hop_legacy(self):
|
||||
pass
|
||||
|
||||
def test_get_routes_by_bgp_speaker_id_with_fip_dvr(self):
|
||||
pass
|
||||
|
||||
def test_ha_router_fips_has_no_next_hop_to_fip_agent_gateway(self):
|
||||
pass
|
||||
|
||||
def test_legacy_router_fips_has_no_next_hop_to_fip_agent_gateway(self):
|
||||
pass
|
||||
|
||||
def test_floatingip_update_callback(self):
|
||||
pass
|
||||
|
||||
def test_get_ipv6_tenant_subnet_routes_by_bgp_speaker_ipv6(self):
|
||||
pass
|
||||
|
||||
def test_get_routes_by_bgp_speaker_id_with_fip(self):
|
||||
# base class tests uses no-snat router with floating ips
|
||||
self.skipTest('No SNAT with floating ips not supported')
|
||||
|
||||
def test_get_routes_by_bgp_speaker_binding_with_fip(self):
|
||||
# base class tests uses no-snat router with floating ips
|
||||
self.skipTest('No SNAT with floating ips not supported')
|
||||
|
||||
def test__get_routes_by_router_with_fip(self):
|
||||
# base class tests uses no-snat router with floating ips
|
||||
self.skipTest('No SNAT with floating ips not supported')
|
||||
|
||||
def test_add_bgp_peer_with_bad_id(self):
|
||||
with self.subnetpool_with_address_scope(
|
||||
4, prefixes=['8.0.0.0/8']) as sp:
|
||||
with self.bgp_speaker(sp['ip_version'], 1234) as speaker:
|
||||
self.assertRaises(ext_bgp.BgpPeerNotFound,
|
||||
self.bgp_plugin.add_bgp_peer,
|
||||
self.context,
|
||||
speaker['id'],
|
||||
{'bgp_peer_id': 'aaa'})
|
@ -1,271 +0,0 @@
|
||||
# Copyright 2016 VMware, 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.
|
||||
from unittest import mock
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import importutils
|
||||
|
||||
from neutron.api import extensions as api_ext
|
||||
from neutron.common import config
|
||||
from neutron_lib.api.definitions import portbindings
|
||||
from neutron_lib import context
|
||||
from neutron_lib.plugins import directory
|
||||
|
||||
from networking_sfc.db import flowclassifier_db as fdb
|
||||
from networking_sfc.extensions import flowclassifier
|
||||
from networking_sfc.services.flowclassifier.common import context as fc_ctx
|
||||
from networking_sfc.services.flowclassifier.common import exceptions as fc_exc
|
||||
from networking_sfc.tests import base
|
||||
from networking_sfc.tests.unit.db import test_flowclassifier_db
|
||||
|
||||
from vmware_nsx.services.flowclassifier.nsx_v import driver as nsx_v_driver
|
||||
from vmware_nsx.tests import unit as vmware
|
||||
from vmware_nsx.tests.unit.nsx_v.vshield import fake_vcns
|
||||
|
||||
|
||||
class TestNsxvFlowClassifierDriver(
|
||||
test_flowclassifier_db.FlowClassifierDbPluginTestCaseBase,
|
||||
base.NeutronDbPluginV2TestCase):
|
||||
|
||||
resource_prefix_map = dict([
|
||||
(k, flowclassifier.FLOW_CLASSIFIER_PREFIX)
|
||||
for k in flowclassifier.RESOURCE_ATTRIBUTE_MAP.keys()
|
||||
])
|
||||
|
||||
def setUp(self):
|
||||
# init the flow classifier plugin
|
||||
flowclassifier_plugin = (
|
||||
test_flowclassifier_db.DB_FLOWCLASSIFIER_PLUGIN_CLASS)
|
||||
|
||||
service_plugins = {
|
||||
flowclassifier.FLOW_CLASSIFIER_EXT: flowclassifier_plugin
|
||||
}
|
||||
fdb.FlowClassifierDbPlugin.supported_extension_aliases = [
|
||||
flowclassifier.FLOW_CLASSIFIER_EXT]
|
||||
fdb.FlowClassifierDbPlugin.path_prefix = (
|
||||
flowclassifier.FLOW_CLASSIFIER_PREFIX
|
||||
)
|
||||
|
||||
super(TestNsxvFlowClassifierDriver, self).setUp(
|
||||
ext_mgr=None,
|
||||
plugin=None,
|
||||
service_plugins=service_plugins
|
||||
)
|
||||
|
||||
self.flowclassifier_plugin = importutils.import_object(
|
||||
flowclassifier_plugin)
|
||||
ext_mgr = api_ext.PluginAwareExtensionManager(
|
||||
test_flowclassifier_db.extensions_path,
|
||||
{
|
||||
flowclassifier.FLOW_CLASSIFIER_EXT: self.flowclassifier_plugin
|
||||
}
|
||||
)
|
||||
app = config.load_paste_app('extensions_test_app')
|
||||
self.ext_api = api_ext.ExtensionMiddleware(app, ext_mgr=ext_mgr)
|
||||
self.ctx = context.get_admin_context()
|
||||
|
||||
# use the fake vcns
|
||||
mock_vcns = mock.patch(vmware.VCNS_NAME, autospec=True)
|
||||
mock_vcns_instance = mock_vcns.start()
|
||||
self.fc2 = fake_vcns.FakeVcns()
|
||||
mock_vcns_instance.return_value = self.fc2
|
||||
|
||||
# use the nsxv flow classifier driver
|
||||
self._profile_id = 'serviceprofile-1'
|
||||
cfg.CONF.set_override('service_insertion_profile_id',
|
||||
self._profile_id, 'nsxv')
|
||||
cfg.CONF.set_override('service_insertion_redirect_all',
|
||||
True, 'nsxv')
|
||||
|
||||
self.driver = nsx_v_driver.NsxvFlowClassifierDriver()
|
||||
self.driver.initialize()
|
||||
|
||||
self._fc_name = 'test1'
|
||||
self._fc_description = 'test 1'
|
||||
self._fc_source = '10.10.0.0/24'
|
||||
self._fc_dest = '20.10.0.0/24'
|
||||
self._fc_prot = 'TCP'
|
||||
self._fc_source_ports = range(100, 115)
|
||||
self._fc_dest_ports = range(80, 81)
|
||||
self._fc = {'name': self._fc_name,
|
||||
'description': self._fc_description,
|
||||
'logical_source_port': None,
|
||||
'logical_destination_port': None,
|
||||
'source_ip_prefix': self._fc_source,
|
||||
'destination_ip_prefix': self._fc_dest,
|
||||
'protocol': self._fc_prot,
|
||||
'source_port_range_min': self._fc_source_ports[0],
|
||||
'source_port_range_max': self._fc_source_ports[-1],
|
||||
'destination_port_range_min': self._fc_dest_ports[0],
|
||||
'destination_port_range_max': self._fc_dest_ports[-1]}
|
||||
|
||||
def tearDown(self):
|
||||
super(TestNsxvFlowClassifierDriver, self).tearDown()
|
||||
|
||||
def test_driver_init(self):
|
||||
self.assertEqual(self._profile_id, self.driver._profile_id)
|
||||
self.assertEqual(self.driver._security_group_id, '0')
|
||||
|
||||
orig_get_plugin = directory.get_plugin
|
||||
|
||||
def mocked_get_plugin(plugin=None):
|
||||
# mock only the core plugin
|
||||
if plugin:
|
||||
return orig_get_plugin(plugin)
|
||||
return mock_nsxv_plugin
|
||||
|
||||
mock_nsxv_plugin = mock.Mock()
|
||||
fc_plugin = directory.get_plugin(flowclassifier.FLOW_CLASSIFIER_EXT)
|
||||
with mock.patch.object(directory, 'get_plugin',
|
||||
new=mocked_get_plugin):
|
||||
with mock.patch.object(
|
||||
mock_nsxv_plugin,
|
||||
'add_vms_to_service_insertion') as fake_add:
|
||||
with mock.patch.object(
|
||||
fc_plugin,
|
||||
'create_flow_classifier') as fake_create:
|
||||
self.driver.init_complete(None, None, {})
|
||||
# check that the plugin was called to add vms to the
|
||||
# security group
|
||||
self.assertTrue(fake_add.called)
|
||||
# check that redirect_all flow classifier entry
|
||||
# was created
|
||||
self.assertTrue(fake_create.called)
|
||||
|
||||
def test_create_flow_classifier_precommit(self):
|
||||
with self.flow_classifier(flow_classifier=self._fc) as fc:
|
||||
fc_context = fc_ctx.FlowClassifierContext(
|
||||
self.flowclassifier_plugin, self.ctx,
|
||||
fc['flow_classifier']
|
||||
)
|
||||
# just make sure it does not raise an exception
|
||||
self.driver.create_flow_classifier_precommit(fc_context)
|
||||
|
||||
def test_create_flow_classifier_precommit_logical_source_port(self):
|
||||
with self.port(
|
||||
name='port1',
|
||||
device_owner='compute',
|
||||
device_id='test',
|
||||
arg_list=(
|
||||
portbindings.HOST_ID,
|
||||
),
|
||||
**{portbindings.HOST_ID: 'test'}
|
||||
) as src_port:
|
||||
with self.flow_classifier(flow_classifier={
|
||||
'name': 'test1',
|
||||
'logical_source_port': src_port['port']['id']
|
||||
}) as fc:
|
||||
fc_context = fc_ctx.FlowClassifierContext(
|
||||
self.flowclassifier_plugin, self.ctx,
|
||||
fc['flow_classifier']
|
||||
)
|
||||
self.assertRaises(
|
||||
fc_exc.FlowClassifierBadRequest,
|
||||
self.driver.create_flow_classifier_precommit,
|
||||
fc_context)
|
||||
|
||||
def test_create_flow_classifier_precommit_logical_dest_port(self):
|
||||
with self.port(
|
||||
name='port1',
|
||||
device_owner='compute',
|
||||
device_id='test',
|
||||
arg_list=(
|
||||
portbindings.HOST_ID,
|
||||
),
|
||||
**{portbindings.HOST_ID: 'test'}
|
||||
) as dst_port:
|
||||
with self.flow_classifier(flow_classifier={
|
||||
'name': 'test1',
|
||||
'logical_destination_port': dst_port['port']['id']
|
||||
}) as fc:
|
||||
fc_context = fc_ctx.FlowClassifierContext(
|
||||
self.flowclassifier_plugin, self.ctx,
|
||||
fc['flow_classifier']
|
||||
)
|
||||
self.assertRaises(
|
||||
fc_exc.FlowClassifierBadRequest,
|
||||
self.driver.create_flow_classifier_precommit,
|
||||
fc_context)
|
||||
|
||||
def _validate_rule_structure(self, rule):
|
||||
self.assertEqual(self._fc_description, rule.find('notes').text)
|
||||
self.assertEqual('ipv4', rule.find('packetType').text)
|
||||
self.assertEqual(
|
||||
self._fc_source,
|
||||
rule.find('sources').find('source').find('value').text)
|
||||
self.assertEqual(
|
||||
self._fc_dest,
|
||||
rule.find('destinations').find('destination').find('value').text)
|
||||
ports = "%s-%s" % (self._fc_source_ports[0], self._fc_source_ports[-1])
|
||||
if self._fc_source_ports[0] == self._fc_source_ports[-1]:
|
||||
ports = str(self._fc_source_ports[0])
|
||||
self.assertEqual(
|
||||
ports,
|
||||
rule.find('services').find('service').find('sourcePort').text)
|
||||
ports = "%s-%s" % (self._fc_dest_ports[0], self._fc_dest_ports[-1])
|
||||
if self._fc_dest_ports[0] == self._fc_dest_ports[-1]:
|
||||
ports = str(self._fc_dest_ports[0])
|
||||
self.assertEqual(
|
||||
ports,
|
||||
rule.find('services').find('service').find('destinationPort').text)
|
||||
self.assertEqual(
|
||||
self._fc_prot,
|
||||
rule.find('services').find('service').find('protocolName').text)
|
||||
self.assertTrue(rule.find('name').text.startswith(self._fc_name))
|
||||
|
||||
def test_create_flow_classifier(self):
|
||||
with self.flow_classifier(flow_classifier=self._fc) as fc:
|
||||
fc_context = fc_ctx.FlowClassifierContext(
|
||||
self.flowclassifier_plugin, self.ctx,
|
||||
fc['flow_classifier']
|
||||
)
|
||||
with mock.patch.object(
|
||||
self.driver,
|
||||
'update_redirect_section_in_backed') as mock_update_section:
|
||||
self.driver.create_flow_classifier(fc_context)
|
||||
self.assertTrue(mock_update_section.called)
|
||||
section = mock_update_section.call_args[0][0]
|
||||
self._validate_rule_structure(section.find('rule'))
|
||||
|
||||
def test_update_flow_classifier(self):
|
||||
with self.flow_classifier(flow_classifier=self._fc) as fc:
|
||||
fc_context = fc_ctx.FlowClassifierContext(
|
||||
self.flowclassifier_plugin, self.ctx,
|
||||
fc['flow_classifier']
|
||||
)
|
||||
self.driver.create_flow_classifier(fc_context)
|
||||
with mock.patch.object(
|
||||
self.driver,
|
||||
'update_redirect_section_in_backed') as mock_update_section:
|
||||
self.driver.update_flow_classifier(fc_context)
|
||||
self.assertTrue(mock_update_section.called)
|
||||
section = mock_update_section.call_args[0][0]
|
||||
self._validate_rule_structure(section.find('rule'))
|
||||
|
||||
def test_delete_flow_classifier(self):
|
||||
with self.flow_classifier(flow_classifier=self._fc) as fc:
|
||||
fc_context = fc_ctx.FlowClassifierContext(
|
||||
self.flowclassifier_plugin, self.ctx,
|
||||
fc['flow_classifier']
|
||||
)
|
||||
self.driver.create_flow_classifier(fc_context)
|
||||
with mock.patch.object(
|
||||
self.driver,
|
||||
'update_redirect_section_in_backed') as mock_update_section:
|
||||
self.driver.delete_flow_classifier(fc_context)
|
||||
self.assertTrue(mock_update_section.called)
|
||||
section = mock_update_section.call_args[0][0]
|
||||
# make sure the rule is not there
|
||||
self.assertIsNone(section.find('rule'))
|
@ -1,114 +0,0 @@
|
||||
# Copyright 2016 VMware, 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.
|
||||
from oslo_config import cfg
|
||||
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin
|
||||
|
||||
from neutron_lib.api.definitions import provider_net as pnet
|
||||
|
||||
|
||||
class TestNsxvIpamSubnets(test_plugin.TestSubnetsV2):
|
||||
"""Run the nsxv plugin subnets tests with the ipam driver"""
|
||||
def setUp(self):
|
||||
cfg.CONF.set_override(
|
||||
"ipam_driver",
|
||||
"vmware_nsx.services.ipam.nsx_v.driver.NsxvIpamDriver")
|
||||
super(TestNsxvIpamSubnets, self).setUp()
|
||||
|
||||
def provider_net(self):
|
||||
name = 'dvs-provider-net'
|
||||
providernet_args = {pnet.NETWORK_TYPE: 'vlan',
|
||||
pnet.SEGMENTATION_ID: 43,
|
||||
pnet.PHYSICAL_NETWORK: 'dvs-uuid'}
|
||||
return self.network(name=name, do_delete=False,
|
||||
providernet_args=providernet_args,
|
||||
arg_list=(pnet.NETWORK_TYPE,
|
||||
pnet.SEGMENTATION_ID,
|
||||
pnet.PHYSICAL_NETWORK))
|
||||
|
||||
def test_provider_net_use_driver(self):
|
||||
with self.provider_net() as net:
|
||||
before = len(self.fc2._ipam_pools)
|
||||
with self.subnet(network=net, cidr='10.10.10.0/29',
|
||||
enable_dhcp=False):
|
||||
self.assertEqual(before + 1, len(self.fc2._ipam_pools))
|
||||
|
||||
def test_ext_net_use_driver(self):
|
||||
with self.network(router__external=True) as net:
|
||||
before = len(self.fc2._ipam_pools)
|
||||
with self.subnet(network=net, cidr='10.10.10.0/29',
|
||||
enable_dhcp=False):
|
||||
self.assertEqual(before + 1, len(self.fc2._ipam_pools))
|
||||
|
||||
def test_regular_net_dont_use_driver(self):
|
||||
with self.network() as net:
|
||||
before = len(self.fc2._ipam_pools)
|
||||
with self.subnet(network=net, cidr='10.10.10.0/29',
|
||||
enable_dhcp=False):
|
||||
self.assertEqual(before, len(self.fc2._ipam_pools))
|
||||
|
||||
def test_no_more_ips(self):
|
||||
# create a small provider network, and use all the IPs
|
||||
with self.provider_net() as net:
|
||||
with self.subnet(network=net, cidr='10.10.10.0/29',
|
||||
enable_dhcp=False) as subnet:
|
||||
# create ports on this subnet until there are no more free ips
|
||||
# legal ips are 10.10.10.2 - 10.10.10.6
|
||||
fixed_ips = [{'subnet_id': subnet['subnet']['id']}]
|
||||
for counter in range(5):
|
||||
port_res = self._create_port(
|
||||
self.fmt, net['network']['id'], fixed_ips=fixed_ips)
|
||||
port = self.deserialize('json', port_res)
|
||||
self.assertIn('port', port)
|
||||
|
||||
# try to create another one - should fail
|
||||
port_res = self._create_port(
|
||||
self.fmt, net['network']['id'], fixed_ips=fixed_ips)
|
||||
port = self.deserialize('json', port_res)
|
||||
self.assertIn('NeutronError', port)
|
||||
self.assertIn('message', port['NeutronError'])
|
||||
self.assertTrue(('No more IP addresses available' in
|
||||
port['NeutronError']['message']))
|
||||
|
||||
def test_use_same_ips(self):
|
||||
# create a provider network and try to allocate the same ip twice
|
||||
with self.provider_net() as net:
|
||||
with self.subnet(network=net, cidr='10.10.10.0/24',
|
||||
enable_dhcp=False) as subnet:
|
||||
fixed_ips = [{'ip_address': '10.10.10.2',
|
||||
'subnet_id': subnet['subnet']['id']}]
|
||||
# First port should succeed
|
||||
port_res = self._create_port(
|
||||
self.fmt, net['network']['id'], fixed_ips=fixed_ips)
|
||||
port = self.deserialize('json', port_res)
|
||||
self.assertIn('port', port)
|
||||
|
||||
# try to create another one - should fail
|
||||
port_res = self._create_port(
|
||||
self.fmt, net['network']['id'], fixed_ips=fixed_ips)
|
||||
port = self.deserialize('json', port_res)
|
||||
self.assertIn('NeutronError', port)
|
||||
self.assertIn('message', port['NeutronError'])
|
||||
self.assertTrue(('already allocated in subnet' in
|
||||
port['NeutronError']['message']))
|
||||
|
||||
|
||||
class TestNsxvIpamPorts(test_plugin.TestPortsV2):
|
||||
"""Run the nsxv plugin ports tests with the ipam driver"""
|
||||
def setUp(self):
|
||||
cfg.CONF.set_override(
|
||||
"ipam_driver",
|
||||
"vmware_nsx.services.ipam.nsx_v.driver.NsxvIpamDriver")
|
||||
super(TestNsxvIpamPorts, self).setUp()
|
@ -1,209 +0,0 @@
|
||||
# Copyright 2015 VMware, 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.
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from networking_l2gw.db.l2gateway import l2gateway_db
|
||||
from neutron.tests import base
|
||||
from neutron_lib import context
|
||||
from neutron_lib import exceptions as n_exc
|
||||
|
||||
from vmware_nsx.common import exceptions as nsx_exc
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.dvs import dvs_utils
|
||||
from vmware_nsx.services.l2gateway.nsx_v import driver as nsx_v_driver
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin
|
||||
|
||||
CORE_PLUGIN = "vmware_nsx.plugins.nsx_v.plugin.NsxVPluginV2"
|
||||
|
||||
|
||||
class TestL2gatewayDriver(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestL2gatewayDriver, self).setUp()
|
||||
self.context = context.get_admin_context()
|
||||
self.plugin = nsx_v_driver.NsxvL2GatewayDriver(mock.MagicMock())
|
||||
|
||||
def test_validate_device_with_multi_devices(self):
|
||||
fake_l2gw_dict = {"l2_gateway":
|
||||
{"tenant_id": "fake__tenant_id",
|
||||
"name": "fake_l2gw",
|
||||
"devices": [{"interfaces":
|
||||
[{"name": "fake_inter"}],
|
||||
"device_name": "fake_dev"},
|
||||
{"interfaces":
|
||||
[{"name": "fake_inter_1"}],
|
||||
"device_name": "fake_dev_1"}]}}
|
||||
with mock.patch.object(l2gateway_db.L2GatewayMixin, '_admin_check'):
|
||||
self.assertRaises(n_exc.InvalidInput,
|
||||
self.plugin.create_l2_gateway,
|
||||
self.context, fake_l2gw_dict)
|
||||
|
||||
def test_validate_interface_with_multi_interfaces(self):
|
||||
fake_l2gw_dict = {"l2_gateway":
|
||||
{"tenant_id": "fake_tenant_id",
|
||||
"name": "fake_l2gw",
|
||||
"devices": [{"interfaces":
|
||||
[{"name": "fake_inter_1"},
|
||||
{"name": "fake_inter_2"}],
|
||||
"device_name": "fake_dev"}]}}
|
||||
with mock.patch.object(l2gateway_db.L2GatewayMixin, '_admin_check'):
|
||||
self.assertRaises(n_exc.InvalidInput,
|
||||
self.plugin.create_l2_gateway,
|
||||
self.context, fake_l2gw_dict)
|
||||
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._nsxv')
|
||||
def test_validate_interface_with_invalid_interfaces(self, _nsxv):
|
||||
fake_interfaces = [{"name": "fake_inter"}]
|
||||
_nsxv.vcns.validate_network.return_value = False
|
||||
self.assertRaises(n_exc.InvalidInput,
|
||||
self.plugin._validate_interface_list,
|
||||
self.context,
|
||||
fake_interfaces)
|
||||
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._edge_manager')
|
||||
def test_create_gw_edge_failure(self, edge_manager):
|
||||
with mock.patch.object(nsxv_db,
|
||||
'get_nsxv_router_binding',
|
||||
return_value=None):
|
||||
self.assertRaises(nsx_exc.NsxL2GWDeviceNotFound,
|
||||
self.plugin._create_l2_gateway_edge,
|
||||
self.context)
|
||||
|
||||
@mock.patch('networking_l2gw.db.l2gateway.l2gateway_db.'
|
||||
'L2GatewayMixin._admin_check')
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._validate_device_list')
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._validate_interface_list')
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._create_l2_gateway_edge')
|
||||
@mock.patch('networking_l2gw.db.l2gateway.l2gateway_db.'
|
||||
'L2GatewayMixin.create_l2_gateway')
|
||||
def test_create_l2_gateway_failure(self, create_l2gw, _create_l2gw_edge,
|
||||
val_inter, val_dev, _admin_check):
|
||||
fake_l2gw_dict = {"l2_gateway":
|
||||
{"tenant_id": "fake_teannt_id",
|
||||
"name": "fake_l2gw",
|
||||
"devices": [{"interfaces":
|
||||
[{"name": "fake_inter"}],
|
||||
"device_name": "fake_dev"}]}}
|
||||
_create_l2gw_edge.side_effect = nsx_exc.NsxL2GWDeviceNotFound
|
||||
self.assertRaises(nsx_exc.NsxL2GWDeviceNotFound,
|
||||
self.plugin.create_l2_gateway,
|
||||
self.context, fake_l2gw_dict)
|
||||
|
||||
@mock.patch('networking_l2gw.db.l2gateway.l2gateway_db.'
|
||||
'L2GatewayMixin._admin_check')
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._validate_device_list')
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._validate_interface_list')
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._create_l2_gateway_edge')
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._edge_manager')
|
||||
def test_create_l2_gateway(self, edge_manager, _create_l2gw_edge,
|
||||
val_inter, val_dev, _admin_check):
|
||||
fake_l2gw_dict = {"l2_gateway":
|
||||
{"tenant_id": "fake_teannt_id",
|
||||
"name": "fake_l2gw",
|
||||
"devices": [{"interfaces":
|
||||
[{"name": "fake_inter"}],
|
||||
"device_name": "fake_dev"}]}}
|
||||
fake_devices = [{"interfaces": [{"name": "fake_inter"}],
|
||||
"device_name": "fake_dev"}]
|
||||
fake_interfaces = [{"name": "fake_inter"}]
|
||||
_create_l2gw_edge.return_value = 'fake_dev'
|
||||
self.plugin.create_l2_gateway(self.context, fake_l2gw_dict)
|
||||
_admin_check.assert_called_with(self.context, 'CREATE')
|
||||
val_dev.assert_called_with(fake_devices)
|
||||
val_inter.assert_called_with(self.context, fake_interfaces)
|
||||
|
||||
@mock.patch('networking_l2gw.db.l2gateway.l2gateway_db.'
|
||||
'L2GatewayMixin._admin_check')
|
||||
@mock.patch('networking_l2gw.db.l2gateway.l2gateway_db.'
|
||||
'L2GatewayMixin.get_l2_gateway_connection')
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._get_device')
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._nsxv')
|
||||
def test_delete_l2_gateway_connection(self, nsxv, get_devices,
|
||||
get_conn, admin_check):
|
||||
fake_conn_dict = {'l2_gateway_id': 'fake_l2gw_id'}
|
||||
fake_device_dict = {'id': 'fake_dev_id',
|
||||
'device_name': 'fake_dev_name'}
|
||||
get_conn.return_value = fake_conn_dict
|
||||
get_devices.return_value = fake_device_dict
|
||||
self.plugin.delete_l2_gateway_connection(self.context, fake_conn_dict)
|
||||
admin_check.assert_called_with(self.context, 'DELETE')
|
||||
get_conn.assert_called_with(self.context, fake_conn_dict)
|
||||
get_devices.assert_called_with(self.context, 'fake_l2gw_id')
|
||||
self.plugin._nsxv().del_bridge.asert_called_with('fake_dev_name')
|
||||
|
||||
@mock.patch('networking_l2gw.db.l2gateway.l2gateway_db.'
|
||||
'L2GatewayMixin._admin_check')
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._get_device')
|
||||
@mock.patch('vmware_nsx.db.'
|
||||
'nsxv_db.get_nsxv_router_binding_by_edge')
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._edge_manager')
|
||||
def test_delete_l2_gateway(self, edge_manager, get_nsxv_router,
|
||||
get_devices, admin_check):
|
||||
fake_device_dict = {"id": "fake_dev_id",
|
||||
"device_name": "fake_edge_name",
|
||||
"l2_gateway_id": "fake_l2gw_id"}
|
||||
fake_rtr_binding = {"router_id": 'fake_router_id'}
|
||||
get_devices.return_value = fake_device_dict
|
||||
get_nsxv_router.return_value = fake_rtr_binding
|
||||
self.plugin.delete_l2_gateway(self.context, 'fake_l2gw_id')
|
||||
admin_check.assert_called_with(self.context, 'DELETE')
|
||||
get_devices.assert_called_with(self.context, 'fake_l2gw_id')
|
||||
get_nsxv_router.assert_called_with(self.context.session,
|
||||
"fake_edge_name")
|
||||
|
||||
|
||||
class TestL2GatewayDriverRouter(test_plugin.NsxVPluginV2TestCase):
|
||||
|
||||
@mock.patch.object(dvs_utils, 'dvs_create_session')
|
||||
def setUp(self, *mocks):
|
||||
# init the nsxv plugin, edge manager and fake vcns
|
||||
super(TestL2GatewayDriverRouter, self).setUp(plugin=CORE_PLUGIN,
|
||||
ext_mgr=None)
|
||||
self.context = context.get_admin_context()
|
||||
# init the L2 gateway driver
|
||||
self.driver = nsx_v_driver.NsxvL2GatewayDriver(mock.MagicMock())
|
||||
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._validate_device_list')
|
||||
@mock.patch('vmware_nsx.services.l2gateway.'
|
||||
'nsx_v.driver.NsxvL2GatewayDriver._validate_interface_list')
|
||||
def test_create_l2_gateway_router(self, val_inter, val_dev):
|
||||
# Verify that creating the router doesn't fail
|
||||
fake_l2gw_dict = {"l2_gateway":
|
||||
{"tenant_id": "fake_teannt_id",
|
||||
"name": "fake_l2gw",
|
||||
"devices": [{"interfaces":
|
||||
[{"name": "fake_inter"}],
|
||||
"device_name": "fake_dev"}]}}
|
||||
self.driver.create_l2_gateway(self.context, fake_l2gw_dict)
|
||||
|
||||
def test_create_l2_gateway_router_edge(self):
|
||||
# Verify that the router edge is really created
|
||||
edge_id = self.driver._create_l2_gateway_edge(self.context)
|
||||
self.assertEqual('edge-1', edge_id)
|
@ -1,340 +0,0 @@
|
||||
# Copyright 2016 VMware, 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 copy
|
||||
from unittest import mock
|
||||
|
||||
from neutron.services.qos import qos_plugin
|
||||
from neutron.tests.unit.services.qos import base
|
||||
from neutron_lib import context
|
||||
from neutron_lib.objects import registry as obj_reg
|
||||
from neutron_lib.plugins import directory
|
||||
from neutron_lib.services.qos import constants as qos_consts
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from vmware_nsx.dvs import dvs
|
||||
from vmware_nsx.dvs import dvs_utils
|
||||
from vmware_nsx.services.qos.common import utils as qos_com_utils
|
||||
from vmware_nsx.services.qos.nsx_v import driver as qos_driver
|
||||
from vmware_nsx.services.qos.nsx_v import utils as qos_utils
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin
|
||||
|
||||
CORE_PLUGIN = "vmware_nsx.plugins.nsx_v.plugin.NsxVPluginV2"
|
||||
QosPolicy = obj_reg.load_class('QosPolicy')
|
||||
QosPolicyDefault = obj_reg.load_class('QosPolicyDefault')
|
||||
QosBandwidthLimitRule = obj_reg.load_class('QosBandwidthLimitRule')
|
||||
QosDscpMarkingRule = obj_reg.load_class('QosDscpMarkingRule')
|
||||
|
||||
|
||||
class TestQosNsxVNotification(test_plugin.NsxVPluginV2TestCase,
|
||||
base.BaseQosTestCase):
|
||||
|
||||
@mock.patch.object(dvs_utils, 'dvs_create_session')
|
||||
def setUp(self, *mocks):
|
||||
# init the nsx-v plugin for testing with DVS
|
||||
self._init_dvs_config()
|
||||
# Reset the drive to re-create it
|
||||
qos_driver.DRIVER = None
|
||||
# Skip Octavia init because of RPC conflicts
|
||||
with mock.patch("vmware_nsx.services.lbaas.octavia.octavia_listener."
|
||||
"NSXOctaviaListener.__init__", return_value=None),\
|
||||
mock.patch("vmware_nsx.services.lbaas.octavia.octavia_listener."
|
||||
"NSXOctaviaStatisticsCollector.__init__",
|
||||
return_value=None):
|
||||
super(TestQosNsxVNotification, self).setUp(plugin=CORE_PLUGIN,
|
||||
ext_mgr=None,
|
||||
with_md_proxy=False)
|
||||
self.setup_coreplugin(CORE_PLUGIN)
|
||||
|
||||
plugin_instance = directory.get_plugin()
|
||||
self._core_plugin = plugin_instance
|
||||
self._core_plugin.init_is_complete = True
|
||||
|
||||
self.qos_plugin = qos_plugin.QoSPlugin()
|
||||
mock.patch.object(qos_utils.NsxVQosRule,
|
||||
'_get_qos_plugin',
|
||||
return_value=self.qos_plugin).start()
|
||||
|
||||
# Pre defined QoS data for the tests
|
||||
self.test_tenant_id = '1d7ddf4daf1f47529b5cc93b2e843980'
|
||||
self.ctxt = context.Context('fake_user', self.test_tenant_id)
|
||||
|
||||
self.policy_data = {
|
||||
'policy': {'id': uuidutils.generate_uuid(),
|
||||
'project_id': self.test_tenant_id,
|
||||
'name': 'test-policy',
|
||||
'description': 'Test policy description',
|
||||
'shared': True}}
|
||||
|
||||
self.rule_data = {
|
||||
'bandwidth_limit_rule': {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'max_kbps': 100,
|
||||
'max_burst_kbps': 150,
|
||||
'type': qos_consts.RULE_TYPE_BANDWIDTH_LIMIT}}
|
||||
self.ingress_rule_data = {
|
||||
'bandwidth_limit_rule': {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'max_kbps': 200,
|
||||
'max_burst_kbps': 250,
|
||||
'direction': 'ingress',
|
||||
'type': qos_consts.RULE_TYPE_BANDWIDTH_LIMIT}}
|
||||
self.dscp_rule_data = {
|
||||
'dscp_marking_rule': {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'dscp_mark': 22,
|
||||
'type': qos_consts.RULE_TYPE_DSCP_MARKING}}
|
||||
|
||||
self.policy = QosPolicy(
|
||||
self.ctxt, **self.policy_data['policy'])
|
||||
|
||||
# egress bw rule
|
||||
self.rule = QosBandwidthLimitRule(
|
||||
self.ctxt, **self.rule_data['bandwidth_limit_rule'])
|
||||
# ingress bw rule
|
||||
self.ingress_rule = QosBandwidthLimitRule(
|
||||
self.ctxt, **self.ingress_rule_data['bandwidth_limit_rule'])
|
||||
# dscp marking rule
|
||||
self.dscp_rule = QosDscpMarkingRule(
|
||||
self.ctxt, **self.dscp_rule_data['dscp_marking_rule'])
|
||||
|
||||
self._net_data = {'network': {
|
||||
'name': 'test-qos',
|
||||
'tenant_id': self.test_tenant_id,
|
||||
'qos_policy_id': self.policy.id,
|
||||
'port_security_enabled': False,
|
||||
'admin_state_up': False,
|
||||
'shared': False
|
||||
}}
|
||||
self._rules = [self.rule_data['bandwidth_limit_rule']]
|
||||
self._dscp_rules = [self.dscp_rule_data['dscp_marking_rule']]
|
||||
|
||||
mock.patch.object(QosPolicy, 'obj_load_attr').start()
|
||||
|
||||
def _init_dvs_config(self):
|
||||
# Ensure that DVS is enabled
|
||||
# and enable the DVS features for nsxv qos support
|
||||
cfg.CONF.set_override('host_ip', 'fake_ip', group='dvs')
|
||||
cfg.CONF.set_override('host_username', 'fake_user', group='dvs')
|
||||
cfg.CONF.set_override('host_password', 'fake_password', group='dvs')
|
||||
cfg.CONF.set_override('dvs_name', 'fake_dvs', group='dvs')
|
||||
cfg.CONF.set_default('use_dvs_features', True, 'nsxv')
|
||||
|
||||
def _create_net(self, net_data=None):
|
||||
if net_data is None:
|
||||
net_data = self._net_data
|
||||
net_data['tenant_id'] = self.test_tenant_id
|
||||
with mock.patch('vmware_nsx.services.qos.common.utils.'
|
||||
'get_network_policy_id',
|
||||
return_value=self.policy.id):
|
||||
return self._core_plugin.create_network(self.ctxt, net_data)
|
||||
|
||||
@mock.patch.object(qos_com_utils, 'update_network_policy_binding')
|
||||
@mock.patch.object(dvs.DvsManager, 'update_port_groups_config')
|
||||
def test_create_network_with_policy_rule(self,
|
||||
dvs_update_mock,
|
||||
update_bindings_mock):
|
||||
"""Test the DVS update when a QoS rule is attached to a network"""
|
||||
# Create a policy with a rule
|
||||
_policy = QosPolicy(
|
||||
self.ctxt, **self.policy_data['policy'])
|
||||
setattr(_policy, "rules", [self.rule, self.ingress_rule,
|
||||
self.dscp_rule])
|
||||
|
||||
with mock.patch('neutron.services.qos.qos_plugin.QoSPlugin.'
|
||||
'get_policy',
|
||||
return_value=_policy) as get_rules_mock,\
|
||||
mock.patch.object(self.plugin, '_validate_qos_policy_id'):
|
||||
# create the network to use this policy
|
||||
net = self._create_net()
|
||||
|
||||
# make sure the network-policy binding was updated
|
||||
update_bindings_mock.assert_called_once_with(
|
||||
self.ctxt, net['id'], self.policy.id)
|
||||
# make sure the qos rule was found
|
||||
get_rules_mock.assert_called_with(self.ctxt, self.policy.id)
|
||||
# make sure the dvs was updated
|
||||
self.assertTrue(dvs_update_mock.called)
|
||||
|
||||
@mock.patch.object(qos_com_utils, 'update_network_policy_binding')
|
||||
@mock.patch.object(dvs.DvsManager, 'update_port_groups_config')
|
||||
def test_create_network_with_default_policy(self,
|
||||
dvs_update_mock,
|
||||
update_bindings_mock):
|
||||
"""Test the DVS update when default policy attached to a network"""
|
||||
# Create a default policy with a rule
|
||||
policy_data = copy.deepcopy(self.policy_data['policy'])
|
||||
policy_data['is_default'] = True
|
||||
_policy = QosPolicy(self.ctxt, **policy_data)
|
||||
setattr(_policy, "rules", [self.rule, self.dscp_rule])
|
||||
default_policy = QosPolicyDefault(
|
||||
qos_policy_id=policy_data['id'])
|
||||
|
||||
with mock.patch('neutron.services.qos.qos_plugin.QoSPlugin.'
|
||||
'get_policy',
|
||||
return_value=_policy) as get_rules_mock,\
|
||||
mock.patch.object(
|
||||
QosPolicyDefault, 'get_object', return_value=default_policy):
|
||||
# create the network (with no specific qos policy)
|
||||
net_data = copy.deepcopy(self._net_data)
|
||||
del net_data['network']['qos_policy_id']
|
||||
net = self._create_net(net_data=net_data)
|
||||
|
||||
# make sure the network-policy binding was updated
|
||||
update_bindings_mock.assert_called_once_with(
|
||||
self.ctxt, net['id'], self.policy.id)
|
||||
# make sure the qos rule was found
|
||||
get_rules_mock.assert_called_with(self.ctxt, self.policy.id)
|
||||
# make sure the dvs was updated
|
||||
self.assertTrue(dvs_update_mock.called)
|
||||
|
||||
def _test_rule_action_notification(self, action):
|
||||
# Create a policy with a rule
|
||||
_policy = QosPolicy(
|
||||
self.ctxt, **self.policy_data['policy'])
|
||||
|
||||
# set the rule in the policy data
|
||||
setattr(_policy, "rules", [self.rule])
|
||||
|
||||
with mock.patch.object(qos_com_utils,
|
||||
'update_network_policy_binding'),\
|
||||
mock.patch.object(dvs.DvsManager, 'update_port_groups_config'
|
||||
) as dvs_update_mock,\
|
||||
mock.patch('neutron.services.qos.qos_plugin.QoSPlugin.'
|
||||
'get_policy',
|
||||
return_value=_policy) as get_rules_mock,\
|
||||
mock.patch.object(QosPolicy, 'get_object', return_value=_policy):
|
||||
# create the network to use this policy
|
||||
net = self._create_net()
|
||||
dvs_update_mock.called = False
|
||||
get_rules_mock.called = False
|
||||
|
||||
with mock.patch('neutron.objects.db.api.create_object',
|
||||
return_value=self.rule_data),\
|
||||
mock.patch('neutron.objects.db.api.update_object',
|
||||
return_value=self.rule_data),\
|
||||
mock.patch('neutron.objects.db.api.delete_object'),\
|
||||
mock.patch.object(_policy, 'get_bound_networks',
|
||||
return_value=[net['id']]),\
|
||||
mock.patch.object(self.ctxt.session, 'expunge'):
|
||||
|
||||
# create/update/delete the rule
|
||||
if action == 'create':
|
||||
self.qos_plugin.create_policy_bandwidth_limit_rule(
|
||||
self.ctxt, self.policy.id, self.rule_data)
|
||||
elif action == 'update':
|
||||
self.qos_plugin.update_policy_bandwidth_limit_rule(
|
||||
self.ctxt, self.rule.id,
|
||||
self.policy.id, self.rule_data)
|
||||
else:
|
||||
self.qos_plugin.delete_policy_bandwidth_limit_rule(
|
||||
self.ctxt, self.rule.id, self.policy.id)
|
||||
|
||||
# make sure the qos rule was found
|
||||
self.assertTrue(get_rules_mock.called)
|
||||
# make sure the dvs was updated
|
||||
self.assertTrue(dvs_update_mock.called)
|
||||
|
||||
def test_create_rule_notification(self):
|
||||
"""Test the DVS update when a QoS rule, attached to a network,
|
||||
is created
|
||||
"""
|
||||
self._test_rule_action_notification('create')
|
||||
|
||||
def test_update_rule_notification(self):
|
||||
"""Test the DVS update when a QoS rule, attached to a network,
|
||||
is modified
|
||||
"""
|
||||
self._test_rule_action_notification('update')
|
||||
|
||||
def test_delete_rule_notification(self):
|
||||
"""Test the DVS update when a QoS rule, attached to a network,
|
||||
is deleted
|
||||
"""
|
||||
self._test_rule_action_notification('delete')
|
||||
|
||||
def _test_dscp_rule_action_notification(self, action):
|
||||
# Create a policy with a rule
|
||||
_policy = QosPolicy(
|
||||
self.ctxt, **self.policy_data['policy'])
|
||||
|
||||
# set the rule in the policy data
|
||||
setattr(_policy, "rules", [self.dscp_rule])
|
||||
plugin = self.qos_plugin
|
||||
with mock.patch.object(qos_com_utils,
|
||||
'update_network_policy_binding'),\
|
||||
mock.patch.object(dvs.DvsManager, 'update_port_groups_config'
|
||||
) as dvs_update_mock,\
|
||||
mock.patch('neutron.services.qos.qos_plugin.QoSPlugin.'
|
||||
'get_policy',
|
||||
return_value=_policy) as rules_mock,\
|
||||
mock.patch.object(QosPolicy, 'get_object',
|
||||
return_value=_policy),\
|
||||
mock.patch.object(self.ctxt.session, 'expunge'):
|
||||
# create the network to use this policy
|
||||
net = self._create_net()
|
||||
dvs_update_mock.called = False
|
||||
rules_mock.called = False
|
||||
|
||||
with mock.patch('neutron.objects.db.api.create_object',
|
||||
return_value=self.dscp_rule_data),\
|
||||
mock.patch('neutron.objects.db.api.update_object',
|
||||
return_value=self.dscp_rule_data),\
|
||||
mock.patch('neutron.objects.db.api.delete_object'),\
|
||||
mock.patch.object(_policy, 'get_bound_networks',
|
||||
return_value=[net['id']]),\
|
||||
mock.patch.object(self.ctxt.session, 'expunge'):
|
||||
|
||||
# create/update/delete the rule
|
||||
if action == 'create':
|
||||
plugin.create_policy_dscp_marking_rule(
|
||||
self.ctxt,
|
||||
self.policy.id,
|
||||
self.dscp_rule_data)
|
||||
elif action == 'update':
|
||||
plugin.update_policy_dscp_marking_rule(
|
||||
self.ctxt,
|
||||
self.dscp_rule.id,
|
||||
self.policy.id,
|
||||
self.dscp_rule_data)
|
||||
else:
|
||||
plugin.delete_policy_dscp_marking_rule(
|
||||
self.ctxt,
|
||||
self.dscp_rule.id,
|
||||
self.policy.id)
|
||||
|
||||
# make sure the qos rule was found
|
||||
self.assertTrue(rules_mock.called)
|
||||
|
||||
# make sure the dvs was updated
|
||||
self.assertTrue(dvs_update_mock.called)
|
||||
|
||||
def test_create_dscp_rule_notification(self):
|
||||
"""Test the DVS update when a QoS DSCP rule, attached to a network,
|
||||
is created
|
||||
"""
|
||||
self._test_dscp_rule_action_notification('create')
|
||||
|
||||
def test_update_dscp_rule_notification(self):
|
||||
"""Test the DVS update when a QoS DSCP rule, attached to a network,
|
||||
is modified
|
||||
"""
|
||||
self._test_dscp_rule_action_notification('update')
|
||||
|
||||
def test_delete_dscp_rule_notification(self):
|
||||
"""Test the DVS update when a QoS DSCP rule, attached to a network,
|
||||
is deleted
|
||||
"""
|
||||
self._test_dscp_rule_action_notification('delete')
|
@ -1,335 +0,0 @@
|
||||
# Copyright 2016 VMware, 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 contextlib
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from neutron_lib.api.definitions import external_net as extnet_apidef
|
||||
from neutron_lib import context
|
||||
from neutron_lib.plugins import directory
|
||||
from neutron_vpnaas.db.vpn import vpn_models # noqa
|
||||
from neutron_vpnaas.extensions import vpnaas
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from vmware_nsx.common import exceptions as nsxv_exc
|
||||
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as vcns_exc
|
||||
from vmware_nsx.services.vpnaas.nsxv import ipsec_driver
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin
|
||||
|
||||
|
||||
_uuid = uuidutils.generate_uuid
|
||||
|
||||
DRIVER_PATH = "vmware_nsx.services.vpnaas.nsxv.ipsec_driver.NSXvIPsecVpnDriver"
|
||||
VALI_PATH = "vmware_nsx.services.vpnaas.nsxv.ipsec_validator.IPsecValidator"
|
||||
FAKE_ROUTER_ID = "aaaaaa-bbbbb-ccc"
|
||||
FAKE_VPNSERVICE_ID = _uuid()
|
||||
FAKE_IPSEC_CONNECTION = {"vpnservice_id": FAKE_VPNSERVICE_ID,
|
||||
"id": _uuid()}
|
||||
FAKE_EDGE_ID = _uuid()
|
||||
FAKE_IPSEC_VPN_SITE = {"peerIp": "192.168.1.1"}
|
||||
FAKE_VCNSAPIEXC = {"status": "fail",
|
||||
"head": "fake_head",
|
||||
"response": "error"}
|
||||
FAKE_NEW_CONNECTION = {"peer_cidrs": "192.168.1.0/24"}
|
||||
|
||||
|
||||
class TestVpnaasDriver(test_plugin.NsxVPluginV2TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestVpnaasDriver, self).setUp()
|
||||
self.context = context.get_admin_context()
|
||||
self.service_plugin = mock.Mock()
|
||||
self.validator = mock.Mock()
|
||||
self.driver = ipsec_driver.NSXvIPsecVpnDriver(self.service_plugin)
|
||||
self.plugin = directory.get_plugin()
|
||||
self.l3plugin = self.plugin
|
||||
|
||||
@contextlib.contextmanager
|
||||
def router(self, name='vpn-test-router', tenant_id=_uuid(),
|
||||
admin_state_up=True, **kwargs):
|
||||
request = {'router': {'tenant_id': tenant_id,
|
||||
'name': name,
|
||||
'admin_state_up': admin_state_up}}
|
||||
for arg in kwargs:
|
||||
request['router'][arg] = kwargs[arg]
|
||||
router = self.l3plugin.create_router(self.context, request)
|
||||
yield router
|
||||
|
||||
@mock.patch('%s._convert_ipsec_conn' % DRIVER_PATH)
|
||||
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
|
||||
@mock.patch('%s._generate_new_sites' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_status' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_firewall_rules' % DRIVER_PATH)
|
||||
def test_create_ipsec_site_connection(self, mock_update_fw,
|
||||
mock_update_status,
|
||||
mock_update_ipsec, mock_gen_new,
|
||||
mock_get_id,
|
||||
mock_conv_ipsec):
|
||||
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
|
||||
mock_conv_ipsec.return_value = FAKE_IPSEC_VPN_SITE
|
||||
mock_gen_new.return_value = FAKE_IPSEC_VPN_SITE
|
||||
self.driver.create_ipsec_site_connection(self.context,
|
||||
FAKE_IPSEC_CONNECTION)
|
||||
mock_conv_ipsec.assert_called_with(self.context,
|
||||
FAKE_IPSEC_CONNECTION)
|
||||
mock_get_id.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
|
||||
mock_gen_new.assert_called_with(FAKE_EDGE_ID, FAKE_IPSEC_VPN_SITE)
|
||||
mock_update_ipsec.assert_called_with(FAKE_EDGE_ID,
|
||||
FAKE_IPSEC_VPN_SITE,
|
||||
enabled=True)
|
||||
mock_update_fw.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
|
||||
mock_update_status.assert_called_with(
|
||||
self.context,
|
||||
FAKE_IPSEC_CONNECTION["vpnservice_id"],
|
||||
FAKE_IPSEC_CONNECTION["id"],
|
||||
"ACTIVE")
|
||||
|
||||
@mock.patch('%s._convert_ipsec_conn' % DRIVER_PATH)
|
||||
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
|
||||
@mock.patch('%s._generate_new_sites' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_status' % DRIVER_PATH)
|
||||
def test_create_ipsec_site_connection_fail(self,
|
||||
mock_update_status,
|
||||
mock_update_ipsec,
|
||||
mock_gen_new, mock_get_id,
|
||||
mock_conv_ipsec):
|
||||
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
|
||||
mock_conv_ipsec.return_value = FAKE_IPSEC_VPN_SITE
|
||||
mock_gen_new.return_value = FAKE_IPSEC_VPN_SITE
|
||||
mock_update_ipsec.side_effect = (
|
||||
vcns_exc.VcnsApiException(**FAKE_VCNSAPIEXC))
|
||||
self.assertRaises(nsxv_exc.NsxPluginException,
|
||||
self.driver.create_ipsec_site_connection,
|
||||
self.context, FAKE_IPSEC_CONNECTION)
|
||||
mock_conv_ipsec.assert_called_with(self.context, FAKE_IPSEC_CONNECTION)
|
||||
mock_get_id.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
|
||||
mock_gen_new.assert_called_with(FAKE_EDGE_ID, FAKE_IPSEC_VPN_SITE)
|
||||
mock_update_ipsec.assert_called_with(FAKE_EDGE_ID,
|
||||
FAKE_IPSEC_VPN_SITE,
|
||||
enabled=True)
|
||||
mock_update_status.assert_called_with(
|
||||
self.context,
|
||||
FAKE_IPSEC_CONNECTION["vpnservice_id"],
|
||||
FAKE_IPSEC_CONNECTION["id"],
|
||||
"ERROR")
|
||||
|
||||
@mock.patch('%s._convert_ipsec_conn' % DRIVER_PATH)
|
||||
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
|
||||
@mock.patch('%s._generate_new_sites' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_status' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_firewall_rules' % DRIVER_PATH)
|
||||
def test_update_fw_fail(self, mock_update_fw, mock_update_status,
|
||||
mock_update_ipsec, mock_gen_new,
|
||||
mock_get_id, mock_conv_ipsec):
|
||||
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
|
||||
mock_conv_ipsec.return_value = FAKE_IPSEC_VPN_SITE
|
||||
mock_gen_new.return_value = FAKE_IPSEC_VPN_SITE
|
||||
mock_update_fw.side_effect = (
|
||||
vcns_exc.VcnsApiException(**FAKE_VCNSAPIEXC))
|
||||
self.assertRaises(nsxv_exc.NsxPluginException,
|
||||
self.driver.create_ipsec_site_connection,
|
||||
self.context, FAKE_IPSEC_CONNECTION)
|
||||
mock_conv_ipsec.assert_called_with(self.context, FAKE_IPSEC_CONNECTION)
|
||||
mock_get_id.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
|
||||
mock_gen_new.assert_called_with(FAKE_EDGE_ID, FAKE_IPSEC_VPN_SITE)
|
||||
mock_update_ipsec.assert_called_with(FAKE_EDGE_ID,
|
||||
FAKE_IPSEC_VPN_SITE,
|
||||
enabled=True)
|
||||
mock_update_fw.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
|
||||
mock_update_status.assert_called_with(
|
||||
self.context,
|
||||
FAKE_IPSEC_CONNECTION["vpnservice_id"],
|
||||
FAKE_IPSEC_CONNECTION["id"],
|
||||
"ERROR")
|
||||
|
||||
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_site_dict' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_firewall_rules' % DRIVER_PATH)
|
||||
def test_update_ipsec(self, mock_update_fw, mock_update_ipsec,
|
||||
mock_update_sites, mock_get_id):
|
||||
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
|
||||
mock_update_sites.return_value = FAKE_IPSEC_VPN_SITE
|
||||
self.driver.update_ipsec_site_connection(self.context,
|
||||
FAKE_IPSEC_CONNECTION,
|
||||
FAKE_NEW_CONNECTION)
|
||||
mock_update_sites.assert_called_with(self.context, FAKE_EDGE_ID,
|
||||
FAKE_IPSEC_CONNECTION,
|
||||
FAKE_NEW_CONNECTION)
|
||||
mock_update_ipsec.assert_called_with(FAKE_EDGE_ID, FAKE_IPSEC_VPN_SITE)
|
||||
mock_update_fw.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
|
||||
|
||||
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_site_dict' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_firewall_rules' % DRIVER_PATH)
|
||||
def test_update_ipsec_fail_with_notfound(self, mock_update_fw,
|
||||
mock_update_ipsec,
|
||||
mock_update_sites, mock_get_id):
|
||||
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
|
||||
mock_update_sites.return_value = {}
|
||||
self.assertRaises(nsxv_exc.NsxIPsecVpnMappingNotFound,
|
||||
self.driver.update_ipsec_site_connection,
|
||||
self.context, FAKE_IPSEC_CONNECTION,
|
||||
FAKE_NEW_CONNECTION)
|
||||
mock_update_sites.assert_called_with(self.context,
|
||||
FAKE_EDGE_ID,
|
||||
FAKE_IPSEC_CONNECTION,
|
||||
FAKE_NEW_CONNECTION)
|
||||
|
||||
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_site_dict' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_firewall_rules' % DRIVER_PATH)
|
||||
def test_update_ipsec_fail_with_fw_fail(self, mock_update_fw,
|
||||
mock_update_ipsec,
|
||||
mock_update_sites, mock_get_id):
|
||||
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
|
||||
mock_update_fw.side_effect = (
|
||||
vcns_exc.VcnsApiException(**FAKE_VCNSAPIEXC))
|
||||
self.assertRaises(nsxv_exc.NsxPluginException,
|
||||
self.driver.update_ipsec_site_connection,
|
||||
self.context, FAKE_IPSEC_CONNECTION,
|
||||
FAKE_NEW_CONNECTION)
|
||||
mock_update_sites.assert_called_with(self.context, FAKE_EDGE_ID,
|
||||
FAKE_IPSEC_CONNECTION,
|
||||
FAKE_NEW_CONNECTION)
|
||||
mock_update_fw.assert_called_with(self.context, FAKE_VPNSERVICE_ID)
|
||||
|
||||
@mock.patch('%s._get_router_edge_id' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_site_dict' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_ipsec_config' % DRIVER_PATH)
|
||||
@mock.patch('%s._update_status' % DRIVER_PATH)
|
||||
def test_update_ipsec_fail_with_site_fail(self, mock_update_status,
|
||||
mock_update_ipsec,
|
||||
mock_update_sites, mock_get_id):
|
||||
mock_get_id.return_value = (FAKE_ROUTER_ID, FAKE_EDGE_ID)
|
||||
mock_update_sites.return_value = FAKE_IPSEC_VPN_SITE
|
||||
mock_update_ipsec.side_effect = (
|
||||
vcns_exc.VcnsApiException(**FAKE_VCNSAPIEXC))
|
||||
self.assertRaises(nsxv_exc.NsxPluginException,
|
||||
self.driver.update_ipsec_site_connection,
|
||||
self.context,
|
||||
FAKE_IPSEC_CONNECTION,
|
||||
FAKE_NEW_CONNECTION)
|
||||
mock_update_sites.assert_called_with(self.context, FAKE_EDGE_ID,
|
||||
FAKE_IPSEC_CONNECTION,
|
||||
FAKE_NEW_CONNECTION)
|
||||
mock_update_ipsec.assert_called_with(FAKE_EDGE_ID,
|
||||
FAKE_IPSEC_VPN_SITE)
|
||||
mock_update_status.assert_called_with(
|
||||
self.context,
|
||||
FAKE_IPSEC_CONNECTION["vpnservice_id"],
|
||||
FAKE_IPSEC_CONNECTION["id"],
|
||||
"ERROR")
|
||||
|
||||
def test_create_vpn_service_legal(self):
|
||||
"""Create a legal vpn service"""
|
||||
# create an external network with a subnet, and an exclusive router
|
||||
providernet_args = {extnet_apidef.EXTERNAL: True}
|
||||
with self.network(name='ext-net',
|
||||
providernet_args=providernet_args,
|
||||
arg_list=(extnet_apidef.EXTERNAL, )) as ext_net,\
|
||||
self.subnet(ext_net),\
|
||||
self.router(router_type='exclusive',
|
||||
external_gateway_info={'network_id':
|
||||
ext_net['network']['id']}) as router,\
|
||||
self.subnet(cidr="20.0.0.0/24") as sub:
|
||||
# add an interface to the router
|
||||
self.l3plugin.add_router_interface(
|
||||
self.context,
|
||||
router['id'],
|
||||
{'subnet_id': sub['subnet']['id']})
|
||||
# create the service
|
||||
vpnservice = {'router_id': router['id'],
|
||||
'id': _uuid(),
|
||||
'subnet_id': sub['subnet']['id']}
|
||||
with mock.patch.object(self.driver, '_get_gateway_ips',
|
||||
return_value=(None, None)):
|
||||
self.driver.create_vpnservice(self.context, vpnservice)
|
||||
|
||||
def test_create_vpn_service_on_shared_router(self):
|
||||
"""Creating a service with shared router is not allowed"""
|
||||
# create an external network with a subnet, and a shared router
|
||||
providernet_args = {extnet_apidef.EXTERNAL: True}
|
||||
with self.network(name='ext-net',
|
||||
providernet_args=providernet_args,
|
||||
arg_list=(extnet_apidef.EXTERNAL, )) as ext_net,\
|
||||
self.subnet(ext_net),\
|
||||
self.router(router_type='shared',
|
||||
external_gateway_info={'network_id':
|
||||
ext_net['network']['id']}) as router,\
|
||||
self.subnet(cidr="20.0.0.0/24") as sub:
|
||||
# add an interface to the router
|
||||
self.l3plugin.add_router_interface(
|
||||
self.context,
|
||||
router['id'],
|
||||
{'subnet_id': sub['subnet']['id']})
|
||||
# create the service
|
||||
vpnservice = {'router_id': router['id'],
|
||||
'id': _uuid(),
|
||||
'subnet_id': sub['subnet']['id']}
|
||||
self.assertRaises(nsxv_exc.NsxPluginException,
|
||||
self.driver.create_vpnservice,
|
||||
self.context, vpnservice)
|
||||
|
||||
def test_create_vpn_service_on_router_without_if(self):
|
||||
"""Creating a service with unattached subnet is not allowed"""
|
||||
# create an external network with a subnet, and an exclusive router
|
||||
providernet_args = {extnet_apidef.EXTERNAL: True}
|
||||
with self.network(name='ext-net',
|
||||
providernet_args=providernet_args,
|
||||
arg_list=(extnet_apidef.EXTERNAL, )) as ext_net,\
|
||||
self.subnet(ext_net),\
|
||||
self.router(router_type='exclusive',
|
||||
external_gateway_info={'network_id':
|
||||
ext_net['network']['id']}) as router,\
|
||||
self.subnet() as sub:
|
||||
# create the service
|
||||
vpnservice = {'router_id': router['id'],
|
||||
'id': _uuid(),
|
||||
'subnet_id': sub['subnet']['id']}
|
||||
self.assertRaises(vpnaas.SubnetIsNotConnectedToRouter,
|
||||
self.driver.create_vpnservice,
|
||||
self.context, vpnservice)
|
||||
|
||||
def test_create_vpn_service_without_subnet(self):
|
||||
"""Creating a service without a subnet is not allowed"""
|
||||
# create an external network with a subnet, and an exclusive router
|
||||
providernet_args = {extnet_apidef.EXTERNAL: True}
|
||||
with self.network(name='ext-net',
|
||||
providernet_args=providernet_args,
|
||||
arg_list=(extnet_apidef.EXTERNAL, )) as ext_net,\
|
||||
self.subnet(ext_net),\
|
||||
self.router(router_type='exclusive',
|
||||
external_gateway_info={'network_id':
|
||||
ext_net['network']['id']}) as router,\
|
||||
self.subnet(cidr="20.0.0.0/24") as sub:
|
||||
# add an interface to the router
|
||||
self.l3plugin.add_router_interface(
|
||||
self.context,
|
||||
router['id'],
|
||||
{'subnet_id': sub['subnet']['id']})
|
||||
# create the service without the subnet
|
||||
vpnservice = {'router_id': router['id'],
|
||||
'id': _uuid(),
|
||||
'subnet_id': None}
|
||||
self.assertRaises(nsxv_exc.NsxPluginException,
|
||||
self.driver.create_vpnservice,
|
||||
self.context, vpnservice)
|
@ -27,22 +27,17 @@ from neutron.db import servicetype_db # noqa
|
||||
from neutron.quota import resource_registry
|
||||
from neutron.tests import base
|
||||
from neutron_lib.callbacks import registry
|
||||
from neutron_lib.plugins import constants
|
||||
|
||||
from vmware_nsx._i18n import _
|
||||
from vmware_nsx.common import config # noqa
|
||||
from vmware_nsx.db import nsxv_db
|
||||
from vmware_nsx.dvs import dvs_utils
|
||||
from vmware_nsx.services.lbaas.octavia import octavia_listener
|
||||
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
|
||||
from vmware_nsx.shell.admin.plugins.nsxp.resources import utils as nsxp_utils
|
||||
from vmware_nsx.shell.admin.plugins.nsxv.resources import migration
|
||||
from vmware_nsx.shell.admin.plugins.nsxv.resources import utils as nsxv_utils
|
||||
from vmware_nsx.shell.admin.plugins.nsxv3.resources import utils as nsxv3_utils
|
||||
from vmware_nsx.shell import resources
|
||||
from vmware_nsx.tests import unit as vmware
|
||||
from vmware_nsx.tests.unit.nsx_p import test_plugin as test_p_plugin
|
||||
from vmware_nsx.tests.unit.nsx_v import test_plugin as test_v_plugin
|
||||
from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_v3_plugin
|
||||
from vmware_nsxlib.v3 import client as v3_client
|
||||
from vmware_nsxlib.v3 import core_resources
|
||||
@ -125,177 +120,6 @@ class AbstractTestAdminUtils(base.BaseTestCase, metaclass=abc.ABCMeta):
|
||||
return self._plugin.create_router(self.edgeapi.context, data)
|
||||
|
||||
|
||||
class TestNsxvAdminUtils(AbstractTestAdminUtils,
|
||||
test_v_plugin.NsxVPluginV2TestCase):
|
||||
|
||||
def _get_plugin_name(self):
|
||||
return 'nsxv'
|
||||
|
||||
def _init_mock_plugin(self, *mocks):
|
||||
super(TestNsxvAdminUtils, self)._init_mock_plugin()
|
||||
|
||||
# support the dvs manager:
|
||||
mock.patch.object(dvs_utils, 'dvs_create_session').start()
|
||||
# override metadata get-object
|
||||
dummy_lb = {
|
||||
'enabled': True,
|
||||
'enableServiceInsertion': True,
|
||||
'accelerationEnabled': True,
|
||||
'virtualServer': [],
|
||||
'applicationProfile': [],
|
||||
'pool': [],
|
||||
'applicationRule': []
|
||||
}
|
||||
mock.patch('vmware_nsx.plugins.nsx_v.vshield.nsxv_edge_cfg_obj.'
|
||||
'NsxvEdgeCfgObj.get_object',
|
||||
return_value=dummy_lb).start()
|
||||
|
||||
# Tests shouldn't wait for dummy spawn jobs to finish
|
||||
mock.patch('vmware_nsx.shell.admin.plugins.nsxv.resources.utils.'
|
||||
'NsxVPluginWrapper.count_spawn_jobs',
|
||||
return_value=0).start()
|
||||
|
||||
self._plugin = nsxv_utils.NsxVPluginWrapper()
|
||||
|
||||
def get_plugin_mock(alias=constants.CORE):
|
||||
if alias in (constants.CORE, constants.L3):
|
||||
return self._plugin
|
||||
|
||||
mock.patch("neutron_lib.plugins.directory.get_plugin",
|
||||
side_effect=get_plugin_mock).start()
|
||||
|
||||
# Create a router to make sure we have deployed an edge
|
||||
self.router = self._create_router()
|
||||
self.dist_router = self._create_router(dist=True)
|
||||
self.network = self._create_net()
|
||||
|
||||
def tearDown(self):
|
||||
if self.router and self.router.get('id'):
|
||||
self._plugin.delete_router(
|
||||
self.edgeapi.context, self.router['id'])
|
||||
if self.dist_router and self.dist_router.get('id'):
|
||||
self._plugin.delete_router(
|
||||
self.edgeapi.context, self.dist_router['id'])
|
||||
if self.network and self.network.get('id'):
|
||||
self._plugin.delete_network(
|
||||
self.edgeapi.context, self.network['id'])
|
||||
super(TestNsxvAdminUtils, self).tearDown()
|
||||
|
||||
def test_nsxv_resources(self):
|
||||
self._test_resources(resources.nsxv_resources)
|
||||
|
||||
def _test_edge_nsx_update(self, edge_id, params):
|
||||
args = {'property': ["edge-id=%s" % edge_id]}
|
||||
args['property'].extend(params)
|
||||
self._test_resource('edges', 'nsx-update', **args)
|
||||
|
||||
def _create_router(self, dist=False):
|
||||
# Create an exclusive router (with an edge)
|
||||
tenant_id = uuidutils.generate_uuid()
|
||||
data = {'router': {'tenant_id': tenant_id}}
|
||||
data['router']['name'] = 'dummy'
|
||||
data['router']['admin_state_up'] = True
|
||||
if dist:
|
||||
data['router']['distributes'] = True
|
||||
else:
|
||||
data['router']['router_type'] = 'exclusive'
|
||||
|
||||
return self._plugin.create_router(self.edgeapi.context, data)
|
||||
|
||||
def _create_net(self):
|
||||
tenant_id = uuidutils.generate_uuid()
|
||||
data = {'network': {'tenant_id': tenant_id,
|
||||
'name': 'dummy',
|
||||
'admin_state_up': True,
|
||||
'shared': False}}
|
||||
net = self._plugin.create_network(self.edgeapi.context, data)
|
||||
data = {'subnet': {'tenant_id': tenant_id,
|
||||
'name': 'dummy',
|
||||
'admin_state_up': True,
|
||||
'network_id': net['id'],
|
||||
'cidr': '1.1.1.0/16',
|
||||
'enable_dhcp': True,
|
||||
'ip_version': 4,
|
||||
'dns_nameservers': None,
|
||||
'host_routes': None,
|
||||
'allocation_pools': None}}
|
||||
self._plugin.create_subnet(self.edgeapi.context, data)
|
||||
return net
|
||||
|
||||
def get_edge_id(self):
|
||||
bindings = nsxv_db.get_nsxv_router_bindings(
|
||||
self.edgeapi.context.session)
|
||||
for binding in bindings:
|
||||
if binding.edge_id:
|
||||
return binding.edge_id
|
||||
# use a dummy edge
|
||||
return "edge-1"
|
||||
|
||||
def test_edge_nsx_updates(self):
|
||||
"""Test eges/nsx-update utility with different inputs."""
|
||||
edge_id = self.get_edge_id()
|
||||
self._test_edge_nsx_update(edge_id, ["appliances=true"])
|
||||
self._test_edge_nsx_update(edge_id, ["size=compact"])
|
||||
self._test_edge_nsx_update(edge_id, ["hostgroup=update"])
|
||||
self._test_edge_nsx_update(edge_id, ["hostgroup=all"])
|
||||
self._test_edge_nsx_update(edge_id, ["hostgroup=clean"])
|
||||
self._test_edge_nsx_update(edge_id, ["highavailability=True"])
|
||||
self._test_edge_nsx_update(edge_id, ["resource=cpu", "limit=100"])
|
||||
self._test_edge_nsx_update(edge_id, ["syslog-server=1.1.1.1",
|
||||
"syslog-proto=tcp",
|
||||
"log-level=debug"])
|
||||
|
||||
def test_bad_args(self):
|
||||
args = {'property': ["xxx"]}
|
||||
errors = self._test_resource_with_errors(
|
||||
'networks', 'nsx-update', **args)
|
||||
self.assertEqual(1, len(errors))
|
||||
|
||||
def test_resources_with_common_args(self):
|
||||
"""Run all nsxv admin utilities with some common arguments
|
||||
|
||||
Using arguments like edge-id which many apis need
|
||||
This improves the test coverage
|
||||
"""
|
||||
edge_id = self.get_edge_id()
|
||||
args = ["edge-id=%s" % edge_id,
|
||||
"router-id=e5b9b249-0034-4729-8ab6-fe4dacaa3a12",
|
||||
"policy-id=1",
|
||||
"network_id=net-1",
|
||||
"net-id=net-1",
|
||||
"network=net-1",
|
||||
"port=port-1",
|
||||
"security-group-id=sg-1",
|
||||
"dvs-id=dvs-1",
|
||||
"moref=virtualwire-1",
|
||||
"teamingpolicy=LACP_ACTIVE",
|
||||
"log-allowed-traffic=true",
|
||||
"az-name=default",
|
||||
"transit-network=abc",
|
||||
"moref=abc",
|
||||
]
|
||||
self._test_resources_with_args(
|
||||
resources.nsxv_resources, args)
|
||||
|
||||
def test_router_recreate(self):
|
||||
# Testing router-recreate separately because it may change the edge-id
|
||||
edge_id = self.get_edge_id()
|
||||
args = {'property': ["edge-id=%s" % edge_id]}
|
||||
self._test_resource('routers', 'nsx-recreate', **args)
|
||||
|
||||
def test_migration_validation(self):
|
||||
# check that validation fails
|
||||
payload = admin_utils.MetadataEventPayload(
|
||||
{'property': ["transit-network=1.1.1.0/24"]})
|
||||
try:
|
||||
migration.validate_config_for_migration(
|
||||
'nsx-migrate-v2t', 'validate', None, payload)
|
||||
except SystemExit:
|
||||
return
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
|
||||
class TestNsxv3AdminUtils(AbstractTestAdminUtils,
|
||||
test_v3_plugin.NsxV3PluginTestCaseMixin):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user