zoukankan      html  css  js  c++  java
  • 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('
    ')
    # 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)
    Kernel 
     on an m",
                    'hostname': 'c2.com'
                }
            else:
                output = {
                    'os_platform': command_func("uname").strip(),
                    'os_version': command_func("cat /etc/issue").strip().split('
    ')[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('
    ')
            # 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('
    '):
                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('
    
    '):
                for row_line in item.split('
    '):
                    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('
    
    
    
    '):
                result.append(row_line)
            for item in result:
                temp_dict = {}
                for row in item.split('
    '):
                    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('
    	')
                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 + '
    ' + 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('
    ?
    \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)
  • 相关阅读:
    Vue --》this.$set()的神奇用法
    vue --》路由query 编程式导航传值与监听
    elementUI -->实现简单的购物车
    vue--》如何使用wacth监听对象的属性变化?
    laravel redis 删除指定前缀的 key
    php in_array 的一个坑
    laravel/lumen Command 的构造函数需要注意的地方
    git 合并连续的几个 commits
    盘点 php 里面那些冷门又实用的小技巧
    mockery expectation 覆盖
  • 原文地址:https://www.cnblogs.com/huangxuanya/p/11625791.html
Copyright © 2011-2022 走看看