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~