• CMDB 项目涉及知识点总结


    AGENT 模式唯一标识主机名

    客户端以自身主机名为唯一标识将数据上报到API,每个客户端数据根据主机名去存储,若主机名被改变则数据会被认为是新主机得数据造成信息上报失误。

    • 解决方式

    客户端建立配置文件,第一次数据采集后把主机名配置写入配置文件,第二次后以配置文件中主机名为准进行数据上报

    • 代码

     1 config/settings.py
     2 
     3 CERT_PATH = os.path.join(BASEDIR,'config','cert')
     4 
     5 src/plugins/client.py
     6 class Agent(Base):    def execute(self):
     7 
     8         server_info = PluginManager().exec_plugin()
     9         #唯一标识主机名得处理(在config/cert为记录主机名得文件)
    10         hostname = server_info['basic']['data']['hostname']
    11         certname = open(Settings.CERT_PATH,'r',encoding='utf-8').read()
    12         if not certname.strip():              #注意去空行。如果文件中没有,第一次会写入获取得主机名
    13             with open(Settings.CERT_PATH,'w',encoding='utf-8') as f:
    14                 f.write(hostname)
    15         else:                                 #如果有就以文件中主机名为准
    16             server_info['basic']['data']['hostname'] = certname
    17         self.post_asset(server_info)
    View Code

    SSH/SALTSTATC 模式的多线程

    • 描述

    主机数量很多,代理端采用for 循环逐个执行效率低,可以建立一个线程池解决此问题
    • 代码

    from concurrent.futures import ThreadPoolExecutor             #引入线程池
    class SSHSALT(Base):
        def get_host(self):
            # 获取未采集的主机列表:
            response = requests.get(Settings.API)
            result = json.loads(response.text) # "{status:'True',data: ['c1.com','c2.com']}"
            if not result['status']:
                return
            return result['data']
    
        def run(self,host):
            server_info = PluginManager(host).exec_plugin()
            self.post_asset(server_info)
    
        def execute(self):
            pool = ThreadPoolExecutor(10)              #实例化一个并发量为10得线程池得对象
            host_list = self.get_host()
            for host in host_list:
                pool.submit(self.run(),host)            #一直保持10个任务在同时运行,host为传入self.run()中得参数
    View Code

    Autoserver  服务端

    API(数据接收)/backendmanger(后台管理)/repository(数据库管理)

    创建django框架 autoserver ,启动服务通过app API实时接收主机数据

    autoserver/autoserver/urls.py
    from django.conf.urls import url,include
    from django.contrib import admin
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^api/', include('api.urls')),
    ]
    autoserver/api/urls.py
    from django.conf.urls import url,include
    from django.contrib import admin
    from api import views
    urlpatterns = [
        url(r'^asset.html$', views.asset),
    ]
    
    autoserver/api/views.py
    import json
    from django.shortcuts import render,HttpResponse
    from repository import models
    def asset(request):
        if request.method == 'POST':
            # 新资产信息
            server_info = json.loads(request.body.decode('utf-8'))               #数据为bytes格式需要解码
            hostname = server_info['basic']['data']['hostname']                  #采集数据中的主机名
            server_obj = models.Server.objects.filter(hostname=hostname).first() #查询数据库中是否有此主机名的记录
            if not server_obj:
                return HttpResponse('当前主机名在资产中未录入')
            asset_obj = server_obj.asset                                      #server与asset通过asset 一对一映射关系
    View Code
    数据采集端代码
    cmdb/config/settings.py
    
    API = "http://127.0.0.1:8000/api/asset.html"
    
    cmdb/src/client.py
    .....
    View Code

    API 接收数据的处理及入库

    数据库表结构

    表 server 与表disk cpu memory 是一对多的关系,server中记录hostname ,每个server 有多个disk 、cpu、memory ...

    数据入库逻辑顺序

    新资产上架,hostname 等信息是web管理界面手动输入,其他如disk  cpu  memory 是数据采集通过API入库,数据采集的主机名与数据库中一致时入库数据,不一致则不入库采集数据

    采集数据处理

    disk  cpu memory 等每个主机有多个相关信息,例如磁盘,磁盘的个数存在增加删除磁盘大小变更等情况,所有入库前采集数据与数据库中数据进行数据比对。由于每个磁盘都有插巢,所有在以id 标识每个插巢,数据对比处理以插巢id 为基准

    """
    1. 根据新资产和原资产进行比较:新["5","1"]      老["4","5","6"]
    2. 增加: [1,]   更新:[5,]    删除:[4,6]
    3. 增加:
            server_info中根据[1,],找到资产详细:入库
       删除:
            数据库中找当前服务器的硬盘:[4,6]
    
       更新:[5,]
            disk_list = [obj,obj,obj]
    
            {
                'data': {
                    '5': {'slot': '5', 'capacity': '476.939', 'pd_type': 'SATA', 'model': 'S1AXNSAFB00549A     Samsung SSD 840 PRO Series              DXM06B0Q'},
                    '3': {'slot': '3', 'capacity': '476.939', 'pd_type': 'SATA', 'model': 'S1AXNSAF912433K     Samsung SSD 840 PRO Series              DXM06B0Q'},
                    '4': {'slot': '4', 'capacity': '476.939', 'pd_type': 'SATA', 'model': 'S1AXNSAF303909M     Samsung SSD 840 PRO Series              DXM05B0Q'},
                    '0': {'slot': '0', 'capacity': '279.396', 'pd_type': 'SAS', 'model': 'SEAGATE ST300MM0006     LS08S0K2B5NV'},
                    '2': {'slot': '2', 'capacity': '476.939', 'pd_type': 'SATA', 'model': 'S1SZNSAFA01085L     Samsung SSD 850 PRO 512GB               EXM01B6Q'},
                    '1': {'slot': '1', 'capacity': '279.396', 'pd_type': 'SAS', 'model': 'SEAGATE ST300MM0006     LS08S0K2B5AH'}
                },
    
                'status': True
            }
    
            log_list = []      #创建日志列表用于存储增删该查等日志记录
    
            dict_info = {'slot': '5', 'capacity': '476.939', 'pd_type': 'SATA', 'model': 'S1AXNSAFB00549A     Samsung SSD 840 PRO Series              DXM06B0Q'},
            obj
                if obj.capacity != dict_info['capacity']:
                    log_list.append('硬盘容量由%s变更为%s' %s(obj.capacity,dict_info['capacity'])
                    obj.capacity = dict_info['capacity']
                ...
            obj.save()
    
            models.xxx.object.create(detail=''.join(log_list))
    
    """
    View Code
  • 相关阅读:
    jQuery Ajax 实例 全解析
    用Javascript评估用户输入密码的强度
    常用网址
    常用的107条Javascript
    根据键盘操作表格
    HTML5吧
    css3动画简介以及动画库animate.css的使用
    jquery插件下载地址
    CEO、COO、CFO、CTO
    springboot与shiro配置
  • 原文地址:https://www.cnblogs.com/fanggege/p/10093260.html
Copyright © 2020-2023  润新知