Example #1
0
class Fan(FanBase):
    """Nokia platform-specific Fan class"""

    def __init__(self, fan_index, fan_drawer, psu_fan=False, dependency=None):
        self.is_psu_fan = psu_fan
        ADT7473_DIR = "/sys/bus/i2c/devices/0-002e/hwmon/hwmon1/"

        if not self.is_psu_fan:
            # Fan is 1-based in Nokia platforms
            self.index = fan_index + 1
            self.fan_drawer = fan_drawer
            self.set_fan_speed_reg = ADT7473_DIR+"pwm{}".format(self.index)
            self.get_fan_speed_reg = ADT7473_DIR+"fan{}_input".format(self.index)
            self.max_fan_speed = MAX_IXS7215_FAN_SPEED
            self.supported_led_color = ['off', 'green', 'red']

            # Fan eeprom
            self.eeprom = Eeprom(is_fan=True, fan_index=self.index)
        else:
            # this is a PSU Fan
            self.index = fan_index
            self.dependency = dependency

    def _get_i2c_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 e:
            rv = 'ERR'

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

    def _set_i2c_register(self, reg_file, value):
        # On successful write, the value read will be written on
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'

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

        try:
            with open(reg_file, 'w') as fd:
                rv = fd.write(str(value))
        except Exception as e:
            rv = 'ERR'

        # Ensure that the write operation has succeeded
        if (int(self._get_i2c_register(reg_file)) != value ):
            time.sleep(3)
            if (int(self._get_i2c_register(reg_file)) != value ):
                rv = 'ERR'

        return rv

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

        Returns:
            string: The name of the Fan
        """
        if not self.is_psu_fan:
            return "Fan{}".format(self.index)
        else:
            return "PSU{} Fan".format(self.index)

    def get_presence(self):
        """
        Retrieves the presence of the Fan Unit

        Returns:
            bool: True if Fan is present, False if not
        """
        if smbus_present == 0:
            sonic_logger.log_info("PMON fan-smbus ERROR - presence ")
            return False
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICE_REG = 0xb
            fanstatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)

        if self.index == 1:
            fanstatus = fanstatus & 1
            if fanstatus == 1:
                return False
        if self.index == 2:
            fanstatus = fanstatus & 2
            if fanstatus == 2:
                return False
        return True

    def get_model(self):
        """
        Retrieves the model number of the Fan

        Returns:
            string: Model number of Fan. Use part number for this.
        """
        return self.eeprom.part_number_str()

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

        Returns:
            string: Serial number of Fan
        """
        return self.eeprom.serial_number_str()

    def get_part_number(self):
        """
        Retrieves the part number of the Fan

        Returns:
            string: Part number of Fan
        """
        return self.eeprom.part_number_str()

    def get_service_tag(self):
        """
        Retrieves the service tag of the Fan

        Returns:
            string: Service Tag of Fan
        """
        return self.eeprom.service_tag_str()

    def get_status(self):
        """
        Retrieves the operational status of the Fan

        Returns:
            bool: True if Fan is operating properly, False if not
        """
        status = False

        fan_speed = self._get_i2c_register(self.get_fan_speed_reg)
        if (fan_speed != 'ERR'):
            if (int(fan_speed) > WORKING_IXS7215_FAN_SPEED):
                status = True

        return status

    def get_direction(self):
        """
        Retrieves the fan airflow direction
        Possible fan directions (relative to port-side of device)
        Returns:
            A string, either FAN_DIRECTION_INTAKE or
            FAN_DIRECTION_EXHAUST depending on fan direction
        """

        return 'intake'

    def get_position_in_parent(self):
        """
        Retrieves 1-based relative physical position in parent device
        Returns:
            integer: The 1-based relative physical position in parent device
        """
        return self.index

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


    def get_speed(self):
        """
        Retrieves the speed of a Front FAN in the tray in revolutions per
                 minute defined by 1-based index
        :param index: An integer, 1-based index of the FAN to query speed
        :return: integer, denoting front FAN speed
        """
        speed = 0

        fan_speed = self._get_i2c_register(self.get_fan_speed_reg)
        if (fan_speed != 'ERR'):
            speed_in_rpm = int(fan_speed)
        else:
            speed_in_rpm = 0

        speed = 100*speed_in_rpm//MAX_IXS7215_FAN_SPEED
        if speed > 100:
            speed = 100

        return speed

    def get_speed_tolerance(self):
        """
        Retrieves the speed tolerance of the fan

        Returns:
            An integer, the percentage of variance from target speed
            which is considered tolerable
        """
        if self.get_presence():
            # The tolerance value is fixed as 25% for this platform
            tolerance = 25
        else:
            tolerance = 0

        return tolerance

    def set_speed(self, speed):
        """
        Set fan speed to expected value
        Args:
            speed: An integer, the percentage of full fan speed to set
            fan to, in the range 0 (off) to 100 (full speed)
        Returns:
            bool: True if set success, False if fail.
        """
        if self.is_psu_fan:
            return False

        # Set current fan duty cycle
        # - 0x00 : fan off
        # - 0x40 : 25% duty cycle
        # - 0x80 : 50% duty cycle (default)
        # - 0xff : 100% duty cycle (full speed)
        if speed in range(0, 6):
            fandutycycle = 0x00
        elif speed in range(6, 41):
            fandutycycle = 64
        elif speed in range(41, 76):
            fandutycycle = 128
        elif speed in range(76, 101):
            fandutycycle = 255
        else:
            return False

        rv = self._set_i2c_register(self.set_fan_speed_reg, fandutycycle)
        if (rv != 'ERR'):
            return True
        else:
            return False

    def set_status_led(self, color):
        """
        Set led to expected color
        Args:
            color: A string representing the color with which to set the
                   fan module status LED
        Returns:
            bool: True if set success, False if fail.

            off , red and green are the only settings 7215 fans
        """

        if self.is_psu_fan or (color not in self.supported_led_color):
            return False
        if (color == self.STATUS_LED_COLOR_AMBER):
            return False
        if (color == self.STATUS_LED_COLOR_RED):
            value = 0x02
        elif (color == self.STATUS_LED_COLOR_GREEN):
            value = 0x01
        elif (color == self.STATUS_LED_COLOR_OFF):
            value = 0x00
        else:
            return False

        if smbus_present == 0:
            return False
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICEREG = 0x8
            original = bus.read_byte_data(DEVICE_ADDRESS, DEVICEREG)
            if (self.index == 1):
                new = value << 4
                ledstatus = original & 0xcf
                ledstatus = ledstatus | new
            elif self.index == 2:
                new = value << 6
                ledstatus = original & 0x3f
                ledstatus = ledstatus | new
            else:
                return False

            bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, ledstatus)

        return True

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

        Returns:
            A string, one of the predefined STATUS_LED_COLOR_* strings.
        """

        if self.is_psu_fan:
            return None

        if smbus_present == 0:
            return None
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICE_REG = 0x8
            ledstatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)

        if self.index == 1:
            ledstatus = (ledstatus & 0x30)
            ledstatus = ledstatus >> 4
        elif self.index == 2:
            ledstatus = (ledstatus & 0xC0)
            ledstatus = ledstatus >> 6
        if ledstatus == 0x02:
            return self.STATUS_LED_COLOR_RED
        elif ledstatus == 0x1:
            return self.STATUS_LED_COLOR_GREEN
        else:
            return self.STATUS_LED_COLOR_OFF

    def get_target_speed(self):
        """
        Retrieves the target (expected) speed of the fan

        Returns:
            An integer, the percentage of full fan speed, in the range 0
            (off) to 100 (full speed)
        """
        speed = 0

        fan_duty = self._get_i2c_register(self.set_fan_speed_reg)
        if (fan_duty != 'ERR'):
            dutyspeed = int(fan_duty)
            if dutyspeed == 0:
                speed = 0
            elif dutyspeed == 64:
                speed = 25
            elif dutyspeed == 128:
                speed = 50
            elif dutyspeed == 255:
                speed = 100

        return speed
Example #2
0
class Module(ModuleBase):
    """DellEMC Platform-specific Module class"""

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

    IOM_I2C_MAPPING = {1: 14, 2: 16, 3: 15, 4: 17}
    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, 34],
        17: [8, 35],
        18: [8, 36],
        19: [8, 37],
        20: [8, 38],
        21: [8, 39],
        22: [8, 40],
        23: [8, 41],
        24: [8, 42],
        25: [8, 43],
        26: [8, 44],
        27: [8, 45],
        28: [8, 46],
        29: [8, 47],
        30: [8, 48],
        31: [8, 49],
        # IOM 3
        32: [7, 50],
        33: [7, 51],
        34: [7, 52],
        35: [7, 53],
        36: [7, 54],
        37: [7, 55],
        38: [7, 56],
        39: [7, 57],
        40: [7, 58],
        41: [7, 59],
        42: [7, 60],
        43: [7, 61],
        44: [7, 62],
        45: [7, 63],
        46: [7, 64],
        47: [7, 65],
        # 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]
    }

    def __init__(self, module_index):
        # Modules are 1-based in DellEMC platforms
        self.index = module_index + 1
        self.port_start = (self.index - 1) * 16
        self.port_end = (self.index * 16) - 1
        self.port_i2c_line = self.IOM_I2C_MAPPING[self.index]
        self._eeprom = Eeprom(iom_eeprom=True, i2c_line=self.port_i2c_line)

        self.iom_status_reg = "iom_status"
        self.iom_presence_reg = "iom_presence"

        # Overriding _component_list and _sfp_list class variables defined in
        # ModuleBase, to make them unique per Module object
        self._component_list = []
        self._sfp_list = []

        component = Component(is_module=True,
                              iom_index=self.index,
                              i2c_line=self.port_i2c_line)
        self._component_list.append(component)

        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/i2c-{1}/{1}-0050/eeprom"
        sfp_ctrl_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-003e/"

        # 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.
        for index in range(self.port_start, self.port_end + 1):
            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_line)
            sfp_node = Sfp(index, 'QSFP', eeprom_path, sfp_control, index)
            self._sfp_list.append(sfp_node)

    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 "IOM{}: {}".format(self.index, self._eeprom.modelstr())

    def get_presence(self):
        """
        Retrieves the presence of the Module

        Returns:
            bool: True if Module is present, False if not
        """
        status = False
        iom_presence = self._get_pmc_register(self.iom_presence_reg)
        if (iom_presence != 'ERR'):
            iom_presence = int(iom_presence, 16)
            if (~iom_presence & (1 << (self.index - 1))):
                status = True

        return status

    def get_model(self):
        """
        Retrieves the part number of the module

        Returns:
            string: part number of module
        """
        return self._eeprom.part_number_str()

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

        Returns:
            string: Serial number of module
        """
        return self._eeprom.serial_str()

    def get_status(self):
        """
        Retrieves the operational status of the Module

        Returns:
            bool: True if Module is operating properly, False if not
        """
        status = False
        iom_status = self._get_pmc_register(self.iom_status_reg)
        if (iom_status != 'ERR'):
            iom_status = int(iom_status, 16)
            if (~iom_status & (1 << (self.index - 1))):
                status = True

        return status

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

        Returns:
            A string containing the MAC address in the format
            'XX:XX:XX:XX:XX:XX'
        """
        # In S6100, individual modules doesn't have MAC address
        return '00:00:00:00:00:00'

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

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

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

        Returns:
            A dictionary where keys are the type code defined in
            OCP ONIE TlvInfo EEPROM format and values are their corresponding
            values.
            Ex. { ‘0x21’:’AG9064’, ‘0x22’:’V1.0’, ‘0x23’:’AG9064-0109867821’,
                  ‘0x24’:’001c0f000fcd0a’, ‘0x25’:’02/03/2018 16:22:00’,
                  ‘0x26’:’01’, ‘0x27’:’REV01’, ‘0x28’:’AG9064-C2358-16G’}
        """
        return self._eeprom.system_eeprom_info()
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    REBOOT_CAUSE_PATH = "/host/reboot-cause/platform/reboot_reason"
    oir_fd = -1
    epoll = -1

    _global_port_pres_dict = {}

    _port_to_i2c_mapping = {
        1: 2,
        2: 3,
        3: 4,
        4: 5,
        5: 6,
        6: 7,
        7: 8,
        8: 9,
        9: 10,
        10: 11,
        11: 12,
        12: 13,
        13: 14,
        14: 15,
        15: 16,
        16: 17,
        17: 18,
        18: 19,
        19: 20,
        20: 21,
        21: 22,
        22: 23,
        23: 24,
        24: 25,
        25: 26,
        26: 27,
        27: 28,
        28: 29,
        29: 30,
        30: 31,
        31: 32,
        32: 33,
        33: 34,
        34: 35,
        35: 36,
        36: 37,
        37: 38,
        38: 39,
        39: 40,
        40: 41,
        41: 42,
        42: 43,
        43: 44,
        44: 45,
        45: 46,
        46: 47,
        47: 48,
        48: 49,
        # DD + QSFP28
        49: 50,
        50: 50,
        51: 51,
        52: 51,
        53: 52,
        54: 53,
        55: 54,
        56: 55,
    }

    def __init__(self):
        ChassisBase.__init__(self)
        # sfp.py will read eeprom contents and retrive the eeprom data.
        # We pass the eeprom path from chassis.py
        self.PORT_START = 1
        self.PORT_END = 56
        self.PORTS_IN_BLOCK = (self.PORT_END + 1)
        _sfp_port = range(49, self.PORTS_IN_BLOCK)
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
        for index in range(self.PORT_START, self.PORTS_IN_BLOCK):
            eeprom_path = eeprom_base.format(self._port_to_i2c_mapping[index])
            port_type = 'QSFP' if index in _sfp_port else 'SFP'
            sfp_node = Sfp(index, port_type, eeprom_path)
            self._sfp_list.append(sfp_node)

        self._eeprom = Eeprom()
        self._watchdog = Watchdog()
        self._num_sfps = self.PORT_END
        self._num_fans = MAX_S5248F_FANTRAY * MAX_S5248F_FAN
        self._fan_list = [Fan(i, j) for i in range(MAX_S5248F_FANTRAY) \
                            for j in range(MAX_S5248F_FAN)]
        for i in range(MAX_S5248F_FANTRAY):
            fandrawer = FanDrawer(i)
            self._fan_drawer_list.append(fandrawer)
            self._fan_list.extend(fandrawer._fan_list)

        self._psu_list = [Psu(i) for i in range(MAX_S5248F_PSU)]
        self._thermal_list = [Thermal(i) for i in range(MAX_S5248F_THERMAL)]
        self._component_list = [
            Component(i) for i in range(MAX_S5248F_COMPONENT)
        ]
        for port_num in range(self.PORT_START, self.PORTS_IN_BLOCK):
            # sfp get uses zero-indexing, but port numbers start from 1
            presence = self.get_sfp(port_num - 1).get_presence()
            self._global_port_pres_dict[port_num] = '1' if presence else '0'

        #self.LOCATOR_LED_ON = self.STATUS_LED_COLOR_BLUE_BLINK
        #self.LOCATOR_LED_OFF = self.STATUS_LED_COLOR_OFF

    def __del__(self):
        if self.oir_fd != -1:
            self.epoll.unregister(self.oir_fd.fileno())
            self.epoll.close()
            self.oir_fd.close()

