#settings.py
# ————————01CMDB获取服务器基本信息————————
import os BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))##当前路径 # 采集资产的方式,选项有:agent(默认), salt, ssh
MODE = 'agent' # ————————01CMDB获取服务器基本信息———————— # ————————02CMDB将服务器基本信息提交到API接口————————
# 资产信息API
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
# ASSET_API = "http://127.0.0.1:8000/api/asset"
ASSET_API = "http://192.168.80.53:8000/api/asset"
# ————————06CMDB测试Linux系统采集硬件数据的命令———————— # ————————02CMDB将服务器基本信息提交到API接口———————— # ————————03CMDB信息安全API接口交互认证————————
# 用于API认证的KEY
KEY = '299095cc-1330-11e5-b06a-a45e60bec08b' #认证的密码
# 用于API认证的请求头
AUTH_KEY_NAME = 'auth-key'
# ————————03CMDB信息安全API接口交互认证———————— # ————————04CMDB本地(Agent)模式客户端唯一标识(ID)————————
# Agent模式保存服务器唯一ID的文件
CERT_FILE_PATH = os.path.join(BASEDIR, 'config', 'cert') #文件路径
# ————————04CMDB本地(Agent)模式客户端唯一标识(ID)———————— # ————————05CMDB采集硬件数据的插件————————
# 采集硬件数据的插件
PLUGINS_DICT = {
'cpu': 'src.plugins.cpu.CpuPlugin',
'disk': 'src.plugins.disk.DiskPlugin',
'main_board': 'src.plugins.main_board.MainBoardPlugin',
'memory': 'src.plugins.memory.MemoryPlugin',
'nic': 'src.plugins.nic.NicPlugin',
}
# ————————05CMDB采集硬件数据的插件———————— # ————————07CMDB文件模式测试采集硬件数据————————
# 是否测试模式,测试模时候数据从files目录下读取信息 选项有:#True False
TEST_MODE = True
# ————————07CMDB文件模式测试采集硬件数据———————— # ————————08CMDB采集硬件数据日志记录————————
# 错误日志
ERROR_LOG_FILE = os.path.join(BASEDIR, "log", 'error.log')
# 运行日志
RUN_LOG_FILE = os.path.join(BASEDIR, "log", 'run.log')
# ————————08CMDB采集硬件数据日志记录————————

#settings.py

 #log.py

 # ————————08CMDB采集硬件数据日志记录————————
import os # 操作系统层面执行
import logging #日志模块
from config import settings #配置文件 class Logger(object):
__instance = None #实例 def __init__(self):
self.run_log_file = settings.RUN_LOG_FILE #运行日志路径 RUN_LOG_FILE = os.path.join(BASEDIR, "log", 'run.log')
self.error_log_file = settings.ERROR_LOG_FILE #错误日志路径 ERROR_LOG_FILE = os.path.join(BASEDIR, "log", 'error.log')
self.run_logger = None #写运行日志
self.error_logger = None #写错误日志
self.initialize_run_log() #初始化运行日志
self.initialize_error_log() #初始化错误日志 def __new__(cls, *args, **kwargs):
if not cls.__instance: #实例
cls.__instance = object.__new__(cls, *args, **kwargs)
return cls.__instance #实例 @staticmethod# 返回函数的静态方法
def check_path_exist(log_abs_file): #路径
log_path = os.path.split(log_abs_file)[0]#log文件夹
# print('日志文件:',log_path)
if not os.path.exists(log_path):#判断是否存在 log文件夹
os.mkdir(log_path) #创建 log文件夹 def initialize_run_log(self):#初始化运行日志
self.check_path_exist(self.run_log_file) #运行日志路径
#————————创建文件————————
file_1_1 = logging.FileHandler(self.run_log_file, 'a', encoding='utf-8')#
fmt = logging.Formatter(fmt="%(asctime)s - %(levelname)s : %(message)s")
file_1_1.setFormatter(fmt)#为这个处理程序设置格式化程序。
# ————————创建文件————————
logger1 = logging.Logger('run_log', level=logging.INFO)#INFO = 20
logger1.addHandler(file_1_1) #指定处理程序添加到这个记录器。
self.run_logger = logger1
"""
日志对应的级别
#CRITICAL = 50 #FATAL = CRITICAL #ERROR = 40 #WARNING = 30
#WARN = WARNING #INFO = 20 #DEBUG = 10 #NOTSET = 0
"""
def initialize_error_log(self): #初始化错误日志
self.check_path_exist(self.error_log_file)#错误日志路径
# ————————创建文件————————
file_1_1 = logging.FileHandler(self.error_log_file, 'a', encoding='utf-8')
fmt = logging.Formatter(fmt="%(asctime)s - %(levelname)s : %(message)s")
file_1_1.setFormatter(fmt)
# ————————创建文件————————
logger1 = logging.Logger('run_log', level=logging.ERROR)#ERROR = 40
logger1.addHandler(file_1_1)
self.error_logger = logger1 def log(self, message, mode=True):#callback #写入日志#mode: True表示运行信息,False表示错误信息 if mode:
self.run_logger.info(message) #Logger().log(ret['message'], True)
else:
self.error_logger.error(message)# Logger().log(ret['message'], False)
# ————————08CMDB采集硬件数据日志记录————————

#log.py

 # client.py
