Exemplo n.º 1
0
class Chassis(ChassisBase):
    """Platform-specific Chassis class"""

    # System status LED
    _led = None

    def __init__(self):
        super(Chassis, self).__init__()

        self.name = "Undefined"
        self.model = "Undefined"

        # Initialize Platform name
        self.platform_name = device_info.get_platform()

        # move the initialization of each components to their dedicated initializer
        # which will be called from platform
        self.sfp_module_initialized = False
        self.sfp_event_initialized = False
        self.reboot_cause_initialized = False
        logger.log_info("Chassis loaded successfully")

    def __del__(self):
        if self.sfp_event_initialized:
            self.sfp_event.deinitialize()

        if self.sfp_module_initialized:
            from sonic_platform.sfp import deinitialize_sdk_handle
            deinitialize_sdk_handle(self.sdk_handle)

    def initialize_psu(self):
        from sonic_platform.psu import Psu
        # Initialize PSU list
        self.psu_module = Psu
        for index in range(MLNX_NUM_PSU):
            psu = Psu(index, self.platform_name)
            self._psu_list.append(psu)

    def initialize_fan(self):
        from .device_data import DEVICE_DATA
        from sonic_platform.fan import Fan
        from .fan_drawer import RealDrawer, VirtualDrawer

        fan_data = DEVICE_DATA[self.platform_name]['fans']
        drawer_num = fan_data['drawer_num']
        drawer_type = fan_data['drawer_type']
        fan_num_per_drawer = fan_data['fan_num_per_drawer']
        drawer_ctor = RealDrawer if drawer_type == 'real' else VirtualDrawer
        fan_index = 0
        for drawer_index in range(drawer_num):
            drawer = drawer_ctor(drawer_index, fan_data)
            self._fan_drawer_list.append(drawer)
            for index in range(fan_num_per_drawer):
                fan = Fan(fan_index, drawer, index + 1)
                fan_index += 1
                drawer._fan_list.append(fan)
                self._fan_list.append(fan)

    def initialize_sfp(self):
        from sonic_platform.sfp import SFP
        from sonic_platform.sfp import initialize_sdk_handle

        self.sfp_module = SFP
        self.sdk_handle = initialize_sdk_handle()

        if self.sdk_handle is None:
            self.sfp_module_initialized = False
            return

        # Initialize SFP list
        port_position_tuple = self._get_port_position_tuple_by_platform_name()
        self.PORT_START = port_position_tuple[0]
        self.QSFP_PORT_START = port_position_tuple[1]
        self.PORT_END = port_position_tuple[2]
        self.PORTS_IN_BLOCK = port_position_tuple[3]

        for index in range(self.PORT_START, self.PORT_END + 1):
            if index in range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1):
                sfp_module = SFP(index, 'QSFP', self.sdk_handle,
                                 self.platform_name)
            else:
                sfp_module = SFP(index, 'SFP', self.sdk_handle,
                                 self.platform_name)

            self._sfp_list.append(sfp_module)

        self.sfp_module_initialized = True

    def initialize_thermals(self):
        from sonic_platform.thermal import initialize_chassis_thermals
        # Initialize thermals
        initialize_chassis_thermals(self.platform_name, self._thermal_list)

    def initialize_eeprom(self):
        from eeprom import Eeprom
        # Initialize EEPROM
        self._eeprom = Eeprom()
        # Get chassis name and model from eeprom
        self.name = self._eeprom.get_product_name()
        self.model = self._eeprom.get_part_number()

    def initialize_components(self):
        # Initialize component list
        from sonic_platform.component import ComponentONIE, ComponentSSD, ComponentBIOS, ComponentCPLD
        self._component_list.append(ComponentONIE())
        self._component_list.append(ComponentSSD())
        self._component_list.append(ComponentBIOS())
        self._component_list.extend(ComponentCPLD.get_component_list())

    def initizalize_system_led(self):
        from .led import SystemLed
        Chassis._led = SystemLed()

    def get_name(self):
        """
        Retrieves the name of the device

        Returns:
            string: The name of the device
        """
        return self.name

    def get_model(self):
        """
        Retrieves the model number (or part number) of the device

        Returns:
            string: Model/part number of device
        """
        return self.model

    ##############################################
    # 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
        """
        if not self.sfp_module_initialized:
            self.initialize_sfp()

        sfp = None
        index -= 1
        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 _extract_num_of_fans_and_fan_drawers(self):
        num_of_fan = 0
        num_of_drawer = 0
        for f in listdir(self.fan_path):
            if isfile(join(self.fan_path, f)):
                match_obj = re.match('fan(\d+)_speed_get', f)
                if match_obj != None:
                    if int(match_obj.group(1)) > num_of_fan:
                        num_of_fan = int(match_obj.group(1))
                else:
                    match_obj = re.match('fan(\d+)_status', f)
                    if match_obj != None and int(
                            match_obj.group(1)) > num_of_drawer:
                        num_of_drawer = int(match_obj.group(1))

        return num_of_fan, num_of_drawer

    def _get_port_position_tuple_by_platform_name(self):
        position_tuple = port_position_tuple_list[platform_dict_port[
            self.platform_name]]
        return position_tuple

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

        Returns:
            An object derived from WatchdogBase representing the hardware
            watchdog device

        Note:
            We overload this method to ensure that watchdog is only initialized
            when it is referenced. Currently, only one daemon can open the watchdog.
            To initialize watchdog in the constructor causes multiple daemon 
            try opening watchdog when loading and constructing a chassis object
            and fail. By doing so we can eliminate that risk.
        """
        try:
            if self._watchdog is None:
                from sonic_platform.watchdog import get_watchdog
                self._watchdog = get_watchdog()
        except Exception as e:
            logger.log_info("Fail to load watchdog due to {}".format(repr(e)))

        return self._watchdog

    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_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 _read_generic_file(self, filename, len):
        """
        Read a generic file, returns the contents of the file
        """
        result = ''
        try:
            fileobj = io.open(filename)
            result = fileobj.read(len)
            fileobj.close()
            return result
        except Exception as e:
            logger.log_info("Fail to read file {} due to {}".format(
                filename, repr(e)))
            return '0'

    def _verify_reboot_cause(self, filename):
        '''
        Open and read the reboot cause file in 
        /var/run/hwmanagement/system (which is defined as REBOOT_CAUSE_ROOT)
        If a reboot cause file doesn't exists, returns '0'.
        '''
        return bool(
            int(
                self._read_generic_file(
                    join(REBOOT_CAUSE_ROOT,
                         filename), REBOOT_CAUSE_FILE_LENGTH).rstrip('\n')))

    def initialize_reboot_cause(self):
        self.reboot_major_cause_dict = {
            'reset_main_pwr_fail': self.REBOOT_CAUSE_POWER_LOSS,
            'reset_aux_pwr_or_ref': self.REBOOT_CAUSE_POWER_LOSS,
            'reset_asic_thermal': self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC,
            'reset_hotswap_or_wd': self.REBOOT_CAUSE_WATCHDOG,
            'reset_swb_wd': self.REBOOT_CAUSE_WATCHDOG,
            'reset_sff_wd': self.REBOOT_CAUSE_WATCHDOG
        }
        self.reboot_minor_cause_dict = {
            'reset_fw_reset':
            "Reset by ASIC firmware",
            'reset_long_pb':
            "Reset by long press on power button",
            'reset_short_pb':
            "Reset by short press on power button",
            'reset_comex_thermal':
            "ComEx thermal shutdown",
            'reset_comex_pwr_fail':
            "ComEx power fail",
            'reset_comex_wd':
            "Reset requested from ComEx",
            'reset_from_asic':
            "Reset requested from ASIC",
            'reset_reload_bios':
            "Reset caused by BIOS reload",
            'reset_hotswap_or_halt':
            "Reset caused by hotswap or halt",
            'reset_from_comex':
            "Reset from ComEx",
            'reset_voltmon_upgrade_fail':
            "Reset due to voltage monitor devices upgrade failure"
        }
        self.reboot_by_software = 'reset_sw_reset'
        self.reboot_cause_initialized = True

    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.
        """
        #read reboot causes files in the following order
        if not self.reboot_cause_initialized:
            self.initialize_reboot_cause()

        for reset_file, reset_cause in self.reboot_major_cause_dict.iteritems(
        ):
            if self._verify_reboot_cause(reset_file):
                return reset_cause, ''

        for reset_file, reset_cause in self.reboot_minor_cause_dict.iteritems(
        ):
            if self._verify_reboot_cause(reset_file):
                return self.REBOOT_CAUSE_HARDWARE_OTHER, reset_cause

        if self._verify_reboot_cause(self.reboot_by_software):
            logger.log_info(
                "Hardware reboot cause: the system was rebooted due to software requesting"
            )
        else:
            logger.log_info(
                "Hardware reboot cause: no hardware reboot cause found")

        return self.REBOOT_CAUSE_NON_HARDWARE, ''

    def _show_capabilities(self):
        """
        This function is for debug purpose
        Some features require a xSFP module to support some capabilities but it's unrealistic to
        check those modules one by one.
        So this function is introduce to show some capabilities of all xSFP modules mounted on the device.
        """
        for s in self._sfp_list:
            try:
                print "index {} tx disable {} dom {} calibration {} temp {} volt {} power (tx {} rx {})".format(
                    s.index, s.dom_tx_disable_supported, s.dom_supported,
                    s.calibration, s.dom_temp_supported, s.dom_volt_supported,
                    s.dom_rx_power_supported, s.dom_tx_power_supported)
            except:
                print "fail to retrieve capabilities for module index {}".format(
                    s.index)

    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.
        """
        # Initialize SFP event first
        if not self.sfp_event_initialized:
            from sonic_platform.sfp_event import sfp_event
            self.sfp_event = sfp_event()
            self.sfp_event.initialize()
            self.MAX_SELECT_EVENT_RETURNED = self.PORT_END
            self.sfp_event_initialized = True

        wait_for_ever = (timeout == 0)
        port_dict = {}
        if wait_for_ever:
            timeout = MAX_SELECT_DELAY
            while True:
                status = self.sfp_event.check_sfp_status(port_dict, timeout)
                if bool(port_dict):
                    break
        else:
            status = self.sfp_event.check_sfp_status(port_dict, timeout)

        if status:
            self.reinit_sfps(port_dict)
            return True, {'sfp': port_dict}
        else:
            return True, {'sfp': {}}

    def reinit_sfps(self, port_dict):
        """
        Re-initialize SFP if there is any newly inserted SFPs
        :param port_dict: SFP event data
        :return:
        """
        # SFP not initialize yet, do nothing
        if not self.sfp_module_initialized:
            return

        from . import sfp
        for index, status in port_dict.items():
            if status == sfp.SFP_STATUS_INSERTED:
                try:
                    self.get_sfp(index).reinit()
                except Exception as e:
                    logger.log_error(
                        "Fail to re-initialize SFP {} - {}".format(
                            index, repr(e)))

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

    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
        """
        return False if not Chassis._led else Chassis._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.
        """
        return None if not Chassis._led else Chassis._led.get_status()

    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
Exemplo n.º 2
0
 def _eeprom(self):
     if self.__eeprom is None:
         self.__eeprom = Eeprom()
     return self.__eeprom
