Merge branch 'fix-event-ack'
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -29,6 +29,7 @@ awsconfig
|
|||||||
/public_gen
|
/public_gen
|
||||||
/tmp
|
/tmp
|
||||||
vendor/phantomjs/phantomjs
|
vendor/phantomjs/phantomjs
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
# Built plugin
|
# Built plugin
|
||||||
dist/
|
dist/
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
module.exports = function(grunt) {
|
module.exports = function(grunt) {
|
||||||
|
|
||||||
|
const sass = require('node-sass');
|
||||||
require('load-grunt-tasks')(grunt);
|
require('load-grunt-tasks')(grunt);
|
||||||
|
|
||||||
grunt.loadNpmTasks('grunt-execute');
|
grunt.loadNpmTasks('grunt-execute');
|
||||||
@@ -114,6 +115,7 @@ module.exports = function(grunt) {
|
|||||||
|
|
||||||
sass: {
|
sass: {
|
||||||
options: {
|
options: {
|
||||||
|
implementation: sass,
|
||||||
sourceMap: true
|
sourceMap: true
|
||||||
},
|
},
|
||||||
dist: {
|
dist: {
|
||||||
|
|||||||
33
package.json
33
package.json
@@ -22,36 +22,35 @@
|
|||||||
"url": "https://github.com/alexanderzobnin/grafana-zabbix/issues"
|
"url": "https://github.com/alexanderzobnin/grafana-zabbix/issues"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-jest": "^21.2.0",
|
"babel": "^6.23.0",
|
||||||
|
"babel-jest": "^23.6.0",
|
||||||
"babel-plugin-transform-es2015-for-of": "^6.6.0",
|
"babel-plugin-transform-es2015-for-of": "^6.6.0",
|
||||||
"babel-plugin-transform-es2015-modules-systemjs": "^6.5.0",
|
"babel-plugin-transform-es2015-modules-systemjs": "^6.5.0",
|
||||||
"babel-preset-es2015": "^6.5.0",
|
"babel-preset-es2015": "^6.5.0",
|
||||||
"babel": "~6.5.1",
|
|
||||||
"benchmark": "^2.1.4",
|
"benchmark": "^2.1.4",
|
||||||
"codecov": "^3.0.0",
|
"codecov": "^3.1.0",
|
||||||
"grunt-babel": "~6.0.0",
|
"grunt": "^1.0.3",
|
||||||
|
"grunt-babel": "^7.0.0",
|
||||||
"grunt-benchmark": "^1.0.0",
|
"grunt-benchmark": "^1.0.0",
|
||||||
"grunt-cli": "~1.2.0",
|
"grunt-cli": "^1.3.1",
|
||||||
"grunt-contrib-clean": "~0.6.0",
|
"grunt-contrib-clean": "^2.0.0",
|
||||||
"grunt-contrib-copy": "~0.8.2",
|
"grunt-contrib-copy": "^1.0.0",
|
||||||
"grunt-contrib-jshint": "^1.0.0",
|
"grunt-contrib-jshint": "^2.0.0",
|
||||||
"grunt-contrib-uglify": "~0.11.0",
|
"grunt-contrib-uglify": "^4.0.0",
|
||||||
"grunt-contrib-watch": "^0.6.1",
|
"grunt-contrib-watch": "^1.1.0",
|
||||||
"grunt-execute": "~0.2.2",
|
"grunt-execute": "^0.2.2",
|
||||||
"grunt-jscs": "^2.8.0",
|
"grunt-jscs": "^3.0.1",
|
||||||
"grunt-sass": "^1.1.0",
|
"grunt-sass": "^3.0.2",
|
||||||
"grunt-systemjs-builder": "^0.2.5",
|
"grunt-systemjs-builder": "^1.0.0",
|
||||||
"grunt": "~0.4.5",
|
|
||||||
"jest": "^23.5.0",
|
"jest": "^23.5.0",
|
||||||
"jsdom": "~11.3.0",
|
"jsdom": "~11.3.0",
|
||||||
"jshint-stylish": "^2.1.0",
|
"jshint-stylish": "^2.1.0",
|
||||||
"load-grunt-tasks": "~3.2.0",
|
"load-grunt-tasks": "~3.2.0",
|
||||||
"lodash": "~4.17.5",
|
"lodash": "~4.17.5",
|
||||||
"moment": "~2.21.0",
|
"moment": "~2.21.0",
|
||||||
|
"node-sass": "^4.9.4",
|
||||||
"systemjs": "^0.20.19",
|
"systemjs": "^0.20.19",
|
||||||
"tether-drop": "^1.4.2"
|
"tether-drop": "^1.4.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
|
||||||
},
|
|
||||||
"homepage": "http://grafana-zabbix.org"
|
"homepage": "http://grafana-zabbix.org"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ import _ from 'lodash';
|
|||||||
import { migrateDSConfig } from './migrations';
|
import { migrateDSConfig } from './migrations';
|
||||||
|
|
||||||
const SUPPORTED_SQL_DS = ['mysql', 'postgres'];
|
const SUPPORTED_SQL_DS = ['mysql', 'postgres'];
|
||||||
|
const zabbixVersions = [
|
||||||
|
{ name: '2.x', value: 2 },
|
||||||
|
{ name: '3.x', value: 3 },
|
||||||
|
{ name: '4.x', value: 4 },
|
||||||
|
];
|
||||||
|
|
||||||
const defaultConfig = {
|
const defaultConfig = {
|
||||||
trends: false,
|
trends: false,
|
||||||
@@ -10,7 +15,8 @@ const defaultConfig = {
|
|||||||
alerting: false,
|
alerting: false,
|
||||||
addThresholds: false,
|
addThresholds: false,
|
||||||
alertingMinSeverity: 3,
|
alertingMinSeverity: 3,
|
||||||
disableReadOnlyUsersAck: false
|
disableReadOnlyUsersAck: false,
|
||||||
|
zabbixVersion: 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ZabbixDSConfigController {
|
export class ZabbixDSConfigController {
|
||||||
@@ -22,6 +28,8 @@ export class ZabbixDSConfigController {
|
|||||||
this.current.jsonData = migrateDSConfig(this.current.jsonData);
|
this.current.jsonData = migrateDSConfig(this.current.jsonData);
|
||||||
_.defaults(this.current.jsonData, defaultConfig);
|
_.defaults(this.current.jsonData, defaultConfig);
|
||||||
this.sqlDataSources = this.getSupportedSQLDataSources();
|
this.sqlDataSources = this.getSupportedSQLDataSources();
|
||||||
|
this.zabbixVersions = _.cloneDeep(zabbixVersions);
|
||||||
|
this.autoDetectZabbixVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
getSupportedSQLDataSources() {
|
getSupportedSQLDataSources() {
|
||||||
@@ -30,4 +38,23 @@ export class ZabbixDSConfigController {
|
|||||||
return _.includes(SUPPORTED_SQL_DS, ds.type);
|
return _.includes(SUPPORTED_SQL_DS, ds.type);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
autoDetectZabbixVersion() {
|
||||||
|
if (!this.current.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.datasourceSrv.loadDatasource(this.current.name)
|
||||||
|
.then(ds => {
|
||||||
|
return ds.getVersion();
|
||||||
|
})
|
||||||
|
.then(version => {
|
||||||
|
if (version) {
|
||||||
|
if (!_.find(zabbixVersions, ['value', version])) {
|
||||||
|
this.zabbixVersions.push({ name: version + '.x', value: version });
|
||||||
|
}
|
||||||
|
this.current.jsonData.zabbixVersion = version;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
// Data point
|
||||||
|
export const DATAPOINT_VALUE = 0;
|
||||||
|
export const DATAPOINT_TS = 1;
|
||||||
|
|
||||||
// Editor modes
|
// Editor modes
|
||||||
export const MODE_METRICS = 0;
|
export const MODE_METRICS = 0;
|
||||||
export const MODE_ITSERVICE = 1;
|
export const MODE_ITSERVICE = 1;
|
||||||
@@ -17,9 +21,10 @@ export const SHOW_ALL_TRIGGERS = [0, 1];
|
|||||||
export const SHOW_ALL_EVENTS = [0, 1];
|
export const SHOW_ALL_EVENTS = [0, 1];
|
||||||
export const SHOW_OK_EVENTS = 1;
|
export const SHOW_OK_EVENTS = 1;
|
||||||
|
|
||||||
// Data point
|
// Acknowledge
|
||||||
export const DATAPOINT_VALUE = 0;
|
export const ZBX_ACK_ACTION_NONE = 0;
|
||||||
export const DATAPOINT_TS = 1;
|
export const ZBX_ACK_ACTION_ACK = 2;
|
||||||
|
export const ZBX_ACK_ACTION_ADD_MESSAGE = 4;
|
||||||
|
|
||||||
export const TRIGGER_SEVERITY = [
|
export const TRIGGER_SEVERITY = [
|
||||||
{val: 0, text: 'Not classified'},
|
{val: 0, text: 'Not classified'},
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import responseHandler from './responseHandler';
|
|||||||
import { Zabbix } from './zabbix/zabbix';
|
import { Zabbix } from './zabbix/zabbix';
|
||||||
import { ZabbixAPIError } from './zabbix/connectors/zabbix_api/zabbixAPICore';
|
import { ZabbixAPIError } from './zabbix/connectors/zabbix_api/zabbixAPICore';
|
||||||
|
|
||||||
|
const DEFAULT_ZABBIX_VERSION = 3;
|
||||||
|
|
||||||
export class ZabbixDatasource {
|
export class ZabbixDatasource {
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
@@ -47,6 +49,7 @@ export class ZabbixDatasource {
|
|||||||
|
|
||||||
// Other options
|
// Other options
|
||||||
this.disableReadOnlyUsersAck = jsonData.disableReadOnlyUsersAck;
|
this.disableReadOnlyUsersAck = jsonData.disableReadOnlyUsersAck;
|
||||||
|
this.zabbixVersion = jsonData.zabbixVersion || DEFAULT_ZABBIX_VERSION;
|
||||||
|
|
||||||
// Direct DB Connection options
|
// Direct DB Connection options
|
||||||
this.enableDirectDBConnection = jsonData.dbConnectionEnable || false;
|
this.enableDirectDBConnection = jsonData.dbConnectionEnable || false;
|
||||||
@@ -59,6 +62,7 @@ export class ZabbixDatasource {
|
|||||||
password: this.password,
|
password: this.password,
|
||||||
basicAuth: this.basicAuth,
|
basicAuth: this.basicAuth,
|
||||||
withCredentials: this.withCredentials,
|
withCredentials: this.withCredentials,
|
||||||
|
zabbixVersion: this.zabbixVersion,
|
||||||
cacheTTL: this.cacheTTL,
|
cacheTTL: this.cacheTTL,
|
||||||
enableDirectDBConnection: this.enableDirectDBConnection,
|
enableDirectDBConnection: this.enableDirectDBConnection,
|
||||||
dbConnectionDatasourceId: this.dbConnectionDatasourceId,
|
dbConnectionDatasourceId: this.dbConnectionDatasourceId,
|
||||||
@@ -380,6 +384,20 @@ export class ZabbixDatasource {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Zabbix version
|
||||||
|
*/
|
||||||
|
getVersion() {
|
||||||
|
return this.zabbix.getVersion()
|
||||||
|
.then(version => {
|
||||||
|
const zabbixVersion = utils.parseVersion(version);
|
||||||
|
if (!zabbixVersion) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return zabbixVersion.major;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// Templating //
|
// Templating //
|
||||||
////////////////
|
////////////////
|
||||||
|
|||||||
@@ -67,12 +67,21 @@
|
|||||||
Zabbix data source caches metric names in memory. Specify how often data will be updated.
|
Zabbix data source caches metric names in memory. Specify how often data will be updated.
|
||||||
</info-popover>
|
</info-popover>
|
||||||
</span>
|
</span>
|
||||||
<input class="gf-form-input max-width-5"
|
<input class="gf-form-input max-width-7"
|
||||||
type="text"
|
type="text"
|
||||||
ng-model='ctrl.current.jsonData.cacheTTL'
|
ng-model='ctrl.current.jsonData.cacheTTL'
|
||||||
placeholder="1h">
|
placeholder="1h">
|
||||||
</input>
|
</input>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form max-width-20">
|
||||||
|
<span class="gf-form-label width-12">Zabbix version</span>
|
||||||
|
<div class="gf-form-select-wrapper max-width-7">
|
||||||
|
<select class="gf-form-input" ng-model="ctrl.current.jsonData.zabbixVersion"
|
||||||
|
ng-options="s.value as s.name for s in ctrl.zabbixVersions">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gf-form-group">
|
<div class="gf-form-group">
|
||||||
|
|||||||
@@ -240,6 +240,24 @@ export function sequence(funcsArray) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const versionPattern = /^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([0-9A-Za-z\.]+))?/;
|
||||||
|
|
||||||
|
export function isValidVersion(version) {
|
||||||
|
return versionPattern.exec(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseVersion(version) {
|
||||||
|
const match = versionPattern.exec(version);
|
||||||
|
if (!match) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const major = Number(match[1]);
|
||||||
|
const minor = Number(match[2] || 0);
|
||||||
|
const patch = Number(match[3] || 0);
|
||||||
|
const meta = match[4];
|
||||||
|
return { major, minor, patch, meta };
|
||||||
|
}
|
||||||
|
|
||||||
// Fix for backward compatibility with lodash 2.4
|
// Fix for backward compatibility with lodash 2.4
|
||||||
if (!_.includes) {
|
if (!_.includes) {
|
||||||
_.includes = _.contains;
|
_.includes = _.contains;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import * as utils from '../../../utils';
|
import * as utils from '../../../utils';
|
||||||
import { ZabbixAPICore } from './zabbixAPICore';
|
import { ZabbixAPICore } from './zabbixAPICore';
|
||||||
|
import { ZBX_ACK_ACTION_NONE, ZBX_ACK_ACTION_ACK, ZBX_ACK_ACTION_ADD_MESSAGE } from '../../../constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zabbix API Wrapper.
|
* Zabbix API Wrapper.
|
||||||
@@ -8,11 +9,12 @@ import { ZabbixAPICore } from './zabbixAPICore';
|
|||||||
* Wraps API calls and provides high-level methods.
|
* Wraps API calls and provides high-level methods.
|
||||||
*/
|
*/
|
||||||
export class ZabbixAPIConnector {
|
export class ZabbixAPIConnector {
|
||||||
constructor(api_url, username, password, basicAuth, withCredentials, backendSrv) {
|
constructor(api_url, username, password, version, basicAuth, withCredentials, backendSrv) {
|
||||||
this.url = api_url;
|
this.url = api_url;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.auth = "";
|
this.auth = '';
|
||||||
|
this.version = version;
|
||||||
|
|
||||||
this.requestOptions = {
|
this.requestOptions = {
|
||||||
basicAuth: basicAuth,
|
basicAuth: basicAuth,
|
||||||
@@ -47,9 +49,7 @@ export class ZabbixAPIConnector {
|
|||||||
.then(() => this.request(method, params));
|
.then(() => this.request(method, params));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Handle API errors
|
return Promise.reject(error);
|
||||||
let message = error.data ? error.data : error.statusText;
|
|
||||||
return Promise.reject(message);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -92,9 +92,11 @@ export class ZabbixAPIConnector {
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
acknowledgeEvent(eventid, message) {
|
acknowledgeEvent(eventid, message) {
|
||||||
var params = {
|
const action = this.version >= 4 ? ZBX_ACK_ACTION_ACK + ZBX_ACK_ACTION_ADD_MESSAGE : ZBX_ACK_ACTION_NONE;
|
||||||
|
const params = {
|
||||||
eventids: eventid,
|
eventids: eventid,
|
||||||
message: message
|
message: message,
|
||||||
|
action: action
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.request('event.acknowledge', params);
|
return this.request('event.acknowledge', params);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const REQUESTS_TO_CACHE = [
|
|||||||
|
|
||||||
const REQUESTS_TO_BIND = [
|
const REQUESTS_TO_BIND = [
|
||||||
'getHistory', 'getTrend', 'getMacros', 'getItemsByIDs', 'getEvents', 'getAlerts', 'getHostAlerts',
|
'getHistory', 'getTrend', 'getMacros', 'getItemsByIDs', 'getEvents', 'getAlerts', 'getHostAlerts',
|
||||||
'getAcknowledges', 'getITService', 'getVersion', 'login'
|
'getAcknowledges', 'getITService', 'getVersion', 'login', 'acknowledgeEvent'
|
||||||
];
|
];
|
||||||
|
|
||||||
export class Zabbix {
|
export class Zabbix {
|
||||||
@@ -28,6 +28,7 @@ export class Zabbix {
|
|||||||
password,
|
password,
|
||||||
basicAuth,
|
basicAuth,
|
||||||
withCredentials,
|
withCredentials,
|
||||||
|
zabbixVersion,
|
||||||
cacheTTL,
|
cacheTTL,
|
||||||
enableDirectDBConnection,
|
enableDirectDBConnection,
|
||||||
dbConnectionDatasourceId,
|
dbConnectionDatasourceId,
|
||||||
@@ -43,7 +44,7 @@ export class Zabbix {
|
|||||||
};
|
};
|
||||||
this.cachingProxy = new CachingProxy(cacheOptions);
|
this.cachingProxy = new CachingProxy(cacheOptions);
|
||||||
|
|
||||||
this.zabbixAPI = new ZabbixAPIConnector(url, username, password, basicAuth, withCredentials, backendSrv);
|
this.zabbixAPI = new ZabbixAPIConnector(url, username, password, zabbixVersion, basicAuth, withCredentials, backendSrv);
|
||||||
|
|
||||||
if (enableDirectDBConnection) {
|
if (enableDirectDBConnection) {
|
||||||
let dbConnectorOptions = {
|
let dbConnectorOptions = {
|
||||||
|
|||||||
@@ -102,6 +102,23 @@ export class TriggerPanelCtrl extends PanelCtrl {
|
|||||||
this.events.on('refresh', this.onRefresh.bind(this));
|
this.events.on('refresh', this.onRefresh.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setPanelError(err, defaultError) {
|
||||||
|
const defaultErrorMessage = defaultError || "Request Error";
|
||||||
|
this.inspector = { error: err };
|
||||||
|
this.error = err.message || defaultErrorMessage;
|
||||||
|
if (err.data) {
|
||||||
|
if (err.data.message) {
|
||||||
|
this.error = err.data.message;
|
||||||
|
}
|
||||||
|
if (err.data.error) {
|
||||||
|
this.error = err.data.error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.events.emit('data-error', err);
|
||||||
|
console.log('Panel data error:', err);
|
||||||
|
}
|
||||||
|
|
||||||
initDatasources() {
|
initDatasources() {
|
||||||
let promises = _.map(this.panel.datasources, (ds) => {
|
let promises = _.map(this.panel.datasources, (ds) => {
|
||||||
// Load datasource
|
// Load datasource
|
||||||
@@ -161,18 +178,7 @@ export class TriggerPanelCtrl extends PanelCtrl {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.error = err.message || "Request Error";
|
this.setPanelError(err);
|
||||||
if (err.data) {
|
|
||||||
if (err.data.message) {
|
|
||||||
this.error = err.data.message;
|
|
||||||
}
|
|
||||||
if (err.data.error) {
|
|
||||||
this.error = err.data.error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.events.emit('data-error', err);
|
|
||||||
console.log('Panel data error:', err);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,16 +465,14 @@ export class TriggerPanelCtrl extends PanelCtrl {
|
|||||||
return Promise.reject({message: 'You have no permissions to acknowledge events.'});
|
return Promise.reject({message: 'You have no permissions to acknowledge events.'});
|
||||||
}
|
}
|
||||||
if (eventid) {
|
if (eventid) {
|
||||||
return datasource.zabbix.zabbixAPI.acknowledgeEvent(eventid, ack_message);
|
return datasource.zabbix.acknowledgeEvent(eventid, ack_message);
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject({message: 'Trigger has no events. Nothing to acknowledge.'});
|
return Promise.reject({message: 'Trigger has no events. Nothing to acknowledge.'});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(this.onRefresh.bind(this))
|
.then(this.onRefresh.bind(this))
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
this.error = err.message || "Acknowledge Error";
|
this.setPanelError(err);
|
||||||
this.events.emit('data-error', err);
|
|
||||||
console.log('Panel data error:', err);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user