Example #1
0
    def tablelize(keys, data):
        table = []

        for k in natsorted(keys):
            members = set(data[k].get('members', []))
            for (vlan, interface_name) in member_data:
                if vlan == k:
                    members.add(interface_name)

            for m in members:
                r = []
                r.append(k)
                r.append(data[k]['vlanid'])
                if clicommon.get_interface_naming_mode() == "alias":
                    alias = clicommon.InterfaceAliasConverter(
                        db).name_to_alias(m)
                    r.append(alias)
                else:
                    r.append(m)

                entry = db.cfgdb.get_entry('VLAN_MEMBER', (k, m))
                mode = entry.get('tagging_mode')
                if mode is None:
                    r.append('?')
                else:
                    r.append(mode)

                table.append(r)

        return table
Example #2
0
def del_vlan_member(db, vid, port):
    """Delete VLAN member"""

    ctx = click.get_current_context()

    log.log_info("'vlan member del {} {}' executing...".format(vid, port))

    if not clicommon.is_vlanid_in_range(vid):
        ctx.fail("Invalid VLAN ID {} (1-4094)".format(vid))

    vlan = 'Vlan{}'.format(vid)
    if clicommon.check_if_vlanid_exist(db.cfgdb, vlan) == False:
        ctx.fail("{} does not exist".format(vlan))

    if clicommon.get_interface_naming_mode() == "alias":
        alias = port
        iface_alias_converter = clicommon.InterfaceAliasConverter(db)
        port = iface_alias_converter.alias_to_name(alias)
        if port is None:
            ctx.fail("cannot find port name for alias {}".format(alias))

    if not clicommon.is_port_vlan_member(db.cfgdb, port, vlan):
        ctx.fail("{} is not a member of {}".format(port, vlan))

    db.cfgdb.set_entry('VLAN_MEMBER', (vlan, port), None)
Example #3
0
def expected(db, interfacename):
    """Show expected neighbor information by interfaces"""

    neighbor_dict = db.cfgdb.get_table("DEVICE_NEIGHBOR")
    if neighbor_dict is None:
        click.echo("DEVICE_NEIGHBOR information is not present.")
        return

    neighbor_metadata_dict = db.cfgdb.get_table("DEVICE_NEIGHBOR_METADATA")
    if neighbor_metadata_dict is None:
        click.echo("DEVICE_NEIGHBOR_METADATA information is not present.")
        return

    #Swap Key and Value from interface: name to name: interface
    device2interface_dict = {}
    for port in natsorted(neighbor_dict.keys()):
        temp_port = port
        if clicommon.get_interface_naming_mode() == "alias":
            port = clicommon.InterfaceAliasConverter().name_to_alias(port)
            neighbor_dict[port] = neighbor_dict.pop(temp_port)
        device2interface_dict[neighbor_dict[port]['name']] = {
            'localPort': port,
            'neighborPort': neighbor_dict[port]['port']
        }

    header = [
        'LocalPort', 'Neighbor', 'NeighborPort', 'NeighborLoopback',
        'NeighborMgmt', 'NeighborType'
    ]
    body = []
    if interfacename:
        try:
            device = neighbor_dict[interfacename]['name']
            body.append([
                interfacename, device, neighbor_dict[interfacename]['port'],
                neighbor_metadata_dict[device]['lo_addr'],
                neighbor_metadata_dict[device]['mgmt_addr'],
                neighbor_metadata_dict[device]['type']
            ])
        except KeyError:
            click.echo(
                "No neighbor information available for interface {}".format(
                    interfacename))
            return
    else:
        for port in natsorted(neighbor_dict.keys()):
            try:
                device = neighbor_dict[port]['name']
                body.append([
                    port, device, neighbor_dict[port]['port'],
                    neighbor_metadata_dict[device]['lo_addr'],
                    neighbor_metadata_dict[device]['mgmt_addr'],
                    neighbor_metadata_dict[device]['type']
                ])
            except KeyError:
                pass

    click.echo(tabulate(body, header))
