#!/usr/bin/python2 import os import re import time from datetime import datetime import subprocess from .. import data_manager from ..common_fn import exec_cmd_and_get_list, exec_cmd_and_set_object_by_key,\ get_scan_summary_no_shift, exe_shell_cmd_and_check_output, get_current_time from .. import scanner_logger, mem_logger, stresser_logger from .. picasso import Picasso class nvdimm(object): def __init__(self): self.is_scan = False self.scan_result = None self.test_result = None self.nvdimmFlagFile = '{0}/nvdimmFlag'.format(data_manager._log_dir) self.question_destroy_data = 'Do you want to destroy the backup data on NVDIMM?' self.warning_power_cycle = 'System will power cycle and wait NVDIMM backup' self.arm_message = 'Arm NVDIMM and write pattern to DRAM' self.dis_arm_message = 'Dis-Arm NVDIMM and verify pattern' self.diag_ui = Picasso() def start(self): pass def stop(self): pass def scan(self, dev_config): self.dev_config = dev_config title = ["DIMM", "Size", "Speed", "Rank", "Manufacturer", "PN", "SN"] scanner_logger.info("=======================================================") scanner_logger.info("NVDIMM:") self.print_info(title) scan_cmd = ("diag -d mem -p nvdimm -t showdata") resp, output = exe_shell_cmd_and_check_output(scan_cmd) if resp: self.dev_id_list = re.findall('(?<=Slot )[0-9]+', output) self.show_dev_info(self.dev_id_list) self.is_scan = True return self.dev_id_list def show_dev_info(self, dev_id_list): for dev_id in dev_id_list: for dev_info in data_manager.mem_obj_list: if dev_info['slot'] == dev_id: self.print_info( [dev_info['name'], dev_info["Size"], dev_info['Speed'], dev_info['Rank'], dev_info['Manufacturer'], dev_info['Part Number'], dev_info['Serial Number']]) return def print_info(self, info_list): if len(info_list) < 7: return scanner_logger.info( "{0:<7} {1:<9} {2:<9} {3:<5} {4:<19} {5:<22} {6:<9}".format( info_list[0], info_list[1], info_list[2], info_list[3], info_list[4], info_list[5], info_list[6])) def scan_summary(self): if not self.is_scan: scanner_logger.info("Has not scan NVDIMM yet.") return False scanner_logger.info('') scanner_logger.info(get_scan_summary_no_shift( "NVDIMM", len(self.dev_config), len(self.dev_id_list))) self.print_summary_info(["Slot", "PN", "SN"]) for dev_id in self.dev_id_list: for dev in data_manager.mem_obj_list: if dev['slot'] == dev_id: self.print_summary_info( [dev['name'], dev["Part Number"], dev["Serial Number"]]) def print_summary_info(self, info_list): if len(info_list) < 3: return scanner_logger.info("{0:<13} {1:<22} {2}".format( info_list[0], info_list[1], info_list[2])) def is_valid_data(self, reg80, nvdimm): if (int(reg80, 16) & 0x1): mem_logger.info('NVDIMM {} has valid data!'.format( nvdimm)) return True else: mem_logger.info('NVDIMM {} has no valid data!'.format( nvdimm)) return False def i2cget_byte(self, bus, slave_address, data_address): cmd = 'i2cget -y {} {} {} b'.format(bus, hex(slave_address), hex(data_address)) resp, output = exe_shell_cmd_and_check_output(cmd) if not resp: return '' return output.strip() def has_valid_data(self): # for 8+1: # NVDIMM on DIMM slot 11 # DIMM slot 11: bus:2, slave address with r/w bit:0x88 if len(self.dev_id_list) == 1: data = self.i2cget_byte(2, 0x88 >> 1, 0x80) return self.is_valid_data(data, self.dev_id_list[0]) # for 20+2: # NVDIMM on DIMM slot 10 and 21 # DIMM slot 10: bus:2, slave address with r/w bit:0x8a # DIMM slot 21: bus:4, slave address with r/w bit:0x8a if len(self.dev_id_list) == 2: data = self.i2cget_byte(2, 0x8a >> 1, 0x80) result = self.is_valid_data(data, self.dev_id_list[0]) if result: return True data = self.i2cget_byte(4, 0x8a >> 1, 0x80) result = self.is_valid_data(data, self.dev_id_list[1]) if result: return True # has no valid data return False def arm_nvdimm_and_write_pattern_to_dram(self): mem_logger.info("\nNVDIMM Test The First Half Start: {}\n".format(get_current_time())) start_time = datetime.now() mem_logger.info(self.arm_message) cmd = 'diag -d mem -p nvdimm -t patternstore' resp, result = exe_shell_cmd_and_check_output(cmd) if resp: mem_logger.info(result) # set NVDIMM pattern check flag mem_logger.info("Set NVDIMM pattern check flag") open(self.nvdimmFlagFile, 'a').close() mem_logger.info("Sync file system, force check flag be saved") subprocess.call("sync; sync; sync", shell=True) stop_time = datetime.now() elapsed_time = stop_time - start_time mem_logger.info("\nNVDIMM Test The First Half Stop: {}\n".format(get_current_time())) mem_logger.info('------------------------------------------------\n') mem_logger.info("Elapsed Time: {}\n".format(elapsed_time)) mem_logger.info('------------------------------------------------\n') mem_logger.info(self.warning_power_cycle) mem_logger.info("Chassis Power Control: Cycle") # wait for log be flush time.sleep(3) subprocess.call("ipmitool chassis power cycle", shell=True) else: mem_logger.error('Arm NVDIMM and write pattern to DRAM failed') def test(self): if not data_manager.is_logpath_exist: mem_logger.info('Warning: Persistent storage is not available.') mem_logger.info("The NVDIMM test can't continue") return None # if no NVDIMM flag in NVMe if not os.path.isfile(self.nvdimmFlagFile): hasValidData = self.has_valid_data() if hasValidData: # show warning messages and user interaction menu self.answer_destroy_data = self.diag_ui.show_yesno_dialog(self.question_destroy_data) if 'ok' == self.answer_destroy_data: self.arm_nvdimm_and_write_pattern_to_dram() else: return None else: # handle no valid data self.arm_nvdimm_and_write_pattern_to_dram() # if NVDIMM flag in NVMe else: mem_logger.info("\nNVDIMM Test The Second Half Start: {}\n".format(get_current_time())) start_time = datetime.now() mem_logger.info(self.dis_arm_message) cmd = 'diag -d mem -p nvdimm -t patternverify' resp, result = exe_shell_cmd_and_check_output(cmd) if resp: # clear NVDIMM pattern check flag os.remove(self.nvdimmFlagFile) mem_logger.info('Clear NVDIMM pattern check flag') mem_logger.info(result) stop_time = datetime.now() elapsed_time = stop_time - start_time mem_logger.info("\nNVDIMM Test The Second Half Stop: {}\n".format(get_current_time())) mem_logger.info('------------------------------------------------\n') mem_logger.info("Elapsed Time: {}\n".format(elapsed_time)) mem_logger.info('------------------------------------------------\n') else: mem_logger.error('Disarm NVDIMM and verify DRAM failed') def stress(self): pass