Skip to content

Commit f3efef8

Browse files
committed
jsm zabbix integration
1 parent f03cdb7 commit f3efef8

File tree

10 files changed

+708
-1
lines changed

10 files changed

+708
-1
lines changed

release/jec-builder/version.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
"solarwinds-msp-n-central": "0.1.0",
1111
"solarwinds-npm": "0.1.0",
1212
"solarwinds-web-help-desk": "0.1.0",
13-
"zenoss": "0.1.0"
13+
"zenoss": "0.1.0",
14+
"zabbix": "0.1.0"
1415
}

zabbix/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Zabbix integration plugin for Jira Service Management
2+
3+
:warning: If the feature isn't available on your site, keep checking Jira Service Management for updates.

zabbix/conf/integration.conf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
######################################## ZABBIX CONFIGURATION #######################################
2+
#zabbix2jsm.logger=warning
3+
logPath = /var/log/jec/send2jsm.log
4+
5+
#responders=<comma_separated_list_of_responders>
6+
#tags=<comma_separated_list_of_tags>
7+
8+
####################################### PROXY CONFIGURATION FOR ZABBIX ############################################
9+
zabbix2jsm.http.proxy.enabled = false
10+
zabbix2jsm.http.proxy.port = 11111
11+
zabbix2jsm.http.proxy.host = localhost
12+
zabbix2jsm.http.proxy.protocol = http
13+
#zabbix2jsm.http.proxy.username=admin
14+
#zabbix2jsm.http.proxy.password=changeme

zabbix/conf/jec-config.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"apiKey": "<API_KEY>",
3+
"baseUrl": "https://api.atlassian.com",
4+
"logLevel": "DEBUG",
5+
"globalArgs": [],
6+
"globalFlags": {
7+
"command_url": "http://localhost/zabbix/api_jsonrpc.php",
8+
"user": "Admin",
9+
"password": "zabbix"
10+
},
11+
"actionMappings": {
12+
"Acknowledge": {
13+
"filepath": "<path_of_script>",
14+
"sourceType": "<local | git>",
15+
"env": [],
16+
"stdout": "<path_of_output_file_of_script>"
17+
}
18+
},
19+
"pollerConf": {
20+
"pollingWaitIntervalInMillis": 100,
21+
"visibilityTimeoutInSec": 30,
22+
"maxNumberOfMessages": 10
23+
},
24+
"poolConf": {
25+
"maxNumberOfWorker": 12,
26+
"minNumberOfWorker": 4,
27+
"monitoringPeriodInMillis": 15000,
28+
"keepAliveTimeInMillis": 6000,
29+
"queueSize": 0
30+
}
31+
}

zabbix/scripts/action_command.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/home/jsm/jec/scripts/send2jsm -triggerName='{TRIGGER.NAME}' -triggerId='{TRIGGER.ID}' -triggerStatus='{TRIGGER.STATUS}' -triggerSeverity='{TRIGGER.SEVERITY}' -triggerDescription='{TRIGGER.DESCRIPTION}' -triggerUrl='{TRIGGER.URL}' -triggerValue='{TRIGGER.VALUE}' -triggerHostGroupName='{TRIGGER.HOSTGROUP.NAME}' -hostName='{HOST.NAME}' -ipAddress='{IPADDRESS}' -eventId='{EVENT.ID}' -date='{DATE}' -time='{TIME}' -itemKey='{ITEM.KEY}' -itemValue='{ITEM.VALUE}' -recoveryEventStatus='{EVENT.RECOVERY.STATUS}'

