diff --git a/README.md b/README.md index 6856f864..754f7c3c 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,15 @@ A simple web interface(user-frendly web GUI) for managing Haproxy servers 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. Disabling / enabling the backend servers without reboot (after reboot, will work as specified in the config), viewing server state data -5. Browsing Configs -6. Add sections: listen, frontend, backend from web interface -7. Editing configs -8. Rollback to previous versions of the config -9. Comparing versions of configs -10. Users roles: admin, editor, viewer -11. Telegram notification +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 +6. Browsing Configs +7. Add sections: listen, frontend, backend from web interface +8. Editing configs +9. Rollback to previous versions of the config +10. Comparing versions of configs +11. Users roles: admin, editor, viewer +12. Telegram notification # Install Can be used as a service, or via fastaci apache + fastCGI(recommend, because it works faster), how to use the service: diff --git a/cgi-bin/edit.py b/cgi-bin/edit.py index c2e3fa68..c9874149 100644 --- a/cgi-bin/edit.py +++ b/cgi-bin/edit.py @@ -82,11 +82,13 @@ if form.getvalue('servaction') is not None: 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('

You %s %s on HAproxy %s. Look it or Edit something else


' % (enable, backend, serv, serv)) print('
'.join(map(str, output))) - + if err: + print('
'.join(map(str, err))) action = 'edit.py ' + enable + ' ' + backend funct.logging(serv, action) diff --git a/cgi-bin/funct.py b/cgi-bin/funct.py index 53a02170..793359ae 100644 --- a/cgi-bin/funct.py +++ b/cgi-bin/funct.py @@ -97,6 +97,7 @@ def links(): '
  • Stats
  • ' '
  • Monitoring
  • ' '
  • Logs
  • ' + '
  • Map
  • ' '' '' '
  • Edit settings
  • ' @@ -107,7 +108,7 @@ def links(): '
  • Add listen
  • ' '
  • Add frontend
  • ' '
  • Add backend
  • ' - '
  • Edit
  • ' + '
  • Edit
  • ' '' '' '
  • Versions' @@ -293,7 +294,6 @@ def compare(stdout): print('') def show_log(stdout): - #print('' % serv) i = 0 for line in stdout: i = i + 1 @@ -302,21 +302,6 @@ def show_log(stdout): else: print('
    ' + line + '
    ') -def show_log_tailf(channel, serv): - import select - print('' % serv) - print('
    ')
    -	while 1:
    -		rl, wl, xl = select.select([channel],[],[],0.0)
    -		if len(rl) > 0:
    -			print(channel.recv(200).decode(encoding='UTF-8'))
    -	print('' % serv)
    -		#i = i + 1
    -		#if i % 2 == 0: 
    -		#	print('
    ' + line + '
    ') - #else: - # print('
    ' + line + '
    ') - def show_ip(stdout): for line in stdout: print(line) @@ -329,13 +314,6 @@ def server_status(stdout): def ssh_command(serv, commands, **kwargs): ssh = ssh_connect(serv) - - if kwargs.get("tailf") == "1": - transport = ssh.get_transport() - channel = transport.open_session() - channel.exec_command('tail -f /var/log/haproxy.log') - show_log_tailf(channel, serv) - for command in commands: try: diff --git a/cgi-bin/logs.py b/cgi-bin/logs.py index d683eae5..60d118f9 100644 --- a/cgi-bin/logs.py +++ b/cgi-bin/logs.py @@ -56,7 +56,7 @@ if form.getvalue('grep') is not None: else: grep = ' ' -print('' % rows) +print('' % rows) print('' % grep) print('' '' @@ -86,6 +86,6 @@ if form.getvalue('serv') is not None: commands = [ 'sudo tail -%s /var/log/%s/syslog.log %s %s' % (rows, serv, grep_act, grep) ] syslog_server = config.get('logs', 'syslog_server') - funct.ssh_command(syslog_server, commands, show_log="1", tailf="0") + funct.ssh_command(syslog_server, commands, show_log="1") funct.footer() \ No newline at end of file diff --git a/cgi-bin/map.py b/cgi-bin/map.py new file mode 100644 index 00000000..6d2dd8fd --- /dev/null +++ b/cgi-bin/map.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +import html +import cgi +import os +import funct +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() +serv = form.getvalue('serv') +servNew = form.getvalue('serNew') + +funct.head("Show HAproxy config") +funct.check_config() +funct.check_login() + +path_config = "haproxy-webintarface.config" +config = configparser.ConfigParser() +config.read(path_config) +time_zone = config.get('main', 'time_zone') +hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir') +haproxy_config_path = config.get('haproxy', 'haproxy_config_path') + +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("map.py#map", "Show HAproxy map", "n") + +if form.getvalue('serv') is not None and form.getvalue('open') is not None : + print('') + print("

    Map from %s


    " % serv) + + G = nx.DiGraph() + + funct.get_config(serv, cfg) + conf = open(cfg, "r") + + node = "" + line_new2 = [1,""] + i = 1200 + k = 1200 + j = 0 + for line in conf: + if "listen" in line or "frontend" in line or line.find("backend") == 0: + if "stats" not in line: + G.add_node(line,pos=(k,i),label_pos=(k,i+150)) + node = line + i = i - 100 + if "server " in line or "use_backend" in line or "default_backend" in line: + if "timeout" not in line and "default-server" not in line and "#use_backend" not in line: + i = i - 300 + j = j + 1 + if "check" in line: + line_new = line.split("check") + else: + line_new = line.split("if") + if "server" in line: + line_new1 = line_new[0].split("server") + line_new[0] = line_new1[1] + line_new2 = line_new[0].split(":") + line_new[0] = line_new2[0] + + line_new[0] = line_new[0].strip(' \t\n\r') + line_new2[1] = line_new2[1].strip(' \t\n\r') + if j % 2 == 0: + G.add_node(line_new[0],pos=(k+250,i-350),label_pos=(k+225,i-100)) + else: + G.add_node(line_new[0],pos=(k-250,i-50),label_pos=(k-225,i+180)) + if line_new2[1] != "": + G.add_edge(node, line_new[0], port=line_new2[1]) + else: + G.add_edge(node,line_new[0]) + + os.system("/bin/rm -f " + cfg) + os.chdir("/var/www/haproxy-wi/cgi-bin/") + + pos=nx.get_node_attributes(G,'pos') + pos_label=nx.get_node_attributes(G,'label_pos') + edge_labels = nx.get_edge_attributes(G,'port') + + try: + plt.figure(10,figsize=(9.5,15)) + nx.draw(G, pos, with_labels=False, font_weight='bold', width=3, alpha=0.1,linewidths=5) + nx.draw_networkx_nodes(G,pos, node_color="skyblue", node_size=100, alpha=0.8, node_shape="p") + nx.draw_networkx_edges(G,pos, width=0.5,alpha=0.5, edge_color="#5D9CEB",arrows=False) + nx.draw_networkx_labels(G,pos=pos_label, alpha=1, font_color="green", font_size=10) + nx.draw_networkx_edge_labels(G, pos,label_pos=0.5,font_color="blue", labels=edge_labels, font_size=8) + + plt.savefig("map.png") + plt.show() + except Exception as e: + print("!!! There was an issue, " + str(e)) + + commands = [ "mv /var/www/haproxy-wi/cgi-bin/map.png /var/www/haproxy-wi/" ] + funct.ssh_command("localhost", commands) + print('map') + +funct.footer() \ No newline at end of file diff --git a/image/9.jpeg b/image/9.jpeg new file mode 100644 index 00000000..65f6ab1b Binary files /dev/null and b/image/9.jpeg differ diff --git a/index.html b/index.html index 44efe5a8..70cf70fe 100644 --- a/index.html +++ b/index.html @@ -15,6 +15,7 @@ Overview
    View stats
    Logs
    + Map
    Edit settings
    Compare
    Show
    @@ -23,7 +24,7 @@ Upload old config
    Delete old config
    diff --git a/requirements.txt b/requirements.txt index 29c5a822..288f975e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,8 @@ pytz==2017.3 requests==2.18.4 requests_toolbelt==0.8.0 telegram==0.0.1 -dump==0.0.3 \ No newline at end of file +dump==0.0.3 +networkx==2.1 +numpy==1.14.0 +matplotlib==2.1.2 +urllib3==1.22 \ No newline at end of file