# check for this event change for sfp / do we need to handle timeout/sleep

    def get_change_event(self, timeout=0):
        """
        Returns a nested dictionary containing all devices which have
        experienced a change at chassis level
        """
        start_ms = time.time() * 1000
        port_dict = {}
        change_dict = {}
        change_dict['sfp'] = port_dict
        while True:
            time.sleep(0.5)
            for port_num in range(self.PORT_START, (self.PORT_END + 1)):
                presence = self.get_sfp(port_num - 1).get_presence()
                if (presence and self._global_port_pres_dict[port_num] == '0'):
                    self._global_port_pres_dict[port_num] = '1'
                    port_dict[port_num] = '1'
                elif (not presence
                      and self._global_port_pres_dict[port_num] == '1'):
                    self._global_port_pres_dict[port_num] = '0'
                    port_dict[port_num] = '0'

            if (len(port_dict) > 0):
                return True, change_dict

            if timeout:
                now_ms = time.time() * 1000
                if (now_ms - start_ms >= timeout):
                    return True, change_dict

    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 Ethernet1 and so on.

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

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

    def get_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_eeprom(self):
        """
        Retrieves the Sys Eeprom instance for the chassis.
        Returns :
            The instance of the Sys Eeprom
        """
        return self._eeprom

    def get_num_fans(self):
        """
        Retrives the number of Fans on the chassis.
        Returns :
            An integer represents the number of Fans on the chassis.
        """
        return self._num_fans

    def get_num_sfps(self):
        """
        Retrives the numnber of Media on the chassis.
        Returns:
            An integer represences the number of SFPs on the chassis.
        """
        return self._num_sfps

    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.
        """
        try:
            with open(self.REBOOT_CAUSE_PATH) as fd:
                reboot_cause = int(fd.read(), 16)
        except EnvironmentError:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)

        if reboot_cause & 0x1:
            return (self.REBOOT_CAUSE_POWER_LOSS, None)
        elif reboot_cause & 0x2:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)
        elif reboot_cause & 0x4:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "PSU Shutdown")
        elif reboot_cause & 0x8:
            return (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, None)
        elif reboot_cause & 0x10:
            return (self.REBOOT_CAUSE_WATCHDOG, None)
        elif reboot_cause & 0x20:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "BMC Shutdown")
        elif reboot_cause & 0x40:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Hot-Swap Shutdown")
        elif reboot_cause & 0x80:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Shutdown")
        elif reboot_cause & 0x100:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER,
                    "Reset Button Cold Reboot")
        else:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)

    def get_qualified_media_list(self):
        return media_part_num_list

    def set_locator_led(self, color):
        """
        Sets the state of the Chassis Locator LED

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

        Returns:
            bool: True if the Chassis Locator LED state is set successfully, False if not

        """
        resource = "/sys/bus/pci/devices/0000:04:00.0/resource0"
        val = pci_get_value(resource, SYSTEM_LED_REG)
        if self.LOCATOR_LED_ON == color:
            val = int(val) | SYSTEM_BEACON_LED_SET
        elif self.LOCATOR_LED_OFF == color:
            val = int(val) & SYSTEM_BEACON_LED_CLEAR
        else:
            return False
        pci_set_value(resource, val, SYSTEM_LED_REG)
        return True

    def get_locator_led(self):
        """
        Gets the state of the Chassis Locator LED

        Returns:
            LOCATOR_LED_ON or LOCATOR_LED_OFF
        """
        resource = "/sys/bus/pci/devices/0000:04:00.0/resource0"
        val = pci_get_value(resource, SYSTEM_LED_REG)
        val = int(val) & SYSTEM_BEACON_LED_SET
        if not val:
            return self.LOCATOR_LED_OFF
        else:
            return self.LOCATOR_LED_ON
Example #4
0
class PddfChassis(ChassisBase):
    """
    PDDF Generic Chassis class
    """
    pddf_obj = {}
    plugin_data = {}

    def __init__(self, pddf_data=None, pddf_plugin_data=None):

        ChassisBase.__init__(self)

        self.pddf_obj = pddf_data if pddf_data else None
        self.plugin_data = pddf_plugin_data if pddf_plugin_data else None
        if not self.pddf_obj or not self.plugin_data:
            try:
                from . import pddfapi
                import json
                self.pddf_obj = pddfapi.PddfApi()
                with open(
                        '/usr/share/sonic/platform/pddf/pd-plugin.json') as pd:
                    self.plugin_data = json.load(pd)
            except Exception as e:
                raise Exception("Error: Unable to load PDDF JSON data - %s" %
                                str(e))

        self.platform_inventory = self.pddf_obj.get_platform()

        # Initialize EEPROM
        try:
            self._eeprom = Eeprom(self.pddf_obj, self.plugin_data)
        except Exception as err:
            sys.stderr.write("Unable to initialize syseeprom - {}".format(
                repr(err)))
            # Dont exit as we dont want failure in loading other components

        # FANs
        for i in range(self.platform_inventory['num_fantrays']):
            fandrawer = FanDrawer(i, self.pddf_obj, self.plugin_data)
            self._fan_drawer_list.append(fandrawer)
            self._fan_list.extend(fandrawer._fan_list)

        # PSUs
        for i in range(self.platform_inventory['num_psus']):
            psu = Psu(i, self.pddf_obj, self.plugin_data)
            self._psu_list.append(psu)

        # OPTICs
        for index in range(self.platform_inventory['num_ports']):
            sfp = Sfp(index, self.pddf_obj, self.plugin_data)
            self._sfp_list.append(sfp)

        # THERMALs
        for i in range(self.platform_inventory['num_temps']):
            thermal = Thermal(i, self.pddf_obj, self.plugin_data)
            self._thermal_list.append(thermal)

    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_service_tag(self):
        """
        Retrieves the service tag of the chassis
        Returns:
            string: Sevice tag 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(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.
        """
        raise NotImplementedError

    ##############################################
    # Component methods
    ##############################################

    ##############################################
    # Module methods
    ##############################################
    # All module methods are part of chassis_base.py
    # if they need to be overwritten, define them here

    ##############################################
    # Fan methods
    ##############################################
    # All fan methods are part of chassis_base.py
    # if they need to be overwritten, define them here

    ##############################################
    # PSU methods
    ##############################################
    # All psu methods are part of chassis_base.py
    # if they need to be overwritten, define them here

    ##############################################
    # THERMAL methods
    ##############################################
    # All thermal methods are part of chassis_base.py
    # if they need to be overwritten, define them here

    ##############################################
    # SFP methods
    ##############################################
    # All sfp methods are part of chassis_base.py
    # if they need to be overwritten, define them here

    ##############################################
    # System LED  methods
    ##############################################
    def set_system_led(self, led_device_name, color):
        result, msg = self.pddf_obj.is_supported_sysled_state(
            led_device_name, color)
        if result == False:
            print(msg)
            return (False)

        index = self.pddf_obj.data[led_device_name]['dev_attr']['index']
        device_name = self.pddf_obj.data[led_device_name]['dev_info'][
            'device_name']
        self.pddf_obj.create_attr('device_name', device_name,
                                  self.pddf_obj.get_led_path())
        self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path())
        self.pddf_obj.create_attr('color', color,
                                  self.pddf_obj.get_led_cur_state_path())
        self.pddf_obj.create_attr('dev_ops', 'set_status',
                                  self.pddf_obj.get_led_path())
        return (True)

    def get_system_led(self, led_device_name):
        if led_device_name not in self.pddf_obj.data.keys():
            status = "[FAILED] " + led_device_name + " is not configured"
            return (status)

        index = self.pddf_obj.data[led_device_name]['dev_attr']['index']
        device_name = self.pddf_obj.data[led_device_name]['dev_info'][
            'device_name']
        self.pddf_obj.create_attr('device_name', device_name,
                                  self.pddf_obj.get_led_path())
        self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path())
        self.pddf_obj.create_attr('dev_ops', 'get_status',
                                  self.pddf_obj.get_led_path())
        color = self.pddf_obj.get_led_color()
        return (color)
Example #5
0
class Psu(PsuBase):
    """Nokia platform-specific PSU class for 7215 """
    def __init__(self, psu_index):
        PsuBase.__init__(self)
        # PSU is 1-based in Nokia platforms
        self.index = psu_index + 1
        self._fan_list = []

        # PSU eeprom
        self.eeprom = Eeprom(is_psu=True, psu_index=self.index)

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

        Returns:
            string: The name of the device
        """
        return "PSU{}".format(self.index)

    def get_presence(self):
        """
        Retrieves the presence of the Power Supply Unit (PSU)

        Returns:
            bool: True if PSU is present, False if not
        """

        if smbus_present == 0:  # if called from psuutil outside of pmon
            cmdstatus, psustatus = cmd.getstatusoutput(
                'sudo i2cget -y 0 0x41 0xa')
            psustatus = int(psustatus, 16)
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICE_REG = 0xa
            psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)

        if self.index == 1:
            psustatus = psustatus & 1
            if psustatus == 1:
                return False
        if self.index == 2:
            psustatus = psustatus & 2
            if psustatus == 2:
                return False

        return True

    def get_model(self):
        """
        Retrieves the part number of the PSU

        Returns:
            string: Part number of PSU
        """
        return self.eeprom.modelstr()

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

        Returns:
            string: Serial number of PSU
        """
        return self.eeprom.serial_number_str()

    def get_part_number(self):
        """
        Retrieves the part number of the PSU

        Returns:
            string: Part number of PSU
        """
        return self.eeprom.part_number_str()

    def get_status(self):
        """
        Retrieves the operational status of the PSU

        Returns:
            bool: True if PSU is operating properly, False if not
        """

        if smbus_present == 0:
            cmdstatus, psustatus = cmd.getstatusoutput(
                'sudo i2cget -y 0 0x41 0xa')
            psustatus = int(psustatus, 16)
            sonic_logger.log_warning("PMON psu-smbus - presence = 0 ")
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICE_REG = 0xa
            psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)

        if self.index == 1:
            psustatus = psustatus & 4
            if psustatus == 4:
                return True
        if self.index == 2:
            psustatus = psustatus & 8
            if psustatus == 8:
                return True

        return False

    def get_voltage(self):
        """
        Retrieves current PSU voltage output

        Returns:
            A float number, the output voltage in volts,
            e.g. 12.1
        """
        if smbus_present == 0:
            cmdstatus, psustatus = cmd.getstatusoutput(
                'sudo i2cget -y 0 0x41 0xa')
            psustatus = int(psustatus, 16)
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICE_REG = 0xa
            psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)

        if self.index == 1:
            psustatus = psustatus & 4
            if psustatus == 4:
                psu_voltage = 12.0
                return psu_voltage
        if self.index == 2:
            psustatus = psustatus & 8
            if psustatus == 8:
                psu_voltage = 12.0
                return psu_voltage

        psu_voltage = 0.0
        return psu_voltage

    def get_position_in_parent(self):
        """
        Retrieves 1-based relative physical position in parent device
        Returns:
            integer: The 1-based relative physical position in parent device
        """
        return self.index

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

    def get_powergood_status(self):
        """
        Retrieves the powergood status of PSU
        Returns:
            A boolean, True if PSU has stablized its output voltages and
            passed all its internal self-tests, False if not.
        """

        if smbus_present == 0:
            cmdstatus, psustatus = cmd.getstatusoutput(
                'sudo i2cget -y 0 0x41 0xa')
            psustatus = int(psustatus, 16)
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICE_REG = 0xa
            psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)

        if self.index == 1:
            psustatus = psustatus & 4
            if psustatus == 4:
                return True
        if self.index == 2:
            psustatus = psustatus & 8
            if psustatus == 8:
                return True

        return False

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

        Returns:
            A string, one of the predefined STATUS_LED_COLOR_* strings.
        """
        if self.get_powergood_status():
            return self.STATUS_LED_COLOR_GREEN
        else:
            return self.STATUS_LED_COLOR_OFF

    def set_status_led(self, color):
        """
        Sets the state of the PSU status LED
        Args:
            color: A string representing the color with which to set the
                   PSU status LED
        Returns:
            bool: True if status LED state is set successfully, False if
                  not
        """
        # The firmware running in the PSU controls the LED
        # and the PSU LED state cannot be changed from CPU.
        return False
Example #6
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    REBOOT_CAUSE_PATH = "/host/reboot-cause/platform/reboot_reason"
    oir_fd = -1
    epoll = -1
    io_res = "/dev/port"
    sysled_offset = 0xA162
    SYSLED_COLOR_TO_REG = {
        "green": 0xd0,
        "yellow": 0xe0,
        "flash_green": 0xd2,
        "flash_yellow": 0xe2
    }

    REG_TO_SYSLED_COLOR = {
        0xd0: "green",
        0xe0: "yellow",
        0xd2: "flash_green",
        0xd1: "flash_green",
        0xe2: "flash_yellow",
        0xe1: "flash_yellow"
    }

    _global_port_pres_dict = {}
    _port_to_i2c_mapping = {
        1: 10,
        2: 11,
        3: 12,
        4: 13,
        5: 14,
        6: 15,
        7: 16,
        8: 17,
        9: 18,
        10: 19,
        11: 20,
        12: 21,
        13: 22,
        14: 23,
        15: 24,
        16: 25,
        17: 26,
        18: 27,
        19: 28,
        20: 29,
        21: 30,
        22: 31,
        23: 32,
        24: 33,
        25: 34,
        26: 35,
        27: 36,
        28: 37,
        29: 38,
        30: 39,
        31: 40,
        32: 41,
        33: 1,
        34: 2,
    }

    def __init__(self):
        ChassisBase.__init__(self)
        # sfp.py will read eeprom contents and retrive the eeprom data.
        # We pass the eeprom path from chassis.py
        self.PORT_START = 1
        self.PORT_END = 34
        self.PORTS_IN_BLOCK = (self.PORT_END + 1)
        _sfp_port = range(33, self.PORTS_IN_BLOCK)
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
        for index in range(self.PORT_START, self.PORTS_IN_BLOCK):
            eeprom_path = eeprom_base.format(self._port_to_i2c_mapping[index])
            port_type = 'SFP' if index in _sfp_port else 'QSFP'
            sfp_node = Sfp(index, port_type, eeprom_path)
            self._sfp_list.append(sfp_node)

        self._eeprom = Eeprom()
        self._watchdog = Watchdog()
        for i in range(MAX_Z9332F_FANTRAY):
            fandrawer = FanDrawer(i)
            self._fan_drawer_list.append(fandrawer)
            self._fan_list.extend(fandrawer._fan_list)

        self._num_sfps = self.PORT_END
        self._num_fans = MAX_Z9332F_FANTRAY * MAX_Z9332F_FAN
        self._psu_list = [Psu(i) for i in range(MAX_Z9332F_PSU)]
        self._thermal_list = [Thermal(i) for i in range(MAX_Z9332F_THERMAL)]
        self._component_list = [
            Component(i) for i in range(MAX_Z9332F_COMPONENT)
        ]
        for port_num in range(self.PORT_START, self.PORTS_IN_BLOCK):
            # sfp get uses zero-indexing, but port numbers start from 1
            presence = self.get_sfp(port_num).get_presence()
            self._global_port_pres_dict[port_num] = '1' if presence else '0'

        self._watchdog = Watchdog()

    def __del__(self):
        if self.oir_fd != -1:
            self.epoll.unregister(self.oir_fd.fileno())
            self.epoll.close()
            self.oir_fd.close()

# check for this event change for sfp / do we need to handle timeout/sleep

    def get_change_event(self, timeout=0):
        """
        Returns a nested dictionary containing all devices which have
        experienced a change at chassis level
        """
        start_ms = time.time() * 1000
        port_dict = {}
        change_dict = {}
        change_dict['sfp'] = port_dict
        while True:
            time.sleep(0.5)
            for port_num in range(self.PORT_START, (self.PORT_END + 1)):
                presence = self.get_sfp(port_num).get_presence()
                if (presence and self._global_port_pres_dict[port_num] == '0'):
                    self._global_port_pres_dict[port_num] = '1'
                    port_dict[port_num] = '1'
                elif (not presence
                      and self._global_port_pres_dict[port_num] == '1'):
                    self._global_port_pres_dict[port_num] = '0'
                    port_dict[port_num] = '0'

            if (len(port_dict) > 0):
                return True, change_dict

            if timeout:
                now_ms = time.time() * 1000
                if (now_ms - start_ms >= timeout):
                    return True, change_dict

    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
        """
        sfp = None

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

    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_eeprom(self):
        """
        Retrieves the Sys Eeprom instance for the chassis.
        Returns :
            The instance of the Sys Eeprom
        """
        return self._eeprom

    def get_num_fans(self):
        """
        Retrives the number of Fans on the chassis.
        Returns :
            An integer represents the number of Fans on the chassis.
        """
        return self._num_fans

    def get_num_sfps(self):
        """
        Retrives the numnber of Media on the chassis.
        Returns:
            An integer represences the number of SFPs on the chassis.
        """
        return self._num_sfps

    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.
        """
        try:
            with open(self.REBOOT_CAUSE_PATH) as fd:
                reboot_cause = int(fd.read(), 16)
        except EnvironmentError:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)

        if reboot_cause & 0x1:
            return (self.REBOOT_CAUSE_POWER_LOSS, None)
        elif reboot_cause & 0x2:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)
        elif reboot_cause & 0x44:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "CPU warm reset")
        elif reboot_cause & 0x8:
            return (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, None)
        elif reboot_cause & 0x66:
            return (self.REBOOT_CAUSE_WATCHDOG, None)
        elif reboot_cause & 0x55:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "CPU cold reset")
        elif reboot_cause & 0x11:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Power on reset")
        elif reboot_cause & 0x77:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Power Cycle reset")
        else:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)

    def get_qualified_media_list(self):
        return media_part_num_list

    def initizalize_system_led(self):
        self.sys_ledcolor = "green"

    def get_status_led(self):
        """
        Gets the current system LED color

        Returns:
            A string that represents the supported color
        """
        val = hwaccess.io_reg_read(self.io_res, self.sysled_offset)
        if val != -1:
            return self.REG_TO_SYSLED_COLOR.get(val)
        return self.sys_ledcolor

    def set_status_led(self, color):
        """ 
        Set system LED status based on the color type passed in the argument.
        Argument: Color to be set
        Returns:
          bool: True is specified color is set, Otherwise return False
        """

        if color not in list(self.SYSLED_COLOR_TO_REG.keys()):
            return False

        if (not hwaccess.io_reg_write(self.io_res, self.sysled_offset,
                                      self.SYSLED_COLOR_TO_REG[color])):
            return False
        self.sys_ledcolor = color
        return True
