程序员 开源 编程 nginx Python shell google Windows php java apache Android Ubuntu centos linux 云计算 微软 mysql wordpress Firefox

運維前線:一線運維專家的運維方法、技巧與實踐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提供的幾個好用的功能模塊。

延伸阅读

    评论