Example #4
0
def try_convert_interfacename_from_alias(ctx, interfacename):
    """try to convert interface name from alias"""

    if clicommon.get_interface_naming_mode() == "alias":
        alias = interfacename
        interfacename = clicommon.InterfaceAliasConverter().alias_to_name(alias)
        # TODO: ideally alias_to_name should return None when it cannot find
        # the port name for the alias
        if interfacename == alias:
            ctx.fail("cannot find interface name for alias {}".format(alias))

    return interfacename
Example #5
0
def add_vlan_member(db, vid, port, untagged):
    """Add VLAN member"""

    ctx = click.get_current_context()

    log.log_info("'vlan member add {} {}' executing...".format(vid, port))

    if not clicommon.is_vlanid_in_range(vid):
        ctx.fail("Invalid VLAN ID {} (1-4094)".format(vid))

    vlan = 'Vlan{}'.format(vid)
    if clicommon.check_if_vlanid_exist(db.cfgdb, vlan) == False:
        ctx.fail("{} does not exist".format(vlan))

    if clicommon.get_interface_naming_mode() == "alias":
        alias = port
        iface_alias_converter = clicommon.InterfaceAliasConverter(db)
        port = iface_alias_converter.alias_to_name(alias)
        if port is None:
            ctx.fail("cannot find port name for alias {}".format(alias))

    if clicommon.is_port_mirror_dst_port(db.cfgdb, port):
        ctx.fail("{} is configured as mirror destination port".format(port))

    if clicommon.is_port_vlan_member(db.cfgdb, port, vlan):
        ctx.fail("{} is already a member of {}".format(port, vlan))

    if clicommon.is_valid_port(db.cfgdb, port):
        is_port = True
    elif clicommon.is_valid_portchannel(db.cfgdb, port):
        is_port = False
    else:
        ctx.fail("{} does not exist".format(port))

    if (is_port and clicommon.is_port_router_interface(db.cfgdb, port)) or \
       (not is_port and clicommon.is_pc_router_interface(db.cfgdb, port)):
        ctx.fail("{} is a router interface!".format(port))

    portchannel_member_table = db.cfgdb.get_table('PORTCHANNEL_MEMBER')

    if (is_port and clicommon.interface_is_in_portchannel(
            portchannel_member_table, port)):
        ctx.fail("{} is part of portchannel!".format(port))

    if (clicommon.interface_is_untagged_member(db.cfgdb, port) and untagged):
        ctx.fail("{} is already untagged member!".format(port))

    db.cfgdb.set_entry('VLAN_MEMBER', (vlan, port),
                       {'tagging_mode': "untagged" if untagged else "tagged"})
Example #6
0
    def get_teamshow_result(self):
        """
             Get teamshow results by parsing the output of teamdctl and combining port channel status.
        """
        for team in self.teams:
            info = {}
            team_id = self.get_team_id(team)
            if team_id not in self.teamsraw:
                info['protocol'] = 'N/A'
                self.summary[team_id] = info
                self.summary[team_id]['ports'] = ''
                continue
            state = self.teamsraw[team_id]
            info['protocol'] = "LACP"
            info['protocol'] += "(A)" if state['runner.active'] == "true" else '(I)'

            portchannel_status = self.get_portchannel_status(team)
            if portchannel_status is None:
                info['protocol'] += '(N/A)'
            elif portchannel_status.lower() == 'up':
                info['protocol'] += '(Up)'
            elif portchannel_status.lower() == 'down':
                info['protocol'] += '(Dw)'
            else:
                info['protocol'] += '(N/A)'

            info['ports'] = ""
            member_keys = self.db.keys(self.db.STATE_DB, PORT_CHANNEL_MEMBER_STATE_TABLE_PREFIX+team+'|*')
            if member_keys is None:
                info['ports'] = 'N/A'
            else:
                ports = [key[len(PORT_CHANNEL_MEMBER_STATE_TABLE_PREFIX+team+'|'):] for key in member_keys]
                for port in ports:
                    status = self.get_portchannel_member_status(team, port)
                    pstate = self.db.get_all(self.db.STATE_DB, PORT_CHANNEL_MEMBER_STATE_TABLE_PREFIX+team+'|'+port)
                    selected = True if pstate['runner.aggregator.selected'] == "true" else False
                    if clicommon.get_interface_naming_mode() == "alias":
                        alias = clicommon.InterfaceAliasConverter(self.db2).name_to_alias(port)
                        info["ports"] += alias + "("
                    else:
                        info["ports"] += port + "("
                    info["ports"] += "S" if selected else "D"
                    if status is None or (status == "enabled" and not selected) or (status == "disabled" and selected):
                        info["ports"] += "*"
                    info["ports"] += ") "

            self.summary[team_id] = info
