This commit is contained in:
Roger Ho 2024-03-25 08:54:22 +08:00 committed by GitHub
commit bf5991289e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 2468 additions and 138 deletions

View File

@ -0,0 +1,167 @@
- bus: '00'
dev: '00'
fn: '0'
id: '1980'
name: 'Host bridge: Intel Corporation Atom Processor C3000 Series System Agent (rev
11)'
- bus: '00'
dev: '04'
fn: '0'
id: 19a1
name: 'Host bridge: Intel Corporation Atom Processor C3000 Series Error Registers
(rev 11)'
- bus: '00'
dev: '05'
fn: '0'
id: 19a2
name: 'Generic system peripheral [0807]: Intel Corporation Atom Processor C3000
Series Root Complex Event Collector (rev 11)'
- bus: '00'
dev: '06'
fn: '0'
id: 19a3
name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated QAT
Root Port (rev 11)'
- bus: '00'
dev: 09
fn: '0'
id: 19a4
name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root
Port #0 (rev 11)'
- bus: '00'
dev: 0b
fn: '0'
id: 19a6
name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root
Port #2 (rev 11)'
- bus: '00'
dev: 0e
fn: '0'
id: 19a8
name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root
Port #4 (rev 11)'
- bus: '00'
dev: '10'
fn: '0'
id: 19aa
name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series PCI Express Root
Port #6 (rev 11)'
- bus: '00'
dev: '12'
fn: '0'
id: 19ac
name: 'System peripheral: Intel Corporation Atom Processor C3000 Series SMBus Contoller
- Host (rev 11)'
- bus: '00'
dev: '13'
fn: '0'
id: 19b2
name: 'SATA controller: Intel Corporation Atom Processor C3000 Series SATA Controller
0 (rev 11)'
- bus: '00'
dev: '15'
fn: '0'
id: 19d0
name: 'USB controller: Intel Corporation Atom Processor C3000 Series USB 3.0 xHCI
Controller (rev 11)'
- bus: '00'
dev: '16'
fn: '0'
id: 19d1
name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN
Root Port #0 (rev 11)'
- bus: '00'
dev: '17'
fn: '0'
id: 19d2
name: 'PCI bridge: Intel Corporation Atom Processor C3000 Series Integrated LAN
Root Port #1 (rev 11)'
- bus: '00'
dev: '18'
fn: '0'
id: 19d3
name: 'Communication controller: Intel Corporation Atom Processor C3000 Series ME
HECI 1 (rev 11)'
- bus: '00'
dev: 1a
fn: '0'
id: 19d8
name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller
(rev 11)'
- bus: '00'
dev: 1a
fn: '1'
id: 19d8
name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller
(rev 11)'
- bus: '00'
dev: 1a
fn: '2'
id: 19d8
name: 'Serial controller: Intel Corporation Atom Processor C3000 Series HSUART Controller
(rev 11)'
- bus: '00'
dev: 1c
fn: '0'
id: 19db
name: 'SD Host controller: Intel Corporation Device 19db (rev 11)'
- bus: '00'
dev: 1f
fn: '0'
id: 19dc
name: 'ISA bridge: Intel Corporation Atom Processor C3000 Series LPC or eSPI (rev
11)'
- bus: '00'
dev: 1f
fn: '1'
id: 19dd
name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Primary
to Side Band (P2SB) Bridge (rev 11)'
- bus: '00'
dev: 1f
fn: '2'
id: 19de
name: 'Memory controller: Intel Corporation Atom Processor C3000 Series Power Management
Controller (rev 11)'
- bus: '00'
dev: 1f
fn: '4'
id: 19df
name: 'SMBus: Intel Corporation Atom Processor C3000 Series SMBus controller (rev
11)'
- bus: '00'
dev: 1f
fn: '5'
id: 19e0
name: 'Serial bus controller [0c80]: Intel Corporation Atom Processor C3000 Series
SPI Controller (rev 11)'
- bus: '01'
dev: '00'
fn: '0'
id: 19e2
name: 'Co-processor: Intel Corporation Atom Processor C3000 Series QuickAssist Technology
(rev 11)'
- bus: '05'
dev: '00'
fn: '0'
id: b371
name: 'Ethernet controller: Broadcom Inc. and subsidiaries BCM56371 Switch ASIC
(rev 03)'
- bus: '06'
dev: '00'
fn: '0'
id: 15c2
name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane
(rev 11)'
- bus: '06'
dev: '00'
fn: '1'
id: 15c2
name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 Backplane
(rev 11)'
- bus: 08
dev: '00'
fn: '0'
id: 15e5
name: 'Ethernet controller: Intel Corporation Ethernet Connection X553 1GbE (rev
11)'

View File

@ -33,11 +33,11 @@
{
"i2c":
{
"valmap": { "F2B":"EXHAUST", "B2F":"INTAKE" }
"valmap": { "F2B":"exhaust", "B2F":"intake" }
}
},
"PSU_FAN_MAX_SPEED":"18000"
"PSU_FAN_MAX_SPEED":"26688"
},
"FAN":
@ -46,7 +46,7 @@
{
"i2c":
{
"valmap": {"1":"EXHAUST", "0":"INTAKE"}
"valmap": {"1":"exhaust", "0":"intake"}
}
},

View File

