运维前线:一线运维专家的运维方法、技巧与实践2.5 使用Django快速构建CMDB系统

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

2.5 使用Django快速构建CMDB系统


2.5.1 Django介绍

Django是一个免费的、开源的Web框架,由Python语言编写,由于其是在一个快节奏的新闻编译室环境中开发出来的,因此它的设计目的是让普通开发者的工作变得简单。Django遵循模型-视图-控制器(MVC)框架模式,目前由一个非盈利的独立组织的软件基金会(DSF)维持。

Django鼓励快速开发和干净实用的设计。Django可以更容易更快速地构建更好的Web应用程序。它是由经验丰富的开发人员来创建的,省去了Web开发的很多麻烦,因此你可以专注地开发应用程序而不需要去白费力气地重复工作。

Django目前已经被运维圈广泛使用,本文在此不会详细介绍Django的基础知识,有兴趣的朋友可以去Django官网查看更为详细的介绍,同时也有Django中文文档可供学习。

2.5.2 Django安装

Django的安装分为4个步骤,下面以Django 1.7.1、CentOS 6.5 x86_64为例进行讲解,详细步骤如下。

1.?安装Python 2.7.x

用CentOS 7以下版本的朋友需要将Python升级到2.7.x以上,Django对Python版本存在依赖,具体如图2-7所示。

编译步骤如下:

# yum install -y zlib-dev openssl-devel sqlite-devel bzip2-devel

# wget http://www.python.org/ftp/python/2.7.6/Python-2.7.6.tgz

# tar zxf Python-2.7.6.tgz

# cd Python-2.7.6

# ./configure --prefix=/usr/local

# make && make altinstall

(1)安装easy_install工具,操作命令如下:

$ wget https://bootstrap.pypa.io/ez_setup.py -O -| python

(2)安装Django,使用easy_install来安装,安装的版本为1.7.1,具体命令如下:

$ easy_install django==1.7.1

(3)测试Django的安装,操作命令如下:

$ easy_install django==1.7.1

$ django-admin –version

1.7.1

2.?MySQL安装

本文推荐使用yum命令进行安装,并设置MySQL root密码,创建cmdbtest数据库,具体安装步骤如下:

$ yum -y install mysql mysql-server

$ mysql_install_db --user=mysql

$ /etc/init.d/mysqld start

$ mysqladmin -u root password 'cmdbtest'

$ mysql -u root -pcmdbtest -e 'create database if not exists cmdbtest'

2.5.3 Django常用命令

完成Django的安装后,可以通过如下命令快速熟悉Django的操作,以便快速创建一个CMDB App,如果你对如下这些Django命令很熟悉,可以直接跳过。

(1)新建一个django-project:

$ django-admin startproject project-name

(2)新建App:

$ django-admin startapp app-name

(3)同步数据库:

$ python manage.py syncdb

(4)启动Django服务器:

$ python manage.py runserver

(5)Django Shell调试:

$ python manage.py shell

(6)帮助:

$ django-admin --help

$ python manage.py --help

2.5.4 Django的配置

1.?环境准备

笔者准备了两台测试机器用来进行代码测试,测试机器的环境信息分别如下。

(1)服务端机器信息:

IP: 10.20.122.100

Role: puppet server + cmdb

System OS: CentOS release 6.5 x86_64

Python version: 2.7.8 Django version: 1.7.1

Mysql version: 5.1.73

(2)客户端机器信息:

IP: 10.20.122.111

Role: puppet agent

System OS: CentOS release 6.5 x86_64

2.?软件安装

前几节已经对所需要的环境进行了安装,在这里我们再回顾一下:

(1)master安装Puppet Server。

(2)master安装Python。

(3)master安装MySQL。

(4)master安装Django。

(5)master安装项目依赖的Python模块。

(6)Agent安装Puppet Agent。

3.?创建CMDB项目

创建CMDB项目的同时,在这个项目中创建一个CMDB App,登录10.20.122.100,运行如下命令。

(1)创建一个Project:

$ django-admin startproject myproject

(2)进入myproject目录:

$ cd myproject

(3)创建一个CMDB App:

$ django-admin startapp cmdb

(4)创建一个存放静态文件和模板的目录:

$ mkdir static templates

运行成功后使用11命令就可以看到如图2-8所示的目录结构。

4.?配置CMDB项目信息

