file文件自己去拷贝(这里不提供)

custom_settings.py

import os

BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))   获取到根路径

MODE = 'agent'

SSH_USERNAME = 'root'

SSH_PASSWORD = ''

SHH_PORT = 22

DEBUG = True     #代码调试,如果为True就会读取file中文件的内容,如果不是会执行linux命令

PLUGINS_DICT = {   ##新增的basic,nic要在这里添加才可以采集到数据
'basic':'src.plugins.basic.Basic',
'board': 'src.plugins.board.Board',
'disk': 'src.plugins.disk.Disk',
'memory': 'src.plugins.memory.Memory',
'cpu':'src.plugins.cpu.Cpu',
'nic':'src.plugins.nic.Nic'
}

convert.py

convert.py

#!/usr/bin/env python
# -*- coding:utf-8 -*- def convert_to_int(value,default=0): try:
result = int(value)
except Exception as e:
result = default return result def convert_mb_to_gb(value,default=0): try:
value = value.strip('MB')
result = int(value)
except Exception as e:
result = default return result

读取file文件中board.out的代码测试

s3.py

res  = '''
SMBIOS 2.7 present. Handle 0x0001, DMI type 1, 27 bytes
System Information
Manufacturer: Parallels Software International Inc.
Product Name: Parallels Virtual Platform
Version: None
Serial Number: Parallels-1A 1B CB 3B 64 66 4B 13 86 B0 86 FF 7E 2B 20 30
UUID: 3BCB1B1A-6664-134B-86B0-86FF7E2B2030
Wake-up Type: Power Switch
SKU Number: Undefined
Family: Parallels VM
''' '''
result = {
'manufacturer' : 'Parallels Software International Inc.' ,
'product_name' : 'Parallels Virtual Platform',
'sn' : 'Parallels-1A 1B CB 3B 64 66 4B 13 86 B0 86 FF 7E 2B 20 30'
}
''' key_map = {
"Manufacturer" : 'manufacturer',
"Product Name" : 'product_name',
"Serial Number": 'sn'
} result = {}
data = res.strip().split('\n')
# print(data)
for k in data:
v = (k.strip().split(':'))
if len(v) == 2:
if v[0] in key_map:
result[key_map[v[0]]] = v[1].strip() print(result)

修改了一些代码

from lib.config.config import settings
import traceback
import importlib
import subprocess #管理插件信息的类
class PluginsManger(object): def __init__(self, hostname=None):
self.plugins_dict = settings.PLUGINS_DICT
self.hostname = hostname
self.debug = settings.DEBUG if settings.MODE == 'ssh':
self.port = settings.SSH_PORT
self.username = settings.SSH_USERNAME
self.pwd = settings.SSH_PASSWORD #读取配置文件中的pluginsdict, 并执行对应模块中的process方法
def execute(self):
response = {}
for k,v in self.plugins_dict.items():
ret = {'status':None, 'data':None}
'''
k: board,...
v: src.plugins.board.Board 字符串
'''
#修改
try:
#1.导入模块路径
moudle_path,class_name = v.rsplit('.', 1)
#2.导入这个路径 moudle_name = importlib.import_module(moudle_path) #3.导入对应的类
classobj = getattr(moudle_name, class_name) #4.执行类下面对应的process方法 res = classobj().process(self.__cmd_run, self.debug)
ret['status'] = 10000
ret['data'] = res
except Exception as e:
ret['status'] = 10001
ret['data'] = "[%s] 采集 [%s] 出错了, 错误信息是:%s" % (
self.hostname if self.hostname else "Agent", k, str(traceback.format_exc()))
response[k] = ret
return response def __cmd_run(self,cmd):
if settings.MODE == 'agent':
return self.__cmd_agent(cmd)
elif settings.MODE == 'ssh':
return self.__cmd_ssh(cmd)
elif settings.MODE == 'salt':
return self.__cmd_salt(cmd)
else:
print('只支持的模式,agent/ssh/salt') def __cmd_agent(self,cmd):
res = subprocess.getoutput(cmd)
return res def __cmd_ssh(self, cmd):
import paramiko # 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname=self.hostname, port= self.port, username=self.username, password=self.pwd)
# 执行命令
stdin, stdout, stderr = ssh.exec_command(cmd)
# 获取命令结果
result = stdout.read() # 关闭连接
ssh.close()
return result def __cmd_salt(self,cmd):
command = "salt %s cmd.run %s" %(self.hostname,cmd)
res = subprocess.getoutput(command)
return res

