CMDB

浅谈ITIL

TIL即IT基础架构库(Information Technology Infrastructure Library, ITIL,信息技术基础架构库)由英国政府部门CCTA(Central Computing and Telecommunications Agency)在20世纪80年代末制订,现由英国商务部OGC(Office of Government Commerce)负责管理,主要适用于IT服务管理(ITSM)。ITIL为企业的IT服务管理实践提供了一个客观、严谨、可量化的标准和规范。

1、事件管理(Incident Management)

事故管理负责记录、归类和安排专家处理事故并监督整个处理过程直至事故得到解决和终止。事故管理的目的是在尽可能最小地影响客户和用户业务的情况下使IT系统恢复到服务级别协议所定义的服务级别。

2、问题管理(Problem Management)

问题管理是指通过调查和分析IT基础架构的薄弱环节、查明事故产生的潜在原因,并制定解决事故的方案和防止事故再次发生的措施,将由于问题和事故对业务产生的负面影响减小到最低的服务管理流程。与事故管理强调事故恢复的速度不同,问题管理强调的是找出事故产生的根源,从而制定恰当的解决方案或防止其再次发生的预防措施。

3、配置管理(Configuration Management)

配置管理是识别和确认系统的配置项,记录和报告配置项状态和变更请求,检验配置项的正确性和完整性等活动构成的过程,其目的是提供IT基础架构的逻辑模型,支持其它服务管理流程特别是变更管理和发布管理的运作。

4、变更管理(Change Management)

变更管理是指为在最短的中断时间内完成基础架构或服务的任一方面的变更而对其进行控制的服务管理流程。变更管理的目标是确保在变更实施过程中使用标准的方法和步骤,尽快地实施变更,以将由变更所导致的业务中断对业务的影响减小到最低。

5、发布管理(Release Management)

发布管理是指对经过测试后导入实际应用的新增或修改后的配置项进行分发和宣传的管理流程。发布管理以前又称为软件控制与分发,它由变更管理流程控制。

事件管理的目标是在不影响业务的情况下,尽可能快速的恢复服务,从而保证最佳的效率和服务的可持续性。事件管理流程的建立包括事件分类,确定事件的优先级和建立事件的升级机制。

问题管理是调查基础设施和所有可用信息,包括事件数据库,来确定引起事件发生的真正潜在原因,一起提供的服务中可能存在的故障。

配置管理的目标是:定义和控制服务与基础设施的部件,并保持准确的配置信息。

变更管理的目标是:以受控的方式,确保所有变更得到评估、批准、实施和评审。

发布管理的目标是:在实际运行环境的发布中,交付、分发并跟踪一个或多个变更。

服务台:服务台是IT部门和IT服务用户之间的单一联系点。它通过提供一个集中和专职的服务联系点促进了组织业务流程与服务管理基础架构集成。服务台的主要目标是协调客户(用户)和IT部门之间的联系,为IT服务运作提供支持,从而提高客户的满意度。

CMDB介绍

CMDB --Configuration Management Database 配置管理数据库, CMDB存储与管理企业IT架构中设备的各种配置信息,它与所有服务支持和服务交付流程都紧密相联,支持这些流程的运转、发挥配置信息的价值,同时依赖于相关流程保证数据的准确性。

在实际的项目中,CMDB常常被认为是构建其它ITIL流程的基础而优先考虑,ITIL项目的成败与是否成功建立CMDB有非常大的关系。

70%~80%的IT相关问题与环境的变更有着直接的关系。实施变更管理的难点和重点并不是工具,而是流程。即通过一个自动化的、可重复的流程管理变更,使得当变更发生的时候,有一个标准化的流程去执行,能够预测到这个变更对整个系统管理产生的影响,并对这些影响进行评估和控制。而变更管理流程自动化的实现关键就是CMDB。

CMDB工具中至少包含这几种关键的功能:整合、调和、同步、映射和可视化。

  • 整合是指能够充分利用来自其他数据源的信息,对CMDB中包含的记录源属性进行存取,将多个数据源合并至一个视图中,生成连同来自CMDB和其他数据源信息在内的报告;
  • 调和能力是指通过对来自每个数据源的匹配字段进行对比,保证CMDB中的记录在多个数据源中没有重复现象,维持CMDB中每个配置项目数据源的完整性;自动调整流程使得初始实施、数据库管理员的手动运作和现场维护支持工作降至最低;
  • 同步指确保CMDB中的信息能够反映联合数据源的更新情况,在联合数据源更新频率的基础上确定CMDB更新日程,按照经过批准的变更来更新 CMDB,找出未被批准的变更;
  • 应用映射与可视化,说明应用间的关系并反应应用和其他组件之间的依存关系,了解变更造成的影响并帮助诊断问题。

CMDB 资产管理部分实现

需求

  • •存储所有IT资产信息
  • •数据可手动添加
  • •硬件信息可自动收集
  • •硬件信息可自动变更

立业之本:定义表结构

  • 各种硬件都能存
  • 资产变更有纪录
  • 资产ID永不变
  • 资产要有状态机

demo:

from django.db import models

# Create your models here.
from Wolf.models import UserProfile

class Asset(models.Model):
    asset_type_choices = (
        (‘server‘, u‘服务器‘),
        (‘switch‘, u‘交换机‘),
        (‘router‘, u‘路由器‘),
        (‘firewall‘, u‘防火墙‘),
        (‘storage‘, u‘存储设备‘),
        (‘NLB‘, u‘NetScaler‘),
        (‘wireless‘, u‘无线AP‘),
        (‘software‘, u‘软件资产‘),
        (‘others‘, u‘其它类‘),
    )
    asset_type = models.CharField(choices=asset_type_choices,max_length=64, default=‘server‘)
    name = models.CharField(max_length=64,unique=True)
    sn = models.CharField(u‘资产SN号‘,max_length=128, unique=True)
    manufactory = models.ForeignKey(‘Manufactory‘,verbose_name=u‘制造商‘,null=True, blank=True)
    management_ip = models.GenericIPAddressField(u‘管理IP‘,blank=True,null=True)
    contract = models.ForeignKey(‘Contract‘,verbose_name=u‘合同‘,blank=True,null=True)
    trade_date = models.DateField(u‘购买时间‘,null=True,blank=True)
    expire_date = models.DateField(u‘过保修期‘,null=True,blank=True)
    price = models.FloatField(u‘价格‘,null=True,blank=True)
    business_unit = models.ForeignKey(‘BusinessUnit‘,verbose_name=u‘所属业务线‘,null=True,blank=True)

    tags = models.ManyToManyField(‘Tag‘,blank=True)
    admin = models.ForeignKey(UserProfile,verbose_name=u‘资产管理员‘,null=True, blank=True)
    idc = models.ForeignKey(‘IDC‘,verbose_name=u‘IDC机房‘,null=True, blank=True)
    memo = models.TextField(u‘备注‘,null=True,blank=True)
    create_date = models.DateTimeField(blank=True,auto_now_add=True)
    update_date = models.DateTimeField(blank=True,auto_now=True)
    class Meta:
        verbose_name = ‘资产总表‘
        verbose_name_plural = ‘资产总表‘
    def __str__(self):
        return ‘id:%s name:%s‘ %(self.id,self.name)
