用python+django+twistd 開發一個屬於自己的運維繫統
阿新 • • 發佈:2019-01-04
開源的運維繫統不少,比如nagios、zabbix、cati等等,但是遇到自己個性化的運維需求的時候,總是顯的力不從心!最近在學習python,所以就考慮用python+django+twisted來定做一個完全個性化的運維繫統。
運維繫統有幾個主要的功能:監控、分析、報警、更甚者直接根據分析的結果進行反應操作。而以上幾點通過上述的框架可以比較容易的實現。
下面上圖說明:
使用freemind整理了下思路:
下面是一些程式碼段,完整的程式碼下載見文件底部:
Server:
Client端#!/usr/bin/env python #coding:utf-8 __author__ = 'dwj' from twisted.internet.protocol import ServerFactory from twisted.protocols import basic import cx_Oracle from twisted.application import service, internet class Mornitor_Protocol(basic.LineReceiver): def __init__(self): # _oracle_conn=cx_Oracle.connect('xxxx', 'xxxx', '192.168.7.17/test', threaded=True) _oracle_conn.autocommit = True self.cur = _oracle_conn.cursor() self._oracle_conn=_oracle_conn def ruku(self, line): ip=self.transport.getPeer().host #獲取客戶端IP line=line.split(':::') #使用:::分割原始資料 if line[1] in ['cpu', 'mem', 'disk', 'tcp', 'net', 'process_down']: #根據資料包頭來確定使用insert還是update,當是tcp包頭的時候插入,其餘的更新 if line[1] == 'tcp': sql = "insert into MORNITOR_BASICINFO (ipadd,time,tcp) values (\'%s\',\'%s\',\'%s\')"%(ip,line[0],line[3]) print sql self.cur.execute(sql) else: line_again = line[3].split('::') sql = 'update MORNITOR_BASICINFO set %s=\'%s\',%s=\'%s\' where ipadd=\'%s\' and time=\'%s\''%(line[1],line_again[0],line[2],line_again[1],ip,line[0]) print sql self.cur.execute(sql) def connectionMade(self): print 'Connected!' def lineReceived(self, line): print line self.ruku(line) #接受到資料之後執行入庫操作! def connectionLost(self, reason='connectionDone'): self._oracle_conn.close() print 'The db is close... ok!' class Mornitor_Factory(ServerFactory): #還沒想好要初始化什麼 def __init__(self,service): self.service = service protocol = Mornitor_Protocol class Fish_Service(service.Service): def __init__(self): pass def startService(self): service.Service.startService(self) #什麼都不做,開始服務 # def stopService(self): # return self._port.stopListening() #配置引數 port = 10000 iface = '127.0.0.1' top_server = service.MultiService() #定義服務容器 fish_server = Fish_Service() #例項化我們的服務 fish_server.setServiceParent(top_server) #把自定義的服務加入到服務容器 factory = Mornitor_Factory(Fish_Service) #工廠化服務 tcp_server = internet.TCPServer(port, factory, interface=iface) #定義tcp服務 tcp_server.setServiceParent(top_server) #把tcp服務加入到服務容器 application = service.Application('Fish_Service') #給應用起個名字 top_server.setServiceParent(application) #把服務容器丟到應用中去
from twisted.protocols import basic from twisted.internet import protocol, defer, task import Get_basic_info_2 as Huoqu import guardian as shouhu import time from twisted.application import service, internet class Monitor_Protocol(basic.LineReceiver): #自定義客戶端和服務端的連線協議,從basic的line繼承 def __init__(self): # pass @staticmethod def huoqu_shuju(): #定義一個函式獲取本機的一些狀態 now = str(time.strftime('%Y-%m-%d %H:%M:%S')) def add_tag(source, tag1, tag2 = 'none'): #定義格式化字串函式 return ':::'.join([now, tag1, tag2, source]) #使用:::分隔時間、簡單資訊、詳細資訊、原始資訊 tcp = add_tag(Huoqu.net_tcp(), 'tcp') cpu = add_tag(Huoqu.cpu(), 'cpu', 'cpu_detail') mem = add_tag(Huoqu.mem(), 'mem', 'mem_detail') disk = add_tag(Huoqu.disk_usage(), 'disk', 'disk_detail') net = add_tag(Huoqu.net_rate(), 'net', 'net_detail') process = add_tag(shouhu.check_alive(), 'process_down', 'process_alived') result = (tcp, cpu, mem, disk, net, process, ) d = defer.Deferred() #使用defered返回結果 d.callback(result) return d def xunhuan(self, list): #定義迴圈傳送函式 for i in list: self.sendLine(i) def fasong(self): #定義程式執行順序,取得資訊後用callback交給傳送函式傳送 self.huoqu_shuju().addCallback(self.xunhuan) def loop(self): #使用twist內建的迴圈函式定義幾秒監控資料傳送到服務端 l = task.LoopingCall(self.fasong) l.start(1) def connectionMade(self): #覆蓋協議的connectmade函式,定義於服務端的連線建立後開始迴圈 print 'Connected!......ok!' self.loop() def lineReceived(self, line): #必須覆蓋接受函式,否則twist會報not importent錯誤! pass class Moinitor_client_factory(protocol.ReconnectingClientFactory): def __init__(self, service): #還沒想要要寫什麼 self.service = service protocol = Monitor_Protocol class Client_Service(service.Service): def __init__(self): pass def startService(self): service.Service.startService(self) #配置檔案開始 port = 10000 host = '127.0.0.1' #守護程序 top_service = service.MultiService() #定義服務容器 client_service = Client_Service() #例項化服務類 client_service.setServiceParent(top_service) #把自己定義的服務丟到服務容器中 factory = Moinitor_client_factory(client_service) #定義服務工廠化 tcp_service = internet.TCPClient(host, port, factory) #定義tcp連線的服務 tcp_service.setServiceParent(top_service) #把tcp服務丟到服務容器中去 application = service.Application('Fish_Service') #定義應用名字 top_service.setServiceParent(application) #把服務容器丟到應用中去
一些自定義監控程式是否存活的指令碼:
program = {'nginx': ['/opt/nginx/logs/nginx.pid', '/opt/nginx/sbin/nginx'], 'rsync-C': ['/var/run/rsyncd.pid', 'rsync --daemon'], } def main(): for k in program: a = get_pid(k, program[k][0]) if isinstance(a, tuple): print '%s is not running!' % k print 'Start the program by Horland_guardian!' subprocess.call(program[k][1], shell=True) else: print 'The %s is running!' % k def check_alive(): l_lived = [] l_downed = [] for k in program: a = get_pid(k, program[k][0]) if isinstance(a, tuple): l_downed.append(k) else: l_lived.append(k) process_alived = ' '.join(l_lived) process_down = ' '.join(l_downed) return '::'.join([process_down, process_alived])
django的使用目前只需要使用到admin模組就可以。
下面是一些程式碼段:
model
class BasicInfo(models.Model):
ipadd = models.IPAddressField(verbose_name = u'IP地址')
time = models.CharField(max_length=50, verbose_name = u'時間')
cpu = models.CharField(max_length=255, blank=True, verbose_name = u'CPU%')
cpu_detail = models.CharField(max_length=255, blank=True, verbose_name = u'CPU詳情')
mem = models.CharField(max_length=255, blank=True, verbose_name = u'記憶體%')
mem_detail = models.CharField(max_length=255, blank=True, verbose_name = u'記憶體詳情')
disk = models.CharField(max_length=255, blank=True, verbose_name = u'磁碟%')
disk_detail = models.CharField(max_length=255, blank=True, verbose_name = u'磁碟詳情')
net = models.CharField(max_length=255, blank=True, verbose_name = u'流量 bytes/s')
net_detail = models.CharField(max_length=1000, blank=True, verbose_name = u'流量詳情')
tcp = models.CharField(max_length=255, blank=True, verbose_name = u'tcp連線狀態')
process_down = models.CharField(max_length=255, blank=True, verbose_name = u'DOWN-程序')
process_alived = models.CharField(max_length=255, blank=True, verbose_name = u'Process_UP')
def Process_DOWN(self):
return '<span style="color: #%s;">%s</span>' % ('ff0000', self.process_down) #拓機的程序用紅色標識
Process_DOWN.allow_tags = True
註冊到admin
class BasicInfo_admin(admin.ModelAdmin):
list_display = ('time', 'cpu', 'cpu_detail', 'mem', 'mem_detail', 'disk', 'disk_detail', 'net', 'net_detail', 'tcp', 'Process_DOWN', 'process_alived')
list_filter = ('ipadd', )
admin.site.register(BasicInfo, BasicInfo_admin)
freemind整理的思路中還有一些功能沒有實現,目前這個只能算個簡單的demon吧,但是基本實現了監控的目的。歡迎大家給我留言!
下面上個django的admin介面截圖吧!
程式碼下載
http://download.csdn.net/detail/qcpm1983/7611579