# -*- coding:utf-8 -*- # Copyright (c) 2020 Huawei Technologies Co.,Ltd. # # openGauss is licensed under Mulan PSL v2. # You can use this software according to the terms # and conditions of the Mulan PSL v2. # You may obtain a copy of Mulan PSL v2 at: # # http://license.coscl.org.cn/MulanPSL2 # # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, # WITHOUT WARRANTIES OF ANY KIND, # EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, # MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. # See the Mulan PSL v2 for more details. # ---------------------------------------------------------------------------- import subprocess from gspylib.inspection.common import SharedFuncs from gspylib.inspection.common.CheckItem import BaseItem from gspylib.inspection.common.CheckResult import ResultStatus from gspylib.common.ErrorCode import ErrorCode from gspylib.common.Common import DefaultValue from base_utils.os.cmd_util import CmdUtil from base_utils.os.file_util import FileUtil from base_utils.os.net_util import NetUtil needRepairNetworkCardNum = [] networkCardNums = [] netWorkLevel = 10000 class CheckMultiQueue(BaseItem): def __init__(self): super(CheckMultiQueue, self).__init__(self.__class__.__name__) def doCheck(self): global needRepairNetworkCardNum global networkCardNums flag = "Normal" self.result.val = "" self.result.raw = "" if self.cluster: LocalNodeInfo = self.cluster.getDbNodeByName(self.host) backIP = LocalNodeInfo.backIps[0] elif self.ipAddr: backIP = self.ipAddr else: backIP = SharedFuncs.getIpByHostName(self.host) # Get the network card number allNetworkInfo = NetUtil.getAllNetworkInfo() for network in allNetworkInfo: if network.ipAddress == backIP: networkNum = network.NICNum BondMode = network.networkBondModeInfo confFile = network.networkConfigFile break if not networkNum or not BondMode or not confFile: if DefaultValue.checkDockerEnv(): return raise Exception(ErrorCode.GAUSS_506["GAUSS_50619"]) if BondMode != "BondMode Null": bondFile = '/proc/net/bonding/%s' % networkNum bondInfoList = FileUtil.readFile(bondFile, "Slave Interface") for bondInfo in bondInfoList: networkNum = bondInfo.split(':')[-1].strip() networkCardNums.append(networkNum) else: networkCardNums.append(networkNum) for networkCardNum in networkCardNums: cmdGetSpeedStr = "/sbin/ethtool %s | grep 'Speed:'" \ % networkCardNum (status, output) = subprocess.getstatusoutput(cmdGetSpeedStr) if len(output.split('\n')) > 1: for line in output.split('\n'): if line.find("Speed:") >= 0: output = line break if output.find("Speed:") >= 0 and output.find("Mb/s") >= 0: netLevel = int(output.split(':')[1].strip()[:-4]) if netLevel >= int(netWorkLevel): cmd = "for i in `cat /proc/interrupts | grep '%s-' |" \ " awk -F ' ' '{print $1}' | " \ "awk -F ':' '{print $1}'`; " \ "do cat /proc/irq/$i/smp_affinity ; done" \ % networkCardNum (status, output) = subprocess.getstatusoutput(cmd) if status != 0: self.result.val += "Failed to obtain network card" \ " [%s] interrupt value. " \ "Commands for getting interrupt" \ " value: %s.\n" % (networkCardNum, cmd) if networkCardNum not in needRepairNetworkCardNum: needRepairNetworkCardNum.append(networkCardNum) flag = "Error" continue # cpu core number followed by 1 2 4 8,every 4 left shift 1 Mapping = {0: "1", 1: "2", 2: "4", 3: "8"} for index, eachLine in enumerate(output.split()): # Remove the ',' eachLine = eachLine.replace(",", "") # Replace 0000,00001000 to 1,Remove invalid content validValue = eachLine.replace("0", "") # Convert the row index to the expected value expandNum = Mapping[index % 4] # Convert line index to expected position expandBit = index / 4 * -1 - 1 # value and position is correct if (len(eachLine) * -1) > expandBit: self.result.val += "Network card [%s] " \ "multi-queue support is not" \ " enabled.\n" % networkCardNum flag = "Error" break if (eachLine[expandBit] == expandNum and validValue == expandNum): continue else: self.result.val += "Network card [%s] " \ "multi-queue support is " \ "not enabled.\n" \ % networkCardNum if (networkCardNum not in needRepairNetworkCardNum): needRepairNetworkCardNum.append( networkCardNum) flag = "Error" break self.result.raw += "%s: \n %s \n" \ % (networkCardNum, output) else: self.result.val += "Warning: The speed of current card" \ " \"%s\" is less than %s Mb/s.\n" \ % (networkCardNum, netWorkLevel) else: if output.find("Speed:") >= 0: if (networkCardNum not in needRepairNetworkCardNum): needRepairNetworkCardNum.append(networkCardNum) flag = "Error" self.result.val += "Failed to obtain the network card" \ " [%s] speed value. Maybe the network" \ " card is not working.\n" \ % networkCardNum else: self.result.val += "Failed to obtain the network" \ " card [%s] speed value. Commands" \ " for obtain the network card speed:" \ " %s. Error:\n%s\n" \ % (networkCardNum, cmdGetSpeedStr, output) if flag == "Normal": self.result.rst = ResultStatus.OK elif flag == "Warning": self.result.rst = ResultStatus.WARNING else: self.result.rst = ResultStatus.NG def doSet(self): self.result.val = "" cmd = "ps ax | grep -v grep | grep -q irqbalance; echo $?" (status, output) = subprocess.getstatusoutput(cmd) if status != 0 and output.strip() == "0": subprocess.getstatusoutput("%s irqbalance" % CmdUtil.findCmdInPath("killall")) for networkCardNum in networkCardNums: cmd = "cat /proc/interrupts | grep '%s-' | wc -l" % networkCardNum (status, output) = subprocess.getstatusoutput(cmd) if status != 0: self.result.val += " Failed to obtain network" \ " card interrupt count numbers. " if not str(output.strip()).isdigit(): count = 0 else: count = int(output.strip()) i = 0 while i < count: # the dev name type like this: # eth1-1, eth1-rx-1, eth1-tx-1, eth1-TxRx-1 # eth1-rx1, eth-tx1 in arm, get all network name interrupt cmd_IRQ = "cat /proc/interrupts | grep '%s.*-' |" \ " awk -F ' ' '{print $1}' | " \ "awk -F ':' '{print $1}'|awk 'NR==%s'" \ % (networkCardNum, str(i + 1)) (status, output) = subprocess.getstatusoutput(cmd_IRQ) if status != 0 or output.strip() == "": self.result.val = "Failed to obtain network card" \ " interrupt value. Commands for " \ "getting interrupt value: %s." % cmd_IRQ else: IRQ = output.strip() self.result.raw += "The network '%s' interrupt" \ " configuration path:" \ " /proc/irq/%s/smp_affinity." \ % (networkCardNum, IRQ) num = 2 ** i # Under SuSE platform, when the length is greater than 8, # the ',' must be used. value = str(hex(num))[2:] # Decimal 63 or more long number sending in L if len(value) > 16 and value[-1] == 'L': value = value[:-1] result_value = '' while len(value) > 8: result_value = ",%s%s" % (value[-8:], result_value) value = value[:-8] result_value = "%s%s" % (value, result_value) cmd_set = "echo '%s'> /proc/irq/%s/smp_affinity" % ( result_value, IRQ) (status, output) = subprocess.getstatusoutput(cmd_set) if status != 0: self.result.val += "Failed to set network '%s' IRQ." \ " Commands for setting: %s." \ % (networkCardNum, cmd_set) else: self.result.val += "Set network card '%s' IRQ" \ " to \"%s\"." % (networkCardNum, result_value) i += 1