class Server(models.Model):
    asset = models.OneToOneField(‘Asset‘)

    created_by_choices = (
        (‘auto‘,‘Auto‘),
        (‘manual‘,‘Manual‘),
    )

    create_by = models.CharField(max_length=32,choices=created_by_choices,default=‘auto‘)
    hosted_on = models.ForeignKey(‘self‘,related_name=‘hosted_on_server‘,blank=True,null=True)
    model = models.CharField(u‘型号‘,max_length=128,null=True,blank=True)
    raid_type = models.CharField(u‘raid类型‘,max_length=512,blank=True,null=True)
    os_type = models.CharField(u‘操作系统类型‘,max_length=64,blank=True,null=True)
    os_distribution = models.CharField(u‘发行版本‘,max_length=64,blank=True,null=True)
    os_release = models.CharField(u‘操作系统版本‘,max_length=64,blank=True,null=True)

    create_date = models.DateTimeField(blank=True,auto_now_add=True)
    update_date = models.DateTimeField(blank=True,auto_now=True)
    class Meta:
        verbose_name = ‘服务器‘
        verbose_name_plural = ‘服务器‘

    def __str__(self):

        return ‘%s sn:%s‘ %(self.asset,self.asset.sn)
class NetworkDevice(models.Model):

    asset = models.ForeignKey(‘Asset‘)

    vlan_ip = models.GenericIPAddressField(u‘VlanIP‘,blank=True,null=True)
    intranet_ip = models.GenericIPAddressField(u‘内网IP‘,blank=True,null=True)
    sn = models.CharField(u‘SN号‘,max_length=128,unique=True)
    model = models.CharField(u‘型号‘,max_length=128,null=True,blank=True)
    firmware = models.ForeignKey(‘Software‘,blank=True,null=True)
    port_num = models.SmallIntegerField(u‘端口个数‘,null=True,blank=True)
    device_detail = models.TextField(u‘设置详细配置‘,null=True,blank=True)
    create_date = models.DateTimeField(auto_now_add=True)
    update_date =models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = ‘网络设备‘
        verbose_name_plural = ‘网络设备‘

class Software(models.Model):
    os_type_choices = (
        (‘linux‘,‘Linux‘),
        (‘windows‘,‘Windows‘),
        (‘network_firmware‘,‘Network Firmware‘),
        (‘software‘,‘Softwares‘)
    )

    os_distribution_choices = (
        (‘windows‘,‘Windows‘),
        (‘centos‘,‘CentOS‘),
        (‘ubuntu‘,‘Ubuntu‘)
    )
    type = models.CharField(u‘系统类型‘,choices=os_type_choices,max_length=64,help_text=u‘eg. GNU/Linux‘,default=1)
    distribution = models.CharField(u‘发行版本‘,choices=os_distribution_choices,max_length=32,default=‘windows‘)
    version = models.CharField(u‘软件/系统版本‘,max_length=64,help_text=u‘eg. CentOS release 6.5 (Final)‘, unique=True)
    language_choices = (
        (‘cn‘,u‘中文‘),
        (‘en‘,u‘英文‘),
    )
    language = models.CharField(u‘系统语言‘,choices=language_choices,max_length=64,default=‘cn‘)

    def __str__(self):

        return self.version

    class Meta:
        verbose_name = ‘软件/系统‘
        verbose_name_plural = ‘软件/系统‘

class CPU(models.Model):

    asset = models.OneToOneField(‘Asset‘)
    cpu_model = models.CharField(u‘CPU型号‘,max_length=128,blank=True)
    cpu_count = models.SmallIntegerField(u‘物理cpu个数‘)
    cpu_core_count = models.SmallIntegerField(u‘cpu核数‘)
    memo = models.TextField(u‘备注‘,null=True,blank=True)
    create_date = models.DateTimeField(auto_now_add=True)
    update_date =models.DateTimeField(auto_now=True,blank=True,null=True)

    class Meta:
        verbose_name = ‘CPU部件‘
        verbose_name_plural = ‘CPU部件‘
    def __str__(self):
        return self.cpu_model
class RAM(models.Model):

    asset = models.ForeignKey(‘Asset‘)
    sn = models.CharField(u‘SN号‘,max_length=128,blank=True,null=True)
    manufactory = models.CharField(u‘制造商‘,max_length=64,blank=True,null=True)
    model = models.CharField(u‘内存类型‘,max_length=128)
    slot = models.CharField(u‘插槽‘,max_length=64)
    capacity = models.IntegerField(u‘内存大小(MB)‘)
    memo = models.CharField(u‘备注‘,max_length=128,blank=True,null=True)
    create_date = models.DateTimeField(blank=True,auto_now_add=True)
    update_date =models.DateTimeField(auto_now=True,blank=True,null=True)

    def __str__(self):

        return ‘%s:%s:%s‘ %(self.asset_id,self.slot,self.capacity)
    class Meta:
        verbose_name = ‘RAM‘
        verbose_name_plural = ‘RAM‘
        unique_together = [‘asset‘,‘model‘,]
    auto_create_fields = [‘sn‘,‘slot‘,‘model‘,‘capacity‘,]

class Disk(models.Model):
    asset = models.ForeignKey(‘Asset‘)
    sn = models.CharField(u‘SN号‘,max_length=128,blank=True,null=True)
    slot = models.CharField(u‘插槽位‘,max_length=64)
    manufactory = models.CharField(u‘制造商‘,max_length=64,blank=True,null=True)
    model = models.CharField(u‘磁盘型号‘,max_length=128,blank=True,null=True)
    capacity = models.FloatField(u‘磁盘容量GB‘)
    disk_iface_choice = (
        (‘SATA‘,‘SATA‘),
        (‘SAS‘,‘SAS‘),
        (‘SCSI‘,‘SCSI‘),
        (‘SSD‘,‘SSD‘)
    )

    iface_type = models.CharField(u‘接口类型‘,max_length=64,choices=disk_iface_choice,default=‘SAS‘)
    memo = models.TextField(u‘备注‘,blank=True,null=True)
    create_date = models.DateTimeField(blank=True, auto_now_add=True)
    update_date = models.DateTimeField(blank=True,null=True,auto_now=True)

    auto_create_fields = [‘sn‘,‘slot‘,‘manufactory‘,‘model‘,‘capacity‘,‘iface_type‘]
    class Meta:
        unique_together = [‘asset‘,‘slot‘]
        verbose_name = ‘硬盘‘
        verbose_name_plural = ‘硬盘‘
    def __str__(self):
        return ‘%s:slot:%s capacity:%s‘ %(self.asset_id,self.slot,self.capacity)