在图2-8中我们可以在myproject目录下看到settings.py的全局配置文件,Django在运行时会默认先加载此配置文件,因此我们需要先对它进行定义,需要配置如下6个地方,操作步骤具体如下。

(1)修改数据库设置:

DATABASES = {

'default': { 'ENGINE': 'django.db.backends.mysql',

'NAME': 'cmdbtest',

'HOST': 'localhost',

'USER': 'root',

'PASSWORD': 'cmdbtest',

'PORT': '3306',

'OPTIONS': {'init_command': 'SET storage_engine=INNODB', 'charset': 'utf8', }

} }

(2)设置App,把我们新建的CMDB App加到末尾,代码如下:

NSTALLED_APPS = ('django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles', 'cmdb',

)

(3)设置静态文件存放目录:

STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static/'), )

(4)设置模板文件存放目录:

TEMPLATE_DIRS = [ os.path.join(BASE_DIR, 'templates'), ]

(5)设置登录URL:

LOGIN_URL = '/cmdb/login/'

(6)设置其他参数,可以根据自己的需求进行设置:

TEMPLATE_CONTEXT_PROCESSORS = ( 'django.core.context_processors.static', 'cmdb.context_processors.menu', "django.contrib.auth.context_processors.auth", "django.core.context_processors.request",

) CMDB_VERSION = '1.0' CMDB_NAME = u'测试 CMDB' LOGIN_REDIRECT_URL = '/home/'

到此为止基础环境已经准备完毕,接下来需要设计数据库,并定义好视图。

5.?数据表设计

Django遵循MVC设计,其中M(模型)就是数据库模型,也就是App中的models.py文件的设置,Django自带数据库的ORM(Object Relational Mapping)架构,这使得我们不用再需要学习复杂的数据库操作,只需要通过定义models即可。下面是我设置的最简单的CMDB数据结构:

# 指定解析器为Python

# !/usr/bin/env python

# 指定字符编码为utf8

# encoding:utf8

# 从django.db中导入models模块

from django.db import models

# 导入User模块

from django.contrib.auth.models import User

# Create your models here.

# 定义一个Server_Group类,从models.Model中继承,这里就是所谓的数据表结构

class Server_Group(models.Model):

    # 定义主机组名称字段

    name = models.CharField(u'主机组', max_length=255, unique=True)

    # 关联的项目字段,这里是关联一个外键

    project = models.ForeignKey("Project", verbose_name='项目名称')

    # 备注字段

    memo = models.CharField(u'备注', max_length=255, blank=True)

    # unicode返回值

    def __unicode__(self):

        # 返回的格式

        return '%s-%s' % (self.project.name, self.name)

 

    # 定义Meta属性

    class Meta:

        # 数据库中的表名

        db_table = 'server_group'

        # 存储的时候需要确认组合键是唯一的

        unique_together = (("name", "project"),)

 

# 定义一个IDC类,主要存储IDC信息,数据表结构有2个字段

class IDC(models.Model):

    # 定义IDC的名称字段

    name = models.CharField(u'IDC名称', max_length=255, unique=True)

    memo = models.CharField(u'备注', max_length=255, blank=True)

 

    def __unicode__(self):

        return self.name

 

    class Meta:

        db_table = 'idc'

 

# 定义一个Project类,主要存储项目信息,数据表结构有2个字段

class Project(models.Model):

    name = models.CharField(u'项目名称', max_length=255, unique=True)

    memo = models.CharField(u'备注', max_length=255, blank=True)

 

    def __unicode__(self):

        return self.name

 

    class Meta:

        db_table = 'project'

 

# 定义一个Server_Role类,主要存储服务器角色信息,数据表结构有3个字段

class Server_Role(models.Model):

    name = models.CharField(u'角色', max_length=255)

    # 关联Server_Group,也就是服务器组

    group = models.ForeignKey("Server_Group", verbose_name='项目组')

    memo = models.CharField(u'备注', max_length=255, blank=True)

 

    def __unicode__(self):

        return '%s-%s-%s' % (self.group.project.name, self.group.name, self.name)

 

    class Meta:

        # 设置数据库表名

        db_table = 'server_role'

        # 存储的时候需要确认组合键是唯一的

        unique_together = (("name", "group"),)

 

 

# CMDB核心数据表结构,用来存储服务器系统信息

