Merge "Round-robin SVI switch selection fails on Cisco Nexus plugin"

This commit is contained in:
Jenkins 2013-11-17 18:04:00 +00:00 committed by Gerrit Code Review
commit 19e38dc7ed
5 changed files with 77 additions and 5 deletions

View File

@ -106,6 +106,13 @@ CISCO_PLUGINS = cfg.CONF.CISCO_PLUGINS
#
device_dictionary = {}
#
# first_device_ip - IP address of first switch discovered in config
#
# Used for SVI placement when round-robin placement is disabled
#
first_device_ip = None
class CiscoConfigOptions():
"""Cisco Configuration Options Class."""
@ -119,17 +126,22 @@ class CiscoConfigOptions():
device supported sections. Ex. NEXUS_SWITCH, N1KV.
"""
global first_device_ip
multi_parser = cfg.MultiConfigParser()
read_ok = multi_parser.read(CONF.config_file)
if len(read_ok) != len(CONF.config_file):
raise cfg.Error(_("Some config files were not parsed properly"))
first_device_ip = None
for parsed_file in multi_parser.parsed:
for parsed_item in parsed_file.keys():
dev_id, sep, dev_ip = parsed_item.partition(':')
if dev_id.lower() in ['nexus_switch', 'n1kv']:
for dev_key, value in parsed_file[parsed_item].items():
if dev_ip and not first_device_ip:
first_device_ip = dev_ip
device_dictionary[dev_id, dev_ip, dev_key] = value[0]

View File

@ -228,15 +228,14 @@ class NexusPlugin(L2DevicePluginBase):
switch_dict[switch_ip] += 1
# Search for the lowest value in the dict
if switch_dict:
switch_ip = min(switch_dict.items(), key=switch_dict.get)
return switch_ip[0]
switch_ip = min(switch_dict, key=switch_dict.get)
return switch_ip
except cisco_exc.NexusPortBindingNotFound:
pass
LOG.debug(_("No round robin or zero weights, using first switch"))
# Return the first switch in the config
for switch_ip, attr in nexus_switches:
return switch_ip
return conf.first_device_ip
def delete_network(self, tenant_id, net_id, **kwargs):
"""Delete network.

View File

@ -127,6 +127,12 @@ class CiscoNetworkPluginV2TestCase(test_db_plugin.NeutronDbPluginV2TestCase):
super(CiscoNetworkPluginV2TestCase, self).setUp(CORE_PLUGIN)
self.port_create_status = 'DOWN'
# Set Cisco config module's first configured Nexus IP address.
# Used for SVI placement when round-robin placement is disabled.
mock.patch.object(cisco_config, 'first_device_ip',
new=NEXUS_IP_ADDR).start()
self.addCleanup(mock.patch.stopall)
def _get_plugin_ref(self):
plugin_obj = NeutronManager.get_plugin()
if getattr(plugin_obj, "_master"):

View File

@ -14,11 +14,14 @@
# under the License.
import collections
import mock
import testtools
from neutron.db import api as db
from neutron.plugins.cisco.common import cisco_exceptions as c_exc
from neutron.plugins.cisco.common import config
from neutron.plugins.cisco.db import nexus_db_v2 as nxdb
from neutron.plugins.cisco.nexus import cisco_nexus_plugin_v2
from neutron.tests import base
@ -166,6 +169,52 @@ class CiscoNexusDbTest(base.BaseTestCase):
npb_svi = nxdb.get_nexussvi_bindings()
self.assertEqual(len(npb_svi), 2)
def test_nexussviswitch_find(self):
"""Test Nexus switch selection for SVI placement."""
# Configure 2 Nexus switches
nexus_switches = {
('1.1.1.1', 'username'): 'admin',
('1.1.1.1', 'password'): 'password1',
('1.1.1.1', 'host1'): '1/1',
('2.2.2.2', 'username'): 'admin',
('2.2.2.2', 'password'): 'password2',
('2.2.2.2', 'host2'): '1/1',
}
nexus_plugin = cisco_nexus_plugin_v2.NexusPlugin()
nexus_plugin._client = mock.Mock()
nexus_plugin._client.nexus_switches = nexus_switches
# Set the Cisco config module's first configured device IP address
# according to the preceding switch config
with mock.patch.object(config, 'first_device_ip', new='1.1.1.1'):
# Enable round-robin mode with no SVIs configured on any of the
# Nexus switches (i.e. no entries in the SVI database). The
# plugin should select the first switch in the configuration.
config.CONF.set_override('svi_round_robin', True, 'CISCO')
switch_ip = nexus_plugin._find_switch_for_svi()
self.assertEqual(switch_ip, '1.1.1.1')
# Keep round-robin mode enabled, and add entries to the SVI
# database. The plugin should select the switch with the least
# number of entries in the SVI database.
vlan = 100
npbr11 = self._npb_test_obj('router', vlan, switch='1.1.1.1',
instance='instance11')
npbr12 = self._npb_test_obj('router', vlan, switch='1.1.1.1',
instance='instance12')
npbr21 = self._npb_test_obj('router', vlan, switch='2.2.2.2',
instance='instance21')
self._add_to_db([npbr11, npbr12, npbr21])
switch_ip = nexus_plugin._find_switch_for_svi()
self.assertEqual(switch_ip, '2.2.2.2')
# Disable round-robin mode. The plugin should select the
# first switch in the configuration.
config.CONF.clear_override('svi_round_robin', 'CISCO')
switch_ip = nexus_plugin._find_switch_for_svi()
self.assertEqual(switch_ip, '1.1.1.1')
def test_nexusbinding_update(self):
npb11 = self._npb_test_obj(10, 100, switch='1.1.1.1', instance='test')
npb21 = self._npb_test_obj(20, 100, switch='1.1.1.1', instance='test')

View File

@ -22,6 +22,7 @@ from neutron.extensions import providernet as provider
from neutron.openstack.common import importutils
from neutron.plugins.cisco.common import cisco_constants as const
from neutron.plugins.cisco.common import cisco_exceptions as cisco_exc
from neutron.plugins.cisco.common import config as cisco_config
from neutron.plugins.cisco.db import network_db_v2 as cdb
from neutron.plugins.cisco.nexus import cisco_nexus_plugin_v2
from neutron.tests import base
@ -146,12 +147,17 @@ class TestCiscoNexusPlugin(base.BaseTestCase):
self.patch_obj = mock.patch.dict('sys.modules',
{'ncclient': self.mock_ncclient})
self.patch_obj.start()
self.addCleanup(self.patch_obj.stop)
with mock.patch.object(cisco_nexus_plugin_v2.NexusPlugin,
'__init__', new=new_nexus_init):
self._cisco_nexus_plugin = cisco_nexus_plugin_v2.NexusPlugin()
self.addCleanup(self.patch_obj.stop)
# Set the Cisco config module's first configured device IP address
# according to the preceding switch config.
mock.patch.object(cisco_config, 'first_device_ip',
new=NEXUS_IP_ADDRESS).start()
self.addCleanup(mock.patch.stopall)
def test_create_delete_networks(self):
"""Tests creation of two new Virtual Networks."""