# ————————01CMDB获取服务器基本信息————————
from src import plugins #__init__.py
from lib.serialize import Json #转成字符串或者模式 # ————————02CMDB将服务器基本信息提交到API接口————————
import requests #伪造页面访问
from config import settings #文件配置
# ————————02CMDB将服务器基本信息提交到API接口———————— # ————————03CMDB信息安全API接口交互认证————————
import hashlib
import time
# ————————03CMDB信息安全API接口交互认证———————— # ————————04CMDB本地(Agent)模式客户端唯一标识(ID)————————
import os #操作系统层面执行
import shutil #高级的 文件、文件夹、压缩包 处理模块
# ————————04CMDB本地(Agent)模式客户端唯一标识(ID)————————
class AutoBase(object): # ————————02CMDB将服务器基本信息提交到API接口————————
def __init__(self):
self.asset_api = settings.ASSET_API #ASSET_API = "http://127.0.0.1:8000/api/asset" # ————————03CMDB信息安全API接口交互认证————————
self.key = settings.KEY # 用于API认证的KEY#KEY = '299095cc-1330-11e5-b06a-a45e60bec08b'
self.key_name = settings.AUTH_KEY_NAME # 'auth-key' API认证的请求头
# ————————03CMDB信息安全API接口交互认证———————— # ————————03CMDB信息安全API接口交互认证————————
def auth_key(self):#API接口认证
ha = hashlib.md5(self.key.encode('utf-8'))#认证的密码
time_span = time.time() #现在的时间戳 #1529819687.8867188
ha.update(bytes("%s|%f" % (self.key, time_span), encoding='utf-8'))#更新认证密码#密码+时间戳
encryption = ha.hexdigest() # 对‘时间密码’进行哈希
result = "%s|%f" % (encryption, time_span) #把‘时间密码’和 时间戳(解密用) 作为 API认证的请求头
print('‘时间密码’和 时间戳:',result)
return {self.key_name: result} # 'auth-key' API认证的请求头
# ————————03CMDB信息安全API接口交互认证———————— # ————————08CMDB采集硬件数据日志记录————————
# def post_asset(self, msg):#post方式向API接口提交资产信息
def post_asset(self, msg, callback=None): #post方式向API接口提交资产信息
# ————————08CMDB采集硬件数据日志记录———————— status = True#是否获取到信息
try:
# ————————03CMDB信息安全API接口交互认证————————
headers = {}
headers.update(self.auth_key())##认证的密码
# ————————03CMDB信息安全API接口交互认证————————
response = requests.post(
url=self.asset_api,
# ————————03CMDB信息安全API接口交互认证————————
headers=headers,
# ————————03CMDB信息安全API接口交互认证————————
json=msg
)
except Exception as e:
response = e
status = False #获取信息时出现错误
print(response.json())
# ————————02CMDB将服务器基本信息提交到API接口———————— # ————————08CMDB采集硬件数据日志记录————————
print('服务器反馈:')
print(callback)
if callback:
callback(status, response)
# ————————08CMDB采集硬件数据日志记录———————— # ————————08CMDB采集硬件数据日志记录————————
def callback(self, status, response):#提交资产到服务器后的回调函数#请求成功,则是响应内容对象;请求错误,则是异常对象
import json
from lib.log import Logger #写日志
if not status:
Logger().log(str(response), False)
return
ret = json.loads(response.text)
if ret['code'] == 1000: #{'code': 1000, 'message': '[%s]更新完成' % hostname}
#参数1:内容 参数2:True 运行日志 False 错误日志
Logger().log(ret['message'], True)
else:#错误日志
Logger().log(ret['message'], False)
# ————————08CMDB采集硬件数据日志记录———————— def process(self):#派生类需要继承此方法,用于处理请求的入口
raise NotImplementedError('您必须实现过程的方法') class AutoAgent(AutoBase): # ————————04CMDB本地(Agent)模式客户端唯一标识(ID)————————
def __init__(self):
self.cert_file_path = settings.CERT_FILE_PATH# Agent模式保存服务器唯一ID的文件
super(AutoAgent, self).__init__()
"""
super() 函数是用于调用父类(超类)的一个方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,
但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
"""
def load_local_cert(self):# 获取本地唯一标识
if not os.path.exists(self.cert_file_path):#使用os.path.exists()方法可以直接判断文件(或者文件夹)是否存在
return None #如果文件(或者文件夹)不存在 #返回空
if os.path.isfile(self.cert_file_path): #判断是不是文件
with open(self.cert_file_path, mode='r') as f: #如果文件存在 #打开读取文件
data = f.read()#获取唯一ID的文件#read() 方法用于从文件读取指定的字节数,如果未给定或为负则读取所有。
if not data: # 如果文件没有内容 #返回空
return None
cert = data.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
return cert # 返回 本地唯一标识
else: #防止有文件夹叫cert,导致无法创建cert文件
shutil.rmtree(self.cert_file_path)#就 递归的去删除文件夹 #这个目录以及子文件全部删除
return None #返回空 #去创建文件 def write_local_cert(self, cert):#写入本地唯一标识
with open(self.cert_file_path, mode='w') as f: #循环打开文件 #没有就创建 然后打开
f.write(cert) #写入本地唯一标识
# ————————04CMDB本地(Agent)模式客户端唯一标识(ID)———————— def process(self):
server_info = plugins.get_server_info()#获取本地基本信息 # ————————04CMDB本地(Agent)模式客户端唯一标识(ID)————————
if not server_info.status: #获取的基本信息是否出错
return
local_cert = self.load_local_cert() # 去获取本地唯一标识
if local_cert: #如果 获取本地唯一标识 后 #不是 return None
if local_cert == server_info.data['hostname']: #判断本地文件的唯一标识 是不是等于 获取的基本信息里主机名
pass #一样就什么都不干
else: #不一样就把 获取的基本信息里主机名 替换成 本地文件的唯一标识
#防止 恶意篡改 主机名 ,上报API时 错认为是 新资产
server_info.data['hostname'] = local_cert # 更新字典的主机名
else: # 获取本地唯一标识为None时 #把获取到的主机名写入本地做为唯一标识
self.write_local_cert(server_info.data['hostname'])
# ————————04CMDB本地(Agent)模式客户端唯一标识(ID)———————— server_json = Json.dumps(server_info.data)#json.dumps将 Python 对象编码成 JSON 字符串
print('提交资产信息:',server_json)
# ————————01CMDB获取服务器基本信息———————— # ————————08CMDB采集硬件数据日志记录————————
# ————————02CMDB将服务器基本信息提交到API接口————————
# self.post_asset(server_json)# post方式向接口提交资产信息
self.post_asset(server_json, self.callback)# post方式向接口提交资产信息
# ————————02CMDB将服务器基本信息提交到API接口————————
# ————————08CMDB采集硬件数据日志记录————————

# client.py

 #base.py