class Chassis(ChassisBase):
    """Platform-specific Chassis class"""

    def __init__(self):
        super(Chassis, self).__init__()

        # Initialize SKU name
        self.sku_name = self._get_sku_name()

        # move the initialization of each components to their dedicated initializer
        # which will be called from platform
        self.sfp_module_initialized = False
        self.sfp_event_initialized = False
        self.reboot_cause_initialized = False
        logger.log_info("Chassis loaded successfully")

    def __del__(self):
        if self.sfp_event_initialized:
            self.sfp_event.deinitialize()

    def initialize_psu(self):
        from sonic_platform.psu import Psu
        # Initialize PSU list
        self.psu_module = Psu
        for index in range(MLNX_NUM_PSU):
            psu = Psu(index, self.sku_name)
            self._psu_list.append(psu)

    def initialize_fan(self):
        from sonic_platform.fan import Fan
        from sonic_platform.fan import FAN_PATH
        self.fan_module = Fan
        self.fan_path = FAN_PATH
        # Initialize FAN list
        multi_rotor_in_drawer = False
        num_of_fan, num_of_drawer = self._extract_num_of_fans_and_fan_drawers()
        multi_rotor_in_drawer = num_of_fan > num_of_drawer

        for index in range(num_of_fan):
            if multi_rotor_in_drawer:
                fan = Fan(index, index/2)
            else:
                fan = Fan(index, index)
            self._fan_list.append(fan)

    def initialize_sfp(self):
        from sonic_platform.sfp import SFP

        self.sfp_module = SFP

        # Initialize SFP list
        port_position_tuple = self._get_port_position_tuple_by_sku_name()
        self.PORT_START = port_position_tuple[0]
        self.QSFP_PORT_START = port_position_tuple[1]
        self.PORT_END = port_position_tuple[2]
        self.PORTS_IN_BLOCK = port_position_tuple[3]

        for index in range(self.PORT_START, self.PORT_END + 1):
            if index in range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 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_thermals(self):
        from sonic_platform.thermal import initialize_thermals
        # Initialize thermals
        initialize_thermals(self.sku_name, self._thermal_list, self._psu_list)

    def initialize_eeprom(self):
        from eeprom import Eeprom
        # Initialize EEPROM
        self._eeprom = Eeprom()

    def initialize_components_list(self):
        # Initialize component list
        self._component_name_list.append(COMPONENT_BIOS)
        self._component_name_list.append(COMPONENT_FIRMWARE)
        self._component_name_list.append(COMPONENT_CPLD1)
        self._component_name_list.append(COMPONENT_CPLD2)

    ##############################################
    # 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 (0-based) index <index>

        Args:
            index: An integer, the index (0-based) of the sfp to retrieve.
                   The index should be the sequence of a physical port in a chassis,
                   starting from 0.
                   For example, 0 for Ethernet0, 1 for Ethernet4 and so on.

        Returns:
            An object dervied from SfpBase representing the specified sfp
        """
        if not self.sfp_module_initialized:
            self.initialize_sfp()

        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 _extract_num_of_fans_and_fan_drawers(self):
        num_of_fan = 0
        num_of_drawer = 0
        for f in listdir(self.fan_path):
            if isfile(join(self.fan_path, f)):
                match_obj = re.match('fan(\d+)_speed_get', f)
                if match_obj != None:
                    if int(match_obj.group(1)) > num_of_fan:
                        num_of_fan = int(match_obj.group(1))
                else:
                    match_obj = re.match('fan(\d+)_status', f)
                    if match_obj != None and int(match_obj.group(1)) > num_of_drawer:
                        num_of_drawer = int(match_obj.group(1))

        return num_of_fan, num_of_drawer

    def _get_sku_name(self):
        p = subprocess.Popen(GET_HWSKU_CMD, shell=True, stdout=subprocess.PIPE)
        out, err = p.communicate()
        return out.rstrip('\n')

    def _get_port_position_tuple_by_sku_name(self):
        position_tuple = port_position_tuple_list[hwsku_dict_port[self.sku_name]]
        return position_tuple

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

        Returns:
            An object derived from WatchdogBase representing the hardware
            watchdog device

        Note:
            We overload this method to ensure that watchdog is only initialized
            when it is referenced. Currently, only one daemon can open the watchdog.
            To initialize watchdog in the constructor causes multiple daemon 
            try opening watchdog when loading and constructing a chassis object
            and fail. By doing so we can eliminate that risk.
        """
        try:
            if self._watchdog is None:
                from sonic_platform.watchdog import get_watchdog
                self._watchdog = get_watchdog()
        except Exception as e:
            logger.log_info("Fail to load watchdog due to {}".format(repr(e)))

        return self._watchdog

    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_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_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 _read_generic_file(self, filename, len):
        """
        Read a generic file, returns the contents of the file
        """
        result = ''
        try:
            fileobj = io.open(filename)
            result = fileobj.read(len)
            fileobj.close()
            return result
        except Exception as e:
            logger.log_info("Fail to read file {} due to {}".format(filename, repr(e)))
            return '0'

    def _verify_reboot_cause(self, filename):
        '''
        Open and read the reboot cause file in 
        /var/run/hwmanagement/system (which is defined as REBOOT_CAUSE_ROOT)
        If a reboot cause file doesn't exists, returns '0'.
        '''
        return bool(int(self._read_generic_file(join(REBOOT_CAUSE_ROOT, filename), REBOOT_CAUSE_FILE_LENGTH).rstrip('\n')))

    def initialize_reboot_cause(self):
        self.reboot_major_cause_dict = {
            'reset_main_pwr_fail'       :   self.REBOOT_CAUSE_POWER_LOSS,
            'reset_aux_pwr_or_ref'      :   self.REBOOT_CAUSE_POWER_LOSS,
            'reset_asic_thermal'        :   self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC,
            'reset_hotswap_or_wd'       :   self.REBOOT_CAUSE_WATCHDOG,
            'reset_swb_wd'              :   self.REBOOT_CAUSE_WATCHDOG,
            'reset_sff_wd'              :   self.REBOOT_CAUSE_WATCHDOG
        }
        self.reboot_minor_cause_dict = {
            'reset_fw_reset'            :   "Reset by ASIC firmware",
            'reset_long_pb'             :   "Reset by long press on power button",
            'reset_short_pb'            :   "Reset by short press on power button",
            'reset_comex_thermal'       :   "ComEx thermal shutdown",
            'reset_comex_pwr_fail'      :   "ComEx power fail",
            'reset_comex_wd'            :   "Reset requested from ComEx",
            'reset_from_asic'           :   "Reset requested from ASIC",
            'reset_reload_bios'         :   "Reset caused by BIOS reload",
            'reset_sw_reset'            :   "Software reset",
            'reset_hotswap_or_halt'     :   "Reset caused by hotswap or halt",
            'reset_from_comex'          :   "Reset from ComEx",
            'reset_voltmon_upgrade_fail':   "Reset due to voltage monitor devices upgrade failure"
        }
        self.reboot_cause_initialized = True

    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.
        """
        #read reboot causes files in the following order
        if not self.reboot_cause_initialized:
            self.initialize_reboot_cause()

        for reset_file, reset_cause in self.reboot_major_cause_dict.iteritems():
            if self._verify_reboot_cause(reset_file):
                return reset_cause, ''

        for reset_file, reset_cause in self.reboot_minor_cause_dict.iteritems():
            if self._verify_reboot_cause(reset_file):
                return self.REBOOT_CAUSE_HARDWARE_OTHER, reset_cause

        return self.REBOOT_CAUSE_NON_HARDWARE, ''

    def _get_cpld_version(self, version_file):
        cpld_version = self._read_generic_file(join(CPLD_VERSION_ROOT, version_file), CPLD_VERSION_MAX_LENGTH)
        return cpld_version.rstrip('\n')

    def _get_command_result(self, cmdline):
        try:
            proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT)
            stdout = proc.communicate()[0]
            proc.wait()
            result = stdout.rstrip('\n')

        except OSError, e:
            result = ''

        return result
Exemplo n.º 4
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
    HWMON_NODE = os.listdir(HWMON_DIR)[0]
    MAILBOX_DIR = HWMON_DIR + HWMON_NODE
    EEPROM_I2C_MAPPING = {
        0: [9, 18],
        1: [9, 19],
        2: [9, 20],
        3: [9, 21],
        4: [9, 22],
        5: [9, 23],
        6: [9, 24],
        7: [9, 25],
        8: [8, 26],
        9: [8, 27],
        10: [8, 28],
        11: [8, 29],
        12: [8, 31],
        13: [8, 30],
        14: [8, 33],
        15: [8, 32],  # Remapped 4 entries
        16: [7, 34],
        17: [7, 35],
        18: [7, 36],
        19: [7, 37],
        20: [7, 38],
        21: [7, 39],
        22: [7, 40],
        23: [7, 41],
        24: [6, 42],
        25: [6, 43],
        26: [6, 44],
        27: [6, 45],
        28: [6, 46],
        29: [6, 47],
        30: [6, 48],
        31: [6, 49]
    }
    PORT_I2C_MAPPING = {
        # 0th Index = i2cLine, 1st Index = portIdx in i2cLine
        0: [14, 0],
        1: [14, 1],
        2: [14, 2],
        3: [14, 3],
        4: [14, 4],
        5: [14, 5],
        6: [14, 6],
        7: [14, 7],
        8: [14, 8],
        9: [14, 9],
        10: [14, 10],
        11: [14, 11],
        12: [15, 0],
        13: [15, 1],
        14: [15, 2],
        15: [15, 3],
        16: [15, 4],
        17: [15, 5],
        18: [15, 6],
        19: [15, 7],
        20: [15, 8],
        21: [15, 9],
        22: [16, 0],
        23: [16, 1],
        24: [16, 2],
        25: [16, 3],
        26: [16, 4],
        27: [16, 5],
        28: [16, 6],
        29: [16, 7],
        30: [16, 8],
        31: [16, 9]
    }

    reset_reason_dict = {}
    reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    reset_reason_dict[33] = ChassisBase.REBOOT_CAUSE_WATCHDOG
    reset_reason_dict[44] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
    reset_reason_dict[55] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE

    power_reason_dict = {}
    power_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    power_reason_dict[22] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU
    power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
    power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED

    def __init__(self):
        ChassisBase.__init__(self)
        PORT_START = 0
        PORT_END = 31
        PORTS_IN_BLOCK = (PORT_END + 1)

        # sfp.py will read eeprom contents and retrive the eeprom data.
        # It will also provide support sfp controls like reset and setting
        # low power mode.
        # We pass the eeprom path and sfp control path from chassis.py
        # So that sfp.py implementation can be generic to all platforms
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom"
        sfp_ctrl_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-003e/"
        for index in range(0, PORTS_IN_BLOCK):
            eeprom_path = eeprom_base.format(self.EEPROM_I2C_MAPPING[index][0],
                                             self.EEPROM_I2C_MAPPING[index][1])
            sfp_control = sfp_ctrl_base.format(self.PORT_I2C_MAPPING[index][0])
            sfp_node = Sfp(index, 'QSFP', eeprom_path, sfp_control,
                           self.PORT_I2C_MAPPING[index][1])
            self._sfp_list.append(sfp_node)

        # Initialize EEPROM
        self._eeprom = Eeprom()
        for i in range(MAX_Z9100_FANTRAY):
            for j in range(MAX_Z9100_FAN):
                fan = Fan(i, j)
                self._fan_list.append(fan)

        for i in range(MAX_Z9100_PSU):
            psu = Psu(i)
            self._psu_list.append(psu)

        for i in range(MAX_Z9100_THERMAL):
            thermal = Thermal(i)
            self._thermal_list.append(thermal)

        for i in range(MAX_Z9100_COMPONENT):
            component = Component(i)
            self._component_list.append(component)

    def _get_pmc_register(self, reg_name):
        # On successful read, returns the value read from given
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'
        mb_reg_file = self.MAILBOX_DIR + '/' + reg_name

        if (not os.path.isfile(mb_reg_file)):
            return rv

        try:
            with open(mb_reg_file, 'r') as fd:
                rv = fd.read()
        except Exception as error:
            rv = 'ERR'

        rv = rv.rstrip('\r\n')
        rv = rv.lstrip(" ")
        return rv

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

    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 chassis
        Returns:
            string: Model/part number of chassis
        """
        return self._eeprom.part_number_str()

    def get_serial(self):
        """
        Retrieves the serial number of the chassis (Service tag)
        Returns:
            string: Serial number of chassis
        """
        return self._eeprom.serial_str()

    def get_status(self):
        """
        Retrieves the operational status of the chassis
        Returns:
            bool: A boolean value, True if chassis 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.base_mac_addr()

    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.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.system_eeprom_info()

    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.
        """
        reset_reason = int(self._get_pmc_register('smf_reset_reason'))
        power_reason = int(self._get_pmc_register('smf_poweron_reason'))

        # Reset_Reason = 11 ==> PowerLoss
        # So return the reboot reason from Last Power_Reason Dictionary
        # If Reset_Reason is not 11 return from Reset_Reason dictionary
        # Also check if power_reason, reset_reason are valid values by
        # checking key presence in dictionary else return
        # REBOOT_CAUSE_HARDWARE_OTHER as the Power_Reason and Reset_Reason
        # registers returned invalid data
        if (reset_reason == 11):
            if (power_reason in self.power_reason_dict):
                return (self.power_reason_dict[power_reason], None)
        else:
            if (reset_reason in self.reset_reason_dict):
                return (self.reset_reason_dict[reset_reason], None)

        return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
