1 #settings.py 2 # ————————01CMDB获取服务器基本信息———————— 3 import os 4 5 BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))##当前路径 6 7 # 采集资产的方式,选项有:agent(默认), salt, ssh 8 MODE = 'agent' 9 10 # ————————01CMDB获取服务器基本信息———————— 11 12 # ————————02CMDB将服务器基本信息提交到API接口———————— 13 # 资产信息API 14 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 15 # ASSET_API = "http://127.0.0.1:8000/api/asset" 16 ASSET_API = "http://192.168.80.53:8000/api/asset" 17 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 18 19 # ————————02CMDB将服务器基本信息提交到API接口———————— 20 21 # ————————03CMDB信息安全API接口交互认证———————— 22 # 用于API认证的KEY 23 KEY = '299095cc-1330-11e5-b06a-a45e60bec08b' #认证的密码 24 # 用于API认证的请求头 25 AUTH_KEY_NAME = 'auth-key' 26 # ————————03CMDB信息安全API接口交互认证———————— 27 28 29 # ————————04CMDB本地(Agent)模式客户端唯一标识(ID)———————— 30 # Agent模式保存服务器唯一ID的文件 31 CERT_FILE_PATH = os.path.join(BASEDIR, 'config', 'cert') #文件路径 32 # ————————04CMDB本地(Agent)模式客户端唯一标识(ID)———————— 33 34 # ————————05CMDB采集硬件数据的插件———————— 35 # 采集硬件数据的插件 36 PLUGINS_DICT = { 37 'cpu': 'src.plugins.cpu.CpuPlugin', 38 'disk': 'src.plugins.disk.DiskPlugin', 39 'main_board': 'src.plugins.main_board.MainBoardPlugin', 40 'memory': 'src.plugins.memory.MemoryPlugin', 41 'nic': 'src.plugins.nic.NicPlugin', 42 } 43 # ————————05CMDB采集硬件数据的插件———————— 44 45 # ————————07CMDB文件模式测试采集硬件数据———————— 46 # 是否测试模式,测试模时候数据从files目录下读取信息 选项有:#True False 47 TEST_MODE = True 48 # ————————07CMDB文件模式测试采集硬件数据———————— 49 50 51 52 # ————————08CMDB采集硬件数据日志记录———————— 53 # 错误日志 54 ERROR_LOG_FILE = os.path.join(BASEDIR, "log", 'error.log') 55 # 运行日志 56 RUN_LOG_FILE = os.path.join(BASEDIR, "log", 'run.log') 57 # ————————08CMDB采集硬件数据日志记录————————
1 #log.py 2 3 # ————————08CMDB采集硬件数据日志记录———————— 4 import os # 操作系统层面执行 5 import logging #日志模块 6 from config import settings #配置文件 7 8 class Logger(object): 9 __instance = None #实例 10 11 def __init__(self): 12 self.run_log_file = settings.RUN_LOG_FILE #运行日志路径 RUN_LOG_FILE = os.path.join(BASEDIR, "log", 'run.log') 13 self.error_log_file = settings.ERROR_LOG_FILE #错误日志路径 ERROR_LOG_FILE = os.path.join(BASEDIR, "log", 'error.log') 14 self.run_logger = None #写运行日志 15 self.error_logger = None #写错误日志 16 self.initialize_run_log() #初始化运行日志 17 self.initialize_error_log() #初始化错误日志 18 19 def __new__(cls, *args, **kwargs): 20 if not cls.__instance: #实例 21 cls.__instance = object.__new__(cls, *args, **kwargs) 22 return cls.__instance #实例 23 24 @staticmethod# 返回函数的静态方法 25 def check_path_exist(log_abs_file): #路径 26 log_path = os.path.split(log_abs_file)[0]#log文件夹 27 # print('日志文件:',log_path) 28 if not os.path.exists(log_path):#判断是否存在 log文件夹 29 os.mkdir(log_path) #创建 log文件夹 30 31 32 def initialize_run_log(self):#初始化运行日志 33 self.check_path_exist(self.run_log_file) #运行日志路径 34 #————————创建文件———————— 35 file_1_1 = logging.FileHandler(self.run_log_file, 'a', encoding='utf-8')# 36 fmt = logging.Formatter(fmt="%(asctime)s - %(levelname)s : %(message)s") 37 file_1_1.setFormatter(fmt)#为这个处理程序设置格式化程序。 38 # ————————创建文件———————— 39 logger1 = logging.Logger('run_log', level=logging.INFO)#INFO = 20 40 logger1.addHandler(file_1_1) #指定处理程序添加到这个记录器。 41 self.run_logger = logger1 42 """ 43 日志对应的级别 44 #CRITICAL = 50 #FATAL = CRITICAL #ERROR = 40 #WARNING = 30 45 #WARN = WARNING #INFO = 20 #DEBUG = 10 #NOTSET = 0 46 """ 47 def initialize_error_log(self): #初始化错误日志 48 self.check_path_exist(self.error_log_file)#错误日志路径 49 # ————————创建文件———————— 50 file_1_1 = logging.FileHandler(self.error_log_file, 'a', encoding='utf-8') 51 fmt = logging.Formatter(fmt="%(asctime)s - %(levelname)s : %(message)s") 52 file_1_1.setFormatter(fmt) 53 # ————————创建文件———————— 54 logger1 = logging.Logger('run_log', level=logging.ERROR)#ERROR = 40 55 logger1.addHandler(file_1_1) 56 self.error_logger = logger1 57 58 def log(self, message, mode=True):#callback #写入日志#mode: True表示运行信息,False表示错误信息 59 60 if mode: 61 self.run_logger.info(message) #Logger().log(ret['message'], True) 62 else: 63 self.error_logger.error(message)# Logger().log(ret['message'], False) 64 # ————————08CMDB采集硬件数据日志记录————————
1 # client.py 2 # ————————01CMDB获取服务器基本信息———————— 3 from src import plugins #__init__.py 4 from lib.serialize import Json #转成字符串或者模式 5 6 # ————————02CMDB将服务器基本信息提交到API接口———————— 7 import requests #伪造页面访问 8 from config import settings #文件配置 9 # ————————02CMDB将服务器基本信息提交到API接口———————— 10 11 # ————————03CMDB信息安全API接口交互认证———————— 12 import hashlib 13 import time 14 # ————————03CMDB信息安全API接口交互认证———————— 15 16 # ————————04CMDB本地(Agent)模式客户端唯一标识(ID)———————— 17 import os #操作系统层面执行 18 import shutil #高级的 文件、文件夹、压缩包 处理模块 19 # ————————04CMDB本地(Agent)模式客户端唯一标识(ID)———————— 20 class AutoBase(object): 21 22 # ————————02CMDB将服务器基本信息提交到API接口———————— 23 def __init__(self): 24 self.asset_api = settings.ASSET_API #ASSET_API = "http://127.0.0.1:8000/api/asset" 25 26 # ————————03CMDB信息安全API接口交互认证———————— 27 self.key = settings.KEY # 用于API认证的KEY#KEY = '299095cc-1330-11e5-b06a-a45e60bec08b' 28 self.key_name = settings.AUTH_KEY_NAME # 'auth-key' API认证的请求头 29 # ————————03CMDB信息安全API接口交互认证———————— 30 31 # ————————03CMDB信息安全API接口交互认证———————— 32 def auth_key(self):#API接口认证 33 ha = hashlib.md5(self.key.encode('utf-8'))#认证的密码 34 time_span = time.time() #现在的时间戳 #1529819687.8867188 35 ha.update(bytes("%s|%f" % (self.key, time_span), encoding='utf-8'))#更新认证密码#密码+时间戳 36 encryption = ha.hexdigest() # 对‘时间密码’进行哈希 37 result = "%s|%f" % (encryption, time_span) #把‘时间密码’和 时间戳(解密用) 作为 API认证的请求头 38 print('‘时间密码’和 时间戳:',result) 39 return {self.key_name: result} # 'auth-key' API认证的请求头 40 # ————————03CMDB信息安全API接口交互认证———————— 41 42 # ————————08CMDB采集硬件数据日志记录———————— 43 # def post_asset(self, msg):#post方式向API接口提交资产信息 44 def post_asset(self, msg, callback=None): #post方式向API接口提交资产信息 45 # ————————08CMDB采集硬件数据日志记录———————— 46 47 status = True#是否获取到信息 48 try: 49 # ————————03CMDB信息安全API接口交互认证———————— 50 headers = {} 51 headers.update(self.auth_key())##认证的密码 52 # ————————03CMDB信息安全API接口交互认证———————— 53 response = requests.post( 54 url=self.asset_api, 55 # ————————03CMDB信息安全API接口交互认证———————— 56 headers=headers, 57 # ————————03CMDB信息安全API接口交互认证———————— 58 json=msg 59 ) 60 except Exception as e: 61 response = e 62 status = False #获取信息时出现错误 63 print(response.json()) 64 # ————————02CMDB将服务器基本信息提交到API接口———————— 65 66 # ————————08CMDB采集硬件数据日志记录———————— 67 print('服务器反馈:') 68 print(callback) 69 if callback: 70 callback(status, response) 71 # ————————08CMDB采集硬件数据日志记录———————— 72 73 # ————————08CMDB采集硬件数据日志记录———————— 74 def callback(self, status, response):#提交资产到服务器后的回调函数#请求成功,则是响应内容对象;请求错误,则是异常对象 75 import json 76 from lib.log import Logger #写日志 77 if not status: 78 Logger().log(str(response), False) 79 return 80 ret = json.loads(response.text) 81 if ret['code'] == 1000: #{'code': 1000, 'message': '[%s]更新完成' % hostname} 82 #参数1:内容 参数2:True 运行日志 False 错误日志 83 Logger().log(ret['message'], True) 84 else:#错误日志 85 Logger().log(ret['message'], False) 86 # ————————08CMDB采集硬件数据日志记录———————— 87 88 89 def process(self):#派生类需要继承此方法,用于处理请求的入口 90 raise NotImplementedError('您必须实现过程的方法') 91 92 class AutoAgent(AutoBase): 93 94 # ————————04CMDB本地(Agent)模式客户端唯一标识(ID)———————— 95 def __init__(self): 96 self.cert_file_path = settings.CERT_FILE_PATH# Agent模式保存服务器唯一ID的文件 97 super(AutoAgent, self).__init__() 98 """ 99 super() 函数是用于调用父类(超类)的一个方法。 100 super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题, 101 但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。 102 MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。 103 """ 104 def load_local_cert(self):# 获取本地唯一标识 105 if not os.path.exists(self.cert_file_path):#使用os.path.exists()方法可以直接判断文件(或者文件夹)是否存在 106 return None #如果文件(或者文件夹)不存在 #返回空 107 if os.path.isfile(self.cert_file_path): #判断是不是文件 108 with open(self.cert_file_path, mode='r') as f: #如果文件存在 #打开读取文件 109 data = f.read()#获取唯一ID的文件#read() 方法用于从文件读取指定的字节数,如果未给定或为负则读取所有。 110 if not data: # 如果文件没有内容 #返回空 111 return None 112 cert = data.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 113 return cert # 返回 本地唯一标识 114 else: #防止有文件夹叫cert,导致无法创建cert文件 115 shutil.rmtree(self.cert_file_path)#就 递归的去删除文件夹 #这个目录以及子文件全部删除 116 return None #返回空 #去创建文件 117 118 def write_local_cert(self, cert):#写入本地唯一标识 119 with open(self.cert_file_path, mode='w') as f: #循环打开文件 #没有就创建 然后打开 120 f.write(cert) #写入本地唯一标识 121 # ————————04CMDB本地(Agent)模式客户端唯一标识(ID)———————— 122 123 def process(self): 124 server_info = plugins.get_server_info()#获取本地基本信息 125 126 # ————————04CMDB本地(Agent)模式客户端唯一标识(ID)———————— 127 if not server_info.status: #获取的基本信息是否出错 128 return 129 local_cert = self.load_local_cert() # 去获取本地唯一标识 130 if local_cert: #如果 获取本地唯一标识 后 #不是 return None 131 if local_cert == server_info.data['hostname']: #判断本地文件的唯一标识 是不是等于 获取的基本信息里主机名 132 pass #一样就什么都不干 133 else: #不一样就把 获取的基本信息里主机名 替换成 本地文件的唯一标识 134 #防止 恶意篡改 主机名 ,上报API时 错认为是 新资产 135 server_info.data['hostname'] = local_cert # 更新字典的主机名 136 else: # 获取本地唯一标识为None时 #把获取到的主机名写入本地做为唯一标识 137 self.write_local_cert(server_info.data['hostname']) 138 # ————————04CMDB本地(Agent)模式客户端唯一标识(ID)———————— 139 140 server_json = Json.dumps(server_info.data)#json.dumps将 Python 对象编码成 JSON 字符串 141 print('提交资产信息:',server_json) 142 # ————————01CMDB获取服务器基本信息———————— 143 144 # ————————08CMDB采集硬件数据日志记录———————— 145 # ————————02CMDB将服务器基本信息提交到API接口———————— 146 # self.post_asset(server_json)# post方式向接口提交资产信息 147 self.post_asset(server_json, self.callback)# post方式向接口提交资产信息 148 # ————————02CMDB将服务器基本信息提交到API接口———————— 149 # ————————08CMDB采集硬件数据日志记录————————
1 #base.py 2 # ————————08CMDB采集硬件数据日志记录———————— 3 from lib.log import Logger 4 # ————————08CMDB采集硬件数据日志记录———————— 5 6 # ————————01CMDB获取服务器基本信息———————— 7 from config import settings #配置文件 8 9 class BasePlugin(object): 10 def __init__(self, hostname=''): 11 12 # ————————08CMDB采集硬件数据日志记录———————— 13 self.logger = Logger() #日志 实例化 14 self.hostname = hostname # 主机名默认为空,hostname='' 15 # ————————08CMDB采集硬件数据日志记录———————— 16 17 # ————————07CMDB文件模式测试采集硬件数据———————— 18 self.test_mode = settings.TEST_MODE#是否测试模式 19 # ————————07CMDB文件模式测试采集硬件数据———————— 20 21 if hasattr(settings, 'MODE'): 22 self.mode = settings.MODE #采集资产的方式 23 else: 24 self.mode = 'agent'#默认,采集资产的方式 25 def execute(self): 26 27 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 28 # return self.windows() 29 try:#判断系统平台类型 30 31 # ————————07CMDB文件模式测试采集硬件数据———————— 32 if self.test_mode: # 是否测试模式 33 return self.test() # 测试模式 34 # ————————07CMDB文件模式测试采集硬件数据———————— 35 36 import platform # 获取操作系统信息 的模块 37 if platform.system() == 'Linux': 38 return self.linux() #执行 #def linux(self): 39 elif platform.system() == 'Windows': 40 return self.windows() # 执行 #def windows(self): 41 except Exception as e: 42 return '未知的系统平台类型!' 43 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 44 45 def windows(self): 46 raise Exception('您必须实现windows的方法') 47 # ————————01CMDB获取服务器基本信息———————— 48 49 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 50 def linux(self): 51 raise Exception('您必须实现linux的方法') 52 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 53 54 # ————————07CMDB文件模式测试采集硬件数据———————— 55 def test(self):#测试模式 56 raise Exception('您必须实现test的方法') 57 # ————————07CMDB文件模式测试采集硬件数据————————
1 # basic.py 2 # ————————01CMDB获取服务器基本信息———————— 3 from .base import BasePlugin #采集资产的方式 4 from lib.response import BaseResponse #提交数据的类型 5 import platform #platform模块给我们提供了很多方法去获取操作系统的信息 6 7 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 8 # import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 9 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 10 """ 11 本模块基于windows操作系统,依赖wmi和win32com库,需要提前使用pip进行安装, 12 我们依然可以通过pip install pypiwin32来安装win32com模块 13 或者下载安装包手动安装。 14 """ 15 16 class BasicPlugin(BasePlugin): 17 def os_platform(self):#获取系统平台 18 # ————————07CMDB文件模式测试采集硬件数据———————— 19 # output=platform.system() #windows和Linux 都可以执行 20 # return output.strip()#strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 21 22 try: 23 if self.test_mode: # 是否测试模式 24 output = 'Linux' # 选择要测试的系统(windows和Linux或者苹果等未知的系统) 25 return output.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 26 output = platform.system() #windows和Linux 都可以执行 27 return output.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 28 except Exception as e: 29 return '未知的系统平台!' 30 # ————————07CMDB文件模式测试采集硬件数据———————— 31 32 def os_version(self):#获取系统版本 33 # output = wmi.WMI().Win32_OperatingSystem()[0].Caption 34 # return output.strip()#strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 35 36 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 37 try: 38 39 # ————————07CMDB文件模式测试采集硬件数据———————— 40 if self.test_mode: # 是否测试模式 41 output = """CentOS release 6.6 (Final) Kernel on an m""" 42 result = output.strip().split(' ')[0] # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。#split() 通过指定分隔符对字符串进行切片 43 return result 44 # ————————07CMDB文件模式测试采集硬件数据———————— 45 46 if platform.system() == 'Linux': 47 import subprocess # 启动一个新的进程并且与之通信 48 output = subprocess.getoutput('cat /etc/issue') # Linux系统下的命令 49 result = output.strip().split(' ')[0] # split() 通过指定分隔符对字符串进行切片 50 # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 51 return result 52 if platform.system() == 'Windows': 53 import wmi # Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 54 output = wmi.WMI().Win32_OperatingSystem()[0].Caption # Windows系统下的命令 55 result = output.strip() 56 # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 57 return result 58 except Exception as e: 59 return '未知的系统版本!' 60 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 61 62 def os_hostname(self):#获取主机名 63 # output = wmi.WMI().Win32_OperatingSystem()[0].CSName 64 # return output.strip()#strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 65 66 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 67 try: 68 69 # ————————07CMDB文件模式测试采集硬件数据———————— 70 if self.test_mode: # 是否测试模式 71 output = 'test.com' 72 return output.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 73 # ————————07CMDB文件模式测试采集硬件数据———————— 74 75 if platform.system() == 'Linux': 76 import subprocess # 启动一个新的进程并且与之通信 77 output = subprocess.getoutput('hostname') # Linux系统下的命令 78 return output.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 79 elif platform.system() == 'Windows': 80 import wmi # Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 81 output = wmi.WMI().Win32_OperatingSystem()[0].CSName # Windows系统下的命令 82 return output.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 83 except Exception as e: 84 return '未知的主机名!' 85 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 86 87 def windows(self): 88 response = BaseResponse()#提交数据的类型 89 try: 90 ret = { 91 'os_platform': self.os_platform(),#系统平台 92 'os_version': self.os_version(),#系统版本 93 'hostname': self.os_hostname(),#主机名 94 } 95 response.data = ret #字典形式 96 print('windows服务器基本信息:',response.data) 97 except Exception as e: 98 99 # ————————08CMDB采集硬件数据日志记录———————— 100 msg = "%s 基本的插件错误:%s" #错误信息 101 import traceback #捕获并打印异常 102 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 103 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 104 # ————————08CMDB采集硬件数据日志记录———————— 105 106 response.status = False # 获取信息时出现错误 107 return response 108 """ 109 class BaseResponse(object): #提交数据的类型 110 def __init__(self): 111 self.status = True #状态 112 self.message = None #消息 113 self.data = None #数据内容 114 self.error = None #错误信息 115 116 """ 117 # ————————01CMDB获取服务器基本信息———————— 118 119 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 120 def linux(self): 121 response = self.windows() #因为执行同样的方法,所以,就不重复写。 122 print('linux服务器基本信息:', response.data) 123 return response 124 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 125 126 # ————————07CMDB文件模式测试采集硬件数据———————— 127 def test(self): 128 response = self.windows() #因为执行同样的方法,所以,就不重复写。 129 print('test服务器基本信息:', response.data) 130 return response 131 # ————————07CMDB文件模式测试采集硬件数据————————
1 # cpu.py 2 # ————————05CMDB采集硬件数据的插件———————— 3 from .base import BasePlugin #采集资产的方式 和 系统平台 4 from lib.response import BaseResponse #提交数据的类型(字典) 5 6 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 7 # import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 8 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 9 10 class CpuPlugin(BasePlugin): 11 def windows(self): 12 response = BaseResponse() #提交数据的类型(字典) 13 try: 14 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 15 import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 16 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 17 output =wmi.WMI().Win32_Processor() #获取CPU相关信息 18 response.data = self.windows_parse(output) #解析相关信息 返回结果 #存到字典 19 except Exception as e: 20 21 # ————————08CMDB采集硬件数据日志记录———————— 22 msg = "%s windows系统CPU插件错误:%s" #错误信息 23 import traceback #捕获并打印异常 24 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 25 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 26 # ————————08CMDB采集硬件数据日志记录———————— 27 28 response.status = False 29 return response 30 31 @staticmethod#返回函数的静态方法 32 def windows_parse(content): 33 response = {} 34 cpu_physical_set = set()#set()函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。 35 for item in content: 36 response['cpu_model'] = item.Manufacturer # cpu型号 37 response['cpu_count'] = item.NumberOfCores # cpu核心个量 38 cpu_physical_set.add(item.DeviceID) #CPU物理个量 39 response['cpu_physical_count'] = len(cpu_physical_set)#CPU物理个量 40 return response #返回结果 41 42 # ————————05CMDB采集硬件数据的插件———————— 43 44 # ————————07CMDB文件模式测试采集硬件数据———————— 45 def test(self): 46 response = BaseResponse() #提交数据的类型(字典) 47 import os # 操作系统层面执行 48 from config.settings import BASEDIR # 获取路径 49 try: 50 output = open(os.path.join(BASEDIR, 'files/linux_out/cpu.out'), 'r').read() #打开文件获取内容 51 response.data = self.linux_parse(output)#解析shell命令返回结果 52 except Exception as e: 53 54 # ————————08CMDB采集硬件数据日志记录———————— 55 msg = "%s 测试系统CPU插件错误:%s" #错误信息 56 import traceback #捕获并打印异常 57 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 58 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 59 # ————————08CMDB采集硬件数据日志记录———————— 60 61 response.status = False 62 return response 63 # ————————07CMDB文件模式测试采集硬件数据———————— 64 65 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 66 def linux(self): 67 response = BaseResponse() # 提交数据的类型(字典) 68 try: 69 import subprocess # 启动一个新的进程并且与之通信 70 shell_command = "cat /proc/cpuinfo" # 定义命令 lscpu 71 output = subprocess.getoutput(shell_command) # linux系统上执行的命令 72 response.data = self.linux_parse(output) # 解析shell命令返回结果 73 except Exception as e: 74 75 # ————————08CMDB采集硬件数据日志记录———————— 76 msg = "%s linux系统CPU插件错误:%s" #错误信息 77 import traceback #捕获并打印异常 78 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 79 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 80 # ————————08CMDB采集硬件数据日志记录———————— 81 82 response.status = False 83 return response 84 85 @staticmethod # 返回函数的静态方法 86 def linux_parse(content): # 解析shell命令返回结果 87 response = {'cpu_count': 0, 'cpu_physical_count': 0, 'cpu_model': ''} 88 cpu_physical_set = set() # set()函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。 89 content = content.strip() # strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列 90 for item in content.split(' '): # split()通过指定分隔符对字符串进行切片 91 for row_line in item.split(' '): 92 key, value = row_line.split(':') 93 key = key.strip() 94 if key == 'processor': 95 response['cpu_count'] += 1 # cpu核心个量 96 elif key == 'physical id': 97 cpu_physical_set.add(value) # CPU物理个量 98 elif key == 'model name': 99 if not response['cpu_model']: 100 response['cpu_model'] = value # cpu型号 101 response['cpu_physical_count'] = len(cpu_physical_set) # CPU物理个量 102 return response 103 # ————————06CMDB测试Linux系统采集硬件数据的命令————————
1 # disk.py 2 # ————————05CMDB采集硬件数据的插件———————— 3 from .base import BasePlugin #采集资产的方式 和 系统平台 4 from lib.response import BaseResponse #提交数据的类型(字典) 5 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 6 # import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 7 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 8 9 class DiskPlugin(BasePlugin): 10 def windows(self): 11 response = BaseResponse() #提交数据的类型(字典) 12 try: 13 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 14 import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 15 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 16 output =wmi.WMI().Win32_DiskDrive() #获取磁盘相关信息 17 response.data = self.windows_parse(output) #解析相关信息 返回结果 #存到字典 18 except Exception as e: 19 20 # ————————08CMDB采集硬件数据日志记录———————— 21 msg = "%s windows系统硬盘插件错误:%s" #错误信息 22 import traceback #捕获并打印异常 23 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 24 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 25 # ————————08CMDB采集硬件数据日志记录———————— 26 27 response.status = False 28 return response 29 30 @staticmethod#返回函数的静态方法 31 def windows_parse(content): 32 response = {} 33 for item in content: 34 item_dict = {} 35 item_dict['slot'] = item.Index #插槽位 36 item_dict['pd_type'] = item.InterfaceType #磁盘型号 37 item_dict['capacity'] = round(int(item.Size) / (1024**3)) # 磁盘容量 38 item_dict['model'] = item.Model #磁盘类型 39 response[item_dict['slot']] = item_dict #分割存每个 磁盘信息 40 return response #返回结果 41 # ————————05CMDB采集硬件数据的插件———————— 42 43 # ————————07CMDB文件模式测试采集硬件数据———————— 44 def test(self): 45 response = BaseResponse() #提交数据的类型(字典) 46 import os # 操作系统层面执行 47 from config.settings import BASEDIR # 获取路径 48 try: 49 output = open(os.path.join(BASEDIR, 'files/linux_out/disk.out'), 'r').read() #打开文件获取内容 linux_virtual_out linux_out 50 response.data = self.linux_parse(output)#解析shell命令返回结果 51 except Exception as e:#如果获取内容错误或者解析错误就换一个方式 52 try: 53 output = open(os.path.join(BASEDIR, 'files/linux_virtual_out/disk.out'),'r').read() # 打开文件获取内容 linux_virtual_out linux_out 54 response.data = self.linux_virtual_parse(output) # 解析shell命令返回结果 55 except Exception as e:#如果 出现未知错误 56 57 # ————————08CMDB采集硬件数据日志记录———————— 58 msg = "%s 测试系统硬盘插件错误:%s" # 错误信息 59 import traceback # 捕获并打印异常 60 self.logger.log(msg % (self.hostname, traceback.format_exc()), False) # 写入本地日志 61 response.error = msg % (self.hostname, traceback.format_exc()) # 发送到远程日志 62 # ————————08CMDB采集硬件数据日志记录———————— 63 response.status = False 64 return response 65 66 # ————————07CMDB文件模式测试采集硬件数据———————— 67 68 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 69 def linux(self): 70 response = BaseResponse() #提交数据的类型(字典) 71 try: 72 import subprocess # 启动一个新的进程并且与之通信 73 shell_command = "sudo MegaCli -PDList -aALL" #定义命令#需要安装 MegaCli 模块 74 output = subprocess.getoutput(shell_command) #linux系统上执行的命令 75 if 'MegaCli'in output: 76 shell_command = "lsblk" # 虚拟机 #lsblk 77 output = subprocess.getoutput(shell_command) # linux系统上执行的命令 78 response.data = self.linux_virtual_parse(output) # 解析shell命令返回结果 79 else: 80 response.data = self.linux_parse(output)#解析shell命令返回结果 81 except Exception as e: # 如果 出现未知错误 82 83 # ————————08CMDB采集硬件数据日志记录———————— 84 msg = "%s linux系统硬盘插件错误:%s" #错误信息 85 import traceback #捕获并打印异常 86 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 87 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 88 # ————————08CMDB采集硬件数据日志记录———————— 89 90 response.status = False 91 return response 92 93 def linux_virtual_parse(self, content): # 解析shell命令返回结果 94 content = [i for i in content.split(' ') if i != ''] # split()通过指定分隔符对字符串进行切片 95 key_list = [i for i in content[0].split(' ') if i != ''] # split()通过指定分隔符对字符串进行切片 96 key_list[0] = 'slot' # 替换key的名字 97 key_list[3] = 'capacity' 98 key_list[5] = 'pd_type' 99 ram_dict = {} 100 for i in content[1:]: # 从列表下标1开始循环 101 segment = {} 102 value = [x for x in i.split(' ') if x != ''] # 如果不是空值就循环 # split()通过指定分隔符对字符串进行切片 103 filter = str(value) # 列表转成字符串进行判断 104 if '攢' not in filter: # '─' '攢' #二级逻辑硬盘 105 if '─' not in filter: # '─' '攢' #二级逻辑硬盘 106 list = zip(key_list, value) # zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。 107 for k, v in list: 108 if k == 'capacity': # 处理单位问题 109 if 'G' in v: 110 l = v.split('G') # split()通过指定分隔符对字符串进行切片 111 v = l[0] 112 if 'M' in v: # 处理单位问题 113 l = v.split('M') # split()通过指定分隔符对字符串进行切片 114 s = l[0] 115 m = int(s) 116 v = m / 1024 117 segment[k] = v 118 ram_dict[value[0]] = segment 119 return ram_dict 120 121 def linux_parse(self, content): # 解析shell命令返回结果 122 import re # 正则表达式 123 response = {} 124 result = [] 125 for row_line in content.split(" "): # split()通过指定分隔符对字符串进行切片 126 result.append(row_line) # 添加到列表 127 for item in result: # 循环列表 128 temp_dict = {} 129 for row in item.split(' '): # split()通过指定分隔符对字符串进行切片 130 if not row.strip(): # strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列 131 continue 132 if len(row.split(':')) != 2: # 测试长度 133 continue 134 key, value = row.split(':') # split()通过指定分隔符对字符串进行切片 135 name = self.mega_patter_match(key) 136 if name: 137 if key == 'Raw Size': # 磁盘容量 138 raw_size = re.search('(d+.d+)', 139 value.strip()) # Raw Size: 279.396 GB [0x22ecb25c Sectors] 140 if raw_size: 141 temp_dict[name] = raw_size.group() 142 else: 143 raw_size = '0' 144 else: 145 temp_dict[name] = value.strip() # 磁盘型号 #磁盘类型 146 if temp_dict: 147 response[temp_dict['slot']] = temp_dict # 插槽位 #分割存每个 磁盘信息 148 return response 149 150 @staticmethod # 返回函数的静态方法 151 def mega_patter_match(needle): 152 grep_pattern = {'Slot': 'slot', 'Raw Size': 'capacity', 'Inquiry': 'model', 'PD Type': 'pd_type'} 153 for key, value in grep_pattern.items(): 154 if needle.startswith(key): # 确定此字符串实例的开头是否与指定的字符串匹配 155 return value 156 return False 157 # ————————06CMDB测试Linux系统采集硬件数据的命令————————
1 # main_board.py 2 # ————————05CMDB采集硬件数据的插件———————— 3 from .base import BasePlugin #采集资产的方式 和 系统平台 4 from lib.response import BaseResponse #提交数据的类型(字典) 5 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 6 # import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 7 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 8 9 class MainBoardPlugin(BasePlugin): 10 def windows(self): 11 response = BaseResponse() #提交数据的类型(字典) 12 try: 13 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 14 import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 15 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 16 output =wmi.WMI().Win32_BaseBoard() #获取主板相关信息 17 response.data = self.windows_parse(output) #解析相关信息 返回结果 #存到字典 18 except Exception as e: 19 20 # ————————08CMDB采集硬件数据日志记录———————— 21 msg = "%s windows系统主板插件错误:%s" #错误信息 22 import traceback #捕获并打印异常 23 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 24 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 25 # ————————08CMDB采集硬件数据日志记录———————— 26 27 response.status = False 28 return response 29 30 @staticmethod#返回函数的静态方法 31 def windows_parse(content): 32 response = {} 33 for item in content: 34 response['Manufacturer'] = item.Manufacturer #主板制造商 35 response['model'] = item.Name #主板型号 36 response['sn'] = item.SerialNumber #主板SN号 37 return response #返回结果 38 # ————————05CMDB采集硬件数据的插件———————— 39 40 # ————————07CMDB文件模式测试采集硬件数据———————— 41 def test(self): 42 response = BaseResponse() #提交数据的类型(字典) 43 import os # 操作系统层面执行 44 from config.settings import BASEDIR # 获取路径 45 try: 46 output = open(os.path.join(BASEDIR, 'files/linux_out/board.out'), 'r').read() #打开文件获取内容 47 response.data = self.linux_parse(output)#解析shell命令返回结果 48 except Exception as e: 49 # ————————08CMDB采集硬件数据日志记录———————— 50 msg = "%s 测试系统主板插件错误:%s" #错误信息 51 import traceback #捕获并打印异常 52 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 53 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 54 # ————————08CMDB采集硬件数据日志记录———————— 55 response.status = False 56 return response 57 # ————————07CMDB文件模式测试采集硬件数据———————— 58 59 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 60 def linux(self): 61 response = BaseResponse() #提交数据的类型(字典) 62 try: 63 import subprocess # 启动一个新的进程并且与之通信 64 shell_command = "sudo dmidecode -t1" #定义命令 65 output =subprocess.getoutput(shell_command) #linux系统上执行的命令 66 response.data = self.linux_parse(output) #解析shell命令返回结果 67 except Exception as e: 68 # ————————08CMDB采集硬件数据日志记录———————— 69 msg = "%s linux系统主板插件错误:%s" #错误信息 70 import traceback #捕获并打印异常 71 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 72 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 73 # ————————08CMDB采集硬件数据日志记录———————— 74 response.status = False 75 return response 76 77 def linux_parse(self, content):#解析shell命令返回结果 78 result = {} 79 key_map = {'Manufacturer': 'manufacturer', 'Product Name': 'model','Serial Number': 'sn',} 80 for item in content.split(' '): #split()通过指定分隔符对字符串进行切片 81 row_data = item.strip().split(':') #strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列 82 if len(row_data) == 2: 83 if row_data[0] in key_map:#如果在需要的字典里 84 result[key_map[row_data[0]]] = row_data[1].strip() if row_data[1] else row_data[1] 85 return result 86 # ————————06CMDB测试Linux系统采集硬件数据的命令————————
1 # memory.py 2 # ————————05CMDB采集硬件数据的插件———————— 3 from .base import BasePlugin #采集资产的方式 和 系统平台 4 from lib.response import BaseResponse #提交数据的类型(字典) 5 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 6 # import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 7 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 8 9 class MemoryPlugin(BasePlugin): 10 def windows(self): 11 response = BaseResponse() #提交数据的类型(字典) 12 try: 13 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 14 import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 15 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 16 output =wmi.WMI().Win32_PhysicalMemory() #获取内存相关信息 17 response.data = self.windows_parse(output) 18 except Exception as e: 19 20 # ————————08CMDB采集硬件数据日志记录———————— 21 msg = "%s windows系统内存插件错误:%s" #错误信息 22 import traceback #捕获并打印异常 23 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 24 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 25 # ————————08CMDB采集硬件数据日志记录———————— 26 27 response.status = False 28 return response 29 30 @staticmethod#返回函数的静态方法 31 def windows_parse(content): 32 response={} 33 for item in content: 34 item_dict = {} 35 item_dict['slot'] = item.DeviceLocator #插槽位 36 item_dict['manufacturer'] = item.Manufacturer # 内存制造商 37 item_dict['model'] =item.FormFactor # 内存型号 38 item_dict['Capacity'] = round(int(item.Capacity) / (1024**3)) # 内存容量 39 item_dict['sn'] = item.SerialNumber #内存SN号 40 item_dict['speed'] = item.Speed #内存速度 41 response[item_dict['slot']] = item_dict #分割存每条 内存信息 42 return response 43 44 # ————————05CMDB采集硬件数据的插件———————— 45 # ————————07CMDB文件模式测试采集硬件数据———————— 46 def test(self): 47 response = BaseResponse() #提交数据的类型(字典) 48 import os # 操作系统层面执行 49 from config.settings import BASEDIR # 获取路径 50 try: 51 output = open(os.path.join(BASEDIR, 'files/linux_out/memory.out'), 'r').read() #打开文件获取内容 linux_virtual_out linux_out 52 response.data = self.linux_parse(output) # 解析shell命令返回结果 53 except Exception as e:#如果获取内容错误或者解析错误就换一个方式 54 try: 55 output = open(os.path.join(BASEDIR, 'files/linux_virtual_out/memory.out'),'r').read() # 打开文件获取内容 linux_virtual_out linux_out 56 response.data = self.linux_virtual_parse(output) # 解析shell命令返回结果 57 except Exception as e: 58 # ————————08CMDB采集硬件数据日志记录———————— 59 msg = "%s 测试系统内存插件错误:%s" # 错误信息 60 import traceback # 捕获并打印异常 61 self.logger.log(msg % (self.hostname, traceback.format_exc()), False) # 写入本地日志 62 response.error = msg % (self.hostname, traceback.format_exc()) # 发送到远程日志 63 # ————————08CMDB采集硬件数据日志记录———————— 64 response.status = False 65 return response 66 # ————————07CMDB文件模式测试采集硬件数据———————— 67 68 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 69 def linux(self): 70 response = BaseResponse() #提交数据的类型(字典) 71 try: 72 import subprocess # 启动一个新的进程并且与之通信 73 shell_command = "sudo dmidecode -q -t 17 2>/dev/null" #定义命令 cat /proc/swaps #swapon 74 output = subprocess.getoutput(shell_command) #linux系统上执行的命令 75 if not output: 76 shell_command = "swapon" # 定义命令 cat /proc/swaps #swapon 77 output = subprocess.getoutput(shell_command) # linux系统上执行的命令 78 response.data = self.linux_virtual_parse(output) # 解析shell命令返回结果 79 else: 80 response.data = self.linux_parse(output) # 解析shell命令返回结果 81 except Exception as e: # 如果 出现未知错误 82 # ————————08CMDB采集硬件数据日志记录———————— 83 msg = "%s linux系统内存插件错误:%s" #错误信息 84 import traceback #捕获并打印异常 85 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 86 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 87 # ————————08CMDB采集硬件数据日志记录———————— 88 response.status = False 89 return response 90 91 def convert_mb_to_gb(self,value, default=0):#转换单位 92 try: 93 value = value.strip('MB') #strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列 94 result = int(value) 95 except Exception as e: 96 result = default 97 return result 98 99 def linux_virtual_parse(self, content): # 解析shell命令返回结果 100 content = [i for i in content.split(' ') if i != ''] # split()通过指定分隔符对字符串进行切片 101 key_list = [i for i in content[0].split(' ') if i != ''] # split()通过指定分隔符对字符串进行切片 102 key_list[0] = 'slot' #替换key的名字 103 key_list[1] = 'model' 104 key_list[2] = 'capacity' 105 ram_dict = {} 106 for i in content[1:]: # 从列表下标1开始循环 107 segment = {} 108 value = [x for x in i.split(' ') if x != '']#如果不是空值就循环 # split()通过指定分隔符对字符串进行切片 109 list = zip(key_list, value) # zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。 110 for k, v in list: 111 if k=='capacity': #处理单位问题 112 if 'M' in v: 113 l = v.split('M') # split()通过指定分隔符对字符串进行切片 114 v = l[0] 115 if 'G' in v: # 处理单位问题 116 l = v.split('G') # split()通过指定分隔符对字符串进行切片 117 s = l[0] 118 m = int(s) 119 v = m * 1024 120 segment[k] = v 121 ram_dict[value[0]] = segment 122 return ram_dict 123 124 def linux_parse(self, content): # 解析shell命令返回结果 125 ram_dict = {} 126 key_map = {'Size': 'capacity','Locator': 'slot','Type': 'model','Speed': 'speed', 127 'Manufacturer': 'manufacturer','Serial Number': 'sn',} 128 devices = content.split('Memory Device') #split()通过指定分隔符对字符串进行切片 129 for item in devices: 130 item = item.strip() #strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列 131 if not item: 132 continue 133 if item.startswith('#'): #startswith()方法用于检查字符串是否是以指定子字符串开头 134 continue 135 segment = {} 136 lines = item.split(' ') #split()通过指定分隔符对字符串进行切片 137 for line in lines: 138 if len(line.split(':')) > 1: #split()通过指定分隔符对字符串进行切片 139 key, value = line.split(':') #split()通过指定分隔符对字符串进行切片 140 else: 141 key = line.split(':')[0] #split()通过指定分隔符对字符串进行切片 142 value = "" 143 if key in key_map: 144 if key == 'Size': # 内存容量 145 segment[key_map['Size']] = self.convert_mb_to_gb(value, 0) #转换单位 146 else: 147 segment[key_map[key.strip()]] = value.strip() #strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列 148 ram_dict[segment['slot']] = segment #插槽位 #分割存每条 内存信息 149 return ram_dict 150 # ————————06CMDB测试Linux系统采集硬件数据的命令————————
1 # nic.py 2 # ————————05CMDB采集硬件数据的插件———————— 3 from .base import BasePlugin #采集资产的方式 和 系统平台 4 from lib.response import BaseResponse #提交数据的类型(字典) 5 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 6 # import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 7 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 8 9 class NicPlugin(BasePlugin): 10 def windows(self): 11 response = BaseResponse() #提交数据的类型(字典) 12 try: 13 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 14 import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块 15 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 16 output =wmi.WMI().Win32_NetworkAdapterConfiguration() #获取网卡相关信息 17 response.data = self.windows_parse(output) #解析相关信息 返回结果 #存到字典 18 except Exception as e: 19 20 # ————————08CMDB采集硬件数据日志记录———————— 21 msg = "%s windows系统网卡插件错误:%s" #错误信息 22 import traceback #捕获并打印异常 23 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 24 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 25 # ————————08CMDB采集硬件数据日志记录———————— 26 27 response.status = False 28 return response 29 30 @staticmethod#返回函数的静态方法 31 def windows_parse(content): 32 response={} 33 IPCM = 0 # 权重 34 for item in content: 35 if item.IPConnectionMetric: # 权重 36 if item.IPConnectionMetric > IPCM: # 权重 #防止虚拟网卡 37 item_dict = {} 38 name=item.ServiceName # 网卡名称 39 item_dict['hwaddr'] = item.MACAddress # 网卡MAC地址 40 item_dict['ipaddrs'] = item.IPAddress[0] # IP地址 41 item_dict['netmask'] = item.IPSubnet[0] # IP子网掩码 42 item_dict['up'] = item.IPEnabled #是否有启用 43 response[name] = item_dict 44 IPCM = item.IPConnectionMetric # 权重 45 return response 46 # ————————05CMDB采集硬件数据的插件———————— 47 48 # ————————07CMDB文件模式测试采集硬件数据———————— 49 def test(self): 50 response = BaseResponse() #提交数据的类型(字典) 51 import os # 操作系统层面执行 52 from config.settings import BASEDIR # 获取路径 53 try: 54 output = open(os.path.join(BASEDIR, 'files/linux_out/nic.out'), 'r').read() #打开文件获取内容 55 interfaces_info = self._interfaces_ip(output) #接口 # 解析shell命令返回结果 56 self.standard(interfaces_info) # 内容进行 标准化 57 response.data = interfaces_info # 解析shell命令返回结果 58 except Exception as e: 59 # ————————08CMDB采集硬件数据日志记录———————— 60 msg = "%s 测试系统网卡插件错误:%s" #错误信息 61 import traceback #捕获并打印异常 62 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 63 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 64 # ————————08CMDB采集硬件数据日志记录———————— 65 response.status = False 66 return response 67 # ————————07CMDB文件模式测试采集硬件数据———————— 68 69 70 # ————————06CMDB测试Linux系统采集硬件数据的命令———————— 71 def linux(self): 72 response = BaseResponse() #提交数据的类型(字典) 73 try: 74 interfaces_info = self.linux_interfaces() #linux系统上执行的命令 75 self.standard(interfaces_info) # 内容进行 标准化 76 response.data = interfaces_info # 解析shell命令返回结果 77 except Exception as e: 78 # ————————08CMDB采集硬件数据日志记录———————— 79 msg = "%s linux系统网卡插件错误:%s" #错误信息 80 import traceback #捕获并打印异常 81 self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志 82 response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志 83 # ————————08CMDB采集硬件数据日志记录———————— 84 response.status = False 85 return response 86 87 def standard(self, interfaces_info):# 内容进行 标准化 88 for key, value in interfaces_info.items(): 89 ipaddrs = set()#set()函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。 90 netmask = set() 91 if not 'inet' in value: 92 value['ipaddrs'] = '' # IP地址 93 value['netmask'] = '' # IP子网掩码 94 else: 95 for item in value['inet']: 96 ipaddrs.add(item['address']) # IP地址 97 netmask.add(item['netmask']) # IP子网掩码 98 value['ipaddrs'] = '/'.join(ipaddrs) # IP地址 99 value['netmask'] = '/'.join(netmask) # IP子网掩码 100 del value['inet'] 101 102 def linux_interfaces(self):#获得* NIX / BSD变种接口信息 103 ifaces = dict() #dict() 函数用于创建一个字典。返回一个字典。 104 ip_path = 'ip' 105 if ip_path: 106 # ————————在使用#linux系统上执行的命令时开启———————— 107 import subprocess # 启动一个新的进程并且与之通信 108 cmd1 = subprocess.getoutput('sudo {0} link show'.format(ip_path)) #定义命令ip link show 109 cmd2 = subprocess.getoutput('sudo {0} addr show'.format(ip_path)) #定义命令ip addr show 110 ifaces = self._interfaces_ip(cmd1 + ' ' + cmd2) #linux系统上执行的命令 #接口 # 解析shell命令返回结果 111 # ————————在使用#linux系统上执行的命令时开启———————— 112 return ifaces 113 114 def which(self, exe): 115 import os # 操作系统层面执行 116 def _is_executable_file_or_link(exe): 117 # 检查操作系统。X_OK不足够了,因为目录可能会执行 118 return (os.access(exe, os.X_OK) and 119 (os.path.isfile(exe) or os.path.islink(exe))) 120 121 if exe: 122 if _is_executable_file_or_link(exe): 123 # executable in cwd or fullpath 124 return exe 125 126 # 默认路径基于busybox的默认 127 default_path = '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin' 128 search_path = os.environ.get('PATH', default_path) 129 path_ext = os.environ.get('PATHEXT', '.EXE') 130 ext_list = path_ext.split(';') 131 132 search_path = search_path.split(os.pathsep) 133 if True: 134 """ 135 # 添加任何dirs default_path search_path不。如果 136 # 没有PATH变量中发现操作系统。环境,那么这将是 137 # 无为法。这将确保所有dirs default_path 138 # 搜索,让salt.utils.which()调用时工作得很好 139 # salt-call从cron(取决于平台 140 # 有一个极其有限的路径)。 141 """ 142 search_path.extend( 143 [ 144 x for x in default_path.split(os.pathsep) 145 if x not in search_path 146 ] 147 ) 148 for path in search_path: 149 full_path = os.path.join(path, exe) 150 if _is_executable_file_or_link(full_path): 151 return full_path 152 return None 153 154 def _number_of_set_bits_to_ipv4_netmask(self, set_bits): # pylint: disable=C0103 155 ''' 156 返回一个整数表示的IPv4网络掩码,面具。 157 158 Ex. 0xffffff00 -> '255.255.255.0' 159 ''' 160 return self.cidr_to_ipv4_netmask(self._number_of_set_bits(set_bits)) 161 def cidr_to_ipv4_netmask(self, cidr_bits): 162 ''' 163 返回一个IPv4网络掩码 164 ''' 165 try: 166 cidr_bits = int(cidr_bits) 167 if not 1 <= cidr_bits <= 32: 168 return '' 169 except ValueError: 170 return '' 171 netmask = '' 172 for idx in range(4): 173 if idx: 174 netmask += '.' 175 if cidr_bits >= 8: 176 netmask += '255' 177 cidr_bits -= 8 178 else: 179 netmask += '{0:d}'.format(256 - (2 ** (8 - cidr_bits))) 180 cidr_bits = 0 181 return netmask 182 def _number_of_set_bits(self, x): 183 ''' 184 返回的比特数,设置在一个32位整数 185 #来自http://stackoverflow.com/a/4912729 186 ''' 187 x -= (x >> 1) & 0x55555555 188 x = ((x >> 2) & 0x33333333) + (x & 0x33333333) 189 x = ((x >> 4) + x) & 0x0f0f0f0f 190 x += x >> 8 191 x += x >> 16 192 return x & 0x0000003f 193 194 def _interfaces_ip(self, out): #接口 # 解析shell命令返回结果 195 import re # 正则表达式 196 ''' 197 使用ip来返回一个字典的接口的各种信息 198 每个(向上/向下状态、ip地址、子网掩码和hwaddr) 199 ''' 200 ret = dict() 201 right_keys = ['name', 'hwaddr', 'up', 'netmask', 'ipaddrs'] 202 203 def parse_network(value, cols): 204 ''' 205 子网掩码,返回一个元组的ip广播 206 基于当前的关口 207 ''' 208 brd = None 209 if '/' in value: # 我们有一个CIDR在这个地址 210 ip, cidr = value.split('/') # pylint:禁用= C0103 211 else: 212 ip = value # pylint:禁用= C0103 213 cidr = 32 214 215 if type_ == 'inet': 216 mask = self.cidr_to_ipv4_netmask(int(cidr)) 217 if 'brd' in cols: 218 brd = cols[cols.index('brd') + 1] 219 return (ip, mask, brd) 220 221 groups = re.compile(' ? \d').split(out) 222 for group in groups: 223 iface = None 224 data = dict() 225 226 for line in group.splitlines(): 227 if ' ' not in line: 228 continue 229 match = re.match(r'^d*:s+([w.-]+)(?:@)?([w.-]+)?:s+<(.+)>', line) 230 if match: 231 iface, parent, attrs = match.groups() 232 if 'UP' in attrs.split(','): 233 data['up'] = True 234 else: 235 data['up'] = False 236 if parent and parent in right_keys: 237 data[parent] = parent 238 continue 239 240 cols = line.split() 241 if len(cols) >= 2: 242 type_, value = tuple(cols[0:2]) 243 iflabel = cols[-1:][0] 244 if type_ in ('inet',): 245 if 'secondary' not in cols: 246 ipaddr, netmask, broadcast = parse_network(value, cols) 247 if type_ == 'inet': 248 if 'inet' not in data: 249 data['inet'] = list() 250 addr_obj = dict() 251 addr_obj['address'] = ipaddr 252 addr_obj['netmask'] = netmask 253 addr_obj['broadcast'] = broadcast 254 data['inet'].append(addr_obj) 255 256 else: 257 if 'secondary' not in data: 258 data['secondary'] = list() 259 ip_, mask, brd = parse_network(value, cols) 260 data['secondary'].append({ 261 'type': type_, 262 'address': ip_, 263 'netmask': mask, 264 'broadcast': brd, 265 }) 266 del ip_, mask, brd 267 elif type_.startswith('link'): 268 data['hwaddr'] = value 269 if iface: 270 if iface.startswith('pan') or iface.startswith('lo') or iface.startswith('v'): 271 del iface, data 272 else: 273 ret[iface] = data 274 del iface, data 275 return ret 276 # ————————06CMDB测试Linux系统采集硬件数据的命令————————