572 lines
21 KiB
Python
572 lines
21 KiB
Python
# -*- coding:utf-8 -*-
|
|
#############################################################################
|
|
# Portions Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
|
# Portions Copyright (c) 2007 Agendaless Consulting and Contributors.
|
|
#
|
|
# 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.
|
|
# ----------------------------------------------------------------------------
|
|
# Description : net_util.py is a utility to do something for network information.
|
|
#############################################################################
|
|
import os
|
|
import re
|
|
import socket
|
|
import subprocess
|
|
import sys
|
|
import _thread
|
|
import time
|
|
|
|
from gspylib.common.ErrorCode import ErrorCode
|
|
from base_utils.os.cmd_util import CmdUtil
|
|
from base_utils.os.network_info import NetworkInfo
|
|
from base_utils.security.security_checker import SecurityChecker
|
|
from gspylib.threads.parallelTool import parallelTool
|
|
from os_platform.UserPlatform import g_Platform
|
|
|
|
localDirPath = os.path.dirname(os.path.realpath(__file__))
|
|
sys.path.insert(0, localDirPath + "/../../../lib/netifaces/")
|
|
from netifaces import interfaces, ifaddresses, AF_INET, AF_INET6
|
|
sys.path.insert(0, localDirPath + "/../../../lib")
|
|
try:
|
|
import psutil
|
|
except ImportError as e:
|
|
if not bool(os.listdir(localDirPath + "/../../../lib")):
|
|
raise
|
|
# mv psutil mode .so file by python version
|
|
pythonVer = str(sys.version_info[0]) + '.' + str(sys.version_info[1])
|
|
psutilLinux = os.path.join(localDirPath,
|
|
"./../../../lib/psutil/_psutil_linux.so")
|
|
psutilPosix = os.path.join(localDirPath,
|
|
"./../../../lib/psutil/_psutil_posix.so")
|
|
psutilLinuxBak = "%s_%s" % (psutilLinux, pythonVer)
|
|
psutilPosixBak = "%s_%s" % (psutilPosix, pythonVer)
|
|
|
|
glo_cmd = "rm -rf '%s' && cp -r '%s' '%s' " % (psutilLinux,
|
|
psutilLinuxBak,
|
|
psutilLinux)
|
|
glo_cmd += " && rm -rf '%s' && cp -r '%s' '%s' " % (psutilPosix,
|
|
psutilPosixBak,
|
|
psutilPosix)
|
|
psutilFlag = True
|
|
for psutilnum in range(3):
|
|
(status_mvPsutil, output_mvPsutil) = subprocess.getstatusoutput(
|
|
glo_cmd)
|
|
if status_mvPsutil != 0:
|
|
psutilFlag = False
|
|
time.sleep(1)
|
|
else:
|
|
psutilFlag = True
|
|
break
|
|
if not psutilFlag:
|
|
print("Failed to execute cmd: %s. Error:\n%s" % (glo_cmd,
|
|
output_mvPsutil))
|
|
sys.exit(1)
|
|
# del error import and reload psutil
|
|
del sys.modules['psutil._common']
|
|
del sys.modules['psutil._psposix']
|
|
import psutil
|
|
|
|
|
|
|
|
g_failed_address_list = []
|
|
g_lock = _thread.allocate_lock()
|
|
|
|
|
|
class NetUtil(object):
|
|
"""net util"""
|
|
|
|
@staticmethod
|
|
def GetHostIpOrName():
|
|
"""
|
|
function: Obtaining the local IP address
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
env_dist = os.environ
|
|
if "HOST_IP" not in list(env_dist.keys()):
|
|
return NetUtil.getHostName()
|
|
host_ip = env_dist.get("HOST_IP")
|
|
if host_ip is not None and NetUtil.isIpValid(host_ip):
|
|
return host_ip
|
|
try:
|
|
host_ip = socket.gethostbyname(socket.gethostname())
|
|
except Exception as e:
|
|
raise e
|
|
return host_ip
|
|
|
|
@staticmethod
|
|
def getHostName():
|
|
"""
|
|
function : Get host name
|
|
input : NA
|
|
output: string
|
|
"""
|
|
host_cmd = CmdUtil.findCmdInPath("hostname")
|
|
(status, output) = subprocess.getstatusoutput(host_cmd)
|
|
# if cmd failed, then exit
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] % "host name"
|
|
+ "The cmd is %s" % host_cmd)
|
|
return output
|
|
|
|
@staticmethod
|
|
def isIpValid(ip_address):
|
|
"""
|
|
function : check if the input ip address is valid
|
|
input : String
|
|
output : bool
|
|
"""
|
|
Valid = re.match(r"^(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|"
|
|
r"[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9]["
|
|
r"0-9]"
|
|
r"|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9]"
|
|
r"[0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|"
|
|
r"[1-9][0-9]|[0-9])$", ip_address)
|
|
return Valid and Valid.group() == ip_address
|
|
|
|
@staticmethod
|
|
def executePingCmd(ip_address):
|
|
"""
|
|
function : Send the network command of ping.
|
|
input : String
|
|
output : NA
|
|
"""
|
|
ping_cmd = CmdUtil.getPingCmd(ip_address, "5", "1")
|
|
cmd = "%s | %s ttl | %s -l" % (ping_cmd, CmdUtil.getGrepCmd(),
|
|
CmdUtil.getWcCmd())
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if str(output) == '0' or status != 0:
|
|
g_lock.acquire()
|
|
g_failed_address_list.append(ip_address)
|
|
g_lock.release()
|
|
|
|
@staticmethod
|
|
def checkIpAddressList(ip_address_list):
|
|
"""
|
|
function : Check the connection status of network.
|
|
input : []
|
|
output : []
|
|
"""
|
|
global g_failed_address_list
|
|
g_failed_address_list = []
|
|
parallelTool.parallelExecute(NetUtil.executePingCmd, ip_address_list)
|
|
return g_failed_address_list
|
|
|
|
@staticmethod
|
|
def getAllNetworkIp():
|
|
"""
|
|
function: get All network ip
|
|
"""
|
|
network_info_list = []
|
|
mapping_list = NetUtil.getIpAddressAndNICList()
|
|
for onelist in mapping_list:
|
|
data = NetworkInfo()
|
|
# NIC number
|
|
data.NICNum = onelist[0]
|
|
# ip address
|
|
data.ipAddress = onelist[1]
|
|
network_info_list.append(data)
|
|
return network_info_list
|
|
|
|
@staticmethod
|
|
def getIpAddressAndNICList(ip_type="ipv4"):
|
|
"""
|
|
function: get ip address and nicList
|
|
input: ip_type
|
|
output: []
|
|
"""
|
|
return list(NetUtil.getIpAddressAndNIC(ip_type))
|
|
|
|
@staticmethod
|
|
def getIpAddressAndNIC(ip_type="ipv4"):
|
|
"""
|
|
function: get ip address and nic
|
|
input: ip_type
|
|
output: NA
|
|
"""
|
|
if ip_type == "ipv4":
|
|
key = AF_INET
|
|
else:
|
|
key = AF_INET6
|
|
|
|
for iface in interfaces():
|
|
if key in ifaddresses(iface):
|
|
ip_address = ifaddresses(iface)[key][0]['addr']
|
|
yield (iface, ip_address)
|
|
|
|
@staticmethod
|
|
def getHostNameByIPAddr(ip_address):
|
|
"""
|
|
function: get host name by ip addr
|
|
input: ip_address
|
|
output: str
|
|
"""
|
|
return socket.gethostbyaddr(ip_address)[0]
|
|
|
|
@staticmethod
|
|
def getNetworkBondModeByBondConfigFile(bonding_conf_file):
|
|
"""
|
|
function: get Network Bond Mode By Bond ConfigFile
|
|
input: bonding_conf_file
|
|
output: str
|
|
"""
|
|
# Check the bond mode
|
|
cmd = "%s -w '\<Bonding Mode\>' %s | %s -F ':' '{print $NF}'" % (
|
|
CmdUtil.getGrepCmd(), bonding_conf_file, CmdUtil.getAwkCmd())
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd +
|
|
" Error: \n%s " % output)
|
|
return "BondMode %s" % output.strip()
|
|
|
|
@staticmethod
|
|
def getNetworkBondModeInfo(network_conf_file, network_card_num):
|
|
"""
|
|
function: get Network Bond Mode Info
|
|
input: network_conf_file, network_card_num
|
|
output: str
|
|
"""
|
|
# Get the bond profile
|
|
if not os.path.isfile(network_conf_file):
|
|
return "BondMode Null"
|
|
|
|
bonding_conf_file = "/proc/net/bonding/%s" % (network_card_num)
|
|
cmd = "%s -i 'BONDING_OPTS\|BONDING_MODULE_OPTS' %s" % (
|
|
CmdUtil.getGrepCmd(), network_conf_file)
|
|
output = subprocess.getstatusoutput(cmd)[1]
|
|
# Analysis results
|
|
if output.strip() != "":
|
|
if (output.find("mode") > 0) and os.path.exists(bonding_conf_file):
|
|
bond_info = NetUtil.getNetworkBondModeByBondConfigFile(
|
|
bonding_conf_file)
|
|
else:
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd +
|
|
" Error: \n%s " % output)
|
|
elif os.path.exists(bonding_conf_file):
|
|
bond_info = NetUtil.getNetworkBondModeByBondConfigFile(bonding_conf_file)
|
|
bond_info += "\nNo 'BONDING_OPTS' or \
|
|
'BONDING_MODULE_OPTS' in bond config file[%s]." % network_conf_file
|
|
else:
|
|
bond_info = "BondMode Null"
|
|
return bond_info
|
|
|
|
@staticmethod
|
|
def getNetworkMaskByNICNum(network_card_num, ip_type="ipv4"):
|
|
"""
|
|
function: get Network Mask By NICNum
|
|
input: network_card_num, ip_type
|
|
output: str
|
|
"""
|
|
if ip_type == "ipv4":
|
|
return ifaddresses(network_card_num)[AF_INET][0]["netmask"]
|
|
else:
|
|
return ifaddresses(network_card_num)[AF_INET6][0]["netmask"]
|
|
|
|
@staticmethod
|
|
def getNetworkRXTXValueByNICNum(network_card_num, value_type):
|
|
"""
|
|
function: get Network RXTX Value By NICNum
|
|
input: network_card_num, value_type
|
|
output: int
|
|
"""
|
|
cmd = "%s -g %s | %s '%s:' | %s -n 1" % (CmdUtil.getEthtoolCmd(),
|
|
network_card_num,
|
|
CmdUtil.getGrepCmd(),
|
|
value_type.upper(),
|
|
CmdUtil.getTailCmd())
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd +
|
|
" Error: \n%s " % output)
|
|
value = output.split(':')[-1].split(' ')[0].strip()
|
|
if not str(value).isdigit():
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd +
|
|
" Error: \n%s " % output)
|
|
return int(value)
|
|
|
|
@staticmethod
|
|
def getNetworkSpeedByNICNum(network_card_num):
|
|
"""
|
|
function: get Network Speed By NICNum
|
|
input: network_card_num
|
|
output: int
|
|
"""
|
|
key_word = "Speed: "
|
|
speed_unit = "Mb/s"
|
|
cmd = "%s %s | grep '%s'" % (CmdUtil.getEthtoolCmd(),
|
|
network_card_num, key_word)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0 or output == "":
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd +
|
|
" Error: \n%s " % output)
|
|
if len(output.split('\n')) >= 1:
|
|
for line in output.split('\n'):
|
|
if line.find(key_word) >= 0 and line.find(speed_unit) >= 0:
|
|
return int(line.split(':')[-1].strip()[:-4])
|
|
return 0
|
|
|
|
@staticmethod
|
|
def getNetworkConfigFileByNICNum(network_card_num):
|
|
"""
|
|
function: get linux network config file
|
|
input: network_conf_path, network_card_num
|
|
output: str
|
|
"""
|
|
network_conf_path = g_Platform.getNetWorkConfPath()
|
|
network_conf_file = "%sifcfg-%s" % (network_conf_path, network_card_num)
|
|
# Network configuration file does not exist
|
|
if not os.path.exists(network_conf_file):
|
|
cmd = "%s %s -iname 'ifcfg-*-%s' -print" % (CmdUtil.getFindCmd(),
|
|
network_conf_file,
|
|
network_card_num)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0 or output.strip() == ""
|
|
or len(output.split('\n')) != 1):
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] %
|
|
network_conf_file + "The cmd is %s" % cmd)
|
|
network_conf_file = output.strip()
|
|
return network_conf_file
|
|
|
|
@staticmethod
|
|
def getAllNetworkInfo():
|
|
"""
|
|
function: get all network info
|
|
"""
|
|
network_info_list = []
|
|
mapping_list = NetUtil.getIpAddressAndNICList()
|
|
for one_list in mapping_list:
|
|
data = NetworkInfo()
|
|
# NIC number
|
|
data.NICNum = one_list[0]
|
|
# ip address
|
|
data.ipAddress = one_list[1]
|
|
|
|
# host name
|
|
try:
|
|
data.hostName = NetUtil.getHostNameByIPAddr(
|
|
data.ipAddress)
|
|
except Exception:
|
|
data.hostName = ""
|
|
|
|
# network mask
|
|
try:
|
|
data.networkMask = NetUtil.getNetworkMaskByNICNum(
|
|
data.NICNum)
|
|
except Exception:
|
|
data.networkMask = ""
|
|
|
|
# MTU value
|
|
try:
|
|
data.MTUValue = psutil.net_if_stats()[data.NICNum].mtu
|
|
except Exception:
|
|
data.MTUValue = ""
|
|
|
|
# TX value
|
|
try:
|
|
data.TXValue = NetUtil.getNetworkRXTXValueByNICNum(
|
|
data.NICNum, 'tx')
|
|
except Exception:
|
|
data.TXValue = ""
|
|
|
|
# RX value
|
|
try:
|
|
data.RXValue = NetUtil.getNetworkRXTXValueByNICNum(
|
|
data.NICNum, 'rx')
|
|
except Exception:
|
|
data.RXValue = ""
|
|
|
|
# network speed
|
|
try:
|
|
data.networkSpeed = NetUtil.getNetworkSpeedByNICNum(
|
|
data.NICNum)
|
|
except Exception:
|
|
data.networkSpeed = ""
|
|
|
|
# network config file
|
|
try:
|
|
data.networkConfigFile = \
|
|
NetUtil.getNetworkConfigFileByNICNum(data.NICNum)
|
|
except Exception:
|
|
data.networkConfigFile = ""
|
|
|
|
# network bond mode info
|
|
try:
|
|
data.networkBondModeInfo = NetUtil.getNetworkBondModeInfo(
|
|
data.networkConfigFile, data.NICNum)
|
|
except Exception:
|
|
data.networkBondModeInfo = ""
|
|
|
|
network_info_list.append(data)
|
|
return network_info_list
|
|
|
|
@staticmethod
|
|
def getLocalIp():
|
|
"""
|
|
function: Obtaining the local IP address
|
|
input: NA
|
|
output: str
|
|
"""
|
|
try:
|
|
env_dist = os.environ
|
|
if "HOST_IP" not in list(env_dist.keys()):
|
|
host_name = NetUtil.getHostName()
|
|
return host_name
|
|
host_ip = env_dist.get("HOST_IP")
|
|
if host_ip is not None:
|
|
if NetUtil.isIpValid(host_ip):
|
|
return host_ip
|
|
host_ip = socket.gethostbyname(socket.gethostname())
|
|
except Exception as e:
|
|
raise Exception(str(e))
|
|
return host_ip
|
|
|
|
@staticmethod
|
|
def checkBondMode(bonding_conf_file, is_check_os=True):
|
|
"""
|
|
function : Check Bond mode
|
|
input : String, bool
|
|
output : List
|
|
"""
|
|
net_name_list = []
|
|
|
|
SecurityChecker.check_injection_char(bonding_conf_file)
|
|
|
|
cmd = "grep -w 'Bonding Mode' %s | awk -F ':' '{print $NF}'" % bonding_conf_file
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0 or output.strip() == "":
|
|
raise Exception(ErrorCode.GAUSS_506["GAUSS_50611"] + " Error: \n%s" % output)
|
|
if is_check_os:
|
|
print("BondMode %s" % output.strip())
|
|
cmd = "grep -w 'Slave Interface' %s | awk -F ':' '{print $NF}'" % bonding_conf_file
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_506["GAUSS_50611"] + " Error: \n%s" % output)
|
|
for networkname in output.split('\n'):
|
|
net_name_list.append(networkname.strip())
|
|
return net_name_list
|
|
|
|
@staticmethod
|
|
def getNetWorkBondFlag(network_card_num):
|
|
"""
|
|
function: Check if the network interface card number is bondCard by psutil module
|
|
input: network interface card number
|
|
output: FLAG, netcardList
|
|
"""
|
|
try:
|
|
flag = False
|
|
nic_addr = ""
|
|
netcard_list = []
|
|
net_work_info = psutil.net_if_addrs()
|
|
for snic in net_work_info[network_card_num]:
|
|
if snic.family == 17:
|
|
nic_addr = snic.address
|
|
if nic_addr == "":
|
|
return flag, netcard_list
|
|
for net_num in list(net_work_info.keys()):
|
|
if net_num == network_card_num:
|
|
continue
|
|
for net_info in net_work_info[net_num]:
|
|
if net_info.address == nic_addr:
|
|
netcard_list.append(net_num)
|
|
if len(netcard_list) >= 2:
|
|
flag = True
|
|
for net_num in netcard_list:
|
|
cmd = "ip link | grep '%s'" % net_num
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
raise Exception((ErrorCode.GAUSS_514["GAUSS_51400"] %
|
|
cmd) + "\nError: %s" % output)
|
|
if str(output).find("master %s" % network_card_num) == -1:
|
|
flag = False
|
|
netcard_list = []
|
|
break
|
|
return flag, netcard_list
|
|
except Exception as e:
|
|
raise Exception(ErrorCode.GAUSS_530["GAUSS_53011"] % (
|
|
"if the netcardNum[%s] is bondCard" % network_card_num)
|
|
+ " Error: \n%s" % str(e))
|
|
|
|
@staticmethod
|
|
def getNICNum(ip_address):
|
|
"""
|
|
function: Obtain network interface card number by psutil module
|
|
input: ip_address
|
|
output: netWorkNum
|
|
"""
|
|
try:
|
|
net_work_num = ""
|
|
net_work_info = psutil.net_if_addrs()
|
|
for nic_num in list(net_work_info.keys()):
|
|
net_info = net_work_info[nic_num][0]
|
|
if net_info.address == ip_address:
|
|
net_work_num = nic_num
|
|
break
|
|
if net_work_num == "":
|
|
raise Exception(ErrorCode.GAUSS_506["GAUSS_50604"] % ip_address)
|
|
return net_work_num
|
|
except Exception as excep:
|
|
raise Exception(ErrorCode.GAUSS_506["GAUSS_50604"] % ip_address +
|
|
" Error: \n%s" % str(excep))
|
|
|
|
@staticmethod
|
|
def getIpAddressList():
|
|
"""
|
|
Get IP address list
|
|
"""
|
|
# Obtain all Ips by psutil module
|
|
try:
|
|
ip_address_list = []
|
|
net_work_info = psutil.net_if_addrs()
|
|
for per_num in net_work_info.keys():
|
|
net_info = net_work_info[per_num][0]
|
|
if len(net_info.address.split('.')) == 4:
|
|
ip_address_list.append(net_info.address)
|
|
if len(ip_address_list) == 0:
|
|
raise Exception(ErrorCode.GAUSS_506["GAUSS_50616"])
|
|
return ip_address_list
|
|
except Exception as excep:
|
|
raise Exception(ErrorCode.GAUSS_506["GAUSS_50616"] +
|
|
" Error: \n%s" % str(excep))
|
|
|
|
@staticmethod
|
|
def getNetworkConfiguredFile(ip):
|
|
"""
|
|
function: get network configuration file for RHEL
|
|
input: ip
|
|
output: networkFile
|
|
"""
|
|
pattern = re.compile("ifcfg-.*:.*")
|
|
network_file = ""
|
|
# network scripts file for RHEL
|
|
REDHAT_NETWORK_PATH = "/etc/sysconfig/network-scripts"
|
|
try:
|
|
for filename in os.listdir(REDHAT_NETWORK_PATH):
|
|
result = pattern.match(filename)
|
|
if result is None:
|
|
continue
|
|
paramfile = "%s/%s" % (REDHAT_NETWORK_PATH,
|
|
filename)
|
|
with open(paramfile, "r") as fp:
|
|
file_info = fp.readlines()
|
|
# The current opened file is generated while configing
|
|
# virtual IP,
|
|
# there are 3 lines in file, and the second line is IPADDR=IP
|
|
if len(file_info) == 3 and \
|
|
file_info[1].find("IPADDR=%s" % ip) >= 0:
|
|
network_file += "%s " % paramfile
|
|
return network_file
|
|
except Exception as e:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] %
|
|
"network configuration file" +
|
|
" Error: \n%s " % str(e))
|