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 Watchdog(WatchdogBase): def __init__(self): # Init helper self._api_helper = APIHelper() # Init cpld reg path self.setreg_path = os.path.join(PLATFORM_CPLD_PATH, SETREG_FILE) self.getreg_path = os.path.join(PLATFORM_CPLD_PATH, GETREG_FILE) # Set default value self._disable() self.armed = False self.timeout = self._gettimeout() def _enable(self): """ Turn on the watchdog timer """ # echo 0x141 0x1 > /sys/devices/platform/dx010_cpld/setreg enable_val = '{} {}'.format(WDT_ENABLE_REG, ENABLE_CMD) return self._api_helper.write_txt_file(self.setreg_path, enable_val) def _disable(self): """ Turn off the watchdog timer """ # echo 0x141 0x0 > /sys/devices/platform/dx010_cpld/setreg disable_val = '{} {}'.format(WDT_ENABLE_REG, DISABLE_CMD) return self._api_helper.write_txt_file(self.setreg_path, disable_val) def _keepalive(self): """ Keep alive watchdog timer """ # echo 0x145 0x1 > /sys/devices/platform/dx010_cpld/setreg enable_val = '{} {}'.format(WDT_KEEP_ALVIVE_REG, ENABLE_CMD) return self._api_helper.write_txt_file(self.setreg_path, enable_val) def _get_level_hex(self, sub_hex): sub_hex_str = sub_hex.replace("x", "0") return hex(int(sub_hex_str, 16)) def _seconds_to_lmh_hex(self, seconds): ms = seconds*1000 # calculate timeout in ms format hex_str = hex(ms) l = self._get_level_hex(hex_str[-2:]) m = self._get_level_hex(hex_str[-4:-2]) h = self._get_level_hex(hex_str[-6:-4]) return (l, m, h) def _settimeout(self, seconds): """ Set watchdog timer timeout @param seconds - timeout in seconds @return is the actual set timeout """ # max = 0xffffff = 16777.215 seconds (l, m, h) = self._seconds_to_lmh_hex(seconds) set_h_val = '{} {}'.format(WDT_TIMER_H_BIT_REG, h) set_m_val = '{} {}'.format(WDT_TIMER_M_BIT_REG, m) set_l_val = '{} {}'.format(WDT_TIMER_L_BIT_REG, l) self._api_helper.write_txt_file(self.setreg_path, set_h_val) self._api_helper.write_txt_file(self.setreg_path, set_m_val) self._api_helper.write_txt_file(self.setreg_path, set_l_val) return seconds def _gettimeout(self): """ Get watchdog timeout @return watchdog timeout """ h_bit = self._api_helper.get_cpld_reg_value( self.getreg_path, WDT_TIMER_H_BIT_REG) m_bit = self._api_helper.get_cpld_reg_value( self.getreg_path, WDT_TIMER_M_BIT_REG) l_bit = self._api_helper.get_cpld_reg_value( self.getreg_path, WDT_TIMER_L_BIT_REG) hex_time = '0x{}{}{}'.format(h_bit[2:], m_bit[2:], l_bit[2:]) ms = int(hex_time, 16) return int(float(ms)/1000) ################################################################# def arm(self, seconds): """ Arm the hardware watchdog with a timeout of <seconds> seconds. If the watchdog is currently armed, calling this function will simply reset the timer to the provided value. If the underlying hardware does not support the value provided in <seconds>, this method should arm the watchdog with the *next greater* available value. Returns: An integer specifying the *actual* number of seconds the watchdog was armed with. On failure returns -1. """ ret = WDT_COMMON_ERROR if seconds < 0: return ret if seconds > 16778: return ret try: if self.timeout != seconds: self.timeout = self._settimeout(seconds) if self.armed: self._keepalive() else: self._enable() self.armed = True ret = self.timeout self.arm_timestamp = time.time() except IOError as e: pass return ret def disarm(self): """ Disarm the hardware watchdog Returns: A boolean, True if watchdog is disarmed successfully, False if not """ disarmed = False if self.is_armed(): try: self._disable() self.armed = False disarmed = True except IOError: pass return disarmed def is_armed(self): """ Retrieves the armed state of the hardware watchdog. Returns: A boolean, True if watchdog is armed, False if not """ return self.armed def get_remaining_time(self): """ If the watchdog is armed, retrieve the number of seconds remaining on the watchdog timer Returns: An integer specifying the number of seconds remaining on thei watchdog timer. If the watchdog is not armed, returns -1. """ return int(self.timeout - (time.time() - self.arm_timestamp)) if self.armed else WDT_COMMON_ERROR