[dts] [PATCH V1 3/6] pmd_bonded_8023ad: add switch module in dts/framework
yufengx.mo at intel.com
yufengx.mo at intel.com
Wed Jun 6 07:38:30 CEST 2018
From: yufengmx <yufengx.mo at intel.com>
support to query and configure switch equipment running parameters/statistics.
Currently, support quanta switch model t3048-iz1, which is a 10G switch
equipment. This module support to auto configure a 802.3ad running environment
and query statistics data.
Signed-off-by: yufengmx <yufengx.mo at intel.com>
---
framework/switch.py | 1445 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1445 insertions(+)
create mode 100644 framework/switch.py
diff --git a/framework/switch.py b/framework/switch.py
new file mode 100644
index 0000000..d006f76
--- /dev/null
+++ b/framework/switch.py
@@ -0,0 +1,1445 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2018 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+import os
+import sys
+import re
+import time
+from abc import abstractmethod
+
+from config import SwitchConf
+from logger import getLogger
+from ssh_connection import SSHConnection
+from exception import TimeoutException, ConfigParseException, SwitchException
+
+################################################
+# use for put switch console on background, control it using queue.
+# it is thread safe
+import traceback
+
+join_l = os.linesep.join
+
+class QuantaONS(object):
+ '''quanta switch
+
+ Intel Open Network Software (ONS)
+ '''
+ NAME = 'Quanta switch'
+ MAX_PORTS = None
+ VLAN_RANGE = None
+ PORT_CHANNEL_RANGE = None
+ def __init__(self, *args, **kwargs):
+ self.console = kwargs.get('console')
+ self.logger = kwargs.get('logger')
+ # use for static port attribute
+ self._cache = {}
+ ########################################################################
+ #### utils method
+ ########################################################################
+ def filter_one_attrs(self, output):
+ '''deal with one section output message format as
+
+ Port .................................... 2
+ '''
+ pat = '(.*) \.+ (.*)\r'
+ data = re.findall(pat, output, re.M)
+ stats = dict(data)
+ num_pat = '^\d+$'
+ for key in stats.keys():
+ value = stats[key]
+ flg = re.match(num_pat, value)
+ if flg:
+ stats[key] = int(value)
+ return stats
+
+ def filter_ports_attr(self, content):
+ '''deal with multiple section output message format as
+
+ Port .................................... 1
+
+ Port .................................... 2
+ '''
+ info = {}
+ sections =content.split("\r\n\r\n")[1].split(" ")
+ for output in sections:
+ stats = self.filter_one_attrs(output)
+ if not stats:
+ continue
+ info[stats['Port']] = stats
+
+ return info
+
+ def filter_pchs_attr(self, content):
+ '''deal with multiple section output message format as
+
+ Port Channel ............................ lag4000
+ '''
+ info = {}
+ sections =content.split("\r\n\r\n")[1].split(" ")
+ for output in sections:
+ stats = self.filter_one_attrs(output)
+ if not stats:
+ continue
+ info[stats['Port Channel']] = stats
+
+ return info
+
+ def filter_one_section(self, content):
+ '''deal with one running-config message section'''
+ info = content.split(" ")
+ _info = [ item.strip() for item in info if item.strip()]
+ attrs = map(lambda x: x.replace(" ", "").splitlines(), _info)
+ return attrs
+
+ def filter_interfaces_config(self, output):
+ '''deal with multiple section running-config message'''
+ patIntf = r'(?<= interface).+?(?=exit)'
+ sections = re.findall(patIntf, output, re.S)
+ infos = {}
+ for section in sections:
+ info = self.filter_one_section(section)
+ name = info[0][0].strip()
+ infos[name] = info[1:]
+ return infos
+ ########################################################################
+ #### switch mode select
+ ########################################################################
+ def get_current_mode(self):
+ '''get current switch mode
+
+ quanta ons system has no command to show shell layer. Currently use
+ help output message to judge current shell level
+ '''
+ modes = {
+ # shell level : prompt, help
+ "user": 'enable Enter to the privileged mode',
+ "privileged": ('configure '
+ 'Enter configuration mode'),
+ "configure": 'interface Configure interfaces',
+ "port config":
+ ('channel-group '
+ 'Ethernet channel group bundling configuration'),
+ "port-channel config":
+ ('lacp '
+ 'Determines whether this LAG processes Received LACPDUs'),
+ }
+ mode = "unknown"
+ try:
+ output = self.console(["help", 'Switch'])
+ for name, value in modes.iteritems():
+ if value in output:
+ mode = name
+ break
+ except Exception as e:
+ print e
+ finally:
+ pass
+
+ msg = "current on {0} mode".format(mode)
+ self.logger.info(msg)
+ return mode
+
+ def enter_user(self):
+ '''enter user mode'''
+ mode = self.get_current_mode()
+ if mode == "user":
+ return
+ elif mode == "privileged":
+ cmds = ['exit', 'Switch >']
+ elif mode == "configure":
+ cmds = ["exit", "Switch #"]
+ else:
+ cmds = [["exit", "Switch \(config\)#"],
+ ["exit", "Switch #"]]
+
+ self.console(cmds)
+
+ def enter_privileged(self):
+ '''enter privileged mode'''
+ mode = self.get_current_mode()
+ if mode == "user":
+ cmds = ["enable", "Switch #"]
+ elif mode == "privileged":
+ return
+ elif mode == "configure":
+ cmds = ["exit", "Switch #"]
+ else:
+ cmds = [["exit", "Switch \(config\)#"],
+ ["exit", "Switch #"]]
+
+ self.console(cmds)
+
+ def enter_configure(self):
+ '''enter configure mode'''
+ mode = self.get_current_mode()
+ if mode == "user":
+ cmds = [["enable", "Switch #"],
+ ["configure", "Switch \(config\)#"],]
+ elif mode == "privileged":
+ cmds = ["configure", "Switch \(config\)#"]
+ elif mode == "configure":
+ return
+ else:
+ cmds = ["exit", "Switch \(config\)#"]
+ self.console(cmds)
+ ########################################################################
+ #### global effective method
+ ########################################################################
+ def clear_switch_stats(self):
+ '''
+ quanta switch doesn't support clear specified port channel. When
+ multiple scenes are running, don't run this method
+ '''
+ msg = "clear switch all ports statistics data"
+ self.logger.warning(msg)
+ cmds = [['clear statistics', 'Proceed with clear operation'],
+ ['yes', '#', 2]]
+
+ self.enter_privileged()
+ self.console(cmds)
+ ########################################################################
+ #### interface method
+ ########################################################################
+ def intf_get_config(self, ports):
+ '''get interface configuration by port name or port name list
+ '''
+ if isinstance(ports, (tuple, list)):
+ _ports = ",".join(ports)
+ elif isinstance(ports, str):
+ _ports = ports
+ else:
+ msg = "ports param are wrong"
+ raise SwitchException(msg)
+
+ cmds = ["show running-config interface {0}".format(_ports), '#']
+
+ self.enter_privileged()
+ output = self.console(cmds)
+ configs = self.filter_interfaces_config(output)
+
+ return configs
+
+ def intf_reset_config(self, port, attrs):
+ '''reset interface configurationt to default status'''
+ cmds = ["interface {0}".format(port), '#']
+
+ self.enter_privileged()
+ self.console(cmds)
+
+ cmds = []
+ for attr in attrs:
+ if not attr.startswith('no '):
+ cmds.append(["no {0}".format(attr), '#'])
+ else:
+ cmds.append([attr[3:], "# "])
+ self.console(cmds)
+
+ def intf_get_vlan_attr(self, port_id):
+ '''get interface vlan ids'''
+ prompt = 'Switch #'
+ cmd = ["show running-config interface {0}".format(port_id), prompt]
+
+ self.enter_privileged()
+ output = self.console(cmd)
+ pat = "switchport vlan add (.*) .*"
+ vlan_ids = re.findall(pat, output)
+ return vlan_ids
+
+ def intf_set_vlan_attr(self, vlan_id, port_id, scene='normal'):
+ '''remove port from previous vlan and add port to new vlan'''
+ prompt = 'Switch \(config-if {0}\)#'.format(port_id)
+
+ if scene == 'lacp':
+ _cmds =[
+ "interface {0}".format(port_id),
+ "no switchport pvid",
+ "switchport pvid {0}".format(vlan_id),]
+ else:
+ vlans = self.intf_get_vlan_attr(port_id)
+ clear_vlan_cmd = "" if not vlans \
+ else "no switchport vlan add {0}".format(",".join(vlans))
+ _cmds =[
+ "interface {0}".format(port_id),
+ # clear old vlan
+ "no switchport pvid",
+ clear_vlan_cmd,
+ # set vlan attribute
+ "switchport vlan add {0} untagged".format(vlan_id),
+ "switchport pvid {0}".format(vlan_id),]
+ cmds = map(lambda x: [x, prompt], _cmds)
+
+ self.enter_configure()
+ self.console(cmds)
+
+ def intf_get_pch_id(self, port_id):
+ '''get interface port channel id.
+
+ If not binding to any port channel, return None
+ '''
+ attrs = self.intf_get_config([port_id])
+ for attr_section in attrs.values()[0]:
+ if attr_section[0] and "channel-group" in attr_section[0]:
+ pch_attr = attr_section
+ break
+ else:
+ return None
+ pat = "channel-group (\d+) .*"
+ ch_grp_id = re.findall(pat, pch_attr[0])
+ return int(ch_grp_id[0])
+
+ def intf_unbind_pch(self, ch_grp_id, port_id):
+ '''unbind interface from port channel'''
+ prompt = 'Switch \(config-if {0}\)#'.format(port_id)
+ _cmds =[
+ "interface {0}".format(port_id),
+ "no channel-group {0}".format(ch_grp_id),]
+ cmds = map(lambda x: [x, prompt], _cmds)
+ ret_mode= [['exit', '#']]
+
+ self.enter_configure()
+ self.console(cmds + ret_mode)
+
+ def intf_close_lldp(self, port_id):
+ '''close interface lldp transmit/receive'''
+ prompt = 'Switch \(config-if {0}\)#'.format(port_id)
+ _cmds =[
+ "interface {0}".format(port_id),
+ "no lldp receive",
+ "no lldp transmit"]
+ cmds = map(lambda x: [x, prompt], _cmds)
+ ret_mode= [['exit', '#']]
+
+ self.enter_configure()
+ self.console(cmds + ret_mode)
+
+ def intf_open_lldp(self, port_id):
+ '''open interface lldp transmit/receive'''
+ prompt = 'Switch \(config-if {0}\)#'.format(port_id)
+ _cmds =[
+ "interface {0}".format(port_id),
+ "lldp receive",
+ "lldp transmit"]
+ cmds = map(lambda x: [x, prompt], _cmds)
+ ret_mode= [['exit', '#']]
+
+ self.enter_configure()
+ self.console(cmds + ret_mode)
+
+ def intf_get_brief(self, port):
+ '''get interface brief information'''
+ cmds = ['show interface {0}'.format(port), '#', 3]
+
+ self.enter_privileged()
+ output = self.console(cmds)
+ if not output:
+ return None
+ attrs = self.filter_ports_attr(output)
+ return attrs
+
+ def intf_get_transceiver(self, port):
+ '''get interface transceiver information'''
+ cmds = ["show interface {0} transceiver".format(port), '#']
+
+ self.enter_privileged()
+ output = self.console(cmds)
+ if not output:
+ return None
+ attrs = self.filter_ports_attr(output)
+ return attrs
+
+ def intf_shutdown(self, port_id):
+ '''set interface link down
+
+ Quanta swith don't support set shutdown when the port is a member
+ of port channel, it herit the port status of port channel
+ '''
+ self.enter_configure()
+ cmds = [["interface {0}".format(port_id), '#'],
+ ["shutdown", '#']]
+ self.console(cmds)
+
+ def intf_no_shutdown(self, port_id):
+ '''set interface link up
+
+ Quanta swith don't support set shutdown when the port is a member
+ of port channel, it herit the port status of port channel
+ '''
+ self.enter_configure()
+ cmds = [["interface {0}".format(port_id), '#'],
+ ["no shutdown", '#']]
+ self.console(cmds)
+
+ def intf_get_stats(self, port):
+ '''get interface statistics data'''
+ cmds = ['show statistics interface {0}'.format(port), '#', 5]
+
+ self.enter_privileged()
+ output = self.console(cmds)
+ return self.filter_one_attrs(output)
+
+ def intf_clear_stats(self, port):
+ '''clear interface statistics data
+
+ only apply on the interface not binding to any port-channel
+ '''
+ cmds = [
+ ['clear statistics {0}'.format(port), 'Proceed with clear operation'],
+ ['yes', '#', 2]]
+
+ self.enter_privileged()
+ self.console(cmds)
+
+ ########################################################################
+ #### port channel/channel group method
+ ########################################################################
+ def create_port_channel(self, ch_grp_id):
+ '''create a new port channel'''
+ if self.pch_is_exist(ch_grp_id):
+ msg = "port channel {0} has created".format(ch_grp_id)
+ self.logger.info(msg)
+ return
+ # create a new one
+ prompt = 'Switch \(config-if\)#'
+ cmds = [['interface port-channel {0}'.format(ch_grp_id), prompt],
+ ['shutdown', prompt],
+ ['exit', '#']]
+
+ self.enter_configure()
+ self.console(cmds)
+ # check status
+ if self.pch_is_exist(ch_grp_id):
+ msg = "port channel {0} create successful".format(ch_grp_id)
+ self.logger.info(msg)
+ else:
+ msg = "port channel {0} create failed".format(ch_grp_id)
+ raise SwitchException(msg)
+
+ def pch_is_exist(self, ch_grp_id):
+ '''check if port channel has been created'''
+ cmds = ['show interface port-channel', '#']
+
+ self.enter_privileged()
+ output = self.console(cmds)
+ infos = self.filter_pchs_attr(output)
+ name = "lag{0}".format(ch_grp_id)
+ if name in infos.keys():
+ return True
+ else:
+ return False
+
+ def pch_id_in_range(self, ch_grp_id):
+ '''check if port channel id is in the right range
+
+ The range is set by sub class
+ '''
+ if not self.PORT_CHANNEL_RANGE:
+ msg = "PORT_CHANNEL_RANGE should be set by subclass"
+ raise SwitchException(msg)
+
+ flag = ch_grp_id >= self.PORT_CHANNEL_RANGE[0] and \
+ ch_grp_id <= self.PORT_CHANNEL_RANGE[1]
+ return flag
+
+ def pch_set_load_balance(self, mode):
+ '''set port channel load balance
+
+ It is a global effective status flag
+
+ @param mode:
+ dscp Load balancing by IP DSCP.
+ dst-ip Load balancing by destination IP address.
+ dst-mac Load balancing by destination MAC address.
+ ether-type Load balancing by ethertype.
+ inner-vlan-id Load balancing by in VLAN ID.
+ inner-vlan-pri Load balancing by in VLAN priority.
+ ip-protocol Load balancing by IP protocol.
+ ip6-flow Load balancing by IPv6 traffic flow.
+ l4-dst-port Load balancing by layer 4 destination port.
+ l4-src-port Load balancing by layer 4 source port.
+ outer-vlan-id Load balancing by out VLAN ID.
+ outer-vlan-pri Load balancing by out VLAN priority.
+ src-ip Load balancing by source IP address.
+ src-mac Load balancing by source MAC address.
+ '''
+ supports = [
+ 'dscp', 'dst-ip', 'dst-mac', 'ether-type', 'inner-vlan-id',
+ 'inner-vlan-pri', 'ip-protocol', 'ip6-flow', 'l4-dst-port',
+ 'l4-src-port', 'outer-vlan-id', 'outer-vlan-pri', 'src-ip',
+ 'src-mac']
+ if mode not in supports:
+ msg = "load balance {0} is not supported".format(mode)
+ raise SwitchException(msg)
+
+ prompt = 'Switch \(config\)#'
+ cmds = ['port-channel load-balance {0}'.format(mode), prompt]
+
+ self.enter_configure()
+ self.console(cmds)
+
+ def pch_remove_port(self, ch_grp_id, port):
+ '''unbind a port from port channel
+
+ only remove port in channel group, not change other configuration
+ '''
+ ch = ch_grp_id
+ prompt = 'Switch \(config-if {0}\)#'.format(port)
+ cmds = [
+ ['interface {0}'.format(port), prompt, 2],
+ ['no channel-group {0}'.format(ch), prompt, 2],
+ ['exit', "Switch \(config\)#"],
+ ['exit', "Switch #"]]
+
+ self.enter_configure()
+ self.console(cmds)
+
+ def pch_add_port(self, ch_grp_id, port):
+ '''bind a port to a port channel
+
+ only add port in channel group, not change other configuration
+ '''
+ ch = ch_grp_id
+ prompt = 'Switch \(config-if {0}\)#'.format(port)
+ cmds = [
+ ['interface {0}'.format(port), prompt, 2],
+ ['channel-group {0}'.format(ch), prompt],
+ ['exit', "Switch \(config\)#"],
+ ['exit', "Switch #"]]
+
+ self.enter_configure()
+ self.console(cmds)
+
+ def pch_remove_ports(self, ports):
+ '''unbind a list of port from any port channel'''
+ for port in ports:
+ ch = self.intf_get_pch_id(port)
+ if not ch:
+ continue
+ prompt = 'Switch \(config-if {0}\)#'.format(port)
+ cmds = [
+ ['interface {0}'.format(port), prompt, 2],
+ ['no channel-group {0}'.format(ch), prompt, 2],
+ ['exit', "Switch \(config\)#", 2]]
+
+ self.enter_configure()
+ self.console(cmds)
+
+ def pch_get_ports_config(self, ch_grp_id):
+ '''get ports' configuration belong to a port channel
+
+ quanta switch not support query all ports config in one command, so it
+ will be very slow here
+ '''
+ ports = self.pch_get_member(ch_grp_id)
+ members = {}
+ self.enter_privileged()
+ for port_name in ports:
+ cmds = ["show running-config interface " + port_name, '#']
+ output = self.console(cmds)
+ if output:
+ members[port_name] = output
+
+ return members
+
+ def pch_reset_port_config(self, port, attrs):
+ '''release interface from port channel'''
+ # not done here
+ return False
+ cmds = ["interface {0}".format(port), '#']
+
+ self.enter_privileged()
+ self.console(cmds)
+
+ cmds = []
+ for attr in attrs:
+ if not attr.startswith('no '):
+ cmds.append(["no {0}".format(attr), '#'])
+ else:
+ cmds.append([attr[3:], "# "])
+ self.console(cmds)
+
+ def pch_set_ip_igmp(self, ch_grp_id):
+ '''set port channel ip igmp'''
+ prompt = 'Switch \(config-if\)#'
+ cmds = [['interface port-channel {0}'.format(ch_grp_id), prompt],
+ ['ip igmp', prompt],
+ ['exit', '#']]
+
+ self.enter_configure()
+ self.console(cmds)
+
+ def pch_close_ip_igmp(self, ch_grp_id):
+ '''close port channel ip igmp'''
+ prompt = 'Switch \(config-if\)#'
+ cmds = [['interface port-channel {0}'.format(ch_grp_id), prompt],
+ ['no ip igmp', prompt],
+ ['exit', '#']]
+
+ self.enter_configure()
+ self.console(cmds)
+
+ def pch_no_shutdown(self, ch_grp_id):
+ '''set port channel on ``no shutdown`` status'''
+ prompt = 'Switch \(config-if\)#'
+ cmds = [['interface port-channel {0}'.format(ch_grp_id), prompt],
+ ['no shutdown', prompt],
+ ['ip igmp', prompt], # TBD
+ ['exit', '#']]
+
+ self.enter_configure()
+ self.console(cmds)
+
+ def pch_shutdown(self, ch_grp_id):
+ '''set port channel on ``no shutdown`` status'''
+ prompt = 'Switch \(config-if\)#'
+ cmds = [['interface port-channel {0}'.format(ch_grp_id), prompt],
+ ['shutdown', prompt],
+ ['no ip igmp', prompt],
+ ['exit', '#']]
+
+ self.enter_configure()
+ self.console(cmds)
+
+ def pch_get_member(self, ch_grp_id):
+ '''get port member of a port channel'''
+ details = self.pch_get_group_info(ch_grp_id)
+ members = sorted(details.keys())
+
+ return members
+
+ def pch_get_member_status(self, ch_grp_id):
+ '''get port members' status of a port channel'''
+ members = self.pch_get_member(ch_grp_id)
+ if not members:
+ msg = "no member attached on port-channel {0}".format(ch_grp_id)
+ self.logger.error(msg)
+ return False
+
+ err_port = []
+ for name, attrs in members.iteritems():
+ if attrs['Mode'] != 'Active':
+ err_port.append(name)
+ if err_port:
+ msg = "{0} not at Active mode".format(" ".join(err_port))
+ self.logger.error(msg)
+ return False
+ else:
+ return True
+
+ def pch_get_group_info(self, ch_grp_id):
+ '''get port member status of a channel group'''
+ cmd = ["show channel-group {0}".format(ch_grp_id), "#"]
+
+ self.enter_privileged()
+ output = self.console(cmd)
+ if "Error! Invalid interface range has been specified" in output:
+ return []
+ infos = self.filter_ports_attr(output)
+ return infos
+
+ def pch_get_grp_remote_info(self, ch_grp_id):
+ '''get all ports remote information of a channel group'''
+ cmd = ["show channel-group {0} remote".format(ch_grp_id), "#"]
+
+ self.enter_privileged()
+ output = self.console(cmd)
+ infos = self.filter_ports_attr(output)
+ return infos
+
+ def pch_get_grp_admin_info(self, ch_grp_id):
+ '''get all ports admin information of a channel group'''
+ cmd = ["show channel-group {0} admin".format(ch_grp_id), "#"]
+
+ self.enter_privileged()
+ output = self.console(cmd)
+ infos = self.filter_ports_attr(output)
+ return infos
+
+ def pch_get_ports_stats(self, ports):
+ '''get all ports statistics of a channel group'''
+ stats_grp = {}
+ for port_id in ports:
+ stats = self.intf_get_stats(port_id)
+ stats_grp[port_id] = stats
+ return stats_grp
+
+ def pch_clear_stats(self, ch_grp_id, ports):
+ '''clear all ports statistics data of a port channel
+
+ quanta switch doesn't support clear specified port channel statistics.
+ An interface should unbind from a port channel before clear its
+ statistics data
+ '''
+ for port_id in ports:
+ self.pch_remove_port(ch_grp_id, port_id)
+ self.intf_clear_stats(port_id)
+ self.pch_add_port(ch_grp_id, port_id)
+
+ ########################################################################
+ #### vlan method
+ ########################################################################
+ def create_vlan(self, vlan_id):
+ '''create a new vlan'''
+ if self.vlan_is_exist(vlan_id):
+ msg = "vlan {0} has created".format(vlan_id)
+ self.logger.info(msg)
+ return
+ # create a new one
+ cmds = [['vlan-database', 'Switch \(vlan\)#'],
+ ['vlan {0}'.format(vlan_id), 'Switch \(vlan\)#'],
+ ['exit', '#', 2]]
+
+ self.enter_privileged()
+ self.console(cmds)
+ if self.vlan_is_exist(vlan_id):
+ msg = "vlan {0} create successful".format(vlan_id)
+ self.logger.info(msg)
+ else:
+ msg = "vlan {0} create failed".format(vlan_id)
+ raise SwitchException(msg)
+
+ def vlan_is_exist(self, vlan_id):
+ '''check if vlan has been created'''
+ cmds = ['show vlan', '#']
+
+ self.enter_privileged()
+ output = self.console(cmds)
+ name = str(vlan_id) + " "
+ if name in output:
+ return True
+ else:
+ return False
+
+ def vlan_id_in_range(self, vlan_id):
+ '''check if vlan id is in the right range'''
+ if not self.VLAN_RANGE:
+ msg = "VLAN_RANGE should be set by subclass"
+ raise SwitchException(msg)
+
+ flag = vlan_id >= self.VLAN_RANGE[0] and \
+ vlan_id <= self.VLAN_RANGE[1]
+ return flag
+
+ def vlan_remove_ports(self, ports):
+ '''reset port vlan to default 1'''
+ pass
+ ########################################################################
+ #### lacp method
+ ########################################################################
+ def lacp_set_port_channel(self, vlan_id, ch_grp_id):
+ '''set a new port channel for lacp scene'''
+ prompt = 'Switch \(config-if\)#'
+ _cmds =['interface port-channel {0}'.format(ch_grp_id),
+ 'no switchport vlan add 1',
+ 'switchport vlan add {0} untagged'.format(vlan_id),
+ 'switchport pvid {0}'.format(vlan_id),
+ 'lacp',
+ 'shutdown']
+ cmds = map(lambda x: [x, prompt], _cmds) + [['exit', '#']]
+
+ self.enter_configure()
+ self.console(cmds)
+
+ def lacp_init_ports(self, vlan_id, ch_grp_id, ports):
+ '''initialize lacp configuration
+
+ add ports into one port channel, set it on correct lacp
+ configuration and check if port has been added successfully.
+ '''
+ # reset port configuration
+ for port in ports:
+ _ch_grp_id = self.intf_get_pch_id(port)
+ if not _ch_grp_id:
+ continue
+ if _ch_grp_id == ch_grp_id:
+ continue
+ self.intf_unbind_pch(_ch_grp_id, port)
+ # release ports bind to port channel
+ members = self.pch_get_member(ch_grp_id)
+ self.pch_remove_ports(members)
+ # add ports
+ for port in ports:
+ self.intf_set_vlan_attr(vlan_id, port, 'lacp')
+ self.pch_add_port(ch_grp_id, port)
+ # set lacp configuration
+ for port in ports:
+ self.lacp_intf_set_attr(vlan_id, ch_grp_id, port)
+ # close lldp
+ for port in ports:
+ self.intf_close_lldp(port)
+ # check if port channel members are the desired interfaces
+ members = self.pch_get_member(ch_grp_id)
+ if cmp(sorted(members), sorted(ports)) == 0:
+ msg = "add ports success"
+ self.logger.info(msg)
+ else:
+ msg = "fail to add ports"
+ self.logger.error(msg)
+ raise SwitchException(msg)
+
+ def lacp_add_ports(self, vlan, ch_grp_id, ports):
+ '''add ports to a lacp
+
+ add ports into one port channel, set it on correct lacp
+ configuration and check if port has been added successfully.
+ '''
+ _cmds =[
+ 'interface {port_id}',
+ 'channel-group {ch_grp_id}',
+ 'channel-group {ch_grp_id} mode passive',
+ 'no channel-group {ch_grp_id} collecting',
+ 'no channel-group {ch_grp_id} distributing',
+ #'channel-group {ch_grp_id} synchronization'
+ ]
+ ret_mode= [['exit', '#']]
+ # set port lacp configuration
+ for port in ports:
+ #attrs = self.intf_get_config(port)
+ #self.intf_reset_config(port, attrs)
+ attrs = {'port_id': port,
+ 'ch_grp_id': ch_grp_id,}
+ prompt = 'Switch \(config-if {0}\)#'.format(port)
+ cmds = map(lambda x: [x.format(**attrs), prompt], _cmds)
+
+ self.enter_configure()
+ self.console(cmds + ret_mode)
+ self.intf_close_lldp(port)
+ # check lacp channel group create successfully
+ members = self.pch_get_member(ch_grp_id)
+ if cmp(sorted(members), sorted(ports)) == 0:
+ msg = "add ports success"
+ self.logger.info(msg)
+ else:
+ msg = "fail to add ports"
+ self.logger.error(msg)
+ raise SwitchException(msg)
+
+ def lacp_intf_set_attr(self, vlan_id, ch_grp_id, port_id):
+ '''set interface lacp configuration'''
+ attrs = {'port_id': port_id,
+ 'ch_grp_id': ch_grp_id,}
+ _cmds =[
+ "interface {port_id}",
+ # config actor, set port in passive status
+ "channel-group {ch_grp_id} mode passive",
+ "channel-group {ch_grp_id} timeout long",
+ "channel-group {ch_grp_id} aggregation multiple",
+ "channel-group {ch_grp_id} lacp port-priority 128",
+ #"channel-group {ch_grp_id} key {0}",
+ "no channel-group {ch_grp_id} synchronization",
+ "channel-group {ch_grp_id} expired",
+ "no channel-group {ch_grp_id} collecting",
+ "no channel-group {ch_grp_id} defaulting",
+ "no channel-group {ch_grp_id} distributing",
+ # config parter
+ "channel-group {ch_grp_id} partner key 0",
+ "channel-group {ch_grp_id} partner number 1",
+ "channel-group {ch_grp_id} partner priority 32768",
+ "channel-group {ch_grp_id} partner system priority 8"
+ ]
+ prompt = 'Switch \(config-if {0}\)#'.format(port_id)
+ cmds = map(lambda x: [x.format(**attrs), prompt], _cmds)
+ ret_mode= [['exit', '#']]
+
+ self.enter_configure()
+ self.console(cmds + ret_mode)
+
+ def lacp_close_ports(self, ch_grp_id, ports):
+ ret_mode= [['exit', '#']]
+ #---------------------------------------
+ # close lacp port channel
+ _cmds =[
+ 'interface {port_id}',
+ 'channel-group {ch_grp_id} mode passive',
+ 'no channel-group {ch_grp_id} collecting',
+ 'no channel-group {ch_grp_id} distributing']
+ self.enter_configure()
+ for port in sorted(ports):
+ attrs = {'port_id': port,
+ 'ch_grp_id': ch_grp_id,}
+ prompt = 'Switch \(config-if {0}\)#'.format(port)
+ cmds = map(lambda x: [x.format(**attrs), prompt], _cmds)
+ self.console(cmds + ret_mode)
+ time.sleep(5)
+
+ def lacp_set_port_ready(self, ch_grp_id, ports):
+ #---------------------------------------
+ # close lacp port channel
+ self.lacp_close_ports(ch_grp_id, ports)
+ #---------------------------------------
+ ret_mode= [['exit', '#']]
+ # reset lacp port channel
+ _cmds =[
+ 'interface {port_id}',
+ #'channel-group {ch_grp_id} lacp port-priority 128',
+ "no channel-group {ch_grp_id} defaulting",
+ 'channel-group {ch_grp_id} timeout long',
+ 'channel-group {ch_grp_id} mode active',
+ #'channel-group {ch_grp_id} partner key 0',
+ #'channel-group {ch_grp_id} partner number 1,
+ ]
+ for port in sorted(ports):
+ attrs = {'port_id': port,
+ 'ch_grp_id': ch_grp_id,}
+ prompt = 'Switch \(config-if {0}\)#'.format(port)
+ cmds = map(lambda x: [x.format(**attrs), prompt], _cmds)
+ self.console(cmds + ret_mode)
+ # wait 5 second to make sure port ready to work
+ time.sleep(5)
+ _cmds = ['interface {port_id}',
+ 'channel-group {ch_grp_id} collecting',
+ 'channel-group {ch_grp_id} distributing',
+ 'channel-group {ch_grp_id} synchronization',]
+ for port in sorted(ports):
+ attrs = {'port_id': port,
+ 'ch_grp_id': ch_grp_id,}
+ prompt = 'Switch \(config-if {0}\)#'.format(port)
+ cmds = map(lambda x: [x.format(**attrs), prompt], _cmds)
+ self.console(cmds + ret_mode)
+ # wait default long timeout interval to make sure lacp sync with
+ # parter successful
+ time.sleep(30)
+
+ def lacp_get_info(self, ch_grp_id):
+ infos = self.pch_get_group_info(ch_grp_id)
+ return infos
+
+ def lacp_get_remote_info(self, ch_grp_id):
+ infos = self.pch_get_grp_remote_info(ch_grp_id)
+ return infos
+
+ def lacp_get_admin_info(self, ch_grp_id):
+ infos = self.pch_get_grp_admin_info(ch_grp_id)
+ return infos
+
+ def lacp_is_ready(self, ch_grp_id):
+ max_try = 3
+ time_interval = 10
+ while max_try:
+ details = self.lacp_get_info(ch_grp_id)
+ msgs = []
+ for port, value in details.iteritems():
+ # check if interface lacp is on enable status
+ if value['LACP Operational Status'] != 'Enabled':
+ msg = "interface {0} lacp not ready".format(port)
+ msgs.append(msg)
+ # check if interface is ready for traffic
+ if 'Churn Detection Status' != 'True':
+ msg = "interface {0} traffic not ready".format(port)
+ msgs.append(msg)
+ else:
+ return True
+ time.sleep(time_interval)
+ max_try -= 1
+ else:
+ error = os.linesep.join(msgs)
+ raise SwitchException(error)
+
+ def lacp_filter_intf_attrs(self, content, patStr):
+ pat = re.compile(patStr)
+ result = pat.findall(content)
+ if not result:
+ msg = "have not found expected content"
+ self.logger.error(msg)
+ return None
+ info = result[0]
+ attrs = {}
+ for cnt in range(1, len(info), 2):
+ attrs.update({info[cnt]: info[cnt+1]})
+ attrs.update({'id': info[0]})
+ return attrs
+ ########################################################################
+ ##### use for debug/unit test
+ ########################################################################
+ def test_debug_cmds(self):
+ self.pch_add_ports(100, 4000, ['xe1', 'xe2', 'xe3', 'xe4'])
+ self.pch_get_ports_config(4000)
+ self.pch_get_member_status(4000)
+ self.intf_get_config(["xe1"])
+ self.intf_shutdown("xe10")
+ self.intf_no_shutdown("xe10")
+
+ def test_get_current_mode(self):
+ self.enter_configure()
+ self.console(["interface xe1", "Switch"])
+ self.enter_configure()
+ self.console(["exit", "Switch"])
+ self.enter_configure()
+
+class QuantaT3048Iz1(QuantaONS):
+ '''Quanta switch T3048-Iz1'''
+ # quanta 3048H switch maximum port number
+ MAX_PORTS = 48
+ VLAN_RANGE = [1, 4094]
+ PORT_CHANNEL_RANGE = [3800, 4094]
+ def __init__(self, *args, **kwargs):
+ super(QuantaT3048Iz1, self).__init__(*args, **kwargs)
+
+class LacpSceneBase(object):
+ def __init__(self):
+ pass
+
+ def set_interface_down(self, port):
+ raise NotImplementedError
+
+ def set_interface_up(self, port):
+ raise NotImplementedError
+
+ def get_interface_stats(self):
+ raise NotImplementedError
+
+ def get_all_statistics(self):
+ raise NotImplementedError
+
+ def clear_all_statistics(self):
+ raise NotImplementedError
+
+ @abstractmethod
+ def create_scene(self):
+ '''create lacp scene'''
+ raise NotImplementedError
+
+ @abstractmethod
+ def init_scene(self):
+ '''initialize lacp scene'''
+ raise NotImplementedError
+
+ @abstractmethod
+ def start_scene(self):
+ '''start lacp scene'''
+ raise NotImplementedError
+
+ @abstractmethod
+ def reset_scene(self):
+ '''close lacp scene'''
+ raise NotImplementedError
+
+ @abstractmethod
+ def stop_scene(self):
+ '''close lacp scene'''
+ raise NotImplementedError
+
+ @abstractmethod
+ def delete_scene(self):
+ '''delete lacp scene, release all resource'''
+ raise NotImplementedError
+
+ @abstractmethod
+ def close(self):
+ raise NotImplementedError
+
+class QuantaLacpScene(LacpSceneBase):
+ '''Quanta switch lacp scene'''
+
+ CLS ={'t3048-iz1': QuantaT3048Iz1}
+ def __init__(self, cls_name, *args, **kwargs):
+ model = kwargs.get('model')
+ if not model:
+ msg = "desired switch {0} is not supported".format(model)
+ raise SwitchException(msg)
+ self.logger = kwargs.get('logger')
+ self.logger.info("use switch <{model}>".format(**kwargs))
+ #self.sw = cls_name(*args, **kwargs)
+ self.sw = self.CLS[model](*args, **kwargs)
+ ########################################################################
+ # switch logic method for lacp
+ ########################################################################
+ def lacp_bind_ports(self, vlan, ch_grp_id, ports):
+ self.sw.lacp_add_ports(vlan, ch_grp_id, ports)
+
+ def lacp_unbind_ports(self, vlan, ch_grp_id, ports):
+ self.sw.pch_remove_ports(vlan, ch_grp_id, ports)
+
+ def lacp_get_interface_info(self, port_id):
+ '''get port status related with lacp'''
+ pass
+ ########################################################################
+ ##### switch abstract method for user
+ ########################################################################
+ def get_member(self):
+ ''' get lacp members '''
+ return self.sw.pch_get_member(self.ch_grp_id)
+
+ def get_all_statistics(self):
+ ''' get lacp members' statistics '''
+ return self.sw.pch_get_ports_stats(self.ports)
+
+ def clear_all_statistics(self):
+ '''clear lacp members' statistics
+
+ Run it before creating lacp channel with testpmd
+ '''
+ self.sw.pch_shutdown(self.ch_grp_id)
+ self.sw.pch_clear_stats(self.ch_grp_id, self.ports)
+ #self.sw.pch_no_shutdown(self.ch_grp_id)
+ # here long time wait for port rebind to port channel
+
+ def set_ready(self):
+ ''' set lacp members on ready status '''
+ self.sw.lacp_set_port_ready(self.ch_grp_id, self.ports)
+ self.sw.lacp_is_ready(self.ch_grp_id)
+
+ def set_interface_down(self, port):
+ '''set a interface on link down'''
+ msg = "quanta switch don't support shutdown port at lacp mode"
+ self.logger.warning(msg)
+
+ def set_interface_up(self, port):
+ '''set a interface on link up'''
+ msg = "quanta switch don't support no shutdown port at lacp mode"
+ self.logger.warning(msg)
+
+ def create_scene(self, vlan_id, ch_grp_id, ports):
+ '''create lacp scene on switch'''
+ self.sw.create_vlan(vlan_id)
+ self.sw.create_port_channel(ch_grp_id)
+ self.sw.lacp_set_port_channel(vlan_id, ch_grp_id)
+ #self.sw.pch_clear_ports(ports)
+ self.sw.lacp_init_ports(vlan_id, ch_grp_id, ports)
+ self.sw.pch_no_shutdown(ch_grp_id)
+
+ def init_scene(self, auto_config=False, **kwargs):
+ '''create a desired lacp scene
+
+ @param auto_config:
+ ``True`` create a desired lacp scene automatically
+ ``False`` use a lacp scene set by user manually
+ '''
+ # get lacp scene configuration
+ _id = kwargs.get('vlan id')
+ self.vlan_id = int(_id) if isinstance(_id, (str, unicode)) else _id
+ if not self.vlan_id or not self.sw.vlan_id_in_range(self.vlan_id):
+ msg = 'vlan id not set'
+ raise SwitchException(msg)
+
+ _id = kwargs.get('channel group id')
+ self.ch_grp_id = int(_id) if isinstance(_id, (str, unicode)) else _id
+ if not self.ch_grp_id or not self.sw.pch_id_in_range(self.ch_grp_id):
+ msg = 'channel group id not set'
+ raise SwitchException(msg)
+
+ self.ports = kwargs.get('port member')
+ if not self.ports:
+ msg = 'port member not set'
+ raise SwitchException(msg)
+ # create lacp scene on switch
+ if auto_config:
+ self.create_scene(self.vlan_id, self.ch_grp_id, self.ports)
+
+ def clear_scene(self):
+ '''clear lacp scene
+
+ clear interface statistics data and LPDU Counter data
+ '''
+ self.clear_all_statistics()
+ # testpmd 802.3ad long timeout is 90 second, so wait longer than that
+ # to make sure parter/actor sync successful
+ time.sleep(120)
+
+ def start_scene(self):
+ '''start lacp scene'''
+ self.sw.pch_no_shutdown(self.ch_grp_id)
+ time.sleep(60)
+
+ def reset_scene(self):
+ '''reset lacp scene'''
+ #self.clear_all_statistics()
+ self.set_ready()
+ #self.sw.pch_shutdown(self.ch_grp_id)
+ #time.sleep(10)
+ #self.sw.pch_no_shutdown(self.ch_grp_id)
+ #time.sleep(10)
+ #self.set_ready()
+ # testpmd 802.3ad long timeout is 90 second, so wait longer than that
+ # to make sure parter/actor sync successful
+ time.sleep(120)
+
+ def stop_scene(self):
+ '''stop lacp scene'''
+ self.sw.pch_shutdown(self.ch_grp_id)
+ self.sw.lacp_close_ports(self.ch_grp_id, self.ports)
+ time.sleep(60)
+
+ def delete_scene(self):
+ '''delete lacp scene'''
+ pass
+
+class CiscoLacpScene(): pass
+
+class SwitchScene(SSHConnection):
+ '''
+ : create a switch work scene base
+ '''
+ # define different work scene based on switch manufacturer/model
+ CLS = {'quanta lacp': [QuantaLacpScene, '# '],
+ 'cisco lacp': [CiscoLacpScene, '#']}
+ def __init__(self, *arg):
+ # get switch configuration
+ (self.name, self.switch_name, self.model, ip, user, passwd,
+ self.scene, self.vlan_id, self.port_channel_id, self.ports_list,
+ auto_config) = arg
+ name = " ".join([self.switch_name, self.scene])
+ switch_CLS = self.CLS[name][0]
+ self.default_prompt = self.CLS[name][1]
+ # initialize switch session/logger
+ self.logger = getLogger(self.name)
+ super(SwitchScene, self).__init__(ip, self.name, passwd,
+ user, node_type="switch")
+ super(SwitchScene, self).init_log(self.logger)
+ # initialize switch equipment
+ self.say("initialize")
+ configs = {"console": self.console,
+ "model": self.model,
+ 'logger': self.logger}
+ self.switch = switch_CLS(self.switch_name, *[], **configs)
+ lacp_scene = {'vlan id': self.vlan_id,
+ 'channel group id': self.port_channel_id,
+ 'port member': self.ports_list}
+ self.switch.init_scene(auto_config=auto_config, **lacp_scene)
+
+ def say(self, action):
+ msg_fmt = "{0} <{1}> [{2} {3}] '{4}' work scene".format
+ self.logger.info(msg_fmt(action, self.name, self.switch_name,
+ self.model, self.scene))
+ ########################################################################
+ ##### console method used to run switch command
+ ########################################################################
+ def check_disired_msg(self, output, expected_items):
+ self.logger.info(output)
+ expected_output = expected_items[1]
+ check_type = True if len(expected_items) == 2 else expected_items[2]
+ if check_type and expected_output in output:
+ msg = "expected '{0}' is in output".format(expected_output)
+ self.logger.info(msg)
+ elif not check_type and expected_output not in output:
+ msg = "unexpected '{0}' is not in output".format(
+ expected_output)
+ self.logger.info(msg)
+ else:
+ status = "isn't in" if check_type else "is in"
+ msg = "[{0}] {1} output".format(expected_output, status)
+ self.logger.error(msg)
+ raise SwitchException(msg)
+
+ def console(self, cmds):
+ if len(cmds) == 0:
+ return
+ # check if cmds is string
+ if isinstance(cmds, str):
+ timeout = 15
+ cmds = [[cmds, '', timeout]]
+ # check if cmds is only one command
+ if not isinstance(cmds[0], list):
+ cmds = [cmds]
+ output_list = []
+ for item in cmds:
+ cmd = item[0]
+ expected_items = item[1]
+ if expected_items and isinstance(expected_items, (list, tuple)):
+ check_output = True
+ expected_str = expected_items[0] or self.default_prompt
+ else:
+ check_output = False
+ expected_str = expected_items or self.default_prompt
+ #----------------
+ timeout = int(item[2]) if len(item) == 3 else 5
+ #----------------
+ # run command on session
+ try:
+ output = self.send_expect(cmd, expected_str, timeout)
+ output = self.session.get_output_all() \
+ if not output.strip() else output
+ except TimeoutException:
+ # quanta switch software don't display all output when output
+ # is more than one pagepage, so use space charater to show the
+ # left content
+ if self.switch_name == 'quanta':
+ output_1 = self.session.get_output_all()
+ try:
+ if "<?> - help" in output_1:
+ output_1 ='\r\n'.join(output_1.splitlines()[:-1])+\
+ '\r\n'
+ output_2 = self.send_expect(" ", expected_str,
+ timeout)
+ output = output_1 + output_2
+ except Exception as e:
+ output = output_1
+ finally:
+ pass
+ else:
+ msg = "execute '{0}' timeout".format(cmd)
+ raise TimeoutException(cmd, msg)
+ except Exception as e:
+ exc_info = sys.exc_info()
+ traceback.print_exception(exc_info[0], exc_info[1],
+ exc_info[2], None, sys.stderr)
+ finally:
+ pass
+ # when user set expected string, check it on output
+ if check_output and len(expected_items) >= 2:
+ self.check_disired_msg(output, expected_items)
+ else:
+ output_list.append(output)
+ time.sleep(2)
+ retOutput = output_list[0] if len(cmds) == 1 else output_list
+ return retOutput
+ ########################################################################
+ ##### methods for dts framework
+ ########################################################################
+ def get_ports(self):
+ """ get switch ports """
+ plist = list()
+ if self.session is None:
+ msg = "switch session failed to create"
+ self.logger.warning(msg)
+ return plist
+ for port in self.ports_list:
+ plist.append({'type': 'switch',
+ 'pci': 'SWITCH:{0}'.format(port)})
+ return plist
+ ########################################################################
+ ##### switch methods for user
+ ########################################################################
+ def _get_mac(self, port):
+ return self.switch.get_mac(port)
+
+ def vlan(self):
+ """ return lacp scene vlan id """
+ return self.vlan_id
+
+ def port_channel(self):
+ """ return lacp scene port channel id """
+ return self.port_channel_id
+
+ def ports(self):
+ """ return lacp scene ports """
+ return self.ports_list
+
+ def get_stats(self):
+ ''' get lacp members' statistics '''
+ results = self.switch.get_all_statistics()
+ return results
+
+ def clear_stats(self):
+ ''' clear lacp members' statistics '''
+ self.switch.clear_all_statistics()
+
+ def set_intf_down(self, port_id):
+ ''' set interface down '''
+ self.switch.set_interface_down(port_id)
+
+ def set_intf_up(self, port_id):
+ ''' set interface up '''
+ self.switch.set_interface_up(port_id)
+
+ def get_member(self):
+ ''' get interfaces belong a lacp configuration '''
+ return self.switch.get_member()
+
+ def clear(self):
+ '''clear switch work scene'''
+ self.say('start')
+ self.switch.clear_scene()
+
+ def start(self):
+ '''activate switch work scene'''
+ self.say('start')
+ self.switch.start_scene()
+
+ def reset(self):
+ '''reset switch work scene to original status'''
+ self.say('reset')
+ self.switch.reset_scene()
+
+ def stop(self):
+ '''stop switch work scene'''
+ self.say('stop')
+ self.switch.stop_scene()
+
+ def quit(self):
+ '''quit switch work scene'''
+ self.say('quit')
+ self.switch.stop_scene()
+ self.close(force=True)
+
+class Switch(object):
+ '''use for switch work scene creation
+
+ support multiple work scenes creation, every work scene configuration
+ is in dts/conf/switch.cfg. Each ``SwitchScene`` class instance manage
+ its own resources/status of work scene.
+ '''
+ def __init__(self):
+ self.switch_grp = {}
+
+ def init_scenes(self, tester):
+ for name, config in self.get_config(tester):
+ self.switch_grp[name] = SwitchScene(*config)
+
+ def get_config(self, tester):
+ '''get switch configuration from cfg file'''
+ switchRef = tester.get_switch_crb()
+ switchcfg = SwitchConf()
+ switchConfigs = switchcfg.load_switch_config()
+ if not switchRef or not switchConfigs:
+ msg = "wrong switch configuration"
+ raise ConfigParseException(msg)
+
+ for name, switch_config in switchConfigs.iteritems():
+ # under default status, switch scene will config resources status
+ # automatically
+ if 'auto_config' not in switch_config:
+ auto_config = True
+ else:
+ value = switch_config['auto_config'].lower()
+ auto_config = True if value == 'true' else False
+ config = [name,
+ # 'manufacturer'
+ switch_config["manufacturer"],
+ # 'model'
+ switch_config["model"],
+ # switch ip address/user/passwd
+ # 'ip':
+ switch_config["ip"],
+ # 'user':
+ switch_config["user"],
+ # 'passwd':
+ switch_config["passwd"],
+ # configuration scene
+ # 'scene':
+ switch_config["scene"],
+ # 'vlan_id':
+ switch_config["vlan"],
+ # 'port_channel_id':
+ switch_config["port-channel"],
+ # 'ports':
+ switch_config["ports"],
+ auto_config]
+
+ yield name, config
\ No newline at end of file
--
1.9.3
More information about the dts
mailing list