Exemplo n.º 5
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
    HWMON_NODE = os.listdir(HWMON_DIR)[0]
    MAILBOX_DIR = HWMON_DIR + HWMON_NODE

    PORT_START = 0
    PORT_END = 63
    PORTS_IN_BLOCK = (PORT_END + 1)
    IOM1_PORT_START = 0
    IOM2_PORT_START = 16
    IOM3_PORT_START = 32
    IOM4_PORT_START = 48

    PORT_I2C_MAPPING = {}
    # 0th Index = i2cLine, 1st Index = EepromIdx in i2cLine
    EEPROM_I2C_MAPPING = {
        # IOM 1
        0: [6, 66],
        1: [6, 67],
        2: [6, 68],
        3: [6, 69],
        4: [6, 70],
        5: [6, 71],
        6: [6, 72],
        7: [6, 73],
        8: [6, 74],
        9: [6, 75],
        10: [6, 76],
        11: [6, 77],
        12: [6, 78],
        13: [6, 79],
        14: [6, 80],
        15: [6, 81],
        # IOM 2
        16: [8, 50],
        17: [8, 51],
        18: [8, 52],
        19: [8, 53],
        20: [8, 54],
        21: [8, 55],
        22: [8, 56],
        23: [8, 57],
        24: [8, 58],
        25: [8, 59],
        26: [8, 60],
        27: [8, 61],
        28: [8, 62],
        29: [8, 63],
        30: [8, 64],
        31: [8, 65],
        # IOM 3
        32: [7, 34],
        33: [7, 35],
        34: [7, 36],
        35: [7, 37],
        36: [7, 38],
        37: [7, 39],
        38: [7, 40],
        39: [7, 41],
        40: [7, 42],
        41: [7, 43],
        42: [7, 44],
        43: [7, 45],
        44: [7, 46],
        45: [7, 47],
        46: [7, 48],
        47: [7, 49],
        # IOM 4
        48: [9, 18],
        49: [9, 19],
        50: [9, 20],
        51: [9, 21],
        52: [9, 22],
        53: [9, 23],
        54: [9, 24],
        55: [9, 25],
        56: [9, 26],
        57: [9, 27],
        58: [9, 28],
        59: [9, 29],
        60: [9, 30],
        61: [9, 31],
        62: [9, 32],
        63: [9, 33]
    }

    reset_reason_dict = {}
    reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    reset_reason_dict[33] = ChassisBase.REBOOT_CAUSE_WATCHDOG
    reset_reason_dict[44] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
    reset_reason_dict[55] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE

    power_reason_dict = {}
    power_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    power_reason_dict[22] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU
    power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
    power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED

    _component_name_list = ["BIOS", "CPLD1", "CPLD2", "FPGA"]

    def __init__(self):

        ChassisBase.__init__(self)
        # Initialize EEPROM
        self.sys_eeprom = Eeprom()
        for i in range(MAX_S6100_FAN):
            fan = Fan(i)
            self._fan_list.append(fan)

        for i in range(MAX_S6100_PSU):
            psu = Psu(i)
            self._psu_list.append(psu)

        self._populate_port_i2c_mapping()

        # sfp.py will read eeprom contents and retrive the eeprom data.
        # It will also provide support sfp controls like reset and setting
        # low power mode.
        # We pass the eeprom path and sfp control path from chassis.py
        # So that sfp.py implementation can be generic to all platforms
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom"
        sfp_ctrl_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-003e/"
        for index in range(0, self.PORTS_IN_BLOCK):
            eeprom_path = eeprom_base.format(self.EEPROM_I2C_MAPPING[index][0],
                                             self.EEPROM_I2C_MAPPING[index][1])
            sfp_control = sfp_ctrl_base.format(self.PORT_I2C_MAPPING[index])
            sfp_node = Sfp(index, 'QSFP', eeprom_path, sfp_control, index)
            self._sfp_list.append(sfp_node)

    def _populate_port_i2c_mapping(self):
        # port_num and i2c match
        for port_num in range(0, self.PORTS_IN_BLOCK):
            if ((port_num >= self.IOM1_PORT_START)
                    and (port_num < self.IOM2_PORT_START)):
                i2c_line = 14
            elif ((port_num >= self.IOM2_PORT_START)
                  and (port_num < self.IOM3_PORT_START)):
                i2c_line = 16
            elif ((port_num >= self.IOM3_PORT_START)
                  and (port_num < self.IOM4_PORT_START)):
                i2c_line = 15
            elif ((port_num >= self.IOM4_PORT_START)
                  and (port_num < self.PORTS_IN_BLOCK)):
                i2c_line = 17
            self.PORT_I2C_MAPPING[port_num] = i2c_line

    def _get_pmc_register(self, reg_name):
        # On successful read, returns the value read from given
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'
        mb_reg_file = self.MAILBOX_DIR + '/' + reg_name

        if (not os.path.isfile(mb_reg_file)):
            return rv

        try:
            with open(mb_reg_file, 'r') as fd:
                rv = fd.read()
        except Exception as error:
            rv = 'ERR'

        rv = rv.rstrip('\r\n')
        rv = rv.lstrip(" ")
        return rv

    # Run bash command and print output to stdout
    def run_command(self, command):
        click.echo(
            click.style("Command: ", fg='cyan') +
            click.style(command, fg='green'))

        proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
        (out, err) = proc.communicate()

        click.echo(out)

        if proc.returncode != 0:
            sys.exit(proc.returncode)

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

    def get_presence(self):
        """
        Retrieves the presence of the device
        Returns:
            bool: True if device 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.sys_eeprom.part_number_str()

    def get_serial(self):
        """
        Retrieves the serial number of the device (Service tag)
        Returns:
            string: Serial number of device
        """
        return self.sys_eeprom.serial_str()

    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.sys_eeprom.base_mac_addr()

    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.sys_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.
        """

    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.
        """

        reset_reason = int(self._get_pmc_register('smf_reset_reason'))
        power_reason = int(self._get_pmc_register('smf_poweron_reason'))

        # Reset_Reason = 11 ==> PowerLoss
        # So return the reboot reason from Last Power_Reason Dictionary
        # If Reset_Reason is not 11 return from Reset_Reason dictionary
        # Also check if power_reason, reset_reason are valid values by
        # checking key presence in dictionary else return
        # REBOOT_CAUSE_HARDWARE_OTHER as the Power_Reason and Reset_Reason
        # registers returned invalid data
        if (reset_reason == 11):
            if (power_reason in self.power_reason_dict):
                return (self.power_reason_dict[power_reason], None)
        else:
            if (reset_reason in self.reset_reason_dict):
                return (self.reset_reason_dict[reset_reason], None)

        return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")

    def get_component_name_list(self):
        """
        Retrieves chassis components list such as BIOS, CPLD, FPGA, etc.

        Returns:
            A list containing component name.
        """
        return self._component_name_list

    def get_firmware_version(self, component_name):

        version = None

        if component_name in self._component_name_list:

            if component_name == self._component_name_list[0]:  # BIOS
                status, version = getstatusoutput(
                    "dmidecode -s system-version")

            elif component_name == self._component_name_list[1]:  # CPLD1
                version = None

            elif component_name == self._component_name_list[2]:  # CPLD2
                version = None

            elif component_name == self._component_name_list[3]:  # SMF
                version = None

        return version

    def install_component_firmware(self, component_name, image_path):

        bios_image = None
        bios_version = "3.25.0."
        bios_file_name = "S6100*BIOS*"
        flashrom = "/usr/local/bin/flashrom"
        PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
        machine_info = sonic_device_util.get_machine_info()
        platform = sonic_device_util.get_platform_info(machine_info)
        platform_path = "/".join([PLATFORM_ROOT_PATH, platform, "bin"])

        warning = """
        ********************************************************************
        * Warning - Upgrading BIOS is inherently risky and should only be  *
        * attempted when necessary.  A failure at this upgrade may cause   *
        * a board RMA.  Proceed with caution !                             *
        ********************************************************************
        """

        if component_name in self._component_name_list:
            if component_name == self._component_name_list[0]:  # BIOS

                # current BIOS version
                current_bios_version = self.get_firmware_version("BIOS")

                # Construct BIOS image path
                if image_path is not None:
                    image_path = image_path + platform_path
                    for name in glob.glob(
                            os.path.join(image_path, bios_file_name)):
                        bios_image = image_path = name

                if not bios_image:
                    print "BIOS image file not found:", image_path
                    return False

                # Extract BIOS image version
                bios_image = os.path.basename(bios_image)
                bios_image = bios_image.strip('S6100-BIOS-')
                bios_image_version = bios_image.strip('.bin')

                if bios_image_version.startswith(bios_version):
                    bios_image_minor = bios_image_version.replace(
                        bios_image_version[:7], '')
                    if bios_image_minor.startswith("2"):
                        bios_image_minor = bios_image_minor.split("-")[1]

                if current_bios_version.startswith(bios_version):
                    current_bios_minor = current_bios_version.replace(
                        current_bios_version[:7], '')
                    if current_bios_minor.startswith("2"):
                        current_bios_minor = current_bios_minor.split("-")[1]

                # BIOS version check
                if bios_image_minor > current_bios_minor:

                    print warning
                    prompt_text = "New BIOS image " + bios_image_version + \
                        " available to install, continue?"
                    yes = click.confirm(prompt_text)

                elif current_bios_minor > bios_image_minor:

                    print warning
                    prompt_text = "Do you want to downgrade BIOS image from " \
                        + current_bios_version + " to " + \
                        bios_image_version + " continue?"

                    yes = click.confirm(prompt_text)

                else:
                    print("BIOS is already with {} latest version".format(
                        current_bios_version))
                    return True

                if yes:
                    command = flashrom + " -p" + " internal" + " -w " + \
                                         image_path
                    self.run_command(command)

            elif component_name == self._component_name_list[1]:  # CPLD1
                return False

            elif component_name == self._component_name_list[2]:  # CPLD2
                return False

            elif component_name == self._component_name_list[3]:  # SMF
                return False
        else:
            print "Invalid component Name:", component_name

        return True
Exemplo n.º 6
0
class Chassis(ChassisBase):
    """Platform-specific Chassis class"""
    def __init__(self):
        super(Chassis, self).__init__()

        # Initialize SKU name
        self.sku_name = self._get_sku_name()

        # move the initialization of each components to their dedicated initializer
        # which will be called from platform
        self.sfp_module_initialized = False
        self.sfp_event_initialized = False
        self.reboot_cause_initialized = False
        logger.log_info("Chassis loaded successfully")

    def __del__(self):
        if self.sfp_event_initialized:
            self.sfp_event.deinitialize()

    def initialize_psu(self):
        from sonic_platform.psu import Psu
        # Initialize PSU list
        self.psu_module = Psu
        for index in range(MLNX_NUM_PSU):
            psu = Psu(index, self.sku_name)
            self._psu_list.append(psu)

    def initialize_fan(self):
        from sonic_platform.fan import Fan
        from sonic_platform.fan import FAN_PATH
        self.fan_module = Fan
        self.fan_path = FAN_PATH
        # Initialize FAN list
        multi_rotor_in_drawer = False
        num_of_fan, num_of_drawer = self._extract_num_of_fans_and_fan_drawers()
        multi_rotor_in_drawer = num_of_fan > num_of_drawer

        for index in range(num_of_fan):
            if multi_rotor_in_drawer:
                fan = Fan(index, index / 2)
            else:
                fan = Fan(index, index)
            self._fan_list.append(fan)

    def initialize_sfp(self):
        from sonic_platform.sfp import SFP

        self.sfp_module = SFP

        # Initialize SFP list
        port_position_tuple = self._get_port_position_tuple_by_sku_name()
        self.PORT_START = port_position_tuple[0]
        self.QSFP_PORT_START = port_position_tuple[1]
        self.PORT_END = port_position_tuple[2]
        self.PORTS_IN_BLOCK = port_position_tuple[3]

        for index in range(self.PORT_START, self.PORT_END + 1):
            if index in range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 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_thermals(self):
        from sonic_platform.thermal import initialize_thermals
        # Initialize thermals
        initialize_thermals(self.sku_name, self._thermal_list, self._psu_list)

    def initialize_eeprom(self):
        from eeprom import Eeprom
        # Initialize EEPROM
        self._eeprom = Eeprom()

    def initialize_components(self):
        # Initialize component list
        from sonic_platform.component import ComponentBIOS, ComponentCPLD
        self._component_list.append(ComponentBIOS())
        self._component_list.append(ComponentCPLD())

    ##############################################
    # 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 (0-based) index <index>

        Args:
            index: An integer, the index (0-based) of the sfp to retrieve.
                   The index should be the sequence of a physical port in a chassis,
                   starting from 0.
                   For example, 0 for Ethernet0, 1 for Ethernet4 and so on.

        Returns:
            An object dervied from SfpBase representing the specified sfp
        """
        if not self.sfp_module_initialized:
            self.initialize_sfp()

        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 _extract_num_of_fans_and_fan_drawers(self):
        num_of_fan = 0
        num_of_drawer = 0
        for f in listdir(self.fan_path):
            if isfile(join(self.fan_path, f)):
                match_obj = re.match('fan(\d+)_speed_get', f)
                if match_obj != None:
                    if int(match_obj.group(1)) > num_of_fan:
                        num_of_fan = int(match_obj.group(1))
                else:
                    match_obj = re.match('fan(\d+)_status', f)
                    if match_obj != None and int(
                            match_obj.group(1)) > num_of_drawer:
                        num_of_drawer = int(match_obj.group(1))

        return num_of_fan, num_of_drawer

    def _get_sku_name(self):
        p = subprocess.Popen(GET_HWSKU_CMD, shell=True, stdout=subprocess.PIPE)
        out, err = p.communicate()
        return out.rstrip('\n')

    def _get_port_position_tuple_by_sku_name(self):
        position_tuple = port_position_tuple_list[hwsku_dict_port[
            self.sku_name]]
        return position_tuple

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

        Returns:
            An object derived from WatchdogBase representing the hardware
            watchdog device

        Note:
            We overload this method to ensure that watchdog is only initialized
            when it is referenced. Currently, only one daemon can open the watchdog.
            To initialize watchdog in the constructor causes multiple daemon 
            try opening watchdog when loading and constructing a chassis object
            and fail. By doing so we can eliminate that risk.
        """
        try:
            if self._watchdog is None:
                from sonic_platform.watchdog import get_watchdog
                self._watchdog = get_watchdog()
        except Exception as e:
            logger.log_info("Fail to load watchdog due to {}".format(repr(e)))

        return self._watchdog

    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_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_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 _read_generic_file(self, filename, len):
        """
        Read a generic file, returns the contents of the file
        """
        result = ''
        try:
            fileobj = io.open(filename)
            result = fileobj.read(len)
            fileobj.close()
            return result
        except Exception as e:
            logger.log_info("Fail to read file {} due to {}".format(
                filename, repr(e)))
            return '0'

    def _verify_reboot_cause(self, filename):
        '''
        Open and read the reboot cause file in 
        /var/run/hwmanagement/system (which is defined as REBOOT_CAUSE_ROOT)
        If a reboot cause file doesn't exists, returns '0'.
        '''
        return bool(
            int(
                self._read_generic_file(
                    join(REBOOT_CAUSE_ROOT,
                         filename), REBOOT_CAUSE_FILE_LENGTH).rstrip('\n')))

    def initialize_reboot_cause(self):
        self.reboot_major_cause_dict = {
            'reset_main_pwr_fail': self.REBOOT_CAUSE_POWER_LOSS,
            'reset_aux_pwr_or_ref': self.REBOOT_CAUSE_POWER_LOSS,
            'reset_asic_thermal': self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC,
            'reset_hotswap_or_wd': self.REBOOT_CAUSE_WATCHDOG,
            'reset_swb_wd': self.REBOOT_CAUSE_WATCHDOG,
            'reset_sff_wd': self.REBOOT_CAUSE_WATCHDOG
        }
        self.reboot_minor_cause_dict = {
            'reset_fw_reset':
            "Reset by ASIC firmware",
            'reset_long_pb':
            "Reset by long press on power button",
            'reset_short_pb':
            "Reset by short press on power button",
            'reset_comex_thermal':
            "ComEx thermal shutdown",
            'reset_comex_pwr_fail':
            "ComEx power fail",
            'reset_comex_wd':
            "Reset requested from ComEx",
            'reset_from_asic':
            "Reset requested from ASIC",
            'reset_reload_bios':
            "Reset caused by BIOS reload",
            'reset_sw_reset':
            "Software reset",
            'reset_hotswap_or_halt':
            "Reset caused by hotswap or halt",
            'reset_from_comex':
            "Reset from ComEx",
            'reset_voltmon_upgrade_fail':
            "Reset due to voltage monitor devices upgrade failure"
        }
        self.reboot_cause_initialized = True

    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.
        """
        #read reboot causes files in the following order
        if not self.reboot_cause_initialized:
            self.initialize_reboot_cause()

        for reset_file, reset_cause in self.reboot_major_cause_dict.iteritems(
        ):
            if self._verify_reboot_cause(reset_file):
                return reset_cause, ''

        for reset_file, reset_cause in self.reboot_minor_cause_dict.iteritems(
        ):
            if self._verify_reboot_cause(reset_file):
                return self.REBOOT_CAUSE_HARDWARE_OTHER, reset_cause

        return self.REBOOT_CAUSE_NON_HARDWARE, ''

    def _show_capabilities(self):
        """
        This function is for debug purpose
        Some features require a xSFP module to support some capabilities but it's unrealistic to
        check those modules one by one.
        So this function is introduce to show some capabilities of all xSFP modules mounted on the device.
        """
        for s in self._sfp_list:
            try:
                print "index {} tx disable {} dom {} calibration {} temp {} volt {} power (tx {} rx {})".format(
                    s.index, s.dom_tx_disable_supported, s.dom_supported,
                    s.calibration, s.dom_temp_supported, s.dom_volt_supported,
                    s.dom_rx_power_supported, s.dom_tx_power_supported)
            except:
                print "fail to retrieve capabilities for module index {}".format(
                    s.index)

    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.
        """
        # Initialize SFP event first
        if not self.sfp_event_initialized:
            from sonic_platform.sfp_event import sfp_event
            self.sfp_event = sfp_event()
            self.sfp_event.initialize()
            self.MAX_SELECT_EVENT_RETURNED = self.PORT_END
            self.sfp_event_initialized = True

        wait_for_ever = (timeout == 0)
        port_dict = {}
        if wait_for_ever:
            timeout = MAX_SELECT_DELAY
            while True:
                status = self.sfp_event.check_sfp_status(port_dict, timeout)
                if not port_dict == {}:
                    break
        else:
            status = self.sfp_event.check_sfp_status(port_dict, timeout)

        if status:
            # get_change_event has the meaning of retrieving all the notifications through a single call.
            # Typically this is implemented via a select framework which requires the underlay file-reading
            # interface able to retrieve all notifications without blocking once the fd has been selected.
            # However, sdk doesn't provide any interface satisfied the requirement. as a result,
            # check_sfp_status returns only one notification may indicate more notifications in its queue.
            # In this sense, we have to iterate in a loop to get all the notifications in case that
            # the first call returns at least one.
            i = 0
            while i < self.MAX_SELECT_EVENT_RETURNED:
                status = self.sfp_event.check_sfp_status(port_dict, 0)
                if not status:
                    break
                i = i + 1
            return True, {'sfp': port_dict}
        else:
            return True, {'sfp': {}}
Exemplo n.º 7
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
    HWMON_NODE = os.listdir(HWMON_DIR)[0]
    MAILBOX_DIR = HWMON_DIR + HWMON_NODE
    POLL_INTERVAL = 1  # Poll interval in seconds

    reset_reason_dict = {}
    reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    reset_reason_dict[33] = ChassisBase.REBOOT_CAUSE_WATCHDOG
    reset_reason_dict[44] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
    reset_reason_dict[55] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
    reset_reason_dict[66] = ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER
    reset_reason_dict[77] = ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER

    power_reason_dict = {}
    power_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    power_reason_dict[22] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU
    power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
    power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED

    def __init__(self):

        ChassisBase.__init__(self)
        # Initialize EEPROM
        self._eeprom = Eeprom()
        for i in range(MAX_S6100_MODULE):
            module = Module(i)
            self._module_list.append(module)
            self._sfp_list.extend(module._sfp_list)

        for i in range(MAX_S6100_FAN):
            fan = Fan(i)
            self._fan_list.append(fan)

        for i in range(MAX_S6100_PSU):
            psu = Psu(i)
            self._psu_list.append(psu)

        for i in range(MAX_S6100_THERMAL):
            thermal = Thermal(i)
            self._thermal_list.append(thermal)

        for i in range(MAX_S6100_COMPONENT):
            component = Component(i)
            self._component_list.append(component)

        self._watchdog = Watchdog()
        self._transceiver_presence = self._get_transceiver_presence()

    def _get_reboot_reason_smf_register(self):
        # In S6100, mb_poweron_reason register will
        # Returns 0xaa or 0xcc on software reload
        # Returns 0xff or 0xbb on power-cycle
        # Returns 0xdd on Watchdog
        # Returns 0xee on Thermal Shutdown
        # Returns 0x99 on Unknown reset
        smf_mb_reg_reason = self._get_pmc_register('mb_poweron_reason')
        return int(smf_mb_reg_reason, 16)

    def _get_pmc_register(self, reg_name):
        # On successful read, returns the value read from given
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'
        mb_reg_file = self.MAILBOX_DIR + '/' + reg_name

        if (not os.path.isfile(mb_reg_file)):
            return rv

        try:
            with open(mb_reg_file, 'r') as fd:
                rv = fd.read()
        except Exception as error:
            rv = 'ERR'

        rv = rv.rstrip('\r\n')
        rv = rv.lstrip(" ")
        return rv

    def _get_register(self, reg_file):
        # On successful read, returns the value read from given
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'

        if (not os.path.isfile(reg_file)):
            return rv

        try:
            with open(reg_file, 'r') as fd:
                rv = fd.read()
        except Exception as error:
            rv = 'ERR'

        rv = rv.rstrip('\r\n')
        rv = rv.lstrip(" ")
        return rv

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

    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 chassis
        Returns:
            string: Model/part number of chassis
        """
        return self._eeprom.part_number_str()

    def get_serial(self):
        """
        Retrieves the serial number of the chassis (Service tag)
        Returns:
            string: Serial number of chassis
        """
        return self._eeprom.serial_str()

    def get_status(self):
        """
        Retrieves the operational status of the chassis
        Returns:
            bool: A boolean value, True if chassis 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.base_mac_addr()

    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.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.system_eeprom_info()

    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.
        """

        reset_reason = int(self._get_pmc_register('smf_reset_reason'))
        power_reason = int(self._get_pmc_register('smf_poweron_reason'))
        smf_mb_reg_reason = self._get_reboot_reason_smf_register()

        if ((smf_mb_reg_reason == 0xbb) or (smf_mb_reg_reason == 0xff)):
            return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)
        elif ((smf_mb_reg_reason == 0xaa) or (smf_mb_reg_reason == 0xcc)):
            return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
        elif (smf_mb_reg_reason == 0xdd):
            return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
        elif (smf_mb_reg_reason == 0xee):
            return (self.power_reason_dict[power_reason], None)
        elif (reset_reason == 66):
            return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER,
                    "Emulated Cold Reset")
        elif (reset_reason == 77):
            return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER,
                    "Emulated Warm Reset")
        else:
            return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)

        return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")

    def _get_transceiver_presence(self):

        cpld2_modprs = self._get_register(
            "/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_modprs")
        cpld3_modprs = self._get_register(
            "/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_modprs")
        cpld4_modprs = self._get_register(
            "/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_modprs")
        cpld5_modprs = self._get_register(
            "/sys/class/i2c-adapter/i2c-17/17-003e/qsfp_modprs")

        # If IOM is not present, register read will fail.
        # Handle the scenario gracefully
        if (cpld2_modprs == 'read error') or (cpld2_modprs == 'ERR'):
            cpld2_modprs = '0x0'
        if (cpld3_modprs == 'read error') or (cpld3_modprs == 'ERR'):
            cpld3_modprs = '0x0'
        if (cpld4_modprs == 'read error') or (cpld4_modprs == 'ERR'):
            cpld4_modprs = '0x0'
        if (cpld5_modprs == 'read error') or (cpld5_modprs == 'ERR'):
            cpld5_modprs = '0x0'

        # Make it contiguous
        transceiver_presence = (int(cpld2_modprs, 16) & 0xffff) |\
                               ((int(cpld4_modprs, 16) & 0xffff) << 16) |\
                               ((int(cpld3_modprs, 16) & 0xffff) << 32) |\
                               ((int(cpld5_modprs, 16) & 0xffff) << 48)

        return transceiver_presence

    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.
        """
        port_dict = {}
        ret_dict = {'sfp': port_dict}
        forever = False

        if timeout == 0:
            forever = True
        elif timeout > 0:
            timeout = timeout / float(1000)  # Convert to secs
        else:
            return False, ret_dict  # Incorrect timeout

        while True:
            if forever:
                timer = self.POLL_INTERVAL
            else:
                timer = min(timeout, self.POLL_INTERVAL)
                start_time = time.time()

            time.sleep(timer)
            cur_presence = self._get_transceiver_presence()

            # Update dict only if a change has been detected
            if cur_presence != self._transceiver_presence:
                changed_ports = self._transceiver_presence ^ cur_presence
                for port in range(self.get_num_sfps()):
                    # Mask off the bit corresponding to particular port
                    mask = 1 << port
                    if changed_ports & mask:
                        # qsfp_modprs 1 => optics is removed
                        if cur_presence & mask:
                            port_dict[port] = '0'
                        # qsfp_modprs 0 => optics is inserted
                        else:
                            port_dict[port] = '1'

                # Update current presence
                self._transceiver_presence = cur_presence
                break

            if not forever:
                elapsed_time = time.time() - start_time
                timeout = round(timeout - elapsed_time, 3)
                if timeout <= 0:
                    break

        return True, ret_dict
Exemplo n.º 8
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
    HWMON_NODE = os.listdir(HWMON_DIR)[0]
    MAILBOX_DIR = HWMON_DIR + HWMON_NODE

    PORT_START = 0
    PORT_END = 63
    PORTS_IN_BLOCK = (PORT_END + 1)
    IOM1_PORT_START = 0
    IOM2_PORT_START = 16
    IOM3_PORT_START = 32
    IOM4_PORT_START = 48

    PORT_I2C_MAPPING = {}
    # 0th Index = i2cLine, 1st Index = EepromIdx in i2cLine
    EEPROM_I2C_MAPPING = {
        # IOM 1
        0: [6, 66],
        1: [6, 67],
        2: [6, 68],
        3: [6, 69],
        4: [6, 70],
        5: [6, 71],
        6: [6, 72],
        7: [6, 73],
        8: [6, 74],
        9: [6, 75],
        10: [6, 76],
        11: [6, 77],
        12: [6, 78],
        13: [6, 79],
        14: [6, 80],
        15: [6, 81],
        # IOM 2
        16: [8, 50],
        17: [8, 51],
        18: [8, 52],
        19: [8, 53],
        20: [8, 54],
        21: [8, 55],
        22: [8, 56],
        23: [8, 57],
        24: [8, 58],
        25: [8, 59],
        26: [8, 60],
        27: [8, 61],
        28: [8, 62],
        29: [8, 63],
        30: [8, 64],
        31: [8, 65],
        # IOM 3
        32: [7, 34],
        33: [7, 35],
        34: [7, 36],
        35: [7, 37],
        36: [7, 38],
        37: [7, 39],
        38: [7, 40],
        39: [7, 41],
        40: [7, 42],
        41: [7, 43],
        42: [7, 44],
        43: [7, 45],
        44: [7, 46],
        45: [7, 47],
        46: [7, 48],
        47: [7, 49],
        # IOM 4
        48: [9, 18],
        49: [9, 19],
        50: [9, 20],
        51: [9, 21],
        52: [9, 22],
        53: [9, 23],
        54: [9, 24],
        55: [9, 25],
        56: [9, 26],
        57: [9, 27],
        58: [9, 28],
        59: [9, 29],
        60: [9, 30],
        61: [9, 31],
        62: [9, 32],
        63: [9, 33]
    }

    reset_reason_dict = {}
    reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    reset_reason_dict[33] = ChassisBase.REBOOT_CAUSE_WATCHDOG
    reset_reason_dict[44] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
    reset_reason_dict[55] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE

    power_reason_dict = {}
    power_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    power_reason_dict[22] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU
    power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
    power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED

    def __init__(self):

        ChassisBase.__init__(self)
        # Initialize EEPROM
        self.sys_eeprom = Eeprom()
        for i in range(MAX_S6100_FAN):
            fan = Fan(i)
            self._fan_list.append(fan)

        for i in range(MAX_S6100_PSU):
            psu = Psu(i)
            self._psu_list.append(psu)

        self._populate_port_i2c_mapping()

        # sfp.py will read eeprom contents and retrive the eeprom data.
        # It will also provide support sfp controls like reset and setting
        # low power mode.
        # We pass the eeprom path and sfp control path from chassis.py
        # So that sfp.py implementation can be generic to all platforms
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom"
        sfp_ctrl_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-003e/"
        for index in range(0, self.PORTS_IN_BLOCK):
            eeprom_path = eeprom_base.format(self.EEPROM_I2C_MAPPING[index][0],
                                             self.EEPROM_I2C_MAPPING[index][1])
            sfp_control = sfp_ctrl_base.format(self.PORT_I2C_MAPPING[index])
            sfp_node = Sfp(index, 'QSFP', eeprom_path, sfp_control, index)
            self._sfp_list.append(sfp_node)

    def _populate_port_i2c_mapping(self):
        # port_num and i2c match
        for port_num in range(0, self.PORTS_IN_BLOCK):
            if ((port_num >= self.IOM1_PORT_START)
                    and (port_num < self.IOM2_PORT_START)):
                i2c_line = 14
            elif ((port_num >= self.IOM2_PORT_START)
                  and (port_num < self.IOM3_PORT_START)):
                i2c_line = 16
            elif ((port_num >= self.IOM3_PORT_START)
                  and (port_num < self.IOM4_PORT_START)):
                i2c_line = 15
            elif ((port_num >= self.IOM4_PORT_START)
                  and (port_num < self.PORTS_IN_BLOCK)):
                i2c_line = 17
            self.PORT_I2C_MAPPING[port_num] = i2c_line

    def _get_pmc_register(self, reg_name):
        # On successful read, returns the value read from given
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'
        mb_reg_file = self.MAILBOX_DIR + '/' + reg_name

        if (not os.path.isfile(mb_reg_file)):
            return rv

        try:
            with open(mb_reg_file, 'r') as fd:
                rv = fd.read()
        except Exception as error:
            rv = 'ERR'

        rv = rv.rstrip('\r\n')
        rv = rv.lstrip(" ")
        return rv

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

    def get_presence(self):
        """
        Retrieves the presence of the device
        Returns:
            bool: True if device 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.sys_eeprom.part_number_str()

    def get_serial(self):
        """
        Retrieves the serial number of the device (Service tag)
        Returns:
            string: Serial number of device
        """
        return self.sys_eeprom.serial_str()

    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.sys_eeprom.base_mac_addr()

    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.sys_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.
        """

    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.
        """

        reset_reason = int(self._get_pmc_register('smf_reset_reason'))
        power_reason = int(self._get_pmc_register('smf_poweron_reason'))

        # Reset_Reason = 11 ==> PowerLoss
        # So return the reboot reason from Last Power_Reason Dictionary
        # If Reset_Reason is not 11 return from Reset_Reason dictionary
        # Also check if power_reason, reset_reason are valid values by
        # checking key presence in dictionary else return
        # REBOOT_CAUSE_HARDWARE_OTHER as the Power_Reason and Reset_Reason
        # registers returned invalid data
        if (reset_reason == 11):
            if (power_reason in self.power_reason_dict):
                return (self.power_reason_dict[power_reason], None)
        else:
            if (reset_reason in self.reset_reason_dict):
                return (self.reset_reason_dict[reset_reason], None)

        return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
    d = []
    for d_ in data:
        d.append(d_[3])
        d.append(d_[2])
        d.append(d_[1])
        d.append(d_[0])
    return bytes(d)


