Zenoss 是一個開源的企業級 IT 基礎設施智能監控軟件,它允許 IT 運維人員通過 Web 界面控制台來監控整個網絡架構的狀態和健康度。通過配置,Zenoss 可以發現和管理公司的服務器、網絡設備等各類資源。最典型的應用包括服務器宕機報警,我們已經實現了利用 Skype API 在服務器報警後自動打電話到運維的手機上。

zenoss

這套系統太好用了,以至於我們希望能將它的報警機制應用到應用層。也就是說,不僅僅是運維可以用,程序開發屌絲也可以強勢插入,比如在程序段錯誤崩潰、php error 時發一條短信給程序員,方便 debug,多麼美好的願景……

遺憾的是,現實總是不盡人意的,Zenoss 沒有提供 API 來讓我們激發報警事件。(好吧,運維把我忽悠了,是有API的,以下內容娛樂一下就算了。)但是,你一定要相信人民群眾的智慧,比如下面這個極其 hack 的方法——

Python 腳本實現 Zenoss 報警

import httplib2
import pprint
import urllib
import sys
client = httplib2.Http(".cache")
 
devicename=sys.argv[1]
componentmsg=sys.argv[2]
summarymsg=sys.argv[3]
 
eventtag=sys.argv[4]
 
# request initial page
loginurl = 'http://zenoss.mydomain.com:8080/zport/acl_users/cookieAuthHelper/login'
headers = {'Referer': 'http://zenoss.mydomain.com:8080/zport/acl_users/cookieAuthHelper/login_form'}
response, content = client.request(loginurl, 'GET', )
 
# log in and set the damn cookie
body = {'__ac_name': 'myapiuser', '__ac_password': 'myapipwd', 'submitted':'true', 'came_from':'http://zenoss.mydomain.com:8080/zport/dmd/index_html?submitted=', 'submitbutton':''}
headers = {'Content-type': 'application/x-www-form-urlencoded'}
response, content = client.request(loginurl, 'POST', headers=headers, body=urllib.urlencode(body))
#pprint.pprint(response)
headers = {'Cookie': response['set-cookie']}
 
# request the IP address
uri = "http://zenoss.mydomain.com:8080/zport/dmd/ZenEventManager/manage_addEvent?device=" + devicename + "&component=" + componentmsg  + "&summary=" + summarymsg + "&severity=5&eventclass=" + eventtag
body_string = ""
(response,content) = client.request(uri=uri,method='GET', body=body_string,headers=headers)
#pprint.pprint(response)
 
print content

系統需求 python 2.x , httplib2 package

使用方法:

python zenossREST.python <<Device Name>> <<Alert Title>> <<Detail Message>> <<Event Tag>>

基本原理就是模擬瀏覽器訪問提交表單行為。默認情況下這段腳本提交一個紅色警戒事件(最高級),你可以修改代碼實現多級警報水平。

為了自己調用方便,我把它改寫成了一個 PHP 類——

PHP 實現 Zenoss 報警

<?php
/**
 * ZenossAlert.php
 *
 * Alert engineers/developer when any error occurs in system.
 *
 * @author     Zeng Xi 
 * @version    SVN: $Id$
 * @date       2012-06-29
 */
class ZenossAlert {
	private $_params = array();
	private $_config = array();
 
	function __construct($params, $config)
	{
		$this->_params = $params;
		$this->_config = $config;
	}
 
 
	function initRequest()
	{
		$loginurl = $this->_config['url'].'/zport/acl_users/cookieAuthHelper/login';
		$referer = $this->_config['url'].'/zport/acl_users/cookieAuthHelper/login_form';
 
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $loginurl);
		curl_setopt($ch, CURLOPT_REFERER, $referer);
 
		$data = curl_exec($ch);
		curl_close($ch);
		return $data;
	}
 
	function getLoginCookie()
	{
		$loginurl = $this->_config['url'].'/zport/acl_users/cookieAuthHelper/login';
 
		$postData = '__ac_name=' . urlencode($this->_config['username']) . '&__ac_password=' . urlencode($this->_config['password']) . '&submitted=' . urlencode('true') . '&came_from=' . urlencode($this->_config['url'].'/zport/dmd/index_html?submitted=') . '&submitbutton=' . urlencode('');
 
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $loginurl);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
		curl_setopt($ch, CURLOPT_HEADER, 1);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
		curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));
 
		$returnData = curl_exec($ch);
		curl_close($ch);
 
		preg_match_all('|Set-Cookie: (.*);|U', $returnData, $results);    
		$cookie = implode(';', $results[1]);
 
		return $cookie;
 
	}
 
	function setAlert()
	{
		$this->initRequest();
		$cookie = $this->getLoginCookie();
		$addEventUrl = $this->_config['url'].'/zport/dmd/ZenEventManager/manage_addEvent?device='.urlencode($this->_params['devicename']).'&component='.urlencode($this->_params['componentmsg']).'&summary='.urlencode($this->_params['summarymsg']).'&severity=5&eventclass='.urlencode($this->_params['eventtag']);
 
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_COOKIE, $cookie);
		curl_setopt($ch, CURLOPT_URL, $addEventUrl);
 
		$data = curl_exec($ch);
		curl_close($ch);
		return $data;
	}
}
?>

用法:

$zenoss_config = array(
	'alertOn' => false,
	'url' => 'http://zenoss.mydomain.com:8080',
	'username' => 'myapiuser',
	'password' => 'myapipwd',
);
$params = array(
	'devicename'=>'Testing_Software',
	'componentmsg'=>'Testing Msg',
	'summarymsg'=>'TestingAlertMsgByXi',
	'eventtag'=>'Testing',
);
 
if($zenoss_config['alertOn'])
{
	$zenoss = new ZenossAlert($params, $zenoss_config);
	$zenoss->setAlert();
}

Enjoy~