Example #7
0
def config(db):
    data = db.cfgdb.get_table('VLAN')
    keys = list(data.keys())
    member_data = db.cfgdb.get_table('VLAN_MEMBER')
    interface_naming_mode = clicommon.get_interface_naming_mode()
    iface_alias_converter = clicommon.InterfaceAliasConverter(db)

    def get_iface_name_for_display(member):
        name_for_display = member
        if interface_naming_mode == "alias" and member:
            name_for_display = iface_alias_converter.name_to_alias(member)
        return name_for_display

    def get_tagging_mode(vlan, member):
        if not member:
            return ''
        tagging_mode = db.cfgdb.get_entry('VLAN_MEMBER',
                                          (vlan, member)).get('tagging_mode')
        return '?' if tagging_mode is None else tagging_mode

    def tablelize(keys, data):
        table = []

        for k in natsorted(keys):
            members = set([(vlan, member)
                           for vlan, member in member_data if vlan == k] +
                          [(k, member)
                           for member in set(data[k].get('members', []))])
            # vlan with no members
            if not members:
                members = [(k, '')]

            for vlan, member in natsorted(members):
                r = [
                    vlan, data[vlan]['vlanid'],
                    get_iface_name_for_display(member),
                    get_tagging_mode(vlan, member)
                ]
                table.append(r)

        return table

    header = ['Name', 'VID', 'Member', 'Mode']
    click.echo(tabulate(tablelize(keys, data), header))
Example #8
0
def del_port(db, port):
    """
    Delete MACsec port
    """
    ctx = click.get_current_context()

    if clicommon.get_interface_naming_mode() == "alias":
        alias = port
        iface_alias_converter = clicommon.InterfaceAliasConverter(db)
        port = iface_alias_converter.alias_to_name(alias)
        if port is None:
            ctx.fail("cannot find port name for alias {}".format(alias))

    port_entry = db.cfgdb.get_entry('PORT', port)
    if len(port_entry) == 0:
        ctx.fail("port {} doesn't exist".format(port))

    del port_entry['macsec']

    db.cfgdb.set_entry("PORT", port, port_entry)
Example #9
0
def mpls(ctx, interfacename):
    """Show Interface MPLS status"""

    appl_db = SonicV2Connector()
    appl_db.connect(appl_db.APPL_DB)

    if interfacename is not None:
        interfacename = try_convert_interfacename_from_alias(ctx, interfacename)

    # Fetching data from appl_db for intfs
    keys = appl_db.keys(appl_db.APPL_DB, "INTF_TABLE:*")
    intfs_data = {}
    for key in keys if keys else []:
        tokens = key.split(":")
        # Skip INTF_TABLE entries with address information
        if len(tokens) != 2:
            continue

        if (interfacename is not None) and (interfacename != tokens[1]):
            continue

        mpls = appl_db.get(appl_db.APPL_DB, key, 'mpls')
        if mpls is None or mpls == '':
            intfs_data.update({tokens[1]: 'disable'})
        else:
            intfs_data.update({tokens[1]: mpls})

    header = ['Interface', 'MPLS State']
    body = []

    # Output name and alias for all interfaces
    for intf_name in natsorted(list(intfs_data.keys())):
        if clicommon.get_interface_naming_mode() == "alias":
            alias = clicommon.InterfaceAliasConverter().name_to_alias(intf_name)
            body.append([alias, intfs_data[intf_name]])
        else:
            body.append([intf_name, intfs_data[intf_name]])

    click.echo(tabulate(body, header))
