openGauss-OM/script/gspylib/inspection/items/os/CheckMaxProcMemory.py
2020-12-16 17:25:24 +08:00

167 lines
6.4 KiB
Python

# -*- 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 os
import subprocess
import json
import multiprocessing
from gspylib.inspection.common import SharedFuncs
from gspylib.inspection.common.CheckItem import BaseItem
from gspylib.inspection.common.CheckResult import ResultStatus
from gspylib.inspection.common.Exception import CheckNAException
from gspylib.common.ErrorCode import ErrorCode
# master
MASTER_INSTANCE = 0
# standby
STANDBY_INSTANCE = 1
# dummy standby
DUMMY_STANDBY_INSTANCE = 2
# cn
INSTANCE_ROLE_COODINATOR = 3
# dn
INSTANCE_ROLE_DATANODE = 4
g_gucDist = {}
RecommendedMaxMem = 0
class CheckMaxProcMemory(BaseItem):
def __init__(self):
super(CheckMaxProcMemory, self).__init__(self.__class__.__name__)
self.Threshold_NG = None
def preCheck(self):
super(CheckMaxProcMemory, self).preCheck()
# check the threshold was set correctly
if (not self.threshold.__contains__('Threshold_NG')):
raise Exception(ErrorCode.GAUSS_530["GAUSS_53013"]
% "The threshold Threshold_NG")
if (not self.threshold['Threshold_NG'].isdigit()):
raise Exception(ErrorCode.GAUSS_530["GAUSS_53014"]
% "The threshold Threshold_NG")
self.Threshold_NG = int(self.threshold['Threshold_NG'])
def checkInstanceGucValue(self, Instance):
"""
get CN/DN instance guc parameters
"""
global g_gucDist
Role = ""
needm = False
if (Instance.instanceRole == INSTANCE_ROLE_COODINATOR):
needm = False
elif (self.checkMaster(Instance.instanceId)):
needm = False
else:
needm = True
sqlcmd = "select setting from pg_settings " \
"where name='max_process_memory';"
output = SharedFuncs.runSqlCmd(sqlcmd, self.user, "", Instance.port,
self.tmpPath, "postgres",
self.mpprcFile, needm)
if (Instance.instanceRole == INSTANCE_ROLE_COODINATOR):
Role = "CN"
elif (Instance.instanceRole == INSTANCE_ROLE_DATANODE):
Role = "DN"
instanceName = "%s_%s" % (Role, Instance.instanceId)
g_gucDist[instanceName] = output
def checkMaster(self, instanceId):
cmd = "gs_om -t query |grep %s" % (instanceId)
output = SharedFuncs.runShellCmd(cmd, self.user, self.mpprcFile)
line = output.splitlines()[0]
instanceinfo = line.split()
for idx in range(len(instanceinfo)):
if (instanceinfo[idx] == str(instanceId)):
if (instanceinfo[idx + 2] == "Primary"):
return True
else:
return False
return False
def doCheck(self):
"""
"""
global g_gucDist
global RecommendedMaxMem
DNidList = []
nodeInfo = self.cluster.getDbNodeByName(self.host)
CN = nodeInfo.coordinators
for DnInstance in nodeInfo.datanodes:
if (self.checkMaster(DnInstance.instanceId)):
DNidList.append(DnInstance)
if (len(CN) < 1 and len(DNidList) < 1):
self.result.rst = ResultStatus.NA
self.result.val = "NA"
return
# test database Connection
for Instance in (CN + DNidList):
if not Instance:
continue
sqlcmd = "select pg_sleep(1);"
output = SharedFuncs.runSqlCmd(sqlcmd, self.user, "",
Instance.port, self.tmpPath,
'postgres',
self.mpprcFile)
self.checkInstanceGucValue(Instance)
cmd = "/sbin/sysctl -a |grep vm.min_free_kbytes|awk '{print $3}'"
min_free_kbytes = int(SharedFuncs.runShellCmd(cmd).splitlines()[-1])
cmd = "free -k | grep 'Mem'| grep -v 'grep'|awk '{print $2}'"
raw = int(SharedFuncs.runShellCmd(cmd))
if (min_free_kbytes * 100 > raw * 5):
RecommendedMaxMem = int((raw * 0.7) // (len(DNidList) + 1))
else:
RecommendedMaxMem = int((raw * 0.8) // (len(DNidList) + 1))
self.result.rst = ResultStatus.OK
result = "RecommendedMaxMem is %s\n" % RecommendedMaxMem
for key, value in g_gucDist.items():
if (int(value) > RecommendedMaxMem):
self.result.rst = ResultStatus.NG
result += "%s : %s\n" % (key, value)
if (self.result.rst == ResultStatus.OK):
self.result.val = "parameter max_process_memory setting is ok"
else:
self.result.val = "parameter max_process_memory " \
"setting should not be bigger than " \
"recommended(kb):%s:\n%s" % (
RecommendedMaxMem, result)
def doSet(self):
resultStr = ""
cmd = "su - %s -c \"source %s;gs_guc set " \
"-N all -I all -c 'max_process_memory=%s'\"" % (
self.user, self.mpprcFile, RecommendedMaxMem)
(status, output) = subprocess.getstatusoutput(cmd)
if (status != 0):
resultStr += "Set CN instance Failed.\n Error : %s." % output
resultStr += "The cmd is %s " % cmd
cmd = "su - %s -c \"source %s;gs_guc set " \
"-N all -I all -c 'max_process_memory=%s'\"" % (
self.user, self.mpprcFile, RecommendedMaxMem)
(status, output) = subprocess.getstatusoutput(cmd)
if (status != 0):
resultStr += "Set database node instance Failed.\n " \
"Error : %s." % output
resultStr += "The cmd is %s " % cmd
if (len(resultStr) > 0):
self.result.val = resultStr
else:
self.result.val = "Set max_process_memory successfully."