[BFN] Updated platform plugins (#9540)

* [BFN] Updated platform APIs impl

Signed-off-by: Andriy Kokhan <andriyx.kokhan@intel.com>

* Extended BFN platform SFP APIs implementation

* Update sfp.py

* [BFN] Extended SFP platform plugin implementation

Signed-off-by: Andriy Kokhan <andriyx.kokhan@intel.com>

* [BFN] Extended Fans platform plugin implementation

* [BFN] divided classes Fan and  FanDrawer into 2 files

* Signed-off-by: Vadym Yashchenko <vadymx.yashchenko@intel.com>

What I did
	Add get_model() function
	Add get_low_critical_threshold() function
	Change __get(...) function.
How I did it
	Differnece from previous implementation of __get(...) function is return real value or -9999.9 if value is not provided by thrift API

* Add get_presence() function and revised __get() function

Signed-off-by: Vadym Yashchenko <vadymx.yashchenko@intel.com>

* [BFN] Updated PSU platform APIs impl

Signed-off-by: Dmytro Lytvynenko <dmytrox.lytvynenko@intel.com>

* Added BFN PSU cache (#9)

Signed-off-by: Andriy Kokhan <andriyx.kokhan@intel.com>

* [BFN]  Fans and Fantray platform APIs update (#7)

* [BFN] Updated SFP platform APIs (#10)

Signed-off-by: Volodymyr Boyko <volodymyrx.boiko@intel.com>

* [BFN] Updated platform API for thermal (#8)

* Signed-off-by: Vadym Yashchenko <vadymx.yashchenko@intel.com>

* Revert "[BFN]  Fans and Fantray platform APIs update (#7)" (#11)

This reverts commit c62a733443be49cbe4ba2d06047aac7516f0495e.

* Add support health monitor system (#15)

Signed-off-by: Petro Bratash <petrox.bratash@intel.com>

* Update chassis.py

* [BFN] Updated FANs and FAN Tray platform API (#14)

* Fix fix_alignment (#17)

Signed-off-by: Petro Bratash <petrox.bratash@intel.com>

* [BFN] Improvement show environment (#16)

* Added PSU temperature skip into platform.json (#18)

Signed-off-by: Andriy Kokhan <andriyx.kokhan@intel.com>

* Do not skip psud on Newport

Signed-off-by: Andriy Kokhan <andriyx.kokhan@intel.com>

* [BFN] fix fan status from Not OK to Ok (#19)

* [BFN] Updated SFP platform plugin (#13)

Signed-off-by: Volodymyr Boyko <volodymyrx.boiko@intel.com>

* [DPB] Fix typo for Ethernet0 2x200G[100G,40G] breakout mode (#21)

Signed-off-by: Mykola Gerasymenko <mykolax.gerasymenko@intel.com>

* [barefoot] Tmp fix vendor_rev (#22)

Signed-off-by: Volodymyr Boyko <volodymyrx.boiko@intel.com>

* Fixed python issues in sonic_platform/fan_drawer.py

Signed-off-by: Andriy Kokhan <andriyx.kokhan@intel.com>

* Updated fan_drawer.py

* Fixing trailing white spaces in fan_drawer.py

* [BFN] Fix thrift for SFPs API

Signed-off-by: Volodymyr Boyko <volodymyrx.boiko@intel.com>

* In platform.json, replaced 'false' with '0' to workaround ast.literal_eval() issue

Signed-off-by: Andriy Kokhan <andriyx.kokhan@intel.com>

* [Newport] Thermal manager  (#23)

* Signed-off-by: Vadym Yashchenko <vadymx.yashchenko@intel.com>

* Revert "In platform.json, replaced 'false' with '0' to workaround ast.literal_eval() issue"

This reverts commit 1e73127830.

* Removed 'controllable' options from platform.json to fix factory default config generation

Signed-off-by: Andriy Kokhan <andriyx.kokhan@intel.com>

* Update thermal_manager.py

* Migrated SFP plugin to sonic_xcvr API (#30)

Signed-off-by: Andriy Kokhan <andriyx.kokhan@intel.com>

Co-authored-by: KostiantynYarovyiBf <kostiantynx.yarovyi@intel.com>
Co-authored-by: Vadym Yashchenko <vadymx.yashchenko@intel.com>
Co-authored-by: Dmytro Lytvynenko <dmytrox.lytvynenko@intel.com>
Co-authored-by: Volodymyr Boiko <volodymyrx.boiko@intel.com>
Co-authored-by: Petro Bratash <petrox.bratash@intel.com>
Co-authored-by: Mykola Gerasymenko <mykolax.gerasymenko@intel.com>
This commit is contained in:
Andriy Kokhan 2022-01-17 07:46:20 +02:00 committed by GitHub
parent a0150120ae
commit 4037867b7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 5910 additions and 739 deletions

View File

@ -21,10 +21,9 @@
"name": "counter-rotating-fan-6"
}
],
"fan_drawers":[
"fan_drawers": [
{
"name": "fantray",
"num_fans" : 6,
"name": "fantray-1",
"fans": [
{
"name": "counter-rotating-fan-1"
@ -57,13 +56,49 @@
],
"thermals": [
{
"name": "tmp75-i2c-3-4b:switch-temp"
"name": "com_e_driver-i2c-4-33:cpu-temp"
},
{
"name": "com_e_driver-i2c-4-33:memory-temp"
},
{
"name": "com_e_driver-i2c-4-33:cpu-temp"
"name": "psu_driver-i2c-7-59:psu2-temp1"
},
{
"name": "psu_driver-i2c-7-59:psu2-temp2"
},
{
"name": "psu_driver-i2c-7-59:psu2-temp3"
},
{
"name": "psu_driver-i2c-7-5a:psu1-temp1"
},
{
"name": "psu_driver-i2c-7-5a:psu1-temp2"
},
{
"name": "psu_driver-i2c-7-5a:psu1-temp3"
},
{
"name": "tmp75-i2c-3-48:chip-temp"
},
{
"name": "tmp75-i2c-3-49:exhaust2-temp"
},
{
"name": "tmp75-i2c-3-4a:exhaust-temp"
},
{
"name": "tmp75-i2c-3-4b:intake-temp"
},
{
"name": "tmp75-i2c-3-4c:tofino-temp"
},
{
"name": "tmp75-i2c-3-4d:intake2-temp"
},
{
"name": "coretemp-isa-0000:package-id-0"
},
{
"name": "coretemp-isa-0000:core-0"
@ -76,128 +111,104 @@
},
{
"name": "coretemp-isa-0000:core-3"
},
{
"name": "coretemp-isa-0000:package-id-0"
},
{
"name": "psu_driver-i2c-7-5a:psu1-temp1"
},
{
"name": "psu_driver-i2c-7-5a:psu1-temp2"
},
{
"name": "psu_driver-i2c-7-5a:psu1-temp3"
},
{
"name": "tmp75-i2c-3-4a:inlet-left-temp"
},
{
"name": "tmp75-i2c-3-4c:inlet-right-temp"
},
{
"name": "tmp75-i2c-3-4d:temp1"
},
{
"name": "tmp75-i2c-3-48:outlet-middle-temp"
},
{
"name": "tmp75-i2c-3-49:inlet-middle-temp"
}
],
"sfps": [
{
"name": "Ethernet0"
"name": "sfp1"
},
{
"name": "Ethernet8"
"name": "sfp2"
},
{
"name": "Ethernet16"
"name": "sfp3"
},
{
"name": "Ethernet32"
"name": "sfp4"
},
{
"name": "Ethernet40"
"name": "sfp5"
},
{
"name": "Ethernet48"
"name": "sfp6"
},
{
"name": "Ethernet56"
"name": "sfp7"
},
{
"name": "Ethernet64"
"name": "sfp8"
},
{
"name": "Ethernet72"
"name": "sfp9"
},
{
"name": "Ethernet80"
"name": "sfp10"
},
{
"name": "Ethernet88"
"name": "sfp11"
},
{
"name": "Ethernet96"
"name": "sfp12"
},
{
"name": "Ethernet104"
"name": "sfp13"
},
{
"name": "Ethernet112"
"name": "sfp14"
},
{
"name": "Ethernet120"
"name": "sfp15"
},
{
"name": "Ethernet128"
"name": "sfp16"
},
{
"name": "Ethernet136"
"name": "sfp17"
},
{
"name": "Ethernet144"
"name": "sfp18"
},
{
"name": "Ethernet152"
"name": "sfp19"
},
{
"name": "Ethernet160"
"name": "sfp20"
},
{
"name": "Ethernet168"
"name": "sfp21"
},
{
"name": "Ethernet176"
"name": "sfp22"
},
{
"name": "Ethernet184"
"name": "sfp23"
},
{
"name": "Ethernet192"
"name": "sfp24"
},
{
"name": "Ethernet200"
"name": "sfp25"
},
{
"name": "Ethernet208"
"name": "sfp26"
},
{
"name": "Ethernet216"
"name": "sfp27"
},
{
"name": "Ethernet224"
"name": "sfp28"
},
{
"name": "Ethernet232"
"name": "sfp29"
},
{
"name": "Ethernet240"
"name": "sfp30"
},
{
"name": "Ethernet248"
"name": "sfp31"
},
{
"name": "sfp32"
}
]
},
@ -207,7 +218,7 @@
"lanes": "0,1,2,3,4,5,6,7",
"breakout_modes": {
"1x400G[200G]": ["Ethernet0"],
"2x200G[100G,40G]": ["Ethernet0, Ethernet4"],
"2x200G[100G,40G]": ["Ethernet0", "Ethernet4"],
"4x100G[50G]": ["Ethernet0", "Ethernet2", "Ethernet4", "Ethernet6"],
"8x50G[25G,10G]": ["Ethernet0", "Ethernet1", "Ethernet2", "Ethernet3", "Ethernet4", "Ethernet5", "Ethernet6", "Ethernet7"],
"1x200G[100G,40G](4)+4x50G[25G,10G](4)": ["Ethernet0", "Ethernet4", "Ethernet5", "Ethernet6", "Ethernet7"],
@ -587,4 +598,4 @@
}
}
}
}
}

View File

@ -4,6 +4,6 @@
"skip_thermalctld": false,
"skip_ledd": true,
"skip_xcvrd": false,
"skip_psud": true,
"skip_psud": false,
"skip_syseepromd": false
}

View File

@ -0,0 +1,11 @@
{
"services_to_ignore": [],
"devices_to_ignore": [],
"user_defined_checkers": [],
"polling_interval": 60,
"led_color": {
"fault": "amber",
"normal": "green",
"booting": "orange_blink"
}
}

View File

@ -18,10 +18,9 @@
"name": "counter-rotating-fan-5"
}
],
"fan_drawers":[
"fan_drawers": [
{
"name": "fantray",
"num_fans" : 5,
"name": "fantray-1",
"fans": [
{
"name": "counter-rotating-fan-1"
@ -110,100 +109,100 @@
],
"sfps": [
{
"name": "Ethernet0"
"name": "sfp1"
},
{
"name": "Ethernet4"
"name": "sfp2"
},
{
"name": "Ethernet8"
"name": "sfp3"
},
{
"name": "Ethernet12"
"name": "sfp4"
},
{
"name": "Ethernet16"
"name": "sfp5"
},
{
"name": "Ethernet20"
"name": "sfp6"
},
{
"name": "Ethernet24"
"name": "sfp7"
},
{
"name": "Ethernet28"
"name": "sfp8"
},
{
"name": "Ethernet32"
"name": "sfp9"
},
{
"name": "Ethernet36"
"name": "sfp10"
},
{
"name": "Ethernet40"
"name": "sfp11"
},
{
"name": "Ethernet44"
"name": "sfp12"
},
{
"name": "Ethernet48"
"name": "sfp13"
},
{
"name": "Ethernet52"
"name": "sfp14"
},
{
"name": "Ethernet56"
"name": "sfp15"
},
{
"name": "Ethernet60"
"name": "sfp16"
},
{
"name": "Ethernet64"
"name": "sfp17"
},
{
"name": "Ethernet68"
"name": "sfp18"
},
{
"name": "Ethernet72"
"name": "sfp19"
},
{
"name": "Ethernet76"
"name": "sfp20"
},
{
"name": "Ethernet80"
"name": "sfp21"
},
{
"name": "Ethernet84"
"name": "sfp22"
},
{
"name": "Ethernet88"
"name": "sfp23"
},
{
"name": "Ethernet92"
"name": "sfp24"
},
{
"name": "Ethernet96"
"name": "sfp25"
},
{
"name": "Ethernet100"
"name": "sfp26"
},
{
"name": "Ethernet104"
"name": "sfp27"
},
{
"name": "Ethernet108"
"name": "sfp28"
},
{
"name": "Ethernet112"
"name": "sfp29"
},
{
"name": "Ethernet116"
"name": "sfp30"
},
{
"name": "Ethernet120"
"name": "sfp31"
},
{
"name": "Ethernet124"
"name": "sfp32"
}
]
},

View File

@ -0,0 +1,11 @@
{
"services_to_ignore": [],
"devices_to_ignore": [],
"user_defined_checkers": [],
"polling_interval": 60,
"led_color": {
"fault": "amber",
"normal": "green",
"booting": "orange_blink"
}
}

View File

@ -1,4 +1,89 @@
{
"chassis": {
"name": "Mavericks",
"fans": [
{
"name": "counter-rotating-fan-1"
},
{
"name": "counter-rotating-fan-2"
},
{
"name": "counter-rotating-fan-3"
},
{
"name": "counter-rotating-fan-4"
},
{
"name": "counter-rotating-fan-5"
},
{
"name": "counter-rotating-fan-6"
},
{
"name": "counter-rotating-fan-7"
},
{
"name": "counter-rotating-fan-8"
},
{
"name": "counter-rotating-fan-9"
},
{
"name": "counter-rotating-fan-10"
}
],
"fan_drawers": [
{
"name": "fantray-1",
"fans": [
{
"name": "counter-rotating-fan-1"
},
{
"name": "counter-rotating-fan-2"
},
{
"name": "counter-rotating-fan-3"
},
{
"name": "counter-rotating-fan-4"
},
{
"name": "counter-rotating-fan-5"
}
]
},
{
"name": "fantray-2",
"fans": [
{
"name": "counter-rotating-fan-6"
},
{
"name": "counter-rotating-fan-7"
},
{
"name": "counter-rotating-fan-8"
},
{
"name": "counter-rotating-fan-9"
},
{
"name": "counter-rotating-fan-10"
}
]
}
]
},
"psus": [
{
"name": "psu-1"
},
{
"name": "psu-2"
}
],
"interfaces": {
"Ethernet0": {
"index": "1,1,1,1",

View File

@ -0,0 +1,11 @@
{
"services_to_ignore": [],
"devices_to_ignore": [],
"user_defined_checkers": [],
"polling_interval": 60,
"led_color": {
"fault": "amber",
"normal": "green",
"booting": "orange_blink"
}
}

View File

@ -1,13 +1,22 @@
#!/usr/bin/env python
try:
import sys
import time
import syslog
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.sfp import Sfp, sfp_list_get
from sonic_platform.sfp import Sfp
from sonic_platform.psu import psu_list_get
from sonic_platform.fan_drawer import fan_drawer_list_get
from sonic_platform.thermal import thermal_list_get
from eeprom import Eeprom
from sonic_platform.thermal_manager import ThermalManager
from sonic_platform.platform_thrift_client import pltfm_mgr_ready
from sonic_platform.platform_thrift_client import thrift_try
from sonic_py_common import device_info
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
@ -15,14 +24,29 @@ class Chassis(ChassisBase):
"""
Platform-specific Chassis class
"""
PORT_START = 1
PORT_END = 0
PORTS_IN_BLOCK = 0
QSFP_PORT_START = 1
QSFP_PORT_END = 0
QSFP_CHECK_INTERVAL = 4
def __init__(self):
ChassisBase.__init__(self)
self.__eeprom = None
self.__fan_drawers = None
self.__fan_list = None
self.__thermals = None
self.__psu_list = None
self.__sfp_list = None
self.__thermal_mngr = None
self.__polling_thermal_time = 30
self.ready = False
self.phy_port_cur_state = {}
self.qsfp_interval = self.QSFP_CHECK_INTERVAL
@property
def _eeprom(self):
@ -44,6 +68,18 @@ class Chassis(ChassisBase):
def _fan_drawer_list(self, value):
pass
@property
def _fan_list(self):
if self.__fan_list is None:
self.__fan_list = []
for fan_drawer in self._fan_drawer_list:
self.__fan_list.extend(fan_drawer._fan_list)
return self.__fan_list
@_fan_list.setter
def _fan_list(self, value):
pass
@property
def _thermal_list(self):
if self.__thermals is None:
@ -67,13 +103,44 @@ class Chassis(ChassisBase):
@property
def _sfp_list(self):
if self.__sfp_list is None:
self.__sfp_list = sfp_list_get()
self.__update_port_info()
self.__sfp_list = []
for index in range(self.PORT_START, self.PORT_END + 1):
sfp_node = Sfp(index)
self.__sfp_list.append(sfp_node)
return self.__sfp_list
@_sfp_list.setter
def _sfp_list(self, value):
pass
@property
def _thermal_mngr(self):
if self.__thermal_mngr is None:
self.__thermal_mngr = ThermalManager(self.__polling_thermal_time)
return self.__thermal_mngr
@_thermal_mngr.setter
def _thermal_mngr(self, value):
self.__thermal_mngr = ThermalManager(value)
def __update_port_info(self):
def qsfp_max_port_get(client):
return client.pltfm_mgr.pltfm_mgr_qsfp_get_max_port()
if self.QSFP_PORT_END == 0:
platform = device_info.get_platform()
self.QSFP_PORT_END = thrift_try(qsfp_max_port_get)
exclude_cpu_port = [
"x86_64-accton_as9516_32d-r0",
"x86_64-accton_as9516bf_32d-r0",
"x86_64-accton_wedge100bf_32x-r0"
]
if platform in exclude_cpu_port:
self.QSFP_PORT_END -= 1
self.PORT_END = self.QSFP_PORT_END
self.PORTS_IN_BLOCK = self.QSFP_PORT_END
def get_name(self):
"""
Retrieves the name of the chassis
@ -106,6 +173,14 @@ class Chassis(ChassisBase):
"""
return self._eeprom.serial_number_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_sfp(self, index):
"""
Retrieves sfp represented by (1-based) index <index>
@ -124,7 +199,7 @@ class Chassis(ChassisBase):
try:
sfp = self._sfp_list[index-1]
except IndexError:
sys.stderr.write("SFP index {} out of range (1-{})\n".format(
syslog.syslog(syslog.LOG_ERR, "SFP index {} out of range (1-{})\n".format(
index, len(self._sfp_list)-1))
return sfp
@ -158,8 +233,60 @@ class Chassis(ChassisBase):
"""
return self._eeprom.system_eeprom_info()
def __get_transceiver_change_event(self, timeout=0):
forever = False
if timeout == 0:
forever = True
elif timeout > 0:
timeout = timeout / float(1000) # Convert to secs
else:
syslog.syslog(syslog.LOG_ERR, "Invalid timeout value {}".format(timeout))
return False, {}
phy_port_dict = {} if self.ready else {'-1': 'system_not_ready'}
while forever or timeout > 0:
if not self.ready:
if pltfm_mgr_ready():
self.ready = True
phy_port_dict = {}
if self.ready and self.qsfp_interval == 0:
self.qsfp_interval = self.QSFP_CHECK_INTERVAL
# Get presence of each SFP
for port in range(self.PORT_START, self.PORT_END + 1):
try:
sfp_resent = self.get_sfp(port).get_presence()
except Exception:
sfp_resent = False
sfp_state = '1' if sfp_resent else '0'
if port in self.phy_port_cur_state:
if self.phy_port_cur_state[port] != sfp_state:
phy_port_dict[port] = sfp_state
else:
phy_port_dict[port] = sfp_state
# Update port current state
self.phy_port_cur_state[port] = sfp_state
# Break if tranceiver state has changed
if phy_port_dict:
break
if timeout:
timeout -= 1
if self.qsfp_interval:
self.qsfp_interval -= 1
time.sleep(1)
return self.ready, phy_port_dict
def get_change_event(self, timeout=0):
ready, event_sfp = Sfp.get_transceiver_change_event(timeout)
ready, event_sfp = self.__get_transceiver_change_event(timeout)
return ready, { 'sfp': event_sfp } if ready else {}
def get_reboot_cause(self):
@ -174,3 +301,55 @@ class Chassis(ChassisBase):
to pass a description of the reboot cause.
"""
return self.REBOOT_CAUSE_NON_HARDWARE, ''
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return -1
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return False
def initizalize_system_led(self):
self.system_led = ""
return True
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
"""
self.system_led = 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.
"""
return self.system_led
def get_thermal_manager(self):
return self._thermal_mngr
def __del__(self):
if self.__thermal_mngr is not None:
self.__thermal_mngr.stop()

View File

@ -24,20 +24,21 @@ except ImportError as e:
_platform_eeprom_map = {
"prod_name" : ("Product Name", "0x21", 12),
"odm_pcba_part_num" : ("Part Number", "0x22", 13),
"prod_ser_num" : ("Serial Number", "0x23", 12),
"ext_mac_addr" : ("Extended MAC Address Base", "0x24", 12),
"sys_mfg_date" : ("System Manufacturing Date", "0x25", 4),
"prod_ver" : ("Product Version", "0x26", 1),
"ext_mac_addr_size" : ("Extende MAC Address Size", "0x2A", 2),
"sys_mfger" : ("Manufacturer", "0x2B", 8)
"prod_name" : ("Product Name", "0x21", 12),
"odm_pcba_part_num" : ("Part Number", "0x22", 13),
"prod_ser_num" : ("Serial Number", "0x23", 12),
"ext_mac_addr" : ("Extended MAC Address Base", "0x24", 12),
"sys_mfg_date" : ("System Manufacturing Date", "0x25", 4),
"prod_ver" : ("Product Version", "0x26", 1),
"ext_mac_addr_size" : ("Extende MAC Address Size", "0x2A", 2),
"sys_mfger" : ("Manufacturer", "0x2B", 8)
}
_product_dict = { "Montara" : "Wedge100BF-32X-O-AC-F-BF",
"Lower MAV" : "Wedge100BF-65X-O-AC-F-BF",
"Upper MAV" : "Wedge100BF-65X-O-AC-F-BF"
}
_product_dict = {
"Montara" : "Wedge100BF-32X-O-AC-F-BF",
"Lower MAV" : "Wedge100BF-65X-O-AC-F-BF",
"Upper MAV" : "Wedge100BF-65X-O-AC-F-BF"
}
_EEPROM_SYMLINK = "/var/run/platform/eeprom/syseeprom"
_EEPROM_STATUS = "/var/run/platform/eeprom/status"
@ -148,3 +149,6 @@ class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
def modelstr(self):
return self.__tlv_get(self._TLV_CODE_PRODUCT_NAME)
def revision_str(self):
return self.__tlv_get(self._TLV_CODE_LABEL_REVISION)

View File

@ -0,0 +1,105 @@
try:
from sonic_platform.platform_thrift_client import thrift_try
from sonic_platform_base.fan_base import FanBase
from sonic_py_common import device_info
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
def _fan_info_get(fan_num, cb, default=None):
def get_data(client):
return client.pltfm_mgr.pltfm_mgr_fan_info_get(fan_num)
fan_info = thrift_try(get_data)
if fan_num == fan_info.fan_num:
return cb(fan_info)
if default is None:
raise LookupError
return default
# Fan -> FanBase -> DeviceBase
class Fan(FanBase):
def __init__(self, index, fantrayindex):
self.__index = index
self.__fantrayindex = fantrayindex
# FanBase interface methods:
# returns speed in percents
def get_speed(self):
def cb(info): return info.percent
return _fan_info_get(self.__index, cb, 0)
def set_speed(self, percent):
# Fan tray speed controlled by BMC
return False
# DeviceBase interface methods:
def get_name(self):
return "counter-rotating-fan-{}".format((self.__fantrayindex - 1) * self.__index + self.__index)
def get_presence(self):
return _fan_info_get(self.__index, lambda _: True, False)
def get_position_in_parent(self):
return self.__index
def is_replaceable(self):
return False
def get_status(self):
return (self.get_presence() and self.get_presence() > 0)
def get_model(self):
"""
Retrieves the part number of the fan drawer
Returns:
string: Part number of fan drawer
"""
return 'N/A'
def get_direction(self):
"""
Retrieves the direction of fan
Returns:
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
depending on fan direction
"""
return 'N/A'
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 self.get_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 device_info.get_platform() in ["x86_64-accton_as9516_32d-r0", "x86_64-accton_as9516bf_32d-r0"]:
return 6
return 3
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return 'N/A'
def set_status_led(self, color):
"""
Sets the state of the fan module status LED
Args:
color: A string representing the color with which to set the
fan module status LED
Returns:
bool: True if status LED state is set successfully, False if not
"""
# Fan tray status LED controlled by BMC
return False

View File

@ -1,71 +1,20 @@
try:
from sonic_platform.platform_thrift_client import thrift_try
from sonic_platform_base.fan_drawer_base import FanDrawerBase
from sonic_platform_base.fan_base import FanBase
from sonic_py_common import device_info
from sonic_platform.fan import Fan
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
_MAX_FAN = 10
def _fan_info_get(fan_num, cb, default=None):
def get_data(client):
return client.pltfm_mgr.pltfm_mgr_fan_info_get(fan_num)
fan_info = thrift_try(get_data)
if fan_num == fan_info.fan_num:
return cb(fan_info)
if default is None:
raise LookupError
return default
def _fan_info_get_all():
for fan_num in range(1, _MAX_FAN + 1):
def get_data(client, fan_num=fan_num):
return client.pltfm_mgr.pltfm_mgr_fan_info_get(fan_num)
fan_info = thrift_try(get_data)
if fan_info.fan_num == fan_num:
yield fan_info
# Fan -> FanBase -> DeviceBase
class Fan(FanBase):
def __init__(self, num):
self.__num = num
# FanBase interface methods:
# returns speed in percents
def get_speed(self):
def cb(info): return info.percent
return _fan_info_get(self.__num, cb, 0)
def set_speed(self, percent):
def set_fan_speed(client):
return client.pltfm_mgr.pltfm_mgr_fan_speed_set(self.__num, percent)
return thrift_try(set_fan_speed)
# DeviceBase interface methods:
def get_name(self):
return f"counter-rotating-fan-{self.__num}"
def get_presence(self):
return _fan_info_get(self.__num, lambda _: True, False)
def get_position_in_parent(self):
return self.__num
def is_replaceable(self):
return True
def get_status(self):
return True
# FanDrawer -> FanDrawerBase -> DeviceBase
class FanDrawer(FanDrawerBase):
def __init__(self):
def __init__(self, fantray_index, max_fan):
# For now we return only present fans
self._fan_list = [Fan(i.fan_num) for i in _fan_info_get_all()]
self.fantrayindex = fantray_index
self._fan_list = [Fan(i, self.fantrayindex) for i in range(1, max_fan + 1)]
# DeviceBase interface methods:
def get_name(self):
return 'fantray'
return f"fantray-{self.fantrayindex}"
def get_presence(self):
return True
@ -73,5 +22,78 @@ class FanDrawer(FanDrawerBase):
def get_status(self):
return True
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device.
Returns:
integer: The 1-based relative physical position in parent
device or -1 if cannot determine the position
"""
return self.fantrayindex
def is_replaceable(self):
"""
Indicate whether this fan drawer is replaceable.
Returns:
bool: True if it is replaceable, False if not
"""
return False
def get_model(self):
"""
Retrieves the part number of the fan drawer
Returns:
string: Part number of fan drawer
"""
return 'N/A'
def get_serial(self):
"""
Retrieves the serial number of the fan drawer
Returns:
string: Serial number of the fan drawer
"""
return 'N/A'
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.
"""
# Fan tray status LED controlled by BMC
return False
def get_status_led(self):
"""
Gets the state of the fan drawer LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings above
"""
return "N/A"
def get_maximum_consumed_power(self):
"""
Retrives the maximum power drawn by Fan Drawer
Returns:
A float, with value of the maximum consumable power of the
component.
"""
return 36.0
def fan_drawer_list_get():
return [FanDrawer()]
platform = device_info.get_platform()
if platform in ["x86_64-accton_as9516_32d-r0", "x86_64-accton_as9516bf_32d-r0"]:
max_fantray = 1
max_fan = 6
elif platform == "x86_64-accton_wedge100bf_65x-r0":
max_fantray = 2
max_fan = 5
else:
max_fantray = 1
max_fan = 5
return [FanDrawer(i, max_fan) for i in range(1, max_fantray + 1)]

View File

@ -25,9 +25,9 @@ class ThriftClient(object):
self.transport = TTransport.TBufferedTransport(self.transport)
bprotocol = TBinaryProtocol.TBinaryProtocol(self.transport)
pltfm_mgr_client_module = importlib.import_module(".".join(["pltfm_mgr_rpc", "pltfm_mgr_rpc"]))
self.pltfm_mgr_module = importlib.import_module(".".join(["pltfm_mgr_rpc", "pltfm_mgr_rpc"]))
pltfm_mgr_protocol = TMultiplexedProtocol.TMultiplexedProtocol(bprotocol, "pltfm_mgr_rpc")
self.pltfm_mgr = pltfm_mgr_client_module.Client(pltfm_mgr_protocol)
self.pltfm_mgr = self.pltfm_mgr_module.Client(pltfm_mgr_protocol)
self.transport.open()
return self
@ -38,6 +38,13 @@ class ThriftClient(object):
def __exit__(self, exc_type, exc_value, tb):
self.close()
def pltfm_mgr_ready():
try:
with ThriftClient():
return True
except Exception:
return False
def thrift_try(func, attempts=35):
for attempt in range(attempts):
try:
@ -47,3 +54,12 @@ def thrift_try(func, attempts=35):
if attempt + 1 == attempts:
raise e
time.sleep(1)
def pltfm_mgr_try(func, default=None, thrift_attempts=35):
def pm_cb_run(client):
try:
return (None, func(client.pltfm_mgr))
except client.pltfm_mgr_module.InvalidPltfmMgrOperation as ouch:
return (ouch.code, default)
return thrift_try(pm_cb_run)

View File

@ -1,5 +1,5 @@
#
# Autogenerated by Thrift Compiler (0.10.0)
# Autogenerated by Thrift Compiler (0.13.0)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#
@ -8,9 +8,12 @@
from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, TApplicationException
from thrift.protocol.TProtocol import TProtocolException
from thrift.TRecursive import fix_spec
import sys
from thrift.transport import TTransport
all_structs = []
class pltfm_mgr_sys_tmp_t(object):
@ -26,21 +29,9 @@ class pltfm_mgr_sys_tmp_t(object):
- tmp8
- tmp9
- tmp10
"""
thrift_spec = (
None, # 0
(1, TType.DOUBLE, 'tmp1', None, None, ), # 1
(2, TType.DOUBLE, 'tmp2', None, None, ), # 2
(3, TType.DOUBLE, 'tmp3', None, None, ), # 3
(4, TType.DOUBLE, 'tmp4', None, None, ), # 4
(5, TType.DOUBLE, 'tmp5', None, None, ), # 5
(6, TType.DOUBLE, 'tmp6', None, None, ), # 6
(7, TType.DOUBLE, 'tmp7', None, None, ), # 7
(8, TType.DOUBLE, 'tmp8', None, None, ), # 8
(9, TType.DOUBLE, 'tmp9', None, None, ), # 9
(10, TType.DOUBLE, 'tmp10', None, None, ), # 10
)
def __init__(self, tmp1=None, tmp2=None, tmp3=None, tmp4=None, tmp5=None, tmp6=None, tmp7=None, tmp8=None, tmp9=None, tmp10=None,):
self.tmp1 = tmp1
@ -56,7 +47,7 @@ class pltfm_mgr_sys_tmp_t(object):
def read(self, iprot):
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))
iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
return
iprot.readStructBegin()
while True:
@ -120,7 +111,7 @@ class pltfm_mgr_sys_tmp_t(object):
def write(self, oprot):
if oprot._fast_encode is not None and self.thrift_spec is not None:
oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))
oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
return
oprot.writeStructBegin('pltfm_mgr_sys_tmp_t')
if self.tmp1 is not None:
@ -206,33 +197,9 @@ class pltfm_mgr_eeprom_t(object):
- ext_mac_addr_size
- location
- crc8
"""
thrift_spec = (
None, # 0
(1, TType.I16, 'version', None, None, ), # 1
(2, TType.STRING, 'prod_name', 'UTF8', None, ), # 2
(3, TType.STRING, 'prod_part_num', 'UTF8', None, ), # 3
(4, TType.STRING, 'sys_asm_part_num', 'UTF8', None, ), # 4
(5, TType.STRING, 'bfn_pcba_part_num', 'UTF8', None, ), # 5
(6, TType.STRING, 'bfn_pcbb_part_num', 'UTF8', None, ), # 6
(7, TType.STRING, 'odm_pcba_part_num', 'UTF8', None, ), # 7
(8, TType.STRING, 'odm_pcba_ser_num', 'UTF8', None, ), # 8
(9, TType.I16, 'prod_state', None, None, ), # 9
(10, TType.I16, 'prod_ver', None, None, ), # 10
(11, TType.I16, 'prod_sub_ver', None, None, ), # 11
(12, TType.STRING, 'prod_ser_num', 'UTF8', None, ), # 12
(13, TType.STRING, 'prod_ast_tag', 'UTF8', None, ), # 13
(14, TType.STRING, 'sys_mfger', 'UTF8', None, ), # 14
(15, TType.STRING, 'sys_mfg_date', 'UTF8', None, ), # 15
(16, TType.STRING, 'pcb_mfger', 'UTF8', None, ), # 16
(17, TType.STRING, 'assembled_at', 'UTF8', None, ), # 17
(18, TType.STRING, 'loc_mac_addr', 'UTF8', None, ), # 18
(19, TType.STRING, 'ext_mac_addr', 'UTF8', None, ), # 19
(20, TType.I32, 'ext_mac_addr_size', None, None, ), # 20
(21, TType.STRING, 'location', 'UTF8', None, ), # 21
(22, TType.I16, 'crc8', None, None, ), # 22
)
def __init__(self, version=None, prod_name=None, prod_part_num=None, sys_asm_part_num=None, bfn_pcba_part_num=None, bfn_pcbb_part_num=None, odm_pcba_part_num=None, odm_pcba_ser_num=None, prod_state=None, prod_ver=None, prod_sub_ver=None, prod_ser_num=None, prod_ast_tag=None, sys_mfger=None, sys_mfg_date=None, pcb_mfger=None, assembled_at=None, loc_mac_addr=None, ext_mac_addr=None, ext_mac_addr_size=None, location=None, crc8=None,):
self.version = version
@ -260,7 +227,7 @@ class pltfm_mgr_eeprom_t(object):
def read(self, iprot):
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))
iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
return
iprot.readStructBegin()
while True:
@ -384,7 +351,7 @@ class pltfm_mgr_eeprom_t(object):
def write(self, oprot):
if oprot._fast_encode is not None and self.thrift_spec is not None:
oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))
oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
return
oprot.writeStructBegin('pltfm_mgr_eeprom_t')
if self.version is not None:
@ -506,21 +473,9 @@ class pltfm_mgr_pwr_supply_info_t(object):
- model
- serial
- rev
"""
thrift_spec = (
None, # 0
(1, TType.I32, 'vin', None, None, ), # 1
(2, TType.I32, 'vout', None, None, ), # 2
(3, TType.I32, 'iout', None, None, ), # 3
(4, TType.I32, 'pwr_out', None, None, ), # 4
(5, TType.I32, 'fspeed', None, None, ), # 5
(6, TType.BOOL, 'ffault', None, None, ), # 6
(7, TType.BOOL, 'load_sharing', None, None, ), # 7
(8, TType.STRING, 'model', 'UTF8', None, ), # 8
(9, TType.STRING, 'serial', 'UTF8', None, ), # 9
(10, TType.STRING, 'rev', 'UTF8', None, ), # 10
)
def __init__(self, vin=None, vout=None, iout=None, pwr_out=None, fspeed=None, ffault=None, load_sharing=None, model=None, serial=None, rev=None,):
self.vin = vin
@ -536,7 +491,7 @@ class pltfm_mgr_pwr_supply_info_t(object):
def read(self, iprot):
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))
iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
return
iprot.readStructBegin()
while True:
@ -600,7 +555,7 @@ class pltfm_mgr_pwr_supply_info_t(object):
def write(self, oprot):
if oprot._fast_encode is not None and self.thrift_spec is not None:
oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))
oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
return
oprot.writeStructBegin('pltfm_mgr_pwr_supply_info_t')
if self.vin is not None:
@ -680,27 +635,9 @@ class pltfm_mgr_pwr_rail_info_t(object):
- vrail14
- vrail15
- vrail16
"""
thrift_spec = (
None, # 0
(1, TType.I32, 'vrail1', None, None, ), # 1
(2, TType.I32, 'vrail2', None, None, ), # 2
(3, TType.I32, 'vrail3', None, None, ), # 3
(4, TType.I32, 'vrail4', None, None, ), # 4
(5, TType.I32, 'vrail5', None, None, ), # 5
(6, TType.I32, 'vrail6', None, None, ), # 6
(7, TType.I32, 'vrail7', None, None, ), # 7
(8, TType.I32, 'vrail8', None, None, ), # 8
(9, TType.I32, 'vrail9', None, None, ), # 9
(10, TType.I32, 'vrail10', None, None, ), # 10
(11, TType.I32, 'vrail11', None, None, ), # 11
(12, TType.I32, 'vrail12', None, None, ), # 12
(13, TType.I32, 'vrail13', None, None, ), # 13
(14, TType.I32, 'vrail14', None, None, ), # 14
(15, TType.I32, 'vrail15', None, None, ), # 15
(16, TType.I32, 'vrail16', None, None, ), # 16
)
def __init__(self, vrail1=None, vrail2=None, vrail3=None, vrail4=None, vrail5=None, vrail6=None, vrail7=None, vrail8=None, vrail9=None, vrail10=None, vrail11=None, vrail12=None, vrail13=None, vrail14=None, vrail15=None, vrail16=None,):
self.vrail1 = vrail1
@ -722,7 +659,7 @@ class pltfm_mgr_pwr_rail_info_t(object):
def read(self, iprot):
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))
iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
return
iprot.readStructBegin()
while True:
@ -816,7 +753,7 @@ class pltfm_mgr_pwr_rail_info_t(object):
def write(self, oprot):
if oprot._fast_encode is not None and self.thrift_spec is not None:
oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))
oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
return
oprot.writeStructBegin('pltfm_mgr_pwr_rail_info_t')
if self.vrail1 is not None:
@ -908,15 +845,9 @@ class pltfm_mgr_fan_info_t(object):
- front_rpm
- rear_rpm
- percent
"""
thrift_spec = (
None, # 0
(1, TType.I32, 'fan_num', None, None, ), # 1
(2, TType.I32, 'front_rpm', None, None, ), # 2
(3, TType.I32, 'rear_rpm', None, None, ), # 3
(4, TType.I32, 'percent', None, None, ), # 4
)
def __init__(self, fan_num=None, front_rpm=None, rear_rpm=None, percent=None,):
self.fan_num = fan_num
@ -926,7 +857,7 @@ class pltfm_mgr_fan_info_t(object):
def read(self, iprot):
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))
iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
return
iprot.readStructBegin()
while True:
@ -960,7 +891,7 @@ class pltfm_mgr_fan_info_t(object):
def write(self, oprot):
if oprot._fast_encode is not None and self.thrift_spec is not None:
oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))
oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
return
oprot.writeStructBegin('pltfm_mgr_fan_info_t')
if self.fan_num is not None:
@ -997,23 +928,361 @@ class pltfm_mgr_fan_info_t(object):
return not (self == other)
class pltfm_mgr_qsfp_alarm_flags_t(object):
"""
Attributes:
- highalarm
- lowalarm
- highwarning
- lowwarning
"""
def __init__(self, highalarm=None, lowalarm=None, highwarning=None, lowwarning=None,):
self.highalarm = highalarm
self.lowalarm = lowalarm
self.highwarning = highwarning
self.lowwarning = lowwarning
def read(self, iprot):
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
if fid == 1:
if ftype == TType.BOOL:
self.highalarm = iprot.readBool()
else:
iprot.skip(ftype)
elif fid == 2:
if ftype == TType.BOOL:
self.lowalarm = iprot.readBool()
else:
iprot.skip(ftype)
elif fid == 3:
if ftype == TType.BOOL:
self.highwarning = iprot.readBool()
else:
iprot.skip(ftype)
elif fid == 4:
if ftype == TType.BOOL:
self.lowwarning = iprot.readBool()
else:
iprot.skip(ftype)
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot._fast_encode is not None and self.thrift_spec is not None:
oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
return
oprot.writeStructBegin('pltfm_mgr_qsfp_alarm_flags_t')
if self.highalarm is not None:
oprot.writeFieldBegin('highalarm', TType.BOOL, 1)
oprot.writeBool(self.highalarm)
oprot.writeFieldEnd()
if self.lowalarm is not None:
oprot.writeFieldBegin('lowalarm', TType.BOOL, 2)
oprot.writeBool(self.lowalarm)
oprot.writeFieldEnd()
if self.highwarning is not None:
oprot.writeFieldBegin('highwarning', TType.BOOL, 3)
oprot.writeBool(self.highwarning)
oprot.writeFieldEnd()
if self.lowwarning is not None:
oprot.writeFieldBegin('lowwarning', TType.BOOL, 4)
oprot.writeBool(self.lowwarning)
oprot.writeFieldEnd()
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.items()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)
class pltfm_mgr_qsfp_threshold_t(object):
"""
Attributes:
- highalarm
- lowalarm
- highwarning
- lowwarning
"""
def __init__(self, highalarm=None, lowalarm=None, highwarning=None, lowwarning=None,):
self.highalarm = highalarm
self.lowalarm = lowalarm
self.highwarning = highwarning
self.lowwarning = lowwarning
def read(self, iprot):
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
if fid == 1:
if ftype == TType.DOUBLE:
self.highalarm = iprot.readDouble()
else:
iprot.skip(ftype)
elif fid == 2:
if ftype == TType.DOUBLE:
self.lowalarm = iprot.readDouble()
else:
iprot.skip(ftype)
elif fid == 3:
if ftype == TType.DOUBLE:
self.highwarning = iprot.readDouble()
else:
iprot.skip(ftype)
elif fid == 4:
if ftype == TType.DOUBLE:
self.lowwarning = iprot.readDouble()
else:
iprot.skip(ftype)
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot._fast_encode is not None and self.thrift_spec is not None:
oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
return
oprot.writeStructBegin('pltfm_mgr_qsfp_threshold_t')
if self.highalarm is not None:
oprot.writeFieldBegin('highalarm', TType.DOUBLE, 1)
oprot.writeDouble(self.highalarm)
oprot.writeFieldEnd()
if self.lowalarm is not None:
oprot.writeFieldBegin('lowalarm', TType.DOUBLE, 2)
oprot.writeDouble(self.lowalarm)
oprot.writeFieldEnd()
if self.highwarning is not None:
oprot.writeFieldBegin('highwarning', TType.DOUBLE, 3)
oprot.writeDouble(self.highwarning)
oprot.writeFieldEnd()
if self.lowwarning is not None:
oprot.writeFieldBegin('lowwarning', TType.DOUBLE, 4)
oprot.writeDouble(self.lowwarning)
oprot.writeFieldEnd()
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.items()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)
class pltfm_mgr_qsfp_thresholds_t(object):
"""
Attributes:
- rx_pwr
- temp
- tx_bias
- tx_pwr
- vcc
- rx_pwr_is_set
- temp_is_set
- tx_bias_is_set
- tx_pwr_is_set
- vcc_is_set
"""
def __init__(self, rx_pwr=None, temp=None, tx_bias=None, tx_pwr=None, vcc=None, rx_pwr_is_set=None, temp_is_set=None, tx_bias_is_set=None, tx_pwr_is_set=None, vcc_is_set=None,):
self.rx_pwr = rx_pwr
self.temp = temp
self.tx_bias = tx_bias
self.tx_pwr = tx_pwr
self.vcc = vcc
self.rx_pwr_is_set = rx_pwr_is_set
self.temp_is_set = temp_is_set
self.tx_bias_is_set = tx_bias_is_set
self.tx_pwr_is_set = tx_pwr_is_set
self.vcc_is_set = vcc_is_set
def read(self, iprot):
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
if fid == 1:
if ftype == TType.STRUCT:
self.rx_pwr = pltfm_mgr_qsfp_threshold_t()
self.rx_pwr.read(iprot)
else:
iprot.skip(ftype)
elif fid == 2:
if ftype == TType.STRUCT:
self.temp = pltfm_mgr_qsfp_threshold_t()
self.temp.read(iprot)
else:
iprot.skip(ftype)
elif fid == 3:
if ftype == TType.STRUCT:
self.tx_bias = pltfm_mgr_qsfp_threshold_t()
self.tx_bias.read(iprot)
else:
iprot.skip(ftype)
elif fid == 4:
if ftype == TType.STRUCT:
self.tx_pwr = pltfm_mgr_qsfp_threshold_t()
self.tx_pwr.read(iprot)
else:
iprot.skip(ftype)
elif fid == 5:
if ftype == TType.STRUCT:
self.vcc = pltfm_mgr_qsfp_threshold_t()
self.vcc.read(iprot)
else:
iprot.skip(ftype)
elif fid == 6:
if ftype == TType.BOOL:
self.rx_pwr_is_set = iprot.readBool()
else:
iprot.skip(ftype)
elif fid == 7:
if ftype == TType.BOOL:
self.temp_is_set = iprot.readBool()
else:
iprot.skip(ftype)
elif fid == 8:
if ftype == TType.BOOL:
self.tx_bias_is_set = iprot.readBool()
else:
iprot.skip(ftype)
elif fid == 9:
if ftype == TType.BOOL:
self.tx_pwr_is_set = iprot.readBool()
else:
iprot.skip(ftype)
elif fid == 10:
if ftype == TType.BOOL:
self.vcc_is_set = iprot.readBool()
else:
iprot.skip(ftype)
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot._fast_encode is not None and self.thrift_spec is not None:
oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
return
oprot.writeStructBegin('pltfm_mgr_qsfp_thresholds_t')
if self.rx_pwr is not None:
oprot.writeFieldBegin('rx_pwr', TType.STRUCT, 1)
self.rx_pwr.write(oprot)
oprot.writeFieldEnd()
if self.temp is not None:
oprot.writeFieldBegin('temp', TType.STRUCT, 2)
self.temp.write(oprot)
oprot.writeFieldEnd()
if self.tx_bias is not None:
oprot.writeFieldBegin('tx_bias', TType.STRUCT, 3)
self.tx_bias.write(oprot)
oprot.writeFieldEnd()
if self.tx_pwr is not None:
oprot.writeFieldBegin('tx_pwr', TType.STRUCT, 4)
self.tx_pwr.write(oprot)
oprot.writeFieldEnd()
if self.vcc is not None:
oprot.writeFieldBegin('vcc', TType.STRUCT, 5)
self.vcc.write(oprot)
oprot.writeFieldEnd()
if self.rx_pwr_is_set is not None:
oprot.writeFieldBegin('rx_pwr_is_set', TType.BOOL, 6)
oprot.writeBool(self.rx_pwr_is_set)
oprot.writeFieldEnd()
if self.temp_is_set is not None:
oprot.writeFieldBegin('temp_is_set', TType.BOOL, 7)
oprot.writeBool(self.temp_is_set)
oprot.writeFieldEnd()
if self.tx_bias_is_set is not None:
oprot.writeFieldBegin('tx_bias_is_set', TType.BOOL, 8)
oprot.writeBool(self.tx_bias_is_set)
oprot.writeFieldEnd()
if self.tx_pwr_is_set is not None:
oprot.writeFieldBegin('tx_pwr_is_set', TType.BOOL, 9)
oprot.writeBool(self.tx_pwr_is_set)
oprot.writeFieldEnd()
if self.vcc_is_set is not None:
oprot.writeFieldBegin('vcc_is_set', TType.BOOL, 10)
oprot.writeBool(self.vcc_is_set)
oprot.writeFieldEnd()
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.items()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)
class InvalidPltfmMgrOperation(TException):
"""
Attributes:
- code
"""
thrift_spec = (
None, # 0
(1, TType.I32, 'code', None, None, ), # 1
)
def __init__(self, code=None,):
self.code = code
def read(self, iprot):
if iprot._fast_decode is not None and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None:
iprot._fast_decode(self, iprot, (self.__class__, self.thrift_spec))
iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])
return
iprot.readStructBegin()
while True:
@ -1032,7 +1301,7 @@ class InvalidPltfmMgrOperation(TException):
def write(self, oprot):
if oprot._fast_encode is not None and self.thrift_spec is not None:
oprot.trans.write(oprot._fast_encode(self, (self.__class__, self.thrift_spec)))
oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))
return
oprot.writeStructBegin('InvalidPltfmMgrOperation')
if self.code is not None:
@ -1058,3 +1327,122 @@ class InvalidPltfmMgrOperation(TException):
def __ne__(self, other):
return not (self == other)
all_structs.append(pltfm_mgr_sys_tmp_t)
pltfm_mgr_sys_tmp_t.thrift_spec = (
None, # 0
(1, TType.DOUBLE, 'tmp1', None, None, ), # 1
(2, TType.DOUBLE, 'tmp2', None, None, ), # 2
(3, TType.DOUBLE, 'tmp3', None, None, ), # 3
(4, TType.DOUBLE, 'tmp4', None, None, ), # 4
(5, TType.DOUBLE, 'tmp5', None, None, ), # 5
(6, TType.DOUBLE, 'tmp6', None, None, ), # 6
(7, TType.DOUBLE, 'tmp7', None, None, ), # 7
(8, TType.DOUBLE, 'tmp8', None, None, ), # 8
(9, TType.DOUBLE, 'tmp9', None, None, ), # 9
(10, TType.DOUBLE, 'tmp10', None, None, ), # 10
)
all_structs.append(pltfm_mgr_eeprom_t)
pltfm_mgr_eeprom_t.thrift_spec = (
None, # 0
(1, TType.I16, 'version', None, None, ), # 1
(2, TType.STRING, 'prod_name', 'UTF8', None, ), # 2
(3, TType.STRING, 'prod_part_num', 'UTF8', None, ), # 3
(4, TType.STRING, 'sys_asm_part_num', 'UTF8', None, ), # 4
(5, TType.STRING, 'bfn_pcba_part_num', 'UTF8', None, ), # 5
(6, TType.STRING, 'bfn_pcbb_part_num', 'UTF8', None, ), # 6
(7, TType.STRING, 'odm_pcba_part_num', 'UTF8', None, ), # 7
(8, TType.STRING, 'odm_pcba_ser_num', 'UTF8', None, ), # 8
(9, TType.I16, 'prod_state', None, None, ), # 9
(10, TType.I16, 'prod_ver', None, None, ), # 10
(11, TType.I16, 'prod_sub_ver', None, None, ), # 11
(12, TType.STRING, 'prod_ser_num', 'UTF8', None, ), # 12
(13, TType.STRING, 'prod_ast_tag', 'UTF8', None, ), # 13
(14, TType.STRING, 'sys_mfger', 'UTF8', None, ), # 14
(15, TType.STRING, 'sys_mfg_date', 'UTF8', None, ), # 15
(16, TType.STRING, 'pcb_mfger', 'UTF8', None, ), # 16
(17, TType.STRING, 'assembled_at', 'UTF8', None, ), # 17
(18, TType.STRING, 'loc_mac_addr', 'UTF8', None, ), # 18
(19, TType.STRING, 'ext_mac_addr', 'UTF8', None, ), # 19
(20, TType.I32, 'ext_mac_addr_size', None, None, ), # 20
(21, TType.STRING, 'location', 'UTF8', None, ), # 21
(22, TType.I16, 'crc8', None, None, ), # 22
)
all_structs.append(pltfm_mgr_pwr_supply_info_t)
pltfm_mgr_pwr_supply_info_t.thrift_spec = (
None, # 0
(1, TType.I32, 'vin', None, None, ), # 1
(2, TType.I32, 'vout', None, None, ), # 2
(3, TType.I32, 'iout', None, None, ), # 3
(4, TType.I32, 'pwr_out', None, None, ), # 4
(5, TType.I32, 'fspeed', None, None, ), # 5
(6, TType.BOOL, 'ffault', None, None, ), # 6
(7, TType.BOOL, 'load_sharing', None, None, ), # 7
(8, TType.STRING, 'model', 'UTF8', None, ), # 8
(9, TType.STRING, 'serial', 'UTF8', None, ), # 9
(10, TType.STRING, 'rev', 'UTF8', None, ), # 10
)
all_structs.append(pltfm_mgr_pwr_rail_info_t)
pltfm_mgr_pwr_rail_info_t.thrift_spec = (
None, # 0
(1, TType.I32, 'vrail1', None, None, ), # 1
(2, TType.I32, 'vrail2', None, None, ), # 2
(3, TType.I32, 'vrail3', None, None, ), # 3
(4, TType.I32, 'vrail4', None, None, ), # 4
(5, TType.I32, 'vrail5', None, None, ), # 5
(6, TType.I32, 'vrail6', None, None, ), # 6
(7, TType.I32, 'vrail7', None, None, ), # 7
(8, TType.I32, 'vrail8', None, None, ), # 8
(9, TType.I32, 'vrail9', None, None, ), # 9
(10, TType.I32, 'vrail10', None, None, ), # 10
(11, TType.I32, 'vrail11', None, None, ), # 11
(12, TType.I32, 'vrail12', None, None, ), # 12
(13, TType.I32, 'vrail13', None, None, ), # 13
(14, TType.I32, 'vrail14', None, None, ), # 14
(15, TType.I32, 'vrail15', None, None, ), # 15
(16, TType.I32, 'vrail16', None, None, ), # 16
)
all_structs.append(pltfm_mgr_fan_info_t)
pltfm_mgr_fan_info_t.thrift_spec = (
None, # 0
(1, TType.I32, 'fan_num', None, None, ), # 1
(2, TType.I32, 'front_rpm', None, None, ), # 2
(3, TType.I32, 'rear_rpm', None, None, ), # 3
(4, TType.I32, 'percent', None, None, ), # 4
)
all_structs.append(pltfm_mgr_qsfp_alarm_flags_t)
pltfm_mgr_qsfp_alarm_flags_t.thrift_spec = (
None, # 0
(1, TType.BOOL, 'highalarm', None, None, ), # 1
(2, TType.BOOL, 'lowalarm', None, None, ), # 2
(3, TType.BOOL, 'highwarning', None, None, ), # 3
(4, TType.BOOL, 'lowwarning', None, None, ), # 4
)
all_structs.append(pltfm_mgr_qsfp_threshold_t)
pltfm_mgr_qsfp_threshold_t.thrift_spec = (
None, # 0
(1, TType.DOUBLE, 'highalarm', None, None, ), # 1
(2, TType.DOUBLE, 'lowalarm', None, None, ), # 2
(3, TType.DOUBLE, 'highwarning', None, None, ), # 3
(4, TType.DOUBLE, 'lowwarning', None, None, ), # 4
)
all_structs.append(pltfm_mgr_qsfp_thresholds_t)
pltfm_mgr_qsfp_thresholds_t.thrift_spec = (
None, # 0
(1, TType.STRUCT, 'rx_pwr', [pltfm_mgr_qsfp_threshold_t, None], None, ), # 1
(2, TType.STRUCT, 'temp', [pltfm_mgr_qsfp_threshold_t, None], None, ), # 2
(3, TType.STRUCT, 'tx_bias', [pltfm_mgr_qsfp_threshold_t, None], None, ), # 3
(4, TType.STRUCT, 'tx_pwr', [pltfm_mgr_qsfp_threshold_t, None], None, ), # 4
(5, TType.STRUCT, 'vcc', [pltfm_mgr_qsfp_threshold_t, None], None, ), # 5
(6, TType.BOOL, 'rx_pwr_is_set', None, None, ), # 6
(7, TType.BOOL, 'temp_is_set', None, None, ), # 7
(8, TType.BOOL, 'tx_bias_is_set', None, None, ), # 8
(9, TType.BOOL, 'tx_pwr_is_set', None, None, ), # 9
(10, TType.BOOL, 'vcc_is_set', None, None, ), # 10
)
all_structs.append(InvalidPltfmMgrOperation)
InvalidPltfmMgrOperation.thrift_spec = (
None, # 0
(1, TType.I32, 'code', None, None, ), # 1
)
fix_spec(all_structs)
del all_structs