Example #10
0
def get_vlan_ports(ctx, vlan):
    cfg, db = ctx
    _, _, vlan_ports_data = cfg
    vlan_ports = []
    iface_alias_converter = clicommon.InterfaceAliasConverter(db)
    # Here natsorting is important in relation to another
    # column which prints port tagging mode.
    # If we sort both in the same way using same keys
    # we will result in right order in both columns.
    # This should be fixed by cli code autogeneration tool
    # and we won't need this specific approach with
    # VlanBrief.COLUMNS anymore.
    for key in natsorted(list(vlan_ports_data.keys())):
        ports_key, ports_value = key
        if vlan != ports_key:
            continue

        if clicommon.get_interface_naming_mode() == "alias":
            ports_value = iface_alias_converter.name_to_alias(ports_value)

        vlan_ports.append(ports_value)

    return '\n'.join(vlan_ports)
Example #11
0
        if return_cmd:
            output = proc.communicate()[0]
            return output
        output = proc.stdout.readline()
        if output == "" and proc.poll() is not None:
            break
        if output:
            click.echo(output.rstrip('\n'))

    rc = proc.poll()
    if rc != 0:
        sys.exit(rc)


# Global class instance for SONiC interface name to alias conversion
iface_alias_converter = clicommon.InterfaceAliasConverter()


def connect_config_db():
    """
    Connects to config_db
    """
    config_db = ConfigDBConnector()
    config_db.connect()
    return config_db


CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help', '-?'])

#
# 'cli' group (root group)
Example #12
0
def brief(db, verbose):
    """Show all bridge information"""
    header = [
        'VLAN ID', 'IP Address', 'Ports', 'Port Tagging',
        'DHCP Helper Address', 'Proxy ARP'
    ]
    body = []

    # Fetching data from config db for VLAN, VLAN_INTERFACE and VLAN_MEMBER
    vlan_dhcp_helper_data = db.cfgdb.get_table('VLAN')
    vlan_ip_data = db.cfgdb.get_table('VLAN_INTERFACE')
    vlan_ports_data = db.cfgdb.get_table('VLAN_MEMBER')

    # Defining dictionaries for DHCP Helper address, Interface Gateway IP,
    # VLAN ports and port tagging
    vlan_dhcp_helper_dict = {}
    vlan_ip_dict = {}
    vlan_ports_dict = {}
    vlan_tagging_dict = {}
    vlan_proxy_arp_dict = {}

    # Parsing DHCP Helpers info
    for key in natsorted(list(vlan_dhcp_helper_data.keys())):
        try:
            if vlan_dhcp_helper_data[key]['dhcp_servers']:
                vlan_dhcp_helper_dict[key.strip(
                    'Vlan')] = vlan_dhcp_helper_data[key]['dhcp_servers']
        except KeyError:
            vlan_dhcp_helper_dict[key.strip('Vlan')] = " "

    # Parsing VLAN Gateway info
    for key in vlan_ip_data:
        if clicommon.is_ip_prefix_in_key(key):
            interface_key = key[0].strip("Vlan")
            interface_value = key[1]

            if interface_key in vlan_ip_dict:
                vlan_ip_dict[interface_key].append(interface_value)
            else:
                vlan_ip_dict[interface_key] = [interface_value]
        else:
            interface_key = key.strip("Vlan")
            if 'proxy_arp' in vlan_ip_data[key]:
                proxy_arp_status = vlan_ip_data[key]['proxy_arp']
            else:
                proxy_arp_status = "disabled"

            vlan_proxy_arp_dict[interface_key] = proxy_arp_status

    iface_alias_converter = clicommon.InterfaceAliasConverter(db)

    # Parsing VLAN Ports info
    for key in natsorted(list(vlan_ports_data.keys())):
        ports_key = key[0].strip("Vlan")
        ports_value = key[1]
        ports_tagging = vlan_ports_data[key]['tagging_mode']
        if ports_key in vlan_ports_dict:
            if clicommon.get_interface_naming_mode() == "alias":
                ports_value = iface_alias_converter.name_to_alias(ports_value)
            vlan_ports_dict[ports_key].append(ports_value)
        else:
            if clicommon.get_interface_naming_mode() == "alias":
                ports_value = iface_alias_converter.name_to_alias(ports_value)
            vlan_ports_dict[ports_key] = [ports_value]
        if ports_key in vlan_tagging_dict:
            vlan_tagging_dict[ports_key].append(ports_tagging)
        else:
            vlan_tagging_dict[ports_key] = [ports_tagging]

    # Printing the following dictionaries in tablular forms:
    # vlan_dhcp_helper_dict={}, vlan_ip_dict = {}, vlan_ports_dict = {}
    # vlan_tagging_dict = {}
    for key in natsorted(list(vlan_dhcp_helper_dict.keys())):
        if key not in vlan_ip_dict:
            ip_address = ""
        else:
            ip_address = ','.replace(',', '\n').join(vlan_ip_dict[key])
        if key not in vlan_ports_dict:
            vlan_ports = ""
        else:
            vlan_ports = ','.replace(',', '\n').join((vlan_ports_dict[key]))
        if key not in vlan_dhcp_helper_dict:
            dhcp_helpers = ""
        else:
            dhcp_helpers = ','.replace(',',
                                       '\n').join(vlan_dhcp_helper_dict[key])
        if key not in vlan_tagging_dict:
            vlan_tagging = ""
        else:
            vlan_tagging = ','.replace(',', '\n').join(
                (vlan_tagging_dict[key]))
        vlan_proxy_arp = vlan_proxy_arp_dict.get(key, "disabled")
        body.append([
            key, ip_address, vlan_ports, vlan_tagging, dhcp_helpers,
            vlan_proxy_arp
        ])
    click.echo(tabulate(body, header, tablefmt="grid"))
