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
This commit is contained in:
Arvind Somya 2013-05-28 12:47:09 -07:00
parent 7095354c81
commit b42405da60
9 changed files with 184 additions and 107 deletions

View File

@ -86,11 +86,12 @@ def update_nexusport_binding(port_id, new_vlan_id):
return binding return binding
def get_nexusvm_binding(vlan_id, instance_id): def get_nexusvm_bindings(vlan_id, instance_id):
"""Lists nexusvm bindings.""" """Lists nexusvm bindings."""
LOG.debug(_("get_nexusvm_binding() called")) 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): def get_port_vlan_switch_binding(port_id, vlan_id, switch_ip):

View File

@ -406,7 +406,8 @@ class VirtualPhysicalSwitchModelV2(neutron_plugin_base_v2.NeutronPluginBaseV2):
""" """
LOG.debug(_("delete_port() called")) LOG.debug(_("delete_port() called"))
port = self.get_port(context, id) 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']) vlan_id = self._get_segmentation_id(port['network_id'])
n_args = [port['device_id'], vlan_id] n_args = [port['device_id'], vlan_id]
self._invoke_plugin_per_device(const.NEXUS_PLUGIN, self._invoke_plugin_per_device(const.NEXUS_PLUGIN,

View File

@ -151,53 +151,57 @@ class CiscoNEXUSDriver():
confstr = self.create_xml_snippet(confstr) confstr = self.create_xml_snippet(confstr)
self._edit_config(nexus_host, target='running', config=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.""" """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) confstr = self.create_xml_snippet(confstr)
LOG.debug(_("NexusDriver: %s"), confstr) LOG.debug(_("NexusDriver: %s"), confstr)
self._edit_config(nexus_host, target='running', config=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.""" """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) confstr = self.create_xml_snippet(confstr)
LOG.debug(_("NexusDriver: %s"), confstr) LOG.debug(_("NexusDriver: %s"), confstr)
self._edit_config(nexus_host, target='running', config=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.""" """Enable a VLAN on a trunk interface."""
# If one or more VLANs are already configured on this interface, # If one or more VLANs are already configured on this interface,
# include the 'add' keyword. # 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 snippet = snipp.CMD_INT_VLAN_ADD_SNIPPET
else: else:
snippet = snipp.CMD_INT_VLAN_SNIPPET snippet = snipp.CMD_INT_VLAN_SNIPPET
confstr = snippet % (interface, vlanid) confstr = snippet % (etype, interface, vlanid, etype)
confstr = self.create_xml_snippet(confstr) confstr = self.create_xml_snippet(confstr)
LOG.debug(_("NexusDriver: %s"), confstr) LOG.debug(_("NexusDriver: %s"), confstr)
self._edit_config(nexus_host, target='running', config=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.""" """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) confstr = self.create_xml_snippet(confstr)
LOG.debug(_("NexusDriver: %s"), confstr) LOG.debug(_("NexusDriver: %s"), confstr)
self._edit_config(nexus_host, target='running', config=confstr) self._edit_config(nexus_host, target='running', config=confstr)
def create_and_trunk_vlan(self, nexus_host, vlan_id, vlan_name, 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.""" """Create VLAN and trunk it on the specified ports."""
self.create_vlan(nexus_host, vlan_id, vlan_name) self.create_vlan(nexus_host, vlan_id, vlan_name)
LOG.debug(_("NexusDriver created VLAN: %s"), vlan_id) LOG.debug(_("NexusDriver created VLAN: %s"), vlan_id)
if nexus_port: 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.""" """Delete VLAN and untrunk it from the specified ports."""
self.delete_vlan(nexus_host, vlan_id) self.delete_vlan(nexus_host, vlan_id)
if nexus_port: 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): def create_vlan_svi(self, nexus_host, vlan_id, gateway_ip):
confstr = snipp.CMD_VLAN_SVI_SNIPPET % (vlan_id, gateway_ip) confstr = snipp.CMD_VLAN_SVI_SNIPPET % (vlan_id, gateway_ip)

View File

@ -48,6 +48,7 @@ class NexusPlugin(L2DevicePluginBase):
"""Extract configuration parameters from the configuration file.""" """Extract configuration parameters from the configuration file."""
self._client = importutils.import_object(conf.CISCO.nexus_driver) self._client = importutils.import_object(conf.CISCO.nexus_driver)
LOG.debug(_("Loaded driver %s"), 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): def get_all_networks(self, tenant_id):
"""Get all networks. """Get all networks.
@ -71,10 +72,20 @@ class NexusPlugin(L2DevicePluginBase):
appropriate interfaces for this VLAN. appropriate interfaces for this VLAN.
""" """
LOG.debug(_("NexusPlugin:create_network() called")) LOG.debug(_("NexusPlugin:create_network() called"))
# Grab the switch IP and port for this host # Grab the switch IPs and ports for this host
host = str(attachment[const.HOST_NAME]) host_connections = []
switch_ip, port_id = self._client.get_switch_and_port_id(host) host = attachment['host_name']
if not switch_ip and not port_id: 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) raise cisco_exc.NexusComputeHostNotConfigured(host=host)
vlan_id = network[const.NET_VLAN_ID] vlan_id = network[const.NET_VLAN_ID]
@ -88,21 +99,19 @@ class NexusPlugin(L2DevicePluginBase):
auto_trunk = conf.CISCO.provider_vlan_auto_trunk auto_trunk = conf.CISCO.provider_vlan_auto_trunk
# Check if this network is already in the DB # Check if this network is already in the DB
vlan_created = False for switch_ip, etype, port_id in host_connections:
vlan_trunked = False vlan_created = False
vlan_trunked = False
try: eport_id = '%s:%s' % (etype, port_id)
nxos_db.get_port_vlan_switch_binding(port_id, vlan_id, switch_ip)
except cisco_exc.NexusPortBindingNotFound:
# Check for vlan/switch binding
try: 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: except cisco_exc.NexusPortBindingNotFound:
if auto_create and auto_trunk: if auto_create and auto_trunk:
# Create vlan and trunk vlan on the port # Create vlan and trunk vlan on the port
LOG.debug("Nexus: create & trunk vlan %s" % vlan_name) LOG.debug("Nexus: create & trunk vlan %s" % vlan_name)
self._client.create_and_trunk_vlan( 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_created = True
vlan_trunked = True vlan_trunked = True
elif auto_create: elif auto_create:
@ -110,32 +119,35 @@ class NexusPlugin(L2DevicePluginBase):
LOG.debug("Nexus: create vlan %s" % vlan_name) LOG.debug("Nexus: create vlan %s" % vlan_name)
self._client.create_vlan(switch_ip, vlan_id, vlan_name) self._client.create_vlan(switch_ip, vlan_id, vlan_name)
vlan_created = True vlan_created = True
else: elif auto_trunk:
if auto_trunk:
# Only trunk vlan on the port # Only trunk vlan on the port
LOG.debug("Nexus: trunk vlan %s" % vlan_name) LOG.debug("Nexus: trunk vlan %s" % vlan_name)
self._client.enable_vlan_on_trunk_int( self._client.enable_vlan_on_trunk_int(
switch_ip, vlan_id, port_id) switch_ip, vlan_id, etype, port_id)
vlan_trunked = True vlan_trunked = True
try: try:
instance = attachment[const.INSTANCE_ID] instance = attachment[const.INSTANCE_ID]
nxos_db.add_nexusport_binding(port_id, str(vlan_id), nxos_db.add_nexusport_binding(eport_id, str(vlan_id),
switch_ip, instance) switch_ip, instance)
except Exception: except Exception:
with excutils.save_and_reraise_exception(): with excutils.save_and_reraise_exception():
# Add binding failed, roll back any vlan creation/enabling # Add binding failed, roll back any vlan creation/enabling
if vlan_created and vlan_trunked: if vlan_created and vlan_trunked:
LOG.debug("Nexus: delete & untrunk vlan %s" % vlan_name) LOG.debug("Nexus: delete & untrunk vlan %s" %
self._client.delete_and_untrunk_vlan(switch_ip, vlan_id, vlan_name)
port_id) self._client.delete_and_untrunk_vlan(switch_ip,
elif vlan_created: vlan_id,
LOG.debug("Nexus: delete vlan %s" % vlan_name) etype, port_id)
self._client.delete_vlan(switch_ip, vlan_id) elif vlan_created:
elif vlan_trunked: LOG.debug("Nexus: delete vlan %s" % vlan_name)
LOG.debug("Nexus: untrunk vlan %s" % vlan_name) self._client.delete_vlan(switch_ip, vlan_id)
self._client.disable_vlan_on_trunk_int(switch_ip, vlan_id, elif vlan_trunked:
port_id) 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] net_id = network[const.NET_ID]
new_net_dict = {const.NET_ID: net_id, new_net_dict = {const.NET_ID: net_id,
@ -160,10 +172,10 @@ class NexusPlugin(L2DevicePluginBase):
except cisco_exc.NexusPortBindingNotFound: except cisco_exc.NexusPortBindingNotFound:
# Create vlan and trunk vlan on the port # Create vlan and trunk vlan on the port
self._client.create_and_trunk_vlan( 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 # Check if a router interface has already been created
try: 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, raise cisco_exc.SubnetInterfacePresent(subnet_id=subnet_id,
router_id=router_id) router_id=router_id)
except cisco_exc.NexusPortBindingNotFound: except cisco_exc.NexusPortBindingNotFound:
@ -176,8 +188,8 @@ class NexusPlugin(L2DevicePluginBase):
def remove_router_interface(self, vlan_id, router_id): def remove_router_interface(self, vlan_id, router_id):
"""Remove VLAN SVI from the Nexus Switch.""" """Remove VLAN SVI from the Nexus Switch."""
# Grab switch_ip from database # Grab switch_ip from database
switch_ip = nxos_db.get_nexusvm_binding(vlan_id, switch_ip = nxos_db.get_nexusvm_bindings(vlan_id,
router_id).switch_ip router_id)[0].switch_ip
# Delete the SVI interface from the switch # Delete the SVI interface from the switch
self._client.delete_vlan_svi(switch_ip, vlan_id) self._client.delete_vlan_svi(switch_ip, vlan_id)
@ -250,9 +262,9 @@ class NexusPlugin(L2DevicePluginBase):
is still required on the interfaces trunked. is still required on the interfaces trunked.
""" """
LOG.debug(_("NexusPlugin:delete_port() called")) LOG.debug(_("NexusPlugin:delete_port() called"))
# Delete DB row for this port # Delete DB row(s) for this port
try: 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: except cisco_exc.NexusPortBindingNotFound:
return return
@ -263,37 +275,42 @@ class NexusPlugin(L2DevicePluginBase):
auto_untrunk = conf.CISCO.provider_vlan_auto_trunk auto_untrunk = conf.CISCO.provider_vlan_auto_trunk
LOG.debug("delete_network(): provider vlan %s" % vlan_id) LOG.debug("delete_network(): provider vlan %s" % vlan_id)
switch_ip = row.switch_ip instance_id = False
nexus_port = None for row in rows:
if row.port_id != 'router': instance_id = row['instance_id']
nexus_port = row.port_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, nxos_db.remove_nexusport_binding(row.port_id, row.vlan_id,
row.switch_ip, row.switch_ip,
row.instance_id) row.instance_id)
# Check for any other bindings with the same vlan_id and switch_ip # 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:
try: try:
# Delete this vlan from this switch nxos_db.get_nexusvlan_binding(row.vlan_id, row.switch_ip)
if nexus_port and auto_untrunk: except cisco_exc.NexusPortBindingNotFound:
self._client.disable_vlan_on_trunk_int( try:
switch_ip, row.vlan_id, nexus_port) # Delete this vlan from this switch
if auto_delete: if nexus_port and auto_untrunk:
self._client.delete_vlan(switch_ip, row.vlan_id) self._client.disable_vlan_on_trunk_int(
except Exception: switch_ip, row.vlan_id, etype, nexus_port)
# The delete vlan operation on the Nexus failed, if auto_delete:
# so this delete_port request has failed. For self._client.delete_vlan(switch_ip, row.vlan_id)
# consistency, roll back the Nexus database to what except Exception:
# it was before this request. # The delete vlan operation on the Nexus failed,
with excutils.save_and_reraise_exception(): # so this delete_port request has failed. For
nxos_db.add_nexusport_binding(row.port_id, # consistency, roll back the Nexus database to what
row.vlan_id, # it was before this request.
row.switch_ip, with excutils.save_and_reraise_exception():
row.instance_id) nxos_db.add_nexusport_binding(row.port_id,
row.vlan_id,
row.switch_ip,
row.instance_id)
return row.instance_id return instance_id
def update_port(self, tenant_id, net_id, port_id, port_state, **kwargs): def update_port(self, tenant_id, net_id, port_id, port_state, **kwargs):
"""Update port. """Update port.

View File

@ -15,6 +15,7 @@
# under the License. # under the License.
# #
# @author: Edgar Magana, Cisco Systems, Inc. # @author: Edgar Magana, Cisco Systems, Inc.
# @author: Arvind Somya (asomya@cisco.com) Cisco Systems, Inc.
""" """
Nexus-OS XML-based configuration snippets Nexus-OS XML-based configuration snippets
@ -88,7 +89,7 @@ CMD_NO_VLAN_CONF_SNIPPET = """
CMD_INT_VLAN_HEADER = """ CMD_INT_VLAN_HEADER = """
<interface> <interface>
<ethernet> <%s>
<interface>%s</interface> <interface>%s</interface>
<__XML__MODE_if-ethernet-switch> <__XML__MODE_if-ethernet-switch>
<switchport> <switchport>
@ -109,7 +110,7 @@ CMD_INT_VLAN_TRAILER = """
</trunk> </trunk>
</switchport> </switchport>
</__XML__MODE_if-ethernet-switch> </__XML__MODE_if-ethernet-switch>
</ethernet> </%s>
</interface> </interface>
""" """
@ -123,7 +124,7 @@ CMD_INT_VLAN_ADD_SNIPPET = (CMD_INT_VLAN_HEADER +
CMD_PORT_TRUNK = """ CMD_PORT_TRUNK = """
<interface> <interface>
<ethernet> <%s>
<interface>%s</interface> <interface>%s</interface>
<__XML__MODE_if-ethernet-switch> <__XML__MODE_if-ethernet-switch>
<switchport></switchport> <switchport></switchport>
@ -134,13 +135,13 @@ CMD_PORT_TRUNK = """
</mode> </mode>
</switchport> </switchport>
</__XML__MODE_if-ethernet-switch> </__XML__MODE_if-ethernet-switch>
</ethernet> </%s>
</interface> </interface>
""" """
CMD_NO_SWITCHPORT = """ CMD_NO_SWITCHPORT = """
<interface> <interface>
<ethernet> <%s>
<interface>%s</interface> <interface>%s</interface>
<__XML__MODE_if-ethernet-switch> <__XML__MODE_if-ethernet-switch>
<no> <no>
@ -148,14 +149,14 @@ CMD_NO_SWITCHPORT = """
</switchport> </switchport>
</no> </no>
</__XML__MODE_if-ethernet-switch> </__XML__MODE_if-ethernet-switch>
</ethernet> </%s>
</interface> </interface>
""" """
CMD_NO_VLAN_INT_SNIPPET = """ CMD_NO_VLAN_INT_SNIPPET = """
<interface> <interface>
<ethernet> <%s>
<interface>%s</interface> <interface>%s</interface>
<__XML__MODE_if-ethernet-switch> <__XML__MODE_if-ethernet-switch>
<switchport></switchport> <switchport></switchport>
@ -171,7 +172,7 @@ CMD_NO_VLAN_INT_SNIPPET = """
</trunk> </trunk>
</switchport> </switchport>
</__XML__MODE_if-ethernet-switch> </__XML__MODE_if-ethernet-switch>
</ethernet> </%s>
</interface> </interface>
""" """

View File

@ -53,7 +53,7 @@ class CiscoNEXUSFakeDriver():
"""Disable trunk mode an interface on Nexus Switch.""" """Disable trunk mode an interface on Nexus Switch."""
pass 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 vlan on trunk interface.
Enable trunk mode vlan access an interface on Nexus Switch given Enable trunk mode vlan access an interface on Nexus Switch given

View File

@ -184,7 +184,9 @@ class TestCiscoPortsV2(CiscoNetworkPluginV2TestCase,
with self.network(name=name) as network: with self.network(name=name) as network:
with self.subnet(network=network, cidr=cidr) as subnet: with self.subnet(network=network, cidr=cidr) as subnet:
net_id = subnet['subnet']['network_id'] 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) port = self.deserialize(self.fmt, res)
try: try:
yield res yield res

View File

@ -115,13 +115,13 @@ class CiscoNexusDbTest(base.BaseTestCase):
npb22 = self._npb_test_obj(20, 200) npb22 = self._npb_test_obj(20, 200)
self._add_to_db([npb11, npb21, npb22]) 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) 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) self._assert_equal(npb, npb22)
with testtools.ExpectedException(c_exc.NexusPortBindingNotFound): 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): def test_nexusportvlanswitchbinding_get(self):
npb11 = self._npb_test_obj(10, 100) npb11 = self._npb_test_obj(10, 100)

