diff --git a/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/fanutil.py b/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/fanutil.py index 791fc35ca4db..c0b58b89928d 100644 --- a/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/fanutil.py +++ b/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/fanutil.py @@ -1,117 +1,51 @@ -#!/usr/bin/env python - -__author__ = 'Wirut G.' -__license__ = "GPL" -__version__ = "0.2.0" -__status__ = "Development" +#!/usr/bin/python import requests import re - -NUM_FAN_TRAY = 4 -NUM_ROTER = 2 +import json class FanUtil(): - """Platform-specific FanUtil class""" + BMC_REQ_BASE_URI = "http://240.1.1.1:8080/api" + ROTOR_PER_FAN = 2 def __init__(self): - self.fan_info_url = "http://240.1.1.1:8080/api/fan/info" - self.all_fan_dict = None - - def request_data(self, url): - try: - r = requests.get(url) - data = r.json() - except Exception as e: - return {} - return data - - def get_num_fans(self): - """ - Get the number of fans - :return: int num_fans - """ - all_fan_dict = self.get_all() - num_fan_tray = all_fan_dict.get('Number', NUM_FAN_TRAY) - - return num_fan_tray * NUM_ROTER - - def get_fan_speed(self, fan_name): - """ - Get the current speed of the fan, the unit is "RPM" - :return: int fan_speed - """ - - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) - - return fan_info.get('Speed', 0) - - def get_fan_low_threshold(self, fan_name): - """ - Get the low speed threshold of the fan. - if the current speed < low speed threshold, - the status of the fan is not ok. - :return: int fan_low_threshold - """ - - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) - - return fan_info.get('LowThd', 0) + self.fan_info_uri = "/".join([self.BMC_REQ_BASE_URI, "fan/info"]) + self.fan_num_uri = "/".join([self.BMC_REQ_BASE_URI, "fan/number"]) - def get_fan_high_threshold(self, fan_name): - """ - Get the hight speed threshold of the fan, - if the current speed > high speed threshold, - the status of the fan is not ok - :return: int fan_high_threshold - """ - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) + def _get_fan_info(self): + resp = requests.get(self.fan_info_uri) + if not resp: + return False - return fan_info.get('HighThd', 0) + fan_json = resp.json() + if not fan_json or not "data" in fan_json: + return False - def get_fan_pn(self, fan_name): - """ - Get the product name of the fan - :return: str fan_pn - """ + self.fan_info = fan_json["data"] - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) + return True - return fan_info.get('PN', 'N/A') - - def get_fan_sn(self, fan_name): - """ - Get the serial number of the fan - :return: str fan_sn + def get_num_fans(self): """ - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) - - return fan_info.get('SN', 'N/A') + Get total fan number - def get_fans_name_list(self): + @return number of fan, -1 for failure """ - Get list of fan name. - :return: list fan_names - """ - fan_names = [] + resp = requests.get(self.fan_num_uri) + if not resp: + return -1 - # Get the number of fans - n_fan = self.get_num_fans() + fan_nr_json = resp.json() + if not fan_nr_json or "data" not in fan_nr_json: + return -1 - # Set fan name and add to the list. - for x in range(1, n_fan + 1): - f_index = int(round(float(x)/2)) - pos = 1 if x % 2 else 2 - fan_name = 'FAN{}_{}'.format(f_index, pos) - fan_names.append(fan_name) + try: + nr_fan = fan_nr_json["data"]["Number"] + except Exception as e: + nr_fan = -1 - return fan_names + return nr_fan def get_all(self): """ @@ -126,41 +60,55 @@ def get_all(self): PN, conditional, if PRESENT is True, PN of the FAN, string SN, conditional, if PRESENT is True, SN of the FAN, string) """ + fan_info = {} + if not self._get_fan_info(): + return fan_info + + if "Number" not in self.fan_info: + return fan_info + + fan_nr = self.fan_info["Number"] + for fan_idx in range(1, fan_nr+1): + fan_name = "FAN%d" % fan_idx + if not fan_name in self.fan_info: + print("%s not in self.fan_info" % fan_name) + continue + fi = self.fan_info[fan_name] + if "Rotors" not in fi: + print("Rotors not in fi") + continue + rotor_nr = fi["Rotors"] + for ridx in range(1, rotor_nr+1): + sub_name = "%s_%d" % (fan_name, ridx) + rname = "Rotor%d" % ridx + sub_fan_info = {} + if rname not in fi: + print("%s not in fi" % rname) + continue + try: + sub_fan_info["Present"] = True if fi["Present"] == "yes" else False + sub_fan_info["Running"] = fi[rname]["Running"] + sub_fan_info["Speed"] = fi[rname]["Speed"] + sub_fan_info["LowThd"] = fi[rname]["SpeedMin"] + sub_fan_info["HighThd"] = fi[rname]["SpeedMax"] + sub_fan_info["PN"] = fi["PN"] + sub_fan_info["SN"] = fi["SN"] + sub_fan_info["AirFlow"] = fi["AirFlow"] + if (fi[rname]["HwAlarm"] == "no") and \ + (sub_fan_info["Speed"] != None and sub_fan_info["LowThd"] != None and sub_fan_info["Speed"] >= sub_fan_info["LowThd"]) and \ + (sub_fan_info["Speed"] != None and sub_fan_info["HighThd"] != None and sub_fan_info["Speed"] <= sub_fan_info["HighThd"]): + sub_fan_info["Status"] = True + else: + sub_fan_info["Status"] = False + + fan_info[sub_name] = sub_fan_info + except Exception as e: + print("GOT EXCEPTON: %s" % str(e)) + continue + fan_info["Number"] = fan_nr * self.ROTOR_PER_FAN + + #j = json.dumps(fan_info, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + + return fan_info - if not self.all_fan_dict: - all_fan_dict = dict() - - fan_info_req = self.request_data(self.fan_info_url) - fan_info_data = fan_info_req.get('data', {}) - all_fan_dict["Number"] = fan_info_data.get('Number', NUM_FAN_TRAY) - - for fan_idx in range(1, all_fan_dict["Number"] + 1): - num_of_roter = fan_info_data.get('Rotors', NUM_ROTER) - - for fan_pos in range(1, num_of_roter + 1): - fan_key = 'FAN{}'.format(str(fan_idx)) - roter_key = 'Rotor{}'.format(str(fan_pos)) - - fan_info = fan_info_data.get(fan_key, {}) - roter_info = fan_info.get(roter_key, {}) - - fan_info_dict = dict() - fan_info_dict["Present"] = True if fan_info.get( - "Present") == 'yes' else False - fan_info_dict["Speed"] = roter_info.get("Speed", "N/A") - fan_info_dict["Running"] = True if roter_info.get( - "Running") == 'yes' else False - fan_info_dict["HighThd"] = roter_info.get( - "SpeedMax", "N/A") - fan_info_dict["LowThd"] = roter_info.get("SpeedMin", "N/A") - fan_info_dict["Status"] = False if roter_info.get( - "HwAlarm") == 'yes' else True - fan_info_dict["PN"] = fan_info.get("PN", "N/A") - fan_info_dict["SN"] = fan_info.get("SN", "N/A") - fan_info_dict["AirFlow"] = fan_info.get("AirFlow", "N/A") - - fan_name = '{}_{}'.format(fan_key, fan_pos) - all_fan_dict[fan_name] = fan_info_dict - self.all_fan_dict = all_fan_dict - - return self.all_fan_dict diff --git a/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/fwmgrutil.py b/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/fwmgrutil.py index 7e5fe101c5c4..94f57d386da8 100644 --- a/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/fwmgrutil.py +++ b/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/fwmgrutil.py @@ -1,14 +1,5 @@ -#!/usr/bin/env python -# -# fwmgrutil.py -# -# Platform-specific firmware management interface for SONiC -# - -__author__ = 'Wirut G.' -__license__ = "GPL" -__version__ = "0.2.1" -__status__ = "Development" +#!/usr/bin/python + import subprocess import requests @@ -28,33 +19,51 @@ class FwMgrUtil(FwMgrUtilBase): - - """Platform-specific FwMgrUtil class""" + BMC_REQ_BASE_URI = "http://240.1.1.1:8080/api" + ONIE_CFG_FILE = "/host/machine.conf" def __init__(self): self.platform_name = "AS1332h" - self.onie_config_file = "/host/machine.conf" - self.bmc_info_url = "http://240.1.1.1:8080/api/bmc/info" - self.cpld_info_url = "http://240.1.1.1:8080/api/firmware/cpldversion" - self.bmc_raw_command_url = "http://240.1.1.1:8080/api/hw/rawcmd" - self.fw_upgrade_url = "http://240.1.1.1:8080/api/firmware/upgrade" - self.fw_refresh_url = "http://240.1.1.1:8080/api/firmware/refresh" - self.bios_next_boot = "http://240.1.1.1:8080/api/firmware/biosnextboot" - self.bmc_next_boot = "http://240.1.1.1:8080/api/bmc/nextboot" - self.bmc_reboot_url = "http://240.1.1.1:8080/api/bmc/reboot" - self.bios_boot_info = "http://240.1.1.1:8080/api/misc/biosbootstatus" - self.onie_config_file = "/host/machine.conf" + self.bmc_info_uri = "/".join([self.BMC_REQ_BASE_URI, "bmc/info"]) + self.bmc_nextboot_uri = "/".join([self.BMC_REQ_BASE_URI, "bmc/nextboot"]) + self.bmc_reboot_uri = "/".join([self.BMC_REQ_BASE_URI, "bmc/reboot"]) + self.fw_upgrade_uri = "/".join([self.BMC_REQ_BASE_URI, "firmware/upgrade"]) + self.fw_refresh_uri = "/".join([self.BMC_REQ_BASE_URI, "firmware/refresh"]) + self.fw_upgrade_logger_path = "/var/log/fw_upgrade.log" - self.cpldb_version_path = "/sys/devices/platform/%s.cpldb/getreg" % self.platform_name + + self.cpld_ver_info = { + "CPLD_B": { + "path": "/sys/devices/platform/%s.cpldb/getreg" % self.platform_name, + "offset": "0xA100" + }, + "CPLD_C": { + "path": "/sys/devices/platform/%s.cpldb/getreg" % self.platform_name, + "offset": "0xA1E0" + }, + "CPLD_1": { + "path": "/sys/devices/platform/%s.switchboard/CPLD1/getreg" % self.platform_name, + "offset": "0x00" + }, + "CPLD_2": { + "path": "/sys/devices/platform/%s.switchboard/CPLD2/getreg" % self.platform_name, + "offset": "0x00" + }, + "CPLD_3": { + "path": "/sys/devices/platform/%s.switchboard/CPLD3/getreg" % self.platform_name, + "offset": "0x00" + }, + "CPLD_4": { + "path": "/sys/devices/platform/%s.switchboard/CPLD1/getreg" % self.platform_name, + "offset": "0x00" + }, + "CPLD_FAN": { + "path": "bmc", + "offset": "0x00" + } + } self.fpga_version_path = "/sys/devices/platform/%s.switchboard/FPGA/getreg" % self.platform_name - self.switchboard_cpld1_path = "/sys/devices/platform/%s.switchboard/CPLD1/getreg" % self.platform_name - self.switchboard_cpld2_path = "/sys/devices/platform/%s.switchboard/CPLD2/getreg" % self.platform_name - self.switchboard_cpld3_path = "/sys/devices/platform/%s.switchboard/CPLD3/getreg" % self.platform_name - self.switchboard_cpld4_path = "/sys/devices/platform/%s.switchboard/CPLD4/getreg" % self.platform_name self.bmc_pwd_path = "/usr/local/etc/bmcpwd" - self.cpld_name_list = ["CPU_CPLD", "COMBO_CPLD", - "SW_CPLD1", "SW_CPLD2", "TOP_LC_CPLD", "BOT_LC_CPLD"] - self.api_time_out = 300 def __get_register_value(self, path, register): cmd = "echo {1} > {0}; cat {0}".format(path, register) @@ -66,6 +75,30 @@ def __get_register_value(self, path, register): else: return raw_data.strip() + def __fpga_pci_rescan(self): + """ + An sequence to trigger FPGA to load new configuration after upgrade. + """ + fpga_pci_device_remove = '/sys/devices/pci0000:00/0000:00:1c.0/0000:09:00.0/remove' + parent_pci_device_rescan = '/sys/devices/pci0000:00/0000:00:1c.0/rescan' + cmd = 'modprobe -r switchboard_fpga' + os.system(cmd) + cmd = 'echo 1 > %s' % fpga_pci_device_remove + rc = os.system(cmd) + if rc > 0: + return rc + cmd = 'echo 0xa10a 0 > /sys/devices/platform/%s.cpldb/setreg' % self.platform_name + rc = os.system(cmd) + if rc > 0: + return rc + time.sleep(10) + cmd = 'echo 1 > %s' % parent_pci_device_rescan + rc = os.system(cmd) + if rc > 0: + return rc + os.system('modprobe switchboard_fpga') + return 0 + def __update_fw_upgrade_logger(self, header, message): if not os.path.isfile(self.fw_upgrade_logger_path): cmd = "sudo touch %s && sudo chmod +x %s" % ( @@ -76,7 +109,7 @@ def __update_fw_upgrade_logger(self, header, message): logging.basicConfig(filename=self.fw_upgrade_logger_path, filemode='a', format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s', - datefmt='%b %d %H:%M:%S', + datefmt='%H:%M:%S', level=logging.INFO) log_message = "%s : %s" % (header, message) @@ -99,27 +132,58 @@ def get_bmc_pass(self): return "".join(dec) return False + def get_from_bmc(self, uri): + resp = requests.get(uri) + if not resp: + return None + + data = resp.json() + if not data or "data" not in data or "status" not in data: + return None + + if data["status"] != "OK": + return None + + return data["data"] + def get_bmc_version(self): - """Get BMC version from SONiC - :returns: version string + bmc_ver = "N/A" + data = self.get_from_bmc(self.bmc_info_uri) + if not data or "Version" not in data: + return bmc_ver - """ - bmc_version = None - bmc_version_key = "Version" - bmc_info_req = requests.get( - self.bmc_info_url, timeout=self.api_time_out) - if bmc_info_req.status_code == 200: - bmc_info_json = bmc_info_req.json() - bmc_info = bmc_info_json.get('data') - bmc_version = bmc_info.get(bmc_version_key) - return str(bmc_version) - - def upload_file_bmc(self, fw_path): - scp_command = 'sudo scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r %s root@240.1.1.1:/home/root/' % os.path.abspath( - fw_path) + return data["Version"] + + def get_bmc_flash(self): + flash = "N/A" + data = self.get_from_bmc(self.bmc_info_uri) + if not data or "Flash" not in data: + return flash + + return data["Flash"] + + def post_to_bmc(self, uri, data): + resp = requests.post(uri, json=data) + if not resp: + print "No response" + return False + + data = resp.json() + if "status" not in data: + return False + + if data["status"] != "OK": + return False + + return True + + def upload_to_bmc(self, fw_path): + scp_command = 'sudo scp -o StrictHostKeyChecking=no -o ' \ + 'UserKnownHostsFile=/dev/null -r %s root@240.1.1.1:/tmp/' \ + % os.path.abspath(fw_path) + print scp_command child = pexpect.spawn(scp_command) - child.timeout = self.api_time_out - i = child.expect(["root@240.1.1.1's password:"]) + i = child.expect(["root@240.1.1.1's password:"], timeout=30) bmc_pwd = self.get_bmc_pass() if i == 0 and bmc_pwd: child.sendline(bmc_pwd) @@ -127,58 +191,25 @@ def upload_file_bmc(self, fw_path): print(data) child.close return os.path.isfile(fw_path) + return False def get_cpld_version(self): - """Get CPLD version from SONiC - :returns: dict like {'CPLD_1': version_string, 'CPLD_2': version_string} - """ - - CPLD_B = self.__get_register_value(self.cpldb_version_path, '0xA100') - CPLD_C = self.__get_register_value(self.cpldb_version_path, '0xA1E0') - CPLD_1 = self.__get_register_value(self.switchboard_cpld1_path, '0x00') - CPLD_2 = self.__get_register_value(self.switchboard_cpld2_path, '0x00') - CPLD_3 = self.__get_register_value(self.switchboard_cpld3_path, '0x00') - CPLD_4 = self.__get_register_value(self.switchboard_cpld4_path, '0x00') - - fan_cpld_key = "CPLD_FAN" - fan_cpld = None - fan_cpld_req = requests.get(self.cpld_info_url) - if fan_cpld_req.status_code == 200: - fancpld_info_json = fan_cpld_req.json() - fancpld_info_data = fancpld_info_json.get('data') - fan_cpld = fancpld_info_data.get(fan_cpld_key) - - CPLD_B = 'None' if CPLD_B is 'None' else "{}.{}".format( - int(CPLD_B[2], 16), int(CPLD_B[3], 16)) - CPLD_C = 'None' if CPLD_C is 'None' else "{}.{}".format( - int(CPLD_C[2], 16), int(CPLD_C[3], 16)) - CPLD_1 = 'None' if CPLD_1 is 'None' else "{}.{}".format( - int(CPLD_1[2], 16), int(CPLD_1[3], 16)) - CPLD_2 = 'None' if CPLD_2 is 'None' else "{}.{}".format( - int(CPLD_2[2], 16), int(CPLD_2[3], 16)) - CPLD_3 = 'None' if CPLD_3 is 'None' else "{}.{}".format( - int(CPLD_3[2], 16), int(CPLD_3[3], 16)) - CPLD_4 = 'None' if CPLD_4 is 'None' else "{}.{}".format( - int(CPLD_4[2], 16), int(CPLD_4[3], 16)) - FAN_CPLD = 'None' if fan_cpld is None else fan_cpld - cpld_version_dict = {} - cpld_version_dict.update({'CPLD_B': CPLD_B}) - cpld_version_dict.update({'CPLD_C': CPLD_C}) - cpld_version_dict.update({'CPLD_1': CPLD_1}) - cpld_version_dict.update({'CPLD_2': CPLD_2}) - cpld_version_dict.update({'CPLD_3': CPLD_3}) - cpld_version_dict.update({'CPLD_4': CPLD_4}) - cpld_version_dict.update({'CPLD_FAN': FAN_CPLD}) + for cpld_name, info in self.cpld_ver_info.items(): + if info["path"] == "bmc": + #cpld_ver = self.get_from_bmc(self.cpld_ver_uri) + cpld_ver = "None" + else: + cpld_ver = self.__get_register_value(info["path"], info["offset"]) + + cpld_ver_str = "None" if cpld_ver is "None" else \ + "{}.{}".format(int(cpld_ver[2], 16), int(cpld_ver[3], 16)) + cpld_version_dict[cpld_name] = cpld_ver_str return cpld_version_dict def get_bios_version(self): - """Get BIOS version from SONiC - :returns: version string - - """ bios_version = None p = subprocess.Popen( @@ -190,17 +221,13 @@ def get_bios_version(self): bios_version = raw_data_list[0] if len( raw_data_list) == 1 else raw_data_list[-2] - return str(bios_version).strip() + return str(bios_version) def get_onie_version(self): - """Get ONiE version from SONiC - :returns: version string - - """ onie_verison = None onie_version_keys = "onie_version" - onie_config_file = open(self.onie_config_file, "r") + onie_config_file = open(self.ONIE_CFG_FILE, "r") for line in onie_config_file.readlines(): if onie_version_keys in line: onie_version_raw = line.split('=') @@ -210,10 +237,6 @@ def get_onie_version(self): return str(onie_verison) def get_pcie_version(self): - """Get PCiE version from SONiC - :returns: version dict { "PCIE_FW_LOADER": "2.5", "PCIE_FW": "D102_08" } - - """ cmd = "sudo bcmcmd 'pciephy fw version'" p = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -233,16 +256,19 @@ def get_pcie_version(self): return pcie_version def get_fpga_version(self): - """Get FPGA version from SONiC - :returns: version string - - """ version = self.__get_register_value(self.fpga_version_path, '0x00') if version is not 'None': version = "{}.{}".format( - int(version[2:][1:4], 16), int(version[2:][4:], 16)) + int(version[2:][:4], 16), int(version[2:][4:], 16)) return str(version) + def upgrade_logger(self, upgrade_list): + try: + with open(self.fw_upgrade_logger_path, 'w') as filetowrite: + json.dump(upgrade_list, filetowrite) + except Exception as e: + pass + def firmware_upgrade(self, fw_type, fw_path, fw_extra=None): """ @fw_type MANDATORY, firmware type, should be one of the strings: 'cpld', 'fpga', 'bios', 'bmc' @@ -254,97 +280,69 @@ def firmware_upgrade(self, fw_type, fw_path, fw_extra=None): value should be one of 'master' or 'slave' or 'both' """ fw_type = fw_type.lower() + upgrade_list = [] bmc_pwd = self.get_bmc_pass() if not bmc_pwd and fw_type != "fpga": - self.__update_fw_upgrade_logger( - "fw_upgrade", "fail, message=BMC credential not found") + print("Failed: BMC credential not found") return False if fw_type == 'bmc': - fw_extra_str = str(fw_extra).lower() - if fw_extra_str not in ["master", "slave", "both", "pingpong"]: - return False - - self.__update_fw_upgrade_logger( - "bmc_upgrade", "start BMC upgrade") # Copy BMC image file to BMC - last_fw_upgrade = ["BMC", fw_path, fw_extra_str, "FAILED"] - upload_file = self.upload_file_bmc(fw_path) - if not upload_file: - self.__update_fw_upgrade_logger( - "fw_upgrade", "fail, message=unable to upload BMC image to BMC") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + print("BMC Upgrade") + print("Uploading image to BMC...") + if not self.upload_to_bmc(fw_path): + print("Failed: Unable to upload BMC image to BMC") return False + print("Upload bmc image %s to BMC done" % fw_path) - filename_w_ext = os.path.basename(fw_path) - json_data = dict() + # Fill json param, "Name", "Path", "Flash" + image_name = os.path.basename(fw_path) + json_data = {} json_data["Name"] = "bmc" - json_data["Path"] = "/home/root/%s" % filename_w_ext + json_data["Path"] = "/tmp/%s" % image_name + + # Determine which flash to upgrade + fw_extra_str = str(fw_extra).lower() + current_bmc = self.get_bmc_flash() + flash_list = ["master", "slave", "both"] + if fw_extra_str not in flash_list: + if fw_extra_str != "pingpong": + print "BMC flash should be master/slave/both/pingpong" + return False - # Set flash type - current_bmc = self.get_running_bmc() - flash = fw_extra_str if fw_extra_str in [ - "master", "slave", "both"] else "both" if fw_extra_str == "pingpong": - #flash = "master" if current_bmc == "slave" else "slave" - flash = "slave" + flash = "slave" if current_bmc == "master" else "master" + else: + flash = fw_extra_str json_data["Flash"] = flash - # Install BMC - if flash == "both": - self.__update_fw_upgrade_logger( - "bmc_upgrade", "install BMC as master mode") - json_data["Flash"] = "master" - r = requests.post(self.fw_upgrade_url, json=json_data) - if r.status_code != 200 or r.json().get('status') != 'OK': - self.__update_fw_upgrade_logger( - "bmc_upgrade", "fail, message={}".format(r.json().get('messages'))) - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - return False - json_data["Flash"] = "slave" + # Send the upgrade request BMC + if not self.post_to_bmc(self.fw_upgrade_uri, json_data): + print "Failed to upgrade BMC %s flash" % flash + return False - self.__update_fw_upgrade_logger( - "bmc_upgrade", "install BMC as %s mode" % json_data["Flash"]) - r = requests.post(self.fw_upgrade_url, json=json_data) - if r.status_code == 200 and r.json().get('status') == 'OK': - if fw_extra_str == "pingpong": - flash = "master" if current_bmc == "slave" else "slave" - self.__update_fw_upgrade_logger( - "bmc_upgrade", "switch to boot from %s" % flash) - self.set_bmc_boot_flash(flash) - self.__update_fw_upgrade_logger("bmc_upgrade", "reboot BMC") - if not self.reboot_bmc(): + # Change boot flash if required + if current_bmc != flash: + # Set desired boot flash + print("Current BMC boot flash %s, user requested %s" % (current_bmc, flash)) + json_data = {} + json_data["Flash"] = flash + if not self.post_to_bmc(self.bmc_nextboot_uri, json_data): + print "Failed to set BMC next boot to %s" % flash return False - last_fw_upgrade[3] = "DONE" - else: - self.__update_fw_upgrade_logger( - "bmc_upgrade", "fail, message={}".format(r.json().get('messages'))) - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + + # Reboot BMC + print("Upgrade BMC %s done, reboot it" % fw_extra_str) + if not self.post_to_bmc(self.bmc_reboot_uri, {}): + print "Failed to reboot BMC after upgrade" return False - self.__update_fw_upgrade_logger( - "bmc_upgrade", "done") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + print("Upgrade BMC %s full process done" % fw_extra_str) return True - elif fw_type == 'fpga': - last_fw_upgrade = ["FPGA", fw_path, None, "FAILED"] - self.__update_fw_upgrade_logger( - "fpga_upgrade", "start FPGA upgrade") - - if not os.path.isfile(fw_path): - self.__update_fw_upgrade_logger( - "fpga_upgrade", "fail, message=FPGA image not found %s" % fw_path) - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - return False - + print("FPGA Upgrade") command = 'fpga_prog ' + fw_path - print("Running command : %s" % command) + print("Running command : ", command) process = subprocess.Popen( command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -352,177 +350,42 @@ def firmware_upgrade(self, fw_type, fw_path, fw_extra=None): output = process.stdout.readline() if output == '' and process.poll() is not None: break + if output: + print(output.strip()) - rc = process.returncode - if rc != 0: - self.__update_fw_upgrade_logger( - "fw_upgrade", "fail, message=unable to install FPGA") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - return False - - self.__update_fw_upgrade_logger("fpga_upgrade", "done") - last_fw_upgrade[3] = "DONE" - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - self.firmware_refresh(["FPGA"], None, None) - return True - - elif 'cpld' in fw_type: - self.__update_fw_upgrade_logger( - "cpld_upgrade", "start CPLD upgrade") - # Check input - fw_extra_str = str(fw_extra).upper() - if ":" in fw_path and ":" in fw_extra_str: - fw_path_list = fw_path.split(":") - fw_extra_str_list = fw_extra_str.split(":") + if process.returncode == 0: + rc = self.__fpga_pci_rescan() + if rc != 0: + print("Failed: Unable to load new FPGA firmware") + return False else: - fw_path_list = [fw_path] - fw_extra_str_list = [fw_extra_str] - - if len(fw_path_list) != len(fw_extra_str_list): - self.__update_fw_upgrade_logger( - "cpld_upgrade", "fail, message=invalid input") + print("Failed: Invalid fpga image") return False - data_list = list(zip(fw_path_list, fw_extra_str_list)) - refresh_img_path = None - cpld_result_list = ["FAILED" for i in range( - 0, len(fw_extra_str_list))] - last_fw_upgrade = ["CPLD", ":".join( - fw_path_list), ":".join(fw_extra_str_list), ":".join(cpld_result_list)] - for i in range(0, len(data_list)): - data = data_list[i] - fw_path = data[0] - fw_extra_str = data[1] - - # Set fw_extra - fw_extra_str = { - "TOP_LC_CPLD": "top_lc", - "BOT_LC_CPLD": "bottom_lc", - "FAN_CPLD": "fan", - "CPU_CPLD": "cpu", - "BASE_CPLD": "base", - "COMBO_CPLD": "combo", - "SW_CPLD1": "switch", - "SW_CPLD2": "switch", - "REFRESH_CPLD": "refresh" - }.get(fw_extra_str, None) - - if fw_extra_str == "refresh": - refresh_img_path = fw_path - del cpld_result_list[i] - del fw_extra_str_list[i] - continue - - if fw_extra_str is None: - self.__update_fw_upgrade_logger( - "cpld_upgrade", "fail, message=invalid extra information string") - continue - - # Uploading image to BMC - self.__update_fw_upgrade_logger( - "cpld_upgrade", "start %s upgrade" % data[1]) - upload_file = self.upload_file_bmc(fw_path) - if not upload_file: - self.__update_fw_upgrade_logger( - "cpld_upgrade", "fail, message=unable to upload BMC image to BMC") - continue - - filename_w_ext = os.path.basename(fw_path) - json_data = dict() - json_data["Path"] = "/home/root/%s" % filename_w_ext - json_data["Name"] = "cpld" - - # Call BMC api to install cpld image - print("Installing...") - r = requests.post(self.fw_upgrade_url, json=json_data) - if r.status_code != 200 or r.json().get('status') != 'OK': - self.__update_fw_upgrade_logger( - "cpld_upgrade", "fail, message={}".format(r.json().get('messages'))) - continue - - cpld_result_list[i] = "DONE" - self.__update_fw_upgrade_logger( - "cpld_upgrade", "%s upgrade done" % data[1]) - last_fw_upgrade[3] = ":".join(cpld_result_list) - self.__update_fw_upgrade_logger( - "cpld_upgrade", "done") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - - # Refresh CPLD - refresh_img_str_list = [] - for fw_extra in fw_extra_str_list: - if "BASE_CPLD" in fw_extra or "FAN_CPLD" in fw_extra: - refresh_img_str_list.append(refresh_img_path) - else: - refresh_img_str_list.append("None") - self.firmware_refresh(None, fw_extra_str_list, - ":".join(refresh_img_str_list)) - + print("Done") return True - elif 'bios' in fw_type: - fw_extra_str = str(fw_extra).lower() - if fw_extra_str not in ["master", "slave", "both"]: - return False + print("BIOS Upgrade") - self.__update_fw_upgrade_logger( - "bios_upgrade", "start BIOS upgrade") - last_fw_upgrade = ["BIOS", fw_path, None, "FAILED"] fw_extra_str = str(fw_extra).lower() - flash = fw_extra_str.lower() - - if not os.path.exists(fw_path): - self.__update_fw_upgrade_logger( - "bios_upgrade", "fail, message=image not found") - return False + flash = fw_extra_str if fw_extra_str in ["master", "slave"] else "master" - upload_file = self.upload_file_bmc(fw_path) - if not upload_file: - self.__update_fw_upgrade_logger( - "bios_upgrade", "fail, message=unable to upload image to BMC") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + print("Uploading BIOS image %s to BMC..." % fw_path) + if not self.upload_to_bmc(fw_path): + print("Failed to upload %s to bmc" % fw_path) return False - # json_data = dict() - # json_data["Command"] = "/usr/bin/ipmitool -b 1 -t 0x2c raw 0x2e 0xdf 0x57 0x01 0x00 0x01" - # r = requests.post(self.bmc_raw_command_url, json=json_data) - # if r.status_code != 200: - # self.__update_fw_upgrade_logger( - # "bios_upgrade", "fail, message=unable to set state") - # self.__update_fw_upgrade_logger( - # "last_upgrade_result", str(last_fw_upgrade)) - # return False - - filename_w_ext = os.path.basename(fw_path) - json_data = dict() - json_data["Path"] = "/home/root/%s" % filename_w_ext + image_name = os.path.basename(fw_path) + json_data = {} json_data["Name"] = "bios" + json_data["Path"] = "/tmp/%s" % image_name json_data["Flash"] = flash - print("Installing...") - r = requests.post(self.fw_upgrade_url, json=json_data) - if r.status_code != 200 or r.json().get('status') != 'OK': - self.__update_fw_upgrade_logger( - "bios_upgrade", "fail, message={}".format(r.json().get('messages'))) - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + if not self.post_to_bmc(self.fw_upgrade_uri, json_data): + print "Failed to upgrade %s BIOS" % flash return False - last_fw_upgrade[3] = "DONE" - self.__update_fw_upgrade_logger( - "bios_upgrade", "done") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - else: - self.__update_fw_upgrade_logger( - "fw_upgrade", "fail, message=invalid firmware type") - return False - - return True + return True def get_last_upgrade_result(self): """ @@ -744,57 +607,43 @@ def firmware_refresh(self, fpga_list, cpld_list, fw_extra=None): self.firmware_refresh(None, ["FAN_CPLD", "LC1_CPLD", "BASE_CPLD"], "/tmp/fw/fan_refresh.vme:none:/tmp/fw/base_refresh.vme") """ - self.__update_fw_upgrade_logger( - "fw_refresh", "start firmware refresh") - - cpld_list = [x.upper() for x in cpld_list] if cpld_list else [] - fpga_list = [x.upper() for x in fpga_list] if fpga_list else [] - refresh_list = cpld_list + fpga_list - fw_path_list = str(fw_extra).split(':') - refresh_img_list = ["none" for i in range(len(refresh_list))] - - if len(refresh_list) == 0 : - self.__update_fw_upgrade_logger( - "fw_refresh", "fail, message=Invalid input") - return False - - for idx in range(0, len(refresh_list)): - if refresh_list[idx] in ["FAN_CPLD", "BASE_CPLD"]: - if not self.upload_file_bmc(fw_path_list[idx]): - self.__update_fw_upgrade_logger( - "cpld_refresh", "fail, message=Unable to upload refresh image to BMC") - return False - refresh_img_list[idx] = "/home/root/%s" % os.path.basename( - fw_path_list[idx]) + fw_names = [] + fw_files = [] + # FPGA list may contain FPGA and BIOS + if fpga_list: + for name in fpga_list: + fw_names.append(name) + fw_files.append("/tmp/none") + + if cpld_list: + for name in cpld_list: + fw_names.append(name) + + if fw_extra: + for fpath in fw_extra: + if fpath == "none": + continue - json_data = dict() - json_data["Paths"] = refresh_img_list - json_data["Names"] = refresh_list - r = requests.post(self.fw_refresh_url, json=json_data) - if r.status_code != 200 or r.json().get('status') != 'OK': - self.__update_fw_upgrade_logger( - "cpld_refreshfw", "fail, message={}".format(r.json().get('messages'))) + fname = os.path.basename(fpath) + bmc_fpath = "/tmp/%s" % fname + fw_files.append(bmc_fpath) + + if os.path.exists(fpath) and os.path.isfile(fpath): + # upload refresh file to bmc + if not self.upload_to_bmc(fpath): + return False + + data = {} + data["Names"] = fw_names + data["Paths"] = fw_files + #j = json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + if not self.post_to_bmc(self.fw_refresh_uri, data): + print("Failed to refresh firmware") return False - self.__update_fw_upgrade_logger("fw_refresh", "done") - return True - def get_running_bmc(self): - """ - Get booting flash of running BMC. - @return a string, "master" or "slave" - """ - running_bmc = "master" - running_bmc_key = "Flash" - bmc_info_req = requests.get( - self.bmc_info_url, timeout=self.api_time_out) - if bmc_info_req.status_code == 200: - bmc_info_json = bmc_info_req.json() - bmc_info = bmc_info_json.get('data') - running_bmc = bmc_info.get(running_bmc_key) - return str(running_bmc).lower() - def set_bmc_boot_flash(self, flash): """ Set booting flash of BMC @@ -803,8 +652,8 @@ def set_bmc_boot_flash(self, flash): if flash.lower() not in ["master", "slave"]: return False json_data = dict() - json_data["Flash"] = flash - r = requests.post(self.bmc_next_boot, json=json_data) + json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;bmc_reboot %s" % flash + r = requests.post(self.bmc_raw_command_url, json=json_data) if r.status_code != 200: return False return True @@ -813,13 +662,10 @@ def reboot_bmc(self): """ Reboot BMC """ - try: - r = requests.post(self.bmc_reboot_url) - if r.status_code != 200: - return False - except Exception as e: - if "Connection aborted." in e.message[0]: - return True + json_data = dict() + json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;bmc_reboot reboot" + r = requests.post(self.bmc_raw_command_url, json=json_data) + if r.status_code != 200: return False return True @@ -828,39 +674,17 @@ def get_current_bios(self): # Get booting bios image of current running host OS # @return a string, "master" or "slave" """ - bios_boot_info = requests.get( - self.bios_boot_info, timeout=self.api_time_out) - if bios_boot_info.status_code == 200: - bios_boot_info_json = bios_boot_info.json() - bios_boot_info_data = bios_boot_info_json.get('data') - bios_boot = bios_boot_info_data.get("Flash") - return str(bios_boot) - - def get_bios_next_boot(self): - """ - # Get booting bios image of next booting host OS - # @return a string, "master" or "slave" - """ - bios_next_boot = "master" - bios_next_boot_info = requests.get( - self.bios_next_boot, timeout=self.api_time_out) - if bios_next_boot_info.status_code == 200: - bios_next_boot_info_json = bios_next_boot_info.json() - bios_next_boot_info_data = bios_next_boot_info_json.get('data') - bios_next_boot = bios_next_boot_info_data.get("Flash") - return str(bios_next_boot) - - def set_bios_next_boot(self, flash): - """ - # Set booting bios image of next booting host OS - # @return a string, "master" or "slave" - """ - if str(flash).lower() not in ['master', 'slave']: - return False - json_data = dict() - json_data["Flash"] = str(flash).lower() - r = requests.post(self.bios_next_boot, json=json_data) - if r.status_code != 200: - return False - return True + json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;come_boot_info" + r = requests.post(self.bmc_raw_command_url, json=json_data) + try: + cpu_boot_info_list = r.json().get('result') + for cpu_boot_info_raw in cpu_boot_info_list: + if "COMe CPU boots from BIOS" in cpu_boot_info_raw: + bios_image = "master" if "master "in cpu_boot_info_raw.lower( + ) else "slave" + return bios_image + raise Exception( + "Error: Unable to detect current running bios image") + except Exception as e: + raise Exception(e) diff --git a/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/psuutil.py b/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/psuutil.py index b36cc0510918..13d98a745827 100644 --- a/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/psuutil.py +++ b/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/psuutil.py @@ -1,47 +1,63 @@ -#!/usr/bin/env python +#!/usr/bin/python -__author__ = 'Wirut G.' -__license__ = "GPL" -__version__ = "0.2.0" -__status__ = "Development" +############################################################################### +# +## PSU utility. +# +## Copyright (C) Alibaba, INC. +# +################################################################################ import requests import re +import json try: from sonic_psu.psu_base import PsuBase except ImportError as e: raise ImportError(str(e) + "- required module not found") -NUM_PSU = 2 - class PsuUtil(PsuBase): - """Platform-specific PSUutil class""" + BMC_REQ_BASE_URI = "http://240.1.1.1:8080/api" def __init__(self): PsuBase.__init__(self) + self.psu_info_uri = "/".join([self.BMC_REQ_BASE_URI, "psu/info"]) + self.psu_num_uri = "/".join([self.BMC_REQ_BASE_URI, "psu/number"]) - self.psu_info_url = "http://240.1.1.1:8080/api/psu/info" - self.all_psu_dict = None + def _get_psu_info(self): + resp = requests.get(self.psu_info_uri) + if not resp: + return False - def request_data(self, url): - try: - r = requests.get(url) - data = r.json() - except Exception as e: - return {} - return data + psu_json = resp.json() + if not psu_json or not "data" in psu_json: + return False + + self.psu_info = psu_json["data"] + + return True def get_num_psus(self): """ Retrieves the number of PSUs available on the device :return: An integer, the number of PSUs available on the device """ + resp = requests.get(self.psu_num_uri) + if not resp: + return -1 - all_psu_dict = self.get_all() + psu_nr_json = resp.json() + if not psu_nr_json or "data" not in psu_nr_json: + return -1 - return all_psu_dict.get('Number', NUM_PSU) + try: + nr_psu = psu_nr_json["data"]["Number"] + except Exception as e: + nr_psu = -1 + + return nr_psu def get_psu_status(self, index): """ @@ -51,11 +67,28 @@ def get_psu_status(self, index): :return: Boolean, True if PSU is operating properly, False if PSU is faulty """ - all_psu_dict = self.get_all() - psu_key = 'PSU{}'.format(index) - psu_info = all_psu_dict.get(psu_key, {}) + # init data + psu_key = "PSU" + str(index) + psu_status_key = "Power Status" + psu_power_status = False + + try: + # Request and validate sensor's information + self.fru_status_list, self.psu_info_list = self.request_data() + + # Get PSU power status. + for fru_status in self.fru_status_list: + is_psu = fru_status.get(psu_key) + psu_status = str(fru_status.get(psu_status_key)).strip() + + if is_psu is not None and psu_status == "OK": + psu_power_status = True + + except: + print("Error: Unable to access PSU power status") + return False - return psu_info.get('PowerStatus', False) + return psu_power_status def get_psu_presence(self, index): """ @@ -64,11 +97,29 @@ def get_psu_presence(self, index): :param index: An integer, 1-based index of the PSU of which to query status :return: Boolean, True if PSU is plugged, False if not """ - all_psu_dict = self.get_all() - psu_key = 'PSU{}'.format(index) - psu_info = all_psu_dict.get(psu_key, {}) - return psu_info.get('Present', False) + # Init data + psu_key = "PSU" + str(index) + psu_presence_key = "Present" + psu_presence_status = False + + try: + # Request and validate sensor's information. + self.fru_status_list, self.psu_info_list = self.request_data() + + # Get PSU present status. + for fru_status in self.fru_status_list: + is_psu = fru_status.get(psu_key) + psu_status = str(fru_status.get(psu_presence_key)).strip() + + if is_psu is not None and psu_status == "Present": + psu_presence_status = True + + except: + print("Error: Unable to access PSU presence status") + return False + + return psu_presence_status def get_psu_sn(self, index): """ @@ -77,12 +128,25 @@ def get_psu_sn(self, index): :param index: An integer, 1-based index of the PSU. :return: Serial number """ + serial_number = "N/A" + psu_key = "PSU" + str(index) + " FRU" + psu_sn_key = "Serial Number" - all_psu_dict = self.get_all() - psu_key = 'PSU{}'.format(index) - psu_info = all_psu_dict.get(psu_key, {}) + try: + # Request and validate sensor's information. + self.fru_status_list, self.psu_info_list = self.request_data() - return psu_info.get('SN', False) + # Get PSU fru info. + for psu_fru in self.psu_info_list: + psu_sn = str(psu_fru.get(psu_sn_key)).strip() + if psu_fru.get(psu_key) is not None: + serial_number = psu_sn if psu_sn.strip() != "" else "N/A" + break + + except: + return "N/A" + + return serial_number def get_psu_pn(self, index): """ @@ -91,12 +155,25 @@ def get_psu_pn(self, index): :param index: An integer, 1-based index of the PSU. :return: Product name """ + product_name = "N/A" + psu_key = "PSU" + str(index) + " FRU" + psu_pn_key = "Product Name" + + try: + # Request and validate sensor's information + self.fru_status_list, self.psu_info_list = self.request_data() + + # Get PSU fru info. + for psu_fru in self.psu_info_list: + psu_pn = str(psu_fru.get(psu_pn_key)).strip() + if psu_fru.get(psu_key) is not None: + product_name = psu_pn if psu_pn.strip() != "" else "N/A" + break + + except: + return "N/A" - all_psu_dict = self.get_all() - psu_key = 'PSU{}'.format(index) - psu_info = all_psu_dict.get(psu_key, {}) - - return psu_info.get('PN', False) + return product_name def get_all(self): """ @@ -107,35 +184,131 @@ def get_all(self): PN, conditional, if PRESENT is True, PN of the PSU, string SN, conditional, if PRESENT is True, SN of the PSU, string """ +#{ +# "Number": 4, +# "PSU1": { +# "AirFlow": "N/A", +# "FanSpeed": { +# "Max": 30000, +# "Min": 1000, +# "Unit": "RPM", +# "Value": -99999 +# }, +# "Inputs": { +# "Current": { +# "HighAlarm": 7.0, +# "LowAlarm": 0.0, +# "Unit": "A", +# "Value": -99999.0 +# }, +# "Power": { +# "HighAlarm": 1220.0, +# "LowAlarm": -1, +# "Unit": "W", +# "Value": -99999.0 +# }, +# "Status": false, +# "Type": "Unknown", +# "Voltage": { +# "HighAlarm": 264.0, +# "LowAlarm": 90.0, +# "Unit": "V", +# "Value": -99999.0 +# } +# }, +# "Outputs": { +# "Current": { +# "HighAlarm": 90.0, +# "LowAlarm": 0.0, +# "Unit": "A", +# "Value": -99999.0 +# }, +# "Power": { +# "HighAlarm": 1100.0, +# "LowAlarm": -1, +# "Unit": "W", +# "Value": -99999.0 +# }, +# "Status": false, +# "Type": "Unknown", +# "Voltage": { +# "HighAlarm": 13.2, +# "LowAlarm": 10.8, +# "Unit": "V", +# "Value": -99999.0 +# } +# }, +# "PN": "", +# "SN": "JHZD1849000585", +# "Temperature": { +# "Max": 70.0, +# "Min": 60.0, +# "Unit": "C", +# "Value": -99999.0 +# } +# } +#} + psu_info = {} + if not self._get_psu_info(): + return psu_info + + #j = json.dumps(self.psu_info, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + + if "Number" not in self.psu_info: + return psu_info + + psu_nr = self.psu_info["Number"] + psu_info["Number"] = psu_nr + for idx in range(1, psu_nr+1): + psu_name = "PSU%d" % idx + if not psu_name in self.psu_info: + print("%s not in self.psu_info" % psu_name) + continue + + pi = self.psu_info[psu_name] + pinfo = {} + try: + pinfo["Present"] = True if pi["Present"] == "yes" else False + pinfo["AirFlow"] = pi["AirFlow"] + pinfo["PN"] = pi["PN"] + pinfo["SN"] = pi["SN"] + except Exception as e: + print("%s not in self.psu_info, exception 1" % psu_name) + continue + + if "Inputs" in pi: + pii = pi["Inputs"] + if "Status" in pii: + try: + pinfo["InputStatus"] = pii["Status"] + pinfo["InputType"] = pii["Type"] + except Exception as e: + pinfo["InputType"] = "N/AA" + + if "Outputs" in pi: + pio = pi["Outputs"] + if "Status" in pio: + try: + pinfo["OutputStatus"] = pio["Status"] + except Exception as e: + pinfo["OutputStatus"] = False + + if "FanSpeed" in pi: + pif = pi["FanSpeed"] + try: + pinfo["Speed"] = pif["Value"] + pinfo["LowThd"] = pif["Min"] + pinfo["HighThd"] = pif["Max"] + except Exception as e: + pinfo["Speed"] = 0 + pinfo["LowThd"] = 0 + pinfo["HighThd"] = 0 + + psu_info[psu_name] = pinfo + + #j = json.dumps(psu_info, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + + return psu_info - if not self.all_psu_dict: - all_psu_dict = dict() - - psu_info_req = self.request_data(self.psu_info_url) - psu_info_data = psu_info_req.get('data', {}) - all_psu_dict["Number"] = psu_info_data.get('Number', NUM_PSU) - - for psu_idx in range(1, all_psu_dict["Number"] + 1): - psu_key = 'PSU{}'.format(str(psu_idx)) - psu_info = psu_info_data.get(psu_key, {}) - psu_input_info = psu_info.get('Inputs', {}) - psu_output_info = psu_info.get('Outputs', {}) - - psu_info_dict = dict() - psu_info_dict["InputType"] = psu_input_info.get("Type", "N/A") - psu_info_dict["InputStatus"] = True if psu_input_info.get( - "Status") else False - psu_info_dict["OutputStatus"] = True if psu_output_info.get( - "Status") else False - psu_info_dict["PowerStatus"] = ( - psu_info_dict["InputStatus"] and psu_info_dict["OutputStatus"]) - psu_info_dict["PN"] = psu_info.get("PN", "N/A") - psu_info_dict["SN"] = psu_info.get("SN", "N/A") - psu_info_dict["Present"] = True if psu_info.get("Present") == 'yes' else False - psu_info_dict["AirFlow"] = psu_info.get("AirFlow", "N/A") - - all_psu_dict[psu_key] = psu_info_dict - - self.all_psu_dict = all_psu_dict - - return self.all_psu_dict diff --git a/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/sensorutil.py b/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/sensorutil.py index efed1e850306..4b5a7e3d4519 100644 --- a/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/sensorutil.py +++ b/device/alibaba/x86_64-alibaba_as13-32h-cl-r0/plugins/sensorutil.py @@ -1,206 +1,115 @@ -#!/usr/bin/env python +#!/usr/bin/python + +############################################################################### +# +### Sensor utility. +# +### Copyright (C) Alibaba, INC. +# +################################################################################# -__author__ = 'Wirut G.' -__license__ = "GPL" -__version__ = "0.2.0" -__status__ = "Development" import requests +import json class SensorUtil(): - """Platform-specific SensorUtil class""" + BMC_REQ_BASE_URI = "http://240.1.1.1:8080/api" def __init__(self): - self.sensor_info_url = "http://240.1.1.1:8080/api/sensor/info" - self.all_sensor_dict = None - - def request_data(self, url): - try: - r = requests.get(url) - data = r.json() - except Exception as e: - return {} - return data - - def input_type_selector(self, unit): - # Set input type. - return { - "C": "temperature", - "V": "voltage", - "RPM": "RPM", - "A": "amp", - "W": "power" - }.get(unit, unit) - - def input_name_selector(self, raw_sensor_name): - - sensor_name_list = raw_sensor_name.split('_') - sensor_name = sensor_name_list[0] - input_name = '_'.join(sensor_name_list[1:]) - - if sensor_name_list[0] in ["TOP", "BOTTOM"]: - sensor_name = '_'.join(sensor_name_list[0:2]) - input_name = '_'.join(sensor_name_list[2:]) - - return str(sensor_name).upper(), str(input_name).upper() - - def get_num_sensors(self): - """ - Get the number of sensors - :return: int num_sensors - """ - - all_sensor_dict = self.get_all() - - return len(all_sensor_dict) - - def get_sensor_input_num(self, index): - """ - Get the number of the input items of the specified sensor - :return: int input_num - """ - - all_sensor_dict = self.get_all() - ss_keys = all_sensor_dict.keys()[index] - sensor_info = all_sensor_dict.get(ss_keys, {}) - ss_if_keys = sensor_info.keys() - - return len(ss_if_keys) - - def get_sensor_name(self, index): - """ - Get the device name of the specified sensor. - for example "coretemp-isa-0000" - :return: str sensor_name - """ - all_sensor_dict = self.get_all() - sensor_name = all_sensor_dict.keys()[index] - - return sensor_name - - def get_sensor_input_name(self, sensor_index, input_index): - """ - Get the input item name of the specified input item of the - specified sensor index, for example "Physical id 0" - :return: str sensor_input_name - """ - - all_sensor_dict = self.get_all() + self.sensor_info_uri = "/".join([self.BMC_REQ_BASE_URI, "sensor/info"]) + self.sensor_info = None - ss_keys = all_sensor_dict.keys()[sensor_index] - sensor_info = all_sensor_dict.get(ss_keys, {}) - ss_if_keys = sensor_info.keys()[input_index] + def _get_sensor_info(self): + resp = requests.get(self.sensor_info_uri) + if not resp: + return False - return ss_if_keys + sensor_json = resp.json() + if not sensor_json or not "data" in sensor_json: + return False - def get_sensor_input_type(self, sensor_index, input_index): - """ - Get the item type of the specified input item of the specified sensor index, - The return value should among "valtage","temperature" - :return: str sensor_input_type - """ + self.sensor_info = sensor_json["data"] - all_sensor_dict = self.get_all() + return True - ss_keys = all_sensor_dict.keys()[sensor_index] - sensor_info = all_sensor_dict.get(ss_keys, {}) + def get_sys_airflow(self): + sys_air_flow = "Unknown" - ss_if_keys = sensor_info.keys()[input_index] - sensor_input_info = sensor_info.get(ss_if_keys, {}) + sys_pn = sys_pn_data[0][1] + if "R1240-F0001" in sys_pn: + sys_air_flow = "FTOB" + elif"R1240-F0002" in sys_pn: + sys_air_flow = "BTOF" - sensor_input_type = sensor_input_info.get('Type', "N/A") - return sensor_input_type + return sys_air_flow - def get_sensor_input_value(self, sensor_index, input_index): - """ - Get the current value of the input item, the unit is "V" or "C" - :return: float sensor_input_value - """ + def _get_type(self, unit_str): + unit2type = {"C": "temperature", "A": "amp", "V": "voltage", + "RPM": "RPM", "W": "power"} - all_sensor_dict = self.get_all() + if unit_str in unit2type: + return unit2type[unit_str] + return None - ss_keys = all_sensor_dict.keys()[sensor_index] - sensor_info = all_sensor_dict.get(ss_keys, {}) - - ss_if_keys = sensor_info.keys()[input_index] - sensor_input_info = sensor_info.get(ss_if_keys, {}) - - sensor_input_value = sensor_input_info.get('Value', 0.0) - return sensor_input_value - - def get_sensor_input_low_threshold(self, sensor_index, input_index): - """ - Get the low threshold of the value, - the status of this item is not ok if the current value high_threshold - :return: float sensor_input_high_threshold - """ - all_sensor_dict = self.get_all() - - ss_keys = all_sensor_dict.keys()[sensor_index] - sensor_info = all_sensor_dict.get(ss_keys, {}) - - ss_if_keys = sensor_info.keys()[input_index] - sensor_input_info = sensor_info.get(ss_if_keys, {}) - - sensor_input_high_threshold = sensor_input_info.get('HighThd', 0.0) - return sensor_input_high_threshold + def get_num_sensors(self): + sensor_dict = self.get_all() + sum = 0 + for sensor_name, sensor_obj in sensor_dict.items(): + if cmp(sensor_name, 'Number') == 0: + continue + sum += len(sensor_obj.keys()) + return sum def get_all(self): - """ - Get all information of system sensors, returns JSON objects in python 'DICT'. - SensorName1, SensorName2, ... optional, string - SensorInput1, SensorInput2, ... optional, string - Type, mandatory in SensorInput$INDEX, should be on of { "temperature", "voltage", "power", "amp", "RPM" } - Value, mandatory in SensorInput$INDEX, float , real value - LowThd, mandatory in SensorInput$INDEX, float , lower bound of value - HighThd, mandatory in SensorInput$INDEX, float , upper bound of value - Return python 'dict' objects, example: - """ - - if not self.all_sensor_dict: - all_sensor_dict = dict() - - sensor_info_req = self.request_data(self.sensor_info_url) - sensor_info_data = sensor_info_req.get('data', {}) - - for raw_ss_name, sensor_info in sensor_info_data.items(): - - sensor_name, input_name = self.input_name_selector(raw_ss_name) - sensor_dict = all_sensor_dict.get(sensor_name, {}) - new_sensor_dict = dict() - new_sensor_dict["Type"] = self.input_type_selector( - sensor_info.get('Unit', 'N/A')) - new_sensor_dict["Value"] = float(sensor_info.get('Value', 0.0)) - new_sensor_dict["HighThd"] = float(sensor_info.get('Max', 0.0)) - new_sensor_dict["LowThd"] = float(sensor_info.get('Min', 0.0)) - - if sensor_dict == {}: - all_sensor_dict[sensor_name] = dict() - - input_name = input_name if input_name != '' else new_sensor_dict["Type"].upper( - ) - sensor_dict[input_name] = new_sensor_dict - all_sensor_dict[sensor_name].update(sensor_dict) - - self.all_sensor_dict = all_sensor_dict - - return self.all_sensor_dict + sensor_info = {} + + if not self._get_sensor_info(): + return sensor_info + + sname_temp_cl = ["Cpu", "Inlet", "Switch"] + sname_temp_rj = ["CPU_TEMP", "INLET_TEMP", "SWITCH_TEMP"] + for si_name, si_val in self.sensor_info.items(): + if si_name.startswith("PSU"): + sname = si_name.split("_")[0] + if si_name.find("Temperature") != -1: + new_si_name = "%s_TEMP" % sname + si_name = new_si_name + elif si_name in sname_temp_cl: + sname = "TEMPERATURE" + new_si_name = "%s_temp" % si_name + si_name = new_si_name.upper() + elif si_name in sname_temp_rj: + sname = "TEMPERATURE" + elif si_name.startswith("CPU"): + sname = "CPU" + elif si_name.startswith("FAN"): + sname = "FAN" + elif si_name.startswith("Switch") or \ + si_name.startswith("SWITCH") or \ + si_name.find("_LC_") != -1: + sname = "SWITCH" + elif si_name.startswith("SYS") or \ + si_name.startswith("Baseboard"): + sname = "SYSTEM" + else: + sname = "OTHER" + + si_info = {} + si_info["LowThd"] = si_val["Min"] + si_info["HighThd"] = si_val["Max"] + si_info["Value"] = si_val["Value"] + type = self._get_type(si_val["Unit"]) + if not type: + continue + si_info["Type"] = type + + if sname not in sensor_info: + sensor_info[sname] = {} + + sensor_info[sname][si_name] = si_info + + #j = json.dumps(self.sensor_info, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + + return sensor_info diff --git a/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/fanutil.py b/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/fanutil.py index 791fc35ca4db..c0b58b89928d 100644 --- a/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/fanutil.py +++ b/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/fanutil.py @@ -1,117 +1,51 @@ -#!/usr/bin/env python - -__author__ = 'Wirut G.' -__license__ = "GPL" -__version__ = "0.2.0" -__status__ = "Development" +#!/usr/bin/python import requests import re - -NUM_FAN_TRAY = 4 -NUM_ROTER = 2 +import json class FanUtil(): - """Platform-specific FanUtil class""" + BMC_REQ_BASE_URI = "http://240.1.1.1:8080/api" + ROTOR_PER_FAN = 2 def __init__(self): - self.fan_info_url = "http://240.1.1.1:8080/api/fan/info" - self.all_fan_dict = None - - def request_data(self, url): - try: - r = requests.get(url) - data = r.json() - except Exception as e: - return {} - return data - - def get_num_fans(self): - """ - Get the number of fans - :return: int num_fans - """ - all_fan_dict = self.get_all() - num_fan_tray = all_fan_dict.get('Number', NUM_FAN_TRAY) - - return num_fan_tray * NUM_ROTER - - def get_fan_speed(self, fan_name): - """ - Get the current speed of the fan, the unit is "RPM" - :return: int fan_speed - """ - - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) - - return fan_info.get('Speed', 0) - - def get_fan_low_threshold(self, fan_name): - """ - Get the low speed threshold of the fan. - if the current speed < low speed threshold, - the status of the fan is not ok. - :return: int fan_low_threshold - """ - - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) - - return fan_info.get('LowThd', 0) + self.fan_info_uri = "/".join([self.BMC_REQ_BASE_URI, "fan/info"]) + self.fan_num_uri = "/".join([self.BMC_REQ_BASE_URI, "fan/number"]) - def get_fan_high_threshold(self, fan_name): - """ - Get the hight speed threshold of the fan, - if the current speed > high speed threshold, - the status of the fan is not ok - :return: int fan_high_threshold - """ - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) + def _get_fan_info(self): + resp = requests.get(self.fan_info_uri) + if not resp: + return False - return fan_info.get('HighThd', 0) + fan_json = resp.json() + if not fan_json or not "data" in fan_json: + return False - def get_fan_pn(self, fan_name): - """ - Get the product name of the fan - :return: str fan_pn - """ + self.fan_info = fan_json["data"] - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) + return True - return fan_info.get('PN', 'N/A') - - def get_fan_sn(self, fan_name): - """ - Get the serial number of the fan - :return: str fan_sn + def get_num_fans(self): """ - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) - - return fan_info.get('SN', 'N/A') + Get total fan number - def get_fans_name_list(self): + @return number of fan, -1 for failure """ - Get list of fan name. - :return: list fan_names - """ - fan_names = [] + resp = requests.get(self.fan_num_uri) + if not resp: + return -1 - # Get the number of fans - n_fan = self.get_num_fans() + fan_nr_json = resp.json() + if not fan_nr_json or "data" not in fan_nr_json: + return -1 - # Set fan name and add to the list. - for x in range(1, n_fan + 1): - f_index = int(round(float(x)/2)) - pos = 1 if x % 2 else 2 - fan_name = 'FAN{}_{}'.format(f_index, pos) - fan_names.append(fan_name) + try: + nr_fan = fan_nr_json["data"]["Number"] + except Exception as e: + nr_fan = -1 - return fan_names + return nr_fan def get_all(self): """ @@ -126,41 +60,55 @@ def get_all(self): PN, conditional, if PRESENT is True, PN of the FAN, string SN, conditional, if PRESENT is True, SN of the FAN, string) """ + fan_info = {} + if not self._get_fan_info(): + return fan_info + + if "Number" not in self.fan_info: + return fan_info + + fan_nr = self.fan_info["Number"] + for fan_idx in range(1, fan_nr+1): + fan_name = "FAN%d" % fan_idx + if not fan_name in self.fan_info: + print("%s not in self.fan_info" % fan_name) + continue + fi = self.fan_info[fan_name] + if "Rotors" not in fi: + print("Rotors not in fi") + continue + rotor_nr = fi["Rotors"] + for ridx in range(1, rotor_nr+1): + sub_name = "%s_%d" % (fan_name, ridx) + rname = "Rotor%d" % ridx + sub_fan_info = {} + if rname not in fi: + print("%s not in fi" % rname) + continue + try: + sub_fan_info["Present"] = True if fi["Present"] == "yes" else False + sub_fan_info["Running"] = fi[rname]["Running"] + sub_fan_info["Speed"] = fi[rname]["Speed"] + sub_fan_info["LowThd"] = fi[rname]["SpeedMin"] + sub_fan_info["HighThd"] = fi[rname]["SpeedMax"] + sub_fan_info["PN"] = fi["PN"] + sub_fan_info["SN"] = fi["SN"] + sub_fan_info["AirFlow"] = fi["AirFlow"] + if (fi[rname]["HwAlarm"] == "no") and \ + (sub_fan_info["Speed"] != None and sub_fan_info["LowThd"] != None and sub_fan_info["Speed"] >= sub_fan_info["LowThd"]) and \ + (sub_fan_info["Speed"] != None and sub_fan_info["HighThd"] != None and sub_fan_info["Speed"] <= sub_fan_info["HighThd"]): + sub_fan_info["Status"] = True + else: + sub_fan_info["Status"] = False + + fan_info[sub_name] = sub_fan_info + except Exception as e: + print("GOT EXCEPTON: %s" % str(e)) + continue + fan_info["Number"] = fan_nr * self.ROTOR_PER_FAN + + #j = json.dumps(fan_info, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + + return fan_info - if not self.all_fan_dict: - all_fan_dict = dict() - - fan_info_req = self.request_data(self.fan_info_url) - fan_info_data = fan_info_req.get('data', {}) - all_fan_dict["Number"] = fan_info_data.get('Number', NUM_FAN_TRAY) - - for fan_idx in range(1, all_fan_dict["Number"] + 1): - num_of_roter = fan_info_data.get('Rotors', NUM_ROTER) - - for fan_pos in range(1, num_of_roter + 1): - fan_key = 'FAN{}'.format(str(fan_idx)) - roter_key = 'Rotor{}'.format(str(fan_pos)) - - fan_info = fan_info_data.get(fan_key, {}) - roter_info = fan_info.get(roter_key, {}) - - fan_info_dict = dict() - fan_info_dict["Present"] = True if fan_info.get( - "Present") == 'yes' else False - fan_info_dict["Speed"] = roter_info.get("Speed", "N/A") - fan_info_dict["Running"] = True if roter_info.get( - "Running") == 'yes' else False - fan_info_dict["HighThd"] = roter_info.get( - "SpeedMax", "N/A") - fan_info_dict["LowThd"] = roter_info.get("SpeedMin", "N/A") - fan_info_dict["Status"] = False if roter_info.get( - "HwAlarm") == 'yes' else True - fan_info_dict["PN"] = fan_info.get("PN", "N/A") - fan_info_dict["SN"] = fan_info.get("SN", "N/A") - fan_info_dict["AirFlow"] = fan_info.get("AirFlow", "N/A") - - fan_name = '{}_{}'.format(fan_key, fan_pos) - all_fan_dict[fan_name] = fan_info_dict - self.all_fan_dict = all_fan_dict - - return self.all_fan_dict diff --git a/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/fwmgrutil.py b/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/fwmgrutil.py index 8bcccba74d28..77b5d00375e1 100644 --- a/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/fwmgrutil.py +++ b/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/fwmgrutil.py @@ -1,14 +1,5 @@ -#!/usr/bin/env python -# -# fwmgrutil.py -# -# Platform-specific firmware management interface for SONiC -# - -__author__ = 'Wirut G.' -__license__ = "GPL" -__version__ = "0.2.1" -__status__ = "Development" +#!/usr/bin/python + import subprocess import requests @@ -28,33 +19,51 @@ class FwMgrUtil(FwMgrUtilBase): - - """Platform-specific FwMgrUtil class""" + BMC_REQ_BASE_URI = "http://240.1.1.1:8080/api" + ONIE_CFG_FILE = "/host/machine.conf" def __init__(self): self.platform_name = "AS1348f8h" - self.onie_config_file = "/host/machine.conf" - self.bmc_info_url = "http://240.1.1.1:8080/api/bmc/info" - self.cpld_info_url = "http://240.1.1.1:8080/api/firmware/cpldversion" - self.bmc_raw_command_url = "http://240.1.1.1:8080/api/hw/rawcmd" - self.fw_upgrade_url = "http://240.1.1.1:8080/api/firmware/upgrade" - self.fw_refresh_url = "http://240.1.1.1:8080/api/firmware/refresh" - self.bios_next_boot = "http://240.1.1.1:8080/api/firmware/biosnextboot" - self.bmc_next_boot = "http://240.1.1.1:8080/api/bmc/nextboot" - self.bmc_reboot_url = "http://240.1.1.1:8080/api/bmc/reboot" - self.bios_boot_info = "http://240.1.1.1:8080/api/misc/biosbootstatus" - self.onie_config_file = "/host/machine.conf" + self.bmc_info_uri = "/".join([self.BMC_REQ_BASE_URI, "bmc/info"]) + self.bmc_nextboot_uri = "/".join([self.BMC_REQ_BASE_URI, "bmc/nextboot"]) + self.bmc_reboot_uri = "/".join([self.BMC_REQ_BASE_URI, "bmc/reboot"]) + self.fw_upgrade_uri = "/".join([self.BMC_REQ_BASE_URI, "firmware/upgrade"]) + self.fw_refresh_uri = "/".join([self.BMC_REQ_BASE_URI, "firmware/refresh"]) + self.fw_upgrade_logger_path = "/var/log/fw_upgrade.log" - self.cpldb_version_path = "/sys/devices/platform/%s.cpldb/getreg" % self.platform_name + + self.cpld_ver_info = { + "CPLD_B": { + "path": "/sys/devices/platform/%s.cpldb/getreg" % self.platform_name, + "offset": "0xA100" + }, + "CPLD_C": { + "path": "/sys/devices/platform/%s.cpldb/getreg" % self.platform_name, + "offset": "0xA1E0" + }, + "CPLD_1": { + "path": "/sys/devices/platform/%s.switchboard/CPLD1/getreg" % self.platform_name, + "offset": "0x00" + }, + "CPLD_2": { + "path": "/sys/devices/platform/%s.switchboard/CPLD2/getreg" % self.platform_name, + "offset": "0x00" + }, + "CPLD_3": { + "path": "/sys/devices/platform/%s.switchboard/CPLD3/getreg" % self.platform_name, + "offset": "0x00" + }, + "CPLD_4": { + "path": "/sys/devices/platform/%s.switchboard/CPLD1/getreg" % self.platform_name, + "offset": "0x00" + }, + "CPLD_FAN": { + "path": "bmc", + "offset": "0x00" + } + } self.fpga_version_path = "/sys/devices/platform/%s.switchboard/FPGA/getreg" % self.platform_name - self.switchboard_cpld1_path = "/sys/devices/platform/%s.switchboard/CPLD1/getreg" % self.platform_name - self.switchboard_cpld2_path = "/sys/devices/platform/%s.switchboard/CPLD2/getreg" % self.platform_name - self.switchboard_cpld3_path = "/sys/devices/platform/%s.switchboard/CPLD3/getreg" % self.platform_name - self.switchboard_cpld4_path = "/sys/devices/platform/%s.switchboard/CPLD4/getreg" % self.platform_name self.bmc_pwd_path = "/usr/local/etc/bmcpwd" - self.cpld_name_list = ["CPU_CPLD", "COMBO_CPLD", - "SW_CPLD1", "SW_CPLD2", "TOP_LC_CPLD", "BOT_LC_CPLD"] - self.api_time_out = 300 def __get_register_value(self, path, register): cmd = "echo {1} > {0}; cat {0}".format(path, register) @@ -66,6 +75,30 @@ def __get_register_value(self, path, register): else: return raw_data.strip() + def __fpga_pci_rescan(self): + """ + An sequence to trigger FPGA to load new configuration after upgrade. + """ + fpga_pci_device_remove = '/sys/devices/pci0000:00/0000:00:1c.0/0000:09:00.0/remove' + parent_pci_device_rescan = '/sys/devices/pci0000:00/0000:00:1c.0/rescan' + cmd = 'modprobe -r switchboard_fpga' + os.system(cmd) + cmd = 'echo 1 > %s' % fpga_pci_device_remove + rc = os.system(cmd) + if rc > 0: + return rc + cmd = 'echo 0xa10a 0 > /sys/devices/platform/%s.cpldb/setreg' % self.platform_name + rc = os.system(cmd) + if rc > 0: + return rc + time.sleep(10) + cmd = 'echo 1 > %s' % parent_pci_device_rescan + rc = os.system(cmd) + if rc > 0: + return rc + os.system('modprobe switchboard_fpga') + return 0 + def __update_fw_upgrade_logger(self, header, message): if not os.path.isfile(self.fw_upgrade_logger_path): cmd = "sudo touch %s && sudo chmod +x %s" % ( @@ -76,7 +109,7 @@ def __update_fw_upgrade_logger(self, header, message): logging.basicConfig(filename=self.fw_upgrade_logger_path, filemode='a', format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s', - datefmt='%b %d %H:%M:%S', + datefmt='%H:%M:%S', level=logging.INFO) log_message = "%s : %s" % (header, message) @@ -99,27 +132,58 @@ def get_bmc_pass(self): return "".join(dec) return False + def get_from_bmc(self, uri): + resp = requests.get(uri) + if not resp: + return None + + data = resp.json() + if not data or "data" not in data or "status" not in data: + return None + + if data["status"] != "OK": + return None + + return data["data"] + def get_bmc_version(self): - """Get BMC version from SONiC - :returns: version string + bmc_ver = "N/A" + data = self.get_from_bmc(self.bmc_info_uri) + if not data or "Version" not in data: + return bmc_ver - """ - bmc_version = None - bmc_version_key = "Version" - bmc_info_req = requests.get( - self.bmc_info_url, timeout=self.api_time_out) - if bmc_info_req.status_code == 200: - bmc_info_json = bmc_info_req.json() - bmc_info = bmc_info_json.get('data') - bmc_version = bmc_info.get(bmc_version_key) - return str(bmc_version) - - def upload_file_bmc(self, fw_path): - scp_command = 'sudo scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r %s root@240.1.1.1:/home/root/' % os.path.abspath( - fw_path) + return data["Version"] + + def get_bmc_flash(self): + flash = "N/A" + data = self.get_from_bmc(self.bmc_info_uri) + if not data or "Flash" not in data: + return flash + + return data["Flash"] + + def post_to_bmc(self, uri, data): + resp = requests.post(uri, json=data) + if not resp: + print "No response" + return False + + data = resp.json() + if "status" not in data: + return False + + if data["status"] != "OK": + return False + + return True + + def upload_to_bmc(self, fw_path): + scp_command = 'sudo scp -o StrictHostKeyChecking=no -o ' \ + 'UserKnownHostsFile=/dev/null -r %s root@240.1.1.1:/tmp/' \ + % os.path.abspath(fw_path) + print scp_command child = pexpect.spawn(scp_command) - child.timeout = self.api_time_out - i = child.expect(["root@240.1.1.1's password:"]) + i = child.expect(["root@240.1.1.1's password:"], timeout=30) bmc_pwd = self.get_bmc_pass() if i == 0 and bmc_pwd: child.sendline(bmc_pwd) @@ -127,58 +191,25 @@ def upload_file_bmc(self, fw_path): print(data) child.close return os.path.isfile(fw_path) + return False def get_cpld_version(self): - """Get CPLD version from SONiC - :returns: dict like {'CPLD_1': version_string, 'CPLD_2': version_string} - """ - - CPLD_B = self.__get_register_value(self.cpldb_version_path, '0xA100') - CPLD_C = self.__get_register_value(self.cpldb_version_path, '0xA1E0') - CPLD_1 = self.__get_register_value(self.switchboard_cpld1_path, '0x00') - CPLD_2 = self.__get_register_value(self.switchboard_cpld2_path, '0x00') - CPLD_3 = self.__get_register_value(self.switchboard_cpld3_path, '0x00') - CPLD_4 = self.__get_register_value(self.switchboard_cpld4_path, '0x00') - - fan_cpld_key = "CPLD_FAN" - fan_cpld = None - fan_cpld_req = requests.get(self.cpld_info_url) - if fan_cpld_req.status_code == 200: - fancpld_info_json = fan_cpld_req.json() - fancpld_info_data = fancpld_info_json.get('data') - fan_cpld = fancpld_info_data.get(fan_cpld_key) - - CPLD_B = 'None' if CPLD_B is 'None' else "{}.{}".format( - int(CPLD_B[2], 16), int(CPLD_B[3], 16)) - CPLD_C = 'None' if CPLD_C is 'None' else "{}.{}".format( - int(CPLD_C[2], 16), int(CPLD_C[3], 16)) - CPLD_1 = 'None' if CPLD_1 is 'None' else "{}.{}".format( - int(CPLD_1[2], 16), int(CPLD_1[3], 16)) - CPLD_2 = 'None' if CPLD_2 is 'None' else "{}.{}".format( - int(CPLD_2[2], 16), int(CPLD_2[3], 16)) - CPLD_3 = 'None' if CPLD_3 is 'None' else "{}.{}".format( - int(CPLD_3[2], 16), int(CPLD_3[3], 16)) - CPLD_4 = 'None' if CPLD_4 is 'None' else "{}.{}".format( - int(CPLD_4[2], 16), int(CPLD_4[3], 16)) - FAN_CPLD = 'None' if fan_cpld is None else fan_cpld - cpld_version_dict = {} - cpld_version_dict.update({'CPLD_B': CPLD_B}) - cpld_version_dict.update({'CPLD_C': CPLD_C}) - cpld_version_dict.update({'CPLD_1': CPLD_1}) - cpld_version_dict.update({'CPLD_2': CPLD_2}) - cpld_version_dict.update({'CPLD_3': CPLD_3}) - cpld_version_dict.update({'CPLD_4': CPLD_4}) - cpld_version_dict.update({'CPLD_FAN': FAN_CPLD}) + for cpld_name, info in self.cpld_ver_info.items(): + if info["path"] == "bmc": + #cpld_ver = self.get_from_bmc(self.cpld_ver_uri) + cpld_ver = "None" + else: + cpld_ver = self.__get_register_value(info["path"], info["offset"]) + + cpld_ver_str = "None" if cpld_ver is "None" else \ + "{}.{}".format(int(cpld_ver[2], 16), int(cpld_ver[3], 16)) + cpld_version_dict[cpld_name] = cpld_ver_str return cpld_version_dict def get_bios_version(self): - """Get BIOS version from SONiC - :returns: version string - - """ bios_version = None p = subprocess.Popen( @@ -190,17 +221,13 @@ def get_bios_version(self): bios_version = raw_data_list[0] if len( raw_data_list) == 1 else raw_data_list[-2] - return str(bios_version).strip() + return str(bios_version) def get_onie_version(self): - """Get ONiE version from SONiC - :returns: version string - - """ onie_verison = None onie_version_keys = "onie_version" - onie_config_file = open(self.onie_config_file, "r") + onie_config_file = open(self.ONIE_CFG_FILE, "r") for line in onie_config_file.readlines(): if onie_version_keys in line: onie_version_raw = line.split('=') @@ -210,10 +237,6 @@ def get_onie_version(self): return str(onie_verison) def get_pcie_version(self): - """Get PCiE version from SONiC - :returns: version dict { "PCIE_FW_LOADER": "2.5", "PCIE_FW": "D102_08" } - - """ cmd = "sudo bcmcmd 'pciephy fw version'" p = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -233,16 +256,19 @@ def get_pcie_version(self): return pcie_version def get_fpga_version(self): - """Get FPGA version from SONiC - :returns: version string - - """ version = self.__get_register_value(self.fpga_version_path, '0x00') if version is not 'None': version = "{}.{}".format( - int(version[2:][1:4], 16), int(version[2:][4:], 16)) + int(version[2:][:4], 16), int(version[2:][4:], 16)) return str(version) + def upgrade_logger(self, upgrade_list): + try: + with open(self.fw_upgrade_logger_path, 'w') as filetowrite: + json.dump(upgrade_list, filetowrite) + except Exception as e: + pass + def firmware_upgrade(self, fw_type, fw_path, fw_extra=None): """ @fw_type MANDATORY, firmware type, should be one of the strings: 'cpld', 'fpga', 'bios', 'bmc' @@ -254,97 +280,69 @@ def firmware_upgrade(self, fw_type, fw_path, fw_extra=None): value should be one of 'master' or 'slave' or 'both' """ fw_type = fw_type.lower() + upgrade_list = [] bmc_pwd = self.get_bmc_pass() if not bmc_pwd and fw_type != "fpga": - self.__update_fw_upgrade_logger( - "fw_upgrade", "fail, message=BMC credential not found") + print("Failed: BMC credential not found") return False if fw_type == 'bmc': - fw_extra_str = str(fw_extra).lower() - if fw_extra_str not in ["master", "slave", "both", "pingpong"]: - return False - - self.__update_fw_upgrade_logger( - "bmc_upgrade", "start BMC upgrade") # Copy BMC image file to BMC - last_fw_upgrade = ["BMC", fw_path, fw_extra_str, "FAILED"] - upload_file = self.upload_file_bmc(fw_path) - if not upload_file: - self.__update_fw_upgrade_logger( - "fw_upgrade", "fail, message=unable to upload BMC image to BMC") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + print("BMC Upgrade") + print("Uploading image to BMC...") + if not self.upload_to_bmc(fw_path): + print("Failed: Unable to upload BMC image to BMC") return False + print("Upload bmc image %s to BMC done" % fw_path) - filename_w_ext = os.path.basename(fw_path) - json_data = dict() + # Fill json param, "Name", "Path", "Flash" + image_name = os.path.basename(fw_path) + json_data = {} json_data["Name"] = "bmc" - json_data["Path"] = "/home/root/%s" % filename_w_ext + json_data["Path"] = "/tmp/%s" % image_name + + # Determine which flash to upgrade + fw_extra_str = str(fw_extra).lower() + current_bmc = self.get_bmc_flash() + flash_list = ["master", "slave", "both"] + if fw_extra_str not in flash_list: + if fw_extra_str != "pingpong": + print "BMC flash should be master/slave/both/pingpong" + return False - # Set flash type - current_bmc = self.get_running_bmc() - flash = fw_extra_str if fw_extra_str in [ - "master", "slave", "both"] else "both" if fw_extra_str == "pingpong": - #flash = "master" if current_bmc == "slave" else "slave" - flash = "slave" + flash = "slave" if current_bmc == "master" else "master" + else: + flash = fw_extra_str json_data["Flash"] = flash - # Install BMC - if flash == "both": - self.__update_fw_upgrade_logger( - "bmc_upgrade", "install BMC as master mode") - json_data["Flash"] = "master" - r = requests.post(self.fw_upgrade_url, json=json_data) - if r.status_code != 200 or r.json().get('status') != 'OK': - self.__update_fw_upgrade_logger( - "bmc_upgrade", "fail, message={}".format(r.json().get('messages'))) - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - return False - json_data["Flash"] = "slave" + # Send the upgrade request BMC + if not self.post_to_bmc(self.fw_upgrade_uri, json_data): + print "Failed to upgrade BMC %s flash" % flash + return False - self.__update_fw_upgrade_logger( - "bmc_upgrade", "install BMC as %s mode" % json_data["Flash"]) - r = requests.post(self.fw_upgrade_url, json=json_data) - if r.status_code == 200 and r.json().get('status') == 'OK': - if fw_extra_str == "pingpong": - flash = "master" if current_bmc == "slave" else "slave" - self.__update_fw_upgrade_logger( - "bmc_upgrade", "switch to boot from %s" % flash) - self.set_bmc_boot_flash(flash) - self.__update_fw_upgrade_logger("bmc_upgrade", "reboot BMC") - if not self.reboot_bmc(): + # Change boot flash if required + if current_bmc != flash: + # Set desired boot flash + print("Current BMC boot flash %s, user requested %s" % (current_bmc, flash)) + json_data = {} + json_data["Flash"] = flash + if not self.post_to_bmc(self.bmc_nextboot_uri, json_data): + print "Failed to set BMC next boot to %s" % flash return False - last_fw_upgrade[3] = "DONE" - else: - self.__update_fw_upgrade_logger( - "bmc_upgrade", "fail, message={}".format(r.json().get('messages'))) - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + + # Reboot BMC + print("Upgrade BMC %s done, reboot it" % fw_extra_str) + if not self.post_to_bmc(self.bmc_reboot_uri, {}): + print "Failed to reboot BMC after upgrade" return False - self.__update_fw_upgrade_logger( - "bmc_upgrade", "done") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + print("Upgrade BMC %s full process done" % fw_extra_str) return True - elif fw_type == 'fpga': - last_fw_upgrade = ["FPGA", fw_path, None, "FAILED"] - self.__update_fw_upgrade_logger( - "fpga_upgrade", "start FPGA upgrade") - - if not os.path.isfile(fw_path): - self.__update_fw_upgrade_logger( - "fpga_upgrade", "fail, message=FPGA image not found %s" % fw_path) - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - return False - + print("FPGA Upgrade") command = 'fpga_prog ' + fw_path - print("Running command : %s" % command) + print("Running command : ", command) process = subprocess.Popen( command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -352,177 +350,42 @@ def firmware_upgrade(self, fw_type, fw_path, fw_extra=None): output = process.stdout.readline() if output == '' and process.poll() is not None: break + if output: + print(output.strip()) - rc = process.returncode - if rc != 0: - self.__update_fw_upgrade_logger( - "fw_upgrade", "fail, message=unable to install FPGA") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - return False - - self.__update_fw_upgrade_logger("fpga_upgrade", "done") - last_fw_upgrade[3] = "DONE" - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - self.firmware_refresh(["FPGA"], None, None) - return True - - elif 'cpld' in fw_type: - self.__update_fw_upgrade_logger( - "cpld_upgrade", "start CPLD upgrade") - # Check input - fw_extra_str = str(fw_extra).upper() - if ":" in fw_path and ":" in fw_extra_str: - fw_path_list = fw_path.split(":") - fw_extra_str_list = fw_extra_str.split(":") + if process.returncode == 0: + rc = self.__fpga_pci_rescan() + if rc != 0: + print("Failed: Unable to load new FPGA firmware") + return False else: - fw_path_list = [fw_path] - fw_extra_str_list = [fw_extra_str] - - if len(fw_path_list) != len(fw_extra_str_list): - self.__update_fw_upgrade_logger( - "cpld_upgrade", "fail, message=invalid input") + print("Failed: Invalid fpga image") return False - data_list = list(zip(fw_path_list, fw_extra_str_list)) - refresh_img_path = None - cpld_result_list = ["FAILED" for i in range( - 0, len(fw_extra_str_list))] - last_fw_upgrade = ["CPLD", ":".join( - fw_path_list), ":".join(fw_extra_str_list), ":".join(cpld_result_list)] - for i in range(0, len(data_list)): - data = data_list[i] - fw_path = data[0] - fw_extra_str = data[1] - - # Set fw_extra - fw_extra_str = { - "TOP_LC_CPLD": "top_lc", - "BOT_LC_CPLD": "bottom_lc", - "FAN_CPLD": "fan", - "CPU_CPLD": "cpu", - "BASE_CPLD": "base", - "COMBO_CPLD": "combo", - "SW_CPLD1": "switch", - "SW_CPLD2": "switch", - "REFRESH_CPLD": "refresh" - }.get(fw_extra_str, None) - - if fw_extra_str == "refresh": - refresh_img_path = fw_path - del cpld_result_list[i] - del fw_extra_str_list[i] - continue - - if fw_extra_str is None: - self.__update_fw_upgrade_logger( - "cpld_upgrade", "fail, message=invalid extra information string") - continue - - # Uploading image to BMC - self.__update_fw_upgrade_logger( - "cpld_upgrade", "start %s upgrade" % data[1]) - upload_file = self.upload_file_bmc(fw_path) - if not upload_file: - self.__update_fw_upgrade_logger( - "cpld_upgrade", "fail, message=unable to upload BMC image to BMC") - continue - - filename_w_ext = os.path.basename(fw_path) - json_data = dict() - json_data["Path"] = "/home/root/%s" % filename_w_ext - json_data["Name"] = "cpld" - - # Call BMC api to install cpld image - print("Installing...") - r = requests.post(self.fw_upgrade_url, json=json_data) - if r.status_code != 200 or r.json().get('status') != 'OK': - self.__update_fw_upgrade_logger( - "cpld_upgrade", "fail, message={}".format(r.json().get('messages'))) - continue - - cpld_result_list[i] = "DONE" - self.__update_fw_upgrade_logger( - "cpld_upgrade", "%s upgrade done" % data[1]) - last_fw_upgrade[3] = ":".join(cpld_result_list) - self.__update_fw_upgrade_logger( - "cpld_upgrade", "done") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - - # Refresh CPLD - refresh_img_str_list = [] - for fw_extra in fw_extra_str_list: - if "BASE_CPLD" in fw_extra or "FAN_CPLD" in fw_extra: - refresh_img_str_list.append(refresh_img_path) - else: - refresh_img_str_list.append("None") - self.firmware_refresh(None, fw_extra_str_list, - ":".join(refresh_img_str_list)) - + print("Done") return True - elif 'bios' in fw_type: - fw_extra_str = str(fw_extra).lower() - if fw_extra_str not in ["master", "slave", "both"]: - return False + print("BIOS Upgrade") - self.__update_fw_upgrade_logger( - "bios_upgrade", "start BIOS upgrade") - last_fw_upgrade = ["BIOS", fw_path, None, "FAILED"] fw_extra_str = str(fw_extra).lower() - flash = fw_extra_str.lower() - - if not os.path.exists(fw_path): - self.__update_fw_upgrade_logger( - "bios_upgrade", "fail, message=image not found") - return False + flash = fw_extra_str if fw_extra_str in ["master", "slave"] else "master" - upload_file = self.upload_file_bmc(fw_path) - if not upload_file: - self.__update_fw_upgrade_logger( - "bios_upgrade", "fail, message=unable to upload image to BMC") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + print("Uploading BIOS image %s to BMC..." % fw_path) + if not self.upload_to_bmc(fw_path): + print("Failed to upload %s to bmc" % fw_path) return False - # json_data = dict() - # json_data["Command"] = "/usr/bin/ipmitool -b 1 -t 0x2c raw 0x2e 0xdf 0x57 0x01 0x00 0x01" - # r = requests.post(self.bmc_raw_command_url, json=json_data) - # if r.status_code != 200: - # self.__update_fw_upgrade_logger( - # "bios_upgrade", "fail, message=unable to set state") - # self.__update_fw_upgrade_logger( - # "last_upgrade_result", str(last_fw_upgrade)) - # return False - - filename_w_ext = os.path.basename(fw_path) - json_data = dict() - json_data["Path"] = "/home/root/%s" % filename_w_ext + image_name = os.path.basename(fw_path) + json_data = {} json_data["Name"] = "bios" + json_data["Path"] = "/tmp/%s" % image_name json_data["Flash"] = flash - print("Installing...") - r = requests.post(self.fw_upgrade_url, json=json_data) - if r.status_code != 200 or r.json().get('status') != 'OK': - self.__update_fw_upgrade_logger( - "bios_upgrade", "fail, message={}".format(r.json().get('messages'))) - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + if not self.post_to_bmc(self.fw_upgrade_uri, json_data): + print "Failed to upgrade %s BIOS" % flash return False - last_fw_upgrade[3] = "DONE" - self.__update_fw_upgrade_logger( - "bios_upgrade", "done") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - else: - self.__update_fw_upgrade_logger( - "fw_upgrade", "fail, message=invalid firmware type") - return False - - return True + return True def get_last_upgrade_result(self): """ @@ -744,57 +607,43 @@ def firmware_refresh(self, fpga_list, cpld_list, fw_extra=None): self.firmware_refresh(None, ["FAN_CPLD", "LC1_CPLD", "BASE_CPLD"], "/tmp/fw/fan_refresh.vme:none:/tmp/fw/base_refresh.vme") """ - self.__update_fw_upgrade_logger( - "fw_refresh", "start firmware refresh") - - cpld_list = [x.upper() for x in cpld_list] if cpld_list else [] - fpga_list = [x.upper() for x in fpga_list] if fpga_list else [] - refresh_list = cpld_list + fpga_list - fw_path_list = str(fw_extra).split(':') - refresh_img_list = ["none" for i in range(len(refresh_list))] - - if len(refresh_list) == 0 : - self.__update_fw_upgrade_logger( - "fw_refresh", "fail, message=Invalid input") - return False - - for idx in range(0, len(refresh_list)): - if refresh_list[idx] in ["FAN_CPLD", "BASE_CPLD"]: - if not self.upload_file_bmc(fw_path_list[idx]): - self.__update_fw_upgrade_logger( - "cpld_refresh", "fail, message=Unable to upload refresh image to BMC") - return False - refresh_img_list[idx] = "/home/root/%s" % os.path.basename( - fw_path_list[idx]) + fw_names = [] + fw_files = [] + # FPGA list may contain FPGA and BIOS + if fpga_list: + for name in fpga_list: + fw_names.append(name) + fw_files.append("/tmp/none") + + if cpld_list: + for name in cpld_list: + fw_names.append(name) + + if fw_extra: + for fpath in fw_extra: + if fpath == "none": + continue - json_data = dict() - json_data["Paths"] = refresh_img_list - json_data["Names"] = refresh_list - r = requests.post(self.fw_refresh_url, json=json_data) - if r.status_code != 200 or r.json().get('status') != 'OK': - self.__update_fw_upgrade_logger( - "cpld_refreshfw", "fail, message={}".format(r.json().get('messages'))) + fname = os.path.basename(fpath) + bmc_fpath = "/tmp/%s" % fname + fw_files.append(bmc_fpath) + + if os.path.exists(fpath) and os.path.isfile(fpath): + # upload refresh file to bmc + if not self.upload_to_bmc(fpath): + return False + + data = {} + data["Names"] = fw_names + data["Paths"] = fw_files + #j = json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + if not self.post_to_bmc(self.fw_refresh_uri, data): + print("Failed to refresh firmware") return False - self.__update_fw_upgrade_logger("fw_refresh", "done") - return True - def get_running_bmc(self): - """ - Get booting flash of running BMC. - @return a string, "master" or "slave" - """ - running_bmc = "master" - running_bmc_key = "Flash" - bmc_info_req = requests.get( - self.bmc_info_url, timeout=self.api_time_out) - if bmc_info_req.status_code == 200: - bmc_info_json = bmc_info_req.json() - bmc_info = bmc_info_json.get('data') - running_bmc = bmc_info.get(running_bmc_key) - return str(running_bmc).lower() - def set_bmc_boot_flash(self, flash): """ Set booting flash of BMC @@ -803,8 +652,8 @@ def set_bmc_boot_flash(self, flash): if flash.lower() not in ["master", "slave"]: return False json_data = dict() - json_data["Flash"] = flash - r = requests.post(self.bmc_next_boot, json=json_data) + json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;bmc_reboot %s" % flash + r = requests.post(self.bmc_raw_command_url, json=json_data) if r.status_code != 200: return False return True @@ -813,13 +662,10 @@ def reboot_bmc(self): """ Reboot BMC """ - try: - r = requests.post(self.bmc_reboot_url) - if r.status_code != 200: - return False - except Exception as e: - if "Connection aborted." in e.message[0]: - return True + json_data = dict() + json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;bmc_reboot reboot" + r = requests.post(self.bmc_raw_command_url, json=json_data) + if r.status_code != 200: return False return True @@ -828,39 +674,17 @@ def get_current_bios(self): # Get booting bios image of current running host OS # @return a string, "master" or "slave" """ - bios_boot_info = requests.get( - self.bios_boot_info, timeout=self.api_time_out) - if bios_boot_info.status_code == 200: - bios_boot_info_json = bios_boot_info.json() - bios_boot_info_data = bios_boot_info_json.get('data') - bios_boot = bios_boot_info_data.get("Flash") - return str(bios_boot) - - def get_bios_next_boot(self): - """ - # Get booting bios image of next booting host OS - # @return a string, "master" or "slave" - """ - bios_next_boot = "master" - bios_next_boot_info = requests.get( - self.bios_next_boot, timeout=self.api_time_out) - if bios_next_boot_info.status_code == 200: - bios_next_boot_info_json = bios_next_boot_info.json() - bios_next_boot_info_data = bios_next_boot_info_json.get('data') - bios_next_boot = bios_next_boot_info_data.get("Flash") - return str(bios_next_boot) - - def set_bios_next_boot(self, flash): - """ - # Set booting bios image of next booting host OS - # @return a string, "master" or "slave" - """ - if str(flash).lower() not in ['master', 'slave']: - return False - json_data = dict() - json_data["Flash"] = str(flash).lower() - r = requests.post(self.bios_next_boot, json=json_data) - if r.status_code != 200: - return False - return True + json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;come_boot_info" + r = requests.post(self.bmc_raw_command_url, json=json_data) + try: + cpu_boot_info_list = r.json().get('result') + for cpu_boot_info_raw in cpu_boot_info_list: + if "COMe CPU boots from BIOS" in cpu_boot_info_raw: + bios_image = "master" if "master "in cpu_boot_info_raw.lower( + ) else "slave" + return bios_image + raise Exception( + "Error: Unable to detect current running bios image") + except Exception as e: + raise Exception(e) diff --git a/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/psuutil.py b/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/psuutil.py index b36cc0510918..13d98a745827 100644 --- a/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/psuutil.py +++ b/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/psuutil.py @@ -1,47 +1,63 @@ -#!/usr/bin/env python +#!/usr/bin/python -__author__ = 'Wirut G.' -__license__ = "GPL" -__version__ = "0.2.0" -__status__ = "Development" +############################################################################### +# +## PSU utility. +# +## Copyright (C) Alibaba, INC. +# +################################################################################ import requests import re +import json try: from sonic_psu.psu_base import PsuBase except ImportError as e: raise ImportError(str(e) + "- required module not found") -NUM_PSU = 2 - class PsuUtil(PsuBase): - """Platform-specific PSUutil class""" + BMC_REQ_BASE_URI = "http://240.1.1.1:8080/api" def __init__(self): PsuBase.__init__(self) + self.psu_info_uri = "/".join([self.BMC_REQ_BASE_URI, "psu/info"]) + self.psu_num_uri = "/".join([self.BMC_REQ_BASE_URI, "psu/number"]) - self.psu_info_url = "http://240.1.1.1:8080/api/psu/info" - self.all_psu_dict = None + def _get_psu_info(self): + resp = requests.get(self.psu_info_uri) + if not resp: + return False - def request_data(self, url): - try: - r = requests.get(url) - data = r.json() - except Exception as e: - return {} - return data + psu_json = resp.json() + if not psu_json or not "data" in psu_json: + return False + + self.psu_info = psu_json["data"] + + return True def get_num_psus(self): """ Retrieves the number of PSUs available on the device :return: An integer, the number of PSUs available on the device """ + resp = requests.get(self.psu_num_uri) + if not resp: + return -1 - all_psu_dict = self.get_all() + psu_nr_json = resp.json() + if not psu_nr_json or "data" not in psu_nr_json: + return -1 - return all_psu_dict.get('Number', NUM_PSU) + try: + nr_psu = psu_nr_json["data"]["Number"] + except Exception as e: + nr_psu = -1 + + return nr_psu def get_psu_status(self, index): """ @@ -51,11 +67,28 @@ def get_psu_status(self, index): :return: Boolean, True if PSU is operating properly, False if PSU is faulty """ - all_psu_dict = self.get_all() - psu_key = 'PSU{}'.format(index) - psu_info = all_psu_dict.get(psu_key, {}) + # init data + psu_key = "PSU" + str(index) + psu_status_key = "Power Status" + psu_power_status = False + + try: + # Request and validate sensor's information + self.fru_status_list, self.psu_info_list = self.request_data() + + # Get PSU power status. + for fru_status in self.fru_status_list: + is_psu = fru_status.get(psu_key) + psu_status = str(fru_status.get(psu_status_key)).strip() + + if is_psu is not None and psu_status == "OK": + psu_power_status = True + + except: + print("Error: Unable to access PSU power status") + return False - return psu_info.get('PowerStatus', False) + return psu_power_status def get_psu_presence(self, index): """ @@ -64,11 +97,29 @@ def get_psu_presence(self, index): :param index: An integer, 1-based index of the PSU of which to query status :return: Boolean, True if PSU is plugged, False if not """ - all_psu_dict = self.get_all() - psu_key = 'PSU{}'.format(index) - psu_info = all_psu_dict.get(psu_key, {}) - return psu_info.get('Present', False) + # Init data + psu_key = "PSU" + str(index) + psu_presence_key = "Present" + psu_presence_status = False + + try: + # Request and validate sensor's information. + self.fru_status_list, self.psu_info_list = self.request_data() + + # Get PSU present status. + for fru_status in self.fru_status_list: + is_psu = fru_status.get(psu_key) + psu_status = str(fru_status.get(psu_presence_key)).strip() + + if is_psu is not None and psu_status == "Present": + psu_presence_status = True + + except: + print("Error: Unable to access PSU presence status") + return False + + return psu_presence_status def get_psu_sn(self, index): """ @@ -77,12 +128,25 @@ def get_psu_sn(self, index): :param index: An integer, 1-based index of the PSU. :return: Serial number """ + serial_number = "N/A" + psu_key = "PSU" + str(index) + " FRU" + psu_sn_key = "Serial Number" - all_psu_dict = self.get_all() - psu_key = 'PSU{}'.format(index) - psu_info = all_psu_dict.get(psu_key, {}) + try: + # Request and validate sensor's information. + self.fru_status_list, self.psu_info_list = self.request_data() - return psu_info.get('SN', False) + # Get PSU fru info. + for psu_fru in self.psu_info_list: + psu_sn = str(psu_fru.get(psu_sn_key)).strip() + if psu_fru.get(psu_key) is not None: + serial_number = psu_sn if psu_sn.strip() != "" else "N/A" + break + + except: + return "N/A" + + return serial_number def get_psu_pn(self, index): """ @@ -91,12 +155,25 @@ def get_psu_pn(self, index): :param index: An integer, 1-based index of the PSU. :return: Product name """ + product_name = "N/A" + psu_key = "PSU" + str(index) + " FRU" + psu_pn_key = "Product Name" + + try: + # Request and validate sensor's information + self.fru_status_list, self.psu_info_list = self.request_data() + + # Get PSU fru info. + for psu_fru in self.psu_info_list: + psu_pn = str(psu_fru.get(psu_pn_key)).strip() + if psu_fru.get(psu_key) is not None: + product_name = psu_pn if psu_pn.strip() != "" else "N/A" + break + + except: + return "N/A" - all_psu_dict = self.get_all() - psu_key = 'PSU{}'.format(index) - psu_info = all_psu_dict.get(psu_key, {}) - - return psu_info.get('PN', False) + return product_name def get_all(self): """ @@ -107,35 +184,131 @@ def get_all(self): PN, conditional, if PRESENT is True, PN of the PSU, string SN, conditional, if PRESENT is True, SN of the PSU, string """ +#{ +# "Number": 4, +# "PSU1": { +# "AirFlow": "N/A", +# "FanSpeed": { +# "Max": 30000, +# "Min": 1000, +# "Unit": "RPM", +# "Value": -99999 +# }, +# "Inputs": { +# "Current": { +# "HighAlarm": 7.0, +# "LowAlarm": 0.0, +# "Unit": "A", +# "Value": -99999.0 +# }, +# "Power": { +# "HighAlarm": 1220.0, +# "LowAlarm": -1, +# "Unit": "W", +# "Value": -99999.0 +# }, +# "Status": false, +# "Type": "Unknown", +# "Voltage": { +# "HighAlarm": 264.0, +# "LowAlarm": 90.0, +# "Unit": "V", +# "Value": -99999.0 +# } +# }, +# "Outputs": { +# "Current": { +# "HighAlarm": 90.0, +# "LowAlarm": 0.0, +# "Unit": "A", +# "Value": -99999.0 +# }, +# "Power": { +# "HighAlarm": 1100.0, +# "LowAlarm": -1, +# "Unit": "W", +# "Value": -99999.0 +# }, +# "Status": false, +# "Type": "Unknown", +# "Voltage": { +# "HighAlarm": 13.2, +# "LowAlarm": 10.8, +# "Unit": "V", +# "Value": -99999.0 +# } +# }, +# "PN": "", +# "SN": "JHZD1849000585", +# "Temperature": { +# "Max": 70.0, +# "Min": 60.0, +# "Unit": "C", +# "Value": -99999.0 +# } +# } +#} + psu_info = {} + if not self._get_psu_info(): + return psu_info + + #j = json.dumps(self.psu_info, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + + if "Number" not in self.psu_info: + return psu_info + + psu_nr = self.psu_info["Number"] + psu_info["Number"] = psu_nr + for idx in range(1, psu_nr+1): + psu_name = "PSU%d" % idx + if not psu_name in self.psu_info: + print("%s not in self.psu_info" % psu_name) + continue + + pi = self.psu_info[psu_name] + pinfo = {} + try: + pinfo["Present"] = True if pi["Present"] == "yes" else False + pinfo["AirFlow"] = pi["AirFlow"] + pinfo["PN"] = pi["PN"] + pinfo["SN"] = pi["SN"] + except Exception as e: + print("%s not in self.psu_info, exception 1" % psu_name) + continue + + if "Inputs" in pi: + pii = pi["Inputs"] + if "Status" in pii: + try: + pinfo["InputStatus"] = pii["Status"] + pinfo["InputType"] = pii["Type"] + except Exception as e: + pinfo["InputType"] = "N/AA" + + if "Outputs" in pi: + pio = pi["Outputs"] + if "Status" in pio: + try: + pinfo["OutputStatus"] = pio["Status"] + except Exception as e: + pinfo["OutputStatus"] = False + + if "FanSpeed" in pi: + pif = pi["FanSpeed"] + try: + pinfo["Speed"] = pif["Value"] + pinfo["LowThd"] = pif["Min"] + pinfo["HighThd"] = pif["Max"] + except Exception as e: + pinfo["Speed"] = 0 + pinfo["LowThd"] = 0 + pinfo["HighThd"] = 0 + + psu_info[psu_name] = pinfo + + #j = json.dumps(psu_info, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + + return psu_info - if not self.all_psu_dict: - all_psu_dict = dict() - - psu_info_req = self.request_data(self.psu_info_url) - psu_info_data = psu_info_req.get('data', {}) - all_psu_dict["Number"] = psu_info_data.get('Number', NUM_PSU) - - for psu_idx in range(1, all_psu_dict["Number"] + 1): - psu_key = 'PSU{}'.format(str(psu_idx)) - psu_info = psu_info_data.get(psu_key, {}) - psu_input_info = psu_info.get('Inputs', {}) - psu_output_info = psu_info.get('Outputs', {}) - - psu_info_dict = dict() - psu_info_dict["InputType"] = psu_input_info.get("Type", "N/A") - psu_info_dict["InputStatus"] = True if psu_input_info.get( - "Status") else False - psu_info_dict["OutputStatus"] = True if psu_output_info.get( - "Status") else False - psu_info_dict["PowerStatus"] = ( - psu_info_dict["InputStatus"] and psu_info_dict["OutputStatus"]) - psu_info_dict["PN"] = psu_info.get("PN", "N/A") - psu_info_dict["SN"] = psu_info.get("SN", "N/A") - psu_info_dict["Present"] = True if psu_info.get("Present") == 'yes' else False - psu_info_dict["AirFlow"] = psu_info.get("AirFlow", "N/A") - - all_psu_dict[psu_key] = psu_info_dict - - self.all_psu_dict = all_psu_dict - - return self.all_psu_dict diff --git a/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/sensorutil.py b/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/sensorutil.py index efed1e850306..4b5a7e3d4519 100644 --- a/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/sensorutil.py +++ b/device/alibaba/x86_64-alibaba_as13-48f8h-cl-r0/plugins/sensorutil.py @@ -1,206 +1,115 @@ -#!/usr/bin/env python +#!/usr/bin/python + +############################################################################### +# +### Sensor utility. +# +### Copyright (C) Alibaba, INC. +# +################################################################################# -__author__ = 'Wirut G.' -__license__ = "GPL" -__version__ = "0.2.0" -__status__ = "Development" import requests +import json class SensorUtil(): - """Platform-specific SensorUtil class""" + BMC_REQ_BASE_URI = "http://240.1.1.1:8080/api" def __init__(self): - self.sensor_info_url = "http://240.1.1.1:8080/api/sensor/info" - self.all_sensor_dict = None - - def request_data(self, url): - try: - r = requests.get(url) - data = r.json() - except Exception as e: - return {} - return data - - def input_type_selector(self, unit): - # Set input type. - return { - "C": "temperature", - "V": "voltage", - "RPM": "RPM", - "A": "amp", - "W": "power" - }.get(unit, unit) - - def input_name_selector(self, raw_sensor_name): - - sensor_name_list = raw_sensor_name.split('_') - sensor_name = sensor_name_list[0] - input_name = '_'.join(sensor_name_list[1:]) - - if sensor_name_list[0] in ["TOP", "BOTTOM"]: - sensor_name = '_'.join(sensor_name_list[0:2]) - input_name = '_'.join(sensor_name_list[2:]) - - return str(sensor_name).upper(), str(input_name).upper() - - def get_num_sensors(self): - """ - Get the number of sensors - :return: int num_sensors - """ - - all_sensor_dict = self.get_all() - - return len(all_sensor_dict) - - def get_sensor_input_num(self, index): - """ - Get the number of the input items of the specified sensor - :return: int input_num - """ - - all_sensor_dict = self.get_all() - ss_keys = all_sensor_dict.keys()[index] - sensor_info = all_sensor_dict.get(ss_keys, {}) - ss_if_keys = sensor_info.keys() - - return len(ss_if_keys) - - def get_sensor_name(self, index): - """ - Get the device name of the specified sensor. - for example "coretemp-isa-0000" - :return: str sensor_name - """ - all_sensor_dict = self.get_all() - sensor_name = all_sensor_dict.keys()[index] - - return sensor_name - - def get_sensor_input_name(self, sensor_index, input_index): - """ - Get the input item name of the specified input item of the - specified sensor index, for example "Physical id 0" - :return: str sensor_input_name - """ - - all_sensor_dict = self.get_all() + self.sensor_info_uri = "/".join([self.BMC_REQ_BASE_URI, "sensor/info"]) + self.sensor_info = None - ss_keys = all_sensor_dict.keys()[sensor_index] - sensor_info = all_sensor_dict.get(ss_keys, {}) - ss_if_keys = sensor_info.keys()[input_index] + def _get_sensor_info(self): + resp = requests.get(self.sensor_info_uri) + if not resp: + return False - return ss_if_keys + sensor_json = resp.json() + if not sensor_json or not "data" in sensor_json: + return False - def get_sensor_input_type(self, sensor_index, input_index): - """ - Get the item type of the specified input item of the specified sensor index, - The return value should among "valtage","temperature" - :return: str sensor_input_type - """ + self.sensor_info = sensor_json["data"] - all_sensor_dict = self.get_all() + return True - ss_keys = all_sensor_dict.keys()[sensor_index] - sensor_info = all_sensor_dict.get(ss_keys, {}) + def get_sys_airflow(self): + sys_air_flow = "Unknown" - ss_if_keys = sensor_info.keys()[input_index] - sensor_input_info = sensor_info.get(ss_if_keys, {}) + sys_pn = sys_pn_data[0][1] + if "R1240-F0001" in sys_pn: + sys_air_flow = "FTOB" + elif"R1240-F0002" in sys_pn: + sys_air_flow = "BTOF" - sensor_input_type = sensor_input_info.get('Type', "N/A") - return sensor_input_type + return sys_air_flow - def get_sensor_input_value(self, sensor_index, input_index): - """ - Get the current value of the input item, the unit is "V" or "C" - :return: float sensor_input_value - """ + def _get_type(self, unit_str): + unit2type = {"C": "temperature", "A": "amp", "V": "voltage", + "RPM": "RPM", "W": "power"} - all_sensor_dict = self.get_all() + if unit_str in unit2type: + return unit2type[unit_str] + return None - ss_keys = all_sensor_dict.keys()[sensor_index] - sensor_info = all_sensor_dict.get(ss_keys, {}) - - ss_if_keys = sensor_info.keys()[input_index] - sensor_input_info = sensor_info.get(ss_if_keys, {}) - - sensor_input_value = sensor_input_info.get('Value', 0.0) - return sensor_input_value - - def get_sensor_input_low_threshold(self, sensor_index, input_index): - """ - Get the low threshold of the value, - the status of this item is not ok if the current value high_threshold - :return: float sensor_input_high_threshold - """ - all_sensor_dict = self.get_all() - - ss_keys = all_sensor_dict.keys()[sensor_index] - sensor_info = all_sensor_dict.get(ss_keys, {}) - - ss_if_keys = sensor_info.keys()[input_index] - sensor_input_info = sensor_info.get(ss_if_keys, {}) - - sensor_input_high_threshold = sensor_input_info.get('HighThd', 0.0) - return sensor_input_high_threshold + def get_num_sensors(self): + sensor_dict = self.get_all() + sum = 0 + for sensor_name, sensor_obj in sensor_dict.items(): + if cmp(sensor_name, 'Number') == 0: + continue + sum += len(sensor_obj.keys()) + return sum def get_all(self): - """ - Get all information of system sensors, returns JSON objects in python 'DICT'. - SensorName1, SensorName2, ... optional, string - SensorInput1, SensorInput2, ... optional, string - Type, mandatory in SensorInput$INDEX, should be on of { "temperature", "voltage", "power", "amp", "RPM" } - Value, mandatory in SensorInput$INDEX, float , real value - LowThd, mandatory in SensorInput$INDEX, float , lower bound of value - HighThd, mandatory in SensorInput$INDEX, float , upper bound of value - Return python 'dict' objects, example: - """ - - if not self.all_sensor_dict: - all_sensor_dict = dict() - - sensor_info_req = self.request_data(self.sensor_info_url) - sensor_info_data = sensor_info_req.get('data', {}) - - for raw_ss_name, sensor_info in sensor_info_data.items(): - - sensor_name, input_name = self.input_name_selector(raw_ss_name) - sensor_dict = all_sensor_dict.get(sensor_name, {}) - new_sensor_dict = dict() - new_sensor_dict["Type"] = self.input_type_selector( - sensor_info.get('Unit', 'N/A')) - new_sensor_dict["Value"] = float(sensor_info.get('Value', 0.0)) - new_sensor_dict["HighThd"] = float(sensor_info.get('Max', 0.0)) - new_sensor_dict["LowThd"] = float(sensor_info.get('Min', 0.0)) - - if sensor_dict == {}: - all_sensor_dict[sensor_name] = dict() - - input_name = input_name if input_name != '' else new_sensor_dict["Type"].upper( - ) - sensor_dict[input_name] = new_sensor_dict - all_sensor_dict[sensor_name].update(sensor_dict) - - self.all_sensor_dict = all_sensor_dict - - return self.all_sensor_dict + sensor_info = {} + + if not self._get_sensor_info(): + return sensor_info + + sname_temp_cl = ["Cpu", "Inlet", "Switch"] + sname_temp_rj = ["CPU_TEMP", "INLET_TEMP", "SWITCH_TEMP"] + for si_name, si_val in self.sensor_info.items(): + if si_name.startswith("PSU"): + sname = si_name.split("_")[0] + if si_name.find("Temperature") != -1: + new_si_name = "%s_TEMP" % sname + si_name = new_si_name + elif si_name in sname_temp_cl: + sname = "TEMPERATURE" + new_si_name = "%s_temp" % si_name + si_name = new_si_name.upper() + elif si_name in sname_temp_rj: + sname = "TEMPERATURE" + elif si_name.startswith("CPU"): + sname = "CPU" + elif si_name.startswith("FAN"): + sname = "FAN" + elif si_name.startswith("Switch") or \ + si_name.startswith("SWITCH") or \ + si_name.find("_LC_") != -1: + sname = "SWITCH" + elif si_name.startswith("SYS") or \ + si_name.startswith("Baseboard"): + sname = "SYSTEM" + else: + sname = "OTHER" + + si_info = {} + si_info["LowThd"] = si_val["Min"] + si_info["HighThd"] = si_val["Max"] + si_info["Value"] = si_val["Value"] + type = self._get_type(si_val["Unit"]) + if not type: + continue + si_info["Type"] = type + + if sname not in sensor_info: + sensor_info[sname] = {} + + sensor_info[sname][si_name] = si_info + + #j = json.dumps(self.sensor_info, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + + return sensor_info diff --git a/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/fanutil.py b/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/fanutil.py index f25dbdd587eb..c0b58b89928d 100644 --- a/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/fanutil.py +++ b/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/fanutil.py @@ -1,117 +1,51 @@ -#!/usr/bin/env python - -__author__ = 'Wirut G.' -__license__ = "GPL" -__version__ = "0.2.0" -__status__ = "Development" +#!/usr/bin/python import requests import re - -NUM_FAN_TRAY = 5 -NUM_ROTER = 2 +import json class FanUtil(): - """Platform-specific FanUtil class""" + BMC_REQ_BASE_URI = "http://240.1.1.1:8080/api" + ROTOR_PER_FAN = 2 def __init__(self): - self.fan_info_url = "http://240.1.1.1:8080/api/fan/info" - self.all_fan_dict = None - - def request_data(self, url): - try: - r = requests.get(url) - data = r.json() - except Exception as e: - return {} - return data - - def get_num_fans(self): - """ - Get the number of fans - :return: int num_fans - """ - all_fan_dict = self.get_all() - num_fan_tray = all_fan_dict.get('Number', NUM_FAN_TRAY) - - return num_fan_tray * NUM_ROTER - - def get_fan_speed(self, fan_name): - """ - Get the current speed of the fan, the unit is "RPM" - :return: int fan_speed - """ - - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) - - return fan_info.get('Speed', 0) - - def get_fan_low_threshold(self, fan_name): - """ - Get the low speed threshold of the fan. - if the current speed < low speed threshold, - the status of the fan is not ok. - :return: int fan_low_threshold - """ - - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) - - return fan_info.get('LowThd', 0) + self.fan_info_uri = "/".join([self.BMC_REQ_BASE_URI, "fan/info"]) + self.fan_num_uri = "/".join([self.BMC_REQ_BASE_URI, "fan/number"]) - def get_fan_high_threshold(self, fan_name): - """ - Get the hight speed threshold of the fan, - if the current speed > high speed threshold, - the status of the fan is not ok - :return: int fan_high_threshold - """ - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) + def _get_fan_info(self): + resp = requests.get(self.fan_info_uri) + if not resp: + return False - return fan_info.get('HighThd', 0) + fan_json = resp.json() + if not fan_json or not "data" in fan_json: + return False - def get_fan_pn(self, fan_name): - """ - Get the product name of the fan - :return: str fan_pn - """ + self.fan_info = fan_json["data"] - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) + return True - return fan_info.get('PN', 'N/A') - - def get_fan_sn(self, fan_name): - """ - Get the serial number of the fan - :return: str fan_sn + def get_num_fans(self): """ - all_fan_dict = self.get_all() - fan_info = all_fan_dict.get(fan_name, {}) - - return fan_info.get('SN', 'N/A') + Get total fan number - def get_fans_name_list(self): + @return number of fan, -1 for failure """ - Get list of fan name. - :return: list fan_names - """ - fan_names = [] + resp = requests.get(self.fan_num_uri) + if not resp: + return -1 - # Get the number of fans - n_fan = self.get_num_fans() + fan_nr_json = resp.json() + if not fan_nr_json or "data" not in fan_nr_json: + return -1 - # Set fan name and add to the list. - for x in range(1, n_fan + 1): - f_index = int(round(float(x)/2)) - pos = 1 if x % 2 else 2 - fan_name = 'FAN{}_{}'.format(f_index, pos) - fan_names.append(fan_name) + try: + nr_fan = fan_nr_json["data"]["Number"] + except Exception as e: + nr_fan = -1 - return fan_names + return nr_fan def get_all(self): """ @@ -126,41 +60,55 @@ def get_all(self): PN, conditional, if PRESENT is True, PN of the FAN, string SN, conditional, if PRESENT is True, SN of the FAN, string) """ + fan_info = {} + if not self._get_fan_info(): + return fan_info + + if "Number" not in self.fan_info: + return fan_info + + fan_nr = self.fan_info["Number"] + for fan_idx in range(1, fan_nr+1): + fan_name = "FAN%d" % fan_idx + if not fan_name in self.fan_info: + print("%s not in self.fan_info" % fan_name) + continue + fi = self.fan_info[fan_name] + if "Rotors" not in fi: + print("Rotors not in fi") + continue + rotor_nr = fi["Rotors"] + for ridx in range(1, rotor_nr+1): + sub_name = "%s_%d" % (fan_name, ridx) + rname = "Rotor%d" % ridx + sub_fan_info = {} + if rname not in fi: + print("%s not in fi" % rname) + continue + try: + sub_fan_info["Present"] = True if fi["Present"] == "yes" else False + sub_fan_info["Running"] = fi[rname]["Running"] + sub_fan_info["Speed"] = fi[rname]["Speed"] + sub_fan_info["LowThd"] = fi[rname]["SpeedMin"] + sub_fan_info["HighThd"] = fi[rname]["SpeedMax"] + sub_fan_info["PN"] = fi["PN"] + sub_fan_info["SN"] = fi["SN"] + sub_fan_info["AirFlow"] = fi["AirFlow"] + if (fi[rname]["HwAlarm"] == "no") and \ + (sub_fan_info["Speed"] != None and sub_fan_info["LowThd"] != None and sub_fan_info["Speed"] >= sub_fan_info["LowThd"]) and \ + (sub_fan_info["Speed"] != None and sub_fan_info["HighThd"] != None and sub_fan_info["Speed"] <= sub_fan_info["HighThd"]): + sub_fan_info["Status"] = True + else: + sub_fan_info["Status"] = False + + fan_info[sub_name] = sub_fan_info + except Exception as e: + print("GOT EXCEPTON: %s" % str(e)) + continue + fan_info["Number"] = fan_nr * self.ROTOR_PER_FAN + + #j = json.dumps(fan_info, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + + return fan_info - if not self.all_fan_dict: - all_fan_dict = dict() - - fan_info_req = self.request_data(self.fan_info_url) - fan_info_data = fan_info_req.get('data', {}) - all_fan_dict["Number"] = fan_info_data.get('Number', NUM_FAN_TRAY) - - for fan_idx in range(1, all_fan_dict["Number"] + 1): - num_of_roter = fan_info_data.get('Rotors', NUM_ROTER) - - for fan_pos in range(1, num_of_roter + 1): - fan_key = 'FAN{}'.format(str(fan_idx)) - roter_key = 'Rotor{}'.format(str(fan_pos)) - - fan_info = fan_info_data.get(fan_key, {}) - roter_info = fan_info.get(roter_key, {}) - - fan_info_dict = dict() - fan_info_dict["Present"] = True if fan_info.get( - "Present") == 'yes' else False - fan_info_dict["Speed"] = roter_info.get("Speed", "N/A") - fan_info_dict["Running"] = True if roter_info.get( - "Running") == 'yes' else False - fan_info_dict["HighThd"] = roter_info.get( - "SpeedMax", "N/A") - fan_info_dict["LowThd"] = roter_info.get("SpeedMin", "N/A") - fan_info_dict["Status"] = False if roter_info.get( - "HwAlarm") == 'yes' else True - fan_info_dict["PN"] = fan_info.get("PN", "N/A") - fan_info_dict["SN"] = fan_info.get("SN", "N/A") - fan_info_dict["AirFlow"] = fan_info.get("AirFlow", "N/A") - - fan_name = '{}_{}'.format(fan_key, fan_pos) - all_fan_dict[fan_name] = fan_info_dict - self.all_fan_dict = all_fan_dict - - return self.all_fan_dict diff --git a/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/fwmgrutil.py b/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/fwmgrutil.py index e91cf6f3f3c0..610d025775d0 100644 --- a/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/fwmgrutil.py +++ b/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/fwmgrutil.py @@ -1,14 +1,5 @@ -#!/usr/bin/env python -# -# fwmgrutil.py -# -# Platform-specific firmware management interface for SONiC -# - -__author__ = 'Wirut G.' -__license__ = "GPL" -__version__ = "0.2.1" -__status__ = "Development" +#!/usr/bin/python + import subprocess import requests @@ -28,33 +19,51 @@ class FwMgrUtil(FwMgrUtilBase): - - """Platform-specific FwMgrUtil class""" + BMC_REQ_BASE_URI = "http://240.1.1.1:8080/api" + ONIE_CFG_FILE = "/host/machine.conf" def __init__(self): self.platform_name = "AS23128h" - self.onie_config_file = "/host/machine.conf" - self.bmc_info_url = "http://240.1.1.1:8080/api/bmc/info" - self.cpld_info_url = "http://240.1.1.1:8080/api/firmware/cpldversion" - self.bmc_raw_command_url = "http://240.1.1.1:8080/api/hw/rawcmd" - self.fw_upgrade_url = "http://240.1.1.1:8080/api/firmware/upgrade" - self.fw_refresh_url = "http://240.1.1.1:8080/api/firmware/refresh" - self.bios_next_boot = "http://240.1.1.1:8080/api/firmware/biosnextboot" - self.bmc_next_boot = "http://240.1.1.1:8080/api/bmc/nextboot" - self.bmc_reboot_url = "http://240.1.1.1:8080/api/bmc/reboot" - self.bios_boot_info = "http://240.1.1.1:8080/api/misc/biosbootstatus" - self.onie_config_file = "/host/machine.conf" + self.bmc_info_uri = "/".join([self.BMC_REQ_BASE_URI, "bmc/info"]) + self.bmc_nextboot_uri = "/".join([self.BMC_REQ_BASE_URI, "bmc/nextboot"]) + self.bmc_reboot_uri = "/".join([self.BMC_REQ_BASE_URI, "bmc/reboot"]) + self.fw_upgrade_uri = "/".join([self.BMC_REQ_BASE_URI, "firmware/upgrade"]) + self.fw_refresh_uri = "/".join([self.BMC_REQ_BASE_URI, "firmware/refresh"]) + self.fw_upgrade_logger_path = "/var/log/fw_upgrade.log" - self.cpldb_version_path = "/sys/devices/platform/%s.cpldb/getreg" % self.platform_name + + self.cpld_ver_info = { + "CPLD_B": { + "path": "/sys/devices/platform/%s.cpldb/getreg" % self.platform_name, + "offset": "0xA100" + }, + "CPLD_C": { + "path": "/sys/devices/platform/%s.cpldb/getreg" % self.platform_name, + "offset": "0xA1E0" + }, + "CPLD_1": { + "path": "/sys/devices/platform/%s.switchboard/CPLD1/getreg" % self.platform_name, + "offset": "0x00" + }, + "CPLD_2": { + "path": "/sys/devices/platform/%s.switchboard/CPLD2/getreg" % self.platform_name, + "offset": "0x00" + }, + "CPLD_3": { + "path": "/sys/devices/platform/%s.switchboard/CPLD3/getreg" % self.platform_name, + "offset": "0x00" + }, + "CPLD_4": { + "path": "/sys/devices/platform/%s.switchboard/CPLD1/getreg" % self.platform_name, + "offset": "0x00" + }, + "CPLD_FAN": { + "path": "bmc", + "offset": "0x00" + } + } self.fpga_version_path = "/sys/devices/platform/%s.switchboard/FPGA/getreg" % self.platform_name - self.switchboard_cpld1_path = "/sys/devices/platform/%s.switchboard/CPLD1/getreg" % self.platform_name - self.switchboard_cpld2_path = "/sys/devices/platform/%s.switchboard/CPLD2/getreg" % self.platform_name - self.switchboard_cpld3_path = "/sys/devices/platform/%s.switchboard/CPLD3/getreg" % self.platform_name - self.switchboard_cpld4_path = "/sys/devices/platform/%s.switchboard/CPLD4/getreg" % self.platform_name self.bmc_pwd_path = "/usr/local/etc/bmcpwd" - self.cpld_name_list = ["CPU_CPLD", "COMBO_CPLD", - "SW_CPLD1", "SW_CPLD2", "TOP_LC_CPLD", "BOT_LC_CPLD"] - self.api_time_out = 300 def __get_register_value(self, path, register): cmd = "echo {1} > {0}; cat {0}".format(path, register) @@ -66,6 +75,30 @@ def __get_register_value(self, path, register): else: return raw_data.strip() + def __fpga_pci_rescan(self): + """ + An sequence to trigger FPGA to load new configuration after upgrade. + """ + fpga_pci_device_remove = '/sys/devices/pci0000:00/0000:00:1c.0/0000:09:00.0/remove' + parent_pci_device_rescan = '/sys/devices/pci0000:00/0000:00:1c.0/rescan' + cmd = 'modprobe -r switchboard_fpga' + os.system(cmd) + cmd = 'echo 1 > %s' % fpga_pci_device_remove + rc = os.system(cmd) + if rc > 0: + return rc + cmd = 'echo 0xa10a 0 > /sys/devices/platform/%s.cpldb/setreg' % self.platform_name + rc = os.system(cmd) + if rc > 0: + return rc + time.sleep(10) + cmd = 'echo 1 > %s' % parent_pci_device_rescan + rc = os.system(cmd) + if rc > 0: + return rc + os.system('modprobe switchboard_fpga') + return 0 + def __update_fw_upgrade_logger(self, header, message): if not os.path.isfile(self.fw_upgrade_logger_path): cmd = "sudo touch %s && sudo chmod +x %s" % ( @@ -76,7 +109,7 @@ def __update_fw_upgrade_logger(self, header, message): logging.basicConfig(filename=self.fw_upgrade_logger_path, filemode='a', format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s', - datefmt='%b %d %H:%M:%S', + datefmt='%H:%M:%S', level=logging.INFO) log_message = "%s : %s" % (header, message) @@ -99,27 +132,58 @@ def get_bmc_pass(self): return "".join(dec) return False + def get_from_bmc(self, uri): + resp = requests.get(uri) + if not resp: + return None + + data = resp.json() + if not data or "data" not in data or "status" not in data: + return None + + if data["status"] != "OK": + return None + + return data["data"] + def get_bmc_version(self): - """Get BMC version from SONiC - :returns: version string + bmc_ver = "N/A" + data = self.get_from_bmc(self.bmc_info_uri) + if not data or "Version" not in data: + return bmc_ver - """ - bmc_version = None - bmc_version_key = "Version" - bmc_info_req = requests.get( - self.bmc_info_url, timeout=self.api_time_out) - if bmc_info_req.status_code == 200: - bmc_info_json = bmc_info_req.json() - bmc_info = bmc_info_json.get('data') - bmc_version = bmc_info.get(bmc_version_key) - return str(bmc_version) - - def upload_file_bmc(self, fw_path): - scp_command = 'sudo scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -r %s root@240.1.1.1:/home/root/' % os.path.abspath( - fw_path) + return data["Version"] + + def get_bmc_flash(self): + flash = "N/A" + data = self.get_from_bmc(self.bmc_info_uri) + if not data or "Flash" not in data: + return flash + + return data["Flash"] + + def post_to_bmc(self, uri, data): + resp = requests.post(uri, json=data) + if not resp: + print "No response" + return False + + data = resp.json() + if "status" not in data: + return False + + if data["status"] != "OK": + return False + + return True + + def upload_to_bmc(self, fw_path): + scp_command = 'sudo scp -o StrictHostKeyChecking=no -o ' \ + 'UserKnownHostsFile=/dev/null -r %s root@240.1.1.1:/tmp/' \ + % os.path.abspath(fw_path) + print scp_command child = pexpect.spawn(scp_command) - child.timeout = self.api_time_out - i = child.expect(["root@240.1.1.1's password:"]) + i = child.expect(["root@240.1.1.1's password:"], timeout=30) bmc_pwd = self.get_bmc_pass() if i == 0 and bmc_pwd: child.sendline(bmc_pwd) @@ -127,58 +191,25 @@ def upload_file_bmc(self, fw_path): print(data) child.close return os.path.isfile(fw_path) + return False def get_cpld_version(self): - """Get CPLD version from SONiC - :returns: dict like {'CPLD_1': version_string, 'CPLD_2': version_string} - """ - - CPLD_B = self.__get_register_value(self.cpldb_version_path, '0xA100') - CPLD_C = self.__get_register_value(self.cpldb_version_path, '0xA1E0') - CPLD_1 = self.__get_register_value(self.switchboard_cpld1_path, '0x00') - CPLD_2 = self.__get_register_value(self.switchboard_cpld2_path, '0x00') - CPLD_3 = self.__get_register_value(self.switchboard_cpld3_path, '0x00') - CPLD_4 = self.__get_register_value(self.switchboard_cpld4_path, '0x00') - - fan_cpld_key = "CPLD_FAN" - fan_cpld = None - fan_cpld_req = requests.get(self.cpld_info_url) - if fan_cpld_req.status_code == 200: - fancpld_info_json = fan_cpld_req.json() - fancpld_info_data = fancpld_info_json.get('data') - fan_cpld = fancpld_info_data.get(fan_cpld_key) - - CPLD_B = 'None' if CPLD_B is 'None' else "{}.{}".format( - int(CPLD_B[2], 16), int(CPLD_B[3], 16)) - CPLD_C = 'None' if CPLD_C is 'None' else "{}.{}".format( - int(CPLD_C[2], 16), int(CPLD_C[3], 16)) - CPLD_1 = 'None' if CPLD_1 is 'None' else "{}.{}".format( - int(CPLD_1[2], 16), int(CPLD_1[3], 16)) - CPLD_2 = 'None' if CPLD_2 is 'None' else "{}.{}".format( - int(CPLD_2[2], 16), int(CPLD_2[3], 16)) - CPLD_3 = 'None' if CPLD_3 is 'None' else "{}.{}".format( - int(CPLD_3[2], 16), int(CPLD_3[3], 16)) - CPLD_4 = 'None' if CPLD_4 is 'None' else "{}.{}".format( - int(CPLD_4[2], 16), int(CPLD_4[3], 16)) - FAN_CPLD = 'None' if fan_cpld is None else fan_cpld - cpld_version_dict = {} - cpld_version_dict.update({'CPLD_B': CPLD_B}) - cpld_version_dict.update({'CPLD_C': CPLD_C}) - cpld_version_dict.update({'CPLD_1': CPLD_1}) - cpld_version_dict.update({'CPLD_2': CPLD_2}) - cpld_version_dict.update({'CPLD_3': CPLD_3}) - cpld_version_dict.update({'CPLD_4': CPLD_4}) - cpld_version_dict.update({'CPLD_FAN': FAN_CPLD}) + for cpld_name, info in self.cpld_ver_info.items(): + if info["path"] == "bmc": + #cpld_ver = self.get_from_bmc(self.cpld_ver_uri) + cpld_ver = "None" + else: + cpld_ver = self.__get_register_value(info["path"], info["offset"]) + + cpld_ver_str = "None" if cpld_ver is "None" else \ + "{}.{}".format(int(cpld_ver[2], 16), int(cpld_ver[3], 16)) + cpld_version_dict[cpld_name] = cpld_ver_str return cpld_version_dict def get_bios_version(self): - """Get BIOS version from SONiC - :returns: version string - - """ bios_version = None p = subprocess.Popen( @@ -190,17 +221,13 @@ def get_bios_version(self): bios_version = raw_data_list[0] if len( raw_data_list) == 1 else raw_data_list[-2] - return str(bios_version).strip() + return str(bios_version) def get_onie_version(self): - """Get ONiE version from SONiC - :returns: version string - - """ onie_verison = None onie_version_keys = "onie_version" - onie_config_file = open(self.onie_config_file, "r") + onie_config_file = open(self.ONIE_CFG_FILE, "r") for line in onie_config_file.readlines(): if onie_version_keys in line: onie_version_raw = line.split('=') @@ -210,10 +237,6 @@ def get_onie_version(self): return str(onie_verison) def get_pcie_version(self): - """Get PCiE version from SONiC - :returns: version dict { "PCIE_FW_LOADER": "2.5", "PCIE_FW": "D102_08" } - - """ cmd = "sudo bcmcmd 'pciephy fw version'" p = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -233,16 +256,19 @@ def get_pcie_version(self): return pcie_version def get_fpga_version(self): - """Get FPGA version from SONiC - :returns: version string - - """ version = self.__get_register_value(self.fpga_version_path, '0x00') if version is not 'None': version = "{}.{}".format( - int(version[2:][1:4], 16), int(version[2:][4:], 16)) + int(version[2:][:4], 16), int(version[2:][4:], 16)) return str(version) + def upgrade_logger(self, upgrade_list): + try: + with open(self.fw_upgrade_logger_path, 'w') as filetowrite: + json.dump(upgrade_list, filetowrite) + except Exception as e: + pass + def firmware_upgrade(self, fw_type, fw_path, fw_extra=None): """ @fw_type MANDATORY, firmware type, should be one of the strings: 'cpld', 'fpga', 'bios', 'bmc' @@ -254,97 +280,69 @@ def firmware_upgrade(self, fw_type, fw_path, fw_extra=None): value should be one of 'master' or 'slave' or 'both' """ fw_type = fw_type.lower() + upgrade_list = [] bmc_pwd = self.get_bmc_pass() if not bmc_pwd and fw_type != "fpga": - self.__update_fw_upgrade_logger( - "fw_upgrade", "fail, message=BMC credential not found") + print("Failed: BMC credential not found") return False if fw_type == 'bmc': - fw_extra_str = str(fw_extra).lower() - if fw_extra_str not in ["master", "slave", "both", "pingpong"]: - return False - - self.__update_fw_upgrade_logger( - "bmc_upgrade", "start BMC upgrade") # Copy BMC image file to BMC - last_fw_upgrade = ["BMC", fw_path, fw_extra_str, "FAILED"] - upload_file = self.upload_file_bmc(fw_path) - if not upload_file: - self.__update_fw_upgrade_logger( - "fw_upgrade", "fail, message=unable to upload BMC image to BMC") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + print("BMC Upgrade") + print("Uploading image to BMC...") + if not self.upload_to_bmc(fw_path): + print("Failed: Unable to upload BMC image to BMC") return False + print("Upload bmc image %s to BMC done" % fw_path) - filename_w_ext = os.path.basename(fw_path) - json_data = dict() + # Fill json param, "Name", "Path", "Flash" + image_name = os.path.basename(fw_path) + json_data = {} json_data["Name"] = "bmc" - json_data["Path"] = "/home/root/%s" % filename_w_ext + json_data["Path"] = "/tmp/%s" % image_name + + # Determine which flash to upgrade + fw_extra_str = str(fw_extra).lower() + current_bmc = self.get_bmc_flash() + flash_list = ["master", "slave", "both"] + if fw_extra_str not in flash_list: + if fw_extra_str != "pingpong": + print "BMC flash should be master/slave/both/pingpong" + return False - # Set flash type - current_bmc = self.get_running_bmc() - flash = fw_extra_str if fw_extra_str in [ - "master", "slave", "both"] else "both" if fw_extra_str == "pingpong": - #flash = "master" if current_bmc == "slave" else "slave" - flash = "slave" + flash = "slave" if current_bmc == "master" else "master" + else: + flash = fw_extra_str json_data["Flash"] = flash - # Install BMC - if flash == "both": - self.__update_fw_upgrade_logger( - "bmc_upgrade", "install BMC as master mode") - json_data["Flash"] = "master" - r = requests.post(self.fw_upgrade_url, json=json_data) - if r.status_code != 200 or r.json().get('status') != 'OK': - self.__update_fw_upgrade_logger( - "bmc_upgrade", "fail, message={}".format(r.json().get('messages'))) - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - return False - json_data["Flash"] = "slave" + # Send the upgrade request BMC + if not self.post_to_bmc(self.fw_upgrade_uri, json_data): + print "Failed to upgrade BMC %s flash" % flash + return False - self.__update_fw_upgrade_logger( - "bmc_upgrade", "install BMC as %s mode" % json_data["Flash"]) - r = requests.post(self.fw_upgrade_url, json=json_data) - if r.status_code == 200 and r.json().get('status') == 'OK': - if fw_extra_str == "pingpong": - flash = "master" if current_bmc == "slave" else "slave" - self.__update_fw_upgrade_logger( - "bmc_upgrade", "switch to boot from %s" % flash) - self.set_bmc_boot_flash(flash) - self.__update_fw_upgrade_logger("bmc_upgrade", "reboot BMC") - if not self.reboot_bmc(): + # Change boot flash if required + if current_bmc != flash: + # Set desired boot flash + print("Current BMC boot flash %s, user requested %s" % (current_bmc, flash)) + json_data = {} + json_data["Flash"] = flash + if not self.post_to_bmc(self.bmc_nextboot_uri, json_data): + print "Failed to set BMC next boot to %s" % flash return False - last_fw_upgrade[3] = "DONE" - else: - self.__update_fw_upgrade_logger( - "bmc_upgrade", "fail, message={}".format(r.json().get('messages'))) - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + + # Reboot BMC + print("Upgrade BMC %s done, reboot it" % fw_extra_str) + if not self.post_to_bmc(self.bmc_reboot_uri, {}): + print "Failed to reboot BMC after upgrade" return False - self.__update_fw_upgrade_logger( - "bmc_upgrade", "done") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + print("Upgrade BMC %s full process done" % fw_extra_str) return True - elif fw_type == 'fpga': - last_fw_upgrade = ["FPGA", fw_path, None, "FAILED"] - self.__update_fw_upgrade_logger( - "fpga_upgrade", "start FPGA upgrade") - - if not os.path.isfile(fw_path): - self.__update_fw_upgrade_logger( - "fpga_upgrade", "fail, message=FPGA image not found %s" % fw_path) - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - return False - + print("FPGA Upgrade") command = 'fpga_prog ' + fw_path - print("Running command : %s" % command) + print("Running command : ", command) process = subprocess.Popen( command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -352,177 +350,42 @@ def firmware_upgrade(self, fw_type, fw_path, fw_extra=None): output = process.stdout.readline() if output == '' and process.poll() is not None: break + if output: + print(output.strip()) - rc = process.returncode - if rc != 0: - self.__update_fw_upgrade_logger( - "fw_upgrade", "fail, message=unable to install FPGA") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - return False - - self.__update_fw_upgrade_logger("fpga_upgrade", "done") - last_fw_upgrade[3] = "DONE" - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - self.firmware_refresh(["FPGA"], None, None) - return True - - elif 'cpld' in fw_type: - self.__update_fw_upgrade_logger( - "cpld_upgrade", "start CPLD upgrade") - # Check input - fw_extra_str = str(fw_extra).upper() - if ":" in fw_path and ":" in fw_extra_str: - fw_path_list = fw_path.split(":") - fw_extra_str_list = fw_extra_str.split(":") + if process.returncode == 0: + rc = self.__fpga_pci_rescan() + if rc != 0: + print("Failed: Unable to load new FPGA firmware") + return False else: - fw_path_list = [fw_path] - fw_extra_str_list = [fw_extra_str] - - if len(fw_path_list) != len(fw_extra_str_list): - self.__update_fw_upgrade_logger( - "cpld_upgrade", "fail, message=invalid input") + print("Failed: Invalid fpga image") return False - data_list = list(zip(fw_path_list, fw_extra_str_list)) - refresh_img_path = None - cpld_result_list = ["FAILED" for i in range( - 0, len(fw_extra_str_list))] - last_fw_upgrade = ["CPLD", ":".join( - fw_path_list), ":".join(fw_extra_str_list), ":".join(cpld_result_list)] - for i in range(0, len(data_list)): - data = data_list[i] - fw_path = data[0] - fw_extra_str = data[1] - - # Set fw_extra - fw_extra_str = { - "TOP_LC_CPLD": "top_lc", - "BOT_LC_CPLD": "bottom_lc", - "FAN_CPLD": "fan", - "CPU_CPLD": "cpu", - "BASE_CPLD": "base", - "COMBO_CPLD": "combo", - "SW_CPLD1": "switch", - "SW_CPLD2": "switch", - "REFRESH_CPLD": "refresh" - }.get(fw_extra_str, None) - - if fw_extra_str == "refresh": - refresh_img_path = fw_path - del cpld_result_list[i] - del fw_extra_str_list[i] - continue - - if fw_extra_str is None: - self.__update_fw_upgrade_logger( - "cpld_upgrade", "fail, message=invalid extra information string") - continue - - # Uploading image to BMC - self.__update_fw_upgrade_logger( - "cpld_upgrade", "start %s upgrade" % data[1]) - upload_file = self.upload_file_bmc(fw_path) - if not upload_file: - self.__update_fw_upgrade_logger( - "cpld_upgrade", "fail, message=unable to upload BMC image to BMC") - continue - - filename_w_ext = os.path.basename(fw_path) - json_data = dict() - json_data["Path"] = "/home/root/%s" % filename_w_ext - json_data["Name"] = "cpld" - - # Call BMC api to install cpld image - print("Installing...") - r = requests.post(self.fw_upgrade_url, json=json_data) - if r.status_code != 200 or r.json().get('status') != 'OK': - self.__update_fw_upgrade_logger( - "cpld_upgrade", "fail, message={}".format(r.json().get('messages'))) - continue - - cpld_result_list[i] = "DONE" - self.__update_fw_upgrade_logger( - "cpld_upgrade", "%s upgrade done" % data[1]) - last_fw_upgrade[3] = ":".join(cpld_result_list) - self.__update_fw_upgrade_logger( - "cpld_upgrade", "done") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - - # Refresh CPLD - refresh_img_str_list = [] - for fw_extra in fw_extra_str_list: - if "BASE_CPLD" in fw_extra or "FAN_CPLD" in fw_extra: - refresh_img_str_list.append(refresh_img_path) - else: - refresh_img_str_list.append("None") - self.firmware_refresh(None, fw_extra_str_list, - ":".join(refresh_img_str_list)) - + print("Done") return True - elif 'bios' in fw_type: - fw_extra_str = str(fw_extra).lower() - if fw_extra_str not in ["master", "slave", "both"]: - return False + print("BIOS Upgrade") - self.__update_fw_upgrade_logger( - "bios_upgrade", "start BIOS upgrade") - last_fw_upgrade = ["BIOS", fw_path, None, "FAILED"] fw_extra_str = str(fw_extra).lower() - flash = fw_extra_str.lower() - - if not os.path.exists(fw_path): - self.__update_fw_upgrade_logger( - "bios_upgrade", "fail, message=image not found") - return False + flash = fw_extra_str if fw_extra_str in ["master", "slave"] else "master" - upload_file = self.upload_file_bmc(fw_path) - if not upload_file: - self.__update_fw_upgrade_logger( - "bios_upgrade", "fail, message=unable to upload image to BMC") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + print("Uploading BIOS image %s to BMC..." % fw_path) + if not self.upload_to_bmc(fw_path): + print("Failed to upload %s to bmc" % fw_path) return False - # json_data = dict() - # json_data["Command"] = "/usr/bin/ipmitool -b 1 -t 0x2c raw 0x2e 0xdf 0x57 0x01 0x00 0x01" - # r = requests.post(self.bmc_raw_command_url, json=json_data) - # if r.status_code != 200: - # self.__update_fw_upgrade_logger( - # "bios_upgrade", "fail, message=unable to set state") - # self.__update_fw_upgrade_logger( - # "last_upgrade_result", str(last_fw_upgrade)) - # return False - - filename_w_ext = os.path.basename(fw_path) - json_data = dict() - json_data["Path"] = "/home/root/%s" % filename_w_ext + image_name = os.path.basename(fw_path) + json_data = {} json_data["Name"] = "bios" + json_data["Path"] = "/tmp/%s" % image_name json_data["Flash"] = flash - print("Installing...") - r = requests.post(self.fw_upgrade_url, json=json_data) - if r.status_code != 200 or r.json().get('status') != 'OK': - self.__update_fw_upgrade_logger( - "bios_upgrade", "fail, message={}".format(r.json().get('messages'))) - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) + if not self.post_to_bmc(self.fw_upgrade_uri, json_data): + print "Failed to upgrade %s BIOS" % flash return False - last_fw_upgrade[3] = "DONE" - self.__update_fw_upgrade_logger( - "bios_upgrade", "done") - self.__update_fw_upgrade_logger( - "last_upgrade_result", str(last_fw_upgrade)) - else: - self.__update_fw_upgrade_logger( - "fw_upgrade", "fail, message=invalid firmware type") - return False - - return True + return True def get_last_upgrade_result(self): """ @@ -744,57 +607,43 @@ def firmware_refresh(self, fpga_list, cpld_list, fw_extra=None): self.firmware_refresh(None, ["FAN_CPLD", "LC1_CPLD", "BASE_CPLD"], "/tmp/fw/fan_refresh.vme:none:/tmp/fw/base_refresh.vme") """ - self.__update_fw_upgrade_logger( - "fw_refresh", "start firmware refresh") - - cpld_list = [x.upper() for x in cpld_list] if cpld_list else [] - fpga_list = [x.upper() for x in fpga_list] if fpga_list else [] - refresh_list = cpld_list + fpga_list - fw_path_list = str(fw_extra).split(':') - refresh_img_list = ["none" for i in range(len(refresh_list))] - - if len(refresh_list) == 0 : - self.__update_fw_upgrade_logger( - "fw_refresh", "fail, message=Invalid input") - return False - - for idx in range(0, len(refresh_list)): - if refresh_list[idx] in ["FAN_CPLD", "BASE_CPLD"]: - if not self.upload_file_bmc(fw_path_list[idx]): - self.__update_fw_upgrade_logger( - "cpld_refresh", "fail, message=Unable to upload refresh image to BMC") - return False - refresh_img_list[idx] = "/home/root/%s" % os.path.basename( - fw_path_list[idx]) + fw_names = [] + fw_files = [] + # FPGA list may contain FPGA and BIOS + if fpga_list: + for name in fpga_list: + fw_names.append(name) + fw_files.append("/tmp/none") + + if cpld_list: + for name in cpld_list: + fw_names.append(name) + + if fw_extra: + for fpath in fw_extra: + if fpath == "none": + continue - json_data = dict() - json_data["Paths"] = refresh_img_list - json_data["Names"] = refresh_list - r = requests.post(self.fw_refresh_url, json=json_data) - if r.status_code != 200 or r.json().get('status') != 'OK': - self.__update_fw_upgrade_logger( - "cpld_refreshfw", "fail, message={}".format(r.json().get('messages'))) + fname = os.path.basename(fpath) + bmc_fpath = "/tmp/%s" % fname + fw_files.append(bmc_fpath) + + if os.path.exists(fpath) and os.path.isfile(fpath): + # upload refresh file to bmc + if not self.upload_to_bmc(fpath): + return False + + data = {} + data["Names"] = fw_names + data["Paths"] = fw_files + #j = json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + if not self.post_to_bmc(self.fw_refresh_uri, data): + print("Failed to refresh firmware") return False - self.__update_fw_upgrade_logger("fw_refresh", "done") - return True - def get_running_bmc(self): - """ - Get booting flash of running BMC. - @return a string, "master" or "slave" - """ - running_bmc = "master" - running_bmc_key = "Flash" - bmc_info_req = requests.get( - self.bmc_info_url, timeout=self.api_time_out) - if bmc_info_req.status_code == 200: - bmc_info_json = bmc_info_req.json() - bmc_info = bmc_info_json.get('data') - running_bmc = bmc_info.get(running_bmc_key) - return str(running_bmc).lower() - def set_bmc_boot_flash(self, flash): """ Set booting flash of BMC @@ -803,8 +652,8 @@ def set_bmc_boot_flash(self, flash): if flash.lower() not in ["master", "slave"]: return False json_data = dict() - json_data["Flash"] = flash - r = requests.post(self.bmc_next_boot, json=json_data) + json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;bmc_reboot %s" % flash + r = requests.post(self.bmc_raw_command_url, json=json_data) if r.status_code != 200: return False return True @@ -813,13 +662,10 @@ def reboot_bmc(self): """ Reboot BMC """ - try: - r = requests.post(self.bmc_reboot_url) - if r.status_code != 200: - return False - except Exception as e: - if "Connection aborted." in e.message[0]: - return True + json_data = dict() + json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;bmc_reboot reboot" + r = requests.post(self.bmc_raw_command_url, json=json_data) + if r.status_code != 200: return False return True @@ -828,39 +674,17 @@ def get_current_bios(self): # Get booting bios image of current running host OS # @return a string, "master" or "slave" """ - bios_boot_info = requests.get( - self.bios_boot_info, timeout=self.api_time_out) - if bios_boot_info.status_code == 200: - bios_boot_info_json = bios_boot_info.json() - bios_boot_info_data = bios_boot_info_json.get('data') - bios_boot = bios_boot_info_data.get("Flash") - return str(bios_boot) - - def get_bios_next_boot(self): - """ - # Get booting bios image of next booting host OS - # @return a string, "master" or "slave" - """ - bios_next_boot = "master" - bios_next_boot_info = requests.get( - self.bios_next_boot, timeout=self.api_time_out) - if bios_next_boot_info.status_code == 200: - bios_next_boot_info_json = bios_next_boot_info.json() - bios_next_boot_info_data = bios_next_boot_info_json.get('data') - bios_next_boot = bios_next_boot_info_data.get("Flash") - return str(bios_next_boot) - - def set_bios_next_boot(self, flash): - """ - # Set booting bios image of next booting host OS - # @return a string, "master" or "slave" - """ - if str(flash).lower() not in ['master', 'slave']: - return False - json_data = dict() - json_data["Flash"] = str(flash).lower() - r = requests.post(self.bios_next_boot, json=json_data) - if r.status_code != 200: - return False - return True + json_data["data"] = "source /usr/local/bin/openbmc-utils.sh;come_boot_info" + r = requests.post(self.bmc_raw_command_url, json=json_data) + try: + cpu_boot_info_list = r.json().get('result') + for cpu_boot_info_raw in cpu_boot_info_list: + if "COMe CPU boots from BIOS" in cpu_boot_info_raw: + bios_image = "master" if "master "in cpu_boot_info_raw.lower( + ) else "slave" + return bios_image + raise Exception( + "Error: Unable to detect current running bios image") + except Exception as e: + raise Exception(e) diff --git a/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/psuutil.py b/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/psuutil.py index 8a0d9334586f..13d98a745827 100644 --- a/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/psuutil.py +++ b/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/psuutil.py @@ -1,47 +1,63 @@ -#!/usr/bin/env python +#!/usr/bin/python -__author__ = 'Wirut G.' -__license__ = "GPL" -__version__ = "0.2.0" -__status__ = "Development" +############################################################################### +# +## PSU utility. +# +## Copyright (C) Alibaba, INC. +# +################################################################################ import requests import re +import json try: from sonic_psu.psu_base import PsuBase except ImportError as e: raise ImportError(str(e) + "- required module not found") -NUM_PSU = 4 - class PsuUtil(PsuBase): - """Platform-specific PSUutil class""" + BMC_REQ_BASE_URI = "http://240.1.1.1:8080/api" def __init__(self): PsuBase.__init__(self) + self.psu_info_uri = "/".join([self.BMC_REQ_BASE_URI, "psu/info"]) + self.psu_num_uri = "/".join([self.BMC_REQ_BASE_URI, "psu/number"]) - self.psu_info_url = "http://240.1.1.1:8080/api/psu/info" - self.all_psu_dict = None + def _get_psu_info(self): + resp = requests.get(self.psu_info_uri) + if not resp: + return False - def request_data(self, url): - try: - r = requests.get(url) - data = r.json() - except Exception as e: - return {} - return data + psu_json = resp.json() + if not psu_json or not "data" in psu_json: + return False + + self.psu_info = psu_json["data"] + + return True def get_num_psus(self): """ Retrieves the number of PSUs available on the device :return: An integer, the number of PSUs available on the device """ + resp = requests.get(self.psu_num_uri) + if not resp: + return -1 - all_psu_dict = self.get_all() + psu_nr_json = resp.json() + if not psu_nr_json or "data" not in psu_nr_json: + return -1 - return all_psu_dict.get('Number', NUM_PSU) + try: + nr_psu = psu_nr_json["data"]["Number"] + except Exception as e: + nr_psu = -1 + + return nr_psu def get_psu_status(self, index): """ @@ -51,11 +67,28 @@ def get_psu_status(self, index): :return: Boolean, True if PSU is operating properly, False if PSU is faulty """ - all_psu_dict = self.get_all() - psu_key = 'PSU{}'.format(index) - psu_info = all_psu_dict.get(psu_key, {}) + # init data + psu_key = "PSU" + str(index) + psu_status_key = "Power Status" + psu_power_status = False + + try: + # Request and validate sensor's information + self.fru_status_list, self.psu_info_list = self.request_data() + + # Get PSU power status. + for fru_status in self.fru_status_list: + is_psu = fru_status.get(psu_key) + psu_status = str(fru_status.get(psu_status_key)).strip() + + if is_psu is not None and psu_status == "OK": + psu_power_status = True + + except: + print("Error: Unable to access PSU power status") + return False - return psu_info.get('PowerStatus', False) + return psu_power_status def get_psu_presence(self, index): """ @@ -64,11 +97,29 @@ def get_psu_presence(self, index): :param index: An integer, 1-based index of the PSU of which to query status :return: Boolean, True if PSU is plugged, False if not """ - all_psu_dict = self.get_all() - psu_key = 'PSU{}'.format(index) - psu_info = all_psu_dict.get(psu_key, {}) - return psu_info.get('Present', False) + # Init data + psu_key = "PSU" + str(index) + psu_presence_key = "Present" + psu_presence_status = False + + try: + # Request and validate sensor's information. + self.fru_status_list, self.psu_info_list = self.request_data() + + # Get PSU present status. + for fru_status in self.fru_status_list: + is_psu = fru_status.get(psu_key) + psu_status = str(fru_status.get(psu_presence_key)).strip() + + if is_psu is not None and psu_status == "Present": + psu_presence_status = True + + except: + print("Error: Unable to access PSU presence status") + return False + + return psu_presence_status def get_psu_sn(self, index): """ @@ -77,12 +128,25 @@ def get_psu_sn(self, index): :param index: An integer, 1-based index of the PSU. :return: Serial number """ + serial_number = "N/A" + psu_key = "PSU" + str(index) + " FRU" + psu_sn_key = "Serial Number" - all_psu_dict = self.get_all() - psu_key = 'PSU{}'.format(index) - psu_info = all_psu_dict.get(psu_key, {}) + try: + # Request and validate sensor's information. + self.fru_status_list, self.psu_info_list = self.request_data() - return psu_info.get('SN', False) + # Get PSU fru info. + for psu_fru in self.psu_info_list: + psu_sn = str(psu_fru.get(psu_sn_key)).strip() + if psu_fru.get(psu_key) is not None: + serial_number = psu_sn if psu_sn.strip() != "" else "N/A" + break + + except: + return "N/A" + + return serial_number def get_psu_pn(self, index): """ @@ -91,12 +155,25 @@ def get_psu_pn(self, index): :param index: An integer, 1-based index of the PSU. :return: Product name """ + product_name = "N/A" + psu_key = "PSU" + str(index) + " FRU" + psu_pn_key = "Product Name" + + try: + # Request and validate sensor's information + self.fru_status_list, self.psu_info_list = self.request_data() + + # Get PSU fru info. + for psu_fru in self.psu_info_list: + psu_pn = str(psu_fru.get(psu_pn_key)).strip() + if psu_fru.get(psu_key) is not None: + product_name = psu_pn if psu_pn.strip() != "" else "N/A" + break + + except: + return "N/A" - all_psu_dict = self.get_all() - psu_key = 'PSU{}'.format(index) - psu_info = all_psu_dict.get(psu_key, {}) - - return psu_info.get('PN', False) + return product_name def get_all(self): """ @@ -107,35 +184,131 @@ def get_all(self): PN, conditional, if PRESENT is True, PN of the PSU, string SN, conditional, if PRESENT is True, SN of the PSU, string """ +#{ +# "Number": 4, +# "PSU1": { +# "AirFlow": "N/A", +# "FanSpeed": { +# "Max": 30000, +# "Min": 1000, +# "Unit": "RPM", +# "Value": -99999 +# }, +# "Inputs": { +# "Current": { +# "HighAlarm": 7.0, +# "LowAlarm": 0.0, +# "Unit": "A", +# "Value": -99999.0 +# }, +# "Power": { +# "HighAlarm": 1220.0, +# "LowAlarm": -1, +# "Unit": "W", +# "Value": -99999.0 +# }, +# "Status": false, +# "Type": "Unknown", +# "Voltage": { +# "HighAlarm": 264.0, +# "LowAlarm": 90.0, +# "Unit": "V", +# "Value": -99999.0 +# } +# }, +# "Outputs": { +# "Current": { +# "HighAlarm": 90.0, +# "LowAlarm": 0.0, +# "Unit": "A", +# "Value": -99999.0 +# }, +# "Power": { +# "HighAlarm": 1100.0, +# "LowAlarm": -1, +# "Unit": "W", +# "Value": -99999.0 +# }, +# "Status": false, +# "Type": "Unknown", +# "Voltage": { +# "HighAlarm": 13.2, +# "LowAlarm": 10.8, +# "Unit": "V", +# "Value": -99999.0 +# } +# }, +# "PN": "", +# "SN": "JHZD1849000585", +# "Temperature": { +# "Max": 70.0, +# "Min": 60.0, +# "Unit": "C", +# "Value": -99999.0 +# } +# } +#} + psu_info = {} + if not self._get_psu_info(): + return psu_info + + #j = json.dumps(self.psu_info, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + + if "Number" not in self.psu_info: + return psu_info + + psu_nr = self.psu_info["Number"] + psu_info["Number"] = psu_nr + for idx in range(1, psu_nr+1): + psu_name = "PSU%d" % idx + if not psu_name in self.psu_info: + print("%s not in self.psu_info" % psu_name) + continue + + pi = self.psu_info[psu_name] + pinfo = {} + try: + pinfo["Present"] = True if pi["Present"] == "yes" else False + pinfo["AirFlow"] = pi["AirFlow"] + pinfo["PN"] = pi["PN"] + pinfo["SN"] = pi["SN"] + except Exception as e: + print("%s not in self.psu_info, exception 1" % psu_name) + continue + + if "Inputs" in pi: + pii = pi["Inputs"] + if "Status" in pii: + try: + pinfo["InputStatus"] = pii["Status"] + pinfo["InputType"] = pii["Type"] + except Exception as e: + pinfo["InputType"] = "N/AA" + + if "Outputs" in pi: + pio = pi["Outputs"] + if "Status" in pio: + try: + pinfo["OutputStatus"] = pio["Status"] + except Exception as e: + pinfo["OutputStatus"] = False + + if "FanSpeed" in pi: + pif = pi["FanSpeed"] + try: + pinfo["Speed"] = pif["Value"] + pinfo["LowThd"] = pif["Min"] + pinfo["HighThd"] = pif["Max"] + except Exception as e: + pinfo["Speed"] = 0 + pinfo["LowThd"] = 0 + pinfo["HighThd"] = 0 + + psu_info[psu_name] = pinfo + + #j = json.dumps(psu_info, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + + return psu_info - if not self.all_psu_dict: - all_psu_dict = dict() - - psu_info_req = self.request_data(self.psu_info_url) - psu_info_data = psu_info_req.get('data', {}) - all_psu_dict["Number"] = psu_info_data.get('Number', NUM_PSU) - - for psu_idx in range(1, all_psu_dict["Number"] + 1): - psu_key = 'PSU{}'.format(str(psu_idx)) - psu_info = psu_info_data.get(psu_key, {}) - psu_input_info = psu_info.get('Inputs', {}) - psu_output_info = psu_info.get('Outputs', {}) - - psu_info_dict = dict() - psu_info_dict["InputType"] = psu_input_info.get("Type", "N/A") - psu_info_dict["InputStatus"] = True if psu_input_info.get( - "Status") else False - psu_info_dict["OutputStatus"] = True if psu_output_info.get( - "Status") else False - psu_info_dict["PowerStatus"] = ( - psu_info_dict["InputStatus"] and psu_info_dict["OutputStatus"]) - psu_info_dict["PN"] = psu_info.get("PN", "N/A") - psu_info_dict["SN"] = psu_info.get("SN", "N/A") - psu_info_dict["Present"] = True if psu_info.get("Present") == 'yes' else False - psu_info_dict["AirFlow"] = psu_info.get("AirFlow", "N/A") - - all_psu_dict[psu_key] = psu_info_dict - - self.all_psu_dict = all_psu_dict - - return self.all_psu_dict diff --git a/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/sensorutil.py b/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/sensorutil.py index efed1e850306..4b5a7e3d4519 100644 --- a/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/sensorutil.py +++ b/device/alibaba/x86_64-alibaba_as23-128h-cl-r0/plugins/sensorutil.py @@ -1,206 +1,115 @@ -#!/usr/bin/env python +#!/usr/bin/python + +############################################################################### +# +### Sensor utility. +# +### Copyright (C) Alibaba, INC. +# +################################################################################# -__author__ = 'Wirut G.' -__license__ = "GPL" -__version__ = "0.2.0" -__status__ = "Development" import requests +import json class SensorUtil(): - """Platform-specific SensorUtil class""" + BMC_REQ_BASE_URI = "http://240.1.1.1:8080/api" def __init__(self): - self.sensor_info_url = "http://240.1.1.1:8080/api/sensor/info" - self.all_sensor_dict = None - - def request_data(self, url): - try: - r = requests.get(url) - data = r.json() - except Exception as e: - return {} - return data - - def input_type_selector(self, unit): - # Set input type. - return { - "C": "temperature", - "V": "voltage", - "RPM": "RPM", - "A": "amp", - "W": "power" - }.get(unit, unit) - - def input_name_selector(self, raw_sensor_name): - - sensor_name_list = raw_sensor_name.split('_') - sensor_name = sensor_name_list[0] - input_name = '_'.join(sensor_name_list[1:]) - - if sensor_name_list[0] in ["TOP", "BOTTOM"]: - sensor_name = '_'.join(sensor_name_list[0:2]) - input_name = '_'.join(sensor_name_list[2:]) - - return str(sensor_name).upper(), str(input_name).upper() - - def get_num_sensors(self): - """ - Get the number of sensors - :return: int num_sensors - """ - - all_sensor_dict = self.get_all() - - return len(all_sensor_dict) - - def get_sensor_input_num(self, index): - """ - Get the number of the input items of the specified sensor - :return: int input_num - """ - - all_sensor_dict = self.get_all() - ss_keys = all_sensor_dict.keys()[index] - sensor_info = all_sensor_dict.get(ss_keys, {}) - ss_if_keys = sensor_info.keys() - - return len(ss_if_keys) - - def get_sensor_name(self, index): - """ - Get the device name of the specified sensor. - for example "coretemp-isa-0000" - :return: str sensor_name - """ - all_sensor_dict = self.get_all() - sensor_name = all_sensor_dict.keys()[index] - - return sensor_name - - def get_sensor_input_name(self, sensor_index, input_index): - """ - Get the input item name of the specified input item of the - specified sensor index, for example "Physical id 0" - :return: str sensor_input_name - """ - - all_sensor_dict = self.get_all() + self.sensor_info_uri = "/".join([self.BMC_REQ_BASE_URI, "sensor/info"]) + self.sensor_info = None - ss_keys = all_sensor_dict.keys()[sensor_index] - sensor_info = all_sensor_dict.get(ss_keys, {}) - ss_if_keys = sensor_info.keys()[input_index] + def _get_sensor_info(self): + resp = requests.get(self.sensor_info_uri) + if not resp: + return False - return ss_if_keys + sensor_json = resp.json() + if not sensor_json or not "data" in sensor_json: + return False - def get_sensor_input_type(self, sensor_index, input_index): - """ - Get the item type of the specified input item of the specified sensor index, - The return value should among "valtage","temperature" - :return: str sensor_input_type - """ + self.sensor_info = sensor_json["data"] - all_sensor_dict = self.get_all() + return True - ss_keys = all_sensor_dict.keys()[sensor_index] - sensor_info = all_sensor_dict.get(ss_keys, {}) + def get_sys_airflow(self): + sys_air_flow = "Unknown" - ss_if_keys = sensor_info.keys()[input_index] - sensor_input_info = sensor_info.get(ss_if_keys, {}) + sys_pn = sys_pn_data[0][1] + if "R1240-F0001" in sys_pn: + sys_air_flow = "FTOB" + elif"R1240-F0002" in sys_pn: + sys_air_flow = "BTOF" - sensor_input_type = sensor_input_info.get('Type', "N/A") - return sensor_input_type + return sys_air_flow - def get_sensor_input_value(self, sensor_index, input_index): - """ - Get the current value of the input item, the unit is "V" or "C" - :return: float sensor_input_value - """ + def _get_type(self, unit_str): + unit2type = {"C": "temperature", "A": "amp", "V": "voltage", + "RPM": "RPM", "W": "power"} - all_sensor_dict = self.get_all() + if unit_str in unit2type: + return unit2type[unit_str] + return None - ss_keys = all_sensor_dict.keys()[sensor_index] - sensor_info = all_sensor_dict.get(ss_keys, {}) - - ss_if_keys = sensor_info.keys()[input_index] - sensor_input_info = sensor_info.get(ss_if_keys, {}) - - sensor_input_value = sensor_input_info.get('Value', 0.0) - return sensor_input_value - - def get_sensor_input_low_threshold(self, sensor_index, input_index): - """ - Get the low threshold of the value, - the status of this item is not ok if the current value high_threshold - :return: float sensor_input_high_threshold - """ - all_sensor_dict = self.get_all() - - ss_keys = all_sensor_dict.keys()[sensor_index] - sensor_info = all_sensor_dict.get(ss_keys, {}) - - ss_if_keys = sensor_info.keys()[input_index] - sensor_input_info = sensor_info.get(ss_if_keys, {}) - - sensor_input_high_threshold = sensor_input_info.get('HighThd', 0.0) - return sensor_input_high_threshold + def get_num_sensors(self): + sensor_dict = self.get_all() + sum = 0 + for sensor_name, sensor_obj in sensor_dict.items(): + if cmp(sensor_name, 'Number') == 0: + continue + sum += len(sensor_obj.keys()) + return sum def get_all(self): - """ - Get all information of system sensors, returns JSON objects in python 'DICT'. - SensorName1, SensorName2, ... optional, string - SensorInput1, SensorInput2, ... optional, string - Type, mandatory in SensorInput$INDEX, should be on of { "temperature", "voltage", "power", "amp", "RPM" } - Value, mandatory in SensorInput$INDEX, float , real value - LowThd, mandatory in SensorInput$INDEX, float , lower bound of value - HighThd, mandatory in SensorInput$INDEX, float , upper bound of value - Return python 'dict' objects, example: - """ - - if not self.all_sensor_dict: - all_sensor_dict = dict() - - sensor_info_req = self.request_data(self.sensor_info_url) - sensor_info_data = sensor_info_req.get('data', {}) - - for raw_ss_name, sensor_info in sensor_info_data.items(): - - sensor_name, input_name = self.input_name_selector(raw_ss_name) - sensor_dict = all_sensor_dict.get(sensor_name, {}) - new_sensor_dict = dict() - new_sensor_dict["Type"] = self.input_type_selector( - sensor_info.get('Unit', 'N/A')) - new_sensor_dict["Value"] = float(sensor_info.get('Value', 0.0)) - new_sensor_dict["HighThd"] = float(sensor_info.get('Max', 0.0)) - new_sensor_dict["LowThd"] = float(sensor_info.get('Min', 0.0)) - - if sensor_dict == {}: - all_sensor_dict[sensor_name] = dict() - - input_name = input_name if input_name != '' else new_sensor_dict["Type"].upper( - ) - sensor_dict[input_name] = new_sensor_dict - all_sensor_dict[sensor_name].update(sensor_dict) - - self.all_sensor_dict = all_sensor_dict - - return self.all_sensor_dict + sensor_info = {} + + if not self._get_sensor_info(): + return sensor_info + + sname_temp_cl = ["Cpu", "Inlet", "Switch"] + sname_temp_rj = ["CPU_TEMP", "INLET_TEMP", "SWITCH_TEMP"] + for si_name, si_val in self.sensor_info.items(): + if si_name.startswith("PSU"): + sname = si_name.split("_")[0] + if si_name.find("Temperature") != -1: + new_si_name = "%s_TEMP" % sname + si_name = new_si_name + elif si_name in sname_temp_cl: + sname = "TEMPERATURE" + new_si_name = "%s_temp" % si_name + si_name = new_si_name.upper() + elif si_name in sname_temp_rj: + sname = "TEMPERATURE" + elif si_name.startswith("CPU"): + sname = "CPU" + elif si_name.startswith("FAN"): + sname = "FAN" + elif si_name.startswith("Switch") or \ + si_name.startswith("SWITCH") or \ + si_name.find("_LC_") != -1: + sname = "SWITCH" + elif si_name.startswith("SYS") or \ + si_name.startswith("Baseboard"): + sname = "SYSTEM" + else: + sname = "OTHER" + + si_info = {} + si_info["LowThd"] = si_val["Min"] + si_info["HighThd"] = si_val["Max"] + si_info["Value"] = si_val["Value"] + type = self._get_type(si_val["Unit"]) + if not type: + continue + si_info["Type"] = type + + if sname not in sensor_info: + sensor_info[sname] = {} + + sensor_info[sname][si_name] = si_info + + #j = json.dumps(self.sensor_info, sort_keys=True, indent=4, separators=(',', ': ')) + #print j + + return sensor_info