if __name__ == '__main__':
    data = big2little(patch_bin)
    code = vsdsp.Code.disassemble(data, 0)
    codes = vsdsp.Codes()
    codes.append(code)
    print(codes.text())

    if len(sys.argv) == 2:
        eeprom = open(sys.argv[1], 'rb').read()
        eeprom = Eeprom.decode(eeprom)
        for blob in eeprom[0]:
            for idx in range(0, len(blob.data) - 3, 4):
                if blob.data[idx + 3] == 0x29:
                    if len(blob.data) > len(data) + 8:
                        blob.data = blob.data[:idx +
                                              8] + data + blob.data[idx + 8 +
                                                                    len(data):]
                        open(sys.argv[1] + '.patch_0000.bin',
                             'wb').write(eeprom.blob())
                        sys.exit(0)
    raise RuntimeError('szz')
Exemplo n.º 10
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
    HWMON_NODE = os.listdir(HWMON_DIR)[0]
    MAILBOX_DIR = HWMON_DIR + HWMON_NODE

    reset_reason_dict = {}
    reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    reset_reason_dict[33] = ChassisBase.REBOOT_CAUSE_WATCHDOG
    reset_reason_dict[44] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
    reset_reason_dict[55] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE

    power_reason_dict = {}
    power_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    power_reason_dict[22] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU
    power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
    power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED

    def __init__(self):

        ChassisBase.__init__(self)
        # Initialize EEPROM
        self.sys_eeprom = Eeprom()
        for i in range(MAX_S6100_MODULE):
            module = Module(i)
            self._module_list.append(module)

        for i in range(MAX_S6100_FAN):
            fan = Fan(i)
            self._fan_list.append(fan)

        for i in range(MAX_S6100_PSU):
            psu = Psu(i)
            self._psu_list.append(psu)

        for i in range(MAX_S6100_THERMAL):
            thermal = Thermal(i)
            self._thermal_list.append(thermal)

        # Initialize component list
        self._component_name_list.append(COMPONENT_BIOS)
        self._component_name_list.append(SWITCH_CPLD)
        self._component_name_list.append(SMF_FPGA)

    def _get_reboot_reason_smf_register(self):
        # Returns 0xAA on software reload
        # Returns 0xFF on power-cycle
        # Returns 0x01 on first-boot
        smf_mb_reg_reason = self._get_pmc_register('mb_poweron_reason')
        return int(smf_mb_reg_reason, 16)

    def _get_pmc_register(self, reg_name):
        # On successful read, returns the value read from given
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'
        mb_reg_file = self.MAILBOX_DIR + '/' + reg_name

        if (not os.path.isfile(mb_reg_file)):
            return rv

        try:
            with open(mb_reg_file, 'r') as fd:
                rv = fd.read()
        except Exception as error:
            rv = 'ERR'

        rv = rv.rstrip('\r\n')
        rv = rv.lstrip(" ")
        return rv

    # Run bash command and print output to stdout
    def run_command(self, command):
        click.echo(click.style("Command: ", fg='cyan') +
                   click.style(command, fg='green'))

        proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
        (out, err) = proc.communicate()

        click.echo(out)

        if proc.returncode != 0:
            sys.exit(proc.returncode)

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

    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 chassis
        Returns:
            string: Model/part number of chassis
        """
        return self.sys_eeprom.part_number_str()

    def get_serial(self):
        """
        Retrieves the serial number of the chassis (Service tag)
        Returns:
            string: Serial number of chassis
        """
        return self.sys_eeprom.serial_str()

    def get_status(self):
        """
        Retrieves the operational status of the chassis
        Returns:
            bool: A boolean value, True if chassis 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.sys_eeprom.base_mac_addr()

    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.sys_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.sys_eeprom.system_eeprom_info()

    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.
        """

        reset_reason = int(self._get_pmc_register('smf_reset_reason'))
        power_reason = int(self._get_pmc_register('smf_poweron_reason'))
        smf_mb_reg_reason = self._get_reboot_reason_smf_register()

        if ((smf_mb_reg_reason == 0x01) and (power_reason == 0x11)):
            return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)

        # Reset_Reason = 11 ==> PowerLoss
        # So return the reboot reason from Last Power_Reason Dictionary
        # If Reset_Reason is not 11 return from Reset_Reason dictionary
        # Also check if power_reason, reset_reason are valid values by
        # checking key presence in dictionary else return
        # REBOOT_CAUSE_HARDWARE_OTHER as the Power_Reason and Reset_Reason
        # registers returned invalid data

        # In S6100, if Reset_Reason is not 11 and smf_mb_reg_reason
        # is ff or bb, then it is PowerLoss
        if (reset_reason == 11):
            if (power_reason in self.power_reason_dict):
                return (self.power_reason_dict[power_reason], None)
        else:
            if ((smf_mb_reg_reason == 0xbb) or (smf_mb_reg_reason == 0xff)):
                return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)

            if (reset_reason in self.reset_reason_dict):
                return (self.reset_reason_dict[reset_reason], None)

        return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")

    def _get_command_result(self, cmdline):
        try:
            proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE,
                                    shell=True, stderr=subprocess.STDOUT)
            stdout = proc.communicate()[0]
            proc.wait()
            result = stdout.rstrip('\n')
        except OSError:
            result = ''

        return result

    def _get_cpld_version(self):
        io_resource = "/dev/port"
        CPLD1_VERSION_ADDR = 0x100

        fd = os.open(io_resource, os.O_RDONLY)
        if (fd < 0):
            return 'NA'
        if (os.lseek(fd, CPLD1_VERSION_ADDR, os.SEEK_SET)
            != CPLD1_VERSION_ADDR):
            return 'NA'

        buf = os.read(fd, 1)
        cpld_version = ord(buf)
        os.close(fd)

        return "%d.%d" % (((cpld_version & 0xF0) >> 4), cpld_version & 0xF)

    def _get_fpga_version(self):
        fpga_ver = float(self._get_pmc_register('smf_firmware_ver'))
        return fpga_ver

    def get_firmware_version(self, component_name):
        """
        Retrieves platform-specific hardware/firmware versions for
        chassis componenets such as BIOS, CPLD, FPGA, etc.
        Args:
            component_name: A string, the component name.
        Returns:
            A string containing platform-specific component versions
        """
        if component_name in self._component_name_list :
            if component_name == COMPONENT_BIOS:
                return self._get_command_result(BIOS_QUERY_VERSION_COMMAND)
            elif component_name == SWITCH_CPLD:
                return self._get_cpld_version()
            elif component_name == SMF_FPGA:
                return self._get_fpga_version()

        return None

    def install_component_firmware(self, component_name, image_path):

        bios_image = None
        bios_version = "3.25.0."
        bios_file_name = "S6100*BIOS*"
        flashrom = "/usr/local/bin/flashrom"
        PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
        machine_info = sonic_device_util.get_machine_info()
        platform = sonic_device_util.get_platform_info(machine_info)
        platform_path = "/".join([PLATFORM_ROOT_PATH, platform, "bin"])

        warning = """
        ********************************************************************
        * Warning - Upgrading BIOS is inherently risky and should only be  *
        * attempted when necessary.  A failure at this upgrade may cause   *
        * a board RMA.  Proceed with caution !                             *
        ********************************************************************
        """

        if component_name in self._component_name_list:
            if component_name == COMPONENT_BIOS:  # BIOS

                # current BIOS version
                current_bios_version = self.get_firmware_version("BIOS")

                # Construct BIOS image path
                if image_path is not None:
                    image_path = image_path + platform_path
                    for name in glob.glob(
                                    os.path.join(image_path, bios_file_name)):
                        bios_image = image_path = name

                if not bios_image:
                    print "BIOS image file not found:", image_path
                    return False

                # Extract BIOS image version
                bios_image = os.path.basename(bios_image)
                bios_image = bios_image.strip('S6100-BIOS-')
                bios_image_version = bios_image.strip('.bin')

                if bios_image_version.startswith(bios_version):
                    bios_image_minor = bios_image_version.replace(
                                                bios_image_version[:7], '')
                    if bios_image_minor.startswith("2"):
                        bios_image_minor = bios_image_minor.split("-")[1]

                if current_bios_version.startswith(bios_version):
                    current_bios_minor = current_bios_version.replace(
                                                current_bios_version[:7], '')
                    if current_bios_minor.startswith("2"):
                        current_bios_minor = current_bios_minor.split("-")[1]

                # BIOS version check
                if bios_image_minor > current_bios_minor:

                    print warning
                    prompt_text = "New BIOS image " + bios_image_version + \
                        " available to install, continue?"
                    yes = click.confirm(prompt_text)

                elif current_bios_minor > bios_image_minor:

                    print warning
                    prompt_text = "Do you want to downgrade BIOS image from " \
                        + current_bios_version + " to " + \
                        bios_image_version + " continue?"

                    yes = click.confirm(prompt_text)

                else:
                    print("BIOS is already with {} latest version".format(
                        current_bios_version))
                    return True

                if yes:
                    command = flashrom + " -p" + " internal" + " -w " + \
                                         image_path
                    self.run_command(command)

            elif component_name == SWITCH_CPLD:  # CPLD
                return False

            elif component_name == SMF_FPGA:  # SMF
                return False
        else:
            print "Invalid component Name:", component_name

        return True
Exemplo n.º 11
0
def big2little(data):
    """Convert 4B ints from big to little endian (and vice versa)."""
    d = []
    for d_ in data:
        d.append(d_[3])
        d.append(d_[2])
        d.append(d_[1])
        d.append(d_[0])
    return bytes(d)


if __name__ == "__main__":
    data = big2little(patch_bin)
    code = vsdsp.Code.disassemble(data, 0)
    codes = vsdsp.Codes()
    codes.append(code)
    print(codes.text())

    if len(sys.argv) == 2:
        eeprom = open(sys.argv[1], "rb").read()
        eeprom = Eeprom.decode(eeprom)
        for blob in eeprom[0]:
            for idx in range(0, len(blob.data) - 3, 4):
                if blob.data[idx + 3] == 0x29:
                    if len(blob.data) > len(data) + 8:
                        blob.data = blob.data[: idx + 8] + data + blob.data[idx + 8 + len(data) :]
                        open(sys.argv[1] + ".patch_0000.bin", "wb").write(eeprom.blob())
                        sys.exit(0)
    raise RuntimeError("szz")
Exemplo n.º 12
0
class Chassis(ChassisBase):
    """Platform-specific Chassis class"""
    def __init__(self):
        super(Chassis, self).__init__()

        # Initialize SKU name
        self.sku_name = self._get_sku_name()

        # Initialize PSU list
        for index in range(MLNX_NUM_PSU):
            psu = Psu(index, self.sku_name)
            self._psu_list.append(psu)

        # Initialize watchdog
        self._watchdog = get_watchdog()

        # Initialize FAN list
        multi_rotor_in_drawer = False
        num_of_fan, num_of_drawer = self._extract_num_of_fans_and_fan_drawers()
        multi_rotor_in_drawer = num_of_fan > num_of_drawer

        for index in range(num_of_fan):
            if multi_rotor_in_drawer:
                fan = Fan(index, index / 2)
            else:
                fan = Fan(index, index)
            self._fan_list.append(fan)

        # Initialize SFP list
        port_position_tuple = self._get_port_position_tuple_by_sku_name()
        self.PORT_START = port_position_tuple[0]
        self.QSFP_PORT_START = port_position_tuple[1]
        self.PORT_END = port_position_tuple[2]
        self.PORTS_IN_BLOCK = port_position_tuple[3]

        for index in range(self.PORT_START, self.PORT_END + 1):
            if index in range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1):
                sfp_module = SFP(index, 'QSFP')
            else:
                sfp_module = SFP(index, 'SFP')
            self._sfp_list.append(sfp_module)

        # Initialize thermals
        initialize_thermals(self.sku_name, self._thermal_list, self._psu_list)

        # Initialize EEPROM
        self.eeprom = Eeprom()

        # Initialize component list
        self._component_name_list.append(COMPONENT_BIOS)
        self._component_name_list.append(COMPONENT_FIRMWARE)
        self._component_name_list.append(COMPONENT_CPLD1)
        self._component_name_list.append(COMPONENT_CPLD2)

    def _extract_num_of_fans_and_fan_drawers(self):
        num_of_fan = 0
        num_of_drawer = 0
        for f in listdir(FAN_PATH):
            if isfile(join(FAN_PATH, f)):
                match_obj = re.match('fan(\d+)_speed_get', f)
                if match_obj != None:
                    if int(match_obj.group(1)) > num_of_fan:
                        num_of_fan = int(match_obj.group(1))
                else:
                    match_obj = re.match('fan(\d+)_status', f)
                    if match_obj != None and int(
                            match_obj.group(1)) > num_of_drawer:
                        num_of_drawer = int(match_obj.group(1))

        return num_of_fan, num_of_drawer

    def _get_sku_name(self):
        p = subprocess.Popen(GET_HWSKU_CMD, shell=True, stdout=subprocess.PIPE)
        out, err = p.communicate()
        return out.rstrip('\n')

    def _get_port_position_tuple_by_sku_name(self):
        position_tuple = port_position_tuple_list[hwsku_dict_port[
            self.sku_name]]
        return position_tuple

    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_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_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 _read_generic_file(self, filename, len):
        """
        Read a generic file, returns the contents of the file
        """
        result = ''
        try:
            fileobj = io.open(filename)
            result = fileobj.read(len)
            fileobj.close()
            return result
        except Exception as e:
            logger.log_info("Fail to read file {} due to {}".format(
                filename, repr(e)))
            return ''

    def _verify_reboot_cause(self, filename):
        '''
        Open and read the reboot cause file in 
        /var/run/hwmanagement/system (which is defined as REBOOT_CAUSE_ROOT)
        If a reboot cause file doesn't exists, returns '0'.
        '''
        return bool(
            int(
                self._read_generic_file(
                    join(REBOOT_CAUSE_ROOT,
                         filename), REBOOT_CAUSE_FILE_LENGTH).rstrip('\n')))

    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.
        """
        #read reboot causes files in the following order
        minor_cause = ''
        if self._verify_reboot_cause(REBOOT_CAUSE_POWER_LOSS_FILE):
            major_cause = self.REBOOT_CAUSE_POWER_LOSS
        elif self._verify_reboot_cause(
                REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC_FILE):
            major_cause = self.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
        elif self._verify_reboot_cause(REBOOT_CAUSE_WATCHDOG_FILE):
            major_cause = self.REBOOT_CAUSE_WATCHDOG
        else:
            major_cause = self.REBOOT_CAUSE_HARDWARE_OTHER
            if self._verify_reboot_cause(REBOOT_CAUSE_MLNX_FIRMWARE_RESET):
                minor_cause = "Reset by ASIC firmware"
            else:
                major_cause = self.REBOOT_CAUSE_NON_HARDWARE

        return major_cause, minor_cause

    def _get_cpld_version(self, version_file):
        cpld_version = self._read_generic_file(
            join(CPLD_VERSION_ROOT, version_file), CPLD_VERSION_MAX_LENGTH)
        return cpld_version.rstrip('\n')

    def _get_command_result(self, cmdline):
        try:
            proc = subprocess.Popen(cmdline,
                                    stdout=subprocess.PIPE,
                                    shell=True,
                                    stderr=subprocess.STDOUT)
            stdout = proc.communicate()[0]
            proc.wait()
            result = stdout.rstrip('\n')

        except OSError, e:
            result = ''

        return result
