1. Code is optimized.
2. Add new pages: "View users actions logs", "HAproxy-wi view settings"
3. Bugs fixed
4. Some design changes
pull/19/head
Aidaho12 2018-04-21 20:40:59 +06:00
parent 456fb657e5
commit 6ffbfae981
22 changed files with 234 additions and 190 deletions

View File

@ -1,5 +1,3 @@
# Meet Haproxy-wi 2.0! Now with DB and Admin web interface! Life has become easier, life has become more cheerful!
# Haproxy web interface # Haproxy web interface
A simple web interface(user-frendly web GUI) for managing Haproxy servers. Leave your [feedback](https://github.com/Aidaho12/haproxy-wi/issues) A simple web interface(user-frendly web GUI) for managing Haproxy servers. Leave your [feedback](https://github.com/Aidaho12/haproxy-wi/issues)
@ -17,7 +15,8 @@ A simple web interface(user-frendly web GUI) for managing Haproxy servers. Leave
9. Rollback to previous versions of the config 9. Rollback to previous versions of the config
10. Comparing versions of configs 10. Comparing versions of configs
11. Users roles: admin, editor, viewer 11. Users roles: admin, editor, viewer
12. Telegram notification 12. Server groups
13. Telegram notification
# Install # Install

View File

@ -4,23 +4,17 @@ import cgi
import os import os
import funct import funct
import sql import sql
import paramiko from configparser import ConfigParser, ExtendedInterpolation
import configparser
import http.cookies
from paramiko import SSHClient
from datetime import datetime
from pytz import timezone
funct.head("Add") funct.head("Add")
funct.check_config() funct.check_config()
funct.check_login() funct.check_login()
path_config = "haproxy-webintarface.config" path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser() config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(path_config) config.read(path_config)
funct.page_for_admin(level = 1) funct.page_for_admin(level = 2)
haproxy_configs_server = config.get('configs', 'haproxy_configs_server')
hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir') hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir')
form = cgi.FieldStorage() form = cgi.FieldStorage()
listhap = sql.get_dick_permit() listhap = sql.get_dick_permit()
@ -29,6 +23,7 @@ if form.getvalue('mode') is not None:
serv = form.getvalue('serv') serv = form.getvalue('serv')
port = form.getvalue('port') port = form.getvalue('port')
mode = " mode " + form.getvalue('mode') mode = " mode " + form.getvalue('mode')
ssl = ""
if form.getvalue('balance') is not None: if form.getvalue('balance') is not None:
balance = " balance " + form.getvalue('balance') + "\n" balance = " balance " + form.getvalue('balance') + "\n"
@ -101,10 +96,8 @@ if form.getvalue('mode') is not None:
config_add = name + "\n" + bind + mode + "\n" + balance + options_split + backend + servers_split + "\n" config_add = name + "\n" + bind + mode + "\n" + balance + options_split + backend + servers_split + "\n"
os.chdir(config.get('configs', 'haproxy_save_configs_dir')) os.chdir(config.get('configs', 'haproxy_save_configs_dir'))
fmt = "%Y-%m-%d.%H:%M:%S" cfg = hap_configs_dir + serv + "-" + funct.get_data('config') + ".cfg"
now_utc = datetime.now(timezone(config.get('main', 'time_zone')))
cfg = hap_configs_dir + serv + "-" + now_utc.strftime(fmt) + ".cfg"
funct.get_config(serv, cfg) funct.get_config(serv, cfg)
try: try:
@ -135,12 +128,12 @@ print('<div id="tabs">'
'<div id="listen">' '<div id="listen">'
'<form name="add-listner" action="add.py">' '<form name="add-listner" action="add.py">'
'<table>' '<table>'
'<caption><h2>Add listen</h2></caption>' '<caption><h3 style="margin-left: 20px; margin-bottom: 10px;">Add listen</h3></caption>'
'<tr>' '<tr>'
'<td class="addName">Select server: </td>' '<td class="addName">Select server: </td>'
'<td class="addOption">' '<td class="addOption">'
'<select required name="serv" id="serv">' '<select required name="serv" id="serv">'
'<option disabled selected>Choose server</option>') '<option disabled selected>Choose server</option>')
for i in listhap: for i in listhap:
print('<option value="%s">%s</option>' % (i[2], i[1])) print('<option value="%s">%s</option>' % (i[2], i[1]))
@ -255,12 +248,12 @@ print('</td>'
'<div id="frontend">' '<div id="frontend">'
'<form name="add-frontend" action="add.py">' '<form name="add-frontend" action="add.py">'
'<table>' '<table>'
'<caption><h2>Add frontend</h2></caption>' '<caption><h3 style="margin-left: 20px; margin-bottom: 10px;">Add frontend</h3></caption>'
'<tr>' '<tr>'
'<td class="addName">Select server: </td>' '<td class="addName">Select server: </td>'
'<td class="addOption">' '<td class="addOption">'
'<select required name="serv" id="serv2">' '<select required name="serv" id="serv2">'
'<option disabled selected>Choose server</option>') '<option disabled selected>Choose server</option>')
for i in listhap: for i in listhap:
print('<option value="%s">%s</option>' % (i[2], i[1])) print('<option value="%s">%s</option>' % (i[2], i[1]))
@ -339,12 +332,12 @@ print('</td>'
'<div id="backend">' '<div id="backend">'
'<form name="add-backend" action="add.py">' '<form name="add-backend" action="add.py">'
'<table>' '<table>'
'<caption><h2>Add frontend</h2></caption>' '<caption><h3 style="margin-left: 20px; margin-bottom: 10px;">Add backend</h3></caption>'
'<tr>' '<tr>'
'<td class="addName">Select server: </td>' '<td class="addName">Select server: </td>'
'<td class="addOption">' '<td class="addOption">'
'<select required name="serv">' '<select required name="serv">'
'<option disabled selected>Choose server</option>') '<option disabled selected>Choose server</option>')
for i in listhap: for i in listhap:
print('<option value="%s">%s</option>' % (i[2], i[1])) print('<option value="%s">%s</option>' % (i[2], i[1]))