__init__.py

增加了basic采集数据

#修改一

class Basic(object):
def __init__(self):
pass @classmethod
def initial(cls):
return cls() def process(self, command_func, debug):
if debug:
output = {
'os_platform': "linux",
'os_version': "CentOS release 6.6 (Final)\nKernel \r on an \m",
'hostname': 'c2.com'
}
else:
output = {
'os_platform': command_func("uname").strip(),
'os_version': command_func("cat /etc/issue").strip().split('\n')[0],
'hostname': command_func("hostname").strip(), } return output

basic.py

修改了board,cpu,disk,memory代码

from lib.config.config import settings
import subprocess
import os class Board(object):
# 修改二(1)
def __init__(self):
pass
#修改二(2)
@classmethod
def initial(cls):
return cls() def process(self, command_func, debug):
if debug:
output = open(os.path.join(settings.BASEDIR, 'files/board.out'), 'r', encoding='utf8').read()
else:
#修改三命令
output = command_func('sudo dmidecode -t1') #修改四
# data = self.parse_output(output)
# return data
return self.parse(output) def parse(self, content):
key_map = {
"Manufacturer": 'manufacturer',
"Product Name": 'product_name',
"Serial Number": 'sn'
} result = {} #修改五
# data = res.strip().split('\n')
# for k in data:
# v = (k.strip().split(':'))
# if len(v) == 2:
# if v[0] in key_map:
# result[key_map[v[0]]] = v[1].strip()
# return result
for item in content.split('\n'):
row_data = item.strip().split(':')
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

board.py

import os

from lib.config.config import settings

class Cpu(object):
def __init__(self):
pass @classmethod
def initial(cls):
return cls() def process(self,command_func, debug):
if debug:
output = open(os.path.join(settings.BASEDIR, 'files/cpuinfo.out'), 'r',encoding='utf-8').read()
else:
output = command_func("cat /proc/cpuinfo")
return self.parse(output) def parse(self, content):
"""
解析shell命令返回结果
:param content: shell 命令结果
:return:解析后的结果
"""
response = {'cpu_count': 0, 'cpu_physical_count': 0, 'cpu_model': ''}
cpu_physical_set = set() content = content.strip()
for item in content.split('\n\n'):
for row_line in item.split('\n'):
key, value = row_line.split(':')
key = key.strip()
if key == 'processor':
response['cpu_count'] += 1
elif key == 'physical id':
cpu_physical_set.add(value)
elif key == 'model name':
if not response['cpu_model']:
response['cpu_model'] = value
response['cpu_physical_count'] = len(cpu_physical_set) return response

cpu.py

from lib.config.config import settings
import subprocess import os import re class Disk(object): #修改一 def __init__(self):
pass @classmethod
def initial(cls):
return cls() #修改二
def process(self, command_func,debug):
if debug:
output = open(os.path.join(settings.BASEDIR, 'files/disk.out'), 'r', encoding='utf-8').read()
else:
output = command_func('sudo MegaCli -PDList -aALL')
return self.parse(output) def parse(self, content):
"""
解析shell命令返回结果
:param content: shell 命令结果
:return:解析后的结果
"""
response = {}
result = []
for row_line in content.split('\n\n\n\n'):
result.append(row_line)
for item in result:
temp_dict = {}
for row in item.split('\n'):
if not row.strip():
continue
if len(row.split(':')) !=2:
continue
key,value = row.split(':')
name = self.mega_patter_match(key)
if name:
if key == 'Raw Size':
raw_size = re.search('(\d+\.\d+)', value.strip())
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

disk.py

import os

from lib import convert

from lib.config.config import settings

