Пример #1
0
def get_route_entries():
    """
    helper to read present route entries from ASIC-DB and 
    as well initiate selector for ASIC-DB:ASIC-state updates.
    :return (selector,  subscriber, <list of sorted routes>)
    """
    db = swsscommon.DBConnector(ASIC_DB_NAME, 0)
    subs = swsscommon.SubscriberStateTable(db, ASIC_TABLE_NAME)
    print_message(syslog.LOG_DEBUG, "ASIC DB connected")

    rt = []
    while True:
        k, _, _ = subs.pop()
        if not k:
            break
        res, e = checkout_rt_entry(k)
        if res:
            rt.append(e)

    print_message(syslog.LOG_DEBUG,
                  json.dumps({"ASIC_ROUTE_ENTRY": sorted(rt)}, indent=4))

    selector = swsscommon.Select()
    selector.addSelectable(subs)
    return (selector, subs, sorted(rt))
Пример #2
0
    def get_transceiver_change_event(self, timeout=0):
        phy_port_dict = {}
        status = True

        if self.db_sel == None:
            from swsscommon import swsscommon
            self.state_db = swsscommon.DBConnector(swsscommon.STATE_DB,
                                                   REDIS_HOSTNAME, REDIS_PORT,
                                                   REDIS_TIMEOUT_USECS)

            # Subscribe to state table for SFP change notifications
            self.db_sel = swsscommon.Select()
            self.db_sel_tbl = swsscommon.NotificationConsumer(
                self.state_db, 'TRANSCEIVER_NOTIFY')
            self.db_sel.addSelectable(self.db_sel_tbl)
            self.db_sel_timeout = swsscommon.Select.TIMEOUT
            self.db_sel_object = swsscommon.Select.OBJECT
            self.sfpd_status_tbl = swsscommon.Table(self.state_db,
                                                    'MLNX_SFPD_TASK')

        # Check the liveness of mlnx-sfpd, if it failed, return false
        keys = self.sfpd_status_tbl.getKeys()
        if 'LIVENESS' not in keys:
            return False, phy_port_dict

        (state, c) = self.db_sel.select(timeout)
        if state == self.db_sel_timeout:
            status = True
        elif state != self.db_sel_object:
            status = False
        else:
            (key, op, fvp) = self.db_sel_tbl.pop()
            phy_port_dict[key] = op

        return status, phy_port_dict
Пример #3
0
    def get_transceiver_change_event(self, timeout=0):
        phy_port_dict = {}
        status = True

        if self.db_sel == None:
            from swsscommon import swsscommon
            self.state_db = swsscommon.DBConnector(swsscommon.STATE_DB,
                                                   REDIS_HOSTNAME, REDIS_PORT,
                                                   REDIS_TIMEOUT_USECS)

            # Subscribe to state table for SFP change notifications
            self.db_sel = swsscommon.Select()
            self.db_sel_tbl = swsscommon.NotificationConsumer(
                self.state_db, 'TRANSCEIVER_NOTIFY')
            self.db_sel.addSelectable(self.db_sel_tbl)
            self.db_sel_timeout = swsscommon.Select.TIMEOUT
            self.db_sel_object = swsscommon.Select.OBJECT

        (state, c) = self.db_sel.select(timeout)
        if state == self.db_sel_timeout:
            status = True
        elif state != self.db_sel_object:
            status = False
        else:
            (key, op, fvp) = self.db_sel_tbl.pop()
            phy_port_dict[key] = op

        return status, phy_port_dict
Пример #4
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
Пример #5
0
 def __init__(self):
     """ Constructor """
     self.db_connectors = {}
     self.selector = swsscommon.Select()
     self.callbacks = defaultdict(
         lambda: defaultdict(list))  # db -> table -> handlers[]
     self.subscribers = set()