View File

@ -3,12 +3,8 @@ import html
import cgi import cgi
import os import os
import http.cookies import http.cookies
import configparser from configparser import ConfigParser, ExtendedInterpolation
import funct import funct
import paramiko
from paramiko import SSHClient
from datetime import datetime
from pytz import timezone
form = cgi.FieldStorage() form = cgi.FieldStorage()
serv = form.getvalue('serv') serv = form.getvalue('serv')
@ -20,21 +16,19 @@ funct.check_login()
funct.page_for_admin(level = 1) funct.page_for_admin(level = 1)
path_config = "haproxy-webintarface.config" path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser() config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(path_config) config.read(path_config)
log_path = config.get('main', 'log_path') log_path = config.get('main', 'log_path')
hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir') hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir')
time_zone = config.get('main', 'time_zone')
if serv is not None:
fmt = "%Y-%m-%d.%H:%M:%S"
now_utc = datetime.now(timezone(time_zone))
cfg = hap_configs_dir + serv + "-" + now_utc.strftime(fmt) + ".cfg"
funct.chooseServer("config.py", "Edit HAproxy config", "y") funct.chooseServer("config.py", "Edit HAproxy config", "y")
if serv is not None:
cfg = hap_configs_dir + serv + "-" + funct.get_data('config') + ".cfg"
if form.getvalue('serv') is not None and form.getvalue('open') is not None : if form.getvalue('serv') is not None and form.getvalue('open') is not None :
funct.logging(serv, "config.py open config") funct.logging(serv, "config.py open config")
funct.get_config(serv, cfg) funct.get_config(serv, cfg)
@ -69,7 +63,7 @@ if form.getvalue('serv') is not None and form.getvalue('config') is not None:
funct.upload_and_restart(serv, cfg, just_save=save) funct.upload_and_restart(serv, cfg, just_save=save)
os.system("/bin/diff -ub %s %s >> %s/config_edit.log" % (oldcfg, cfg, log_path)) os.system("/bin/diff -ub %s %s >> %s/config_edit-%s.log" % (oldcfg, cfg, log_path, funct.get_data('logs')))
os.system("/bin/rm -f " + hap_configs_dir + "*.old") os.system("/bin/rm -f " + hap_configs_dir + "*.old")
print('</br><a href="viewsttats.py?serv=%s" target="_blank" title="View stats">Go to view stats</a> <br />' % serv) print('</br><a href="viewsttats.py?serv=%s" target="_blank" title="View stats">Go to view stats</a> <br />' % serv)

View File

