import os import re import netifaces import subprocess class NetWorkConfig: def __init__(self): pass @staticmethod def check_network_isvalid(ip, netmask, gateway, dns): """ 判斷用戶輸入的網絡配置是否可用 :param ip: str,IP地址 :param netmask: str,子網掩碼 :param gateway: str,網關 :param dns: str,DNS :return: bool,True表示配置可用,False表示配置不可用 """ # 判斷IP地址是否合法 if not re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", ip): return False # 判斷子網掩碼是否合法 if not re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", netmask): return False # 判斷網關是否合法 if not re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", gateway): return False # 判斷DNS是否合法 if not re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", dns): return False # 判斷網絡是否可用 cmd_ping = f"ping {gateway}" try: subprocess.check_call(cmd_ping, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except subprocess.CalledProcessError: return False return True @staticmethod def get_network_config(physical=False): """ 獲取網卡配置信息 :param physical: 是否僅獲取物理網卡 :return: 返回服務器網卡配置 """ i_faces = netifaces.interfaces() configs = [] for i in i_faces: if physical and not i.startswith("e"): continue addr_s = netifaces.ifaddresses(i) inet = addr_s.get(netifaces.AF_INET) if not inet: continue ip = inet[0].get("addr") netmask = inet[0].get("netmask") broadcast = inet[0].get("broadcast") gateway = netifaces.gateways().get("default", {}).get(netifaces.AF_INET, [])[0] dns = netifaces.gateways().get("default", {}).get(netifaces.AF_INET, [])[1] configs.append({ "iface": i, "ip": ip, "netmask": netmask, "broadcast": broadcast, "gateway": gateway, "dns": dns, }) return configs @staticmethod def _check_network_config(iface, ip_address, netmask, gateway, dns): """ 檢查IP地址和子網掩碼修改是否生效 :param iface: 網卡 :param ip_address: ip地址 :param netmask: 子網掩碼 :param gateway: 網關 :param dns: DNS :return: 返回配置是否生效 """ # 檢查ip地址是否生效 cmd = f"ifconfig {iface} | grep {ip_address}" output = subprocess.check_output(cmd, shell=True) if ip_address not in output.decode("utf-8"): return False # 檢查子網掩碼是否生效 cmd = f"ifconfig {iface} | grep {netmask}" output = subprocess.check_output(cmd, shell=True) if netmask not in output.decode("utf-8"): return False # 檢查默認網關是否生效 cmd = "route" output = subprocess.check_output(cmd, shell=True) pattern = rf"{gateway}\s.*\s{iface}" matches = re.findall(pattern, output.decode("utf-8"), re.MULTILINE) if not matches: return False # 檢查DNS是否生效 with open("/etc/resolv.conf", "r") as f: content = f.read() if dns not in content: return False return True @staticmethod def _write_network_config_to_file(config, mode="w"): """ 配置信息寫入網卡 """ with open("/etc/network/interfaces", mode) as f: f.write(config) @staticmethod def _restart_network(): """重啓網絡""" os.system("service networking restart") @staticmethod def _cp_config(cmd=None): """ 拷貝配置文件 :param cmd: backup表示備份 rollback表示回滾 """ if cmd == "backup": os.system("cp /etc/network/interfaces /etc/network/interfaces.bak") if cmd == "rollback": os.system("cp /etc/network/interfaces.bak /etc/network/interfaces") def set_network_config(self, iface, ip_address, netmask, gateway, dns): """ 修改網絡配置 :param iface: 網卡名稱 :param ip_address: IP地址 :param netmask: 子網掩碼 :param gateway: 默認網關 :param dns: DNS服務器 :return: 是否修改成功 """ self._cp_config(cmd="backup") config = f""" auto {iface} iface {iface} inet static address {ip_address} netmask {netmask} gateway {gateway} dns-nameservers {dns} """ self._write_network_config_to_file(config, "w") self._restart_network() if self._check_network_config(iface, ip_address, netmask, gateway, dns): return True else: self._cp_config(cmd="rollback") self._restart_network() return False