Merge "Nexus Baremetal Automated Port Channel Creation"

This commit is contained in:
Jenkins 2017-06-28 20:33:13 +00:00 committed by Gerrit Code Review
commit 8a24884055
22 changed files with 2079 additions and 498 deletions

View File

@ -44,6 +44,7 @@
# password=<credential password> (4)
# nve_src_intf=<loopback number> (5)
# physnet=<physical network> (6)
# vpc_pool=<start,end> (7)
#
# (1) For each host connected to a port on the switch, specify the hostname
# and the Nexus physical port (interface) it is connected to.
@ -69,6 +70,16 @@
# to this switch. The vlan ranges defined in network_vlan_ranges for a
# a physical network are allocated dynamically and are unique per physical
# network. These dynamic vlans may be reused across physical networks.
# (7) VPC pool is valid for Baremetal configurations.
# When there is a list of ethernet interfaces provided by Ironic to neutron
# in a port binding transaction, these are assumed to be port-channel type
# configurations. Ironic only learns ethernet interfaces so it is up to
# the Nexus ML2 Driver to either learn the port channel if the channel-group
# is already applied to the ethernet interfaces OR create a new port-channel
# and apply the channel-group to the ethernet interface. This pool is the
# reserved port-channel IDs available for allocation by the Nexus ML2 driver
# for each switch. Existing port-channel interfaces preconfigured on
# ethernet interfaces in use will be reused by the driver.
#
# Example:
# [ml2_mech_cisco_nexus:1.1.1.1]
@ -80,6 +91,7 @@
# password=mySecretPassword
# nve_src_intf=1
# physnet=physnet1
# vpc_pool=1001,1025
# (StrOpt) A short prefix to prepend to the VLAN number when creating a
# provider VLAN interface. For example, if an interface is being created

View File

@ -1 +1 @@
9148d96f9b39
f3765e42de23

View File

@ -0,0 +1,39 @@
# Copyright 2017 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Add VPC alloc table
Revision ID: f3765e42de23
Revises: 9148d96f9b39
Create Date: 2017-06-07 17:10:09.597016
"""
# revision identifiers, used by Alembic.
revision = 'f3765e42de23'
down_revision = '9148d96f9b39'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.create_table('cisco_ml2_nexus_vpc_alloc',
sa.Column('switch_ip', sa.String(length=64), nullable=False,
index=True),
sa.Column('vpc_id', sa.Integer(), nullable=False),
sa.Column('learned', sa.Boolean(), nullable=False),
sa.Column('active', sa.Boolean(), nullable=False),
sa.PrimaryKeyConstraint('switch_ip', 'vpc_id')
)

View File

@ -20,6 +20,8 @@ from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
constants as const)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_db_v2 as nxos_db)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_helpers as nexus_help)
ml2_cisco_opts = [
cfg.StrOpt('vlan_name_prefix', default='q-',
@ -85,7 +87,7 @@ class ML2MechCiscoConfig(object):
keys (host systems) are saved in the host mapping db.
"""
defined_attributes = [const.USERNAME, const.PASSWORD, const.SSHPORT,
const.PHYSNET, const.NVE_SRC_INTF]
const.PHYSNET, const.NVE_SRC_INTF, const.VPCPOOL]
multi_parser = cfg.MultiConfigParser()
read_ok = multi_parser.read(cfg.CONF.config_file)
@ -102,5 +104,10 @@ class ML2MechCiscoConfig(object):
self.nexus_dict[dev_ip, dev_key] = value[0]
else:
for if_id in value[0].split(','):
if_type, port = (
nexus_help.split_interface_name(
if_id))
interface = nexus_help.format_interface_name(
if_type, port)
nxos_db.add_host_mapping(
dev_key, dev_ip, if_id, 0, True)
dev_key, dev_ip, interface, 0, True)

View File

@ -19,6 +19,7 @@ RESERVED_PORT_HOST_ID = 'reserved_port'
CREDENTIAL_USERNAME = 'user_name'
CREDENTIAL_PASSWORD = 'password'
VPCPOOL = 'vpc_pool'
USERNAME = 'username'
PASSWORD = 'password'
SSHPORT = 'ssh_port'

View File

