diff --git a/report/.gitignore b/report/.gitignore new file mode 100644 index 0000000..48b8bf9 --- /dev/null +++ b/report/.gitignore @@ -0,0 +1 @@ +vendor/ diff --git a/report/composer.json b/report/composer.json new file mode 100644 index 0000000..3bbcb37 --- /dev/null +++ b/report/composer.json @@ -0,0 +1,6 @@ +{ + "require": { + "cosenary/simple-php-cache": "dev-master", + "confirm-it-solutions/php-zabbix-api": "^2.4" + } +} diff --git a/report/composer.lock b/report/composer.lock new file mode 100644 index 0000000..bdab1bc --- /dev/null +++ b/report/composer.lock @@ -0,0 +1,108 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "content-hash": "0ea7dbfb81eedadb45c5f01f143cdd3d", + "packages": [ + { + "name": "confirm-it-solutions/php-zabbix-api", + "version": "v2.4.5", + "source": { + "type": "git", + "url": "https://github.com/confirm/PhpZabbixApi.git", + "reference": "820f635e0c3e4dee418145ad0ba9ef506747757e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/confirm/PhpZabbixApi/zipball/820f635e0c3e4dee418145ad0ba9ef506747757e", + "reference": "820f635e0c3e4dee418145ad0ba9ef506747757e", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "build/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dominique Barton", + "email": "dbarton@confirm.ch", + "homepage": "http://www.confirm.ch", + "role": "Developer" + } + ], + "description": "PhpZabbixApi library", + "homepage": "http://github.com/confirm-it-solutions/PhpZabbixApi", + "keywords": [ + "api", + "zabbix" + ], + "time": "2016-05-12T11:40:53+00:00" + }, + { + "name": "cosenary/simple-php-cache", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/cosenary/Simple-PHP-Cache.git", + "reference": "39607c9307b32248bae2fd6a945183c7249156da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cosenary/Simple-PHP-Cache/zipball/39607c9307b32248bae2fd6a945183c7249156da", + "reference": "39607c9307b32248bae2fd6a945183c7249156da", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.2.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "." + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "authors": [ + { + "name": "Christian Metz", + "email": "christian-metz1@gmx.net", + "homepage": "http://metzweb.net" + } + ], + "description": "A light, simple but powerful PHP5 Cache Class which uses the filesystem for caching.", + "homepage": "https://github.com/cosenary/Simple-PHP-Cache", + "keywords": [ + "Simple", + "cache", + "filesystem", + "json" + ], + "time": "2015-01-03 18:28:23" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "cosenary/simple-php-cache": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/report/control.zaf b/report/control.zaf new file mode 100644 index 0000000..627d8a3 --- /dev/null +++ b/report/control.zaf @@ -0,0 +1,25 @@ + +Plugin: csv + +Description:: + Reporting pluginn for Zabbix. It can generate reports from Zabbix using API calls. +:: + +Version: 0.1 + +Url: https://raw.githubusercontent.com/limosek/zaf-plugins/master/report +Web: https://github.com/limosek/zaf-plugins/ + +# Maintainer +Maintainer: Lukas Macura + +# Dependencies +Depends-dpkg: dash php-cli +Depends-opkg: busybox php +Depends-bin: composer + +Install-files: functions.inc.php +Install-cmd: query +Install: + + diff --git a/report/functions.inc.php b/report/functions.inc.php new file mode 100644 index 0000000..e1bd4f2 --- /dev/null +++ b/report/functions.inc.php @@ -0,0 +1,200 @@ + 'JS', + 'path' => Config::getOpt("cache.dir") . "/", + 'extension' => '.cache' + ) + ); + self::$cache->eraseExpired(); + } + + public function toCache($key,$data,$expiry=false) { + if (!$expiry) { + $expiry=self::$defaultexpiry; + } else { + $expiry=min($expiry,self::$maxexpiry); + } + self::$cache->store($key, $data, $expiry); + } + + public function fromCache($key) { + return(self::$cache->retrieve($key)); + } + + public function apiCall($func, $args) { + $key = serialize($args) . $func . self::$apiurl . self::$apiuser; + $data = self::fromCache($key); + if (!$data) { + $data = self::$api->$func($args); + self::toCache($key, $data); + } + return($data); + } + + public function itemsToArray($items) { + $array = Array(); + foreach ($items as $i) { + $array[$i->key_] = $i->itemid; + } + return($array); + } + + public static function getValue($host, $item, $function, $args) { + $items = self::apiCall("itemGet", array( + "host" => $host, + "search" => Array( + "key_" => $item + ) + ) + ); + if (count($items)<1) { + return(false); + } else { + foreach ($items as $i) { + if ($i->key_==$item) { + break; + } + } + if (!$i) { + return(false); + } + $fromtime = time() - 3600 * 24 * 365; + $history = self::apiCall("historyGet", array( + "history" => $i->value_type, + "time_from" => $fromtime, + "itemids" => $i->itemid, + "sortfield" => "clock", + "sortorder" => "ASC" + )); + switch ($function) { + case "last": + return($history[0]->value); + break; + case "regexp": + foreach ($history as $h) { + if (preg_match("/$args/",$h->value)) { + return("1"); + } + } + return("0"); + break; + case "iregexp": + foreach ($history as $h) { + if (preg_match("/$args/i",$h->value)) { + return("1"); + } + } + return("0"); + break; + case "history": + $out=Array(); + foreach ($history as $h) { + $out[]=$h->value; + } + return(join("\n",$out)); + break; + case "csv": + $out=Array(); + foreach ($history as $h) { + $out[]=$h->value; + } + return(Csv::row($out,true)); + break; + } + return(false); + } + } + + public static function expandMacros($query) { + while (preg_match("/{([^{]*):([^{]*)\.([^{]*)\(([^{]*)\)}/", $query, $matches)) { + $macro = $matches[0]; + $host = $matches[1]; + $item = $matches[2]; + $function = $matches[3]; + $args = $matches[4]; + $value = self::getValue($host,$item,$function,$args); + if ($value===false) { + $value=""; + } + $query = str_replace("{$macro}", $value, $query); + } + return($query); + } + + public static function evalQuery($query) { + if (preg_match('/\((?>[^)(]+|(?R))*\)/',$query,$match)) { + if (substr($match[0],1,1)==" ") { + $subquery=substr(substr($match[0],1),0,strlen($match[0])-2); + Console::debug("subquery: $subquery"); + $sub=self::evalQuery($subquery); + if ($sub) { + $sub="1=1"; + } else { + $sub="1=0"; + } + Console::debug("=$sub\n"); + return( + self::evalQuery(str_replace("($subquery)",$sub,$query)) + ); + } + } + if (preg_match("/ and /",$query)) { + $queries=preg_split("/ and /",$query); + Console::debug("( "); + foreach ($queries as $query) { + Console::debug("and $query "); + if (!self::evalQuery($query)) { + Console::debug(")=false\n"); + return(false); + } + } + Console::debug(")=true\n"); + return(true); + } + if (preg_match("/ or /",$query)) { + $queries=preg_split("/ or /",$query); + Console::debug("( "); + foreach ($queries as $query) { + Console::debug("or $query "); + if (self::evalQuery($query)) { + Console::debug(")=true\n"); + return(true); + } + } + Console::debug("=false\n"); + return(false); + } + if (preg_match("/=/",$query)) { + List($macro,$value)=preg_split("/=/",$query); + $mvalue=self::expandMacros($macro); + return($mvalue == $value); + } elseif (preg_match("//",$query)) { + List($macro,$value)=preg_split("/>/",$query); + $mvalue=self::expandMacros($macro); + return($mvalue > $value); + } else { + Console::error(1,"Not a zabbix query: $query\n"); + } + } + +}