class Memory(object):
def __init__(self):
pass @classmethod
def initial(cls):
return cls() def process(self,command_func, debug):
if debug:
output = open(os.path.join(settings.BASEDIR, 'files/memory.out'), 'r', encoding='utf-8').read()
else:
output = command_func("sudo dmidecode -q -t 17 2>/dev/null")
return self.parse(output) def parse(self, content):
"""
解析shell命令返回结果
:param content: shell 命令结果
:return:解析后的结果
"""
ram_dict = {}
key_map = {
'Size': 'capacity',
'Locator': 'slot',
'Type': 'model',
'Speed': 'speed',
'Manufacturer': 'manufacturer',
'Serial Number': 'sn', }
devices = content.split('Memory Device')
for item in devices:
item = item.strip()
if not item:
continue
if item.startswith('#'):
continue
segment = {}
lines = item.split('\n\t')
for line in lines:
if not line.strip():
continue
if len(line.split(':')):
key, value = line.split(':')
else:
key = line.split(':')[0]
value = ""
if key in key_map:
if key == 'Size':
segment[key_map['Size']] = convert.convert_mb_to_gb(value, 0)
else:
segment[key_map[key.strip()]] = value.strip() ram_dict[segment['slot']] = segment return ram_dict

memory.py

增加了nic.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import os
import re
from lib.config.config import settings class Nic(object):
def __init__(self):
pass @classmethod
def initial(cls):
return cls() def process(self, command_func, debug):
if debug:
output = open(os.path.join(settings.BASEDIR, 'files/nic.out'), 'r', encoding='utf-8').read()
interfaces_info = self._interfaces_ip(output)
else:
interfaces_info = self.linux_interfaces(command_func) self.standard(interfaces_info) return interfaces_info def linux_interfaces(self, command_func):
'''
Obtain interface information for *NIX/BSD variants
'''
ifaces = dict()
ip_path = 'ip'
if ip_path:
cmd1 = command_func('sudo {0} link show'.format(ip_path))
cmd2 = command_func('sudo {0} addr show'.format(ip_path))
ifaces = self._interfaces_ip(cmd1 + '\n' + cmd2)
return ifaces def which(self, exe):
def _is_executable_file_or_link(exe):
# check for os.X_OK doesn't suffice because directory may executable
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 # default path based on busybox's default
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:
# Add any dirs in the default_path which are not in search_path. If
# there was no PATH variable found in os.environ, then this will be
# a no-op. This ensures that all dirs in the default_path are
# searched, which lets salt.utils.which() work well when invoked by
# salt-call running from cron (which, depending on platform, may
# have a severely limited PATH).
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
'''
Returns an IPv4 netmask from the integer representation of that mask. 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):
'''
Returns an IPv4 netmask
'''
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):
'''
Returns the number of bits that are set in a 32bit int
'''
# Taken from http://stackoverflow.com/a/4912729. Many thanks!
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):
'''
Uses ip to return a dictionary of interfaces with various information about
each (up/down state, ip address, netmask, and hwaddr)
'''
ret = dict()
right_keys = ['name', 'hwaddr', 'up', 'netmask', 'ipaddrs'] def parse_network(value, cols):
'''
Return a tuple of ip, netmask, broadcast
based on the current set of cols
'''
brd = None
if '/' in value: # we have a CIDR in this address
ip, cidr = value.split('/') # pylint: disable=C0103
else:
ip = value # pylint: disable=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 def standard(self, interfaces_info): for key, value in interfaces_info.items():
ipaddrs = set()
netmask = set()
if not 'inet' in value:
value['ipaddrs'] = ''
value['netmask'] = ''
else:
for item in value['inet']:
ipaddrs.add(item['address'])
netmask.add(item['netmask'])
value['ipaddrs'] = '/'.join(ipaddrs)
value['netmask'] = '/'.join(netmask)
del value['inet']

nic.py

启动文件进行测试

from src.plugins import PluginsManger

if __name__ == '__main__':

    res = PluginsManger().execute()
for k,v in res.items():
print(k,v)

cmdb客户端采集数据的完善的更多相关文章

  1. cmdb客户端代码完善2

    目录: 1.面试提问 2.完善采集端代码 3.唯一标识的问题 4.API的验证 1.面试会问到的问题: # 1. 为啥要做CMDB?# - 实现运维自动化, 而CMDB是实现运维自动化的基石# - 之 ...

  2. cmdb采集数据的版本

    在局部配置文件中配置MODE=' agent',或者MODE=‘ssh’,或者MODE=‘’saltstack ',  实现只需要修改这个配置,就会使用对应的方案进行采集数据 第一种版本: 启动文件中 ...

  3. CMDB资产采集方案

    CMDB资产采集方案 CMDB 资产采集的方案总共有四种 Agent SSH类 Saltstack Puttet 方案设计,从性能上考虑 下面前三种是用Python开发的,目标是兼容三种采集方式的软件 ...

  4. CMDB资产采集笔记

    一.资产采集四种方式 1. Agent方式 API:Django接收数据并入库 程序:放置在每台服务器 应用场景:针对服务器较多的公司 步骤一: #执行本地命令的库 import subprocess ...

  5. CMDB资产采集的四种方式

    转 https://www.cnblogs.com/guotianbao/p/7703921.html 资产采集的概念 资产采集的四种方式:Agent.SSH.saltstack.puppet 资产采 ...

  6. Flume简介与使用(二)——Thrift Source采集数据

    Flume简介与使用(二)——Thrift Source采集数据 继上一篇安装Flume后,本篇将介绍如何使用Thrift Source采集数据. Thrift是Google开发的用于跨语言RPC通信 ...

  7. 使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置)

    原文:使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置) 在上一篇中说到了Silverlight下的Socket通信,在最后的时候说到本篇将会结合地图. ...

  8. 01 Zabbix采集数据方式

    Zabbix采集数据方式 1. zabbix采集数据方式: 基于专用agent   被监控的设备上面安装agent软件,这个agent必须在设备上面有采集数据的权限 基于SNMP,  net-snmp ...

  9. tsar采集数据原理

    系统模块 cpu 字段含义 user: 表示CPU执行用户进程的时间,通常期望用户空间CPU越高越好. sys: 表示CPU在内核运行时间,系统CPU占用率高,表明系统某部分存在瓶颈.通常值越低越好. ...

随机推荐

  1. 自研测试框架ktest介绍(适用于UI和API)

    iTesting,爱测试,爱分享 在自动化测试的过程中,测试框架是我们绕不过去的一个工具,无论你是不需要写代码直接改动数据生成脚本,还是你需要检查测试结果甚至持续集成,测试框架都在发挥它的作用. 不同 ...

  2. 彪悍的Surface Book2发布:能重拾笔记本行业的信心吗?

    ​ Book2发布:能重拾笔记本行业的信心吗?" title="彪悍的Surface Book2发布:能重拾笔记本行业的信心吗?"> ​  在智能手机全面普及之后, ...

  3. Mysql或者SQL Server数据库的运行机制和体系架构

    一.MySQL主要分为以下几个组件: 连接池组件 管理服务和工具组件 SQL接口组件 分析器组件 优化器组件 缓冲组件 插件式存储引擎 物理文件 二.MySql的组成:Mysql是由SQL接口,解析器 ...

  4. 前端每日实战:125# 视频演示如何用纯 CSS 创作一个失落的人独自行走的动画

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/MqpOdR/ 可交互视频 此视频是 ...

  5. Vue 项目分环境打包

       我们开发项目的时候,用vue-cli 2.x版本新建的项目,只有dev, pro两种开发环境, 有时需要个test环境来给测试使用,所以找了很多方法,总结了个最简单的方法来给大家使用 packa ...

  6. 用CSS3实现钟表效果

    背景:最近在学习CSS3,看到了一个小案例,通过自己的学习,动手实现了它,现在把它分享出来. 效果图 实现过程 1.首先我们需要在页面中写出一个静态的钟表效果.首先我们需要一个表盘div wrap 对 ...

  7. Codeforces Round #626 (Div. 2, based on Moscow Open Olympiad in Informatics)

    A. Even Subset Sum Problem 题意 给出一串数,找到其中的一些数使得他们的和为偶数 题解 水题,找到一个偶数或者两个奇数就好了 代码 #include<iostream& ...

  8. Codeforces Round #292 (Div. 2) C. Drazil and Factorial 515C

    C. Drazil and Factorial time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  9. 【译文连载】 理解Istio服务网格(第七章 安全)

    全书目录 第一章 概述 第二章 安装 第三章 流控 第四章 服务弹性 第五章 混沌测试 第六章 可观测性 本文目录 第7章 安全 7.1 身份认证 7.1.1 Kubernetes上的Istio的身份 ...

  10. ysoserial源码结构分析

    1.前言 之前也花了几天晚上熟悉了一下commonscollections系列的构造,那么学习一下这个项目是如何设计的也挺重要,多学习大佬如何写代码应该也能对自己的代码能力有提升吧~2333 2.项目 ...