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)\nKernel \r on an \m""" 42 result = output.strip().split('\n')[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('\n')[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('\n\n'): # split()經過指定分隔符對字符串進行切片 91 for row_line in item.split('\n'): 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('\n') 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("\n\n\n\n"): # split()經過指定分隔符對字符串進行切片 126 result.append(row_line) # 添加到列表 127 for item in result: # 循環列表 128 temp_dict = {} 129 for row in item.split('\n'): # 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('\n'): #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('\n') 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('\n\t') #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 + '\n' + 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('\r?\n\\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系統採集硬件數據的命令————————