Merge "Nexus Baremetal Automated Port Channel Creation"
This commit is contained in:
commit
8a24884055
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
9148d96f9b39
|
||||
f3765e42de23
|
||||
|
|
|
@ -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')
|
||||
)
|
|
@ -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)
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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: "
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue