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

    xiaoxiao2024-01-04  158

    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 信息导入界面

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)