Skip to content

Commit

Permalink
[device/celestica]: Implement Silverstone platform API [THERMAL/COMPO…
Browse files Browse the repository at this point in the history
…NENT] (sonic-net#3938)

- Add Thermal APIs
- Add Component APIs
  • Loading branch information
Wirut Getbamrung authored and lguohan committed Jan 16, 2020
1 parent 5229163 commit 4c526d9
Show file tree
Hide file tree
Showing 4 changed files with 340 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,19 @@

try:
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.component import Component
from sonic_platform.eeprom import Tlv
from sonic_platform.fan import Fan
from sonic_platform.psu import Psu
from sonic_platform.thermal import Thermal
from helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")

NUM_FAN_TRAY = 7
NUM_FAN = 2
NUM_PSU = 2
NUM_THERMAL = 5
NUM_THERMAL = 10
NUM_SFP = 32
NUM_COMPONENT = 5

Expand All @@ -50,6 +52,12 @@ def __init__(self):
for index in range(0, NUM_PSU):
psu = Psu(index)
self._psu_list.append(psu)
for index in range(0, NUM_COMPONENT):
component = Component(index)
self._component_list.append(component)
for index in range(0, NUM_THERMAL):
thermal = Thermal(index)
self._thermal_list.append(thermal)

def get_base_mac(self):
"""
Expand Down Expand Up @@ -92,7 +100,8 @@ def get_reboot_cause(self):

status, raw_cause = self._api_helper.ipmi_raw(
IPMI_OEM_NETFN, IPMI_GET_REBOOT_CAUSE)
hx_cause = raw_cause.split()[0] if status else 00
hx_cause = raw_cause.split()[0] if status and len(
raw_cause.split()) > 0 else 00
reboot_cause = {
"00": self.REBOOT_CAUSE_HARDWARE_OTHER,
"11": self.REBOOT_CAUSE_POWER_LOSS,
Expand Down
121 changes: 121 additions & 0 deletions device/celestica/x86_64-cel_silverstone-r0/sonic_platform/component.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/env python

#############################################################################
# Celestica
#
# Component contains an implementation of SONiC Platform Base API and
# provides the components firmware management function
#
#############################################################################

import json
import os.path

try:
from sonic_platform_base.component_base import ComponentBase
from helper import APIHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")

COMPONENT_LIST = [
("BIOS", "Basic Input/Output System"),
("BMC", "Baseboard Management Controller"),
("SWITCH_CPLD", "Switch board CPLD"),
("BASE_CPLD", "Base board CPLD"),
("FPGA", "Field-programmable gate array")
]
SW_CPLD_VER_PATH = "/sys/module/switch_cpld/version"
BASE_CPLD_VER_PATH = "/sys/module/baseboard_lpc/version"
CPLD_UPGRADE_OPT = 4
BIOS_VER_PATH = "/sys/class/dmi/id/bios_version"
BIOS__UPGRADE_OPT = 2
BMC_VER_CMD = "ipmitool mc info | grep 'Firmware Revision'"
BMC_UPGRADE_OPT = 1
CFUFLASH_FW_UPGRADE_CMD = "CFUFLASH -cd -d {} -mse 3 {}"
MEM_PCI_RESOURCE = "/sys/bus/pci/devices/0000:09:00.0/resource0"
FPGA_VER_MEM_OFFSET = 0


class Component(ComponentBase):
"""Platform-specific Component class"""

DEVICE_TYPE = "component"

def __init__(self, component_index):
ComponentBase.__init__(self)
self.index = component_index
self.name = self.get_name()
self._api_helper = APIHelper()

def __get_bmc_ver(self):
bmc_ver = "Unknown"
status, raw_bmc_data = self._api_helper.run_command(BMC_VER_CMD)
if status:
bmc_ver_data = raw_bmc_data.split(":")
bmc_ver = bmc_ver_data[-1].strip() if len(
bmc_ver_data) > 1 else bmc_ver
return bmc_ver

def __get_fpga_ver(self):
fpga_ver = "Unknown"
status, reg_val = self._api_helper.pci_get_value(
MEM_PCI_RESOURCE, FPGA_VER_MEM_OFFSET)
if status:
major = reg_val[0] >> 16
minor = int(bin(reg_val[0])[16:32], 2)
fpga_ver = '{}.{}'.format(major, minor)
return fpga_ver

def get_name(self):
"""
Retrieves the name of the component
Returns:
A string containing the name of the component
"""
return COMPONENT_LIST[self.index][0]

def get_description(self):
"""
Retrieves the description of the component
Returns:
A string containing the description of the component
"""
return COMPONENT_LIST[self.index][1]

def get_firmware_version(self):
"""
Retrieves the firmware version of module
Returns:
string: The firmware versions of the module
"""
fw_version = {
"BIOS": self._api_helper.read_txt_file(BIOS_VER_PATH),
"BMC": self.__get_bmc_ver(),
"FPGA": self.__get_fpga_ver(),
"SWITCH_CPLD": self._api_helper.read_txt_file(SW_CPLD_VER_PATH),
"BASE_CPLD": self._api_helper.read_txt_file(BASE_CPLD_VER_PATH),
}.get(self.name, "Unknown")

return fw_version

def install_firmware(self, image_path):
"""
Install firmware to module
Args:
image_path: A string, path to firmware image
Returns:
A boolean, True if install successfully, False if not
"""
install_command = {
"BMC": CFUFLASH_FW_UPGRADE_CMD.format(BMC_UPGRADE_OPT, image_path),
"BIOS": CFUFLASH_FW_UPGRADE_CMD.format(BIOS__UPGRADE_OPT, image_path),
"SWITCH_CPLD": CFUFLASH_FW_UPGRADE_CMD.format(CPLD_UPGRADE_OPT, image_path),
"BASE_CPLD": CFUFLASH_FW_UPGRADE_CMD.format(CPLD_UPGRADE_OPT, image_path)
}.get(self.name, None)

if not os.path.isfile(image_path) or install_command is None:
return False

# print(install_command)
status = self._api_helper.run_interactive_command(install_command)
return status
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#!/usr/bin/env python

import os
import struct
import subprocess

from mmap import *

HOST_CHK_CMD = "docker > /dev/null 2>&1"
EMPTY_STRING = ""
Expand All @@ -16,6 +17,39 @@ def __init__(self):
def is_host(self):
return os.system(HOST_CHK_CMD) == 0

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:
status = False
return status, result

def run_command(self, cmd):
status = True
result = ""
try:
p = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
raw_data, err = p.communicate()
if err == '':
result = raw_data.strip()
except:
status = False
return status, result

def run_interactive_command(self, cmd):
try:
os.system(cmd)
except:
return False
return True

def read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
Expand All @@ -35,6 +69,8 @@ def ipmi_raw(self, netfn, cmd):
raw_data, err = p.communicate()
if err == '':
result = raw_data.strip()
else:
status = False
except:
status = False
return status, result
Expand All @@ -51,6 +87,24 @@ def ipmi_fru_id(self, id, key=None):
raw_data, err = p.communicate()
if err == '':
result = raw_data.strip()
else:
status = False
except:
status = False
return status, result

def ipmi_set_ss_thres(self, id, threshold_key, value):
status = True
result = ""
try:
cmd = "ipmitool sensor thresh '{}' {} {}".format(str(id), str(threshold_key), str(value))
p = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
raw_data, err = p.communicate()
if err == '':
result = raw_data.strip()
else:
status = False
except:
status = False
return status, result
Loading

0 comments on commit 4c526d9

Please sign in to comment.