예제 #1
0
def delete_ports_status_for_y_cable():

    state_db, port_tbl, y_cable_tbl = {}, {}, {}
    y_cable_tbl_keys = {}
    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        state_db[asic_id] = daemon_base.db_connect("STATE_DB", namespace)
        y_cable_tbl[asic_id] = swsscommon.Table(
            state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME)
        y_cable_tbl_keys[asic_id] = y_cable_tbl[asic_id].getKeys()

    # delete PORTS on Y cable table if ports on Y cable
    logical_port_list = y_cable_platform_sfputil.logical
    for logical_port_name in logical_port_list:

        # Get the asic to which this port belongs
        asic_index = y_cable_platform_sfputil.get_asic_id_for_logical_port(
            logical_port_name)
        if asic_index is None:
            logger.log_warning("Got invalid asic index for {}, ignored".format(
                logical_port_name))

        if logical_port_name in y_cable_tbl_keys[asic_index]:
            delete_port_from_y_cable_table(logical_port_name,
                                           y_cable_tbl[asic_index])
예제 #2
0
def metrics(port, json_output):
    """Show muxcable metrics <port>"""

    metrics_table_keys = {}
    per_npu_statedb = {}
    metrics_dict = {}

    # Getting all front asic namespace and correspding config and state DB connector

    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        # replace these with correct macros
        per_npu_statedb[asic_id] = swsscommon.SonicV2Connector(use_unix_socket_path=True, namespace=namespace)
        per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)

        metrics_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
            per_npu_statedb[asic_id].STATE_DB, 'MUX_METRICS_TABLE|*')

    if port is not None:

        logical_port_list = platform_sfputil_helper.get_logical_list()

        if port not in logical_port_list:
            click.echo(("ERR: Not a valid logical port for muxcable firmware {}".format(port)))
            sys.exit(CONFIG_FAIL)

        asic_index = None
        if platform_sfputil is not None:
            asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(port)
            if asic_index is None:
                # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
                # is fully mocked
                import sonic_platform_base.sonic_sfp.sfputilhelper
                asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper().get_asic_id_for_logical_port(port)
                if asic_index is None:
                    click.echo("Got invalid asic index for port {}, cant retreive mux status".format(port))


        metrics_dict[asic_index] = per_npu_statedb[asic_index].get_all(
            per_npu_statedb[asic_index].STATE_DB, 'MUX_METRICS_TABLE|{}'.format(port))

        if json_output:
            click.echo("{}".format(json.dumps(metrics_dict[asic_index], indent=4)))
        else:
            print_data = []
            for key, val in metrics_dict[asic_index].items():
                print_port_data = []
                print_port_data.append(port)
                print_port_data.append(key)
                print_port_data.append(val)
                print_data.append(print_port_data)

            headers = ['PORT', 'EVENT', 'TIME']

            click.echo(tabulate(print_data, headers=headers))
예제 #3
0
    def task_worker(self, stopping_event, sfp_error_event, y_cable_presence):
        helper_logger.log_info("Start Ycable monitoring loop")

        # Connect to STATE_DB and listen to ycable transceiver status update tables
        state_db, status_tbl = {}, {}
        port_dict = {}

        sel = swsscommon.Select()

        # Get the namespaces in the platform
        namespaces = multi_asic.get_front_end_namespaces()
        for namespace in namespaces:
            asic_id = multi_asic.get_asic_index_from_namespace(namespace)
            state_db[asic_id] = daemon_base.db_connect("STATE_DB", namespace)
            status_tbl[asic_id] = swsscommon.SubscriberStateTable(
                state_db[asic_id], TRANSCEIVER_STATUS_TABLE)
            sel.addSelectable(status_tbl[asic_id])

        while True:

            if self.task_stopping_event.is_set():
                break

            (state, selectableObj) = sel.select(SELECT_TIMEOUT)

            if state == swsscommon.Select.TIMEOUT:
                # Do not flood log when select times out
                continue
            if state != swsscommon.Select.OBJECT:
                helper_logger.log_warning(
                    "sel.select() did not  return swsscommon.Select.OBJECT for sonic_y_cable updates"
                )
                continue

            # Get the redisselect object  from selectable object
            redisSelectObj = swsscommon.CastSelectableToRedisSelectObj(
                selectableObj)
            # Get the corresponding namespace from redisselect db connector object
            namespace = redisSelectObj.getDbConnector().getNamespace()
            asic_index = multi_asic.get_asic_index_from_namespace(namespace)

            while True:
                (port, op, fvp) = status_tbl[asic_index].pop()
                if not port:
                    break

                if fvp:
                    fvp_dict = dict(fvp)

                if not fvp_dict:
                    continue

                port_dict[port] = fvp_dict.get('status', None)

                y_cable_helper.change_ports_status_for_y_cable_change_event(
                    port_dict, y_cable_presence, stopping_event)
예제 #4
0
def get_response_for_version(port, mux_info_dict):
    state_db = {}
    xcvrd_show_fw_res_tbl = {}

    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        state_db[asic_id] = db_connect("STATE_DB", namespace)
        xcvrd_show_fw_res_tbl[asic_id] = swsscommon.Table(
            state_db[asic_id], "XCVRD_SHOW_FW_RES")

    logical_port_list = platform_sfputil_helper.get_logical_list()
    if port not in logical_port_list:
        click.echo("ERR: This is not a valid port, valid ports ({})".format(
            ", ".join(logical_port_list)))
        rc = EXIT_FAIL
        res_dict[1] = rc
        return mux_info_dict

    asic_index = None
    if platform_sfputil is not None:
        asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(port)
    if asic_index is None:
        # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
        # is fully mocked
        import sonic_platform_base.sonic_sfp.sfputilhelper
        asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper(
        ).get_asic_id_for_logical_port(port)
        if asic_index is None:
            click.echo(
                "Got invalid asic index for port {}, cant retreive mux status".
                format(port))
            rc = CONFIG_FAIL
            res_dict[1] = rc
            return mux_info_dict

    (status, fvp) = xcvrd_show_fw_res_tbl[asic_index].get(port)
    res_dir = dict(fvp)
    mux_info_dict["version_nic_active"] = res_dir.get("version_nic_active",
                                                      None)
    mux_info_dict["version_nic_inactive"] = res_dir.get(
        "version_nic_inactive", None)
    mux_info_dict["version_nic_next"] = res_dir.get("version_nic_next", None)
    mux_info_dict["version_peer_active"] = res_dir.get("version_peer_active",
                                                       None)
    mux_info_dict["version_peer_inactive"] = res_dir.get(
        "version_peer_inactive", None)
    mux_info_dict["version_peer_next"] = res_dir.get("version_peer_next", None)
    mux_info_dict["version_self_active"] = res_dir.get("version_self_active",
                                                       None)
    mux_info_dict["version_self_inactive"] = res_dir.get(
        "version_self_inactive", None)
    mux_info_dict["version_self_next"] = res_dir.get("version_self_next", None)

    return mux_info_dict
def subscribe_port_config_change():
    sel = swsscommon.Select()
    asic_context = {}
    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        config_db = daemon_base.db_connect("CONFIG_DB", namespace=namespace)
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        port_tbl = swsscommon.SubscriberStateTable(
            config_db, swsscommon.CFG_PORT_TABLE_NAME)
        asic_context[port_tbl] = asic_id
        sel.addSelectable(port_tbl)
    return sel, asic_context
예제 #6
0
def get_per_npu_statedb(per_npu_statedb, port_table_keys):

    # Getting all front asic namespace and correspding config and state DB connector

    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        # replace these with correct macros
        per_npu_statedb[asic_id] = SonicV2Connector(use_unix_socket_path=True, namespace=namespace)
        per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)

        port_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
            per_npu_statedb[asic_id].STATE_DB, 'MUX_CABLE_TABLE|*')
예제 #7
0
def delete_all_keys_in_db_table(db_type, table_name):

    redis_db = {}
    table = {}
    table_keys = {}

    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        redis_db[asic_id] = db_connect(db_type, namespace)
        table[asic_id] = swsscommon.Table(redis_db[asic_id], table_name)
        table_keys[asic_id] = table[asic_id].getKeys()
        for key in table_keys[asic_id]:
            table[asic_id]._del(key)
예제 #8
0
def init_ports_status_for_y_cable(platform_sfp,
                                  platform_chassis,
                                  y_cable_presence,
                                  stop_event=threading.Event()):
    global y_cable_platform_sfputil
    global y_cable_platform_chassis
    # Connect to CONFIG_DB and create port status table inside state_db
    config_db, state_db, port_tbl, y_cable_tbl = {}, {}, {}, {}
    port_table_keys = {}

    y_cable_platform_sfputil = platform_sfp
    y_cable_platform_chassis = platform_chassis

    # Get the namespaces in the platform
    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        config_db[asic_id] = daemon_base.db_connect("CONFIG_DB", namespace)
        port_tbl[asic_id] = swsscommon.Table(config_db[asic_id], "PORT")
        port_table_keys[asic_id] = port_tbl[asic_id].getKeys()

    # Init PORT_STATUS table if ports are on Y cable
    logical_port_list = y_cable_platform_sfputil.logical
    for logical_port_name in logical_port_list:
        if stop_event.is_set():
            break

        # Get the asic to which this port belongs
        asic_index = y_cable_platform_sfputil.get_asic_id_for_logical_port(
            logical_port_name)
        if asic_index is None:
            helper_logger.log_warning(
                "Got invalid asic index for {}, ignored".format(
                    logical_port_name))
            continue

        if logical_port_name in port_table_keys[asic_index]:
            check_identifier_presence_and_update_mux_table_entry(
                state_db, port_tbl, y_cable_tbl, asic_index, logical_port_name,
                y_cable_presence)
        else:
            # This port does not exist in Port table of config but is present inside
            # logical_ports after loading the port_mappings from port_config_file
            # This should not happen
            helper_logger.log_warning(
                "Could not retreive port inside config_db PORT table ".format(
                    logical_port_name))