class Server_Device(models.Model):

    # 服务器状态选择,具体的字段存储数据为0~3的int数字

    SERVER_STATUS = (

        (0, u'下线'),

        (1, u'在线'),

        (2, u'待上线'),

        (3, u'测试'),

    )

    # 定义一个名称字段,若blank没有设置则默认为False,不能为空,且unique=True必须唯一

    name = models.CharField(u'主机名称', max_length=100, unique=True)

    # 定义SN编号字段, blank=True,可以为空

    sn = models.CharField(u'SN号', max_length=200, blank=True)

    # 公网IP字段,可以为空

    public_ip = models.CharField(u'外网IP', max_length=200, blank=True)

    # 私网IP字段,可以为空

    private_ip = models.CharField(u'内网IP', max_length=200, blank=True)

    # 定义MAC地址字段

    mac = models.CharField(u'MAC地址', max_length=200, blank=True)

    # 定义操作系统字段

    os = models.CharField(u'操作系统', max_length=200, blank=True)

   # 定义磁盘信息字段

    disk = models.CharField(u'磁盘', max_length=200, blank=True)

    # 定义内存信息字段

    mem = models.CharField(u'内存', max_length=200, blank=True)

    # 定义CPU信息字段

    cpu = models.CharField(u'CPU', max_length=200, blank=True)

    # 关联IDC信息

    idc = models.ForeignKey(IDC, max_length=255, blank=True, null=True, verbose_

    name='机房名称')

    # 定义一个多对多字段,一台服务器可以对应多个角色

    role = models.ManyToManyField("Server_Role", verbose_name='角色', blank=True)

    # 机器状态,默认都为在线状态

    status = models.SmallIntegerField(verbose_name='机器状态', choices=SERVER_STATUS,

    default=1)

    # 管理用户信息

    admin = models.ForeignKey('auth.User', verbose_name='管理员', null=True, blank=True)

    # 定义备注字段

    memo = models.CharField(u'备注', max_length=200, blank=True)

 

    def __unicode__(self):

        return self.name

 

    class Meta:

        db_table = 'server_device'

初始化数据库,同时设置登录所需要的username和password,命令如下:

$ python manage.py syncdb

Operations to perform:

Apply all migrations: admin, contenttypes, auth, sessions

Running migrations:

Applying contenttypes.0001_initial... OK

Applying auth.0001_initial... OK

Applying admin.0001_initial... OK

Applying sessions.0001_initial... OK

You have installed Django's auth system, and don't have any superusers defined.

Would you like to create one now? (yes/no): yes

# 这里输入用户名

Username (leave blank to use 'root'): admin

Email address:

# 这里输入密码

Password:

# 重复输入密码

Password (again):

Superuser created successfully.

在命令行登录数据库,并查看数据库信息,就能看到如图2-9所示的内容,说明数据库已创建成功。

6.?视图设置

上文中我们已经成功设置了Django的M(Models,模型),下面我们来设置V(View,视图),如下代码是一个登出页面和一个home页面的View:

# encoding:utf8

# Create your views here.

# 导入需要使用的模块

from django.template import RequestContext

from django.shortcuts import render_to_response

from django.contrib.auth.decorators import login_required

from django.contrib.auth.views import logout_then_login

# 判断用户是否登录

@login_required

# 登出时的调用

def logout_view(request):

    return logout_then_login(request)

# 判断用户是否登录

@login_required

# 登录后调用home页所展示的页面,template为home.html

def home(request):

    return render_to_response('home.html', locals(), context_instance=RequestCo

    ntext(request))

 

URL设置(这里直接使用了Django自带的login函数,所以不需要自己写login view):

# 设置字符编码

# encoding:utf8

# 从urls中导入patterns、include、url模块

from django.conf.urls import patterns, include, url

# 从contrib中导入admin模块

from django.contrib import admin

# 从http中导入HttpResponseRedirect模块

from django.http import HttpResponseRedirect

 

# 设置前端访问的URL对应的后端视图