@ -4,35 +4,32 @@ import cgi
import os import os
import funct import funct
import paramiko import paramiko
import configparser from configparser import ConfigParser, ExtendedInterpolation
from datetime import datetime from datetime import datetime
from pytz import timezone from pytz import timezone
form = cgi.FieldStorage() form = cgi.FieldStorage()
serv = form.getvalue('serv') serv = form.getvalue('serv')
servNew = form.getvalue('serNew')
funct.head("Show HAproxy config") funct.head("Show HAproxy config")
funct.check_config() funct.check_config()
funct.check_login() funct.check_login()
path_config = "haproxy-webintarface.config" path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser() config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(path_config) config.read(path_config)
ssh_keys = config.get('ssh', 'ssh_keys') ssh_keys = config.get('ssh', 'ssh_keys')
ssh_user_name = config.get('ssh', 'ssh_user_name') ssh_user_name = config.get('ssh', 'ssh_user_name')
hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir') hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir')
haproxy_config_path = config.get('haproxy', 'haproxy_config_path') haproxy_config_path = config.get('haproxy', 'haproxy_config_path')
time_zone = config.get('main', 'time_zone')
funct.chooseServer("configshow.py", "Show HAproxy config", "n", onclick="showConfig()") funct.chooseServer("configshow.py", "Show HAproxy config", "n", onclick="showConfig()")
print('<div id="ajax">') print('<div id="ajax">')
if form.getvalue('serv') is not None and form.getvalue('open') is not None : if serv is not None and form.getvalue('open') is not None :
fmt = "%Y-%m-%d.%H:%M:%S"
now_utc = datetime.now(timezone(time_zone)) cfg = hap_configs_dir + serv + "-" + funct.get_data('config') + ".cfg"
cfg = hap_configs_dir + serv + "-" + now_utc.strftime(fmt) + ".cfg"
funct.get_config(serv, cfg) funct.get_config(serv, cfg)

View File

@ -1,15 +1,9 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import html import html
import cgi import cgi
import subprocess
import os import os
import http.cookies
import funct import funct
import paramiko from configparser import ConfigParser, ExtendedInterpolation
import configparser
from paramiko import SSHClient
from datetime import datetime
from pytz import timezone
form = cgi.FieldStorage() form = cgi.FieldStorage()
serv = form.getvalue('serv') serv = form.getvalue('serv')
@ -18,10 +12,10 @@ configver = form.getvalue('configver')
funct.head("Old Versions HAproxy config") funct.head("Old Versions HAproxy config")
funct.check_config() funct.check_config()
funct.check_login() funct.check_login()
funct.page_for_admin(level = 1) funct.page_for_admin(level = 2)
path_config = "haproxy-webintarface.config" path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser() config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(path_config) config.read(path_config)
hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir') hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir')
@ -39,7 +33,7 @@ if serv is not None and form.getvalue('open') is not None:
os.chdir(hap_configs_dir) os.chdir(hap_configs_dir)
for files in glob.glob('*.cfg'): for files in sorted(glob.glob('*.cfg')):
ip = files.split("-") ip = files.split("-")
if serv == ip[0]: if serv == ip[0]:
if configver == files: if configver == files:
@ -61,7 +55,7 @@ if serv is not None and form.getvalue('open') is not None:
funct.logging(serv, "open old config %s" % configver) funct.logging(serv, "open old config %s" % configver)
print("<h3>Config from %s, and version is: %s</h3>" % (serv, configver)) print("<h3>Config from %s, and version is: %s</h3>" % (serv, configver))
print('<form action="configver.py#conf" method="post">') print('<form action="configver.py#conf" method="get">')
print('<input type="hidden" value="%s" name="serv">' % serv) print('<input type="hidden" value="%s" name="serv">' % serv)
print('<input type="hidden" value="%s" name="configver">' % configver) print('<input type="hidden" value="%s" name="configver">' % configver)
print('<input type="hidden" value="1" name="config">') print('<input type="hidden" value="1" name="config">')
@ -83,7 +77,7 @@ if form.getvalue('serv') is not None and form.getvalue('config') is not None:
funct.logging(serv, "configver.py upload old config %s" % configver) funct.logging(serv, "configver.py upload old config %s" % configver)
print("<b>Uploaded old config ver: %s </b></br></br>" % configver) print("<center><b>Uploaded old config ver: %s </b></br></br></center>" % configver)
funct.upload_and_restart(serv, configver, just_save=save) funct.upload_and_restart(serv, configver, just_save=save)

View File

@ -3,7 +3,7 @@ import html
import cgi import cgi
import os import os
import funct import funct
import configparser from configparser import ConfigParser, ExtendedInterpolation
import glob import glob
form = cgi.FieldStorage() form = cgi.FieldStorage()
@ -14,12 +14,12 @@ funct.check_config()
funct.check_login() funct.check_login()
path_config = "haproxy-webintarface.config" path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser() config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(path_config) config.read(path_config)
hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir') hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir')
funct.page_for_admin(level = 1) funct.page_for_admin()
funct.chooseServer("delver.py", "Delete Versions HAproxy config", "n") funct.chooseServer("delver.py", "Delete Versions HAproxy config", "n")
if serv is not None and form.getvalue('open') is not None: if serv is not None and form.getvalue('open') is not None:

View File