def get_port_mapping():
    """Get port mapping from CONFIG_DB
    """
    port_mapping = PortMapping()
    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        config_db = daemon_base.db_connect("CONFIG_DB", namespace=namespace)
        port_table = swsscommon.Table(config_db,
                                      swsscommon.CFG_PORT_TABLE_NAME)
        for key in port_table.getKeys():
            if not validate_port(key):
                continue
            _, port_config = port_table.get(key)
            port_config_dict = dict(port_config)
            port_change_event = PortChangeEvent(key, port_config_dict['index'],
                                                asic_id,
                                                PortChangeEvent.PORT_ADD)
            port_mapping.handle_port_change_event(port_change_event)
    return port_mapping
def subscribe_port_update_event(db_list=['APPL_DB', 'STATE_DB']):
    port_tbl_map = {
        'APPL_DB': swsscommon.APP_PORT_TABLE_NAME,
        'CONFIG_DB': swsscommon.CFG_PORT_TABLE_NAME,
        'STATE_DB': 'TRANSCEIVER_INFO'
    }

    sel = swsscommon.Select()
    asic_context = {}
    namespaces = multi_asic.get_front_end_namespaces()
    for db_name in db_list:
        if db_name not in port_tbl_map:
            continue
        for namespace in namespaces:
            db = daemon_base.db_connect(db_name, namespace=namespace)
            asic_id = multi_asic.get_asic_index_from_namespace(namespace)
            port_tbl = swsscommon.SubscriberStateTable(db,
                                                       port_tbl_map[db_name])
            asic_context[port_tbl] = asic_id
            sel.addSelectable(port_tbl)
    return sel, asic_context
def check_identifier_presence_and_update_mux_table_entry(
        state_db, port_tbl, y_cable_tbl, asic_index, logical_port_name,
        y_cable_presence):

    (status, fvs) = port_tbl[asic_index].get(logical_port_name)
    if status is False:
        helper_logger.log_warning(
            "Could not retreive fieldvalue pairs for {}, inside config_db".
            format(logical_port_name))
        return

    else:
        # Convert list of tuples to a dictionary
        mux_table_dict = dict(fvs)
        if "mux_cable" in mux_table_dict:
            val = mux_table_dict.get("mux_cable", None)
            if val == "true":

                y_cable_asic_table = y_cable_tbl.get(asic_index, None)
                if y_cable_presence[
                        0] is True and y_cable_asic_table is not None:
                    # fill in the newly found entry
                    read_y_cable_and_update_statedb_port_tbl(
                        logical_port_name, y_cable_tbl[asic_index])

                else:
                    # first create the state db y cable table and then fill in the entry
                    y_cable_presence[:] = [True]
                    namespaces = multi_asic.get_front_end_namespaces()
                    for namespace in namespaces:
                        asic_id = multi_asic.get_asic_index_from_namespace(
                            namespace)
                        state_db[asic_id] = daemon_base.db_connect(
                            "STATE_DB", namespace)
                        y_cable_tbl[asic_id] = swsscommon.Table(
                            state_db[asic_id],
                            swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME)
                    # fill the newly found entry
                    read_y_cable_and_update_statedb_port_tbl(
                        logical_port_name, y_cable_tbl[asic_index])
예제 #12
0
    def task_worker(self, y_cable_presence):
        helper_logger.log_info("Start Ycable monitoring loop")

        # Connect to STATE_DB and create transceiver ycable config table
        state_db = {}
        mux_tbl = {}
        status_tbl = {}

        # Get the namespaces in the platform
        namespaces = multi_asic.get_front_end_namespaces()
        for namespace in namespaces:
            asic_id = multi_asic.get_asic_index_from_namespace(namespace)
            state_db[asic_id] = daemon_base.db_connect("STATE_DB", namespace)
            status_tbl[asic_id] = swsscommon.Table(state_db[asic_id],
                                                   TRANSCEIVER_STATUS_TABLE)

        time.sleep(0.1)
        # Start loop to update ycable info in DB periodically
        while not self.task_stopping_event.wait(
                YCABLE_INFO_UPDATE_PERIOD_SECS):
            logical_port_list = platform_sfputil.logical
            for logical_port_name in logical_port_list:
                # Get the asic to which this port belongs
                asic_index = platform_sfputil.get_asic_id_for_logical_port(
                    logical_port_name)
                if asic_index is None:
                    logger.log_warning(
                        "Got invalid asic index for {}, ignored".format(
                            logical_port_name))
                    continue

                if not detect_port_in_error_status(logical_port_name,
                                                   status_tbl[asic_index]):
                    if y_cable_presence[0] is True:
                        y_cable_helper.check_identifier_presence_and_update_mux_info_entry(
                            state_db, mux_tbl, asic_index, logical_port_name)

        helper_logger.log_info("Stop DOM monitoring loop")
예제 #13
0
def check_identifier_presence_and_delete_mux_table_entry(
        state_db, port_tbl, asic_index, logical_port_name, y_cable_presence,
        delete_change_event):

    y_cable_tbl = {}

    # if there is No Y cable do not do anything here
    if y_cable_presence[0] is False:
        return

    (status, fvs) = port_tbl[asic_index].get(logical_port_name)
    if status is False:
        helper_logger.log_warning(
            "Could not retreive fieldvalue pairs for {}, inside config_db".
            format(logical_port_name))
        return

    else:
        # Convert list of tuples to a dictionary
        mux_table_dict = dict(fvs)
        if "mux_cable" in mux_table_dict:
            if y_cable_presence[0] is True:
                # delete this entry in the y cable table found and update the delete event
                namespaces = multi_asic.get_front_end_namespaces()
                for namespace in namespaces:
                    asic_id = multi_asic.get_asic_index_from_namespace(
                        namespace)
                    state_db[asic_id] = daemon_base.db_connect(
                        "STATE_DB", namespace)
                    y_cable_tbl[asic_id] = swsscommon.Table(
                        state_db[asic_id],
                        swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME)
                # fill the newly found entry
                delete_port_from_y_cable_table(logical_port_name,
                                               y_cable_tbl[asic_index])
                delete_change_event[:] = [True]
예제 #14
0
    def init(self):
        global platform_sfputil
        global platform_chassis

        self.log_info("Start daemon init...")
        config_db, metadata_tbl, metadata_dict = {}, {}, {}
        is_vs = False

        namespaces = multi_asic.get_front_end_namespaces()
        for namespace in namespaces:
            asic_id = multi_asic.get_asic_index_from_namespace(namespace)
            config_db[asic_id] = daemon_base.db_connect("CONFIG_DB", namespace)
            metadata_tbl[asic_id] = swsscommon.Table(config_db[asic_id],
                                                     "DEVICE_METADATA")

        (status, fvs) = metadata_tbl[0].get("localhost")

        if status is False:
            helper_logger.log_debug(
                "Could not retreive fieldvalue pairs for {}, inside config_db table {}"
                .format('localhost', metadata_tbl[0].getTableName()))
            return

        else:
            # Convert list of tuples to a dictionary
            metadata_dict = dict(fvs)
            if "platform" in metadata_dict:
                val = metadata_dict.get("platform", None)
                if val == "x86_64-kvm_x86_64-r0":
                    is_vs = True

        # Load new platform api class
        try:
            if is_vs is False:
                import sonic_platform.platform
                platform_chassis = sonic_platform.platform.Platform(
                ).get_chassis()
                self.log_info("chassis loaded {}".format(platform_chassis))
            # we have to make use of sfputil for some features
            # even though when new platform api is used for all vendors.
            # in this sense, we treat it as a part of new platform api.
            # we have already moved sfputil to sonic_platform_base
            # which is the root of new platform api.
            import sonic_platform_base.sonic_sfp.sfputilhelper
            platform_sfputil = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper(
            )
        except Exception as e:
            self.log_warning("Failed to load chassis due to {}".format(
                repr(e)))

        # Load platform specific sfputil class
        if platform_chassis is None or platform_sfputil is None:
            if is_vs is False:
                try:
                    platform_sfputil = self.load_platform_util(
                        PLATFORM_SPECIFIC_MODULE_NAME,
                        PLATFORM_SPECIFIC_CLASS_NAME)
                except Exception as e:
                    self.log_error("Failed to load sfputil: {}".format(str(e)),
                                   True)
                    sys.exit(SFPUTIL_LOAD_ERROR)

        if multi_asic.is_multi_asic():
            # Load the namespace details first from the database_global.json file.
            swsscommon.SonicDBConfig.initializeGlobalConfig()

        # Load port info
        try:
            if multi_asic.is_multi_asic():
                # For multi ASIC platforms we pass DIR of port_config_file_path and the number of asics
                (platform_path, hwsku_path
                 ) = device_info.get_paths_to_platform_and_hwsku_dirs()
                platform_sfputil.read_all_porttab_mappings(
                    hwsku_path, self.num_asics)
            else:
                # For single ASIC platforms we pass port_config_file_path and the asic_inst as 0
                port_config_file_path = device_info.get_path_to_port_config_file(
                )
                platform_sfputil.read_porttab_mappings(port_config_file_path,
                                                       0)
        except Exception as e:
            self.log_error("Failed to read port info: {}".format(str(e)), True)
            sys.exit(PORT_CONFIG_LOAD_ERROR)

        # Connect to STATE_DB and create ycable tables
        state_db = {}

        # Get the namespaces in the platform
        namespaces = multi_asic.get_front_end_namespaces()
        for namespace in namespaces:
            asic_id = multi_asic.get_asic_index_from_namespace(namespace)
            state_db[asic_id] = daemon_base.db_connect("STATE_DB", namespace)
        """
        # TODO need to decide if we need warm start capability in this ycabled daemon
        warmstart = swsscommon.WarmStart()
        warmstart.initialize("ycabled", "pmon")
        warmstart.checkWarmStart("ycabled", "pmon", False)
        is_warm_start = warmstart.isWarmStart()
        """

        # Make sure this daemon started after all port configured
        self.log_info("Wait for port config is done")

        # Init port y_cable status table
        y_cable_helper.init_ports_status_for_y_cable(platform_sfputil,
                                                     platform_chassis,
                                                     self.y_cable_presence,
                                                     self.stop_event, is_vs)
