Merge "Change nexus_dict to accept port lists"

This commit is contained in:
Jenkins 2014-08-29 11:13:10 +00:00 committed by Gerrit Code Review
commit 50ea826f36
3 changed files with 72 additions and 26 deletions

View File

@ -66,12 +66,13 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
host_connections = []
for switch_ip, attr in self._nexus_switches:
if str(attr) == str(host_id):
port_id = self._nexus_switches[switch_ip, attr]
if ':' in port_id:
intf_type, port = port_id.split(':')
else:
intf_type, port = 'ethernet', port_id
host_connections.append((switch_ip, intf_type, port))
for port_id in (
self._nexus_switches[switch_ip, attr].split(',')):
if ':' in port_id:
intf_type, port = port_id.split(':')
else:
intf_type, port = 'ethernet', port_id
host_connections.append((switch_ip, intf_type, port))
if host_connections:
return host_connections
@ -100,18 +101,30 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
vlan_name = cfg.CONF.ml2_cisco.vlan_name_prefix + str(vlan_id)
host_connections = self._get_switch_info(host_id)
# (nexus_port,switch_ip) will be unique in each iteration.
# But switch_ip will repeat if host has >1 connection to same switch.
# So track which switch_ips already have vlan created in this loop.
vlan_already_created = []
for switch_ip, intf_type, nexus_port in host_connections:
# Check to see if this is the first binding to use this vlan on the
# switch/port. Configure switch accordingly.
bindings = nxos_db.get_nexusvlan_binding(vlan_id, switch_ip)
if len(bindings) == 1:
LOG.debug(_("Nexus: create & trunk vlan %s"), vlan_name)
self.driver.create_and_trunk_vlan(
switch_ip, vlan_id, vlan_name, intf_type, nexus_port)
else:
LOG.debug(_("Nexus: trunk vlan %s"), vlan_name)
# The VLAN needs to be created on the switch if no other
# instance has been placed in this VLAN on a different host
# attached to this switch. Search the existing bindings in the
# database. If all the instance_id in the database match the
# current device_id, then create the VLAN, but only once per
# switch_ip. Otherwise, just trunk.
all_bindings = nxos_db.get_nexusvlan_binding(vlan_id, switch_ip)
previous_bindings = [row for row in all_bindings
if row.instance_id != device_id]
if previous_bindings or (switch_ip in vlan_already_created):
LOG.debug("Nexus: trunk vlan %s"), vlan_name
self.driver.enable_vlan_on_trunk_int(switch_ip, vlan_id,
intf_type, nexus_port)
else:
vlan_already_created.append(switch_ip)
LOG.debug("Nexus: create & trunk vlan %s"), vlan_name
self.driver.create_and_trunk_vlan(
switch_ip, vlan_id, vlan_name, intf_type, nexus_port)
def _delete_nxos_db(self, vlan_id, device_id, host_id):
"""Delete the nexus database entry.
@ -135,7 +148,13 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
Called during update postcommit port event.
"""
host_connections = self._get_switch_info(host_id)
# (nexus_port,switch_ip) will be unique in each iteration.
# But switch_ip will repeat if host has >1 connection to same switch.
# So track which switch_ips already have vlan removed in this loop.
vlan_already_removed = []
for switch_ip, intf_type, nexus_port in host_connections:
# if there are no remaining db entries using this vlan on this
# nexus switch port then remove vlan from the switchport trunk.
port_id = '%s:%s' % (intf_type, nexus_port)
@ -151,7 +170,11 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
try:
nxos_db.get_nexusvlan_binding(vlan_id, switch_ip)
except excep.NexusPortBindingNotFound:
self.driver.delete_vlan(switch_ip, vlan_id)
# Do not perform a second time on same switch
if switch_ip not in vlan_already_removed:
self.driver.delete_vlan(switch_ip, vlan_id)
vlan_already_removed.append(switch_ip)
def _is_vm_migration(self, context):
if not context.bound_segment and context.original_bound_segment:

View File