@ -3,7 +3,6 @@ import html
import cgi import cgi
import funct import funct
import ovw import ovw
import configparser
form = cgi.FieldStorage() form = cgi.FieldStorage()
serv = form.getvalue('serv') serv = form.getvalue('serv')
@ -13,14 +12,6 @@ right = form.getvalue('right')
funct.head("Compare HAproxy configs") funct.head("Compare HAproxy configs")
funct.check_config() funct.check_config()
funct.check_login() funct.check_login()
path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser()
config.read(path_config)
haproxy_configs_server = config.get('configs', 'haproxy_configs_server')
hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir')
funct.chooseServer("diff.py#diff", "Compare HAproxy configs", "n", onclick="showCompareConfigs()") funct.chooseServer("diff.py#diff", "Compare HAproxy configs", "n", onclick="showCompareConfigs()")
print('<div id="ajax-compare">') print('<div id="ajax-compare">')
@ -30,7 +21,7 @@ if serv is not None and form.getvalue('open') is not None :
print('</div><div id=ajax>') print('</div><div id=ajax>')
if serv is not None and form.getvalue('right') is not None: if serv is not None and right is not None:
ovw.comapre_show() ovw.comapre_show()
print('</div>') print('</div>')

View File

@ -5,26 +5,18 @@ import http.cookies
from paramiko import SSHClient from paramiko import SSHClient
from datetime import datetime from datetime import datetime
from pytz import timezone from pytz import timezone
import configparser from configparser import ConfigParser, ExtendedInterpolation
import sql import sql
def check_config():
path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser()
config.read(path_config)
for section in [ 'main', 'configs', 'ssh', 'logs', 'haproxy' ]:
if not config.has_section(section):
print('<b style="color: red">Check config file, no %s section</b>' % section)
path_config = "haproxy-webintarface.config" path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser() config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(path_config) config.read(path_config)
form = cgi.FieldStorage() form = cgi.FieldStorage()
serv = form.getvalue('serv') serv = form.getvalue('serv')
fullpath = config.get('main', 'fullpath') fullpath = config.get('main', 'fullpath')
log_path = config.get('main', 'log_path')
time_zone = config.get('main', 'time_zone')
ssh_keys = config.get('ssh', 'ssh_keys') ssh_keys = config.get('ssh', 'ssh_keys')
ssh_user_name = config.get('ssh', 'ssh_user_name') ssh_user_name = config.get('ssh', 'ssh_user_name')
haproxy_configs_server = config.get('configs', 'haproxy_configs_server') haproxy_configs_server = config.get('configs', 'haproxy_configs_server')
@ -32,8 +24,20 @@ hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir')
haproxy_config_path = config.get('haproxy', 'haproxy_config_path') haproxy_config_path = config.get('haproxy', 'haproxy_config_path')
tmp_config_path = config.get('haproxy', 'tmp_config_path') tmp_config_path = config.get('haproxy', 'tmp_config_path')
restart_command = config.get('haproxy', 'restart_command') restart_command = config.get('haproxy', 'restart_command')
time_zone = config.get('main', 'time_zone')
def check_config():
for section in [ 'main', 'configs', 'ssh', 'logs', 'haproxy' ]:
if not config.has_section(section):
print('<b style="color: red">Check config file, no %s section</b>' % section)
def get_data(type):
now_utc = datetime.now(timezone(time_zone))
if type == 'config':
fmt = "%Y-%m-%d.%H:%M:%S"
if type == 'logs':
fmt = '%Y%m%d'
return now_utc.strftime(fmt)
def logging(serv, action): def logging(serv, action):
dateFormat = "%b %d %H:%M:%S" dateFormat = "%b %d %H:%M:%S"
now_utc = datetime.now(timezone(time_zone)) now_utc = datetime.now(timezone(time_zone))
@ -41,7 +45,7 @@ def logging(serv, action):
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE")) cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
login = cookie.get('login') login = cookie.get('login')
mess = now_utc.strftime(dateFormat) + " from " + IP + " user: " + login.value + " " + action + " for: " + serv + "\n" mess = now_utc.strftime(dateFormat) + " from " + IP + " user: " + login.value + " " + action + " for: " + serv + "\n"
log = open(fullpath + "log/config_edit.log", "a") log = open(log_path + "/config_edit-"+get_data('logs')+".log", "a")
log.write(mess) log.write(mess)
log.close log.close
@ -185,10 +189,12 @@ def links():
'<li><a href=/cgi-bin/users.py#groups title="Actions with groups" class="group head-submenu">Groups</a></li>' '<li><a href=/cgi-bin/users.py#groups title="Actions with groups" class="group head-submenu">Groups</a></li>'
'<li><a href=/cgi-bin/users.py#servers title="Actions with servers" class="runtime head-submenu">Servers</a></li>' '<li><a href=/cgi-bin/users.py#servers title="Actions with servers" class="runtime head-submenu">Servers</a></li>'
'<li><a href=/cgi-bin/users.py#roles title="Users roles" class="role head-submenu">Roles</a></li>' '<li><a href=/cgi-bin/users.py#roles title="Users roles" class="role head-submenu">Roles</a></li>'
'<li><a href=/cgi-bin/settings.py title="View settings" class="settings head-submenu">View settings</a></li>'
'<li><a href=/cgi-bin/viewlogs.py title="View users actions logs" class="logs head-submenu">View logs</a></li>'
'</li>') '</li>')
print('</ul>' print('</ul>'
'</nav>' '</nav>'
'<div class="copyright-menu">HAproxy-WI v2.0.2.1</div>' '<div class="copyright-menu">HAproxy-WI v2.0.3</div>'
'</div>') '</div>')
def show_login_links(): def show_login_links():
@ -352,9 +358,7 @@ def show_config(cfg):
conf.close conf.close
def upload_and_restart(serv, cfg, **kwargs): def upload_and_restart(serv, cfg, **kwargs):
fmt = "%Y-%m-%d.%H:%M:%S" tmp_file = tmp_config_path + "/" + get_data('config') + ".cfg"
now_utc = datetime.now(timezone(config.get('main', 'time_zone')))
tmp_file = tmp_config_path + "/" + now_utc.strftime(fmt) + ".cfg"
ssh = ssh_connect(serv) ssh = ssh_connect(serv)
print("<center>connected<br />") print("<center>connected<br />")

View File

@ -15,7 +15,7 @@ haproxy_save_configs_dir = /var/www/haproxy-wi/cgi-bin/hap_config/
#If ssh connect disable entare password for ssh connect. Default enable #If ssh connect disable entare password for ssh connect. Default enable
ssh_keys_enable = 1 ssh_keys_enable = 1
#SSH keys to connect without password to HAproxy servers #SSH keys to connect without password to HAproxy servers
ssh_keys = /var/www/haproxy-wi/cgi-bin/id_rsa.pem ssh_keys = ${main:fullpath}/cgi-bin/id_rsa.pem
#Username for connect ssh #Username for connect ssh
ssh_user_name = root ssh_user_name = root
ssh_pass = ssh_pass =
@ -40,12 +40,13 @@ proxy =
restart_command = service haproxy restart restart_command = service haproxy restart
status_command = systemctl status haproxy status_command = systemctl status haproxy
#Username and password for Stats web page HAproxy #Username and password for Stats web page HAproxy
user = admin stats_user = admin
password = password stats_password = password
stats_port = 8085 stats_port = 8085
stats_page = stats stats_page = stats
haproxy_config_path = /etc/haproxy/haproxy.cfg haproxy_dir = /etc/haproxy
server_state_file = /etc/haproxy/haproxy.state haproxy_config_path = ${haproxy_dir}/haproxy.cfg
server_state_file = ${haproxy_dir}/haproxy.state
haproxy_sock = /var/run/haproxy.sock haproxy_sock = /var/run/haproxy.sock
#Temp store configs, for haproxy check #Temp store configs, for haproxy check
tmp_config_path = /tmp tmp_config_path = /tmp

View File

@ -2,7 +2,6 @@
import html import html
import cgi import cgi
import funct import funct
import configparser
form = cgi.FieldStorage() form = cgi.FieldStorage()
serv = form.getvalue('serv') serv = form.getvalue('serv')
@ -10,12 +9,8 @@ serv = form.getvalue('serv')
funct.head("HAproxy Logs") funct.head("HAproxy Logs")
funct.check_config() funct.check_config()
funct.check_login() funct.check_login()
path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser()
config.read(path_config)
funct.get_auto_refresh("HAproxy logs") funct.get_auto_refresh("HAproxy logs")
print('<table class="overview">' print('<table class="overview">'
'<tr class="overviewHead">' '<tr class="overviewHead">'
'<td class="padding10 first-collumn">Server</td>' '<td class="padding10 first-collumn">Server</td>'
@ -33,7 +28,7 @@ funct.choose_only_select(serv)
print('</select>') print('</select>')
if form.getvalue('serv') is not None: if serv is not None:
rows = 'value='+form.getvalue('rows') rows = 'value='+form.getvalue('rows')
else: else:
rows = 'value=10' rows = 'value=10'
@ -52,5 +47,8 @@ print('</td>'
'</form>' '</form>'
'</tr></table>' '</tr></table>'
'<div id="ajax">' '<div id="ajax">'
'</div>') '</div>'
'<script>'
'window.onload = showLog()'
'</script>')
funct.footer() funct.footer()

View File

@ -4,13 +4,6 @@ import cgi
import os import os
import funct import funct
import ovw import ovw
import configparser
from datetime import datetime
from pytz import timezone
import networkx as nx
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
form = cgi.FieldStorage() form = cgi.FieldStorage()
serv = form.getvalue('serv') serv = form.getvalue('serv')
@ -21,7 +14,7 @@ funct.check_login()
funct.chooseServer("map.py", "Show HAproxy map", "n", onclick="showMap()") funct.chooseServer("map.py", "Show HAproxy map", "n", onclick="showMap()")
print('<div id="ajax">') print('<div id="ajax">')
if form.getvalue('serv') is not None: if serv is not None:
ovw.get_map(serv) ovw.get_map(serv)
print('</div>') print('</div>')

View File

@ -5,12 +5,12 @@ import json
import subprocess import subprocess
import funct import funct
import ovw import ovw
import configparser from configparser import ConfigParser, ExtendedInterpolation
options = [ "acl", "http-request", "http-response", "set-uri", "set-url", "set-header", "add-header", "del-header", "replace-header", "path_beg", "url_beg()", "urlp_sub()", "tcpka", "tcplog", "forwardfor", "option" ] options = [ "acl", "http-request", "http-response", "set-uri", "set-url", "set-header", "add-header", "del-header", "replace-header", "path_beg", "url_beg()", "urlp_sub()", "tcpka", "tcplog", "forwardfor", "option" ]
path_config = "haproxy-webintarface.config" path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser() config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(path_config) config.read(path_config)
funct.check_config() funct.check_config()
@ -80,8 +80,8 @@ if serv is not None and act == "stats":
import requests import requests
from requests_toolbelt.utils import dump from requests_toolbelt.utils import dump
haproxy_user = config.get('haproxy', 'user') haproxy_user = config.get('haproxy', 'stats_user')
haproxy_pass = config.get('haproxy', 'password') haproxy_pass = config.get('haproxy', 'stats_password')
stats_port = config.get('haproxy', 'stats_port') stats_port = config.get('haproxy', 'stats_port')
stats_page = config.get('haproxy', 'stats_page') stats_page = config.get('haproxy', 'stats_page')
try: try:
@ -158,10 +158,7 @@ if serv is not None and act == "configShow":
from pytz import timezone from pytz import timezone
hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir') hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir')
time_zone = config.get('main', 'time_zone') cfg = hap_configs_dir + serv + "-" + funct.get_data('config') + ".cfg"
fmt = "%Y-%m-%d.%H:%M:%S"
now_utc = datetime.now(timezone(time_zone))
cfg = hap_configs_dir + serv + "-" + now_utc.strftime(fmt) + ".cfg"
funct.get_config(serv, cfg) funct.get_config(serv, cfg)
@ -176,6 +173,19 @@ if serv is not None and act == "configShow":
os.system("/bin/rm -f " + cfg) os.system("/bin/rm -f " + cfg)
if form.getvalue('viewlogs') is not None:
viewlog = form.getvalue('viewlogs')
log_path = config.get('main', 'log_path')
log = open(log_path + viewlog, "r")
print('<center><h3>Shows log: %s</h3></center><br />' % viewlog)
i = 0
for line in log:
i = i + 1
if i % 2 == 0:
print('<div class="line3">' + line + '</div>')
else:
print('<div class="line">' + line + '</div>')
if form.getvalue('tailf_stop') is not None: if form.getvalue('tailf_stop') is not None:
serv = form.getvalue('serv') serv = form.getvalue('serv')
commands = [ "ps ax |grep python3 |grep -v grep |awk '{ print $1 }' |xargs kill" ] commands = [ "ps ax |grep python3 |grep -v grep |awk '{ print $1 }' |xargs kill" ]

View File

@ -9,10 +9,6 @@ funct.check_config()
funct.check_login() funct.check_login()
funct.get_auto_refresh("Overview") funct.get_auto_refresh("Overview")
print('<div id="ajax">') print('<script> window.onload = showOverview()</script><div id="ajax"></div>')
ovw.get_overview()
print('</div>')
funct.footer() funct.footer()

View File

@ -1,12 +1,11 @@
import funct import funct
import configparser from configparser import ConfigParser, ExtendedInterpolation
import json
import os import os
import cgi import cgi
import sql import sql
path_config = "haproxy-webintarface.config" path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser() config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(path_config) config.read(path_config)
time_zone = config.get('main', 'time_zone') time_zone = config.get('main', 'time_zone')
@ -123,9 +122,8 @@ def get_map(serv):
matplotlib.use('Agg') matplotlib.use('Agg')
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
fmt = "%Y-%m-%d.%H:%M:%S" date = funct.get_data('config')
now_utc = datetime.now(timezone(time_zone)) cfg = hap_configs_dir + serv + "-" + date + ".cfg"
cfg = hap_configs_dir + serv + "-" + now_utc.strftime(fmt) + ".cfg"
print('<center>') print('<center>')
print("<h3>Map from %s</h3><br />" % serv) print("<h3>Map from %s</h3><br />" % serv)
@ -207,9 +205,9 @@ def get_map(serv):
except Exception as e: except Exception as e:
print("!!! There was an issue, " + str(e)) print("!!! There was an issue, " + str(e))
commands = [ "rm -f "+fullpath+"/map*.png", "mv %s/map.png %s/map%s.png" % (cgi_path, fullpath, now_utc.strftime(fmt)) ] commands = [ "rm -f "+fullpath+"/map*.png", "mv %s/map.png %s/map%s.png" % (cgi_path, fullpath, date) ]
funct.ssh_command("localhost", commands) funct.ssh_command("localhost", commands)
print('<img src="/map%s.png" alt="map">' % now_utc.strftime(fmt)) print('<img src="/map%s.png" alt="map">' % date)
def show_compare_configs(serv): def show_compare_configs(serv):
import glob import glob

33
cgi-bin/settings.py Normal file
View File

@ -0,0 +1,33 @@
#!/usr/bin/env python3
import html
import cgi
import sys
import os
import funct
from configparser import ConfigParser, ExtendedInterpolation
funct.head("Admin area: View settings")
funct.check_config()
funct.check_login()
funct.page_for_admin()
path_config = "haproxy-webintarface.config"
config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(path_config)
fullpath = config.get('main', 'fullpath')
print('<h2>Admin area: View settings</h2>'
'<div id="ajax">'
'<h3 style="padding-left: 30px; width:inherit; margin: 0" class="overviewHead padding10">Only view, edit you can here: {fullpath}/haproxy-webintarface.config</h3>'
'<pre>'.format(fullpath=fullpath))
for section_name in config.sections():
print('Section:', section_name)
#print(' Options:', config.options(section_name))
for name, value in config.items(section_name):
print(' {} = {}'.format(name, value))
print()
print('</div>')
funct.footer()

48
cgi-bin/viewlogs.py Normal file
View File

@ -0,0 +1,48 @@
#!/usr/bin/env python3
import html
import cgi
import os
import funct
from configparser import ConfigParser, ExtendedInterpolation
import glob
form = cgi.FieldStorage()
viewlog = form.getvalue('viewlogs')
funct.head("View logs")
funct.check_config()
funct.check_login()
path_config = "haproxy-webintarface.config"
config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(path_config)
log_path = config.get('main', 'log_path')
funct.page_for_admin()
funct.get_auto_refresh("View logs")
os.chdir(log_path)
print('<script src="/inc/users.js"></script>'
'<a name="top"></a>'
'<center><h3>Choose log file</h3><br />'
'<select id="viewlogs">')
i = 0
for files in sorted(glob.glob('*.log')):
i = i + 1
if files == viewlog:
selected = 'selected'
else:
selected = ''
print('<option value="%s" %s>%s</option>' % (files, selected, files))
print('</select>'
'<a class="ui-button ui-widget ui-corner-all" id="show" title="Show stats" onclick="viewLogs()">Show</a>'
'</center><br />'
'<div id="ajax"></div>'
'<script>'
'window.onload = viewLogs()'
'</script>')
funct.footer()

View File

@ -4,19 +4,10 @@ import cgi
import requests import requests
import funct import funct
import sql import sql
import configparser from configparser import ConfigParser, ExtendedInterpolation
from requests_toolbelt.utils import dump from requests_toolbelt.utils import dump
print("Content-type: text/html\n") print("Content-type: text/html\n")
funct.check_config()
path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser()
config.read(path_config)
haproxy_user = config.get('haproxy', 'user')
haproxy_pass = config.get('haproxy', 'password')
stats_port = config.get('haproxy', 'stats_port')
stats_page = config.get('haproxy', 'stats_page')
form = cgi.FieldStorage() form = cgi.FieldStorage()
serv = form.getvalue('serv') serv = form.getvalue('serv')
@ -40,28 +31,9 @@ funct.choose_only_select(serv, virt=1)
print('</select>' print('</select>'
'<a class="ui-button ui-widget ui-corner-all" id="show" title="Show stats" onclick="showStats()">Show</a>' '<a class="ui-button ui-widget ui-corner-all" id="show" title="Show stats" onclick="showStats()">Show</a>'
'</form>') '</form>'
'<div id="ajax" style="margin-left: 10px;"></div>')
try:
response = requests.get('http://%s:%s/%s' % (serv, stats_port, stats_page), auth=(haproxy_user, haproxy_pass))
except requests.exceptions.ConnectTimeout:
print('Oops. Connection timeout occured!')
except requests.exceptions.ReadTimeout:
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)
data = response.content
print('<a name="conf"></a><div id="ajax" style="margin-left: 10px;">')
print(data.decode('utf-8'))
print('</div>')
funct.head("Stats HAproxy configs") funct.head("Stats HAproxy configs")
print('</div>') print('</div><script> window.onload = showStats()</script>')
funct.footer() funct.footer()

View File

@ -101,6 +101,11 @@
font-family: "Font Awesome 5 Solid"; font-family: "Font Awesome 5 Solid";
content: "\f2b9"; content: "\f2b9";
} }
.settings::before {
display: none;
font-family: "Font Awesome 5 Solid";
content: "\f0ad";
}
.add-admin:before { .add-admin:before {
display: none; display: none;
font-family: "Font Awesome 5 Solid"; font-family: "Font Awesome 5 Solid";

View File

@ -57,8 +57,11 @@ function startSetInterval(interval) {
showStats() showStats()
} else if (cur_url[0] == "overview.py") { } else if (cur_url[0] == "overview.py") {
intervalId = setInterval('showOverview()', interval); intervalId = setInterval('showOverview()', interval);
showOverview(); showOverview();
} } else if (cur_url[0] == "viewlogs.py") {
intervalId = setInterval('viewLogs()', interval);
viewLogs();
}
} }
function pauseAutoRefresh() { function pauseAutoRefresh() {
clearInterval(intervalId); clearInterval(intervalId);
@ -123,6 +126,7 @@ function showLog() {
type: "GET", type: "GET",
success: function( data ) { success: function( data ) {
$("#ajax").html(data); $("#ajax").html(data);
window.history.pushState("Logs", "Logs", cur_url[0]+"?serv="+$("#serv").val()+"&rows="+$('#rows').val()+"&grep="+$("#grep").val());
} }
} ); } );
} }
@ -210,7 +214,19 @@ function showConfig() {
} }
} ); } );
} }
function viewLogs() {
$.ajax( {
url: "options.py",
data: {
viewlogs: $('#viewlogs').val(),
},
type: "GET",
success: function( data ) {
$("#ajax").html(data);
window.history.pushState("View logs", "View logs", cur_url[0]+"?viewlogs="+$("#viewlogs").val());
}
} );
}
$( function() { $( function() {
$( "#serv" ).on('selectmenuchange',function() { $( "#serv" ).on('selectmenuchange',function() {
$("#show").css("pointer-events", "inherit"); $("#show").css("pointer-events", "inherit");

View File

@ -70,15 +70,7 @@ pre {
float: left; float: left;
padding-left: 20px; padding-left: 20px;
} }
.top-menu a, .footer a {
padding: 10px;
margin-top: 10px;
padding-left: 7px;
padding-right: 7px;
}
.footer-link {
margin-left: 44%;
}
.container { .container {
min-height: calc(100vh - 115px); min-height: calc(100vh - 115px);
max-width: 91%; max-width: 91%;
@ -228,11 +220,13 @@ pre {
width: 120px; width: 120px;
} }
.addOption, .addName { .addOption, .addName {
border: 1px solid #ddd; border-bottom: 1px solid #ddd;
padding: 15px; padding: 15px;
} }
.addButton { .addButton {
padding-top: 15px; padding-top: 15px;
padding-left: 15px;
padding-bottom: 5px;
} }
.addButton:hover { .addButton:hover {
background-color: #fff; background-color: #fff;
@ -329,8 +323,8 @@ pre {
min-height: calc(100vh - 70px); min-height: calc(100vh - 70px);
} }
.menu ul li{ .menu ul li{
padding: 10px; padding: 7px;
padding-left: 20px; padding-left: 40px;
margin-right: 0px !important; margin-right: 0px !important;
} }
@ -406,7 +400,14 @@ pre {
.ui-tabs-nav { .ui-tabs-nav {
padding-left: 20px !important; padding-left: 20px !important;
} }
.ui-widget-header { .ui-tabs .ui-tabs-panel {
padding: 0 !important;
padding-bottom: 10px !important;
}
.ui-tabs {
padding-left: 0 !important;
}
.ui-widget-header {
background: #5d9ceb !important; background: #5d9ceb !important;
} }
.ui-menu, .ui-menu-item { .ui-menu, .ui-menu-item {

View File

@ -299,4 +299,4 @@ function updateServer(id) {
} }
} }
} ); } );
} }

View File

@ -8,4 +8,5 @@ dump==0.0.3
networkx==2.1 networkx==2.1
numpy==1.14.0 numpy==1.14.0
matplotlib==2.1.2 matplotlib==2.1.2
urllib3==1.22 urllib3==1.22
future==0.13.1