class NIC(models.Model):

    asset = models.ForeignKey(‘Asset‘)
    name = models.CharField(u‘网卡名‘,max_length=64,blank=True,null=True)
    sn = models.CharField(u‘SN号‘,max_length=128,blank=True,null=True)
    model = models.CharField(u‘网卡型号‘,max_length=128,blank=True,null=True)
    macaddress = models.CharField(u‘MAC‘,max_length=64,unique=True)
    ipaddress = models.GenericIPAddressField(u‘IP‘,blank=True,null=True)
    netmask = models.CharField(max_length=64,blank=True,null=True)
    bonding = models.CharField(max_length=64,blank=True,null=True)
    memo = models.CharField(u‘备注‘,max_length=128,blank=True,null=True)
    create_date = models.DateTimeField(blank=True, auto_now_add=True)
    update_date = models.DateTimeField(blank=True,null=True,auto_now=True)

    def __str__(self):
        return ‘%s:%s‘ %(self.asset_id,self.macaddress)

    class Meta:
        verbose_name = u‘网卡‘
        verbose_name_plural = u‘网卡‘
    auto_create_fields = [‘name‘,‘sn‘,‘model‘,‘macaddress‘,‘ipaddress‘,‘netmask‘,‘bonding‘]
class RaidAdaptor(models.Model):

    asset = models.ForeignKey(‘Asset‘)
    sn = models.CharField(u‘SN型号‘,max_length=128,blank=True,null=True)
    slot = models.CharField(u‘插口‘,max_length=64)
    model = models.CharField(u‘型号‘,max_length=64,blank=True,null=True)
    memo = models.TextField(u‘备注‘,blank=True,null=True)
    create_date = models.DateTimeField(blank=True, auto_now_add=True)
    update_date = models.DateTimeField(blank=True,null=True,auto_now=True)

    def __str__(self):
        return self.name
    class Meta:
        unique_together = (‘asset‘,‘slot‘)

class Manufactory(models.Model):

    manufactory = models.CharField(u‘厂商名称‘,max_length=64,unique=True)
    support_num = models.CharField(u‘支持电话‘,max_length=30,blank=True,null=True)
    memo = models.CharField(u‘备注‘,max_length=128,blank=True)
    def __str__(self):
        return self.manufactory
    class Meta:
        verbose_name = ‘厂商‘
        verbose_name_plural = ‘厂商‘

class BusinessUnit(models.Model):

    parent_unit = models.ForeignKey(‘self‘,related_name=‘parent_level‘,blank=True,null=True)

    name = models.CharField(u‘业务线‘,max_length=64,unique=True)
    memo = models.CharField(u‘备注‘,max_length=128,blank=True)

    def __str__(self):
        return self.name
    class Meta:
        verbose_name = ‘业务线‘
        verbose_name_plural = ‘业务线‘
class Contract(models.Model):

    sn = models.CharField(u‘合同号‘,max_length=128,unique=True)
    name = models.CharField(u‘合同名称‘,max_length=64)
    memo = models.TextField(u‘备注‘,blank=True,null=True)
    price = models.IntegerField(u‘合同金额‘)
    detail = models.TextField(u‘合同详细‘,blank=True,null=True)
    start_date = models.DateField(blank=True)
    end_date = models.DateField(blank=True)
    license_num = models.IntegerField(u‘license数量‘,blank=True,)
    create_date = models.DateTimeField(blank=True, auto_now_add=True)
    update_date = models.DateTimeField(blank=True,null=True,auto_now=True)
    class Meta:
        verbose_name = ‘合同‘
        verbose_name_plural = ‘合同‘
    def __str__(self):
        return self.name

class IDC(models.Model):

    name = models.CharField(u‘机房名称‘,max_length=64,unique=True)
    memo = models.CharField(u‘备注‘,max_length=128,blank=True,null=True)

    def __str__(self):
        return self.name
    class Meta:
        verbose_name = ‘机房‘
        verbose_name_plural = ‘机房‘

class Tag(models.Model):

    name = models.CharField(‘Tag name‘,max_length=32,unique=True)
    creater = models.ForeignKey(UserProfile)
    create_date = models.DateField(auto_now_add=True)
    def __str__(self):
        return self.name

class EventLog(models.Model):

    name = models.CharField(u‘事件名称‘,max_length=128)
    event_type_choices = (
        (1,u‘硬件变更‘),
        (2,u‘新增配件‘),
        (3,u‘设备下线‘),
        (4,u‘设备上线‘),
        (5,u‘定期维护‘),
        (6,u‘设备上线\更新\变更‘),
        (7,u‘其他‘),
    )
    event_type = models.SmallIntegerField(u‘事件类型‘,choices=event_type_choices)
    asset = models.ForeignKey(‘Asset‘)
    component = models.CharField(‘事件子项‘,max_length=255,blank=True,null=True)
    detail = models.TextField(u‘事件详情‘)
    date = models.DateTimeField(u‘事件时间‘,auto_now_add=True)
    user = models.ForeignKey(UserProfile,verbose_name=u‘事件源‘)
    memo = models.TextField(u‘备注‘,blank=True,null=True)

    def __str__(self):
        return self.name
    class Meta:

        verbose_name = ‘事件纪录‘
        verbose_name_plural = ‘事件纪录‘

    def colored_event_type(self):

        if self.event_type == 1:
            cell_html = ‘<span style = "background: orange;">%s</span>‘
        elif self.event_type == 2:
            cell_html = ‘<span style="background: yellowgreen;">%s</span>‘
        else:
            cell_html = ‘<span >%s</span>‘
        return cell_html % self.get_event_type_display()
    colored_event_type.allow_tags = True
    colored_event_type.short_description = u‘事件类型‘

class NewAssetApprovalZone(models.Model):

    sn = models.CharField(u‘资产SN号‘,max_length=128,unique=True)
    asset_type_choices = (
        (‘server‘,u‘服务器‘),
        (‘switch‘,u‘交换机‘),
        (‘router‘,u‘路由器‘),
        (‘firewall‘,u‘防火墙‘),
        (‘storage‘,u‘存储设备‘),
        (‘NLB‘,u‘NetScaler‘),
        (‘wireless‘,u‘无线AP‘),
        (‘software‘,u‘软件资产‘),
        (‘others‘,u‘其他类‘),
    )
    asset_type = models.CharField(choices=asset_type_choices,max_length=64,blank=True,null=True)
    manufactory = models.CharField(max_length=64,blank=True,null=True)
    model = models.CharField(max_length=128,blank=True,null=True)
    ram_size = models.IntegerField(blank=True,null=True)
    cpu_model = models.CharField(max_length=128,blank=True,null=True)
    cpu_count = models.IntegerField(blank=True,null=True)
    cpu_core_count = models.IntegerField(blank=True,null=True)
    os_distribution = models.CharField(max_length=64,blank=True,null=True)
    os_type = models.CharField(max_length=64,blank=True,null=True)
    os_release = models.CharField(max_length=64,blank=True,null=True)
    data = models.TextField(u‘资产数据‘)
    date = models.DateTimeField(u‘汇报日期‘,auto_now_add=True)
    approved = models.BooleanField(u‘已批准‘,default=False)
    approved_by = models.ForeignKey(UserProfile,verbose_name=u‘批准人‘,blank=True,null=True)
    approved_date = models.DateTimeField(u‘批准日期‘,blank=True,null=True)

    def __str__(self):

        return self.sn
    class Meta:

        verbose_name = ‘新上线待批准资产‘
        verbose_name_plural = ‘新上线待批准资产‘

