From 0109cc967c0a8adb9073b6e89276312cb5a95bc4 Mon Sep 17 00:00:00 2001 From: Arvind Somya Date: Tue, 28 May 2013 12:47:09 -0700 Subject: [PATCH] Adding VPC support to the Cisco plugin Adding VPC(Virtual Port Channel) support to the Cisco plugin. Change-Id: I898e4355d05f6f43593deb2d977dfc1e55fb2fc8 Implements: Blueprint cisco-plugin-vpc-support --- neutron/plugins/cisco/db/nexus_db_v2.py | 7 +- .../plugins/cisco/models/virt_phy_sw_v2.py | 3 +- .../nexus/cisco_nexus_network_driver_v2.py | 30 ++-- .../cisco/nexus/cisco_nexus_plugin_v2.py | 155 ++++++++++-------- .../cisco/nexus/cisco_nexus_snippets.py | 17 +- .../cisco/test/nexus/fake_nexus_driver.py | 2 +- .../tests/unit/cisco/test_network_plugin.py | 4 +- neutron/tests/unit/cisco/test_nexus_db.py | 6 +- neutron/tests/unit/cisco/test_nexus_plugin.py | 69 +++++++- 9 files changed, 185 insertions(+), 108 deletions(-) diff --git a/neutron/plugins/cisco/db/nexus_db_v2.py b/neutron/plugins/cisco/db/nexus_db_v2.py index 6ee7ca911..a11a8a041 100644 --- a/neutron/plugins/cisco/db/nexus_db_v2.py +++ b/neutron/plugins/cisco/db/nexus_db_v2.py @@ -86,11 +86,12 @@ def update_nexusport_binding(port_id, new_vlan_id): return binding -def get_nexusvm_binding(vlan_id, instance_id): +def get_nexusvm_bindings(vlan_id, instance_id): """Lists nexusvm bindings.""" LOG.debug(_("get_nexusvm_binding() called")) - return _lookup_first_nexus_binding(instance_id=instance_id, - vlan_id=vlan_id) + + return _lookup_all_nexus_bindings(vlan_id=vlan_id, + instance_id=instance_id) def get_port_vlan_switch_binding(port_id, vlan_id, switch_ip): diff --git a/neutron/plugins/cisco/models/virt_phy_sw_v2.py b/neutron/plugins/cisco/models/virt_phy_sw_v2.py index f3c49eec1..4b42a095f 100644 --- a/neutron/plugins/cisco/models/virt_phy_sw_v2.py +++ b/neutron/plugins/cisco/models/virt_phy_sw_v2.py @@ -406,7 +406,8 @@ class VirtualPhysicalSwitchModelV2(neutron_plugin_base_v2.NeutronPluginBaseV2): """ LOG.debug(_("delete_port() called")) port = self.get_port(context, id) - if self.config_nexus: + exclude_list = ('', 'compute:none', 'network:dhcp') + if self.config_nexus and port['device_owner'] not in exclude_list: vlan_id = self._get_segmentation_id(port['network_id']) n_args = [port['device_id'], vlan_id] self._invoke_plugin_per_device(const.NEXUS_PLUGIN, diff --git a/neutron/plugins/cisco/nexus/cisco_nexus_network_driver_v2.py b/neutron/plugins/cisco/nexus/cisco_nexus_network_driver_v2.py index 645d91400..bb0f8e6de 100644 --- a/neutron/plugins/cisco/nexus/cisco_nexus_network_driver_v2.py +++ b/neutron/plugins/cisco/nexus/cisco_nexus_network_driver_v2.py @@ -151,53 +151,57 @@ class CiscoNEXUSDriver(): confstr = self.create_xml_snippet(confstr) self._edit_config(nexus_host, target='running', config=confstr) - def enable_port_trunk(self, nexus_host, interface): + def enable_port_trunk(self, nexus_host, etype, interface): """Enable trunk mode an interface on Nexus Switch.""" - confstr = snipp.CMD_PORT_TRUNK % (interface) + confstr = snipp.CMD_PORT_TRUNK % (etype, interface, etype) confstr = self.create_xml_snippet(confstr) LOG.debug(_("NexusDriver: %s"), confstr) self._edit_config(nexus_host, target='running', config=confstr) - def disable_switch_port(self, nexus_host, interface): + def disable_switch_port(self, nexus_host, etype, interface): """Disable trunk mode an interface on Nexus Switch.""" - confstr = snipp.CMD_NO_SWITCHPORT % (interface) + confstr = snipp.CMD_NO_SWITCHPORT % (etype, interface, etype) confstr = self.create_xml_snippet(confstr) LOG.debug(_("NexusDriver: %s"), confstr) self._edit_config(nexus_host, target='running', config=confstr) - def enable_vlan_on_trunk_int(self, nexus_host, vlanid, interface): + def enable_vlan_on_trunk_int(self, nexus_host, vlanid, etype, interface): """Enable a VLAN on a trunk interface.""" # If one or more VLANs are already configured on this interface, # include the 'add' keyword. - if nexus_db_v2.get_port_switch_bindings(interface, nexus_host): + if nexus_db_v2.get_port_switch_bindings('%s:%s' % (etype, interface), + nexus_host): snippet = snipp.CMD_INT_VLAN_ADD_SNIPPET else: snippet = snipp.CMD_INT_VLAN_SNIPPET - confstr = snippet % (interface, vlanid) + confstr = snippet % (etype, interface, vlanid, etype) confstr = self.create_xml_snippet(confstr) LOG.debug(_("NexusDriver: %s"), confstr) self._edit_config(nexus_host, target='running', config=confstr) - def disable_vlan_on_trunk_int(self, nexus_host, vlanid, interface): + def disable_vlan_on_trunk_int(self, nexus_host, vlanid, etype, interface): """Disable a VLAN on a trunk interface.""" - confstr = snipp.CMD_NO_VLAN_INT_SNIPPET % (interface, vlanid) + confstr = snipp.CMD_NO_VLAN_INT_SNIPPET % (etype, interface, + vlanid, etype) confstr = self.create_xml_snippet(confstr) LOG.debug(_("NexusDriver: %s"), confstr) self._edit_config(nexus_host, target='running', config=confstr) def create_and_trunk_vlan(self, nexus_host, vlan_id, vlan_name, - nexus_port): + etype, nexus_port): """Create VLAN and trunk it on the specified ports.""" self.create_vlan(nexus_host, vlan_id, vlan_name) LOG.debug(_("NexusDriver created VLAN: %s"), vlan_id) if nexus_port: - self.enable_vlan_on_trunk_int(nexus_host, vlan_id, nexus_port) + self.enable_vlan_on_trunk_int(nexus_host, vlan_id, + etype, nexus_port) - def delete_and_untrunk_vlan(self, nexus_host, vlan_id, nexus_port): + def delete_and_untrunk_vlan(self, nexus_host, vlan_id, etype, nexus_port): """Delete VLAN and untrunk it from the specified ports.""" self.delete_vlan(nexus_host, vlan_id) if nexus_port: - self.disable_vlan_on_trunk_int(nexus_host, vlan_id, nexus_port) + self.disable_vlan_on_trunk_int(nexus_host, vlan_id, + etype, nexus_port) def create_vlan_svi(self, nexus_host, vlan_id, gateway_ip): confstr = snipp.CMD_VLAN_SVI_SNIPPET % (vlan_id, gateway_ip) diff --git a/neutron/plugins/cisco/nexus/cisco_nexus_plugin_v2.py b/neutron/plugins/cisco/nexus/cisco_nexus_plugin_v2.py index 68b8bbf12..4f700b46c 100644 --- a/neutron/plugins/cisco/nexus/cisco_nexus_plugin_v2.py +++ b/neutron/plugins/cisco/nexus/cisco_nexus_plugin_v2.py @@ -48,6 +48,7 @@ class NexusPlugin(L2DevicePluginBase): """Extract configuration parameters from the configuration file.""" self._client = importutils.import_object(conf.CISCO.nexus_driver) LOG.debug(_("Loaded driver %s"), conf.CISCO.nexus_driver) + self._nexus_switches = conf.get_device_dictionary() def get_all_networks(self, tenant_id): """Get all networks. @@ -71,10 +72,20 @@ class NexusPlugin(L2DevicePluginBase): appropriate interfaces for this VLAN. """ LOG.debug(_("NexusPlugin:create_network() called")) - # Grab the switch IP and port for this host - host = str(attachment[const.HOST_NAME]) - switch_ip, port_id = self._client.get_switch_and_port_id(host) - if not switch_ip and not port_id: + # Grab the switch IPs and ports for this host + host_connections = [] + host = attachment['host_name'] + for switch_type, switch_ip, attr in self._nexus_switches: + if str(attr) == str(host): + port = self._nexus_switches[switch_type, switch_ip, attr] + # Get ether type for port, assume an ethernet type + # if none specified. + if ':' in port: + etype, port_id = port.split(':') + else: + etype, port_id = 'ethernet', port + host_connections.append((switch_ip, etype, port_id)) + if not host_connections: raise cisco_exc.NexusComputeHostNotConfigured(host=host) vlan_id = network[const.NET_VLAN_ID] @@ -88,21 +99,19 @@ class NexusPlugin(L2DevicePluginBase): auto_trunk = conf.CISCO.provider_vlan_auto_trunk # Check if this network is already in the DB - vlan_created = False - vlan_trunked = False - - try: - nxos_db.get_port_vlan_switch_binding(port_id, vlan_id, switch_ip) - except cisco_exc.NexusPortBindingNotFound: - # Check for vlan/switch binding + for switch_ip, etype, port_id in host_connections: + vlan_created = False + vlan_trunked = False + eport_id = '%s:%s' % (etype, port_id) try: - nxos_db.get_nexusvlan_binding(vlan_id, switch_ip) + nxos_db.get_port_vlan_switch_binding(eport_id, vlan_id, + switch_ip) except cisco_exc.NexusPortBindingNotFound: if auto_create and auto_trunk: # Create vlan and trunk vlan on the port LOG.debug("Nexus: create & trunk vlan %s" % vlan_name) self._client.create_and_trunk_vlan( - switch_ip, vlan_id, vlan_name, port_id) + switch_ip, vlan_id, vlan_name, etype, port_id) vlan_created = True vlan_trunked = True elif auto_create: @@ -110,32 +119,35 @@ class NexusPlugin(L2DevicePluginBase): LOG.debug("Nexus: create vlan %s" % vlan_name) self._client.create_vlan(switch_ip, vlan_id, vlan_name) vlan_created = True - else: - if auto_trunk: + elif auto_trunk: # Only trunk vlan on the port LOG.debug("Nexus: trunk vlan %s" % vlan_name) self._client.enable_vlan_on_trunk_int( - switch_ip, vlan_id, port_id) + switch_ip, vlan_id, etype, port_id) vlan_trunked = True - try: - instance = attachment[const.INSTANCE_ID] - nxos_db.add_nexusport_binding(port_id, str(vlan_id), - switch_ip, instance) - except Exception: - with excutils.save_and_reraise_exception(): - # Add binding failed, roll back any vlan creation/enabling - if vlan_created and vlan_trunked: - LOG.debug("Nexus: delete & untrunk vlan %s" % vlan_name) - self._client.delete_and_untrunk_vlan(switch_ip, vlan_id, - port_id) - elif vlan_created: - LOG.debug("Nexus: delete vlan %s" % vlan_name) - self._client.delete_vlan(switch_ip, vlan_id) - elif vlan_trunked: - LOG.debug("Nexus: untrunk vlan %s" % vlan_name) - self._client.disable_vlan_on_trunk_int(switch_ip, vlan_id, - port_id) + try: + instance = attachment[const.INSTANCE_ID] + nxos_db.add_nexusport_binding(eport_id, str(vlan_id), + switch_ip, instance) + except Exception: + with excutils.save_and_reraise_exception(): + # Add binding failed, roll back any vlan creation/enabling + if vlan_created and vlan_trunked: + LOG.debug("Nexus: delete & untrunk vlan %s" % + vlan_name) + self._client.delete_and_untrunk_vlan(switch_ip, + vlan_id, + etype, port_id) + elif vlan_created: + LOG.debug("Nexus: delete vlan %s" % vlan_name) + self._client.delete_vlan(switch_ip, vlan_id) + elif vlan_trunked: + LOG.debug("Nexus: untrunk vlan %s" % vlan_name) + self._client.disable_vlan_on_trunk_int(switch_ip, + vlan_id, + etype, + port_id) net_id = network[const.NET_ID] new_net_dict = {const.NET_ID: net_id, @@ -160,10 +172,10 @@ class NexusPlugin(L2DevicePluginBase): except cisco_exc.NexusPortBindingNotFound: # Create vlan and trunk vlan on the port self._client.create_and_trunk_vlan( - switch_ip, vlan_id, vlan_name, nexus_port=None) + switch_ip, vlan_id, vlan_name, etype=None, nexus_port=None) # Check if a router interface has already been created try: - nxos_db.get_nexusvm_binding(vlan_id, router_id) + nxos_db.get_nexusvm_bindings(vlan_id, router_id) raise cisco_exc.SubnetInterfacePresent(subnet_id=subnet_id, router_id=router_id) except cisco_exc.NexusPortBindingNotFound: @@ -176,8 +188,8 @@ class NexusPlugin(L2DevicePluginBase): def remove_router_interface(self, vlan_id, router_id): """Remove VLAN SVI from the Nexus Switch.""" # Grab switch_ip from database - switch_ip = nxos_db.get_nexusvm_binding(vlan_id, - router_id).switch_ip + switch_ip = nxos_db.get_nexusvm_bindings(vlan_id, + router_id)[0].switch_ip # Delete the SVI interface from the switch self._client.delete_vlan_svi(switch_ip, vlan_id) @@ -250,9 +262,9 @@ class NexusPlugin(L2DevicePluginBase): is still required on the interfaces trunked. """ LOG.debug(_("NexusPlugin:delete_port() called")) - # Delete DB row for this port + # Delete DB row(s) for this port try: - row = nxos_db.get_nexusvm_binding(vlan_id, device_id) + rows = nxos_db.get_nexusvm_bindings(vlan_id, device_id) except cisco_exc.NexusPortBindingNotFound: return @@ -263,37 +275,42 @@ class NexusPlugin(L2DevicePluginBase): auto_untrunk = conf.CISCO.provider_vlan_auto_trunk LOG.debug("delete_network(): provider vlan %s" % vlan_id) - switch_ip = row.switch_ip - nexus_port = None - if row.port_id != 'router': - nexus_port = row.port_id + instance_id = False + for row in rows: + instance_id = row['instance_id'] + switch_ip = row.switch_ip + etype, nexus_port = '', '' + if row['port_id'] == 'router': + etype, nexus_port = 'vlan', row['port_id'] + else: + etype, nexus_port = row['port_id'].split(':') - nxos_db.remove_nexusport_binding(row.port_id, row.vlan_id, - row.switch_ip, - row.instance_id) - # Check for any other bindings with the same vlan_id and switch_ip - try: - nxos_db.get_nexusvlan_binding(row.vlan_id, row.switch_ip) - except cisco_exc.NexusPortBindingNotFound: + nxos_db.remove_nexusport_binding(row.port_id, row.vlan_id, + row.switch_ip, + row.instance_id) + # Check for any other bindings with the same vlan_id and switch_ip try: - # Delete this vlan from this switch - if nexus_port and auto_untrunk: - self._client.disable_vlan_on_trunk_int( - switch_ip, row.vlan_id, nexus_port) - if auto_delete: - self._client.delete_vlan(switch_ip, row.vlan_id) - except Exception: - # The delete vlan operation on the Nexus failed, - # so this delete_port request has failed. For - # consistency, roll back the Nexus database to what - # it was before this request. - with excutils.save_and_reraise_exception(): - nxos_db.add_nexusport_binding(row.port_id, - row.vlan_id, - row.switch_ip, - row.instance_id) - - return row.instance_id + nxos_db.get_nexusvlan_binding(row.vlan_id, row.switch_ip) + except cisco_exc.NexusPortBindingNotFound: + try: + # Delete this vlan from this switch + if nexus_port and auto_untrunk: + self._client.disable_vlan_on_trunk_int( + switch_ip, row.vlan_id, etype, nexus_port) + if auto_delete: + self._client.delete_vlan(switch_ip, row.vlan_id) + except Exception: + # The delete vlan operation on the Nexus failed, + # so this delete_port request has failed. For + # consistency, roll back the Nexus database to what + # it was before this request. + with excutils.save_and_reraise_exception(): + nxos_db.add_nexusport_binding(row.port_id, + row.vlan_id, + row.switch_ip, + row.instance_id) + + return instance_id def update_port(self, tenant_id, net_id, port_id, port_state, **kwargs): """Update port. diff --git a/neutron/plugins/cisco/nexus/cisco_nexus_snippets.py b/neutron/plugins/cisco/nexus/cisco_nexus_snippets.py index cf7f6332f..831462154 100644 --- a/neutron/plugins/cisco/nexus/cisco_nexus_snippets.py +++ b/neutron/plugins/cisco/nexus/cisco_nexus_snippets.py @@ -15,6 +15,7 @@ # under the License. # # @author: Edgar Magana, Cisco Systems, Inc. +# @author: Arvind Somya (asomya@cisco.com) Cisco Systems, Inc. """ Nexus-OS XML-based configuration snippets @@ -88,7 +89,7 @@ CMD_NO_VLAN_CONF_SNIPPET = """ CMD_INT_VLAN_HEADER = """ - + <%s> %s <__XML__MODE_if-ethernet-switch> @@ -109,7 +110,7 @@ CMD_INT_VLAN_TRAILER = """ - + """ @@ -123,7 +124,7 @@ CMD_INT_VLAN_ADD_SNIPPET = (CMD_INT_VLAN_HEADER + CMD_PORT_TRUNK = """ - + <%s> %s <__XML__MODE_if-ethernet-switch> @@ -134,13 +135,13 @@ CMD_PORT_TRUNK = """ - + """ CMD_NO_SWITCHPORT = """ - + <%s> %s <__XML__MODE_if-ethernet-switch> @@ -148,14 +149,14 @@ CMD_NO_SWITCHPORT = """ - + """ CMD_NO_VLAN_INT_SNIPPET = """ - + <%s> %s <__XML__MODE_if-ethernet-switch> @@ -171,7 +172,7 @@ CMD_NO_VLAN_INT_SNIPPET = """ - + """ diff --git a/neutron/plugins/cisco/test/nexus/fake_nexus_driver.py b/neutron/plugins/cisco/test/nexus/fake_nexus_driver.py index 0841d363e..e56b4866e 100644 --- a/neutron/plugins/cisco/test/nexus/fake_nexus_driver.py +++ b/neutron/plugins/cisco/test/nexus/fake_nexus_driver.py @@ -53,7 +53,7 @@ class CiscoNEXUSFakeDriver(): """Disable trunk mode an interface on Nexus Switch.""" pass - def enable_vlan_on_trunk_int(self, mgr, interface, vlanid): + def enable_vlan_on_trunk_int(self, mgr, etype, interface, vlanid): """Enable vlan on trunk interface. Enable trunk mode vlan access an interface on Nexus Switch given diff --git a/neutron/tests/unit/cisco/test_network_plugin.py b/neutron/tests/unit/cisco/test_network_plugin.py index dcb982664..656f00861 100644 --- a/neutron/tests/unit/cisco/test_network_plugin.py +++ b/neutron/tests/unit/cisco/test_network_plugin.py @@ -184,7 +184,9 @@ class TestCiscoPortsV2(CiscoNetworkPluginV2TestCase, with self.network(name=name) as network: with self.subnet(network=network, cidr=cidr) as subnet: net_id = subnet['subnet']['network_id'] - res = self._create_port(self.fmt, net_id) + res = self._create_port(self.fmt, net_id, + device_id='testdev', + device_owner='testowner') port = self.deserialize(self.fmt, res) try: yield res diff --git a/neutron/tests/unit/cisco/test_nexus_db.py b/neutron/tests/unit/cisco/test_nexus_db.py index 712dffd40..023bcc029 100644 --- a/neutron/tests/unit/cisco/test_nexus_db.py +++ b/neutron/tests/unit/cisco/test_nexus_db.py @@ -115,13 +115,13 @@ class CiscoNexusDbTest(base.BaseTestCase): npb22 = self._npb_test_obj(20, 200) self._add_to_db([npb11, npb21, npb22]) - npb = nxdb.get_nexusvm_binding(npb21.vlan, npb21.instance) + npb = nxdb.get_nexusvm_bindings(npb21.vlan, npb21.instance)[0] self._assert_equal(npb, npb21) - npb = nxdb.get_nexusvm_binding(npb22.vlan, npb22.instance) + npb = nxdb.get_nexusvm_bindings(npb22.vlan, npb22.instance)[0] self._assert_equal(npb, npb22) with testtools.ExpectedException(c_exc.NexusPortBindingNotFound): - nxdb.get_nexusvm_binding(npb21.vlan, "dummyInstance") + nxdb.get_nexusvm_bindings(npb21.vlan, "dummyInstance") def test_nexusportvlanswitchbinding_get(self): npb11 = self._npb_test_obj(10, 100) diff --git a/neutron/tests/unit/cisco/test_nexus_plugin.py b/neutron/tests/unit/cisco/test_nexus_plugin.py index cf0c70fe7..a8507797d 100644 --- a/neutron/tests/unit/cisco/test_nexus_plugin.py +++ b/neutron/tests/unit/cisco/test_nexus_plugin.py @@ -30,10 +30,15 @@ from neutron.tests import base NEXUS_IP_ADDRESS = '1.1.1.1' HOSTNAME1 = 'testhost1' HOSTNAME2 = 'testhost2' +HOSTNAME3 = 'testhost3' INSTANCE1 = 'testvm1' INSTANCE2 = 'testvm2' +INSTANCE3 = 'testvm3' NEXUS_PORT1 = '1/10' NEXUS_PORT2 = '1/20' +NEXUS_PC_IP_ADDRESS = '2.2.2.2' +NEXUS_PORTCHANNELS = 'portchannel:2' +PC_HOSTNAME = 'testpchost' NEXUS_SSH_PORT = '22' NEXUS_DRIVER = ('neutron.plugins.cisco.nexus.' 'cisco_nexus_network_driver_v2.CiscoNEXUSDriver') @@ -58,6 +63,8 @@ class TestCiscoNexusPlugin(base.BaseTestCase): self.second_net_id = 5 self.second_vlan_name = "q-" + str(self.second_net_id) + "vlan" self.second_vlan_id = 265 + self._pchostname = PC_HOSTNAME + self.attachment1 = { const.TENANT_ID: self.tenant_id, const.INSTANCE_ID: INSTANCE1, @@ -68,6 +75,11 @@ class TestCiscoNexusPlugin(base.BaseTestCase): const.INSTANCE_ID: INSTANCE2, const.HOST_NAME: HOSTNAME2, } + self.attachment3 = { + const.TENANT_ID: self.second_tenant_id, + const.INSTANCE_ID: INSTANCE3, + const.HOST_NAME: HOSTNAME3, + } self.network1 = { const.NET_ID: self.net_id, const.NET_NAME: self.net_name, @@ -80,6 +92,12 @@ class TestCiscoNexusPlugin(base.BaseTestCase): const.NET_VLAN_NAME: self.second_vlan_name, const.NET_VLAN_ID: self.second_vlan_id, } + self.network3 = { + const.NET_ID: 8, + const.NET_NAME: 'vpc_net', + const.NET_VLAN_NAME: 'q-268', + const.NET_VLAN_ID: '268', + } self.providernet = { const.NET_ID: 9, const.NET_NAME: 'pnet1', @@ -97,12 +115,28 @@ class TestCiscoNexusPlugin(base.BaseTestCase): (NEXUS_IP_ADDRESS, 'ssh_port'): NEXUS_SSH_PORT, (NEXUS_IP_ADDRESS, HOSTNAME2): NEXUS_PORT2, (NEXUS_IP_ADDRESS, 'ssh_port'): NEXUS_SSH_PORT, + (NEXUS_PC_IP_ADDRESS, 'ssh_port'): NEXUS_SSH_PORT, + } + self._nexus_switches = { + ('NEXUS_SWITCH', NEXUS_IP_ADDRESS, HOSTNAME1): NEXUS_PORT1, + ('NEXUS_SWITCH', NEXUS_IP_ADDRESS, HOSTNAME2): NEXUS_PORT2, + ('NEXUS_SWITCH', NEXUS_PC_IP_ADDRESS, HOSTNAME3): + NEXUS_PORTCHANNELS, + ('NEXUS_SWITCH', NEXUS_PC_IP_ADDRESS, 'ssh_port'): + NEXUS_SSH_PORT, + ('NEXUS_SWITCH', NEXUS_IP_ADDRESS, HOSTNAME3): + NEXUS_PORTCHANNELS, + ('NEXUS_SWITCH', NEXUS_IP_ADDRESS, 'ssh_port'): NEXUS_SSH_PORT, } self._client.credentials = { NEXUS_IP_ADDRESS: { 'username': 'admin', 'password': 'pass1234' }, + NEXUS_PC_IP_ADDRESS: { + 'username': 'admin', + 'password': 'password' + }, } db.configure_db() @@ -118,18 +152,28 @@ class TestCiscoNexusPlugin(base.BaseTestCase): self.addCleanup(self.patch_obj.stop) - def test_create_networks(self): + def test_create_delete_networks(self): """Tests creation of two new Virtual Networks.""" new_net_dict = self._cisco_nexus_plugin.create_network( self.network1, self.attachment1) for attr in NET_ATTRS: self.assertEqual(new_net_dict[attr], self.network1[attr]) + expected_instance_id = self._cisco_nexus_plugin.delete_port( + INSTANCE1, self.vlan_id) + + self.assertEqual(expected_instance_id, INSTANCE1) + new_net_dict = self._cisco_nexus_plugin.create_network( self.network2, self.attachment1) for attr in NET_ATTRS: self.assertEqual(new_net_dict[attr], self.network2[attr]) + expected_instance_id = self._cisco_nexus_plugin.delete_port( + INSTANCE1, self.second_vlan_id) + + self.assertEqual(expected_instance_id, INSTANCE1) + def test_create_providernet(self): with mock.patch.object(cdb, 'is_provider_vlan', return_value=True) as mock_db: @@ -169,15 +213,22 @@ class TestCiscoNexusPlugin(base.BaseTestCase): for attr in NET_ATTRS: self.assertEqual(new_net_dict[attr], self.providernet[attr]) - def test_nexus_delete_port(self): - """Test deletion of a vlan.""" - self._cisco_nexus_plugin.create_network( - self.network1, self.attachment1) - - expected_instance_id = self._cisco_nexus_plugin.delete_port( - INSTANCE1, self.vlan_id) + def test_create_delete_network_portchannel(self): + """Tests creation of a network over a portchannel.""" + new_net_dict = self._cisco_nexus_plugin.create_network( + self.network3, self.attachment3) + self.assertEqual(new_net_dict[const.NET_ID], + self.network3[const.NET_ID]) + self.assertEqual(new_net_dict[const.NET_NAME], + self.network3[const.NET_NAME]) + self.assertEqual(new_net_dict[const.NET_VLAN_NAME], + self.network3[const.NET_VLAN_NAME]) + self.assertEqual(new_net_dict[const.NET_VLAN_ID], + self.network3[const.NET_VLAN_ID]) - self.assertEqual(expected_instance_id, INSTANCE1) + self._cisco_nexus_plugin.delete_port( + INSTANCE3, self.network3[const.NET_VLAN_ID] + ) def test_nexus_add_remove_router_interface(self): """Tests addition of a router interface.""" -- 2.45.2