@ -5,7 +5,7 @@
"num_fantrays":3,
"num_fans_pertray":1,
"num_ports":54,
"num_temps": 3,
"num_temps": 4,
"pddf_dev_types":
{
"description":"AS4630 - Below is the list of supported PDDF device types (chip names) for various components. If any component uses some other driver, we will create the client using 'echo <dev-address> <dev-type> > <path>/new_device' method",
@ -211,6 +211,21 @@
}
},
"TEMP4" :
{
"dev_info": { "device_type":"TEMP_SENSOR", "device_name":"TEMP4"},
"dev_attr": { "display_name":"coretemp-isa-0000"},
"i2c":
{
"path_info": {"sysfs_base_path": "/sys/class/hwmon/hwmon1"},
"attr_list":
[
{ "attr_name": "temp1_high_crit_threshold", "drv_attr_name":"temp1_crit"},
{ "attr_name": "temp1_high_threshold", "drv_attr_name":"temp1_max"},
{ "attr_name": "temp1_input"}
]
}
},
"CPLD1":
{
@ -251,15 +266,15 @@
"SYS_LED":
{
"dev_info": { "device_type":"LED", "device_name":"SYS_LED"},
"dev_attr": { "index":"0"},
"dev_attr": { "index":"0", "flag": "rw"},
"i2c" : {
"attr_list":
[
{"attr_name":"STATUS_LED_COLOR_GREEN", "bits" : "7:5", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"},
{"attr_name":"STATUS_LED_COLOR_GREEN_BLINK", "bits" : "7:5", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"},
{"attr_name":"STATUS_LED_COLOR_AMBER", "bits" : "7:5", "descr" : "", "value" : "0x4", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"},
{"attr_name":"STATUS_LED_COLOR_AMBER_BLINK", "bits" : "7:5", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"},
{"attr_name":"STATUS_LED_COLOR_OFF", "bits" : "7:5", "descr" : "", "value" : "0x7", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}
{"attr_name":"green", "bits" : "7:5", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"},
{"attr_name":"green_blink", "bits" : "7:5", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"},
{"attr_name":"amber", "bits" : "7:5", "descr" : "", "value" : "0x4", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"},
{"attr_name":"amber_blink", "bits" : "7:5", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"},
{"attr_name":"off", "bits" : "7:5", "descr" : "", "value" : "0x7", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}
]
}
},
@ -268,13 +283,13 @@
"PSU1_LED":
{
"dev_info": { "device_type":"LED", "device_name":"PSU_LED"},
"dev_attr": { "index":"0"},
"dev_attr": { "index":"0", "flag": "r"},
"i2c" : {
"attr_list":
[
{"attr_name":"STATUS_LED_COLOR_GREEN", "bits" : "1:0", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"},
{"attr_name":"STATUS_LED_COLOR_AMBER", "bits" : "1:0", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"},
{"attr_name":"STATUS_LED_COLOR_OFF", "bits" : "1:0", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}
{"attr_name":"green", "bits" : "1:0", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"},
{"attr_name":"amber", "bits" : "1:0", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"},
{"attr_name":"off", "bits" : "1:0", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x30"}
]
}
},
@ -282,13 +297,13 @@
"PSU2_LED":
{
"dev_info": { "device_type":"LED", "device_name":"PSU_LED"},
"dev_attr": { "index":"1"},
"dev_attr": { "index":"1", "flag": "r"},
"i2c" : {
"attr_list":
[
{"attr_name":"STATUS_LED_COLOR_GREEN", "bits" : "7:6", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"},
{"attr_name":"STATUS_LED_COLOR_AMBER", "bits" : "7:6", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"},
{"attr_name":"STATUS_LED_COLOR_OFF", "bits" : "7:6", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}
{"attr_name":"green", "bits" : "7:6", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"},
{"attr_name":"amber", "bits" : "7:6", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"},
{"attr_name":"off", "bits" : "7:6", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}
]
}
},
@ -296,13 +311,13 @@
"FAN_LED":
{
"dev_info": { "device_type":"LED", "device_name":"FAN_LED"},
"dev_attr": { "index":"0"},
"dev_attr": { "index":"0", "flag": "r"},
"i2c" : {
"attr_list":
[
{"attr_name":"STATUS_LED_COLOR_GREEN", "bits" : "3:2", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"},
{"attr_name":"STATUS_LED_COLOR_AMBER", "bits" : "3:2", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"},
{"attr_name":"STATUS_LED_COLOR_OFF", "bits" : "3:2", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}
{"attr_name":"green", "bits" : "3:2", "descr" : "", "value" : "0x1", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"},
{"attr_name":"amber", "bits" : "3:2", "descr" : "", "value" : "0x2", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"},
{"attr_name":"off", "bits" : "3:2", "descr" : "", "value" : "0x3", "swpld_addr" : "0x60", "swpld_addr_offset" : "0x31"}
]
}
},
@ -336,7 +351,11 @@
{ "attr_name":"psu_i_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_p_out", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_temp1_input", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}
{ "attr_name":"psu_temp1_input", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_v_out_max", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_v_out_min", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_p_out_max", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x58", "attr_devtype":"pmbus", "attr_offset":"0xa8", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}
]
}
},
@ -387,7 +406,11 @@
{ "attr_name":"psu_i_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8c", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_p_out", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x96", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_fan1_speed_rpm", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x90", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_temp1_input", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}
{ "attr_name":"psu_temp1_input", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0x8d", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_v_out_max", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa5", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_v_out_min", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa4", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_p_out_max", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa7", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"},
{ "attr_name":"psu_temp1_high_threshold", "attr_devaddr":"0x59", "attr_devtype":"pmbus", "attr_offset":"0xa8", "attr_mask":"0x0", "attr_cmpval":"0xff", "attr_len":"2"}
]
}
},
@ -592,7 +615,9 @@
"topo_info": { "parent_bus":"0x16", "dev_addr":"0x53", "dev_type":"pddf_xcvr"},
"attr_list":
[
{ "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"}
{ "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x0", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"xcvr_reset", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x3", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"xcvr_intr_status", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x2", "attr_cmpval":"0x0", "attr_len":"1"}
]
}
},
@ -630,7 +655,9 @@
"topo_info": { "parent_bus":"0x17", "dev_addr":"0x53", "dev_type":"pddf_xcvr"},
"attr_list":
[
{ "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"}
{ "attr_name":"xcvr_present", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x4", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"xcvr_reset", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x7", "attr_cmpval":"0x0", "attr_len":"1"},
{ "attr_name":"xcvr_intr_status", "attr_devaddr":"0x60", "attr_devtype":"cpld", "attr_devname":"CPLD1", "attr_offset":"0x21", "attr_mask":"0x5", "attr_cmpval":"0x0", "attr_len":"1"}
]
}
}

View File

@ -0,0 +1,785 @@
{
"chassis": {
"name": "4630-54PE",
"thermal_manager":false,
"status_led": {
"controllable": true,
"colors": ["STATUS_LED_COLOR_GREEN", "STATUS_LED_COLOR_GREEN_BLINK", "STATUS_LED_COLOR_AMBER", "STATUS_LED_COLOR_AMBER_BLINK", "STATUS_LED_COLOR_OFF"]
},
"components": [
{
"name": "CPLD1"
},
{
"name": "BIOS"
}
],
"fans": [
{
"name": "FAN-1",
"speed": {
"controllable": true,
"minimum": 7
},
"status_led": {
"controllable": false
}
},
{
"name": "FAN-2",
"speed": {
"controllable": true,
"minimum": 7
},
"status_led": {
"controllable": false
}
},
{
"name": "FAN-3",
"speed": {
"controllable": true,
"minimum": 7
},
"status_led": {
"controllable": false
}
}
],
"fan_drawers":[
{
"name": "FanTray1",
"status_led": {
"controllable": false
},
"num_fans" : 1,
"fans": [
{
"name": "FAN-1",
"speed": {
"controllable": true,
"minimum": 7
},
"status_led": {
"controllable": false
}
}
]
},
{
"name": "FanTray2",
"status_led": {
"controllable": false
},
"num_fans" : 1,
"fans": [
{
"name": "FAN-2",
"speed": {
"controllable": true,
"minimum": 7
},
"status_led": {
"controllable": false
}
}
]
},
{
"name": "FanTray3",
"status_led": {
"controllable": false
},
"num_fans" : 1,
"fans": [
{
"name": "FAN-3",
"speed": {
"controllable": true,
"minimum": 7
},
"status_led": {
"controllable": false
}
}
]
}
],
"psus": [
{
"name": "PSU-1",
"status_led": {
"controllable": true,
"colors": ["STATUS_LED_COLOR_GREEN", "STATUS_LED_COLOR_AMBER", "STATUS_LED_COLOR_OFF"]
},
"fans": [
{
"name": "PSU-1 FAN-1"
}
],
"thermals": [
{
"name": "PSU-1 temp sensor 1",
"controllable": false,
"low-crit-threshold": false,
"high-crit-threshold": false
}
]
},
{
"name": "PSU-2",
"status_led": {
"controllable": true,
"colors": ["STATUS_LED_COLOR_GREEN", "STATUS_LED_COLOR_AMBER", "STATUS_LED_COLOR_OFF"]
},
"fans": [
{
"name": "PSU-2 FAN-1"
}
],
"thermals": [
{
"name": "PSU-2 temp sensor 1",
"controllable": false,
"low-crit-threshold": false,
"high-crit-threshold": false
}
]
}
],
"thermals": [
{
"name": "Temp sensor 1",
"controllable": true,
"low-threshold": false,
"high-threshold": true,
"low-crit-threshold": false,
"high-crit-threshold": false
},
{
"name": "Temp sensor 2",
"controllable": true,
"low-threshold": false,
"high-threshold": true,
"low-crit-threshold": false,
"high-crit-threshold": false
},
{
"name": "Temp sensor 3",
"controllable": true,
"low-threshold": false,
"high-threshold": true,
"low-crit-threshold": false,
"high-crit-threshold": false
},
{
"name": "Temp sensor 4",
"controllable": false,
"low-threshold": false,
"high-threshold": true,
"low-crit-threshold": false,
"high-crit-threshold": true
}
],
"sfps": [
{
"name": "Ethernet0"
},
{
"name": "Ethernet1"
},
{
"name": "Ethernet2"
},
{
"name": "Ethernet3"
},
{
"name": "Ethernet4"
},
{
"name": "Ethernet5"
},
{
"name": "Ethernet6"
},
{
"name": "Ethernet7"
},
{
"name": "Ethernet8"
},
{
"name": "Ethernet9"
},
{
"name": "Ethernet10"
},
{
"name": "Ethernet11"
},
{
"name": "Ethernet12"
},
{
"name": "Ethernet13"
},
{
"name": "Ethernet14"
},
{
"name": "Ethernet15"
},
{
"name": "Ethernet16"
},
{
"name": "Ethernet17"
},
{
"name": "Ethernet18"
},
{
"name": "Ethernet19"
},
{
"name": "Ethernet20"
},
{
"name": "Ethernet21"
},
{
"name": "Ethernet22"
},
{
"name": "Ethernet23"
},
{
"name": "Ethernet24"
},
{
"name": "Ethernet25"
},
{
"name": "Ethernet26"
},
{
"name": "Ethernet27"
},
{
"name": "Ethernet28"
},
{
"name": "Ethernet29"
},
{
"name": "Ethernet30"
},
{
"name": "Ethernet31"
},
{
"name": "Ethernet32"
},
{
"name": "Ethernet33"
},
{
"name": "Ethernet34"
},
{
"name": "Ethernet35"
},
{
"name": "Ethernet36"
},
{
"name": "Ethernet37"
},
{
"name": "Ethernet38"
},
{
"name": "Ethernet39"
},
{
"name": "Ethernet40"
},
{
"name": "Ethernet41"
},
{
"name": "Ethernet42"
},
{
"name": "Ethernet43"
},
{
"name": "Ethernet44"
},
{
"name": "Ethernet45"
},
{
"name": "Ethernet46"
},
{
"name": "Ethernet47"
},
{
"name": "Ethernet48"
},
{
"name": "Ethernet49"
},
{
"name": "Ethernet50"
},
{
"name": "Ethernet51"
},
{
"name": "Ethernet52"
},
{
"name": "Ethernet56"
}
]
},
"interfaces": {
"Ethernet0": {
"index": "1",
"lanes": "26",
"breakout_modes": {
"1x1G": ["Eth1(Port1)"]
}
},
"Ethernet1": {
"index": "2",
"lanes": "25",
"breakout_modes": {
"1x1G": ["Eth2(Port2)"]
}
},
"Ethernet2": {
"index": "3",
"lanes": "28",
"breakout_modes": {
"1x1G": ["Eth3(Port3)"]
}
},
"Ethernet3": {
"index": "4",
"lanes": "27",
"breakout_modes": {
"1x1G": ["Eth4(Port4)"]
}
},
"Ethernet4": {
"index": "5",
"lanes": "30",
"breakout_modes": {
"1x1G": ["Eth5(Port5)"]
}
},
"Ethernet5": {
"index": "6",
"lanes": "29",
"breakout_modes": {
"1x1G": ["Eth6(Port6)"]
}
},
"Ethernet6": {
"index": "7",
"lanes": "32",
"breakout_modes": {
"1x1G": ["Eth7(Port7)"]
}
},
"Ethernet7": {
"index": "8",
"lanes": "31",
"breakout_modes": {
"1x1G": ["Eth8(Port8)"]
}
},
"Ethernet8": {
"index": "9",
"lanes": "38",
"breakout_modes": {
"1x1G": ["Eth9(Port9)"]
}
},
"Ethernet9": {
"index": "10",
"lanes": "37",
"breakout_modes": {
"1x1G": ["Eth10(Port10)"]
}
},
"Ethernet10": {
"index": "11",
"lanes": "40",
"breakout_modes": {
"1x1G": ["Eth11(Port11)"]
}
},
"Ethernet11": {
"index": "12",
"lanes": "39",
"breakout_modes": {
"1x1G": ["Eth12(Port12)"]
}
},
"Ethernet12": {
"index": "13",
"lanes": "34",
"breakout_modes": {
"1x1G": ["Eth13(Port13)"]
}
},
"Ethernet13": {
"index": "14",
"lanes": "33",
"breakout_modes": {
"1x1G": ["Eth14(Port14)"]
}
},
"Ethernet14": {
"index": "15",
"lanes": "36",
"breakout_modes": {
"1x1G": ["Eth15(Port15)"]
}
},
"Ethernet15": {
"index": "16",
"lanes": "35",
"breakout_modes": {
"1x1G": ["Eth16(Port16)"]
}
},
"Ethernet16": {
"index": "17",
"lanes": "46",
"breakout_modes": {
"1x1G": ["Eth17(Port17)"]
}
},
"Ethernet17": {
"index": "18",
"lanes": "45",
"breakout_modes": {
"1x1G": ["Eth18(Port18)"]
}
},
"Ethernet18": {
"index": "19",
"lanes": "48",
"breakout_modes": {
"1x1G": ["Eth19(Port19)"]
}
},
"Ethernet19": {
"index": "20",
"lanes": "47",
"breakout_modes": {
"1x1G": ["Eth20(Port20)"]
}
},
"Ethernet20": {
"index": "21",
"lanes": "42",
"breakout_modes": {
"1x1G": ["Eth21(Port21)"]
}
},
"Ethernet21": {
"index": "22",
"lanes": "41",
"breakout_modes": {
"1x1G": ["Eth22(Port22)"]
}
},
"Ethernet22": {
"index": "23",
"lanes": "44",
"breakout_modes": {
"1x1G": ["Eth23(Port23)"]
}
},
"Ethernet23": {
"index": "24",
"lanes": "43",
"breakout_modes": {
"1x1G": ["Eth24(Port24)"]
}
},
"Ethernet24": {
"index": "25",
"lanes": "2",
"breakout_modes": {
"1x1G": ["Eth25(Port25)"]
}
},
"Ethernet25": {
"index": "26",
"lanes": "1",
"breakout_modes": {
"1x1G": ["Eth26(Port26)"]
}
},
"Ethernet26": {
"index": "27",
"lanes": "4",
"breakout_modes": {
"1x1G": ["Eth27(Port27)"]
}
},
"Ethernet27": {
"index": "28",
"lanes": "3",
"breakout_modes": {
"1x1G": ["Eth28(Port28)"]
}
},
"Ethernet28": {
"index": "29",
"lanes": "6",
"breakout_modes": {
"1x1G": ["Eth29(Port29)"]
}
},
"Ethernet29": {
"index": "30",
"lanes": "5",
"breakout_modes": {
"1x1G": ["Eth30(Port30)"]
}
},
"Ethernet30": {
"index": "31",
"lanes": "8",
"breakout_modes": {
"1x1G": ["Eth31(Port31)"]
}
},
"Ethernet31": {
"index": "32",
"lanes": "7",
"breakout_modes": {
"1x1G": ["Eth32(Port32)"]
}
},
"Ethernet32": {
"index": "33",
"lanes": "10",
"breakout_modes": {
"1x1G": ["Eth33(Port33)"]
}
},
"Ethernet33": {
"index": "34",
"lanes": "9",
"breakout_modes": {
"1x1G": ["Eth34(Port34)"]
}
},
"Ethernet34": {
"index": "35",
"lanes": "12",
"breakout_modes": {
"1x1G": ["Eth35(Port35)"]
}
},
"Ethernet35": {
"index": "36",
"lanes": "11",
"breakout_modes": {
"1x1G": ["Eth36(Port36)"]
}
},
"Ethernet36": {
"index": "37",
"lanes": "14",
"breakout_modes": {
"1x1G": ["Eth37(Port37)"]
}
},
"Ethernet37": {
"index": "38",
"lanes": "13",
"breakout_modes": {
"1x1G": ["Eth38(Port38)"]
}
},
"Ethernet38": {
"index": "39",
"lanes": "16",
"breakout_modes": {
"1x1G": ["Eth39(Port39)"]
}
},
"Ethernet39": {
"index": "40",
"lanes": "15",
"breakout_modes": {
"1x1G": ["Eth40(Port40)"]
}
},
"Ethernet40": {
"index": "41",
"lanes": "18",
"breakout_modes": {
"1x1G": ["Eth41(Port41)"]
}
},
"Ethernet41": {
"index": "42",
"lanes": "17",
"breakout_modes": {
"1x1G": ["Eth42(Port42)"]
}
},
"Ethernet42": {
"index": "43",
"lanes": "20",
"breakout_modes": {
"1x1G": ["Eth43(Port43)"]
}
},
"Ethernet43": {
"index": "44",
"lanes": "19",
"breakout_modes": {
"1x1G": ["Eth44(Port44)"]
}
},
"Ethernet44": {
"index": "45",
"lanes": "22",
"breakout_modes": {
"1x1G": ["Eth45(Port45)"]
}
},
"Ethernet45": {
"index": "46",
"lanes": "21",
"breakout_modes": {
"1x1G": ["Eth46(Port46)"]
}
},
"Ethernet46": {
"index": "47",
"lanes": "24",
"breakout_modes": {
"1x1G": ["Eth47(Port47)"]
}
},
"Ethernet47": {
"index": "48",
"lanes": "23",
"breakout_modes": {
"1x1G": ["Eth48(Port48)"]
}
},
"Ethernet48": {
"index": "49",
"lanes": "67",
"breakout_modes": {
"1x25G[10G]": ["Eth49(Port49)"]
}
},
"Ethernet49": {
"index": "50",
"lanes": "66",
"breakout_modes": {
"1x25G[10G]": ["Eth50(Port50)"]
}
},
"Ethernet50": {
"index": "51",
"lanes": "65",
"breakout_modes": {
"1x25G[10G]": ["Eth51(Port51)"]
}
},
"Ethernet51": {
"index": "52",
"lanes": "68",
"breakout_modes": {
"1x25G[10G]": ["Eth52(Port52)"]
}
},
"Ethernet52": {
"index": "53,53,53,53",
"lanes": "73,74,75,76",
"breakout_modes": {
"1x100G[40G]": ["Eth53(Port53)"],
"2x50G": ["Eth53/1(Port53)", "Eth53/2(Port53)"],
"4x25G[10G]": ["Eth53/1(Port53)", "Eth53/2(Port53)", "Eth53/3(Port53)", "Eth53/4(Port53)"]
}
},
"Ethernet56": {
"index": "54,54,54,54",
"lanes": "69,70,71,72",
"breakout_modes": {
"1x100G[40G]": ["Eth54(Port54)"],
"2x50G": ["Eth54/1(Port54)", "Eth54/2(Port54)"],
"4x25G[10G]": ["Eth54/1(Port54)", "Eth54/2(Port54)", "Eth54/3(Port54)", "Eth54/4(Port54)"]
}
}
}
}

View File

@ -0,0 +1,10 @@
{
"chassis": {
"4630-54PE-O-AC-F": {
"component": {
"CPLD1": { },
"BIOS": { }
}
}
}
}

View File

@ -1,5 +1,4 @@
{
"skip_ledd": true,
"skip_pcied": true
"skip_ledd": true
}

View File

@ -1,17 +1,13 @@
{
"services_to_ignore": [],
"devices_to_ignore": [
"asic",
"psu.voltage",
"psu.temperature",
"PSU1_FAN1.speed",
"PSU2_FAN1.speed"
"asic"
],
"user_defined_checkers": [],
"polling_interval": 60,
"led_color": {
"fault": "STATUS_LED_COLOR_AMBER",
"normal": "STATUS_LED_COLOR_GREEN",
"booting": "STATUS_LED_COLOR_GREEN_BLINK"
"fault": "amber",
"normal": "green",
"booting": "green_blink"
}
}

View File

@ -0,0 +1,16 @@
[Unit]
Description=Accton AS4630-54PE Platform Monitoring service
Before=pmon.service
After=pddf-platform-init.service
DefaultDependencies=no
[Service]
ExecStart=/usr/local/bin/accton_as4630_54pe_pddf_monitor.py
KillSignal=SIGKILL
SuccessExitStatus=SIGKILL
# Resource Limitations
LimitCORE=infinity
[Install]
WantedBy=multi-user.target

View File

@ -10,10 +10,14 @@ try:
import sys
from sonic_platform_pddf_base.pddf_chassis import PddfChassis
from .event import SfpEvent
from .helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
NUM_COMPONENT = 2
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"
class Chassis(PddfChassis):
"""
@ -26,6 +30,7 @@ class Chassis(PddfChassis):
PddfChassis.__init__(self, pddf_data, pddf_plugin_data)
self.__initialize_components()
self._sfpevent = SfpEvent(self.get_all_sfps())
self._api_helper = APIHelper()
def __initialize_components(self):
from sonic_platform.component import Component
@ -68,3 +73,57 @@ class Chassis(PddfChassis):
def set_status_led(self, color):
return self.set_system_led(self.SYSLED_DEV_NAME, color)
def get_port_or_cage_type(self, port):
from sonic_platform_base.sfp_base import SfpBase
if port in range(1, 49):
return SfpBase.SFP_PORT_TYPE_BIT_RJ45
elif port in range(49, 53):
return SfpBase.SFP_PORT_TYPE_BIT_SFP | SfpBase.SFP_PORT_TYPE_BIT_SFP_PLUS | SfpBase.SFP_PORT_TYPE_BIT_SFP28
else:
return SfpBase.SFP_PORT_TYPE_BIT_QSFP | SfpBase.SFP_PORT_TYPE_BIT_QSFP_PLUS | SfpBase.SFP_PORT_TYPE_BIT_QSFP28
def get_reboot_cause(self):
"""
Retrieves the cause of the previous reboot
Returns:
A tuple (string, string) where the first element is a string
containing the cause of the previous reboot. This string must be
one of the predefined strings in this class. If the first string
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
to pass a description of the reboot cause.
"""
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE)
sw_reboot_cause = self._api_helper.read_txt_file(
reboot_cause_path) or "Unknown"
return ('REBOOT_CAUSE_NON_HARDWARE', sw_reboot_cause)
def get_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 get_revision(self):
"""
Retrieves the hardware revision of the device
Returns:
string: Revision value of device
"""
return self._eeprom.revision_str()

View File

@ -8,6 +8,8 @@
#############################################################################
try:
import os
import json
from sonic_platform_base.component_base import ComponentBase
from sonic_py_common.general import getstatusoutput_noshell
except ImportError as e:
@ -82,4 +84,85 @@ class Component(ComponentBase):
Returns:
A boolean, True if install successfully, False if not
"""
raise NotImplementedError
ret, output = getstatusoutput_noshell(["tar", "-C", "/tmp", "-xzf", image_path ] )
if ret != 0 :
print("Installation failed because of wrong image package")
return False
if os.path.exists("/tmp/install.json") is False:
print("Installation failed without jsonfile")
return False
input_file = open ('/tmp/install.json')
json_array = json.load(input_file)
ret = 1
for item in json_array:
if item.get('id')==None or item.get('path')==None:
continue
if self.name == item['id'] and item['path'] and item.get('cpu'):
print( "Find", item['id'], item['path'], item['cpu'] )
ret, output = getstatusoutput_noshell(["/tmp/run_install.sh", item['id'], item['path'], item['cpu'] ])
if ret==0:
break
elif self.name == item['id'] and item['path']:
print( "Find", item['id'], item['path'] )
ret, output = getstatusoutput_noshell(["/tmp/run_install.sh", item['id'], item['path'] ])
if ret==0:
break
if ret==0:
return True
else :
return False
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 'N/A'
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return '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 True
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

View File

@ -1,11 +1,21 @@
try:
import time
from sonic_py_common.logger import Logger
from .sfp import Sfp
except ImportError as e:
raise ImportError(repr(e) + " - required module not found")
POLL_INTERVAL_IN_SEC = 1
# SFP errors that will block eeprom accessing
SFP_BLOCKING_ERRORS = [
Sfp.SFP_ERROR_BIT_I2C_STUCK,
Sfp.SFP_ERROR_BIT_BAD_EEPROM,
Sfp.SFP_ERROR_BIT_UNSUPPORTED_CABLE,
Sfp.SFP_ERROR_BIT_HIGH_TEMP,
Sfp.SFP_ERROR_BIT_BAD_CABLE
]
class SfpEvent:
''' Listen to insert/remove sfp events '''
@ -46,15 +56,54 @@ class SfpEvent:
if changed_ports != 0:
for sfp in self._sfp_list:
i=sfp.get_position_in_parent() - 1
if (changed_ports & (1 << i)):
if (bitmap & (1 << i)) == 0:
port_dict[i+1] = '0'
else:
port_dict[i+1] = '1'
if (changed_ports & (1 << i)) == 0:
continue
if (bitmap & (1 << i)) == 0:
port_dict[i+1] = '0'
else:
# sfp.refresh_optoe_dev_class()
sfp_state_bits = self.get_sfp_state_bits(sfp, True)
sfp_state_bits = self.check_sfp_blocking_errors(sfp_state_bits)
port_dict[i+1] = str(sfp_state_bits)
# Update the cache dict
self._sfp_change_event_data['present'] = bitmap
return True, change_dict
else:
return True, change_dict
def get_sfp_state_bits(self, sfp, present):
sfp_state_bits = 0
if present is True:
sfp_state_bits |= Sfp.SFP_STATUS_BIT_INSERTED
else:
return sfp_state_bits
status = sfp.validate_eeprom()
if status is None:
sfp_state_bits |= Sfp.SFP_ERROR_BIT_I2C_STUCK
return sfp_state_bits
elif status is not True:
sfp_state_bits |= Sfp.SFP_ERROR_BIT_BAD_EEPROM
return sfp_state_bits
status = sfp.validate_temperature()
if status is None:
sfp_state_bits |= Sfp.SFP_ERROR_BIT_I2C_STUCK
return sfp_state_bits
elif status is not True:
sfp_state_bits |= Sfp.SFP_ERROR_BIT_HIGH_TEMP
return sfp_state_bits
return sfp_state_bits
def check_sfp_blocking_errors(self, sfp_state_bits):
for i in SFP_BLOCKING_ERRORS:
if (i & sfp_state_bits) == 0:
continue
sfp_state_bits |= Sfp.SFP_ERROR_BIT_BLOCKING
return sfp_state_bits

View File

@ -6,6 +6,7 @@ try:
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3"]
class Fan(PddfFan):
"""PDDF Platform-Specific Fan class"""
@ -24,25 +25,53 @@ class Fan(PddfFan):
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
depending on fan direction
"""
direction = 'N/A'
if self.is_psu_fan:
direction = self.FAN_DIRECTION_EXHAUST
else:
idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index
attr = "fan" + str(idx) + "_direction"
output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr)
if not output:
return False
mode = output['mode']
val = output['status']
val = val.rstrip()
vmap = self.plugin_data['FAN']['direction'][mode]['valmap']
if val in vmap:
direction = vmap[val]
else:
direction = val
direction = super().get_direction()
if direction is not None and len(direction) > 0:
return direction
return direction
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
fan_name = FAN_NAME_LIST[self.fantray_index - 1] \
if not self.is_psu_fan \
else "PSU-{} FAN-{}".format(self.fans_psu_index, self.fan_index)
return fan_name
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return 'N/A'
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
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)
"""
if self.is_psu_fan:
return super().get_speed()
else:
return super().get_target_speed()

View File

@ -15,3 +15,26 @@ class FanDrawer(PddfFanDrawer):
PddfFanDrawer.__init__(self, tray_idx, pddf_data, pddf_plugin_data)
# Provide the functions/variables below for which implementation is to be overwritten
def get_name(self):
"""
Retrieves the fan drawer name
Returns:
string: The name of the device
"""
return "FanTray{}".format(self.fantray_index)
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return 'N/A'
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return 'N/A'

View File

@ -0,0 +1,368 @@
import os
import struct
import json
import fcntl
from mmap import *
from sonic_py_common import device_info
from sonic_py_common import logger
from threading import Lock
from typing import cast
from sonic_py_common.general import getstatusoutput_noshell_pipe
from sonic_py_common.general import getstatusoutput_noshell
HOST_CHK_CMD = ["docker"]
EMPTY_STRING = ""
class APIHelper():
def __init__(self):
(self.platform, self.hwsku) = device_info.get_platform_and_hwsku()
def is_host(self):
try:
status, output = getstatusoutput_noshell(HOST_CHK_CMD)
return status == 0
except Exception:
return False
def pci_get_value(self, resource, offset):
status = True
result = ""
try:
fd = os.open(resource, os.O_RDWR)
mm = mmap(fd, 0)
mm.seek(int(offset))
read_data_stream = mm.read(4)
result = struct.unpack('I', read_data_stream)
except Exception:
status = False
return status, result
def run_interactive_command(self, cmd):
try:
os.system(cmd)
except Exception:
return False
return True
def read_txt_file(self, file_path):
try:
with open(file_path, 'r', errors='replace') as fd:
data = fd.read()
ret = data.strip()
if len(ret) > 0:
return ret
except IOError:
pass
return None
def write_txt_file(self, file_path, value):
try:
with open(file_path, 'w') as fd:
fd.write(str(value))
except IOError:
return False
return True
def ipmi_raw(self, netfn, cmd):
status = True
result = ""
try:
err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'raw', str(netfn), str(cmd)])
if err == [0]:
result = raw_data.strip()
else:
status = False
except Exception:
status = False
return status, result
def ipmi_fru_id(self, id, key=None):
status = True
result = ""
try:
if (key is None):
err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'fru', 'print', str(id)])
else:
err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'fru', 'print', str(id)], ['grep', str(key)])
if err == [0] or err == [0, 0]:
result = raw_data.strip()
else:
status = False
except Exception:
status = False
return status, result
def ipmi_set_ss_thres(self, id, threshold_key, value):
status = True
result = ""
try:
err, raw_data = getstatusoutput_noshell_pipe(['ipmitool', 'sensor', 'thresh', str(id), str(threshold_key), str(value)])
if err == [0]:
result = raw_data.strip()
else:
status = False
except Exception:
status = False
return status, result
class FileLock:
"""
Due to pmon docker not installing the py-filelock, this class
implements a simple file lock feature.
Ref: https://github.com/tox-dev/py-filelock/blob/main/src/filelock/
"""
def __init__(self, lock_file):
self._lock_file = lock_file
self._thread_lock = Lock()
self.is_locked = False
def acquire(self):
with self._thread_lock:
if self.is_locked:
return
fd = os.open(self._lock_file, flags=(os.O_RDWR | os.O_CREAT | os.O_TRUNC))
fcntl.flock(fd, fcntl.LOCK_EX)
self._lock_file_fd = fd
self.is_locked = True
def release(self):
with self._thread_lock:
if self.is_locked:
fd = cast(int, self._lock_file_fd)
self._lock_file_fd = None
fcntl.flock(fd, fcntl.LOCK_UN)
os.close(fd)
self.is_locked = False
def __enter__(self):
self.acquire()
return self
def __exit__(self, exc_type, exc_val, traceback):
self.release()
def __del__(self):
self.release()
DEVICE_THRESHOLD_JSON_PATH = "/tmp/device_threshold.json"
class DeviceThreshold:
HIGH_THRESHOLD = 'high_threshold'
LOW_THRESHOLD = 'low_threshold'
HIGH_CRIT_THRESHOLD = 'high_critical_threshold'
LOW_CRIT_THRESHOLD = 'low_critical_threshold'
NOT_AVAILABLE = 'N/A'
def __init__(self, th_name = NOT_AVAILABLE):
self.flock = FileLock("{}.lock".format(DEVICE_THRESHOLD_JSON_PATH))
self.name = th_name
self.__log = logger.Logger(log_identifier="DeviceThreshold")
self.__db_data = {}
self.__db_mtime = 0
def __reload_db(self):
try:
db_data = {}
with self.flock:
with open(DEVICE_THRESHOLD_JSON_PATH, "r") as db_file:
db_data = json.load(db_file)
except Exception as e:
self.__log.log_warning('{}'.format(str(e)))
return None
return db_data
def __get_data(self, field):
"""
Retrieves data frome JSON file by field
Args :
field: String
Returns:
A string if getting is successfully, 'N/A' if not
"""
if os.path.exists(DEVICE_THRESHOLD_JSON_PATH):
new_mtime = os.path.getmtime(DEVICE_THRESHOLD_JSON_PATH)
if new_mtime != self.__db_mtime:
new_data = self.__reload_db()
if new_data is not None:
self.__db_data = new_data
self.__db_mtime = new_mtime
if self.name not in self.__db_data.keys():
return self.NOT_AVAILABLE
if field not in self.__db_data[self.name].keys():
return self.NOT_AVAILABLE
return self.__db_data[self.name][field]
def __set_data(self, field, new_val):
"""
Set data to JSON file by field
Args :
field: String
new_val: String
Returns:
A boolean, True if setting is set successfully, False if not
"""
if self.name not in self.__db_data.keys():
self.__db_data[self.name] = {}
old_val = self.__db_data[self.name].get(field, None)
if old_val is not None and old_val == new_val:
return True
self.__db_data[self.name][field] = new_val
try:
with self.flock:
db_data = {}
mode = "r+" if os.path.exists(DEVICE_THRESHOLD_JSON_PATH) else "w+"
with open(DEVICE_THRESHOLD_JSON_PATH, mode) as db_file:
if mode == "r+":
db_data = json.load(db_file)
if self.name not in db_data.keys():
db_data[self.name] = {}
db_data[self.name][field] = new_val
if mode == "r+":
db_file.seek(0)
# erase old data
db_file.truncate(0)
# write all data
json.dump(db_data, db_file, indent=4)
self.__db_mtime = os.path.getmtime(DEVICE_THRESHOLD_JSON_PATH)
except Exception as e:
self.__log.log_error('{}'.format(str(e)))
return False
return True
def get_high_threshold(self):
"""
Retrieves the high threshold temperature from JSON file.
Returns:
string : the high threshold temperature of thermal,
e.g. "30.125"
"""
return self.__get_data(self.HIGH_THRESHOLD)
def set_high_threshold(self, temperature):
"""
Sets the high threshold temperature of thermal
Args :
temperature: A string of temperature, e.g. "30.125"
Returns:
A boolean, True if threshold is set successfully, False if not
"""
if isinstance(temperature, str) is not True:
raise TypeError('The parameter requires string type.')
try:
if temperature != self.NOT_AVAILABLE:
float(temperature)
except ValueError:
raise ValueError('The parameter requires a float string. ex:\"30.1\"')
return self.__set_data(self.HIGH_THRESHOLD, temperature)
def get_low_threshold(self):
"""
Retrieves the low threshold temperature from JSON file.
Returns:
string : the low threshold temperature of thermal,
e.g. "30.125"
"""
return self.__get_data(self.LOW_THRESHOLD)
def set_low_threshold(self, temperature):
"""
Sets the low threshold temperature of thermal
Args :
temperature: A string of temperature, e.g. "30.125"
Returns:
A boolean, True if threshold is set successfully, False if not
"""
if isinstance(temperature, str) is not True:
raise TypeError('The parameter requires string type.')
try:
if temperature != self.NOT_AVAILABLE:
float(temperature)
except ValueError:
raise ValueError('The parameter requires a float string. ex:\"30.1\"')
return self.__set_data(self.LOW_THRESHOLD, temperature)
def get_high_critical_threshold(self):
"""
Retrieves the high critical threshold temperature from JSON file.
Returns:
string : the high critical threshold temperature of thermal,
e.g. "30.125"
"""
return self.__get_data(self.HIGH_CRIT_THRESHOLD)
def set_high_critical_threshold(self, temperature):
"""
Sets the high critical threshold temperature of thermal
Args :
temperature: A string of temperature, e.g. "30.125"
Returns:
A boolean, True if threshold is set successfully, False if not
"""
if isinstance(temperature, str) is not True:
raise TypeError('The parameter requires string type.')
try:
if temperature != self.NOT_AVAILABLE:
float(temperature)
except ValueError:
raise ValueError('The parameter requires a float string. ex:\"30.1\"')
return self.__set_data(self.HIGH_CRIT_THRESHOLD, temperature)
def get_low_critical_threshold(self):
"""
Retrieves the low critical threshold temperature from JSON file.
Returns:
string : the low critical threshold temperature of thermal,
e.g. "30.125"
"""
return self.__get_data(self.LOW_CRIT_THRESHOLD)
def set_low_critical_threshold(self, temperature):
"""
Sets the low critical threshold temperature of thermal
Args :
temperature: A string of temperature, e.g. "30.125"
Returns:
A boolean, True if threshold is set successfully, False if not
"""
if isinstance(temperature, str) is not True:
raise TypeError('The parameter requires string type.')
try:
if temperature != self.NOT_AVAILABLE:
float(temperature)
except ValueError:
raise ValueError('The parameter requires a float string. ex:\"30.1\"')
return self.__set_data(self.LOW_CRIT_THRESHOLD, temperature)

View File

@ -0,0 +1,19 @@
#############################################################################
# Edgecore
#
# Module contains an implementation of SONiC Platform Base API and
# provides the fan status which are available in the platform
# Base PCIe class
#############################################################################
try:
from sonic_platform_base.sonic_pcie.pcie_common import PcieUtil
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Pcie(PcieUtil):
"""Edgecore Platform-specific PCIe class"""
def __init__(self, platform_path):
PcieUtil.__init__(self, platform_path)

View File

@ -11,41 +11,120 @@ except ImportError as e:
class Psu(PddfPsu):
"""PDDF Platform-Specific PSU class"""
PLATFORM_PSU_CAPACITY = 1200
def __init__(self, index, pddf_data=None, pddf_plugin_data=None):
PddfPsu.__init__(self, index, pddf_data, pddf_plugin_data)
# Provide the functions/variables below for which implementation is to be overwritten
def get_capacity(self):
def get_name(self):
return "PSU-{}".format(self.psu_index)
def get_revision(self):
"""
Gets the capacity (maximum output power) of the PSU in watts
Retrieves the hardware revision of the device
Returns:
An integer, the capacity of PSU
string: Revision value of device
"""
return (self.PLATFORM_PSU_CAPACITY)
return 'N/A'
def get_type(self):
def get_temperature_high_threshold(self):
"""
Gets the type of the PSU
Retrieves the high threshold temperature of PSU
Returns:
A float number, the high threshold temperature of PSU in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
threshold = super().get_temperature_high_threshold()
for psu_thermal_idx in range(self.num_psu_thermals):
try:
tmp = self._thermal_list[psu_thermal_idx].get_high_threshold()
if threshold > tmp or threshold == 0.0:
threshold = tmp
except Exception:
pass
return threshold
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
A string, the type of PSU (AC/DC)
string: Model/part number of device
"""
ptype = "AC"
# Currently the platform supports only AC type of PSUs
#try:
#import sonic_platform.platform
#ch=sonic_platform.platform.Platform().get_chassis()
#e=ch.sys_eeprom.read_eeprom()
#ret, prod_name = ch.sys_eeprom.get_tlv_field(e,0x21)
#if ret:
#prod_name = prod_name[2]
##print("Product name is {}".format(prod_name))
#if '48V' in prod_name:
#ptype = 'DC'
#except Exception as e:
#print("Error while trying to read syseeprom to get PSU type")
model = super().get_model()
if model and model.strip() == "":
return None
return model
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
serial = super().get_serial()
if serial and serial.strip() == "":
return None
return serial
def get_voltage(self):
"""
Retrieves current PSU voltage output
Returns:
A float number, the output voltage in volts,
e.g. 12.1
"""
if self.get_status() is not True:
return 0.0
return super().get_voltage()
def get_current(self):
"""
Retrieves present electric current supplied by PSU
Returns:
A float number, electric current in amperes,
e.g. 15.4
"""
if self.get_status() is not True:
return 0.0
return super().get_current()
def get_power(self):
"""
Retrieves current energy supplied by PSU
Returns:
A float number, the power in watts,
e.g. 302.6
"""
if self.get_status() is not True:
return 0.0
return super().get_power()
def get_maximum_supplied_power(self):
"""
Retrieves current energy supplied by PSU
Returns:
A float number, the power in watts,
e.g. 302.6
"""
device = "PSU{}".format(self.psu_index)
output = self.pddf_obj.get_attr_name_output(device, "psu_p_out_max")
if not output:
return 0.0
p_out = output['status']
# power is returned in micro watts
return float(p_out)/1000
return ptype

View File

@ -1,7 +1,10 @@
#!/usr/bin/env python
try:
import natsort
from sonic_platform_pddf_base.pddf_sfp import PddfSfp
from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper
from sonic_py_common import device_info
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
@ -11,10 +14,197 @@ class Sfp(PddfSfp):
PDDF Platform-Specific Sfp class
"""
SFP_TYPE_CODE_LIST = [
0x03, # SFP/SFP+/SFP28
0x0b # DWDM-SFP/SFP+
]
QSFP_TYPE_CODE_LIST = [
0x0c, # QSFP
0x0d, # QSFP+ or later
0x11, # QSFP28 or later
0xe1 # QSFP28 EDFA
]
def __init__(self, index, pddf_data=None, pddf_plugin_data=None):
PddfSfp.__init__(self, index, pddf_data, pddf_plugin_data)
self.index = self.port_index
# Provide the functions/variables below for which implementation is to be overwritten
def get_position_in_parent(self):
"""Retrieves 1-based relative physical position in parent device."""
return self.port_index
def __get_path_to_port_config_file(self):
platform, hwsku = device_info.get_platform_and_hwsku()
hwsku_path = "/".join(["/usr/share/sonic/platform",hwsku])
return "/".join([hwsku_path, "port_config.ini"])
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
sfputil_helper = SfpUtilHelper()
sfputil_helper.read_porttab_mappings(
self.__get_path_to_port_config_file())
logical_port_list = sfputil_helper.logical
logical_port_list = natsort.natsorted(logical_port_list)
name = logical_port_list[self.port_index-1] or "Unknown"
return name
def __validate_eeprom_sfp(self):
checksum_test = 0
eeprom_raw = self.read_eeprom(0, 96)
if eeprom_raw is None:
return None
for i in range(0, 63):
checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF
else:
if checksum_test != eeprom_raw[63]:
return False
checksum_test = 0
for i in range(64, 95):
checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF
else:
if checksum_test != eeprom_raw[95]:
return False
api = self.get_xcvr_api()
if api is None:
return False
if api.is_flat_memory():
return True
checksum_test = 0
eeprom_raw = self.read_eeprom(384, 96)
if eeprom_raw is None:
return None
for i in range(0, 95):
checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF
else:
if checksum_test != eeprom_raw[95]:
return False
return True
def __validate_eeprom_qsfp(self):
checksum_test = 0
eeprom_raw = self.read_eeprom(128, 96)
if eeprom_raw is None:
return None
for i in range(0, 63):
checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF
else:
if checksum_test != eeprom_raw[63]:
return False
checksum_test = 0
for i in range(64, 95):
checksum_test = (checksum_test + eeprom_raw[i]) & 0xFF
else:
if checksum_test != eeprom_raw[95]:
return False
api = self.get_xcvr_api()
if api is None:
return False
if api.is_flat_memory():
return True
return True
def validate_eeprom(self):
id_byte_raw = self.read_eeprom(0, 1)
if id_byte_raw is None:
return None
id = id_byte_raw[0]
if id in self.QSFP_TYPE_CODE_LIST:
return self.__validate_eeprom_qsfp()
elif id in self.SFP_TYPE_CODE_LIST:
return self.__validate_eeprom_sfp()
else:
return False
def validate_temperature(self):
temperature = self.get_temperature()
if temperature is None:
return None
threshold_dict = self.get_transceiver_threshold_info()
if threshold_dict is None:
return None
if isinstance(temperature, float) is not True:
return True
if isinstance(threshold_dict['temphighalarm'], float) is not True:
return True
return threshold_dict['temphighalarm'] > temperature
def __get_error_description(self):
if not self.get_presence():
return self.SFP_STATUS_UNPLUGGED
err_stat = self.SFP_STATUS_BIT_INSERTED
status = self.validate_eeprom()
if status is not True:
err_stat = (err_stat | self.SFP_ERROR_BIT_BAD_EEPROM)
status = self.validate_temperature()
if status is not True:
err_stat = (err_stat | self.SFP_ERROR_BIT_HIGH_TEMP)
if err_stat is self.SFP_STATUS_BIT_INSERTED:
return self.SFP_STATUS_OK
else:
err_desc = ''
cnt = 0
for key in self.SFP_ERROR_BIT_TO_DESCRIPTION_DICT:
if (err_stat & key) != 0:
if cnt > 0:
err_desc = err_desc + "|"
cnt = cnt + 1
err_desc = err_desc + self.SFP_ERROR_BIT_TO_DESCRIPTION_DICT[key]
return err_desc
def get_reset_status(self):
if self.sfp_type == "QSFP28":
return super().get_reset_status()
return False
def reset(self):
if self.sfp_type == "QSFP28":
return super().reset()
return False
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 self.sfp_type != "SFP28" and self.sfp_type != "QSFP28":
return "Not implemented"
try:
ret = super().get_error_description()
if ret is not None:
return ret
except NotImplementedError:
pass
return self.__get_error_description()

View File

@ -3,10 +3,55 @@
try:
from sonic_platform_pddf_base.pddf_thermal import PddfThermal
from .helper import DeviceThreshold
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
NOT_AVAILABLE = DeviceThreshold.NOT_AVAILABLE
HIGH_THRESHOLD = DeviceThreshold.HIGH_THRESHOLD
LOW_THRESHOLD = DeviceThreshold.LOW_THRESHOLD
HIGH_CRIT_THRESHOLD = DeviceThreshold.HIGH_CRIT_THRESHOLD
LOW_CRIT_THRESHOLD = DeviceThreshold.LOW_CRIT_THRESHOLD
DEFAULT_THRESHOLD = {
'Temp sensor 1' : {
HIGH_THRESHOLD : '80.0',
LOW_THRESHOLD : NOT_AVAILABLE,
HIGH_CRIT_THRESHOLD : NOT_AVAILABLE,
LOW_CRIT_THRESHOLD : NOT_AVAILABLE
},
'Temp sensor 2' : {
HIGH_THRESHOLD : '80.0',
LOW_THRESHOLD : NOT_AVAILABLE,
HIGH_CRIT_THRESHOLD : NOT_AVAILABLE,
LOW_CRIT_THRESHOLD : NOT_AVAILABLE
},
'Temp sensor 3' : {
HIGH_THRESHOLD : '80.0',
LOW_THRESHOLD : NOT_AVAILABLE,
HIGH_CRIT_THRESHOLD : NOT_AVAILABLE,
LOW_CRIT_THRESHOLD : NOT_AVAILABLE
},
'Temp sensor 4' : {
HIGH_THRESHOLD : '71.0',
LOW_THRESHOLD : NOT_AVAILABLE,
HIGH_CRIT_THRESHOLD : '91.0',
LOW_CRIT_THRESHOLD : NOT_AVAILABLE
},
'PSU-1 temp sensor 1' : {
HIGH_THRESHOLD : '80.0',
LOW_THRESHOLD : NOT_AVAILABLE,
HIGH_CRIT_THRESHOLD : NOT_AVAILABLE,
LOW_CRIT_THRESHOLD : NOT_AVAILABLE
},
'PSU-2 temp sensor 1' : {
HIGH_THRESHOLD : '80.0',
LOW_THRESHOLD : NOT_AVAILABLE,
HIGH_CRIT_THRESHOLD : NOT_AVAILABLE,
LOW_CRIT_THRESHOLD : NOT_AVAILABLE
}
}
class Thermal(PddfThermal):
"""PDDF Platform-Specific Thermal class"""
@ -14,4 +59,196 @@ class Thermal(PddfThermal):
def __init__(self, index, pddf_data=None, pddf_plugin_data=None, is_psu_thermal=False, psu_index=0):
PddfThermal.__init__(self, index, pddf_data, pddf_plugin_data, is_psu_thermal, psu_index)
# Threshold Configuration
self.__conf = DeviceThreshold(self.get_name())
# Default threshold.
self.__default_threshold = DEFAULT_THRESHOLD[self.get_name()]
self.min_temperature = None
self.max_temperature = None
# Provide the functions/variables below for which implementation is to be overwritten
def get_name(self):
if self.is_psu_thermal:
return "PSU-{0} temp sensor 1".format(self.thermals_psu_index)
else:
return "Temp sensor {0}".format(self.thermal_index)
def get_status(self):
get_temp=self.get_temperature()
if get_temp is not None:
return True if get_temp else False
def get_temperature(self):
current = super().get_temperature()
if self.min_temperature is None or \
current < self.min_temperature:
self.min_temperature = current
if self.max_temperature is None or \
current > self.max_temperature:
self.max_temperature = current
return current
def set_high_threshold(self, temperature):
try:
value = float(temperature)
except Exception:
return False
# The new value can not be more than the default value.
default_value = self.__default_threshold[HIGH_THRESHOLD]
if default_value != NOT_AVAILABLE:
if value > float(default_value):
return False
try:
self.__conf.set_high_threshold(str(value))
except Exception:
return False
return True
def get_high_threshold(self):
value = self.__conf.get_high_threshold()
if value != NOT_AVAILABLE:
return float(value)
default_value = self.__default_threshold[HIGH_THRESHOLD]
if default_value != NOT_AVAILABLE:
return float(default_value)
raise NotImplementedError
def set_low_threshold(self, temperature):
try:
value = float(temperature)
except Exception:
return False
# The new value can not be less than the default value.
default_value = self.__default_threshold[LOW_THRESHOLD]
if default_value != NOT_AVAILABLE:
if value < float(default_value):
return False
try:
self.__conf.set_low_threshold(str(value))
except Exception:
return False
return True
def get_low_threshold(self):
value = self.__conf.get_low_threshold()
if value != NOT_AVAILABLE:
return float(value)
default_value = self.__default_threshold[LOW_THRESHOLD]
if default_value != NOT_AVAILABLE:
return float(default_value)
raise NotImplementedError
def set_high_critical_threshold(self, temperature):
try:
value = float(temperature)
except Exception:
return False
# The new value can not be more than the default value.
default_value = self.__default_threshold[HIGH_CRIT_THRESHOLD]
if default_value != NOT_AVAILABLE:
if value > float(default_value):
return False
try:
self.__conf.set_high_critical_threshold(str(value))
except Exception:
return False
return True
def get_high_critical_threshold(self):
value = self.__conf.get_high_critical_threshold()
if value != NOT_AVAILABLE:
return float(value)
default_value = self.__default_threshold[HIGH_CRIT_THRESHOLD]
if default_value != NOT_AVAILABLE:
return float(default_value)
raise NotImplementedError
def set_low_critical_threshold(self, temperature):
try:
value = float(temperature)
except Exception:
return False
# The new value can not be less than the default value.
default_value = self.__default_threshold[LOW_CRIT_THRESHOLD]
if default_value != NOT_AVAILABLE:
if value < float(default_value):
return False
try:
self.__conf.set_low_critical_threshold(str(value))
except Exception:
return False
return True
def get_low_critical_threshold(self):
value = self.__conf.get_low_critical_threshold()
if value != NOT_AVAILABLE:
return float(value)
default_value = self.__default_threshold[LOW_CRIT_THRESHOLD]
if default_value != NOT_AVAILABLE:
return float(default_value)
raise NotImplementedError
def get_model(self):
"""
Retrieves the model number (or part number) of the device
Returns:
string: Model/part number of device
"""
return "N/A"
def get_serial(self):
"""
Retrieves the serial number of the device
Returns:
string: Serial number of device
"""
return "N/A"
def get_minimum_recorded(self):
"""
Retrieves the minimum recorded temperature of thermal
Returns:
A float number, the minimum recorded temperature of thermal in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
if self.min_temperature is None:
self.get_temperature()
return self.min_temperature
def get_maximum_recorded(self):
"""
Retrieves the maximum recorded temperature of thermal
Returns:
A float number, the maximum recorded temperature of thermal in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
if self.max_temperature is None:
self.get_temperature()
return self.max_temperature

View File

@ -207,14 +207,24 @@ class device_monitor(object):
fan_fail_list[i] = 0
if sum(fan_fail_list) == NUM_FANS:
logging.critical(
'Alarm for all fan faulty/absent is detected, disable PoE')
cmd_str = ["i2cset", "-f", "-y", "16", "0x20", "0x06", "0x0", "0x0", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xFE", "i"]
getstatusoutput_noshell(cmd_str) # Disable PoE
# Critical: Either all the fans are faulty or they are removed, shutdown the system
logging.critical('Alarm for all fan faulty/absent is detected')
logging.critical("Alarm for all fan faulty/absent is detected, reset DUT")
cmd_str = ["i2cset", "-y", "-f", "3", "0x60", "0x4", "0xE4"]
logging.critical("Alarm for all fan faulty/absent is detected, shutdown DUT")
# Sync log buffer to disk
cmd_str = ["sync"]
getstatusoutput_noshell(cmd_str)
cmd_str = ["/sbin/fstrim", "-av"]
getstatusoutput_noshell(cmd_str)
time.sleep(3)
cmd_str = ["i2cset", "-y", "-f", "3", "0x60", "0x4", "0x74"]
time.sleep(2)
getstatusoutput_noshell('sync')
getstatusoutput_noshell('sync')
getstatusoutput_noshell('sync')
getstatusoutput_noshell(cmd_str)
elif sum(fan_fail_list) != 0:
# Set the 100% speed only for first fan failure detection
@ -243,8 +253,13 @@ class device_monitor(object):
if temp[0] >= 70000: # LM77-48
# critical case*/
logging.critical(
'Alarm-Critical for temperature critical is detected, disable PoE')
cmd_str = ["i2cset", "-f", "-y", "16", "0x20", "0x06", "0x0", "0x0", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xff", "0xFE", "i"]
getstatusoutput_noshell(cmd_str) # Disable PoE
logging.critical('Alarm for temperature critical is detected')
logging.critical("Alarm-Critical for temperature critical is detected, reset DUT")
logging.critical("Alarm-Critical for temperature critical is detected, shutdown DUT")
# Update the reboot cause file to reflect that critical temperature
# has been crossed. Upon next boot, the contents of this file will
# be used to determine the cause of the previous reboot
@ -255,10 +270,14 @@ class device_monitor(object):
if status:
logging.warning('Reboot cause file not updated. {}'.format(output))
cmd_str = ["i2cset", "-y", "-f", "3", "0x60", "0x4", "0xE4"]
getstatusoutput_noshell('sync')
getstatusoutput_noshell('sync')
getstatusoutput_noshell('sync')
# Sync log buffer to disk
cmd_str = ["sync"]
getstatusoutput_noshell(cmd_str)
cmd_str = ["/sbin/fstrim", "-av"]
getstatusoutput_noshell(cmd_str)
time.sleep(3)
cmd_str = ["i2cset", "-y", "-f", "3", "0x60", "0x4", "0x74"]
time.sleep(3)
getstatusoutput_noshell(cmd_str)

View File

@ -16,21 +16,30 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Usage: %(scriptName)s [options] command object
options:
-h | --help : this help message
-d | --debug : run with debug mode
-f | --force : ignore error during installation or clean
command:
install : install drivers and generate related sysfs nodes
clean : uninstall drivers and remove related sysfs nodes
usage: accton_as4630_54pe_util.py [-h] [-d] [-f] {install,clean,api,api_clean,threshold} ...
AS4630-54PE Platform Utility
optional arguments:
-h, --help show this help message and exit
-d, --debug run with debug mode
-f, --force ignore error during installation or clean
Utility Command:
{install,clean,api,api_clean,threshold}
install : install drivers and generate related sysfs nodes
clean : uninstall drivers and remove related sysfs nodes
api : install SONiC platform API
api_clean : uninstall SONiC platform API
threshold : modify thermal threshold
"""
import subprocess
import getopt
import sys
import logging
import time
import os
import argparse
from sonic_py_common.general import getstatusoutput_noshell
PROJECT_NAME = 'as4630_54pe'
version = '0.0.1'
@ -97,40 +106,48 @@ def main():
global DEBUG
global args
global FORCE
global THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH
if len(sys.argv)<2:
show_help()
util_parser = argparse.ArgumentParser(description="AS4630-54PE Platform Utility")
util_parser.add_argument("-d", "--debug", dest='debug', action='store_true', default=False,
help="run with debug mode")
util_parser.add_argument("-f", "--force", dest='force', action='store_true', default=False,
help="ignore error during installation or clean")
subcommand = util_parser.add_subparsers(dest='cmd', title='Utility Command', required=True)
subcommand.add_parser('install', help=': install drivers and generate related sysfs nodes')
subcommand.add_parser('clean', help=': uninstall drivers and remove related sysfs nodes')
subcommand.add_parser('api', help=': install SONiC platform API')
subcommand.add_parser('api_clean', help=': uninstall SONiC platform API')
threshold_parser = subcommand.add_parser('threshold', help=': modify thermal threshold')
threshold_parser.add_argument("-l", dest='list', action='store_true', default=False,
help="list avaliable thermal")
threshold_parser.add_argument("-t", dest='thermal', type=str, metavar='THERMAL_NAME',
help="thermal name, ex: -t 'Temp sensor 1'")
threshold_parser.add_argument("-ht", dest='high_threshold', type=restricted_float,
metavar='THRESHOLD_VALUE',
help="high threshold: %.1f ~ %.1f" % (THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH))
threshold_parser.add_argument("-hct", dest='high_crit_threshold', type=restricted_float,
metavar='THRESHOLD_VALUE',
help="high critical threshold : %.1f ~ %.1f" % (THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH))
args = util_parser.parse_args()
options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help',
'debug',
'force',
])
if DEBUG == True:
print(options)
print(args)
print(len(sys.argv))
for opt, arg in options:
if opt in ('-h', '--help'):
show_help()
elif opt in ('-d', '--debug'):
DEBUG = True
logging.basicConfig(level=logging.INFO)
elif opt in ('-f', '--force'):
FORCE = 1
else:
logging.info('no option')
for arg in args:
if arg == 'install':
do_install()
elif arg == 'clean':
do_uninstall()
elif arg == 'api':
do_sonic_platform_install()
elif arg == 'api_clean':
do_sonic_platform_clean()
else:
show_help()
DEBUG = args.debug
FORCE = 1 if args.force else 0
if args.cmd == 'install':
do_install()
elif args.cmd == 'clean':
do_uninstall()
elif args.cmd == 'api':
do_sonic_platform_install()
elif args.cmd == 'api_clean':
do_sonic_platform_clean()
elif args.cmd == 'threshold':
do_threshold()
return 0
@ -382,5 +399,162 @@ def device_exist():
ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0)
return not(ret1 or ret2)
THRESHOLD_RANGE_LOW = 30.0
THRESHOLD_RANGE_HIGH = 110.0
# Code to initialize chassis object
init_chassis_code = \
"import sonic_platform.platform\n"\
"platform = sonic_platform.platform.Platform()\n"\
"chassis = platform.get_chassis()\n\n"
# Looking for thermal
looking_for_thermal_code = \
"thermal = None\n"\
"all_thermals = chassis.get_all_thermals()\n"\
"for psu in chassis.get_all_psus():\n"\
" all_thermals += psu.get_all_thermals()\n"\
"for tmp in all_thermals:\n"\
" if '{}' == tmp.get_name():\n"\
" thermal = tmp\n"\
" break\n"\
"if thermal == None:\n"\
" print('{} not found!')\n"\
" exit(1)\n\n"
def avaliable_thermals():
global init_chassis_code
get_all_thermal_name_code = \
"thermal_list = []\n"\
"all_thermals = chassis.get_all_thermals()\n"\
"for psu in chassis.get_all_psus():\n"\
" all_thermals += psu.get_all_thermals()\n"\
"for tmp in all_thermals:\n"\
" thermal_list.append(tmp.get_name())\n"\
"print(str(thermal_list)[1:-1])\n"
all_code = "{}{}".format(init_chassis_code, get_all_thermal_name_code)
status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code])
if status != 0:
return ""
return output
def restricted_float(x):
global THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH
try:
x = float(x)
except ValueError:
raise argparse.ArgumentTypeError("%r not a floating-point literal" % (x,))
if x < THRESHOLD_RANGE_LOW or x > THRESHOLD_RANGE_HIGH:
raise argparse.ArgumentTypeError("%r not in range [%.1f ~ %.1f]" %
(x, THRESHOLD_RANGE_LOW, THRESHOLD_RANGE_HIGH))
return x
def get_high_threshold(name):
global init_chassis_code, looking_for_thermal_code
get_high_threshold_code = \
"try:\n"\
" print(thermal.get_high_threshold())\n"\
" exit(0)\n"\
"except NotImplementedError:\n"\
" print('Not implement the get_high_threshold method!')\n"\
" exit(1)"
all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(name, name),
get_high_threshold_code)
status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code])
if status == 1:
return None
return float(output)
def get_high_crit_threshold(name):
global init_chassis_code, looking_for_thermal_code
get_high_crit_threshold_code = \
"try:\n"\
" print(thermal.get_high_critical_threshold())\n"\
" exit(0)\n"\
"except NotImplementedError:\n"\
" print('Not implement the get_high_critical_threshold method!')\n"\
" exit(1)"
all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(name, name),
get_high_crit_threshold_code)
status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code])
if status == 1:
return None
return float(output)
def do_threshold():
global args, init_chassis_code, looking_for_thermal_code
if args.list:
print("Thermals: " + avaliable_thermals())
return
if args.thermal is None:
print("The following arguments are required: -t")
return
set_threshold_code = ""
if args.high_threshold is not None:
if args.high_crit_threshold is not None and \
args.high_threshold >= args.high_crit_threshold:
print("Invalid Threshold!(High threshold can not be more than " \
"or equal to high critical threshold.)")
exit(1)
high_crit = get_high_crit_threshold(args.thermal)
if high_crit is not None and \
args.high_threshold >= high_crit:
print("Invalid Threshold!(High threshold can not be more than " \
"or equal to high critical threshold.)")
exit(1)
set_threshold_code += \
"try:\n"\
" if thermal.set_high_threshold({}) is False:\n"\
" print('{}: set_high_threshold failure!')\n"\
" exit(1)\n"\
"except NotImplementedError:\n"\
" print('Not implement the set_high_threshold method!')\n"\
"print('Apply the new high threshold successfully.')\n"\
"\n".format(args.high_threshold, args.thermal)
if args.high_crit_threshold is not None:
high = get_high_threshold(args.thermal)
if high is not None and \
args.high_crit_threshold <= high:
print("Invalid Threshold!(High critical threshold can not " \
"be less than or equal to high threshold.)")
exit(1)
set_threshold_code += \
"try:\n"\
" if thermal.set_high_critical_threshold({}) is False:\n"\
" print('{}: set_high_critical_threshold failure!')\n"\
" exit(1)\n"\
"except NotImplementedError:\n"\
" print('Not implement the set_high_critical_threshold method!')\n"\
"print('Apply the new high critical threshold successfully.')\n"\
"\n".format(args.high_crit_threshold, args.thermal)
if set_threshold_code == "":
return
all_code = "{}{}{}".format(init_chassis_code, looking_for_thermal_code.format(args.thermal, args.thermal), set_threshold_code)
status, output = getstatusoutput_noshell(["docker", "exec", "pmon", "python3", "-c", all_code])
print(output)
if __name__ == "__main__":
main()

