[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