9 python+django 實現 nagios 自動化添加監控項目
Python實戰-從菜鳥到大牛的進階之路 作者:極客學院 投票推薦 加入書簽 留言反饋
最近機房剛上了一批機器(有 100 台左右),需要使用 nagios 對這一批機器進行監控。領導要求兩天時間完成所有主機的監控。從原來的經驗來看,兩天時間肯定完成不了。那怎麽辦?按照之前的想法,肯定是在 nagios 配置文件逐一添加每台客戶端的監控信息,工作量巨大。突然,想到一個想法,是否可以通過腳本來實現批量對主機進行監控,也就是運維自動化。
寫腳本,最重要的就是思路。思路壓倒一切,經過思考最終決定就這麽做了。先貼出來一張網路拓撲圖:
圖片 9.1 pic
整個過程可以分為三部分。 <ul><li>cmdb 端:主要用來實現對數據的收集,采用兩個 api,一個是提供給客戶機的 api。用於將客戶端的數據上傳的 cmdb 服務器;另外一 個 api 是 nagios 通過此 api 可以得到要監控主機的信息,然後對該信息進行整理,做成 nagios 監控模板。</li><li>client 端:通過 python 腳本收集本機器要監控的軟硬件信息,然後通過 cmdb 端提供的 api 接口將數據上傳到 cmdb 端的數據庫。</li><li>nagios 端:通過 cmdb 端提供的 api 接口實現對 cmdb 收集到的信息進行抓取,然後將數據寫入到模板,最後 copy 到 naigos 指定的 objects 目錄,最終實現對客戶機的監控。</li></ul>
這三部分最重要的應該是 cmdb 端。接下來通過安裝 django 和編寫 api 接口實現 cmdb 可以正常工作。可以將 cmdb 端分為三個步驟來完成: <ul><li>安裝 django</li><li>配置 django</li><li>編寫 api 接口</li></ul>
首先來進行安裝 django:
在安裝 django 之前首先應該安裝 python (版本建議 2.7.)
1.下載 django 軟件包 可以到 django 官方網站下載最新 django 軟件包(https://.djangoproject).2.解壓縮並安裝軟件包 tar -zxvf django-1.5.1.tar.gz cd django-1.5.1 python setup.py install </pre>
創建項目和應用:
1.創建一個項目python startproject simplecmdb2.創建一個應用python startapp hostinfo </pre>
配置 django:
1.修改 setting.py
databases = {\''engin\'':\''django.db.backends.sqlite\'',\''name\'':path.join(\''cmdb.db\'')} #使用的數據庫及數據庫名installed_apps =(hostinfoinstalled_apps = (\''hostinfo\'')installed_apps = (\''hostinfo\'') #應用的名稱 </pre>
2.修改urls.py
url(r\''^api/gethost.json$\'',\''hostinfo.views.gethosts\''), #nagios客戶端訪問api接口地址url(r\''^api/clooect$\'',\''hostinfo.views.collect\''), #客戶端訪問api進行上傳數據的apiurl(r\''^admin/\'',include(admin.site.urls)), #django後台管理登入urlfrom django.contrib import adminadmin.autodiscover </pre>
3.修改項目 hostinfo 下的 views.py
代碼如下:
# create your views here. #包含以下模塊from django.shortcuts import render_to_responsefrom django.http import httpresponsefrom models import host, hostgroup #包含json模塊try: import jsonexcept 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 = hosthost.hostname = hostnamehost.product = producthost.cpu_num = cpu_numhost.cpu_model = cpu_modelhost.cpu_vendor = cpu_vendorhost.memory_part_number = memory_part_numberhost.memory_manufacturer = memory_manufacturerhost.memory_size = memory_sizehost.device_model = device_modelhost.device_version = device_versionhost.device_sn = device_snhost.device_size = device_sizehost.osver = osverhost.os_release = os_releasehost.vendor = vendorhost.sn = snhost.ipaddr = ipaddrshost.save #將客戶端傳過來的數據通過post接收,存入數據庫return httpresponse(\''ok\'') #如果插入成功,返回\''ok\'' else:return httpresponse(\''no post data\'') #提供給nagios 的apidef gethosts(req): d = hostgroups = hostgroup.objects.all for hg in hostgroups:ret_hg = {\''hostgroup\'':hg.name,\''members\'':}members = hg.members.allfor 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)) </pre>
4.修改 model.py 文件
代碼如下:
from django.db import models # create your models here. #插入數據庫的host表,主要存儲客戶端主機的信息ss 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 #主機組表,用來對主機進行分組ss hostgroup(models.model): name = models.charfield(max_length=30) members = models.manytomanyfield(host) </pre>
5.修改 admin.py 文件
#from models import host, ipaddrfrom models import host, hostgroupfrom django.contrib import admin #設置在django在admin後天顯示的名稱ss hostadmin(admin.moddmin): list_disy = [\''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顯示的組名稱ss hostgroupadmin(admin.moddmin): list_disy = [\''name\'',] #將如上兩個類的數據展示到django的後台admin.site.register(hostgroup,hostgroupadmin)admin.site.register(host, hostadmin) </pre>
6.創建數據庫
python manager.py syncdb #創建數據庫 </pre>
7.啟動應用
python manager.py runserver 0.0.0.0:8000 </pre>
8.測試
http://132.96.77.12:8000/admin
圖片 9.2 pic
圖片 9.3 pic
通過上圖可以看到,django 已經配置成功。
接下來可以在客戶端編寫收集主機信息的腳本了,主要抓取 cpu、內存、硬盤、服務器型號、服務器 sn、ip 地址、主機名稱、操作係統版本等信息,共 7 個腳本:
1.cpu 抓取腳本:
#!/usr/local/src/python/bin/python #-*- coding:utf-8 -*-from subprocess import pipe,popenimport redef getcpuinfo: p = popen([\''cat\'',\''/proc/cpuinfo\''],shell=false,stdout=pipe) stdout, stderr = pmunicate return stdout.stripdef parsercpuinfo(cpudata): pd = {} model_name = repile(r\''.*model names+:s(.*)\'') vendor_id = repile(r\''vendor_ids+:(.*)\'') cpu_cores = repile(r\''cpu coress+: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].stripif vendor: pd[\''vendor_id\''] = vendor.groups[0].stripif cores: pd[\''cpu_cores\''] = cores.groups[0]else: pd[\''cpu_cores\''] = int(\''1\'') return pdif __name__ == \''__main__\'': cpudata = getcpuinfo print parsercpuinfo(cpudata) </pre>
2.硬盤抓取腳本:
#!/usr/local/src/python/bin/python #-*- coding:utf-8 -*-from subprocess import pipe,popenimport redef getdiskinfo: disk_dev = repile(r\''disks/dev/[a-z]{3}\'') disk_name = repile(r\''/dev/[a-z]{3}\'') p = popen([\''fdisk\'',\''-l\''],shell=false,stdout=pipe) stdout, stderr = pmunicate 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 = nmunicate return stdout.stripdef parserdiskinfo(diskdata): ld = pd = {} device_model = repile(r\''(device model):(s+.*)\'') serial_number = repile(r\''(serial number):(s+[dw]{1,30})\'') firmware_version = repile(r\''(firmware version):(s+[w]{1,20})\'') user_capacity = repile(r\''(user capacity):(s+[dw, ]{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].stripif serial: pd[\''serial_number\''] = serial.groups[1].stripif firmware: pd[\''firmware_version\''] = firmware.groups[1].stripif user: pd[\''user_capacity\''] = user.groups[1].strip return pdif __name__ == \''__main__\'': diskdata = getdiskinfo print parserdiskinfo(diskdata) </pre>
3.內存抓取腳本:
#!/usr/local/src/python/bin/python #-*- coding:utf-8 -*-from subprocess import pipe,popenimport reimport sysdef getmeminfo: p = popen([\''dmidecode\''],shell=false,stdout=pipe) stdout, stderr = pmunicate return stdout.stripdef 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\'' continueif line.startswith(\''t\'') and line_in: mem_str+=lineelse: line_in = false for i in mem_str.split(\''n\'')[1:]:lines = i.rece(\''t\'',\''n\'').stripfor ln in lines.split(\''n\''): k, v = [i for i in ln.split(\'':\'')] pd[k.strip] = v.stripif 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.stripyield fdif __name__ == \''__main__\'': memdata = getmeminfo for i in parsermeminfo(memdata):print i </pre>
4.抓取服務器信息腳本:
#!/usr/local/src/python/bin/python # -*- coding:utf-8 -*-from subprocess import pipe,popenimport urllib, urllib2def getdmi: p = popen(\''dmidecode\'',shell=true,stdout=pipe) stdout, stderr = pmunicate return stdoutdef parserdmi(dmidata): pd = {} fd = {} line_in = false for line in dmidata.split(\''n\''):if line.startswith(\''system information\''): line_in = true continueif line.startswith(\''t\'') and line_in: k, v = [i.strip for i in line.split(\'':\'')] pd[k] = velse: 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 fdif __name__ == \''__main__\'': dmidata = getdmi postdata = parserdmi(dmidata) print postdata </pre>
5.抓取主機信息
#!/usr/local/src/python/bin/python #-*- coding:utf-8 -*-import tformdef gethostinfo: pd ={} version = tform.dist os_name = tform.node os_release = tform.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 pdif __name__ == \''__main__\'': print gethostinfo </pre>
6.抓取 ip 地址:
#!/usr/local/src/python/bin/python #-*- coding:utf-8 -*-from subprocess import pipe,popenimport redef getipaddr: p = popen([\''ifconfig\''],shell=false,stdout=pipe) stdout, stderr = pmunicate return stdout.stripdef parseripaddr(ipdata): device = repile(r\''(ethd)\'') ipaddr = repile(r\''( addr:[d.]{7,15})\'') mac = repile(r\''(hwaddrs[0-9a-fa-f:]{17})\'') link = repile(r\''(link encap:[w]{3,14})\'') mask = repile(r\''(mask:[d.]{9,15})\'') for lines in ipdata.split(\''nn\''):pd = {}eth_device = re.search(device,lines)_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 _ip:ipaddr = _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 pdif __name__ == \''__main__\'': ipdata = getipaddr for i in parseripaddr(ipdata):print i </pre>
7.對這些信息進行合並,並通過api形式將數據發送給cmdb端
#!/usr/local/src/python/bin/pythonimport urllib, urllib2from 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 lddef parserhosttotal(hostdata): pg = {} for i in hostdata:pg[i[0]] = i[1] return pgdef urlpost(postdata): data = urllib.urlencode(postdata) req = urllib2.request(\''http://132.96.77.12:8000/api/collect\'',data) response = urllib2.urlopen(req) return response.readif __name__ == \''__main__\'': hostdata = gethosttotal postdata = parserhosttotal(hostdata) print urlpost(postdata) </pre>
到目前為止,cmdb 係統已經可以將所有客戶端的主機信息寫入到數據庫,並且可以通過 nagios 端的 api 接口直接調到數據:
http://132.96.77.12:8000/api/gethosts.json
圖片 9.4 pic
通過圖可以看到,已經成功調用到 api 接口的數據。
接下來可以在 nagios 端進行調用 api 接口的數據,對數據進行格式化。並寫入文件。
1.nagios腳本
#!/opt/data/py/bin/python #!-*- coding:utf-8 -*-import urllib, urllib2import jsonimport osimport shutilcurr_dir = os.path.abspath(os.path.dirname(__file__))host_conf_dir = os.path.join(curr_dir,\''hosts\'')host_tmp = """define host { uselinux-server host_name %(hostname)s checkmand 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 </pre>
現在已經生成 nagios 主機的配置文件,並 copy 到 nagios/objects 目錄下 hosts.cfg。接下來可以測試是否 nagios 配置有問題,如果沒有問題,就可以啟動 nagios 服務
[root@yem-v2 bin]# ./nagios -v /etc/nagios/nagios.cfg </pre>
通過測試,nagios 沒有發生錯誤或警告信息,現在可以啟動 nagios 服務:
[root@yem-v2 bin]# service nagios restart </pre>
最後,可以通過瀏覽器查看 nagios 的監控界麵:
圖片 9.5 pic
通過上圖,可以看到已經將一台主機加入到監控組。由於是生產環境,所有隻能拿測試服務器進行測試。其實測試環境和生產環境的代碼完全一致。
寫腳本,最重要的就是思路。思路壓倒一切,經過思考最終決定就這麽做了。先貼出來一張網路拓撲圖:
圖片 9.1 pic
整個過程可以分為三部分。 <ul><li>cmdb 端:主要用來實現對數據的收集,采用兩個 api,一個是提供給客戶機的 api。用於將客戶端的數據上傳的 cmdb 服務器;另外一 個 api 是 nagios 通過此 api 可以得到要監控主機的信息,然後對該信息進行整理,做成 nagios 監控模板。</li><li>client 端:通過 python 腳本收集本機器要監控的軟硬件信息,然後通過 cmdb 端提供的 api 接口將數據上傳到 cmdb 端的數據庫。</li><li>nagios 端:通過 cmdb 端提供的 api 接口實現對 cmdb 收集到的信息進行抓取,然後將數據寫入到模板,最後 copy 到 naigos 指定的 objects 目錄,最終實現對客戶機的監控。</li></ul>
這三部分最重要的應該是 cmdb 端。接下來通過安裝 django 和編寫 api 接口實現 cmdb 可以正常工作。可以將 cmdb 端分為三個步驟來完成: <ul><li>安裝 django</li><li>配置 django</li><li>編寫 api 接口</li></ul>
首先來進行安裝 django:
在安裝 django 之前首先應該安裝 python (版本建議 2.7.)
1.下載 django 軟件包 可以到 django 官方網站下載最新 django 軟件包(https://.djangoproject).2.解壓縮並安裝軟件包 tar -zxvf django-1.5.1.tar.gz cd django-1.5.1 python setup.py install </pre>
創建項目和應用:
1.創建一個項目python startproject simplecmdb2.創建一個應用python startapp hostinfo </pre>
配置 django:
1.修改 setting.py
databases = {\''engin\'':\''django.db.backends.sqlite\'',\''name\'':path.join(\''cmdb.db\'')} #使用的數據庫及數據庫名installed_apps =(hostinfoinstalled_apps = (\''hostinfo\'')installed_apps = (\''hostinfo\'') #應用的名稱 </pre>
2.修改urls.py
url(r\''^api/gethost.json$\'',\''hostinfo.views.gethosts\''), #nagios客戶端訪問api接口地址url(r\''^api/clooect$\'',\''hostinfo.views.collect\''), #客戶端訪問api進行上傳數據的apiurl(r\''^admin/\'',include(admin.site.urls)), #django後台管理登入urlfrom django.contrib import adminadmin.autodiscover </pre>
3.修改項目 hostinfo 下的 views.py
代碼如下:
# create your views here. #包含以下模塊from django.shortcuts import render_to_responsefrom django.http import httpresponsefrom models import host, hostgroup #包含json模塊try: import jsonexcept 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 = hosthost.hostname = hostnamehost.product = producthost.cpu_num = cpu_numhost.cpu_model = cpu_modelhost.cpu_vendor = cpu_vendorhost.memory_part_number = memory_part_numberhost.memory_manufacturer = memory_manufacturerhost.memory_size = memory_sizehost.device_model = device_modelhost.device_version = device_versionhost.device_sn = device_snhost.device_size = device_sizehost.osver = osverhost.os_release = os_releasehost.vendor = vendorhost.sn = snhost.ipaddr = ipaddrshost.save #將客戶端傳過來的數據通過post接收,存入數據庫return httpresponse(\''ok\'') #如果插入成功,返回\''ok\'' else:return httpresponse(\''no post data\'') #提供給nagios 的apidef gethosts(req): d = hostgroups = hostgroup.objects.all for hg in hostgroups:ret_hg = {\''hostgroup\'':hg.name,\''members\'':}members = hg.members.allfor 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)) </pre>
4.修改 model.py 文件
代碼如下:
from django.db import models # create your models here. #插入數據庫的host表,主要存儲客戶端主機的信息ss 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 #主機組表,用來對主機進行分組ss hostgroup(models.model): name = models.charfield(max_length=30) members = models.manytomanyfield(host) </pre>
5.修改 admin.py 文件
#from models import host, ipaddrfrom models import host, hostgroupfrom django.contrib import admin #設置在django在admin後天顯示的名稱ss hostadmin(admin.moddmin): list_disy = [\''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顯示的組名稱ss hostgroupadmin(admin.moddmin): list_disy = [\''name\'',] #將如上兩個類的數據展示到django的後台admin.site.register(hostgroup,hostgroupadmin)admin.site.register(host, hostadmin) </pre>
6.創建數據庫
python manager.py syncdb #創建數據庫 </pre>
7.啟動應用
python manager.py runserver 0.0.0.0:8000 </pre>
8.測試
http://132.96.77.12:8000/admin
圖片 9.2 pic
圖片 9.3 pic
通過上圖可以看到,django 已經配置成功。
接下來可以在客戶端編寫收集主機信息的腳本了,主要抓取 cpu、內存、硬盤、服務器型號、服務器 sn、ip 地址、主機名稱、操作係統版本等信息,共 7 個腳本:
1.cpu 抓取腳本:
#!/usr/local/src/python/bin/python #-*- coding:utf-8 -*-from subprocess import pipe,popenimport redef getcpuinfo: p = popen([\''cat\'',\''/proc/cpuinfo\''],shell=false,stdout=pipe) stdout, stderr = pmunicate return stdout.stripdef parsercpuinfo(cpudata): pd = {} model_name = repile(r\''.*model names+:s(.*)\'') vendor_id = repile(r\''vendor_ids+:(.*)\'') cpu_cores = repile(r\''cpu coress+: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].stripif vendor: pd[\''vendor_id\''] = vendor.groups[0].stripif cores: pd[\''cpu_cores\''] = cores.groups[0]else: pd[\''cpu_cores\''] = int(\''1\'') return pdif __name__ == \''__main__\'': cpudata = getcpuinfo print parsercpuinfo(cpudata) </pre>
2.硬盤抓取腳本:
#!/usr/local/src/python/bin/python #-*- coding:utf-8 -*-from subprocess import pipe,popenimport redef getdiskinfo: disk_dev = repile(r\''disks/dev/[a-z]{3}\'') disk_name = repile(r\''/dev/[a-z]{3}\'') p = popen([\''fdisk\'',\''-l\''],shell=false,stdout=pipe) stdout, stderr = pmunicate 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 = nmunicate return stdout.stripdef parserdiskinfo(diskdata): ld = pd = {} device_model = repile(r\''(device model):(s+.*)\'') serial_number = repile(r\''(serial number):(s+[dw]{1,30})\'') firmware_version = repile(r\''(firmware version):(s+[w]{1,20})\'') user_capacity = repile(r\''(user capacity):(s+[dw, ]{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].stripif serial: pd[\''serial_number\''] = serial.groups[1].stripif firmware: pd[\''firmware_version\''] = firmware.groups[1].stripif user: pd[\''user_capacity\''] = user.groups[1].strip return pdif __name__ == \''__main__\'': diskdata = getdiskinfo print parserdiskinfo(diskdata) </pre>
3.內存抓取腳本:
#!/usr/local/src/python/bin/python #-*- coding:utf-8 -*-from subprocess import pipe,popenimport reimport sysdef getmeminfo: p = popen([\''dmidecode\''],shell=false,stdout=pipe) stdout, stderr = pmunicate return stdout.stripdef 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\'' continueif line.startswith(\''t\'') and line_in: mem_str+=lineelse: line_in = false for i in mem_str.split(\''n\'')[1:]:lines = i.rece(\''t\'',\''n\'').stripfor ln in lines.split(\''n\''): k, v = [i for i in ln.split(\'':\'')] pd[k.strip] = v.stripif 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.stripyield fdif __name__ == \''__main__\'': memdata = getmeminfo for i in parsermeminfo(memdata):print i </pre>
4.抓取服務器信息腳本:
#!/usr/local/src/python/bin/python # -*- coding:utf-8 -*-from subprocess import pipe,popenimport urllib, urllib2def getdmi: p = popen(\''dmidecode\'',shell=true,stdout=pipe) stdout, stderr = pmunicate return stdoutdef parserdmi(dmidata): pd = {} fd = {} line_in = false for line in dmidata.split(\''n\''):if line.startswith(\''system information\''): line_in = true continueif line.startswith(\''t\'') and line_in: k, v = [i.strip for i in line.split(\'':\'')] pd[k] = velse: 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 fdif __name__ == \''__main__\'': dmidata = getdmi postdata = parserdmi(dmidata) print postdata </pre>
5.抓取主機信息
#!/usr/local/src/python/bin/python #-*- coding:utf-8 -*-import tformdef gethostinfo: pd ={} version = tform.dist os_name = tform.node os_release = tform.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 pdif __name__ == \''__main__\'': print gethostinfo </pre>
6.抓取 ip 地址:
#!/usr/local/src/python/bin/python #-*- coding:utf-8 -*-from subprocess import pipe,popenimport redef getipaddr: p = popen([\''ifconfig\''],shell=false,stdout=pipe) stdout, stderr = pmunicate return stdout.stripdef parseripaddr(ipdata): device = repile(r\''(ethd)\'') ipaddr = repile(r\''( addr:[d.]{7,15})\'') mac = repile(r\''(hwaddrs[0-9a-fa-f:]{17})\'') link = repile(r\''(link encap:[w]{3,14})\'') mask = repile(r\''(mask:[d.]{9,15})\'') for lines in ipdata.split(\''nn\''):pd = {}eth_device = re.search(device,lines)_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 _ip:ipaddr = _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 pdif __name__ == \''__main__\'': ipdata = getipaddr for i in parseripaddr(ipdata):print i </pre>
7.對這些信息進行合並,並通過api形式將數據發送給cmdb端
#!/usr/local/src/python/bin/pythonimport urllib, urllib2from 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 lddef parserhosttotal(hostdata): pg = {} for i in hostdata:pg[i[0]] = i[1] return pgdef urlpost(postdata): data = urllib.urlencode(postdata) req = urllib2.request(\''http://132.96.77.12:8000/api/collect\'',data) response = urllib2.urlopen(req) return response.readif __name__ == \''__main__\'': hostdata = gethosttotal postdata = parserhosttotal(hostdata) print urlpost(postdata) </pre>
到目前為止,cmdb 係統已經可以將所有客戶端的主機信息寫入到數據庫,並且可以通過 nagios 端的 api 接口直接調到數據:
http://132.96.77.12:8000/api/gethosts.json
圖片 9.4 pic
通過圖可以看到,已經成功調用到 api 接口的數據。
接下來可以在 nagios 端進行調用 api 接口的數據,對數據進行格式化。並寫入文件。
1.nagios腳本
#!/opt/data/py/bin/python #!-*- coding:utf-8 -*-import urllib, urllib2import jsonimport osimport shutilcurr_dir = os.path.abspath(os.path.dirname(__file__))host_conf_dir = os.path.join(curr_dir,\''hosts\'')host_tmp = """define host { uselinux-server host_name %(hostname)s checkmand 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 </pre>
現在已經生成 nagios 主機的配置文件,並 copy 到 nagios/objects 目錄下 hosts.cfg。接下來可以測試是否 nagios 配置有問題,如果沒有問題,就可以啟動 nagios 服務
[root@yem-v2 bin]# ./nagios -v /etc/nagios/nagios.cfg </pre>
通過測試,nagios 沒有發生錯誤或警告信息,現在可以啟動 nagios 服務:
[root@yem-v2 bin]# service nagios restart </pre>
最後,可以通過瀏覽器查看 nagios 的監控界麵:
圖片 9.5 pic
通過上圖,可以看到已經將一台主機加入到監控組。由於是生產環境,所有隻能拿測試服務器進行測試。其實測試環境和生產環境的代碼完全一致。