@ -65,6 +65,45 @@ class NexusHostMappingNotFound(exceptions.NeutronException):
super(NexusHostMappingNotFound, self).__init__(filters=filters)
class NexusVPCAllocNotFound(exceptions.NeutronException):
"""Nexus VPC alloc is not present."""
message = _("Nexus VPC Alloc (%(filters)s) is not present")
def __init__(self, **kwargs):
filters = ','.join('%s=%s' % i for i in kwargs.items())
super(NexusVPCAllocNotFound, self).__init__(filters=filters)
class NexusVPCAllocInvalidArgValue(exceptions.NeutronException):
"""Nexus VPC alloc arg values not valid."""
message = _("Nexus VPC Alloc init failed. Args "
"start (%(vpcstart)s) and end (%(vpcend)s) "
"difference should be greater than 0. ")
class NexusVPCAllocIncorrectArgCount(exceptions.NeutronException):
"""Nexus VPC alloc args count incorrect."""
message = _("Nexus VPC Alloc init failed. "
"Expected 2 args for start,end "
"received %(count)d), content %(content)s.")
class NexusVPCLearnedNotConsistent(exceptions.NeutronException):
"""Learned Channel group not consistent on interface set in switches."""
message = _("Learned Nexus Channel Group not consistent on"
"this interface set: first interface %(first)s, "
"second interface %(second)s. "
"Check Nexus Config and make consistent.")
class NexusVPCExpectedNoChgrp(exceptions.NeutronException):
"""Allocated Channel group not consistent on interface set in switches."""
message = _("Channel Group state in baremetal interface set not "
"consistent: first interface %(first)s, "
"second interface %(second)s. "
"Check Nexus Config and make consistent.")
class NexusMissingRequiredFields(exceptions.NeutronException):
"""Missing required fields to configure nexus switch."""
message = _("Missing required field(s) to configure nexus switch: "

View File

@ -49,6 +49,9 @@ from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
exceptions as excep)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_db_v2 as nxos_db)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_helpers as nexus_help)
LOG = logging.getLogger(__name__)
@ -74,7 +77,8 @@ class CiscoNexusCfgMonitor(object):
# this initialization occurs later for replay case
if not self._mdriver.is_replay_enabled():
try:
self._initialize_trunk_interfaces_to_none(switch_ip)
self._initialize_trunk_interfaces_to_none(
switch_ip, replay=False)
except Exception:
pass
@ -89,20 +93,22 @@ class CiscoNexusCfgMonitor(object):
const.NEXUS_TYPE_INVALID):
self._mdriver.set_switch_nexus_type(switch_ip, nexus_type)
def _initialize_trunk_interfaces_to_none(self, switch_ip):
def _initialize_trunk_interfaces_to_none(self, switch_ip, replay=True):
"""Initialize all nexus interfaces to trunk allowed none."""
try:
# The following determines if the switch interfaces are
# in place. If so, make sure they have a basic trunk
# configuration applied to none.
switch_ifs = self._mdriver._get_switch_interfaces(switch_ip)
switch_ifs = self._mdriver._get_switch_interfaces(
switch_ip, cfg_only=(False if replay else True))
if not switch_ifs:
LOG.debug("Skipping switch %s which has no configured "
"interfaces",
switch_ip)
return
self._driver.initialize_all_switch_interfaces(switch_ifs)
self._driver.initialize_all_switch_interfaces(
switch_ifs, switch_ip)
except Exception:
with excutils.save_and_reraise_exception():
LOG.warning(_LW("Unable to initialize interfaces to "
@ -111,26 +117,6 @@ class CiscoNexusCfgMonitor(object):
self._mdriver.register_switch_as_inactive(switch_ip,
'replay init_interface')
# Only baremetal transactions will have these Reserved
# port entries. If found, determine if there's a change
# then change dependent port bindings.
for switch_ip, intf_type, port, is_native, ch_grp in switch_ifs:
try:
reserved = nxos_db.get_switch_if_host_mappings(
switch_ip,
self._mdriver.format_interface_name(
intf_type, port))
except excep.NexusHostMappingNotFound:
continue
if reserved[0].ch_grp != ch_grp:
LOG.warning(_LW("port-channel mismatch. skip"))
#TODO(caboucha)Temporarily Skip the following until
#HN72 automated vPC is implemented
#self._mdriver._change_baremetal_interfaces(
# reserved[0].host_id,
# switch_ip, intf_type, port,
# reserved[0].ch_grp, ch_grp)
# When replay not enabled, this is call early during initialization.
# To prevent bogus ssh handles from being copied to child processes,
# release the handles now.
@ -298,6 +284,37 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
conf.cfg.CONF.ml2_cisco.nexus_driver)
raise SystemExit(1)
def _initialize_vpc_alloc_pools(self):
for switch_ip, attr in self._nexus_switches:
if str(attr) == const.VPCPOOL:
try:
countvpc, minvpc, maxvpc = (
nxos_db.get_switch_vpc_count_min_max(
switch_ip)
)
except excep.NexusVPCAllocNotFound:
countvpc = 0
value = self._nexus_switches.get((switch_ip, attr))
vpc_range = value.split(',')
if len(vpc_range) != 2:
raise excep.NexusVPCAllocIncorrectArgCount(
count=len(vpc_range), content=value)
fromvpc = int(vpc_range[0])
tovpc = int(vpc_range[1])
count = tovpc - fromvpc + 1
if countvpc == 0:
nxos_db.init_vpc_entries(switch_ip, fromvpc, tovpc)
elif (countvpc != count or minvpc != fromvpc or
maxvpc != tovpc):
LOG.warning(_LW("Cannot resize switch vpc_pool config "
"from %(today)d to %(chg)d entries nor from "
"%(from)d and to %(to)d values. Ignoring "
"config change for switch %(ip)s."),
{'today': countvpc, 'chg': count,
'from': fromvpc, 'to': tovpc,
'ip': switch_ip})
def initialize(self):
# Create ML2 device dictionary from ml2_conf.ini entries.
conf.ML2MechCiscoConfig()
@ -310,6 +327,7 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
self._switch_state = {}
self.driver = self._load_nexus_cfg_driver()
self._initialize_vpc_alloc_pools()
# This method is only called once regardless of number of
# api/rpc workers defined.
@ -327,52 +345,6 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
if self.is_replay_enabled():
eventlet.spawn_after(DELAY_MONITOR_THREAD, self._monitor_thread)
def format_interface_name(self, intf_type, port, ch_grp=0):
"""Method to format interface name given type, port.
Given interface type, port, and channel-group, this
method formats an interface name. If channel-group is
non-zero, then port-channel is configured.
:param intf_type: Such as 'ethernet' or 'port-channel'
:param port: unique identification -- 1/32 or 1
:ch_grp: If non-zero, ignore other params and format
port-channel<ch_grp>
:returns: the full formatted interface name.
ex: ethernet:1/32, port-channel:1
"""
if ch_grp > 0:
return 'port-channel:%s' % str(ch_grp)
return '%s:%s' % (intf_type, port)
def split_interface_name(self, interface, ch_grp=0):
"""Method to split interface type, id from name.
Takes an interface name or just interface suffix
and returns interface type and number separately.
:param interface: interface name or just suffix
:param ch_grp: if non-zero, ignore interface
name and return 'port-channel' grp
:returns: interface type like 'ethernet'
:returns: returns suffix to interface name
"""
interface = interface.lower()
if ch_grp != 0:
intf_type = 'port-channel'
port = str(ch_grp)
elif ':' in interface:
intf_type, port = interface.split(':')
elif interface.startswith('ethernet'):
interface = interface.replace(" ", "")
_, intf_type, port = interface.partition('ethernet')
else:
intf_type, port = 'ethernet', interface
return intf_type, port
def is_replay_enabled(self):
return conf.cfg.CONF.ml2_cisco.switch_heartbeat_time > 0
@ -704,7 +676,7 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
for link_info in all_link_info:
# Extract port info
intf_type, port = self.split_interface_name(
intf_type, port = nexus_help.split_interface_name(
link_info['port_id'])
# Determine if this switch is to be skipped
@ -727,19 +699,22 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
is_native = switch_info['is_native']
else:
is_native = const.NOT_NATIVE
ch_grp = 0
if not from_segment:
try:
reserved = nxos_db.get_switch_if_host_mappings(
switch_ip,
self.format_interface_name(
nexus_help.format_interface_name(
intf_type, port))
if reserved[0].ch_grp > 0:
intf_type, port = self.split_interface_name(
'', reserved[0].ch_grp)
ch_grp = reserved[0].ch_grp
intf_type, port = nexus_help.split_interface_name(
'', ch_grp)
except excep.NexusHostMappingNotFound:
pass
connections.append((switch_ip, intf_type, port, is_native))
connections.append((switch_ip, intf_type, port,
is_native, ch_grp))
return connections
@ -776,11 +751,11 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
return
# Get all bindings to this switch interface
reserved_port_id = self.format_interface_name(
reserved_port_id = nexus_help.format_interface_name(
intf_type, port)
old_port_id = self.format_interface_name(
old_port_id = nexus_help.format_interface_name(
intf_type, port, old_ch_grp)
new_port_id = self.format_interface_name(
new_port_id = nexus_help.format_interface_name(
intf_type, port, ch_grp)
# Get all port instances related to this switch interface
@ -865,11 +840,11 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
connections = self._get_baremetal_connections(
port_seg, False, True)
for switch_ip, intf_type, port, is_native in connections:
for switch_ip, intf_type, port, is_native, _ in connections:
try:
reserved = nxos_db.get_switch_if_host_mappings(
switch_ip,
self.format_interface_name(
nexus_help.format_interface_name(
intf_type, port))
reserved_exists.append(
(switch_ip, intf_type, port, is_native,
@ -878,13 +853,13 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
if self.is_switch_active(switch_ip):
# channel-group added later
list_to_init.append(
(switch_ip, intf_type, port, is_native))
(switch_ip, intf_type, port, is_native, 0))
else:
inactive_switch.append(
(switch_ip, intf_type, port, is_native, 0))
# channel_group is appended to tuples in list_to_init
self.driver.initialize_all_switch_interfaces(list_to_init)
self.driver.initialize_baremetal_switch_interfaces(list_to_init)
host_id = port_seg.get('dns_name')
if host_id is None:
@ -897,7 +872,7 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
nxos_db.add_host_mapping(
host_id,
switch_ip,
self.format_interface_name(intf_type, port),
nexus_help.format_interface_name(intf_type, port),
ch_grp, False)
device_id = port_seg.get('device_id')
@ -909,7 +884,8 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
# port_binding data base entries
list_to_init += reserved_exists
for switch_ip, intf_type, port, is_native, ch_grp in list_to_init:
port_id = self.format_interface_name(intf_type, port, ch_grp)
port_id = nexus_help.format_interface_name(
intf_type, port, ch_grp)
try:
nxos_db.get_nexusport_binding(
port_id, vlan_id, switch_ip, device_id)
@ -973,13 +949,13 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
if (only_active_switch and
not self.is_switch_active(ifs.switch_ip)):
continue
intf_type, port = self.split_interface_name(
ifs.if_id)
intf_type, port = nexus_help.split_interface_name(
ifs.if_id, ifs.ch_grp)
# is_native set to const.NOT_NATIVE for
# VNIC_TYPE of normal
host_connections.append((
ifs.switch_ip, intf_type, port,
const.NOT_NATIVE))
const.NOT_NATIVE, ifs.ch_grp))
if not host_found:
LOG.warning(HOST_NOT_FOUND, host_id)
@ -998,7 +974,7 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
def _get_active_port_connections(self, port, host_id):
return self._get_port_connections(port, host_id, True)
def _get_switch_interfaces(self, requested_switch_ip):
def _get_switch_interfaces(self, requested_switch_ip, cfg_only=False):
"""Get switch interfaces from host mapping DB.
For a given switch, this returns all known port
@ -1019,11 +995,13 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
port_info = []
for binding in port_info:
intf_type, port = self.split_interface_name(
if cfg_only and not binding.is_static:
continue
intf_type, port = nexus_help.split_interface_name(
binding.if_id)
switch_ifs.append(
(requested_switch_ip, intf_type, port,
const.NOT_NATIVE))
const.NOT_NATIVE, binding.ch_grp))
return switch_ifs
def get_switch_ips(self):
@ -1125,8 +1103,8 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
Called during update precommit port event.
"""
host_connections = self._get_port_connections(port, host_id)
for switch_ip, intf_type, nexus_port, is_native in host_connections:
port_id = self.format_interface_name(intf_type, nexus_port)
for switch_ip, intf_type, nexus_port, is_native, _ in host_connections:
port_id = nexus_help.format_interface_name(intf_type, nexus_port)
try:
nxos_db.get_nexusport_binding(port_id, vlan_id, switch_ip,
device_id)
@ -1242,7 +1220,7 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
port, native_vlan):
"""Restores a set of vlans for a given port."""
intf_type, nexus_port = self.split_interface_name(port)
intf_type, nexus_port = nexus_help.split_interface_name(port)
# If native_vlan is configured, this is isolated since
# two configs (native + trunk) must be sent for this vlan only.
@ -1326,7 +1304,7 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
vlan_already_created = []
starttime = time.time()
for switch_ip, intf_type, nexus_port, is_native in connections:
for switch_ip, intf_type, nexus_port, is_native, _ in connections:
all_bindings = nxos_db.get_nexusvlan_binding(vlan_id, switch_ip)
previous_bindings = [row for row in all_bindings
@ -1512,6 +1490,55 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
except excep.NexusPortBindingNotFound:
return
def _delete_port_channel_resources(self, host_id, switch_ip,
intf_type, nexus_port, port_id):
'''This determines if port channel id needs to be freed.'''
# if this connection is not a port-channel, nothing to do.
if intf_type != 'port-channel':
return
# Check if this driver created it and its no longer needed.
try:
vpc = nxos_db.get_switch_vpc_alloc(
switch_ip, nexus_port)
except excep.NexusVPCAllocNotFound:
# This can occur for non-baremetal configured
# port-channels. Nothing more to do.
return
# if this isn't one which was allocated or learned,
# don't do any further processing.
if not vpc.active:
return
# Is this port-channel still in use?
# If so, nothing more to do.
try:
nxos_db.get_nexus_switchport_binding(port_id, switch_ip)
return
except excep.NexusPortBindingNotFound:
pass
# need to get ethernet interface name
try:
mapping = nxos_db.get_switch_and_host_mappings(
host_id, switch_ip)
eth_type, eth_port = nexus_help.split_interface_name(
mapping[0].if_id)
except excep.NexusHostMappingNotFound:
return
# Remove the channel group from ethernet interface
# and remove port channel from this switch.
if not vpc.learned:
self.driver.delete_ch_grp_to_interface(
switch_ip, eth_type, eth_port,
nexus_port)
self.driver.delete_port_channel(switch_ip,
nexus_port)
nxos_db.free_vpcid_for_switch(nexus_port, switch_ip)
def _delete_switch_entry(self, port, vlan_id, device_id, host_id, vni,
is_provider_vlan):
"""Delete the nexus switch entry.
@ -1528,11 +1555,11 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
# 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, is_native in connections:
for switch_ip, intf_type, nexus_port, is_native, _ in 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 = self.format_interface_name(intf_type, nexus_port)
port_id = nexus_help.format_interface_name(intf_type, nexus_port)
auto_create = True
auto_trunk = True
if is_provider_vlan:
@ -1562,11 +1589,15 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
if switch_ip not in vlan_already_removed:
self.driver.delete_vlan(switch_ip, vlan_id)
vlan_already_removed.append(switch_ip)
self._delete_port_channel_resources(
host_id, switch_ip, intf_type, nexus_port, port_id)
if self._is_baremetal(port):
connections = self._get_baremetal_connections(
port, False, True)
for switch_ip, intf_type, nexus_port, is_native in connections:
if_id = self.format_interface_name(
for switch_ip, intf_type, nexus_port, is_native, _ in connections:
if_id = nexus_help.format_interface_name(
intf_type, nexus_port)
try:
mapping = nxos_db.get_switch_if_host_mappings(
@ -1574,7 +1605,7 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
ch_grp = mapping[0].ch_grp
except excep.NexusHostMappingNotFound:
ch_grp = 0
bind_port_id = self.format_interface_name(
bind_port_id = nexus_help.format_interface_name(
intf_type, nexus_port, ch_grp)
binding = nxos_db.get_port_switch_bindings(
bind_port_id,
@ -1867,7 +1898,7 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
if not host_connections:
return
for switch_ip, attr2, attr3, attr4 in host_connections:
for switch_ip, _, _, _, _ in host_connections:
physnet = self._nexus_switches.get(
(switch_ip, const.PHYSNET))
if physnet:

View File

@ -95,17 +95,16 @@ class CiscoNexusBaseDriver(object):
"""
return None
def initialize_all_switch_interfaces(self, interfaces):
def initialize_all_switch_interfaces(self, interfaces,
switch_ip=None, replay=True):
"""Configure Nexus interface and get port channel number.
Receive a list of interfaces containing:
:param nexus_host: IP address of Nexus switch
:param intf_type: String which specifies interface type.
example: ethernet
:param interface: String indicating which interface.
example: 1/19
:returns interface: Appends port channel to each entry
channel number is 0 if none
:param interfaces: List of interfaces for a given switch.
ch_grp can be altered as last arg
to each interface. If no ch_grp,
this arg will be zero.
:param switch_ip: IP address of Nexus switch
:param replay: Whether in replay path
"""
pass

View File

@ -16,6 +16,7 @@
from oslo_log import log as logging
import sqlalchemy.orm.exc as sa_exc
from sqlalchemy.sql import func
from networking_cisco._i18n import _LW
@ -532,3 +533,190 @@ def remove_all_static_host_mappings():
session.flush()
except c_exc.NexusHostMappingNotFound:
pass
def _lookup_vpc_allocs(query_type, session=None, **bfilter):
"""Look up 'query_type' Nexus VPC Allocs matching the filter.
:param query_type: 'all', 'one' or 'first'
:param session: db session
:param bfilter: filter for mappings query
:return: VPCs if query gave a result, else
raise NexusVPCAllocNotFound.
"""
if session is None:
session = db.get_session()
query_method = getattr(session.query(
nexus_models_v2.NexusVPCAlloc).filter_by(**bfilter), query_type)
try:
vpcs = query_method()
if vpcs:
return vpcs
except sa_exc.NoResultFound:
pass
raise c_exc.NexusVPCAllocNotFound(**bfilter)
def _lookup_vpc_count_min_max(session=None, **bfilter):
"""Look up count/min/max Nexus VPC Allocs for given switch.
:param session: db session
:param bfilter: filter for mappings query
:return: number of VPCs and min value if query gave a result,
else raise NexusVPCAllocNotFound.
"""
if session is None:
session = db.get_session()
try:
res = session.query(
func.count(nexus_models_v2.NexusVPCAlloc.vpc_id),
func.min(nexus_models_v2.NexusVPCAlloc.vpc_id),
func.max(nexus_models_v2.NexusVPCAlloc.vpc_id),
).filter(nexus_models_v2.NexusVPCAlloc.switch_ip ==
bfilter['switch_ip']).one()
count = res[0]
sw_min = res[1]
sw_max = res[2]
return count, sw_min, sw_max
except sa_exc.NoResultFound:
pass
raise c_exc.NexusVPCAllocNotFound(**bfilter)
def _lookup_all_vpc_allocs(session=None, **bfilter):
return _lookup_vpc_allocs('all', session, **bfilter)
def _lookup_one_vpc_allocs(session=None, **bfilter):
return _lookup_vpc_allocs('one', session, **bfilter)
def get_all_switch_vpc_allocs(switch_ip):
return(_lookup_all_vpc_allocs(switch_ip=switch_ip))
def get_switch_vpc_count_min_max(switch_ip):
return(_lookup_vpc_count_min_max(switch_ip=switch_ip))
def get_active_switch_vpc_allocs(switch_ip):
return(_lookup_all_vpc_allocs(switch_ip=switch_ip, active=True))
def get_free_switch_vpc_allocs(switch_ip):
return(_lookup_all_vpc_allocs(switch_ip=switch_ip, active=False))
def get_switch_vpc_alloc(switch_ip, vpc_id):
return(_lookup_one_vpc_allocs(switch_ip=switch_ip, vpc_id=vpc_id))
def init_vpc_entries(nexus_ip, vpc_start, vpc_end):
"""Initialize switch/vpc entries in vpc alloc data base.
param: nexus_ip is the ip addr of the nexus switch for this interface
param: vpc_start is the starting vpc id
param: vpc_end is the ending vpc id
"""
LOG.debug("init_vpc_entries() called")
session = db.get_session()
count = vpc_end - vpc_start + 1
if count <= 0:
raise c_exc.NexusVPCAllocInvalidArgValue(
vpcstart=vpc_start, vpcend=vpc_end)
vpc_max = vpc_end + 1
for count in range(vpc_start, vpc_max):
vpc_alloc = nexus_models_v2.NexusVPCAlloc(
switch_ip=nexus_ip,
vpc_id=count,
learned=False,
active=False)
session.add(vpc_alloc)
session.flush()
def update_vpc_entry(nexus_ip, vpc_id, learned, active):
"""Change active state in vpc_allocate data base."""
LOG.debug("update_vpc_entry called")
session = db.get_session()
try:
vpc_alloc = _lookup_one_vpc_allocs(
switch_ip=nexus_ip,
vpc_id=vpc_id)
except c_exc.NexusVPCAllocNotFound:
return None
vpc_alloc.learned = learned
vpc_alloc.active = active
session.merge(vpc_alloc)
session.flush()
return vpc_alloc
def alloc_vpcid(nexus_ips):
"""Allocate a vpc id for the given list of switch_ips."""
LOG.debug("alloc_vpc() called")
vpc_list = []
# First build a set of vlans for each switch
for n_ip in nexus_ips:
switch_free_list = get_free_switch_vpc_allocs(n_ip)
vpc_set = set()
for switch_ip, vpcid, learned, active in switch_free_list:
vpc_set.add(vpcid[1])
vpc_list.append(vpc_set)
# Now get intersection
intersect = vpc_list[0]
for switch_list in vpc_list:
intersect = intersect & switch_list
intersect = list(intersect)
if len(intersect) > 0:
intersect.sort()
vpc_id = intersect[0] # get smallest
for n_ip in nexus_ips:
update_vpc_entry(n_ip, vpc_id, False, True)
else:
vpc_id = 0
return vpc_id
def free_vpcid_for_switch_list(vpc_id, nexus_ips):
"""Free a vpc id for the given list of switch_ips."""
LOG.debug("free_vpcid_for_switch_list() called")
if vpc_id == 0:
return
for n_ip in nexus_ips:
update_vpc_entry(n_ip, vpc_id, False, False)
def free_vpcid_for_switch(vpc_id, nexus_ip):
"""Free a vpc id for the given switch_ip."""
LOG.debug("free_vpcid_for_switch() called")
if vpc_id == 0:
return
update_vpc_entry(nexus_ip, vpc_id, False, False)

View File

@ -0,0 +1,66 @@
# Copyright (c) 2017 Cisco Systems, Inc.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
ML2 Nexus Driver - Helper Methods
"""
def format_interface_name(intf_type, port, ch_grp=0):
"""Method to format interface name given type, port.
Given interface type, port, and channel-group, this
method formats an interface name. If channel-group is
non-zero, then port-channel is configured.
:param intf_type: Such as 'ethernet' or 'port-channel'
:param port: unique identification -- 1/32 or 1
:ch_grp: If non-zero, ignore other params and format
port-channel<ch_grp>
:returns: the full formatted interface name.
ex: ethernet:1/32, port-channel:1
"""
if ch_grp > 0:
return 'port-channel:%s' % str(ch_grp)
return '%s:%s' % (intf_type.lower(), port)
def split_interface_name(interface, ch_grp=0):
"""Method to split interface type, id from name.
Takes an interface name or just interface suffix
and returns interface type and number separately.
:param interface: interface name or just suffix
:param ch_grp: if non-zero, ignore interface
name and return 'port-channel' grp
:returns: interface type like 'ethernet'
:returns: returns suffix to interface name
"""
interface = interface.lower()
if ch_grp != 0:
intf_type = 'port-channel'
port = str(ch_grp)
elif ':' in interface:
intf_type, port = interface.split(':')
elif interface.startswith('ethernet'):
interface = interface.replace(" ", "")
_, intf_type, port = interface.partition('ethernet')
else:
intf_type, port = 'ethernet', interface
return intf_type, port

View File

@ -108,3 +108,21 @@ class NexusHostMapping(bc.model_base.BASEV2):
if_id = sa.Column(sa.String(255), nullable=False, primary_key=True)
ch_grp = sa.Column(sa.Integer(), nullable=False)
is_static = sa.Column(sa.Boolean(), nullable=False)
class NexusVPCAlloc(bc.model_base.BASEV2):
"""Nexus Port Channel Allocation."""
__tablename__ = 'cisco_ml2_nexus_vpc_alloc'
switch_ip = sa.Column(sa.String(64), nullable=False,
primary_key=True)
vpc_id = sa.Column(sa.Integer, nullable=False, primary_key=True,
autoincrement=False)
# learned indicates this ch_grp was predefined on Nexus Switch
# as opposed to ML2 Nexus driver creating the port channel #
learned = sa.Column(sa.Boolean, nullable=False)
# active indicates this ch_grp is in use
active = sa.Column(sa.Boolean, nullable=False)

View File

@ -304,17 +304,21 @@ class CiscoNexusSshDriver(basedrvr.CiscoNexusBaseDriver):
"config", {'if_type': intf_type, 'interface': interface})
return response
def initialize_all_switch_interfaces(self, interfaces):
def initialize_baremetal_switch_interfaces(self, interfaces):
"""Initialize Nexus interfaces and for initial baremetal event."""
self.initialize_all_switch_interfaces(interfaces)
def initialize_all_switch_interfaces(self, interfaces, switch_ip=None,
replay=True):
"""Configure Nexus interface and get port channel number.
Receive a list of interfaces containing:
:param nexus_host: IP address of Nexus switch
:param intf_type: String which specifies interface type.
example: ethernet
:param interface: String indicating which interface.
example: 1/19
:returns interface: Appends port channel to each entry
channel number is 0 if none
:param interfaces: List of interfaces for a given switch.
ch_grp can be altered as last arg
to each interface. If no ch_grp,
this arg will be zero.
:param switch_ip: IP address of Nexus switch
:param replay: Whether in replay path
"""
if not interfaces:
@ -322,22 +326,27 @@ class CiscoNexusSshDriver(basedrvr.CiscoNexusBaseDriver):
starttime = time.time()
ifs = []
for i in range(len(interfaces)):
nexus_host, intf_type, nexus_port, is_native = interfaces[i]
for i, (nexus_host, intf_type, nexus_port, is_native,
ch_grp_saved) in enumerate(interfaces):
response = self.get_interface_switch(
nexus_host, intf_type, nexus_port)
# Collect the port-channel number from response
mo = re.search("channel-group\s(\d*)\s", response)
try:
ch_grp = int(mo.group(1))
except Exception:
ch_grp = 0
if ch_grp_saved == 0:
# Collect the port-channel number from response
mo = re.search("channel-group\s(\d*)\s", response)
try:
ch_grp = int(mo.group(1))
except Exception:
ch_grp = 0
#substitute content of ch_grp
no_chgrp_len = len(interfaces[i]) - 1
interfaces[i] = interfaces[i][:no_chgrp_len] + (ch_grp,)
else:
ch_grp = ch_grp_saved
if ch_grp is not 0:
# if channel-group returned, init port-channel
# if channel-group exists, init port-channel
# instead of the provided ethernet interface
intf_type = 'port-channel'
nexus_port = str(ch_grp)
interfaces[i] += (ch_grp,)
if (response and
"switchport trunk allowed vlan" in response):
pass

View File

@ -22,14 +22,20 @@ import time
from oslo_log import log as logging
from networking_cisco._i18n import _LW
from networking_cisco._i18n import _LE, _LW
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
config as conf)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
constants as const)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
exceptions as cexc)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_base_network_driver as basedrvr)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_db_v2 as nxos_db)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_helpers as nexus_help)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_restapi_client as client)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
@ -137,6 +143,95 @@ class CiscoNexusRestapiDriver(basedrvr.CiscoNexusBaseDriver):
return found
def add_ch_grp_to_interface(
self, nexus_host, if_type, port, ch_grp):
"""Applies channel-group n to ethernet interface."""
if if_type != "ethernet":
LOG.error(_LE("Unexpected interface type %(iftype)s when "
"adding change group"), {'iftype': if_type})
return
starttime = time.time()
path_snip = snipp.PATH_ALL
path_interface = "phys-[eth" + port + "]"
body_snip = snipp.BODY_ADD_CH_GRP % (ch_grp, ch_grp, path_interface)
self.send_edit_string(nexus_host, path_snip, body_snip)
self.capture_and_print_timeshot(
starttime, "add_ch_group",
switch=nexus_host)
def delete_ch_grp_to_interface(
self, nexus_host, if_type, port, ch_grp):
"""Removes channel-group n from ethernet interface."""
if if_type != "ethernet":
LOG.error(_LE("Unexpected interface type %(iftype)s when "
"deleting change group"), {'iftype': if_type})
return
starttime = time.time()
path_snip = snipp.PATH_ALL
path_interface = "phys-[eth" + port + "]"
body_snip = snipp.BODY_DEL_CH_GRP % (ch_grp, path_interface)
self.send_edit_string(nexus_host, path_snip, body_snip)
self.capture_and_print_timeshot(
starttime, "del_ch_group",
switch=nexus_host)
def _apply_user_port_channel_config(self, nexus_host, vpc_nbr):
"""Adds STP and no lacp suspend config to port channel. """
vpc_str = str(vpc_nbr)
path_snip = snipp.PATH_ALL
body_snip = snipp.BODY_ADD_PORT_CH_P2 % (vpc_str, vpc_str)
self.send_edit_string(nexus_host, path_snip, body_snip)
def create_port_channel(self, nexus_host, vpc_nbr):
"""Creates port channel n on Nexus switch."""
starttime = time.time()
vpc_str = str(vpc_nbr)
path_snip = snipp.PATH_ALL
body_snip = snipp.BODY_ADD_PORT_CH % (vpc_str, vpc_str, vpc_str)
self.send_edit_string(nexus_host, path_snip, body_snip)
self._apply_user_port_channel_config(nexus_host, vpc_nbr)
self.send_enable_vlan_on_trunk_int(
nexus_host, "", 'port-channel',
vpc_str, False, add_mode=True)
self.capture_and_print_timeshot(
starttime, "create_port_channel",
switch=nexus_host)
def delete_port_channel(self, nexus_host, vpc_nbr):
"""Deletes delete port channel on Nexus switch."""
starttime = time.time()
path_snip = snipp.PATH_ALL
body_snip = snipp.BODY_DEL_PORT_CH % (vpc_nbr)
self.send_edit_string(nexus_host, path_snip, body_snip)
self.capture_and_print_timeshot(
starttime, "delete_port_channel",
switch=nexus_host)
def _get_port_channel_group(
self, nexus_host, intf_type, interface):
"""Look for 'channel-group x' config and return x.
@ -180,37 +275,188 @@ class CiscoNexusRestapiDriver(basedrvr.CiscoNexusBaseDriver):
return ch_grp
def initialize_all_switch_interfaces(self, interfaces):
def initialize_baremetal_switch_interfaces(self, interfaces):
"""Initialize Nexus interfaces and for initial baremetal event.
This get/create port channel number, applies channel-group to
ethernet interface, and initializes trunking on interface.
:param interface: Receive a list of interfaces containing:
nexus_host: IP address of Nexus switch
intf_type: String which specifies interface type.
example: ethernet
interface: String indicating which interface.
example: 1/19
is_native: Whether native vlan must be configured.
ch_grp: May replace port channel to each entry.
channel number is 0 if none
"""
if not interfaces:
return
max_ifs = len(interfaces)
starttime = time.time()
# build host list in case you need to allocate vpc_id
prev_ch_grp = -1
nexus_ip_list = []
for (nexus_host, intf_type, nexus_port,
is_native, ch_grp) in interfaces:
nexus_ip_list.append(nexus_host)
if prev_ch_grp != -1 and prev_ch_grp != ch_grp:
# LOG error Baremetal set does not have matching ch_grp
LOG.error(_LE("Inconsistent change group stored in "
"port entries. Saw %(ch_grp)d expected "
"%(p_ch_grp)d for switch %(switch)s interface "
"%(intf)s."), {
'ch_grp': ch_grp,
'p_ch_grp': prev_ch_grp,
'switch': nexus_host,
'intf': nexus_help.format_interface_name(
intf_type, nexus_port)})
return
prev_ch_grp = ch_grp
ch_grp = 0
for i, (nexus_host, intf_type, nexus_port, is_native,
ch_grp_saved) in enumerate(interfaces):
add_trunk_mode = False
if max_ifs > 1 and ch_grp_saved == 0:
learned_ch_grp = self._get_port_channel_group(
nexus_host, intf_type, nexus_port)
if i == 0: # if first in the set
if learned_ch_grp == 0:
# When allocating vpcid, it must be unique for
# all switches in the set.
ch_grp = nxos_db.alloc_vpcid(nexus_ip_list)
self.create_port_channel(nexus_host, ch_grp)
learned = False
add_trunk_mode = True
self.add_ch_grp_to_interface(
nexus_host, intf_type, nexus_port, ch_grp)
else:
ch_grp = learned_ch_grp
learned = True
save_1st_if = (nexus_host + ', ' +
intf_type + ':' + nexus_port + ', ')
else:
if learned:
if learned_ch_grp != ch_grp:
this_if = (nexus_host + ', ' + intf_type +
':' + nexus_port +
', vpc=' + str(learned_ch_grp))
raise cexc.NexusVPCLearnedNotConsistent(
first=save_1st_if + 'vpc=' + str(ch_grp),
second=this_if)
# if newly learned ch_grp
if ch_grp_saved == 0:
nxos_db.update_vpc_entry(
nexus_host, ch_grp, learned, True)
elif learned_ch_grp != 0:
# Remove port-channels just created
for y in range(i):
self.delete_port_channel(
nexus_ip_list[y], ch_grp)
nxos_db.free_vpcid_for_switch_list(
ch_grp, nexus_ip_list)
raise cexc.NexusVPCExpectedNoChgrp(
first=save_1st_if + 'vpc=None',
second=this_if)
else:
self.create_port_channel(nexus_host, ch_grp)
self.add_ch_grp_to_interface(
nexus_host, intf_type, nexus_port, ch_grp)
if ch_grp is not 0:
# if channel-group returned, init port-channel
# instead of the provided ethernet interface
intf_type = 'port-channel'
nexus_port = str(ch_grp)
elif i == 0:
ch_grp = ch_grp_saved
#substitute content of ch_grp
no_chgrp_len = len(interfaces[i]) - 1
interfaces[i] = interfaces[i][:no_chgrp_len] + (ch_grp,)
present = self._get_interface_switch_trunk_present(
nexus_host, intf_type, nexus_port)
if not present:
self.send_enable_vlan_on_trunk_int(
nexus_host, "", intf_type, nexus_port, False,
add_trunk_mode)
self.capture_and_print_timeshot(
starttime, "init_bmif",
switch=nexus_host)
def initialize_all_switch_interfaces(self, interfaces,
switch_ip=None, replay=True):
"""Configure Nexus interface and get port channel number.
Receive a list of interfaces containing:
:param nexus_host: IP address of Nexus switch
:param intf_type: String which specifies interface type.
example: ethernet
:param interface: String indicating which interface.
example: 1/19
:returns interface: Appends port channel to each entry
channel number is 0 if none
Called during switch replay or just init if no replay
is configured. For latter case, only configured interfaces
are affected by this method.
During switch replay, the change group from the
host mapping data base is used. There is no attempt
to relearn port-channel from the Nexus switch. What
we last knew it to be will persist.
:param interfaces: List of interfaces for a given switch.
ch_grp can be altered as last arg
to each interface. If no ch_grp,
this arg will be zero.
:param switch_ip: IP address of Nexus switch
:param replay: Whether in replay path
"""
if not interfaces:
return
starttime = time.time()
for i in range(len(interfaces)):
nexus_host, intf_type, nexus_port, is_native = interfaces[i]
ch_grp = self._get_port_channel_group(
nexus_host, intf_type, nexus_port)
if ch_grp is not 0:
# if channel-group returned, init port-channel
if replay:
try:
vpcs = nxos_db.get_active_switch_vpc_allocs(switch_ip)
except cexc.NexusVPCAllocNotFound:
vpcs = []
for vpc in vpcs:
# if this is an allocated vpc, then recreate it
if not vpc.learned:
self.create_port_channel(switch_ip, vpc.vpc_id)
for i, (nexus_host, intf_type, nexus_port, is_native,
ch_grp) in enumerate(interfaces):
add_trunk_mode = False
if replay and ch_grp != 0:
try:
vpc = nxos_db.get_switch_vpc_alloc(switch_ip, ch_grp)
if not vpc.learned:
add_trunk_mode = True
self.add_ch_grp_to_interface(
nexus_host, intf_type, nexus_port, ch_grp)
except cexc.NexusVPCAllocNotFound:
pass
# if channel-group exists, switch to port-channel
# instead of the provided ethernet interface
intf_type = 'port-channel'
nexus_port = str(ch_grp)
interfaces[i] += (ch_grp,)
#substitute content of ch_grp
no_chgrp_len = len(interfaces[i]) - 1
interfaces[i] = interfaces[i][:no_chgrp_len] + (ch_grp,)
present = self._get_interface_switch_trunk_present(
nexus_host, intf_type, nexus_port)
nexus_host, intf_type, nexus_port)
if not present:
self.send_enable_vlan_on_trunk_int(
nexus_host, "", intf_type, nexus_port, False)
nexus_host, "", intf_type, nexus_port, False,
add_trunk_mode)
self.capture_and_print_timeshot(
starttime, "get_allif",
switch=nexus_host)
@ -249,7 +495,7 @@ class CiscoNexusRestapiDriver(basedrvr.CiscoNexusBaseDriver):
def start_create_vlan(self):
"""Returns REST API path and config start."""
return snipp.PATH_VLAN_ALL, snipp.BODY_VLAN_ALL_BEG
return snipp.PATH_ALL, snipp.BODY_VLAN_ALL_BEG
def end_create_vlan(self, conf_str):
"""Returns current config + end of config."""
@ -337,7 +583,8 @@ class CiscoNexusRestapiDriver(basedrvr.CiscoNexusBaseDriver):
switch=nexus_host)
def _get_vlan_body_on_trunk_int(self, nexus_host, vlanid, intf_type,
interface, is_native, is_delete):
interface, is_native, is_delete,
add_mode):
"""Prepares an XML snippet for VLAN on a trunk interface.
:param nexus_host: IP address of Nexus switch
@ -348,6 +595,7 @@ class CiscoNexusRestapiDriver(basedrvr.CiscoNexusBaseDriver):
example: 1/19
:param is_native: Is native vlan config desired?
:param is_delete: Is this a delete operation?
:param add_mode: Add mode trunk
:returns path_snippet, body_snippet
"""
@ -365,6 +613,7 @@ class CiscoNexusRestapiDriver(basedrvr.CiscoNexusBaseDriver):
path_snip = (snipp.PATH_IF % (path_interface))
mode = snipp.BODY_PORT_CH_MODE if add_mode else ''
if is_delete:
increment_it = "-"
debug_desc = "delif"
@ -379,11 +628,11 @@ class CiscoNexusRestapiDriver(basedrvr.CiscoNexusBaseDriver):
if is_native:
body_snip = (snipp.BODY_NATIVE_TRUNKVLAN %
(body_if_type, increment_it + str(vlanid),
(body_if_type, mode, increment_it + str(vlanid),
str(native_vlan)))
else:
body_snip = (snipp.BODY_TRUNKVLAN %
(body_if_type, increment_it + str(vlanid)))
(body_if_type, mode, increment_it + str(vlanid)))
self.capture_and_print_timeshot(
starttime, debug_desc,
@ -399,7 +648,7 @@ class CiscoNexusRestapiDriver(basedrvr.CiscoNexusBaseDriver):
path_snip, body_snip = self._get_vlan_body_on_trunk_int(
nexus_host, vlanid, intf_type, interface,
is_native, True)
is_native, True, False)
self.send_edit_string(nexus_host, path_snip, body_snip)
self.capture_and_print_timeshot(
starttime, "delif",
@ -418,12 +667,12 @@ class CiscoNexusRestapiDriver(basedrvr.CiscoNexusBaseDriver):
switch=nexus_host)
def send_enable_vlan_on_trunk_int(self, nexus_host, vlanid, intf_type,
interface, is_native):
interface, is_native, add_mode=False):
"""Gathers and sends an interface trunk XML snippet."""
path_snip, body_snip = self._get_vlan_body_on_trunk_int(
nexus_host, vlanid, intf_type, interface,
is_native, False)
is_native, False, add_mode)
self.send_edit_string(nexus_host, path_snip, body_snip)
def create_and_trunk_vlan(self, nexus_host, vlan_id,

View File

@ -21,7 +21,7 @@ PATH_GET_NEXUS_TYPE = 'api/mo/sys/ch.json'
# conf t
# vlan <a,n-y>
# state active
PATH_VLAN_ALL = 'api/mo.json'
PATH_ALL = 'api/mo.json'
BODY_VLAN_ALL_BEG = '{"topSystem": { "children": [ {"bdEntity":'
BODY_VLAN_ALL_BEG += ' { children": ['
BODY_VLAN_ALL_INCR = ' {"l2BD": {"attributes": {"fabEncap": "vlan-%s",'
@ -44,6 +44,49 @@ BODY_VLAN_ALL_CONT + BODY_VLAN_ALL_END)
BODY_VXLAN_ADD = (BODY_VLAN_ALL_BEG + BODY_VXLAN_ALL_INCR +
BODY_VLAN_ALL_CONT + BODY_VLAN_ALL_END)
BODY_PORT_CH_BEG = '{"topSystem": { "children": [ '
BODY_PORT_CH_BEG += ' { "interfaceEntity": { "children": ['
BODY_PORT_CH_BEG += ' { "pcAggrIf": { "attributes": '
BODY_PORT_CH_BEG += '{ "id": "po%s" '
BODY_PORT_CH_END = '} } ] } } ] } }'
BODY_ADD_PORT_CH = BODY_PORT_CH_BEG + ' } } } ] } }, {"vpcEntity": '
BODY_ADD_PORT_CH += '{ "children": [ { "vpcInst": { "children": [ '
BODY_ADD_PORT_CH += '{ "vpcDom": { "children": [ '
BODY_ADD_PORT_CH += '{ "vpcIf": { "attributes": { "id": "%s" }, '
BODY_ADD_PORT_CH += '"children": [ { "vpcRsVpcConf": '
BODY_ADD_PORT_CH += '{ "attributes": { "tDn": "sys/intf/aggr-[po%s]"'
BODY_ADD_PORT_CH += ' } } } ] } }'
BODY_ADD_PORT_CH += '] } } ]' + BODY_PORT_CH_END
BODY_ADD_STP_PORT_CH = '{ "stpEntity": { "children": [ '
BODY_ADD_STP_PORT_CH += ' { "stpInst": { "children": [ '
BODY_ADD_STP_PORT_CH += ' { "stpIf": { "attributes": { '
BODY_ADD_STP_PORT_CH += ' "id": "po%s", "mode": "trunk"'
BODY_ADD_STP_PORT_CH += ' } } } ] } } ] } }'
BODY_ADD_PORT_CH_P2 = BODY_PORT_CH_BEG + ', "ctrl": "graceful-conv"'
BODY_ADD_PORT_CH_P2 += '} } } ] } },'
BODY_ADD_PORT_CH_P2 += BODY_ADD_STP_PORT_CH
BODY_ADD_PORT_CH_P2 += '] } }'
BODY_DEL_PORT_CH = BODY_PORT_CH_BEG + ', "status": "deleted" } '
BODY_DEL_PORT_CH += BODY_PORT_CH_END
BODY_ADD_CH_GRP = BODY_PORT_CH_BEG + ', "isExplicit": "no", '
BODY_ADD_CH_GRP += '"pcMode": "active" },'
BODY_ADD_CH_GRP += '"children": [ { "pcShadowAggrIf": {'
BODY_ADD_CH_GRP += '"attributes": { "id": "po%s" } } }, '
BODY_ADD_CH_GRP += '{ "pcRsMbrIfs": { "attributes": { '
BODY_ADD_CH_GRP += '"isMbrForce": "yes", '
BODY_ADD_CH_GRP += '"tDn": "sys/intf/%s"'
BODY_ADD_CH_GRP += '} } } ] ' + BODY_PORT_CH_END
BODY_DEL_CH_GRP = BODY_PORT_CH_BEG + ' },'
BODY_DEL_CH_GRP += '"children": [ { "pcRsMbrIfs": {'
BODY_DEL_CH_GRP += ' "attributes": { "status": "deleted",'
BODY_DEL_CH_GRP += '"tDn": "sys/intf/%s"'
BODY_DEL_CH_GRP += '} } } ] ' + BODY_PORT_CH_END
# conf t
# vlan <n>
# state active
@ -66,8 +109,9 @@ PATH_IF = 'api/mo/sys/intf/%s.json'
# switchport trunk allowed vlan none | add <vlan> | remove <vlan>
# first %s is "l1PhysIf" | "pcAggrIf", 2nd trunkvlan string, 3rd one
# native vlan
BODY_TRUNKVLAN = '{"%s": {"attributes": {"trunkVlans": "%s"}}}'
BODY_NATIVE_TRUNKVLAN = '{"%s": {"attributes": {"trunkVlans": "%s",'
BODY_PORT_CH_MODE = '"mode": "trunk",'
BODY_TRUNKVLAN = '{"%s": {"attributes": {%s "trunkVlans": "%s"}}}'
BODY_NATIVE_TRUNKVLAN = '{"%s": {"attributes": {%s "trunkVlans": "%s",'
BODY_NATIVE_TRUNKVLAN += ' "nativeVlan": "%s"}}}'
# conf t

