最近机房刚上了一批机器(有100台左右),需要使用Nagios对这一批机器进行监控。领导要求两天时间完成所有主机的监控。从原来的经验来看,两天时间肯定完成不了。那怎么办?按照之前的想法,肯定是在nagios配置文件逐一添加每台客户端的监控信息,工作量巨大。突然,想到一个想法,是否可以通过脚本来实现批量对主机进行监控,也就是运维自动化。

写脚本,最重要的就是思路。思路压倒一切,经过思考最终决定就这么做了。先贴出来一张网路拓扑图:

整个过程可以分为三部分。

  • cmdb端:主要用来实现对数据的收集,采用两个API,一个是提供给客户机的API。用于将客户端的数据上传的cmdb服务器;另外一个API是nagios通过此API可以得到要监控主机的信息,然后对该信息进行整理,做成nagios监控模板。

  • Client端:通过Python脚本收集本机器要监控的软硬件信息,然后通过cmdb端提供的API接口将数据上传到cmdb端的数据库。

  • Nagios端:通过cmdb端提供的API接口实现对cmdb收集到的信息进行抓取,然后将数据写入到模板,最后copy到naigos指定的objects目录,最终实现对客户机的监控。

这三部分最重要的应该是CMDB端。接下来通过安装django和编写API接口实现cmdb可以正常工作。可以将cmdb端分为三个步骤来完成:

  • 安装django

  • 配置django

  • 编写API接口

首先来进行安装django:

在安装django之前首先应该安装python(版本建议2.7.)

1.下载django软件包
可以到django官方网站下载最新django软件包(https://www.djangoproject.com).
2.解压缩并安装软件包
tar -zxvf Django-1.5.1.tar.gz
cd Django-1.5.1
python setup.py install

创建项目和应用:

1.创建一个项目
python startproject simplecmdb
2.创建一个应用
python startapp hostinfo

配置django:

1.修改setting.py

  • DATABASES = {'ENGIN':'django.db.backends.sqlite','name':path.join('CMDB.db')}  #使用的数据库及数据库名

  • INSTALLED_APPS =(hostinfoINSTALLED_APPS = ('hostinfo')

  • INSTALLED_APPS = ('hostinfo')    #应用的名称

2.修改urls.py

  • url(r'^api/gethost\.json$','hostinfo.views.gethosts'),   #nagios客户端访问API接口地址

  • url(r'^api/clooect$','hostinfo.views.collect'),   #客户端访问API进行上传数据的API

  • url(r'^admin/',include(admin.site.urls)),   #django后台管理登入url

  • from django.contrib import admin

  • admin.autodiscover()

3.修改项目hostinfo下的views.py

代码如下:

# Create your views here.
#包含以下模块
from django.shortcuts import render_to_response
from django.http import HttpResponse
from models import Host, HostGroup
#包含json模块
try:
import json
except ImportError,e:
import simplejson as json
#用来接收客户端服务器发送过来的数据
def collect(request):
req = request
if req.POST:
vendor = req.POST.get('Product_Name')
sn = req.POST.get('Serial_Number')
product = req.POST.get('Manufacturer')
cpu_model = req.POST.get('Model_Name')
cpu_num = req.POST.get('Cpu_Cores')
cpu_vendor = req.POST.get('Vendor_Id')
memory_part_number = req.POST.get('Part_Number')
memory_manufacturer = req.POST.get('Manufacturer')
memory_size = req.POST.get('Size')
device_model = req.POST.get('Device_Model')
device_version = req.POST.get('Firmware_Version')
device_sn = req.POST.get('Serial_Number')
device_size = req.POST.get('User_Capacity')
osver = req.POST.get('os_version')
hostname = req.POST.get('os_name')
os_release = req.POST.get('os_release')
ipaddrs = req.POST.get('Ipaddr')
mac = req.POST.get('Device')
link = req.POST.get('Link')
mask = req.POST.get('Mask')
device = req.POST.get('Device')
host = Host()
host.hostname = hostname
host.product = product
host.cpu_num = cpu_num
host.cpu_model = cpu_model
host.cpu_vendor = cpu_vendor
host.memory_part_number = memory_part_number
host.memory_manufacturer = memory_manufacturer
host.memory_size = memory_size
host.device_model = device_model
host.device_version = device_version
host.device_sn = device_sn
host.device_size = device_size
host.osver = osver
host.os_release = os_release
host.vendor = vendor
host.sn = sn
host.ipaddr = ipaddrs
host.save() #将客户端传过来的数据通过POST接收,存入数据库 return HttpResponse('OK') #如果插入成功,返回'ok'
else:
return HttpResponse('no post data')
#提供给NAGIOS 的API
def gethosts(req):
d = []
hostgroups = HostGroup.objects.all()
for hg in hostgroups:
ret_hg = {'hostgroup':hg.name,'members':[]}
members = hg.members.all()
for h in members:
ret_h = {'hostname':h.hostname, #API接口返回的数据
'ipaddr':h.ipaddr
}
ret_hg['members'].append(ret_h)
d.append(ret_hg)
ret = {'status':0,'data':d,'message':'ok'}
return HttpResponse(json.dumps(ret))

4.修改model.py 文件

代码如下:

from django.db import models
# Create your models here.
#插入数据库的Host表,主要存储客户端主机的信息
class Host(models.Model):
"""store host information"""
vendor = models.CharField(max_length=30,null=True)
sn = models.CharField(max_length=30,null=True)
product = models.CharField(max_length=30,null=True)
cpu_model = models.CharField(max_length=50,null=True)
cpu_num = models.CharField(max_length=2,null=True)
cpu_vendor = models.CharField(max_length=30,null=True)
memory_part_number = models.CharField(max_length=30,null=True)
memory_manufacturer = models.CharField(max_length=30,null=True)
memory_size = models.CharField(max_length=20,null=True)
device_model = models.CharField(max_length=30,null=True)
device_version = models.CharField(max_length=30,null=True)
device_sn = models.CharField(max_length=30,null=True)
device_size = models.CharField(max_length=30,null=True)
osver = models.CharField(max_length=30,null=True)
hostname = models.CharField(max_length=30,null=True)
os_release = models.CharField(max_length=30,null=True)
ipaddr = models.IPAddressField(max_length=15)
def __unicode__(self):
return self.hostname
#主机组表,用来对主机进行分组
class HostGroup(models.Model):
name = models.CharField(max_length=30)
members = models.ManyToManyField(Host)

5.修改admin.py文件

#from models import Host, IPaddr
from models import Host, HostGroup
from django.contrib import admin
#设置在django在admin后天显示的名称
class HostAdmin(admin.ModelAdmin):
list_display = ['vendor',
'sn',
'product',
'cpu_model',
'cpu_num',
'cpu_vendor',
'memory_part_number',
'memory_manufacturer',
'memory_size',
'device_model',
'device_version',
'device_sn',
'device_size',
'osver',
'hostname',
'os_release'
]
#在django后台amdin显示的组名称
class HostGroupAdmin(admin.ModelAdmin):
list_display = ['name',]
#将如上两个类的数据展示到django的后台
admin.site.register(HostGroup,HostGroupAdmin)
admin.site.register(Host, HostAdmin)

6.创建数据库

python manager.py syncdb  #创建数据库

7.启动应用

python manager.py runserver 0.0.0.0:8000

8.测试

http://132.96.77.12:8000/admin

通过上图可以看到,django已经配置成功。

接下来可以在客户端编写收集主机信息的脚本了,主要抓取cpu、内存、硬盘、服务器型号、服务器sn、ip地址、主机名称、操作系统版本等信息,共7个脚本:

1.cpu抓取脚本:

#!/usr/local/src/python/bin/python
#-*- coding:utf-8 -*-
from subprocess import PIPE,Popen
import re
def getCpuInfo():
p = Popen(['cat','/proc/cpuinfo'],shell=False,stdout=PIPE)
stdout, stderr = p.communicate()
return stdout.strip()
def parserCpuInfo(cpudata):
pd = {}
model_name = re.compile(r'.*model name\s+:\s(.*)')
vendor_id = re.compile(r'vendor_id\s+:(.*)')
cpu_cores = re.compile(r'cpu cores\s+:\s([\d]+)')
lines = [line for line in cpudata.split('\n')]
for line in lines:
model = re.match(model_name,line)
vendor = re.match(vendor_id,line)
cores = re.match(cpu_cores,line)
if model:
pd['Model_Name'] = model.groups()[0].strip()
if vendor:
pd['Vendor_Id'] = vendor.groups()[0].strip()
if cores:
pd['Cpu_Cores'] = cores.groups()[0]
else:
pd['Cpu_Cores'] = int('1')
return pd
if __name__ == '__main__':
cpudata = getCpuInfo()
print parserCpuInfo(cpudata)

2.硬盘抓取脚本:

#!/usr/local/src/python/bin/python
#-*- coding:utf-8 -*-
from subprocess import PIPE,Popen
import re
def getDiskInfo():
disk_dev = re.compile(r'Disk\s/dev/[a-z]{3}')
disk_name = re.compile(r'/dev/[a-z]{3}')
p = Popen(['fdisk','-l'],shell=False,stdout=PIPE)
stdout, stderr = p.communicate()
for i in stdout.split('\n'):
disk = re.match(disk_dev,i)
if disk:
dk = re.search(disk_name,disk.group()).group()
n = Popen('smartctl -i %s' % dk,shell=True,stdout=PIPE)
stdout, stderr = n.communicate()
return stdout.strip()
def parserDiskInfo(diskdata):
ld = []
pd = {}
device_model = re.compile(r'(Device Model):(\s+.*)')
serial_number = re.compile(r'(Serial Number):(\s+[\d\w]{1,30})')
firmware_version = re.compile(r'(Firmware Version):(\s+[\w]{1,20})')
user_capacity = re.compile(r'(User Capacity):(\s+[\d\w, ]{1,50})')
for line in diskdata.split('\n'):
serial = re.search(serial_number,line)
device = re.search(device_model,line)
firmware = re.search(firmware_version,line)
user = re.search(user_capacity,line)
if device:
pd['Device_Model'] = device.groups()[1].strip()
if serial:
pd['Serial_Number'] = serial.groups()[1].strip()
if firmware:
pd['Firmware_Version'] = firmware.groups()[1].strip()
if user:
pd['User_Capacity'] = user.groups()[1].strip()
return pd
if __name__ == '__main__':
diskdata = getDiskInfo()
print parserDiskInfo(diskdata)

3.内存抓取脚本:

#!/usr/local/src/python/bin/python
#-*- coding:utf-8 -*-
from subprocess import PIPE,Popen
import re
import sys
def getMemInfo():
p = Popen(['dmidecode'],shell=False,stdout=PIPE)
stdout, stderr = p.communicate()
return stdout.strip()
def parserMemInfo(memdata):
line_in = False
mem_str = ''
pd = {}
fd = {}
for line in memdata.split('\n'):
if line.startswith('Memory Device') and line.endswith('Memory Device'):
line_in = True
mem_str+='\n'
continue
if line.startswith('\t') and line_in:
mem_str+=line
else:
line_in = False
for i in mem_str.split('\n')[1:]:
lines = i.replace('\t','\n').strip()
for ln in lines.split('\n'):
k, v = [i for i in ln.split(':')]
pd[k.strip()] = v.strip()
if pd['Size'] != 'No Module Installed':
mem_info = 'Size:%s ; Part_Number:%s ; Manufacturer:%s' % (pd['Size'],pd['Part Number'],pd['Manufacturer'])
for line in mem_info.split('\n'):
for word in line.split(';'):
k, v = [i.strip() for i in word.split(':')]
fd[k] = v.strip()
yield fd
if __name__ == '__main__':
memdata = getMemInfo()
for i in parserMemInfo(memdata):
print i

4.抓取服务器信息脚本:

#!/usr/local/src/python/bin/python
# -*- coding:utf-8 -*-
from subprocess import PIPE,Popen
import urllib, urllib2
def getDMI():
p = Popen('dmidecode',shell=True,stdout=PIPE)
stdout, stderr = p.communicate()
return stdout
def parserDMI(dmidata):
pd = {}
fd = {}
line_in = False
for line in dmidata.split('\n'):
if line.startswith('System Information'):
line_in = True
continue
if line.startswith('\t') and line_in:
k, v = [i.strip() for i in line.split(':')]
pd[k] = v
else:
line_in = False
name = "Manufacturer:%s ; Serial_Number:%s ; Product_Name:%s" % (pd['Manufacturer'],pd['Serial Number'],pd['Product Name'])
for i in name.split(';'):
k, v = [j.strip() for j in i.split(':')]
fd[k] = v
return fd
if __name__ == '__main__':
dmidata = getDMI()
postdata = parserDMI(dmidata)
print postdata

5.抓取主机信息

#!/usr/local/src/python/bin/python
#-*- coding:utf-8 -*-
import platform
def getHostInfo():
pd ={}
version = platform.dist()
os_name = platform.node()
os_release = platform.release()
os_version = '%s %s' % (version[0],version[1])
pd['os_name'] = os_name
pd['os_release'] = os_release
pd['os_version'] = os_version
return pd
if __name__ == '__main__':
print getHostInfo()

6.抓取ip地址:

#!/usr/local/src/python/bin/python
#-*- coding:utf-8 -*-
from subprocess import PIPE,Popen
import re
def getIpaddr():
p = Popen(['ifconfig'],shell=False,stdout=PIPE)
stdout, stderr = p.communicate()
return stdout.strip()
def parserIpaddr(ipdata):
device = re.compile(r'(eth\d)')
ipaddr = re.compile(r'(inet addr:[\d.]{7,15})')
mac = re.compile(r'(HWaddr\s[0-9A-Fa-f:]{17})')
link = re.compile(r'(Link encap:[\w]{3,14})')
mask = re.compile(r'(Mask:[\d.]{9,15})')
for lines in ipdata.split('\n\n'):
pd = {}
eth_device = re.search(device,lines)
inet_ip = re.search(ipaddr,lines)
hw = re.search(mac,lines)
link_encap = re.search(link,lines)
_mask = re.search(mask,lines)
if eth_device:
if eth_device:
Device = eth_device.groups()[0]
if inet_ip:
Ipaddr = inet_ip.groups()[0].split(':')[1]
if hw:
Mac = hw.groups()[0].split()[1]
if link_encap:
Link = link_encap.groups()[0].split(':')[1]
if _mask:
Mask = _mask.groups()[0].split(':')[1]
pd['Device'] = Device
pd['Ipaddr'] = Ipaddr
pd['Mac'] = Mac
pd['Link'] = Link
pd['Mask'] = Mask
yield pd
if __name__ == '__main__':
ipdata = getIpaddr()
for i in parserIpaddr(ipdata):
print i

7.对这些信息进行合并,并通过API形式将数据发送给cmdb端

#!/usr/local/src/python/bin/python
import urllib, urllib2
from cpuinfo import *
from diskinfo import *
from meminfo import *
from product import *
from hostinfo import *
from ipaddress import *
def getHostTotal():
ld = []
cpuinfo = parserCpuInfo(getCpuInfo())
diskinfo = parserDiskInfo(getDiskInfo())
for i in parserMemInfo(getMemInfo()):
meminfo = i
productinfo = parserDMI(getDMI())
hostinfo = getHostInfo()
ipaddr = parserIpaddr(getIpaddr())
for i in ipaddr:
ip = i
for k in cpuinfo.iteritems():
ld.append(k)
for i in diskinfo.iteritems():
ld.append(i)
for j in meminfo.iteritems():
ld.append(j)
for v in productinfo.iteritems():
ld.append(v)
for x in hostinfo.iteritems():
ld.append(x)
for y in ip.iteritems():
ld.append(y)
return ld
def parserHostTotal(hostdata):
pg = {}
for i in hostdata:
pg[i[0]] = i[1]
return pg
def urlPost(postdata):
data = urllib.urlencode(postdata)
req = urllib2.Request('http://132.96.77.12:8000/api/collect',data)
response = urllib2.urlopen(req)
return response.read()
if __name__ == '__main__':
hostdata = getHostTotal()
postdata = parserHostTotal(hostdata)
print urlPost(postdata)

到目前为止,cmdb系统已经可以将所有客户端的主机信息写入到数据库,并且可以通过nagios端的API接口直接调到数据:

http://132.96.77.12:8000/api/gethosts.json

通过图可以看到,已经成功调用到API接口的数据。

接下来可以在nagios端进行调用API接口的数据,对数据进行格式化。并写入文件。

1.nagios脚本

#!/opt/data/py/bin/python
#!-*- coding:utf-8 -*-
import urllib, urllib2
import json
import os
import shutil
CURR_DIR = os.path.abspath(os.path.dirname(__file__))
HOST_CONF_DIR = os.path.join(CURR_DIR,'hosts')
HOST_TMP = """define host {
use linux-server
host_name %(hostname)s
check_command check-host-alive
alias %(hostname)s
address %(ipaddr)s
contact_groups admins
}
"""
def getHosts():
url = 'http://132.96.77.12:8000/api/gethosts.json'
return json.loads(urllib2.urlopen(url).read())
def initDir():
if not os.path.exists(HOST_CONF_DIR):
os.mkdir(HOST_CONF_DIR)
def writeFile(f,s):
with open(f,'w') as fd:
fd.write(s)
def genNagiosHost(hostdata):
initDir()
conf = os.path.join(HOST_CONF_DIR,'hosts.cfg')
hostconf = ""
for hg in hostdata:
for h in hg['members']:
hostconf+=HOST_TMP %h
writeFile(conf,hostconf)
return "ok"
def main():
result = getHosts()
if result['status'] == 0:
print genNagiosHost(result['data'])
else:
print 'Error: %s' % result['message']
if os.path.exists(os.path.join(HOST_CONF_DIR,'hosts.cfg')):
os.chdir(HOST_CONF_DIR)
shutil.copyfile('hosts.cfg','/etc/nagios/objects/hosts.cfg')
if __name__ == "__main__":
main()

现在已经生成nagios主机的配置文件,并copy到nagios/objects目录下hosts.cfg。接下来可以测试是否nagios配置有问题,如果没有问题,就可以启动nagios服务

[root@yetcomm-v2 bin]# ./nagios -v /etc/nagios/nagios.cfg

通过测试,nagios没有发生错误或警告信息,现在可以启动nagios服务:

[root@yetcomm-v2 bin]# service nagios restart

最后,可以通过浏览器查看nagios的监控界面:   

通过上图,可以看到已经将一台主机加入到监控组。由于是生产环境,所有只能拿测试服务器进行测试。其实测试环境和生产环境的代码完全一致。

python+Django实现Nagios自动化添加监控项目的更多相关文章

  1. Python+Django+ansible playbook自动化运维项目实战☝☝☝

    Python+Django+ansible playbook自动化运维项目实战☝☝☝  一.入门引导 DevOPSDevOps(英文Development和Operations的组合)是一组过程.方法 ...

  2. Python+Django+ansible playbook自动化运维项目实战✍✍✍

    Python+Django+ansible playbook自动化运维项目实战  整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受 ...

  3. Python+Django+Ansible Playbook自动化运维项目实战

    Python+Django+AnsiblePlaybook自动化运维项目实战 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受,单 ...

  4. zabbix的自动发现、自定义添加监控项目、配置邮件告警

    1.zabbix的自动发现这里的自动发现,所显示出来的是规则的上自动了现 然后 可以对其内容进行相关的配制,如时间或周期 注意:对于单个主机的规则,可以自行添加或删除, 但对于已经添加好了的规则,若需 ...

  5. 【转】python+django+vue搭建前后端分离项目

    https://www.cnblogs.com/zhixi/p/9996832.html 以前一直是做基于PHP或JAVA的前后端分离开发,最近跟着python风搭建了一个基于django的前后端分享 ...

  6. python+django+vue搭建前后端分离项目

    以前一直是做基于PHP或JAVA的前后端分离开发,最近跟着python风搭建了一个基于django的前后端分享项目 准备工作:IDE,[JetBrains PyCharm2018][webpack 3 ...

  7. zabbix添加自定义监控项目

    在zabbix里添加一个自定义监控项目,简单做个笔记,怕忘了 首先需要定义 zabbix_agentd.conf  中的 UnsafeUserParameters 修改为 UnsafeUserPara ...

  8. Django-Multitenant,分布式多租户数据库项目实战(Python/Django+Postgres+Citus)

    Python/Django 支持分布式多租户数据库,如 Postgres+Citus. 通过将租户上下文添加到您的查询来实现轻松横向扩展,使数据库(例如 Citus)能够有效地将查询路由到正确的数据库 ...

  9. Python(Django)项目与Apache的管理

    (开开心心每一天~ ---虫瘾师) Python(Django)项目交给Apache的管理(一) 准备:Django的环境(Python).Apache.Wsgi(必须文件) 首先需要电脑有Pytho ...

随机推荐

  1. Mybatis分页插件-PageHelper的使用

    转载:http://blog.csdn.net/u012728960/article/details/50791343 Mybatis分页插件-PageHelper的使用 怎样配置mybatis这里就 ...

  2. Git以及github的使用方法(四),版本回退

    现在,你已经学会了修改文件,然后把修改提交到Git版本库,现在,再练习一次,修改readme.txt文件如下: Git is a distributed version control system. ...

  3. php如何读取ini文件

    很多时候,我们使用配置文件来读取配置,那么php如何使用ini文件呢? 代码如下: 例如将:数据库信息存到ini文件中,进行读取. <?php header('content-type:text ...

  4. SpringMVC:JSON

    @ResponseBody params="json":访问我这个方法的时候一定要有参数名为json 返回值Userjackson-all-1.9.0.jar @RequestMa ...

  5. 利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model

    利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model   使用场景:网站配置项目,为了便于管理,网站有几个Model类来管理配置文件, 比如ConfigWebsiteMo ...

  6. linux 信号屏蔽

    <span style="font-size:18px;">#include <sys/types.h> #include <unistd.h> ...

  7. Codeforces Round #267 (Div. 2) B. Fedor and New Game

    After you had helped George and Alex to move in the dorm, they went to help their friend Fedor play ...

  8. Django+uwsgi+nginx+angular.js项目部署

    这次部署的前后端分离的项目: 前端采用angular.js,后端采用Django(restframework),他俩之间主要以json数据作为交互 Django+uwsgi的配置可以参考我之前的博客: ...

  9. caffe2 安装与介绍

    http://blog.csdn.net/yan_joy/article/details/70241319 标签: 深度学习 2017-04-19 15:31 5970人阅读 评论(0) 收藏 举报 ...

  10. php pack()函数详解与示例

    pack和unpack在一般的程序中还真的不容易见到,但是如果你用过很久以前的php生成excel你就会知道了.他的excel的头就是pack出来的最近在尝试与C交互的时候又用上了这玩意,所以不得不再 ...