View File

@ -1,9 +1,7 @@
#!/bin/bash
#Due to the hardware design, as4630-54pe use "eth2" instead of "eth0" as management interface.
#Rename netdev "eth0" and "eth2" to swap original "eth2" to "eth0".
ifconfig eth0 down
ip link set eth0 name eth3
ip link set eth2 name eth0
ifconfig eth0 up
# Re-install the igb and ixgbe again to make the NIC sequence follow the udev rule
modprobe -r igb
modprobe -r ixgbe
modprobe igb
modprobe ixgbe

View File

@ -27,6 +27,7 @@ UTILS_DIR := utils
SERVICE_DIR := service
UDEV_DIR := udev
CONF_DIR := conf
UDEV_DIR := udev
%:
dh $@ --with systemd,python3 --buildsystem=pybuild
@ -70,11 +71,11 @@ binary-indep:
dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/local/bin; \
dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \
dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} etc/udev/rules.d; \
dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} etc/udev/rules.d; \
cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \
cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \
cp $(MOD_SRC_DIR)/$${mod}/$(UDEV_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/udev/rules.d/; \
cp $(MOD_SRC_DIR)/$${mod}/$(UDEV_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/etc/udev/rules.d/; \
$(PYTHON3) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \
done)
# Resuming debhelper scripts

View File

@ -8,3 +8,5 @@ systemctl start pddf-platform-init.service
systemctl enable as4630-54pe-pddf-platform-monitor.service
systemctl start as4630-54pe-pddf-platform-monitor.service
/usr/local/bin/restart_ixgbe.sh
systemctl enable as4630-54pe-platform-handle-mgmt-interface.service
systemctl start as4630-54pe-platform-handle-mgmt-interface.service