Example #7
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    REBOOT_CAUSE_PATH = "/host/reboot-cause/platform/reboot_reason"
    OIR_FD_PATH = "/sys/bus/pci/devices/0000:03:00.0/port_msi"
    pci_res = "/sys/bus/pci/devices/0000:03:00.0/resource0"

    oir_fd = -1
    epoll = -1

    sysled_offset = 0x0024
    SYSLED_COLOR_TO_REG = {
        "blinking_green": 0x0,
        "green"         : 0x10,
        "amber"         : 0x20,
        "blinking_amber": 0x30
        }

    REG_TO_SYSLED_COLOR = {
        0x0  : "blinking_green",
        0x10 : "green",
        0x20 : "amber",
        0x30 : "blinking_amber"
        }

    _global_port_pres_dict = {}

    def __init__(self):
        ChassisBase.__init__(self)
        self.STATUS_LED_COLOR_BLUE_BLINK = "blinking blue"
        self.STATUS_LED_COLOR_OFF = "off"
        # sfp.py will read eeprom contents and retrive the eeprom data.
        # We pass the eeprom path from chassis.py
        self.PORT_START = 1
        self.PORT_END = 15
        PORTS_IN_BLOCK = (self.PORT_END + 1)
        _qsfp_port = range(13, self.PORT_END + 1)
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"

        for index in range(self.PORT_START, PORTS_IN_BLOCK):
            port_num = index + 1
            eeprom_path = eeprom_base.format(port_num)
            if index in _qsfp_port:
                sfp_node = Sfp(index, 'QSFP', eeprom_path)
            else:
                sfp_node = Sfp(index, 'SFP', eeprom_path)
            self._sfp_list.append(sfp_node)

        self._eeprom = Eeprom()
        self._watchdog = Watchdog()
        self._num_sfps = self.PORT_END
        self._num_fans = MAX_S5212F_FAN * MAX_S5212F_FANTRAY

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

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

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

        for i in range(MAX_S5212F_FANTRAY):
            fandrawer = FanDrawer(i)
            self._fan_drawer_list.append(fandrawer)
            self._fan_list.extend(fandrawer._fan_list)

        for port_num in range(self.PORT_START, (self.PORT_END + 1)):
            # sfp get uses zero-indexing, but port numbers start from 1
            presence = self.get_sfp(port_num-1).get_presence()
            if presence:
                self._global_port_pres_dict[port_num] = '1'
            else:
                self._global_port_pres_dict[port_num] = '0'

        self.LOCATOR_LED_ON = self.STATUS_LED_COLOR_BLUE_BLINK
        self.LOCATOR_LED_OFF = self.STATUS_LED_COLOR_OFF


    def __del__(self):
        if self.oir_fd != -1:
            self.epoll.unregister(self.oir_fd.fileno())
            self.epoll.close()
            self.oir_fd.close()

# not needed /delete after validation

    def _get_register(self, reg_file):
        retval = 'ERR'
        if (not os.path.isfile(reg_file)):
            print(reg_file,  'not found !')
            return retval

        try:
            with os.fdopen(os.open(reg_file, os.O_RDONLY)) as fd:
                retval = fd.read()
        except Exception:
            pass
        retval = retval.rstrip('\r\n')
        retval = retval.lstrip(" ")
        return retval

# not needed /delete after validation

    def _check_interrupts(self, port_dict):
        retval = 0
        is_port_dict_updated = False
        for port_num in range(self.PORT_START, (self.PORT_END + 1)):
            # sfp get uses zero-indexing, but port numbers start from 1
            sfp = self.get_sfp(port_num-1)
            presence = sfp.get_presence()
            if(presence and (self._global_port_pres_dict[port_num] == '0')):
                is_port_dict_updated = True
                self._global_port_pres_dict[port_num] = '1'
                port_dict[port_num] = '1'
            elif(not presence and (self._global_port_pres_dict[port_num] == '1')):
                is_port_dict_updated = True
                self._global_port_pres_dict[port_num] = '0'
                port_dict[port_num] = '0'
        return retval, is_port_dict_updated

# check for this event change for sfp / do we need to handle timeout/sleep

    def get_change_event(self, timeout=0):
        """
        Returns a nested dictionary containing all devices which have
        experienced a change at chassis level
        """
        start_ms = time.time() * 1000
        port_dict = {}
        change_dict = {}
        change_dict['sfp'] = port_dict
        while True:
            time.sleep(0.5)
            for port_num in range(self.PORT_START, (self.PORT_END + 1)):
                presence = self.get_sfp(port_num-1).get_presence()
                if(presence and self._global_port_pres_dict[port_num] == '0'):
                    self._global_port_pres_dict[port_num] = '1'
                    port_dict[port_num] = '1'
                    self.get_sfp(port_num-1)._initialize_media(delay=True)
                elif(not presence and
                        self._global_port_pres_dict[port_num] == '1'):
                    self._global_port_pres_dict[port_num] = '0'
                    port_dict[port_num] = '0'

            if(len(port_dict) > 0):
                return True, change_dict

            if timeout:
                now_ms = time.time() * 1000
                if (now_ms - start_ms >= timeout):
                    return True, change_dict


    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
        """
        sfp = None

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

    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_revision(self):
        """
        Retrieves the revision number of the chassis (Service tag)
        Returns:
            string: Revision number of chassis
        """
        return self._eeprom.revision_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_eeprom(self):
        """
        Retrieves the Sys Eeprom instance for the chassis.
        Returns :
            The instance of the Sys Eeprom
        """
        return self._eeprom

    def get_num_fans(self):
        """
        Retrives the number of Fans on the chassis.
        Returns :
            An integer represents the number of Fans on the chassis.
        """
        return self._num_fans

    def get_num_sfps(self):
        """
        Retrives the numnber of Media on the chassis.
        Returns:
            An integer represences the number of SFPs on the chassis.
        """
        return self._num_sfps

    def initizalize_system_led(self):
        self.sys_ledcolor = "green"

    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.
        """
        try:
            with open(self.REBOOT_CAUSE_PATH) as fd:
                reboot_cause = int(fd.read(), 16)
        except Exception:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)

        if reboot_cause & 0x1:
            return (self.REBOOT_CAUSE_POWER_LOSS, "Power on reset")
        elif reboot_cause & 0x2:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)
        elif reboot_cause & 0x4:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "PSU Shutdown")
        elif reboot_cause & 0x8:
            return (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, "Thermal overload")
        elif reboot_cause & 0x10:
            return (self.REBOOT_CAUSE_WATCHDOG, "Watchdog reset")
        elif reboot_cause & 0x20:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "BMC Shutdown")
        elif reboot_cause & 0x40:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Hot-Swap Shutdown")
        elif reboot_cause & 0x80:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Shutdown")
        elif reboot_cause & 0x100:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Cold Reboot")
        else:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)

    def get_qualified_media_list(self):
        return media_part_num_list

    def set_locator_led(self, color):
        """
        Sets the state of the Chassis Locator LED
        Args:
            color: A string representing the color with which to set the Chassis Locator LED
        Returns:
            bool: True if the Chassis Locator LED state is set successfully, False if not
        """
        resource = "/sys/bus/pci/devices/0000:04:00.0/resource0"
        val = pci_get_value(resource, SYSTEM_LED_REG)
        if  self.LOCATOR_LED_ON == color:
            val = int(val) | SYSTEM_BEACON_LED_SET
        elif self.LOCATOR_LED_OFF == color:
            val = int(val) & SYSTEM_BEACON_LED_CLEAR
        else:
            return False
        pci_set_value(resource, val, SYSTEM_LED_REG)
        return True

    def get_locator_led(self):
        """
        Gets the state of the Chassis Locator LED
        Returns:
            LOCATOR_LED_ON or LOCATOR_LED_OFF
        """
        resource = "/sys/bus/pci/devices/0000:04:00.0/resource0"
        val = pci_get_value(resource, SYSTEM_LED_REG)
        val = int(val) & SYSTEM_BEACON_LED_SET
        if not val:
            return self.LOCATOR_LED_OFF
        else:
            return self.LOCATOR_LED_ON

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

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

    def set_status_led(self, color):
        """
        Sets the state of the system LED
        Args:
            color: A string representing the color with which to set the
                   system LED
        Returns:
            bool: True if system LED state is set successfully, False if not
        """
        if color not in list(self.SYSLED_COLOR_TO_REG.keys()):
            return False

        val = pci_get_value(self.pci_res, self.sysled_offset)
        val = (val & 0xFFCF) | self.SYSLED_COLOR_TO_REG[color]

        pci_set_value(self.pci_res, val, self.sysled_offset)
        self.sys_ledcolor = color
        return True

    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.
        """
        val = pci_get_value(self.pci_res, self.sysled_offset)
        if val != -1:
            val = val & 0x30
            return self.REG_TO_SYSLED_COLOR.get(val)
        return self.sys_ledcolor
class Chassis(ChassisBase):

    def __init__(self):
        ChassisBase.__init__(self)
        self.__num_of_psus = 2
        self.__num_of_ports = 56
        self.__num_of_sfps = 48
        self.__num_of_fan_drawers = 6
        self.__fan_per_drawer = 2
        self.__num_of_thermals = 28
        self.__xcvr_presence = {}

        # Initialize EEPROM
        self._eeprom = Eeprom()

        # Initialize watchdog
        #self._watchdog = Watchdog()

        # Initialize FAN
        fan_index = 1
        for drawer_index in range(1, self.__num_of_fan_drawers + 1):
            drawer_fan_list = []
            for index in range(0, self.__fan_per_drawer):
                fan = Fan(fan_index, False)
                fan_index += 1
                self._fan_list.append(fan)
                drawer_fan_list.append(fan)
            fan_drawer = FanDrawer(drawer_index, drawer_fan_list)
            self._fan_drawer_list.append(fan_drawer)

        # Initialize thermal
        for index in range(1, self.__num_of_thermals + 1):
            thermal = Thermal(index)
            self._thermal_list.append(thermal)

        # Initialize PSU and PSU_FAN
        for index in range(1, self.__num_of_psus + 1):
            psu = Psu(index)
            self._psu_list.append(psu)

        # Initialize SFP
        for index in range(1, self.__num_of_ports + 1):
            if index in range(1, self.__num_of_sfps + 1):
                sfp = Sfp(index, 'SFP')
            else:
                sfp = Sfp(index, 'QSFP')

            self._sfp_list.append(sfp)

        for index in range(1, self.__num_of_ports + 1):
            self.__xcvr_presence[index] = self._sfp_list[index-1].get_presence()

##############################################
# Device methods
##############################################

    def get_sfp(self, index):
        """
        Retrieves sfp represented by (1-based) index <index>
        For Quanta IX8A the index in sfputil.py starts from 1, so override

        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.

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

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

        return sfp

    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
        Returns:
            string: Serial number of chassis
        """
        return self._eeprom.serial_number_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

##############################################
# Chassis methods
##############################################

    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.
            Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
                  '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
                  '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
        """
        return self._eeprom.system_eeprom_info()

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

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

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

    def get_change_event(self, timeout=0):
        """
        Currently only support transceiver change events
        """

        start_ms = time.time() * 1000
        xcvr_change_event_dict = {}
        event = False

        while True:
            time.sleep(0.5)
            for index in range(1, self.__num_of_ports + 1):
                cur_xcvr_presence = self._sfp_list[index-1].get_presence()
                if cur_xcvr_presence != self.__xcvr_presence[index]:
                    if cur_xcvr_presence is True:
                        xcvr_change_event_dict[str(index)] = '1'
                        self.__xcvr_presence[index] = True
                    elif cur_xcvr_presence is False:
                        xcvr_change_event_dict[str(index)] = '0'
                        self.__xcvr_presence[index] = False
                    event = True

            if event is True:
                return True, {'sfp':xcvr_change_event_dict}

            if timeout:
                now_ms = time.time() * 1000
                if (now_ms - start_ms >= timeout):
                    return True, {'sfp':xcvr_change_event_dict}
Example #9
0
class Chassis(ChassisBase):

    __num_of_fans = 4
    __num_of_psus = 2
    __num_of_sfps = 56
    __start_of_qsfp = 48
    __num_of_thermals = 15
    __num_of_components = 4

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

        # Initialize EEPROM
        self._eeprom = Eeprom()
        self._eeprom_data = self._eeprom.get_eeprom_data()

        # Initialize FAN
        for index in range(self.__num_of_fans):
            fandrawer = FanDrawer(index)
            self._fan_drawer_list.append(fandrawer)
            self._fan_list.extend(fandrawer._fan_list)

        # Initialize PSU
        for index in range(self.__num_of_psus):
            psu = Psu(index)
            self._psu_list.append(psu)

        # Initialize SFP
        for index in range(self.__num_of_sfps):
            if index < self.__start_of_qsfp:
                sfp = Sfp(index)
            else:
                sfp = QSfp(index)
            self._sfp_list.append(sfp)

        # Initialize THERMAL
        for index in range(self.__num_of_thermals):
            thermal = Thermal(index)
            self._thermal_list.append(thermal)

        # Initialize COMPONENT
        for index in range(self.__num_of_components):
            component = Component(index)
            self._component_list.append(component)

        # Initialize WATCHDOG
        self._watchdog = Watchdog()

    def __read_txt_file(self, file_path):
        try:
            with open(file_path, 'r') as fd:
                data = fd.read()
                return data.strip()
        except IOError:
            pass
        return None

##############################################
# Device methods
##############################################

    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
        Returns:
            string: Serial number of chassis
        """
        return self._eeprom.serial_number_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

##############################################
# Chassis methods
##############################################

    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(self._eeprom_data)

    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(self._eeprom_data)

    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.
            Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
                  '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
                  '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
        """
        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.
        """
        description = 'None'
        reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER

        reboot_cause_path = PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE
        prev_reboot_cause_path = PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE

        sw_reboot_cause = self.__read_txt_file(reboot_cause_path) or "Unknown"
        prev_sw_reboot_cause = self.__read_txt_file(
            prev_reboot_cause_path) or "Unknown"

        if sw_reboot_cause == "Unknown" and prev_sw_reboot_cause in (
                "Unknown", self.REBOOT_CAUSE_POWER_LOSS):
            reboot_cause = self.REBOOT_CAUSE_POWER_LOSS
            description = prev_sw_reboot_cause
        elif sw_reboot_cause != "Unknown":
            reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
            description = sw_reboot_cause
        elif prev_reboot_cause_path != "Unknown":
            reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
            description = prev_sw_reboot_cause

        return (reboot_cause, description)

    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.
        """
        global monitor
        port_dict = {}
        while True:
            with EventMonitor(timeout) as monitor:
                while True:
                    event = monitor.get_events()

                    if not bool(event):
                        return True, {'sfp': port_dict}
                    else:
                        if event['SUBSYSTEM'] == 'swps':
                            portname = event['DEVPATH'].split("/")[-1]
                            rc = re.match(r"port(?P<num>\d+)", portname)
                            if rc is not None:
                                if event['ACTION'] == "remove":
                                    remove_num = int(rc.group("num"))
                                    port_dict[remove_num] = "0"
                                elif event['ACTION'] == "add":
                                    add_num = int(rc.group("num"))
                                    port_dict[add_num] = "1"
                                return True, {'sfp': port_dict}
                            return False, {'sfp': port_dict}
                        else:
                            pass
Example #10
0
class Chassis(ChassisBase):
    def __init__(self):
        ChassisBase.__init__(self)

        if os.path.isdir(CONTAINER_PLATFORM_PATH):
            platform_path = CONTAINER_PLATFORM_PATH
        else:
            platform = device_info.get_platform()
            if platform is None:
                raise
            platform_path = os.path.join(HOST_DEVICE_PATH, platform)

        port_config_file = "/".join(
            [platform_path, "E530-24x2q", "port_config.ini"])
        try:
            f = open(port_config_file)
        except:
            raise
        for line in f:
            line.strip()
            if re.search('^#', line) is not None:
                Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
                break
        f.close()
        f = open(port_config_file)
        _port_cfgs = [
            Port_cfg(*tuple((line.strip().split()))) for line in f
            if re.search('^#', line) is None
        ]
        f.close()

        # Initialize EEPROM
        self._eeprom = Eeprom()
        # Initialize FAN
        for i in range(NUM_FAN_TRAY):
            fandrawer = FanDrawer(i)
            self._fan_drawer_list.append(fandrawer)
            self._fan_list.extend(fandrawer._fan_list)
        # Initialize THERMAL
        for index in range(0, NUM_THERMAL):
            thermal = Thermal(index)
            self._thermal_list.append(thermal)
        # Initialize SFP
        for port_cfg in _port_cfgs:
            sfp = Sfp(int(port_cfg.index))
            self._sfp_list.append(sfp)
        # Initialize PSU
        for index in range(0, NUM_PSU):
            psu = Psu(index + 1)
            self._psu_list.append(psu)

##############################################
# Device methods
##############################################

    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
        Returns:
            string: Serial number of chassis
        """
        return self._eeprom.serial_number_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

##############################################
# Chassis methods
##############################################

    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.
            Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
                  '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
                  '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
        """
        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.
        """
        return (None, None)

    def get_change_event(self, timeout=2000):
        """
        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.
        """
        ret, port_dict = self._sfp_list[0].get_transceiver_change_event(
            timeout)
        ret_dict = {"sfp": port_dict}
        return ret, ret_dict

    def get_num_psus(self):
        return len(self._psu_list)

    def get_psu(self, psu_index):
        return self._psu_list[psu_index]
Example #11
0
class Chassis(ChassisBase):
    # System status LED
    _led = None

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

        self.data = {'valid': 0, 'last': 0}
        self.sfp_presence = {}

        if os.path.isdir(CONTAINER_PLATFORM_PATH):
            platform_path = CONTAINER_PLATFORM_PATH
        else:
            platform = device_info.get_platform()
            if platform is None:
                raise
            platform_path = os.path.join(HOST_DEVICE_PATH, platform)

        port_config_file = "/".join(
            [platform_path, "V682-48y8c", "port_config.ini"])
        try:
            f = open(port_config_file)
        except:
            raise
        for line in f:
            line.strip()
            if re.search('^#', line) is not None:
                Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
                break
        f.close()
        f = open(port_config_file)
        _port_cfgs = [
            Port_cfg(*tuple((line.strip().split()))) for line in f
            if re.search('^#', line) is None
        ]
        f.close()

        # Initialize EEPROM
        self._eeprom = Eeprom()

        # Initialize FAN
        for i in range(NUM_FAN_TRAY):
            fandrawer = FanDrawer(i + 1)
            self._fan_drawer_list.append(fandrawer)
            self._fan_list.extend(fandrawer._fan_list)

        # Initialize PSU
        for index in range(0, NUM_PSU):
            psu = Psu(index + 1)
            self._psu_list.append(psu)

        # Initialize THERMAL
        for index in range(0, NUM_THERMAL):
            thermal = Thermal(index)
            self._thermal_list.append(thermal)

        # Initialize SFP
        for port_cfg in _port_cfgs:
            sfp = Sfp(int(port_cfg.index),
                      'SFP' if int(port_cfg.index) < 48 else 'QSFP')
            self._sfp_list.append(sfp)
            self.sfp_presence[int(port_cfg.index)] = False

##############################################
# Device methods
##############################################

    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
        Returns:
            string: Serial number of chassis
        """
        return self._eeprom.serial_number_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