View File

@ -30,10 +30,15 @@ from neutron.tests import base
NEXUS_IP_ADDRESS = '1.1.1.1' NEXUS_IP_ADDRESS = '1.1.1.1'
HOSTNAME1 = 'testhost1' HOSTNAME1 = 'testhost1'
HOSTNAME2 = 'testhost2' HOSTNAME2 = 'testhost2'
HOSTNAME3 = 'testhost3'
INSTANCE1 = 'testvm1' INSTANCE1 = 'testvm1'
INSTANCE2 = 'testvm2' INSTANCE2 = 'testvm2'
INSTANCE3 = 'testvm3'
NEXUS_PORT1 = '1/10' NEXUS_PORT1 = '1/10'
NEXUS_PORT2 = '1/20' NEXUS_PORT2 = '1/20'
NEXUS_PC_IP_ADDRESS = '2.2.2.2'
NEXUS_PORTCHANNELS = 'portchannel:2'
PC_HOSTNAME = 'testpchost'
NEXUS_SSH_PORT = '22' NEXUS_SSH_PORT = '22'
NEXUS_DRIVER = ('neutron.plugins.cisco.nexus.' NEXUS_DRIVER = ('neutron.plugins.cisco.nexus.'
'cisco_nexus_network_driver_v2.CiscoNEXUSDriver') 'cisco_nexus_network_driver_v2.CiscoNEXUSDriver')
@ -58,6 +63,8 @@ class TestCiscoNexusPlugin(base.BaseTestCase):
self.second_net_id = 5 self.second_net_id = 5
self.second_vlan_name = "q-" + str(self.second_net_id) + "vlan" self.second_vlan_name = "q-" + str(self.second_net_id) + "vlan"
self.second_vlan_id = 265 self.second_vlan_id = 265
self._pchostname = PC_HOSTNAME
self.attachment1 = { self.attachment1 = {
const.TENANT_ID: self.tenant_id, const.TENANT_ID: self.tenant_id,
const.INSTANCE_ID: INSTANCE1, const.INSTANCE_ID: INSTANCE1,
@ -68,6 +75,11 @@ class TestCiscoNexusPlugin(base.BaseTestCase):
const.INSTANCE_ID: INSTANCE2, const.INSTANCE_ID: INSTANCE2,
const.HOST_NAME: HOSTNAME2, const.HOST_NAME: HOSTNAME2,
} }
self.attachment3 = {
const.TENANT_ID: self.second_tenant_id,
const.INSTANCE_ID: INSTANCE3,
const.HOST_NAME: HOSTNAME3,
}
self.network1 = { self.network1 = {
const.NET_ID: self.net_id, const.NET_ID: self.net_id,
const.NET_NAME: self.net_name, 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_NAME: self.second_vlan_name,
const.NET_VLAN_ID: self.second_vlan_id, 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 = { self.providernet = {
const.NET_ID: 9, const.NET_ID: 9,
const.NET_NAME: 'pnet1', const.NET_NAME: 'pnet1',
@ -97,12 +115,28 @@ class TestCiscoNexusPlugin(base.BaseTestCase):
(NEXUS_IP_ADDRESS, 'ssh_port'): NEXUS_SSH_PORT, (NEXUS_IP_ADDRESS, 'ssh_port'): NEXUS_SSH_PORT,
(NEXUS_IP_ADDRESS, HOSTNAME2): NEXUS_PORT2, (NEXUS_IP_ADDRESS, HOSTNAME2): NEXUS_PORT2,
(NEXUS_IP_ADDRESS, 'ssh_port'): NEXUS_SSH_PORT, (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 = { self._client.credentials = {
NEXUS_IP_ADDRESS: { NEXUS_IP_ADDRESS: {
'username': 'admin', 'username': 'admin',
'password': 'pass1234' 'password': 'pass1234'
}, },
NEXUS_PC_IP_ADDRESS: {
'username': 'admin',
'password': 'password'
},
} }
db.configure_db() db.configure_db()
@ -118,18 +152,28 @@ class TestCiscoNexusPlugin(base.BaseTestCase):
self.addCleanup(self.patch_obj.stop) self.addCleanup(self.patch_obj.stop)
def test_create_networks(self): def test_create_delete_networks(self):
"""Tests creation of two new Virtual Networks.""" """Tests creation of two new Virtual Networks."""
new_net_dict = self._cisco_nexus_plugin.create_network( new_net_dict = self._cisco_nexus_plugin.create_network(
self.network1, self.attachment1) self.network1, self.attachment1)
for attr in NET_ATTRS: for attr in NET_ATTRS:
self.assertEqual(new_net_dict[attr], self.network1[attr]) 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( new_net_dict = self._cisco_nexus_plugin.create_network(
self.network2, self.attachment1) self.network2, self.attachment1)
for attr in NET_ATTRS: for attr in NET_ATTRS:
self.assertEqual(new_net_dict[attr], self.network2[attr]) 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): def test_create_providernet(self):
with mock.patch.object(cdb, 'is_provider_vlan', with mock.patch.object(cdb, 'is_provider_vlan',
return_value=True) as mock_db: return_value=True) as mock_db:
@ -169,15 +213,22 @@ class TestCiscoNexusPlugin(base.BaseTestCase):
for attr in NET_ATTRS: for attr in NET_ATTRS:
self.assertEqual(new_net_dict[attr], self.providernet[attr]) self.assertEqual(new_net_dict[attr], self.providernet[attr])
def test_nexus_delete_port(self): def test_create_delete_network_portchannel(self):
"""Test deletion of a vlan.""" """Tests creation of a network over a portchannel."""
self._cisco_nexus_plugin.create_network( new_net_dict = self._cisco_nexus_plugin.create_network(
self.network1, self.attachment1) 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])
expected_instance_id = self._cisco_nexus_plugin.delete_port( self._cisco_nexus_plugin.delete_port(
INSTANCE1, self.vlan_id) INSTANCE3, self.network3[const.NET_VLAN_ID]
)
self.assertEqual(expected_instance_id, INSTANCE1)
def test_nexus_add_remove_router_interface(self): def test_nexus_add_remove_router_interface(self):
"""Tests addition of a router interface.""" """Tests addition of a router interface."""