예제 #15
0
def version(port):
    """Show muxcable firmware version"""

    port_table_keys = {}
    y_cable_asic_table_keys = {}
    per_npu_statedb = {}
    physical_port_list = []

    # Getting all front asic namespace and correspding config and state DB connector

    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        # replace these with correct macros
        per_npu_statedb[asic_id] = swsscommon.SonicV2Connector(
            use_unix_socket_path=True, namespace=namespace)
        per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)

        port_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
            per_npu_statedb[asic_id].STATE_DB, 'MUX_CABLE_TABLE|*')

    if port is not None:

        logical_port_list = platform_sfputil_helper.get_logical_list()

        if port not in logical_port_list:
            click.echo(
                ("ERR: Not a valid logical port for muxcable firmware {}".
                 format(port)))
            sys.exit(CONFIG_FAIL)

        asic_index = None
        if platform_sfputil is not None:
            asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(
                port)
            if asic_index is None:
                # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
                # is fully mocked
                import sonic_platform_base.sonic_sfp.sfputilhelper
                asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper(
                ).get_asic_id_for_logical_port(port)
                if asic_index is None:
                    click.echo(
                        "Got invalid asic index for port {}, cant retreive mux status"
                        .format(port))

        if platform_sfputil is not None:
            physical_port_list = platform_sfputil_helper.logical_port_name_to_physical_port_list(
                port)

        if not isinstance(physical_port_list, list):
            click.echo(
                ("ERR: Unable to locate physical port information for {}".
                 format(port)))
            sys.exit(CONFIG_FAIL)

        if len(physical_port_list) != 1:
            click.echo(
                "ERR: Found multiple physical ports ({}) associated with {}".
                format(", ".join(physical_port_list), port))
            sys.exit(CONFIG_FAIL)

        mux_info_dict = {}
        physical_port = physical_port_list[0]
        if per_npu_statedb[asic_index] is not None:
            y_cable_asic_table_keys = port_table_keys[asic_index]
            logical_key = "MUX_CABLE_TABLE|{}".format(port)
            import sonic_y_cable.y_cable
            read_side = sonic_y_cable.y_cable.check_read_side(physical_port)
            if logical_key in y_cable_asic_table_keys:
                if read_side == 1:
                    get_firmware_dict(physical_port, 1, "self", mux_info_dict)
                    get_firmware_dict(physical_port, 2, "peer", mux_info_dict)
                    get_firmware_dict(physical_port, 0, "nic", mux_info_dict)
                    click.echo("{}".format(json.dumps(mux_info_dict,
                                                      indent=4)))
                elif read_side == 2:
                    get_firmware_dict(physical_port, 2, "self", mux_info_dict)
                    get_firmware_dict(physical_port, 1, "peer", mux_info_dict)
                    get_firmware_dict(physical_port, 0, "nic", mux_info_dict)
                    click.echo("{}".format(json.dumps(mux_info_dict,
                                                      indent=4)))
                else:
                    click.echo(
                        "Did not get a valid read_side for muxcable".format(
                            port))
                    sys.exit(CONFIG_FAIL)

            else:
                click.echo(
                    "this is not a valid port present on mux_cable".format(
                        port))
                sys.exit(CONFIG_FAIL)
        else:
            click.echo(
                "there is not a valid asic table for this asic_index".format(
                    asic_index))
예제 #16
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            up_ports=dict(type='raw', default={}),
            namespace=dict(default=None),
        ),
        supports_check_mode=False)

    m_args = module.params
    up_ports = m_args['up_ports']
    namespace_passed = m_args['namespace']

    # Create a python script file in the DUT.
    with open(INTF_IP_GET_INFO_SCRIPT, "w") as f:
        f.write(INTF_IP_GET_INFO_CMDs)
        f.close()

    interfaces = dict()
    ips = dict(
         all_ipv4_addresses = [],
         all_ipv6_addresses = [],
    )

    # Initialize the cmd string which to invoke the python script which we created on the DUT.
    cmd_prefix = ''
    cmd = '/usr/bin/python {}'.format(INTF_IP_GET_INFO_SCRIPT)

    for namespace in multi_asic.get_front_end_namespaces():
        if namespace_passed and namespace != namespace_passed:
            continue
        # If the user passed a namespace parameter invoke that script with the cmd_prefix
        if namespace:
            cmd_prefix = 'sudo ip netns exec {} '.format(namespace)
        rc, output, err = module.run_command(cmd_prefix + cmd, use_unsafe_shell=True)
        if rc != 0:
            module.fail_json(msg="Failed to run {}, rc={}, stdout={}, stderr={}".format(cmd, rc, output, err))

        # Get the output from the gather interface info script.
        if output:
            ips_interfaces = json.loads(output)
            interfaces.update(ips_interfaces["interfaces"])
            ips.update(ips_interfaces["ips"])

    # Remove the file which was created earlier
    os.remove(INTF_IP_GET_INFO_SCRIPT)

    results = {}

    down_ports = []
    for name in up_ports:
        try:
            if not interfaces[name]['link']:
                down_ports += [name]
        except:
            down_ports += [name]
            pass

    results['ansible_interface_facts'] = interfaces
    results['ansible_interface_ips'] = ips
    results['ansible_interface_link_down_ports'] = down_ports
    module.exit_json(ansible_facts=results)
예제 #17
0
def muxdirection(port):
    """Shows the current direction of the muxcable {active/standy}"""

    per_npu_statedb = {}
    transceiver_table_keys = {}
    transceiver_dict = {}

    # Getting all front asic namespace and correspding config and state DB connector

    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        per_npu_statedb[asic_id] = SonicV2Connector(use_unix_socket_path=False,
                                                    namespace=namespace)
        per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)

        transceiver_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
            per_npu_statedb[asic_id].STATE_DB, 'TRANSCEIVER_INFO|*')

    if port is not None:

        logical_port_list = platform_sfputil_helper.get_logical_list()
        if port not in logical_port_list:
            click.echo(
                "ERR: This is not a valid port, valid ports ({})".format(
                    ", ".join(logical_port_list)))
            sys.exit(EXIT_FAIL)

        asic_index = None
        if platform_sfputil is not None:
            asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(
                port)
        if asic_index is None:
            # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
            # is fully mocked
            import sonic_platform_base.sonic_sfp.sfputilhelper
            asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper(
            ).get_asic_id_for_logical_port(port)
            if asic_index is None:
                click.echo(
                    "Got invalid asic index for port {}, cant retreive mux status"
                    .format(port))
                sys.exit(CONFIG_FAIL)

        transceiver_dict[asic_index] = per_npu_statedb[asic_index].get_all(
            per_npu_statedb[asic_index].STATE_DB,
            'TRANSCEIVER_INFO|{}'.format(port))

        vendor_value = get_value_for_key_in_dict(transceiver_dict[asic_index],
                                                 port, "manufacturer",
                                                 "TRANSCEIVER_INFO")
        model_value = get_value_for_key_in_dict(transceiver_dict[asic_index],
                                                port, "model",
                                                "TRANSCEIVER_INFO")
        """ This check is required for checking whether or not this port is connected to a Y cable
        or not. The check gives a way to differentiate between non Y cable ports and Y cable ports.
        TODO: this should be removed once their is support for multiple vendors on Y cable"""

        if vendor_value != VENDOR_NAME or model_value != VENDOR_MODEL:
            click.echo(
                "ERR: Got invalid vendor value and model for port {}".format(
                    port))
            sys.exit(EXIT_FAIL)

        if platform_sfputil is not None:
            physical_port_list = platform_sfputil_helper.logical_port_name_to_physical_port_list(
                port)

        if not isinstance(physical_port_list, list):
            click.echo(
                ("ERR: Unable to locate physical port information for {}".
                 format(port)))
            sys.exit(EXIT_FAIL)
        if len(physical_port_list) != 1:
            click.echo(
                "ERR: Found multiple physical ports ({}) associated with {}".
                format(", ".join(physical_port_list), port))
            sys.exit(EXIT_FAIL)

        physical_port = physical_port_list[0]

        logical_port_list_for_physical_port = platform_sfputil_helper.get_physical_to_logical(
        )

        logical_port_list_per_port = logical_port_list_for_physical_port.get(
            physical_port, None)
        """ This check is required for checking whether or not this logical port is the one which is 
        actually mapped to physical port and by convention it is always the first port.
        TODO: this should be removed with more logic to check which logical port maps to actual physical port
        being used"""

        if port != logical_port_list_per_port[0]:
            click.echo(
                "ERR: This logical Port {} is not on a muxcable".format(port))
            sys.exit(EXIT_FAIL)

        import sonic_y_cable.y_cable
        read_side = sonic_y_cable.y_cable.check_read_side(physical_port)
        if read_side == False or read_side == -1:
            click.echo(
                ("ERR: Unable to get read_side for the cable port {}".format(
                    port)))
            sys.exit(EXIT_FAIL)

        mux_direction = sonic_y_cable.y_cable.check_mux_direction(
            physical_port)
        if mux_direction == False or mux_direction == -1:
            click.echo(
                ("ERR: Unable to get mux direction for the cable port {}".
                 format(port)))
            sys.exit(EXIT_FAIL)

        if int(read_side) == 1:
            if mux_direction == 1:
                state = "active"
            elif mux_direction == 2:
                state = "standby"
        elif int(read_side) == 2:
            if mux_direction == 1:
                state = "standby"
            elif mux_direction == 2:
                state = "active"
        else:
            click.echo(
                ("ERR: Unable to get mux direction, port {}".format(port)))
            state = "unknown"
        headers = ['Port', 'Direction']

        body = [[port, state]]
        click.echo(tabulate(body, headers=headers))

    else:

        logical_port_list = platform_sfputil_helper.get_logical_list()

        rc = True
        body = []
        for port in logical_port_list:

            temp_list = []
            if platform_sfputil is not None:
                physical_port_list = platform_sfputil_helper.logical_port_name_to_physical_port_list(
                    port)

            if not isinstance(physical_port_list, list):
                continue
            if len(physical_port_list) != 1:
                continue

            asic_index = None
            if platform_sfputil is not None:
                asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(
                    port)
            if asic_index is None:
                # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
                # is fully mocked
                import sonic_platform_base.sonic_sfp.sfputilhelper
                asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper(
                ).get_asic_id_for_logical_port(port)
                if asic_index is None:
                    continue

            transceiver_dict[asic_index] = per_npu_statedb[asic_index].get_all(
                per_npu_statedb[asic_index].STATE_DB,
                'TRANSCEIVER_INFO|{}'.format(port))
            vendor_value = transceiver_dict[asic_index].get(
                "manufacturer", None)
            model_value = transceiver_dict[asic_index].get("model", None)
            """ This check is required for checking whether or not this port is connected to a Y cable
            or not. The check gives a way to differentiate between non Y cable ports and Y cable ports.
            TODO: this should be removed once their is support for multiple vendors on Y cable"""

            if vendor_value != VENDOR_NAME or model_value != VENDOR_MODEL:
                continue

            physical_port = physical_port_list[0]
            logical_port_list_for_physical_port = platform_sfputil_helper.get_physical_to_logical(
            )

            logical_port_list_per_port = logical_port_list_for_physical_port.get(
                physical_port, None)
            """ This check is required for checking whether or not this logical port is the one which is 
            actually mapped to physical port and by convention it is always the first port.
            TODO: this should be removed with more logic to check which logical port maps to actual physical port
            being used"""

            if port != logical_port_list_per_port[0]:
                continue

            import sonic_y_cable.y_cable
            read_side = sonic_y_cable.y_cable.check_read_side(physical_port)
            if read_side == False or read_side == -1:
                rc = False
                temp_list.append(port)
                temp_list.append("unknown")
                body.append(temp_list)
                continue

            mux_direction = sonic_y_cable.y_cable.check_mux_direction(
                physical_port)
            if mux_direction == False or mux_direction == -1:
                rc = False
                temp_list.append(port)
                temp_list.append("unknown")
                body.append(temp_list)
                continue

            if int(read_side) == 1:
                if mux_direction == 1:
                    state = "active"
                elif mux_direction == 2:
                    state = "standby"
            elif int(read_side) == 2:
                if mux_direction == 1:
                    state = "standby"
                elif mux_direction == 2:
                    state = "active"
            else:
                rc = False
                temp_list.append(port)
                temp_list.append("unknown")
                body.append(temp_list)
                continue
            temp_list.append(port)
            temp_list.append(state)
            body.append(temp_list)

        headers = ['Port', 'Direction']

        click.echo(tabulate(body, headers=headers))
        if rc == False:
            sys.exit(EXIT_FAIL)
