Skip to content

Commit 3ee6ef1

Browse files
authored
Merge pull request #2 from vasvlad/add_zabbix_configuration
Add zabbix configuration
2 parents b2b69b8 + edfe3e2 commit 3ee6ef1

File tree

2 files changed

+317
-0
lines changed

2 files changed

+317
-0
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,11 @@ curl -X POST --location "http://localhost:8000/webservices/rest.php?version=1.4"
245245
\"output_fields\": \"title,status,team_id_friendlyname,agent_id_friendlyname,solution\"
246246
}"
247247
```
248+
249+
### Интеграция с Zabbix
250+
251+
Используя файл examples/zabbix/media_itop.yaml, который является модифицированной версией конфигурационного файла вот с этого источника:
252+
https://git.zabbix.com/projects/ZBX/repos/zabbix/browse/templates/media/itop/media_itop.yaml
253+
можно легко интегрировать данный модуль с системой мониторинга Zabbix следуя вот этой инструкции:
254+
https://www.zabbix.com/integrations/itop
255+

examples/zabbix/media_itop.yaml

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
zabbix_export:
2+
version: '6.0'
3+
media_types:
4+
-
5+
name: iTop
6+
type: WEBHOOK
7+
parameters:
8+
0:
9+
name: alert_message
10+
value: '{ALERT.MESSAGE}'
11+
1:
12+
name: alert_subject
13+
value: '{ALERT.SUBJECT}'
14+
2:
15+
name: event_recovery_value
16+
value: '{EVENT.RECOVERY.VALUE}'
17+
3:
18+
name: event_source
19+
value: '{EVENT.SOURCE}'
20+
4:
21+
name: event_update_status
22+
value: '{EVENT.UPDATE.STATUS}'
23+
5:
24+
name: event_value
25+
value: '{EVENT.VALUE}'
26+
6:
27+
name: itop_api_version
28+
value: '1.3'
29+
7:
30+
name: itop_class
31+
value: UserRequest
32+
14:
33+
name: itop_comment
34+
value: 'Created by Zabbix action {ACTION.NAME}'
35+
8:
36+
name: itop_id
37+
value: '{EVENT.TAGS.__zbx_itop_id}'
38+
9:
39+
name: itop_log
40+
value: private_log
41+
10:
42+
name: itop_organization_id
43+
value: '<PLACE ORGANIZATION ID>'
44+
11:
45+
name: itop_password
46+
value: '<PLACE PASSWORD OR TOKEN>'
47+
12:
48+
name: itop_url
49+
value: '<PLACE YOUR ITOP URL>'
50+
13:
51+
name: itop_user
52+
value: '<PLACE LOGIN>'
53+
15:
54+
name: itop_context
55+
value: '<PLACE CONTEXT for monitorng - for example demo_context>'
56+
16:
57+
name: itop_ci
58+
value: '{HOST.NAME}'
59+
60+
script: |
61+
var Itop = {
62+
params: {},
63+
64+
setParams: function (params) {
65+
if (typeof params !== 'object') {
66+
return;
67+
}
68+
69+
if (params.log !== 'private_log' && params.log !== 'public_log') {
70+
throw 'Incorrect "itop_log" parameter given: ' + params.log + '\nMust be "private_log" or "public_log".';
71+
}
72+
73+
Itop.params = params;
74+
if (typeof Itop.params.url === 'string') {
75+
if (!Itop.params.url.endsWith('/')) {
76+
Itop.params.url += '/';
77+
}
78+
79+
Itop.params.url += 'webservices/rest.php?version=' + encodeURIComponent(Itop.params.api_version);
80+
}
81+
},
82+
83+
setProxy: function (HTTPProxy) {
84+
Itop.HTTPProxy = HTTPProxy;
85+
},
86+
87+
setCreatePayload: function () {
88+
json_data.operation = 'monitoring/alarm';
89+
json_data.ci_key = params.itop_ci;
90+
json_data.state = params.event_value;
91+
json_data.message = params.alert_subject;
92+
json_data.description = params.alert_message.replace('<', '&lt;')
93+
.replace('>', '&gt;')
94+
.replace(/(?:\r\n|\r|\n)/g, '<br>');
95+
},
96+
97+
setUpdatePayload: function () {
98+
json_data.key = Itop.params.id;
99+
json_data.fields.title = params.alert_subject;
100+
json_data.operation = 'monitoring/alarm';
101+
json_data.ci_key = params.itop_ci;
102+
json_data.state = params.event_value;
103+
json_data.message = params.alert_subject + '\n' + params.alert_message;
104+
},
105+
106+
request: function (data) {
107+
['url', 'user', 'password', 'organization_id', 'class', 'api_version', 'id'].forEach(function (field) {
108+
if (typeof Itop.params !== 'object' || typeof Itop.params[field] === 'undefined'
109+
|| Itop.params[field] === '' ) {
110+
throw 'Required Itop param is not set: "itop_' + field + '".';
111+
}
112+
});
113+
114+
var response,
115+
url = Itop.params.url,
116+
request = new HttpRequest(),
117+
object;
118+
119+
request.addHeader('Content-Type: multipart/form-data');
120+
request.addHeader('Authorization: Basic ' + btoa(Itop.params.user + ':' + Itop.params.password));
121+
122+
if (Itop.HTTPProxy) {
123+
request.setProxy(Itop.HTTPProxy);
124+
}
125+
126+
if (typeof data !== 'undefined') {
127+
data = JSON.stringify(data);
128+
}
129+
130+
Zabbix.log(4, '[ iTop Webhook ] Sending request: ' + url + '&json_data=' + data);
131+
132+
response = request.post(url + '&json_data=' + encodeURIComponent(data));
133+
134+
Zabbix.log(4, '[ iTop Webhook ] Received response with status code ' + request.getStatus() + '\n' + response);
135+
136+
try {
137+
response = JSON.parse(response);
138+
}
139+
catch (error) {
140+
Zabbix.log(4, '[ iTop Webhook ] Failed to parse response received from iTop');
141+
throw 'Failed to parse response received from iTop.\nRequest status code ' +
142+
request.getStatus() + '. Check debug log for more information.';
143+
}
144+
145+
if (request.getStatus() < 200 || request.getStatus() >= 300) {
146+
throw 'Request failed with status code ' + request.getStatus() + '. Check debug log for more information.';
147+
}
148+
else if (typeof response.code !== 'undefined' && response.code !== 0) {
149+
throw 'Request failed with iTop code ' + response.code + ': ' +
150+
JSON.stringify(response.message) + '. Check debug log for more information.';
151+
}
152+
else {
153+
Object.keys(response.objects)
154+
.forEach(function (key) {
155+
object = response.objects[key];
156+
});
157+
158+
return {
159+
status: request.getStatus(),
160+
response: object.fields
161+
};
162+
}
163+
}
164+
};
165+
166+
try {
167+
var params = JSON.parse(value),
168+
json_data = {},
169+
itop_params = {},
170+
result = {tags: {}},
171+
required_params = [
172+
'alert_subject', 'summary', 'event_recovery_value',
173+
'event_source', 'event_value', 'action_name'
174+
];
175+
176+
Object.keys(params)
177+
.forEach(function (key) {
178+
if (key.startsWith('itop_')) {
179+
itop_params[key.substring(5)] = params[key];
180+
}
181+
else if (required_params.indexOf(key) !== -1 && params[key] === '') {
182+
throw 'Parameter "' + key + '" can\'t be empty.';
183+
}
184+
});
185+
186+
if ([0, 1, 2, 3].indexOf(parseInt(params.event_source)) === -1) {
187+
throw 'Incorrect "event_source" parameter given: ' + params.event_source + '\nMust be 0-3.';
188+
}
189+
190+
// Check {EVENT.VALUE} for trigger-based and internal events.
191+
if (params.event_value !== '0' && params.event_value !== '1'
192+
&& (params.event_source === '0' || params.event_source === '3')) {
193+
throw 'Incorrect "event_value" parameter given: ' + params.event_value + '\nMust be 0 or 1.';
194+
}
195+
196+
// Check {EVENT.UPDATE.STATUS} only for trigger-based events.
197+
if (params.event_update_status !== '0' && params.event_update_status !== '1' && params.event_source === '0') {
198+
throw 'Incorrect "event_update_status" parameter given: ' + params.event_update_status + '\nMust be 0 or 1.';
199+
}
200+
201+
if (params.event_source !== '0' && params.event_recovery_value === '0') {
202+
throw 'Recovery operations are supported only for trigger-based actions.';
203+
}
204+
205+
Itop.setParams(itop_params);
206+
Itop.setProxy(params.HTTPProxy);
207+
208+
json_data.operation = '';
209+
json_data.context = Itop.params.context;
210+
json_data.class = Itop.params.class;
211+
json_data.comment = Itop.params.comment;
212+
json_data.output_fields = 'id, friendlyname';
213+
json_data.fields = {};
214+
215+
// Create issue for non trigger-based events.
216+
if (params.event_source !== '0' && params.event_recovery_value !== '0') {
217+
Itop.setCreatePayload();
218+
Itop.request(json_data);
219+
}
220+
// Create issue for trigger-based events.
221+
else if (params.event_value === '1' && params.event_update_status === '0'
222+
&& Itop.params.id === '{EVENT.TAGS.__zbx_itop_id}') {
223+
Itop.setCreatePayload();
224+
225+
var response = Itop.request(json_data);
226+
227+
result.tags.__zbx_itop_id = response.response.id;
228+
result.tags.__zbx_itop_key = response.response.friendlyname;
229+
result.tags.__zbx_itop_link = params.itop_url + (params.itop_url.endsWith('/') ? '' : '/') +
230+
'pages/UI.php?operation=details&class=' + encodeURIComponent(Itop.params.class) + '&id=' +
231+
encodeURIComponent(response.response.id);
232+
}
233+
// Update created issue for trigger-based event.
234+
else {
235+
if (Itop.params.id === '{EVENT.TAGS.__zbx_itop_id}') {
236+
throw 'Incorrect iTop ticket ID given: ' + Itop.params.id;
237+
}
238+
Itop.setUpdatePayload();
239+
Itop.request(json_data);
240+
}
241+
242+
return JSON.stringify(result);
243+
}
244+
catch (error) {
245+
Zabbix.log(3, '[ iTop Webhook ] ERROR: ' + error);
246+
throw 'Sending failed: ' + error;
247+
}
248+
process_tags: 'YES'
249+
show_event_menu: 'YES'
250+
event_menu_url: '{EVENT.TAGS.__zbx_itop_link}'
251+
event_menu_name: 'iTop: {EVENT.TAGS.__zbx_itop_key}'
252+
message_templates:
253+
-
254+
event_source: TRIGGERS
255+
operation_mode: PROBLEM
256+
subject: '[{EVENT.STATUS}] {EVENT.NAME}'
257+
message: |
258+
Problem started at {EVENT.TIME} on {EVENT.DATE}
259+
Problem name: {EVENT.NAME}
260+
Host: {HOST.NAME}
261+
Severity: {EVENT.SEVERITY}
262+
Operational data: {EVENT.OPDATA}
263+
Original problem ID: {EVENT.ID}
264+
{TRIGGER.URL}
265+
-
266+
event_source: TRIGGERS
267+
operation_mode: RECOVERY
268+
subject: '[{EVENT.STATUS}] {EVENT.NAME}'
269+
message: |
270+
Problem has been resolved in {EVENT.DURATION} at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
271+
Problem name: {EVENT.NAME}
272+
Host: {HOST.NAME}
273+
Severity: {EVENT.SEVERITY}
274+
Original problem ID: {EVENT.ID}
275+
{TRIGGER.URL}
276+
-
277+
event_source: TRIGGERS
278+
operation_mode: UPDATE
279+
subject: '[{EVENT.STATUS}] {EVENT.NAME}'
280+
message: |
281+
{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
282+
{EVENT.UPDATE.MESSAGE}
283+
284+
Current problem status is {EVENT.STATUS}, acknowledged: {EVENT.ACK.STATUS}.
285+
-
286+
event_source: DISCOVERY
287+
operation_mode: PROBLEM
288+
subject: 'Discovery: {DISCOVERY.DEVICE.STATUS} {DISCOVERY.DEVICE.IPADDRESS}'
289+
message: |
290+
Discovery rule: {DISCOVERY.RULE.NAME}
291+
292+
Device IP: {DISCOVERY.DEVICE.IPADDRESS}
293+
Device DNS: {DISCOVERY.DEVICE.DNS}
294+
Device status: {DISCOVERY.DEVICE.STATUS}
295+
Device uptime: {DISCOVERY.DEVICE.UPTIME}
296+
297+
Device service name: {DISCOVERY.SERVICE.NAME}
298+
Device service port: {DISCOVERY.SERVICE.PORT}
299+
Device service status: {DISCOVERY.SERVICE.STATUS}
300+
Device service uptime: {DISCOVERY.SERVICE.UPTIME}
301+
-
302+
event_source: AUTOREGISTRATION
303+
operation_mode: PROBLEM
304+
subject: 'Autoregistration: {HOST.HOST}'
305+
message: |
306+
Host name: {HOST.HOST}
307+
Host IP: {HOST.IP}
308+
Agent port: {HOST.PORT}
309+

0 commit comments

Comments
 (0)