mirror of https://github.com/Aidaho12/haproxy-wi
parent
612a2a112f
commit
4a4c78f5c8
|
@ -69,6 +69,6 @@ if form.getvalue('serv') is not None and form.getvalue('open') is not None :
|
||||||
if form.getvalue('serv') is not None and form.getvalue('right') is not None:
|
if form.getvalue('serv') is not None and form.getvalue('right') is not None:
|
||||||
commands = [ 'diff -ub %s%s %s%s' % (hap_configs_dir, left, hap_configs_dir, right) ]
|
commands = [ 'diff -ub %s%s %s%s' % (hap_configs_dir, left, hap_configs_dir, right) ]
|
||||||
|
|
||||||
funct.ssh_command(haproxy_configs_server, commands, compare="compare")
|
funct.ssh_command(haproxy_configs_server, commands, compare="1")
|
||||||
|
|
||||||
funct.footer()
|
funct.footer()
|
|
@ -301,38 +301,33 @@ def show_ip(stdout):
|
||||||
for line in stdout:
|
for line in stdout:
|
||||||
print(line)
|
print(line)
|
||||||
|
|
||||||
|
def server_status(stdout):
|
||||||
|
if " " not in stdout.read().decode(encoding='UTF-8'):
|
||||||
|
print('<span class="serverUp"> UP</span> running 3 processes')
|
||||||
|
else:
|
||||||
|
print('<span lass="serverDown"> DOWN</span> running 0 processes')
|
||||||
|
|
||||||
def ssh_command(serv, commands, **kwargs):
|
def ssh_command(serv, commands, **kwargs):
|
||||||
ssh = ssh_connect(serv)
|
ssh = ssh_connect(serv)
|
||||||
|
|
||||||
ip = 0
|
|
||||||
compare_funct = 0
|
|
||||||
show_log_funct = 0
|
|
||||||
|
|
||||||
for k in kwargs:
|
|
||||||
if "ip" in kwargs[k]:
|
|
||||||
ip = 1
|
|
||||||
if "compare" in kwargs[k]:
|
|
||||||
compare_funct = 1
|
|
||||||
if "show_log" in kwargs[k]:
|
|
||||||
show_log_funct = 1
|
|
||||||
|
|
||||||
for command in commands:
|
for command in commands:
|
||||||
try:
|
try:
|
||||||
stdin, stdout, stderr = ssh.exec_command(command)
|
stdin, stdout, stderr = ssh.exec_command(command)
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if ip is 1:
|
if kwargs.get("ip") == "1":
|
||||||
show_ip(stdout)
|
show_ip(stdout)
|
||||||
if compare_funct is 1:
|
if kwargs.get("compare") == "1":
|
||||||
compare(stdout)
|
compare(stdout)
|
||||||
if show_log_funct is 1:
|
if kwargs.get("show_log") == "1":
|
||||||
show_log(stdout)
|
show_log(stdout)
|
||||||
|
if kwargs.get("server_status") == "1":
|
||||||
|
server_status(stdout)
|
||||||
else:
|
else:
|
||||||
print(stdout.read().decode(encoding='UTF-8'))
|
print(stdout.read().decode(encoding='UTF-8'))
|
||||||
|
|
||||||
print(stderr.read().decode(encoding='UTF-8'))
|
print(stderr.read().decode(encoding='UTF-8'))
|
||||||
#ssh.close()
|
|
||||||
|
|
||||||
def chooseServer(formName, title, note):
|
def chooseServer(formName, title, note):
|
||||||
print('<center><h2>' + title + '</h2>')
|
print('<center><h2>' + title + '</h2>')
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
[main]
|
||||||
|
#Path to files destination
|
||||||
|
fullpath = /var/www/haproxy-wi/
|
||||||
|
server_bind_ip = 0.0.0.0
|
||||||
|
server_port = 8000
|
||||||
|
log_path = %(fullpath)s/log/
|
||||||
|
time_zone = UTC
|
||||||
|
#Enable logo on top menu. Default disable
|
||||||
|
logo_enable = 0
|
||||||
|
logo_path = /logo.png
|
||||||
|
|
||||||
|
[configs]
|
||||||
|
#Server for save configs from HAproxy servers
|
||||||
|
haproxy_configs_server = localhost
|
||||||
|
#Dir where configs will be save
|
||||||
|
haproxy_save_configs_dir = /var/www/haproxy-wi/cgi-bin/hap_config/
|
||||||
|
|
||||||
|
[ssh]
|
||||||
|
#If ssh connect disable entare password for ssh connect. Default enable
|
||||||
|
ssh_keys_enable = 1
|
||||||
|
#SSH keys to connect without password to HAproxy servers
|
||||||
|
ssh_keys = /var/www/haproxy-wi/cgi-bin/id_rsa.pem
|
||||||
|
#Username for connect ssh
|
||||||
|
ssh_user_name = root
|
||||||
|
ssh_pass =
|
||||||
|
|
||||||
|
[logs]
|
||||||
|
#Logs save locally, disable by default
|
||||||
|
local_path_logs = /var/log/haproxy.log
|
||||||
|
#If exist syslog server for HAproxy logs
|
||||||
|
syslog_server_enable = 0
|
||||||
|
syslog_server =
|
||||||
|
|
||||||
|
[telegram]
|
||||||
|
#Send log message to telegram channel
|
||||||
|
#Default bot send message disable
|
||||||
|
enable = 0
|
||||||
|
token =
|
||||||
|
channel_name =
|
||||||
|
proxy =
|
||||||
|
|
||||||
|
[haproxy]
|
||||||
|
#Command for restart HAproxy service
|
||||||
|
restart_command = service haproxy restart
|
||||||
|
#Username and password for Stats web page HAproxy
|
||||||
|
user = admin
|
||||||
|
password = password
|
||||||
|
stats_port = 8085
|
||||||
|
stats_page = stats
|
||||||
|
haproxy_config_path = /etc/haproxy/haproxy.cfg
|
||||||
|
#Temp store configs, for haproxy check
|
||||||
|
tmp_config_path = /tmp
|
||||||
|
#Time in seconds for auto refresh view stats_port
|
||||||
|
refresh_time = 120
|
|
@ -71,6 +71,6 @@ if form.getvalue('serv') is not None:
|
||||||
commands = [ 'sudo tail -%s /var/log/%s/syslog.log %s %s' % (rows, serv, grep_act, grep) ]
|
commands = [ 'sudo tail -%s /var/log/%s/syslog.log %s %s' % (rows, serv, grep_act, grep) ]
|
||||||
syslog_server = config.get('logs', 'syslog_server')
|
syslog_server = config.get('logs', 'syslog_server')
|
||||||
|
|
||||||
funct.ssh_command(syslog_server, commands, show_log="show_log")
|
funct.ssh_command(syslog_server, commands, show_log="1")
|
||||||
|
|
||||||
funct.footer()
|
funct.footer()
|
|
@ -10,7 +10,6 @@ form = cgi.FieldStorage()
|
||||||
req = form.getvalue('req')
|
req = form.getvalue('req')
|
||||||
serv = form.getvalue('serv')
|
serv = form.getvalue('serv')
|
||||||
print('Content-type: text/html\n')
|
print('Content-type: text/html\n')
|
||||||
#print('Content-type: application/json\n')
|
|
||||||
|
|
||||||
if req is not None:
|
if req is not None:
|
||||||
if req is 1:
|
if req is 1:
|
||||||
|
@ -43,7 +42,7 @@ if backend is not None:
|
||||||
|
|
||||||
if form.getvalue('ip') is not None and serv is not None:
|
if form.getvalue('ip') is not None and serv is not None:
|
||||||
commands = [ "ip a |grep inet |egrep -v '::1' |awk '{ print $2 }' |awk -F'/' '{ print $1 }'" ]
|
commands = [ "ip a |grep inet |egrep -v '::1' |awk '{ print $2 }' |awk -F'/' '{ print $1 }'" ]
|
||||||
funct.ssh_command(serv, commands, ip="ip")
|
funct.ssh_command(serv, commands, ip="1")
|
||||||
|
|
||||||
if form.getvalue('name') is not None:
|
if form.getvalue('name') is not None:
|
||||||
name = form.getvalue('name')
|
name = form.getvalue('name')
|
||||||
|
|
|
@ -13,11 +13,20 @@ path_config = "haproxy-webintarface.config"
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read(path_config)
|
config.read(path_config)
|
||||||
|
|
||||||
commands = [ "cat /etc/haproxy/haproxy.cfg |grep -E '^listen|^backend|^frontend' |wc -l", "haproxy -v |head -1", "top -u haproxy -b -n 1" ]
|
|
||||||
print('<h2>Quick Status </h2><table class="overview">')
|
print('<h2>Quick Status </h2><table class="overview">')
|
||||||
|
|
||||||
|
commands = [ "ps -Af |grep [h]aproxy |wc -l" ]
|
||||||
|
|
||||||
|
print('<tr class="overviewHead"><td class="padding10">Server</td><td class="padding10">HAproxy status</td></tr>')
|
||||||
for i in sorted(listhap.listhap):
|
for i in sorted(listhap.listhap):
|
||||||
print('<tr><td class="overviewTr"><h3 title="IP ' + listhap.listhap.get(i) + '">Server ' + i + ':</h3></td>')
|
print('<tr><td class="padding10">' + i + '</td><td>')
|
||||||
|
funct.ssh_command(listhap.listhap.get(i), commands, server_status="1")
|
||||||
|
print('</td></tr>')
|
||||||
|
print('<tr class="overviewHead"><td class="padding10">Server</td><td class="padding10">Server status</td></tr>')
|
||||||
|
print('</td></tr>')
|
||||||
|
commands = [ "cat /etc/haproxy/haproxy.cfg |grep -E '^listen|^backend|^frontend' |grep -v stats |wc -l", "haproxy -v |head -1", "top -u haproxy -b -n 1" ]
|
||||||
|
for i in sorted(listhap.listhap):
|
||||||
|
print('<tr><td class="overviewTr"><h3 title="IP ' + listhap.listhap.get(i) + '">' + i + ':</h3></td>')
|
||||||
print('<td class="overviewTd">Total listen/frontend/backend:<pre>')
|
print('<td class="overviewTd">Total listen/frontend/backend:<pre>')
|
||||||
funct.ssh_command(listhap.listhap.get(i), commands)
|
funct.ssh_command(listhap.listhap.get(i), commands)
|
||||||
print('</pre></td></tr>')
|
print('</pre></td></tr>')
|
||||||
|
|
|
@ -7,8 +7,8 @@ import listserv as listhap
|
||||||
import configparser
|
import configparser
|
||||||
from requests_toolbelt.utils import dump
|
from requests_toolbelt.utils import dump
|
||||||
|
|
||||||
|
print("Content-type: text/html\n")
|
||||||
funct.check_config()
|
funct.check_config()
|
||||||
funct.check_login()
|
|
||||||
|
|
||||||
path_config = "haproxy-webintarface.config"
|
path_config = "haproxy-webintarface.config"
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
|
@ -16,6 +16,7 @@ config.read(path_config)
|
||||||
haproxy_user = config.get('haproxy', 'user')
|
haproxy_user = config.get('haproxy', 'user')
|
||||||
haproxy_pass = config.get('haproxy', 'password')
|
haproxy_pass = config.get('haproxy', 'password')
|
||||||
stats_port = config.get('haproxy', 'stats_port')
|
stats_port = config.get('haproxy', 'stats_port')
|
||||||
|
stats_page = config.get('haproxy', 'stats_page')
|
||||||
|
|
||||||
listhap.listhap = funct.merge_two_dicts(listhap.listhap, listhap.list_hap_vip)
|
listhap.listhap = funct.merge_two_dicts(listhap.listhap, listhap.list_hap_vip)
|
||||||
|
|
||||||
|
@ -27,32 +28,37 @@ if serv is None:
|
||||||
serv = first_serv[0]
|
serv = first_serv[0]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.get('http://%s:%s/stats' % (serv, stats_port), auth=(haproxy_user, haproxy_pass))
|
response = requests.get('http://%s:%s/%s' % (serv, stats_port, stats_page), auth=(haproxy_user, haproxy_pass))
|
||||||
except requests.exceptions.ConnectTimeout:
|
except requests.exceptions.ConnectTimeout:
|
||||||
print('Oops. Connection timeout occured!')
|
print('Oops. Connection timeout occured!')
|
||||||
except requests.exceptions.ReadTimeout:
|
except requests.exceptions.ReadTimeout:
|
||||||
print('Oops. Read timeout occured')
|
print('Oops. Read timeout occured')
|
||||||
|
except requests.exceptions.HTTPError as errh:
|
||||||
|
print ("Http Error:",errh)
|
||||||
|
except requests.exceptions.ConnectionError as errc:
|
||||||
|
print ("Error Connecting:",errc)
|
||||||
|
except requests.exceptions.Timeout as errt:
|
||||||
|
print ("Timeout Error:",errt)
|
||||||
|
except requests.exceptions.RequestException as err:
|
||||||
|
print ("OOps: Something Else",err)
|
||||||
|
|
||||||
print("Content-type: text/html\n")
|
|
||||||
print('<meta http-equiv="refresh" content="%s; url=viewsttats.py?serv=%s">' % (config.get('haproxy', 'refresh_time') ,serv))
|
print('<meta http-equiv="refresh" content="%s; url=viewsttats.py?serv=%s">' % (config.get('haproxy', 'refresh_time') ,serv))
|
||||||
|
|
||||||
for i in listhap.listhap:
|
for i in listhap.listhap:
|
||||||
if listhap.listhap.get(i) == serv:
|
if listhap.listhap.get(i) == serv:
|
||||||
servname = i
|
servname = i
|
||||||
|
|
||||||
print('<h3>Curent server IP - %s, name - %s </h3></br>' % (serv, servname))
|
print('<br /><br /><h3 style="padding-left: 20px; margin-top: 20px;">Choose server!</h3><br />'
|
||||||
print('<a href=/ title="Home Page" style="size:5">Home Page</a></br></br>')
|
'<form style="padding-left: 20px;" action="viewsttats.py" method="get">'
|
||||||
|
'<select autofocus required name="serv">'
|
||||||
print('<h3>Choose server!</h3></br>')
|
'<option disabled>Choose server</option>')
|
||||||
print('<form action="viewsttats.py" method="get">')
|
|
||||||
print('<p><select autofocus required name="serv">')
|
|
||||||
print('<option disabled>Choose server</option>')
|
|
||||||
|
|
||||||
funct.choose_server_with_vip(serv)
|
funct.choose_server_with_vip(serv)
|
||||||
|
|
||||||
print('</select><input type="submit"></p></form>')
|
print('</select><input type="submit" value="Show stats"></form>')
|
||||||
|
|
||||||
data = dump.dump_all(response)
|
data = response.content
|
||||||
print('<a name="conf"></a>')
|
print('<a name="conf"></a>')
|
||||||
print(data.decode('utf-8'))
|
print(data.decode('utf-8'))
|
||||||
|
funct.head("Stats HAproxy configs")
|
||||||
|
print('<style>.conteiner{display:none}</style>')
|
||||||
|
|
|
@ -25,9 +25,9 @@ ssh_user_name = root
|
||||||
ssh_pass =
|
ssh_pass =
|
||||||
|
|
||||||
[logs]
|
[logs]
|
||||||
#Logs save locally
|
#Logs save locally, disable by default
|
||||||
local_path_logs = /var/log/haproxy.log
|
local_path_logs = /var/log/haproxy.log
|
||||||
#If exist syslog server for HAproxy logs, disable by default
|
#If exist syslog server for HAproxy logs
|
||||||
syslog_server_enable = 0
|
syslog_server_enable = 0
|
||||||
syslog_server =
|
syslog_server =
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ restart_command = service haproxy restart
|
||||||
user = admin
|
user = admin
|
||||||
password = password
|
password = password
|
||||||
stats_port = 8085
|
stats_port = 8085
|
||||||
|
stats_page = stats
|
||||||
haproxy_config_path = /etc/haproxy/haproxy.cfg
|
haproxy_config_path = /etc/haproxy/haproxy.cfg
|
||||||
#Temp store configs, for haproxy check
|
#Temp store configs, for haproxy check
|
||||||
tmp_config_path = /tmp
|
tmp_config_path = /tmp
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<body>
|
<body>
|
||||||
<center>
|
<center>
|
||||||
<div class="conteinerIndex">
|
<div class="conteinerIndex">
|
||||||
<h2>Welcome! HAproxy Web Interface</h2>
|
<h2>Welcome to HAproxy-WI!</h2>
|
||||||
<h3>Choose your destiny!</h3>
|
<h3>Choose your destiny!</h3>
|
||||||
<a href="cgi-bin/overview.py" title="Server and service status">Overview</a> <br />
|
<a href="cgi-bin/overview.py" title="Server and service status">Overview</a> <br />
|
||||||
<a href="cgi-bin/viewsttats.py" title="View stats">View stats</a> <br />
|
<a href="cgi-bin/viewsttats.py" title="View stats">View stats</a> <br />
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<a href="cgi-bin/configver.py" title="Upload old config">Upload old config</a> <br />
|
<a href="cgi-bin/configver.py" title="Upload old config">Upload old config</a> <br />
|
||||||
<a href="cgi-bin/delver.py" title="Upload old config">Delete old config</a> <br />
|
<a href="cgi-bin/delver.py" title="Upload old config">Delete old config</a> <br />
|
||||||
<div class="copyright">
|
<div class="copyright">
|
||||||
HAproxy Web Interface v1.6.1
|
HAproxy Web Interface v1.6.2
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -4,9 +4,9 @@ $( function() {
|
||||||
$( "#tabs" ).tabs( "option", "active", 2 );
|
$( "#tabs" ).tabs( "option", "active", 2 );
|
||||||
} );
|
} );
|
||||||
$( "select" ).selectmenu();
|
$( "select" ).selectmenu();
|
||||||
$( document ).tooltip();
|
//$( document ).tooltip();
|
||||||
$( "input[type=submit], button" ).button();
|
$( "input[type=submit], button" ).button();
|
||||||
$( "input" ).checkboxradio();
|
$( "input[type=checkbox]" ).checkboxradio();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
$( function() {
|
$( function() {
|
||||||
|
|
57
style.css
57
style.css
|
@ -11,11 +11,17 @@ body {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
h2 {
|
h2 {
|
||||||
border: 1px solid #aaa;
|
border: 1px solid #5D9CEB;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background: #aaa;
|
background: #5D9CEB;
|
||||||
padding-left: 3%;
|
padding-left: 3%;
|
||||||
|
color: #fff;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
.top-menu {
|
.top-menu {
|
||||||
background-color: #222;
|
background-color: #222;
|
||||||
|
@ -47,7 +53,6 @@ h2 {
|
||||||
padding-left: 7px;
|
padding-left: 7px;
|
||||||
padding-right: 7px;
|
padding-right: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-link {
|
.top-link {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
@ -121,8 +126,8 @@ h2 {
|
||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
}
|
}
|
||||||
.line {
|
.line {
|
||||||
background-color: #eee;
|
background-color: #EBF1F1;
|
||||||
border: 1px solid #000;
|
border: 1px solid #ddd;
|
||||||
}
|
}
|
||||||
.line, .line3 {
|
.line, .line3 {
|
||||||
padding-top:5px;
|
padding-top:5px;
|
||||||
|
@ -134,7 +139,7 @@ h2 {
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
}
|
}
|
||||||
.addName {
|
.addName {
|
||||||
background-color: #eee;
|
background-color: #f6f6f6;
|
||||||
width: 120px;
|
width: 120px;
|
||||||
}
|
}
|
||||||
.addOption, .addName {
|
.addOption, .addName {
|
||||||
|
@ -167,6 +172,11 @@ h2 {
|
||||||
.overview {
|
.overview {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
.overviewHead {
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #EBF1F1;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
.overview tr{
|
.overview tr{
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
@ -179,10 +189,26 @@ h2 {
|
||||||
}
|
}
|
||||||
.overviewTr {
|
.overviewTr {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background-color: #eee;
|
background-color: #f6f6f6;
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
.serverUp, .serverDown {
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.serverUp {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
.serverDown {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
.padding10 {
|
||||||
|
padding: 10px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
.ro {
|
.ro {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
@ -203,6 +229,7 @@ h2 {
|
||||||
}
|
}
|
||||||
.menu ul li, .menu ul{
|
.menu ul li, .menu ul{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
.menu ul{
|
.menu ul{
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -228,7 +255,6 @@ h2 {
|
||||||
.menu li:hover ul{
|
.menu li:hover ul{
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu li:hover li{
|
.menu li:hover li{
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
@ -322,20 +348,9 @@ a,
|
||||||
a:visited {
|
a:visited {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
#a[href]:after {
|
|
||||||
# content: " (" attr(href) ")";
|
|
||||||
# }
|
|
||||||
#abbr[title]:after {
|
|
||||||
# content: " (" attr(title) ")";
|
|
||||||
# }
|
|
||||||
#a[href^="#"]:after,
|
|
||||||
#a[href^="javascript:"]:after {
|
|
||||||
# content: "";
|
|
||||||
# }
|
|
||||||
a {
|
a {
|
||||||
#color: #337ab7;
|
color: #9d9d9d;
|
||||||
color: #9d9d9d;
|
text-decoration: none;
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
a:hover,
|
a:hover,
|
||||||
a:focus {
|
a:focus {
|
||||||
|
|
Loading…
Reference in New Issue