예제 #18
0
def config(port, json_output):
    """Show muxcable config information"""

    port_mux_tbl_keys = {}
    asic_start_idx = None
    per_npu_configdb = {}
    mux_tbl_cfg_db = {}
    peer_switch_tbl_cfg_db = {}

    # Getting all front asic namespace and correspding config and state DB connector

    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        if asic_start_idx is None:
            asic_start_idx = asic_id
        # TO-DO replace the macros with correct swsscommon names
        #config_db[asic_id] = swsscommon.DBConnector("CONFIG_DB", REDIS_TIMEOUT_MSECS, True, namespace)
        #mux_tbl_cfg_db[asic_id] = swsscommon.Table(config_db[asic_id], swsscommon.CFG_MUX_CABLE_TABLE_NAME)
        per_npu_configdb[asic_id] = ConfigDBConnector(
            use_unix_socket_path=False, namespace=namespace)
        per_npu_configdb[asic_id].connect()
        mux_tbl_cfg_db[asic_id] = per_npu_configdb[asic_id].get_table(
            "MUX_CABLE")
        peer_switch_tbl_cfg_db[asic_id] = per_npu_configdb[asic_id].get_table(
            "PEER_SWITCH")
        #peer_switch_tbl_cfg_db[asic_id] = swsscommon.Table(config_db[asic_id], swsscommon.CFG_PEER_SWITCH_TABLE_NAME)
        port_mux_tbl_keys[asic_id] = mux_tbl_cfg_db[asic_id].keys()

    if port is not None:
        asic_index = None
        if platform_sfputil is not None:
            asic_index = platform_sfputil.get_asic_id_for_logical_port(port)
        if asic_index is None:
            # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
            # is fully mocked
            import sonic_platform_base.sonic_sfp.sfputilhelper
            asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper(
            ).get_asic_id_for_logical_port(port)
            if asic_index is None:
                click.echo(
                    "Got invalid asic index for port {}, cant retreive mux status"
                    .format(port))
                sys.exit(CONFIG_FAIL)

        port_status_dict = {}
        port_status_dict["MUX_CABLE"] = {}
        port_status_dict["MUX_CABLE"]["PEER_TOR"] = {}
        peer_switch_value = None

        switch_name = get_switch_name(per_npu_configdb[asic_start_idx])
        if asic_start_idx is not None:
            peer_switch_value = get_value_for_key_in_config_tbl(
                per_npu_configdb[asic_start_idx], switch_name, "address_ipv4",
                "PEER_SWITCH")
            port_status_dict["MUX_CABLE"]["PEER_TOR"] = peer_switch_value
        if port_mux_tbl_keys[asic_id] is not None:
            if port in port_mux_tbl_keys[asic_id]:

                if json_output:

                    port_status_dict["MUX_CABLE"] = {}
                    port_status_dict["MUX_CABLE"]["PORTS"] = {}
                    create_json_dump_per_port_config(port_status_dict,
                                                     per_npu_configdb, asic_id,
                                                     port)

                    click.echo("{}".format(
                        json.dumps(port_status_dict, indent=4)))
                    sys.exit(CONFIG_SUCCESSFUL)
                else:
                    print_data = []
                    print_peer_tor = []

                    create_table_dump_per_port_config(print_data,
                                                      per_npu_configdb,
                                                      asic_id, port)

                    headers = ['SWITCH_NAME', 'PEER_TOR']
                    peer_tor_data = []
                    peer_tor_data.append(switch_name)
                    peer_tor_data.append(peer_switch_value)
                    print_peer_tor.append(peer_tor_data)
                    click.echo(tabulate(print_peer_tor, headers=headers))
                    headers = ['port', 'state', 'ipv4', 'ipv6']
                    click.echo(tabulate(print_data, headers=headers))

                    sys.exit(CONFIG_SUCCESSFUL)

            else:
                click.echo(
                    "this is not a valid port present on mux_cable".format(
                        port))
                sys.exit(CONFIG_FAIL)
        else:
            click.echo(
                "there is not a valid asic table for this asic_index".format(
                    asic_index))
            sys.exit(CONFIG_FAIL)

    else:

        port_status_dict = {}
        port_status_dict["MUX_CABLE"] = {}
        port_status_dict["MUX_CABLE"]["PEER_TOR"] = {}
        peer_switch_value = None

        switch_name = get_switch_name(per_npu_configdb[asic_start_idx])
        if asic_start_idx is not None:
            peer_switch_value = get_value_for_key_in_config_tbl(
                per_npu_configdb[asic_start_idx], switch_name, "address_ipv4",
                "PEER_SWITCH")
            port_status_dict["MUX_CABLE"]["PEER_TOR"] = peer_switch_value
        if json_output:
            port_status_dict["MUX_CABLE"]["PORTS"] = {}
            for namespace in namespaces:
                asic_id = multi_asic.get_asic_index_from_namespace(namespace)
                for port in natsorted(port_mux_tbl_keys[asic_id]):
                    create_json_dump_per_port_config(port_status_dict,
                                                     per_npu_configdb, asic_id,
                                                     port)

            click.echo("{}".format(json.dumps(port_status_dict, indent=4)))
        else:
            print_data = []
            print_peer_tor = []
            for namespace in namespaces:
                asic_id = multi_asic.get_asic_index_from_namespace(namespace)
                for port in natsorted(port_mux_tbl_keys[asic_id]):
                    create_table_dump_per_port_config(print_data,
                                                      per_npu_configdb,
                                                      asic_id, port)

            headers = ['SWITCH_NAME', 'PEER_TOR']
            peer_tor_data = []
            peer_tor_data.append(switch_name)
            peer_tor_data.append(peer_switch_value)
            print_peer_tor.append(peer_tor_data)
            click.echo(tabulate(print_peer_tor, headers=headers))
            headers = ['port', 'state', 'ipv4', 'ipv6']
            click.echo(tabulate(print_data, headers=headers))

        sys.exit(CONFIG_SUCCESSFUL)