View File

@ -19,6 +19,8 @@ from oslo_config import cfg
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
config as cisco_config)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_helpers as nexus_help)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import nexus_db_v2
from neutron.tests.unit import testlib_api
@ -92,7 +94,10 @@ class TestCiscoNexusPluginConfig(testlib_api.SqlTestCase):
for map in maps_sorted:
self.assertEqual(map[0], host_map_data[idx][0])
self.assertEqual(map[1], host_map_data[idx][1])
self.assertEqual(map[2], host_map_data[idx][2])
if_type, port = nexus_help.split_interface_name(
host_map_data[idx][2])
eth_name = nexus_help.format_interface_name(if_type, port)
self.assertEqual(map[2], eth_name)
self.assertEqual(map[3], 0)
self.assertTrue(map[4])
idx += 1

View File

@ -79,6 +79,7 @@ INSTANCE_PC = 'testpcvm'
INSTANCE_DUAL = 'testdualvm'
NEXUS_BAREMETAL_PORT_1 = 'Ethernet 1/10'
NEXUS_BAREMETAL_PORT_2 = 'Ethernet 1/20'
NEXUS_PORT_1 = 'ethernet:1/10'
NEXUS_PORT_2 = 'ethernet:1/20'
NEXUS_PORT_3 = 'ethernet:1/30'
@ -414,6 +415,48 @@ class TestCiscoNexusBase(testlib_api.SqlTestCase):
def _clear_port_dbs(self):
nexus_db_v2.remove_all_nexusport_bindings()
def _set_switch_state(self, port_cfg, state):
# not baremetal transaction
if port_cfg.nexus_ip_addr:
self._cisco_mech_driver.set_switch_ip_and_active_state(
port_cfg.nexus_ip_addr, state)
else: # baremetal transaction
if port_cfg.profile:
all_link_info = port_cfg.profile['local_link_information']
for link_info in all_link_info:
ip_addr = link_info['switch_info']['switch_ip']
self._cisco_mech_driver.set_switch_ip_and_active_state(
ip_addr, state)
def _get_ip_addrs(self, port_cfg):
# not baremetal transaction
if port_cfg.nexus_ip_addr:
if port_cfg.host_name.startswith('baremetal'):
maps = nexus_db_v2.get_host_mappings(port_cfg.host_name)
ipaddrs = []
for map in maps:
ipaddrs.append(map.switch_ip)
return ipaddrs
return [port_cfg.nexus_ip_addr]
else: # baremetal transaction
ipaddrs = []
all_link_info = port_cfg.profile['local_link_information']
for link_info in all_link_info:
ipaddrs.append(link_info['switch_info']['switch_ip'])
return ipaddrs
def _config_switch_cred(self, mech_instance, ip_addr):
mech_instance._nexus_switches[(ip_addr,
'ssh_port')] = NEXUS_SSH_PORT
mech_instance._nexus_switches[(ip_addr,
constants.USERNAME)] = 'admin'
mech_instance._nexus_switches[(ip_addr,
constants.PASSWORD)] = 'password'
mech_instance._nexus_switches[(ip_addr,
'physnet')] = PHYSNET
def setUp(self):
"""Sets up mock client, switch, and credentials dictionaries."""
@ -457,16 +500,23 @@ class TestCiscoNexusBase(testlib_api.SqlTestCase):
mech_instance._switch_state = {}
mech_instance._nexus_switches = collections.OrderedDict()
for name, config in self.test_configs.items():
ip_addr = config.nexus_ip_addr
host_name = config.host_name
nexus_ports = config.nexus_port
# baremetal config done differently
if not ip_addr:
continue
# if VNIC_TYPE is baremetal
# VMs that reference this baremetal
# do not configure an entry in the host mapping db
# since code learns this information.
if not config.nexus_ip_addr:
if not config.profile:
continue
all_link_info = config.profile['local_link_information']
for link_info in all_link_info:
nexus_ports = link_info['port_id']
ip_addr = link_info['switch_info']['switch_ip']
self._config_switch_cred(mech_instance, ip_addr)
else:
ip_addr = config.nexus_ip_addr
nexus_ports = config.nexus_port
## if VNIC_TYPE is baremetal
## VMs that reference this baremetal
## do not configure an entry in the host mapping db
## since code learns this information.
if (host_name is not HOST_NAME_UNUSED and
HOST_NAME_Baremetal not in host_name):
for nexus_port in nexus_ports.split(','):
@ -477,14 +527,7 @@ class TestCiscoNexusBase(testlib_api.SqlTestCase):
nexus_db_v2.add_host_mapping(
host_name, ip_addr, nexus_port,
0, True)
mech_instance._nexus_switches[(ip_addr,
'ssh_port')] = NEXUS_SSH_PORT
mech_instance._nexus_switches[(ip_addr,
constants.USERNAME)] = 'admin'
mech_instance._nexus_switches[(ip_addr,
constants.PASSWORD)] = 'password'
mech_instance._nexus_switches[(ip_addr,
const.PHYSNET)] = PHYSNET
self._config_switch_cred(mech_instance, ip_addr)
mech_instance.driver.nexus_switches = (
mech_instance._nexus_switches)
mech_instance.context = bc.get_context()
@ -580,7 +623,7 @@ class TestCiscoNexusBase(testlib_api.SqlTestCase):
port_context.current, port_config.host_name)
# for port_id in port_config.nexus_port.split(','):
for switch_ip, intf_type, port, is_p_vlan in connections:
for switch_ip, intf_type, port, is_p_vlan, _ in connections:
if switch_ip is not port_config.nexus_ip_addr:
continue
port_id = intf_type + ':' + port
@ -657,7 +700,7 @@ class TestCiscoNexusBase(testlib_api.SqlTestCase):
port_context.current, port_config.host_name)
# for port_id in port_config.nexus_port.split(','):
for switch_ip, intf_type, port, is_p_vlan in connections:
for switch_ip, intf_type, port, is_p_vlan, _ in connections:
if switch_ip is not port_config.nexus_ip_addr:
continue
port_id = intf_type + ':' + port
@ -702,18 +745,23 @@ class TestCiscoNexusBase(testlib_api.SqlTestCase):
# Configure port entry config which puts switch in inactive state
self._create_port(other_test)
# Verify it's in the port binding data base
# Add one to count for the reserved switch state entry
# if replay is enabled
port_cfg = other_test
if self._cisco_mech_driver.is_replay_enabled():
nbr_of_bindings += 1
try:
port_bindings = nexus_db_v2.get_nexusport_switch_bindings(
port_cfg.nexus_ip_addr)
except exceptions.NexusPortBindingNotFound:
port_bindings = []
self.assertEqual(nbr_of_bindings, len(port_bindings))
ipaddrs = self._get_ip_addrs(port_cfg)
bindings_found = 0
for ipaddr in ipaddrs:
try:
port_bindings = nexus_db_v2.get_nexusport_switch_bindings(
ipaddr)
bindings_found += len(port_bindings)
# Verify it's in the port binding data base
# Add one to count for the reserved switch state entry
# if replay is enabled
if self._cisco_mech_driver.is_replay_enabled():
nbr_of_bindings += 1
except exceptions.NexusPortBindingNotFound:
pass
self.assertEqual(nbr_of_bindings, bindings_found)
# Make sure there is only a single attempt to configure.
self._verify_results(test_result)
@ -737,21 +785,25 @@ class TestCiscoNexusBase(testlib_api.SqlTestCase):
# Verify failure stats is not reset and
# verify no driver transactions have been sent
port_cfg = other_test
if self._cisco_mech_driver.is_replay_enabled():
# Add one for the reserved switch state entry
nbr_of_bindings += 1
try:
port_bindings = nexus_db_v2.get_nexusport_switch_bindings(
port_cfg.nexus_ip_addr)
except exceptions.NexusPortBindingNotFound:
port_bindings = []
self.assertEqual(nbr_of_bindings, len(port_bindings))
ipaddrs = self._get_ip_addrs(port_cfg)
bindings_found = 0
for ipaddr in ipaddrs:
try:
port_bindings = nexus_db_v2.get_nexusport_switch_bindings(
ipaddr)
bindings_found += len(port_bindings)
if self._cisco_mech_driver.is_replay_enabled():
# Add one for the reserved switch state entry
nbr_of_bindings += 1
except exceptions.NexusPortBindingNotFound:
pass
self.assertEqual(nbr_of_bindings, bindings_found)
port_context = self._generate_port_context(other_test)
if self._cisco_mech_driver._is_baremetal(port_context.current):
connections = self._cisco_mech_driver._get_baremetal_connections(
port_context.current, False, True)
for switch_ip, intf_type, port, is_p_vlan in connections:
for switch_ip, intf_type, port, is_p_vlan, _ in connections:
port_id = intf_type + ':' + port
try:
host_mapping = nexus_db_v2.get_switch_if_host_mappings(
@ -1015,30 +1067,30 @@ class TestCiscoNexusReplayBase(TestCiscoNexusBase):
# Set all required connection state to True so
# configurations will succeed
port_cfg = self.test_configs[test1]
self._cisco_mech_driver.set_switch_ip_and_active_state(
port_cfg.nexus_ip_addr, const.SWITCH_ACTIVE)
port_cfg = self.test_configs[test2]
self._cisco_mech_driver.set_switch_ip_and_active_state(
port_cfg.nexus_ip_addr, const.SWITCH_ACTIVE)
self._set_switch_state(port_cfg, const.SWITCH_ACTIVE)
if test2:
port_cfg = self.test_configs[test2]
self._set_switch_state(port_cfg, const.SWITCH_ACTIVE)
self._basic_create_verify_port_vlan(
test1, add_result1['driver_results'],
add_result1['nbr_db_entries'])
self._basic_create_verify_port_vlan(
test2, add_result2['driver_results'],
add_result2['nbr_db_entries'])
if test2:
self._basic_create_verify_port_vlan(
test2, add_result2['driver_results'],
add_result2['nbr_db_entries'])
# Set all connection state to False for
# test case HOST_1, NEXUS_IP_ADDRESS_1
cfg_type = ['test_replay_unique1',
'test_replay_duplvlan1',
'test_replay_duplport1']
'test_replay_duplport1',
'test_replay_unique_vPC']
for which_cfg in cfg_type:
if which_cfg in [test1, test2]:
state = const.SWITCH_INACTIVE
port_cfg = self.test_configs[which_cfg]
self._cisco_mech_driver.set_switch_ip_and_active_state(
port_cfg.nexus_ip_addr, state)
self._set_switch_state(port_cfg, const.SWITCH_INACTIVE)
if replay_init:
replay_init()
@ -1047,19 +1099,22 @@ class TestCiscoNexusReplayBase(TestCiscoNexusBase):
self._cfg_monitor.check_connections()
if not replay_result:
replay_result = (if_init_result +
add_result1['driver_results'] +
add_result2['driver_results'])
add_result1['driver_results'])
if test2:
replay_result = (replay_result +
add_result2['driver_results'])
self._verify_results(replay_result)
# Clear mock_call history so we can evaluate
# just the result of replay()
self.mock_ncclient.reset_mock()
if 'nbr_db_mappings' in del_result1:
if test2 and 'nbr_db_mappings' in del_result1:
nbr_db_mappings = del_result1['nbr_db_mappings']
else:
nbr_db_mappings = 0
self._basic_delete_verify_port_vlan(
if test2:
self._basic_delete_verify_port_vlan(
test2, del_result1['driver_results'],
del_result1['nbr_db_entries'],
nbr_db_mappings)

View File

@ -209,3 +209,60 @@ class CiscoNexusDbTest(testlib_api.SqlTestCase):
npb33 = self._npb_test_obj(30, 300, switch='1.1.1.1', instance='test')
with testtools.ExpectedException(exceptions.NexusPortBindingNotFound):
nexus_db_v2.update_nexusport_binding(npb33.port, 200)
class TestCiscoNexusVpcAllocDbTest(testlib_api.SqlTestCase):
"""Unit tests for Cisco mechanism driver's Nexus vpc alloc database."""
def setUp(self):
super(TestCiscoNexusVpcAllocDbTest, self).setUp()
def test_vpcalloc_init(self):
nexus_ips = ['1.1.1.1', '2.2.2.2', '3.3.3.3']
for this_ip in nexus_ips:
nexus_db_v2.init_vpc_entries(this_ip, 1001, 1025)
allocs = nexus_db_v2.get_free_switch_vpc_allocs(this_ip)
self.assertEqual(len(allocs), 25)
nexus_db_v2.update_vpc_entry('1.1.1.1', 1001, False, True)
nexus_db_v2.update_vpc_entry('2.2.2.2', 1002, False, True)
nexus_db_v2.update_vpc_entry('3.3.3.3', 1003, False, True)
new_vpcid = nexus_db_v2.alloc_vpcid(nexus_ips)
self.assertEqual(new_vpcid, 1004)
nexus_db_v2.free_vpcid_for_switch(1002, '2.2.2.2')
nexus_db_v2.free_vpcid_for_switch_list(1004, nexus_ips)
new_vpcid = nexus_db_v2.alloc_vpcid(nexus_ips)
self.assertEqual(new_vpcid, 1002)
def test_vpcalloc_min_max(self):
# Initialize 3 switch vpc entries
nexus_db_v2.init_vpc_entries('1.1.1.1', 1001, 2000)
nexus_db_v2.init_vpc_entries('2.2.2.2', 2001, 3000)
nexus_db_v2.init_vpc_entries('3.3.3.3', 3001, 4000)
# Verify get_switch_vpc_count_min_max() returns correct
# count, min, max values for all 3 switches.
count, min, max = nexus_db_v2.get_switch_vpc_count_min_max(
'1.1.1.1')
self.assertEqual(count, 1000)
self.assertEqual(min, 1001)
self.assertEqual(max, 2000)
count, min, max = nexus_db_v2.get_switch_vpc_count_min_max(
'2.2.2.2')
self.assertEqual(count, 1000)
self.assertEqual(min, 2001)
self.assertEqual(max, 3000)
count, min, max = nexus_db_v2.get_switch_vpc_count_min_max(
'3.3.3.3')
self.assertEqual(count, 1000)
self.assertEqual(min, 3001)
self.assertEqual(max, 4000)

View File

@ -1085,16 +1085,6 @@ class TestCiscoNexusBaremetalResults(
format('ethernet', '1\/10', 265),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(265)]),
'add_port_channel_driver_result': (
[test_cisco_nexus_base.RESULT_ADD_VLAN.format(267),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', 267)]),
'delete_port_channel_driver_result': (
[test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '469', 267),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(267)]),
'add_port_ethernet_native_driver_result': (
[test_cisco_nexus_base.RESULT_ADD_VLAN.format(265),
(test_cisco_nexus_base.RESULT_ADD_NATIVE_INTERFACE.
@ -1109,7 +1099,40 @@ class TestCiscoNexusBaremetalResults(
'[\x00-\x7f]+' +
test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('ethernet', '1\/10', 265)),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(265)])
test_cisco_nexus_base.RESULT_DEL_VLAN.format(265)]),
'driver_result_unique_vPC_add1': (
[test_cisco_nexus_base.RESULT_ADD_VLAN.format(267),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', 267),
test_cisco_nexus_base.RESULT_ADD_VLAN.format(267),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', 267)]),
'driver_result_unique_vPC_del1': (
[test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '469', 267),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(267),
test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '469', 267),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(267)]),
'driver_result_unique_vPC_add1_vm': (
[test_cisco_nexus_base.RESULT_ADD_VLAN.format(265),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', 265),
test_cisco_nexus_base.RESULT_ADD_VLAN.format(265),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', 265)]),
'driver_result_unique_vPC_del1_vm': (
[test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '469', 265),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(265),
test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '469', 265),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(265)]),
}
@ -1129,6 +1152,25 @@ class TestCiscoNexusBaremetalDevice(test_cisco_nexus_base.TestCiscoNexusBase):
]
}
baremetal_profile_vPC = {
"local_link_information": [
{
"port_id": test_cisco_nexus_base.NEXUS_BAREMETAL_PORT_1,
"switch_info": {
"is_native": False,
"switch_ip": test_cisco_nexus_base.NEXUS_IP_ADDRESS_1,
},
},
{
"port_id": test_cisco_nexus_base.NEXUS_BAREMETAL_PORT_2,
"switch_info": {
"is_native": False,
"switch_ip": test_cisco_nexus_base.NEXUS_IP_ADDRESS_2,
},
},
]
}
baremetal_profile_is_native = {
"local_link_information": [
{
@ -1172,6 +1214,19 @@ class TestCiscoNexusBaremetalDevice(test_cisco_nexus_base.TestCiscoNexusBase):
{},
None,
test_cisco_nexus_base.NORMAL_VNIC),
'test_config_vPC':
test_cisco_nexus_base.TestCiscoNexusBase.TestConfigObj(
None,
test_cisco_nexus_base.HOST_NAME_UNUSED,
test_cisco_nexus_base.NEXUS_BAREMETAL_PORT_1,
test_cisco_nexus_base.INSTANCE_1,
test_cisco_nexus_base.VLAN_ID_1,
test_cisco_nexus_base.NO_VXLAN_ID,
None,
test_cisco_nexus_base.DEVICE_OWNER_BAREMETAL,
baremetal_profile_vPC,
test_cisco_nexus_base.HOST_NAME_Baremetal + '1',
test_cisco_nexus_base.BAREMETAL_VNIC),
'test_config_native':
test_cisco_nexus_base.TestCiscoNexusBase.TestConfigObj(
test_cisco_nexus_base.NEXUS_IP_ADDRESS_1,
@ -1194,7 +1249,7 @@ class TestCiscoNexusBaremetalDevice(test_cisco_nexus_base.TestCiscoNexusBase):
super(TestCiscoNexusBaremetalDevice, self).setUp()
self.results = TestCiscoNexusBaremetalResults()
def _init_port_channel(self):
def _init_port_channel(self, which=1):
# this is to prevent interface initialization from occurring
# which adds unnecessary noise to the results.
data_xml = {'connect.return_value.get.return_value.data_xml':
@ -1234,20 +1289,61 @@ class TestCiscoNexusBaremetalDevice(test_cisco_nexus_base.TestCiscoNexusBase):
def test_create_delete_basic_port_channel(self):
"""Basic creation and deletion test of 1 port-channel."""
self._init_port_channel()
self._init_port_channel(3)
self._basic_create_verify_port_vlan(
'test_config1',
'test_config_vPC',
self.results.get_test_results(
'add_port_channel_driver_result'))
'driver_result_unique_vPC_add1'),
nbr_of_bindings=2)
# Clean all the ncclient mock_calls so we can evaluate
# results of delete operations.
self.mock_ncclient.reset_mock()
self._basic_delete_verify_port_vlan(
'test_config1',
'test_config_vPC',
self.results.get_test_results(
'delete_port_channel_driver_result'))
'driver_result_unique_vPC_del1'))
def test_create_delete_learn_vpc_and_vm(self):
"""Basic creation and deletion test of 2 learn port-channel and vm."""
switch_list = ['1.1.1.1', '2.2.2.2']
self._init_port_channel(3)
for switch_ip in switch_list:
nexus_db_v2.init_vpc_entries(switch_ip, 451, 475)
self._basic_create_verify_port_vlan(
'test_config_vPC',
self.results.get_test_results(
'driver_result_unique_vPC_add1'),
nbr_of_bindings=2)
# Clean all the ncclient mock_calls so we can evaluate
# results of delete operations.
self.mock_ncclient.reset_mock()
self._basic_create_verify_port_vlan(
'test_config_vm',
self.results.get_test_results(
'driver_result_unique_vPC_add1_vm'),
nbr_of_bindings=4)
self._basic_delete_verify_port_vlan(
'test_config_vm',
self.results.get_test_results(
'driver_result_unique_vPC_del1_vm'),
nbr_of_bindings=2)
self._basic_delete_verify_port_vlan(
'test_config_vPC',
self.results.get_test_results(
'driver_result_unique_vPC_del1'))
for switch_ip in switch_list:
self.assertEqual(
25, len(nexus_db_v2.get_free_switch_vpc_allocs(switch_ip)))
def test_create_delete_basic_eth_port_is_native(self):
"""Basic creation and deletion test of 1 ethernet port."""
@ -1326,19 +1422,19 @@ class TestCiscoNexusBaremetalDevice(test_cisco_nexus_base.TestCiscoNexusBase):
def test_new_host_mapping_db(self):
nexus_db_v2.add_host_mapping(
"host-1", "1.1.1.1", "ethernet:1/1", 0, False)
"host-1", "110.1.1.1", "ethernet:1/1", 0, False)
nexus_db_v2.add_host_mapping(
"host-1", "2.2.2.2", "ethernet:1/1", 0, False)
"host-1", "112.2.2.2", "ethernet:1/1", 0, False)
nexus_db_v2.add_host_mapping(
"host-2", "1.1.1.1", "ethernet:2/2", 0, False)
"host-2", "110.1.1.1", "ethernet:2/2", 0, False)
nexus_db_v2.add_host_mapping(
"host-3", "3.3.3.3", "ethernet:3/3", 0, True)
"host-3", "113.3.3.3", "ethernet:3/3", 0, True)
nexus_db_v2.add_host_mapping(
"host-4", "4.4.4.4", "ethernet:4/4", 0, True)
"host-4", "114.4.4.4", "ethernet:4/4", 0, True)
# Do a get 1.1.1.1 and verify only host-1 is returned
# Do a get 110.1.1.1 and verify only host-1 is returned
mappings = nexus_db_v2.get_switch_if_host_mappings(
"1.1.1.1", "ethernet:1/1")
"110.1.1.1", "ethernet:1/1")
self.assertEqual(
len(mappings),
1,
@ -1368,8 +1464,8 @@ class TestCiscoNexusBaremetalDevice(test_cisco_nexus_base.TestCiscoNexusBase):
"Expecting interface returned from "
"get_host_mappings")
# Do a get on switch 1.1.1.1 and verify 2 entries returned
mappings = nexus_db_v2.get_switch_host_mappings("1.1.1.1")
# Do a get on switch 110.1.1.1 and verify 2 entries returned
mappings = nexus_db_v2.get_switch_host_mappings("110.1.1.1")
self.assertEqual(
len(mappings),
2,
@ -1377,7 +1473,7 @@ class TestCiscoNexusBaremetalDevice(test_cisco_nexus_base.TestCiscoNexusBase):
for map in mappings:
self.assertEqual(
map.switch_ip,
"1.1.1.1",
"110.1.1.1",
"Expecting switch_ip returned from "
"get_switch_host_mappings")
@ -1385,7 +1481,7 @@ class TestCiscoNexusBaremetalDevice(test_cisco_nexus_base.TestCiscoNexusBase):
nexus_db_v2.update_host_mapping(
"host-2",
"ethernet:2/2",
"1.1.1.1",
"110.1.1.1",
2)
mappings = nexus_db_v2.get_host_mappings("host-2")
self.assertEqual(
@ -1406,7 +1502,7 @@ class TestCiscoNexusBaremetalDevice(test_cisco_nexus_base.TestCiscoNexusBase):
# remove 1 host mapping
nexus_db_v2.remove_host_mapping(
"ethernet:2/2", "1.1.1.1")
"ethernet:2/2", "110.1.1.1")
# Verify it is gone
self.assertRaises(
exceptions.NexusHostMappingNotFound,
@ -1429,9 +1525,9 @@ class TestCiscoNexusBaremetalDevice(test_cisco_nexus_base.TestCiscoNexusBase):
# remove host mappings
nexus_db_v2.remove_host_mapping(
"ethernet:1/1", "2.2.2.2")
"ethernet:1/1", "112.2.2.2")
nexus_db_v2.remove_host_mapping(
"ethernet:1/1", "1.1.1.1")
"ethernet:1/1", "110.1.1.1")
# Verify it is gone
self.assertRaises(
exceptions.NexusHostMappingNotFound,

View File

@ -947,28 +947,20 @@ class TestCiscoNexusBaremetalReplayResults(
format('ethernet', '1\/10', 267),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(267)]),
'driver_result_unique_vPC_init': (
[test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', 'None')]),
'driver_result_unique_vPC_add1': (
'driver_result_unique_vPC_2switch_add1': (
[test_cisco_nexus_base.RESULT_ADD_VLAN.format(267),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', 267),
test_cisco_nexus_base.RESULT_ADD_VLAN.format(267),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', 267)]),
'driver_result_unique_vPC_add2': (
[test_cisco_nexus_base.RESULT_ADD_VLAN.format(265),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', 265)]),
'driver_result_unique_vPC_del1': (
[test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '469', 265),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(265)]),
'driver_result_unique_vPC_del2': (
'driver_result_unique_vPC_2switch_del1': (
[test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '469', 267),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(267),
test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '469', 267),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(267)]),
'driver_result_unique_native_port_ethernet_add': (
@ -992,29 +984,52 @@ class TestCiscoNexusBaremetalReplayResults(
format('ethernet', '1\/10', '265,267'),
test_cisco_nexus_base.RESULT_ADD_VLAN.format('265,267')]),
'driver_result_unique_2vlan_vpc_replay': (
'driver_result_unique_vPC_2if_replay': (
[test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', '265,267'),
test_cisco_nexus_base.RESULT_ADD_VLAN.format('265,267')]),
format('port-channel', '469', 267),
test_cisco_nexus_base.RESULT_ADD_VLAN.format(267),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', 267),
test_cisco_nexus_base.RESULT_ADD_VLAN.format(267)]),
'driver_result_unique_vPC470_add1': (
[test_cisco_nexus_base.RESULT_ADD_VLAN.format(267),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '470', 267),
test_cisco_nexus_base.RESULT_ADD_VLAN.format(267),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '470', 267)]),
'driver_result_unique_vPC470_add2': (
[test_cisco_nexus_base.RESULT_ADD_VLAN.format(265),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '470', 265),
test_cisco_nexus_base.RESULT_ADD_VLAN.format(265),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '470', 265)]),
'driver_result_unique_vPC470_del1': (
[test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '470', 265),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(265),
test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '470', 265),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(265)]),
'driver_result_unique_vPC470_del2': (
[test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '470', 267),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(267),
test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '470', 267),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(267)]),
'driver_result_unique_vPC470_2vlan_replay': (
[test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '470', '265,267'),
test_cisco_nexus_base.RESULT_ADD_VLAN.format('265,267')]),
'driver_result_unique_2vlan_vpc_enchg_replay': (
[test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('ethernet', '1\/10', '265,267'),
test_cisco_nexus_base.RESULT_ADD_VLAN.format('265,267'),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '470', '265,267'),
test_cisco_nexus_base.RESULT_ADD_VLAN.format('265,267')]),
'driver_result_unique_native_2vlan_replay': (
@ -1025,7 +1040,24 @@ class TestCiscoNexusBaremetalReplayResults(
format('ethernet', '1\/10', '265')),
(test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('ethernet', '1\/10', '265,267')),
test_cisco_nexus_base.RESULT_ADD_VLAN.format('265,267')])
test_cisco_nexus_base.RESULT_ADD_VLAN.format('265,267')]),
'driver_result_unique_vPC_add1_vm': (
[test_cisco_nexus_base.RESULT_ADD_VLAN.format(265),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', 265),
test_cisco_nexus_base.RESULT_ADD_VLAN.format(265),
test_cisco_nexus_base.RESULT_ADD_INTERFACE.
format('port-channel', '469', 265)]),
'driver_result_unique_vPC_del1_vm': (
[test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '469', 265),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(265),
test_cisco_nexus_base.RESULT_DEL_INTERFACE.
format('port-channel', '469', 265),
test_cisco_nexus_base.RESULT_DEL_VLAN.format(265)]),
}
@ -1046,6 +1078,25 @@ class TestCiscoNexusBaremetalReplay(
]
}
baremetal_profile_vPC = {
"local_link_information": [
{
"port_id": test_cisco_nexus_base.NEXUS_BAREMETAL_PORT_1,
"switch_info": {
"is_native": False,
"switch_ip": test_cisco_nexus_base.NEXUS_IP_ADDRESS_1,
},
},
{
"port_id": test_cisco_nexus_base.NEXUS_BAREMETAL_PORT_2,
"switch_info": {
"is_native": False,
"switch_ip": test_cisco_nexus_base.NEXUS_IP_ADDRESS_2,
},
},
]
}
baremetal_profile_is_native = {
"local_link_information": [
{
@ -1061,7 +1112,7 @@ class TestCiscoNexusBaremetalReplay(
test_configs = {
'test_replay_unique1':
test_cisco_nexus_base.TestCiscoNexusBase.TestConfigObj(
test_cisco_nexus_base.NEXUS_IP_ADDRESS_1,
None,
test_cisco_nexus_base.HOST_NAME_UNUSED,
test_cisco_nexus_base.NEXUS_BAREMETAL_PORT_1,
test_cisco_nexus_base.INSTANCE_1,
@ -1074,7 +1125,7 @@ class TestCiscoNexusBaremetalReplay(
test_cisco_nexus_base.BAREMETAL_VNIC),
'test_replay_unique2':
test_cisco_nexus_base.TestCiscoNexusBase.TestConfigObj(
test_cisco_nexus_base.NEXUS_IP_ADDRESS_1,
None,
test_cisco_nexus_base.HOST_NAME_UNUSED,
test_cisco_nexus_base.NEXUS_BAREMETAL_PORT_1,
test_cisco_nexus_base.INSTANCE_2,
@ -1085,9 +1136,22 @@ class TestCiscoNexusBaremetalReplay(
baremetal_profile,
test_cisco_nexus_base.HOST_NAME_Baremetal + '1',
test_cisco_nexus_base.BAREMETAL_VNIC),
'test_replay_unique_vPC':
test_cisco_nexus_base.TestCiscoNexusBase.TestConfigObj(
None,
test_cisco_nexus_base.HOST_NAME_UNUSED,
test_cisco_nexus_base.NEXUS_BAREMETAL_PORT_1,
test_cisco_nexus_base.INSTANCE_1,
test_cisco_nexus_base.VLAN_ID_1,
test_cisco_nexus_base.NO_VXLAN_ID,
None,
test_cisco_nexus_base.DEVICE_OWNER_BAREMETAL,
baremetal_profile_vPC,
test_cisco_nexus_base.HOST_NAME_Baremetal + '1',
test_cisco_nexus_base.BAREMETAL_VNIC),
'test_replay_unique_native1':
test_cisco_nexus_base.TestCiscoNexusBase.TestConfigObj(
test_cisco_nexus_base.NEXUS_IP_ADDRESS_1,
None,
test_cisco_nexus_base.HOST_NAME_UNUSED,
test_cisco_nexus_base.NEXUS_BAREMETAL_PORT_1,
test_cisco_nexus_base.INSTANCE_2,
@ -1122,7 +1186,7 @@ class TestCiscoNexusBaremetalReplay(
super(TestCiscoNexusBaremetalReplay, self).setUp()
self.results = TestCiscoNexusBaremetalReplayResults()
def _init_port_channel(self, ch_grp):
def _init_port_channel(self, ch_grp, which=1):
# with Baremetal config when enet interface associated to port-channel,
# the port-channel interface is configured instead. This config
@ -1202,83 +1266,92 @@ class TestCiscoNexusBaremetalReplay(
first_add = {
'driver_results': self.results.get_test_results(
'driver_result_unique_vPC_add1'),
'nbr_db_entries': 1}
second_add = {
'driver_results': self.results.get_test_results(
'driver_result_unique_vPC_add2'),
'driver_result_unique_vPC_2switch_add1'),
'nbr_db_entries': 2}
first_del = {
'driver_results': self.results.get_test_results(
'driver_result_unique_vPC_del1'),
'nbr_db_entries': 1,
'nbr_db_mappings': 1}
second_del = {
'driver_results': self.results.get_test_results(
'driver_result_unique_vPC_del2'),
'driver_result_unique_vPC_2switch_del1'),
'nbr_db_entries': 0}
self._init_port_channel(469)
self._process_replay(
'test_replay_unique1',
'test_replay_unique2',
self.results.get_test_results(
'driver_result_unique_vPC_init'),
'test_replay_unique_vPC',
None,
[],
first_add,
second_add,
None,
self.results.get_test_results(
'driver_result_unique_2vlan_vpc_replay'),
first_del,
'driver_result_unique_vPC_2if_replay'),
None,
second_del)
def test_replay_unique_vPC_ports_chg_vPC_nbr(self):
def test_replay_unique_vPC_ports_and_vm(self):
"""Provides replay data and result data for unique ports. """
self.skipTest("Disable until HN-72 automated vPC implemented")
def replay_init():
# This causes port-channel 470 to get configured instead.
self._init_port_channel(470)
first_add = {
'driver_results': self.results.get_test_results(
'driver_result_unique_vPC_add1'),
'nbr_db_entries': 1}
'driver_result_unique_vPC470_add1'),
'nbr_db_entries': 2}
second_add = {
'driver_results': self.results.get_test_results(
'driver_result_unique_vPC_add2'),
'nbr_db_entries': 2}
'driver_result_unique_vPC470_add2'),
'nbr_db_entries': 4}
first_del = {
'driver_results': self.results.get_test_results(
'driver_result_unique_vPC470_del1'),
'nbr_db_entries': 1}
'nbr_db_entries': 2}
second_del = {
'driver_results': self.results.get_test_results(
'driver_result_unique_vPC470_del2'),
'nbr_db_entries': 0}
# This is to cause port-channel 469 to get configured
self._init_port_channel(469)
self._init_port_channel(470)
# Providing replay_init to change channel-group
self._process_replay(
'test_replay_unique1',
'test_replay_unique2',
self.results.get_test_results(
'driver_result_unique_vPC_init'),
'test_replay_unique_vPC',
'test_config_vm',
[],
first_add,
second_add,
self.results.get_test_results(
'driver_result_unique_vPC470_2vlan_replay'),
first_del,
second_del)
def test_replay_unique_vPC_ports_chg_vPC_nbr(self):
"""Persist with learned channel group even if it changed."""
def replay_init():
# This causes port-channel 469 will persist instead.
# We will not relearn
self._init_port_channel(470)
first_add = {
'driver_results': self.results.get_test_results(
'driver_result_unique_vPC_2switch_add1'),
'nbr_db_entries': 2}
second_del = {
'driver_results': self.results.get_test_results(
'driver_result_unique_vPC_2switch_del1'),
'nbr_db_entries': 0}
self._init_port_channel(469)
self._process_replay(
'test_replay_unique_vPC',
None,
[],
first_add,
None,
self.results.get_test_results(
'driver_result_unique_vPC_2if_replay'),
None,
second_del,
replay_init)
def test_replay_unique_vPC_ports_chg_to_enet(self):
"""Provides replay data and result data for unique ports. """
self.skipTest("Disable until HN-72 automated vPC implemented")
"""Persist with learned channel group even if it was removed."""
def replay_init():
# This causes port-channel to get replaced with enet
@ -1290,34 +1363,24 @@ class TestCiscoNexusBaremetalReplay(
first_add = {
'driver_results': self.results.get_test_results(
'driver_result_unique_vPC_add1'),
'nbr_db_entries': 1}
second_add = {
'driver_results': self.results.get_test_results(
'driver_result_unique_vPC_add2'),
'driver_result_unique_vPC_2switch_add1'),
'nbr_db_entries': 2}
first_del = {
'driver_results': self.results.get_test_results(
'driver_result_unique_eth_del1'),
'nbr_db_entries': 1}
second_del = {
'driver_results': self.results.get_test_results(
'driver_result_unique_eth_del2'),
'driver_result_unique_vPC_2switch_del1'),
'nbr_db_entries': 0}
self._init_port_channel(469)
# Providing replay_init to remove port-channel
self._process_replay(
'test_replay_unique1',
'test_replay_unique2',
self.results.get_test_results(
'driver_result_unique_vPC_init'),
'test_replay_unique_vPC',
None,
[],
first_add,
second_add,
None,
self.results.get_test_results(
'driver_result_unique_2vlan_vpc_enchg_replay'),
first_del,
'driver_result_unique_vPC_2if_replay'),
None,
second_del,
replay_init)