##############################################
# Chassis methods
##############################################

    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.
            Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
                  '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
                  '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
        """
        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.
        """
        if os.path.exists(REBOOT_CAUSE_FILE):
            with open(REBOOT_CAUSE_FILE) as reboot_cause_file:
                reboot_cause = reboot_cause_file.readline()
            if re.search(r'User issued', reboot_cause) is None:
                return (self.REBOOT_CAUSE_POWER_LOSS, None)
            else:
                return (self.REBOOT_CAUSE_NON_HARDWARE, None)
        else:
            return (self.REBOOT_CAUSE_POWER_LOSS, None)

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

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

        Returns:
            (bool, dict):
                - True if call successful, False if not;
                - A nested dictionary where key is a device type,
                  value is a dictionary with key:value pairs in the
                  format of {'device_id':'device_event'},
                  where device_id is the device ID for this device and
                        device_event,
                             status='1' represents device inserted,
                             status='0' represents device removed.
                  Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
                      indicates that fan 0 has been removed, fan 2
                      has been inserted and sfp 11 has been removed.
        """
        SFP_STATUS_INSERTED = '1'
        SFP_STATUS_REMOVED = '0'

        now = time.time()
        port_dict = {}

        if timeout < 1000:
            timeout = 1000
        timeout = (timeout) / float(1000)  # Convert to secs

        if now < (self.data['last'] + timeout) and self.data['valid']:
            return False, {'sfp': {}}

        for sfp in self._sfp_list:
            sfp_presence = sfp.get_presence()
            if sfp_presence != self.sfp_presence[sfp.index]:
                self.sfp_presence[sfp.index] = sfp_presence
                if sfp_presence:
                    port_dict[sfp.index] = SFP_STATUS_INSERTED
                else:
                    port_dict[sfp.index] = SFP_STATUS_REMOVED

        if bool(port_dict):
            self.data['last'] = now
            self.data['valid'] = 1
            ret = True
        else:
            time.sleep(0.5)
            ret = False

        ret_dict = {'sfp': port_dict}
        return ret, ret_dict

    def get_num_psus(self):
        return len(self._psu_list)

    def get_psu(self, psu_index):
        return self._psu_list[psu_index]

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

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

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

        Returns:
            bool: True if system LED state is set successfully, False if not
        """
        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()
Example #12
0
class Chassis(ChassisBase):
    """Platform-specific Chassis class"""

    def __init__(self):
        # Initialize EEPROM and watchdog
        self._eeprom = Eeprom()
        self._watchdog = Watchdog()

        #Initialize FAN object
        for index in range(0, NUM_FAN_TRAY):
            fan = Fan(index)
            self._fan_list.append(fan)

        # Initialize PSU and PSU_fan object
        for index in range(0, NUM_PSU):
            psu = Psu(index)
            self._psu_list.append(psu)
            fan = Fan(index, True)
            self._fan_list.append(fan)

        # Initialize SFP/QSFP object
        for index in range(0, NUM_PORTS):
            if index < QSFP_START:
                sfp = Sfp(index)
            else:
                sfp = QSfp(index)
            self._sfp_list.append(sfp)

        # Initialize Thermal object
        for index in range(0, NUM_THERMAL):
            thermal = Thermal(index)
            self._thermal_list.append(thermal)

        # Initialize Component object
        for index in range(0, NUM_COMPONENT):
            component = Component(index)
            self._component_list.append(component)

    ####################
    # Device base 
    ####################

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

        Returns:
            string: The name of the device
        """
        return self._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._eeprom.part_number_str()

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

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

    def get_status(self):
        """
        Retrieves the operational status of the device

        Returns:
            A boolean value, True if device is operating properly, False if not
        """
        return True


    ####################
    # chassis base
    ####################

    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.
            Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
                  '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
                  '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
        """
        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.
        """
        raise NotImplementedError


    ##############################################
    # Other methods
    ##############################################

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

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

        Returns:
            (bool, dict):
                - True if call successful, False if not;
                - A nested dictionary where key is a device type,
                  value is a dictionary with key:value pairs in the format of
                  {'device_id':'device_event'},
                  where device_id is the device ID for this device and
                        device_event,
                             status='1' represents device inserted,
                             status='0' represents device removed.
                  Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
                      indicates that fan 0 has been removed, fan 2
                      has been inserted and sfp 11 has been removed.
        """
        raise NotImplementedError
Example #13
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    oir_fd = -1
    epoll = -1

    _global_port_pres_dict = {}

    def __init__(self):
        ChassisBase.__init__(self)
        # sfp.py will read eeprom contents and retrive the eeprom data.
        # We pass the eeprom path from chassis.py
        self.PORT_START = 1
        self.PORT_END = 34 
        self.PORTS_IN_BLOCK = (self.PORT_END + 1)
        _sfp_port = range(33, self.PORT_END + 1)
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"

        for index in range(self.PORT_START, self.PORTS_IN_BLOCK):
            port_num = index + 1
            eeprom_path = eeprom_base.format(port_num)
            if index not in _sfp_port:
                sfp_node = Sfp(index, 'QSFP', eeprom_path)
            else:
                sfp_node = Sfp(index, 'SFP', eeprom_path)
            self._sfp_list.append(sfp_node)

        self._eeprom = Eeprom()
        self._watchdog = Watchdog()
        self._num_sfps = self.PORT_END
        self._num_fans = MAX_S5232F_FANTRAY * MAX_S5232F_FAN
        self._fan_list = [Fan(i, j) for i in range(MAX_S5232F_FANTRAY) \
                            for j in range(MAX_S5232F_FAN)]
        self._psu_list = [Psu(i) for i in range(MAX_S5232F_PSU)]
        self._thermal_list = [Thermal(i) for i in range(MAX_S5232F_THERMAL)]
        self._component_list = [Component(i) for i in range(MAX_S5232F_COMPONENT)]

        for port_num in range(self.PORT_START, self.PORTS_IN_BLOCK):
            # sfp get uses zero-indexing, but port numbers start from 1
            presence = self.get_sfp(port_num).get_presence()
            self._global_port_pres_dict[port_num] = '1' if presence else '0'

    def __del__(self):
        if self.oir_fd != -1:
            self.epoll.unregister(self.oir_fd.fileno())
            self.epoll.close()
            self.oir_fd.close()

# check for this event change for sfp / do we need to handle timeout/sleep

    def get_change_event(self, timeout=0):
        from time import sleep
        """
        Returns a nested dictionary containing all devices which have
        experienced a change at chassis level
        """
        port_dict = {}
        change_dict = {}
        change_dict['sfp'] = port_dict
        elapsed_time_ms = 0
        sleep_time_ms = 500
        sleep_time = sleep_time_ms / 1000

        while True:
            for port_num in range(self.PORT_START, (self.PORT_END + 1)):
                presence = self.get_sfp(port_num).get_presence()
                if(presence and self._global_port_pres_dict[port_num] == '0'):
                    self._global_port_pres_dict[port_num] = '1'
                    port_dict[port_num] = '1'
                elif(not presence and
                     self._global_port_pres_dict[port_num] == '1'):
                    self._global_port_pres_dict[port_num] = '0'
                    port_dict[port_num] = '0'

                if(len(port_dict) > 0):
                    return True, change_dict 
            if timeout != 0:
                elapsed_time_ms += sleep_time_ms
                if elapsed_time_ms > timeout:
                    break

            sleep(sleep_time)
        return True, change_dict 

    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
        """
        sfp = None

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

    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_eeprom(self):
        """
        Retrieves the Sys Eeprom instance for the chassis.
        Returns :
            The instance of the Sys Eeprom
        """
        return self._eeprom

    def get_num_fans(self):
        """
        Retrives the number of Fans on the chassis.
        Returns :
            An integer represents the number of Fans on the chassis.
        """
        return self._num_fans 

    def get_num_sfps(self):
        """
        Retrives the numnber of Media on the chassis.
        Returns:
            An integer represences the number of SFPs on the chassis.
        """
        return self._num_sfps
Example #14
0
class Chassis(ChassisBase):
    NUM_THERMAL = 3
    NUM_FANDRAWER = 6
    NUM_FANSPERDRAWER = 2
    NUM_FAN = NUM_FANDRAWER * NUM_FANSPERDRAWER
    NUM_PSU = 2
    NUM_SFP = 34
    HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/"
    PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/"
    REBOOT_CAUSE_FILE = "reboot-cause.txt"
    PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
    HOST_CHK_CMD = "docker > /dev/null 2>&1"

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

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

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

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

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

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

        # initialize eeprom
        self._eeprom = Eeprom()

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

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

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

        return False, {}

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

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

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

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

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

        return False, {}

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

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

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

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

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

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

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

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

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

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

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

        return self._status_led.set_status(color)

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

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

        return self._status_led.get_status()

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

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

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

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

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

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

        return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause)
Example #15
0
class Psu(PsuBase):
    """DellEMC Platform-specific PSU class"""

    CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0/"
    I2C_DIR = "/sys/class/i2c-adapter/"

    def __init__(self, psu_index):
        # PSU is 1-based in DellEMC platforms
        self.index = psu_index + 1
        self.psu_presence_reg = "psu{}_prs".format(psu_index)
        self.psu_status_reg = "powersupply_status"

        if self.index == 1:
            ltc_dir = self.I2C_DIR + "i2c-11/11-0042/hwmon/"
        else:
            ltc_dir = self.I2C_DIR + "i2c-11/11-0040/hwmon/"
        hwmon_node = os.listdir(ltc_dir)[0]
        self.HWMON_DIR = ltc_dir + hwmon_node + '/'

        self.psu_voltage_reg = self.HWMON_DIR + "in1_input"
        self.psu_current_reg = self.HWMON_DIR + "curr1_input"
        self.psu_power_reg = self.HWMON_DIR + "power1_input"

        self.eeprom = Eeprom(is_psu=True, psu_index=self.index)

        # Overriding _fan_list class variable defined in PsuBase, to
        # make it unique per Psu object
        self._fan_list = []

        self._fan_list.append(Fan(self.index, psu_fan=True, dependency=self))

    def _get_cpld_register(self, reg_name):
        # On successful read, returns the value read from given
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'
        cpld_reg_file = self.CPLD_DIR + reg_name

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

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

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

    def _get_i2c_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:
            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 "PSU{}".format(self.index)

    def get_presence(self):
        """
        Retrieves the presence of the Power Supply Unit (PSU)

        Returns:
            bool: True if PSU is present, False if not
        """
        status = False
        psu_presence = self._get_cpld_register(self.psu_presence_reg)
        if (psu_presence != 'ERR'):
            psu_presence = int(psu_presence)
            if psu_presence:
                status = True

        return status

    def get_model(self):
        """
        Retrieves the part number of the PSU

        Returns:
            string: Part number of PSU
        """
        return self.eeprom.part_number_str()

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

        Returns:
            string: Serial number of PSU
        """
        # Sample Serial number format "US-01234D-54321-25A-0123-A00"
        return self.eeprom.serial_number_str()

    def get_status(self):
        """
        Retrieves the operational status of the PSU

        Returns:
            bool: True if PSU is operating properly, False if not
        """
        status = False
        psu_status = self._get_cpld_register(self.psu_status_reg)
        if (psu_status != 'ERR'):
            psu_status = (int(psu_status, 16) >> ((2 - self.index) * 4)) & 0xF
            if (~psu_status & 0b1000) and (~psu_status & 0b0100):
                status = True

        return status

    def get_voltage(self):
        """
        Retrieves current PSU voltage output

        Returns:
            A float number, the output voltage in volts,
            e.g. 12.1
        """
        psu_voltage = self._get_i2c_register(self.psu_voltage_reg)
        if (psu_voltage != 'ERR') and self.get_status():
            # Converting the value returned by driver which is in
            # millivolts to volts
            psu_voltage = float(psu_voltage) / 1000
        else:
            psu_voltage = 0.0

        return psu_voltage

    def get_current(self):
        """
        Retrieves present electric current supplied by PSU

        Returns:
            A float number, electric current in amperes,
            e.g. 15.4
        """
        psu_current = self._get_i2c_register(self.psu_current_reg)
        if (psu_current != 'ERR') and self.get_status():
            # Converting the value returned by driver which is in
            # milliamperes to amperes
            psu_current = float(psu_current) / 1000
        else:
            psu_current = 0.0

        return psu_current

    def get_power(self):
        """
        Retrieves current energy supplied by PSU

        Returns:
            A float number, the power in watts,
            e.g. 302.6
        """
        psu_power = self._get_i2c_register(self.psu_power_reg)
        if (psu_power != 'ERR') and self.get_status():
            # Converting the value returned by driver which is in
            # microwatts to watts
            psu_power = float(psu_power) / 1000000
        else:
            psu_power = 0.0

        return psu_power

    def get_powergood_status(self):
        """
        Retrieves the powergood status of PSU
        Returns:
            A boolean, True if PSU has stablized its output voltages and
            passed all its internal self-tests, False if not.
        """
        status = False
        psu_status = self._get_cpld_register(self.psu_status_reg)
        if (psu_status != 'ERR'):
            psu_status = (int(psu_status, 16) >> ((2 - self.index) * 4)) & 0xF
            if (psu_status == 0x2):
                status = True

        return status

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

        Returns:
            A string, one of the predefined STATUS_LED_COLOR_* strings.
        """
        if self.get_powergood_status():
            return self.STATUS_LED_COLOR_GREEN
        else:
            return self.STATUS_LED_COLOR_OFF

    def set_status_led(self, color):
        """
        Sets the state of the PSU status LED
        Args:
            color: A string representing the color with which to set the
                   PSU status LED
        Returns:
            bool: True if status LED state is set successfully, False if
                  not
        """
        # In S6000, the firmware running in the PSU controls the LED
        # and the PSU LED state cannot be changed from CPU.
        return False
Example #16
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    sysled_offset = 0x0024

    SYSLED_COLOR_TO_REG = {
        "blinking_green": 0x0,
        "green": 0x10,
        "amber": 0x20,
        "blinking_amber": 0x30
    }

    REG_TO_SYSLED_COLOR = {
        0x0: "blinking_green",
        0x10: "green",
        0x20: "amber",
        0x30: "blinking_amber"
    }

    _global_port_pres_dict = {}

    def __init__(self):
        ChassisBase.__init__(self)
        # sfp.py will read eeprom contents and retrive the eeprom data.
        # We pass the eeprom path from chassis.py
        _sfp_port = list(range(33, PORTS_IN_BLOCK))
        i2c_bus_for_port = 2
        i2c_mux_to_populate = 603
        i2c_mux_address = 70
        i2c_mux_is_good = False
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
        mux_channel = "/sys/class/i2c-adapter/i2c-{0}/{0}-00{1}/channel-0"
        for index in range(PORT_START, PORTS_IN_BLOCK):
            eeprom_path = ""
            if index % 8 == 1:  # 8 buses per i2c mux
                i2c_mux_is_good = True if os.path.exists(
                    mux_channel.format(i2c_mux_to_populate,
                                       i2c_mux_address)) else False
                i2c_mux_to_populate += 1
                i2c_mux_address += 1
            if i2c_mux_is_good:
                eeprom_path = eeprom_base.format(i2c_bus_for_port)
                i2c_bus_for_port += 1
            port_type = 'QSFP_DD' if index not in _sfp_port else 'SFP'
            sfp_node = Sfp(index, port_type, eeprom_path)
            self._sfp_list.append(sfp_node)

        self._eeprom = Eeprom()
        self._watchdog = Watchdog()
        self._num_sfps = PORT_END
        self._num_fans = MAX_Z9432F_FANTRAY * MAX_Z9432F_FAN

        for i in range(MAX_Z9432F_FANTRAY):
            fandrawer = FanDrawer(i)
            self._fan_drawer_list.append(fandrawer)
            self._fan_list.extend(fandrawer._fan_list)

        self._psu_list = [Psu(i) for i in range(MAX_Z9432F_PSU)]
        self._thermal_list = [Thermal(i) for i in range(MAX_Z9432F_THERMAL)]
        self._component_list = [
            Component(i) for i in range(MAX_Z9432F_COMPONENT)
        ]
        for port_num in range(PORT_START, PORTS_IN_BLOCK):
            presence = self.get_sfp(port_num).get_presence()
            self._global_port_pres_dict[port_num] = '1' if presence else '0'

        self._watchdog = Watchdog()
        #self.LOCATOR_LED_ON = self.STATUS_LED_COLOR_BLUE_BLINK
        #self.LOCATOR_LED_OFF = self.STATUS_LED_COLOR_OFF
        #ext_media_override()

# check for this event change for sfp / do we need to handle timeout/sleep

    def get_change_event(self, timeout=0):
        """
        Returns a nested dictionary containing all devices which have
        experienced a change at chassis level
        """
        start_ms = time.time() * 1000
        port_dict = {}
        change_dict = {}
        change_dict['sfp'] = port_dict
        while True:
            time.sleep(0.5)
            for port_num in range(PORT_START, (PORT_END + 1)):
                presence = self.get_sfp(port_num).get_presence()
                if presence and self._global_port_pres_dict[port_num] == '0':
                    self._global_port_pres_dict[port_num] = '1'
                    port_dict[port_num] = '1'
                elif (not presence
                      and self._global_port_pres_dict[port_num] == '1'):
                    self._global_port_pres_dict[port_num] = '0'
                    port_dict[port_num] = '0'

                if len(port_dict) > 0:
                    return True, change_dict

            if timeout:
                now_ms = time.time() * 1000
                if now_ms - start_ms >= timeout:
                    return True, change_dict

    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.
        """
        val = hwaccess.pci_get_value(PCI_RES, self.sysled_offset)
        if val != -1:
            val = val & 0x30
            return self.REG_TO_SYSLED_COLOR.get(val)
        return self.sys_ledcolor

    def initizalize_system_led(self):
        self.sys_ledcolor = "green"

    def set_status_led(self, color):
        """
        Sets the state of the system LED
        Args:
            color: A string representing the color with which to set the
                   system LED
        Returns:
            bool: True if system LED state is set successfully, False if not
        """
        if color not in list(self.SYSLED_COLOR_TO_REG.keys()):
            return False

        val = hwaccess.pci_get_value(PCI_RES, self.sysled_offset)
        val = (val & 0xFFCF) | self.SYSLED_COLOR_TO_REG[color]

        hwaccess.pci_set_value(PCI_RES, val, self.sysled_offset)
        self.sys_ledcolor = color
        return True

    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
        """
        sfp = None

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

    def get_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_revision(self):
        """
        Retrieves the hardware revision of the device

        Returns:
            string: Revision value of device
        """
        return self._eeprom.revision_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_eeprom(self):
        """
        Retrieves the Sys Eeprom instance for the chassis.
        Returns :
            The instance of the Sys Eeprom
        """
        return self._eeprom

    def get_num_fans(self):
        """
        Retrives the number of Fans on the chassis.
        Returns :
            An integer represents the number of Fans on the chassis.
        """
        return self._num_fans

    def get_num_sfps(self):
        """
        Retrives the numnber of Media on the chassis.
        Returns:
            An integer represences the number of SFPs on the chassis.
        """
        return self._num_sfps

    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.
        """
        try:
            with open(REBOOT_CAUSE_PATH) as filed:
                reboot_cause = int(filed.read(), 16)
        except EnvironmentError:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)

        if reboot_cause & 0x1:
            retval = (self.REBOOT_CAUSE_POWER_LOSS, None)
        elif reboot_cause & 0x2:
            retval = (self.REBOOT_CAUSE_NON_HARDWARE, None)
        elif reboot_cause & 0x4:
            retval = (self.REBOOT_CAUSE_HARDWARE_OTHER, "PSU Shutdown")
        elif reboot_cause & 0x8:
            retval = (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, None)
        elif reboot_cause & 0x10:
            retval = (self.REBOOT_CAUSE_WATCHDOG, None)
        elif reboot_cause & 0x20:
            retval = (self.REBOOT_CAUSE_HARDWARE_OTHER, "BMC Shutdown")
        elif reboot_cause & 0x40:
            retval = (self.REBOOT_CAUSE_HARDWARE_OTHER, "Hot-Swap Shutdown")
        elif reboot_cause & 0x80:
            retval = (self.REBOOT_CAUSE_HARDWARE_OTHER,
                      "Reset Button Shutdown")
        elif reboot_cause & 0x100:
            retval = (self.REBOOT_CAUSE_HARDWARE_OTHER,
                      "Reset Button Cold Reboot")
        else:
            retval = (self.REBOOT_CAUSE_NON_HARDWARE, None)
        return retval

    @staticmethod
    def get_qualified_media_list():
        """ Returns Dell Qualified Media List """
        return MEDIA_PART_NUM_LIST

    def set_locator_led(self, color):
        """
        Sets the state of the Chassis Locator LED

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

        Returns:
            bool: True if the Chassis Locator LED state is set successfully, False if not

        """
        val = hwaccess.pci_get_value(PCI_RES, SYSTEM_LED_REG)
        if self.LOCATOR_LED_ON == color:
            val = int(val) | SYSTEM_BEACON_LED_SET
        elif self.LOCATOR_LED_OFF == color:
            val = int(val) & SYSTEM_BEACON_LED_CLEAR
        else:
            return False
        hwaccess.pci_set_value(PCI_RES, val, SYSTEM_LED_REG)
        return True

    def get_locator_led(self):
        """
        Gets the state of the Chassis Locator LED

        Returns:
            LOCATOR_LED_ON or LOCATOR_LED_OFF
        """
        val = hwaccess.pci_get_value(PCI_RES, SYSTEM_LED_REG)
        val = int(val) & SYSTEM_BEACON_LED_SET
        if not val:
            return self.LOCATOR_LED_OFF
        else:
            return self.LOCATOR_LED_ON

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

    def is_replaceable(self):
        """
        Indicate whether Chassis is replaceable.
        Returns:
            bool: True if it is replaceable.
        """
        return False
