cmdb事件推送实现jumpserver资产分组同步

在这里插入图片描述

前言

cmdb事件推送实现zabbix资产同步》一文实现了cmdb和zabbix的资产同步,接下来我们就离着《运维思索:cmdb打通zabbix、jumpserver探索》这个小目标就不远了。

言归正传,jumpserver的资产分组同步,即jumpserver的资产列表与cmdb的业务拓扑保持一致,按照业务–集群–模块的树形结构分布。
在这里插入图片描述
而cmdb和jumpserver的同步思路与前面基本保持一致,即:

  1. 主机标识更新
    只有当主机转移至相关模块时,才会触发业务、集群、模块(例如分别对应消金生产环境–运维平台–禅道)的节点创建;而在cmdb侧只创建空的集群、模块时不会触发jumpserver同步,以免导致创建空节点。

  2. 集群、模块删除操作
    cmdb只有在集群和模块下资产都为空的情况才能执行删除,这个策略和jumpserver一致,因此在主机标识更新保证资产粒度级别的分组一致后,删除操作就不是问题了。

  3. 主机导入
    《腾讯蓝鲸实现vsphere虚拟机交付》一文我们通过蓝鲸标准运维已经实现了新建主机在jumpserver中创建、自动注册到cmdb,在保证主机上架流程前提下,我们可以认为所有的主机默认都是在cmdb和jumpserver中已经存在的,我们只需保证jumpserver资产分组和cmdb一致即可。

注意:由于时间的问题,我们本文只介绍“cmdb主机标识更新”触发的jumpserver资产分组同步。

目录结构

我们在gateway网关中,增加了jumpserver模块用于实现资产分组同步。

D:\work\blueking>tree gateway /F
D:\WORK\BLUEKING\GATEWAY
│  .gitignore
│  README.md
│
├─.vscode
│      settings.json
│
└─gateway
    │  manage.py
    │
    ├─.vscode
    │      settings.json
    │
    ├─gateway
    │      asgi.py
    │      settings.py
    │      urls.py
    │      wsgi.py
    │      __init__.py
    │
    └─gw_cmdb
        │  admin.py
        │  apps.py
        │  models.py
        │  tests.py
        │  urls.py
        │  views.py
        │  __init__.py
        │
        ├─common
        │      hostidentifier_cmdb.py
        │      main.py
        │      module_cmdb.py
        │      select_cmdb.py
        │
        ├─jumpserver
        │      api.py
        │      main.py
        │
        └─zabbix
                group.py
                host.py
                main.py
                template.py

其中:

  • common目录是与cmdb相关的模块:
  • main 接收事件推送网关推送过来的参数;
  • hostidentifier_cmdb 针对主机相关事件推送返回格式化参数;
  • module_cmdb 针对模块相关事件推送返回格式化参数;
  • select_cmdb 查询cmdb内容如集群、业务、操作系统等辅助信息;

jumpserver目录是与jumpserver相关的模块:

  • main 解析格式化参数,对jumpserver做相应的处理;
  • api是对按官方jumpserver api进行的重新封装,实现对节点、资产等的操作;

由于分组同步可以在不影响zabbix使用的情况下操作,因此我们在此着重介绍此功能。

分组同步

1.接收cmdb推送参数

cmdb事件推送将参数发送给网关,由views.py接收,json格式数据为:
在这里插入图片描述其中:

  • obj_type,主机标识更新:hostidentifier
  • action, 主机动作:update
  • bk_biz_name ,业务名称:消金生产环境
  • bk_set_name,集群名称:运维平台
  • bk_module_name,模块名称:禅道
  • bk_host_innerip,主机ip:10.166.202.10
from django.http import HttpResponse
from .common.main import main
from .zabbix.main import zabbix_main
from .jumpserver.main import jumpserver_main
import json
import logging

logger = logging.getLogger('log')

# Create your views here
def cmdb_request(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        logger.info('cmdb发送消息:{}'.format(data))
        ## 整理cmdb数据
        res=main(data)
        ##是否需要联动zabbix及jumpserver
        if res['result'] == 1:
            return HttpResponse("ok")
        else:
            logger.info(res)
            #zabbix同步
            zabbix_request = zabbix_main(res)
            logger.info('zabbix 同步完毕:{}'.format(zabbix_request))
            #jumpserver同步
            jumpserver_request = jumpserver_main(res)
            logger.info('jumpserver 同步完毕:{}'.format(jumpserver_request))
            return HttpResponse("ok")
    else:
        logger.info('本接口只支持POST模式')
        return HttpResponse("本接口只支持POST模式")

2.解析参数

(1)common将views接收的请求

vim common/main.py
import logging
from .hostidentifier_cmdb import hostidentifier
from .module_cmdb import module_action

logger = logging.getLogger('log')

def main(data):
    result = {'result': 1,'data': 0}
    ## 模块操作
    if data['obj_type'] == 'module':
        return module_action(data)  
    ## 主机标识操作
    elif data['obj_type'] == 'hostidentifier':
        if data['action'] == 'update' and   data['event_type'] == 'relation' :
            logger.info("主机标识更新: {}".format(data))
            return hostidentifier(data)
        else:
            logger.info("主机标识未知操作: {}".format(data))
    else:
        logger.info("未知操作: {}".format(data))
    return result

(2)主机标识解析

cmdb主机模块转移可能会触发多次请求,因此我们需要借助redis将请求进行去重。

import redis
import json
import hashlib
import logging

logger = logging.getLogger('log')

r = redis.StrictRedis(host='127.0.0.1',port=6379,db=1)

## 模块变更获取主机所有模板定制分组
def hostidentifier(data):
    ##定义数据格式
    datajson= {'tex_id': '','action': data['action'],'obj_type': data['obj_type'],'data': {'cur_data': {'ip': '','group': []},'bk_host_id':data['data']['cur_data']['bk_host_id'],'pre_data': 'None'},'result': 1}
    ## 获取主机组信息,并清理记录reids去除重复会话
    for i in data['data']:
        datajson['data']['cur_data']['ip'] = i['cur_data']['bk_host_innerip']
        grouplist = i['cur_data']['associations']
        for j in grouplist:
            groupname = grouplist[j]['bk_biz_name']+"_"+grouplist[j]['bk_set_name']+"_"+grouplist[j]['bk_module_name']
            datajson['data']['cur_data']['group'].append(groupname)
            datajson['tex_id']= hashlib.md5((data['request_id']+ i['cur_data']['bk_host_innerip']).encode('utf-8')).hexdigest()
    rkey = r.hget('cmdb',datajson['tex_id'])
    logger.info(rkey)
    if rkey is None:
        r.hset('cmdb',datajson['tex_id'],json.dumps(datajson['data']))
        datajson['result'] = 0
        logger.info(datajson)
    return datajson

3.jumpserver操作

(1)jumpserver操作入口


import logging
from django.conf import settings
from urllib import request
import json
from .api import Assets

logger = logging.getLogger('log')

def jumpserver_main(data):
    """
    jumpserver api入口函数,只对主机标识更新响应
    """
    if data['obj_type'] == 'hostidentifier':
        if data['action'] == 'update':
            cur_data = data['data']['cur_data']
            assets = Assets(cur_data)
            assets.perform()
            
        else:
            logger.info("主机标识未知操作: {}".format(data))
    else:
        logger.info("未知操作: {}".format(data))

    return data

(2)jumpserver api操作

import logging
from django.conf import settings
import json
import uuid
import requests

logger = logging.getLogger('log')

class HTTP:
    server = settings.JUMPSERVER_BASEURL

    @classmethod
    def get(cls, url, params=None, **kwargs):
        url = cls.server + url
        headers = settings.JUMPSERVER_HEADERS
        kwargs['headers'] = headers
        res = requests.get(url, params, **kwargs)
        return res

    @classmethod
    def post(cls, url, data=None, json=None, **kwargs):
        url = cls.server + url
        headers = settings.JUMPSERVER_HEADERS
        kwargs['headers'] = headers
        res = requests.post(url, data, json, **kwargs)
        return res

    @classmethod
    def put(cls, url, data=None, **kwargs):
        url = cls.server + url
        headers = settings.JUMPSERVER_HEADERS
        kwargs['headers'] = headers
        res = requests.put(url, data, **kwargs)
        return res

class Node(object):

    def __init__(self, *args):
        self.id = ''
        self.name = None
        self.group = args
        self.full_value = "/Default"

    def exist(self):
        url = '/api/v1/assets/nodes/'
        logger.info('group Is {}'.format(self.group))    
        for item in self.group[0].split('_'):
            self.name = item
            params = {'value': self.name}
            res = HTTP.get(url, params=params)
            res_data = res.json()
            if res.status_code in [200, 201] and res_data:
                self.id = res_data[0].get('id') 
                self.full_value = res_data[0].get('full_value')
                logger.info('节点已存在 {}'.format(self.full_value))
    
            else:
                self.create()
            
        return self.id

    def create(self):
        url = '/api/v1/assets/nodes/' + str(self.id) + '/children/'
        data = {
            'id': str(uuid.uuid1()),
            'value': self.name,
            'full_value': self.full_value
        }
        if self.full_value == "/Default":         
            url = '/api/v1/assets/nodes/'
  
        logger.info('url Is {}'.format(url)) 
        logger.info('data Is {}'.format(data))
        res = HTTP.post(url, json=data)        
        res_data = res.json()
        if res.status_code in [200, 201] and res_data:
            self.id = res_data.get('id')
            self.full_value = res_data.get('full_value')
            logger.info('节点创建成功: {}'.format(res_data))         
        else:
            logger.info('节点创建失败:{}'.format(res_data))

        return self.id

    def delete(self):
        pass

    def perform(self):
        self.exist()
        return self.id

class Assets(object):
    
    def __init__(self, *args):
        self.id = None
        self.node = None
        self.nodeid = []
        self.hostname = None
        self.platform = None
        self.ip = args[0].get('ip')
        self.group = args[0].get('group')
        
    def exist(self):
        url = '/api/v1/assets/assets/'
        params = {
            'ip': self.ip
        }
        res = HTTP.get(url, params)
        res_data = res.json()
        if res.status_code in [200, 201] and res_data:
            self.id = res_data[0].get('id')
            self.hostname = res_data[0].get('hostname')
            self.platform = res_data[0].get('platform')
            logger.info('资产查询成功: {}'.format(res_data))         
            self.update()
        else:
            self.create()   

    def create(self):
        pass

    def update(self):
        url = "/api/v1/assets/assets/" + self.id + "/"
        params = {
            'hostname': self.hostname,
            'ip': self.ip,
            'platform': self.platform,
            'nodes': self.nodeid
        }
        res = HTTP.put(url, json.dumps(params))
        res_data = res.json()
        if res.status_code in [200, 201] and res_data:
            self.id = res_data.get('id')
            logger.info('资产更新成功: {}'.format(res_data))         
        else:
            logger.info('资产更新失败:{}'.format(res_data))

    def perform(self):
        for group in self.group:
            self.node = Node(group)
            self.nodeid.append(self.node.perform())
               
        self.exist()
        logger.info('nodeid Is {}'.format(self.nodeid))

4.操作

(1)cmdb侧主机转移模块

在这里插入图片描述

(2)解析过程

在这里插入图片描述

(3)最终效果

在这里插入图片描述

总结

通过事件推送网关我们初步实现了cmdb和jumpserver的分组同步,我们只需要在cmdb一侧就可以管理主机资源,不仅节省了我们跨平台处理的时间,而且规范了我们基础设施的管理。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Python-CMDB资产管理系统项目是基于Python编程语言开发的一种用于管理企业资产的信息系统。CMDB(Configuration Management Database)是一种用于记录和管理组织内所有硬件和软件资源的数据库。该项目的目标是通过实现一个功能强大且易于使用的资产管理系统,帮助企业更好地管理和维护其资产库。 该系统具备以下特点和功能: 1. 资产信息管理:可以录入和管理所有的企业资产信息,包括硬件设备、软件和网络设备等。用户可以根据自己的需求添加、修改和删除资产信息,并可以对资产进行分类和标记,便于查找和管理。 2. 资产追踪和监控:系统可以实时追踪和监控所有资产的状态和位置,帮助用户快速定位和管理资产。例如,用户可以查询特定设备的位置、使用状况和维护历史等信息。 3. 资产维护计划:系统可以为每个资产设置维护计划,包括定期检查、保养和维修等。用户可以根据资产的使用情况和维护需求制定和调整维护计划,以确保资产的正常运行。 4. 报表和统计分析:系统可以生成各种报表和统计分析图表,帮助用户了解和掌握资产的整体情况和趋势。用户可以根据报表和图表的结果做出决策和调整管理策略。 5. 安全和权限管理:系统支持用户权限管理,可以设置不同用户的访问权限,保护重要数据和操作不受未经授权的访问。 Python-CMDB资产管理系统项目使用Python语言开发,具有开源、跨平台和易于扩展等优势。同时,Python拥有丰富强大的库和框架,可以快速开发和调试系统。通过该项目,企业可以有效地管理和维护其资产,提高工作效率和资产利用率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值