View File

@ -29,6 +29,8 @@ redundant.
from oslo_config import cfg
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_db_v2 as nxos_db)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_restapi_snippets as snipp)
from networking_cisco.tests.unit.ml2.drivers.cisco.nexus import (
@ -43,19 +45,19 @@ class TestCiscoNexusRestDeviceResults(base.TestCiscoNexusBaseResults):
test_results = {
'duplicate_add_port_driver_result': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
'duplicate_del_port_driver_result': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_1,
@ -63,19 +65,19 @@ class TestCiscoNexusRestDeviceResults(base.TestCiscoNexusBaseResults):
base.DELETE]
],
'add_port2_driver_result': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+265')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+265')),
base.POST]
],
'delete_port2_driver_result': [
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-265')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_1,
@ -83,43 +85,43 @@ class TestCiscoNexusRestDeviceResults(base.TestCiscoNexusBaseResults):
base.DELETE]
],
'add_port2_driver_result2': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
'delete_port2_driver_result2': [
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST]
],
'add_port2_driver_result3': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_6,
(snipp.BODY_VLAN_ADD % 268),
base.POST],
[(snipp.PATH_IF % 'aggr-[po2]'),
base.NEXUS_IP_ADDRESS_6,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '+268')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+268')),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_7,
(snipp.BODY_VLAN_ADD % 268),
base.POST],
[(snipp.PATH_IF % 'aggr-[po2]'),
base.NEXUS_IP_ADDRESS_7,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '+268')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+268')),
base.POST]
],
'delete_port2_driver_result3': [
[(snipp.PATH_IF % 'aggr-[po2]'),
base.NEXUS_IP_ADDRESS_6,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '-268')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-268')),
base.POST],
[(snipp.PATH_VLAN % '268'),
base.NEXUS_IP_ADDRESS_6,
@ -127,7 +129,7 @@ class TestCiscoNexusRestDeviceResults(base.TestCiscoNexusBaseResults):
base.DELETE],
[(snipp.PATH_IF % 'aggr-[po2]'),
base.NEXUS_IP_ADDRESS_7,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '-268')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-268')),
base.POST],
[(snipp.PATH_VLAN % '268'),
base.NEXUS_IP_ADDRESS_7,
@ -135,19 +137,19 @@ class TestCiscoNexusRestDeviceResults(base.TestCiscoNexusBaseResults):
base.DELETE]
],
'add_port_channel_driver_result': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 268),
base.POST],
[(snipp.PATH_IF % 'aggr-[po2]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '+268')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+268')),
base.POST]
],
'delete_port_channel_driver_result': [
[(snipp.PATH_IF % 'aggr-[po2]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '-268')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-268')),
base.POST],
[(snipp.PATH_VLAN % '268'),
base.NEXUS_IP_ADDRESS_2,
@ -155,27 +157,27 @@ class TestCiscoNexusRestDeviceResults(base.TestCiscoNexusBaseResults):
base.DELETE]
],
'dual_add_port_driver_result': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_VLAN_ADD % 269),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/3]'),
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+269')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+269')),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_VLAN_ADD % 269),
base.POST],
[(snipp.PATH_IF % 'aggr-[po2]'),
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '+269')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+269')),
base.POST]
],
'dual_delete_port_driver_result': [
[(snipp.PATH_IF % 'phys-[eth1/3]'),
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-269')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-269')),
base.POST],
[(snipp.PATH_VLAN % '269'),
base.NEXUS_IP_ADDRESS_DUAL,
@ -183,23 +185,23 @@ class TestCiscoNexusRestDeviceResults(base.TestCiscoNexusBaseResults):
base.DELETE],
[(snipp.PATH_IF % 'aggr-[po2]'),
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '-269')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-269')),
base.POST],
],
'add_port_driver_result': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
'del_port_driver_result': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_8,
@ -207,13 +209,13 @@ class TestCiscoNexusRestDeviceResults(base.TestCiscoNexusBaseResults):
base.DELETE]
],
'migrate_add_host2_driver_result': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_3,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_3,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
}
@ -279,52 +281,52 @@ class TestCiscoNexusRestInitResults(base.TestCiscoNexusBaseResults):
'duplicate_init_port_driver_result1': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '')),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '')),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '')),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '')),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/3]'),
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '')),
base.POST],
[(snipp.PATH_IF % 'aggr-[po2]'),
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '')),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_3,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '')),
base.POST],
[(snipp.PATH_IF % 'aggr-[po2]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '')),
base.POST],
[(snipp.PATH_IF % 'aggr-[po2]'),
base.NEXUS_IP_ADDRESS_6,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '')),
base.POST],
[(snipp.PATH_IF % 'aggr-[po2]'),
base.NEXUS_IP_ADDRESS_7,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '')),
base.POST],
],
@ -413,20 +415,20 @@ class TestCiscoNexusRestBaremetalResults(base.TestCiscoNexusBaseResults):
test_results = {
'add_port_ethernet_driver_result': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
'delete_port_ethernet_driver_result': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_1,
@ -435,20 +437,20 @@ class TestCiscoNexusRestBaremetalResults(base.TestCiscoNexusBaseResults):
],
'add_vm_port_ethernet_driver_result': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+265')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+265')),
base.POST]
],
'delete_vm_port_ethernet_driver_result': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-265')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_1,
@ -457,20 +459,20 @@ class TestCiscoNexusRestBaremetalResults(base.TestCiscoNexusBaseResults):
],
'add_port_channel_driver_result': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST]
],
'delete_port_channel_driver_result': [
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_1,
@ -479,20 +481,21 @@ class TestCiscoNexusRestBaremetalResults(base.TestCiscoNexusBaseResults):
],
'add_port_ethernet_native_driver_result': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_NATIVE_TRUNKVLAN % ('l1PhysIf', '+265', 'vlan-265')),
(snipp.BODY_NATIVE_TRUNKVLAN % (
'l1PhysIf', '', '+265', 'vlan-265')),
base.POST]
],
'delete_port_ethernet_native_driver_result': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_NATIVE_TRUNKVLAN % ('l1PhysIf', '-265', '')),
(snipp.BODY_NATIVE_TRUNKVLAN % ('l1PhysIf', '', '-265', '')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_1,
@ -500,10 +503,213 @@ class TestCiscoNexusRestBaremetalResults(base.TestCiscoNexusBaseResults):
base.DELETE]
],
'driver_result_unique_vPC_add1': [
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST]
],
'driver_result_unique_vPC_del1': [
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_1,
'',
base.DELETE],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_2,
'',
base.DELETE]
],
'driver_result_unique_vPC_add1_vm': [
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+265')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+265')),
base.POST]
],
'driver_result_unique_vPC_del1_vm': [
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_1,
'',
base.DELETE],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_2,
'',
base.DELETE]
],
'driver_result_unique_auto_vPC_vm_add1': [
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+265')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+265')),
base.POST]
],
'driver_result_unique_auto_vPC_vm_del1': [
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_1,
'',
base.DELETE],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_2,
'',
base.DELETE]
],
'driver_result_unique_auto_vPC_add1': [
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_ADD_PORT_CH % (1001, 1001, 1001)),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_ADD_PORT_CH_P2 % (1001, 1001)),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % (
'pcAggrIf', snipp.BODY_PORT_CH_MODE, '')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_ADD_CH_GRP % (1001, 1001, 'phys-[eth1/10]')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_ADD_PORT_CH % (1001, 1001, 1001)),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_ADD_PORT_CH_P2 % (1001, 1001)),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % (
'pcAggrIf', snipp.BODY_PORT_CH_MODE, '')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_ADD_CH_GRP % (1001, 1001, 'phys-[eth1/20]')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST]
],
'driver_result_unique_auto_vPC_del1': [
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_1,
'',
base.DELETE],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_DEL_CH_GRP % ('1001', 'phys-[eth1/10]')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_DEL_PORT_CH % ('1001')),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_2,
'',
base.DELETE],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_DEL_CH_GRP % ('1001', 'phys-[eth1/20]')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_DEL_PORT_CH % ('1001')),
base.POST]
],
}
GET_PORT_CH_RESPONSE = {
"totalCount": "3",
"totalCount": "4",
"imdata": [
{
"pcRsMbrIfs": {
@ -528,6 +734,14 @@ GET_PORT_CH_RESPONSE = {
"tSKey": "eth1/12",
}
}
},
{
"pcRsMbrIfs": {
"attributes": {
"parentSKey": "po469",
"tSKey": "eth1/20",
}
}
}
]
}
@ -555,11 +769,13 @@ class TestCiscoNexusRestBaremetalDevice(
return {}
def _init_port_channel(self):
def _init_port_channel(self, which=1):
# this is to prevent interface initialization from occurring
# which adds unnecessary noise to the results.
GET_PORT_CH_RESPONSE['imdata'][which]['pcRsMbrIfs'][
'attributes']['parentSKey'] = 'po469'
data_json = {'rest_get.side_effect':
self.get_init_side_effect}
self.mock_ncclient.configure_mock(**data_json)
@ -577,9 +793,14 @@ class TestCiscoNexusRestBaremetalDevice(
test_create_delete_basic_bm_ethernet_port_and_vm())
def test_create_delete_basic_port_channel(self):
"""Basic creation and deletion test of 1 learned port-channel."""
(super(TestCiscoNexusRestBaremetalDevice, self).
test_create_delete_basic_port_channel())
def test_create_delete_learn_vpc_and_vm(self):
(super(TestCiscoNexusRestBaremetalDevice, self).
test_create_delete_learn_vpc_and_vm())
def test_create_delete_basic_eth_port_is_native(self):
(super(TestCiscoNexusRestBaremetalDevice, self).
test_create_delete_basic_eth_port_is_native())
@ -588,6 +809,75 @@ class TestCiscoNexusRestBaremetalDevice(
(super(TestCiscoNexusRestBaremetalDevice, self).
test_create_delete_switch_ip_not_defined())
def test_automated_port_channel_creation_deletion(self):
"""Basic creation and deletion test of 1 auto port-channel."""
switch_list = ['1.1.1.1', '2.2.2.2']
for switch_ip in switch_list:
nxos_db.init_vpc_entries(switch_ip, 1001, 1025)
self._basic_create_verify_port_vlan(
'test_config_vPC',
self.results.get_test_results(
'driver_result_unique_auto_vPC_add1'),
nbr_of_bindings=2)
# Clean all the ncclient mock_calls so we can evaluate
# results of delete operations.
self.mock_ncclient.reset_mock()
self._basic_delete_verify_port_vlan(
'test_config_vPC',
self.results.get_test_results(
'driver_result_unique_auto_vPC_del1'))
for switch_ip in switch_list:
self.assertEqual(
25, len(nxos_db.get_free_switch_vpc_allocs(switch_ip)))
def test_create_delete_automated_vpc_and_vm(self):
"""Basic creation and deletion test of 2 auto port-channel and vm."""
switch_list = ['1.1.1.1', '2.2.2.2']
for switch_ip in switch_list:
nxos_db.init_vpc_entries(switch_ip, 1001, 1025)
self._basic_create_verify_port_vlan(
'test_config_vPC',
self.results.get_test_results(
'driver_result_unique_auto_vPC_add1'),
nbr_of_bindings=2)
# Clean all the ncclient mock_calls so we can evaluate
# results of delete operations.
self.mock_ncclient.reset_mock()
self._basic_create_verify_port_vlan(
'test_config_vm',
self.results.get_test_results(
'driver_result_unique_auto_vPC_vm_add1'),
nbr_of_bindings=4)
self._basic_delete_verify_port_vlan(
'test_config_vm',
self.results.get_test_results(
'driver_result_unique_auto_vPC_vm_del1'),
nbr_of_bindings=2)
self._basic_delete_verify_port_vlan(
'test_config_vPC',
self.results.get_test_results(
'driver_result_unique_auto_vPC_del1'))
for switch_ip in switch_list:
self.assertEqual(
25, len(nxos_db.get_free_switch_vpc_allocs(switch_ip)))
def test_failure_inconsistent_chgrp(self):
pass
# Skipped inheriting event class TestCiscoNexusNonCacheSshDevice
# since it does not apply to REST API

View File

@ -53,13 +53,13 @@ class TestCiscoNexusRestVxlanResults(base.TestCiscoNexusBaseResults):
'70000', '70000', '70000',
base.MCAST_GROUP)),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VXLAN_ADD % (267, 70000)),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
@ -70,7 +70,7 @@ class TestCiscoNexusRestVxlanResults(base.TestCiscoNexusBaseResults):
base.DELETE],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_1,
@ -80,20 +80,20 @@ class TestCiscoNexusRestVxlanResults(base.TestCiscoNexusBaseResults):
'add_port2_driver_result': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VXLAN_ADD % (267, 70000)),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
'delete_port2_driver_result': [
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST],
],
@ -110,29 +110,29 @@ class TestCiscoNexusRestVxlanResults(base.TestCiscoNexusBaseResults):
'70000', '70000', '70000',
base.MCAST_GROUP)),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_6,
(snipp.BODY_VXLAN_ADD % (267, 70000)),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_6,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_7,
(snipp.BODY_VXLAN_ADD % (267, 70000)),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/2]'),
base.NEXUS_IP_ADDRESS_7,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_7,
(snipp.BODY_VXLAN_ADD % (267, 70000)),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/3]'),
base.NEXUS_IP_ADDRESS_7,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
@ -147,7 +147,7 @@ class TestCiscoNexusRestVxlanResults(base.TestCiscoNexusBaseResults):
base.DELETE],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_6,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_6,
@ -155,7 +155,7 @@ class TestCiscoNexusRestVxlanResults(base.TestCiscoNexusBaseResults):
base.DELETE],
[(snipp.PATH_IF % 'phys-[eth1/2]'),
base.NEXUS_IP_ADDRESS_7,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_7,
@ -163,7 +163,7 @@ class TestCiscoNexusRestVxlanResults(base.TestCiscoNexusBaseResults):
base.DELETE],
[(snipp.PATH_IF % 'phys-[eth1/3]'),
base.NEXUS_IP_ADDRESS_7,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST],
],
@ -174,13 +174,13 @@ class TestCiscoNexusRestVxlanResults(base.TestCiscoNexusBaseResults):
'70001', '70001', '70001',
base.MCAST_GROUP)),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_VXLAN_ADD % (265, 70001)),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+265')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+265')),
base.POST]
],
@ -191,7 +191,7 @@ class TestCiscoNexusRestVxlanResults(base.TestCiscoNexusBaseResults):
base.DELETE],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-265')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_8,
@ -205,13 +205,13 @@ class TestCiscoNexusRestVxlanResults(base.TestCiscoNexusBaseResults):
'70000', '70000', '70000',
base.MCAST_GROUP)),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_VXLAN_ADD % (267, 70000)),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
@ -222,7 +222,7 @@ class TestCiscoNexusRestVxlanResults(base.TestCiscoNexusBaseResults):
base.DELETE],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_8,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_8,