Example #17
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    OIR_FD_PATH = "/sys/bus/pci/devices/0000:04:00.0/port_msi"

    oir_fd = -1
    epoll = -1

    _global_port_pres_dict = {}

    def __init__(self):
        ChassisBase.__init__(self)
        # sfp.py will read eeprom contents and retrive the eeprom data.
        # We pass the eeprom path from chassis.py
        self.PORT_START = 1
        self.PORT_END = 66
        PORTS_IN_BLOCK = (self.PORT_END + 1)
        _sfp_port = range(65, self.PORT_END + 1)
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"

        for index in range(self.PORT_START, PORTS_IN_BLOCK):
            port_num = index + 1
            eeprom_path = eeprom_base.format(port_num)
            if index not in _sfp_port:
                sfp_node = Sfp(index, 'QSFP', eeprom_path)
            else:
                sfp_node = Sfp(index, 'SFP', eeprom_path)
            self._sfp_list.append(sfp_node)

        self._eeprom = Eeprom()

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

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

        for port_num in range(self.PORT_START, (self.PORT_END + 1)):
            presence = self.get_sfp(port_num).get_presence()
            if presence:
                self._global_port_pres_dict[port_num] = '1'
            else:
                self._global_port_pres_dict[port_num] = '0'

    def __del__(self):
        if self.oir_fd != -1:
            self.epoll.unregister(self.oir_fd.fileno())
            self.epoll.close()
            self.oir_fd.close()

    def _get_register(self, reg_file):
        retval = 'ERR'
        if (not os.path.isfile(reg_file)):
            print reg_file, 'not found !'
            return retval

        try:
            with os.fdopen(os.open(reg_file, os.O_RDONLY)) as fd:
                retval = fd.read()
        except:
            pass
        retval = retval.rstrip('\r\n')
        retval = retval.lstrip(" ")
        return retval

    def _check_interrupts(self, port_dict):
        retval = 0
        is_port_dict_updated = False
        for port_num in range(self.PORT_START, (self.PORT_END + 1)):
            sfp = self.get_sfp(port_num)
            presence = sfp.get_presence()
            if (presence and (self._global_port_pres_dict[port_num] == '0')):
                is_port_dict_updated = True
                self._global_port_pres_dict[port_num] = '1'
                port_dict[port_num] = '1'
            elif (not presence
                  and (self._global_port_pres_dict[port_num] == '1')):
                is_port_dict_updated = True
                self._global_port_pres_dict[port_num] = '0'
                port_dict[port_num] = '0'
        return retval, is_port_dict_updated

    def get_change_event(self, timeout=0):
        """
        Returns a nested dictionary containing all devices which have
        experienced a change at chassis level
        """
        port_dict = {}
        change_dict = {}
        change_dict['sfp'] = port_dict
        try:
            # We get notified when there is a MSI interrupt (vector 4/5)CVR
            # Open the sysfs file and register the epoll object
            self.oir_fd = os.fdopen(os.open(self.OIR_FD_PATH, os.O_RDONLY))
            if self.oir_fd != -1:
                # Do a dummy read before epoll register
                self.oir_fd.read()
                self.epoll = select.epoll()
                self.epoll.register(self.oir_fd.fileno(),
                                    select.EPOLLIN & select.EPOLLET)
            else:
                print("get_transceiver_change_event : unable to create fd")
                return False, change_dict
            # Check for missed interrupts by invoking self._check_interrupts
            # which will update the port_dict.
            while True:
                interrupt_count_start = self._get_register(self.OIR_FD_PATH)
                retval, is_port_dict_updated = self._check_interrupts(
                    port_dict)
                if ((retval == 0) and (is_port_dict_updated is True)):
                    return True, change_dict
                interrupt_count_end = self._get_register(self.OIR_FD_PATH)
                if (interrupt_count_start == 'ERR'
                        or interrupt_count_end == 'ERR'):
                    print("get_transceiver_change_event : \
                        unable to retrive interrupt count")
                    break
                # check_interrupts() itself may take upto 100s of msecs.
                # We detect a missed interrupt based on the count
                if interrupt_count_start == interrupt_count_end:
                    break
            # Block until an xcvr is inserted or removed with timeout = -1
            events = self.epoll.poll(timeout=timeout if timeout != 0 else -1)
            if events:
                # check interrupts and return the change_dict
                retval, is_port_dict_updated = \
                                          self._check_interrupts(port_dict)
                if (retval != 0):
                    return False, change_dict
            return True, change_dict
        except:
            return False, change_dict
        finally:
            if self.oir_fd != -1:
                self.epoll.unregister(self.oir_fd.fileno())
                self.epoll.close()
                self.oir_fd.close()
                self.oir_fd = -1
                self.epoll = -1
        return False, change_dict

    def get_sfp(self, index):
        """
        Retrieves sfp represented by (1-based) index <index>

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

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

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

    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()
Example #18
0
class Chassis(ChassisBase):
    def __init__(self):
        ChassisBase.__init__(self)
        self.__num_of_psus = 2
        self.__num_of_ports = 54
        self.__num_of_sfps = 48
        self.__num_of_fans = 4
        self.__num_of_thermals = 6

        # Initialize EEPROM
        self._eeprom = Eeprom()

        # Initialize watchdog
        #self._watchdog = Watchdog()

        # Initialize FAN
        for index in range(1, self.__num_of_fans + 1):
            fan = Fan(index)
            self._fan_list.append(fan)

        # Initialize thermal
        for index in range(1, self.__num_of_thermals + 1):
            thermal = Thermal(index)
            self._thermal_list.append(thermal)

        # Initialize PSU and PSU_FAN
        for index in range(1, self.__num_of_psus + 1):
            psu = Psu(index)
            self._psu_list.append(psu)
            fan = Fan(index, True)
            self._fan_list.append(fan)

        # Initialize SFP
        for index in range(0, self.__num_of_ports):
            if index in range(0, self.__num_of_sfps):
                sfp = Sfp(index, 'SFP')
            else:
                sfp = Sfp(index, 'QSFP')

            self._sfp_list.append(sfp)

##############################################
# Device methods
##############################################

    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
        Returns:
            string: Serial number of chassis
        """
        return self._eeprom.serial_number_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

##############################################
# Chassis methods
##############################################

    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.
            Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
                  '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
                  '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
        """
        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.
        """
        raise NotImplementedError
Example #19
0
class Psu(PsuBase):
    """Nokia platform-specific PSU class for 7215 """
    def __init__(self, psu_index):
        PsuBase.__init__(self)
        # PSU is 1-based in Nokia platforms
        self.index = psu_index + 1
        self._fan_list = []

        # PSU eeprom
        self.eeprom = Eeprom(is_psu=True, psu_index=self.index)

    def _write_sysfs_file(self, sysfs_file, value):
        rv = 'ERR'

        if (not os.path.isfile(sysfs_file)):
            return rv
        try:
            with open(sysfs_file, 'w') as fd:
                rv = fd.write(str(value))
        except Exception as e:
            rv = 'ERR'

        return rv

    def _read_sysfs_file(self, sysfs_file):
        rv = 'ERR'

        if (not os.path.isfile(sysfs_file)):
            return rv
        try:
            with open(sysfs_file, 'r') as fd:
                rv = fd.read()
        except Exception as e:
            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 "PSU{}".format(self.index)

    def get_presence(self):
        """
        Retrieves the presence of the Power Supply Unit (PSU)

        Returns:
            bool: True if PSU is present, False if not
        """

        if smbus_present == 0:  # if called from psuutil outside of pmon
            cmdstatus, psustatus = cmd.getstatusoutput(
                'sudo i2cget -y 0 0x41 0xa')
            psustatus = int(psustatus, 16)
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICE_REG = 0xa
            psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)

        if self.index == 1:
            psustatus = psustatus & 1
            if psustatus == 1:
                return False
        if self.index == 2:
            psustatus = psustatus & 2
            if psustatus == 2:
                return False

        return True

    def get_model(self):
        """
        Retrieves the part number of the PSU

        Returns:
            string: Part number of PSU
        """
        return self.eeprom.modelstr()

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

        Returns:
            string: Serial number of PSU
        """
        return self.eeprom.serial_number_str()

    def get_revision(self):
        """
        Retrieves the HW revision of the PSU

        Returns:
            string: HW revision of PSU
        """
        return self.eeprom.part_number_str()

    def get_part_number(self):
        """
        Retrieves the part number of the PSU

        Returns:
            string: Part number of PSU
        """
        return self.eeprom.part_number_str()

    def get_status(self):
        """
        Retrieves the operational status of the PSU

        Returns:
            bool: True if PSU is operating properly, False if not
        """

        if smbus_present == 0:
            cmdstatus, psustatus = cmd.getstatusoutput(
                'sudo i2cget -y 0 0x41 0xa')
            psustatus = int(psustatus, 16)
            sonic_logger.log_warning("PMON psu-smbus - presence = 0 ")
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICE_REG = 0xa
            psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)

        if self.index == 1:
            psustatus = psustatus & 4
            if psustatus == 4:
                return True
        if self.index == 2:
            psustatus = psustatus & 8
            if psustatus == 8:
                return True

        return False

    def get_voltage(self):
        """
        Retrieves current PSU voltage output

        Returns:
            A float number, the output voltage in volts,
            e.g. 12.1
        """
        if smbus_present == 0:
            cmdstatus, psustatus = cmd.getstatusoutput(
                'sudo i2cget -y 0 0x41 0xa')
            psustatus = int(psustatus, 16)
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICE_REG = 0xa
            psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)

        if self.index == 1:
            psustatus = psustatus & 4
            if psustatus == 4:
                psu_voltage = 12.0
                return psu_voltage
        if self.index == 2:
            psustatus = psustatus & 8
            if psustatus == 8:
                psu_voltage = 12.0
                return psu_voltage

        psu_voltage = 0.0
        return psu_voltage

    def get_position_in_parent(self):
        """
        Retrieves 1-based relative physical position in parent device
        Returns:
            integer: The 1-based relative physical position in parent device
        """
        return self.index

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

    def get_powergood_status(self):
        """
        Retrieves the powergood status of PSU
        Returns:
            A boolean, True if PSU has stablized its output voltages and
            passed all its internal self-tests, False if not.
        """

        if smbus_present == 0:
            cmdstatus, psustatus = cmd.getstatusoutput(
                'sudo i2cget -y 0 0x41 0xa')
            psustatus = int(psustatus, 16)
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICE_REG = 0xa
            psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)

        if self.index == 1:
            psustatus = psustatus & 4
            if psustatus == 4:
                return True
        if self.index == 2:
            psustatus = psustatus & 8
            if psustatus == 8:
                return True

        return False

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

        Returns:
            A string, one of the predefined STATUS_LED_COLOR_* strings.
        """
        if self.get_powergood_status():
            return self.STATUS_LED_COLOR_GREEN
        else:
            return self.STATUS_LED_COLOR_OFF

    def set_status_led(self, color):
        """
        Sets the state of the PSU status LED
        Args:
            color: A string representing the color with which to set the
                   PSU status LED
        Returns:
            bool: True if status LED state is set successfully, False if
                  not
        """
        # The firmware running in the PSU controls the LED
        # and the PSU LED state cannot be changed from CPU.
        return False

    def get_status_master_led(self):
        """
        Gets the state of the front panel PSU status LED

        Returns:
            A string, one of the predefined STATUS_LED_COLOR_* strings.
        """
        if (not os.path.isfile("/sys/class/gpio/psuLedGreen/value")
                or not os.path.isfile("/sys/class/gpio/psuLedAmber/value")):
            return None

        green = self._read_sysfs_file("/sys/class/gpio/psuLedGreen/value")
        amber = self._read_sysfs_file("/sys/class/gpio/psuLedAmber/value")
        if green == "ERR" or amber == "ERR":
            return None
        if green == "1":
            return self.STATUS_LED_COLOR_GREEN
        elif amber == "1":
            return self.STATUS_LED_COLOR_AMBER
        else:
            return None

    def set_status_master_led(self, color):
        """
        Sets the state of the front panel PSU status LED

        Returns:
            bool: True if status LED state is set successfully, False if
                  not
        """
        if (not os.path.isfile("/sys/class/gpio/psuLedGreen/value")
                or not os.path.isfile("/sys/class/gpio/psuLedAmber/value")):
            return False

        if color == self.STATUS_LED_COLOR_GREEN:
            rvg = self._write_sysfs_file("/sys/class/gpio/psuLedGreen/value",
                                         1)
            if rvg != "ERR":
                rva = self._write_sysfs_file(
                    "/sys/class/gpio/psuLedAmber/value", 0)
        elif color == self.STATUS_LED_COLOR_AMBER:
            rvg = self._write_sysfs_file("/sys/class/gpio/psuLedGreen/value",
                                         0)
            if rvg != "ERR":
                rva = self._write_sysfs_file(
                    "/sys/class/gpio/psuLedAmber/value", 1)
        else:
            return False

        if rvg == "ERR" or rva == "ERR":
            return False

        return True