# ————————08CMDB采集硬件数据日志记录————————
from lib.log import Logger
# ————————08CMDB采集硬件数据日志记录———————— # ————————01CMDB获取服务器基本信息————————
from config import settings #配置文件 class BasePlugin(object):
def __init__(self, hostname=''): # ————————08CMDB采集硬件数据日志记录————————
self.logger = Logger() #日志 实例化
self.hostname = hostname # 主机名默认为空,hostname=''
# ————————08CMDB采集硬件数据日志记录———————— # ————————07CMDB文件模式测试采集硬件数据————————
self.test_mode = settings.TEST_MODE#是否测试模式
# ————————07CMDB文件模式测试采集硬件数据———————— if hasattr(settings, 'MODE'):
self.mode = settings.MODE #采集资产的方式
else:
self.mode = 'agent'#默认,采集资产的方式
def execute(self): # ————————06CMDB测试Linux系统采集硬件数据的命令————————
# return self.windows()
try:#判断系统平台类型 # ————————07CMDB文件模式测试采集硬件数据————————
if self.test_mode: # 是否测试模式
return self.test() # 测试模式
# ————————07CMDB文件模式测试采集硬件数据———————— import platform # 获取操作系统信息 的模块
if platform.system() == 'Linux':
return self.linux() #执行 #def linux(self):
elif platform.system() == 'Windows':
return self.windows() # 执行 #def windows(self):
except Exception as e:
return '未知的系统平台类型!'
# ————————06CMDB测试Linux系统采集硬件数据的命令———————— def windows(self):
raise Exception('您必须实现windows的方法')
# ————————01CMDB获取服务器基本信息———————— # ————————06CMDB测试Linux系统采集硬件数据的命令————————
def linux(self):
raise Exception('您必须实现linux的方法')
# ————————06CMDB测试Linux系统采集硬件数据的命令———————— # ————————07CMDB文件模式测试采集硬件数据————————
def test(self):#测试模式
raise Exception('您必须实现test的方法')
# ————————07CMDB文件模式测试采集硬件数据————————

#base.py

 # basic.py
# ————————01CMDB获取服务器基本信息————————
from .base import BasePlugin #采集资产的方式
from lib.response import BaseResponse #提交数据的类型
import platform #platform模块给我们提供了很多方法去获取操作系统的信息 # ————————06CMDB测试Linux系统采集硬件数据的命令————————
# import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
"""
本模块基于windows操作系统,依赖wmi和win32com库,需要提前使用pip进行安装,
我们依然可以通过pip install pypiwin32来安装win32com模块
或者下载安装包手动安装。
""" class BasicPlugin(BasePlugin):
def os_platform(self):#获取系统平台
# ————————07CMDB文件模式测试采集硬件数据————————
# output=platform.system() #windows和Linux 都可以执行
# return output.strip()#strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 try:
if self.test_mode: # 是否测试模式
output = 'Linux' # 选择要测试的系统(windows和Linux或者苹果等未知的系统)
return output.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
output = platform.system() #windows和Linux 都可以执行
return output.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
except Exception as e:
return '未知的系统平台!'
# ————————07CMDB文件模式测试采集硬件数据———————— def os_version(self):#获取系统版本
# output = wmi.WMI().Win32_OperatingSystem()[0].Caption
# return output.strip()#strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 # ————————06CMDB测试Linux系统采集硬件数据的命令————————
try: # ————————07CMDB文件模式测试采集硬件数据————————
if self.test_mode: # 是否测试模式
output = """CentOS release 6.6 (Final)\nKernel \r on an \m"""
result = output.strip().split('\n')[0] # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。#split() 通过指定分隔符对字符串进行切片
return result
# ————————07CMDB文件模式测试采集硬件数据———————— if platform.system() == 'Linux':
import subprocess # 启动一个新的进程并且与之通信
output = subprocess.getoutput('cat /etc/issue') # Linux系统下的命令
result = output.strip().split('\n')[0] # split() 通过指定分隔符对字符串进行切片
# strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
return result
if platform.system() == 'Windows':
import wmi # Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
output = wmi.WMI().Win32_OperatingSystem()[0].Caption # Windows系统下的命令
result = output.strip()
# strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
return result
except Exception as e:
return '未知的系统版本!'
# ————————06CMDB测试Linux系统采集硬件数据的命令———————— def os_hostname(self):#获取主机名
# output = wmi.WMI().Win32_OperatingSystem()[0].CSName
# return output.strip()#strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。 # ————————06CMDB测试Linux系统采集硬件数据的命令————————
try: # ————————07CMDB文件模式测试采集硬件数据————————
if self.test_mode: # 是否测试模式
output = 'test.com'
return output.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
# ————————07CMDB文件模式测试采集硬件数据———————— if platform.system() == 'Linux':
import subprocess # 启动一个新的进程并且与之通信
output = subprocess.getoutput('hostname') # Linux系统下的命令
return output.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
elif platform.system() == 'Windows':
import wmi # Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
output = wmi.WMI().Win32_OperatingSystem()[0].CSName # Windows系统下的命令
return output.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
except Exception as e:
return '未知的主机名!'
# ————————06CMDB测试Linux系统采集硬件数据的命令———————— def windows(self):
response = BaseResponse()#提交数据的类型
try:
ret = {
'os_platform': self.os_platform(),#系统平台
'os_version': self.os_version(),#系统版本
'hostname': self.os_hostname(),#主机名
}
response.data = ret #字典形式
print('windows服务器基本信息:',response.data)
except Exception as e: # ————————08CMDB采集硬件数据日志记录————————
msg = "%s 基本的插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录———————— response.status = False # 获取信息时出现错误
return response
"""
class BaseResponse(object): #提交数据的类型
def __init__(self):
self.status = True #状态
self.message = None #消息
self.data = None #数据内容
self.error = None #错误信息 """
# ————————01CMDB获取服务器基本信息———————— # ————————06CMDB测试Linux系统采集硬件数据的命令————————
def linux(self):
response = self.windows() #因为执行同样的方法,所以,就不重复写。
print('linux服务器基本信息:', response.data)
return response
# ————————06CMDB测试Linux系统采集硬件数据的命令———————— # ————————07CMDB文件模式测试采集硬件数据————————
def test(self):
response = self.windows() #因为执行同样的方法,所以,就不重复写。
print('test服务器基本信息:', response.data)
return response
# ————————07CMDB文件模式测试采集硬件数据————————

# basic.py

 # cpu.py
