Exemple #1
0
def main():
    logger = Logger(SYSLOG_IDENTIFIER)
    logger.set_min_log_priority_info()

    if len(sys.argv) != 3:
        raise Exception('Pass service and valid asic-id as arguments')

    service = sys.argv[1]
    args_asic_id = sys.argv[2]

    # Get num asics
    num_asics = multi_asic.get_num_asics()
    if num_asics == 0:
        logger.log_error(
            'Detected no asics on this platform for service {}'.format(
                service))
        sys.exit(1)

    # Connect to STATE_DB and subscribe to chassis-module table notifications
    state_db = daemon_base.db_connect("CHASSIS_STATE_DB")

    sel = swsscommon.Select()
    sst = swsscommon.SubscriberStateTable(state_db, CHASSIS_ASIC_INFO_TABLE)
    sel.addSelectable(sst)

    while True:
        (state, c) = sel.select(SELECT_TIMEOUT_MSECS)
        if state == swsscommon.Select.TIMEOUT:
            continue
        if state != swsscommon.Select.OBJECT:
            continue

        (asic_key, asic_op, asic_fvp) = sst.pop()
        asic_id = re.search(r'\d+$', asic_key)
        global_asic_id = asic_id.group(0)

        if asic_op == 'SET':
            asic_fvs = dict(asic_fvp)
            asic_name = asic_fvs.get('name')
            if asic_name is None:
                logger.log_info('Unable to get asic_name for asic{}'.format(
                    global_asic_id))
                continue

            if asic_name.startswith('FABRIC-CARD') is False:
                logger.log_info(
                    'Skipping module with asic_name {} for asic{}'.format(
                        asic_name, global_asic_id))
                continue

            if (global_asic_id == args_asic_id):
                logger.log_info(
                    'Detected asic{} is online'.format(global_asic_id))
                sys.exit(0)
        elif asic_op == 'DEL':
            logger.log_info(
                'Detected asic{} is offline'.format(global_asic_id))
            sys.exit(1)
        else:
            continue
Exemple #2
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])
    def test_power_budget(self):
        chassis = MockChassis()
        psu1 = MockPsu("PSU 1", 0, True, True)
        psu1_power = 510.0
        psu1.set_maximum_supplied_power(psu1_power)
        chassis._psu_list.append(psu1)

        fan_drawer1 = MockFanDrawer("FanDrawer 1", 0, True, True)
        fan_drawer1_power = 510.0
        fan_drawer1.set_maximum_consumed_power(fan_drawer1_power)
        chassis._fan_drawer_list.append(fan_drawer1)

        module1 = MockModule("Module 1", 0, True, True)
        module1_power = 700.0
        module1.set_maximum_consumed_power(module1_power)
        chassis._module_list.append(module1)

        state_db = daemon_base.db_connect("STATE_DB")
        chassis_tbl = mock_swsscommon.Table(state_db, CHASSIS_INFO_TABLE)
        chassis_info = psud.PsuChassisInfo(SYSLOG_IDENTIFIER, chassis)
        chassis_info.first_run = False

        # Check case where supplied_power < consumed_power
        chassis_info.run_power_budget(chassis_tbl)
        chassis_info.update_master_status()
        fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1))

        assert float(fvs[CHASSIS_INFO_TOTAL_POWER_SUPPLIED_FIELD]) < float(
            fvs[CHASSIS_INFO_TOTAL_POWER_CONSUMED_FIELD])
        assert chassis_info.master_status_good == False

        # We cannot call get_status_master_led() on our mocked PSUs, because
        # they are not instantiated from the same Psu class loaded in psud,
        # so we must call it on the class there.
        assert psud.Psu.get_status_master_led() == MockPsu.STATUS_LED_COLOR_RED

        # Add a PSU
        psu2 = MockPsu("PSU 2", 1, True, True)
        psu2_power = 800.0
        psu2.set_maximum_supplied_power(psu2_power)
        chassis._psu_list.append(psu2)

        # Check case where supplied_power > consumed_power
        chassis_info.run_power_budget(chassis_tbl)
        chassis_info.update_master_status()
        fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1))

        assert float(fvs[CHASSIS_INFO_TOTAL_POWER_SUPPLIED_FIELD]) > float(
            fvs[CHASSIS_INFO_TOTAL_POWER_CONSUMED_FIELD])
        assert chassis_info.master_status_good == True

        # We cannot call get_status_master_led() on our mocked PSUs, because
        # they are not instantiated from the same Psu class loaded in psud,
        # so we must call it on the class there.
        assert psud.Psu.get_status_master_led(
        ) == MockPsu.STATUS_LED_COLOR_GREEN
    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)
