mirror of https://github.com/Aidaho12/haproxy-wi
v2.8
Meet metrics! Now in HAProxy-WI you can see count incomning connections!pull/30/head
parent
08dc1d8146
commit
a8c7b99db8
|
@ -29,6 +29,7 @@ Support the project
|
|||
19. SYN flood protect
|
||||
20. Alerting about changes backends state
|
||||
21. Alerting about HAProxy service state
|
||||
22. Metrics incoming connections
|
||||
|
||||
# Install
|
||||
The installer will ask you a few questions
|
||||
|
|
|
@ -347,7 +347,7 @@ def update_db_v_2_6(**kwargs):
|
|||
return True
|
||||
cur.close()
|
||||
con.close()
|
||||
|
||||
|
||||
def update_db_v_2_61(**kwargs):
|
||||
con, cur = get_cur()
|
||||
sql = """
|
||||
|
@ -406,7 +406,7 @@ def update_db_v_2_7(**kwargs):
|
|||
print("An error occurred:", e)
|
||||
return False
|
||||
else:
|
||||
print("DB was update to 2.7<br />")
|
||||
print("DB was update to 2.7.2<br />")
|
||||
return True
|
||||
cur.close()
|
||||
con.close()
|
||||
|
@ -435,6 +435,63 @@ def update_db_v_2_7_2(**kwargs):
|
|||
cur.close()
|
||||
con.close()
|
||||
|
||||
def update_db_v_2_8(**kwargs):
|
||||
con, cur = get_cur()
|
||||
sql = """CREATE TABLE IF NOT EXISTS `metrics` (`serv` varchar(64), curr_con INTEGER, cur_ssl_con INTEGER, sess_rate INTEGER, max_sess_rate INTEGER,`date` DATETIME default '0000-00-00 00:00:00'); """
|
||||
try:
|
||||
cur.execute(sql)
|
||||
con.commit()
|
||||
except sqltool.Error as e:
|
||||
if kwargs.get('silent') != 1:
|
||||
if e.args[0] == 'duplicate column name: token' or e == "1060 (42S21): Duplicate column name 'token' ":
|
||||
print('Updating... go to version 2.6')
|
||||
else:
|
||||
print("An error occurred:", e.args[0])
|
||||
return False
|
||||
else:
|
||||
print("DB was update to 2.8<br />")
|
||||
return True
|
||||
cur.close()
|
||||
con.close()
|
||||
|
||||
def update_db_v_2_8(**kwargs):
|
||||
con, cur = get_cur()
|
||||
sql = """CREATE TABLE IF NOT EXISTS `metrics` (`serv` varchar(64), curr_con INTEGER, cur_ssl_con INTEGER, sess_rate INTEGER, max_sess_rate INTEGER,`date` DATETIME default '0000-00-00 00:00:00'); """
|
||||
try:
|
||||
cur.execute(sql)
|
||||
con.commit()
|
||||
except sqltool.Error as e:
|
||||
if kwargs.get('silent') != 1:
|
||||
if e.args[0] == 'duplicate column name: token' or e == "1060 (42S21): Duplicate column name 'token' ":
|
||||
print('Updating... go to version 2.6')
|
||||
else:
|
||||
print("An error occurred:", e.args[0])
|
||||
return False
|
||||
else:
|
||||
print("DB was update to 2.8<br />")
|
||||
return True
|
||||
cur.close()
|
||||
con.close()
|
||||
|
||||
def update_db_v_2_8_2(**kwargs):
|
||||
con, cur = get_cur()
|
||||
sql = """ ALTER TABLE `servers` ADD COLUMN metrics INTEGER NOT NULL DEFAULT 0 """
|
||||
try:
|
||||
cur.execute(sql)
|
||||
con.commit()
|
||||
except sqltool.Error as e:
|
||||
if kwargs.get('silent') != 1:
|
||||
if e.args[0] == 'duplicate column name: metrics' or e == "1060 (42S21): Duplicate column name 'metrics' ":
|
||||
print('DB was update to 2.8. It\' last version')
|
||||
else:
|
||||
print("An error occurred:", e.args[0])
|
||||
return False
|
||||
else:
|
||||
print("DB was update to 2.8<br />")
|
||||
return True
|
||||
cur.close()
|
||||
con.close()
|
||||
|
||||
def update_all():
|
||||
update_db_v_2_0_1()
|
||||
update_db_v_2_0_1_1()
|
||||
|
@ -447,6 +504,8 @@ def update_all():
|
|||
update_db_v_2_6_1()
|
||||
update_db_v_2_7()
|
||||
update_db_v_2_7_2()
|
||||
update_db_v_2_8()
|
||||
update_db_v_2_8_2()
|
||||
|
||||
def update_all_silent():
|
||||
update_db_v_2_0_1(silent=1)
|
||||
|
@ -460,4 +519,6 @@ def update_all_silent():
|
|||
update_db_v_2_6_1(silent=1)
|
||||
update_db_v_2_7(silent=1)
|
||||
update_db_v_2_7_2(silent=1)
|
||||
update_db_v_2_8(silent=1)
|
||||
update_db_v_2_8_2(silent=1)
|
||||
|
18
app/funct.py
18
app/funct.py
|
@ -57,12 +57,15 @@ def logging(serv, action, **kwargs):
|
|||
except:
|
||||
pass
|
||||
|
||||
if kwargs.get('alerting') != 1:
|
||||
mess = get_data('date_in_log') + " from " + IP + " user: " + login + " " + action + " for: " + serv + "\n"
|
||||
log = open(log_path + "/config_edit-"+get_data('logs')+".log", "a")
|
||||
else:
|
||||
if kwargs.get('alerting') == 1:
|
||||
mess = get_data('date_in_log') + action + "\n"
|
||||
log = open(log_path + "/checker-"+get_data('logs')+".log", "a")
|
||||
elif kwargs.get('metrics') == 1:
|
||||
mess = get_data('date_in_log') + action + "\n"
|
||||
log = open(log_path + "/metrics-"+get_data('logs')+".log", "a")
|
||||
else:
|
||||
mess = get_data('date_in_log') + " from " + IP + " user: " + login + " " + action + " for: " + serv + "\n"
|
||||
log = open(log_path + "/config_edit-"+get_data('logs')+".log", "a")
|
||||
|
||||
try:
|
||||
log.write(mess)
|
||||
|
@ -272,13 +275,12 @@ def show_config(cfg):
|
|||
|
||||
def diff_config(oldcfg, cfg):
|
||||
import subprocess
|
||||
cmd="/bin/diff -ub %s %s" % (oldcfg, cfg)
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, universal_newlines=True)
|
||||
stdout, stderr = p.communicate()
|
||||
output = stdout.splitlines()
|
||||
log_path = get_config_var('main', 'log_path')
|
||||
diff = ""
|
||||
date = get_data('date_in_log')
|
||||
cmd="/bin/diff -ub %s %s" % (oldcfg, cfg)
|
||||
|
||||
output, stderr = subprocess_execute(cmd)
|
||||
|
||||
for line in output:
|
||||
diff += date + " " + line + "\n"
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sql
|
||||
import http
|
||||
import funct
|
||||
import sql
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
env = Environment(loader=FileSystemLoader('templates/'))
|
||||
template = env.get_template('metrics.html')
|
||||
|
||||
print('Content-type: text/html\n')
|
||||
funct.check_login()
|
||||
|
||||
try:
|
||||
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
|
||||
user_id = cookie.get('uuid')
|
||||
user = sql.get_user_name_by_uuid(user_id.value)
|
||||
servers = sql.get_dick_permit()
|
||||
token = sql.get_token(user_id.value)
|
||||
except:
|
||||
pass
|
||||
|
||||
template = template.render(h2 = 1, title = "Metrics",
|
||||
autorefresh = 1,
|
||||
role = sql.get_user_role_by_uuid(user_id.value),
|
||||
user = user,
|
||||
onclick = "metricsShow()",
|
||||
token = token)
|
||||
print(template)
|
|
@ -352,4 +352,85 @@ if form.getvalue('masteradd'):
|
|||
os.system("rm -f %s" % script)
|
||||
|
||||
if form.getvalue('haproxyaddserv'):
|
||||
funct.install_haproxy(form.getvalue('haproxyaddserv'), syn_flood=form.getvalue('syn_flood'))
|
||||
funct.install_haproxy(form.getvalue('haproxyaddserv'), syn_flood=form.getvalue('syn_flood'))
|
||||
|
||||
if form.getvalue('metrics'):
|
||||
from datetime import timedelta
|
||||
from bokeh.plotting import figure, output_file, show
|
||||
from bokeh.models import ColumnDataSource, HoverTool, DatetimeTickFormatter, DatePicker
|
||||
from bokeh.layouts import widgetbox, gridplot
|
||||
from bokeh.models.widgets import Button, RadioButtonGroup, Select
|
||||
import pandas as pd
|
||||
import json
|
||||
|
||||
servers = sql.select_servers_metrics()
|
||||
|
||||
p = {}
|
||||
for serv in servers:
|
||||
serv = serv[0]
|
||||
p[serv] = {}
|
||||
metric = sql.select_metrics(serv)
|
||||
metrics = {}
|
||||
|
||||
for i in metric:
|
||||
rep_date = str(i[5])
|
||||
metrics[rep_date] = {}
|
||||
metrics[rep_date]['server'] = str(i[0])
|
||||
metrics[rep_date]['curr_con'] = str(i[1])
|
||||
metrics[rep_date]['curr_ssl_con'] = str(i[2])
|
||||
metrics[rep_date]['sess_rate'] = str(i[3])
|
||||
metrics[rep_date]['max_sess_rate'] = str(i[4])
|
||||
|
||||
df = pd.DataFrame.from_dict(metrics, orient="index")
|
||||
df = df.fillna(0)
|
||||
df.index = pd.to_datetime(df.index)
|
||||
df.index.name = 'Date'
|
||||
df.sort_index(inplace=True)
|
||||
source = ColumnDataSource(df)
|
||||
|
||||
output_file("templates/metrics_out.html")
|
||||
|
||||
x_min = df.index.min() - pd.Timedelta(hours=1)
|
||||
x_max = df.index.max() + pd.Timedelta(minutes=1)
|
||||
|
||||
p[serv] = figure(
|
||||
tools="pan,box_zoom,reset,wheel_zoom",
|
||||
title=metric[0][0],
|
||||
x_axis_type="datetime", y_axis_label='Connections',
|
||||
x_range = (x_max.timestamp()*1000-60*100000, x_max.timestamp()*1000)
|
||||
)
|
||||
|
||||
hover = HoverTool(
|
||||
tooltips=[
|
||||
("Connections", "@curr_con"),
|
||||
("SSL connections", "@curr_ssl_con"),
|
||||
("Sessions rate", "@sess_rate"),
|
||||
("Max sessions rate", "@max_sess_rate"),
|
||||
],
|
||||
mode='mouse'
|
||||
)
|
||||
|
||||
p[serv].ygrid.band_fill_color = "olive"
|
||||
p[serv].ygrid.band_fill_alpha = 0.1
|
||||
p[serv].y_range.start = 0
|
||||
p[serv].y_range.end = int(df['max_sess_rate'].max()) + 100
|
||||
p[serv].add_tools(hover)
|
||||
|
||||
p[serv].line("Date", "curr_con", source=source, alpha=0.5, color='#5cb85c', line_width=2, legend="Conn")
|
||||
p[serv].line("Date", "curr_ssl_con", source=source, alpha=0.5, color="#5d9ceb", line_width=2, legend="SSL con")
|
||||
p[serv].line("Date", "sess_rate", source=source, alpha=0.5, color="#33414e", line_width=2, legend="Sessions")
|
||||
p[serv].line("Date", "max_sess_rate", source=source, alpha=0.5, color="red", line_width=2, legend="Max sess")
|
||||
p[serv].legend.orientation = "horizontal"
|
||||
|
||||
#select = Select(title="Option:", value="foo", options=["foo", "bar", "baz", "quux"])
|
||||
#show(widgetbox(select, width=300))
|
||||
|
||||
plots = []
|
||||
i = 0
|
||||
for key, value in p.items():
|
||||
plots.append(value)
|
||||
|
||||
#plots = plots.sort()
|
||||
|
||||
grid = gridplot(plots, ncols=2, plot_width=800, plot_height=250, toolbar_location = "left", toolbar_options=dict(logo=None))
|
||||
show(grid)
|
20
app/ovw.py
20
app/ovw.py
|
@ -3,19 +3,14 @@ import os
|
|||
import cgi
|
||||
import sql
|
||||
|
||||
cgi_path = funct.get_config_var('main', 'cgi_path')
|
||||
fullpath = funct.get_config_var('main', 'fullpath')
|
||||
stats_port= funct.get_config_var('haproxy', 'stats_port')
|
||||
haproxy_config_path = funct.get_config_var('haproxy', 'haproxy_config_path')
|
||||
status_command = funct.get_config_var('haproxy', 'status_command')
|
||||
hap_configs_dir = funct.get_config_var('configs', 'haproxy_save_configs_dir')
|
||||
form = cgi.FieldStorage()
|
||||
|
||||
def get_overview():
|
||||
import os, http.cookies
|
||||
import http.cookies
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
env = Environment(loader=FileSystemLoader('templates/ajax'))
|
||||
template = env.get_template('overview.html')
|
||||
haproxy_config_path = funct.get_config_var('haproxy', 'haproxy_config_path')
|
||||
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
|
||||
user_id = cookie.get('uuid')
|
||||
|
||||
|
@ -31,9 +26,9 @@ def get_overview():
|
|||
|
||||
template = template.render(service_status = servers, role = sql.get_user_role_by_uuid(user_id.value))
|
||||
print(template)
|
||||
|
||||
|
||||
def get_overviewServers():
|
||||
import os, http.cookies
|
||||
import http.cookies
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
env = Environment(loader=FileSystemLoader('templates/ajax'))
|
||||
template = env.get_template('overviewServers.html')
|
||||
|
@ -60,7 +55,6 @@ def get_overviewServers():
|
|||
server_status = (server[1],server[2], out1, funct.ssh_command(server[2], commands),funct.show_backends(server[2], ret=1))
|
||||
servers.append(server_status)
|
||||
|
||||
#print(servers)
|
||||
template = template.render(service_status = servers, role = sql.get_user_role_by_uuid(user_id.value))
|
||||
print(template)
|
||||
|
||||
|
@ -72,6 +66,11 @@ def get_map(serv):
|
|||
matplotlib.use('Agg')
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
cgi_path = funct.get_config_var('main', 'cgi_path')
|
||||
fullpath = funct.get_config_var('main', 'fullpath')
|
||||
stats_port= funct.get_config_var('haproxy', 'stats_port')
|
||||
haproxy_config_path = funct.get_config_var('haproxy', 'haproxy_config_path')
|
||||
hap_configs_dir = funct.get_config_var('configs', 'haproxy_save_configs_dir')
|
||||
date = funct.get_data('config')
|
||||
cfg = hap_configs_dir + serv + "-" + date + ".cfg"
|
||||
|
||||
|
@ -186,6 +185,7 @@ def comapre_show():
|
|||
import subprocess
|
||||
left = form.getvalue('left')
|
||||
right = form.getvalue('right')
|
||||
hap_configs_dir = funct.get_config_var('configs', 'haproxy_save_configs_dir')
|
||||
cmd='diff -ub %s%s %s%s' % (hap_configs_dir, left, hap_configs_dir, right)
|
||||
|
||||
output, stderr = funct.subprocess_execute(cmd)
|
||||
|
|
75
app/sql.py
75
app/sql.py
|
@ -110,13 +110,13 @@ def update_group(name, descript, id):
|
|||
cur.close()
|
||||
con.close()
|
||||
|
||||
def add_server(hostname, ip, group, typeip, enable, master, cred, alert):
|
||||
def add_server(hostname, ip, group, typeip, enable, master, cred, alert, metrics):
|
||||
con, cur = create_db.get_cur()
|
||||
sql = """
|
||||
INSERT INTO servers
|
||||
(hostname, ip, groups, type_ip, enable, master, cred, alert)
|
||||
VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')
|
||||
""" % (hostname, ip, group, typeip, enable, master, cred, alert)
|
||||
(hostname, ip, groups, type_ip, enable, master, cred, alert, metrics)
|
||||
VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')
|
||||
""" % (hostname, ip, group, typeip, enable, master, cred, alert, metrics)
|
||||
try:
|
||||
cur.execute(sql)
|
||||
con.commit()
|
||||
|
@ -143,7 +143,7 @@ def delete_server(id):
|
|||
cur.close()
|
||||
con.close()
|
||||
|
||||
def update_server(hostname, ip, group, typeip, enable, master, id, cred, alert):
|
||||
def update_server(hostname, ip, group, typeip, enable, master, id, cred, alert, metrics):
|
||||
con, cur = create_db.get_cur()
|
||||
sql = """update servers set
|
||||
hostname = '%s',
|
||||
|
@ -153,8 +153,9 @@ def update_server(hostname, ip, group, typeip, enable, master, id, cred, alert):
|
|||
enable = '%s',
|
||||
master = '%s',
|
||||
cred = '%s',
|
||||
alert = '%s'
|
||||
where id = '%s'""" % (hostname, ip, group, typeip, enable, master, cred, alert, id)
|
||||
alert = '%s',
|
||||
metrics = '%s'
|
||||
where id = '%s'""" % (hostname, ip, group, typeip, enable, master, cred, alert, metrics, id)
|
||||
try:
|
||||
cur.execute(sql)
|
||||
con.commit()
|
||||
|
@ -636,6 +637,60 @@ def update_telegram(token, chanel, group, id):
|
|||
cur.close()
|
||||
con.close()
|
||||
|
||||
def insert_mentrics(serv, curr_con, cur_ssl_con, sess_rate, max_sess_rate):
|
||||
con, cur = create_db.get_cur()
|
||||
if mysql_enable == '1':
|
||||
sql = """ insert into metrics (serv, curr_con, cur_ssl_con, sess_rate, max_sess_rate, date) values('%s', '%s', '%s', '%s', '%s', now()) """ % (serv, curr_con, cur_ssl_con, sess_rate, max_sess_rate)
|
||||
else:
|
||||
sql = """ insert into metrics (serv, curr_con, cur_ssl_con, sess_rate, max_sess_rate, date) values('%s', '%s', '%s', '%s', '%s', datetime('now', 'localtime')) """ % (serv, curr_con, cur_ssl_con, sess_rate, max_sess_rate)
|
||||
try:
|
||||
cur.execute(sql)
|
||||
con.commit()
|
||||
except sqltool.Error as e:
|
||||
print('<span class="alert alert-danger" id="error">An error occurred: ' + e.args[0] + ' <a title="Close" id="errorMess"><b>X</b></a></span>')
|
||||
con.rollback()
|
||||
cur.close()
|
||||
con.close()
|
||||
|
||||
def delete_mentrics():
|
||||
con, cur = create_db.get_cur()
|
||||
if mysql_enable == '1':
|
||||
sql = """ delete from metrics where date < now() - INTERVAL 3 day """
|
||||
else:
|
||||
sql = """ delete from metrics where date < datetime('now', '-3 days') """
|
||||
try:
|
||||
cur.execute(sql)
|
||||
con.commit()
|
||||
except sqltool.Error as e:
|
||||
print('<span class="alert alert-danger" id="error">An error occurred: ' + e.args[0] + ' <a title="Close" id="errorMess"><b>X</b></a></span>')
|
||||
con.rollback()
|
||||
cur.close()
|
||||
con.close()
|
||||
|
||||
def select_metrics(serv, **kwargs):
|
||||
con, cur = create_db.get_cur()
|
||||
sql = """ select * from metrics where serv = '%s' order by `date` desc """ % serv
|
||||
try:
|
||||
cur.execute(sql)
|
||||
except sqltool.Error as e:
|
||||
print('<span class="alert alert-danger" id="error">An error occurred: ' + e + ' <a title="Close" id="errorMess"><b>X</b></a></span>')
|
||||
else:
|
||||
return cur.fetchall()
|
||||
cur.close()
|
||||
con.close()
|
||||
|
||||
def select_servers_metrics(**kwargs):
|
||||
con, cur = create_db.get_cur()
|
||||
sql = """ select ip from servers where metrics = '1' """
|
||||
try:
|
||||
cur.execute(sql)
|
||||
except sqltool.Error as e:
|
||||
print('<span class="alert alert-danger" id="error">An error occurred: ' + e + ' <a title="Close" id="errorMess"><b>X</b></a></span>')
|
||||
else:
|
||||
return cur.fetchall()
|
||||
cur.close()
|
||||
con.close()
|
||||
|
||||
def show_update_telegram(token, page):
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
env = Environment(loader=FileSystemLoader('templates/ajax'))
|
||||
|
@ -769,6 +824,7 @@ if form.getvalue('newserver') is not None:
|
|||
master = form.getvalue('slave')
|
||||
cred = form.getvalue('cred')
|
||||
alert = form.getvalue('alert_en')
|
||||
metrics = form.getvalue('metrics')
|
||||
page = form.getvalue('page')
|
||||
page = page.split("#")[0]
|
||||
if ip is None or group is None or cred is None:
|
||||
|
@ -776,7 +832,7 @@ if form.getvalue('newserver') is not None:
|
|||
print(error_mess)
|
||||
else:
|
||||
print('Content-type: text/html\n')
|
||||
if add_server(hostname, ip, group, typeip, enable, master, cred, alert):
|
||||
if add_server(hostname, ip, group, typeip, enable, master, cred, alert, metrics):
|
||||
show_update_server(ip, page)
|
||||
|
||||
if form.getvalue('serverdel') is not None:
|
||||
|
@ -818,13 +874,14 @@ if form.getvalue('updateserver') is not None:
|
|||
id = form.getvalue('id')
|
||||
cred = form.getvalue('cred')
|
||||
alert = form.getvalue('alert_en')
|
||||
metrics = form.getvalue('metrics')
|
||||
if name is None or ip is None:
|
||||
print('Content-type: text/html\n')
|
||||
print(error_mess)
|
||||
else:
|
||||
print('Content-type: text/html\n')
|
||||
#if funct.ssh_connect(ip, check=1):
|
||||
update_server(name, ip, group, typeip, enable, master, id, cred, alert)
|
||||
update_server(name, ip, group, typeip, enable, master, id, cred, alert, metrics)
|
||||
#else:
|
||||
# print('<span class="alert alert-danger" id="error"><a title="Close" id="errorMess"><b>X</b></a></span>')
|
||||
|
||||
|
|
|
@ -165,6 +165,7 @@
|
|||
<td>Enable</td>
|
||||
<td><span title="Vitrual IP, something like VRRP">Virt(?)</span></td>
|
||||
<td><span title="Alert if backend change status. Before enable add Telgram chanel at Checker tab">Alert(?)</span></td>
|
||||
<td><span title="Enable save and show metrics">Metrics(?)</span></td>
|
||||
<td><span title="Actions with master config will automatically apply on slave">Slave for (?)</span></td>
|
||||
<td>Credentials</td>
|
||||
<td></td>
|
||||
|
@ -211,6 +212,13 @@
|
|||
<label for="alert-{{server.0}}"></label><input type="checkbox" id="alert-{{server.0}}">
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if server.9 == 1 %}
|
||||
<label for="metrics-{{server.0}}"></label><input type="checkbox" id="metrics-{{server.0}}" checked>
|
||||
{% else %}
|
||||
<label for="metrics-{{server.0}}"></label><input type="checkbox" id="metrics-{{server.0}}">
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<select id="slavefor-{{server.0}}">
|
||||
<option value="0" selected>Not slave</option>
|
||||
|
@ -251,6 +259,7 @@
|
|||
<td>Enable</td>
|
||||
<td><span title="Vitrual IP, something like VRRP">Virt(?)</span></td>
|
||||
<td><span title="Alert if backend change status">Alert(?)</span></td>
|
||||
<td><span title="Enable save and show metrics">Metrics(?)</span></td>
|
||||
<td title="Actions with master config will automatically apply on slave">Slave for</td>
|
||||
<td>Credentials</td>
|
||||
<td></td>
|
||||
|
@ -279,6 +288,9 @@
|
|||
<td>
|
||||
<label for="alert"></label><input type="checkbox" id="alert">
|
||||
</td>
|
||||
<td>
|
||||
<label for="metrics"></label><input type="checkbox" id="metrics">
|
||||
</td>
|
||||
<td>
|
||||
<select id="slavefor">
|
||||
<option value="0" selected>Not slave</option>
|
||||
|
|
|
@ -43,6 +43,13 @@
|
|||
<label for="alert-{{server.0}}"></label><input type="checkbox" id="alert-{{server.0}}">
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if server.9 == 1 %}
|
||||
<label for="metrics-{{server.0}}"></label><input type="checkbox" id="metrics-{{server.0}}" checked>
|
||||
{% else %}
|
||||
<label for="metrics-{{server.0}}"></label><input type="checkbox" id="metrics-{{server.0}}">
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<select id="slavefor-{{server.0}}">
|
||||
<option value="0" selected>Not slave</option>
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
<li><a href=/app/logs.py title="View logs" class="logs head-submenu"> Logs</a></li>
|
||||
<li><a href=/app/map.py title="View map" class="map head-submenu">Map</a></li>
|
||||
<li><a href=/app/edit.py title="Runtime API" class="runtime head-submenu">Runtime API</a></li>
|
||||
<li><a href=/app/metrics.py title="Metrics" class="overview-link head-submenu">Metrics</a></li>
|
||||
</li>
|
||||
<li><a title="Actions with Haproxy configs" class="config-show">Haproxy</a>
|
||||
<li><a href=/app/configshow.py title="Show Haproxy Config" class="config-show head-submenu">Show config</a></li>
|
||||
|
@ -96,7 +97,7 @@
|
|||
</ul>
|
||||
</nav>
|
||||
<div class="copyright-menu">
|
||||
HAproxy-WI v2.7.3
|
||||
HAproxy-WI v2.8
|
||||
<br>
|
||||
<a href="https://www.patreon.com/haproxy_wi" title="Donate" target="_blank" style="color: #fff; margin-left: 30px; color: red;" class="patreon"> Patreon</a>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<style>
|
||||
iframe {
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
<div id="metrics_iframe"></div>
|
||||
<script>
|
||||
function callIframe(url, callback) {
|
||||
$('#metrics_iframe').html('<iframe id="metrics" style="width:100%;height:100%;" />');
|
||||
$('iframe#metrics').attr('src', url);
|
||||
$('iframe#metrics').load(function() {
|
||||
callback(this);
|
||||
});
|
||||
}
|
||||
|
||||
function loadMetrics() {
|
||||
callIframe('templates/metrics_out.html', function(){
|
||||
$.get( "options.py?metrics=1&token="+$('#token').val(), function( data ) {
|
||||
$( ".result" ).html( data );
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
loadMetrics()
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -24,6 +24,7 @@
|
|||
<td>Enable</td>
|
||||
<td><span title="Vitrual IP, something like VRRP">Virt(?)</span></td>
|
||||
<td><span title="Alert if backend change status. Before enable add Telgram chanel at Checker tab">Alert(?)</span></td>
|
||||
<td><span title="Enable save and show metrics">Metrics(?)</span></td>
|
||||
<td><span title="Actions with master config will automatically apply on slave">Slave for (?)</span></td>
|
||||
<td>Credentials</td>
|
||||
<td></td>
|
||||
|
@ -61,6 +62,13 @@
|
|||
<label for="alert-{{server.0}}"></label><input type="checkbox" id="alert-{{server.0}}">
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if server.9 == 1 %}
|
||||
<label for="metrics-{{server.0}}"></label><input type="checkbox" id="metrics-{{server.0}}" checked>
|
||||
{% else %}
|
||||
<label for="metrics-{{server.0}}"></label><input type="checkbox" id="metrics-{{server.0}}">
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<select id="slavefor-{{server.0}}">
|
||||
<option selected value="0">Not slave</option>
|
||||
|
@ -102,6 +110,7 @@
|
|||
<td>Enable</td>
|
||||
<td><span title="Vitrual IP, something like VRRP">Virt(?)</span></td>
|
||||
<td><span title="Alert if backend change status">Alert(?)</span></td>
|
||||
<td><span title="Enable save and show metrics">Metrics(?)</span></td>
|
||||
<td title="Actions with master config will automatically apply on slave">Slave for</td>
|
||||
<td>Credentials</td>
|
||||
<td></td>
|
||||
|
@ -123,6 +132,9 @@
|
|||
<td>
|
||||
<label for="alert"></label><input type="checkbox" id="alert">
|
||||
</td>
|
||||
<td>
|
||||
<label for="metrics"></label><input type="checkbox" id="metrics">
|
||||
</td>
|
||||
<td>
|
||||
<select id="slavefor">
|
||||
<option selected value="0">Not slave</option>
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 327 KiB After Width: | Height: | Size: 335 KiB |
|
@ -17,7 +17,7 @@ jQuery.expr[':'].regex = function(elem, index, match) {
|
|||
}
|
||||
window.onblur= function() {
|
||||
window.onfocus= function () {
|
||||
if($('.auto-refresh-pause').attr('style') == "display: inline; margin-top: 4px; margin-left: -25px;" && Cookies.get('auto-refresh') > 5000) {
|
||||
if(Cookies.get('auto-refresh-pause') == "0" && Cookies.get('auto-refresh') > 5000) {
|
||||
if (cur_url[0] == "logs.py") {
|
||||
showLog();
|
||||
} else if (cur_url[0] == "viewsttats.py") {
|
||||
|
@ -74,6 +74,7 @@ function setRefreshInterval(interval) {
|
|||
} else {
|
||||
clearInterval(intervalId);
|
||||
Cookies.set('auto-refresh', interval, { expires: 365 });
|
||||
Cookies.set('auto-refresh-pause', "0", { expires: 365 });
|
||||
startSetInterval(interval);
|
||||
hideAutoRefreshDiv();
|
||||
autoRefreshStyle(interval);
|
||||
|
@ -81,33 +82,42 @@ function setRefreshInterval(interval) {
|
|||
}
|
||||
|
||||
function startSetInterval(interval) {
|
||||
if (cur_url[0] == "logs.py") {
|
||||
intervalId = setInterval('showLog()', interval);
|
||||
showLog();
|
||||
} else if (cur_url[0] == "viewsttats.py") {
|
||||
intervalId = setInterval('showStats()', interval);
|
||||
showStats()
|
||||
} else if (cur_url[0] == "overview.py") {
|
||||
if(interval < 60000) {
|
||||
interval = 60000;
|
||||
}
|
||||
intervalId = setInterval('showOverview()', interval);
|
||||
showOverview();
|
||||
} else if (cur_url[0] == "viewlogs.py") {
|
||||
intervalId = setInterval('viewLogs()', interval);
|
||||
viewLogs();
|
||||
}
|
||||
if(Cookies.get('auto-refresh-pause') == "0") {
|
||||
if (cur_url[0] == "logs.py") {
|
||||
intervalId = setInterval('showLog()', interval);
|
||||
showLog();
|
||||
} else if (cur_url[0] == "viewsttats.py") {
|
||||
intervalId = setInterval('showStats()', interval);
|
||||
showStats()
|
||||
} else if (cur_url[0] == "overview.py") {
|
||||
if(interval < 60000) {
|
||||
interval = 60000;
|
||||
}
|
||||
intervalId = setInterval('showOverview()', interval);
|
||||
showOverview();
|
||||
} else if (cur_url[0] == "viewlogs.py") {
|
||||
intervalId = setInterval('viewLogs()', interval);
|
||||
viewLogs();
|
||||
} else if (cur_url[0] == "metrics.py") {
|
||||
intervalId = setInterval('loadMetrics()', interval);
|
||||
loadMetrics();
|
||||
}
|
||||
} else {
|
||||
pauseAutoRefresh();
|
||||
}
|
||||
}
|
||||
function pauseAutoRefresh() {
|
||||
clearInterval(intervalId);
|
||||
$(function() {
|
||||
$('.auto-refresh-pause').css('display', 'none');
|
||||
$('.auto-refresh-resume').css('display', 'inline');
|
||||
Cookies.set('auto-refresh-pause', "1", { expires: 365 });
|
||||
});
|
||||
}
|
||||
function pauseAutoResume(){
|
||||
var autoRefresh = Cookies.get('auto-refresh');
|
||||
setRefreshInterval(autoRefresh);
|
||||
Cookies.set('auto-refresh-pause', "0", { expires: 365 });
|
||||
}
|
||||
|
||||
function hideAutoRefreshDiv() {
|
||||
|
|
13
inc/users.js
13
inc/users.js
|
@ -31,6 +31,8 @@ $( function() {
|
|||
$("#ajax").html('<div class="alert alert-danger">Please fill in all fields</div>')
|
||||
} else if(! $("#vrrp-ip").val().match(ipformat)) {
|
||||
$("#ajax").html('<div class="alert alert-danger">Please enter IP in "VRRP IP" field</div>')
|
||||
} else if ($("#master").val() == $("#slave").val() ){
|
||||
$("#ajax").html('<div class="alert alert-danger">Master and slave must be diff servers</div>')
|
||||
} else {
|
||||
$("#ajax").html('<div class="alert alert-warning">Please don\'t close and don\'t represh page. Wait until the work is completed. This may take some time </div>');
|
||||
$.ajax( {
|
||||
|
@ -101,6 +103,7 @@ $( function() {
|
|||
if ($('#syn_flood').is(':checked')) {
|
||||
syn_flood = '1';
|
||||
}
|
||||
$("#ajax").html('<div class="alert alert-warning">Please don\'t close and don\'t represh page. Wait until the work is completed. This may take some time </div>');
|
||||
$.ajax( {
|
||||
url: "options.py",
|
||||
data: {
|
||||
|
@ -181,6 +184,7 @@ $( function() {
|
|||
var typeip = 0;
|
||||
var enable = 0;
|
||||
var alert_en = 0;
|
||||
var metrics = 0;
|
||||
if ($('#typeip').is(':checked')) {
|
||||
typeip = '1';
|
||||
}
|
||||
|
@ -190,6 +194,9 @@ $( function() {
|
|||
if ($('#alert').is(':checked')) {
|
||||
var alert_en = 0;
|
||||
}
|
||||
if ($('#metrics').is(':checked')) {
|
||||
var alert_en = 0;
|
||||
}
|
||||
$.ajax( {
|
||||
url: "sql.py",
|
||||
data: {
|
||||
|
@ -201,6 +208,7 @@ $( function() {
|
|||
slave: $('#slavefor' ).val(),
|
||||
cred: $('#credentials').val(),
|
||||
alert_en: alert_en,
|
||||
metrics: metrics,
|
||||
page: cur_url[0]
|
||||
},
|
||||
type: "GET",
|
||||
|
@ -621,6 +629,7 @@ function updateServer(id) {
|
|||
var typeip = 0;
|
||||
var enable = 0;
|
||||
var alert_en = 0;
|
||||
var metrics = 0;
|
||||
if ($('#typeip-'+id).is(':checked')) {
|
||||
typeip = '1';
|
||||
}
|
||||
|
@ -630,6 +639,9 @@ function updateServer(id) {
|
|||
if ($('#alert-'+id).is(':checked')) {
|
||||
alert_en = '1';
|
||||
}
|
||||
if ($('#metrics-'+id).is(':checked')) {
|
||||
metrics = '1';
|
||||
}
|
||||
var servergroup = $('#servergroup-'+id+' option:selected' ).val();
|
||||
if (cur_url[0] == "servers.py") {
|
||||
servergroup = $('#servergroup-'+id).val();
|
||||
|
@ -645,6 +657,7 @@ function updateServer(id) {
|
|||
slave: $('#slavefor-'+id+' option:selected' ).val(),
|
||||
cred: $('#credentials-'+id+' option:selected').val(),
|
||||
id: id,
|
||||
metrics: metrics,
|
||||
alert_en: alert_en
|
||||
},
|
||||
type: "GET",
|
||||
|
|
45
install.sh
45
install.sh
|
@ -40,7 +40,7 @@ echo ""
|
|||
echo "################################"
|
||||
|
||||
if hash apt-get 2>/dev/null; then
|
||||
apt-get install git net-tools lshw dos2unix apache2 gcc netcat python3-pip -y
|
||||
apt-get install git net-tools lshw dos2unix apache2 gcc netcat python3-pip gcc-c++ -y
|
||||
HTTPD_CONFIG="/etc/apache2/apache2.conf"
|
||||
HAPROXY_WI_VHOST_CONF="/etc/apache2/sites-enabled/haproxy-wi.conf"
|
||||
HTTPD_NAME="apache2"
|
||||
|
@ -57,7 +57,7 @@ else
|
|||
yum -y install epel-release
|
||||
fi
|
||||
|
||||
yum -y install git nmap-ncat net-tools lshw python34 dos2unix python34-pip httpd mod_ssl python34-devel
|
||||
yum -y install git nmap-ncat net-tools python34 dos2unix python34-pip httpd python34-devel gcc-c++
|
||||
HTTPD_CONFIG="/etc/httpd/conf/httpd.conf"
|
||||
HAPROXY_WI_VHOST_CONF="/etc/httpd/conf.d/haproxy-wi.conf"
|
||||
HTTPD_NAME="httpd"
|
||||
|
@ -190,13 +190,54 @@ cat << EOF > /etc/logrotate.d/checker
|
|||
}
|
||||
EOF
|
||||
|
||||
cat << EOF > /etc/systemd/system/multi-user.target.wants/metrics_haproxy.service
|
||||
[Unit]
|
||||
Description=Haproxy metrics
|
||||
After=syslog.target network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/var/www/haproxy-wi/app/
|
||||
ExecStart=/var/www/haproxy-wi/app/tools/metrics_master.py
|
||||
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=metrics
|
||||
|
||||
RestartSec=2s
|
||||
Restart=on-failure
|
||||
TimeoutStopSec=1s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
cat << EOF > /etc/rsyslog.d/metrics.conf
|
||||
if $programname startswith 'metrics' then /var/www/$HOME_HAPROXY_WI/log/metrics-error.log
|
||||
& stop
|
||||
EOF
|
||||
|
||||
cat << EOF > /etc/logrotate.d/metrics
|
||||
/var/www/$HOME_HAPROXY_WI/log/metrics-error.log {
|
||||
daily
|
||||
rotate 10
|
||||
missingok
|
||||
notifempty
|
||||
create 0644 apache apache
|
||||
dateext
|
||||
sharedscripts
|
||||
}
|
||||
EOF
|
||||
|
||||
sed -i 's/#$UDPServerRun 514/$UDPServerRun 514/g' /etc/rsyslog.conf
|
||||
sed -i 's/#$ModLoad imudp/$ModLoad imudp/g' /etc/rsyslog.conf
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl restart logrotate
|
||||
systemctl restart rsyslog
|
||||
systemctl restart cmetrics_haproxy.service
|
||||
systemctl restart checker_haproxy.service
|
||||
systemctl enable metrics_haproxy.service
|
||||
systemctl enable checker_haproxy.service
|
||||
|
||||
if hash apt-get 2>/dev/null; then
|
||||
|
|
|
@ -11,4 +11,6 @@ matplotlib==2.1.2
|
|||
urllib3==1.22
|
||||
future==0.13.1
|
||||
mysql-connector-python==8.0.11
|
||||
Jinja2==2.10
|
||||
Jinja2==2.10
|
||||
pandas==0.22.0
|
||||
bokeh==0.13.0
|
47
update.sh
47
update.sh
|
@ -10,7 +10,11 @@ mkdir app/certs
|
|||
chmod +x app/*py
|
||||
chmod +x app/tools/*py
|
||||
|
||||
|
||||
if hash apt-get 2>/dev/null; then
|
||||
apt-get install git net-tools lshw dos2unix apache2 gcc netcat python3-pip gcc-c++ -y
|
||||
else
|
||||
yum -y install git nmap-ncat net-tools python34 dos2unix python34-pip httpd python34-devel gcc-c++
|
||||
fi
|
||||
|
||||
at << EOF > /etc/systemd/system/multi-user.target.wants/checker_haproxy.service
|
||||
[Unit]
|
||||
|
@ -51,13 +55,54 @@ $(pwd)/log/checker-error.log {
|
|||
}
|
||||
EOF
|
||||
|
||||
cat << EOF > /etc/systemd/system/multi-user.target.wants/metrics_haproxy.service
|
||||
[Unit]
|
||||
Description=Haproxy metrics
|
||||
After=syslog.target network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/var/www/haproxy-wi/app/
|
||||
ExecStart=/var/www/haproxy-wi/app/tools/metrics_master.py
|
||||
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=metrics
|
||||
|
||||
RestartSec=2s
|
||||
Restart=on-failure
|
||||
TimeoutStopSec=1s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
cat << EOF > /etc/rsyslog.d/metrics.conf
|
||||
if $programname startswith 'metrics' then /var/www/$HOME_HAPROXY_WI/log/metrics-error.log
|
||||
& stop
|
||||
EOF
|
||||
|
||||
cat << EOF > /etc/logrotate.d/metrics
|
||||
/var/www/$HOME_HAPROXY_WI/log/metrics-error.log {
|
||||
daily
|
||||
rotate 10
|
||||
missingok
|
||||
notifempty
|
||||
create 0644 apache apache
|
||||
dateext
|
||||
sharedscripts
|
||||
}
|
||||
EOF
|
||||
|
||||
sed -i 's/#$UDPServerRun 514/$UDPServerRun 514/g' /etc/rsyslog.conf
|
||||
sed -i 's/#$ModLoad imudp/$ModLoad imudp/g' /etc/rsyslog.conf
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl restart logrotate
|
||||
systemctl restart rsyslog
|
||||
systemctl restart cmetrics_haproxy.service
|
||||
systemctl restart checker_haproxy.service
|
||||
systemctl enable metrics_haproxy.service
|
||||
systemctl enable checker_haproxy.service
|
||||
|
||||
chown -R apache:apache *
|
||||
|
|
Loading…
Reference in New Issue