예제 #19
0
def status(port, json_output):
    """Show muxcable status information"""

    port_table_keys = {}
    port_health_table_keys = {}
    per_npu_statedb = {}
    muxcable_info_dict = {}
    muxcable_health_dict = {}

    # Getting all front asic namespace and correspding config and state DB connector

    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        per_npu_statedb[asic_id] = SonicV2Connector(use_unix_socket_path=False,
                                                    namespace=namespace)
        per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)

        port_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
            per_npu_statedb[asic_id].STATE_DB, 'MUX_CABLE_TABLE|*')
        port_health_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
            per_npu_statedb[asic_id].STATE_DB, 'MUX_LINKMGR_TABLE|*')

    if port is not None:
        asic_index = None
        if platform_sfputil is not None:
            asic_index = platform_sfputil.get_asic_id_for_logical_port(port)
        if asic_index is None:
            # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
            # is fully mocked
            import sonic_platform_base.sonic_sfp.sfputilhelper
            asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper(
            ).get_asic_id_for_logical_port(port)
            if asic_index is None:
                click.echo(
                    "Got invalid asic index for port {}, cant retreive mux status"
                    .format(port))
                sys.exit(STATUS_FAIL)

        muxcable_info_dict[asic_index] = per_npu_statedb[asic_index].get_all(
            per_npu_statedb[asic_index].STATE_DB,
            'MUX_CABLE_TABLE|{}'.format(port))
        muxcable_health_dict[asic_index] = per_npu_statedb[asic_index].get_all(
            per_npu_statedb[asic_index].STATE_DB,
            'MUX_LINKMGR_TABLE|{}'.format(port))
        if muxcable_info_dict[asic_index] is not None:
            logical_key = "MUX_CABLE_TABLE|{}".format(port)
            logical_health_key = "MUX_LINKMGR_TABLE|{}".format(port)
            if logical_key in port_table_keys[
                    asic_index] and logical_health_key in port_health_table_keys[
                        asic_index]:

                if json_output:
                    port_status_dict = {}
                    port_status_dict["MUX_CABLE"] = {}

                    create_json_dump_per_port_status(port_status_dict,
                                                     muxcable_info_dict,
                                                     muxcable_health_dict,
                                                     asic_index, port)

                    click.echo("{}".format(
                        json.dumps(port_status_dict, indent=4)))
                    sys.exit(STATUS_SUCCESSFUL)
                else:
                    print_data = []

                    create_table_dump_per_port_status(print_data,
                                                      muxcable_info_dict,
                                                      muxcable_health_dict,
                                                      asic_index, port)

                    headers = ['PORT', 'STATUS', 'HEALTH']

                    click.echo(tabulate(print_data, headers=headers))
                    sys.exit(STATUS_SUCCESSFUL)
            else:
                click.echo(
                    "this is not a valid port present on mux_cable".format(
                        port))
                sys.exit(STATUS_FAIL)
        else:
            click.echo(
                "there is not a valid asic table for this asic_index".format(
                    asic_index))
            sys.exit(STATUS_FAIL)

    else:

        if json_output:
            port_status_dict = {}
            port_status_dict["MUX_CABLE"] = {}
            for namespace in namespaces:
                asic_id = multi_asic.get_asic_index_from_namespace(namespace)
                for key in natsorted(port_table_keys[asic_id]):
                    port = key.split("|")[1]
                    muxcable_info_dict[asic_id] = per_npu_statedb[
                        asic_id].get_all(per_npu_statedb[asic_id].STATE_DB,
                                         'MUX_CABLE_TABLE|{}'.format(port))
                    muxcable_health_dict[asic_id] = per_npu_statedb[
                        asic_id].get_all(per_npu_statedb[asic_id].STATE_DB,
                                         'MUX_LINKMGR_TABLE|{}'.format(port))
                    create_json_dump_per_port_status(port_status_dict,
                                                     muxcable_info_dict,
                                                     muxcable_health_dict,
                                                     asic_id, port)

            click.echo("{}".format(json.dumps(port_status_dict, indent=4)))
        else:
            print_data = []
            for namespace in namespaces:
                asic_id = multi_asic.get_asic_index_from_namespace(namespace)
                for key in natsorted(port_table_keys[asic_id]):
                    port = key.split("|")[1]
                    muxcable_health_dict[asic_id] = per_npu_statedb[
                        asic_id].get_all(per_npu_statedb[asic_id].STATE_DB,
                                         'MUX_LINKMGR_TABLE|{}'.format(port))
                    muxcable_info_dict[asic_id] = per_npu_statedb[
                        asic_id].get_all(per_npu_statedb[asic_id].STATE_DB,
                                         'MUX_CABLE_TABLE|{}'.format(port))

                    create_table_dump_per_port_status(print_data,
                                                      muxcable_info_dict,
                                                      muxcable_health_dict,
                                                      asic_id, port)

            headers = ['PORT', 'STATUS', 'HEALTH']
            click.echo(tabulate(print_data, headers=headers))

        sys.exit(STATUS_SUCCESSFUL)
예제 #20
0
def get_single_port_firmware_version(port, res_dict, mux_info_dict):

    state_db, appl_db = {}, {}
    xcvrd_show_fw_rsp_sts_tbl_keys = {}
    xcvrd_show_fw_rsp_sts_tbl = {}
    xcvrd_show_fw_rsp_tbl = {}
    xcvrd_show_fw_cmd_tbl, xcvrd_show_fw_res_tbl = {}, {}

    sel = swsscommon.Select()
    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        state_db[asic_id] = db_connect("STATE_DB", namespace)
        appl_db[asic_id] = db_connect("APPL_DB", namespace)
        xcvrd_show_fw_cmd_tbl[asic_id] = swsscommon.Table(appl_db[asic_id], "XCVRD_SHOW_FW_CMD")
        xcvrd_show_fw_rsp_tbl[asic_id] = swsscommon.SubscriberStateTable(state_db[asic_id], "XCVRD_SHOW_FW_RSP")
        xcvrd_show_fw_rsp_sts_tbl[asic_id] = swsscommon.Table(state_db[asic_id], "XCVRD_SHOW_FW_RSP")
        xcvrd_show_fw_res_tbl[asic_id] = swsscommon.Table(state_db[asic_id], "XCVRD_SHOW_FW_RES")
        xcvrd_show_fw_rsp_sts_tbl_keys[asic_id] = xcvrd_show_fw_rsp_sts_tbl[asic_id].getKeys()
        for key in xcvrd_show_fw_rsp_sts_tbl_keys[asic_id]:
            xcvrd_show_fw_rsp_sts_tbl[asic_id]._del(key)
        sel.addSelectable(xcvrd_show_fw_rsp_tbl[asic_id])

    rc = 0
    res_dict[0] = 'unknown'

    logical_port_list = platform_sfputil_helper.get_logical_list()
    if port not in logical_port_list:
        click.echo("ERR: This is not a valid port, valid ports ({})".format(", ".join(logical_port_list)))
        rc = EXIT_FAIL
        res_dict[1] = rc
        return

    asic_index = None
    if platform_sfputil is not None:
        asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(port)
    if asic_index is None:
        # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
        # is fully mocked
        import sonic_platform_base.sonic_sfp.sfputilhelper
        asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper().get_asic_id_for_logical_port(port)
        if asic_index is None:
            click.echo("Got invalid asic index for port {}, cant retreive mux status".format(port))
            rc = CONFIG_FAIL
            res_dict[1] = rc
            return

    fvs = swsscommon.FieldValuePairs([('firmware_version', 'probe')])
    xcvrd_show_fw_cmd_tbl[asic_index].set(port, fvs)

    # Listen indefinitely for changes to the HW_MUX_CABLE_TABLE in the Application DB's
    while True:
        # Use timeout to prevent ignoring the signals we want to handle
        # in signal_handler() (e.g. SIGTERM for graceful shutdown)

        (state, selectableObj) = sel.select(SELECT_TIMEOUT)

        if state == swsscommon.Select.TIMEOUT:
            # Do not flood log when select times out
            continue
        if state != swsscommon.Select.OBJECT:
            click.echo("sel.select() did not  return swsscommon.Select.OBJECT for sonic_y_cable updates")
            continue

        # Get the redisselect object  from selectable object
        redisSelectObj = swsscommon.CastSelectableToRedisSelectObj(
            selectableObj)
        # Get the corresponding namespace from redisselect db connector object
        namespace = redisSelectObj.getDbConnector().getNamespace()
        asic_index = multi_asic.get_asic_index_from_namespace(namespace)

        (port_m, op_m, fvp_m) = xcvrd_show_fw_rsp_tbl[asic_index].pop()

        if not port_m:
            click.echo("Did not receive a port response {}".format(port))
            res_dict[0] = 'False'
            res_dict[1] = EXIT_FAIL
            xcvrd_show_fw_rsp_sts_tbl[asic_index]._del(port)
            break

        if port_m != port:

            res_dict[0] = 'False'
            res_dict[1] = EXIT_FAIL
            xcvrd_show_fw_rsp_sts_tbl[asic_index]._del(port)
            continue

        if fvp_m:

            fvp_dict = dict(fvp_m)
            if "status" in fvp_dict:
                # check if xcvrd got a probe command
                state = fvp_dict["status"]

                res_dict[0] = state
                res_dict[1] = EXIT_FAIL
                xcvrd_show_fw_rsp_sts_tbl[asic_index]._del(port)
                (status, fvp) = xcvrd_show_fw_res_tbl[asic_index].get(port)
                res_dir = dict(fvp)
                mux_info_dict["version_nic_active"] = res_dir.get("version_nic_active", None)
                mux_info_dict["version_nic_inactive"] = res_dir.get("version_nic_inactive", None)
                mux_info_dict["version_nic_next"] = res_dir.get("version_nic_next", None)
                mux_info_dict["version_peer_active"] = res_dir.get("version_peer_active", None)
                mux_info_dict["version_peer_inactive"] = res_dir.get("version_peer_inactive", None)
                mux_info_dict["version_peer_next"] = res_dir.get("version_peer_next", None)
                mux_info_dict["version_self_active"] = res_dir.get("version_self_active", None)
                mux_info_dict["version_self_inactive"] = res_dir.get("version_self_inactive", None)
                mux_info_dict["version_self_next"] = res_dir.get("version_self_next", None)
                break
            else:
                res_dict[0] = 'False'
                res_dict[1] = EXIT_FAIL
                xcvrd_show_fw_rsp_sts_tbl[asic_index]._del(port)
                break
        else:
            res_dict[0] = 'False'
            res_dict[1] = EXIT_FAIL
            xcvrd_show_fw_rsp_sts_tbl[asic_index]._del(port)
            break


    delete_all_keys_in_db_table("STATE_DB", "XCVRD_SHOW_FW_RSP")
    delete_all_keys_in_db_table("STATE_DB", "XCVRD_SHOW_FW_RES")

    return