Пример #6
0
def test_SelectMemoryLeak():
    N = 50000

    def table_set(t, state):
        fvs = swsscommon.FieldValuePairs([("status", state)])
        t.set("123", fvs)

    def generator_SelectMemoryLeak():
        app_db = swsscommon.DBConnector("APPL_DB", 0, True)
        t = swsscommon.Table(app_db, "TABLE")
        for i in range(int(N / 2)):
            table_set(t, "up")
            table_set(t, "down")

    tracker = SummaryTracker()
    appl_db = swsscommon.DBConnector("APPL_DB", 0, True)
    sel = swsscommon.Select()
    sst = swsscommon.SubscriberStateTable(appl_db, "TABLE")
    sel.addSelectable(sst)
    thr = Thread(target=generator_SelectMemoryLeak)
    thr.daemon = True
    thr.start()
    time.sleep(5)
    for _ in range(N):
        state, c = sel.select(1000)
    diff = tracker.diff()
    cases = []
    for name, count, _ in diff:
        if count >= N:
            cases.append("%s - %d objects for %d repeats" % (name, count, N))
    thr.join()
    assert not cases
Пример #7
0
def test_SelectYield():
    db = swsscommon.DBConnector("APPL_DB", 0, True)
    db.flushdb()
    sel = swsscommon.Select()
    cst = swsscommon.SubscriberStateTable(db, "testsst")
    sel.addSelectable(cst)

    print("Spawning thread: thread_test_func")
    test_thread = Thread(target=thread_test_func)
    test_thread.start()

    while True:
        # timeout 10s is too long and indicates thread hanging
        (state, c) = sel.select(10000)
        if state == swsscommon.Select.OBJECT:
            break
        elif state == swsscommon.Select.TIMEOUT:
            assert False

    test_thread.join()
    (key, op, cfvs) = cst.pop()
    assert key == "aaa"
    assert op == "SET"
    assert len(cfvs) == 1
    assert cfvs[0] == ('a', 'b')
Пример #8
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)
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
Пример #10
0
    def get_transceiver_change_event(self, timeout=0):
        phy_port_dict = {}
        status = True

        if self.db_sel is None:
            from swsscommon import swsscommon
            self.state_db = swsscommon.DBConnector("STATE_DB",
                                                   REDIS_TIMEOUT_USECS, True)

            # Subscribe to state table for SFP change notifications
            self.db_sel = swsscommon.Select()
            self.db_sel_tbl = swsscommon.NotificationConsumer(
                self.state_db, 'TRANSCEIVER_NOTIFY')
            self.db_sel.addSelectable(self.db_sel_tbl)
            self.db_sel_timeout = swsscommon.Select.TIMEOUT
            self.db_sel_object = swsscommon.Select.OBJECT
            self.sfpd_status_tbl = swsscommon.Table(self.state_db,
                                                    'MLNX_SFPD_TASK')

        # Check the liveness of mlnx-sfpd, if it failed, return system_fail event
        # If mlnx-sfpd not started, return system_not_ready event
        keys = self.sfpd_status_tbl.getKeys()
        if 'LIVENESS' not in keys:
            if self.mlnx_sfpd_started:
                log_err("mlnx-sfpd exited, return false to notify xcvrd.")
                phy_port_dict[EVENT_ON_ALL_SFP] = SYSTEM_FAIL
                return False, phy_port_dict
            else:
                log_info("mlnx-sfpd not ready, return false to notify xcvrd.")
                phy_port_dict[EVENT_ON_ALL_SFP] = SYSTEM_NOT_READY
                return False, phy_port_dict
        else:
            if not self.mlnx_sfpd_started:
                self.mlnx_sfpd_started = True
                log_info("mlnx-sfpd is running")
                phy_port_dict[EVENT_ON_ALL_SFP] = SYSTEM_READY
                return False, phy_port_dict

        if timeout:
            (state, c) = self.db_sel.select(timeout)
        else:
            (state, c) = self.db_sel.select()

        if state == self.db_sel_timeout:
            status = True
        elif state != self.db_sel_object:
            status = False
        else:
            (key, op, fvp) = self.db_sel_tbl.pop()
            phy_port_dict[key] = op

        return status, phy_port_dict