Example #13
0
def mpls(ctx, interfacename, namespace, display):
    """Show Interface MPLS status"""

    #Edge case: Force show frontend interfaces on single asic
    if not (multi_asic.is_multi_asic()):
        if (display == 'frontend' or display == 'all' or display is None):
            display = None
        else:
            print("Error: Invalid display option command for single asic")
            return

    display = "all" if interfacename else display
    masic = multi_asic_util.MultiAsic(display_option=display,
                                      namespace_option=namespace)
    ns_list = masic.get_ns_list_based_on_options()
    intfs_data = {}
    intf_found = False

    for ns in ns_list:

        appl_db = multi_asic.connect_to_all_dbs_for_ns(namespace=ns)

        if interfacename is not None:
            interfacename = try_convert_interfacename_from_alias(
                ctx, interfacename)

        # Fetching data from appl_db for intfs
        keys = appl_db.keys(appl_db.APPL_DB, "INTF_TABLE:*")
        for key in keys if keys else []:
            tokens = key.split(":")
            ifname = tokens[1]
            # Skip INTF_TABLE entries with address information
            if len(tokens) != 2:
                continue

            if (interfacename is not None):
                if (interfacename != ifname):
                    continue

                intf_found = True

            if (display != "all"):
                if ("Loopback" in ifname):
                    continue

                if ifname.startswith(
                        "Ethernet") and multi_asic.is_port_internal(
                            ifname, ns):
                    continue

                if ifname.startswith(
                        "PortChannel") and multi_asic.is_port_channel_internal(
                            ifname, ns):
                    continue

            mpls_intf = appl_db.get_all(appl_db.APPL_DB, key)

            if 'mpls' not in mpls_intf or mpls_intf['mpls'] == 'disable':
                intfs_data.update({ifname: 'disable'})
            else:
                intfs_data.update({ifname: mpls_intf['mpls']})

    # Check if interface is valid
    if (interfacename is not None and not intf_found):
        ctx.fail('interface {} doesn`t exist'.format(interfacename))

    header = ['Interface', 'MPLS State']
    body = []

    # Output name and alias for all interfaces
    for intf_name in natsorted(list(intfs_data.keys())):
        if clicommon.get_interface_naming_mode() == "alias":
            alias = clicommon.InterfaceAliasConverter().name_to_alias(
                intf_name)
            body.append([alias, intfs_data[intf_name]])
        else:
            body.append([intf_name, intfs_data[intf_name]])

    click.echo(tabulate(body, header))