Example #20
0
class Chassis(ChassisBase):

    def __init__(self):
        ChassisBase.__init__(self)
        self.__num_of_fans     = 8
        self.__num_of_psus     = 2
        self.__num_of_sfps     = 56
        self.__start_of_qsfp   = 48
        self.__num_of_thermals = 5

        # Initialize EEPROM
        self._eeprom = Eeprom()

        # Initialize FAN
        for index in range(1, self.__num_of_fans + 1):
            fan = Fan(index, False, 0)
            self._fan_list.append(fan)

        # Initialize PSU
        for index in range(1, self.__num_of_psus + 1):
            psu = Psu(index)
            self._psu_list.append(psu)

        # Initialize SFP
        for index in range(0, self.__num_of_sfps):
            if index < self.__start_of_qsfp:
                sfp = Sfp(index)
            else:
                sfp = QSfp(index)
            self._sfp_list.append(sfp)

        # Initialize THERMAL
        for index in range(0, self.__num_of_thermals):
            thermal = Thermal(index)
            self._thermal_list.append(thermal)

        # Initialize TRANSCEIVER EVENT MONITOR
        self.__xcvr_event = TransceiverEvent()

##############################################
# Device methods
##############################################

    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
        Returns:
            string: Serial number of chassis
        """
        return self._eeprom.serial_number_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

##############################################
# Chassis methods
##############################################

    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_address()

    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.
            Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
                  '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
                  '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
        """
        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.
        """
        raise NotImplementedError

##############################################
# Other methods
##############################################

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

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

        Returns:
            (bool, dict):
                - True if call successful, False if not;
                - A nested dictionary where key is a device type,
                  value is a dictionary with key:value pairs in the format of
                  {'device_id':'device_event'},
                  where device_id is the device ID for this device and
                        device_event,
                             status='1' represents device inserted,
                             status='0' represents device removed.
                  Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
                      indicates that fan 0 has been removed, fan 2
                      has been inserted and sfp 11 has been removed.
        """

        rc, xcvr_event = self.__xcvr_event.get_transceiver_change_event(timeout) 

        return rc, {'sfp': xcvr_event}
Example #21
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """
    CPLD_DIR = '/sys/devices/platform/dell-n3248te-cpld.0/'

    _global_port_pres_dict = {}

    _sfpp_port_to_i2c_mapping = {
            49: 20,
            50: 21,
            51: 22,
            52: 23,
            53: 24,
            54: 25,
            }

    def __init__(self):
        ChassisBase.__init__(self)
        # sfp.py will read eeprom contents and retrive the eeprom data.
        # We pass the eeprom path from chassis.py
        self.PORT_START = 1
        self.PORT_END = 54
        self.PORTS_IN_BLOCK = (self.PORT_END + 1)
        self.SFP_PORT_START = 49
        self._sfp_port = range(self.SFP_PORT_START, self.PORTS_IN_BLOCK)
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
        for index in range(self.PORT_START, self.PORTS_IN_BLOCK):
            eeprom_path = ''
            if index in self._sfp_port:
                eeprom_path = eeprom_base.format(self._sfpp_port_to_i2c_mapping[index])
            if(index < 53):
                port_type = 'SFP'
            else:
                port_type = 'QSFP'

            sfp_node = Sfp(index, port_type, eeprom_path)
            self._sfp_list.append(sfp_node)

        self._eeprom = Eeprom()
        self._watchdog = Watchdog()
        self._num_sfps = 54
        self._num_fans =  MAX_N3248TE_FANTRAY * MAX_N3248TE_FAN
        self._fan_list = [Fan(i, j) for i in range(MAX_N3248TE_FANTRAY) \
                            for j in range(MAX_N3248TE_FAN)]
        for k in range(MAX_N3248TE_FANTRAY):
            fandrawer = FanDrawer(k)
            self._fan_drawer_list.append(fandrawer)
            self._fan_list.extend(fandrawer._fan_list)

        self._psu_list = [Psu(i) for i in range(MAX_N3248TE_PSU)]
        self._thermal_list = [Thermal(i) for i in range(MAX_N3248TE_THERMAL)]
        self._component_list = [Component(i) for i in range(MAX_N3248TE_COMPONENT)]
        for port_num in self._sfp_port:
            # sfp get uses zero-indexing, but port numbers start from 1
            presence = self.get_sfp(port_num-1).get_presence()
            self._global_port_pres_dict[port_num] = '1' if presence else '0'

        self._watchdog = Watchdog()
        self.locator_led_reg = "locator_led"
        self.LOCATOR_LED_ON = "blink_blue"
        self.LOCATOR_LED_OFF = self.STATUS_LED_COLOR_OFF

    def _get_cpld_register(self, reg_name):
        # On successful read, returns the value read from given
        # reg name and on failure rethrns 'ERR'
        cpld_reg_file = self.CPLD_DIR + '/' + reg_name
        try:
            rv = open(cpld_reg_file, 'r').read()
        except IOError : return 'ERR'
        return rv.strip('\r\n').lstrip(' ')

    def _set_cpld_register(self, reg_name, value):
        # On successful write, returns the value will be written on
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'
        cpld_reg_file = self.CPLD_DIR + '/' + reg_name

        if (not os.path.isfile(cpld_reg_file)):
            #print "open error"
            return rv

        try:
           with open(cpld_reg_file, 'w') as fd:
                rv = fd.write(str(value))
        except Exception:
            rv = 'ERR'

        return rv

# check for this event change for sfp / do we need to handle timeout/sleep

    def get_change_event(self, timeout=0):
        """
        Returns a nested dictionary containing all devices which have
        experienced a change at chassis level
        """
        port_dict = {}
        change_dict = {}
        change_dict['sfp'] = port_dict
        while True:
            for port_num in self._sfp_port:
                # sfp get uses zero-indexing, but port numbers start from 1
                presence = self.get_sfp(port_num-1).get_presence()
                if(presence and self._global_port_pres_dict[port_num] == '0'):
                    self._global_port_pres_dict[port_num] = '1'
                    port_dict[port_num] = '1'
                elif(not presence and self._global_port_pres_dict[port_num] == '1'):
                    self._global_port_pres_dict[port_num] = '0'
                    port_dict[port_num] = '0'

                if(len(port_dict) > 0):
                    return True, change_dict

            time.sleep(0.5)



    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
        """
        sfp = None

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

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

    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_cpld_register('reboot_cause'), 16)

        if (reset_reason & 0x02) :
            return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, 'Shutdown by CPU')
        elif (reset_reason & 0x04) :
            return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, "Failed to boot from configured boot device")
        elif (reset_reason & 0x8) :
            return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, "Booted from Backup BIOS")
        elif (reset_reason & 0x10) :
            return(ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
        elif (reset_reason & 0x20):
            return(ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU)
        elif (reset_reason & 0x40) :
            return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, 'Warm Reset')
        elif (reset_reason & 0x80) :
            return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, 'Cold Reset')
        elif (reset_reason & 0x01) :
            return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)

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

    def get_num_fans(self):
        """
        Retrives the number of Fans on the chassis.
        Returns :
            An integer represents the number of Fans on the chassis.
        """
        return self._num_fans

    def get_num_sfps(self):
        """
        Retrives the numnber of Media on the chassis.
        Returns:
            An integer represences the number of SFPs on the chassis.
        """
        return self._num_sfps

    def get_qualified_media_list(self):
        return media_part_num_list

    def set_locator_led(self, color):
        """
        Sets the state of the Chassis Locator LED

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

        Returns:
            bool: True if the Chassis Locator LED state is set successfully, False if not

        """
        if color == self.LOCATOR_LED_ON or color == self.LOCATOR_LED_OFF:
            rv = self._set_cpld_register(self.locator_led_reg, color)
            if (rv != 'ERR'):
                return True
        else:
            return False

    def get_locator_led(self):
        """
        Gets the state of the Chassis Locator LED

        Returns:
            LOCATOR_LED_ON or LOCATOR_LED_OFF
        """
        loc_led = self._get_cpld_register(self.locator_led_reg)
        if (loc_led != 'ERR'):
            # Actually driver returns the color code 'blink_blue'
            # Returning "blue_blink" to make it common to all platforms output
            if (loc_led == self.LOCATOR_LED_ON):
                self.LOCATOR_LED_ON = self.STATUS_LED_COLOR_BLUE_BLINK
                return self.LOCATOR_LED_ON
            else:
                return self.LOCATOR_LED_OFF
        else:
            return self.LOCATOR_LED_OFF
Example #22
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    REBOOT_CAUSE_PATH = "/host/reboot-cause/platform/reboot_reason"
    OIR_FD_PATH = "/sys/bus/pci/devices/0000:03:00.0/port_msi"

    oir_fd = -1
    epoll = -1

    _global_port_pres_dict = {}

    def __init__(self):
        ChassisBase.__init__(self)
        # sfp.py will read eeprom contents and retrive the eeprom data.
        # We pass the eeprom path from chassis.py
        self.PORT_START = 1
        self.PORT_END = 15
        PORTS_IN_BLOCK = (self.PORT_END + 1)
        _qsfp_port = range(13, self.PORT_END + 1)
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"

        for index in range(self.PORT_START, PORTS_IN_BLOCK):
            port_num = index + 1
            eeprom_path = eeprom_base.format(port_num)
            if index in _qsfp_port:
                sfp_node = Sfp(index, 'QSFP', eeprom_path)
            else:
                sfp_node = Sfp(index, 'SFP', eeprom_path)
            self._sfp_list.append(sfp_node)

        self._eeprom = Eeprom()

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

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

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

        for i in range(MAX_S5212F_FANTRAY):
            for j in range(MAX_S5212F_FAN):
                fan = Fan(i, j)
                self._fan_list.append(fan)

        for i in range(MAX_S5212F_FANTRAY):
            fandrawer = FanDrawer(i)
            self._fan_drawer_list.append(fandrawer)
            self._fan_list.extend(fandrawer._fan_list)

        for port_num in range(self.PORT_START, (self.PORT_END + 1)):
            # sfp get uses zero-indexing, but port numbers start from 1
            presence = self.get_sfp(port_num).get_presence()
            if presence:
                self._global_port_pres_dict[port_num] = '1'
            else:
                self._global_port_pres_dict[port_num] = '0'

        self._watchdog = Watchdog()

    def __del__(self):
        if self.oir_fd != -1:
            self.epoll.unregister(self.oir_fd.fileno())
            self.epoll.close()
            self.oir_fd.close()

# not needed /delete after validation

    def _get_register(self, reg_file):
        retval = 'ERR'
        if (not os.path.isfile(reg_file)):
            print(reg_file, 'not found !')
            return retval

        try:
            with os.fdopen(os.open(reg_file, os.O_RDONLY)) as fd:
                retval = fd.read()
        except Exception:
            pass
        retval = retval.rstrip('\r\n')
        retval = retval.lstrip(" ")
        return retval

# not needed /delete after validation

    def _check_interrupts(self, port_dict):
        retval = 0
        is_port_dict_updated = False
        for port_num in range(self.PORT_START, (self.PORT_END + 1)):
            # sfp get uses zero-indexing, but port numbers start from 1
            sfp = self.get_sfp(port_num - 1)
            presence = sfp.get_presence()
            if (presence and (self._global_port_pres_dict[port_num] == '0')):
                is_port_dict_updated = True
                self._global_port_pres_dict[port_num] = '1'
                port_dict[port_num] = '1'
            elif (not presence
                  and (self._global_port_pres_dict[port_num] == '1')):
                is_port_dict_updated = True
                self._global_port_pres_dict[port_num] = '0'
                port_dict[port_num] = '0'
        return retval, is_port_dict_updated

# check for this event change for sfp / do we need to handle timeout/sleep

    def get_change_event(self, timeout=0):
        """
        Returns a nested dictionary containing all devices which have
        experienced a change at chassis level
        """
        start_ms = time.time() * 1000
        port_dict = {}
        change_dict = {}
        change_dict['sfp'] = port_dict
        while True:
            time.sleep(0.5)
            for port_num in range(self.PORT_START, (self.PORT_END + 1)):
                presence = self.get_sfp(port_num - 1).get_presence()
                if (presence and self._global_port_pres_dict[port_num] == '0'):
                    self._global_port_pres_dict[port_num] = '1'
                    port_dict[port_num] = '1'
                    self.get_sfp(port_num - 1)._initialize_media(delay=True)
                elif (not presence
                      and self._global_port_pres_dict[port_num] == '1'):
                    self._global_port_pres_dict[port_num] = '0'
                    port_dict[port_num] = '0'

            if (len(port_dict) > 0):
                return True, change_dict

            if timeout:
                now_ms = time.time() * 1000
                if (now_ms - start_ms >= timeout):
                    return True, change_dict

    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
        """
        sfp = None

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

    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_revision(self):
        """
        Retrieves the revision number of the chassis (Service tag)
        Returns:
            string: Revision number of chassis
        """
        return self._eeprom.revision_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.
        """
        try:
            with open(self.REBOOT_CAUSE_PATH) as fd:
                reboot_cause = int(fd.read(), 16)
        except Exception:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)

        if reboot_cause & 0x1:
            return (self.REBOOT_CAUSE_POWER_LOSS, "Power on reset")
        elif reboot_cause & 0x2:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)
        elif reboot_cause & 0x4:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "PSU Shutdown")
        elif reboot_cause & 0x8:
            return (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, "Thermal overload")
        elif reboot_cause & 0x10:
            return (self.REBOOT_CAUSE_WATCHDOG, "Watchdog reset")
        elif reboot_cause & 0x20:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "BMC Shutdown")
        elif reboot_cause & 0x40:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Hot-Swap Shutdown")
        elif reboot_cause & 0x80:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Shutdown")
        elif reboot_cause & 0x100:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER,
                    "Reset Button Cold Reboot")
        else:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)

    def get_qualified_media_list(self):
        return media_part_num_list
Example #23
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """
    CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0"

    sfp_control = ""
    PORT_START = 0
    PORT_END = 0
    reset_reason_dict = {}
    reset_reason_dict[0xe] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
    reset_reason_dict[0x6] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE

    def __init__(self):
        ChassisBase.__init__(self)
        # Initialize SFP list
        self.PORT_START = 0
        self.PORT_END = 31
        EEPROM_OFFSET = 20
        PORTS_IN_BLOCK = (self.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}/{0}-0050/eeprom"
        self.sfp_control = "/sys/devices/platform/dell-s6000-cpld.0/"

        for index in range(0, PORTS_IN_BLOCK):
            eeprom_path = eeprom_base.format(index + EEPROM_OFFSET)
            sfp_node = Sfp(index, 'QSFP', eeprom_path, self.sfp_control, index)
            self._sfp_list.append(sfp_node)

        # Get Transceiver status
        self.modprs_register = self._get_transceiver_status()

        self._eeprom = Eeprom()
        for i in range(MAX_S6000_FAN):
            fan = Fan(i)
            self._fan_list.append(fan)

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

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

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

    def _get_cpld_register(self, reg_name):
        rv = 'ERR'
        mb_reg_file = self.CPLD_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
        """
        # In S6000, We track the reboot reason by writing the reason in
        # NVRAM. Only Warmboot and Coldboot reason are supported here.
        # Since it does not support any hardware reason, we return
        # non_hardware as default

        lrr = self._get_cpld_register('last_reboot_reason')
        if (lrr != 'ERR'):
            reset_reason = int(lrr, base=16)
            if (reset_reason in self.reset_reason_dict):
                return (self.reset_reason_dict[reset_reason], None)

        return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)

    def _get_transceiver_status(self):
        presence_ctrl = self.sfp_control + 'qsfp_modprs'
        try:
            reg_file = open(presence_ctrl)

        except IOError as e:
            return False

        content = reg_file.readline().rstrip()
        reg_file.close()

        return int(content, 16)

    def get_transceiver_change_event(self, timeout=0):
        """
        Returns a dictionary containing sfp changes which have
        experienced a change at chassis level
        """
        start_time = time.time()
        port_dict = {}
        port = self.PORT_START
        forever = False

        if timeout == 0:
            forever = True
        elif timeout > 0:
            timeout = timeout / float(1000) # Convert to secs
        else:
            return False, {}
        end_time = start_time + timeout

        if (start_time > end_time):
            return False, {} # Time wrap or possibly incorrect timeout

        while (timeout >= 0):
            # Check for OIR events and return updated port_dict
            reg_value = self._get_transceiver_status()
            if (reg_value != self.modprs_register):
                changed_ports = (self.modprs_register ^ reg_value)
                while (port >= self.PORT_START and port <= self.PORT_END):
                    # Mask off the bit corresponding to our port
                    mask = (1 << port)
                    if (changed_ports & mask):
                        # ModPrsL is active low
                        if reg_value & mask == 0:
                            port_dict[port] = '1'
                        else:
                            port_dict[port] = '0'
                    port += 1

                # Update reg value
                self.modprs_register = reg_value
                return True, port_dict

            if forever:
                time.sleep(1)
            else:
                timeout = end_time - time.time()
                if timeout >= 1:
                    time.sleep(1) # We poll at 1 second granularity
                else:
                    if timeout > 0:
                        time.sleep(timeout)
                    return True, {}
        return False, {}