# ————————05CMDB采集硬件数据的插件————————
from .base import BasePlugin #采集资产的方式 和 系统平台
from lib.response import BaseResponse #提交数据的类型(字典) # ————————06CMDB测试Linux系统采集硬件数据的命令————————
# import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
# ————————06CMDB测试Linux系统采集硬件数据的命令———————— class CpuPlugin(BasePlugin):
def windows(self):
response = BaseResponse() #提交数据的类型(字典)
try:
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
output =wmi.WMI().Win32_Processor() #获取CPU相关信息
response.data = self.windows_parse(output) #解析相关信息 返回结果 #存到字典
except Exception as e: # ————————08CMDB采集硬件数据日志记录————————
msg = "%s windows系统CPU插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录———————— response.status = False
return response @staticmethod#返回函数的静态方法
def windows_parse(content):
response = {}
cpu_physical_set = set()#set()函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。
for item in content:
response['cpu_model'] = item.Manufacturer # cpu型号
response['cpu_count'] = item.NumberOfCores # cpu核心个量
cpu_physical_set.add(item.DeviceID) #CPU物理个量
response['cpu_physical_count'] = len(cpu_physical_set)#CPU物理个量
return response #返回结果 # ————————05CMDB采集硬件数据的插件———————— # ————————07CMDB文件模式测试采集硬件数据————————
def test(self):
response = BaseResponse() #提交数据的类型(字典)
import os # 操作系统层面执行
from config.settings import BASEDIR # 获取路径
try:
output = open(os.path.join(BASEDIR, 'files/linux_out/cpu.out'), 'r').read() #打开文件获取内容
response.data = self.linux_parse(output)#解析shell命令返回结果
except Exception as e: # ————————08CMDB采集硬件数据日志记录————————
msg = "%s 测试系统CPU插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录———————— response.status = False
return response
# ————————07CMDB文件模式测试采集硬件数据———————— # ————————06CMDB测试Linux系统采集硬件数据的命令————————
def linux(self):
response = BaseResponse() # 提交数据的类型(字典)
try:
import subprocess # 启动一个新的进程并且与之通信
shell_command = "cat /proc/cpuinfo" # 定义命令 lscpu
output = subprocess.getoutput(shell_command) # linux系统上执行的命令
response.data = self.linux_parse(output) # 解析shell命令返回结果
except Exception as e: # ————————08CMDB采集硬件数据日志记录————————
msg = "%s linux系统CPU插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录———————— response.status = False
return response @staticmethod # 返回函数的静态方法
def linux_parse(content): # 解析shell命令返回结果
response = {'cpu_count': 0, 'cpu_physical_count': 0, 'cpu_model': ''}
cpu_physical_set = set() # set()函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。
content = content.strip() # strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
for item in content.split('\n\n'): # split()通过指定分隔符对字符串进行切片
for row_line in item.split('\n'):
key, value = row_line.split(':')
key = key.strip()
if key == 'processor':
response['cpu_count'] += 1 # cpu核心个量
elif key == 'physical id':
cpu_physical_set.add(value) # CPU物理个量
elif key == 'model name':
if not response['cpu_model']:
response['cpu_model'] = value # cpu型号
response['cpu_physical_count'] = len(cpu_physical_set) # CPU物理个量
return response
# ————————06CMDB测试Linux系统采集硬件数据的命令————————

# cpu.py

 # disk.py
# ————————05CMDB采集硬件数据的插件————————
from .base import BasePlugin #采集资产的方式 和 系统平台
from lib.response import BaseResponse #提交数据的类型(字典)
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
# import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
# ————————06CMDB测试Linux系统采集硬件数据的命令———————— class DiskPlugin(BasePlugin):
def windows(self):
response = BaseResponse() #提交数据的类型(字典)
try:
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
output =wmi.WMI().Win32_DiskDrive() #获取磁盘相关信息
response.data = self.windows_parse(output) #解析相关信息 返回结果 #存到字典
except Exception as e: # ————————08CMDB采集硬件数据日志记录————————
msg = "%s windows系统硬盘插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录———————— response.status = False
return response @staticmethod#返回函数的静态方法
def windows_parse(content):
response = {}
for item in content:
item_dict = {}
item_dict['slot'] = item.Index #插槽位
item_dict['pd_type'] = item.InterfaceType #磁盘型号
item_dict['capacity'] = round(int(item.Size) / (1024**3)) # 磁盘容量
item_dict['model'] = item.Model #磁盘类型
response[item_dict['slot']] = item_dict #分割存每个 磁盘信息
return response #返回结果
# ————————05CMDB采集硬件数据的插件———————— # ————————07CMDB文件模式测试采集硬件数据————————
def test(self):
response = BaseResponse() #提交数据的类型(字典)
import os # 操作系统层面执行
from config.settings import BASEDIR # 获取路径
try:
output = open(os.path.join(BASEDIR, 'files/linux_out/disk.out'), 'r').read() #打开文件获取内容 linux_virtual_out linux_out
response.data = self.linux_parse(output)#解析shell命令返回结果
except Exception as e:#如果获取内容错误或者解析错误就换一个方式
try:
output = open(os.path.join(BASEDIR, 'files/linux_virtual_out/disk.out'),'r').read() # 打开文件获取内容 linux_virtual_out linux_out
response.data = self.linux_virtual_parse(output) # 解析shell命令返回结果
except Exception as e:#如果 出现未知错误 # ————————08CMDB采集硬件数据日志记录————————
msg = "%s 测试系统硬盘插件错误:%s" # 错误信息
import traceback # 捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False) # 写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) # 发送到远程日志
# ————————08CMDB采集硬件数据日志记录————————
response.status = False
return response # ————————07CMDB文件模式测试采集硬件数据———————— # ————————06CMDB测试Linux系统采集硬件数据的命令————————
def linux(self):
response = BaseResponse() #提交数据的类型(字典)
try:
import subprocess # 启动一个新的进程并且与之通信
shell_command = "sudo MegaCli -PDList -aALL" #定义命令#需要安装 MegaCli 模块
output = subprocess.getoutput(shell_command) #linux系统上执行的命令
if 'MegaCli'in output:
shell_command = "lsblk" # 虚拟机 #lsblk
output = subprocess.getoutput(shell_command) # linux系统上执行的命令
response.data = self.linux_virtual_parse(output) # 解析shell命令返回结果
else:
response.data = self.linux_parse(output)#解析shell命令返回结果
except Exception as e: # 如果 出现未知错误 # ————————08CMDB采集硬件数据日志记录————————
msg = "%s linux系统硬盘插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录———————— response.status = False
return response def linux_virtual_parse(self, content): # 解析shell命令返回结果
content = [i for i in content.split('\n') if i != ''] # split()通过指定分隔符对字符串进行切片
key_list = [i for i in content[0].split(' ') if i != ''] # split()通过指定分隔符对字符串进行切片
key_list[0] = 'slot' # 替换key的名字
key_list[3] = 'capacity'
key_list[5] = 'pd_type'
ram_dict = {}
for i in content[1:]: # 从列表下标1开始循环
segment = {}
value = [x for x in i.split(' ') if x != ''] # 如果不是空值就循环 # split()通过指定分隔符对字符串进行切片
filter = str(value) # 列表转成字符串进行判断
if '攢' not in filter: # '─' '攢' #二级逻辑硬盘
if '─' not in filter: # '─' '攢' #二级逻辑硬盘
list = zip(key_list, value) # zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
for k, v in list:
if k == 'capacity': # 处理单位问题
if 'G' in v:
l = v.split('G') # split()通过指定分隔符对字符串进行切片
v = l[0]
if 'M' in v: # 处理单位问题
l = v.split('M') # split()通过指定分隔符对字符串进行切片
s = l[0]
m = int(s)
v = m / 1024
segment[k] = v
ram_dict[value[0]] = segment
return ram_dict def linux_parse(self, content): # 解析shell命令返回结果
import re # 正则表达式
response = {}
result = []
for row_line in content.split("\n\n\n\n"): # split()通过指定分隔符对字符串进行切片
result.append(row_line) # 添加到列表
for item in result: # 循环列表
temp_dict = {}
for row in item.split('\n'): # split()通过指定分隔符对字符串进行切片
if not row.strip(): # strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
continue
if len(row.split(':')) != 2: # 测试长度
continue
key, value = row.split(':') # split()通过指定分隔符对字符串进行切片
name = self.mega_patter_match(key)
if name:
if key == 'Raw Size': # 磁盘容量
raw_size = re.search('(\d+\.\d+)',
value.strip()) # Raw Size: 279.396 GB [0x22ecb25c Sectors]
if raw_size:
temp_dict[name] = raw_size.group()
else:
raw_size = ''
else:
temp_dict[name] = value.strip() # 磁盘型号 #磁盘类型
if temp_dict:
response[temp_dict['slot']] = temp_dict # 插槽位 #分割存每个 磁盘信息
return response @staticmethod # 返回函数的静态方法
def mega_patter_match(needle):
grep_pattern = {'Slot': 'slot', 'Raw Size': 'capacity', 'Inquiry': 'model', 'PD Type': 'pd_type'}
for key, value in grep_pattern.items():
if needle.startswith(key): # 确定此字符串实例的开头是否与指定的字符串匹配
return value
return False
# ————————06CMDB测试Linux系统采集硬件数据的命令————————