Пример #11
0
def set_feature_state(cfgdb_clients, name, state, block):
    """Enable/disable a feature"""
    entry_data_set = set()

    for ns, cfgdb in cfgdb_clients.items():
        entry_data = cfgdb.get_entry('FEATURE', name)
        if not entry_data:
            raise Exception("Feature '{}' doesn't exist".format(name))
        entry_data_set.add(entry_data['state'])

    if len(entry_data_set) > 1:
        raise Exception(
            "Feature '{}' state is not consistent across namespaces".format(
                name))

    if entry_data['state'] == "always_enabled":
        raise Exception(
            "Feature '{}' state is always enabled and can not be modified".
            format(name))

    for ns, cfgdb in cfgdb_clients.items():
        cfgdb.mod_entry('FEATURE', name, {'state': state})

    if block:
        db = swsscommon.DBConnector('STATE_DB', 0)
        tbl = swsscommon.SubscriberStateTable(db, 'FEATURE')
        sel = swsscommon.Select()

        sel.addSelectable(tbl)

        while True:
            rc, _ = sel.select(SELECT_TIMEOUT)

            if rc == swsscommon.Select.TIMEOUT:
                continue
            elif rc == swsscommon.Select.ERROR:
                raise Exception(
                    'Failed to wait till feature reaches desired state: select() failed'
                )
            else:
                feature, _, fvs = tbl.pop()
                if feature != name:
                    continue

                actual_state = dict(fvs).get('state')

                if actual_state == 'failed':
                    raise Exception('Feature failed to be {}'.format(state))
                elif actual_state == state:
                    break
Пример #12
0
def test_SubscriberStateTable():
    db = swsscommon.DBConnector("APPL_DB", 0, True)
    t = swsscommon.Table(db, "testsst")
    sel = swsscommon.Select()
    cst = swsscommon.SubscriberStateTable(db, "testsst")
    sel.addSelectable(cst)
    fvs = swsscommon.FieldValuePairs([('a', 'b')])
    t.set("aaa", fvs)
    (state, c) = sel.select()
    assert state == swsscommon.Select.OBJECT
    (key, op, cfvs) = cst.pop()
    assert key == "aaa"
    assert op == "SET"
    assert len(cfvs) == 1
    assert cfvs[0] == ('a', 'b')
Пример #13
0
def test_Notification():
    db = swsscommon.DBConnector("APPL_DB", 0, True)
    ntfc = swsscommon.NotificationConsumer(db, "testntf")
    sel = swsscommon.Select()
    sel.addSelectable(ntfc)
    fvs = swsscommon.FieldValuePairs([('a', 'b')])
    ntfp = swsscommon.NotificationProducer(db, "testntf")
    ntfp.send("aaa", "bbb", fvs)
    (state, c) = sel.select()
    assert state == swsscommon.Select.OBJECT
    (op, data, cfvs) = ntfc.pop()
    assert op == "aaa"
    assert data == "bbb"
    assert len(cfvs) == 1
    assert cfvs[0] == ('a', 'b')
Пример #14
0
    def subscribe_statedb(self):
        state_db = swsscommon.DBConnector("STATE_DB", REDIS_TIMEOUT_MS, True)
        sel = swsscommon.Select()
        cst = swsscommon.SubscriberStateTable(state_db, "FEATURE")
        sel.addSelectable(cst)

        while not self.task_stopping_event.is_set():
            (state, c) = sel.select(SELECT_TIMEOUT_MSECS)
            if state == swsscommon.Select.TIMEOUT:
                continue
            if state != swsscommon.Select.OBJECT:
                logger.log_warning(
                    "sel.select() did not return swsscommon.Select.OBJECT")
                continue
            (key, op, cfvs) = cst.pop()
            key_ext = key + ".service"
            timestamp = "{}".format(
                datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"))
            msg = {"unit": key_ext, "evt_src": "feature", "time": timestamp}
            self.task_notify(msg)
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 __init__(self):
        REDIS_TIMEOUT_MS = 0
        # Update this list to support more interfaces
        tbl_lst = [
            swsscommon.STATE_PORT_TABLE_NAME, swsscommon.STATE_VLAN_TABLE_NAME
        ]
        self.appl_db = swsscommon.DBConnector("STATE_DB", REDIS_TIMEOUT_MS,
                                              True)

        self.state_db = SonicV2Connector(host='127.0.0.1',
                                         decode_responses=True)
        self.state_db.connect(self.state_db.STATE_DB, False)
        self.sel = swsscommon.Select()
        self.tbls = [
            swsscommon.SubscriberStateTable(self.appl_db, t) for t in tbl_lst
        ]

        self.cur_interfaces = {}

        for t in self.tbls:
            self.sel.addSelectable(t)
Пример #17
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))
Пример #19
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
Пример #20
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)
Пример #21
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