class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): ChassisBase.__init__(self) self._api_helper = APIHelper() self.is_host = self._api_helper.is_host() self.config_data = {} self.__initialize_fan() self.__initialize_psu() self.__initialize_thermals() self.__initialize_components() self.__initialize_sfp() self.__initialize_eeprom() def __initialize_sfp(self): from sonic_platform.sfp import Sfp self.QSFP_PORT_START = QSFP_PORT_START self.QSFP_PORT_END = QSFP_PORT_END for index in range(0, PORT_END): if index in range(self.QSFP_PORT_START, self.QSFP_PORT_END + 1): sfp_module = Sfp(index, 'QSFP') else: sfp_module = Sfp(index, 'SFP') self._sfp_list.append(sfp_module) self.sfp_module_initialized = True def __initialize_fan(self): from sonic_platform.fan import Fan for fant_index in range(0, NUM_FAN_TRAY): for fan_index in range(0, NUM_FAN): fan = Fan(fant_index, fan_index) self._fan_list.append(fan) def __initialize_psu(self): from sonic_platform.psu import Psu for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) def __initialize_thermals(self): from sonic_platform.thermal import Thermal for index in range(0, NUM_THERMAL): thermal = Thermal(index) self._thermal_list.append(thermal) def __initialize_eeprom(self): from sonic_platform.eeprom import Tlv self._eeprom = Tlv() def __initialize_components(self): from sonic_platform.component import Component for index in range(0, NUM_COMPONENT): component = Component(index) self._component_list.append(component) def __initialize_watchdog(self): from sonic_platform.watchdog import Watchdog self._watchdog = Watchdog() def __is_host(self): return os.system(HOST_CHK_CMD) == 0 def __read_txt_file(self, file_path): try: with open(file_path, 'r') as fd: data = fd.read() return data.strip() except IOError: pass return None def get_name(self): """ Retrieves the name of the device Returns: string: The name of the device """ return self._api_helper.hwsku def get_presence(self): """ Retrieves the presence of the Chassis Returns: bool: True if Chassis is present, False if not """ return True def get_status(self): """ Retrieves the operational status of the device Returns: A boolean value, True if device is operating properly, False if not """ return True 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_mac() 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() 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_eeprom() 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 = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) sw_reboot_cause = self._api_helper.read_txt_file( reboot_cause_path) or "Unknown" return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause) 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: sys.stderr.write("SFP index {} out of range (1-{})\n".format( index, len(self._sfp_list))) return sfp
class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): ChassisBase.__init__(self) self._api_helper = APIHelper() self.sfp_module_initialized = False self.__initialize_eeprom() self.is_host = self._api_helper.is_host() if not self.is_host: self.__initialize_fan() self.__initialize_psu() self.__initialize_thermals() else: self.__initialize_components() self._reboot_cause_path = HOST_REBOOT_CAUSE_PATH if self.__is_host( ) else PMON_REBOOT_CAUSE_PATH def __initialize_sfp(self): sfputil_helper = SfpUtilHelper() port_config_file_path = device_info.get_path_to_port_config_file() sfputil_helper.read_porttab_mappings(port_config_file_path, 0) from sonic_platform.sfp import Sfp for index in range(0, NUM_SFP): name_idx = 0 if index + 1 == NUM_SFP else index + 1 sfp = Sfp(index, sfputil_helper.logical[name_idx]) self._sfp_list.append(sfp) self.sfp_module_initialized = True def __initialize_psu(self): from sonic_platform.psu import Psu for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) def __initialize_fan(self): from sonic_platform.fan import Fan for fant_index in range(0, NUM_FAN_TRAY): for fan_index in range(0, NUM_FAN): fan = Fan(fant_index, fan_index) self._fan_list.append(fan) def __initialize_thermals(self): from sonic_platform.thermal import Thermal for index in range(0, NUM_THERMAL): thermal = Thermal(index) self._thermal_list.append(thermal) def __initialize_eeprom(self): from sonic_platform.eeprom import Tlv self._eeprom = Tlv() def __initialize_components(self): from sonic_platform.component import Component for index in range(0, NUM_COMPONENT): component = Component(index) self._component_list.append(component) def __is_host(self): return os.system(HOST_CHK_CMD) == 0 def __read_txt_file(self, file_path): try: with open(file_path, 'r') as fd: data = fd.read() return data.strip() except IOError: pass return None 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_mac() 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_eeprom() 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. """ description = 'None' reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER hw_reboot_cause = self._component_list[0].get_register_value( RESET_REGISTER) sw_reboot_cause = self.__read_txt_file( self._reboot_cause_path) or "Unknown" if hw_reboot_cause == "0x55": reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = sw_reboot_cause elif hw_reboot_cause == "0x11": reboot_cause = self.REBOOT_CAUSE_POWER_LOSS elif hw_reboot_cause == "0x33": reboot_cause = self.REBOOT_CAUSE_WATCHDOG else: reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER description = 'Unknown reason' return (reboot_cause, description) def get_watchdog(self): """ Retreives hardware watchdog device on this chassis Returns: An object derived from WatchdogBase representing the hardware watchdog device """ if self._watchdog is None: from sonic_platform.watchdog import Watchdog self._watchdog = Watchdog() return self._watchdog 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. """ # SFP event if not self.sfp_module_initialized: self.__initialize_sfp() sfp_event = SfpEvent(self._sfp_list).get_sfp_event(timeout) if sfp_event: return True, {'sfp': sfp_event} return False, {'sfp': {}} ############################################################## ######################## SFP methods ######################### ############################################################## 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: sys.stderr.write("SFP index {} out of range (1-{})\n".format( index, len(self._sfp_list))) return sfp ############################################################## ###################### Device methods ######################## ############################################################## def get_name(self): """ Retrieves the name of the device Returns: string: The name of the device """ return self._api_helper.hwsku def get_presence(self): """ Retrieves the presence of the Chassis Returns: bool: True if Chassis is present, False if not """ return True def get_model(self): """ Retrieves the model number (or part number) of the device Returns: string: Model/part number of device """ return self._eeprom.get_pn() def get_serial(self): """ Retrieves the serial number of the device Returns: string: Serial number of device """ return self._eeprom.get_serial() def get_status(self): """ Retrieves the operational status of the device Returns: A boolean value, True if device is operating properly, False if not """ return True
class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): ChassisBase.__init__(self) self._api_helper = APIHelper() self.sfp_module_initialized = False self.__initialize_eeprom() self.is_host = self._api_helper.is_host() if not self.is_host: self.__initialize_fan() self.__initialize_psu() self.__initialize_thermals() else: self.__initialize_components() def __initialize_sfp(self): from sonic_platform.sfp import Sfp for index in range(0, NUM_SFP): sfp = Sfp(index) self._sfp_list.append(sfp) self.sfp_module_initialized = True def __initialize_psu(self): from sonic_platform.psu import Psu for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) def __initialize_fan(self): from sonic_platform.fan import Fan for fant_index in range(0, NUM_FAN_TRAY): for fan_index in range(0, NUM_FAN): fan = Fan(fant_index, fan_index) self._fan_list.append(fan) def __initialize_thermals(self): from sonic_platform.thermal import Thermal for index in range(0, NUM_THERMAL): thermal = Thermal(index) self._thermal_list.append(thermal) def __initialize_eeprom(self): from sonic_platform.eeprom import Tlv self._eeprom = Tlv() def __initialize_components(self): from sonic_platform.component import Component for index in range(0, NUM_COMPONENT): component = Component(index) self._component_list.append(component) 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_mac() 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_eeprom() 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_POWER_LOSS = "Power Loss" REBOOT_CAUSE_THERMAL_OVERLOAD_CPU = "Thermal Overload: CPU" REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC = "Thermal Overload: ASIC" REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER = "Thermal Overload: Other" REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED = "Insufficient Fan Speed" REBOOT_CAUSE_WATCHDOG = "Watchdog" REBOOT_CAUSE_HARDWARE_OTHER = "Hardware - Other" REBOOT_CAUSE_NON_HARDWARE = "Non-Hardware" """ reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) sw_reboot_cause = self._api_helper.read_txt_file( reboot_cause_path) or "Unknown" hw_reboot_cause = self._api_helper.get_cpld_reg_value( GETREG_PATH, RESET_REGISTER) prev_reboot_cause = { '0x11': (self.REBOOT_CAUSE_POWER_LOSS, 'Power on reset'), '0x22': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'CPLD_WD_RESET'), '0x33': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by CPU'), '0x44': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by reset button'), '0x55': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, ''), '0x66': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC, ''), '0x77': (self.REBOOT_CAUSE_WATCHDOG, '') }.get(hw_reboot_cause, (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Unknown reason')) if sw_reboot_cause != 'Unknown' and hw_reboot_cause == '0x11': prev_reboot_cause = ( self.REBOOT_CAUSE_NON_HARDWARE, sw_reboot_cause) return prev_reboot_cause ############################################################## ######################## SFP methods ######################### ############################################################## 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: sys.stderr.write("SFP index {} out of range (1-{})\n".format( index, len(self._sfp_list))) return sfp ############################################################## ####################### Other methods ######################## ############################################################## def get_watchdog(self): """ Retreives hardware watchdog device on this chassis Returns: An object derived from WatchdogBase representing the hardware watchdog device """ if self._watchdog is None: from sonic_platform.watchdog import Watchdog self._watchdog = Watchdog() return self._watchdog ############################################################## ###################### Device methods ######################## ############################################################## def get_name(self): """ Retrieves the name of the device Returns: string: The name of the device """ return self._api_helper.hwsku def get_presence(self): """ Retrieves the presence of the Chassis Returns: bool: True if Chassis is present, False if not """ return True def get_model(self): """ Retrieves the model number (or part number) of the device Returns: string: Model/part number of device """ return self._eeprom.get_pn() def get_serial(self): """ Retrieves the serial number of the device Returns: string: Serial number of device """ return self._eeprom.get_serial() def get_status(self): """ Retrieves the operational status of the device Returns: A boolean value, True if device is operating properly, False if not """ return True
class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): self.config_data = {} for index in range(0, NUM_FAN): fan = Fan(index) self._fan_list.append(fan) for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) for index in range(0, NUM_THERMAL): thermal = Thermal(index) self._thermal_list.append(thermal) for index in range(0, NUM_SFP): sfp = Sfp(index) self._sfp_list.append(sfp) ChassisBase.__init__(self) self._component_name_list = COMPONENT_NAME_LIST self._watchdog = Watchdog() self._eeprom = Tlv() def __read_txt_file(self, file_path): try: with open(file_path, 'r') as fd: data = fd.read() return data.strip() except IOError: raise IOError("Unable to open %s file !" % file_path) 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_mac() 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() 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_eeprom() def get_firmware_version(self, component_name): """ Retrieves platform-specific hardware/firmware versions for chassis componenets such as BIOS, CPLD, FPGA, etc. Args: type: A string, component name Returns: A string containing platform-specific component versions """ self.component = Component(component_name) if component_name not in self._component_name_list: return None return self.component.get_firmware_version() def install_component_firmware(self, component_name, image_path): """ Install firmware to module Args: type: A string, component name. image_path: A string, path to firmware image. Returns: A boolean, True if install successfully, False if not """ self.component = Component(component_name) if component_name not in self._component_name_list: return False return self.component.upgrade_firmware(image_path) 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. """ self.component = Component("SMC_CPLD") description = 'None' reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER hw_reboot_cause = self.component.get_register_value(RESET_REGISTER) sw_reboot_cause = self.__read_txt_file(REBOOT_CAUSE_PATH) if sw_reboot_cause != "Unexpected reboot": reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = sw_reboot_cause elif hw_reboot_cause == "0x11": reboot_cause = self.REBOOT_CAUSE_POWER_LOSS elif hw_reboot_cause == "0x33" or hw_reboot_cause == "0x55": reboot_cause = self.REBOOT_CAUSE_WATCHDOG else: reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER description = 'Unknown reason' return (reboot_cause, description)
class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): super(Chassis, self).__init__() for fantray_index in range(0, NUM_FAN_TRAY): for fan_index in range(0, NUM_FAN): fan = Fan(fantray_index, fan_index) self._fan_list.append(fan) for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) for index in range(0, NUM_THERMAL): thermal = Thermal(index) self._thermal_list.append(thermal) self.PORT_START = SFP_PORT_START self.QSFP_PORT_START = QSFP_PORT_START self.PORT_END = QSFP_PORT_END for index in range(0, NUM_SFP): if index in range(self.QSFP_PORT_START, self.QSPORT_END + 1): sfp_module = Sfp(index, 'QSFP') else: sfp_module = Sfp(index, 'SFP') self._sfp_list.append(sfp_module) self._component_name_list = COMPONENT_NAME_LIST self._watchdog = Watchdog() self._eeprom = Tlv() logger.log_info("Chassis loaded successfully") def __is_host(self): return os.system(HOST_CHK_CMD) == 0 def __read_txt_file(self, file_path): try: with open(file_path, 'r') as fd: data = fd.read() return data.strip() except IOError: pass return None 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_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() 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_eeprom() def get_firmware_version(self, component_name): """ Retrieves platform-specific hardware/firmware versions for chassis componenets such as BIOS, CPLD, FPGA, etc. Args: type: A string, component name Returns: A string containing platform-specific component versions """ self.component = Component(component_name) if component_name not in self._component_name_list: return None return self.component.get_firmware_version() def install_component_firmware(self, component_name, image_path): """ Install firmware to module Args: type: A string, component name. image_path: A string, path to firmware image. Returns: A boolean, True if install successfully, False if not """ self.component = Component(component_name) if component_name not in self._component_name_list: return False return self.component.upgrade_firmware(image_path) 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. """ description = 'None' reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER reboot_cause_path = ( HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE ) if self.__is_host() else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE prev_reboot_cause_path = ( HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) if self.__is_host( ) else PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE sw_reboot_cause = self.__read_txt_file(reboot_cause_path) or "Unknown" prev_sw_reboot_cause = self.__read_txt_file( prev_reboot_cause_path) or "Unknown" if sw_reboot_cause != "Unknown": reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = sw_reboot_cause else: reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER description = 'Unknown reason' return (reboot_cause, description)
class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): self.config_data = {} ChassisBase.__init__(self) self._eeprom = Tlv() self._api_helper = APIHelper() for fant_index in range(0, NUM_FAN_TRAY): for fan_index in range(0, NUM_FAN): fan = Fan(fant_index, fan_index) self._fan_list.append(fan) for index in range(0, NUM_SFP): sfp = Sfp(index) self._sfp_list.append(sfp) for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) for index in range(0, NUM_COMPONENT): component = Component(index) self._component_list.append(component) for index in range(0, NUM_THERMAL): thermal = Thermal(index) self._thermal_list.append(thermal) 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_mac() 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() 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_eeprom() 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. """ status, raw_cause = self._api_helper.ipmi_raw(IPMI_OEM_NETFN, IPMI_GET_REBOOT_CAUSE) hx_cause = raw_cause.split()[0] if status and len( raw_cause.split()) > 0 else 00 reboot_cause = { "00": self.REBOOT_CAUSE_HARDWARE_OTHER, "11": self.REBOOT_CAUSE_POWER_LOSS, "22": self.REBOOT_CAUSE_NON_HARDWARE, "33": self.REBOOT_CAUSE_HARDWARE_OTHER, "44": self.REBOOT_CAUSE_NON_HARDWARE, "55": self.REBOOT_CAUSE_NON_HARDWARE, "66": self.REBOOT_CAUSE_WATCHDOG, "77": self.REBOOT_CAUSE_NON_HARDWARE }.get(hx_cause, self.REBOOT_CAUSE_HARDWARE_OTHER) description = { "00": "Unknown reason", "11": "The last reset is Power on reset", "22": "The last reset is soft-set CPU warm reset", "33": "The last reset is soft-set CPU cold reset", "44": "The last reset is CPU warm reset", "55": "The last reset is CPU cold reset", "66": "The last reset is watchdog reset", "77": "The last reset is power cycle reset" }.get(hx_cause, "Unknown reason") return (reboot_cause, description)
class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): ChassisBase.__init__(self) self.config_data = {} for fant_index in range(0, NUM_FAN_TRAY): for fan_index in range(0, NUM_FAN): fan = Fan(fant_index, fan_index) self._fan_list.append(fan) for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) for index in range(0, NUM_THERMAL): thermal = Thermal(index) self._thermal_list.append(thermal) for index in range(0, NUM_SFP): sfp = Sfp(index) self._sfp_list.append(sfp) for index in range(0, NUM_COMPONENT): component = Component(index) self._component_list.append(component) self._watchdog = Watchdog() self._eeprom = Tlv() def __is_host(self): return os.system(HOST_CHK_CMD) == 0 def __read_txt_file(self, file_path): try: with open(file_path, 'r') as fd: data = fd.read() return data.strip() except IOError: pass return None 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_mac() 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() 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_eeprom() 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. """ description = 'None' reboot_cause_path = ( HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE ) if self.__is_host() else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE prev_reboot_cause_path = ( HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) if self.__is_host( ) else PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE hw_reboot_cause = self._component_list[0].get_register_value( RESET_REGISTER) sw_reboot_cause = self.__read_txt_file(reboot_cause_path) or "Unknown" prev_sw_reboot_cause = self.__read_txt_file( prev_reboot_cause_path) or "Unknown" if sw_reboot_cause == "Unknown" and ( prev_sw_reboot_cause == "Unknown" or prev_sw_reboot_cause == self.REBOOT_CAUSE_POWER_LOSS) and hw_reboot_cause == "0x11": reboot_cause = self.REBOOT_CAUSE_POWER_LOSS elif sw_reboot_cause != "Unknown" and hw_reboot_cause == "0x11": reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = sw_reboot_cause elif prev_reboot_cause_path != "Unknown" and hw_reboot_cause == "0x11": reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = prev_sw_reboot_cause elif hw_reboot_cause == "0x22": reboot_cause = self.REBOOT_CAUSE_WATCHDOG, else: reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER description = 'Unknown reason' return (reboot_cause, description)
class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): ChassisBase.__init__(self) self.config_data = {} for fant_index in range(0, NUM_FAN_TRAY): for fan_index in range(0, NUM_FAN): fan = Fan(fant_index, fan_index) self._fan_list.append(fan) for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) for index in range(0, NUM_THERMAL): thermal = Thermal(index) self._thermal_list.append(thermal) # sfp index start from 1 for index in range(0, NUM_SFP): sfp = Sfp(index) self._sfp_list.append(sfp) for index in range(0, NUM_COMPONENT): component = Component(index) self._component_list.append(component) self._eeprom = Tlv() def __is_host(self): return os.system(HOST_CHK_CMD) == 0 def __read_txt_file(self, file_path): try: with open(file_path, 'r') as fd: data = fd.read() return data.strip() except IOError: pass return None 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_mac() 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() 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_eeprom() 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. """ description = 'None' reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER reboot_cause_path = ( HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE ) if self.__is_host() else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE prev_reboot_cause_path = ( HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) if self.__is_host( ) else PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE hw_reboot_cause = self._component_list[0].get_register_value( RESET_REGISTER) sw_reboot_cause = self.__read_txt_file(reboot_cause_path) or "Unknown" prev_sw_reboot_cause = self.__read_txt_file( prev_reboot_cause_path) or "Unknown" if sw_reboot_cause == "Unknown" and ( prev_sw_reboot_cause == "Unknown" or prev_sw_reboot_cause == self.REBOOT_CAUSE_POWER_LOSS) and hw_reboot_cause == "0x11": reboot_cause = self.REBOOT_CAUSE_POWER_LOSS elif sw_reboot_cause != "Unknown" and hw_reboot_cause == "0x11": reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = sw_reboot_cause elif prev_reboot_cause_path != "Unknown" and hw_reboot_cause == "0x11": reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = prev_sw_reboot_cause elif hw_reboot_cause == "0x22": reboot_cause = self.REBOOT_CAUSE_WATCHDOG, else: reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER description = 'Unknown reason' return (reboot_cause, description) def get_watchdog(self): """ Retreives hardware watchdog device on this chassis Returns: An object derived from WatchdogBase representing the hardware watchdog device """ if self._watchdog is None: from sonic_platform.watchdog import Watchdog self._watchdog = Watchdog() return self._watchdog 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 try: # The index will start from 1 sfp = self._sfp_list[index - 1] except IndexError: sys.stderr.write("SFP index {} out of range (1-{})\n".format( index, len(self._sfp_list))) return sfp
class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): ChassisBase.__init__(self) self._api_helper = APIHelper() self.sfp_module_initialized = False self.__initialize_eeprom() self.is_host = self._api_helper.is_host() if not self.is_host: self.__initialize_fan() self.__initialize_psu() self.__initialize_thermals() else: self.__initialize_components() def __initialize_sfp(self): from sonic_platform.sfp import Sfp for index in range(0, NUM_SFP): sfp = Sfp(index) self._sfp_list.append(sfp) self.sfp_module_initialized = True def __initialize_psu(self): from sonic_platform.psu import Psu for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) def __initialize_fan(self): from sonic_platform.fan import Fan for fant_index in range(0, NUM_FAN_TRAY): for fan_index in range(0, NUM_FAN): fan = Fan(fant_index, fan_index) self._fan_list.append(fan) def __initialize_thermals(self): from sonic_platform.thermal import Thermal for index in range(0, NUM_THERMAL): thermal = Thermal(index) self._thermal_list.append(thermal) def __initialize_eeprom(self): from sonic_platform.eeprom import Tlv self._eeprom = Tlv() def __initialize_components(self): from sonic_platform.component import Component for index in range(0, NUM_COMPONENT): component = Component(index) self._component_list.append(component) 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_mac() 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() 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_eeprom() 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. """ description = 'None' reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER reboot_cause_path = ( HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE ) if self.is_host else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE prev_reboot_cause_path = ( HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE ) if self.is_host else PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE hw_reboot_cause = self._component_list[0].get_register_value( RESET_REGISTER) sw_reboot_cause = self._api_helper.read_txt_file( reboot_cause_path) or "Unknown" prev_sw_reboot_cause = self._api_helper.read_txt_file( prev_reboot_cause_path) or "Unknown" if sw_reboot_cause == "Unknown" and ( prev_sw_reboot_cause == "Unknown" or prev_sw_reboot_cause == self.REBOOT_CAUSE_POWER_LOSS) and hw_reboot_cause == "0x11": reboot_cause = self.REBOOT_CAUSE_POWER_LOSS elif sw_reboot_cause != "Unknown" and hw_reboot_cause == "0x11": reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = sw_reboot_cause elif prev_reboot_cause_path != "Unknown" and hw_reboot_cause == "0x11": reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = prev_sw_reboot_cause elif hw_reboot_cause == "0x22": reboot_cause = self.REBOOT_CAUSE_WATCHDOG, else: reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER description = 'Unknown reason' return (reboot_cause, description) ############################################################## ######################## SFP methods ######################### ############################################################## 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: sys.stderr.write("SFP index {} out of range (1-{})\n".format( index, len(self._sfp_list))) return sfp ############################################################## ####################### Other methods ######################## ############################################################## def get_watchdog(self): """ Retreives hardware watchdog device on this chassis Returns: An object derived from WatchdogBase representing the hardware watchdog device """ if self._watchdog is None: from sonic_platform.watchdog import Watchdog self._watchdog = Watchdog() return self._watchdog ############################################################## ###################### Device methods ######################## ############################################################## def get_name(self): """ Retrieves the name of the device Returns: string: The name of the device """ return self._api_helper.hwsku def get_presence(self): """ Retrieves the presence of the PSU Returns: bool: True if PSU is present, False if not """ return True def get_model(self): """ Retrieves the model number (or part number) of the device Returns: string: Model/part number of device """ return self._eeprom.get_pn() def get_serial(self): """ Retrieves the serial number of the device Returns: string: Serial number of device """ return self.get_serial_number() def get_status(self): """ Retrieves the operational status of the device Returns: A boolean value, True if device is operating properly, False if not """ return True
class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): ChassisBase.__init__(self) self._api_helper = APIHelper() self.is_host = self._api_helper.is_host() self.config_data = {} self.__initialize_fan() self.__initialize_psu() self.__initialize_thermals() self.__initialize_components() self.__initialize_sfp() self.__initialize_eeprom() def __initialize_sfp(self): from sonic_platform.sfp import Sfp for index in range(0, PORT_END): sfp = Sfp(index) self._sfp_list.append(sfp) self._sfpevent = SfpEvent(self._sfp_list) self.sfp_module_initialized = True def __initialize_fan(self): from sonic_platform.fan_drawer import FanDrawer for fant_index in range(NUM_FAN_TRAY): fandrawer = FanDrawer(fant_index) self._fan_drawer_list.append(fandrawer) self._fan_list.extend(fandrawer._fan_list) def __initialize_psu(self): from sonic_platform.psu import Psu for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) def __initialize_thermals(self): from sonic_platform.thermal import Thermal for index in range(0, NUM_THERMAL): thermal = Thermal(index) self._thermal_list.append(thermal) def __initialize_eeprom(self): from sonic_platform.eeprom import Tlv self._eeprom = Tlv() def __initialize_components(self): from sonic_platform.component import Component for index in range(0, NUM_COMPONENT): component = Component(index) self._component_list.append(component) def __initialize_watchdog(self): from sonic_platform.watchdog import Watchdog self._watchdog = Watchdog() def __is_host(self): return os.system(HOST_CHK_CMD) == 0 def __read_txt_file(self, file_path): try: with open(file_path, 'r') as fd: data = fd.read() return data.strip() except IOError: pass return None def get_name(self): """ Retrieves the name of the device Returns: string: The name of the device """ return self._eeprom.get_product_name() def get_presence(self): """ Retrieves the presence of the Chassis Returns: bool: True if Chassis is present, False if not """ return True def get_status(self): """ Retrieves the operational status of the device Returns: A boolean value, True if device is operating properly, False if not """ return True 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_mac() def get_model(self): """ Retrieves the model number (or part number) of the device Returns: string: Model/part number of device """ return self._eeprom.get_pn() 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() 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_eeprom() 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 = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) sw_reboot_cause = self._api_helper.read_txt_file( reboot_cause_path) or "Unknown" return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause) def get_change_event(self, timeout=0): # SFP event if not self.sfp_module_initialized: self.__initialize_sfp() return self._sfpevent.get_sfp_event(timeout) 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: sys.stderr.write("SFP index {} out of range (1-{})\n".format( index, len(self._sfp_list))) return sfp def get_position_in_parent(self): """ Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned 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 def initizalize_system_led(self): return True def get_status_led(self): val = self._api_helper.read_txt_file(SYSLED_FNODE) return SYSLED_MODES[val] if val in SYSLED_MODES else "UNKNOWN" def set_status_led(self, color): mode = None for key, val in SYSLED_MODES.items(): if val == color: mode = key break if mode is None: return False else: return self._api_helper.write_txt_file(SYSLED_FNODE, mode)
class Chassis(ChassisBase): """Platform-specific Chassis class""" CHASSIS_CONFIG = 'chassis.json' THERMAL_CONFIG = 'thermal.json' SFP_CONFIG = 'sfp.json' PSU_CONFIG = 'psu.json' FAN_CONFIG = 'fan.json' COMPONENT_CONFIG = 'component.json' def __init__(self): ChassisBase.__init__(self) self._api_common = Common() config_path = self._api_common.get_config_path(self.CHASSIS_CONFIG) self._config = self._api_common.load_json_file(config_path) self.sfp_module_initialized = False self.__initialize_eeprom() if not self._api_common.is_host(): self.__initialize_fan() self.__initialize_psu() self.__initialize_thermals() else: self.__initialize_components() def __initialize_fan(self): from sonic_platform.fan import Fan from sonic_platform.fan_drawer import FanDrawer fan_config_path = self._api_common.get_config_path(self.FAN_CONFIG) self._fan_config = self._api_common.load_json_file(fan_config_path) if self._fan_config: fan_index = 0 for drawer_index in range(0, self._fan_config['drawer_num']): drawer_fan_list = [] for index in range(0, self._fan_config['fan_num_per_drawer']): fan = Fan(fan_index, conf=self._fan_config) fan_index += 1 self._fan_list.append(fan) drawer_fan_list.append(fan) fan_drawer = FanDrawer(drawer_index, drawer_fan_list) self._fan_drawer_list.append(fan_drawer) def __initialize_sfp(self): from sonic_platform.sfp import Sfp sfp_config_path = self._api_common.get_config_path(self.SFP_CONFIG) sfp_config = self._api_common.load_json_file(sfp_config_path) sfp_index = 0 for index in range(0, sfp_config['port_num']): sfp = Sfp(sfp_index, conf=sfp_config) self._sfp_list.append(sfp) sfp_index += 1 self.sfp_module_initialized = True def __initialize_psu(self): from sonic_platform.psu import Psu psu_config_path = self._api_common.get_config_path(self.PSU_CONFIG) psu_config = self._api_common.load_json_file(psu_config_path) if psu_config: psu_index = 0 for index in range(0, psu_config['psu_num']): psu = Psu(psu_index, conf=psu_config, fan_conf=self._fan_config) psu_index += 1 self._psu_list.append(psu) def __initialize_thermals(self): from sonic_platform.thermal import Thermal thermal_config_path = self._api_common.get_config_path( self.THERMAL_CONFIG) thermal_config = self._api_common.load_json_file(thermal_config_path) thermal_index = 0 for index in range(0, thermal_config['thermal_num']): thermal = Thermal(thermal_index, conf=thermal_config) thermal_index += 1 self._thermal_list.append(thermal) def __initialize_eeprom(self): from sonic_platform.eeprom import Tlv self._eeprom = Tlv(self._config) def __initialize_components(self): from component import Component component_config_path = self._api_common.get_config_path( self.COMPONENT_CONFIG) component_config = self._api_common.load_json_file( component_config_path) for index in range(0, component_config['component_num']): component = Component(index, conf=component_config) self._component_list.append(component) 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_mac() 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_eeprom() 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. Avaliable reboot cause: REBOOT_CAUSE_POWER_LOSS = "Power Loss" REBOOT_CAUSE_THERMAL_OVERLOAD_CPU = "Thermal Overload: CPU" REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC = "Thermal Overload: ASIC" REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER = "Thermal Overload: Other" REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED = "Insufficient Fan Speed" REBOOT_CAUSE_WATCHDOG = "Watchdog" REBOOT_CAUSE_HARDWARE_OTHER = "Hardware - Other" REBOOT_CAUSE_NON_HARDWARE = "Non-Hardware" """ reboot_cause = self._api_common.get_output( 0, self._config['get_reboot_cause'], self.REBOOT_CAUSE_HARDWARE_OTHER) description = self._api_common.get_output( 0, self._config['get_reboot_description'], 'Unknown') return (reboot_cause, description) # ############################################################## # ######################## SFP methods ######################### # ############################################################## 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: sys.stderr.write("SFP index {} out of range (1-{})\n".format( index, len(self._sfp_list))) return sfp ############################################################## ###################### Event methods ######################### ############################################################## 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. """ if not self.sfp_module_initialized: self.__initialize_sfp() return self._api_common.get_event(timeout, self._config['get_change_event'], self._sfp_list) # ############################################################## # ###################### Other methods ######################## # ############################################################## def get_watchdog(self): """ Retreives hardware watchdog device on this chassis Returns: An object derived from WatchdogBase representing the hardware watchdog device """ if self._watchdog is None: wdt = self._api_common.get_output(0, self._config['get_watchdog'], None) self._watchdog = wdt() return self._watchdog # ############################################################## # ###################### Device methods ######################## # ############################################################## def get_name(self): """ Retrieves the name of the device Returns: string: The name of the device """ return self._api_common.hwsku def get_presence(self): """ Retrieves the presence of the PSU Returns: bool: True if PSU is present, False if not """ return True def get_model(self): """ Retrieves the model number (or part number) of the device Returns: string: Model/part number of device """ return self._eeprom.get_pn() def get_serial(self): """ Retrieves the serial number of the device Returns: string: Serial number of device """ return self._eeprom.get_serial() def get_status(self): """ Retrieves the operational status of the device Returns: A boolean value, True if device is operating properly, False if not """ return True
class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): super(Chassis, self).__init__() for fan_index in range(0, NUM_FAN): fan = Fan(fan_index) self._fan_list.append(fan) for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) for index in range(0, NUM_THERMAL): thermal = Thermal(index) self._thermal_list.append(thermal) for index in range(0, NUM_SFP): sfp_module = Sfp(index, 'QSFP-DD') self._sfp_list.append(sfp_module) self._component_name_list = COMPONENT_NAME_LIST self._eeprom = Tlv() self._transceiver_presence = self._get_sfp_presence() def __is_host(self): return os.system(HOST_CHK_CMD) == 0 def __read_txt_file(self, file_path): try: with open(file_path, 'r') as fd: data = fd.read() return data.strip() except IOError: pass return None 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_mac() 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() 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_eeprom() def get_firmware_version(self, component_name): """ Retrieves platform-specific hardware/firmware versions for chassis componenets such as BIOS, CPLD, FPGA, etc. Args: type: A string, component name Returns: A string containing platform-specific component versions """ self.component = Component(component_name) if component_name not in self._component_name_list: return None return self.component.get_firmware_version() def install_component_firmware(self, component_name, image_path): """ Install firmware to module Args: type: A string, component name. image_path: A string, path to firmware image. Returns: A boolean, True if install successfully, False if not """ self.component = Component(component_name) if component_name not in self._component_name_list: return False return self.component.upgrade_firmware(image_path) 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. """ description = 'None' reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER reboot_cause_path = ( HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE ) if self.__is_host() else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE prev_reboot_cause_path = ( HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) if self.__is_host( ) else PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE sw_reboot_cause = self.__read_txt_file(reboot_cause_path) or "Unknown" prev_sw_reboot_cause = self.__read_txt_file( prev_reboot_cause_path) or "Unknown" if sw_reboot_cause != "Unknown": reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = sw_reboot_cause else: reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER description = 'Unknown reason' return (reboot_cause, description) def is_modular_chassis(self): """ Retrieves whether the sonic instance is part of modular chassis Returns: A bool value, should return False by default or for fixed-platforms. Should return True for supervisor-cards, line-cards etc running as part of modular-chassis. """ return False def get_sfp(self, index): sfp = None try: sfp = self._sfp_list[index] except IndexError: sys.stderr.write("SFP index {} out of range (0-{})\n".format( index, len(self._sfp_list) - 1)) return sfp def _get_sfp_presence(self): port_pres = {} for port in range(0, NUM_SFP): sfp = self._sfp_list[port] port_pres[port] = sfp.get_presence() return port_pres def get_change_event(self, timeout=0): port_dict = {} ret_dict = {'sfp': port_dict} forever = False change_event = False if timeout == 0: forever = True elif timeout > 0: timeout = timeout / float(1000) else: return False, ret_dict #Incorrect timeout while True: if forever: timer = 1 else: timer = min(timeout, 1) start_time = time.time() time.sleep(timer) cur_presence = self._get_sfp_presence() for port in range(0, NUM_SFP): if cur_presence[port] == 1: port_dict[port] = '1' else: port_dict[port] = '0' if cur_presence[port] != self._transceiver_presence[port]: change_event = True self._transceiver_presence = cur_presence if change_event == True: break if not forever: elapsed_time = time.time() - start_time timeout = round(timeout - elapsed_time, 3) if timeout <= 0: break for port in range(0, NUM_SFP): sfp = self._sfp_list[port] sfp.reinit() return True, ret_dict
class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): ChassisBase.__init__(self) self._api_helper = APIHelper() self.sfp_module_initialized = False self.__initialize_eeprom() self.is_host = self._api_helper.is_host() if not self.is_host: self.__initialize_fan() self.__initialize_psu() self.__initialize_thermals() else: self.__initialize_components() def __initialize_sfp(self): sfputil_helper = SfpUtilHelper() port_config_file_path = device_info.get_path_to_port_config_file() sfputil_helper.read_porttab_mappings(port_config_file_path, 0) from sonic_platform.sfp import Sfp for index in range(0, NUM_SFP): name_idx = 0 if index + 1 == NUM_SFP else index + 1 sfp = Sfp(index, sfputil_helper.logical[name_idx]) self._sfp_list.append(sfp) self.sfp_module_initialized = True def __initialize_psu(self): from sonic_platform.psu import Psu for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) def __initialize_fan(self): from sonic_platform.fan import Fan for fant_index in range(0, NUM_FAN_TRAY): for fan_index in range(0, NUM_FAN): fan = Fan(fant_index, fan_index) self._fan_list.append(fan) def __initialize_thermals(self): from sonic_platform.thermal import Thermal airflow = self.__get_air_flow() for index in range(0, NUM_THERMAL): thermal = Thermal(index, airflow) self._thermal_list.append(thermal) def __initialize_eeprom(self): from sonic_platform.eeprom import Tlv self._eeprom = Tlv() def __initialize_components(self): from sonic_platform.component import Component for index in range(0, NUM_COMPONENT): component = Component(index) self._component_list.append(component) def __get_air_flow(self): air_flow_path = '/usr/share/sonic/device/{}/fan_airflow'.format( self._api_helper.platform ) if self.is_host else '/usr/share/sonic/platform/fan_airflow' air_flow = self._api_helper.read_one_line_file(air_flow_path) return air_flow or 'B2F' 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_mac() 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_eeprom() 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_POWER_LOSS = "Power Loss" REBOOT_CAUSE_THERMAL_OVERLOAD_CPU = "Thermal Overload: CPU" REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC = "Thermal Overload: ASIC" REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER = "Thermal Overload: Other" REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED = "Insufficient Fan Speed" REBOOT_CAUSE_WATCHDOG = "Watchdog" REBOOT_CAUSE_HARDWARE_OTHER = "Hardware - Other" REBOOT_CAUSE_NON_HARDWARE = "Non-Hardware" """ reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) sw_reboot_cause = self._api_helper.read_txt_file( reboot_cause_path) or "Unknown" hw_reboot_cause = self._api_helper.get_cpld_reg_value( GETREG_PATH, RESET_REGISTER) prev_reboot_cause = { '0x11': (self.REBOOT_CAUSE_POWER_LOSS, 'Power on reset'), '0x22': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'CPLD_WD_RESET'), '0x33': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by CPU'), '0x44': (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Power cycle reset triggered by reset button'), '0x55': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, ''), '0x66': (self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC, ''), '0x77': (self.REBOOT_CAUSE_WATCHDOG, '') }.get(hw_reboot_cause, (self.REBOOT_CAUSE_HARDWARE_OTHER, 'Unknown reason')) if sw_reboot_cause != 'Unknown' and hw_reboot_cause == '0x11': prev_reboot_cause = (self.REBOOT_CAUSE_NON_HARDWARE, sw_reboot_cause) return prev_reboot_cause 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. """ # SFP event if not self.sfp_module_initialized: self.__initialize_sfp() sfp_event = SfpEvent(self._sfp_list).get_sfp_event(timeout) if sfp_event: return True, {'sfp': sfp_event} return False, {'sfp': {}} ############################################################## ######################## SFP methods ######################### ############################################################## 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: sys.stderr.write("SFP index {} out of range (1-{})\n".format( index, len(self._sfp_list))) return sfp ############################################################## ####################### Other methods ######################## ############################################################## def get_watchdog(self): """ Retreives hardware watchdog device on this chassis Returns: An object derived from WatchdogBase representing the hardware watchdog device """ if self._watchdog is None: from sonic_platform.watchdog import Watchdog self._watchdog = Watchdog() return self._watchdog ############################################################## ###################### Device methods ######################## ############################################################## def get_name(self): """ Retrieves the name of the device Returns: string: The name of the device """ return self._api_helper.hwsku def get_presence(self): """ Retrieves the presence of the Chassis Returns: bool: True if Chassis is present, False if not """ return True def get_model(self): """ Retrieves the model number (or part number) of the device Returns: string: Model/part number of device """ return self._eeprom.get_pn() def get_serial(self): """ Retrieves the serial number of the device Returns: string: Serial number of device """ return self._eeprom.get_serial() def get_status(self): """ Retrieves the operational status of the device Returns: A boolean value, True if device is operating properly, False if not """ return True def get_thermal_manager(self): from .thermal_manager import ThermalManager return ThermalManager
class Chassis(ChassisBase): """Platform-specific Chassis class""" def __init__(self): super(Chassis, self).__init__() # Initialize SKU name and Platform name self.sku_name = self._get_sku_name() self.platform_name = self._get_platform_name() self.name = self.sku_name self._transceiver_presence = [0] * NUM_SFP self.__initialize_fan() self.__initialize_psu() self.__initialize_thermals() self.__initialize_sfp() self.__initialize_eeprom() def __initialize_sfp(self): from sonic_platform.sfp import Sfp for index in range(0, NUM_SFP): sfp_module = Sfp(index, 'QSFP_DD') self._sfp_list.append(sfp_module) def __initialize_fan(self): from sonic_platform.fan import Fan for fan_index in range(0, NUM_FAN): fan = Fan(fan_index) self._fan_list.append(fan) def __initialize_psu(self): from sonic_platform.psu import Psu for index in range(0, NUM_PSU): psu = Psu(index) self._psu_list.append(psu) def __initialize_thermals(self): from sonic_platform.thermal import Thermal for index in range(0, NUM_THERMAL): thermal = Thermal(index) self._thermal_list.append(thermal) def __initialize_eeprom(self): from sonic_platform.eeprom import Tlv self._eeprom = Tlv() def __is_host(self): return os.system(HOST_CHK_CMD) == 0 def __read_txt_file(self, file_path): try: with open(file_path, 'r') as fd: data = fd.read() return data.strip() except IOError: pass return None 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_mac() 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() 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_eeprom() 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 = ( HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE ) if self.__is_host() else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE sw_reboot_cause = self.__read_txt_file(reboot_cause_path) or "Unknown" if sw_reboot_cause != "Unknown": reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE description = sw_reboot_cause else: reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER description = 'Unknown reason' return (reboot_cause, description) def _get_sku_name(self): p = subprocess.Popen(GET_HWSKU_CMD, shell=True, stdout=subprocess.PIPE) out, err = p.communicate() return out.decode().rstrip('\n') def _get_platform_name(self): p = subprocess.Popen(GET_PLATFORM_CMD, shell=True, stdout=subprocess.PIPE) out, err = p.communicate() return out.decode().rstrip('\n') def get_name(self): """ Retrieves the name of the device Returns: string: The name of the device """ return self.name def get_sfp(self, index): sfp = None try: sfp = self._sfp_list[index] except IndexError: sys.stderr.write("SFP index {} out of range (0-{})\n".format( index, len(self._sfp_list) - 1)) return sfp def _get_sfp_presence(self): port_pres = {} for port in range(0, NUM_SFP): sfp = self._sfp_list[port] port_pres[port] = sfp.get_presence() return port_pres def get_change_event(self, timeout=0): port_dict = {} ret_dict = {'sfp': port_dict} forever = False change_event = False if timeout == 0: forever = True elif timeout > 0: timeout = timeout / float(1000) else: return False, ret_dict #Incorrect timeout while True: if forever: timer = 1 else: timer = min(timeout, 1) start_time = time.time() time.sleep(timer) cur_presence = self._get_sfp_presence() for port in range(0, NUM_SFP): if cur_presence[port] != self._transceiver_presence[port]: change_event = True if cur_presence[port] == 1: port_dict[port] = '1' else: port_dict[port] = '0' self._transceiver_presence = cur_presence if change_event == True: break if not forever: elapsed_time = time.time() - start_time timeout = round(timeout - elapsed_time, 3) if timeout <= 0: break for port in range(0, NUM_SFP): sfp = self._sfp_list[port] sfp.reinit() return True, ret_dict