# disk.py

 # main_board.py
# ————————05CMDB采集硬件数据的插件————————
from .base import BasePlugin #采集资产的方式 和 系统平台
from lib.response import BaseResponse #提交数据的类型(字典)
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
# import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
# ————————06CMDB测试Linux系统采集硬件数据的命令———————— class MainBoardPlugin(BasePlugin):
def windows(self):
response = BaseResponse() #提交数据的类型(字典)
try:
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
output =wmi.WMI().Win32_BaseBoard() #获取主板相关信息
response.data = self.windows_parse(output) #解析相关信息 返回结果 #存到字典
except Exception as e: # ————————08CMDB采集硬件数据日志记录————————
msg = "%s windows系统主板插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录———————— response.status = False
return response @staticmethod#返回函数的静态方法
def windows_parse(content):
response = {}
for item in content:
response['Manufacturer'] = item.Manufacturer #主板制造商
response['model'] = item.Name #主板型号
response['sn'] = item.SerialNumber #主板SN号
return response #返回结果
# ————————05CMDB采集硬件数据的插件———————— # ————————07CMDB文件模式测试采集硬件数据————————
def test(self):
response = BaseResponse() #提交数据的类型(字典)
import os # 操作系统层面执行
from config.settings import BASEDIR # 获取路径
try:
output = open(os.path.join(BASEDIR, 'files/linux_out/board.out'), 'r').read() #打开文件获取内容
response.data = self.linux_parse(output)#解析shell命令返回结果
except Exception as e:
# ————————08CMDB采集硬件数据日志记录————————
msg = "%s 测试系统主板插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录————————
response.status = False
return response
# ————————07CMDB文件模式测试采集硬件数据———————— # ————————06CMDB测试Linux系统采集硬件数据的命令————————
def linux(self):
response = BaseResponse() #提交数据的类型(字典)
try:
import subprocess # 启动一个新的进程并且与之通信
shell_command = "sudo dmidecode -t1" #定义命令
output =subprocess.getoutput(shell_command) #linux系统上执行的命令
response.data = self.linux_parse(output) #解析shell命令返回结果
except Exception as e:
# ————————08CMDB采集硬件数据日志记录————————
msg = "%s linux系统主板插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录————————
response.status = False
return response def linux_parse(self, content):#解析shell命令返回结果
result = {}
key_map = {'Manufacturer': 'manufacturer', 'Product Name': 'model','Serial Number': 'sn',}
for item in content.split('\n'): #split()通过指定分隔符对字符串进行切片
row_data = item.strip().split(':') #strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
if len(row_data) == 2:
if row_data[0] in key_map:#如果在需要的字典里
result[key_map[row_data[0]]] = row_data[1].strip() if row_data[1] else row_data[1]
return result
# ————————06CMDB测试Linux系统采集硬件数据的命令————————

# main_board.py

 # memory.py
