refactor: move zabbix modules
This commit is contained in:
266
src/datasource-zabbix/zabbix/connectors/sql/zabbixDBConnector.js
Normal file
266
src/datasource-zabbix/zabbix/connectors/sql/zabbixDBConnector.js
Normal file
@@ -0,0 +1,266 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
const DEFAULT_QUERY_LIMIT = 10000;
|
||||
const HISTORY_TO_TABLE_MAP = {
|
||||
'0': 'history',
|
||||
'1': 'history_str',
|
||||
'2': 'history_log',
|
||||
'3': 'history_uint',
|
||||
'4': 'history_text'
|
||||
};
|
||||
|
||||
const TREND_TO_TABLE_MAP = {
|
||||
'0': 'trends',
|
||||
'3': 'trends_uint'
|
||||
};
|
||||
|
||||
const consolidateByFunc = {
|
||||
'avg': 'AVG',
|
||||
'min': 'MIN',
|
||||
'max': 'MAX',
|
||||
'sum': 'SUM',
|
||||
'count': 'COUNT'
|
||||
};
|
||||
|
||||
const consolidateByTrendColumns = {
|
||||
'avg': 'value_avg',
|
||||
'min': 'value_min',
|
||||
'max': 'value_max'
|
||||
};
|
||||
|
||||
export class ZabbixDBConnector {
|
||||
|
||||
constructor(sqlDataSourceId, options, backendSrv, datasourceSrv) {
|
||||
this.backendSrv = backendSrv;
|
||||
this.datasourceSrv = datasourceSrv;
|
||||
|
||||
let limit = options.limit;
|
||||
this.sqlDataSourceId = sqlDataSourceId;
|
||||
this.limit = limit || DEFAULT_QUERY_LIMIT;
|
||||
|
||||
this.loadSQLDataSource(sqlDataSourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to load DS with given id to check it's exist.
|
||||
* @param {*} datasourceId ID of SQL data source
|
||||
*/
|
||||
loadSQLDataSource(datasourceId) {
|
||||
let ds = _.find(this.datasourceSrv.getAll(), {'id': datasourceId});
|
||||
if (ds) {
|
||||
return this.datasourceSrv.loadDatasource(ds.name)
|
||||
.then(ds => {
|
||||
this.sqlDataSourceType = ds.meta.id;
|
||||
return ds;
|
||||
});
|
||||
} else {
|
||||
return Promise.reject(`SQL Data Source with ID ${datasourceId} not found`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to invoke test query for one of Zabbix database tables.
|
||||
*/
|
||||
testSQLDataSource() {
|
||||
let testQuery = TEST_MYSQL_QUERY;
|
||||
if (this.sqlDataSourceType === 'postgres') {
|
||||
testQuery = TEST_POSTGRES_QUERY;
|
||||
}
|
||||
return this.invokeSQLQuery(testQuery);
|
||||
}
|
||||
|
||||
getHistory(items, timeFrom, timeTill, options) {
|
||||
let {intervalMs, consolidateBy} = options;
|
||||
let intervalSec = Math.ceil(intervalMs / 1000);
|
||||
|
||||
consolidateBy = consolidateBy || 'avg';
|
||||
let aggFunction = consolidateByFunc[consolidateBy];
|
||||
|
||||
// Group items by value type and perform request for each value type
|
||||
let grouped_items = _.groupBy(items, 'value_type');
|
||||
let promises = _.map(grouped_items, (items, value_type) => {
|
||||
let itemids = _.map(items, 'itemid').join(', ');
|
||||
let table = HISTORY_TO_TABLE_MAP[value_type];
|
||||
|
||||
let dialect = this.sqlDataSourceType;
|
||||
let query = buildSQLHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, dialect);
|
||||
|
||||
query = compactSQLQuery(query);
|
||||
return this.invokeSQLQuery(query);
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(results => {
|
||||
return _.flatten(results);
|
||||
});
|
||||
}
|
||||
|
||||
getTrends(items, timeFrom, timeTill, options) {
|
||||
let {intervalMs, consolidateBy} = options;
|
||||
let intervalSec = Math.ceil(intervalMs / 1000);
|
||||
|
||||
consolidateBy = consolidateBy || 'avg';
|
||||
let aggFunction = consolidateByFunc[consolidateBy];
|
||||
|
||||
// Group items by value type and perform request for each value type
|
||||
let grouped_items = _.groupBy(items, 'value_type');
|
||||
let promises = _.map(grouped_items, (items, value_type) => {
|
||||
let itemids = _.map(items, 'itemid').join(', ');
|
||||
let table = TREND_TO_TABLE_MAP[value_type];
|
||||
let valueColumn = _.includes(['avg', 'min', 'max'], consolidateBy) ? consolidateBy : 'avg';
|
||||
valueColumn = consolidateByTrendColumns[valueColumn];
|
||||
|
||||
let dialect = this.sqlDataSourceType;
|
||||
let query = buildSQLTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn, dialect);
|
||||
|
||||
query = compactSQLQuery(query);
|
||||
return this.invokeSQLQuery(query);
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(results => {
|
||||
return _.flatten(results);
|
||||
});
|
||||
}
|
||||
|
||||
handleGrafanaTSResponse(history, items, addHostName = true) {
|
||||
return convertGrafanaTSResponse(history, items, addHostName);
|
||||
}
|
||||
|
||||
invokeSQLQuery(query) {
|
||||
let queryDef = {
|
||||
refId: 'A',
|
||||
format: 'time_series',
|
||||
datasourceId: this.sqlDataSourceId,
|
||||
rawSql: query,
|
||||
maxDataPoints: this.limit
|
||||
};
|
||||
|
||||
return this.backendSrv.datasourceRequest({
|
||||
url: '/api/tsdb/query',
|
||||
method: 'POST',
|
||||
data: {
|
||||
queries: [queryDef],
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
let results = response.data.results;
|
||||
if (results['A']) {
|
||||
return results['A'].series;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function convertGrafanaTSResponse(time_series, items, addHostName) {
|
||||
var hosts = _.uniqBy(_.flatten(_.map(items, 'hosts')), 'hostid'); //uniqBy is needed to deduplicate
|
||||
let grafanaSeries = _.map(time_series, series => {
|
||||
let itemid = series.name;
|
||||
var item = _.find(items, {'itemid': itemid});
|
||||
var alias = item.name;
|
||||
if (_.keys(hosts).length > 1 && addHostName) { //only when actual multi hosts selected
|
||||
var host = _.find(hosts, {'hostid': item.hostid});
|
||||
alias = host.name + ": " + alias;
|
||||
}
|
||||
// zabbixCachingProxy deduplicates requests and returns one time series for equal queries.
|
||||
// Clone is needed to prevent changing of series object shared between all targets.
|
||||
let datapoints = _.cloneDeep(series.points);
|
||||
return {
|
||||
target: alias,
|
||||
datapoints: datapoints
|
||||
};
|
||||
});
|
||||
|
||||
return _.sortBy(grafanaSeries, 'target');
|
||||
}
|
||||
|
||||
function compactSQLQuery(query) {
|
||||
return query.replace(/\s+/g, ' ');
|
||||
}
|
||||
|
||||
function buildSQLHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, dialect = 'mysql') {
|
||||
if (dialect === 'postgres') {
|
||||
return buildPostgresHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction);
|
||||
} else {
|
||||
return buildMysqlHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction);
|
||||
}
|
||||
}
|
||||
|
||||
function buildSQLTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn, dialect = 'mysql') {
|
||||
if (dialect === 'postgres') {
|
||||
return buildPostgresTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn);
|
||||
} else {
|
||||
return buildMysqlTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn);
|
||||
}
|
||||
}
|
||||
|
||||
///////////
|
||||
// MySQL //
|
||||
///////////
|
||||
|
||||
function buildMysqlHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
||||
let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;
|
||||
let query = `
|
||||
SELECT itemid AS metric, ${time_expression} AS time_sec, ${aggFunction}(value) AS value
|
||||
FROM ${table}
|
||||
WHERE itemid IN (${itemids})
|
||||
AND clock > ${timeFrom} AND clock < ${timeTill}
|
||||
GROUP BY ${time_expression}, metric
|
||||
ORDER BY time_sec ASC
|
||||
`;
|
||||
return query;
|
||||
}
|
||||
|
||||
function buildMysqlTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
||||
let time_expression = `clock DIV ${intervalSec} * ${intervalSec}`;
|
||||
let query = `
|
||||
SELECT itemid AS metric, ${time_expression} AS time_sec, ${aggFunction}(${valueColumn}) AS value
|
||||
FROM ${table}
|
||||
WHERE itemid IN (${itemids})
|
||||
AND clock > ${timeFrom} AND clock < ${timeTill}
|
||||
GROUP BY ${time_expression}, metric
|
||||
ORDER BY time_sec ASC
|
||||
`;
|
||||
return query;
|
||||
}
|
||||
|
||||
const TEST_MYSQL_QUERY = `SELECT itemid AS metric, clock AS time_sec, value_avg AS value FROM trends_uint LIMIT 1`;
|
||||
|
||||
////////////////
|
||||
// PostgreSQL //
|
||||
////////////////
|
||||
|
||||
const itemid_format = 'FM99999999999999999999';
|
||||
|
||||
function buildPostgresHistoryQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction) {
|
||||
let time_expression = `clock / ${intervalSec} * ${intervalSec}`;
|
||||
let query = `
|
||||
SELECT to_char(itemid, '${itemid_format}') AS metric, ${time_expression} AS time, ${aggFunction}(value) AS value
|
||||
FROM ${table}
|
||||
WHERE itemid IN (${itemids})
|
||||
AND clock > ${timeFrom} AND clock < ${timeTill}
|
||||
GROUP BY 1, 2
|
||||
ORDER BY time ASC
|
||||
`;
|
||||
return query;
|
||||
}
|
||||
|
||||
function buildPostgresTrendsQuery(itemids, table, timeFrom, timeTill, intervalSec, aggFunction, valueColumn) {
|
||||
let time_expression = `clock / ${intervalSec} * ${intervalSec}`;
|
||||
let query = `
|
||||
SELECT to_char(itemid, '${itemid_format}') AS metric, ${time_expression} AS time, ${aggFunction}(${valueColumn}) AS value
|
||||
FROM ${table}
|
||||
WHERE itemid IN (${itemids})
|
||||
AND clock > ${timeFrom} AND clock < ${timeTill}
|
||||
GROUP BY 1, 2
|
||||
ORDER BY time ASC
|
||||
`;
|
||||
return query;
|
||||
}
|
||||
|
||||
const TEST_POSTGRES_QUERY = `
|
||||
SELECT to_char(itemid, '${itemid_format}') AS metric, clock AS time, value_avg AS value
|
||||
FROM trends_uint LIMIT 1
|
||||
`;
|
||||
46
src/datasource-zabbix/zabbix/connectors/zabbixConnector.js
Normal file
46
src/datasource-zabbix/zabbix/connectors/zabbixConnector.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Base class for all Zabbix connectors
|
||||
*/
|
||||
|
||||
export default class ZabbixConnector {
|
||||
|
||||
constructor() {}
|
||||
|
||||
testDataSource() {}
|
||||
|
||||
getHistory() {}
|
||||
|
||||
getTrends() {}
|
||||
|
||||
getGroups() {}
|
||||
|
||||
getHosts() {}
|
||||
|
||||
getApps() {}
|
||||
|
||||
getItems() {}
|
||||
|
||||
getItemsByIDs() {}
|
||||
|
||||
getMacros() {}
|
||||
|
||||
getGlobalMacros() {}
|
||||
|
||||
getLastValue() {}
|
||||
|
||||
getTriggers() {}
|
||||
|
||||
getEvents() {}
|
||||
|
||||
getAlerts() {}
|
||||
|
||||
getHostAlerts() {}
|
||||
|
||||
getAcknowledges() {}
|
||||
|
||||
getITService() {}
|
||||
|
||||
getSLA() {}
|
||||
|
||||
getVersion() {}
|
||||
}
|
||||
@@ -0,0 +1,484 @@
|
||||
import _ from 'lodash';
|
||||
import * as utils from '../../../utils';
|
||||
import { ZabbixAPICoreService } from './zabbixAPICore';
|
||||
|
||||
/**
|
||||
* Zabbix API Wrapper.
|
||||
* Creates Zabbix API instance with given parameters (url, credentials and other).
|
||||
* Wraps API calls and provides high-level methods.
|
||||
*/
|
||||
export class ZabbixAPIConnector {
|
||||
|
||||
/** @ngInject */
|
||||
constructor(api_url, username, password, basicAuth, withCredentials, backendSrv) {
|
||||
this.url = api_url;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.auth = "";
|
||||
|
||||
this.requestOptions = {
|
||||
basicAuth: basicAuth,
|
||||
withCredentials: withCredentials
|
||||
};
|
||||
|
||||
this.loginPromise = null;
|
||||
this.loginErrorCount = 0;
|
||||
this.maxLoginAttempts = 3;
|
||||
|
||||
this.zabbixAPICore = new ZabbixAPICoreService(backendSrv);
|
||||
|
||||
this.getTrend = this.getTrend_ZBXNEXT1193;
|
||||
//getTrend = getTrend_30;
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Core method wrappers //
|
||||
//////////////////////////
|
||||
|
||||
request(method, params) {
|
||||
return this.zabbixAPICore.request(this.url, method, params, this.requestOptions, this.auth)
|
||||
.catch(error => {
|
||||
if (isNotAuthorized(error.data)) {
|
||||
// Handle auth errors
|
||||
this.loginErrorCount++;
|
||||
if (this.loginErrorCount > this.maxLoginAttempts) {
|
||||
this.loginErrorCount = 0;
|
||||
return null;
|
||||
} else {
|
||||
return this.loginOnce()
|
||||
.then(() => this.request(method, params));
|
||||
}
|
||||
} else {
|
||||
// Handle API errors
|
||||
let message = error.data ? error.data : error.statusText;
|
||||
return Promise.reject(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* When API unauthenticated or auth token expired each request produce login()
|
||||
* call. But auth token is common to all requests. This function wraps login() method
|
||||
* and call it once. If login() already called just wait for it (return its promise).
|
||||
* @return login promise
|
||||
*/
|
||||
loginOnce() {
|
||||
if (!this.loginPromise) {
|
||||
this.loginPromise = Promise.resolve(
|
||||
this.login().then(auth => {
|
||||
this.auth = auth;
|
||||
this.loginPromise = null;
|
||||
return auth;
|
||||
})
|
||||
);
|
||||
}
|
||||
return this.loginPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authentication token.
|
||||
*/
|
||||
login() {
|
||||
return this.zabbixAPICore.login(this.url, this.username, this.password, this.requestOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Zabbix API version
|
||||
*/
|
||||
getVersion() {
|
||||
return this.zabbixAPICore.getVersion(this.url, this.requestOptions);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// Zabbix API method wrappers //
|
||||
////////////////////////////////
|
||||
|
||||
acknowledgeEvent(eventid, message) {
|
||||
var params = {
|
||||
eventids: eventid,
|
||||
message: message
|
||||
};
|
||||
|
||||
return this.request('event.acknowledge', params);
|
||||
}
|
||||
|
||||
getGroups() {
|
||||
var params = {
|
||||
output: ['name'],
|
||||
sortfield: 'name',
|
||||
real_hosts: true
|
||||
};
|
||||
|
||||
return this.request('hostgroup.get', params);
|
||||
}
|
||||
|
||||
getHosts(groupids) {
|
||||
var params = {
|
||||
output: ['name', 'host'],
|
||||
sortfield: 'name'
|
||||
};
|
||||
if (groupids) {
|
||||
params.groupids = groupids;
|
||||
}
|
||||
|
||||
return this.request('host.get', params);
|
||||
}
|
||||
|
||||
getApps(hostids) {
|
||||
var params = {
|
||||
output: 'extend',
|
||||
hostids: hostids
|
||||
};
|
||||
|
||||
return this.request('application.get', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Zabbix items
|
||||
* @param {[type]} hostids host ids
|
||||
* @param {[type]} appids application ids
|
||||
* @param {String} itemtype 'num' or 'text'
|
||||
* @return {[type]} array of items
|
||||
*/
|
||||
getItems(hostids, appids, itemtype) {
|
||||
var params = {
|
||||
output: [
|
||||
'name', 'key_',
|
||||
'value_type',
|
||||
'hostid',
|
||||
'status',
|
||||
'state'
|
||||
],
|
||||
sortfield: 'name',
|
||||
webitems: true,
|
||||
filter: {},
|
||||
selectHosts: ['hostid', 'name']
|
||||
};
|
||||
if (hostids) {
|
||||
params.hostids = hostids;
|
||||
}
|
||||
if (appids) {
|
||||
params.applicationids = appids;
|
||||
}
|
||||
if (itemtype === 'num') {
|
||||
// Return only numeric metrics
|
||||
params.filter.value_type = [0, 3];
|
||||
}
|
||||
if (itemtype === 'text') {
|
||||
// Return only text metrics
|
||||
params.filter.value_type = [1, 2, 4];
|
||||
}
|
||||
|
||||
return this.request('item.get', params)
|
||||
.then(utils.expandItems);
|
||||
}
|
||||
|
||||
getItemsByIDs(itemids) {
|
||||
var params = {
|
||||
itemids: itemids,
|
||||
output: [
|
||||
'name', 'key_',
|
||||
'value_type',
|
||||
'hostid',
|
||||
'status',
|
||||
'state'
|
||||
],
|
||||
webitems: true,
|
||||
selectHosts: ['hostid', 'name']
|
||||
};
|
||||
|
||||
return this.request('item.get', params)
|
||||
.then(utils.expandItems);
|
||||
}
|
||||
|
||||
getMacros(hostids) {
|
||||
var params = {
|
||||
output: 'extend',
|
||||
hostids: hostids
|
||||
};
|
||||
|
||||
return this.request('usermacro.get', params);
|
||||
}
|
||||
|
||||
getGlobalMacros() {
|
||||
var params = {
|
||||
output: 'extend',
|
||||
globalmacro: true
|
||||
};
|
||||
|
||||
return this.request('usermacro.get', params);
|
||||
}
|
||||
|
||||
getLastValue(itemid) {
|
||||
var params = {
|
||||
output: ['lastvalue'],
|
||||
itemids: itemid
|
||||
};
|
||||
return this.request('item.get', params)
|
||||
.then(items => items.length ? items[0].lastvalue : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform history query from Zabbix API
|
||||
*
|
||||
* @param {Array} items Array of Zabbix item objects
|
||||
* @param {Number} timeFrom Time in seconds
|
||||
* @param {Number} timeTill Time in seconds
|
||||
* @return {Array} Array of Zabbix history objects
|
||||
*/
|
||||
getHistory(items, timeFrom, timeTill) {
|
||||
|
||||
// Group items by value type and perform request for each value type
|
||||
let grouped_items = _.groupBy(items, 'value_type');
|
||||
let promises = _.map(grouped_items, (items, value_type) => {
|
||||
let itemids = _.map(items, 'itemid');
|
||||
let params = {
|
||||
output: 'extend',
|
||||
history: value_type,
|
||||
itemids: itemids,
|
||||
sortfield: 'clock',
|
||||
sortorder: 'ASC',
|
||||
time_from: timeFrom
|
||||
};
|
||||
|
||||
// Relative queries (e.g. last hour) don't include an end time
|
||||
if (timeTill) {
|
||||
params.time_till = timeTill;
|
||||
}
|
||||
|
||||
return this.request('history.get', params);
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(_.flatten);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform trends query from Zabbix API
|
||||
* Use trends api extension from ZBXNEXT-1193 patch.
|
||||
*
|
||||
* @param {Array} items Array of Zabbix item objects
|
||||
* @param {Number} time_from Time in seconds
|
||||
* @param {Number} time_till Time in seconds
|
||||
* @return {Array} Array of Zabbix trend objects
|
||||
*/
|
||||
getTrend_ZBXNEXT1193(items, timeFrom, timeTill) {
|
||||
|
||||
// Group items by value type and perform request for each value type
|
||||
let grouped_items = _.groupBy(items, 'value_type');
|
||||
let promises = _.map(grouped_items, (items, value_type) => {
|
||||
let itemids = _.map(items, 'itemid');
|
||||
let params = {
|
||||
output: 'extend',
|
||||
trend: value_type,
|
||||
itemids: itemids,
|
||||
sortfield: 'clock',
|
||||
sortorder: 'ASC',
|
||||
time_from: timeFrom
|
||||
};
|
||||
|
||||
// Relative queries (e.g. last hour) don't include an end time
|
||||
if (timeTill) {
|
||||
params.time_till = timeTill;
|
||||
}
|
||||
|
||||
return this.request('trend.get', params);
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(_.flatten);
|
||||
}
|
||||
|
||||
getTrend_30(items, time_from, time_till, value_type) {
|
||||
var self = this;
|
||||
var itemids = _.map(items, 'itemid');
|
||||
|
||||
var params = {
|
||||
output: ["itemid",
|
||||
"clock",
|
||||
value_type
|
||||
],
|
||||
itemids: itemids,
|
||||
time_from: time_from
|
||||
};
|
||||
|
||||
// Relative queries (e.g. last hour) don't include an end time
|
||||
if (time_till) {
|
||||
params.time_till = time_till;
|
||||
}
|
||||
|
||||
return self.request('trend.get', params);
|
||||
}
|
||||
|
||||
getITService(serviceids) {
|
||||
var params = {
|
||||
output: 'extend',
|
||||
serviceids: serviceids
|
||||
};
|
||||
return this.request('service.get', params);
|
||||
}
|
||||
|
||||
getSLA(serviceids, timeRange) {
|
||||
let [timeFrom, timeTo] = timeRange;
|
||||
var params = {
|
||||
serviceids: serviceids,
|
||||
intervals: [{
|
||||
from: timeFrom,
|
||||
to: timeTo
|
||||
}]
|
||||
};
|
||||
return this.request('service.getsla', params);
|
||||
}
|
||||
|
||||
getTriggers(groupids, hostids, applicationids, options) {
|
||||
let {showTriggers, maintenance, timeFrom, timeTo} = options;
|
||||
|
||||
let params = {
|
||||
output: 'extend',
|
||||
groupids: groupids,
|
||||
hostids: hostids,
|
||||
applicationids: applicationids,
|
||||
expandDescription: true,
|
||||
expandData: true,
|
||||
expandComment: true,
|
||||
monitored: true,
|
||||
skipDependent: true,
|
||||
//only_true: true,
|
||||
filter: {
|
||||
value: 1
|
||||
},
|
||||
selectGroups: ['name'],
|
||||
selectHosts: ['name', 'host', 'maintenance_status'],
|
||||
selectItems: ['name', 'key_', 'lastvalue'],
|
||||
selectLastEvent: 'extend',
|
||||
selectTags: 'extend'
|
||||
};
|
||||
|
||||
if (showTriggers) {
|
||||
params.filter.value = showTriggers;
|
||||
}
|
||||
|
||||
if (maintenance) {
|
||||
params.maintenance = true;
|
||||
}
|
||||
|
||||
if (timeFrom || timeTo) {
|
||||
params.lastChangeSince = timeFrom;
|
||||
params.lastChangeTill = timeTo;
|
||||
}
|
||||
|
||||
return this.request('trigger.get', params);
|
||||
}
|
||||
|
||||
getEvents(objectids, timeFrom, timeTo, showEvents) {
|
||||
var params = {
|
||||
output: 'extend',
|
||||
time_from: timeFrom,
|
||||
time_till: timeTo,
|
||||
objectids: objectids,
|
||||
select_acknowledges: 'extend',
|
||||
selectHosts: 'extend',
|
||||
value: showEvents
|
||||
};
|
||||
|
||||
return this.request('event.get', params);
|
||||
}
|
||||
|
||||
getAcknowledges(eventids) {
|
||||
var params = {
|
||||
output: 'extend',
|
||||
eventids: eventids,
|
||||
preservekeys: true,
|
||||
select_acknowledges: 'extend',
|
||||
sortfield: 'clock',
|
||||
sortorder: 'DESC'
|
||||
};
|
||||
|
||||
return this.request('event.get', params)
|
||||
.then(events => {
|
||||
return _.filter(events, (event) => event.acknowledges.length);
|
||||
});
|
||||
}
|
||||
|
||||
getAlerts(itemids, timeFrom, timeTo) {
|
||||
var params = {
|
||||
output: 'extend',
|
||||
itemids: itemids,
|
||||
expandDescription: true,
|
||||
expandData: true,
|
||||
expandComment: true,
|
||||
monitored: true,
|
||||
skipDependent: true,
|
||||
//only_true: true,
|
||||
// filter: {
|
||||
// value: 1
|
||||
// },
|
||||
selectLastEvent: 'extend'
|
||||
};
|
||||
|
||||
if (timeFrom || timeTo) {
|
||||
params.lastChangeSince = timeFrom;
|
||||
params.lastChangeTill = timeTo;
|
||||
}
|
||||
|
||||
return this.request('trigger.get', params);
|
||||
}
|
||||
|
||||
getHostAlerts(hostids, applicationids, options) {
|
||||
let {minSeverity, acknowledged, count, timeFrom, timeTo} = options;
|
||||
let params = {
|
||||
output: 'extend',
|
||||
hostids: hostids,
|
||||
min_severity: minSeverity,
|
||||
filter: { value: 1 },
|
||||
expandDescription: true,
|
||||
expandData: true,
|
||||
expandComment: true,
|
||||
monitored: true,
|
||||
skipDependent: true,
|
||||
selectLastEvent: 'extend',
|
||||
selectGroups: 'extend',
|
||||
selectHosts: ['host', 'name']
|
||||
};
|
||||
|
||||
if (count && acknowledged !== 0 && acknowledged !== 1) {
|
||||
params.countOutput = true;
|
||||
}
|
||||
|
||||
if (applicationids && applicationids.length) {
|
||||
params.applicationids = applicationids;
|
||||
}
|
||||
|
||||
if (timeFrom || timeTo) {
|
||||
params.lastChangeSince = timeFrom;
|
||||
params.lastChangeTill = timeTo;
|
||||
}
|
||||
|
||||
return this.request('trigger.get', params)
|
||||
.then((triggers) => {
|
||||
if (!count || acknowledged === 0 || acknowledged === 1) {
|
||||
triggers = filterTriggersByAcknowledge(triggers, acknowledged);
|
||||
if (count) {
|
||||
triggers = triggers.length;
|
||||
}
|
||||
}
|
||||
return triggers;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function filterTriggersByAcknowledge(triggers, acknowledged) {
|
||||
if (acknowledged === 0) {
|
||||
return _.filter(triggers, (trigger) => trigger.lastEvent.acknowledged === "0");
|
||||
} else if (acknowledged === 1) {
|
||||
return _.filter(triggers, (trigger) => trigger.lastEvent.acknowledged === "1");
|
||||
} else {
|
||||
return triggers;
|
||||
}
|
||||
}
|
||||
|
||||
function isNotAuthorized(message) {
|
||||
return (
|
||||
message === "Session terminated, re-login, please." ||
|
||||
message === "Not authorised." ||
|
||||
message === "Not authorized."
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* General Zabbix API methods
|
||||
*/
|
||||
|
||||
export class ZabbixAPICoreService {
|
||||
|
||||
/** @ngInject */
|
||||
constructor(backendSrv) {
|
||||
this.backendSrv = backendSrv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request data from Zabbix API
|
||||
* @return {object} response.result
|
||||
*/
|
||||
request(api_url, method, params, options, auth) {
|
||||
let requestData = {
|
||||
jsonrpc: '2.0',
|
||||
method: method,
|
||||
params: params,
|
||||
id: 1
|
||||
};
|
||||
|
||||
if (auth === "") {
|
||||
// Reject immediately if not authenticated
|
||||
return Promise.reject(new ZabbixAPIError({data: "Not authorised."}));
|
||||
} else if (auth) {
|
||||
// Set auth parameter only if it needed
|
||||
requestData.auth = auth;
|
||||
}
|
||||
|
||||
let requestOptions = {
|
||||
method: 'POST',
|
||||
url: api_url,
|
||||
data: requestData,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
};
|
||||
|
||||
// Set request options for basic auth
|
||||
if (options.basicAuth || options.withCredentials) {
|
||||
requestOptions.withCredentials = true;
|
||||
}
|
||||
if (options.basicAuth) {
|
||||
requestOptions.headers.Authorization = options.basicAuth;
|
||||
}
|
||||
|
||||
return this.datasourceRequest(requestOptions);
|
||||
}
|
||||
|
||||
datasourceRequest(requestOptions) {
|
||||
return this.backendSrv.datasourceRequest(requestOptions)
|
||||
.then((response) => {
|
||||
if (!response.data) {
|
||||
return Promise.reject(new ZabbixAPIError({data: "General Error, no data"}));
|
||||
} else if (response.data.error) {
|
||||
|
||||
// Handle Zabbix API errors
|
||||
return Promise.reject(new ZabbixAPIError(response.data.error));
|
||||
}
|
||||
|
||||
// Success
|
||||
return response.data.result;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authentication token.
|
||||
* @return {string} auth token
|
||||
*/
|
||||
login(api_url, username, password, options) {
|
||||
let params = {
|
||||
user: username,
|
||||
password: password
|
||||
};
|
||||
return this.request(api_url, 'user.login', params, options, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Zabbix API version
|
||||
* Matches the version of Zabbix starting from Zabbix 2.0.4
|
||||
*/
|
||||
getVersion(api_url, options) {
|
||||
return this.request(api_url, 'apiinfo.version', [], options);
|
||||
}
|
||||
}
|
||||
|
||||
// Define zabbix API exception type
|
||||
export class ZabbixAPIError {
|
||||
constructor(error) {
|
||||
this.code = error.code || null;
|
||||
this.name = error.message || "";
|
||||
this.data = error.data || "";
|
||||
this.message = "Zabbix API Error: " + this.name + " " + this.data;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return this.name + " " + this.data;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user