Exemplo n.º 13
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
    HWMON_NODE = os.listdir(HWMON_DIR)[0]
    MAILBOX_DIR = HWMON_DIR + HWMON_NODE
    EEPROM_I2C_MAPPING = {
        0: [9, 18],
        1: [9, 19],
        2: [9, 20],
        3: [9, 21],
        4: [9, 22],
        5: [9, 23],
        6: [9, 24],
        7: [9, 25],
        8: [8, 26],
        9: [8, 27],
        10: [8, 28],
        11: [8, 29],
        12: [8, 31],
        13: [8, 30],
        14: [8, 33],
        15: [8, 32],  # Remapped 4 entries
        16: [7, 34],
        17: [7, 35],
        18: [7, 36],
        19: [7, 37],
        20: [7, 38],
        21: [7, 39],
        22: [7, 40],
        23: [7, 41],
        24: [6, 42],
        25: [6, 43],
        26: [6, 44],
        27: [6, 45],
        28: [6, 46],
        29: [6, 47],
        30: [6, 48],
        31: [6, 49]
    }
    PORT_I2C_MAPPING = {
        # 0th Index = i2cLine, 1st Index = portIdx in i2cLine
        0: [14, 0],
        1: [14, 1],
        2: [14, 2],
        3: [14, 3],
        4: [14, 4],
        5: [14, 5],
        6: [14, 6],
        7: [14, 7],
        8: [14, 8],
        9: [14, 9],
        10: [14, 10],
        11: [14, 11],
        12: [15, 0],
        13: [15, 1],
        14: [15, 2],
        15: [15, 3],
        16: [15, 4],
        17: [15, 5],
        18: [15, 6],
        19: [15, 7],
        20: [15, 8],
        21: [15, 9],
        22: [16, 0],
        23: [16, 1],
        24: [16, 2],
        25: [16, 3],
        26: [16, 4],
        27: [16, 5],
        28: [16, 6],
        29: [16, 7],
        30: [16, 8],
        31: [16, 9]
    }

    reset_reason_dict = {}
    reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    reset_reason_dict[33] = ChassisBase.REBOOT_CAUSE_WATCHDOG
    reset_reason_dict[44] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
    reset_reason_dict[55] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE

    power_reason_dict = {}
    power_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    power_reason_dict[22] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU
    power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
    power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED

    def __init__(self):
        PORT_START = 0
        PORT_END = 31
        PORTS_IN_BLOCK = (PORT_END + 1)

        # sfp.py will read eeprom contents and retrive the eeprom data.
        # It will also provide support sfp controls like reset and setting
        # low power mode.
        # We pass the eeprom path and sfp control path from chassis.py
        # So that sfp.py implementation can be generic to all platforms
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom"
        sfp_ctrl_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-003e/"
        for index in range(0, PORTS_IN_BLOCK):
            eeprom_path = eeprom_base.format(self.EEPROM_I2C_MAPPING[index][0],
                                             self.EEPROM_I2C_MAPPING[index][1])
            sfp_control = sfp_ctrl_base.format(self.PORT_I2C_MAPPING[index][0])
            sfp_node = Sfp(index, 'QSFP', eeprom_path, sfp_control,
                           self.PORT_I2C_MAPPING[index][1])
            self._sfp_list.append(sfp_node)

        ChassisBase.__init__(self)
        # Initialize EEPROM
        self.sys_eeprom = Eeprom()
        for i in range(MAX_Z9100_FANTRAY):
            for j in range(MAX_Z9100_FAN):
                fan = Fan(i, j)
                self._fan_list.append(fan)

        # Initialize component list
        self._component_name_list.append(COMPONENT_BIOS)
        self._component_name_list.append(SWITCH_CPLD1)
        self._component_name_list.append(SWITCH_CPLD2)
        self._component_name_list.append(SWITCH_CPLD3)
        self._component_name_list.append(SWITCH_CPLD4)
        self._component_name_list.append(SMF_FPGA)

    def _get_pmc_register(self, reg_name):
        # On successful read, returns the value read from given
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'
        mb_reg_file = self.MAILBOX_DIR + '/' + reg_name

        if (not os.path.isfile(mb_reg_file)):
            return rv

        try:
            with open(mb_reg_file, 'r') as fd:
                rv = fd.read()
        except Exception as error:
            rv = 'ERR'

        rv = rv.rstrip('\r\n')
        rv = rv.lstrip(" ")
        return rv

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

    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 chassis
        Returns:
            string: Model/part number of chassis
        """
        return self.sys_eeprom.part_number_str()

    def get_serial(self):
        """
        Retrieves the serial number of the chassis (Service tag)
        Returns:
            string: Serial number of chassis
        """
        return self.sys_eeprom.serial_str()

    def get_status(self):
        """
        Retrieves the operational status of the chassis
        Returns:
            bool: A boolean value, True if chassis 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.sys_eeprom.base_mac_addr()

    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.sys_eeprom.serial_number_str()

    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.
        """
        reset_reason = int(self._get_pmc_register('smf_reset_reason'))
        power_reason = int(self._get_pmc_register('smf_poweron_reason'))

        # Reset_Reason = 11 ==> PowerLoss
        # So return the reboot reason from Last Power_Reason Dictionary
        # If Reset_Reason is not 11 return from Reset_Reason dictionary
        # Also check if power_reason, reset_reason are valid values by
        # checking key presence in dictionary else return
        # REBOOT_CAUSE_HARDWARE_OTHER as the Power_Reason and Reset_Reason
        # registers returned invalid data
        if (reset_reason == 11):
            if (power_reason in self.power_reason_dict):
                return (self.power_reason_dict[power_reason], None)
        else:
            if (reset_reason in self.reset_reason_dict):
                return (self.reset_reason_dict[reset_reason], None)

        return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")

    def _get_command_result(self, cmdline):
        try:
            proc = subprocess.Popen(cmdline,
                                    stdout=subprocess.PIPE,
                                    shell=True,
                                    stderr=subprocess.STDOUT)
            stdout = proc.communicate()[0]
            proc.wait()
            result = stdout.rstrip('\n')
        except OSError:
            result = ''

        return result

    def _get_cpld_version(self, cpld_number):
        io_resource = "/dev/port"
        CPLD1_VERSION_ADDR = 0x100

        if (cpld_number == 1):
            fd = os.open(io_resource, os.O_RDONLY)
            if (fd < 0):
                return 'NA'
            if (os.lseek(fd, CPLD1_VERSION_ADDR, os.SEEK_SET) !=
                    CPLD1_VERSION_ADDR):
                return 'NA'

            buf = os.read(fd, 1)
            cpld_version = ord(buf)
            os.close(fd)

            return "%d.%d" % (((cpld_version & 0xF0) >> 4), cpld_version & 0xF)
        else:
            cpld_version_file = ("/sys/class/i2c-adapter/i2c-{0}/{0}-003e"
                                 "/iom_cpld_vers").format(12 + cpld_number)

            if (not os.path.isfile(cpld_version_file)):
                return 'NA'

            try:
                with open(cpld_version_file, 'r') as fd:
                    ver_str = fd.read()
            except Exception as error:
                return 'NA'

            if ver_str == "read error":
                return 'NA'
            else:
                ver_str = ver_str.rstrip("\r\n")
                cpld_version = int(ver_str.split(":")[1], 16)

            return "%d.%d" % (((cpld_version & 0xF0) >> 4), cpld_version & 0xF)

    def _get_fpga_version(self):
        fpga_ver = float(self._get_pmc_register('smf_firmware_ver'))
        return fpga_ver

    def get_firmware_version(self, component_name):
        """
        Retrieves platform-specific hardware/firmware versions for chassis
        componenets such as BIOS, CPLD, FPGA, etc.
        Args:
            component_name: A string, the component name.
        Returns:
            A string containing platform-specific component versions
        """
        if component_name in self._component_name_list:
            if component_name == COMPONENT_BIOS:
                return self._get_command_result(BIOS_QUERY_VERSION_COMMAND)
            elif component_name == SWITCH_CPLD1:
                return self._get_cpld_version(1)
            elif component_name == SWITCH_CPLD2:
                return self._get_cpld_version(2)
            elif component_name == SWITCH_CPLD3:
                return self._get_cpld_version(3)
            elif component_name == SWITCH_CPLD4:
                return self._get_cpld_version(4)
            elif component_name == SMF_FPGA:
                return self._get_fpga_version()

        return None
Exemplo n.º 14
0
class Chassis(ChassisBase):
    """
    Platform-specific Chassis class
    """
    def __init__(self):
        ChassisBase.__init__(self)

        self._eeprom = Eeprom()

        for index in range(Sfp.port_start(), Sfp.port_end() + 1):
            sfp_node = Sfp(index)
            self._sfp_list.append(sfp_node)

        for i in range(1, Psu.get_num_psus() + 1):
            psu = Psu(i)
            self._psu_list.append(psu)

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

    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 chassis
        Returns:
            string: Model/part number of chassis
        """
        return self._eeprom.part_number_str()

    def get_serial(self):
        """
        Retrieves the serial number of the chassis (Service tag)
        Returns:
            string: Serial number of chassis
        """
        return self._eeprom.serial_str()

    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, 0 for Ethernet0, 1 for Ethernet4 and so on.

        Returns:
            An object dervied from SfpBase representing the specified sfp
        """
        sfp = None

        try:
            sfp = self._sfp_list[index - 1]
        except IndexError:
            sys.stderr.write("SFP index {} out of range (1-{})\n".format(
                index,
                len(self._sfp_list) - 1))
        return sfp

    def get_status(self):
        """
        Retrieves the operational status of the chassis
        Returns:
            bool: A boolean value, True if chassis 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.base_mac_addr()

    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.system_eeprom_info()

    def get_change_event(self, timeout=0):
        ready, event_sfp = Sfp.get_transceiver_change_event(timeout)
        return ready, {'sfp': event_sfp} if ready else {}