# ————————05CMDB采集硬件数据的插件————————
from .base import BasePlugin #采集资产的方式 和 系统平台
from lib.response import BaseResponse #提交数据的类型(字典)
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
# import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
# ————————06CMDB测试Linux系统采集硬件数据的命令———————— class MemoryPlugin(BasePlugin):
def windows(self):
response = BaseResponse() #提交数据的类型(字典)
try:
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
output =wmi.WMI().Win32_PhysicalMemory() #获取内存相关信息
response.data = self.windows_parse(output)
except Exception as e: # ————————08CMDB采集硬件数据日志记录————————
msg = "%s windows系统内存插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录———————— response.status = False
return response @staticmethod#返回函数的静态方法
def windows_parse(content):
response={}
for item in content:
item_dict = {}
item_dict['slot'] = item.DeviceLocator #插槽位
item_dict['manufacturer'] = item.Manufacturer # 内存制造商
item_dict['model'] =item.FormFactor # 内存型号
item_dict['Capacity'] = round(int(item.Capacity) / (1024**3)) # 内存容量
item_dict['sn'] = item.SerialNumber #内存SN号
item_dict['speed'] = item.Speed #内存速度
response[item_dict['slot']] = item_dict #分割存每条 内存信息
return response # ————————05CMDB采集硬件数据的插件————————
# ————————07CMDB文件模式测试采集硬件数据————————
def test(self):
response = BaseResponse() #提交数据的类型(字典)
import os # 操作系统层面执行
from config.settings import BASEDIR # 获取路径
try:
output = open(os.path.join(BASEDIR, 'files/linux_out/memory.out'), 'r').read() #打开文件获取内容 linux_virtual_out linux_out
response.data = self.linux_parse(output) # 解析shell命令返回结果
except Exception as e:#如果获取内容错误或者解析错误就换一个方式
try:
output = open(os.path.join(BASEDIR, 'files/linux_virtual_out/memory.out'),'r').read() # 打开文件获取内容 linux_virtual_out linux_out
response.data = self.linux_virtual_parse(output) # 解析shell命令返回结果
except Exception as e:
# ————————08CMDB采集硬件数据日志记录————————
msg = "%s 测试系统内存插件错误:%s" # 错误信息
import traceback # 捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False) # 写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) # 发送到远程日志
# ————————08CMDB采集硬件数据日志记录————————
response.status = False
return response
# ————————07CMDB文件模式测试采集硬件数据———————— # ————————06CMDB测试Linux系统采集硬件数据的命令————————
def linux(self):
response = BaseResponse() #提交数据的类型(字典)
try:
import subprocess # 启动一个新的进程并且与之通信
shell_command = "sudo dmidecode -q -t 17 2>/dev/null" #定义命令 cat /proc/swaps #swapon
output = subprocess.getoutput(shell_command) #linux系统上执行的命令
if not output:
shell_command = "swapon" # 定义命令 cat /proc/swaps #swapon
output = subprocess.getoutput(shell_command) # linux系统上执行的命令
response.data = self.linux_virtual_parse(output) # 解析shell命令返回结果
else:
response.data = self.linux_parse(output) # 解析shell命令返回结果
except Exception as e: # 如果 出现未知错误
# ————————08CMDB采集硬件数据日志记录————————
msg = "%s linux系统内存插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录————————
response.status = False
return response def convert_mb_to_gb(self,value, default=0):#转换单位
try:
value = value.strip('MB') #strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
result = int(value)
except Exception as e:
result = default
return result def linux_virtual_parse(self, content): # 解析shell命令返回结果
content = [i for i in content.split('\n') if i != ''] # split()通过指定分隔符对字符串进行切片
key_list = [i for i in content[0].split(' ') if i != ''] # split()通过指定分隔符对字符串进行切片
key_list[0] = 'slot' #替换key的名字
key_list[1] = 'model'
key_list[2] = 'capacity'
ram_dict = {}
for i in content[1:]: # 从列表下标1开始循环
segment = {}
value = [x for x in i.split(' ') if x != '']#如果不是空值就循环 # split()通过指定分隔符对字符串进行切片
list = zip(key_list, value) # zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
for k, v in list:
if k=='capacity': #处理单位问题
if 'M' in v:
l = v.split('M') # split()通过指定分隔符对字符串进行切片
v = l[0]
if 'G' in v: # 处理单位问题
l = v.split('G') # split()通过指定分隔符对字符串进行切片
s = l[0]
m = int(s)
v = m * 1024
segment[k] = v
ram_dict[value[0]] = segment
return ram_dict def linux_parse(self, content): # 解析shell命令返回结果
ram_dict = {}
key_map = {'Size': 'capacity','Locator': 'slot','Type': 'model','Speed': 'speed',
'Manufacturer': 'manufacturer','Serial Number': 'sn',}
devices = content.split('Memory Device') #split()通过指定分隔符对字符串进行切片
for item in devices:
item = item.strip() #strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
if not item:
continue
if item.startswith('#'): #startswith()方法用于检查字符串是否是以指定子字符串开头
continue
segment = {}
lines = item.split('\n\t') #split()通过指定分隔符对字符串进行切片
for line in lines:
if len(line.split(':')) > 1: #split()通过指定分隔符对字符串进行切片
key, value = line.split(':') #split()通过指定分隔符对字符串进行切片
else:
key = line.split(':')[0] #split()通过指定分隔符对字符串进行切片
value = ""
if key in key_map:
if key == 'Size': # 内存容量
segment[key_map['Size']] = self.convert_mb_to_gb(value, 0) #转换单位
else:
segment[key_map[key.strip()]] = value.strip() #strip()方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列
ram_dict[segment['slot']] = segment #插槽位 #分割存每条 内存信息
return ram_dict
# ————————06CMDB测试Linux系统采集硬件数据的命令————————

# memory.py

 # nic.py