def init_ports_status_for_y_cable(platform_sfp, stop_event=threading.Event()):
    global platform_sfputil
    # Connect to CONFIG_DB and create port status table inside state_db
    config_db, state_db, port_tbl , y_cable_tbl= {}, {}, {}, {}
    port_table_keys = {}
    state_db_created = False
    platform_sfputil = platform_sfp

    # Get the namespaces in the platform
    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        config_db[asic_id] = daemon_base.db_connect("CONFIG_DB", namespace)
        port_tbl[asic_id] = swsscommon.Table(config_db[asic_id], "PORT")
        port_table_keys[asic_id] = config_db[asic_id].get_keys("PORT")

    # Init PORT_STATUS table if ports are on Y cable
    logical_port_list = platform_sfputil.logical
    for logical_port_name in logical_port_list:
        if stop_event.is_set():
            break

        # Get the asic to which this port belongs
        asic_index = platform_sfputil.get_asic_id_for_logical_port(logical_port_name)
        if asic_index is None:
            logger.log_warning("Got invalid asic index for {}, ignored".format(logical_port_name))
            continue

        if logical_port_name in port_table_keys[asic_index]:
            (status, fvs) = port_tbl[asic_index].get(logical_port_name)
            if status is False:
                logger.log_warning("Could not retreive fieldvalue pairs for {}, inside config_db".format(logical_port_name))
                continue

            else:
                # Convert list of tuples to a dictionary
                mux_table_dict = dict(fvp)
                if "mux_cable" in mux_table_dict:
                    if state_db_created:
                        #fill in the newly found entry
                        update_port_mux_status_table(logical_port_name,y_cable_tbl[asic_index])

                    else:
                        #first create the db and then fill in the entry
                        state_db_created = True
                        namespaces = multi_asic.get_front_end_namespaces()
                        for namespace in namespaces:
                            asic_id = multi_asic.get_asic_index_from_namespace(namespace)
                            state_db[asic_id] = daemon_base.db_connect("STATE_DB", namespace)
                            y_cable_tbl[asic_id] = swsscommon.Table(state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME)
                        # fill the newly found entry    
                        update_port_mux_status_table(logical_port_name,y_cable_tbl[asic_index])
                else:
                    logger.log_info("Port is not connected on a Y cable")

        else:
            ''' This port does not exist in Port table of config but is present inside
                logical_ports after loading the port_mappings from port_config_file
                This should not happen
            '''
            logger.log_warning("Could not retreive port inside config_db PORT table ".format(logical_port_name))

    return state_db_created                
예제 #22
0
def setswitchmode(state, port):
    """Configure the muxcable mux switching mode {auto/manual}"""

    per_npu_statedb = {}
    transceiver_dict = {}

    # Getting all front asic namespace and correspding config and state DB connector

    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        per_npu_statedb[asic_id] = SonicV2Connector(use_unix_socket_path=False,
                                                    namespace=namespace)
        per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)

    if port is not None and port != "all":
        click.confirm((
            'Muxcable at port {} will be changed to {} switching mode. Continue?'
            .format(port, state)),
                      abort=True)
        logical_port_list = platform_sfputil_helper.get_logical_list()
        if port not in logical_port_list:
            click.echo(
                "ERR: This is not a valid port, valid ports ({})".format(
                    ", ".join(logical_port_list)))
            sys.exit(CONFIG_FAIL)

        asic_index = None
        if platform_sfputil is not None:
            asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(
                port)
            if asic_index is None:
                # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
                # is fully mocked
                import sonic_platform_base.sonic_sfp.sfputilhelper
                asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper(
                ).get_asic_id_for_logical_port(port)
                if asic_index is None:
                    click.echo(
                        "Got invalid asic index for port {}, cant retreive mux status"
                        .format(port))
                    sys.exit(CONFIG_FAIL)

        if platform_sfputil is not None:
            physical_port_list = platform_sfputil_helper.logical_port_name_to_physical_port_list(
                port)

        if not isinstance(physical_port_list, list):
            click.echo(
                ("ERR: Unable to locate physical port information for {}".
                 format(port)))
            sys.exit(CONFIG_FAIL)
        if len(physical_port_list) != 1:
            click.echo(
                "ERR: Found multiple physical ports ({}) associated with {}".
                format(", ".join(physical_port_list), port))
            sys.exit(CONFIG_FAIL)

        transceiver_dict[asic_index] = per_npu_statedb[asic_index].get_all(
            per_npu_statedb[asic_index].STATE_DB,
            'TRANSCEIVER_INFO|{}'.format(port))

        vendor_value = get_value_for_key_in_dict(transceiver_dict[asic_index],
                                                 port, "manufacturer",
                                                 "TRANSCEIVER_INFO")
        model_value = get_value_for_key_in_dict(transceiver_dict[asic_index],
                                                port, "model",
                                                "TRANSCEIVER_INFO")
        """ This check is required for checking whether or not this port is connected to a Y cable
        or not. The check gives a way to differentiate between non Y cable ports and Y cable ports.
        TODO: this should be removed once their is support for multiple vendors on Y cable"""

        if vendor_value != VENDOR_NAME or not re.match(VENDOR_MODEL_REGEX,
                                                       model_value):
            click.echo(
                "ERR: Got invalid vendor value and model for port {}".format(
                    port))
            sys.exit(CONFIG_FAIL)

        physical_port = physical_port_list[0]

        logical_port_list_for_physical_port = platform_sfputil_helper.get_physical_to_logical(
        )

        logical_port_list_per_port = logical_port_list_for_physical_port.get(
            physical_port, None)
        """ This check is required for checking whether or not this logical port is the one which is
        actually mapped to physical port and by convention it is always the first port.
        TODO: this should be removed with more logic to check which logical port maps to actual physical port
        being used"""

        if port != logical_port_list_per_port[0]:
            click.echo(
                "ERR: This logical Port {} is not on a muxcable".format(port))
            sys.exit(CONFIG_FAIL)

        if state == "auto":
            mode = sonic_y_cable.y_cable.SWITCHING_MODE_AUTO
        elif state == "manual":
            mode = sonic_y_cable.y_cable.SWITCHING_MODE_MANUAL
        import sonic_y_cable.y_cable
        result = sonic_y_cable.y_cable.set_switching_mode(physical_port, mode)
        if result == False:
            click.echo(
                ("ERR: Unable to set switching mode for the cable port {}".
                 format(port)))
            sys.exit(CONFIG_FAIL)

        click.echo("Success in switching mode on port {} to {}".format(
            port, state))

    elif port == "all" and port is not None:

        click.confirm((
            'Muxcable at port {} will be changed to {} switching mode. Continue?'
            .format(port, state)),
                      abort=True)
        logical_port_list = platform_sfputil_helper.get_logical_list()

        rc = True
        for port in logical_port_list:
            if platform_sfputil is not None:
                physical_port_list = platform_sfputil_helper.logical_port_name_to_physical_port_list(
                    port)

            asic_index = None
            if platform_sfputil is not None:
                asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(
                    port)
                if asic_index is None:
                    # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
                    # is fully mocked
                    import sonic_platform_base.sonic_sfp.sfputilhelper
                    asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper(
                    ).get_asic_id_for_logical_port(port)
                    if asic_index is None:
                        click.echo(
                            "Got invalid asic index for port {}, cant retreive mux status"
                            .format(port))

            if not isinstance(physical_port_list, list):
                click.echo(
                    ("ERR: Unable to locate physical port information for {}".
                     format(port)))
                continue

            if len(physical_port_list) != 1:
                click.echo(
                    "ERR: Found multiple physical ports ({}) associated with {}"
                    .format(", ".join(physical_port_list), port))
                continue

            transceiver_dict[asic_index] = per_npu_statedb[asic_index].get_all(
                per_npu_statedb[asic_index].STATE_DB,
                'TRANSCEIVER_INFO|{}'.format(port))
            vendor_value = transceiver_dict[asic_index].get(
                "manufacturer", None)
            model_value = transceiver_dict[asic_index].get("model", None)
            """ This check is required for checking whether or not this port is connected to a Y cable
            or not. The check gives a way to differentiate between non Y cable ports and Y cable ports.
            TODO: this should be removed once their is support for multiple vendors on Y cable"""

            if vendor_value != VENDOR_NAME or not re.match(
                    VENDOR_MODEL_REGEX, model_value):
                continue

            physical_port = physical_port_list[0]

            logical_port_list_for_physical_port = platform_sfputil_helper.get_physical_to_logical(
            )

            logical_port_list_per_port = logical_port_list_for_physical_port.get(
                physical_port, None)
            """ This check is required for checking whether or not this logical port is the one which is
            actually mapped to physical port and by convention it is always the first port.
            TODO: this should be removed with more logic to check which logical port maps to actual physical port
            being used"""

            if port != logical_port_list_per_port[0]:
                continue

            if state == "auto":
                mode = sonic_y_cable.y_cable.SWITCHING_MODE_AUTO
            elif state == "manual":
                mode = sonic_y_cable.y_cable.SWITCHING_MODE_MANUAL
            import sonic_y_cable.y_cable
            result = sonic_y_cable.y_cable.set_switching_mode(
                physical_port, mode)
            if result == False:
                rc = False
                click.echo(
                    "ERR: Unable to set switching mode on port {} to {}".
                    format(port, state))

            click.echo("Success in switching mode on port {} to {}".format(
                port, state))

        if rc == False:
            click.echo(
                "ERR: Unable to set switching mode one or more ports to {}".
                format(state))
            sys.exit(CONFIG_FAIL)