@ -42,6 +42,7 @@ class TestCiscoNexusPluginConfig(base.BaseTestCase):
'ssh_port': [22],
'compute1': ['1/1'],
'compute2': ['1/2'],
'compute5': ['1/3,1/4']
},
'ml2_mech_cisco_nexus:2.2.2.2': {
'username': ['admin'],
@ -49,6 +50,7 @@ class TestCiscoNexusPluginConfig(base.BaseTestCase):
'ssh_port': [22],
'compute3': ['1/1'],
'compute4': ['1/2'],
'compute5': ['portchannel:20,portchannel:30']
},
}
expected_dev_dict = {
@ -57,11 +59,13 @@ class TestCiscoNexusPluginConfig(base.BaseTestCase):
('1.1.1.1', 'ssh_port'): 22,
('1.1.1.1', 'compute1'): '1/1',
('1.1.1.1', 'compute2'): '1/2',
('1.1.1.1', 'compute5'): '1/3,1/4',
('2.2.2.2', 'username'): 'admin',
('2.2.2.2', 'password'): 'mySecretPassword',
('2.2.2.2', 'ssh_port'): 22,
('2.2.2.2', 'compute3'): '1/1',
('2.2.2.2', 'compute4'): '1/2',
('2.2.2.2', 'compute5'): 'portchannel:20,portchannel:30',
}
with mock.patch.object(cfg, 'MultiConfigParser') as parser:
parser.return_value.read.return_value = cfg.CONF.config_file

View File

@ -31,18 +31,23 @@ from neutron.tests.unit import testlib_api
NEXUS_IP_ADDRESS = '1.1.1.1'
NEXUS_IP_ADDRESS_PC = '2.2.2.2'
NEXUS_IP_ADDRESS_DUAL = '3.3.3.3'
HOST_NAME_1 = 'testhost1'
HOST_NAME_2 = 'testhost2'
HOST_NAME_PC = 'testpchost'
HOST_NAME_DUAL = 'testdualhost'
INSTANCE_1 = 'testvm1'
INSTANCE_2 = 'testvm2'
INSTANCE_PC = 'testpcvm'
INSTANCE_DUAL = 'testdualvm'
NEXUS_PORT_1 = 'ethernet:1/10'
NEXUS_PORT_2 = 'ethernet:1/20'
NEXUS_PORTCHANNELS = 'portchannel:2'
NEXUS_DUAL = 'ethernet:1/3,portchannel:2'
VLAN_ID_1 = 267
VLAN_ID_2 = 265
VLAN_ID_PC = 268
VLAN_ID_DUAL = 269
DEVICE_OWNER = 'compute:test'
NEXUS_SSH_PORT = '22'
PORT_STATE = n_const.PORT_STATUS_ACTIVE
@ -119,6 +124,12 @@ class TestCiscoNexusDevice(testlib_api.SqlTestCase):
NEXUS_PORTCHANNELS,
INSTANCE_PC,
VLAN_ID_PC),
'test_config_dual': TestConfigObj(
NEXUS_IP_ADDRESS_DUAL,
HOST_NAME_DUAL,
NEXUS_DUAL,
INSTANCE_DUAL,
VLAN_ID_DUAL),
}
def setUp(self):
@ -169,19 +180,22 @@ class TestCiscoNexusDevice(testlib_api.SqlTestCase):
self._cisco_mech_driver.update_port_precommit(port_context)
self._cisco_mech_driver.update_port_postcommit(port_context)
bindings = nexus_db_v2.get_nexusport_binding(nexus_port,
vlan_id,
nexus_ip_addr,
instance_id)
self.assertEqual(len(bindings), 1)
for port_id in nexus_port.split(','):
bindings = nexus_db_v2.get_nexusport_binding(port_id,
vlan_id,
nexus_ip_addr,
instance_id)
self.assertEqual(len(bindings), 1)
self._cisco_mech_driver.delete_port_precommit(port_context)
self._cisco_mech_driver.delete_port_postcommit(port_context)
with testtools.ExpectedException(exceptions.NexusPortBindingNotFound):
nexus_db_v2.get_nexusport_binding(nexus_port,
vlan_id,
nexus_ip_addr,
instance_id)
for port_id in nexus_port.split(','):
with testtools.ExpectedException(
exceptions.NexusPortBindingNotFound):
nexus_db_v2.get_nexusport_binding(port_id,
vlan_id,
nexus_ip_addr,
instance_id)
def test_create_delete_ports(self):
"""Tests creation and deletion of two new virtual Ports."""
@ -195,3 +209,8 @@ class TestCiscoNexusDevice(testlib_api.SqlTestCase):
"""Tests creation of a port over a portchannel."""
self._create_delete_port(
TestCiscoNexusDevice.test_configs['test_config_portchannel'])
def test_create_delete_dual(self):
"""Tests creation and deletion of dual ports for single server"""
self._create_delete_port(
TestCiscoNexusDevice.test_configs['test_config_dual'])