add an alternate vrrp
pull/19/head
Aidaho12 2018-04-28 20:42:38 +06:00
parent 90df931e63
commit ac1945b48e
32 changed files with 184 additions and 73 deletions

View File

@ -3,24 +3,25 @@ A simple web interface(user-frendly web GUI) for managing Haproxy servers. Leave
![alt text](image/haproxy-wi-config-show.jpeg "Show config page")
# Capabilities:
1. View statistics of all servers in one place
2. Server and service statsus in one place
3. View logs of all servers in one place
4. Map frontend, backends and servers
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
9. Rollback to previous versions of the config
10. Master/slave servers
11. Configure firewalld on HAProxy servers based on config ports
12. Comparing versions of configs
13. Users roles: admin, editor, viewer
14. Server groups
15. Telegram notification
16. Creating HA HAProxy cluster
17. Editing keepalived configs
# Features:
1. Configure HAproxy In a jiffy with haproxy-wi
2. View and analyse Status of all Frontend/backend server via haproxy-wi from a single control panel.
3. View/Analyse HAproxy logs straight from the haproxy-wi web interface
4. Create and visualise the HAproxy workflow from Web Ui.
5. Push Your changes to your HAproxy servers with a single click through web interface.
6. Get info on past changes, Evaluate your config files and restore a previous stable config anytime with a single click straight from Web interface.
7. Add/Edit Frontend or backend servers via web interface with a click of a button.
8. Edit config of HAproxy and push changes to All Master/Slave server with a single click.
9. Add Multiple server to ensure Config Sync between servers.
10. Auto management of ports assigned to Fronted.
11. Evaluate the changes of recent configs pushed to HAproxy instances straight from web ui
12. Multiple User Roles support for privileged based Viewing and editing of Config.
13. Create Groups and add /remove servers to ensure proper identification for your HAproxy Clusters
14. Send notifications to telegram directly from haproxy-wi.
15. haproxy-wi supports high Availability to ensure uptime to all Master slave servers configured.
16. SSL certificate support.
17. SSH Key support for managing multiple HAproxy Servers straight from haproxy-wi
# Install
The installer will ask you a few questions
@ -37,7 +38,7 @@ $ cd /var/www/
$ git clone https://github.com/Aidaho12/haproxy-wi.git /var/www/haproxy-wi
$ chown -R apache:apache haproxy-wi/
$ pip install -r haproxy-wi/requirements.txt
$ chmod +x haproxy-wi/cgi-bin/*.py
$ chmod +x haproxy-wi/app/*.py
```
For Apache do virtualhost with cgi-bin. Like this:
@ -49,7 +50,7 @@ For Apache do virtualhost with cgi-bin. Like this:
CustomLog /var/log/httpd/haproxy-wi.access.log combined
DocumentRoot /var/www/haproxy-wi
ScriptAlias /cgi-bin/ "/var/www/haproxy-wi/cgi-bin/"
ScriptAlias /cgi-bin/ "/var/www/haproxy-wi/app/"
<Directory /var/www/haproxy-wi>
Options +ExecCGI
@ -74,7 +75,7 @@ MariaDB [(none)]> grant all on haproxywi.* to 'haproxy-wi'@'localhost' IDENTIFIE
# Settings
```
Edit $HOME_HAPROXY-WI/cgi-bin/haproxy-webintarface.config with your env
Edit $HOME_HAPROXY-WI/app/haproxy-webintarface.config with your env
```
Copy ssh key on all HAproxy servers
@ -95,14 +96,14 @@ For Runtime API enable state file on HAproxt servers and need install socat on a
# Update DB
```
$ cd /var/www/haproxy-wi/cgi-bin
$ cd /var/www/haproxy-wi/app
$ ./update_db.py
```
# Troubleshooting
If you have error:
```
Forbidden
You don't have permission to access /cgi-bin/overview.py on this server.
You don't have permission to access /app/overview.py on this server.
```
Check owner(must be apache, or another user for apache)
@ -114,7 +115,7 @@ Internal Server Error
Do this:
```
$ cd /var/www/haproxy-wi
$ cd /var/www/haproxy-wi/app
$ ./update_db.py
```

View File

@ -166,46 +166,46 @@ def links():
'<nav class="menu">'
'<ul>'
'<li><a title="Statistics, monitoring and logs" class="stats">Stats</a>'
'<li><a href=/cgi-bin/overview.py title="Server and service status" class="overview-link head-submenu">Overview</a> </li>'
'<li><a href=/cgi-bin/viewsttats.py title"Show stats" class="stats head-submenu">Stats</a> </li>'
'<li><a href=/cgi-bin/logs.py title="View logs" class="logs head-submenu">Logs</a></li>'
'<li><a href=/cgi-bin/map.py title="View map" class="map head-submenu">Map</a></li>'
'<li><a href=/app/overview.py title="Server and service status" class="overview-link head-submenu">Overview</a> </li>'
'<li><a href=/app/viewsttats.py title"Show stats" class="stats head-submenu">Stats</a> </li>'
'<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>'
'<li><a href=/cgi-bin/edit.py title="Runtime API" class="runtime">Runtime API</a> </li>'
'<li><a href=/app/edit.py title="Runtime API" class="runtime">Runtime API</a> </li>'
'<li><a title="Actions with Haproxy configs" class="config-show">Haproxy</a>'
'<li><a href=/cgi-bin/configshow.py title="Show Haproxy Config" class="config-show head-submenu">Show config</a></li> '
'<li><a href=/cgi-bin/diff.py title="Compare Haproxy Configs" class="compare head-submenu">Compare configs</a></li>')
'<li><a href=/app/configshow.py title="Show Haproxy Config" class="config-show head-submenu">Show config</a></li> '
'<li><a href=/app/diff.py title="Compare Haproxy Configs" class="compare head-submenu">Compare configs</a></li>')
if is_admin(level = 2):
print('<li><a href=/cgi-bin/add.py#listner title="Add single listen" class="add head-submenu">Add listen</a></li>'
'<li><a href=/cgi-bin/add.py#frontend title="Add single frontend" class="add head-submenu">Add frontend</a></li>'
'<li><a href=/cgi-bin/add.py#backend title="Add single backend" class="add head-submenu">Add backend</a></li>'
'<li><a href=/cgi-bin/add.py#ssl title="Upload SSL cert" class="cert head-submenu">SSL</a></li>'
'<li><a href=/cgi-bin/config.py title="Edit Haproxy Config" class="edit head-submenu">Edit config</a> </li>')
print('<li><a href=/app/add.py#listner title="Add single listen" class="add head-submenu">Add listen</a></li>'
'<li><a href=/app/add.py#frontend title="Add single frontend" class="add head-submenu">Add frontend</a></li>'
'<li><a href=/app/add.py#backend title="Add single backend" class="add head-submenu">Add backend</a></li>'
'<li><a href=/app/add.py#ssl title="Upload SSL cert" class="cert head-submenu">SSL</a></li>'
'<li><a href=/app/config.py title="Edit Haproxy Config" class="edit head-submenu">Edit config</a> </li>')
print('</li>')
if is_admin():
print('<li><a title="Keepalived" class="ha">Keepalived</a>'
'<li><a href=/cgi-bin/ha.py title="Create HA cluster" class="keepalived head-submenu">HA</a>'
'<li><a href=/cgi-bin/keepalivedconfig.py title="Edit keepalived config" class="edit head-submenu">Edit config</a></li>')
'<li><a href=/app/ha.py title="Create HA cluster" class="keepalived head-submenu">HA</a>'
'<li><a href=/app/keepalivedconfig.py title="Edit keepalived config" class="edit head-submenu">Edit config</a></li>')
if is_admin(level = 2):
print('<li><a title="Actions with configs" class="version">Versions</a>'
'<li><a href=/cgi-bin/configver.py title="Upload old versions configs" class="upload head-submenu">Upload</a></li>')
'<li><a href=/app/configver.py title="Upload old versions configs" class="upload head-submenu">Upload</a></li>')
if is_admin():
print('<li><a href=/cgi-bin/delver.py title="Delete old versions configs" class="delete head-submenu">Delete</a></li>')
print('<li><a href=/app/delver.py title="Delete old versions configs" class="delete head-submenu">Delete</a></li>')
if is_admin(level = 2):
print('</li>')
show_login_links()
if is_admin():
print('<li><a title="Admin area" class="admin">Admin area</a>'
'<li><a href=/cgi-bin/users.py#users title="Actions with users" class="users head-submenu">Users</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#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><a href=/app/users.py#users title="Actions with users" class="users head-submenu">Users</a></li>'
'<li><a href=/app/users.py#groups title="Actions with groups" class="group head-submenu">Groups</a></li>'
'<li><a href=/app/users.py#servers title="Actions with servers" class="runtime head-submenu">Servers</a></li>'
'<li><a href=/app/users.py#roles title="Users roles" class="role head-submenu">Roles</a></li>'
'<li><a href=/app/settings.py title="View settings" class="settings head-submenu">View settings</a></li>'
'<li><a href=/app/viewlogs.py title="View users actions logs" class="logs head-submenu">View logs</a></li>'
'</li>')
print('</ul>'
'</nav>'
'<div class="copyright-menu">HAproxy-WI v2.2</div>'
'<div class="copyright-menu">HAproxy-WI v2.3</div>'
'</div>')
def show_login_links():
@ -213,9 +213,9 @@ def show_login_links():
login = cookie.get('login')
if login is None:
print('<li><a href=/cgi-bin/login.py? title="Login" class="login">Login</a></li>')
print('<li><a href=/app/login.py? title="Login" class="login">Login</a></li>')
else:
print('<li><a href=/cgi-bin/login.py?logout=logout title="Logout, user name: %s" class="login">Logout</a></li>' % login.value)
print('<li><a href=/app/login.py?logout=logout title="Logout, user name: %s" class="login">Logout</a></li>' % login.value)
def footer():
print('</center></div>'
@ -246,7 +246,7 @@ def get_auto_refresh(h2):
'</li>'
'</ul>'
'</div>'
'<div class="auto-refresh-ul">'
'<div class="auto-refresh-ul" id="secIntervals">'
'<ul>'
'<li>'
'<a title="Auto-refresh every 5 seconds" onclick="setRefreshInterval(5000)">5 seconds</a>'

View File

@ -17,6 +17,7 @@ serv = ""
print('<script src="/inc/users.js"></script>'
'<h2>Configure HA</h2>'
'<table class="overview">'
'<caption class="overviewHead"><h3 style="margin-left: 20px; margin-bottom: 10px;">Create new HA cluster</h3></caption>'
'<tr class="overviewHead">'
'<td class="padding10 first-collumn">Master</td>'
'<td>Slave</td>'
@ -50,6 +51,43 @@ print('</select>'
'<td>'
'<a class="ui-button ui-widget ui-corner-all" id="create" title="Create HA configuration">Create</a>'
'</td>'
'</table>'
'<table>'
'<caption class="overviewHead"><h3 style="margin-left: 20px; margin-bottom: 10px;">Or add VRRP to exist</h3></caption>'
'<tr class="overviewHead">'
'<td class="padding10 first-collumn">Master</td>'
'<td>Slave</td>'
'<td>VRRP interface</td>'
'<td>VRRP IP</td>'
'<td><span title="If checked Haproxy-WI will restart Keepalived">Restart Keepalived(?)</span></td>'
'<td></td>'
'</tr>'
'<tr>'
'<td class="padding10 first-collumn">'
'<select id="master-add">'
'<option disable selected>Choose master</option>')
funct.choose_only_select(serv)
print('</select>'
'</td>'
'<td>'
'<select id="slave-add">'
'<option disable selected>Choose master</option>')
funct.choose_only_select(serv)
print('</select>'
'</td>'
'<td>'
'<input type="text" id="interface-add" class="form-control">'
'</td>'
'<td>'
'<input type="text" id="vrrp-ip-add" class="form-control">'
'</td>'
'<td>'
'<label for="kp"></label><input type="checkbox" id="kp">'
'</td>'
'<td>'
'<a class="ui-button ui-widget ui-corner-all" id="add-vrrp" title="Add HA configuration">Add</a>'
'</td>'
'</table>'
'<div id="ajax"></div>')

View File

@ -1,7 +1,7 @@
[main]
#Path to files destination
fullpath = /var/www/haproxy-wi
cgi_path = ${fullpath}/cgi-bin/
cgi_path = ${fullpath}/app/
log_path = ${fullpath}/log/
cert_local_dir = ${cgi_path}/certs/
time_zone = UTC
@ -10,8 +10,8 @@ time_zone = UTC
#Server for save configs from HAproxy servers
haproxy_configs_server = localhost
#Dir where configs will be save
haproxy_save_configs_dir = ${main:fullpath}/cgi-bin/hap_config/
kp_save_configs_dir = ${main:fullpath}/cgi-bin/kp_config/
haproxy_save_configs_dir = ${main:fullpath}/app/hap_config/
kp_save_configs_dir = ${main:fullpath}/app/kp_config/
[mysql]
#Enable MySQL DB. If default will be used Sqlite DB. Default disable
@ -25,7 +25,7 @@ mysql_host = 127.0.0.1
#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 = ${main:fullpath}/cgi-bin/id_rsa.pem
ssh_keys = ${main:fullpath}/app/id_rsa.pem
#Username for connect ssh
ssh_user_name = root
ssh_pass =

View File

@ -39,8 +39,8 @@ def login_page(error):
print('</form></center>')
if form.getvalue('logout') is not None:
print("Set-cookie: login=; expires=Wed May 18 03:33:20 2003; path=/cgi-bin/; httponly")
print("Set-cookie: role=; expires=Wed May 18 03:33:20 2003; path=/cgi-bin/; httponly")
print("Set-cookie: login=; expires=Wed May 18 03:33:20 2003; path=/app/; httponly")
print("Set-cookie: role=; expires=Wed May 18 03:33:20 2003; path=/app/; httponly")
print("Content-type: text/html\n")
print('<meta http-equiv="refresh" content="0; url=/">')
@ -60,13 +60,13 @@ if login is not None and password is not None:
role = 3
c = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
c["login"] = login
c["login"]["path"] = "/cgi-bin/"
c["login"]["path"] = "/app/"
c["login"]["expires"] = "Wed May 18 03:33:20 2033"
c["role"] = role
c["role"]["path"] = "/cgi-bin/"
c["role"]["path"] = "/app/"
c["role"]["expires"] = "Wed May 18 03:33:20 2033"
c["group"] = users[4]
c["group"]["path"] = "/cgi-bin/"
c["group"]["path"] = "/app/"
c["group"]["expires"] = "Wed May 18 03:33:20 2033"
print(c)
if form.getvalue('ref') is None:

View File

@ -248,4 +248,26 @@ if form.getvalue('master'):
funct.ssh_command(slave, commands)
os.system("rm -f %s" % script)
sql.update_server_master(master, slave)
sql.update_server_master(master, slave)
if form.getvalue('masteradd'):
master = form.getvalue('masteradd')
slave = form.getvalue('slaveadd')
interface = form.getvalue('interfaceadd')
vrrpip = form.getvalue('vrrpipadd')
kp = form.getvalue('kp')
tmp_config_path = config.get('haproxy', 'tmp_config_path')
script = "add_vrrp.sh"
os.system("cp scripts/%s ." % script)
funct.upload(master, tmp_config_path, script)
funct.upload(slave, tmp_config_path, script)
commands = [ "chmod +x "+tmp_config_path+script, tmp_config_path+script+" MASTER "+interface+" "+vrrpip+" "+kp]
funct.ssh_command(master, commands)
commands = [ "chmod +x "+tmp_config_path+script, tmp_config_path+script+" BACKUP "+interface+" "+vrrpip+" "+kp ]
funct.ssh_command(slave, commands)
os.system("rm -f %s" % script)

View File

@ -8,7 +8,7 @@ funct.head("Overview")
funct.check_config()
funct.check_login()
funct.get_auto_refresh("Overview")
print("<script>if (cur_url[0] == 'overview.py') { $('#secIntervals').css('display', 'none');}</script>")
print('<script> window.onload = showOverview()</script><div id="ajax"></div>')
funct.footer()

View File

@ -81,10 +81,10 @@ def get_overview():
print('<a id="%s" class="start" title="Start HAproxy service" onclick = "if (! confirm(\'Start service?\')) return false;"><img src=/image/pic/start.png alt="start" class="icon"></a>' % server[2])
print('<a id="%s" class="stop" title="Stop HAproxy service" onclick = "return confirm(\'Stop service?\')"><img src=/image/pic/stop.png alt="start" class="icon"></a>' % server[2])
print('<a id="%s" class="restart" title="Restart HAproxy service" onclick = "if (! confirm(\'Restart service?\')) return false;"><img src=/image/pic/update.png alt="restart" class="icon"></a>' % server[2])
print('<a href="/cgi-bin/configshow.py?serv=%s&open=open#conf" title="Show config"><img src=/image/pic/show.png alt="show" class="icon"></a>' % server[2])
print('<a href="/cgi-bin/config.py?serv=%s&open=open#conf" title="Edit config"><img src=/image/pic/edit.png alt="edit" class="icon"></a>' % server[2])
print('<a href="/cgi-bin/diff.py?serv=%s&open=open#diff" title="Compare config"><img src=/image/pic/compare.png alt="compare" class="icon"></a>' % server[2])
print('<a href="/cgi-bin/map.py?serv=%s&open=open#map" title="Map listen/frontend/backend"><img src=/image/pic/map.png alt="map" class="icon"></a>' % server[2])
print('<a href="/app/configshow.py?serv=%s&open=open#conf" title="Show config"><img src=/image/pic/show.png alt="show" class="icon"></a>' % server[2])
print('<a href="/app/config.py?serv=%s&open=open#conf" title="Edit config"><img src=/image/pic/edit.png alt="edit" class="icon"></a>' % server[2])
print('<a href="/app/diff.py?serv=%s&open=open#diff" title="Compare config"><img src=/image/pic/compare.png alt="compare" class="icon"></a>' % server[2])
print('<a href="/app/map.py?serv=%s&open=open#map" title="Map listen/frontend/backend"><img src=/image/pic/map.png alt="map" class="icon"></a>' % server[2])
print('</td><td>')
funct.ssh_command(server[2], commands1)
print('</td><td></td></tr>')

49
app/scripts/add_vrrp.sh Normal file
View File

@ -0,0 +1,49 @@
#!/bin/bash
CONF=/etc/keepalived/keepalived.conf
IP=`cat $CONF |grep $3 |sed s/' '//g|sed s/'\t'//g`
if [[ $IP == $3 ]];then
echo -e "error: VRRP address alredy use"
exit 1
fi
cat << EOF >> $CONF
vrrp_instance VI_2 {
state MASTER
interface eth1
virtual_router_id 101
priority 103
#check if we are still running
track_script {
chk_haproxy
}
advert_int 1
authentication {
auth_type PASS
auth_pass VerySecretPass2!
}
virtual_ipaddress {
0.0.0.1
}
}
EOF
if [ $? -eq 1 ]
then
echo "Can't read keepalived config"
exit 1
fi
sed -i "s/MASTER/$1/g" $CONF
sed -i "s/eth1/$2/g" $CONF
sed -i "s/0.0.0.1/$3/g" $CONF
if [[ $1 == "BACKUP" ]];then
sed -i "s/102/103/g" $CONF
fi
if [[ $4 == "1" ]];then
systemctl restart keepalived
fi
echo "success"

View File

@ -2,7 +2,7 @@
yum install haproxy socat -y > /dev/null
if [ -f /etc/haproxy/haproxy.cfg ];then
echo -e "error: Haproxy alredy installed"
echo -e 'error: Haproxy alredy installed. You can edit config<a href="/app/config.py" title="Edit HAProxy config">here</a>'
exit 1
fi
echo "" > /etc/haproxy/haproxy.cfg

View File

@ -2,7 +2,7 @@
CONF=/etc/keepalived/keepalived.conf
if [ -f $CONF ];then
echo -e "error: Keepalived alredy installed"
echo -e 'error: Keepalived alredy installed. You can edit config <a href="/app/keepalivedconfig.py" title="Edit Keepalived config">here</a>'
exit 1
fi

View File

@ -0,0 +1 @@
Just empty file for folder

View File

@ -107,7 +107,7 @@ cat << EOF > /etc/httpd/conf.d/haproxy-wi.conf
CustomLog /var/log/httpd/haproxy-wi.access.log combined
DocumentRoot /var/www/$HOME_HAPROXY_WI
ScriptAlias "/cgi-bin/ "/var/www/$HOME_HAPROXY_WI/cgi-bin/"
ScriptAlias "/cgi-bin/ "/var/www/$HOME_HAPROXY_WI/app/"
<Directory $HOME_HAPROXY_WI>
@ -235,13 +235,13 @@ if [[ $DB == 2 ]];then
echo ""
echo ""
echo "################################"
sed -i '0,/enable = 0/s//enable = 1/' /var/www/$HOME_HAPROXY_WI/cgi-bin/haproxy-webintarface.config
sed -i '0,/enable = 0/s//enable = 1/' /var/www/$HOME_HAPROXY_WI/app/haproxy-webintarface.config
else
cd /var/www/$HOME_HAPROXY_WI/cgi-bin
cd /var/www/$HOME_HAPROXY_WI/app
./update_db.py
fi
if [[ -n $IP ]];then
sed -i "0,/mysql_host = 127.0.0.1/s//mysql_host = $IP/" /var/www/$HOME_HAPROXY_WI/cgi-bin/haproxy-webintarface.config
sed -i "0,/mysql_host = 127.0.0.1/s//mysql_host = $IP/" /var/www/$HOME_HAPROXY_WI/app/haproxy-webintarface.config
fi
echo "################################"
echo ""
@ -274,7 +274,7 @@ else
fi
sed -i "s|^fullpath = .*|fullpath = /var/www/$HOME_HAPROXY_WI|g" /var/www/$HOME_HAPROXY_WI/cgi-bin/haproxy-webintarface.config
sed -i "s|^fullpath = .*|fullpath = /var/www/$HOME_HAPROXY_WI|g" /var/www/$HOME_HAPROXY_WI/app/haproxy-webintarface.config
echo "################################"
echo ""
echo ""
@ -287,7 +287,7 @@ echo "Edit firewalld"
firewall-cmd --zone=public --add-port=$PORT/tcp --permanent
firewall-cmd --reload
chmod +x /var/www/$HOME_HAPROXY_WI/cgi-bin/*.py
chmod +x /var/www/$HOME_HAPROXY_WI/app/*.py
chown -R apache:apache /var/www/$HOME_HAPROXY_WI/
rm -f /var/www/$HOME_HAPROXY_WI/log/config_edit.log