コード例 #1
0
    def test_get_system_eeprom_info_from_db(self):
        return_values = {
            ('EEPROM_INFO|State', 'Initialized'):
            '1',
            ('EEPROM_INFO|{}'.format(hex(Eeprom._TLV_CODE_PRODUCT_NAME)), 'Value'):
            'MSN3420',
            ('EEPROM_INFO|{}'.format(hex(Eeprom._TLV_CODE_PART_NUMBER)), 'Value'):
            'MSN3420-CB2FO',
            ('EEPROM_INFO|{}'.format(hex(Eeprom._TLV_CODE_MAC_BASE)), 'Value'):
            '1C:34:DA:1C:9F:00',
            ('EEPROM_INFO|{}'.format(hex(Eeprom._TLV_CODE_SERIAL_NUMBER)), 'Value'):
            'MT2019X13878',
            ('EEPROM_INFO|{}'.format(hex(Eeprom._TLV_CODE_VENDOR_EXT)), 'Num_vendor_ext'):
            '2',
            ('EEPROM_INFO|{}'.format(hex(Eeprom._TLV_CODE_VENDOR_EXT)), 'Value_0'):
            'ext1',
            ('EEPROM_INFO|{}'.format(hex(Eeprom._TLV_CODE_VENDOR_EXT)), 'Value_1'):
            'ext2',
            ('EEPROM_INFO|{}'.format(hex(Eeprom._TLV_CODE_CRC_32)), 'Value'):
            'CRC_VALUE',
        }

        def side_effect(key, field):
            return return_values.get((key, field))

        eeprom = Eeprom()
        eeprom._redis_hget = MagicMock(side_effect=side_effect)

        info = eeprom.get_system_eeprom_info()
        assert eeprom.get_product_name() == 'MSN3420'
        assert eeprom.get_part_number() == 'MSN3420-CB2FO'
        assert eeprom.get_base_mac() == '1C:34:DA:1C:9F:00'
        assert eeprom.get_serial_number() == 'MT2019X13878'
        assert info[hex(Eeprom._TLV_CODE_VENDOR_EXT)] == ['ext1', 'ext2']
        assert info[hex(Eeprom._TLV_CODE_CRC_32)] == 'CRC_VALUE'
コード例 #2
0
 def test_get_system_eeprom_info_from_hardware(self):
     eeprom = Eeprom()
     eeprom.p = os.path.join(test_path, 'mock_eeprom_data')
     eeprom._redis_hget = MagicMock()
     info = eeprom.get_system_eeprom_info()
     assert eeprom.get_product_name() == 'MSN3800'
     assert eeprom.get_part_number() == 'MSN3800-CS2FO'
     assert eeprom.get_base_mac() == 'B8:59:9F:A9:34:00'
     assert eeprom.get_serial_number() == 'MT1937X00537'
     assert info[hex(Eeprom._TLV_CODE_CRC_32)] == '0x9EFF0119'
