cmdb客户端采集数据的完善

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

custom_settings.py

import os

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

MODE = ‘agent‘

SSH_USERNAME = ‘root‘

SSH_PASSWORD = ‘123‘

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 = ‘0‘
                    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 += ‘255‘
                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)

原文地址:https://www.cnblogs.com/huangxuanya/p/11625791.html

时间: 2024-07-30 10:07:46

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

cmdb采集数据的版本

在局部配置文件中配置MODE=' agent',或者MODE=‘ssh’,或者MODE=‘’saltstack ',  实现只需要修改这个配置,就会使用对应的方案进行采集数据 第一种版本: 启动文件中直接判断 start.py from lib.config.config import settings import subprocess from src.plugins import board,disk,memory if __name__ == '__main__': mode = set

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

原文:使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置) 在上一篇中说到了Silverlight下的Socket通信,在最后的时候说到本篇将会结合地图.下面就来看看本文实现的功能: Silverlight 与服务器利用Socket通讯,实时从服务器获取数据(本文中的数据是地理坐标),由于没有GPS,所以本文在服务器写了一个构造新坐标的函数(本文是一个三角函数),然后利用Timer组件,实时调用,得到新的坐标,并将新的坐标发送给客户端,客户端接收到发

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

Flume简介与使用(二)——Thrift Source采集数据 继上一篇安装Flume后,本篇将介绍如何使用Thrift Source采集数据. Thrift是Google开发的用于跨语言RPC通信,它拥有功能强大的软件堆栈和代码生成引擎,允许定义一个简单的IDL文件来生成不同语言的代码,服务器端和客户端通过共享这个IDL文件来构建来完成通信. Flume的Thrift Source是其实现的众多Source中的一个,Flume已经实现了服务器端,因此我们可以用任意自己熟悉的语言编写自己的Th

CMDB资产采集的四种方式

资产采集的概念 资产采集的四种方式:Agent.SSH.saltstack.puppet 资产采集 Configuration Management Database 简称CMDB,CMDB存储与管理企业IT架构中设备的各种配置信息,它与所有服务支持和服务交付流程都紧密相联,支持这些流程的运转.发挥配置信息的价值,同时依赖于相关流程保证数据的准确性.CMDB可以实现高度的自动化,减少人为错误的发生.降低人员成本,CMDB是实现运维自动化的基础. Agent方式 程序:放置在每台服务器 应用场景:

《ServerSuperIO Designer IDE使用教程》- 7.增加机器学习算法,通讯采集数据与算法相结合。发布:4.2.5 版本

v4.2.5更新内容:1.修复服务实例设置ClearSocketSession参数时,可能出现资源无法释放而造成异常的情况.2.修复关闭宿主程序后进程仍然无法退出的问题.2.增加机器学习框架.3.优化核心代码.下载地址:官方下载 7.增加机器学习算法,通讯采集数据与算法相结合 7.1概述 ServerSuperIO发展到现在,缺少两部分内容:图形组态和算法分析.图形组态部分很快就要做出来了,不管从形式上还是内容上,比市场上同类产品要好很多:算法分析部分现在已经开发出来了,现在支持决策树和KMea

CMDB客户端实现

目录结构 采集资产信息(硬盘, 主板, 网卡) 唯一标识 sn号 只能采集物理机+接口 主机名 需要用规则和流程去规范化, 在服务器装机时候主机名就定义了 流程: 每台主机上需要有一个文件去保存主机名, 所以分2种情况 没有文件 ------->>> 新增的机器 汇报到api 新增到数据库 api 的响应消息中有主机名 客户端 新建文件 把主机名保存到文件中 有文件(修改) 汇报之前, 先读取文件, 拿到机器中存的主机名 判断文件中的主机名和资产采集到的主机名(通过执行命令实时获得)做对

CMDB资产采集方式

一:Agent方式 原理:在每台服务器装上agent客户端程序,定时向数据库发送指定的资产信息. 优点:速度快. 缺点:服务器上需要多装一个软件 1 import subprocess 2 import requests 3 # pip3 install requests 4 5 # ################## 采集数据 ################## 6 # result = subprocess.getoutput('ipconfig') 7 # result正则处理获取想要

C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子)

转自原文C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子) 阅读目录 1.HtmlAgilityPack简介 2.XPath技术介绍与使用 3.采集天气网站案例 4.资源 第一次接触HtmlAgilityPack是在5年前,一些意外,让我从技术部门临时调到销售部门,负责建立一些流程和寻找潜在客户,最后在阿里巴巴找到了很多客户信息,非常全面,刚开始是手动复制到Excel,是真尼玛的累,虽然那个时候C#还很菜,也想能不能通过程序来批量获取(所以平时想法要多才好).几

基于PHP采集数据入库程序(二)

在上篇基于PHP采集数据入库程序(二) 中提到采集新闻信息页的列表数据,接下来讲讲关于采集新闻具体内容 这是上篇博客的最终数据表截图: 接下来要做的操作就是从数据库中读取所需要采集的URL,进行页面抓取就行 新建一个content表 不过需要注意的一点是,不能再采用采集URL这种id递增的方法去采集,因为数据表中可能出现id断续,比如id=9,id=11,当采集到id=10的时候,URL是空白的,这样可能会导致采集到了空字段. 这里用到的一个技巧是数据库的查询语句,在我们采集完第一条数据的时候,