Fixing unit test failures in Cisco plugin
Bug #1038565 The tests for bulk resource creation failure were failing since the bulk API calls were not getting relayed correctly to the virt_phy_sw.py, that has been fixed There tests for the network_multi_blade_v2.py were failing since DB initialization order was incorrect. The tests in test_api_v2.py were failing since the plugin instance was not being reset for each test. Change-Id: I449bd8a61c1f61f98a97acf489574624fe309caa
This commit is contained in:
parent
7afb37af76
commit
8e2812eeaa
@ -22,6 +22,7 @@ import logging
|
||||
|
||||
from quantum.openstack.common import importutils
|
||||
from quantum.plugins.cisco.common import cisco_constants as const
|
||||
from quantum.plugins.cisco.common import cisco_credentials_v2 as cred
|
||||
from quantum.plugins.cisco.db import network_db_v2 as cdb
|
||||
from quantum.plugins.cisco import l2network_plugin_configuration as conf
|
||||
from quantum import quantum_plugin_base_v2
|
||||
@ -46,6 +47,8 @@ class NetworkMultiBladeV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
||||
configured, and load the inventories those device plugins for which the
|
||||
inventory is configured
|
||||
"""
|
||||
cdb.initialize()
|
||||
cred.Store.initialize()
|
||||
self._vlan_mgr = importutils.import_object(conf.MANAGER_CLASS)
|
||||
for key in conf.PLUGINS[const.PLUGINS].keys():
|
||||
plugin_obj = conf.PLUGINS[const.PLUGINS][key]
|
||||
|
@ -41,14 +41,16 @@ class VirtualPhysicalSwitchModelV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
||||
One or more servers to a nexus switch.
|
||||
"""
|
||||
MANAGE_STATE = True
|
||||
__native_bulk_support = True
|
||||
supported_extension_aliases = []
|
||||
_plugins = {}
|
||||
_inventory = {}
|
||||
_methods_to_delegate = ['update_network', 'get_network', 'get_networks',
|
||||
'create_port', 'delete_port', 'update_port',
|
||||
'get_port', 'get_ports',
|
||||
'create_subnet', 'delete_subnet', 'update_subnet',
|
||||
'get_subnet', 'get_subnets']
|
||||
'create_port', 'create_port_bulk', 'delete_port',
|
||||
'update_port', 'get_port', 'get_ports',
|
||||
'create_subnet', 'create_subnet_bulk',
|
||||
'delete_subnet', 'update_subnet', 'get_subnet',
|
||||
'get_subnets', ]
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
@ -69,15 +71,32 @@ class VirtualPhysicalSwitchModelV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
||||
LOG.debug("Loaded device inventory %s\n" %
|
||||
conf.PLUGINS[const.INVENTORY][key])
|
||||
|
||||
if hasattr(self._plugins[const.VSWITCH_PLUGIN],
|
||||
"supported_extension_aliases"):
|
||||
self.supported_extension_aliases.extend(
|
||||
self._plugins[const.VSWITCH_PLUGIN].
|
||||
supported_extension_aliases)
|
||||
|
||||
LOG.debug("%s.%s init done" % (__name__, self.__class__.__name__))
|
||||
|
||||
def __getattribute__(self, name):
|
||||
methods = object.__getattribute__(self, "_methods_to_delegate")
|
||||
"""
|
||||
This delegates the calls to the methods implemented only by the OVS
|
||||
sub-plugin.
|
||||
"""
|
||||
super_getattr = super(VirtualPhysicalSwitchModelV2,
|
||||
self).__getattribute__
|
||||
methods = super_getattr('_methods_to_delegate')
|
||||
|
||||
if name in methods:
|
||||
return getattr(object.__getattribute__(self, "_plugins")
|
||||
[const.VSWITCH_PLUGIN], name)
|
||||
else:
|
||||
return object.__getattribute__(self, name)
|
||||
plugin = super_getattr('_plugins')[const.VSWITCH_PLUGIN]
|
||||
return getattr(plugin, name)
|
||||
|
||||
try:
|
||||
return super_getattr(name)
|
||||
except AttributeError:
|
||||
plugin = super_getattr('_plugins')[const.VSWITCH_PLUGIN]
|
||||
return getattr(plugin, name)
|
||||
|
||||
def _func_name(self, offset=0):
|
||||
"""Get the name of the calling function"""
|
||||
@ -173,6 +192,36 @@ class VirtualPhysicalSwitchModelV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
|
||||
# TODO (Sumit): Check if we need to perform any rollback here
|
||||
raise
|
||||
|
||||
def create_network_bulk(self, context, networks):
|
||||
"""
|
||||
Perform this operation in the context of the configured device
|
||||
plugins.
|
||||
"""
|
||||
LOG.debug("create_network_bulk() called\n")
|
||||
try:
|
||||
args = [context, networks]
|
||||
ovs_output = self._plugins[
|
||||
const.VSWITCH_PLUGIN].create_network_bulk(context, networks)
|
||||
vlan_ids = odb.get_vlans()
|
||||
vlanids = ''
|
||||
for v_id in vlan_ids:
|
||||
vlanids = str(v_id[0]) + ',' + vlanids
|
||||
vlanids = vlanids.strip(',')
|
||||
LOG.debug("ovs_output: %s\n " % ovs_output)
|
||||
ovs_networks = ovs_output
|
||||
for ovs_network in ovs_networks:
|
||||
vlan_id = odb.get_vlan(ovs_network['id'])
|
||||
vlan_name = conf.VLAN_NAME_PREFIX + str(vlan_id)
|
||||
args = [ovs_network['tenant_id'], ovs_network['name'],
|
||||
ovs_network['id'], vlan_name, vlan_id,
|
||||
{'vlan_ids':vlanids}]
|
||||
nexus_output = self._invoke_plugin_per_device(
|
||||
const.NEXUS_PLUGIN, "create_network", args)
|
||||
return ovs_output
|
||||
except:
|
||||
# TODO (Sumit): Check if we need to perform any rollback here
|
||||
raise
|
||||
|
||||
def update_network(self, context, id, network):
|
||||
"""For this model this method will be delegated to vswitch plugin"""
|
||||
pass
|
||||
|
@ -40,25 +40,28 @@ class PluginV2(db_base_plugin_v2.QuantumDbPluginV2):
|
||||
supported_extension_aliases = ["Cisco Credential", "Cisco Port Profile",
|
||||
"Cisco qos", "Cisco Nova Tenant",
|
||||
"Cisco Multiport"]
|
||||
_methods_to_delegate = ['create_network', 'delete_network',
|
||||
'update_network', 'get_network', 'get_networks',
|
||||
'create_port', 'delete_port', 'update_port',
|
||||
'get_port', 'get_ports',
|
||||
'create_subnet', 'delete_subnet', 'update_subnet',
|
||||
'get_subnet', 'get_subnets']
|
||||
_methods_to_delegate = ['create_network', 'create_network_bulk',
|
||||
'delete_network', 'update_network', 'get_network',
|
||||
'get_networks',
|
||||
'create_port', 'create_port_bulk', 'delete_port',
|
||||
'update_port', 'get_port', 'get_ports',
|
||||
'create_subnet', 'create_subnet_bulk',
|
||||
'delete_subnet', 'update_subnet',
|
||||
'get_subnet', 'get_subnets', ]
|
||||
_master = True
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Loads the model class, initializes the DB, and credential store.
|
||||
Loads the model class.
|
||||
"""
|
||||
self._model = importutils.import_object(conf.MODEL_CLASS)
|
||||
if hasattr(self._model, "MANAGE_STATE") and self._model.MANAGE_STATE:
|
||||
self._master = False
|
||||
LOG.debug("Model %s manages state" % conf.MODEL_CLASS)
|
||||
else:
|
||||
cdb.initialize()
|
||||
cred.Store.initialize()
|
||||
native_bulk_attr_name = ("_%s__native_bulk_support"
|
||||
% self._model.__class__.__name__)
|
||||
self.__native_bulk_support = getattr(self._model,
|
||||
native_bulk_attr_name, False)
|
||||
|
||||
if hasattr(self._model, "supported_extension_aliases"):
|
||||
self.supported_extension_aliases.extend(
|
||||
|
@ -2,7 +2,7 @@
|
||||
pipeline = extensions extensions_test_app
|
||||
|
||||
[filter:extensions]
|
||||
paste.filter_factory = quantum.extensions.extensions:plugin_aware_extension_middleware_factory
|
||||
paste.filter_factory = quantum.common.extensions:plugin_aware_extension_middleware_factory
|
||||
|
||||
[app:extensions_test_app]
|
||||
paste.app_factory = quantum.plugins.cisco.tests.unit.test_cisco_extension:app_factory
|
||||
|
@ -0,0 +1,8 @@
|
||||
[pipeline:extensions_app_with_filter]
|
||||
pipeline = extensions extensions_test_app
|
||||
|
||||
[filter:extensions]
|
||||
paste.filter_factory = quantum.common.extensions:plugin_aware_extension_middleware_factory
|
||||
|
||||
[app:extensions_test_app]
|
||||
paste.app_factory = quantum.plugins.cisco.tests.unit.test_cisco_extension:app_factory
|
@ -77,7 +77,7 @@ class CiscoNEXUSFakeDriver():
|
||||
pass
|
||||
|
||||
def create_vlan(self, vlan_name, vlan_id, nexus_host, nexus_user,
|
||||
nexus_password, nexus_ports, nexus_ssh_port):
|
||||
nexus_password, nexus_ports, nexus_ssh_port, vlan_ids):
|
||||
"""
|
||||
Creates a VLAN and Enable on trunk mode an interface on Nexus Switch
|
||||
given the VLAN ID and Name and Interface Number
|
||||
|
@ -12,9 +12,32 @@ bind_host = 0.0.0.0
|
||||
bind_port = 9696
|
||||
|
||||
# Path to the extensions
|
||||
api_extensions_path = ../../../../extensions
|
||||
api_extensions_path = ../../../../../extensions
|
||||
|
||||
# Paste configuration file
|
||||
api_paste_config = api-paste.ini.cisco.test
|
||||
|
||||
core_plugin = quantum.plugins.cisco.network_plugin.PluginV2
|
||||
|
||||
# The messaging module to use, defaults to kombu.
|
||||
rpc_backend = quantum.openstack.common.rpc.impl_fake
|
||||
|
||||
[QUOTAS]
|
||||
# resource name(s) that are supported in quota features
|
||||
quota_items = network,subnet,port
|
||||
|
||||
# default number of resource allowed per tenant, minus for unlimited
|
||||
default_quota = -1
|
||||
|
||||
# number of networks allowed per tenant, and minus means unlimited
|
||||
# quota_network = 10
|
||||
|
||||
# number of subnets allowed per tenant, and minus means unlimited
|
||||
# quota_subnet = 10
|
||||
|
||||
# number of ports allowed per tenant, and minus means unlimited
|
||||
# quota_port = 50
|
||||
|
||||
# default driver to use for quota checks
|
||||
# quota_driver = quantum.quota.ConfDriver
|
||||
quota_driver = quantum.extensions._quotav2_driver.DbQuotaDriver
|
||||
|
@ -20,6 +20,8 @@ import webtest
|
||||
|
||||
from quantum.api.v2 import router
|
||||
from quantum.common import config
|
||||
from quantum.extensions.extensions import PluginAwareExtensionManager
|
||||
from quantum.manager import QuantumManager
|
||||
from quantum.openstack.common import cfg
|
||||
from quantum.tests.unit import test_api_v2
|
||||
|
||||
@ -35,6 +37,10 @@ class APIv2TestCase(test_api_v2.APIv2TestCase):
|
||||
|
||||
def setUp(self):
|
||||
plugin = 'quantum.plugins.cisco.network_plugin.PluginV2'
|
||||
# Ensure 'stale' patched copies of the plugin are never returned
|
||||
QuantumManager._instance = None
|
||||
# Ensure existing ExtensionManager is not used
|
||||
PluginAwareExtensionManager._instance = None
|
||||
# Create the default configurations
|
||||
args = ['--config-file', curdir('quantumv2.conf.cisco.test')]
|
||||
config.parse(args=args)
|
||||
|
@ -20,8 +20,13 @@ import os
|
||||
|
||||
from quantum.api.v2.router import APIRouter
|
||||
from quantum.common import config
|
||||
from quantum.common.test_lib import test_config
|
||||
from quantum import context
|
||||
from quantum.db import api as db
|
||||
from quantum.extensions import _quotav2_model as quotav2_model
|
||||
from quantum.manager import QuantumManager
|
||||
from quantum.plugins.cisco.common import cisco_constants as const
|
||||
from quantum.plugins.cisco.db import network_db_v2
|
||||
from quantum.plugins.cisco.db import network_models_v2
|
||||
from quantum.openstack.common import cfg
|
||||
from quantum.tests.unit import test_db_plugin
|
||||
@ -50,11 +55,35 @@ class NetworkPluginV2TestCase(test_db_plugin.QuantumDbPluginV2TestCase):
|
||||
plugin = 'quantum.plugins.cisco.network_plugin.PluginV2'
|
||||
# Create the default configurations
|
||||
args = ['--config-file', curdir('quantumv2.conf.cisco.test')]
|
||||
# If test_config specifies some config-file, use it, as well
|
||||
for config_file in test_config.get('config_files', []):
|
||||
args.extend(['--config-file', config_file])
|
||||
config.parse(args=args)
|
||||
# Update the plugin
|
||||
cfg.CONF.set_override('core_plugin', plugin)
|
||||
cfg.CONF.set_override('base_mac', "12:34:56:78:90:ab")
|
||||
self.api = APIRouter()
|
||||
cfg.CONF.max_dns_nameservers = 2
|
||||
cfg.CONF.max_subnet_host_routes = 2
|
||||
|
||||
def new_init():
|
||||
db.configure_db({'sql_connection': 'sqlite://',
|
||||
'base': network_models_v2.model_base.BASEV2})
|
||||
|
||||
with mock.patch.object(network_db_v2,
|
||||
'initialize', new=new_init):
|
||||
self.api = APIRouter()
|
||||
|
||||
def _is_native_bulk_supported():
|
||||
plugin_obj = QuantumManager.get_plugin()
|
||||
native_bulk_attr_name = ("_%s__native_bulk_support"
|
||||
% plugin_obj.__class__.__name__)
|
||||
return getattr(plugin_obj, native_bulk_attr_name, False)
|
||||
|
||||
self._skip_native_bulk = not _is_native_bulk_supported()
|
||||
|
||||
ext_mgr = test_config.get('extension_manager', None)
|
||||
if ext_mgr:
|
||||
self.ext_api = test_extensions.setup_extensions_middleware(ext_mgr)
|
||||
LOG.debug("%s.%s.%s done" % (__name__, self.__class__.__name__,
|
||||
inspect.stack()[0][3]))
|
||||
|
||||
@ -65,6 +94,16 @@ class NetworkPluginV2TestCase(test_db_plugin.QuantumDbPluginV2TestCase):
|
||||
|
||||
cfg.CONF.reset()
|
||||
|
||||
def _get_plugin_ref(self):
|
||||
plugin_obj = QuantumManager.get_plugin()
|
||||
if getattr(plugin_obj, "_master"):
|
||||
plugin_ref = plugin_obj
|
||||
else:
|
||||
plugin_ref = getattr(plugin_obj, "_model").\
|
||||
_plugins[const.VSWITCH_PLUGIN]
|
||||
|
||||
return plugin_ref
|
||||
|
||||
|
||||
class TestV2HTTPResponse(NetworkPluginV2TestCase,
|
||||
test_db_plugin.TestV2HTTPResponse):
|
||||
@ -74,14 +113,146 @@ class TestV2HTTPResponse(NetworkPluginV2TestCase,
|
||||
|
||||
class TestPortsV2(NetworkPluginV2TestCase, test_db_plugin.TestPortsV2):
|
||||
|
||||
pass
|
||||
def test_create_ports_bulk_emulated_plugin_failure(self):
|
||||
real_has_attr = hasattr
|
||||
|
||||
#ensures the API choose the emulation code path
|
||||
def fakehasattr(item, attr):
|
||||
if attr.endswith('__native_bulk_support'):
|
||||
return False
|
||||
return real_has_attr(item, attr)
|
||||
|
||||
with mock.patch('__builtin__.hasattr',
|
||||
new=fakehasattr):
|
||||
plugin_ref = self._get_plugin_ref()
|
||||
orig = plugin_ref.create_port
|
||||
with mock.patch.object(plugin_ref,
|
||||
'create_port') as patched_plugin:
|
||||
|
||||
def side_effect(*args, **kwargs):
|
||||
return self._do_side_effect(patched_plugin, orig,
|
||||
*args, **kwargs)
|
||||
|
||||
patched_plugin.side_effect = side_effect
|
||||
with self.network() as net:
|
||||
res = self._create_port_bulk('json', 2,
|
||||
net['network']['id'],
|
||||
'test',
|
||||
True)
|
||||
# We expect a 500 as we injected a fault in the plugin
|
||||
self._validate_behavior_on_bulk_failure(res, 'ports')
|
||||
|
||||
def test_create_ports_bulk_native_plugin_failure(self):
|
||||
if self._skip_native_bulk:
|
||||
self.skipTest("Plugin does not support native bulk port create")
|
||||
ctx = context.get_admin_context()
|
||||
with self.network() as net:
|
||||
plugin_ref = self._get_plugin_ref()
|
||||
orig = plugin_ref.create_port
|
||||
with mock.patch.object(plugin_ref,
|
||||
'create_port') as patched_plugin:
|
||||
|
||||
def side_effect(*args, **kwargs):
|
||||
return self._do_side_effect(patched_plugin, orig,
|
||||
*args, **kwargs)
|
||||
|
||||
patched_plugin.side_effect = side_effect
|
||||
res = self._create_port_bulk('json', 2, net['network']['id'],
|
||||
'test', True, context=ctx)
|
||||
# We expect a 500 as we injected a fault in the plugin
|
||||
self._validate_behavior_on_bulk_failure(res, 'ports')
|
||||
|
||||
|
||||
class TestNetworksV2(NetworkPluginV2TestCase, test_db_plugin.TestNetworksV2):
|
||||
|
||||
pass
|
||||
def test_create_networks_bulk_emulated_plugin_failure(self):
|
||||
real_has_attr = hasattr
|
||||
|
||||
def fakehasattr(item, attr):
|
||||
if attr.endswith('__native_bulk_support'):
|
||||
return False
|
||||
return real_has_attr(item, attr)
|
||||
|
||||
plugin_ref = self._get_plugin_ref()
|
||||
orig = plugin_ref.create_network
|
||||
#ensures the API choose the emulation code path
|
||||
with mock.patch('__builtin__.hasattr',
|
||||
new=fakehasattr):
|
||||
with mock.patch.object(plugin_ref,
|
||||
'create_network') as patched_plugin:
|
||||
def side_effect(*args, **kwargs):
|
||||
return self._do_side_effect(patched_plugin, orig,
|
||||
*args, **kwargs)
|
||||
patched_plugin.side_effect = side_effect
|
||||
res = self._create_network_bulk('json', 2, 'test', True)
|
||||
LOG.debug("response is %s" % res)
|
||||
# We expect a 500 as we injected a fault in the plugin
|
||||
self._validate_behavior_on_bulk_failure(res, 'networks')
|
||||
|
||||
def test_create_networks_bulk_native_plugin_failure(self):
|
||||
if self._skip_native_bulk:
|
||||
self.skipTest("Plugin does not support native bulk network create")
|
||||
plugin_ref = self._get_plugin_ref()
|
||||
orig = plugin_ref.create_network
|
||||
with mock.patch.object(plugin_ref,
|
||||
'create_network') as patched_plugin:
|
||||
|
||||
def side_effect(*args, **kwargs):
|
||||
return self._do_side_effect(patched_plugin, orig,
|
||||
*args, **kwargs)
|
||||
|
||||
patched_plugin.side_effect = side_effect
|
||||
res = self._create_network_bulk('json', 2, 'test', True)
|
||||
# We expect a 500 as we injected a fault in the plugin
|
||||
self._validate_behavior_on_bulk_failure(res, 'networks')
|
||||
|
||||
|
||||
class TestSubnetsV2(NetworkPluginV2TestCase, test_db_plugin.TestSubnetsV2):
|
||||
|
||||
pass
|
||||
def test_create_subnets_bulk_emulated_plugin_failure(self):
|
||||
real_has_attr = hasattr
|
||||
|
||||
#ensures the API choose the emulation code path
|
||||
def fakehasattr(item, attr):
|
||||
if attr.endswith('__native_bulk_support'):
|
||||
return False
|
||||
return real_has_attr(item, attr)
|
||||
|
||||
with mock.patch('__builtin__.hasattr',
|
||||
new=fakehasattr):
|
||||
plugin_ref = self._get_plugin_ref()
|
||||
orig = plugin_ref.create_subnet
|
||||
with mock.patch.object(plugin_ref,
|
||||
'create_subnet') as patched_plugin:
|
||||
|
||||
def side_effect(*args, **kwargs):
|
||||
self._do_side_effect(patched_plugin, orig,
|
||||
*args, **kwargs)
|
||||
|
||||
patched_plugin.side_effect = side_effect
|
||||
with self.network() as net:
|
||||
res = self._create_subnet_bulk('json', 2,
|
||||
net['network']['id'],
|
||||
'test')
|
||||
# We expect a 500 as we injected a fault in the plugin
|
||||
self._validate_behavior_on_bulk_failure(res, 'subnets')
|
||||
|
||||
def test_create_subnets_bulk_native_plugin_failure(self):
|
||||
if self._skip_native_bulk:
|
||||
self.skipTest("Plugin does not support native bulk subnet create")
|
||||
plugin_ref = self._get_plugin_ref()
|
||||
orig = plugin_ref.create_subnet
|
||||
with mock.patch.object(plugin_ref,
|
||||
'create_subnet') as patched_plugin:
|
||||
def side_effect(*args, **kwargs):
|
||||
return self._do_side_effect(patched_plugin, orig,
|
||||
*args, **kwargs)
|
||||
|
||||
patched_plugin.side_effect = side_effect
|
||||
with self.network() as net:
|
||||
res = self._create_subnet_bulk('json', 2,
|
||||
net['network']['id'],
|
||||
'test')
|
||||
|
||||
# We expect a 500 as we injected a fault in the plugin
|
||||
self._validate_behavior_on_bulk_failure(res, 'subnets')
|
||||
|
@ -23,7 +23,7 @@ from quantum.db import api as db
|
||||
|
||||
from quantum.openstack.common import importutils
|
||||
from quantum.plugins.cisco.common import cisco_constants as const
|
||||
from quantum.plugins.cisco.common import cisco_credentials as cred
|
||||
from quantum.plugins.cisco.common import cisco_credentials_v2 as cred
|
||||
from quantum.plugins.cisco.common import cisco_exceptions as cexc
|
||||
from quantum.plugins.cisco.common import cisco_utils as cutil
|
||||
from quantum.plugins.cisco.db import network_db_v2 as cdb
|
||||
|
Loading…
x
Reference in New Issue
Block a user