Exemple #5
0
def main():
    helper_logger.log_notice("Start port_notify")
    # Connect to APP_DB and create transceiver dom info table
    appl_db = daemon_base.db_connect("APPL_DB")

    app_status_port_tbl = swsscommon.ProducerStateTable(
        appl_db, swsscommon.APP_PORT_APP_STATUS_TABLE_NAME)

    state_db = daemon_base.db_connect("STATE_DB")
    state_port_tbl = swsscommon.Table(state_db, STATE_PORT_TABLE)

    # Wait for PortInitDone
    wait_for_port_init_done()

    for port in range(RJ45_PORT_START, RJ45_PORT_END + 1):
        #print("Ethernet{}".format(port))
        notify_port_xcvr_status("Ethernet{}".format(port), app_status_port_tbl,
                                state_port_tbl, XCVR_STATE_READY)

    helper_logger.log_notice("End port_notify")
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
Exemple #7
0
def test_psuchassis_check_power_budget():
    chassis = MockChassis()
    psu = MockPsu(True, True, "PSU 1")
    psu1_power = 510.0
    psu.set_maximum_supplied_power(psu1_power)
    chassis.psu_list.append(psu)

    fan_drawer1 = MockFanDrawer(True, True, "FanDrawer 1")
    fan_drawer1_power = 510.0
    fan_drawer1.set_maximum_consumed_power(fan_drawer1_power)
    chassis.fan_drawer_list.append(fan_drawer1)

    module1 = MockFanDrawer(True, True, "Module 1")
    module1_power = 700.0
    module1.set_maximum_consumed_power(module1_power)
    chassis.module_list.append(module1)

    state_db = daemon_base.db_connect("STATE_DB")
    chassis_tbl = swsscommon.Table(state_db, CHASSIS_INFO_TABLE)
    chassis_info = PsuChassisInfo(SYSLOG_IDENTIFIER, chassis)

    # Check if supplied_power < consumed_power
    chassis_info.run_power_budget(chassis_tbl)
    if chassis_info.update_master_status():
        chassis_info._set_psu_master_led(chassis_info.master_status_good)
    fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1))

    assert float(fvs[CHASSIS_INFO_TOTAL_POWER_SUPPLIED_FIELD]) < float(
        fvs[CHASSIS_INFO_TOTAL_POWER_CONSUMED_FIELD])
    assert chassis_info.master_status_good == False
    assert MockPsu.get_status_master_led() == MockPsu.STATUS_LED_COLOR_RED

    # Add a PSU
    psu = MockPsu(True, True, "PSU 2")
    psu2_power = 800.0
    psu.set_maximum_supplied_power(psu2_power)
    chassis.psu_list.append(psu)

    # Check if supplied_power > consumed_power
    chassis_info.run_power_budget(chassis_tbl)
    if chassis_info.update_master_status():
        chassis_info._set_psu_master_led(chassis_info.master_status_good)
    fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1))

    assert float(fvs[CHASSIS_INFO_TOTAL_POWER_SUPPLIED_FIELD]) > float(
        fvs[CHASSIS_INFO_TOTAL_POWER_CONSUMED_FIELD])
    assert chassis_info.master_status_good == True
    assert MockPsu.get_status_master_led() == MockPsu.STATUS_LED_COLOR_GREEN
Exemple #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))
Exemple #9
0
    def test_supplied_power(self):
        chassis = MockChassis()
        psu1 = MockPsu("PSU 1", 0, True, True)
        psu1_power = 510.0
        psu1.set_maximum_supplied_power(psu1_power)
        chassis._psu_list.append(psu1)

        psu2 = MockPsu("PSU 2", 1, True, True)
        psu2_power = 800.0
        psu2.set_maximum_supplied_power(psu2_power)
        chassis._psu_list.append(psu2)

        psu3 = MockPsu("PSU 3", 2, True, True)
        psu3_power = 350.0
        psu3.set_maximum_supplied_power(psu3_power)
        chassis._psu_list.append(psu3)

        total_power = psu1_power + psu2_power + psu3_power
        state_db = daemon_base.db_connect("STATE_DB")
        chassis_tbl = mock_swsscommon.Table(state_db, CHASSIS_INFO_TABLE)
        chassis_info = psud.PsuChassisInfo(SYSLOG_IDENTIFIER, chassis)
        chassis_info.run_power_budget(chassis_tbl)
        fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1))

        # Check if supplied power is recorded in DB
        assert total_power == float(
            fvs[CHASSIS_INFO_TOTAL_POWER_SUPPLIED_FIELD])

        # Check if psu1 is not present
        psu1.set_presence(False)
        total_power = psu2_power + psu3_power
        chassis_info.run_power_budget(chassis_tbl)
        fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1))
        assert total_power == float(
            fvs[CHASSIS_INFO_TOTAL_POWER_SUPPLIED_FIELD])

        # Check if psu2 status is NOT_OK
        psu2.set_status(False)
        total_power = psu3_power
        chassis_info.run_power_budget(chassis_tbl)
        fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1))
        assert total_power == float(
            fvs[CHASSIS_INFO_TOTAL_POWER_SUPPLIED_FIELD])
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])
Exemple #13
0
    def test_consumed_power(self):
        chassis = MockChassis()
        fan_drawer1 = MockFanDrawer("FanDrawer 1", 0, True, True)
        fan_drawer1_power = 510.0
        fan_drawer1.set_maximum_consumed_power(fan_drawer1_power)
        chassis._fan_drawer_list.append(fan_drawer1)

        module1 = MockModule("Module 1", 0, True, True)
        module1_power = 700.0
        module1.set_maximum_consumed_power(module1_power)
        chassis._module_list.append(module1)

        total_power = fan_drawer1_power + module1_power
        state_db = daemon_base.db_connect("STATE_DB")
        chassis_tbl = mock_swsscommon.Table(state_db, CHASSIS_INFO_TABLE)
        chassis_info = psud.PsuChassisInfo(SYSLOG_IDENTIFIER, chassis)
        chassis_info.run_power_budget(chassis_tbl)
        fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1))

        # Check if supplied power is recorded in DB
        assert total_power == float(
            fvs[CHASSIS_INFO_TOTAL_POWER_CONSUMED_FIELD])

        # Check if fan_drawer1 present
        fan_drawer1.set_presence(False)
        total_power = module1_power
        chassis_info.run_power_budget(chassis_tbl)
        fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1))
        assert total_power == float(
            fvs[CHASSIS_INFO_TOTAL_POWER_CONSUMED_FIELD])

        # Check if module1 present
        fan_drawer1.set_presence(True)
        module1.set_presence(False)
        total_power = fan_drawer1_power
        chassis_info.run_power_budget(chassis_tbl)
        fvs = chassis_tbl.get(CHASSIS_INFO_POWER_KEY_TEMPLATE.format(1))
        assert total_power == float(
            fvs[CHASSIS_INFO_TOTAL_POWER_CONSUMED_FIELD])
    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")
