最近機房剛上了一批機器(有 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


    通過上圖,可以看到已經將一台主機加入到監控組。由於是生產環境,所有隻能拿測試服務器進行測試。其實測試環境和生產環境的代碼完全一致。

章節目錄

閱讀記錄

Python實戰-從菜鳥到大牛的進階之路所有內容均來自互聯網,uu小說網隻為原作者極客學院的小說進行宣傳。歡迎各位書友支持極客學院並收藏Python實戰-從菜鳥到大牛的進階之路最新章節