예제 #23
0
def change_ports_status_for_y_cable_change_event(port_dict,
                                                 y_cable_presence,
                                                 stop_event=threading.Event()):
    # Connect to CONFIG_DB and create port status table inside state_db
    config_db, state_db, port_tbl, y_cable_tbl = {}, {}, {}, {}
    port_table_keys = {}
    delete_change_event = [False]

    # Get the namespaces in the platform
    namespaces = multi_asic.get_front_end_namespaces()
    # Get the keys from PORT table inside config db to prepare check for mux_cable identifier
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        config_db[asic_id] = daemon_base.db_connect("CONFIG_DB", namespace)
        port_tbl[asic_id] = swsscommon.Table(config_db[asic_id], "PORT")
        port_table_keys[asic_id] = port_tbl[asic_id].getKeys()

    # Init PORT_STATUS table if ports are on Y cable and an event is received
    for key, value in port_dict.iteritems():
        logical_port_list = y_cable_platform_sfputil.get_physical_to_logical(
            int(key))
        if logical_port_list is None:
            helper_logger.log_warning(
                "Got unknown FP port index {}, ignored".format(key))
            continue
        for logical_port_name in logical_port_list:

            # Get the asic to which this port belongs
            asic_index = y_cable_platform_sfputil.get_asic_id_for_logical_port(
                logical_port_name)
            if asic_index is None:
                helper_logger.log_warning(
                    "Got invalid asic index for {}, ignored".format(
                        logical_port_name))
                continue

            if logical_port_name in port_table_keys[asic_index]:
                if value == SFP_STATUS_INSERTED:
                    helper_logger.log_info("Got SFP inserted event")
                    check_identifier_presence_and_update_mux_table_entry(
                        state_db, port_tbl, y_cable_tbl, asic_index,
                        logical_port_name, y_cable_presence)
                elif value == SFP_STATUS_REMOVED or value in errors_block_eeprom_reading:
                    check_identifier_presence_and_delete_mux_table_entry(
                        state_db, port_tbl, asic_index, logical_port_name,
                        y_cable_presence, delete_change_event)

                else:
                    # SFP return unkown event, just ignore for now.
                    helper_logger.log_warning(
                        "Got unknown event {}, ignored".format(value))
                    continue

    # If there was a delete event and y_cable_presence was true, reaccess the y_cable presence
    if y_cable_presence[0] is True and delete_change_event[0] is True:

        y_cable_presence[:] = [False]
        for namespace in namespaces:
            asic_id = multi_asic.get_asic_index_from_namespace(namespace)
            y_cable_tbl[asic_id] = swsscommon.Table(
                state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME)
            y_cable_table_size = len(y_cable_tbl[asic_id].getKeys())
            if y_cable_table_size > 0:
                y_cable_presence[:] = [True]
                break
예제 #24
0
    def task_worker(self):

        # Connect to STATE_DB and APPL_DB and get both the HW_MUX_STATUS_TABLE info
        appl_db, state_db, status_tbl, y_cable_tbl = {}, {}, {}, {}
        y_cable_tbl_keys = {}
        mux_cable_command_tbl = {}

        sel = swsscommon.Select()

        # Get the namespaces in the platform
        namespaces = multi_asic.get_front_end_namespaces()
        for namespace in namespaces:
            # Open a handle to the Application database, in all namespaces
            asic_id = multi_asic.get_asic_index_from_namespace(namespace)
            appl_db[asic_id] = daemon_base.db_connect("APPL_DB", namespace)
            status_tbl[asic_id] = swsscommon.SubscriberStateTable(
                appl_db[asic_id], swsscommon.APP_HW_MUX_CABLE_TABLE_NAME)
            mux_cable_command_tbl[asic_id] = swsscommon.SubscriberStateTable(
                appl_db[asic_id], swsscommon.APP_MUX_CABLE_COMMAND_TABLE_NAME)
            state_db[asic_id] = daemon_base.db_connect("STATE_DB", namespace)
            y_cable_tbl[asic_id] = swsscommon.Table(
                state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME)
            y_cable_tbl_keys[asic_id] = y_cable_tbl[asic_id].getKeys()
            sel.addSelectable(status_tbl[asic_id])
            sel.addSelectable(mux_cable_command_tbl[asic_id])

        # Listen indefinitely for changes to the HW_MUX_CABLE_TABLE in the Application DB's
        while True:
            # Use timeout to prevent ignoring the signals we want to handle
            # in signal_handler() (e.g. SIGTERM for graceful shutdown)
            (state, selectableObj) = sel.select(SELECT_TIMEOUT)

            if state == swsscommon.Select.TIMEOUT:
                # Do not flood log when select times out
                continue
            if state != swsscommon.Select.OBJECT:
                helper_logger.log_warning(
                    "sel.select() did not  return swsscommon.Select.OBJECT for sonic_y_cable updates"
                )
                continue

            # Get the redisselect object  from selectable object
            redisSelectObj = swsscommon.CastSelectableToRedisSelectObj(
                selectableObj)
            # Get the corresponding namespace from redisselect db connector object
            namespace = redisSelectObj.getDbConnector().getNamespace()
            asic_index = multi_asic.get_asic_index_from_namespace(namespace)

            (port, op, fvp) = status_tbl[asic_index].pop()
            if fvp:
                # This check might be redundant, to check, the presence of this Port in keys
                # in logical_port_list but keep for now for coherency
                # also skip checking in logical_port_list inside sfp_util
                if port not in y_cable_tbl_keys[asic_index]:
                    continue

                fvp_dict = dict(fvp)

                if "status" in fvp_dict:
                    # got a status change
                    new_status = fvp_dict["status"]
                    (status, fvs) = y_cable_tbl[asic_index].get(port)
                    if status is False:
                        helper_logger.log_warning(
                            "Could not retreive fieldvalue pairs for {}, inside state_db table {}"
                            .format(port, y_cable_tbl[asic_index]))
                        continue
                    mux_port_dict = dict(fvs)
                    old_status = mux_port_dict.get("status")
                    read_side = mux_port_dict.get("read_side")
                    prev_active_side = mux_port_dict.get("active_side")
                    # Now if the old_status does not match new_status toggle the mux appropriately
                    if old_status != new_status:
                        active_side = update_tor_active_side(
                            read_side, new_status, port)
                        fvs_updated = swsscommon.FieldValuePairs([
                            ('status', new_status), ('read_side', read_side),
                            ('active_side', str(active_side))
                        ])
                        y_cable_tbl[asic_index].set(port, fvs_updated)
                        # nothing to do since no status change
                    else:
                        helper_logger.log_warning(
                            "Got a change event on that does not toggle the TOR active side for port  {} status {} active linked side = {} "
                            .format(port, old_status, prev_active_side))
                else:
                    helper_logger.log_info(
                        "Got a change event on port {} of table {} that does not contain status "
                        .format(port, swsscommon.APP_HW_MUX_CABLE_TABLE_NAME))

            (port_m, op_m, fvp_m) = mux_cable_command_tbl[asic_index].pop()
            if fvp_m:

                fvp_dict = dict(fvp_m)

                if "command" in fvp_dict:
                    #check if xcvrd got a probe command
                    probe_identifier = fvp_dict["command"]

                    if probe_identifier == "probe":
                        update_appdb_port_mux_cable_response_table(
                            port_m, asic_index, appl_db)
예제 #25
0
def mode(db, state, port, json_output):
    """Config muxcable mode"""

    port = platform_sfputil_helper.get_interface_alias(port, db)

    port_table_keys = {}
    y_cable_asic_table_keys = {}
    per_npu_configdb = {}
    per_npu_statedb = {}
    mux_tbl_cfg_db = {}

    # Getting all front asic namespace and correspding config and state DB connector

    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        # replace these with correct macros
        per_npu_configdb[asic_id] = ConfigDBConnector(
            use_unix_socket_path=True, namespace=namespace)
        per_npu_configdb[asic_id].connect()
        per_npu_statedb[asic_id] = SonicV2Connector(use_unix_socket_path=True,
                                                    namespace=namespace)
        per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)

        mux_tbl_cfg_db[asic_id] = per_npu_configdb[asic_id].get_table(
            "MUX_CABLE")

        port_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
            per_npu_statedb[asic_id].STATE_DB, 'MUX_CABLE_TABLE|*')

    if port is not None and port != "all":

        asic_index = None
        if platform_sfputil is not None:
            asic_index = platform_sfputil.get_asic_id_for_logical_port(port)
        if asic_index is None:
            # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
            # is fully mocked
            import sonic_platform_base.sonic_sfp.sfputilhelper
            asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper(
            ).get_asic_id_for_logical_port(port)
            if asic_index is None:
                click.echo(
                    "Got invalid asic index for port {}, cant retreive mux status"
                    .format(port))
                sys.exit(CONFIG_FAIL)

        if per_npu_statedb[asic_index] is not None:
            y_cable_asic_table_keys = port_table_keys[asic_index]
            logical_key = "MUX_CABLE_TABLE|{}".format(port)
            if logical_key in y_cable_asic_table_keys:
                port_status_dict = {}
                lookup_statedb_and_update_configdb(
                    per_npu_statedb[asic_index], per_npu_configdb[asic_index],
                    port, state, port_status_dict)

                if json_output:
                    click.echo("{}".format(
                        json.dumps(port_status_dict, indent=4)))
                else:
                    headers = ['port', 'state']
                    data = sorted([(k, v)
                                   for k, v in port_status_dict.items()])
                    click.echo(tabulate(data, headers=headers))

                sys.exit(CONFIG_SUCCESSFUL)

            else:
                click.echo(
                    "this is not a valid port present on mux_cable".format(
                        port))
                sys.exit(CONFIG_FAIL)
        else:
            click.echo(
                "there is not a valid asic table for this asic_index".format(
                    asic_index))
            sys.exit(CONFIG_FAIL)

    elif port == "all" and port is not None:

        port_status_dict = {}
        for namespace in namespaces:
            asic_id = multi_asic.get_asic_index_from_namespace(namespace)
            for key in port_table_keys[asic_id]:
                logical_port = key.split("|")[1]
                lookup_statedb_and_update_configdb(per_npu_statedb[asic_id],
                                                   per_npu_configdb[asic_id],
                                                   logical_port, state,
                                                   port_status_dict)

            if json_output:
                click.echo("{}".format(json.dumps(port_status_dict, indent=4)))
            else:
                data = sorted([(k, v) for k, v in port_status_dict.items()])

                headers = ['port', 'state']
                click.echo(tabulate(data, headers=headers))

        sys.exit(CONFIG_SUCCESSFUL)