View File

@ -31,6 +31,8 @@ redundant.
from oslo_config import cfg
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_db_v2 as nxos_db)
from networking_cisco.plugins.ml2.drivers.cisco.nexus import (
nexus_restapi_snippets as snipp)
from networking_cisco.tests.unit.ml2.drivers.cisco.nexus import (
@ -48,36 +50,36 @@ class TestCiscoNexusRestReplayResults(base.TestCiscoNexusBaseResults):
'driver_result_unique_init': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '')),
base.POST],
],
'driver_result_unique_add1': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
None,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
None,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
'driver_result_unique_add2': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+265')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+265')),
base.POST]
],
'driver_result_unique_del1': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-265')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_1,
@ -88,7 +90,7 @@ class TestCiscoNexusRestReplayResults(base.TestCiscoNexusBaseResults):
'driver_result_unique_del2': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
None,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
None,
@ -99,9 +101,9 @@ class TestCiscoNexusRestReplayResults(base.TestCiscoNexusBaseResults):
'driver_result_unique_2vlan_replay': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+265,267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+265,267')),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD_START % 265) + (
snipp.BODY_VLAN_ADD_NEXT % 267) + snipp.BODY_VLAN_ALL_END,
@ -109,43 +111,43 @@ class TestCiscoNexusRestReplayResults(base.TestCiscoNexusBaseResults):
],
'dupl_vlan_result1_add': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
'dupl_vlan_result2_add': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
'dupl_vlan_result2_del': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_2,
@ -153,20 +155,20 @@ class TestCiscoNexusRestReplayResults(base.TestCiscoNexusBaseResults):
base.DELETE],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST]
],
'dupl_vlan_result_replay': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/20]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
@ -175,29 +177,29 @@ class TestCiscoNexusRestReplayResults(base.TestCiscoNexusBaseResults):
'dupl_port_result_replay': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_3,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_3,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
],
'switch_up_result_add': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_VLAN_ADD % 269),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/3]'),
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+269')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+269')),
base.POST]
],
'switch_up_result_del': [
[(snipp.PATH_IF % 'phys-[eth1/3]'),
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-269')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-269')),
base.POST],
[(snipp.PATH_VLAN % '269'),
base.NEXUS_IP_ADDRESS_DUAL,
@ -206,22 +208,22 @@ class TestCiscoNexusRestReplayResults(base.TestCiscoNexusBaseResults):
],
'switch_restore_result_add': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_VLAN_ADD % 269),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/3]'),
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+269')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+269')),
base.POST]
],
'switch_restore_result_replay': [
[(snipp.PATH_IF % 'phys-[eth1/2]'),
base.NEXUS_IP_ADDRESS_DUAL2,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+269')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+269')),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_DUAL2,
(snipp.BODY_VLAN_ADD % 269),
base.POST]
@ -230,7 +232,7 @@ class TestCiscoNexusRestReplayResults(base.TestCiscoNexusBaseResults):
'switch_restore_result_del': [
[(snipp.PATH_IF % 'phys-[eth1/3]'),
base.NEXUS_IP_ADDRESS_DUAL,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-269')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-269')),
base.POST],
[(snipp.PATH_VLAN % '269'),
base.NEXUS_IP_ADDRESS_DUAL,
@ -238,7 +240,7 @@ class TestCiscoNexusRestReplayResults(base.TestCiscoNexusBaseResults):
base.DELETE],
[(snipp.PATH_IF % 'phys-[eth1/2]'),
base.NEXUS_IP_ADDRESS_DUAL2,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-269')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-269')),
base.POST],
[(snipp.PATH_VLAN % '269'),
base.NEXUS_IP_ADDRESS_DUAL2,
@ -338,36 +340,36 @@ class TestCiscoNexusRestBaremetalReplayResults(base.TestCiscoNexusBaseResults):
'driver_result_unique_init': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '')),
base.POST],
],
'driver_result_unique_eth_add1': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+267')),
base.POST]
],
'driver_result_unique_eth_add2': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+265')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+265')),
base.POST]
],
'driver_result_unique_eth_del1': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-265')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_1,
@ -378,7 +380,7 @@ class TestCiscoNexusRestBaremetalReplayResults(base.TestCiscoNexusBaseResults):
'driver_result_unique_eth_del2': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_1,
@ -386,72 +388,98 @@ class TestCiscoNexusRestBaremetalReplayResults(base.TestCiscoNexusBaseResults):
base.DELETE]
],
'driver_result_unique_vPC_init': [
[(snipp.PATH_IF % 'aggr--[po469]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '')),
base.POST],
],
'driver_result_unique_vPC_add1': [
[snipp.PATH_VLAN_ALL,
'driver_result_unique_vPC_2switch_add1': [
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '+267')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST]
],
'driver_result_unique_vPC_add2': [
[snipp.PATH_VLAN_ALL,
'driver_result_unique_vPC_2switch_add1': [
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 265),
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '+265')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST]
],
'driver_result_unique_vPC_del1': [
'driver_result_unique_vPC_2if_replay': [
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '-265')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST],
[(snipp.PATH_VLAN % '265'),
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
'',
base.DELETE]
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 267),
base.POST]
],
'driver_result_unique_vPC_del2': [
'driver_result_unique_vPC_2switch_del1': [
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_1,
'',
base.DELETE],
[(snipp.PATH_IF % 'aggr-[po469]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_2,
'',
base.DELETE]
],
'driver_result_unique_native_port_ethernet_add': [
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_NATIVE_TRUNKVLAN % ('l1PhysIf', '+265', 'vlan-265')),
(snipp.BODY_NATIVE_TRUNKVLAN % (
'l1PhysIf', '', '+265', 'vlan-265')),
base.POST]
],
'driver_result_unique_native_port_ethernet_del': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_NATIVE_TRUNKVLAN % ('l1PhysIf', '-265', '')),
(snipp.BODY_NATIVE_TRUNKVLAN % ('l1PhysIf', '', '-265', '')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_1,
@ -462,83 +490,303 @@ class TestCiscoNexusRestBaremetalReplayResults(base.TestCiscoNexusBaseResults):
'driver_result_unique_2vlan_replay': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+265,267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+265,267')),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD_START % 265) + (
snipp.BODY_VLAN_ADD_NEXT % 267) + snipp.BODY_VLAN_ALL_END,
base.POST]
],
'driver_result_unique_2vlan_vpc_replay': [
[(snipp.PATH_IF % 'aggr-[po469]'),
'driver_result_unique_vPC470_add1': [
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '+265,267')),
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[snipp.PATH_VLAN_ALL,
[(snipp.PATH_IF % 'aggr-[po470]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po470]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST],
],
'driver_result_unique_vPC470_add2': [
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'aggr-[po470]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+265')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'aggr-[po470]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+265')),
base.POST]
],
'driver_result_unique_vPC470_2vlan_replay': [
[(snipp.PATH_IF % 'aggr-[po470]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+265,267')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD_START % 265) + (
snipp.BODY_VLAN_ADD_NEXT % 267) + snipp.BODY_VLAN_ALL_END,
snipp.BODY_VLAN_ADD_NEXT % 267) + snipp.BODY_VLAN_ALL_END,
base.POST],
[(snipp.PATH_IF % 'aggr-[po470]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+265,267')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD_START % 265) + (
snipp.BODY_VLAN_ADD_NEXT % 267) + snipp.BODY_VLAN_ALL_END,
base.POST]
],
'driver_result_unique_vPC470_del1': [
[(snipp.PATH_IF % 'aggr-[po470]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '-265')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_1,
'',
base.DELETE]
base.DELETE],
[(snipp.PATH_IF % 'aggr-[po470]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_2,
'',
base.DELETE],
],
'driver_result_unique_vPC470_del2': [
[(snipp.PATH_IF % 'aggr-[po470]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '-267')),
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_1,
'',
base.DELETE]
base.DELETE],
[(snipp.PATH_IF % 'aggr-[po470]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_2,
'',
base.DELETE],
],
'driver_result_unique_vPC470_2vlan_replay': [
[(snipp.PATH_IF % 'aggr-[po470]'),
'driver_result_unique_auto_vPC_2vlan_replay': [
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '+265,267')),
(snipp.BODY_ADD_PORT_CH % (1001, 1001, 1001)),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_ADD_PORT_CH_P2 % (1001, 1001)),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % (
'pcAggrIf', snipp.BODY_PORT_CH_MODE, '')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_ADD_CH_GRP % (1001, 1001, 'phys-[eth1/10]')),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+265,267')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD_START % 265) + (
snipp.BODY_VLAN_ADD_NEXT % 267) + snipp.BODY_VLAN_ALL_END,
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_ADD_PORT_CH % (1001, 1001, 1001)),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_ADD_PORT_CH_P2 % (1001, 1001)),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % (
'pcAggrIf', snipp.BODY_PORT_CH_MODE, '')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_ADD_CH_GRP % (1001, 1001, 'phys-[eth1/20]')),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+265,267')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD_START % 265) + (
snipp.BODY_VLAN_ADD_NEXT % 267) + snipp.BODY_VLAN_ALL_END,
base.POST]
],
'driver_result_unique_2vlan_vpc_enchg_replay': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
'driver_result_unique_auto_vPC_vm_add1': [
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+265,267')),
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[snipp.PATH_VLAN_ALL,
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD_START % 265) + (
snipp.BODY_VLAN_ADD_NEXT % 267) + snipp.BODY_VLAN_ALL_END,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+265')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 265),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+265')),
base.POST]
],
'driver_result_unique_auto_vPC_vm_del1': [
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_1,
'',
base.DELETE],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-265')),
base.POST],
[(snipp.PATH_VLAN % '265'),
base.NEXUS_IP_ADDRESS_2,
'',
base.DELETE]
],
'driver_result_unique_auto_vPC_add1': [
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_ADD_PORT_CH % (1001, 1001, 1001)),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_ADD_PORT_CH_P2 % (1001, 1001)),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % (
'pcAggrIf', snipp.BODY_PORT_CH_MODE, '')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_ADD_CH_GRP % (1001, 1001, 'phys-[eth1/10]')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_ADD_PORT_CH % (1001, 1001, 1001)),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_ADD_PORT_CH_P2 % (1001, 1001)),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % (
'pcAggrIf', snipp.BODY_PORT_CH_MODE, '')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_ADD_CH_GRP % (1001, 1001, 'phys-[eth1/20]')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_VLAN_ADD % 267),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '+267')),
base.POST]
],
'driver_result_unique_auto_vPC_del1': [
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_1,
'',
base.DELETE],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_DEL_CH_GRP % ('1001', 'phys-[eth1/10]')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_DEL_PORT_CH % ('1001')),
base.POST],
[(snipp.PATH_IF % 'aggr-[po1001]'),
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_TRUNKVLAN % ('pcAggrIf', '', '-267')),
base.POST],
[(snipp.PATH_VLAN % '267'),
base.NEXUS_IP_ADDRESS_2,
'',
base.DELETE],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_DEL_CH_GRP % ('1001', 'phys-[eth1/20]')),
base.POST],
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_2,
(snipp.BODY_DEL_PORT_CH % ('1001')),
base.POST]
],
'driver_result_unique_native_2vlan_replay': [
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_NATIVE_TRUNKVLAN % ('l1PhysIf', '+265', 'vlan-265')),
(snipp.BODY_NATIVE_TRUNKVLAN % (
'l1PhysIf', '', '+265', 'vlan-265')),
base.POST],
[(snipp.PATH_IF % 'phys-[eth1/10]'),
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '+265,267')),
(snipp.BODY_TRUNKVLAN % ('l1PhysIf', '', '+265,267')),
base.POST],
[snipp.PATH_VLAN_ALL,
[snipp.PATH_ALL,
base.NEXUS_IP_ADDRESS_1,
(snipp.BODY_VLAN_ADD_START % 265) + (
snipp.BODY_VLAN_ADD_NEXT % 267) + snipp.BODY_VLAN_ALL_END,
@ -549,7 +797,7 @@ class TestCiscoNexusRestBaremetalReplayResults(base.TestCiscoNexusBaseResults):
GET_PORT_CH_RESPONSE = {
"totalCount": "3",
"totalCount": "4",
"imdata": [
{
"pcRsMbrIfs": {
@ -574,6 +822,14 @@ GET_PORT_CH_RESPONSE = {
"tSKey": "eth1/12",
}
}
},
{
"pcRsMbrIfs": {
"attributes": {
"parentSKey": "po469",
"tSKey": "eth1/20",
}
}
}
]
}
@ -599,12 +855,12 @@ class TestCiscoNexusRestBaremetalReplay(
return {}
def _init_port_channel(self, ch_grp):
def _init_port_channel(self, ch_grp, which=1):
# this is to prevent interface initialization from occurring
# which adds unnecessary noise to the results.
GET_PORT_CH_RESPONSE['imdata'][1]['pcRsMbrIfs'][
GET_PORT_CH_RESPONSE['imdata'][which]['pcRsMbrIfs'][
'attributes']['parentSKey'] = ('po' + str(ch_grp))
data_json = {'rest_get.side_effect':
self.get_init_side_effect}
@ -622,22 +878,79 @@ class TestCiscoNexusRestBaremetalReplay(
(super(TestCiscoNexusRestBaremetalReplay, self).
test_replay_unique_ethernet_ports())
def test_replay_unique_ethernet_port_and_vm(self):
(super(TestCiscoNexusRestBaremetalReplay, self).
test_replay_unique_ethernet_port_and_vm())
def test_replay_unique_vPC_ports(self):
self._init_port_channel(469, 3)
(super(TestCiscoNexusRestBaremetalReplay, self).
test_replay_unique_vPC_ports())
self._init_port_channel(470, 3)
def test_replay_unique_vPC_ports_and_vm(self):
self._init_port_channel(470, 3)
(super(TestCiscoNexusRestBaremetalReplay, self).
test_replay_unique_vPC_ports_and_vm())
def test_replay_unique_vPC_ports_chg_vPC_nbr(self):
self._init_port_channel(469, 3)
(super(TestCiscoNexusRestBaremetalReplay, self).
test_replay_unique_vPC_ports_chg_vPC_nbr())
self._init_port_channel(470, 3)
def test_replay_unique_vPC_ports_chg_to_enet(self):
self._init_port_channel(469, 3)
(super(TestCiscoNexusRestBaremetalReplay, self).
test_replay_unique_vPC_ports_chg_to_enet())
self._init_port_channel(470, 3)
def test_replay_unique_native_nonnative_ethernet_ports(self):
(super(TestCiscoNexusRestBaremetalReplay, self).
test_replay_unique_native_nonnative_ethernet_ports())
def test_replay_automated_vPC_ports_and_vm(self):
"""Provides replay data and result data for unique ports. """
switch_list = ['1.1.1.1', '2.2.2.2']
for switch_ip in switch_list:
nxos_db.init_vpc_entries(switch_ip, 1001, 1025)
# _init_port_channel is not called so the vpc nbr is created
first_add = {
'driver_results': self.results.get_test_results(
'driver_result_unique_auto_vPC_add1'),
'nbr_db_entries': 2}
second_add = {
'driver_results': self.results.get_test_results(
'driver_result_unique_auto_vPC_vm_add1'),
'nbr_db_entries': 4}
first_del = {
'driver_results': self.results.get_test_results(
'driver_result_unique_auto_vPC_vm_del1'),
'nbr_db_entries': 2}
second_del = {
'driver_results': self.results.get_test_results(
'driver_result_unique_auto_vPC_del1'),
'nbr_db_entries': 0}
self._process_replay(
'test_replay_unique_vPC',
'test_config_vm',
[],
first_add,
second_add,
self.results.get_test_results(
'driver_result_unique_auto_vPC_2vlan_replay'),
first_del,
second_del)
for switch_ip in switch_list:
self.assertEqual(
25, len(nxos_db.get_free_switch_vpc_allocs(switch_ip)))
#The tests in class below is reproduced this is does not apply to restapis.
#class TestCiscoNexusNonCachedSshReplay(