# ————————05CMDB采集硬件数据的插件————————
from .base import BasePlugin #采集资产的方式 和 系统平台
from lib.response import BaseResponse #提交数据的类型(字典)
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
# import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
# ————————06CMDB测试Linux系统采集硬件数据的命令———————— class NicPlugin(BasePlugin):
def windows(self):
response = BaseResponse() #提交数据的类型(字典)
try:
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
import wmi#Windows操作系统上管理数据和操作的基础设施 #linux写无法导入这个模块
# ————————06CMDB测试Linux系统采集硬件数据的命令————————
output =wmi.WMI().Win32_NetworkAdapterConfiguration() #获取网卡相关信息
response.data = self.windows_parse(output) #解析相关信息 返回结果 #存到字典
except Exception as e: # ————————08CMDB采集硬件数据日志记录————————
msg = "%s windows系统网卡插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录———————— response.status = False
return response @staticmethod#返回函数的静态方法
def windows_parse(content):
response={}
IPCM = 0 # 权重
for item in content:
if item.IPConnectionMetric: # 权重
if item.IPConnectionMetric > IPCM: # 权重 #防止虚拟网卡
item_dict = {}
name=item.ServiceName # 网卡名称
item_dict['hwaddr'] = item.MACAddress # 网卡MAC地址
item_dict['ipaddrs'] = item.IPAddress[0] # IP地址
item_dict['netmask'] = item.IPSubnet[0] # IP子网掩码
item_dict['up'] = item.IPEnabled #是否有启用
response[name] = item_dict
IPCM = item.IPConnectionMetric # 权重
return response
# ————————05CMDB采集硬件数据的插件———————— # ————————07CMDB文件模式测试采集硬件数据————————
def test(self):
response = BaseResponse() #提交数据的类型(字典)
import os # 操作系统层面执行
from config.settings import BASEDIR # 获取路径
try:
output = open(os.path.join(BASEDIR, 'files/linux_out/nic.out'), 'r').read() #打开文件获取内容
interfaces_info = self._interfaces_ip(output) #接口 # 解析shell命令返回结果
self.standard(interfaces_info) # 内容进行 标准化
response.data = interfaces_info # 解析shell命令返回结果
except Exception as e:
# ————————08CMDB采集硬件数据日志记录————————
msg = "%s 测试系统网卡插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录————————
response.status = False
return response
# ————————07CMDB文件模式测试采集硬件数据———————— # ————————06CMDB测试Linux系统采集硬件数据的命令————————
def linux(self):
response = BaseResponse() #提交数据的类型(字典)
try:
interfaces_info = self.linux_interfaces() #linux系统上执行的命令
self.standard(interfaces_info) # 内容进行 标准化
response.data = interfaces_info # 解析shell命令返回结果
except Exception as e:
# ————————08CMDB采集硬件数据日志记录————————
msg = "%s linux系统网卡插件错误:%s" #错误信息
import traceback #捕获并打印异常
self.logger.log(msg % (self.hostname, traceback.format_exc()), False)#写入本地日志
response.error = msg % (self.hostname, traceback.format_exc()) #发送到远程日志
# ————————08CMDB采集硬件数据日志记录————————
response.status = False
return response def standard(self, interfaces_info):# 内容进行 标准化
for key, value in interfaces_info.items():
ipaddrs = set()#set()函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。
netmask = set()
if not 'inet' in value:
value['ipaddrs'] = '' # IP地址
value['netmask'] = '' # IP子网掩码
else:
for item in value['inet']:
ipaddrs.add(item['address']) # IP地址
netmask.add(item['netmask']) # IP子网掩码
value['ipaddrs'] = '/'.join(ipaddrs) # IP地址
value['netmask'] = '/'.join(netmask) # IP子网掩码
del value['inet'] def linux_interfaces(self):#获得* NIX / BSD变种接口信息
ifaces = dict() #dict() 函数用于创建一个字典。返回一个字典。
ip_path = 'ip'
if ip_path:
# ————————在使用#linux系统上执行的命令时开启————————
import subprocess # 启动一个新的进程并且与之通信
cmd1 = subprocess.getoutput('sudo {0} link show'.format(ip_path)) #定义命令ip link show
cmd2 = subprocess.getoutput('sudo {0} addr show'.format(ip_path)) #定义命令ip addr show
ifaces = self._interfaces_ip(cmd1 + '\n' + cmd2) #linux系统上执行的命令 #接口 # 解析shell命令返回结果
# ————————在使用#linux系统上执行的命令时开启————————
return ifaces def which(self, exe):
import os # 操作系统层面执行
def _is_executable_file_or_link(exe):
# 检查操作系统。X_OK不足够了,因为目录可能会执行
return (os.access(exe, os.X_OK) and
(os.path.isfile(exe) or os.path.islink(exe))) if exe:
if _is_executable_file_or_link(exe):
# executable in cwd or fullpath
return exe # 默认路径基于busybox的默认
default_path = '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin'
search_path = os.environ.get('PATH', default_path)
path_ext = os.environ.get('PATHEXT', '.EXE')
ext_list = path_ext.split(';') search_path = search_path.split(os.pathsep)
if True:
"""
   # 添加任何dirs default_path search_path不。如果
   # 没有PATH变量中发现操作系统。环境,那么这将是
   # 无为法。这将确保所有dirs default_path
   # 搜索,让salt.utils.which()调用时工作得很好
   # salt-call从cron(取决于平台
   # 有一个极其有限的路径)。
"""
search_path.extend(
[
x for x in default_path.split(os.pathsep)
if x not in search_path
]
)
for path in search_path:
full_path = os.path.join(path, exe)
if _is_executable_file_or_link(full_path):
return full_path
return None def _number_of_set_bits_to_ipv4_netmask(self, set_bits): # pylint: disable=C0103
'''
返回一个整数表示的IPv4网络掩码,面具。 Ex. 0xffffff00 -> '255.255.255.0'
'''
return self.cidr_to_ipv4_netmask(self._number_of_set_bits(set_bits))
def cidr_to_ipv4_netmask(self, cidr_bits):
'''
返回一个IPv4网络掩码
'''
try:
cidr_bits = int(cidr_bits)
if not 1 <= cidr_bits <= 32:
return ''
except ValueError:
return ''
netmask = ''
for idx in range(4):
if idx:
netmask += '.'
if cidr_bits >= 8:
netmask += ''
cidr_bits -= 8
else:
netmask += '{0:d}'.format(256 - (2 ** (8 - cidr_bits)))
cidr_bits = 0
return netmask
def _number_of_set_bits(self, x):
'''
返回的比特数,设置在一个32位整数
#来自http://stackoverflow.com/a/4912729
'''
x -= (x >> 1) & 0x55555555
x = ((x >> 2) & 0x33333333) + (x & 0x33333333)
x = ((x >> 4) + x) & 0x0f0f0f0f
x += x >> 8
x += x >> 16
return x & 0x0000003f def _interfaces_ip(self, out): #接口 # 解析shell命令返回结果
import re # 正则表达式
'''
  使用ip来返回一个字典的接口的各种信息
  每个(向上/向下状态、ip地址、子网掩码和hwaddr)
'''
ret = dict()
right_keys = ['name', 'hwaddr', 'up', 'netmask', 'ipaddrs'] def parse_network(value, cols):
'''
  子网掩码,返回一个元组的ip广播
  基于当前的关口
'''
brd = None
if '/' in value: # 我们有一个CIDR在这个地址
ip, cidr = value.split('/') # pylint:禁用= C0103
else:
ip = value # pylint:禁用= C0103
cidr = 32 if type_ == 'inet':
mask = self.cidr_to_ipv4_netmask(int(cidr))
if 'brd' in cols:
brd = cols[cols.index('brd') + 1]
return (ip, mask, brd) groups = re.compile('\r?\n\\d').split(out)
for group in groups:
iface = None
data = dict() for line in group.splitlines():
if ' ' not in line:
continue
match = re.match(r'^\d*:\s+([\w.\-]+)(?:@)?([\w.\-]+)?:\s+<(.+)>', line)
if match:
iface, parent, attrs = match.groups()
if 'UP' in attrs.split(','):
data['up'] = True
else:
data['up'] = False
if parent and parent in right_keys:
data[parent] = parent
continue cols = line.split()
if len(cols) >= 2:
type_, value = tuple(cols[0:2])
iflabel = cols[-1:][0]
if type_ in ('inet',):
if 'secondary' not in cols:
ipaddr, netmask, broadcast = parse_network(value, cols)
if type_ == 'inet':
if 'inet' not in data:
data['inet'] = list()
addr_obj = dict()
addr_obj['address'] = ipaddr
addr_obj['netmask'] = netmask
addr_obj['broadcast'] = broadcast
data['inet'].append(addr_obj) else:
if 'secondary' not in data:
data['secondary'] = list()
ip_, mask, brd = parse_network(value, cols)
data['secondary'].append({
'type': type_,
'address': ip_,
'netmask': mask,
'broadcast': brd,
})
del ip_, mask, brd
elif type_.startswith('link'):
data['hwaddr'] = value
if iface:
if iface.startswith('pan') or iface.startswith('lo') or iface.startswith('v'):
del iface, data
else:
ret[iface] = data
del iface, data
return ret
# ————————06CMDB测试Linux系统采集硬件数据的命令————————