Exemple #15
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]
Exemple #16
0
def wait_for_port_init_done():
    # Connect to APPL_DB and subscribe to PORT table notifications
    appl_db = daemon_base.db_connect("APPL_DB")

    sel = swsscommon.Select()
    sst = swsscommon.SubscriberStateTable(appl_db,
                                          swsscommon.APP_PORT_TABLE_NAME)
    sel.addSelectable(sst)

    # Make sure this daemon started after all port configured
    while True:
        (state, c) = sel.select(1000)
        if state == swsscommon.Select.TIMEOUT:
            continue
        if state != swsscommon.Select.OBJECT:
            helper_logger.log_warning(
                "sel.select() did not return swsscommon.Select.OBJECT")
            continue

        (key, op, fvp) = sst.pop()

        # Wait until PortInitDone
        if key in ["PortInitDone"]:
            break
    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))
    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)
Exemple #19
0
    def collect(self, chassis):
        """
        Collect thermal sensor temperature change status
        :param chassis: The chassis object
        :return:
        """
        num_modules = chassis.get_num_modules()

        if chassis.get_supervisor_slot() != chassis.get_my_slot():
            return

        chassis_state_db = daemon_base.db_connect("CHASSIS_STATE_DB")
        for module_index in range(1, num_modules + 1):
            # if chassis.get_module(module_index - 1).get_status() is not 'Online':
            #    continue
            if chassis.get_module(module_index -
                                  1).get_type() != ModuleBase.MODULE_TYPE_LINE:
                continue

            slot = chassis.get_module(module_index - 1).get_slot()
            table_name = 'TEMPERATURE_INFO_' + str(slot)
            lc_thermal_tbl = swsscommon.Table(chassis_state_db, table_name)

            # Find min, max, curr, margin temp for each module
            self.init_extreme()

            # Walk the table and store in the dictionary
            keys = lc_thermal_tbl.getKeys()
            if not keys:
                continue

            for key in keys:
                status, fvs = lc_thermal_tbl.get(key)
                fv_dict = dict(fvs)

                # Skip temperature sensors not valid for FAN reading.
                # Can convert this check into a RPC API
                if (float(fv_dict['minimum_temperature'])
                        == self.NOKIA_INVALID_TEMP) and (
                            float(fv_dict['maximum_temperature'])
                            == self.NOKIA_INVALID_TEMP):
                    continue

                # For J2 temperatures, there is remote normalization
                normalize = 0.0
                if (float(fv_dict['high_threshold']) ==
                        self.NOKIA_J2_TEMP_THRESHOLD):
                    normalize = self.NOKIA_J2_TEMP_THRESHOLD - self.NOKIA_IMM_TEMP_THRESHOLD

                self.curr_temp = max(float(self.curr_temp),
                                     float(fv_dict['temperature']) - normalize)
                self.updateminmax(
                    float(fv_dict['minimum_temperature']) - normalize)
                self.updateminmax(
                    float(fv_dict['maximum_temperature']) - normalize)
                margin = float(fv_dict['high_threshold']) - float(
                    fv_dict['temperature'])
                self.margin_temp = min(float(self.margin_temp), margin)

            slot_avg_dict = {}
            slot_avg_dict['curr_temp'] = int(self.curr_temp)
            slot_avg_dict['min_temp'] = int(self.min_temp)
            slot_avg_dict['max_temp'] = int(self.max_temp)
            slot_avg_dict['margin_temp'] = int(self.margin_temp)

            self.lc_thermal_dict[slot] = slot_avg_dict
Exemple #20
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
Exemple #21
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)
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