"
return MENU
def construct_form():
FORM = ""
return FORM
async def check_servers():
global ZABBIX_SERVERS_CHECK
while True:
_logger.info('[INFO] - Checking Zabbix Servers: {}'.format(ZABBIX_SERVERS_CHECK))
j = {}
for ip in ZABBIX_SERVERS_CHECK:
port = 10051
if ':' in ip:
i = ip.split(':')
ip = i[0]
port = int(i[1].strip())
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
result = sock.connect_ex((ip, port))
if result == 0:
_logger.info("[INFO] - Port {} OK: {}".format(port, ip))
else:
_logger.error("[ERR] - Port {} KO: {}".format(port, ip))
j[ip] = result
sock.close()
if os.path.exists('/data/zabbix-servers.json'):
out = read_file('/data/zabbix-servers.json')
out.update(j)
write_file(out, '/data/zabbix-servers.json')
else:
write_file(j, '/data/zabbix-servers.json')
await asyncio.sleep(60)
async def post_note(request):
data = await request.post()
msg = data['msg']
team = data['team']
name = data['name']
url = data['url']
lvl = data['lvl']
ts = int(time.time())
j = {}
j[ts] = []
j[ts].append({
'team': team,
'name': name,
'msg': msg,
'lvl': lvl
})
if os.path.exists('/data/motd.json'):
out = read_file('/data/motd.json')
out.update(j)
write_file(out, '/data/motd.json')
else:
write_file(j, '/data/motd.json')
_logger.info("[ADD] - {}".format(j))
return aiohttp.web.HTTPFound(location=url, text='{}'.format(ts), content_type='text/html')
def read_file(file_to_update):
if os.path.exists(file_to_update):
with open(file_to_update, 'r') as f:
out = json.load(f)
return out
f.close()
return False
def write_file(notes, file_to_update):
with open(file_to_update, 'w+') as f:
json.dump(notes, f)
f.close()
async def del_note(request):
data = await request.post()
note_id = data['note_id']
url = data['url']
out = read_file('/data/motd.json')
_logger.info('[DEL] - {}'.format(out[note_id]))
del out[note_id]
write_file(out, '/data/motd.json')
return aiohttp.web.HTTPFound(location=url)
async def show_alerts(request):
global CONTENT
global NAVBAR
global JS_CONTENT
global TEMPLATE_FOOTER
global TOTAL_ALERTS
data_list = []
html_content = ""
html_notes = "
"
html_check = "
"
response = ""
config.TEMPLATE_HEAD = config.TEMPLATE_HEAD.replace('FORM_TEAM', construct_form())
config.NAVBAR = config.NAVBAR.replace('LIST', construct_menu())
config.NAVBAR = re.sub('\[[0-9]+\]', '['+config.TOTAL_ALERTS+']', config.NAVBAR)
url = str(request.url)
if '/tv/' in url:
config.TEMPLATE_FOOTER = config.TEMPLATE_FOOTER.replace('show', 'hide')
else:
config.TEMPLATE_FOOTER = config.TEMPLATE_FOOTER.replace('hide', 'show')
teams = request.match_info.get('teams')
if not teams:
teams = []
notes = read_file('/data/motd.json')
if notes:
for ts in notes:
for note in notes[ts]:
if note['team'] in teams or note['team'] == 'all':
date_note = datetime.datetime.utcfromtimestamp(int(ts)).strftime('%Y-%m-%d %H:%M:%S')
html_notes += "
"+date_note+"
"+note['msg']+"
(by "+note['name']+")
"
html_notes += '
'
check_zbx = read_file('/data/zabbix-servers.json')
if check_zbx:
for ip in check_zbx:
if check_zbx[ip] != 0:
html_check += "
Zabbix Server: "+ ip + " seems UNREACHABLE!
"
html_check += '
'
### EASTER EGG ###
if teams != 'Team-sys':
IMAGE=''
else:
IMAGE=''
##################
if teams:
team_list = teams.split('+')
for team in team_list:
team_alerts = config.CONTENT.get(team, {})
data_list.extend(team_alerts)
if data_list:
data = sorted(data_list,
key = lambda i: (i['priority'], i['lastchange']),
reverse=True)
result = html_response(data)
html_content = config.TEMPLATE_HEAD.replace('[alerts]', '['+str(len(data))+']').replace('NAVBAR', config.NAVBAR).replace('NOTES', html_notes).replace('CHECK', html_check) + result + config.TEMPLATE_FOOTER
else:
html_content = config.TEMPLATE_HEAD.replace('NAVBAR', config.NAVBAR).replace('NOTES', html_notes).replace('CHECK', html_check) + '
No Alerts for '+str(teams)+'!
'+IMAGE+' ' + config.TEMPLATE_FOOTER
else:
html_content = config.TEMPLATE_HEAD.replace('NAVBAR', config.NAVBAR) + response + config.TEMPLATE_FOOTER
return aiohttp.web.Response(text=html_content, content_type='text/html')
def zabbix_login():
global zapi
x = 0
while x < 10:
try:
zapi = ZabbixAPI(server=ZABBIX_API, timeout=int(TIMEOUT))
zapi.login(ZABBIX_LOGIN, ZABBIX_PASS)
except Exception as e:
x+=1
_logger.error("[ERR] - {} Retry #{}: {}".format(datetime.datetime.now(), x, e))
time.sleep(x)
continue
break
if x >= 10:
sys.exit("Can't connect to Zabbix API.")
def call_zabbix(request, method):
global zapi
x = 0
while x < 10:
try:
if method == 'hostgroup':
resp = zapi.hostgroup.get(request)
elif method == 'triggers':
resp = zapi.trigger.get(request)
except Exception as e:
x+=1
_logger.error("[ERR] - {} Retry #{}: {}".format(datetime.datetime.now(), x, e))
time.sleep(x)
continue
break
if x >= 10:
sys.exit("Can't perform calls to Zabbix API.")
else:
return resp
async def process_zabbix_queue():
global CONTENT
global TOTAL_ALERTS
global HOSTGROUP
global LIMIT
global SEVERITY
global zapi
while True:
try:
zapi.logged_in()
except Exception as e:
_logger.info('[INFO] - {}: Connection to Zabbix API'.format(datetime.datetime.now()))
zabbix_login()
request = dict()
request['output'] = 'extend'
request['search'] = dict()
request['search']['name'] = [HOSTGROUP]
request['searchWildcardsEnabled'] = 1
resp = call_zabbix(request, 'hostgroup')
groupids = []
for x in range(len(resp)):
config.CONTENT[resp[x]['name']] = []
groupids.append(resp[x]['groupid'])
request = dict()
request['limit'] = LIMIT
request['groupids'] = groupids
request['monitored'] = 1
request['maintenance'] = 0
request['active'] = 1
request['min_severity'] = SEVERITY
request['output'] = "extend"
request['expandData'] = 1
request['selectHosts'] = "extend"
request['selectGroups'] = "extend"
request['expandDescription'] = 1
request['only_true'] = 1
request['skipDependent'] = 1
request['withUnacknowledgedEvents'] = 1
request['withLastEventUnacknowledged'] = 1
request['selectTags'] = "extend"
request['filter'] = dict()
request['filter']['value'] = 1
request['sortfield'] = ["priority","lastchange"]
request['sortorder'] = ["DESC"]
_logger.info(request)
resp = call_zabbix(request, 'triggers')
config.TOTAL_ALERTS = str(len(resp))
_logger.info('[NB ALERTS] - {}'.format(config.TOTAL_ALERTS))
hostgroup_to_search = HOSTGROUP.replace('*','')
for x in range(len(resp)):
data = resp[x]
if len(data['hosts']) > 0:
for z in range(len(data['groups'])):
if hostgroup_to_search in data['groups'][z]['name']:
group = data['groups'][z]['name']
config.CONTENT[group].append({'description': data['description'], 'host': data['hosts'][0]['host'], 'priority': data['priority'], 'triggerid': data['triggerid'], 'lastchange': data['lastchange'], 'team': group})
for y in range(len(data['tags'])):
if 'team' == data['tags'][y]['tag']:
team = data['tags'][y]['value']
config.CONTENT[team].append({'description': data['description'], 'host': data['hosts'][0]['host'], 'priority': data['priority'], 'triggerid': data['triggerid'], 'lastchange': data['lastchange'], 'team': team})
_logger.info('[INFO] - {}: Refresh...'.format(datetime.datetime.now()))
await asyncio.sleep(15)
async def start_background_tasks(app):
app['dispatch'] = app.loop.create_task(process_zabbix_queue())
app['dispatch'] = app.loop.create_task(check_servers())
async def cleanup_background_tasks(app):
app['dispatch'].cancel()
await app['dispatch']
def main():
app = aiohttp.web.Application(logger=_logger)
app.add_routes([aiohttp.web.get('/', show_alerts),
aiohttp.web.post('/post', post_note),
aiohttp.web.post('/del', del_note),
aiohttp.web.get('/{teams}', show_alerts),
aiohttp.web.get('/tv/{teams}', show_alerts),
aiohttp.web.static('/images', '/images'),
aiohttp.web.static('/css', '/css'),
aiohttp.web.static('/js', '/js')])
app.on_startup.append(start_background_tasks)
app.on_cleanup.append(cleanup_background_tasks)
aiohttp.web.run_app(app, port=PORT)
if __name__ == '__main__':
main()