Master/slave servers
pull/19/head
Aidaho12 2018-04-24 13:38:48 +06:00
parent cd462dcb7d
commit 653443cdde
10 changed files with 122 additions and 24 deletions

View File

@ -13,10 +13,11 @@ A simple web interface(user-frendly web GUI) for managing Haproxy servers. Leave
7. Add sections: listen, frontend, backend from web interface 7. Add sections: listen, frontend, backend from web interface
8. Editing configs 8. Editing configs
9. Rollback to previous versions of the config 9. Rollback to previous versions of the config
10. Comparing versions of configs 10. Master/slave servers
11. Users roles: admin, editor, viewer 11. Comparing versions of configs
12. Server groups 12. Users roles: admin, editor, viewer
13. Telegram notification 13. Server groups
14. Telegram notification
# Install # Install
@ -32,7 +33,7 @@ $ chmod +x haproxy-wi/cgi-bin/*.py
For Apache do virtualhost with cgi-bin. Like this: For Apache do virtualhost with cgi-bin. Like this:
``` ```
<VirtualHost *:80> <VirtualHost *:8000>
ServerName haproxy-wi ServerName haproxy-wi
ErrorLog /var/log/httpd/haproxy-wi.error.log ErrorLog /var/log/httpd/haproxy-wi.error.log
CustomLog /var/log/httpd/haproxy-wi.access.log combined CustomLog /var/log/httpd/haproxy-wi.access.log combined
@ -80,6 +81,12 @@ For Runtime API enable state file on HAproxt servers and need install socat on a
``` ```
![alt text](image/haproxy-wi-logs.jpeg "View logs page") ![alt text](image/haproxy-wi-logs.jpeg "View logs page")
# Update DB
```
$ cd /var/www/haproxy-wi/cgi-bin
$ ./update_db.py
```
# Further development and support # Further development and support
Offer your ideas and wishes, ask questions. All this is [welcomed](https://github.com/Aidaho12/haproxy-wi/issues) Offer your ideas and wishes, ask questions. All this is [welcomed](https://github.com/Aidaho12/haproxy-wi/issues)

View File

@ -5,6 +5,7 @@ import os
import http.cookies import http.cookies
from configparser import ConfigParser, ExtendedInterpolation from configparser import ConfigParser, ExtendedInterpolation
import funct import funct
import sql
form = cgi.FieldStorage() form = cgi.FieldStorage()
serv = form.getvalue('serv') serv = form.getvalue('serv')
@ -61,6 +62,11 @@ if form.getvalue('serv') is not None and form.getvalue('config') is not None:
print("<center><b>New config was saved as: %s </b></br></br></center>" % cfg) print("<center><b>New config was saved as: %s </b></br></br></center>" % cfg)
MASTERS = sql.is_master(serv)
for master in MASTERS:
if master[0] != None:
funct.upload_and_restart(master[0], cfg, just_save=save)
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-%s.log" % (oldcfg, cfg, log_path, funct.get_data('logs'))) os.system("/bin/diff -ub %s %s >> %s/config_edit-%s.log" % (oldcfg, cfg, log_path, funct.get_data('logs')))

View File

@ -3,6 +3,7 @@ import html
import cgi import cgi
import os import os
import funct import funct
import sql
from configparser import ConfigParser, ExtendedInterpolation from configparser import ConfigParser, ExtendedInterpolation
form = cgi.FieldStorage() form = cgi.FieldStorage()
@ -79,6 +80,11 @@ if form.getvalue('serv') is not None and form.getvalue('config') is not None:
print("<center><b>Uploaded old config ver: %s </b></br></br></center>" % configver) print("<center><b>Uploaded old config ver: %s </b></br></br></center>" % configver)
MASTERS = sql.is_master(serv)
for master in MASTERS:
if master[0] != None:
funct.upload_and_restart(master[0], configver, just_save=save)
funct.upload_and_restart(serv, configver, just_save=save) funct.upload_and_restart(serv, configver, just_save=save)
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

@ -167,8 +167,8 @@ def update_db_v_2_0_1_1():
try: try:
cur.execute(sql) cur.execute(sql)
except sqltool.Error as e: except sqltool.Error as e:
if e.args[0] == 'duplicate column name: enable': if e.args[0] == 'duplicate column name: enable' or e == "1060 (42S21): Duplicate column name 'enable' ":
print('Already updated. No run more. Thx =^.^=') print('Updating... go to version 2.0.5')
return False return False
else: else:
print("An error occurred:", e) print("An error occurred:", e)
@ -179,9 +179,30 @@ def update_db_v_2_0_1_1():
cur.close() cur.close()
con.close() con.close()
def update_db_v_2_0_5():
con, cur = get_cur()
sql = """
ALTER TABLE `servers` ADD COLUMN master INTEGER NOT NULL DEFAULT 0;
"""
try:
cur.execute(sql)
except sqltool.Error as e:
if e.args[0] == 'duplicate column name: master':
print('Already updated. No run more. Thx =^.^=')
return False
else:
print("An error occurred:", e)
return False
else:
print("DB was update to 2.0.5")
return True
cur.close()
con.close()
def update_all(): def update_all():
update_db_v_2_0_1() update_db_v_2_0_1()
update_db_v_2_0_1_1() update_db_v_2_0_1_1()
update_db_v_2_0_5()
#if check_db(): #if check_db():
# create_table() # create_table()

View File

@ -194,7 +194,7 @@ def links():
'</li>') '</li>')
print('</ul>' print('</ul>'
'</nav>' '</nav>'
'<div class="copyright-menu">HAproxy-WI v2.0.4</div>' '<div class="copyright-menu">HAproxy-WI v2.0.5</div>'
'</div>') '</div>')
def show_login_links(): def show_login_links():
@ -528,7 +528,7 @@ def chooseServer(formName, title, note, **kwargs):
print('</p></form>') print('</p></form>')
#if note == "y": if note == "y":
# print('<p><b>Note:</b> If you reconfigure First server, second will reconfigured automatically</p>') print('<p><b>Note:</b> If you reconfigure First server, second will reconfigured automatically</p>')
print('</center>') print('</center>')

View File

@ -14,7 +14,7 @@ if mysql_enable == '1':
from mysql.connector import errorcode from mysql.connector import errorcode
import mysql.connector as sqltool import mysql.connector as sqltool
else: else:
db = "haproxy-wi-test.db" db = "haproxy-wi.db"
import sqlite3 as sqltool import sqlite3 as sqltool
def add_user(user, email, password, role, group): def add_user(user, email, password, role, group):
@ -114,9 +114,9 @@ def update_group(name, descript, id):
cur.close() cur.close()
con.close() con.close()
def add_server(hostname, ip, group, typeip, enable): def add_server(hostname, ip, group, typeip, enable, master):
con, cur = create_db.get_cur() con, cur = create_db.get_cur()
sql = """INSERT INTO servers (hostname, ip, groups, type_ip, enable) VALUES ('%s', '%s', '%s', '%s', '%s')""" % (hostname, ip, group, typeip, enable) sql = """INSERT INTO servers (hostname, ip, groups, type_ip, enable, master) VALUES ('%s', '%s', '%s', '%s', '%s', '%s')""" % (hostname, ip, group, typeip, enable, master)
try: try:
cur.execute(sql) cur.execute(sql)
con.commit() con.commit()
@ -143,15 +143,16 @@ def delete_server(id):
cur.close() cur.close()
con.close() con.close()
def update_server(hostname, ip, group, typeip, enable, id): def update_server(hostname, ip, group, typeip, enable, master, id):
con, cur = create_db.get_cur() con, cur = create_db.get_cur()
sql = """update servers set sql = """update servers set
hostname = '%s', hostname = '%s',
ip = '%s', ip = '%s',
groups = '%s', groups = '%s',
type_ip = '%s', type_ip = '%s',
enable = '%s' enable = '%s',
where id = '%s'""" % (hostname, ip, group, typeip, enable, id) master = '%s'
where id = '%s'""" % (hostname, ip, group, typeip, enable, master, id)
try: try:
cur.execute(sql) cur.execute(sql)
con.commit() con.commit()
@ -225,6 +226,8 @@ def select_servers(**kwargs):
sql = """select * from servers where hostname='%s' """ % kwargs.get("server") sql = """select * from servers where hostname='%s' """ % kwargs.get("server")
if kwargs.get("full") is not None: if kwargs.get("full") is not None:
sql = """select * from servers ORDER BY groups """ sql = """select * from servers ORDER BY groups """
if kwargs.get("get_master_servers") is not None:
sql = """select id,hostname from servers where master = 0 and type_ip = 0 and enable = 1 ORDER BY groups """
try: try:
cur.execute(sql) cur.execute(sql)
except sqltool.Error as e: except sqltool.Error as e:
@ -298,6 +301,16 @@ def get_dick_permit(**kwargs):
cur.close() cur.close()
con.close() con.close()
def is_master(ip):
con, cur = create_db.get_cur()
sql = """ select slave.ip from servers left join servers as slave on servers.id = slave.master where servers.ip = '%s' """ % ip
try:
cur.execute(sql)
except sqltool.Error as e:
return False
else:
return cur
def show_update_servers(): def show_update_servers():
SERVERS = select_servers() SERVERS = select_servers()
print('<tr class="overviewHead">' print('<tr class="overviewHead">'
@ -337,7 +350,6 @@ def show_update_user(user):
need_id_group = "usergroup-%s" % users[0] need_id_group = "usergroup-%s" % users[0]
get_groups_select(need_id_group, selected=users[5]) get_groups_select(need_id_group, selected=users[5])
print('</td>') print('</td>')
#print('<td><a class="update-row" onclick="updateUser(%s)" style="cursor: pointer;"></a></td>' % users[0])
print('<td><a class="delete" onclick="removeUser(%s)" style="cursor: pointer;"></a></td>' % users[0]) print('<td><a class="delete" onclick="removeUser(%s)" style="cursor: pointer;"></a></td>' % users[0])
print('</tr>') print('</tr>')
@ -357,7 +369,15 @@ def show_update_server(server):
print('<td>') print('<td>')
get_type_ip_checkbox(server[0]) get_type_ip_checkbox(server[0])
print('</td>') print('</td>')
#print('<td><a class="update-row" onclick="updateServer(%s)" style="cursor: pointer;"></a></td>' % server[0]) print('<td><select id="slavefor-%s"><option value="0" selected>Not slave</option>' % server[0])
MASTERS = select_servers(get_master_servers=1)
for master in MASTERS:
if master[0] == server[6]:
selected = "selected"
else:
selected = ""
print('<option value="%s" %s>%s</option>' % (master[0], selected, master[1]))
print('</select></td>')
print('<td><a class="delete" onclick="removeServer(%s)" style="cursor: pointer;"></a></td>' % server[0]) print('<td><a class="delete" onclick="removeServer(%s)" style="cursor: pointer;"></a></td>' % server[0])
print('</tr>') print('</tr>')
@ -455,12 +475,13 @@ if form.getvalue('newserver') is not None:
group = form.getvalue('newservergroup') group = form.getvalue('newservergroup')
typeip = form.getvalue('typeip') typeip = form.getvalue('typeip')
enable = form.getvalue('enable') enable = form.getvalue('enable')
master = form.getvalue('slave')
if ip is None or group is None: if ip is None or group is None:
print('Content-type: text/html\n') print('Content-type: text/html\n')
print(error_mess) print(error_mess)
else: else:
print('Content-type: text/html\n') print('Content-type: text/html\n')
if add_server(hostname, ip, group, typeip, enable): if add_server(hostname, ip, group, typeip, enable, master):
show_update_server(hostname) show_update_server(hostname)
if form.getvalue('serverdel') is not None: if form.getvalue('serverdel') is not None:
@ -497,11 +518,12 @@ if form.getvalue('updateserver') is not None:
group = form.getvalue('servergroup') group = form.getvalue('servergroup')
typeip = form.getvalue('typeip') typeip = form.getvalue('typeip')
enable = form.getvalue('enable') enable = form.getvalue('enable')
master = form.getvalue('slave')
id = form.getvalue('id') id = form.getvalue('id')
if name is None or ip is None: if name is None or ip is None:
print('Content-type: text/html\n') print('Content-type: text/html\n')
print(error_mess) print(error_mess)
else: else:
print('Content-type: text/html\n') print('Content-type: text/html\n')
update_server(name, ip, group, typeip, enable, id) update_server(name, ip, group, typeip, enable, master, id)

19
cgi-bin/update_db.py Normal file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-"
import create_db
from configparser import ConfigParser, ExtendedInterpolation
path_config = "haproxy-webintarface.config"
config = ConfigParser(interpolation=ExtendedInterpolation())
config.read(path_config)
mysql_enable = config.get('mysql', 'enable')
if mysql_enable == '1':
from mysql.connector import errorcode
import mysql.connector as sqltool
else:
db = "haproxy-wi.db"
import sqlite3 as sqltool
create_db.update_all()

View File

@ -122,6 +122,7 @@ print('<br /><br /><table class="overview" id="group-add-table" style="display:
'<td>Group</td>' '<td>Group</td>'
'<td>Enable</td>' '<td>Enable</td>'
'<td>Virt</td>' '<td>Virt</td>'
'<td><span title="Actions with master config will automatically apply on slave">Slave for (?)</span></td>'
'<td></td>' '<td></td>'
'<td></td>' '<td></td>'
'</tr>') '</tr>')
@ -140,7 +141,15 @@ for server in SERVERS:
print('<td>') print('<td>')
sql.get_type_ip_checkbox(server[0]) sql.get_type_ip_checkbox(server[0])
print('</td>') print('</td>')
#print('<td><a class="update-row" onclick="updateServer(%s)" style="cursor: pointer;"></a></td>' % server[0]) print('<td><select id="slavefor-%s"><option value="0" selected>Not slave</option>' % server[0])
MASTERS = sql.select_servers(get_master_servers=1)
for master in MASTERS:
if master[0] == server[6]:
selected = "selected"
else:
selected = ""
print('<option value="%s" %s>%s</option>' % (master[0], selected, master[1]))
print('</select></td>')
print('<td><a class="delete" onclick="removeServer(%s)" style="cursor: pointer;"></a></td>' % server[0]) print('<td><a class="delete" onclick="removeServer(%s)" style="cursor: pointer;"></a></td>' % server[0])
print('</tr>') print('</tr>')
print('</table>' print('</table>'
@ -152,6 +161,7 @@ print('</table>'
'<td>Group</td>' '<td>Group</td>'
'<td>Enable</td>' '<td>Enable</td>'
'<td>Virt</td>' '<td>Virt</td>'
'<td title="Actions with master config will automatically apply on slave">Slave for</td>'
'<td></td>' '<td></td>'
'</tr>' '</tr>'
'<tr>' '<tr>'
@ -161,6 +171,11 @@ sql.get_groups_select("new-server-group-add")
print('</td>' print('</td>'
'<td><label for="enable"></label><input type="checkbox" id="enable" checked></td>' '<td><label for="enable"></label><input type="checkbox" id="enable" checked></td>'
'<td><label for="typeip"></label><input type="checkbox" id="typeip"></td>' '<td><label for="typeip"></label><input type="checkbox" id="typeip"></td>'
'<td><select id="slavefor" value="0" selected><option>Not slave</option>')
MASTERS = sql.select_servers(get_master_servers=1)
for master in MASTERS:
print('<option value="%s">%s</option>' % (master[0], master[1]))
print('</select></td>'
'<td><a class="add-admin" id="add-server" style="cursor: pointer;"></a></td>' '<td><a class="add-admin" id="add-server" style="cursor: pointer;"></a></td>'
'</tr>') '</tr>')
print('</table>') print('</table>')

View File

@ -106,8 +106,8 @@
font-family: "Font Awesome 5 Solid"; font-family: "Font Awesome 5 Solid";
content: "\f0ad"; content: "\f0ad";
} }
.add-admin:before { .add-admin::before {
display: none; display: none;
font-family: "Font Awesome 5 Solid"; font-family: "Font Awesome 5 Solid";
content: "\f00c"; content: "\f00c";
} }

View File

@ -85,7 +85,8 @@ $( function() {
newip: $('#new-ip').val(), newip: $('#new-ip').val(),
newservergroup: $('#new-server-group-add').val(), newservergroup: $('#new-server-group-add').val(),
typeip: typeip, typeip: typeip,
enable: enable enable: enable,
slave: $('#slavefor option:selected' ).val()
}, },
type: "GET", type: "GET",
success: function( data ) { success: function( data ) {
@ -282,6 +283,7 @@ function updateServer(id) {
servergroup: $('#servergroup-'+id+' option:selected' ).val(), servergroup: $('#servergroup-'+id+' option:selected' ).val(),
typeip: typeip, typeip: typeip,
enable: enable, enable: enable,
slave: $('#slavefor-'+id+' option:selected' ).val(),
id: id id: id
}, },
type: "GET", type: "GET",