Example #24
0
class Fan(FanBase):
    """DellEMC Platform-specific Fan class"""

    CPLD_DIR = "/sys/devices/platform/dell-s6000-cpld.0/"
    I2C_DIR = "/sys/class/i2c-adapter/"

    def __init__(self, fan_index, psu_fan=False):
        # Fan is 1-based in DellEMC platforms
        self.index = fan_index + 1
        self.is_psu_fan = psu_fan

        if not self.is_psu_fan:
            self.fan_presence_reg = "fan_prs"
            self.fan_led_reg = "fan{}_led".format(fan_index)
            self.get_fan_speed_reg = self.I2C_DIR + "i2c-11/11-0029/" +\
                    "fan{}_input".format(self.index)
            self.set_fan_speed_reg = self.I2C_DIR + "i2c-11/11-0029/" +\
                    "fan{}_target".format(self.index)
            self.eeprom = Eeprom(is_fan=True, fan_index=self.index)
            self.max_fan_speed = MAX_S6000_FAN_SPEED
            self.supported_led_color = ['off', 'green', 'amber']
        else:
            self.get_fan_speed_reg = self.I2C_DIR + "i2c-1/1-005{}/" +\
                    "fan1_input".format(10 - self.index)

    def _get_cpld_register(self, reg_name):
        # On successful read, returns the value read from given
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'
        cpld_reg_file = self.CPLD_DIR + reg_name

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

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

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

    def _set_cpld_register(self, reg_name, value):
        # On successful write, returns the value will be written on
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'
        cpld_reg_file = self.CPLD_DIR + reg_name

        if (not os.path.isfile(cpld_reg_file)):
            print "open error"
            return rv

        try:
            with open(cpld_reg_file, 'w') as fd:
                rv = fd.write(str(value))
        except:
            rv = 'ERR'

        return rv

    def _get_i2c_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:
            rv = 'ERR'

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

    def _set_i2c_register(self, reg_file, value):
        # On successful write, the value read will be written on
        # reg_name and on failure returns 'ERR'
        rv = 'ERR'

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

        try:
            with open(reg_file, 'w') as fd:
                rv = fd.write(str(value))
        except:
            rv = 'ERR'

        return rv

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

        Returns:
            string: The name of the Fan
        """
        if not self.is_psu_fan:
            return "Fan{}".format(self.index)
        else:
            return "PSU{} Fan".format(self.index)

    def get_presence(self):
        """
        Retrieves the presence of the Fan Unit

        Returns:
            bool: True if Fan is present, False if not
        """
        status = False
        fan_presence = self._get_cpld_register(self.fan_presence_reg)
        if (fan_presence != 'ERR'):
            fan_presence = int(fan_presence, 16) & self.index
            if fan_presence:
                status = True

        return status

    def get_model(self):
        """
        Retrieves the part number of the Fan

        Returns:
            string: Part number of Fan
        """
        return self.eeprom.part_number_str()

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

        Returns:
            string: Serial number of Fan
        """
        # Sample Serial number format "US-01234D-54321-25A-0123-A00"
        return self.eeprom.serial_number_str()

    def get_status(self):
        """
        Retrieves the operational status of the Fan

        Returns:
            bool: True if Fan is operating properly, False if not
        """
        status = False
        fan_speed = self._get_i2c_register(self.get_fan_speed_reg)
        if (fan_speed != 'ERR'):
            if (int(fan_speed) > 14000):
                status = True

        return status

    def get_direction(self):
        """
        Retrieves the fan airflow direction

        Returns:
            A string, either FAN_DIRECTION_INTAKE or
            FAN_DIRECTION_EXHAUST depending on fan direction
        """
        direction = {1: 'FAN_DIRECTION_INTAKE', 2: 'FAN_DIRECTION_EXHAUST'}
        fan_direction = self.eeprom.airflow_fan_type()

        return direction.get(fan_direction, 'NA')

    def get_speed(self):
        """
        Retrieves the speed of fan

        Returns:
            int: percentage of the max fan speed
        """
        fan_speed = self._get_i2c_register(self.get_fan_speed_reg)
        if (fan_speed != 'ERR') and self.get_presence():
            speed_in_rpm = int(fan_speed, 10)
            speed = (100 * speed_in_rpm) / self.max_fan_speed
        else:
            speed = 0

        return speed

    def get_speed_tolerance(self):
        """
        Retrieves the speed tolerance of the fan

        Returns:
            An integer, the percentage of variance from target speed
            which is considered tolerable
        """
        if self.get_presence():
            # The tolerance value is fixed as 20% for all the DellEmc platform
            tolerance = 20
        else:
            tolerance = 0

        return tolerance

    def set_speed(self, speed):
        """
        Set fan speed to expected value
        Args:
            speed: An integer, the percentage of full fan speed to set
            fan to, in the range 0 (off) to 100 (full speed)
        Returns:
            bool: True if set success, False if fail.
        """
        fan_set = (speed * self.max_fan_speed) / 100
        rv = self._set_i2c_register(self.set_fan_speed_reg, fan_set)
        if (rv != 'ERR'):
            return True
        else:
            return False

    def set_status_led(self, color):
        """
        Set led to expected color
        Args:
            color: A string representing the color with which to set the
                   fan module status LED
        Returns:
            bool: True if set success, False if fail.
        """
        if color not in self.supported_led_color:
            return False
        if (color == self.STATUS_LED_COLOR_AMBER):
            color = 'yellow'

        rv = self._set_cpld_register(self.fan_led_reg, color)
        if (rv != 'ERR'):
            return True
        else:
            return False

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

        Returns:
            A string, one of the predefined STATUS_LED_COLOR_* strings.
        """
        fan_led = self._get_cpld_register(self.fan_led_reg)
        if (fan_led != 'ERR'):
            if (fan_led == 'yellow'):
                return self.STATUS_LED_COLOR_AMBER
            else:
                return fan_led
        else:
            return self.STATUS_LED_COLOR_OFF

    def get_target_speed(self):
        """
        Retrieves the target (expected) speed of the fan

        Returns:
            An integer, the percentage of full fan speed, in the range 0
            (off) to 100 (full speed)
        """
        return 79
Example #25
0
class PddfChassis(ChassisBase):
    """
    PDDF Generic Chassis class
    """
    pddf_obj = {}
    plugin_data = {}

    def __init__(self, pddf_data=None, pddf_plugin_data=None):

        ChassisBase.__init__(self)

        self.pddf_obj = pddf_data if pddf_data else None
        self.plugin_data = pddf_plugin_data if pddf_plugin_data else None
        if not self.pddf_obj or not self.plugin_data:
            try:
                from . import pddfparse
                import json
                self.pddf_obj = pddfparse.PddfParse()
                with open(
                        '/usr/share/sonic/platform/pddf/pd-plugin.json') as pd:
                    self.plugin_data = json.load(pd)
            except Exception as e:
                raise Exception("Error: Unable to load PDDF JSON data - %s" %
                                str(e))

        self.platform_inventory = self.pddf_obj.get_platform()

        # Initialize EEPROM
        self.sys_eeprom = Eeprom(self.pddf_obj, self.plugin_data)

        # FANs
        for i in range(self.platform_inventory['num_fantrays']):
            for j in range(self.platform_inventory['num_fans_pertray']):
                fan = Fan(i, j, self.pddf_obj, self.plugin_data)
                self._fan_list.append(fan)

        # PSUs
        for i in range(self.platform_inventory['num_psus']):
            psu = Psu(i, self.pddf_obj, self.plugin_data)
            self._psu_list.append(psu)

        # OPTICs
        for index in range(self.platform_inventory['num_ports']):
            sfp = Sfp(index, self.pddf_obj, self.plugin_data)
            self._sfp_list.append(sfp)

        # THERMALs
        for i in range(self.platform_inventory['num_temps']):
            thermal = Thermal(i, self.pddf_obj, self.plugin_data)
            self._thermal_list.append(thermal)

        # SYSTEM LED Test Cases
        """
	#comment out test cases
	sys_led_list= { "LOC":0,
			"DIAG":0, 
			"FAN":0,
			"SYS":0, 
			"PSU1":0,
			"PSU2":1
		      }  

	for led in sys_led_list:
		color=self.get_system_led(led, sys_led_list[led])
		print color

	self.set_system_led("LOC_LED","STATUS_LED_COLOR_GREEN")
	color=self.get_system_led("LOC_LED")
	print "Set Green: " + color
	self.set_system_led("LOC_LED", "STATUS_LED_COLOR_OFF")
	color=self.get_system_led("LOC_LED")
	print "Set off: " + color
	"""

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

    def get_component_name_list(self):
        """
        Retrieves a list of the names of components available on the chassis (e.g., BIOS, CPLD, FPGA, etc.)

        Returns:
            A list containing the names of components available on the chassis
        """
        return self._component_name_list

    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
        """
        raise NotImplementedError

    def install_component_firmware(self, component_name, image_path):
        """
        Install firmware to component
        Args:
            component_name: A string, the component name.
            image_path: A string, path to firmware image.

        Returns:
            A boolean, True if install was successful, False if not
        """
        raise NotImplementedError

    ##############################################
    # Module methods
    ##############################################

    def get_num_modules(self):
        """
        Retrieves the number of modules available on this chassis

        Returns:
            An integer, the number of modules available on this chassis
        """
        return len(self._module_list)

    def get_all_modules(self):
        """
        Retrieves all modules available on this chassis

        Returns:
            A list of objects derived from ModuleBase representing all
            modules available on this chassis
        """
        return self._module_list

    def get_module(self, index):
        """
        Retrieves module represented by (0-based) index <index>

        Args:
            index: An integer, the index (0-based) of the module to
            retrieve

        Returns:
            An object dervied from ModuleBase representing the specified
            module
        """
        module = None

        try:
            module = self._module_list[index]
        except IndexError:
            sys.stderr.write("Module index {} out of range (0-{})\n".format(
                index,
                len(self._module_list) - 1))

        return module

    ##############################################
    # Fan methods
    ##############################################

    def get_num_fans(self):
        """
        Retrieves the number of fans available on this chassis

        Returns:
            An integer, the number of fan modules available on this chassis
        """
        return len(self._fan_list)

    def get_all_fans(self):
        """
        Retrieves all fan modules available on this chassis

        Returns:
            A list of objects derived from FanBase representing all fan
            modules available on this chassis
        """
        return self._fan_list

    def get_fan(self, index):
        """
        Retrieves fan module represented by (0-based) index <index>

        Args:
            index: An integer, the index (0-based) of the fan module to
            retrieve

        Returns:
            An object dervied from FanBase representing the specified fan
            module
        """
        fan = None

        try:
            fan = self._fan_list[index]
        except IndexError:
            sys.stderr.write("Fan index {} out of range (0-{})\n".format(
                index,
                len(self._fan_list) - 1))

        return fan

    ##############################################
    # PSU methods
    ##############################################

    def get_num_psus(self):
        """
        Retrieves the number of power supply units available on this chassis

        Returns:
            An integer, the number of power supply units available on this
            chassis
        """
        return len(self._psu_list)

    def get_all_psus(self):
        """
        Retrieves all power supply units available on this chassis

        Returns:
            A list of objects derived from PsuBase representing all power
            supply units available on this chassis
        """
        return self._psu_list

    def get_psu(self, index):
        """
        Retrieves power supply unit represented by (0-based) index <index>

        Args:
            index: An integer, the index (0-based) of the power supply unit to
            retrieve

        Returns:
            An object dervied from PsuBase representing the specified power
            supply unit
        """
        psu = None

        try:
            psu = self._psu_list[index]
        except IndexError:
            sys.stderr.write("PSU index {} out of range (0-{})\n".format(
                index,
                len(self._psu_list) - 1))

        return psu

    ##############################################
    # THERMAL methods
    ##############################################

    def get_num_thermals(self):
        """
        Retrieves the number of thermals available on this chassis

        Returns:
            An integer, the number of thermals available on this chassis
        """
        return len(self._thermal_list)

    def get_all_thermals(self):
        """
        Retrieves all thermals available on this chassis

        Returns:
            A list of objects derived from ThermalBase representing all thermals
            available on this chassis
        """
        return self._thermal_list

    def get_thermal(self, index):
        """
        Retrieves thermal unit represented by (0-based) index <index>

        Args:
            index: An integer, the index (0-based) of the thermal to
            retrieve

        Returns:
            An object dervied from ThermalBase representing the specified thermal
        """
        thermal = None

        try:
            thermal = self._thermal_list[index]
        except IndexError:
            sys.stderr.write("THERMAL index {} out of range (0-{})\n".format(
                index,
                len(self._thermal_list) - 1))

        return thermal

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

    ##############################################
    # System LED  methods
    ##############################################
    def set_system_led(self, led_device_name, color):
        result, msg = self.pddf_obj.is_supported_sysled_state(
            led_device_name, color)
        if result == False:
            print(msg)
            return (False)

        index = self.pddf_obj.data[led_device_name]['dev_attr']['index']
        device_name = self.pddf_obj.data[led_device_name]['dev_info'][
            'device_name']
        self.pddf_obj.create_attr('device_name', device_name,
                                  self.pddf_obj.get_led_path())
        self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path())
        self.pddf_obj.create_attr('color', color,
                                  self.pddf_obj.get_led_cur_state_path())
        self.pddf_obj.create_attr('dev_ops', 'set_status',
                                  self.pddf_obj.get_led_path())
        return (True)

    def get_system_led(self, led_device_name):
        if led_device_name not in self.pddf_obj.data.keys():
            status = "[FAILED] " + led_device_name + " is not configured"
            return (status)

        index = self.pddf_obj.data[led_device_name]['dev_attr']['index']
        device_name = self.pddf_obj.data[led_device_name]['dev_info'][
            'device_name']
        self.pddf_obj.create_attr('device_name', device_name,
                                  self.pddf_obj.get_led_path())
        self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path())
        self.pddf_obj.create_attr('dev_ops', 'get_status',
                                  self.pddf_obj.get_led_path())
        color = self.pddf_obj.get_led_color()
        return (color)

    ##############################################
    # Other methods
    ##############################################

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

        Returns:
            An object derived from WatchdogBase representing the hardware
            watchdog device
        """
        return self._watchdog

    def get_eeprom(self):
        """
        Retreives eeprom device on this chassis

        Returns:
            An object derived from WatchdogBase representing the hardware
            eeprom device
        """
        return self.sys_eeprom

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

        Args:
            timeout: Timeout in milliseconds (optional). If timeout == 0,
                this method will block until a change is detected.
        Returns:
            (bool, dict):
                - True if call successful, False if not;
                - A nested dictionary where key is a device type,
                  value is a dictionary with key:value pairs in the format of
                  {'device_id':'device_event'},
                  where device_id is the device ID for this device and
                        device_event,
                             status='1' represents device inserted,
                             status='0' represents device removed.
                  Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
                      indicates that fan 0 has been removed, fan 2
                      has been inserted and sfp 11 has been removed.
        """
        raise NotImplementedError
Example #26
0
class Chassis(ChassisBase):
    """
    DELLEMC Platform-specific Chassis class
    """

    REBOOT_CAUSE_PATH = "/host/reboot-cause/platform/reboot_reason"
    OIR_FD_PATH = "/sys/bus/pci/devices/0000:04:00.0/port_msi"

    _global_port_pres_dict = {}

    def __init__(self):
        ChassisBase.__init__(self)
        # sfp.py will read eeprom contents and retrive the eeprom data.
        # We pass the eeprom path from chassis.py
        self.PORT_START = 1
        self.PORT_END = 28
        self.SFP28_PORT_END = 24

        PORTS_IN_BLOCK = (self.PORT_END + 1)
        _sfp_port = range(1, self.SFP28_PORT_END + 1)
        eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"

        for index in range(self.PORT_START, PORTS_IN_BLOCK):
            port_num = index + 1
            eeprom_path = eeprom_base.format(port_num)
            if index not in _sfp_port:
                sfp_node = Sfp(index, 'QSFP', eeprom_path)
            else:
                sfp_node = Sfp(index, 'SFP', eeprom_path)
            self._sfp_list.append(sfp_node)

        self._eeprom = Eeprom()
        self._watchdog = Watchdog()
        self._num_sfps = self.PORT_END
        self._num_fans = MAX_S5224F_FAN * MAX_S5224F_FANTRAY

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

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

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

        for i in range(MAX_S5224F_FANTRAY):
            for j in range(MAX_S5224F_FAN):
                fan = Fan(i,j)
                self._fan_list.append(fan)

        for i in range(MAX_S5224F_FANTRAY):
            fandrawer = FanDrawer(i)
            self._fan_drawer_list.append(fandrawer)
            self._fan_list.extend(fandrawer._fan_list)

        for port_num in range(self.PORT_START, (self.PORT_END + 1)):
            # sfp get uses zero-indexing, but port numbers start from 1
            presence = self.get_sfp(port_num-1).get_presence()
            if presence:
                self._global_port_pres_dict[port_num] = '1'
            else:
                self._global_port_pres_dict[port_num] = '0'