View File

@ -3,6 +3,7 @@
try:
import os
import sys
import time
sys.path.append(os.path.dirname(__file__))
@ -18,6 +19,10 @@ class Psu(PsuBase):
def __init__(self, index):
PsuBase.__init__(self)
self.__index = index
self.__info = None
self.__ts = 0
# STUB IMPLEMENTATION
self.color = ""
'''
Units of returned info object values:
@ -31,7 +36,16 @@ class Psu(PsuBase):
def psu_info_get(client):
return client.pltfm_mgr.pltfm_mgr_pwr_supply_info_get(self.__index)
return thrift_try(psu_info_get)
# Update cache once per 2 seconds
if self.__ts + 2 < time.time():
self.__info = None
try:
self.__info = thrift_try(psu_info_get, attempts=1)
finally:
self.__ts = time.time()
return self.__info
return self.__info
@staticmethod
def get_num_psus():
@ -52,6 +66,8 @@ class Psu(PsuBase):
:return: Boolean, True if PSU is operating properly, False if PSU is faulty
"""
info = self.__info_get()
if info is None:
return False
return info.ffault == False and info.vout != 0
def get_voltage(self):
@ -62,7 +78,8 @@ class Psu(PsuBase):
A float number, the output voltage in volts,
e.g. 12.1
"""
return float(self.__info_get().vout)
info = self.__info_get()
return float(info.vout) if info else 0
def get_current(self):
"""
@ -71,7 +88,8 @@ class Psu(PsuBase):
Returns:
A float number, the electric current in amperes, e.g 15.4
"""
return self.__info_get().iout / 1000.
info = self.__info_get()
return info.iout / 1000 if info else 0
def get_power(self):
"""
@ -80,7 +98,8 @@ class Psu(PsuBase):
Returns:
A float number, the power in watts, e.g. 302.6
"""
return self.__info_get().pwr_out / 1000.
info = self.__info_get()
return info.pwr_out / 1000 if info else 0
def get_presence(self):
"""
@ -92,19 +111,94 @@ class Psu(PsuBase):
def psu_present_get(client):
return client.pltfm_mgr.pltfm_mgr_pwr_supply_present_get(self.__index)
status = thrift_try(psu_present_get)
return status
status = False
try:
status = thrift_try(psu_present_get)
finally:
return status
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
"""
# STUB IMPLEMENTATION
self.color = color
return True
def get_status_led(self):
"""
Gets the state of the PSU status LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings above
"""
# STUB IMPLEMENTATION
return self.color
# DeviceBase iface:
def get_serial(self):
return self.__info_get().serial
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
info = self.__info_get()
return info.serial if info else "N/A"
def get_model(self):
return self.__info_get().model
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
info = self.__info_get()
return info.model if info else "N/A"
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True
def get_revision(self):
"""
Retrieves the hardware revision of the device
Returns:
string: Revision value of device
"""
info = self.__info_get()
return info.rev if info else "N/A"
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 self.get_powergood_status()
def get_position_in_parent(self):
"""
Retrieves 1-based relative physical position in parent device. If the agent cannot determine the parent-relative position
for some reason, or if the associated value of entPhysicalContainedIn is '0', then the value '-1' is returned
Returns:
integer: The 1-based relative physical position in parent device or -1 if cannot determine the position
"""
return self.__index
def psu_list_get():
psu_list = []
for i in range(1, Psu.get_num_psus() + 1):

View File

@ -2,80 +2,47 @@
try:
import os
import sys
import time
import tempfile
from contextlib import contextmanager
from copy import copy
sys.path.append(os.path.dirname(__file__))
from .platform_thrift_client import ThriftClient
from .platform_thrift_client import thrift_try
from sonic_platform_base.sfp_base import SfpBase
from sonic_platform_base.sonic_sfp.sfputilbase import SfpUtilBase
from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase
from sonic_platform.platform_thrift_client import thrift_try
from sonic_platform.platform_thrift_client import pltfm_mgr_try
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""
SFP_TYPE = "SFP"
QSFP_TYPE = "QSFP"
QSFP_DD_TYPE = "QSFP_DD"
PORT_START = 1
PORT_END = 0
PORTS_IN_BLOCK = 0
QSFP_PORT_START = 1
QSFP_PORT_END = 0
EEPROM_OFFSET = 0
QSFP_CHECK_INTERVAL = 4
@property
def port_start(self):
self.update_port_info()
return self.PORT_START
class Sfp(SfpOptoeBase):
"""
BFN Platform-specific SFP class
"""
@property
def port_end(self):
self.update_port_info()
return self.PORT_END
SFP_EEPROM_PATH = "/var/run/platform/sfp/"
@property
def qsfp_ports(self):
self.update_port_info()
return range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)
def __init__(self, port_num):
SfpOptoeBase.__init__(self)
self.index = port_num
self.port_num = port_num
self.sfp_type = QSFP_TYPE
@property
def port_to_eeprom_mapping(self):
print("dependency on sysfs has been removed")
raise Exception()
if not os.path.exists(self.SFP_EEPROM_PATH):
try:
os.makedirs(self.SFP_EEPROM_PATH)
except OSError as e:
if e.errno != errno.EEXIST:
raise
def __init__(self):
self.ready = False
self.phy_port_dict = {'-1': 'system_not_ready'}
self.phy_port_cur_state = {}
self.qsfp_interval = self.QSFP_CHECK_INTERVAL
SfpUtilBase.__init__(self)
def update_port_info(self):
def qsfp_max_port_get(client):
return client.pltfm_mgr.pltfm_mgr_qsfp_get_max_port();
if self.QSFP_PORT_END == 0:
self.QSFP_PORT_END = thrift_try(qsfp_max_port_get)
self.PORT_END = self.QSFP_PORT_END
self.PORTS_IN_BLOCK = self.QSFP_PORT_END
def get_presence(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False
self.eeprom_path = self.SFP_EEPROM_PATH + "sfp{}-eeprom-cache".format(self.index)
def get_presence(self):
"""
Retrieves the presence of the sfp
"""
presence = False
def qsfp_presence_get(client):
return client.pltfm_mgr.pltfm_mgr_qsfp_presence_get(port_num)
return client.pltfm_mgr.pltfm_mgr_qsfp_presence_get(self.index)
try:
presence = thrift_try(qsfp_presence_get)
@ -85,194 +52,156 @@ class SfpUtil(SfpUtilBase):
return presence
def get_low_power_mode(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False
def get_lpmode(self):
"""
Retrieves the lpmode (low power mode) status of this SFP
"""
def qsfp_lpmode_get(client):
return client.pltfm_mgr.pltfm_mgr_qsfp_lpmode_get(port_num)
return client.pltfm_mgr.pltfm_mgr_qsfp_lpmode_get(self.index)
lpmode = thrift_try(qsfp_lpmode_get)
return lpmode
def set_low_power_mode(self, port_num, lpmode):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False
return thrift_try(qsfp_lpmode_get)
def set_lpmode(self, lpmode):
"""
Sets the lpmode (low power mode) of SFP
"""
def qsfp_lpmode_set(client):
return client.pltfm_mgr.pltfm_mgr_qsfp_lpmode_set(port_num, lpmode)
return client.pltfm_mgr.pltfm_mgr_qsfp_lpmode_set(self.index, lpmode)
status = thrift_try(qsfp_lpmode_set)
return (status == 0)
def reset(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False
def qsfp_reset(client):
client.pltfm_mgr.pltfm_mgr_qsfp_reset(port_num, True)
return client.pltfm_mgr.pltfm_mgr_qsfp_reset(port_num, False)
err = thrift_try(qsfp_reset)
return not err
def check_transceiver_change(self):
if not self.ready:
return
self.phy_port_dict = {}
try:
client = ThriftClient().open()
except Exception:
return
# Get presence of each SFP
for port in range(self.port_start, self.port_end + 1):
try:
sfp_resent = client.pltfm_mgr.pltfm_mgr_qsfp_presence_get(port)
except Exception:
sfp_resent = False
sfp_state = '1' if sfp_resent else '0'
if port in self.phy_port_cur_state:
if self.phy_port_cur_state[port] != sfp_state:
self.phy_port_dict[port] = sfp_state
else:
self.phy_port_dict[port] = sfp_state
# Update port current state
self.phy_port_cur_state[port] = sfp_state
client.close()
def get_transceiver_change_event(self, timeout=0):
forever = False
if timeout == 0:
forever = True
elif timeout > 0:
timeout = timeout / float(1000) # Convert to secs
else:
print("get_transceiver_change_event:Invalid timeout value", timeout)
return False, {}
while forever or timeout > 0:
if not self.ready:
try:
with ThriftClient(): pass
except Exception:
pass
else:
self.ready = True
self.phy_port_dict = {}
break
elif self.qsfp_interval == 0:
self.qsfp_interval = self.QSFP_CHECK_INTERVAL
# Process transceiver plug-in/out event
self.check_transceiver_change()
# Break if tranceiver state has changed
if bool(self.phy_port_dict):
break
if timeout:
timeout -= 1
if self.qsfp_interval:
self.qsfp_interval -= 1
time.sleep(1)
return self.ready, self.phy_port_dict
@contextmanager
def eeprom_action(self):
u = copy(self)
with tempfile.NamedTemporaryFile() as f:
u.eeprom_path = f.name
yield u
def _sfp_eeprom_present(self, client_eeprompath, offset):
return client_eeprompath and super(SfpUtil, self)._sfp_eeprom_present(client_eeprompath, offset)
def _get_port_eeprom_path(self, port_num, devid):
def get_eeprom_path(self):
def qsfp_info_get(client):
return client.pltfm_mgr.pltfm_mgr_qsfp_info_get(port_num)
return client.pltfm_mgr.pltfm_mgr_qsfp_info_get(self.index)
if self.get_presence(port_num):
if self.get_presence():
eeprom_hex = thrift_try(qsfp_info_get)
eeprom_raw = bytearray.fromhex(eeprom_hex)
with open(self.eeprom_path, 'wb') as eeprom_cache:
eeprom_cache.write(eeprom_raw)
with open(self.eeprom_path, 'wb') as fp:
fp.write(eeprom_raw)
return self.eeprom_path
return None
class Sfp(SfpBase):
"""Platform-specific Sfp class"""
def write_eeprom(self, offset, num_bytes, write_buffer):
# Not supported at the moment
return False
sfputil = SfpUtil()
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
return "sfp{}".format(self.index)
@staticmethod
def port_start():
return Sfp.sfputil.port_start
@staticmethod
def port_end():
return Sfp.sfputil.port_end
@staticmethod
def qsfp_ports():
return Sfp.sfputil.qsfp_ports()
@staticmethod
def get_transceiver_change_event(timeout=0):
return Sfp.sfputil.get_transceiver_change_event()
def __init__(self, port_num):
self.port_num = port_num
SfpBase.__init__(self)
def get_presence(self):
with Sfp.sfputil.eeprom_action() as u:
return u.get_presence(self.port_num)
def get_lpmode(self):
with Sfp.sfputil.eeprom_action() as u:
return u.get_low_power_mode(self.port_num)
def set_lpmode(self, lpmode):
with Sfp.sfputil.eeprom_action() as u:
return u.set_low_power_mode(self.port_num, lpmode)
def get_reset_status(self):
"""
Retrieves the reset status of SFP
"""
def get_qsfp_reset(pltfm_mgr):
return pltfm_mgr.pltfm_mgr_qsfp_reset_get(self.index)
_, status = pltfm_mgr_try(get_qsfp_reset, False)
return status
def reset(self):
return Sfp.sfputil.reset(self.port_num)
"""
Reset SFP and return all user module settings to their default srate.
"""
def qsfp_reset(client):
client.pltfm_mgr.pltfm_mgr_qsfp_reset(self.index, True)
return client.pltfm_mgr.pltfm_mgr_qsfp_reset(self.index, False)
def get_transceiver_info(self):
with Sfp.sfputil.eeprom_action() as u:
return u.get_transceiver_info_dict(self.port_num)
err = thrift_try(qsfp_reset)
return not err
def get_transceiver_bulk_status(self):
with Sfp.sfputil.eeprom_action() as u:
return u.get_transceiver_dom_info_dict(self.port_num)
def get_status(self):
"""
Retrieves the operational status of the device
"""
reset = self.get_reset_status()
def get_transceiver_threshold_info(self):
with Sfp.sfputil.eeprom_action() as u:
return u.get_transceiver_dom_threshold_info_dict(self.port_num)
if reset:
status = False
else:
status = True
def get_change_event(self, timeout=0):
return Sfp.get_transceiver_change_event(timeout)
return status
def sfp_list_get():
sfp_list = []
for index in range(Sfp.port_start(), Sfp.port_end() + 1):
sfp_node = Sfp(index)
sfp_list.append(sfp_node)
return sfp_list
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 self.index
def is_replaceable(self):
"""
Indicate whether this device is replaceable.
Returns:
bool: True if it is replaceable.
"""
return True
def get_error_description(self):
"""
Retrives the error descriptions of the SFP module
Returns:
String that represents the current error descriptions of vendor specific errors
In case there are multiple errors, they should be joined by '|',
like: "Bad EEPROM|Unsupported cable"
"""
if not self.get_presence():
return self.SFP_STATUS_UNPLUGGED
return self.SFP_STATUS_OK
def tx_disable(self, tx_disable):
"""
Disable SFP TX for all channels
Args:
tx_disable : A Boolean, True to enable tx_disable mode, False to disable
tx_disable mode.
Returns:
A boolean, True if tx_disable is set successfully, False if not
"""
if self.sfp_type == QSFP_TYPE:
return self.tx_disable_channel(0xF, tx_disable)
return False
def tx_disable_channel(self, channel, disable):
"""
Sets the tx_disable for specified SFP channels
Args:
channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3,
e.g. 0x5 for channel 0 and channel 2.
disable : A boolean, True to disable TX channels specified in channel,
False to enable
Returns:
A boolean, True if successful, False if not
"""
def qsfp_tx_disable_channel(client):
return client.pltfm_mgr.pltfm_mgr_qsfp_tx_disable(self.index, channel, disable)
if self.sfp_type == QSFP_TYPE:
status = thrift_try(qsfp_tx_disable_channel)
return (status == 0)
return False
def get_power_override(self):
def get_qsfp_power_override(pltfm_mgr):
return pltfm_mgr.pltfm_mgr_qsfp_pwr_override_get(self.index)
_, pwr_override = pltfm_mgr_try(get_qsfp_power_override)
return pwr_override
def set_power_override(self, power_override, power_set):
def set_qsfp_power_override(pltfm_mgr):
return pltfm_mgr.pltfm_mgr_qsfp_pwr_override_set(
self.index, power_override, power_set
)
_, status = pltfm_mgr_try(set_qsfp_power_override)
return status

View File

@ -1,7 +1,7 @@
try:
import subprocess
from sonic_platform.bfn_extensions.platform_sensors import platform_sensors_get
from bfn_extensions.platform_sensors import platform_sensors_get
from sonic_platform_base.thermal_base import ThermalBase
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
@ -68,20 +68,24 @@ def _value_get(d: dict, key_prefix, key_suffix=''):
# Thermal -> ThermalBase -> DeviceBase
class Thermal(ThermalBase):
def __init__(self, chip, label):
def __init__(self, chip, label, index = 0):
self.__chip = chip
self.__label = label
self.__name = f"{chip}:{label}".lower().replace(' ', '-')
self.__collect_temp = []
self.__index = index
def __get(self, attr_prefix, attr_suffix):
sensor_data = _sensors_get().get(self.__chip, {}).get(self.__label, {})
value = _value_get(sensor_data, attr_prefix, attr_suffix)
if value is not None: return value
raise NotImplementedError
return value if value is not None else -999.9
# ThermalBase interface methods:
def get_temperature(self) -> float:
return float(self.__get('temp', 'input'))
temp = self.__get('temp', 'input')
self.__collect_temp.append(float(temp))
self.__collect_temp.sort()
return float(temp)
def get_high_threshold(self) -> float:
return float(self.__get('temp', 'max'))
@ -89,6 +93,12 @@ class Thermal(ThermalBase):
def get_high_critical_threshold(self) -> float:
return float(self.__get('temp', 'crit'))
def get_low_critical_threshold(self) -> float:
return float(self.__get('temp', 'alarm'))
def get_model(self):
return f"{self.__label}".lower()
# DeviceBase interface methods:
def get_name(self):
return self.__name
@ -99,11 +109,41 @@ class Thermal(ThermalBase):
def get_status(self):
return True
def is_replaceable(self):
return False
def get_low_threshold(self) -> float:
return float(self.__get('temp', 'min'))
def get_serial(self):
return 'N/A'
def get_minimum_recorded(self) -> float:
temp = self.__collect_temp[0] if len(self.__collect_temp) > 0 else 0.1
temp = temp if temp > 0.0 else 0.1
return float(temp)
def get_maximum_recorded(self) -> float:
temp = self.__collect_temp[-1] if len(self.__collect_temp) > 0 else 100.0
temp = temp if temp <= 100.0 else 100.0
return float(temp)
def get_position_in_parent(self):
return self.__index
def set_high_threshold(self, temperature):
return False
def set_low_threshold(self, temperature):
return False
def thermal_list_get():
l = []
index = 0
for chip, chip_data in _sensors_get().items():
for sensor, sensor_data in chip_data.items():
# add only temperature sensors
if _value_get(sensor_data, "temp") is not None:
l.append(Thermal(chip, sensor))
l.append(Thermal(chip, sensor, index))
index += 1
return l

View File

@ -0,0 +1,67 @@
try:
from threading import Timer
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
class ThermalManager():
def __init__(self, polling_time = 30.0):
self.__polling_thermal_time = polling_time
self.__thermals = None
self.__timer = None
self.__chassis = None
def start(self):
self.work()
self.__timer = Timer(self.__polling_thermal_time, self.start)
self.__timer.start()
def work(self):
if self.__chassis is not None:
self.__thermals = self.__chassis._thermal_list
for term in self.__thermals:
self.check(term)
def check(self, sensor):
temperature = sensor.get_temperature()
if temperature is not None:
temp_high = sensor.get_high_threshold()
temp_low = sensor.get_low_threshold()
if temp_high > -999.0:
if temperature > temp_high:
print('Sensor ', sensor.get_name(), ' temperature more then', temp_high, '!!!')
else:
print('Sensor ', sensor.get_name(), ' has no high temperature threshold')
if temp_low > -999.0:
if temperature < temp_low:
print('Sensor ', sensor.get_name(), ' temperature less then', temp_low, '!!!')
else:
print('Sensor ', sensor.get_name(), ' has no low temperature threshold')
def stop(self):
if self.__timer is not None:
self.__timer.cancel()
def __del__(self):
if self.__timer is not None:
self.__timer.cancel()
# for compatibility with old version
def run_policy(self, chassis_def):
self.__chassis = chassis_def
def get_interval(self):
return self.__polling_thermal_time
def initialize(self):
pass
def load(self, json_file):
pass
def init_thermal_algorithm(self, chassis_def):
self.__chassis = chassis_def
self.start()
def deinitialize(self):
self.stop()