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
|
||||
3. View logs of all servers in one place
|
||||
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
|
||||
7. Add sections: listen, frontend, backend from web interface
|
||||
8. Editing configs
|
||||
|
@ -34,15 +34,16 @@ Edit listserv.py, add your HAproxy servers.
|
|||
![alt text](image/7.jpeg "Overview page")
|
||||
|
||||
# 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
|
||||
log 172.28.0.5 local2 debug err
|
||||
stats socket *:1999 level admin
|
||||
global
|
||||
server-state-file /etc/haproxy/haproxy/haproxy.state
|
||||
defaults
|
||||
load-server-state-from-file global
|
||||
```
|
||||
![alt text](image/4.jpeg "View logs page")
|
||||
|
||||
|
|
123
cgi-bin/edit.py
|
@ -6,14 +6,57 @@ import subprocess
|
|||
import os
|
||||
import http.cookies
|
||||
import funct
|
||||
import configparser
|
||||
from funct import head as head
|
||||
|
||||
form = cgi.FieldStorage()
|
||||
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_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>'
|
||||
'<h2>Edit & show HAproxy settings</h2>'
|
||||
|
@ -23,71 +66,49 @@ print('<center>'
|
|||
'<td class="padding10">Server</td>'
|
||||
'<td>Disable/Enable server or output any information</td>'
|
||||
'<td class="padding10">Command</td>'
|
||||
'<td>Save change</td>'
|
||||
'<td></td>'
|
||||
'</tr>'
|
||||
'<tr>'
|
||||
'<td class="padding10" style="width: 35%;">'
|
||||
'<td class="padding10" style="width: 25%;">'
|
||||
'<form action="edit.py" method="get">'
|
||||
'<select autofocus required name="serv">'
|
||||
'<select required name="serv">'
|
||||
'<option disabled selected>Choose server</option>')
|
||||
|
||||
funct.choose_server_with_vip(serv)
|
||||
|
||||
action = form.getvalue('servaction')
|
||||
backend = form.getvalue('servbackend')
|
||||
|
||||
if action == '1':
|
||||
selected1 = 'selected'
|
||||
selected2 = ''
|
||||
selected3 = ''
|
||||
elif action == '2':
|
||||
selected1 = ''
|
||||
selected2 = 'selected'
|
||||
selected3 = ''
|
||||
elif action == '3':
|
||||
selected1 = ''
|
||||
selected2 = ''
|
||||
selected3 = 'selected'
|
||||
else:
|
||||
selected1 = ''
|
||||
selected2 = ''
|
||||
selected3 = ''
|
||||
|
||||
print('</select></td>'
|
||||
'<td style="width: 30%;">'
|
||||
'<select required name="servaction">'
|
||||
'<option disabled selected>Choose action</option>')
|
||||
print('<option value="disable" %s>Disable</option>' % selected1)
|
||||
print('<option value="enable" %s>Enable</option>' % selected2)
|
||||
print('<option value="set" %s>Set</option>' % selected3)
|
||||
print('<option value="show" %s>Show</option>' % selected4)
|
||||
print('</select></td>')
|
||||
print('<td style="width: 35%;"><select autofocus required name="servaction">')
|
||||
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><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('</td><td>')
|
||||
print('</td><td>'
|
||||
'<input type="checkbox" name="save" title="Save changes after restart">'
|
||||
'</td><td>')
|
||||
funct.mode_admin("Enter")
|
||||
print('</td></form>'
|
||||
'</tr></table>')
|
||||
|
||||
if form.getvalue('servaction') is not None:
|
||||
action = form.getvalue('servaction')
|
||||
backend = form.getvalue('servbackend')
|
||||
|
||||
if action == '1':
|
||||
enable = 'disable'
|
||||
elif action == '2':
|
||||
enable = 'enable'
|
||||
elif action == '3':
|
||||
enable = 'show'
|
||||
|
||||
cmd='echo "%s %s" |nc %s 1999' % (enable, backend, serv)
|
||||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, universal_newlines=True)
|
||||
stdout, stderr = p.communicate()
|
||||
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)))
|
||||
enable = form.getvalue('servaction')
|
||||
cmd='echo "%s %s" |socat stdio %s | cut -d "," -f 1-2,5-10,34-36 | column -s, -t' % (enable, backend, haproxy_sock)
|
||||
|
||||
if form.getvalue('save') == "on":
|
||||
save_command = 'echo "show servers state" | socat stdio %s > %s' % (haproxy_sock, server_state_file)
|
||||
command = [ cmd, save_command ]
|
||||
else:
|
||||
command = [ cmd ]
|
||||
|
||||
if enable != "show":
|
||||
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))
|
||||
|
||||
funct.ssh_command(serv, command, show_log="1")
|
||||
action = 'edit.py ' + enable + ' ' + backend
|
||||
funct.logging(serv, action)
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ def links():
|
|||
'<li><a href=/cgi-bin/map.py title="View map">Map</a></li>'
|
||||
'</ul>'
|
||||
'</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>'
|
||||
'<ul>'
|
||||
'<li><a href=/cgi-bin/configshow.py title="Show Config">Show</a></li> '
|
||||
|
|
|
@ -49,6 +49,8 @@ password = password
|
|||
stats_port = 8085
|
||||
stats_page = stats
|
||||
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
|
||||
tmp_config_path = /tmp
|
||||
#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/logs.py" title="View logs">Logs</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/configshow.py" title="Show Config">Show</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/delver.py" title="Upload old config">Delete old config</a> <br />
|
||||
<div class="copyright">
|
||||
HAproxy Web Interface v1.9
|
||||
HAproxy Web Interface v1.9.1
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|