urlpatterns = patterns('',

                     # url什么参数都不带时,直接重定向到login

                       url(r'^$', lambda x: HttpResponseRedirect('/login/')),

                     # 登出对应的视图为cmdb.views.logout_view

                         url(r'^logout/$','cmdb.views.logout_view', name='cmdb_logout'),

                     # 登录对应的view为django.contrib.auth.views.login,对应的

                           template为login.html

                       url(r'^login/$','django.contrib.auth.views.login', {'template_

                       name': 'login.html'},

                           name='cmdb_login'),

                     # home页面,对应的view为cmdb.views.home

                       url(r'^home/$', 'cmdb.views.home', name='home'),

)

通过如上定义,现在就启动Django服务,登录后即可看到如图2-10所示的界面。代码已托管至Github网站https://github.com/oysterclub/open-cmdb,有兴趣的朋友可以去复制下来查看、修改或使用。下面就来展示一下登录界面的效果图(注,前端框架为bootstrap)。

利用python manage.py syncdb命令输入的用户名和密码登录。登录后的页面为home空白页(见图2-11),具体如下(home空白页主要是为了以后做导向流页面或数据图表展示页面,这里先留空):

 

图2-11 系统登录后的界面

7.?使用Python程序获取Facts数据

通过如上定义,我们已经完成了视图、数据表结构的定义。而数据的来源既可以通过添加,也可以通过Facter工具来获取。下面我们就来讲讲如何自动获取Agent机器的系统数据(如果想要充分了解Facter工具,可以参考阅读《Puppet实战》的第9章“Facter介绍”)。Facter工具会在Puppet Agent与Puppet Master通信的时候把获取到的Agent主机系统信息和自己定义的Facts信息汇报给Puppet Master,生成一个hostname.yaml格式的文件,文件存放在/var/lib/puppet/yaml/facts目录下,文件的格式如图2-12所示,其中的values数据:domain、ipaddress、macaddress等正是构建CMDB所需要的系统数据,因此我们可以通过一个Python程序来处理这些数据,并录入MySQL中,最终通过Django来实现前端展示。因此一个最简单的CMDB系统就构建完成了。

 

图2-12 Facter上报至Puppet Master后的yaml部分信息

我们先来具体看一下facter_message.py程序(Python程序处理Facter数据),完整代码如下:

#!/usr/bin/env python

# encoding: utf8

__authors__ = ['liuyu', 'chenlijun']

__version__ = 1.0

__date__ = '2015-09-06 14:58:23'

__licence__ = 'GPL licence'

 

# 导入模块

import yaml

import os

# IPy主要用来判断IP类型,IPy.IP('ip').iptype()

import IPy

 

# yaml文件目录

yaml_dir = '/var/lib/puppet/yaml/facts'

 

# 结果集,结果集的格式{'cmdb_agent':()}

all_host_facter_message = {}

 

# 结果列表

result_list = ['name',

               'SN',

               'public_ip',

               'private_ip',

               'mac',

               'os',

               'disk',

               'mem',

               'cpu',

               'idc',

               'role',

               'status',

               'admin',

               'memo']

 

# db对应的Facter字段,需要获取其他的字段时可以一一对应

list_field = {'name': 'fqdn',

              'public_ip': 'ipaddress__interfaces',

              'private_ip': 'ipaddress__interfaces',

              'mac': 'macaddress__interfaces',

              'os': ['operatingsystem', 'operatingsystemrelease', 'hardwaremodel'],

              'disk': 'blockdevice__blockdevices',

              'mem': 'memorysize',

              'cpu': ['processorcount', 'processor0']}

 

# ruby objectobjectconstruct

def construct_ruby_object(loader, suffix, node):

    return loader.construct_yaml_map(node)

 

def construct_ruby_sym(loader, node):

    return loader.construct_yaml_str(node)

 

# 读取数据

def yaml_file_handle(filename):

    stream = open(filename)

    mydata = yaml.load(stream)

    return mydata

 

# 获取IP的类型

def get_ip_type(ip):

    try:

        return IPy.IP(ip).iptype().lower()

    except Exception, e:

        print e

 

# 处理单个Agent的数据

def handle_facter_message(data):

    # 定义一个结果字典,字段和db一样,处理完的结果和db中的一样

    result_dict = {}

    # 对结果进行处理

    for db_field in result_list:

        # 定义一个字段结果字符

        value = ''

        # result_list中的字段是否存在于我们需要的Facter取值列表中,如果存在

        if db_field in list_field:

            facter_field = list_field[db_field]

            # 先判断facter_field的类型,然后进行处理

            if type(facter_field) == type([]):

                for tag in facter_field:

                    if data.get(tag):

                        value += data[tag] + ' '

            else:

                # 由于disk、IP等需要进一步处理,所以用了一个__来分隔,然后再进行处理

                field_tmp = facter_field.split("__")

                if len(field_tmp) == 2:

                    if db_field == 'disk':

                        for tag in data[field_tmp[1]].split(","):

                            # 对磁盘进行处理, 由于磁盘的字段为blockdevice_type_size,

                                  所以需要单独进行处理

                            f = field_tmp[0] + '_' + tag + '_' + 'size'

                            if data.get(f):

                                # 去除sr0 tag的字段

                                if tag != 'sr0':

                                    # 结果字符串

                                    value += tag + ':' + str(int(data[f]) / 1024 /

                                    1024 / 1024) + 'G' + ' '

                    # 对外网IP进行处理

                    elif db_field == 'public_ip':

                        for tag in data[field_tmp[1]].split(","):

                            f = field_tmp[0] + '_' + tag

                            if data.get(f):

                                # 去除lo tag的字段

                                if tag != 'lo':

                                    if get_ip_type(data[f]) == 'public':

                                        # 结果字符串

                                        value += data[f] + ' '

                    # 对内外IP进行处理

                    elif db_field == 'private_ip':

                        for tag in data[field_tmp[1]].split(","):

                            f = field_tmp[0] + '_' + tag

                            if data.get(f):

                                # 去除lo tag的字段

                                if tag != 'lo':

                                    if get_ip_type(data[f]) == 'private':

                                        # 结果字符串

                                        value += data[f] + ' '

                    else:

                        # 其他的字段直接就处理了

                        for tag in data[field_tmp[1]].split(","):

                            f = field_tmp[0] + '_' + tag

                            if data.get(f):

                                # 去除lo tag的字段

                                if tag != 'lo':

                                    # 结果字符串

                                    value += tag + ':' + data[f] + ' '

                else:

                    if data.get(facter_field):

                        # 结果字符串

                        value = data[facter_field]

            # 将结果添加到result列表中

            result_dict[db_field] = value.strip()

        # 如果不存在

        else:

            result_dict[db_field] = ''

    # 返回结果字典

    return result_dict

 

# 定义获取facter的函数

def get_all_host_facter_message():

    # 由于Puppet的yaml文件是Ruby格式的,因此需要进行转换

    yaml.add_multi_constructor(u"!ruby/object:", construct_ruby_object)

    yaml.add_constructor(u"!ruby/sym", construct_ruby_sym)

    # 获取所有有Facter信息的主机文件名称

    for dirpath, dirnames, filenames in os.walk(yaml_dir):

        # 只需要处理yaml目录下以yaml结尾的文件

        if dirpath == yaml_dir:

            for file in filenames:

                file_name, file_ext = os.path.splitext(file)

                if file_ext == '.yaml':

                    host_yaml_path = yaml_dir + '/' + file

                    # 得到yaml文件的内容, 字典形式

                    host_yaml_result_dict = yaml_file_handle(host_yaml_path)

                    # 对单个Agent的数据进行处理

                    if host_yaml_result_dict:

                        # 由于有key为facts,所以可以直接查找facts key的值

                        if host_yaml_result_dict.has_key('facts'):

                            data_dict = host_yaml_result_dict['facts']['values']

                        # 没有的就直接取

                        else:

                            data_dict = host_yaml_result_dict['values']

 

                    # 现在就可以对data进行处理,获取我们所需要的数据了

                    result_dict = handle_facter_message(data_dict)

                    all_host_facter_message[file_name] = result_dict

    #返回我们最终的数据结果集

    return all_host_facter_message

以上程序可以过滤Facter中我们想要得到的Agent数据,运行facter_message.py程序,结果输出如下:

$ python facter_message.py

{'puppetclient.domain.com':

{'status': '',

'name': 'puppetclient.domain.com',

'mem': '1.83 GB',

'memo': '',

'idc': '',

'public_ip': '',

'admin': '',

'mac': 'eth0:00:1A:4A:25:E2:12 eth1:00:1A:4A:25:E2:13',

'role': '',

'private_ip': '10.20.122.111',

'disk': 'vda:20G vdb:30G',

'os': 'CentOS 6.5 x86_64',

'cpu': '2 Intel Core 2 Duo P9xxx (Penryn Class Core 2)',

'SN': ''}

}

到这里,我们能够看到facter_message.py得到的数据字段和models.py中数据结构的字段正好一样,下一步我们就可以直接将facter_message.py的数据导入到数据库中了,具体程序如下:

# 检测用户是否登录

@login_required

# 定义一个views,用来处理导入信息

def import_data(request, model):

    # 导入计数器

    import_num = 0

    # 查看model是否存在于定义的模板中

    if model in BASE_ADMIN:

        # 获取tag名称

        tag_name = BASE_ADMIN[model]['name']

        # 获取model名称

        model_name = BASE_ADMIN[model]['model']

        # 这里只处理server_device的导入信息

        if model == 'server_device':

            server_device_data = get_all_host_facter_message()

            # 进行数据入库处理

            for hostname, facter_message in server_device_data.items():

                # 主机名处理,判断facter_message中name key是否有值,

                if facter_message['name']:

                    # 如果有值,name就使用该值

                    name = facter_message['name']

                # 如果没有这个值

                else:

                    # 就使用hostname

                    name = hostname

                # 对于IDC信息、User信息、项目角色信息的处理都需要自己去写Facter插件,不

                       写的都为空,然后进行处理

                # IDC关联处理,如果facter_message中的idc key有值

                if facter_message['idc']:

                    # idc_name就为该值

                    idc_name = facter_message['idc']

                    # 同时处理该IDC信息是否存在于IDC表中,如果有则取出ID

                    if IDC.objects.filter(name=idc_name):

                        idc_id = IDC.objects.get(name=idc_name).id

                    # 如果没有,则进行保存,然后取出ID

                    else:

                        idc_sql = IDC(name=idc_name)

                        try:

                            idc_sql.save()

                            # 取出ID

                            idc_id = IDC.objects.get(name=idc_name).id

                        except Exception, e:

                            return e

                # 如果idc key没有值,则为None

                else:

                    idc_id = None

                # 管理员信息关联处理,如果用户存在则关联,不存在则跳过

                if facter_message['admin']:

                    admin_name = facter_message['admin']

                    # 如果用户存在User表中则取ID,若没有则为空

                    if User.objects.filter(username=admin_name):

                        user_id = User.objects.get(username=admin_name).id

                    else:

                        user_id = None

                # 没有就为空

                else:

                    user_id = None

                # 这里还有一个角色多对多关系的处理,由于这里没有定义机器角色,因此此处不处理

                      角色信息

                # 判断主机是否存在于server_device表中,如果不存在则添加

                if not model_name.objects.filter(name=name):

                    import_sql = model_name(name=name,

                                            sn=facter_message['sn'],

                                            public_ip=facter_message['public_ip'],

                                            private_ip=facter_message['private_ip'],

                                            mac=facter_message['mac'],

                                            idc=idc_id,

                                            os=facter_message['os'],

                                            disk=facter_message['disk'],

                                            mem=facter_message['mem'],

                                            cpu=facter_message['cpu'],

                                            admin=user_id,

                                            memo=facter_message['memo'],

                    )

                    try:

                        # 保存

                        import_sql.save()

                    except Exception, e:

                        return e

                # 如果有了,则查询数据,若信息不对则更新

                elif not model_name.objects.filter(name=name,

                    sn=facter_message['sn'],

                    public_ip=facter_message['public_ip'],

                    private_ip=facter_message['private_ip'],

                    mac=facter_message['mac'],

                    os=facter_message['os'],

                    disk=facter_message['disk'],

                    mem=facter_message['mem'],

                    cpu=facter_message['cpu'],

                    memo=facter_message['memo']):

                    try:

                        # 更新数据库

                            model_name.objects.filter(name=name).update(sn=

                            facter_message['sn'],

                            public_ip=facter_message['public_ip'],

                            private_ip=facter_message['private_ip'],

                            mac=facter_message['mac'],

                            os=facter_message['os'],

                            disk=facter_message['disk'],

                            mem=facter_message['mem'],

                            cpu=facter_message['cpu'],

                            memo=facter_message['memo'],

                        )

                    except Exception, e:

                        return e

                # 如果有了,且信息ok,则跳过

                else:

                    continue

        return HttpResponseRedirect('/cmdb/%s/show/' % model)

 

    return render_to_response('all_data_show.html', locals(), context_instance=RequestContext(request))

重新登录CMDB之后的页面,有一个导入主机的按钮,点击导入主机按钮,就可以自动导入通过Facter获取的Agent主机信息了,如图2-13所示。

我们还可以通过添加的方式来维护CMDB的内容,到目前为止我们已经完成了使用Python和Puppet来构建一个小型的、简单的CMDB系统。

CMDB是需要我们定期进行维护和更新的,因此它还需要提供历史查看、API等更实用的功能,为此在2.6节中我们将介绍一下Django提供的几个好用的功能模块。

 

图2-13 信息导入界面

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
运维 Linux Apache
Puppet 作为一款强大的自动化运维工具,被广泛应用于配置管理领域。通过定义资源的状态和关系,Puppet 能够确保系统始终处于期望的配置状态。
Puppet 作为一款强大的自动化运维工具,被广泛应用于配置管理领域。通过定义资源的状态和关系,Puppet 能够确保系统始终处于期望的配置状态。
73 3
|
2天前
|
数据采集 机器学习/深度学习 人工智能
基于AI的网络流量分析:构建智能化运维体系
基于AI的网络流量分析:构建智能化运维体系
33 13
|
1天前
|
Prometheus 运维 监控
Prometheus+Grafana+NodeExporter:构建出色的Linux监控解决方案,让你的运维更轻松
本文介绍如何使用 Prometheus + Grafana + Node Exporter 搭建 Linux 主机监控系统。Prometheus 负责收集和存储指标数据,Grafana 用于可视化展示,Node Exporter 则采集主机的性能数据。通过 Docker 容器化部署,简化安装配置过程。完成安装后,配置 Prometheus 抓取节点数据,并在 Grafana 中添加数据源及导入仪表盘模板,实现对 Linux 主机的全面监控。整个过程简单易行,帮助运维人员轻松掌握系统状态。
19 3
|
1月前
|
Python
Django 框架的路由系统
Django 框架的路由系统
45 6
|
1月前
|
SQL 监控 数据库
深入探索Django ORM:高效数据操作的秘诀与实践####
在当今的Web开发领域,提升数据访问层的效率是优化应用性能的关键。本文旨在通过剖析Django框架中的ORM(对象关系映射)机制,揭示其如何简化数据库交互,并探讨一系列高级技巧与策略,帮助开发者构建更高效、可维护的数据访问代码。我们不涉及安装步骤或基础概念,而是聚焦于实战经验分享,旨在为中高级开发者提供深度洞见。 ####
|
1月前
|
运维 监控
构建高效运维体系:从理论到实践
在当今快速发展的信息化时代,高效的运维体系是保障企业信息系统稳定运行的关键。本文旨在探讨如何构建一个高效、可靠的运维体系,通过分析当前运维面临的挑战,提出相应的解决策略,并结合实际案例,展示这些策略的实施效果。文章首先介绍了高效运维的重要性,接着分析了运维过程中常见的问题,然后详细阐述了构建高效运维体系的策略和步骤,最后通过一个实际案例来验证这些策略的有效性。
|
1月前
|
缓存 运维 监控
【运维必备知识】Linux系统平均负载与top、uptime命令详解
系统平均负载是衡量Linux服务器性能的关键指标之一。通过使用 `top`和 `uptime`命令,可以实时监控系统的负载情况,帮助运维人员及时发现并解决潜在问题。理解这些工具的输出和意义是确保系统稳定运行的基础。希望本文对Linux系统平均负载及相关命令的详细解析能帮助您更好地进行系统运维和性能优化。
53 3
|
1月前
|
人工智能 运维 监控
构建高效运维体系:理论与实践的深度融合####
本文旨在探讨高效IT运维体系的构建策略,通过理论框架与实际案例并重的方式,深入剖析了现代企业面临的运维挑战。文章开篇概述了当前运维领域的新趋势,包括自动化、智能化及DevOps文化的兴起,随后详细阐述了如何将这些先进理念融入日常运维管理中,形成一套既灵活又稳定的运维机制。特别地,文中强调了数据驱动决策的重要性,以及在快速迭代的技术环境中保持持续学习与适应的必要性。最终,通过对比分析几个典型企业的运维转型实例,提炼出可复制的成功模式,为读者提供具有实操性的指导建议。 ####
|
1月前
|
运维 监控 中间件
数据中心运维监控系统产品价值与优势
华汇数据运维监控系统面向IT基础架构及IT支撑平台的监控和运维管理,包含监测、分析、展现和告警。监控范围涵盖了网络设备、主机系统、数据库、中间件和应用软件等。
61 4
|
2月前
|
运维 监控 jenkins
运维自动化实战:利用Jenkins构建高效CI/CD流程
【10月更文挑战第18天】运维自动化实战:利用Jenkins构建高效CI/CD流程