예제 #26
0
def packetloss(db, action, port):
    """config muxcable packetloss reset"""

    port = platform_sfputil_helper.get_interface_name(port, db)

    port_table_keys = {}
    mux_cable_table_keys = {}
    pck_loss_table_keys = {}
    per_npu_configdb = {}
    per_npu_statedb = {}

    # Getting all front asic namespace and correspding config and state DB connector

    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        # replace these with correct macros
        per_npu_configdb[asic_id] = ConfigDBConnector(use_unix_socket_path=True, namespace=namespace)
        per_npu_configdb[asic_id].connect()
        per_npu_statedb[asic_id] = swsscommon.SonicV2Connector(use_unix_socket_path=True, namespace=namespace)
        per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)

        port_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
            per_npu_statedb[asic_id].STATE_DB, 'LINK_PROBE_STATS|*')
        mux_cable_table_keys[asic_id] = per_npu_configdb[asic_id].get_table("MUX_CABLE").keys() # keys here are port names
    if port is not None and port != "all":

        asic_index = None
        if platform_sfputil is not None:
            asic_index = platform_sfputil.get_asic_id_for_logical_port(port)
        if asic_index is None:
            # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
            # is fully mocked
            import sonic_platform_base.sonic_sfp.sfputilhelper
            asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper().get_asic_id_for_logical_port(port)
            if asic_index is None:
                click.echo("Got invalid asic index for port {}, cant retreive mux status".format(port))
                sys.exit(CONFIG_FAIL)

        if per_npu_statedb[asic_index] is not None:
            pck_loss_table_keys = port_table_keys[asic_index]
            logical_key = "LINK_PROBE_STATS|{}".format(port)
            if logical_key in pck_loss_table_keys:
                update_configdb_pck_loss_data(per_npu_configdb[asic_index], port, "reset")
                sys.exit(CONFIG_SUCCESSFUL)
            else:
                click.echo("this is not a valid port present on pck_loss_stats".format(port))
                sys.exit(CONFIG_FAIL)
        else:
            click.echo("there is not a valid asic table for this asic_index".format(asic_index))
            sys.exit(CONFIG_FAIL)

    elif port == "all" and port is not None:

        for namespace in namespaces:
            asic_id = multi_asic.get_asic_index_from_namespace(namespace)
            for key in port_table_keys[asic_id]:
                logical_port = key.split("|")[1]
                if logical_port in mux_cable_table_keys[asic_id]:
                    update_configdb_pck_loss_data(per_npu_configdb[asic_id], logical_port, "reset")

        sys.exit(CONFIG_SUCCESSFUL)
예제 #27
0
def update_and_get_response_for_xcvr_cmd(cmd_name,
                                         rsp_name,
                                         exp_rsp,
                                         cmd_table_name,
                                         rsp_table_name,
                                         port,
                                         cmd_timeout_secs,
                                         arg=None):

    res_dict = {}
    state_db, appl_db = {}, {}
    firmware_rsp_tbl, firmware_rsp_tbl_keys = {}, {}
    firmware_rsp_sub_tbl = {}
    firmware_cmd_tbl = {}

    CMD_TIMEOUT_SECS = cmd_timeout_secs

    time_start = time.time()

    sel = swsscommon.Select()
    namespaces = multi_asic.get_front_end_namespaces()
    for namespace in namespaces:
        asic_id = multi_asic.get_asic_index_from_namespace(namespace)
        state_db[asic_id] = db_connect("STATE_DB", namespace)
        appl_db[asic_id] = db_connect("APPL_DB", namespace)
        firmware_cmd_tbl[asic_id] = swsscommon.Table(appl_db[asic_id],
                                                     cmd_table_name)
        firmware_rsp_sub_tbl[asic_id] = swsscommon.SubscriberStateTable(
            state_db[asic_id], rsp_table_name)
        firmware_rsp_tbl[asic_id] = swsscommon.Table(state_db[asic_id],
                                                     rsp_table_name)
        firmware_rsp_tbl_keys[asic_id] = firmware_rsp_tbl[asic_id].getKeys()
        for key in firmware_rsp_tbl_keys[asic_id]:
            firmware_rsp_tbl[asic_id]._del(key)
        sel.addSelectable(firmware_rsp_sub_tbl[asic_id])

    rc = CONFIG_FAIL
    res_dict[0] = CONFIG_FAIL
    res_dict[1] = 'unknown'

    logical_port_list = platform_sfputil_helper.get_logical_list()
    if port not in logical_port_list:
        click.echo("ERR: This is not a valid port, valid ports ({})".format(
            ", ".join(logical_port_list)))
        res_dict[0] = rc
        return res_dict

    asic_index = None
    if platform_sfputil is not None:
        asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(port)
    if asic_index is None:
        # TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
        # is fully mocked
        import sonic_platform_base.sonic_sfp.sfputilhelper
        asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper(
        ).get_asic_id_for_logical_port(port)
        if asic_index is None:
            click.echo(
                "Got invalid asic index for port {}, cant perform firmware cmd"
                .format(port))
            res_dict[0] = rc
            return res_dict

    if arg is None:
        cmd_arg = "null"
    else:
        cmd_arg = str(arg)

    fvs = swsscommon.FieldValuePairs([(cmd_name, cmd_arg)])
    firmware_cmd_tbl[asic_index].set(port, fvs)

    # Listen indefinitely for changes to the HW_MUX_CABLE_TABLE in the Application DB's
    while True:
        # Use timeout to prevent ignoring the signals we want to handle
        # in signal_handler() (e.g. SIGTERM for graceful shutdown)

        (state, selectableObj) = sel.select(SELECT_TIMEOUT)

        time_now = time.time()
        time_diff = time_now - time_start
        if time_diff >= CMD_TIMEOUT_SECS:
            return res_dict

        if state == swsscommon.Select.TIMEOUT:
            # Do not flood log when select times out
            continue
        if state != swsscommon.Select.OBJECT:
            click.echo(
                "sel.select() did not  return swsscommon.Select.OBJECT for sonic_y_cable updates"
            )
            continue

        # Get the redisselect object  from selectable object
        redisSelectObj = swsscommon.CastSelectableToRedisSelectObj(
            selectableObj)
        # Get the corresponding namespace from redisselect db connector object
        namespace = redisSelectObj.getDbConnector().getNamespace()
        asic_index = multi_asic.get_asic_index_from_namespace(namespace)

        (port_m, op_m, fvp_m) = firmware_rsp_sub_tbl[asic_index].pop()

        if not port_m:
            click.echo("Did not receive a port response {}".format(port))
            res_dict[1] = 'unknown'
            res_dict[0] = CONFIG_FAIL
            firmware_rsp_tbl[asic_index]._del(port)
            break

        if port_m != port:

            res_dict[1] = 'unknown'
            res_dict[0] = CONFIG_FAIL
            firmware_rsp_tbl[asic_index]._del(port)
            continue

        if fvp_m:

            fvp_dict = dict(fvp_m)
            if rsp_name in fvp_dict:
                # check if xcvrd got a probe command
                result = fvp_dict[rsp_name]

                if result == exp_rsp:
                    res_dict[1] = result
                    res_dict[0] = 0
                else:
                    res_dict[1] = result
                    res_dict[0] = CONFIG_FAIL

                firmware_rsp_tbl[asic_index]._del(port)
                break
            else:
                res_dict[1] = 'unknown'
                res_dict[0] = CONFIG_FAIL
                firmware_rsp_tbl[asic_index]._del(port)
                break
        else:
            res_dict[1] = 'unknown'
            res_dict[0] = CONFIG_FAIL
            firmware_rsp_tbl[asic_index]._del(port)
            break

    delete_all_keys_in_db_table("STATE_DB", rsp_table_name)

    return res_dict
    def task_worker(self):

        # Connect to STATE_DB and create transceiver dom info table
        app_db, state_db, status_tbl,y_cable_tbl = {}, {}, {},{}
        y_cable_tbl_keys = {}

        # Get the namespaces in the platform
        sel = swsscommon.Select()

        #logical_port_list = platform_sfputil.logical
        namespaces = multi_asic.get_front_end_namespaces()
        for namespace in namespaces:
            # Open a handle to the Application database, in all namespaces
            asic_id = multi_asic.get_asic_index_from_namespace(namespace)
            app_db[asic_id] = daemon_base.db_connect("APPL_DB", namespace)
            status_tbl[asic_id] = swsscommon.SubscriberStateTable(appl_db[asic_id], swsscommon.APP_HW_MUX_CABLE_TABLE_NAME)
            state_db[asic_id] = daemon_base.db_connect("STATE_DB", namespace)
            y_cable_tbl[asic_id] = swsscommon.Table(state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME)
            sel.addSelectable(status_tbl[asic_id])


        # Listen indefinitely for changes to the APP_MUX_CABLE_TABLE in the Application DB's
        while True:
            # Use timeout to prevent ignoring the signals we want to handle
            # in signal_handler() (e.g. SIGTERM for graceful shutdown)
            (state, selectableObj) = sel.select(SELECT_TIMEOUT)

            if state == swsscommon.Select.TIMEOUT:
                # Do not flood log when select times out
                continue
            if state != swsscommon.Select.OBJECT:
                self.log_warning("sel.select() did not  return swsscommon.Select.OBJECT")
                continue

            # Get the redisselect object  from selectable object
            redisSelectObj = swsscommon.CastSelectableToRedisSelectObj(selectableObj)
            # Get the corresponding namespace from redisselect db connector object
            namespace = redisSelectObj.getDbConnector().getNamespace()
            asic_index = multi_asic.get_asic_index_from_namespace(namespace)
            y_cable_tbl_keys[asic_id] = state_db[asic_index].get_keys(swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME)

            (port, op, fvp) = status_tbl[asic_id].pop()
            if fvp:
                #Might need to check the presence of this Port
                #in logical_port_list but keep for now for coherency
                if port not in y_cable_table_keys[asic_id]:
                    continue

                fvp_dict = dict(fvp)

                if op == "status" in fvp_dict:
                    #got a status change
                    new_status = fvp_dict["status"]
                    (status, fvs) = y_cable_tbl[asic_index].get(port)
                    if status is False:
                        logger.log_warning("Could not retreive fieldvalue pairs for {}, inside config_db".format(logical_port_name))
                        continue
                    mux_port_dict = dict(fvs)
                    old_status = mux_port_dict.get("status") 
                    read_side = mux_port_dict.get("read_side")
                    active_side = mux_port_dict.get("active_side")
                    if old_status != new_staus:
                        update_tor_active_side(read_side, new_status, port)
                        fvs_updated = swsscommon.FieldValuePairs([('status', new_status),
                                                          ('read_side', read_side),
                                                      ('active_side',active_side)])
                        mux_config_tbl.set(logical_port_name, fvs_updated)
                        #nothing to do since no status change
                    else:
                        logger.log_warning("Got a change event on _MUX_TABLE that does not update the current status".format(logical_port_name))