zabbix/scripts/jec_action_executor.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import argparse
2+
import json
3+
import logging
4+
import sys
5+
6+
import requests
7+
8+
parser = argparse.ArgumentParser()
9+
parser.add_argument('-payload', '--queuePayload', help='Payload from queue', required=True)
10+
parser.add_argument('-apiKey', '--apiKey', help='The apiKey of the integration', required=True)
11+
parser.add_argument('-jsmUrl', '--jsmUrl', help='The url', required=True)
12+
parser.add_argument('-logLevel', '--logLevel', help='Log level', required=True)
13+
parser.add_argument('-command_url', '--command_url', help='The Command URL', required=False)
14+
parser.add_argument('-user', '--user', help='User', required=False)
15+
parser.add_argument('-password', '--password', help='Password', required=False)
16+
args = vars(parser.parse_args())
17+
18+
logging.basicConfig(stream=sys.stdout, level=args['logLevel'])
19+
20+
21+
def parse_field(key, mandatory):
22+
variable = queue_message.get(key)
23+
if not variable:
24+
variable = args.get(key)
25+
if mandatory and not variable:
26+
logging.error(LOG_PREFIX + " Skipping action, Mandatory conf item '" + str(key) +
27+
"' is missing. Check your configuration file.")
28+
raise ValueError(LOG_PREFIX + " Skipping action, Mandatory conf item '" + str(key) +
29+
"' is missing. Check your configuration file.")
30+
return variable
31+
32+
33+
def login_to_zabbix(user, password, url):
34+
login_params = {
35+
"jsonrpc": "2.0",
36+
"method": "user.login",
37+
"params": {
38+
"user": user,
39+
"password": password
40+
},
41+
"id": 1
42+
}
43+
logging.debug(LOG_PREFIX + " Logging in to Zabbix. Url: " + str(url) + " user: " + str(user))
44+
content_headers = {
45+
"Content-Type": "application/json"
46+
}
47+
login_result = requests.post(url, data=json.dumps(login_params), headers=content_headers, timeout=timeout)
48+
logging.debug(LOG_PREFIX + " login response: " + str(login_result.status_code) + " " + str(login_result.json()))
49+
if login_result.json() and not (login_result.json()).get('error'):
50+
return (login_result.json()).get('result')
51+
else:
52+
logging.error(
53+
LOG_PREFIX + " Cannot login to Zabbix: Response " + str(login_result.status_code) + " " + str(
54+
login_result.content))
55+
56+
57+
def parse_timeout():
58+
parsed_timeout = args.get('http.timeout')
59+
if not parsed_timeout:
60+
return 30000
61+
return int(parsed_timeout)
62+
63+
64+
def main():
65+
global LOG_PREFIX
66+
global queue_message
67+
global timeout
68+
69+
queue_message_string = args['queuePayload']
70+
queue_message = json.loads(queue_message_string)
71+
72+
alert_id = queue_message["alert"]["alertId"]
73+
action = queue_message["action"]
74+
source = queue_message["source"]
75+
76+
LOG_PREFIX = "[" + action + "]"
77+
78+
timeout = parse_timeout()
79+
80+
logging.info("Will execute " + action + " for alertId " + alert_id)
81+
82+
username = parse_field('user', True)
83+
password = parse_field('password', True)
84+
url = parse_field('command_url', True)
85+
86+
logging.debug("Username: " + str(username))
87+
logging.debug("Command Url: " + str(url))
88+
logging.debug("AlertId: " + str(alert_id))
89+
logging.debug("Source: " + str(source))
90+
logging.debug("Action: " + str(action))
91+
92+
if alert_id:
93+
alert_api_url = args['jsmUrl'] + "/jsm/ops/integration/v2/alerts/" + alert_id
94+
headers = {
95+
"Content-Type": "application/json",
96+
"Accept-Language": "application/json",
97+
"Authorization": "GenieKey " + args['apiKey']
98+
}
99+
alert_response = requests.get(alert_api_url, headers=headers, timeout=timeout)
100+
if alert_response.status_code < 299 and (alert_response.json()).get('data'):
101+
if action == "Acknowledge":
102+
if source and str(source['name']).lower() == "zabbix":
103+
logging.warning("JSM alert is already acknowledged by Zabbix. Discarding!!!")
104+
else:
105+
post_params = {
106+
"jsonrpc": "2.0",
107+
"id": 1,
108+
"method": "event.acknowledge",
109+
"params": {
110+
"eventids": queue_message["alert"]["details"]["eventId"],
111+
"message": "Acknowledged by " + alert_response.json()['data']['report'][
112+
'acknowledgedBy'] + " via JSM"
113+
}
114+
}
115+
auth = login_to_zabbix(username, password, url)
116+
if auth:
117+
logging.debug("Posting to Zabbix. Url: " + str(url) + ", params: " + str(post_params))
118+
post_params.update({"auth": auth})
119+
headers = {
120+
"Content-Type": "application/json",
121+
}
122+
response = requests.post(url, data=json.dumps(post_params), headers=headers, timeout=timeout)
123+
if alert_response.json() and not (alert_response.json()).get('error'):
124+
logging.info("Successfully executed at Zabbix.")
125+
logging.debug("Zabbix response: " + str(response.json()))
126+
else:
127+
logging.warning(
128+
"Could not execute at Zabbix. Zabbix Response: " + str(
129+
response.content) + " Status Code: " + str(response.status_code))
130+
else:
131+
logging.warning(LOG_PREFIX + "Cannot login to Zabbix!")
132+
else:
133+
logging.warning("Alert with id [" + str(alert_id) + "] does not exist in JSM. It is probably deleted.")
134+
else:
135+
logging.warning("Alert id does not exist ")
136+
137+
138+
if __name__ == '__main__':
139+
main()
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import argparse
2+
import json
3+
import logging
4+
import sys
5+
6+
import requests
7+
8+
parser = argparse.ArgumentParser()
9+
parser.add_argument('-payload', '--queuePayload', help='Payload from queue', required=True)
10+
parser.add_argument('-apiKey', '--apiKey', help='The apiKey of the integration', required=True)
11+
parser.add_argument('-jsmUrl', '--jsmUrl', help='The url', required=True)
12+
parser.add_argument('-logLevel', '--logLevel', help='Log level', required=True)
13+
parser.add_argument('-command_url', '--command_url', help='The Command URL', required=False)
14+
parser.add_argument('-user', '--user', help='User', required=False)
15+
parser.add_argument('-password', '--password', help='Password', required=False)
16+
args = vars(parser.parse_args())
17+
18+
logging.basicConfig(stream=sys.stdout, level=args['logLevel'])
19+
20+
21+
def parse_field(key, mandatory):
22+
variable = queue_message.get(key)
23+
if not variable:
24+
variable = args.get(key)
25+
if mandatory and not variable:
26+
logging.error(LOG_PREFIX + " Skipping action, Mandatory conf item '" + str(key) +
27+
"' is missing. Check your configuration file.")
28+
raise ValueError(LOG_PREFIX + " Skipping action, Mandatory conf item '" + str(key) +
29+
"' is missing. Check your configuration file.")
30+
return variable
31+
32+
33+
def parse_timeout():
34+
parsed_timeout = args.get('http.timeout')
35+
if not parsed_timeout:
36+
return 30000
37+
return int(parsed_timeout)
38+
39+
40+
def login_to_zabbix(user, password, url):
41+
login_params = {
42+
"jsonrpc": "2.0",
43+
"method": "user.login",
44+
"params": {
45+
"user": user,
46+
"password": password
47+
},
48+
"id": 1
49+
}
50+
logging.debug(LOG_PREFIX + " Logging in to Zabbix. Url: " + str(url) + " user: " + str(user))
51+
content_headers = {
52+
"Content-Type": "application/json"
53+
}
54+
login_result = requests.post(url, data=json.dumps(login_params), headers=content_headers, timeout=timeout)
55+
logging.debug(LOG_PREFIX + " login response: " + str(login_result.status_code) + " " + str(login_result.json()))
56+
if login_result.json() and not login_result.json().get('error'):
57+
return login_result.json()['result']
58+
else:
59+
logging.error(
60+
LOG_PREFIX + " Cannot login to Zabbix: Response " + str(login_result.status_code) + " " + str(login_result.content))
61+
62+
63+
def main():
64+
global LOG_PREFIX
65+
global queue_message
66+
global timeout
67+
68+
queue_message_string = args['queuePayload']
69+
queue_message = json.loads(queue_message_string)
70+
71+
alert_id = queue_message["alert"]["alertId"]
72+
action = queue_message["action"]
73+
source = queue_message["source"]
74+
75+
LOG_PREFIX = "[" + action + "]"
76+
77+
timeout = parse_timeout()
78+
79+
logging.info("Will execute " + str(action) + " for alertId " + str(alert_id))
80+
81+
username = parse_field('user', True)
82+
password = parse_field('password', True)
83+
url = parse_field('command_url', True)
84+
85+
logging.debug("Username: " + str(username))
86+
logging.debug("Command Url: " + str(url))
87+
logging.debug("AlertId: " + str(alert_id))
88+
logging.debug("Source: " + str(source))
89+
logging.debug("Action: " + str(action))
90+
91+
if alert_id:
92+
alert_api_url = args['jsmUrl'] + "/jsm/ops/integration/v2/alerts/" + alert_id
93+
headers = {
94+
"Content-Type": "application/json",
95+
"Accept-Language": "application/json",
96+
"Authorization": "GenieKey " + args['apiKey']
97+
}
98+
alert_response = requests.get(alert_api_url, headers=headers, timeout=timeout)
99+
if alert_response.status_code < 299 and alert_response.json()['data']:
100+
if action == "Acknowledge":
101+
if source and str(source['name']).lower() == "zabbix":
102+
logging.warning("JSM alert is already acknowledged by Zabbix. Discarding!!!")
103+
else:
104+
post_params = {
105+
"jsonrpc": "2.0",
106+
"id": 1,
107+
"method": "event.acknowledge",
108+
"params": {
109+
"eventids": queue_message["alert"]["details"]["eventId"],
110+
"message": "Acknowledged by " + alert_response.json()['data']['report'][
111+
'acknowledgedBy'] + " via JSM",
112+
"action": 6
113+
}
114+
}
115+
auth = login_to_zabbix(username, password, url)
116+
if auth:
117+
logging.debug("Posting to Zabbix. Url: " + str(url) + ", params: " + str(post_params))
118+
post_params.update({"auth": auth})
119+
headers = {
120+
"Content-Type": "application/json",
121+
}
122+
response = requests.post(url, data=json.dumps(post_params), headers=headers, timeout=timeout)
123+
if alert_response.json() and not alert_response.json().get('error'):
124+
logging.info("Successfully executed at Zabbix.")
125+
logging.debug("Zabbix response: " + str(response.json()))
126+
else:
127+
logging.warning(
128+
"Could not execute at Zabbix. Zabbix Response: " + response.content + " Status Code: " + response.status_code)
129+
else:
130+
logging.warning(LOG_PREFIX + "Cannot login to Zabbix!")
131+
else:
132+
logging.warning("Alert with id [" + str(alert_id) + "] does not exist in JSM. It is probably deleted.")
133+
else:
134+
logging.warning("Alert id does not exist ")
135+
136+
137+
if __name__ == '__main__':
138+
main()

zabbix/scripts/jsm_after.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
chmod 755 /home/jsm/jec/scripts/send2jsm
2+
3+
if id -u zabbix >/dev/null 2>&1; then
4+
usermod -a -G jsm zabbix
5+
chown -R zabbix:jsm /var/log/jec
6+
else
7+
echo "WARNING : zabbix user does not exist. Please don't forget to add your zabbix user to jsm group!"
8+
fi

zabbix/scripts/jsm_before.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
if [ -z $(getent group jsm) ]
2+
then
3+
groupadd jsm
4+
fi

0 commit comments

Comments
 (0)