# nic.py

Django项目:CMDB(服务器硬件资产自动采集系统)--12--08CMDB采集硬件数据日志记录的更多相关文章

  1. Django项目:CMDB(服务器硬件资产自动采集系统)--11--07CMDB文件模式测试采集硬件数据

    #settings.py # ————————01CMDB获取服务器基本信息———————— import os BASEDIR = os.path.dirname(os.path.dirname(o ...

  2. Django项目:CMDB(服务器硬件资产自动采集系统)--05--05CMDB采集硬件数据的插件

    #__init__.py # ————————05CMDB采集硬件数据的插件———————— from config import settings import importlib # —————— ...

  3. Django项目:CMDB(服务器硬件资产自动采集系统)--07--06CMDB测试Linux系统采集硬件数据的命令02

    #settings.py """ Django settings for AutoCmdb project. Generated by 'django-admin sta ...

  4. Django项目:CMDB(服务器硬件资产自动采集系统)--06--06CMDB测试Linux系统采集硬件数据的命令01

    #base.py # ————————01CMDB获取服务器基本信息———————— from config import settings #配置文件 class BasePlugin(object ...

  5. Django项目:CMDB(服务器硬件资产自动采集系统)--03--03CMDB信息安全API接口交互认证

    #settings.py """ Django settings for AutoCmdb project. Generated by 'django-admin sta ...

  6. Django项目:CMDB(服务器硬件资产自动采集系统)--02--02CMDB将服务器基本信息提交到API接口

    AutoCmdb # urls.py """AutoCmdb URL Configuration The `urlpatterns` list routes URLs t ...

  7. Django项目:CMDB(服务器硬件资产自动采集系统)--04--04CMDB本地(Agent)模式客户端唯一标识(ID)

    # client.py # ————————01CMDB获取服务器基本信息———————— from src import plugins #__init__.py from lib.serializ ...

  8. Django项目:CMDB(服务器硬件资产自动采集系统)--01--01CMDB获取服务器基本信息

    AutoClient #settings.py # ————————01CMDB获取服务器基本信息———————— import os BASEDIR = os.path.dirname(os.pat ...

  9. Django项目:CMDB(服务器硬件资产自动采集系统)--10--06CMDB测试Linux系统采集硬件数据的命令05

    cd /py/AutoClient/bin python3 auto-client.py /usr/local/python3/bin/pip install requests python3 aut ...

随机推荐

  1. (转)python基础之迭代器协议和生成器(一)

    一 递归和迭代 二 什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前 ...

  2. 推荐5本纯Java技术书,你看过几本?

    51小长假了,大家应该对它又爱又痛,爱的是终于可以到处浪了,痛的是没钱只能穷游,而且还到处都是人,结果变成了堵高速.去看人头.去蒸饺子,真是受罪啊.. 所以,对于小长假的痛,我相信还是有一部分人会选择 ...

  3. Android笔记之Fragment中创建ViewModel的正确方式

    之前一直都是这么写的 pageViewModel = ViewModelProviders.of(this).get(PageViewModel.class); //参数this是当前fragment ...

  4. vue+nginx配置二级域名

    [1]修改路由文件 [2]修改配置文件 [3]修改本机nginx配置文件 [4]修改服务器nginx配置文件 [5]重启nginx文件,用二级域名访问 http://192.168.199.xxx:7 ...

  5. cms系统视频分享

    cms_001-CMS系统功能需求简介-1.avicms_002-如何采用用例分析方法来理解需求-1.avicms_003-后台管理系统用例-1.avicms_004-实现验证码的初步思路-1.avi ...

  6. OC中Nil nil NULL 和 [NSNULL null]的区别

    关于这个问题看过两三次了,但是每次过两个月脑袋里又会不清晰,索性记录一下加深一下印象. 一.nil 当一个对象置为nil时,这个对象的内存地址就会被系统收回.置空之后是不能进行retain,copy等 ...

  7. mysql的几种启动方式

    mysql的四种启动方式: 1.mysqld 启动mysql服务器:./mysqld --defaults-file=/etc/my.cnf --user=root 客户端连接: mysql --de ...

  8. Spring知识点整理

    1.bean什么时候被实例化 第一:如果你使用BeanFactory作为Spring Bean的工厂类,则所有的bean都是在第一次使用该Bean的时候实例化第二:如果你使用ApplicationCo ...

  9. 软件设计师_C语言基础

    1.常量 表示八进制,不带前缀则默认表示十进制.整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long).后缀可以是大写,也可以是小写, ...

  10. SCRIPT7002: XMLHttpRequest: 网络错误 0x2ef3的解决方法

    最近在使用jquery easyui datagrid 对页面布局,发现有时在IE下会接收不到数据并报错: SCRIPT7002: XMLHttpRequest: 网络错误 0x2ef3, 由于出现错 ...