逻辑核心:资产的自动汇报

?视图demo:

from django.shortcuts import render,HttpResponse
from django.views.decorators.csrf import csrf_exempt
import json
from Sansa import core
# Create your views here.
@csrf_exempt #免除csrf验证
def asset_report(request):

    if request.method == ‘POST‘:
        ass_handler = core.Asset(request)
        if ass_handler.data_is_valid(): #验证数据是否合法
            #注射数据
            ass_handler.data_inject()
        return HttpResponse(json.dumps(ass_handler.response))
    return HttpResponse(‘----test----‘)

core:

#!/usr/bin/env python
import json
from django.core.exceptions import ObjectDoesNotExist
from Sansa import models
from django.utils import timezone

class Asset(object):

    def __init__(self,request):

        self.request = request #view中的request
        #必须要有的字段
        self.manufactory_fields = [‘sn‘,‘asset_id‘,‘asset_type‘]
        self.field_sets = {
            ‘asset‘:[‘manufactory‘],
            ‘server‘:[‘model‘,‘cpu_count‘,‘cpu_core_count‘,‘cpu_model‘,‘raid_type‘,‘os_type‘,‘os_distribution‘,‘os_release‘],
            ‘networkdevice‘:[]
        }
        #给客户端的返回
        self.response = {
            ‘error‘:[],
            ‘info‘:[],
            ‘warning‘:[],
        }
    def response_msg(self,msg_type,key,msg):
        ‘‘‘
        将要返回的值放入self.response字典中
        :param msg_type: 数据类型 如:error
        :param key:
        :param msg:
        :return:
        ‘‘‘
        if msg_type in self.response:
            self.response[msg_type].append({key:msg})
        else:
            raise ValueError
    def mandatory_check(self,data,only_check_sn=False):
        ‘‘‘
        强制性检测函数
        :param data:  传入的数据
        :param only_check_sn:
        :return:
        ‘‘‘
        #遍历强制性检测字段,判断字段有没有
        for field in self.manufactory_fields:
            #没有写入到error中
            if not field in data:
                self.response_msg(‘error‘,‘MandatoryCheckFailed‘,"The field [%s] is mandatory and not provided in your reporting data" % field)
        #如果有错误直接返回不在往下进行
        else:
            if self.response[‘error‘]:return False
        try:
            if not only_check_sn:  #不是新资产
                #获取这条资产的对象
                self.asset_obj = models.Asset.objects.get(id=int(data[‘asset_id‘]),sn=data[‘sn‘])
            else: #是新资产
                self.asset_obj = models.Asset.objects.get(sn=data[‘sn‘])
            return True #前置检测通过
        except ObjectDoesNotExist as e:
            self.response_msg(‘error‘,‘AssetDataInvalid‘,"Cannot find asset object in DB by using asset id [%s] and SN [%s] " % (data[‘asset_id‘],data[‘sn‘]))
            self.waiting_approval = True
            return False
    def get_asset_id_by_sn(self):

        data = self.request.POST.get(‘asset_data‘)
        response = {}
        if data:
            try:
                data = json.loads(data)
                #这个资产已经在数据库中
                if self.mandatory_check(data,only_check_sn=True):
                    response = {‘asset_id‘:self.asset_obj.id}
                else:
                    if hasattr(self,‘waiting_approval‘):
                        response = {‘needs_approval‘:"this is a new asset,needs IT admin‘s approval to create the new asset id."}
                        self.clean_data = data
                        self.save_new_asset_to_approval_zone()
                    else:
                        response = self.response
            except ValueError as e:
                self.response_msg(‘error‘,‘AssetDataInvalid‘,str(e))
                response = self.response
        else:
            self.response_msg(‘error‘,‘AssetDataInvalid‘,"The reported asset data is not valid or provided")
            response = self.response
        return response

    def save_new_asset_to_approval_zone(self):

        asset_sn = self.clean_data.get(‘sn‘)
        asset_already_in_approval_zone = models.NewAssetApprovalZone.objects.get_or_create(
            sn = asset_sn,
            data = json.dumps(self.clean_data),
            manufactory = self.clean_data.get(‘manufactory‘),
            model = self.clean_data.get(‘model‘),
            asset_type = self.clean_data.get(‘asset_type‘),
            ram_size = self.clean_data.get(‘ram_size‘),
            cpu_model = self.clean_data.get(‘cpu_model‘),
            cpu_count = self.clean_data.get(‘cpu_count‘),
            cpu_core_count = self.clean_data.get(‘cpu_core_count‘),
            os_distribution = self.clean_data.get(‘os_distribution‘),
            os_release = self.clean_data.get(‘os_release‘),
            os_type = self.clean_data.get(‘os_type‘),
        )
        return True
    def data_is_valid(self):
        ‘‘‘
        数据检测
        :return:
        ‘‘‘
        data = self.request.POST.get(‘asset_data‘)
        #确保存在数据
        if data:
            try:
                data = json.loads(data)
                #强制性检测
                self.mandatory_check(data)
                self.clean_data = data
                #如果没有错误就往下进行
                if not self.response[‘error‘]:
                    return True
            except ValueError as e:
                self.response_msg(‘error‘,‘AssetDataInvalid‘,str(e))
        else:
            self.response_msg(‘error‘,‘AssetDataInvalid‘,"The reported asset data is not valid or provided")
    def _is_new_asset(self):
        ‘‘‘
        判断是否是新资产
        :return:
        ‘‘‘
        #是新资产
        if not hasattr(self.asset_obj,self.clean_data[‘asset_type‘]):
            return True
        #不是新资产
        else:
            return False
    def data_inject(self):
        ‘‘‘
        注射
        :return:
        ‘‘‘
        #判断是否是新资产
        if self._is_new_asset():
            #创建新资产
            self.create_asset()
        else:
            self.update_asset()
    def data_is_valid_without_id(self):

        data = self.request.POST.get(‘asset_data‘)
        if data:
            try:
                data = json.loads(data)
                asset_obj = models.Asset.objects.get_or_create(
                    sn = data.get(‘sn‘),
                    name = data.get(‘name‘)
                )
                data[‘asset_id‘] = asset_obj[0].id
                self.mandatory_check(data)
                self.clean_data = data
                if not self.response[‘error‘]:
                    return True
            except ValueError as e:
                self.response_msg(‘error‘,‘AssetDataInvalid‘,str(e))
        else:
             self.response_msg(‘error‘,‘AssetDataInvalid‘, "The reported asset data is not valid or provided")
    def reformat_components(self,identify_field,data_set):

        for k,data in data_set.items():
            data[identify_field] = k
    def _verify_field(self,data_set,field_key,data_type,required=True):
        ‘‘‘
        判断客户端传来的数据中的field_key的数据类型是不是data_type
        :param data_set: 客户端数据
        :param field_key: 客户端数据中的key
        :param data_type: 数据类型
        :param required:
        :return:
        ‘‘‘
        field_val = data_set.get(field_key)
        if field_val:
            try:
                data_set[field_key] = data_type(field_val)
            except ValueError as e:
                self.response_msg(‘error‘,‘InvalidField‘,"The field [%s]‘s data type is invalid, the correct data type should be [%s] " % (field_key,data_type))
        elif required == True:
            self.response_msg(‘error‘,‘LackOfField‘,"The field [%s] has no value provided in your reporting data [%s]" % (field_key,data_set))
    def create_asset(self):
        #创建资产,按资产类型不同调用不同的方法创建,如_create_server
        func = getattr(self,‘_create_%s‘ % self.clean_data[‘asset_type‘])
        create_obj = func()
    def update_asset(self):
        #更新资产,按资产类型不同调用不同的方法更新,如_update_server
        func = getattr(self,‘_update_%s‘ % self.clean_data[‘asset_type‘])
        create_obj = func()
    def _update_server(self):
        ‘‘‘
        服务器更新
        :return:
        ‘‘‘
        nic = self._update_asset_component(
            data_source = self.clean_data[‘nic‘],
            fk = ‘nic_set‘,
            update_fields = [‘name‘,‘sn‘,‘model‘,‘macaddress‘,‘ipaddress‘,‘netmask‘,‘bonding‘],
            identify_field = ‘macaddress‘
        )
        disk = self._update_asset_component(
            data_source = self.clean_data[‘physical_disk_driver‘],
            fk = ‘disk_set‘,
            update_fields = [‘slot‘,‘sn‘,‘model‘,‘manufactory‘,‘capacity‘,‘iface_type‘],
            identify_field = ‘slot‘,
        )
        ram = self._update_asset_component(
            data_source = self.clean_data[‘ram‘],
            fk = ‘ram_set‘,
            update_fields = [‘slot‘,‘sn‘,‘model‘,‘capacity‘],
            identify_field = ‘slot‘,
        )
        cpu = self._update_cpu_component()
        manufactory = self._update_manufactory_component()
        server = self._update_server_component()
    def _create_server(self):
        self._create_server_info()
        self._create_or_update_manufactory()
        self._create_cpu_component()
        self._create_disk_component()
        self._create_nic_component()
        self._create_ram_component()

        log_msg = "Asset [<a href=‘/admin/assets/asset/%s‘ target=‘_blank‘>%s</a>] has been created!" % (self.asset_obj.id,self.asset_obj)
        self.response_msg(‘info‘,‘NewAssetOnline‘,log_msg)
    def _create_server_info(self,ignore_errs=False):
        ‘‘‘
        创建服务器信息
        :param ignore_errs:忽略错误
        :return:
        ‘‘‘
        try:
            #判断数据类型
            self._verify_field(self.clean_data,‘model‘,str)
            #如果没有错误或忽略错误
            if not len(self.response[‘error‘]) or ignore_errs == True:
                data_set = {
                    ‘asset_id‘ : self.asset_obj.id,
                    ‘raid_type‘ : self.clean_data.get(‘raid_type‘),
                    ‘model‘ : self.clean_data.get(‘model‘),
                    ‘os_type‘ : self.clean_data.get(‘os_type‘),
                    ‘os_distribution‘ : self.clean_data(‘os_distribution‘),
                    ‘os_release‘ : self.clean_data.get(‘os_release‘)
                }
                #创建server表
                obj = models.Server(**data_set)
                #保存
                obj.save()
                return obj
        except Exception as e:
            self.response_msg(‘error‘,‘ObjectCreationException‘,‘Object [server] %s‘ % str(e) )

    def _create_or_update_manufactory(self,ignore_errs=False):
        ‘‘‘
        创建或更新厂商
        :param ignore_errs:
        :return:
        ‘‘‘
        try:
            #确保厂商字段存在并且类型正确
            self._verify_field(self.clean_data,‘manufactory‘,str)
            #获取厂商名字
            manufactory = self.clean_data.get(‘manufactory‘)
            #判断是否有错误
            if not len(self.response[‘error‘]) or ignore_errs == True:
                #判断数据库中是否有该厂商
                obj_exist = models.Manufactory.objects.filter(manufactory=manufactory)
                #如果有就赋给该server
                if obj_exist:
                    obj = obj_exist[0]
                #没有该厂商就创建厂商
                else:
                    obj = models.Manufactory(manufactory=manufactory)
                    obj.save()
                #将厂商赋给该资产
                self.asset_obj.manufactory = obj
                #保存
                self.asset_obj.save()
        except Exception as e:
            self.response_msg(‘error‘,‘ObjectCreationException‘,‘Object [manufactory] %s‘ % str(e))
    def _create_cpu_component(self,ignore_errs=False):
        ‘‘‘
        创建cpu资产
        :param ignore_errs:
        :return:
        ‘‘‘
        try:
            #检测一些字段是否符合要求
            self._verify_field(self.clean_data,‘model‘,str)
            self._verify_field(self.clean_data,‘cpu_count‘,int)
            self._verify_field(self.clean_data,‘cpu_core_count‘,int)
            if not len(self.response[‘error‘]) or ignore_errs == True:
                data_set = {
                    ‘asset_id‘ : self.asset_obj.id,
                    ‘cpu_model‘ : self.clean_data.get(‘cpu_model‘),
                    ‘cpu_count‘ : self.clean_data.get(‘cpu_count‘),
                    ‘cpu_core_count‘ : self.clean_data(‘cpu_core_count‘)
                }
                #创建cpu资产
                obj = models.CPU(**data_set)
                obj.save()
                #放入返回结果,没有创建日志
                log_msg = "Asset[%s] --> has added new [cpu] component with data [%s]" %(self.asset_obj,data_set)
                self.response_msg(‘info‘,‘NewComponentAdded‘,log_msg)
                return obj
        except Exception as e:
            self.response_msg(‘error‘,‘ObjectCreationException‘,‘Object [cpu] %s‘ % str(e))
    def _create_disk_component(self):
        ‘‘‘
        创建硬盘,可以有多块硬盘
        :return:
        ‘‘‘
        disk_info = self.clean_data.get(‘physical_disk_driver‘)
        if disk_info:
            #遍历硬盘信息
            for disk_item in disk_info:
                try:
                    #信息检测
                    self._verify_field(disk_item,‘slot‘,str)
                    self._verify_field(disk_item,‘capacity‘,float)
                    self._verify_field(disk_item,‘iface_type‘,str)
                    self._verify_field(disk_item,‘model‘,str)
                    #是否有错误
                    if not len(self.response[‘error‘]):
                        data_set = {
                            ‘asset_id‘ : self.asset_obj.id,
                            ‘sn‘ : disk_item.get(‘sn‘),
                            ‘slot‘ : disk_item.get(‘slot‘),
                            ‘capacity‘ : disk_item.get(‘capacity‘),
                            ‘model‘ : disk_item.get(‘model‘),
                            ‘iface_type‘ : disk_item.get(‘iface_type‘),
                            ‘manufactory‘ : disk_item.get(‘manufactory‘),
                        }
                        #写入数据库
                        obj = models.Disk(**data_set)
                        obj.save()
                except Exception as e:

                    self.response_msg(‘error‘,‘ObjectCreationException‘,‘Object [disk] %s‘ % str(e))
        else:
            self.response_msg(‘error‘,‘LacOfData‘,‘Disk info is not provied in your reporting data‘)
    def _create_nic_component(self):
        ‘‘‘
        创建网卡,同硬盘
        :return:
        ‘‘‘
        nic_info = self.clean_data.get(‘nic‘)
        if nic_info:
            for nic_item in nic_info:
                try:
                    self._verify_field(nic_item,‘macaddress‘,str)
                    if not len(self.response[‘error‘]):
                        data_set = {
                            ‘asset_id‘ : self.asset_obj.id,
                            ‘name‘ : nic_item.get(‘name‘),
                            ‘sn‘ : nic_item.get(‘sn‘),
                            ‘macaddress‘ : nic_item.get(‘macaddress‘),
                            ‘ipaddress‘ : nic_item.get(‘ipaddress‘),
                            ‘bonding‘ : nic_item.get(‘bonding‘),
                            ‘model‘ : nic_item.get(‘model‘),
                            ‘netmask‘ : nic_item.get(‘netmask‘),
                        }
                        obj = models.NIC(**data_set)
                        obj.save()
                except Exception as e :
                    self.response_msg(‘error‘,‘ObjectCreationException‘,‘Object [nic] %s‘ % str(e) )
        else:
            self.response_msg(‘error‘,‘LackOfData‘,‘NIC info is not provied in your reporting data‘ )

    def _create_ram_component(self):
        ‘‘‘
        创建内存,同硬盘
        :return:
        ‘‘‘
        ram_info = self.clean_data.get(‘ram‘)
        if ram_info:
            for ram_item in ram_info:
                try:
                    self._verify_field(ram_item,‘capacity‘,int)
                    if not len(self.response[‘error‘]):
                        data_set = {
                            ‘asset_id‘ : self.asset_obj.id,
                            ‘slot‘ : ram_item.get(‘slot‘),
                            ‘sn‘ : ram_item.get(‘sn‘),
                            ‘capacity‘ : ram_item.get(‘capacity‘),
                            ‘model‘ : ram_item.get(‘model‘),
                        }
                        obj = models.RAM(**data_set)
                        obj.save()
                except Exception as e:
                    self.response_msg(‘error‘,‘ObjectCreationException‘,‘Object [ram] %s‘ % str(e))
        else:
            self.response_msg(‘error‘,‘LackOfData‘,‘RAM info is not provied in your reporting data‘)
    def _update_server_component(self):
        update_fields = [‘model‘,‘raid_type‘,‘os_type‘,‘os_distribution‘,‘os_release‘]
        if hasattr(self.asset_obj,‘server‘):
            self._compare_componet(
                model_obj = self.asset_obj.server,
                fields_from_db = update_fields,
                data_source = self.clean_data,
            )
        else:
            self._create_server_info(ignore_errs=True)
    def _update_manufactory_component(self):
        self._create_or_update_manufactory(ignore_errs=True)
    def _update_cpu_component(self):
        update_fields = [‘cpu_model‘,‘cpu_count‘,‘cpu_core_count‘]
        if hasattr(self.asset_obj,‘cpu‘):
            self._compare_componet(
                model_obj = self.asset_obj.cpu,
                fields_from_db = update_fields,
                data_source = self.clean_data,
            )
        else:
            self._create_cpu_component(ignore_errs=True)

    def _update_asset_component(self,data_source,fk,update_fields,identify_field=None):
        ‘‘‘
        通用的更新做对比的方法
        :param data_source: 客户端数据源,网卡列表之类的
        :param fk:  告诉函数比什么类型资产
        :param update_fields: 比什么字段
        :param identify_field: 在数据库中用什么字段去查询
        :return:
        ‘‘‘
        try:
            #取到资产的关联字段,类似于models.Asset.objects.all()[0].nic_set
            component_obj = getattr(self.asset_obj,fk)
            if hasattr(component_obj,‘select_related‘):
                #取到资产的反向关联对象,如models.Asset.objects.all()[0].nic_set.select_related
                objects_from_db = component_obj.select_related()
                #遍历取到的列表对象
                for obj in objects_from_db:
                    #取到数据库中的唯一值,如mac地址的值
                    key_field_data = getattr(obj,identify_field)
                    # if type(data_source) is list:
                    #遍历客户端传过来的数据列表
                    for source_data_item in data_source:
                        #找到客户端传过来的数据中identify_field对应的值,如mac地址
                        key_field_data_from_source_data = source_data_item.get(identify_field)
                        #如果上述值存在
                        if key_field_data_from_source_data:
                            #如果数据库中的唯一值和客户端的相等代表匹配上了,应该比对数据库中的值和客户端的值是否一致
                            if key_field_data == key_field_data_from_source_data:
                                self._compare_componet(
                                    model_obj = obj,
                                    fields_from_db = update_fields,
                                    data_source = source_data_item,
                                )
                                break
                        else:
                            self.response_msg(‘warning‘,‘AssetUpdateWarning‘,"Asset component [%s]‘s key field [%s] is not provided in reporting data " % (fk,identify_field))
                    else:
                        self.response_msg(‘warning‘,‘AssetUpdateWarning‘,"Cannot find any matches in source data by using key field val [%s],component data is missing in reporting data!" %(key_field_data))
                    # elif type(data_source) is dict:
                    #     for key,source_data_item in data_source.items():
                    #         key_field_data_from_source_data = source_data_item.get(identify_field)
                    #         if key_field_data_from_source_data:
                    #             if key_field_data == key_field_data_from_source_data:
                    #                 self._compare_componet(
                    #                     model_obj = obj,
                    #                     fields_from_db=update_fields,
                    #                     data_source = source_data_item,
                    #                 )
                    #                 break
                    #         else:
                    #             self.response_msg(‘warning‘,‘AssetUpdateWarning‘,"Asset component [%s]‘s key field [%s] is not provided in reporting data " % (fk,identify_field))
                    #     else:
                    #         print(‘\033[33;1mWarning:cannot find any matches in source data by using key field val [%s],component data is missing in reporting data!\033[0m‘ %(key_field_data))
                    # else:
                    #     print(‘\033[31;1mMust be sth wrong,logic should not  goes to here at all.\033[0m‘)
                #添加或删除的资产
                self._filter_add_or_deleted_components(
                    #表名,如:NIC
                    model_obj_name=component_obj.model._meta.object_name,
                    #数据库中的数据
                    data_from_db=objects_from_db,
                    #客户端数据
                    data_source=data_source,
                    #关键key
                    identify_field=identify_field,
                )
            else:
                pass
        except ValueError as e:
            print(‘\033[41;1m%s\033[0m‘ % str(e))
    def _filter_add_or_deleted_components(self,model_obj_name,data_from_db,data_source,identify_field):
        #客户端所有的数据列表,如mac地址列表
        data_source_key_list = []
        #遍历客户端数据列表
        for data in data_source:
            #将客户端的数据添加进客户端数据列表中,如网卡中的mac地址
            data_source_key_list.append(data.get(identify_field))
        #将客户端的数据列表变成集合
        data_source_key_list = set(data_source_key_list)
        #将数据库中的数据列表变成集合,如mac地址集合
        data_identify_val_from_db = set([getattr(obj,identify_field) for obj in data_from_db])
        #只在数据库中的数据
        data_only_in_db = data_identify_val_from_db-data_source_key_list
        #只在客户端中的数据
        data_only_in_data_source = data_source_key_list - data_identify_val_from_db
        #只在数据库中的数据应该删除
        self._delete_components(all_components = data_from_db,delete_list = data_only_in_db, identify_field=identify_field)
        #只在数据库中的数据如果存在,应该添加
        if data_only_in_data_source:
            self._add_components(model_obj_name=model_obj_name,all_components=data_source, add_list = data_only_in_data_source, identify_field=identify_field)
    def _add_components(self,model_obj_name,all_components,add_list,identify_field):
        ‘‘‘
        添加资产记录
        :param model_obj_name: 数据库表名,如NIC
        :param all_components: 所有的资产对象,客户端的资产对象,如nic_obj1,如nic_obj2
        :param add_list: 添加列表
        :param identify_field:
        :return:
        ‘‘‘
        #获取表结构的类,如models.NIC
        model_class = getattr(models,model_obj_name)
        #将要添加数据列表,如[mac1,mac2]
        will_be_creating_list = []
        #遍历所有的资产
        for data in all_components:
            #判断资产在不在添加列表中
            if data[identify_field] in add_list:
                #在添加列表中就放入添加数据列表
                will_be_creating_list.append(data)
        try:
            #遍历在添加列表中就放入添加数据列表
            for component in will_be_creating_list:
                #创建数据的字典
                data_set = {}
                #要创建的字段,每一个表时不一样的
                for field in model_class.auto_create_fields:
                    #将客户端的数据写入data_set
                    data_set[field] = component.get(field)
                #写入到哪个资产中
                data_set[‘asset_id‘] = self.asset_obj.id
                #写入数据库
                obj = model_class(**data_set)
                obj.save()
                log_msg = "Asset[%s] --> component[%s] has justed added a new item [%s]" %(self.asset_obj,model_obj_name,data_set)
                self.response_msg(‘info‘,‘NewComponentAdded‘,log_msg)
                #写入日志
                log_handler(self.asset_obj,‘NewComponentAdded‘,self.request.user,log_msg,model_obj_name)
        except Exception as e:
            log_msg = "Asset[%s] --> component[%s] has error: %s" %(self.asset_obj,model_obj_name,str(e))
            self.response_msg(‘error‘,"AddingComponentException",log_msg)
    def _delete_components(self,all_components,delete_list,identify_field):
        ‘‘‘
        删除资产函数
        :param all_components: 所有的资产对象,数据库的资产对象,如nic_obj1,如nic_obj2
        :param delete_list: 要删除的唯一数据列表
        :param identify_field:
        :return:
        ‘‘‘
        #要删除的资产对象列表
        deleting_obj_list = []
        for obj in all_components:
            val = getattr(obj,identify_field) #取出数据库中的值,如mac地址
            if val in delete_list:  #如[mac1,mac2]
                deleting_obj_list.append(obj) #添加的删除对象列表中
        #遍历删除列表并删除
        for i in deleting_obj_list:
            log_msg = "Asset[%s] --> component[%s] --> is lacking from reporting source data, assume it has been removed or replaced,will also delete it from DB" %(self.asset_obj,i)
            self.response_msg(‘info‘,‘HardwareChanges‘,log_msg)
            #添加到日志中
            log_handler(self.asset_obj,‘HardwareChanges‘,self.request.user,log_msg,i)
            i.delete()
    def _compare_componet(self,model_obj,fields_from_db,data_source):
        ‘‘‘
        比较客户端字段和数据库的字段
        :param model_obj: 数据库中的一个对象,如nic的对象
        :param fields_from_db: 数据库中要比较的字段
        :param data_source:  客户端具体的一块网卡的数据,如一块网卡的数据
        :return:
        ‘‘‘
        #遍历要检测的字段
        for field in fields_from_db:
            #数据库中的数据
            val_from_db = getattr(model_obj,field)
            #取出客户端的数据
            val_from_data_source = data_source.get(field)
            #确认客户端数据存在
            if val_from_data_source:
                #转换数据格式,和数据库中的一致
                if type(val_from_db) in (int,):val_from_data_source = int(val_from_data_source)
                elif type(val_from_db) is float:val_from_data_source = float(val_from_data_source)
                #相等不做任何变化
                if val_from_db == val_from_data_source:
                    pass
                else:
                    #获取字段对象
                    db_field = model_obj._meta.get_field(field)
                    #修改数据
                    db_field.save_form_data(model_obj,val_from_data_source)
                    model_obj.update_date = timezone.now()
                    #保存
                    model_obj.save()
                    log_msg = "Asset[%s] --> component[%s] --> field[%s] has changed from [%s] to [%s]" %(self.asset_obj,model_obj,field,val_from_db,val_from_data_source)
                    self.response_msg(‘info‘,‘FieldChanged‘,log_msg)
                    #日志记录
                    log_handler(self.asset_obj,‘FieldChanged‘,self.request.user,log_msg,model_obj)
            else:
                self.response_msg(‘warning‘,‘AssetUpdateWarning‘,"Asset component [%s]‘s field [%s] is not provided in reporting data " % (model_obj,field))
        model_obj.save()
def log_handler(asset_obj,event_name,user,detail,component=None):

    log_catelog = {
        1 : [‘FieldChanged‘,‘HardwareChanges‘],
        2 : [‘NewComponentAdded‘],
    }
    if not user.id:
        user = models.UserProfile.objects.filter(is_admin=True).last()
    event_type = None
    for k,v in log_catelog.items():
        if event_name in v:
            event_type = k
            break
    log_obj = models.EventLog(
        name = event_name,
        event_type = event_type,
        asset_id = asset_obj.id,
        component = component,
        detail = detail,
        user_id = user.id
    )
    log_obj.save()

来自为知笔记(Wiz)

时间: 2024-10-16 14:55:12

CMDB的相关文章

CMDB开发

浅谈ITIL TIL即IT基础架构库(Information Technology Infrastructure Library, ITIL,信息技术基础架构库)由英国政府部门CCTA(Central Computing and Telecommunications Agency)在20世纪80年代末制订,现由英国商务部OGC(Office of Government Commerce)负责管理,主要适用于IT服务管理(ITSM).ITIL为企业的IT服务管理实践提供了一个客观.严谨.可量化的标

CMDB专家实践谈:自动化运维的基石CMDB

CMDB是什么? 运维百花齐放繁荣景象的同时,也让碎片化问题产生:每个人都想整合运维平台,但是往往事与愿违. CMDB就像一个人的大脑核心,是一个信息协调库,其存储的资料是协调身体完成各种复杂运动的信息来源. 我心中的CMDB .碎片整合 面向运维工具的碎片化场景,是盘活整个运维管理的数据核心 .元数据库 提供运维活动的基础元数据,是唯一可信的运维配置数据服务 .场景驱动 为运维联动提供数据驱动,可协调工具来完成各类自动化场景 自动扩容+自动监控 CMDB如何建设? 痛点现象与对策I模型建不好

cmdb项目1

CMDB项目 需求: 1.ip地址 2.mac地址 3. 1.查看Linux硬件基础信息 1.查看cpu       cat/proc/cpuinfo (1)processor:包括这一逻辑处理器的唯一标识符. (2)physical id :包括每个物理封装的唯一标识符. (3)core id :保存每个内核的唯一标识符. (4)siblings :列出了位于相同物理封装中的逻辑处理器的数量. (5)cpu cores :包含位于相同物理封装中的内核数量. (6)如果处理器为英特尔处理器,则v

CMDB内功心法,助我登上运维之巅

很多70.80后甚至90后都在金庸.古龙.梁羽生先生等武林大家熏陶下成长的,这么多年过去了,我的武侠梦依然不曾散去.曾几何,梦想有一天练就一身绝学,搂着小师妹花前月下,仗剑走天涯,快意人生.可每次的酣睡美梦都被班主任大书板子给抽醒,在他们的鞭策之下,浑浑噩噩的成了一位IT骚年.我们都知道武功分为内功和招式,内功是气,而招式是形,以气御形.内功深厚,会让你的招式如虎添翼.势如破竹:内功不济,招式也是花拳绣腿.苍白乏力.同样光有内力而无招式的延展,也仅仅是一只呆头鹅.所以内力和招式相辅相成,相得益彰

Python CMDB开发

Python CMDB开发 运维自动化路线: cmdb的开发需要包含三部分功能: 采集硬件数据 API 页面管理 执行流程:服务器的客户端采集硬件数据,然后将硬件信息发送到API,API负责将获取到的数据保存到数据库中,后台管理程序负责对服务器信息的配置和展示. 采集硬件信息 采集硬件信息可以有两种方式实现: 利用puppet中的report功能 自己写agent,定时执行 两种方式的优缺点各异:方式一,优点是不需要在每台服务器上步一个agent,缺点是依赖于puppet,并且使用ruby开发:

CMDB机柜平台结合zabbix告警展示

最近看了刘天斯老师的机柜展示平台,非常绚丽,而且有大屏显示的话也是能够体现运维价值的,这里就说下我最近在做的CMDB平台的一些数据: CMDB数据: 机房,机柜,机柜电源,机柜位置,机房合同,合同到期时间,机房联系人. 服务器,CPU,硬盘,是否虚拟化,宿主机,raid类型,内存. 资产ID,上架日期,下架记录,服务器代理商,代理商联系方式,服务器到保日期. IP地址,MAC地址,业务线,产品线,操作系统. 通信这块主要技术json-rpc,然后提供Api接口给程序调用,按照固定格式导入即可:硬

CMDB反思3

CMDB模型设计1 http://blog.vsharing.com/xqscool/A1274634.html 分类的问题上比较有感悟.在之前编写新版的CMDB模型的时候,曾将刀片机.x86服务器.小型机等统一归为服务器,通过架构和机箱(刀片.机架.立式,好像是这三种)区分.由于使用的是SD,而且到我那一期时字段剩余的不多,为了方便统计和展示,才出此下策——不过当时感觉很好哈,终于一统天下了,不过也是无奈的选择. 如果分类在存储和展示上都能够自定义而且有足够的空间的话,确实如破子所说,分类是不

ansible通过cmdb资产接口动态创建hosts列表

前言: 在自动化.批量化操作主机的时候,有时候咱们需要定义主机组. 比如,saltstack的group组,及salt -N参数 ,在ansible下的自己搞定ansible的主机组.有些麻烦,要知道,你既然选择了用saltstack.ansible这类的集群操作工具,如果你再选择把几十个多到几百个手动地,一个个地把主机组及相关联的主机写入配置,是不是显得很1+1. 这里简单说下我的一些个方法,首先可以避免这些个配置的写入,在产生minion的id的时候,就给他一个完美又规范的主机域名. 比如,

优云CMDB经验分享之 – 剖析CMDB的设计过程

作为IT管理的核心,CMDB逐渐成为系统管理项目实施的热点.在很多的案例中,由于忽视了CMDB的因素,ITIL的深入应用受到了极大的挑战.同时,由于CMDB是IT管理信息的集中,CMDB也是一个重要的工具和手段. 在CMDB落地过程中需要注意的是,CMDB项目不是一个简单的软件安装过程,而是一个咨询.培训.实施.优化密切结合的综合过程,涉及到平台工具采购.咨询服务.实施服务.培训.甚至扩展开发等内容.同时,一个成功的CMDB项目不能一蹴而就,而是一个循序渐进.持续发展的过程,需要企业后续的投入和

如何让CMDB配置维护更贴近人性

近来很多行业内的大佬关于CMDB连连发声,CMDB的关注度持续高涨,CMDB的前生就是长满雀斑的丑媳妇,扭扭捏捏不受待见这么多年,终于熬出头要见公婆了.哎,她的贤惠谁能懂? 言归正传,在拜读了多篇大牛的文章发现,提及配置维护的内容很少,有也是一带而过.但在过去和用户的接触过程中,发现配置维护一直是一个无法回避的大难题,一块难啃的骨头.业界产品的普遍做法主要是依靠自动发现+人工维护+流程控制.对于自动发现.流程控制,我想只能解决配置维护的60%的工作,真正出现问题的是占用40%工作量的人工维护.由