# check for this event change for sfp / do we need to handle timeout/sleep

    def get_change_event(self, timeout=0):
        """
        Returns a nested dictionary containing all devices which have
        experienced a change at chassis level
        """
        start_ms = time.time() * 1000
        port_dict = {}
        change_dict = {}
        change_dict['sfp'] = port_dict
        while True:
            time.sleep(0.5)
            for port_num in range(self.PORT_START, (self.PORT_END + 1)):
                presence = self.get_sfp(port_num-1).get_presence()
                if(presence and self._global_port_pres_dict[port_num] == '0'):
                    self._global_port_pres_dict[port_num] = '1'
                    port_dict[port_num] = '1'
                    self.get_sfp(port_num-1)._initialize_media(delay=True)
                elif(not presence and
                        self._global_port_pres_dict[port_num] == '1'):
                    self._global_port_pres_dict[port_num] = '0'
                    port_dict[port_num] = '0'

            if(len(port_dict) > 0):
                return True, change_dict

            if timeout:
                now_ms = time.time() * 1000
                if (now_ms - start_ms >= timeout):
                    return True, change_dict


    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
        """
        sfp = None

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

    def get_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_eeprom(self):
        """
        Retrieves the Sys Eeprom instance for the chassis.
        Returns :
            The instance of the Sys Eeprom
        """
        return self._eeprom

    def get_num_fans(self):
        """
        Retrives the number of Fans on the chassis.
        Returns :
            An integer represents the number of Fans on the chassis.
        """
        return self._num_fans

    def get_num_sfps(self):
        """
        Retrives the numnber of Media on the chassis.
        Returns:
            An integer represences the number of SFPs on the chassis.
        """
        return self._num_sfps

    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.
        """
        try:
            with open(self.REBOOT_CAUSE_PATH) as fd:
                reboot_cause = int(fd.read(), 16)
        except EnvironmentError:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)

        if reboot_cause & 0x1:
            return (self.REBOOT_CAUSE_POWER_LOSS, "Power on reset")
        elif reboot_cause & 0x2:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)
        elif reboot_cause & 0x4:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "PSU Shutdown")
        elif reboot_cause & 0x8:
            return (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, "Thermal overload")
        elif reboot_cause & 0x10:
            return (self.REBOOT_CAUSE_WATCHDOG, "Watchdog reset")
        elif reboot_cause & 0x20:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "BMC Shutdown")
        elif reboot_cause & 0x40:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Hot-Swap Shutdown")
        elif reboot_cause & 0x80:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Shutdown")
        elif reboot_cause & 0x100:
            return (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Cold Reboot")
        else:
            return (self.REBOOT_CAUSE_NON_HARDWARE, None)

    def get_qualified_media_list(self):
        return media_part_num_list

    def set_locator_led(self, color):
        """
        Sets the state of the Chassis Locator LED

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

        Returns:
            bool: True if the Chassis Locator LED state is set successfully, False if not

        """
        resource = "/sys/bus/pci/devices/0000:04:00.0/resource0"
        val = pci_get_value(resource, SYSTEM_LED_REG)
        if  self.LOCATOR_LED_ON == color:
            val = int(val) | SYSTEM_BEACON_LED_SET
        elif self.LOCATOR_LED_OFF == color:
            val = int(val) & SYSTEM_BEACON_LED_CLEAR
        else:
            return False
        pci_set_value(resource, val, SYSTEM_LED_REG)
        return True

    def get_locator_led(self):
        """
        Gets the state of the Chassis Locator LED

        Returns:
            LOCATOR_LED_ON or LOCATOR_LED_OFF
        """
        resource = "/sys/bus/pci/devices/0000:04:00.0/resource0"
        val = pci_get_value(resource, SYSTEM_LED_REG)
        val = int(val) & SYSTEM_BEACON_LED_SET
        if not val:
            return self.LOCATOR_LED_OFF
        else:
            return self.LOCATOR_LED_ON
Example #27
0
class Chassis(ChassisBase):
    """
    Nokia platform-specific Chassis class
        Derived from Dell S6000 platform.
        customized for the 7215 platform.
    """
    def __init__(self):
        ChassisBase.__init__(self)
        self.system_led_supported_color = [
            'off', 'amber', 'green', 'amber_blink', 'green_blink'
        ]
        # Port numbers for SFP List Initialization
        self.COPPER_PORT_START = COPPER_PORT_START
        self.COPPER_PORT_END = COPPER_PORT_END
        self.SFP_PORT_START = SFP_PORT_START
        self.SFP_PORT_END = SFP_PORT_END
        self.PORT_END = PORT_END

        # for non-sfp ports create dummy objects for copper / non-sfp ports
        for index in range(self.COPPER_PORT_START, self.COPPER_PORT_END + 1):
            sfp_node = Sfp(index, 'COPPER', 'N/A', 'N/A')
            self._sfp_list.append(sfp_node)

        # Verify optoe2 driver SFP eeprom devices were enumerated and exist
        # then create the sfp nodes
        eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
        mux_dev = sorted(glob.glob("/sys/class/i2c-adapter/i2c-0/i2c-[0-9]"))
        y = 0
        for index in range(self.SFP_PORT_START, self.SFP_PORT_END + 1):
            mux_dev_num = mux_dev[y]
            port_i2c_map = mux_dev_num[-1]
            y = y + 1
            port_eeprom_path = eeprom_path.format(port_i2c_map)
            if not os.path.exists(port_eeprom_path):
                sonic_logger.log_info("path %s didnt exist" % port_eeprom_path)
            sfp_node = Sfp(index, 'SFP', port_eeprom_path, port_i2c_map)
            self._sfp_list.append(sfp_node)
        self.sfp_event_initialized = False

        # Instantiate system eeprom object
        self._eeprom = Eeprom()

        # Construct lists fans, power supplies, thermals & components
        drawer_num = MAX_7215_FAN_DRAWERS
        fan_num_per_drawer = MAX_7215_FANS_PER_DRAWER
        drawer_ctor = RealDrawer
        fan_index = 0
        for drawer_index in range(drawer_num):
            drawer = drawer_ctor(drawer_index)
            self._fan_drawer_list.append(drawer)
            for index in range(fan_num_per_drawer):
                fan = Fan(fan_index, drawer)
                fan_index += 1
                drawer._fan_list.append(fan)
                self._fan_list.append(fan)

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

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

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

    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 physical SFP ports in a
            chassis starting from 1.

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

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

    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_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(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.
        """
        # The ixs7215 CPLD does not have a hardware reboot cause register so
        # the hardware portion of reboot cause can't be implemented

        return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)

    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:
            # xrcvd will call this monitor loop in the "SYSTEM_READY" state
            timeout = MAX_SELECT_DELAY
            while True:
                status = self.sfp_event.check_sfp_status(port_dict, timeout)
                if not port_dict == {}:
                    break
        else:
            # At boot up and in "INIT" state call from xrcvd will have timeout
            # value return true without change after timeout and will
            # transition to "SYSTEM_READY"
            status = self.sfp_event.check_sfp_status(port_dict, timeout)

        if status:
            return True, {'sfp': port_dict}
        else:
            return True, {'sfp': {}}

    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
        """
        if color not in self.system_led_supported_color:
            return False

        if (color == 'off'):
            value = 0x00
        elif (color == 'amber'):
            value = 0x01
        elif (color == 'green'):
            value = 0x02
        elif (color == 'amber_blink'):
            value = 0x03
        elif (color == 'green_blink'):
            value = 0x04
        else:
            return False

        # Write sys led
        if smbus_present == 0:
            sonic_logger.log_warning("PMON LED SET -> smbus present = 0")
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICEREG = 0x7
            bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, value)
            sonic_logger.log_info("  System LED set O.K.  ")
            return True

        return False

    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.
        """
        # Read sys led
        if smbus_present == 0:
            sonic_logger.log_warning("PMON LED GET -> smbus present = 0")
            return False
        else:
            bus = smbus.SMBus(0)
            DEVICE_ADDRESS = 0x41
            DEVICE_REG = 0x7
            value = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)

            if value == 0x00:
                color = 'off'
            elif value == 0x01:
                color = 'amber'
            elif value == 0x02:
                color = 'green'
            elif value == 0x03:
                color = 'amber_blink'
            elif value == 0x04:
                color = 'green_blink'
            else:
                return False

            return color

    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 WatchdogImplBase
                watchdog_device_path = "/dev/watchdog0"
                self._watchdog = WatchdogImplBase(watchdog_device_path)
        except Exception as e:
            sonic_logger.log_warning(" Fail to load watchdog {}".format(
                repr(e)))

        return self._watchdog

    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
Example #28
0
class Chassis(ChassisBase):
    """Platform-specific Chassis class"""

    _global_port_pres_dict = {}

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

        # Initialize SKU name and Platform name
        self.sku_name = self._get_sku_name()
        self.platform_name = self._get_platform_name()
        self.name = self.sku_name

        # get the device infomation of platform
        self.platdev = PlatDev()

        #self._component_list = []
        #self._module_list = []
        #self._fan_drawer_list = []

        self._eeprom = Eeprom()
        # init component
        for i in range(self.platdev.get_component_count()):
            component = Component(i, self.platdev.get_component_name(i),
                                  self.platdev.get_component_descript(i))
            self._component_list.append(component)
        # init fan list
        if self.platdev.get_fan_support():
            fanlist = self.platdev.get_fan_list()
            for index in range(0, len(fanlist)):
                fan_name = fanlist[index]
                for pos in range(0,
                                 self.platdev.get_fan_num_by_name(fan_name)):
                    fan = Fan(index, pos, [
                        self.platdev.get_fan_sysfile_path_by_name(fan_name), ''
                    ])
                    self._fan_list.append(fan)

        # init psu list
        psulist = self.platdev.get_psu_list()
        for index in range(0, len(psulist)):
            psu_name = psulist[index]
            psu = Psu(index, [
                self.platdev.get_psu_attr_path_by_name(psu_name),
                self.platdev.get_psu_status_path_by_name(psu_name)
            ], self.platdev.bmc_is_exist())
            self._psu_list.append(psu)

        # init thermal list
        thermal_info_list = self.platdev.get_thermal_dev_info_all()
        for index in range(0, len(thermal_info_list)):
            if len(self.platdev.get_thermal_dev_tempidx_by_idx(index)) > 1:
                for idx in self.platdev.get_thermal_dev_tempidx_by_idx(index):
                    thermal = Thermal(
                        idx,
                        self.platdev.get_thermal_dev_name_by_idx(index) +
                        "-{}".format(idx),
                        self.platdev.get_thermal_dev_sysfile_path_by_idx(
                            index), self.platdev.bmc_is_exist(),
                        self.platdev.get_thermal_dev_support_mask_by_idx(
                            index),
                        self.platdev.get_thermal_dev_ext_sysfile_list_by_idx(
                            index))
                    self._thermal_list.append(thermal)
            else:
                thermal = Thermal(
                    1, self.platdev.get_thermal_dev_name_by_idx(index),
                    self.platdev.get_thermal_dev_sysfile_path_by_idx(index),
                    self.platdev.bmc_is_exist(),
                    self.platdev.get_thermal_dev_support_mask_by_idx(index),
                    self.platdev.get_thermal_dev_ext_sysfile_list_by_idx(
                        index))
                self._thermal_list.append(thermal)

        # init sfp list
        port_num = 1
        for sfpg_name in self.platdev.get_sfp_group_list():
            if self.platdev.get_sfp_group_type_by_name(sfpg_name) == 'QSFP28':
                sfp_type = QSFP_TYPE
            else:
                sfp_type = SFP_TYPE

            for x in range(
                    0, self.platdev.get_sfp_group_number_by_name(sfpg_name)):
                eeprom_path_list = ['n/a', 'n/a']
                if self.platdev.get_sfp_group_path_by_name(
                        sfpg_name)[x] != 'n/a':
                    eeprom_path_list[
                        0] = self.platdev.get_sfp_group_path_by_name(
                            sfpg_name)[x] + '/eeprom'
                    if os.path.exists(eeprom_path_list[0].replace(
                            "0050", "0051")):
                        eeprom_path_list[1] = eeprom_path_list[0].replace(
                            "0050", "0051")
                # index: port index, start from 0
                # eeprom_path_list : a list of path to eeprom sysfile
                #   [0]: for 0x50
                #   [1]: for 0x51
                # ext_sysfile_list: used to get other function of sfp
                #   [0]: present
                #   [1]: reset
                #   [2]: get lowpower mode
                #   [3]: set lowpower mode
                sfp = Sfp(port_num, eeprom_path_list, sfp_type,
                          self.platdev.get_sfp_ext_sysfile_list())
                port_num += 1
                self._sfp_list.append(sfp)

        self.init_global_port_presence()

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

    def _get_platform_name(self):
        pipe = subprocess.Popen(GET_PLATFORM_CMD,
                                shell=True,
                                stdout=subprocess.PIPE)
        out, err = pipe.communicate()
        return out.decode().rstrip('\n')

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

    def get_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_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_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.
        """
        # not support any hardware reboot, just return REBOOT_CAUSE_NON_HARDWARE
        # to keep reboot cause as software reboot
        return (self.REBOOT_CAUSE_NON_HARDWARE, None)

    ##############################################
    # System LED methods
    ##############################################

    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

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

    ##############################################
    # Other methods
    ##############################################

    def init_global_port_presence(self):
        for port_num in range(0, self.platdev.get_sfp_num()):
            presence = self._sfp_list[port_num].get_presence()
            self._global_port_pres_dict[port_num] = '1' if presence else '0'

    def get_change_event(self, timeout=0):
        """
        Returns a nested dictionary containing all devices which have
        experienced a change at chassis level
        Args:
            timeout: Timeout in milliseconds (optional). If timeout == 0,
                this method will block until a change is detected.
        Returns:
            (bool, dict):
                - True if call successful, False if not;
                - A nested dictionary where key is a device type,
                  value is a dictionary with key:value pairs in the format of
                  {'device_id':'device_event'},
                  where device_id is the device ID for this device and
                        device_event,
                             status='1' represents device inserted,
                             status='0' represents device removed.
                  Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
                      indicates that fan 0 has been removed, fan 2
                      has been inserted and sfp 11 has been removed.
                  Specifically for SFP event, besides SFP plug in and plug out,
                  there are some other error event could be raised from SFP, when
                  these error happened, SFP eeprom will not be avalaible, XCVRD shall
                  stop to read eeprom before SFP recovered from error status.
                      status='2' I2C bus stuck,
                      status='3' Bad eeprom,
                      status='4' Unsupported cable,
                      status='5' High Temperature,
                      status='6' Bad cable.
        """
        port_dict = {}
        while True:
            for port_num in range(0, self.platdev.get_sfp_num()):
                presence = self._sfp_list[port_num].get_presence()
                if (presence and self._global_port_pres_dict[port_num] == '0'):
                    self._global_port_pres_dict[port_num] = '1'
                    port_dict[port_num] = '1'
                elif (not presence
                      and self._global_port_pres_dict[port_num] == '1'):
                    self._global_port_pres_dict[port_num] = '0'
                    port_dict[port_num] = '0'

                if len(port_dict) > 0:
                    return True, {'sfp': port_dict}

            time.sleep(1)

    def sfp_debugger(self):
        """
        Try to show all parameters read from eeprom with sfp methods
        """
        print("SFP EEPROM data:")
        for sfp_n in range(0, len(self._sfp_list)):
            print("======SFP{}==TYPE {}====".format(
                sfp_n, self._sfp_list[sfp_n].sfp_type))
            print("get_transceiver_info:")
            print(self._sfp_list[sfp_n].get_transceiver_info())
            print(" ")

            print("get_transceiver_threshold_info:")
            print(self._sfp_list[sfp_n].get_transceiver_threshold_info())
            print(" ")

            print("get_transceiver_bulk_status:")
            print(self._sfp_list[sfp_n].get_transceiver_bulk_status())
            print(" ")

        print("get_lpmode:")
        for sfp_n in range(0, len(self._sfp_list)):
            print("\tsfp{}: {}".format(sfp_n,
                                       self._sfp_list[sfp_n].get_lpmode()))
            # set_lpmode

        print("get_power_override:")
        for sfp_n in range(0, len(self._sfp_list)):
            print("\tsfp{}: {}".format(
                sfp_n, self._sfp_list[sfp_n].get_power_override()))

        print("get_temperature:")
        for sfp_n in range(0, len(self._sfp_list)):
            print("\tsfp{}: {}".format(
                sfp_n, self._sfp_list[sfp_n].get_temperature()))

        print("get_voltage")
        for sfp_n in range(0, len(self._sfp_list)):
            print("\tsfp{}: {}".format(sfp_n,
                                       self._sfp_list[sfp_n].get_voltage()))

        print("get_tx_bias")
        for sfp_n in range(0, len(self._sfp_list)):
            print("\tsfp{}: {}".format(sfp_n,
                                       self._sfp_list[sfp_n].get_tx_bias()))

        print("get_rx_power")
        for sfp_n in range(0, len(self._sfp_list)):
            print("\tsfp{}: {}".format(sfp_n,
                                       self._sfp_list[sfp_n].get_rx_power()))

        print("get_tx_power")
        for sfp_n in range(0, len(self._sfp_list)):
            print("\tsfp{}: {}".format(sfp_n,
                                       self._sfp_list[sfp_n].get_tx_power()))