Exemplo n.º 15
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
    HWMON_NODE = os.listdir(HWMON_DIR)[0]
    MAILBOX_DIR = HWMON_DIR + HWMON_NODE

    reset_reason_dict = {}
    reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    reset_reason_dict[33] = ChassisBase.REBOOT_CAUSE_WATCHDOG
    reset_reason_dict[44] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
    reset_reason_dict[55] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE

    power_reason_dict = {}
    power_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    power_reason_dict[22] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU
    power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
    power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED

    def __init__(self):

        ChassisBase.__init__(self)
        # Initialize EEPROM
        self._eeprom = Eeprom()
        for i in range(MAX_S6100_MODULE):
            module = Module(i)
            self._module_list.append(module)
            self._sfp_list.extend(module._sfp_list)

        for i in range(MAX_S6100_FAN):
            fan = Fan(i)
            self._fan_list.append(fan)

        for i in range(MAX_S6100_PSU):
            psu = Psu(i)
            self._psu_list.append(psu)

        for i in range(MAX_S6100_THERMAL):
            thermal = Thermal(i)
            self._thermal_list.append(thermal)

        for i in range(MAX_S6100_COMPONENT):
            component = Component(i)
            self._component_list.append(component)

    def _get_reboot_reason_smf_register(self):
        # Returns 0xAA on software reload
        # Returns 0xFF on power-cycle
        # Returns 0x01 on first-boot
        smf_mb_reg_reason = self._get_pmc_register('mb_poweron_reason')
        return int(smf_mb_reg_reason, 16)

    def _get_pmc_register(self, reg_name):
        # On successful read, returns the value read from given
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'
        mb_reg_file = self.MAILBOX_DIR + '/' + reg_name

        if (not os.path.isfile(mb_reg_file)):
            return rv

        try:
            with open(mb_reg_file, 'r') as fd:
                rv = fd.read()
        except Exception as error:
            rv = 'ERR'

        rv = rv.rstrip('\r\n')
        rv = rv.lstrip(" ")
        return rv

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

    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 chassis
        Returns:
            string: Model/part number of chassis
        """
        return self._eeprom.part_number_str()

    def get_serial(self):
        """
        Retrieves the serial number of the chassis (Service tag)
        Returns:
            string: Serial number of chassis
        """
        return self._eeprom.serial_str()

    def get_status(self):
        """
        Retrieves the operational status of the chassis
        Returns:
            bool: A boolean value, True if chassis 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.base_mac_addr()

    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.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.system_eeprom_info()

    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.
        """

        reset_reason = int(self._get_pmc_register('smf_reset_reason'))
        power_reason = int(self._get_pmc_register('smf_poweron_reason'))
        smf_mb_reg_reason = self._get_reboot_reason_smf_register()

        if ((smf_mb_reg_reason == 0x01) and (power_reason == 0x11)):
            return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)

        # Reset_Reason = 11 ==> PowerLoss
        # So return the reboot reason from Last Power_Reason Dictionary
        # If Reset_Reason is not 11 return from Reset_Reason dictionary
        # Also check if power_reason, reset_reason are valid values by
        # checking key presence in dictionary else return
        # REBOOT_CAUSE_HARDWARE_OTHER as the Power_Reason and Reset_Reason
        # registers returned invalid data

        # In S6100, if Reset_Reason is not 11 and smf_mb_reg_reason
        # is ff or bb, then it is PowerLoss
        if (reset_reason == 11):
            if (power_reason in self.power_reason_dict):
                return (self.power_reason_dict[power_reason], None)
        else:
            if ((smf_mb_reg_reason == 0xbb) or (smf_mb_reg_reason == 0xff)):
                return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)

            if (reset_reason in self.reset_reason_dict):
                return (self.reset_reason_dict[reset_reason], None)

        return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
Exemplo n.º 16
0
 def initialize_eeprom(self):
     from eeprom import Eeprom
     # Initialize EEPROM
     self._eeprom = Eeprom()
Exemplo n.º 17
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
    HWMON_NODE = os.listdir(HWMON_DIR)[0]
    MAILBOX_DIR = HWMON_DIR + HWMON_NODE

    reset_reason_dict = {}
    reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    reset_reason_dict[33] = ChassisBase.REBOOT_CAUSE_WATCHDOG
    reset_reason_dict[44] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
    reset_reason_dict[55] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE

    power_reason_dict = {}
    power_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
    power_reason_dict[22] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU
    power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
    power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED

    def __init__(self):

        ChassisBase.__init__(self)
        # Initialize EEPROM
        self.sys_eeprom = Eeprom()
        for i in range(MAX_Z9100_FANTRAY):
            for j in range(MAX_Z9100_FAN):
                fan = Fan(i, j)
                self._fan_list.append(fan)

    def _get_pmc_register(self, reg_name):
        # On successful read, returns the value read from given
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'
        mb_reg_file = self.MAILBOX_DIR + '/' + reg_name

        if (not os.path.isfile(mb_reg_file)):
            return rv

        try:
            with open(mb_reg_file, 'r') as fd:
                rv = fd.read()
        except Exception as error:
            rv = 'ERR'

        rv = rv.rstrip('\r\n')
        rv = rv.lstrip(" ")
        return rv

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

    def get_presence(self):
        """
        Retrieves the presence of the device
        Returns:
            bool: True if device 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.sys_eeprom.part_number_str()

    def get_serial(self):
        """
        Retrieves the serial number of the device (Service tag)
        Returns:
            string: Serial number of device
        """
        return self.sys_eeprom.serial_str()

    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.sys_eeprom.base_mac_addr()

    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.sys_eeprom.serial_number_str()

    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.
        """

        reset_reason = int(self._get_pmc_register('smf_reset_reason'))
        power_reason = int(self._get_pmc_register('smf_poweron_reason'))

        # Reset_Reason = 11 ==> PowerLoss
        # So return the reboot reason from Last Power_Reason Dictionary
        # If Reset_Reason is not 11 return from Reset_Reason dictionary
        # Also check if power_reason, reset_reason are valid values by
        # checking key presence in dictionary else return
        # REBOOT_CAUSE_HARDWARE_OTHER as the Power_Reason and Reset_Reason
        # registers returned invalid data
        if (reset_reason == 11):
            if (power_reason in self.power_reason_dict):
                return (self.power_reason_dict[power_reason], None)
        else:
            if (reset_reason in self.reset_reason_dict):
                return (self.reset_reason_dict[reset_reason], None)

        return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")