コード例 #3
0
ファイル: chassis.py プロジェクト: nokia/sonic-platform
class Chassis(ChassisBase):
    """
    NOKIA IXR7250 Platform-specific Chassis class
    """

    REBOOT_CAUSE_DICT = {
        'powerloss': ChassisBase.REBOOT_CAUSE_POWER_LOSS,
        'overtemp': ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER,
        'reboot': ChassisBase.REBOOT_CAUSE_NON_HARDWARE,
        'watchdog': ChassisBase.REBOOT_CAUSE_WATCHDOG,
        'under-voltage': ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER,
        'over-voltage': ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER,
    }

    def __init__(self):
        ChassisBase.__init__(self)

        # logger.set_min_log_priority_info()

        # Chassis specific slot numbering
        self.is_chassis_modular = nokia_common.is_chassis_modular()
        self.cpm_instance = nokia_common._get_cpm_slot()
        self.my_instance = nokia_common._get_my_slot()
        self.is_cpm = nokia_common.is_cpm()

        # Create a GRPC channel
        self.chassis_stub = None
        self.fan_stub = None
        self.thermal_stub = None
        self.psu_stub = None
        self.firmware_stub = None

        # Get maximum power consumed by each module like cards, fan-trays etc
        self._get_modules_consumed_power()

        # Module list
        self.get_module_list()

        # PSU list
        self._get_psu_list()

        # FAN list
        self._get_fantray_list()

        # Thermal list
        self.get_thermal_list()

        # Component List
        self._get_component_list()

        # SFP
        self.sfp_module_initialized = False
        self.sfp_event_initialized = False

        # Watchdog
        if self._watchdog is None:
            self._watchdog = Watchdog("dog")
            logger.log_info('HW Watchdog initialized')

        # system eeprom
        self._eeprom = Eeprom()

    def get_presence(self):
        module = self._get_my_module()
        if module is not None:
            return module.get_presence()
        return False

    def get_status(self):
        module = self._get_my_module()
        if module is not None:
            return module.get_status()
        return False

    def get_reboot_cause(self):
        unknown = (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
        # if reboot cause is non-hardware, return NON_HARDWARE
        return unknown

    def _get_my_module(self):
        module = None
        my_slot = self.get_my_slot()
        supervisor_slot = self.get_supervisor_slot()
        if supervisor_slot == my_slot:
            index = 0
        else:
            index = self.get_module_index(ModuleBase.MODULE_TYPE_LINE+str(my_slot-1))

        module = self.get_module(index)
        return module

    def get_status_led(self):
        color = Chassis.STATUS_LED_COLOR_OFF
        led_type = platform_ndk_pb2.ReqLedType.LED_TYPE_BOARD_STATUS
        channel, stub = nokia_common.channel_setup(nokia_common.NOKIA_GRPC_LED_SERVICE)
        if not channel or not stub:
            return color
        ret, response = nokia_common.try_grpc(stub.GetLed,
                                              platform_ndk_pb2.ReqLedInfoPb(led_type=led_type))
        nokia_common.channel_shutdown(channel)

        if ret is False:
            return color

        color = nokia_common.led_info_to_color(response.led_get.led_info[0])
        return color

    def set_status_led(self, color):
        led_type = platform_ndk_pb2.ReqLedType.LED_TYPE_BOARD_STATUS
        _led_info = nokia_common.led_color_to_info(color)

        channel, stub = nokia_common.channel_setup(nokia_common.NOKIA_GRPC_LED_SERVICE)
        if not channel or not stub:
            return False
        ret, response = nokia_common.try_grpc(stub.SetLed,
                                              platform_ndk_pb2.ReqLedInfoPb(led_type=led_type, led_info=_led_info))
        nokia_common.channel_shutdown(channel)

        if ret is False:
            return False
        return True

    def is_modular_chassis(self):
        return self.is_chassis_modular

    def get_supervisor_slot(self):
        return self.cpm_instance

    def get_my_slot(self):
        return self.my_instance

    def get_module_list(self):
        channel, stub = nokia_common.channel_setup(nokia_common.NOKIA_GRPC_CHASSIS_SERVICE)
        if not channel or not stub:
            return
        ret, response = nokia_common.try_grpc(stub.GetChassisProperties,
                                              platform_ndk_pb2.ReqModuleInfoPb())
        nokia_common.channel_shutdown(channel)

        if ret is False:
            return

        if self.is_modular_chassis() and not self.is_cpm:
            index = 0
            supervisor = Module(index,
                                ModuleBase.MODULE_TYPE_SUPERVISOR+str(index),
                                ModuleBase.MODULE_TYPE_SUPERVISOR,
                                self.get_supervisor_slot(), self.chassis_stub)
            supervisor.set_maximum_consumed_power(self.supervisor_power)

            index = 1
            module = Module(index,
                            ModuleBase.MODULE_TYPE_LINE+str(self.get_my_slot()-1),
                            ModuleBase.MODULE_TYPE_LINE,
                            self.get_my_slot(), self.chassis_stub)
            module.set_maximum_consumed_power(self.line_card_power)

            self._module_list.append(supervisor)
            self._module_list.append(module)
            logger.log_info('Not control card. Adding self into module list')
            return

        if self.is_modular_chassis() and self.is_cpm:
            for property_index in range(len(response.chassis_property.hw_property)):
                hw_property = response.chassis_property.hw_property[property_index]

                if hw_property.module_type == platform_ndk_pb2.HwModuleType.HW_MODULE_TYPE_CONTROL:
                    # Single CPM is supported in chassis
                    num_control_cards = 1
                    for j in range(num_control_cards):
                        module = Module(property_index,
                                        ModuleBase.MODULE_TYPE_SUPERVISOR+str(j),
                                        ModuleBase.MODULE_TYPE_SUPERVISOR,
                                        self.get_supervisor_slot(),
                                        self.chassis_stub)
                        module.set_maximum_consumed_power(self.supervisor_power)
                        self._module_list.append(module)

                elif hw_property.module_type == platform_ndk_pb2.HwModuleType.HW_MODULE_TYPE_LINE:
                    for j in range(hw_property.max_num):
                        module = Module(property_index,
                                        ModuleBase.MODULE_TYPE_LINE+str(j),
                                        ModuleBase.MODULE_TYPE_LINE,
                                        hw_property.slot[j],
                                        self.chassis_stub)
                        module.set_maximum_consumed_power(self.line_card_power)
                        self._module_list.append(module)

                elif hw_property.module_type == platform_ndk_pb2.HwModuleType.HW_MODULE_TYPE_FABRIC:
                    for j in range(hw_property.max_num):
                        module = Module(property_index,
                                        ModuleBase.MODULE_TYPE_FABRIC+str(j),
                                        ModuleBase.MODULE_TYPE_FABRIC,
                                        hw_property.slot[j],
                                        self.chassis_stub)
                        module.set_maximum_consumed_power(self.fabric_card_power)
                        self._module_list.append(module)

    def get_module_index(self, module_name):
        if not self.is_modular_chassis():
            return -1

        # For IMM on chassis, return supervisor-index as 0 and self index as 1
        if not self.is_cpm:
            if module_name.startswith(ModuleBase.MODULE_TYPE_SUPERVISOR):
                return 0
            else:
                return 1

        # For CPM on chassis
        module_index = -1
        channel, stub = nokia_common.channel_setup(nokia_common.NOKIA_GRPC_CHASSIS_SERVICE)
        if not channel or not stub:
            return module_index
        ret, response = nokia_common.try_grpc(stub.GetChassisProperties,
                                              platform_ndk_pb2.ReqModuleInfoPb())
        nokia_common.channel_shutdown(channel)

        if ret is False:
            return module_index

        for property_index in range(len(response.chassis_property.hw_property)):
            hw_property = response.chassis_property.hw_property[property_index]

            if hw_property.module_type == platform_ndk_pb2.HwModuleType.HW_MODULE_TYPE_CONTROL:
                # Single CPM is supported in chassis
                num_control_cards = 1
            elif hw_property.module_type == platform_ndk_pb2.HwModuleType.HW_MODULE_TYPE_LINE:
                num_line_cards = hw_property.max_num
            # elif hw_property.module_type == platform_ndk_pb2.HwModuleType.HW_MODULE_TYPE_FABRIC:
            #    num_fabric_cards = hw_property.max_num

        if module_name.startswith(ModuleBase.MODULE_TYPE_SUPERVISOR):
            module_index = 0
        elif module_name.startswith(ModuleBase.MODULE_TYPE_LINE):
            import re
            parse_nums = re.findall(r'\d+', module_name)
            module_number = int(parse_nums[0])
            module_index = num_control_cards + int(module_number)
        elif module_name.startswith(ModuleBase.MODULE_TYPE_FABRIC):
            import re
            parse_nums = re.findall(r'\d+', module_name)
            module_number = int(parse_nums[0])
            module_index = num_control_cards + num_line_cards + int(module_number)

        return module_index

    # PSU and power related
    def _get_psu_list(self):
        if not self.is_cpm:
            return []

        channel, stub = nokia_common.channel_setup(nokia_common.NOKIA_GRPC_PSU_SERVICE)
        if not channel or not stub:
            return
        ret, response = nokia_common.try_grpc(stub.GetPsuNum,
                                              platform_ndk_pb2.ReqPsuInfoPb())
        nokia_common.channel_shutdown(channel)

        if ret is False:
            return

        self.num_psus = response.num_psus
        for i in range(self.num_psus):
            psu = Psu(i, self.psu_stub)
            self._psu_list.append(psu)
        return self._psu_list

    def _get_modules_consumed_power(self):
        channel, stub = nokia_common.channel_setup(nokia_common.NOKIA_GRPC_CHASSIS_SERVICE)
        if not channel or not stub:
            return
        ret, response = nokia_common.try_grpc(stub.GetModuleMaxPower,
                                              platform_ndk_pb2.ReqModuleInfoPb())
        nokia_common.channel_shutdown(channel)

        if ret is False:
            return

        i = 0
        while i < len(response.power_info.module_power):
            module_info = response.power_info.module_power[i]
            i = i + 1
            type = module_info.module_type
            if type == platform_ndk_pb2.HwModuleType.HW_MODULE_TYPE_CONTROL:
                self.supervisor_power = module_info.module_maxpower
            elif type == platform_ndk_pb2.HwModuleType.HW_MODULE_TYPE_LINE:
                self.line_card_power = module_info.module_maxpower
            elif type == platform_ndk_pb2.HwModuleType.HW_MODULE_TYPE_FABRIC:
                self.fabric_card_power = module_info.module_maxpower
            elif type == platform_ndk_pb2.HwModuleType.HW_MODULE_TYPE_FANTRAY:
                self.fantray_power = module_info.module_maxpower

    # Fan related
    def _get_fantray_list(self):
        if not self.is_cpm:
            return []

        channel, stub = nokia_common.channel_setup(nokia_common.NOKIA_GRPC_FAN_SERVICE)
        if not channel or not stub:
            return
        ret, response = nokia_common.try_grpc(stub.GetFanNum,
                                              platform_ndk_pb2.ReqFanTrayOpsPb())
        nokia_common.channel_shutdown(channel)

        if ret is False:
            return

        self.num_fantrays = response.fan_nums.num_fantrays

        fan_index = 0
        for drawer_index in range(self.num_fantrays):
            fan_drawer = FanDrawer(drawer_index)
            fan_drawer.set_maximum_consumed_power(self.fantray_power)
            fan = Fan(fan_index, drawer_index, False, self.fan_stub)
            fan_drawer._fan_list.append(fan)
            fan_index = fan_index + 1
            self._fan_drawer_list.append(fan_drawer)

        return self._fan_drawer_list

    def allow_fan_platform_override(self):
        from os import path
        if path.exists(nokia_common.NOKIA_ALLOW_FAN_OVERRIDE_FILE):
            return True
        return False

    # Thermal related
    def get_thermal_list(self):
        channel, stub = nokia_common.channel_setup(nokia_common.NOKIA_GRPC_THERMAL_SERVICE)
        if not channel or not stub:
            return
        ret, response = nokia_common.try_grpc(stub.GetThermalDevicesInfo,
                                              platform_ndk_pb2.ReqTempParamsPb())
        nokia_common.channel_shutdown(channel)

        if ret is False:
            return

        all_temp_devices = response.temp_devices
        self.num_thermals = len(all_temp_devices.temp_device)
        i = 0

        # Empty previous list
        if len(self._thermal_list) != self.num_thermals:
            del self._thermal_list[:]

            for i in range(self.num_thermals):
                temp_device_ = all_temp_devices.temp_device[i]
                thermal = Thermal(i, temp_device_.device_idx, temp_device_.sensor_name, self.thermal_stub)
                self._thermal_list.append(thermal)

    def get_all_thermals(self):
        self.get_thermal_list()
        return self._thermal_list

    def get_thermal_manager(self):
        from .thermal_manager import ThermalManager
        return ThermalManager

    def _get_component_list(self):
        channel, stub = nokia_common.channel_setup(nokia_common.NOKIA_GRPC_FIRMWARE_SERVICE)
        if not channel or not stub:
            return
        ret, response = nokia_common.try_grpc(stub.HwFirmwareGetComponents,
                                              platform_ndk_pb2.ReqHwFirmwareInfoPb())
        nokia_common.channel_shutdown(channel)

        if ret is False:
            return

        for i in range(len(response.firmware_info.component)):
            hw_dev = response.firmware_info.component[i]
            component = Component(i, hw_dev.dev_type, hw_dev.dev_name,
                                  hw_dev.dev_desc, self.firmware_stub)
            self._component_list.append(component)

    # SFP operations below
    def initialize_sfp(self):
        from sonic_platform.sfp import Sfp

        if not nokia_common.is_cpm():
            if self.sfp_module_initialized:
                logger.log_error("SFPs are already initialized! stub {}".format(self.sfp_stub))
                return

            self.sfp_stub = None
            for index in range(1, NUM_SFP+1):
                logger.log_info("Creating SFP '%d'" % index)
                # default to QSFP-DD type for the moment. Type gets set dynamically when module is read
                sfp = Sfp(index, 'QSFP-DD', self.sfp_stub)
                self._sfp_list.append(sfp)
                # force 1st read to dynamically set type and detect dom capability
                sfp.get_transceiver_info()
                sfp._dom_capability_detect()
            self.sfp_module_initialized = True
            logger.log_info("SFPs are now initialized... stub {}".format(self.sfp_stub))

    def get_change_event(self, timeout=0):
        # logger.log_error("Get-change-event with thread-{} start ".format(
        #    str(os.getpid())+str(threading.current_thread().ident)))
        if not self.sfp_event_initialized:
            from sonic_platform.sfp_event import sfp_event
            # use the same stub as direct sfp ops does
            self.sfp_event_stub = self.sfp_stub

            logger.log_info("Initializing sfp_event with num {} and stub {} : sfp stub {}".format(
                NUM_SFP, self.sfp_event_stub, self.sfp_stub))
            self.sfp_event_list = sfp_event(NUM_SFP, self.sfp_event_stub)
            self.sfp_event_list.initialize()
            self.sfp_event_initialized = True

        timeout = 0
        port_dict = {}
        self.sfp_event_list.check_sfp_status(port_dict, timeout)

        return True, {'sfp': port_dict}

    def get_num_sfps(self):
        """
        Retrieves the number of sfps available on this chassis
        Returns:
            An integer, the number of sfps available on this chassis
        """
        if not self.sfp_module_initialized:
            self.initialize_sfp()

        return len(self._sfp_list)

    def get_all_sfps(self):
        """
        Retrieves all sfps available on this chassis
        Returns:
            A list of objects derived from SfpBase representing all sfps
            available on this chassis
        """
        if not self.sfp_module_initialized:
            self.initialize_sfp()

        return self._sfp_list

    def get_sfp(self, index):
        """
        Retrieves sfp represented by (1-based) index <index>
        Args:
            index: An integer, the index (1-based) of the sfp to retrieve.
            The index should be the sequence of a physical port in a chassis,
            starting from 1.
            For example, 1 for Ethernet0, 2 for Ethernet4 and so on.
        Returns:
            An object dervied from SfpBase representing the specified sfp
        """
        sfp = None
        if not self.sfp_module_initialized:
            self.initialize_sfp()

        try:
            # The index will start from 1
            sfp = self._sfp_list[index-1]
        except IndexError:
            logger.log_error("SFP index {} out of range (1-{})\n".format(
                             index, len(self._sfp_list)))

        return sfp

    # System eeprom below
    def get_name(self):
        """
        Retrieves the hardware product name for the chassis

        Returns:
            A string containing the hardware product name for this chassis.
        """
        return self._eeprom.get_product_name()

    def get_base_mac(self):
        """
        Retrieves the base MAC address for the chassis

        Returns:
            A string containing the MAC address in the format
            'XX:XX:XX:XX:XX:XX'
        """
        return self._eeprom.get_base_mac()

    def get_serial(self):
        """
        Retrieves the hardware serial number for the chassis

        Returns:
            A string containing the hardware serial number for this chassis.
        """
        return self._eeprom.get_serial_number()

    def get_serial_number(self):
        """
        Retrieves the hardware serial number for the chassis

        Returns:
            A string containing the hardware serial number for this chassis.
        """
        return self._eeprom.get_serial_number()

    def get_model(self):
        """
        Retrieves the model number (or part number) of the chassis
        Returns:
            string: Model/part number of chassis
        """
        return self._eeprom.get_part_number()

    def get_system_eeprom_info(self):
        """
        Retrieves the full content of system EEPROM information for the chassis

        Returns:
            A dictionary where keys are the type code defined in
            OCP ONIE TlvInfo EEPROM format and values are their corresponding
            values.
        """
        return self._eeprom.get_system_eeprom_info()

    def get_eeprom(self):
        """
        Retrieves the Sys Eeprom instance for the chassis.
        Returns :
            The instance of the Sys Eeprom
        """
        return self._eeprom

    # Midplane
    def init_midplane_switch(self):
        return True

    def get_position_in_parent(self):
        """
        Retrieves 1-based relative physical position in parent device.
        Returns:
            integer: The 1-based relative physical position in parent device or
                     -1 if cannot determine the position
        """
        return -1

    def is_replaceable(self):
        """
        Indicate whether this device is replaceable.
        Returns:
            bool: True if it is replaceable.
        """
        return False

    # Test suitest
    def test_suite_chassis(self):
        print("Starting Chassis UT")
        from sonic_platform.test import test_chassis
        test_chassis.run_all(self)

    def test_suite_psu(self):
        print("Starting PSUs UT")
        from sonic_platform.test import test_psu
        test_psu.run_all(self._psu_list)

    # UT related helper apis
    def empty_fan_drawer_list(self):
        for fantray in self.get_all_fan_drawers():
            del fantray._fan_list[:]
        del self._fan_drawer_list[:]

    def empty_fan_list(self, fantray_idx):
        fantray = self.get_fan_drawer(fantray_idx)
        del fantray._fan_list[:]
コード例 #4
0
class Chassis(ChassisBase):
    NUM_THERMAL = 3
    NUM_FANDRAWER = 6
    NUM_FANSPERDRAWER = 2
    NUM_FAN = NUM_FANDRAWER * NUM_FANSPERDRAWER
    NUM_PSU = 2
    NUM_SFP = 34
    HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/"
    PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/"
    REBOOT_CAUSE_FILE = "reboot-cause.txt"
    PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
    HOST_CHK_CMD = "docker > /dev/null 2>&1"

    def __init__(self):
        ChassisBase.__init__(self)
        # initialize thermals
        for index in range(0, Chassis.NUM_THERMAL):
            thermal = Thermal(index)
            self._thermal_list.append(thermal)

        # initialize fans
        for index in range(0, Chassis.NUM_FANDRAWER):
            fan_drawer = FanDrawer(index)
            for i in range(0, Chassis.NUM_FANSPERDRAWER):
                fan_index = Chassis.NUM_FANSPERDRAWER * index + i
                fan = Fan(fan_index, False)
                fan_drawer._fan_list.append(fan)
                self._fan_list.append(fan)
            self._fan_drawer_list.append(fan_drawer)

        # initialize fan led
        self.fan_led = FanLed.get_fanLed()
        self.fan_led.set_fans(self._fan_list)

        # initialize psus
        for index in range(0, Chassis.NUM_PSU):
            psu = Psu(index)
            self._psu_list.append(psu)

        # initialize psu led
        self.psu_led = PsuLed.get_psuLed()
        self.psu_led.set_psus(self._psu_list)

        # initialize sfps
        self.sfp_state = []
        for index in range(0, Chassis.NUM_SFP):
            if (index < Chassis.NUM_SFP - 2):
                sfp = Sfp(index, 'QSFP')
            else:
                sfp = Sfp(index, 'SFP')
            self._sfp_list.append(sfp)

        # initialize eeprom
        self._eeprom = Eeprom()

    def get_change_event(self, timeout=0):
        """
        Returns a nested dictionary containing all devices which have
        experienced a change at chassis level

        Args:
            timeout: Timeout in milliseconds (optional). If timeout == 0,
                this method will block until a change is detected.

        Returns:
            (bool, dict):
                - True if call successful, False if not;
                - A nested dictionary where key is a device type,
                  value is a dictionary with key:value pairs in the format of
                  {'device_id':'device_event'},
                  where device_id is the device ID for this device and
                        device_event,
                             status='1' represents device inserted,
                             status='0' represents device removed.
                  Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
                      indicates that fan 0 has been removed, fan 2
                      has been inserted and sfp 11 has been removed.
                  Specifically for SFP event, besides SFP plug in and plug out,
                  there are some other error event could be raised from SFP, when
                  these error happened, SFP eeprom will not be avalaible, XCVRD shall
                  stop to read eeprom before SFP recovered from error status.
                      status='2' I2C bus stuck,
                      status='3' Bad eeprom,
                      status='4' Unsupported cable,
                      status='5' High Temperature,
                      status='6' Bad cable.
        """
        change_event_dict = {"sfp": {}}
        sfp_status, sfp_change_dict = self.get_transceiver_change_event(
            timeout)
        change_event_dict["sfp"] = sfp_change_dict
        if sfp_status is True:
            return True, change_event_dict

        return False, {}

    def get_transceiver_change_event(self, timeout=0):
        start_time = time.time()
        # SFP status definition from xcvrd
        SFP_STATUS_INSERTED = '1'
        SFP_STATUS_REMOVED = '0'

        timeout = (timeout / 1000)
        end_time = start_time + timeout
        while (timeout >= 0):
            new_sfp_state = []
            change_dict = {}
            for index in range(self.get_num_sfps()):
                # get current status
                state = self._sfp_list[index].get_presence()
                new_sfp_state.append(state)

                if self.sfp_state == []:
                    change_dict[
                        index] = SFP_STATUS_INSERTED if state == True else SFP_STATUS_REMOVED
                elif state != self.sfp_state[index]:
                    change_dict[
                        index] = SFP_STATUS_INSERTED if state == True else SFP_STATUS_REMOVED

            self.sfp_state = new_sfp_state
            current_time = time.time()

            if bool(change_dict):
                return True, change_dict
            elif timeout == 0 or current_time < end_time:
                time.sleep(1)
                continue
            else:
                return True, {}

        return False, {}

    def get_thermal_manager(self):
        from sonic_platform.thermal_manager import ThermalManager
        return ThermalManager

    def get_name(self):
        """
        Retrieves the name of the device
        Returns:
            string: The name of the device
        """
        return self._eeprom.modelstr()

    def get_model(self):
        """
        Retrieves the model number (or part number) of the chassis
        Returns:
            string: Model/part number of chassis
        """
        return self._eeprom.part_number_str()

    def get_serial(self):
        """
        Retrieves the serial number of the device

        Returns:
            string: Serial number of device
        """
        return self._eeprom.serial_number_str()

    def get_system_eeprom_info(self):
        """
        Retrieves the full content of system EEPROM information for the chassis

        Returns:
            A dictionary where keys are the type code defined in
            OCP ONIE TlvInfo EEPROM format and values are their corresponding
            values.
        """
        return self._eeprom.get_system_eeprom_info()

    def initizalize_system_led(self):
        from .led import SystemLed
        self._status_led = SystemLed.get_systemLed()

    def set_status_led(self, color):
        """
        Sets the state of the system LED

        Args:
            color: A string representing the color with which to set the
                   system LED

        Returns:
            bool: True if system LED state is set successfully, False if not
        """
        if self._status_led is None:
            self.initizalize_system_led()

        return self._status_led.set_status(color)

    def get_status_led(self):
        """
        Gets the state of the system LED

        Returns:
            A string, one of the valid LED color strings which could be vendor
            specified.
        """
        if self._status_led is None:
            self.initizalize_system_led()

        return self._status_led.get_status()

    def get_watchdog(self):
        """
        Retreives hardware watchdog device on this chassis

        Returns:
            An object derived from WatchdogBase representing the hardware
            watchdog device
        """
        try:
            if self._watchdog is None:
                from sonic_platform.watchdog import Watchdog
                # Create the watchdog Instance
                self._watchdog = Watchdog()

        except Exception as e:
            syslog.syslog(syslog.LOG_ERR,
                          "Fail to load watchdog due to {}".format(e))
        return self._watchdog

    def get_reboot_cause(self):
        """
        Retrieves the cause of the previous reboot

        Returns:
            A tuple (string, string) where the first element is a string
            containing the cause of the previous reboot. This string must be
            one of the predefined strings in this class. If the first string
            is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
            to pass a description of the reboot cause.
        """

        reboot_cause_path = (Chassis.HOST_REBOOT_CAUSE_PATH +
                             Chassis.REBOOT_CAUSE_FILE)
        sw_reboot_cause = "Unknown"
        try:
            with open(reboot_cause_path, 'r') as fd:
                sw_reboot_cause = fd.read().strip()
        except IOError:
            pass

        return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause)