15
README.md
|
@ -8,7 +8,7 @@ A simple web interface(user-frendly web GUI) for managing Haproxy servers. Leave
|
||||||
2. Server and service statsus in one place
|
2. Server and service statsus in one place
|
||||||
3. View logs of all servers in one place
|
3. View logs of all servers in one place
|
||||||
4. Map frontend, backends and servers
|
4. Map frontend, backends and servers
|
||||||
5. Disabling / enabling the backend servers without reboot (after reboot, will work as specified in the config), viewing server state data
|
5. Runtime API with the ability to save changes (need install socat on all haproxy servers)
|
||||||
6. Browsing Configs
|
6. Browsing Configs
|
||||||
7. Add sections: listen, frontend, backend from web interface
|
7. Add sections: listen, frontend, backend from web interface
|
||||||
8. Editing configs
|
8. Editing configs
|
||||||
|
@ -34,15 +34,16 @@ Edit listserv.py, add your HAproxy servers.
|
||||||

|

|
||||||
|
|
||||||
# Settings
|
# Settings
|
||||||
edit haproxy-webintarface.config with your env
|
Edit haproxy-webintarface.config with your env
|
||||||
|
|
||||||
copy ssh key on all HAproxy servers
|
Copy ssh key on all HAproxy servers
|
||||||
|
|
||||||
For online edit HAproxy settings enable socket on HAproxt servers:
|
For Runtime API enable state file on HAproxt servers and need install socat on all haproxy servers:
|
||||||
```
|
```
|
||||||
global
|
global
|
||||||
log 172.28.0.5 local2 debug err
|
server-state-file /etc/haproxy/haproxy/haproxy.state
|
||||||
stats socket *:1999 level admin
|
defaults
|
||||||
|
load-server-state-from-file global
|
||||||
```
|
```
|
||||||

|

|
||||||
|
|
||||||
|
|
123
cgi-bin/edit.py
|
@ -6,14 +6,57 @@ import subprocess
|
||||||
import os
|
import os
|
||||||
import http.cookies
|
import http.cookies
|
||||||
import funct
|
import funct
|
||||||
|
import configparser
|
||||||
from funct import head as head
|
from funct import head as head
|
||||||
|
|
||||||
form = cgi.FieldStorage()
|
form = cgi.FieldStorage()
|
||||||
serv = form.getvalue('serv')
|
serv = form.getvalue('serv')
|
||||||
|
action = form.getvalue('servaction')
|
||||||
|
backend = form.getvalue('servbackend')
|
||||||
|
|
||||||
head("Edit & show HAproxy settings")
|
head("Runtime API")
|
||||||
|
|
||||||
funct.check_login()
|
funct.check_login()
|
||||||
|
funct.check_config()
|
||||||
|
|
||||||
|
path_config = "haproxy-webintarface.config"
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read(path_config)
|
||||||
|
|
||||||
|
server_state_file = config.get('haproxy', 'server_state_file')
|
||||||
|
haproxy_sock = config.get('haproxy', 'haproxy_sock')
|
||||||
|
|
||||||
|
if backend is None:
|
||||||
|
backend = ""
|
||||||
|
autofocus = ""
|
||||||
|
else:
|
||||||
|
autofocus = "autofocus"
|
||||||
|
|
||||||
|
if action == 'disable':
|
||||||
|
selected1 = 'selected'
|
||||||
|
selected2 = ''
|
||||||
|
selected3 = ''
|
||||||
|
selected4 = ''
|
||||||
|
elif action == 'enable':
|
||||||
|
selected1 = ''
|
||||||
|
selected2 = 'selected'
|
||||||
|
selected3 = ''
|
||||||
|
selected4 = ''
|
||||||
|
elif action == 'set':
|
||||||
|
selected1 = ''
|
||||||
|
selected2 = ''
|
||||||
|
selected3 = 'selected'
|
||||||
|
selected4 = ''
|
||||||
|
elif action == 'show':
|
||||||
|
selected1 = ''
|
||||||
|
selected2 = ''
|
||||||
|
selected3 = ''
|
||||||
|
selected4 = 'selected'
|
||||||
|
else:
|
||||||
|
selected1 = ''
|
||||||
|
selected2 = ''
|
||||||
|
selected3 = ''
|
||||||
|
selected4 = ''
|
||||||
|
|
||||||
print('<center>'
|
print('<center>'
|
||||||
'<h2>Edit & show HAproxy settings</h2>'
|
'<h2>Edit & show HAproxy settings</h2>'
|
||||||
|
@ -23,71 +66,49 @@ print('<center>'
|
||||||
'<td class="padding10">Server</td>'
|
'<td class="padding10">Server</td>'
|
||||||
'<td>Disable/Enable server or output any information</td>'
|
'<td>Disable/Enable server or output any information</td>'
|
||||||
'<td class="padding10">Command</td>'
|
'<td class="padding10">Command</td>'
|
||||||
|
'<td>Save change</td>'
|
||||||
'<td></td>'
|
'<td></td>'
|
||||||
'</tr>'
|
'</tr>'
|
||||||
'<tr>'
|
'<tr>'
|
||||||
'<td class="padding10" style="width: 35%;">'
|
'<td class="padding10" style="width: 25%;">'
|
||||||
'<form action="edit.py" method="get">'
|
'<form action="edit.py" method="get">'
|
||||||
'<select autofocus required name="serv">'
|
'<select required name="serv">'
|
||||||
'<option disabled selected>Choose server</option>')
|
'<option disabled selected>Choose server</option>')
|
||||||
|
|
||||||
funct.choose_server_with_vip(serv)
|
funct.choose_server_with_vip(serv)
|
||||||
|
|
||||||
action = form.getvalue('servaction')
|
print('</select></td>'
|
||||||
backend = form.getvalue('servbackend')
|
'<td style="width: 30%;">'
|
||||||
|
'<select required name="servaction">'
|
||||||
if action == '1':
|
'<option disabled selected>Choose action</option>')
|
||||||
selected1 = 'selected'
|
print('<option value="disable" %s>Disable</option>' % selected1)
|
||||||
selected2 = ''
|
print('<option value="enable" %s>Enable</option>' % selected2)
|
||||||
selected3 = ''
|
print('<option value="set" %s>Set</option>' % selected3)
|
||||||
elif action == '2':
|
print('<option value="show" %s>Show</option>' % selected4)
|
||||||
selected1 = ''
|
|
||||||
selected2 = 'selected'
|
|
||||||
selected3 = ''
|
|
||||||
elif action == '3':
|
|
||||||
selected1 = ''
|
|
||||||
selected2 = ''
|
|
||||||
selected3 = 'selected'
|
|
||||||
else:
|
|
||||||
selected1 = ''
|
|
||||||
selected2 = ''
|
|
||||||
selected3 = ''
|
|
||||||
|
|
||||||
print('</select></td>')
|
print('</select></td>')
|
||||||
print('<td style="width: 35%;"><select autofocus required name="servaction">')
|
print('<td><input type="text" name="servbackend" size=35 title="Frontend, backend/server, show: info, pools or help" required class="form-control" value="%s" %s>' % (backend, autofocus))
|
||||||
print('<option disabled selected>Choose action</option>')
|
|
||||||
print('<option value=1 %s>Disable</option>' % selected1)
|
|
||||||
print('<option value=2 %s>Enable</option>' % selected2)
|
|
||||||
print('<option value=3 %s>Show</option>' % selected3)
|
|
||||||
print('</select></td>')
|
|
||||||
print('<td><input type="text" name="servbackend" size=35 title="Frontend, backend/server, show: info, pools or help" required class="form-control">')
|
|
||||||
|
|
||||||
print('</td><td>')
|
print('</td><td>'
|
||||||
|
'<input type="checkbox" name="save" title="Save changes after restart">'
|
||||||
|
'</td><td>')
|
||||||
funct.mode_admin("Enter")
|
funct.mode_admin("Enter")
|
||||||
print('</td></form>'
|
print('</td></form>'
|
||||||
'</tr></table>')
|
'</tr></table>')
|
||||||
|
|
||||||
if form.getvalue('servaction') is not None:
|
if form.getvalue('servaction') is not None:
|
||||||
action = form.getvalue('servaction')
|
enable = form.getvalue('servaction')
|
||||||
backend = form.getvalue('servbackend')
|
cmd='echo "%s %s" |socat stdio %s | cut -d "," -f 1-2,5-10,34-36 | column -s, -t' % (enable, backend, haproxy_sock)
|
||||||
|
|
||||||
if action == '1':
|
if form.getvalue('save') == "on":
|
||||||
enable = 'disable'
|
save_command = 'echo "show servers state" | socat stdio %s > %s' % (haproxy_sock, server_state_file)
|
||||||
elif action == '2':
|
command = [ cmd, save_command ]
|
||||||
enable = 'enable'
|
else:
|
||||||
elif action == '3':
|
command = [ cmd ]
|
||||||
enable = 'show'
|
|
||||||
|
if enable != "show":
|
||||||
cmd='echo "%s %s" |nc %s 1999' % (enable, backend, serv)
|
print('<center><h3>You %s %s on HAproxy %s. <a href="viewsttats.py?serv=%s" title="View stat" target="_blank">Look it</a> or <a href="edit.py" title="Edit">Edit something else</a></h3><br />' % (enable, backend, serv, serv))
|
||||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, universal_newlines=True)
|
|
||||||
stdout, stderr = p.communicate()
|
funct.ssh_command(serv, command, show_log="1")
|
||||||
err = stderr.splitlines()
|
|
||||||
output = stdout.splitlines()
|
|
||||||
|
|
||||||
print('<center><h3>You %s %s on HAproxy %s. <a href="viewsttats.py?serv=%s" title="View stat" target="_blank">Look it</a> or <a href="edit.py" title="Edit">Edit something else</a></h3><br />' % (enable, backend, serv, serv))
|
|
||||||
print('<center>'.join(map(str, output)))
|
|
||||||
if err:
|
|
||||||
print('<center>'.join(map(str, err)))
|
|
||||||
action = 'edit.py ' + enable + ' ' + backend
|
action = 'edit.py ' + enable + ' ' + backend
|
||||||
funct.logging(serv, action)
|
funct.logging(serv, action)
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ def links():
|
||||||
'<li><a href=/cgi-bin/map.py title="View map">Map</a></li>'
|
'<li><a href=/cgi-bin/map.py title="View map">Map</a></li>'
|
||||||
'</ul>'
|
'</ul>'
|
||||||
'</li>'
|
'</li>'
|
||||||
'<li><a href=/cgi-bin/edit.py title="Edit settings" style="size:5">Edit settings</a> </li>'
|
'<li><a href=/cgi-bin/edit.py title="Runtime API" style="size:5">Runtime API</a> </li>'
|
||||||
'<li><a href="#">Configs</a>'
|
'<li><a href="#">Configs</a>'
|
||||||
'<ul>'
|
'<ul>'
|
||||||
'<li><a href=/cgi-bin/configshow.py title="Show Config">Show</a></li> '
|
'<li><a href=/cgi-bin/configshow.py title="Show Config">Show</a></li> '
|
||||||
|
|
|
@ -49,6 +49,8 @@ password = password
|
||||||
stats_port = 8085
|
stats_port = 8085
|
||||||
stats_page = stats
|
stats_page = stats
|
||||||
haproxy_config_path = /etc/haproxy/haproxy.cfg
|
haproxy_config_path = /etc/haproxy/haproxy.cfg
|
||||||
|
server_state_file = /etc/haproxy/haproxy.state
|
||||||
|
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
|
||||||
#Time in seconds for auto refresh view stats_port
|
#Time in seconds for auto refresh view stats_port
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
[main]
|
|
||||||
#Path to files destination
|
|
||||||
fullpath = /opt/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 = /opt/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 = /opt/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
|
|
||||||
status_command = systemctl status haproxy
|
|
||||||
#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
|
|
BIN
image/10.jpeg
Before Width: | Height: | Size: 268 KiB After Width: | Height: | Size: 269 KiB |
BIN
image/2.jpeg
Before Width: | Height: | Size: 841 KiB After Width: | Height: | Size: 866 KiB |
BIN
image/3.jpeg
Before Width: | Height: | Size: 332 KiB After Width: | Height: | Size: 530 KiB |
BIN
image/4.jpeg
Before Width: | Height: | Size: 416 KiB After Width: | Height: | Size: 429 KiB |
BIN
image/5.jpeg
Before Width: | Height: | Size: 240 KiB After Width: | Height: | Size: 249 KiB |
BIN
image/6.jpeg
Before Width: | Height: | Size: 382 KiB After Width: | Height: | Size: 412 KiB |
BIN
image/7.jpeg
Before Width: | Height: | Size: 590 KiB After Width: | Height: | Size: 583 KiB |
BIN
image/8.jpeg
Before Width: | Height: | Size: 294 KiB After Width: | Height: | Size: 324 KiB |
BIN
image/9.jpeg
Before Width: | Height: | Size: 276 KiB After Width: | Height: | Size: 277 KiB |
|
@ -16,7 +16,7 @@
|
||||||
<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 />
|
||||||
<a href="cgi-bin/logs.py" title="View logs">Logs</a> <br />
|
<a href="cgi-bin/logs.py" title="View logs">Logs</a> <br />
|
||||||
<a href="cgi-bin/map.py" title="View map">Map</a> <br />
|
<a href="cgi-bin/map.py" title="View map">Map</a> <br />
|
||||||
<a href="cgi-bin/edit.py" title="Edit settings">Edit settings</a> <br />
|
<a href="cgi-bin/edit.py" title="Runtime API">Runtime API</a> <br />
|
||||||
<a href="cgi-bin/diff.py" title="Compare Configs">Compare</a> <br />
|
<a href="cgi-bin/diff.py" title="Compare Configs">Compare</a> <br />
|
||||||
<a href="cgi-bin/configshow.py" title="Show Config">Show</a> <br />
|
<a href="cgi-bin/configshow.py" title="Show Config">Show</a> <br />
|
||||||
<a href="cgi-bin/add.py" title="Add single listen/frontend/backend">Add</a> <br />
|
<a href="cgi-bin/add.py" title="Add single listen/frontend/backend">Add</a> <br />
|
||||||
|
@ -24,7 +24,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.9
|
HAproxy Web Interface v1.9.1
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|