├── HttpServer.py ├── HttpServerManager.py ├── PollManager.py ├── README.md └── WinPollster.py /HttpServer.py: -------------------------------------------------------------------------------- 1 | from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler 2 | from SocketServer import ThreadingMixIn 3 | import threading 4 | import json 5 | from datetime import datetime 6 | import time 7 | import subprocess 8 | import sys 9 | 10 | # Look up the full hostname using gethostbuaddr() is too slow. 11 | import BaseHTTPServer 12 | def not_insance_address_string(self): 13 | host, port = self.client_address[:2] 14 | # Just only return host. 15 | return '%s (no getfqdn)' % host 16 | BaseHTTPServer.BaseHTTPRequestHandler.address_string = not_insance_address_string 17 | 18 | class Handler(BaseHTTPRequestHandler): 19 | content = {'data':'test'} 20 | intvl = 10 21 | 22 | # timestamp of get from host 23 | ts_get = '' 24 | 25 | def do_GET(self): 26 | if self.path == '/getdata': 27 | self.send_response(200) 28 | self.send_header("Content-type", "text/json") 29 | Handler.ts_get = time.asctime(time.localtime()) 30 | t_content = datetime.strptime(Handler.content['timestamp'], "%a %b %d %H:%M:%S %Y") 31 | t_last_get = datetime.strptime(Handler.ts_get, "%a %b %d %H:%M:%S %Y") 32 | if (t_last_get - t_content).seconds < 60: 33 | Handler.content['status'] = 'NORMAL' 34 | else: 35 | Handler.content['status'] = 'POLLING_TIMEOUT' 36 | Handler.content['data'] = {} 37 | obj_str = json.dumps(Handler.content) 38 | self.send_header("Content-Length", str(len(obj_str))) 39 | self.end_headers() 40 | self.wfile.write(obj_str.encode()) 41 | self.wfile.write('\n') 42 | else: 43 | self.send_response(404) 44 | self.end_headers() 45 | 46 | def do_POST(self): 47 | if self.path == '/setdata': 48 | length = self.headers['content-length'] 49 | data = self.rfile.read(int(length)) 50 | Handler.content = eval(data.decode()) 51 | self.send_response(200) 52 | self.end_headers() 53 | self.wfile.write(str(Handler.content)) 54 | self.wfile.write('\n') 55 | else: 56 | self.send_response(404) 57 | self.end_headers() 58 | 59 | class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): 60 | """Handle requests in a separate thread.""" 61 | 62 | # see http://www.techques.com/question/1-153221/Runnning-a-Python-web-server-as-a-service-in-Windows 63 | def serve_forever(self): 64 | self.stop_serving = False 65 | while not self.stop_serving: 66 | self.handle_request() 67 | 68 | def stop (self): 69 | self.stop_serving = True 70 | self.socket.close() 71 | 72 | if __name__ == '__main__': 73 | server = None 74 | try: 75 | server = ThreadedHTTPServer(('0.0.0.0', 8655), Handler) 76 | print 'Starting server, use to stop' 77 | server.serve_forever() 78 | except: 79 | if server: 80 | server.socket.close() 81 | -------------------------------------------------------------------------------- /HttpServerManager.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | import win32serviceutil 3 | import win32service 4 | import win32event 5 | import win32evtlogutil 6 | import time 7 | import traceback 8 | from HttpServer import Handler 9 | from HttpServer import ThreadedHTTPServer 10 | 11 | class HttpServerManager(win32serviceutil.ServiceFramework): 12 | _svc_name_ = "agent_http_server" 13 | _svc_display_name_ = "agent_http_server" 14 | _http_server = None 15 | 16 | def __init__(self, args): 17 | win32serviceutil.ServiceFramework.__init__(self, args) 18 | self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) 19 | self._http_server = ThreadedHTTPServer(('0.0.0.0', 8655), Handler) 20 | print 'Service start.' 21 | 22 | def SvcDoRun(self): 23 | import servicemanager 24 | servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,servicemanager.PYS_SERVICE_STARTED,(self._svc_name_, '')) 25 | self._http_server.serve_forever() 26 | return 27 | 28 | def SvcStop(self): 29 | self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) 30 | self._http_server.stop() 31 | win32event.SetEvent(self.hWaitStop) 32 | print 'Service stop' 33 | return 34 | 35 | if __name__=='__main__': 36 | win32serviceutil.HandleCommandLine(HttpServerManager) 37 | -------------------------------------------------------------------------------- /PollManager.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | import win32serviceutil 3 | import win32service 4 | import win32event 5 | import win32evtlogutil 6 | import time 7 | import json 8 | import urllib2 9 | import traceback 10 | from WinPollster import WinPollster 11 | 12 | def wr_data(url, obj): 13 | '''Write data/parameter through HttpServer.''' 14 | data = json.dumps(obj) 15 | res = None 16 | try: 17 | req = urllib2.Request(url, data, {'Content-Type': 'application/json'}) 18 | res = urllib2.urlopen(req, timeout=5) 19 | return res.read() 20 | except Exception, err: 21 | return False 22 | finally: 23 | if res: 24 | res.close() 25 | 26 | class PollManager(win32serviceutil.ServiceFramework): 27 | _svc_name_ = "agent_poll_manager" 28 | _svc_display_name_ = "agent_poll_manager" 29 | _wp = None 30 | _wr_url = None 31 | _poll_intvl = None 32 | 33 | def __init__(self, args): 34 | win32serviceutil.ServiceFramework.__init__(self, args) 35 | self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) 36 | self._wr_url = 'http://127.0.0.1:8655/' 37 | self._wp = WinPollster() 38 | self._poll_intvl = 20 39 | print 'Service start.' 40 | 41 | def SvcDoRun(self): 42 | import servicemanager 43 | servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,servicemanager.PYS_SERVICE_STARTED,(self._svc_name_, '')) 44 | 45 | self.timeout=100 46 | while True: 47 | rc=win32event.WaitForSingleObject(self.hWaitStop,self.timeout) 48 | 49 | if rc == win32event.WAIT_OBJECT_0: 50 | break 51 | else: 52 | wr_obj = self._wp.combine() 53 | if wr_obj: 54 | wr_data('%s%s' %(self._wr_url, 'setdata'), wr_obj) 55 | time.sleep(self._poll_intvl) 56 | return 57 | 58 | 59 | def SvcStop(self): 60 | self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) 61 | win32event.SetEvent(self.hWaitStop) 62 | print 'Service stop' 63 | return 64 | 65 | if __name__=='__main__': 66 | win32serviceutil.HandleCommandLine(PollManager) 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #wmiagent 2 | 3 | A Windows monitor agent. Fetch data by using WMI(Windows Management Instrumentation). 4 | 5 | ##Requirement: 6 | 1. [WMI Administrative Tools](http://www.microsoft.com/en-us/download/details.aspx?id=24045) 7 | 2. [Python Win32 Extension](http://sourceforge.net/projects/pywin32/) 8 | 3. [Python WMI](https://pypi.python.org/pypi/WMI) 9 | 10 | ##Usage: 11 | 12 | ###1. Start Polling task 13 | python PollManager.py install 14 | python PollManager.py start 15 | 16 | ###2. Start Http Service 17 | python HttpServerManager.py install 18 | python HttpServerManager.py start 19 | 20 | Then, you can see and manage them in Windows Server Manager. 21 | 22 | ###3. Stop Polling task 23 | python PollManager.py stop 24 | 25 | ###4. Stop Http Service 26 | python HttpServerManager.py stop 27 | 28 | Edit by Kevin Shaw dysj4099@gmail.com 29 | -------------------------------------------------------------------------------- /WinPollster.py: -------------------------------------------------------------------------------- 1 | import wmi 2 | import os 3 | import sys 4 | import platform 5 | import time 6 | import traceback 7 | import win32com.client as client 8 | 9 | class WinPollster(object): 10 | _c = None 11 | _cs = None 12 | _os = None 13 | _pfu = None 14 | _com = None 15 | _obj = None 16 | 17 | hostname = None 18 | ipaddress = None 19 | def __init__(self): 20 | self._c = wmi.WMI() 21 | self._com = client.Dispatch("WbemScripting.SWbemRefresher") 22 | self._obj = client.GetObject("winmgmts:\\root\cimv2") 23 | self._cs = self._c.Win32_ComputerSystem() 24 | self._os = self._c.Win32_OperatingSystem() 25 | self._pfu = self._c.Win32_PageFileUsage() 26 | self.hostname = self._os[0].CSName 27 | 28 | def get_cpu(self): 29 | data_dict = {} 30 | cpu_usage_total = 0 31 | 32 | for cpu in self._c.Win32_Processor(): 33 | device = cpu.DeviceID.lower() 34 | data_dict[device] = {'volume':float(cpu.LoadPercentage), 'unit':'%'} 35 | cpu_usage_total += float(cpu.LoadPercentage) 36 | 37 | data_dict['cpu'] = {'volume':cpu_usage_total/len(data_dict), 'unit':'%'} 38 | return {'data':data_dict, 'timestamp':time.asctime(time.localtime())} 39 | 40 | def get_mem(self): 41 | data_dict = {} 42 | data_dict["MemTotal"] = {'volume':float(self._cs[0].TotalPhysicalMemory) / (1024*1024), 'unit':'MB'} 43 | data_dict["MemFree"] = {'volume':float(self._os[0].FreePhysicalMemory)/1024, 'unit':'MB'} 44 | data_dict["Cached"] = {'volume':0, 'unit':'MB'} 45 | data_dict["Buffers"] = {'volume':0, 'unit':'MB'} 46 | data_dict["SwapTotal"] = {'volume':float(self._pfu[0].AllocatedBaseSize), 'unit':'MB'} 47 | data_dict["SwapFree"] = {'volume':float(self._pfu[0].AllocatedBaseSize - self._pfu[0].CurrentUsage), 'unit':'MB'} 48 | return {'data':data_dict, 'timestamp':time.asctime(time.localtime())} 49 | 50 | def get_disk(self): 51 | diskitems = self._com.AddEnum(self._obj, "Win32_PerfFormattedData_PerfDisk_LogicalDisk").objectSet 52 | 53 | data_dict = {} 54 | data_dict['total_available'] = 0 55 | data_dict['total_capacity'] = 0 56 | data_dict['total_free'] = 0 57 | 58 | # DriveType=3 : "Local Disk", 59 | for disk in self._c.Win32_LogicalDisk (DriveType=3): 60 | data_dict['total_available'] += round(float(disk.FreeSpace) / (1024*1024*1024), 2) 61 | data_dict['total_capacity'] += round(float(disk.Size) / (1024*1024*1024), 2) 62 | data_dict['total_free'] += round(float(disk.FreeSpace) / (1024*1024*1024), 2) 63 | 64 | dev_tmp = {} 65 | dev_tmp['dev'] = disk.DeviceID 66 | dev_tmp['available'] = {'volume':round(float(disk.FreeSpace) / (1024*1024*1024), 2), 'unit':'GB'} 67 | dev_tmp['capacity'] = {'volume':round(float(disk.Size) / (1024*1024*1024), 2), 'unit':'GB'} 68 | dev_tmp['free'] = {'volume':round(float(disk.FreeSpace) / (1024*1024*1024), 2), 'unit':'GB'} 69 | dev_tmp['fstype'] = disk.FileSystem 70 | dev_tmp['mnt'] = '' 71 | dev_tmp['used'] = round(long(disk.FreeSpace) / long(disk.Size), 2) 72 | 73 | data_dict[disk.DeviceID] = dev_tmp 74 | 75 | self._com.Refresh() 76 | for item in diskitems: 77 | if item.Name in data_dict: 78 | data_dict[item.Name]['io_stat'] = {} 79 | data_dict[item.Name]['io_stat']['r/s'] = {'volume':float(item.DiskReadsPerSec), 'unit':''} 80 | data_dict[item.Name]['io_stat']['w/s'] = {'volume':float(item.DiskWritesPerSec), 'unit':''} 81 | data_dict[item.Name]['io_stat']['rkB/s'] = {'volume':(float(item.DiskReadBytesPerSec) / 1024), 'unit':'KB/s'} 82 | data_dict[item.Name]['io_stat']['wkB/s'] = {'volume':(float(item.DiskWriteBytesPerSec) / 1024), 'unit':'KB/s'} 83 | return {'data':data_dict, 'timestamp':time.asctime(time.localtime())} 84 | 85 | def get_net(self): 86 | items = self._com.AddEnum(self._obj, "Win32_PerfRawData_Tcpip_NetworkInterface").objectSet 87 | 88 | data_dict = {} 89 | interfaces = [] 90 | for interface in self._c.Win32_NetworkAdapterConfiguration (IPEnabled=1): 91 | if interface.IPAddress[0]: 92 | self.ipaddress = interface.IPAddress[0] 93 | interfaces.append(interface.Description) 94 | 95 | net_bytes_in = 0 96 | net_bytes_out = 0 97 | net_pkts_in = 0 98 | net_pkts_out = 0 99 | 100 | self._com.Refresh() 101 | for item in items: 102 | if item.Name in interfaces: 103 | net_bytes_in += long(item.BytesReceivedPerSec) 104 | net_bytes_out += long(item.BytesSentPerSec) 105 | net_pkts_in += long(item.PacketsReceivedPerSec) 106 | net_pkts_out += long(item.PacketsSentPerSec) 107 | 108 | time.sleep(1) 109 | 110 | net_bytes_in_cur = 0 111 | net_bytes_out_cur = 0 112 | 113 | self._com.Refresh() 114 | for item in items: 115 | if item.Name in interfaces: 116 | net_bytes_in = long(item.BytesReceivedPerSec) - net_bytes_in 117 | net_bytes_in_cur += long(item.BytesReceivedPerSec) 118 | net_bytes_out = long(item.BytesSentPerSec) - net_bytes_out 119 | net_bytes_out_cur += long(item.BytesSentPerSec) 120 | net_pkts_in = long(item.PacketsReceivedPerSec) - net_pkts_in 121 | net_pkts_out = long(item.PacketsSentPerSec) - net_pkts_out 122 | 123 | data_dict['net_bytes_in'] = {'volume':net_bytes_in, 'unit':'B/s'} 124 | data_dict['net_bytes_in_sum'] = {'volume':net_bytes_in_cur, 'unit':'B'} 125 | data_dict['net_bytes_out'] = {'volume':net_bytes_out, 'unit':'B/s'} 126 | data_dict['net_bytes_out_sum'] = {'volume':net_bytes_out_cur, 'unit':'B'} 127 | data_dict['net_pkts_in'] = {'volume':net_pkts_in, 'unit':'p/s'} 128 | data_dict['net_pkts_out'] = {'volume':net_pkts_out, 'unit':'p/s'} 129 | 130 | return {'data':data_dict, 'timestamp':time.asctime(time.localtime())} 131 | 132 | def combine(self): 133 | combine_data = {} 134 | combine_data['data'] = {} 135 | combine_data['hostname'] = self.hostname 136 | try: 137 | combine_data['data']['CPUUsagePollster'] = self.get_cpu() 138 | combine_data['data']['DiskUsagePollster'] = self.get_disk() 139 | combine_data['data']['MemInfoPollster'] = self.get_mem() 140 | combine_data['data']['NetStatPollster'] = self.get_net() 141 | 142 | if self.ipaddress: 143 | combine_data['ip_address'] = self.ipaddress 144 | else: 145 | combine_data['ip_address'] = '127.0.0.1' 146 | combine_data['status'] = 'NORMAL' 147 | except Exception,err: 148 | print err 149 | print traceback.format_exc() 150 | combine_data['status'] = 'ERROR' 151 | finally: 152 | combine_data['timestamp'] = time.asctime(time.localtime()) 153 | return combine_data 154 | 155 | if __name__=='__main__': 156 | wp = WinPollster() 157 | print wp.combine() 158 | 159 | 160 | --------------------------------------------------------------------------------