code optimization, haproxy page, bugs
pull/170/head
Pavel Loginov 2019-10-25 10:18:57 +03:00
parent 0d34ded357
commit acdbff6985
55 changed files with 1032 additions and 1369 deletions

View File

@ -129,6 +129,19 @@ For Apache do virtualhost with cgi-bin. Like this:
Order Deny,Allow Order Deny,Allow
Deny from all Deny from all
</FilesMatch> </FilesMatch>
<IfModule mod_headers.c>
Header set X-XSS-Protection: 1;
Header set X-Frame-Options: deny
Header set X-Content-Type-Options: nosniff
Header set Strict-Transport-Security: max-age=3600;
Header set Cache-Control no-cache
Header set Expires: 0
<filesMatch ".(ico|css|js|gif|jpeg|jpg|png|svg|woff|ttf|eot)$">
Header set Cache-Control "max-age=86400, public"
</filesMatch>
</IfModule>
</VirtualHost> </VirtualHost>
``` ```

View File

@ -68,20 +68,10 @@ if serv is not None and form.getvalue('config') is not None:
except IOError: except IOError:
error = "Can't read import config file" error = "Can't read import config file"
MASTERS = sql.is_master(serv) stderr = funct.master_slave_upload_and_restart(serv, cfg, just_save=save)
for master in MASTERS:
if master[0] != None:
funct.upload_and_restart(master[0], cfg, just_save=save)
stderr = funct.upload_and_restart(serv, cfg, just_save=save)
funct.diff_config(oldcfg, cfg) funct.diff_config(oldcfg, cfg)
#if save:
# c = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
# c["restart"] = form.getvalue('serv')
# print(c)
os.system("/bin/rm -f " + hap_configs_dir + "*.old") os.system("/bin/rm -f " + hap_configs_dir + "*.old")

View File

@ -366,12 +366,15 @@ def update_db_v_3_4_5_2(**kwargs):
def update_db_v_3_4_5_22(**kwargs): def update_db_v_3_4_5_22(**kwargs):
con, cur = get_cur() con, cur = get_cur()
if mysql_enable == '0':
sql = """insert into version ('version') values ('3.4.5.2'); """ sql = """insert into version ('version') values ('3.4.5.2'); """
else:
sql = """INSERT INTO version VALUES ('3.4.5.2'); """
try: try:
cur.execute(sql) cur.execute(sql)
con.commit() con.commit()
except sqltool.Error as e: except sqltool.Error as e:
print('Cannot insert version') print('Cannot insert version %s' % e)
cur.close() cur.close()
con.close() con.close()
@ -435,7 +438,7 @@ def update_db_v_3_5_3(**kwargs):
def update_ver(**kwargs): def update_ver(**kwargs):
con, cur = get_cur() con, cur = get_cur()
sql = """update version set version = '3.5.7.1'; """ sql = """update version set version = '3.5.8'; """
try: try:
cur.execute(sql) cur.execute(sql)
con.commit() con.commit()

View File

@ -442,6 +442,7 @@ def upload(serv, path, file, **kwargs):
return error return error
def upload_and_restart(serv, cfg, **kwargs): def upload_and_restart(serv, cfg, **kwargs):
import sql import sql
tmp_file = sql.get_setting('tmp_config_path') + "/" + get_data('config') + ".cfg" tmp_file = sql.get_setting('tmp_config_path') + "/" + get_data('config') + ".cfg"
@ -480,6 +481,17 @@ def upload_and_restart(serv, cfg, **kwargs):
logging('localhost', error, haproxywi=1) logging('localhost', error, haproxywi=1)
return error return error
def master_slave_upload_and_restart(serv, cfg, just_save):
import sql
MASTERS = sql.is_master(serv)
for master in MASTERS:
if master[0] != None:
upload_and_restart(master[0], cfg, just_save=just_save)
return upload_and_restart(serv, cfg, just_save=just_save)
def open_port_firewalld(cfg): def open_port_firewalld(cfg):
try: try:
conf = open(cfg, "r") conf = open(cfg, "r")
@ -499,6 +511,7 @@ def open_port_firewalld(cfg):
firewalld_commands.append('sudo firewall-cmd --reload') firewalld_commands.append('sudo firewall-cmd --reload')
return firewalld_commands return firewalld_commands
def check_haproxy_config(serv): def check_haproxy_config(serv):
import sql import sql
commands = [ "haproxy -q -c -f %s" % sql.get_setting('haproxy_config_path') ] commands = [ "haproxy -q -c -f %s" % sql.get_setting('haproxy_config_path') ]
@ -511,6 +524,7 @@ def check_haproxy_config(serv):
return False return False
ssh.close() ssh.close()
def show_log(stdout): def show_log(stdout):
i = 0 i = 0
for line in stdout: for line in stdout:
@ -518,10 +532,12 @@ def show_log(stdout):
line_class = "line3" if i % 2 == 0 else "line" line_class = "line3" if i % 2 == 0 else "line"
print('<div class="'+line_class+'">' + escape_html(line) + '</div>') print('<div class="'+line_class+'">' + escape_html(line) + '</div>')
def show_ip(stdout): def show_ip(stdout):
for line in stdout: for line in stdout:
print(line) print(line)
def server_status(stdout): def server_status(stdout):
proc_count = "" proc_count = ""
@ -533,6 +549,7 @@ def server_status(stdout):
proc_count = 0 proc_count = 0
return proc_count return proc_count
def ssh_command(serv, commands, **kwargs): def ssh_command(serv, commands, **kwargs):
ssh = ssh_connect(serv) ssh = ssh_connect(serv)
@ -565,9 +582,11 @@ def ssh_command(serv, commands, **kwargs):
print("<div class='alert alert-danger' style='margin: 0;'>"+str(ssh)+"<a title='Close' id='errorMess'><b>X</b></a></div>") print("<div class='alert alert-danger' style='margin: 0;'>"+str(ssh)+"<a title='Close' id='errorMess'><b>X</b></a></div>")
pass pass
def escape_html(text): def escape_html(text):
return cgi.escape(text, quote=True) return cgi.escape(text, quote=True)
def subprocess_execute(cmd): def subprocess_execute(cmd):
import subprocess import subprocess
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, universal_newlines=True) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, universal_newlines=True)
@ -576,6 +595,7 @@ def subprocess_execute(cmd):
return output, stderr return output, stderr
def show_backends(serv, **kwargs): def show_backends(serv, **kwargs):
import json import json
import sql import sql
@ -600,6 +620,7 @@ def show_backends(serv, **kwargs):
if kwargs.get('ret'): if kwargs.get('ret'):
return ret return ret
def get_files(dir = get_config_var('configs', 'haproxy_save_configs_dir'), format = 'cfg', **kwargs): def get_files(dir = get_config_var('configs', 'haproxy_save_configs_dir'), format = 'cfg', **kwargs):
import glob import glob
if format == 'log': if format == 'log':
@ -624,6 +645,7 @@ def get_files(dir = get_config_var('configs', 'haproxy_save_configs_dir'), forma
else: else:
return files return files
def get_key(item): def get_key(item):
return item[0] return item[0]

View File

@ -9,12 +9,12 @@ INSERT INTO `role` (name, description) VALUES ('editor','Can edit configs');
INSERT INTO `role` (name, description) VALUES ('guest','Read only access'); INSERT INTO `role` (name, description) VALUES ('guest','Read only access');
CREATE TABLE IF NOT EXISTS `groups` (`id` INTEGER NOT NULL AUTO_INCREMENT,`name` VARCHAR ( 80 ) UNIQUE,`description` VARCHAR ( 255 ),PRIMARY KEY(`id`)); CREATE TABLE IF NOT EXISTS `groups` (`id` INTEGER NOT NULL AUTO_INCREMENT,`name` VARCHAR ( 80 ) UNIQUE,`description` VARCHAR ( 255 ),PRIMARY KEY(`id`));
INSERT INTO `groups` (name, description) VALUES ('All','All servers enter in this group'); INSERT INTO `groups` (name, description) VALUES ('All','All servers enter in this group');
CREATE TABLE IF NOT EXISTS `uuid` (`user_id` INTEGER NOT NULL, `uuid` varchar ( 64 ),`exp` DATETIME default '0000-00-00 00:00:00'); CREATE TABLE IF NOT EXISTS `uuid` (`user_id` INTEGER NOT NULL, `uuid` varchar ( 64 ),`exp` DATETIME default CURRENT_TIMESTAMP);
CREATE TABLE IF NOT EXISTS `token` (`user_id` INTEGER, `token` varchar(64), `exp` timestamp default '0000-00-00 00:00:00'); CREATE TABLE IF NOT EXISTS `token` (`user_id` INTEGER, `token` varchar(64), `exp` timestamp default CURRENT_TIMESTAMP);
CREATE TABLE IF NOT EXISTS `cred` (`id` integer primary key AUTO_INCREMENT, `name` VARCHAR ( 64 ) UNIQUE, `enable` INTEGER NOT NULL DEFAULT 1, `username` VARCHAR ( 64 ) NOT NULL, `password` VARCHAR ( 64 ) NOT NULL, groups INTEGER NOT NULL DEFAULT 1 ); CREATE TABLE IF NOT EXISTS `cred` (`id` integer primary key AUTO_INCREMENT, `name` VARCHAR ( 64 ) UNIQUE, `enable` INTEGER NOT NULL DEFAULT 1, `username` VARCHAR ( 64 ) NOT NULL, `password` VARCHAR ( 64 ) NOT NULL, groups INTEGER NOT NULL DEFAULT 1 );
CREATE TABLE IF NOT EXISTS `telegram` (`id` integer primary key auto_increment, `token` VARCHAR ( 64 ), `chanel_name` INTEGER NOT NULL DEFAULT 1, `groups` INTEGER NOT NULL DEFAULT 1); CREATE TABLE IF NOT EXISTS `telegram` (`id` integer primary key auto_increment, `token` VARCHAR ( 64 ), `chanel_name` INTEGER NOT NULL DEFAULT 1, `groups` INTEGER NOT NULL DEFAULT 1);
CREATE TABLE IF NOT EXISTS `metrics` (`serv` varchar(64), curr_con INTEGER, cur_ssl_con INTEGER, sess_rate INTEGER, max_sess_rate INTEGER,`date` DATETIME default '0000-00-00 00:00:00'); CREATE TABLE IF NOT EXISTS `metrics` (`serv` varchar(64), curr_con INTEGER, cur_ssl_con INTEGER, sess_rate INTEGER, max_sess_rate INTEGER,`date` DATETIME default '0000-00-00 00:00:00');
CREATE TABLE IF NOT EXISTS `settings` (`param` varchar(64) UNIQUE, value varchar(64), section varchar(64), `desc` varchar(100)); CREATE TABLE IF NOT EXISTS `settings` (`param` varchar(64) UNIQUE, value varchar(64), section varchar(64), `desc` varchar(100));
CREATE TABLE IF NOT EXISTS `version` (`version` varchar(64), `hash` INTEGER NOT NULL DEFAULT 1,); CREATE TABLE IF NOT EXISTS `version` (`version` varchar(64));
CREATE TABLE IF NOT EXISTS `options` ( `id` INTEGER NOT NULL, `options` VARCHAR ( 64 ), `groups` VARCHAR ( 120 ), PRIMARY KEY(`id`)); CREATE TABLE IF NOT EXISTS `options` ( `id` INTEGER NOT NULL, `options` VARCHAR ( 64 ), `groups` VARCHAR ( 120 ), PRIMARY KEY(`id`));
CREATE TABLE IF NOT EXISTS `saved_servers` ( `id` INTEGER NOT NULL, `server` VARCHAR ( 64 ), `description` VARCHAR ( 120 ), `groups` VARCHAR ( 120 ), PRIMARY KEY(`id`)); CREATE TABLE IF NOT EXISTS `saved_servers` ( `id` INTEGER NOT NULL, `server` VARCHAR ( 64 ), `description` VARCHAR ( 120 ), `groups` VARCHAR ( 120 ), PRIMARY KEY(`id`));

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import funct, sql import funct, sql
import os, http.cookies import os, http.cookies
import cgi
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates/')) env = Environment(loader=FileSystemLoader('templates/'))
template = env.get_template('hapservers.html') template = env.get_template('hapservers.html')
@ -15,12 +16,21 @@ try:
users = sql.select_users() users = sql.select_users()
groups = sql.select_groups() groups = sql.select_groups()
token = sql.get_token(user_id.value) token = sql.get_token(user_id.value)
servers = sql.get_dick_permit()
cmd = "ps ax |grep -e 'keep_alive.py' |grep -v grep |wc -l" cmd = "ps ax |grep -e 'keep_alive.py' |grep -v grep |wc -l"
keep_alive, stderr = funct.subprocess_execute(cmd) keep_alive, stderr = funct.subprocess_execute(cmd)
except: except:
pass pass
form = cgi.FieldStorage()
serv = form.getvalue('serv')
if serv:
servers = sql.select_servers(server=serv)
autorefresh = 1
else:
servers = sql.get_dick_permit()
autorefresh = 0
haproxy_sock_port = sql.get_setting('haproxy_sock_port') haproxy_sock_port = sql.get_setting('haproxy_sock_port')
haproxy_config_path = sql.get_setting('haproxy_config_path') haproxy_config_path = sql.get_setting('haproxy_config_path')
commands = [ "ls -l %s |awk '{ print $6\" \"$7\" \"$8}'" % haproxy_config_path ] commands = [ "ls -l %s |awk '{ print $6\" \"$7\" \"$8}'" % haproxy_config_path ]
@ -50,7 +60,7 @@ for s in servers:
template = template.render(h2 = 1, template = template.render(h2 = 1,
autorefresh = 0, autorefresh = autorefresh,
title = "HAProxy servers overview", title = "HAProxy servers overview",
role = sql.get_user_role_by_uuid(user_id.value), role = sql.get_user_role_by_uuid(user_id.value),
user = user, user = user,
@ -59,5 +69,6 @@ template = template.render(h2 = 1,
servers = servers_with_status1, servers = servers_with_status1,
versions = funct.versions(), versions = funct.versions(),
keep_alive = ''.join(keep_alive), keep_alive = ''.join(keep_alive),
serv = serv,
token = token) token = token)
print(template) print(template)

View File

@ -209,7 +209,7 @@ if act == "overviewwaf":
async def async_get_overviewServers(serv1, serv2): async def async_get_overviewServers(serv1, serv2):
server_status = () server_status = ()
commands = [ "top -u haproxy -b -n 1 -w 67 |grep -e 'haproxy\|PID\|Cpu\|KiB' |grep -v Swap" ] commands = [ "top -u haproxy -b -n 1" ]
cmd = 'echo "show info" |nc %s %s -w 1|grep -e "Ver\|CurrConns\|Maxco\|MB\|Uptime:"' % (serv2, sql.get_setting('haproxy_sock_port')) cmd = 'echo "show info" |nc %s %s -w 1|grep -e "Ver\|CurrConns\|Maxco\|MB\|Uptime:"' % (serv2, sql.get_setting('haproxy_sock_port'))
out = funct.subprocess_execute(cmd) out = funct.subprocess_execute(cmd)
out1 = "" out1 = ""

View File

@ -72,12 +72,7 @@ if serv is not None and form.getvalue('config') is not None:
except IOError: except IOError:
error = "Can't read import config file" error = "Can't read import config file"
MASTERS = sql.is_master(serv) stderr = funct.master_slave_upload_and_restart(serv, cfg, just_save=save)
for master in MASTERS:
if master[0] != None:
funct.upload_and_restart(master[0], cfg, just_save=save)
stderr = funct.upload_and_restart(serv, cfg, just_save=save)
funct.diff_config(oldcfg, cfg) funct.diff_config(oldcfg, cfg)

View File

@ -275,7 +275,7 @@ def select_servers(**kwargs):
if kwargs.get("server") is not None: if kwargs.get("server") is not None:
sql = """select * from servers where ip='%s' """ % kwargs.get("server") sql = """select * from servers where ip='%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 hostname """
if kwargs.get("get_master_servers") is not None: 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 """ sql = """select id,hostname from servers where master = 0 and type_ip = 0 and enable = 1 ORDER BY groups """
if kwargs.get("get_master_servers") is not None and kwargs.get('uuid') is not None: if kwargs.get("get_master_servers") is not None and kwargs.get('uuid') is not None:
@ -846,6 +846,20 @@ def select_waf_servers(serv):
cur.close() cur.close()
con.close() con.close()
def select_all_waf_servers():
con, cur = create_db.get_cur()
sql = """ select serv.ip from waf left join servers as serv on waf.server_id = serv.id """
try:
cur.execute(sql)
except sqltool.Error as e:
out_error(e)
else:
return cur.fetchall()
cur.close()
con.close()
def select_waf_servers_metrics(uuid, **kwargs): def select_waf_servers_metrics(uuid, **kwargs):
con, cur = create_db.get_cur() con, cur = create_db.get_cur()
sql = """ select * from user where username = '%s' """ % get_user_name_by_uuid(uuid) sql = """ select * from user where username = '%s' """ % get_user_name_by_uuid(uuid)
@ -1299,8 +1313,8 @@ def show_update_telegram(token, page):
def show_update_user(user,page): def show_update_user(user,page):
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates/ajax')) env = Environment(loader=FileSystemLoader('templates/'))
template = env.get_template('/new_user.html') template = env.get_template('ajax/new_user.html')
print('Content-type: text/html\n') print('Content-type: text/html\n')
template = template.render(users = select_users(user=user), template = template.render(users = select_users(user=user),
@ -1311,8 +1325,8 @@ def show_update_user(user,page):
def show_update_server(server, page): def show_update_server(server, page):
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates/ajax/')) env = Environment(loader=FileSystemLoader('templates/'))
template = env.get_template('/new_server.html') template = env.get_template('ajax/new_server.html')
print('Content-type: text/html\n') print('Content-type: text/html\n')
output_from_parsed_template = template.render(groups = select_groups(), output_from_parsed_template = template.render(groups = select_groups(),

View File

@ -1,5 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
{% from 'include/input_macros.html' import input, checkbox, select %}
<style> <style>
.container { .container {
margin-right: 0; margin-right: 0;
@ -19,148 +20,9 @@ h3 {
<li><a href="#option">Options</a></li> <li><a href="#option">Options</a></li>
<li><a href="#add-servers">Servers</a></li> <li><a href="#add-servers">Servers</a></li>
<li><a href="#userlist">Userlist</a></li> <li><a href="#userlist">Userlist</a></li>
{% if user %} {% include 'include/login.html' %}
<a href=/app/login.py?logout=logout title="Logout, user name: {{ user }}" class="login"> Logout</a>
{% else %}
<a href=/app/login.py title="Login" class="login"> Login</a>
{% endif %}
</ul> </ul>
<div id="create" style="height: 95%;"> {% include 'include/add_proxy.html' %}
<div id="left-collumn">
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create Listen" class="redirectListen span-link">Create Listen</span>
</div>
<div class="server-desc">
A "listen" section defines a complete proxy with its frontend and backend parts combined in one section. It is generally useful for TCP-only traffic.
</div>
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create HTTP Listen" class="redirectListen span-link" id="create-http-listen">Create HTTP Listen</span>
</div>
<div class="server-desc">
Create HTTP proxy
</div>
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create SSL Listen" class="redirectListen span-link" id="create-ssl-listen">Create SSL Listen</span>
</div>
<div class="server-desc">
Create HTTPS Proxy with the SSL termination on HAProxy and SSL offload.
HAProxy will send to backends HTTP traffic. You need have <span title="Upload SSL" class="redirectSsl span-link" style="color: #5d9ceb">uploaded a PEM certificat</span>
</div>
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create SSL Listen" class="redirectListen span-link" id="create-https-listen">Create HTTPS Listen</span>
</div>
<div class="server-desc">
Create HTTPS Proxy without the SSL termination on HAProxy and SSL offload. HAProxy will send to backends HTTPS traffic
</div>
</div>
</div>
</div>
<div id="middle-collumn">
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create Frontend" class="redirectFrontend span-link">Create Frontend</span>
</div>
<div class="server-desc">
A "frontend" section describes a set of listening sockets accepting client connections.
And forwards them to backend
<br />
</div>
</div>
</div>
<div class="div-server">
<div class="server-name">
<span title="Create HTTP Frontend" class="redirectListen span-link" id="create-http-frontend">Create HTTP Frontend</span>
</div>
<div class="server-desc">
Create HTTP Frontend
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create SSL Frontend" class="redirectListen span-link" id="create-ssl-frontend">Create SSL Frontend</span>
</div>
<div class="server-desc">
Create HTTPS Frontend with the SSL termination on HAProxy and SSL offload. HAProxy will send to backends HTTP traffic. You need have <span title="Upload SSL" class="redirectSsl span-link" style="color: #5d9ceb">uploaded a PEM certificat</span>
</div>
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create HTTPS Frontend" class="redirectListen span-link" id="create-https-frontend">Create HTTPS Frontend</span>
</div>
<div class="server-desc">
Create HTTPS Frontend without the SSL termination on HAProxy and SSL offload. HAProxy will send to backends HTTPS traffic
</div>
</div>
</div>
</div>
<div id="right-collumn">
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create Backend" class="redirectBackend span-link">Create Backend</span>
</div>
<div class="server-desc">
A "backend" section describes a set of servers to which the proxy will connect to forward incoming connections.
<br />
<br />
</div>
</div>
</div>
<div class="div-server">
<div class="server-name">
<span title="Create SSL Backend" class="redirectListen span-link" id="create-http-backend">Create HTTP Backend</span>
</div>
<div class="server-desc">
Create HTTP Backend
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create HTTPS Backend" class="redirectListen span-link" id="create-ssl-backend">Create SSL Backend</span>
</div>
<div class="server-desc">
Create HTTPS Backend with the SSL termination on HAProxy and SSL offload. HAProxy will send to backends HTTP traffic. You need have <span title="Upload SSL" class="redirectSsl span-link" style="color: #5d9ceb">uploaded a PEM certificat</span>
</div>
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create SSL Backend" class="redirectListen span-link" id="create-https-backend">Create HTTPS Backend</span>
</div>
<div class="server-desc">
Create HTTPS Backend without the SSL termination on HAProxy and SSL offload. HAProxy will send to backends HTTPS traffic
</div>
</div>
</div>
</div>
{% if add %}
<div class="alert alert-success" style="margin-left: 20px; clear: both;">
<h3>{{ add }} was success added</h3>
{{ conf_add }}
</div>
{% endif %}
</div>
<div id="listen"> <div id="listen">
<form name="add-listner" action="/app/add.py"> <form name="add-listner" action="/app/add.py">
<table class="add-table"> <table class="add-table">
@ -193,31 +55,30 @@ h3 {
<tr> <tr>
<td class="addName">Name:</td> <td class="addName">Name:</td>
<td class="addOption"> <td class="addOption">
<input type="text" name="listner" id="name" required title="Name Listner" placeholder="web_80" class="form-control"> {{ input('name', name='listner', title="Name Listner", placeholder="web_80", required='required') }}
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="addName">IP and Port:</td> <td class="addName">IP and Port:</td>
<td class="addOption"> <td class="addOption">
<input type="text" name="ip" id="ip" title="" size="15" placeholder="Any" class="form-control"><b>:</b> {{ input('ip', placeholder="Any", size='15') }}<b>:</b>
<input type="number" name="port" id="listen-port" required title="Port for bind listen" size="5" placeholder="8080" class="form-control"> {{ input('listen-port', name='port', type="number", title="Port for bind listen", placeholder="8080", size='5', required='required') }}
<div class="tooltip tooltipTop">IP for bind listner, <b>if empty will be assignet on all IPs</b>. Start typing ip, or press down.<br>If you use <b>VRRP keep in blank</b>. If you assign an IP, the slave will not start</div> <div class="tooltip tooltipTop">IP for bind listner, <b>if empty will be assignet on all IPs</b>. Start typing ip, or press down.<br>If you use <b>VRRP keep in blank</b>. If you assign an IP, the slave will not start</div>
</td> </td>
</tr> </tr>
<tr class="advance"> <tr class="advance">
<td class="addName">Mode: </td> <td class="addName">Mode: </td>
<td class="addOption"> <td class="addOption">
<select required name="mode" id="listen-mode-select"> {% set values = dict() %}
<option value="http" selected>http</option> {% set values = {'http':'http','tcp':'tcp'} %}
<option value="tcp">tcp</option> {{ select('listen-mode-select', name='mode', values=values, selected='http', required='required', class='force_close') }}
</select>
<span id="https-listen-span"> <span id="https-listen-span">
<label for="https-listen" style="margin-top: 5px;" title="Enable ssl">SSL?</label> <label for="https-listen" style="margin-top: 5px;" title="Enable ssl">SSL?</label>
<input type="checkbox" id="https-listen" name="ssl" value="https" > <input type="checkbox" id="https-listen" name="ssl" value="https" >
</span> </span>
<div id="https-hide-listen" style="display: none;"> <div id="https-hide-listen" style="display: none;">
<br /><span class="tooltip tooltipTop">Enter name to pem file, or press down:</span><br /> <br /><span class="tooltip tooltipTop">Enter name to pem file, or press down:</span><br />
<input type="text" name="cert" placeholder="some_cert.pem" class="form-control" size="39" id="path-cert-listen"><br /> {{ input('path-cert-listen', name="cert", placeholder="some_cert.pem", size='39') }}<br />
<label for="ssl-check-listen" style="margin-top: 5px;">Disable ssl verify on servers?</label><input type="checkbox" id="ssl-check-listen" name="ssl-check" value="ssl-check" checked> <label for="ssl-check-listen" style="margin-top: 5px;">Disable ssl verify on servers?</label><input type="checkbox" id="ssl-check-listen" name="ssl-check" value="ssl-check" checked>
</div> </div>
</td> </td>
@ -225,29 +86,25 @@ h3 {
<tr class="advance"> <tr class="advance">
<td class="addName">Maxconn: </td> <td class="addName">Maxconn: </td>
<td class="addOption"> <td class="addOption">
<input type="number" name="maxconn" required title="Fix the maximum number of concurrent connections on a frontend" size="5" value="2000" class="form-control"> {{ input('maxconn', value='2000', type="number", title="Fix the maximum number of concurrent connections on a frontend", size='5', required='required') }}
<div class="tooltip tooltipTop">This value should not exceed the global maxconn. Default global maxconn value: 2000</div> <div class="tooltip tooltipTop">This value should not exceed the global maxconn. Default global maxconn value: 2000</div>
</td> </td>
</tr> </tr>
<tr class="advance"> <tr class="advance">
<td class="addName">Balance: </td> <td class="addName">Balance: </td>
<td class="addOption"> <td class="addOption">
<select required name="balance"> {% set values = dict() %}
<option value="roundrobin" selected>roundrobin</option> {% set values = {'roundrobin':'roundrobin','source':'source','leastconn':'leastconn', 'first':'first', 'rdp-cookie':'rdp-cookie'} %}
<option value="source">source</option> {{ select('balance', values=values, selected='roundrobin', required='required', class='force_close') }}
<option value="leastconn">leastconn</option>
<option value="first">first</option>
<option value="rdp-cookie">rdp-cookie</option>
</select>
</td> </td>
</tr> </tr>
<tr class="advance"> <tr class="advance">
<td class="addName"><span title="Cache support start 1.8 and latter">Web acceleration(?):</span></td> <td class="addName"><span title="Cache support start 1.8 and latter">Web acceleration(?):</span></td>
<td class="addOption"> <td class="addOption">
<span class="controlgroup"> <span class="controlgroup">
<label for="compression" title="Enable Compression">Compression</label><input type="checkbox" id="compression" name="compression" value="1"> {{ checkbox('compression', title='Enable Compression', value='1', desc='Compression') }}
<label for="cache" title="Enable Compression">Cache</label><input type="checkbox" id="cache" name="cache" value="2"> {{ checkbox('cache', title='Enable cache', value='2', desc='Cache') }}
<label for="ssl_offloading" title="Enable SSL Offloading">SSL Offloading</label><input type="checkbox" id="ssl_offloading"> {{ checkbox('ssl_offloading', title='Enable SSL Offloading', desc='SSL Offloading') }}
</span> </span>
</td> </td>
</tr> </tr>
@ -255,14 +112,14 @@ h3 {
<td class="addName"><span title="Web application firewall">WAF(?):</span></td> <td class="addName"><span title="Web application firewall">WAF(?):</span></td>
<td class="addOption"> <td class="addOption">
<span class="controlgroup"> <span class="controlgroup">
<label for="slow_atack" title="Slow atack protect">Slow atack</label><input type="checkbox" id="slow_atack"> {{ checkbox('slow_atack', title='Slow atack protect', desc='Slow atack') }}
<label for="ddos" title="DDOS atack protect">DDOS</label><input type="checkbox" id="ddos"> {{ checkbox('ddos', title='DDOS atack protect', desc='DDOS') }}
<label for="blacklist_checkbox" title="Enable SSL Offloading">Blacklist</label><input type="checkbox" id="blacklist_checkbox"> {{ checkbox('blacklist_checkbox', title='Use blacklist', desc='Blacklist') }}
<label for="waf" title="Web application firewall">WAF</label><input type="checkbox" id="waf" name="waf" value="1"> {{ checkbox('waf', title='Web application firewall', desc='WAF', value='1') }}
</span> </span>
<div id="blacklist-hide" style="display: none;"> <div id="blacklist-hide" style="display: none;">
<br /><span class="tooltip tooltipTop">Enter the name of the blacklist, or press down:</span><br /> <br /><span class="tooltip tooltipTop">Enter the name of the blacklist, or press down:</span><br />
<input type="text" name="blacklist" placeholder="blacklist.lst" class="form-control" size="39" id="blacklist-hide-input"><br /> {{ input('blacklist-hide-input', size='39', name="blacklist", placeholder="blacklist.lst") }}
</div> </div>
</td> </td>
</tr> </tr>
@ -270,53 +127,42 @@ h3 {
<td class="addName">Optinons:</td> <td class="addName">Optinons:</td>
<td class="addOption"> <td class="addOption">
<span class="controlgroup"> <span class="controlgroup">
<label for="forward_for" title="Option Forward for if none">Forward for</label><input type="checkbox" id="forward_for"> {{ checkbox('forward_for', title='Option Forward for if none', desc='Forward for') }}
<label for="redispatch" title="Enable Redispatch">Redispatch</label><input type="checkbox" id="redispatch"> {{ checkbox('redispatch', title='Enable Redispatch', desc='Redispatch') }}
<select name="force_close" class="force_close"> {% set values = dict() %}
<option disabled selected>Force HTTP close</option> {% set values = {'Off':'Off','Server only':'Server only','Force close':'Force close','Pretend keep alive':'Pretend keep alive'} %}
<option>Off</option> {{ select('force_close', values=values, first='Force HTTP close', class='force_close') }}
<option value="1">Server only</option> {{ checkbox('cookie', title='Set cookie', desc='Set cookie', value='1') }}
<option value="2">Force close</option> {{ checkbox('options-listen-show', title='Set options manualy', desc='Set options') }}
<option value="3">Pretend keep alive</option>
</select>
<label for="cookie" title="Enable Redispatch">Set cookie</label><input type="checkbox" id="cookie" name="cookie" value="1">
<label for="options-listen-show" title="Set options manualy">Set options</label><input type="checkbox" id="options-listen-show">
</span> </span>
<br> <br>
<span id="cookie_div" style="display: none;"> <span id="cookie_div" style="display: none;">
<input type="text" placeholder="name" name="cookie_name" id="cookie_name" class="form-control"><br><br> <input type="text" placeholder="name" name="cookie_name" id="cookie_name" class="form-control"><br><br>
<input type="text" placeholder="domain" name="cookie_domain" class="form-control"><br><br> <input type="text" placeholder="domain" name="cookie_domain" class="form-control"><br><br>
<span class="controlgroup"> <span class="controlgroup">
<select name="rewrite" id="rewrite" class="force_close"> {% set values = dict() %}
<option disabled selected>rewrite/indirect/insert</option> {% set values = {'None':'None','rewrite':'rewrite','indirect':'indirect','insert':'insert'} %}
<option>None</option> {{ select('rewrite', values=values, first='rewrite/indirect/insert', class='force_close') }}
<option value="rewrite">rewrite</option> {{ checkbox('prefix', title='This keyword indicates that instead of relying on a dedicated cookie for the persistence, an existing one will be completed', desc='prefix', value='prefix') }}
<option value="indirect">indirect</option> {{ checkbox('nocache', title='This option is recommended in conjunction with the insert mode when there is a cache between the client and HAProxy', desc='nocache', value='nocache') }}
<option value="insert">insert</option> {{ checkbox('postonly', title='This option ensures that cookie insertion will only be performed on responses to POST requests', desc='postonly', value='postonly') }}
</select> {{ checkbox('dynamic', title='Activate dynamic cookies. When used, a session cookie is dynamically created for each server', desc='dynamic', value='dynamic') }}
<label for="prefix" title="This keyword indicates that instead of relying on a dedicated cookie for the persistence, an existing one will be completed.">prefix</label>
<input type="checkbox" name="prefix" value="prefix" id="prefix">
<label for="nocache" title="This option is recommended in conjunction with the insert mode when there is a cache between the client and HAProxy.">nocache</label>
<input type="checkbox" name="nocache" value="nocache" id="nocache">
<label for="postonly" title="This option ensures that cookie insertion will only be performed on responses to POST requests.">postonly</label>
<input type="checkbox" name="postonly" value="postonly" id="postonly">
<label for="dynamic" title="Activate dynamic cookies. When used, a session cookie is dynamically created for each server.">dynamic</label>
<input type="checkbox" name="dynamic" value="dynamic" id="dynamic">
<span id="dynamic_div" style="display: none;"> <span id="dynamic_div" style="display: none;">
dynamic-cookie-key: <input type="text" placeholder="your-custom-key" name="dynamic-cookie-key" id="dynamic-cookie-key" class="form-control"> dynamic-cookie-key: {{ input('dynamic-cookie-key', placeholder="your-custom-key") }}
</span> </span>
</span> </span>
</span> </span>
<div id="options-listen-show-div" style="display: none;"> <div id="options-listen-show-div" style="display: none;">
<div class="tooltip"> <div class="tooltip">
<span style="padding-right: 10px;">Start typing options: </span> <span style="padding-right: 10px;">Start typing options: </span>
{{ input('options') }}
<input type="text" id="options" class="form-control"> <input type="text" id="options" class="form-control">
<span style="padding-left: 10px;"> <span style="padding-left: 10px;">
or press down. <a href="http://cbonte.github.io/haproxy-dconv/1.7/configuration.html" target="_blanck" style="color: #23527c" title="HAproxy docs">Read more about options</a> or press down. <a href="http://cbonte.github.io/haproxy-dconv/1.7/configuration.html" target="_blanck" style="color: #23527c" title="HAproxy docs">Read more about options</a>
</span> </span>
<br /> <br />
<span style="padding-right: 10px;">Start typing saved options: </span> <span style="padding-right: 10px;">Start typing saved options: </span>
<input type="text" id="saved-options" class="form-control"> {{ input('saved-options') }}
It are the options that you saved in the "Options" tab It are the options that you saved in the "Options" tab
</div> </div>
<textarea name="option" title="Options thru" id="optionsInput" cols=80 rows=5 placeholder="acl test hdr_beg(host) -i some_host"></textarea> <textarea name="option" title="Options thru" id="optionsInput" cols=80 rows=5 placeholder="acl test hdr_beg(host) -i some_host"></textarea>
@ -326,19 +172,7 @@ h3 {
<tr> <tr>
<td class="addName">Servers:</td> <td class="addName">Servers:</td>
<td class="addOption"> <td class="addOption">
<span id="servers"> {% include 'include/add_servers.html' %}
<input name="servers" required title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
<input name="server_port" required title="Backend IP" size=1 placeholder="yyy" class="form-control">
<br />
<input name="servers" title="Backend port" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
<input name="server_port" title="Backend port" size=1 placeholder="yyy" class="form-control">
<br />
<input name="servers" title="Backend port" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
<input name="server_port" title="Backend port" size=1 placeholder="yyy" class="form-control">
</span>
<span>
<a class="add-server" id="add-server-input" title="Add backend server" style="cursor: pointer;"></a>
</span>
</td> </td>
</tr> </tr>
<tr class="advance"> <tr class="advance">
@ -352,24 +186,15 @@ h3 {
<div class="controlgroup" id="controlgroup-listen" style="display: none;"> <div class="controlgroup" id="controlgroup-listen" style="display: none;">
<label for="check-servers-listen" title="Ebable servers check">Check</label> <label for="check-servers-listen" title="Ebable servers check">Check</label>
<input type="checkbox" id="check-servers-listen" name="check-servers" checked value="1"> <input type="checkbox" id="check-servers-listen" name="check-servers" checked value="1">
<select name="inter" id="inter-listen" class="force_close"> {% set values = dict() %}
<option value="inter" disabled selected>inter</option> {% set values = {'1000':'1000','2000':'2000','3000':'3000'} %}
<option value="1000">1000</option> {{ select('inter', values=values, first='inter', class='force_close') }}
<option value="2000">2000</option> {% set values = dict() %}
<option value="3000">3000</option> {% set values = {'1':'1','2':'2','3':'3'} %}
</select> {{ select('rise-listen', name='rise-listen', values=values, first='rise', class='force_close') }}
<select name="rise" id="rise-listen"> {% set values = dict() %}
<option value="rise" disabled selected class="force_close">rise</option> {% set values = {'4':'4','5':'5','6':'6'} %}
<option value="1">1</option> {{ select('fall-listen', name='fall', values=values, first='fall', class='force_close') }}
<option value="2">2</option>
<option value="3">3</option>
</select>
<select name="fall" id="fall-listen">
<option value="fall" disabled selected class="force_close">fall</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select>
</div> </div>
</td> </td>
</tr> </tr>
@ -434,24 +259,23 @@ h3 {
<tr class="advance"> <tr class="advance">
<td class="addName">Mode: </td> <td class="addName">Mode: </td>
<td class="addOption"> <td class="addOption">
<select required name="mode" id="frontend-mode-select"> {% set values = dict() %}
<option value="http" selected>http</option> {% set values = {'http':'http','tcp':'tcp'} %}
<option value="tcp">tcp</option> {{ select('frontend-mode-select', name='mode', values=values, selected='http', required='required', class='force_close') }}
</select>
<span id="https-frontend-span"> <span id="https-frontend-span">
<label for="https-frontend" style="margin-top: 5px;">SSL?</label> <label for="https-frontend" style="margin-top: 5px;">SSL?</label>
<input type="checkbox" id="https-frontend" name="ssl" value="https"> <input type="checkbox" id="https-frontend" name="ssl" value="https">
</span> </span>
<div id="https-hide-frontend" style="display: none;"> <div id="https-hide-frontend" style="display: none;">
<br /><span class="tooltip tooltipTop">Enter name to pem file, or press down:</span><br /> <br /><span class="tooltip tooltipTop">Enter name to pem file, or press down:</span><br />
<input type="text" name="cert" placeholder="some_cert.pem" class="form-control" size="39" id="path-cert-frontend"> {{ input('path-cert-frontend', name="cert", placeholder="some_cert.pem", size='39') }}
</div> </div>
</td> </td>
</tr> </tr>
<tr class="advance"> <tr class="advance">
<td class="addName">Maxconn: </td> <td class="addName">Maxconn: </td>
<td class="addOption"> <td class="addOption">
<input type="number" name="maxconn" required title="Fix the maximum number of concurrent connections on a frontend" size="5" value="2000" class="form-control"> {{ input('maxconn', value='2000', type="number", title="Fix the maximum number of concurrent connections on a frontend", size='5', required='required') }}
<div class="tooltip tooltipTop">This value should not exceed the global maxconn. Default global maxconn value: 2000</div> <div class="tooltip tooltipTop">This value should not exceed the global maxconn. Default global maxconn value: 2000</div>
</td> </td>
</tr> </tr>
@ -459,9 +283,9 @@ h3 {
<td class="addName"><span title="Cache support start 1.8 and latter">Web acceleration(?):</span></td> <td class="addName"><span title="Cache support start 1.8 and latter">Web acceleration(?):</span></td>
<td class="addOption"> <td class="addOption">
<span class="controlgroup"> <span class="controlgroup">
<label for="compression2" title="Enable Compression">Compression</label><input type="checkbox" id="compression2" name="compression" value="1"> {{ checkbox('compression2', title='Enable Compression', value='1', desc='Compression') }}
<label for="cache2" title="Enable Compression">Cache</label><input type="checkbox" id="cache2" name="cache" value="2"> {{ checkbox('cache2', title='Enable cache', value='2', desc='Cache') }}
<label for="ssl_offloading1" title="Enable SSL Offloading">SSL Offloading</label><input type="checkbox" id="ssl_offloading1"> {{ checkbox('ssl_offloading1', title='Enable SSL Offloading', desc='SSL Offloading') }}
</span> </span>
</td> </td>
</tr> </tr>
@ -469,13 +293,14 @@ h3 {
<td class="addName"><span title="Web application firewall">WAF(?):</span></td> <td class="addName"><span title="Web application firewall">WAF(?):</span></td>
<td class="addOption"> <td class="addOption">
<span class="controlgroup"> <span class="controlgroup">
<label for="slow_atack1" title="Slow atack protect">Slow atack</label><input type="checkbox" id="slow_atack1"> {{ checkbox('slow_atack1', title='Slow atack protect', desc='Slow atack') }}
<label for="ddos1" title="DDOS atack protect">DDOS</label><input type="checkbox" id="ddos1"> {{ checkbox('ddos1', title='DDOS atack protect', desc='DDOS') }}
<label for="blacklist_checkbox1" title="Enable SSL Offloading">Blacklist</label><input type="checkbox" id="blacklist_checkbox1"> {{ checkbox('blacklist_checkbox1', title='Use blacklist', desc='Blacklist') }}
{{ checkbox('waf2', name='waf', title='Web application firewall', desc='WAF', value='1') }}
</span> </span>
<div id="blacklist-hide1" style="display: none;"> <div id="blacklist-hide1" style="display: none;">
<br /><span class="tooltip tooltipTop">Enter the name of the blacklist, or press down:</span><br /> <br /><span class="tooltip tooltipTop">Enter the name of the blacklist, or press down:</span><br />
<input type="text" name="blacklist" placeholder="blacklist.lst" class="form-control" size="39" id="blacklist-hide-input1"><br /> {{ input('blacklist-hide-input1', size='39', name="blacklist", placeholder="blacklist.lst") }}
</div> </div>
</td> </td>
</tr> </tr>
@ -483,26 +308,22 @@ h3 {
<td class="addName">Optinons:</td> <td class="addName">Optinons:</td>
<td class="addOption"> <td class="addOption">
<span class="controlgroup"> <span class="controlgroup">
<label for="forward_for1" title="Option Forward for if none">Forward for</label><input type="checkbox" id="forward_for1"> {{ checkbox('forward_for1', title='Option Forward for if none', desc='Forward for') }}
<select name="force_close" class="force_close"> {% set values = dict() %}
<option disabled selected>Force HTTP close</option> {% set values = {'Off':'Off','Server only':'Server only','Force close':'Force close','Pretend keep alive':'Pretend keep alive'} %}
<option>Off</option> {{ select('force_close', values=values, first='Force HTTP close', class='force_close') }}
<option value="1">Server only</option> {{ checkbox('options-frontend-show', title='Set options manualy', desc='Set options') }}
<option value="2">Force close</option>
<option value="3">Pretend keep alive</option>
</select>
<label for="options-frontend-show" title="Set options manualy">Set options</label><input type="checkbox" id="options-frontend-show">
</span> </span>
<div id="options-frontend-show-div" style="display: none;"> <div id="options-frontend-show-div" style="display: none;">
<div style="font-size: 12px; padding-bottom: 10px;"> <div style="font-size: 12px; padding-bottom: 10px;">
<span style="padding-right: 10px;">Start typing options: </span> <span style="padding-right: 10px;">Start typing options: </span>
<input type="text" id="options1" class="form-control"> {{ input('options2') }}
<span style="padding-left: 10px;"> <span style="padding-left: 10px;">
or press down. <a href="http://cbonte.github.io/haproxy-dconv/1.7/configuration.html" target="_blanck" style="color: #23527c" title="HAproxy docs">Read more about options</a> or press down. <a href="http://cbonte.github.io/haproxy-dconv/1.7/configuration.html" target="_blanck" style="color: #23527c" title="HAproxy docs">Read more about options</a>
</span> </span>
<br /> <br />
<span style="padding-right: 10px;">Start typing saved options: </span> <span style="padding-right: 10px;">Start typing saved options: </span>
<input type="text" id="saved-options1" class="form-control"> {{ input('saved-options1') }}
It are the options that you saved in the "Options" tab It are the options that you saved in the "Options" tab
</div> </div>
<textarea name="option" title="Options thru" cols=80 rows=5 id="optionsInput1" placeholder="acl test hdr_beg(host) -i some_host"></textarea> <textarea name="option" title="Options thru" cols=80 rows=5 id="optionsInput1" placeholder="acl test hdr_beg(host) -i some_host"></textarea>
@ -513,9 +334,9 @@ h3 {
<td class="addName">Default backend</td> <td class="addName">Default backend</td>
<td class="addOption"> <td class="addOption">
<div style="font-size: 12px; padding-bottom: 10px;">Start typing backend, or press down</div> <div style="font-size: 12px; padding-bottom: 10px;">Start typing backend, or press down</div>
<input name="backend" id="backends" required size="30" placeholder="some_backend" class="form-control"> {{ input('backends', name='backends', placeholder="some_backend", size='30') }}
<span style="font-size: 12px; padding-left: 10px;"> .</span> <span style="font-size: 12px; padding-left: 10px;"> .</span>
<p style="font-size: 12px"><b>Note:</b> If backend don\t exist, you must <a href="#" style="color: #23527c" title="Create backend" class="redirectBackend">create backend first</a>.</p> <p style="font-size: 12px"><b>Note:</b> If backend don't exist, you have to <a href="#" style="color: #23527c" title="Create backend" class="redirectBackend">create backend first</a>.</p>
</td> </td>
</tr> </tr>
<tr class="advance-show"> <tr class="advance-show">
@ -565,16 +386,15 @@ h3 {
<tr> <tr>
<td class="addName">Name:</td> <td class="addName">Name:</td>
<td class="addOption"> <td class="addOption">
<input type="text" name="new_backend" id="new_backend" required title="Name backend" placeholder="web_80" class="form-control"> {{ input('new_backend', title="Name backend", placeholder="web_80", required='required') }}
</td> </td>
</tr> </tr>
<tr class="advance"> <tr class="advance">
<td class="addName">Mode: </td> <td class="addName">Mode: </td>
<td class="addOption"> <td class="addOption">
<select required name="mode" id="backend-mode-select"> {% set values = dict() %}
<option value="http" selected>http</option> {% set values = {'http':'http','tcp':'tcp'} %}
<option value="tcp">tcp</option> {{ select('backend-mode-select', name='mode', values=values, selected='http', required='required', class='force_close') }}
</select>
<span id="https-backend-span"> <span id="https-backend-span">
<label for="https-backend" style="margin-top: 5px;">SSL enabled on frontend?</label> <label for="https-backend" style="margin-top: 5px;">SSL enabled on frontend?</label>
<input type="checkbox" id="https-backend" name="ssl" value="https"> <input type="checkbox" id="https-backend" name="ssl" value="https">
@ -587,22 +407,18 @@ h3 {
<tr class="advance"> <tr class="advance">
<td class="addName">Balance: </td> <td class="addName">Balance: </td>
<td class="addOption"> <td class="addOption">
<select required name="balance"> {% set values = dict() %}
<option value="roundrobin" selected>roundrobin</option> {% set values = {'roundrobin':'roundrobin','source':'source','leastconn':'leastconn', 'first':'first', 'rdp-cookie':'rdp-cookie'} %}
<option value="source">source</option> {{ select('balance', values=values, selected='roundrobin', required='required', class='force_close') }}
<option value="leastconn">leastconn</option>
<option value="first">first</option>
<option value="rdp-cookie">rdp-cookie</option>
</select>
</td> </td>
</tr> </tr>
<tr class="advance"> <tr class="advance">
<td class="addName"><span title="Cache support start 1.8 and latter">Web acceleration(?):</span></td> <td class="addName"><span title="Cache support start 1.8 and latter">Web acceleration(?):</span></td>
<td class="addOption"> <td class="addOption">
<span class="controlgroup"> <span class="controlgroup">
<label for="compression3" title="Enable Compression">Compression</label><input type="checkbox" id="compression3" name="compression" value="1"> {{ checkbox('compression3', title='Enable Compression', value='1', desc='Compression') }}
<label for="cache3" title="Enable Compression">Cache</label><input type="checkbox" id="cache3" name="cache" value="2"> {{ checkbox('cache3', title='Enable cache', value='2', desc='Cache') }}
<label for="ssl_offloading2" title="Enable SSL Offloading">SSL Offloading</label><input type="checkbox" id="ssl_offloading2"> {{ checkbox('ssl_offloading2', title='Enable SSL Offloading', desc='SSL Offloading') }}
</span> </span>
</td> </td>
</tr> </tr>
@ -610,47 +426,35 @@ h3 {
<td class="addName">Optinons:</td> <td class="addName">Optinons:</td>
<td class="addOption"> <td class="addOption">
<span class="controlgroup"> <span class="controlgroup">
<label for="forward_for2" title="Option Forward for if none">Forward for</label><input type="checkbox" id="forward_for2"> {{ checkbox('forward_for2', title='Option Forward for if none', desc='Forward for') }}
<label for="redispatch2" title="Enable Redispatch">Redispatch</label><input type="checkbox" id="redispatch2"> {{ checkbox('redispatch2', title='Enable Redispatch', desc='Redispatch') }}
<select name="force_close" class="force_close"> {% set values = dict() %}
<option disabled selected>Force HTTP close</option> {% set values = {'Off':'Off','Server only':'Server only','Force close':'Force close','Pretend keep alive':'Pretend keep alive'} %}
<option>Off</option> {{ select('force_close', values=values, first='Force HTTP close', class='force_close') }}
<option value="1">Server only</option> {{ checkbox('cookie2', title='Set cookie', desc='Set cookie', value='1') }}
<option value="2">Force close</option> {{ checkbox('options-backend-show', title='Set options manualy', desc='Set options') }}
<option value="3">Pretend keep alive</option>
</select>
<label for="cookie2" title="Enable Redispatch">Set cookie</label><input type="checkbox" id="cookie2" name="cookie" value="1">
<label for="options-backend-show" title="Set options manualy">Set options</label><input type="checkbox" id="options-backend-show">
</span> </span>
<br> <br>
<span id="cookie_div2" style="display: none;"> <span id="cookie_div2" style="display: none;">
<input type="text" placeholder="name" name="cookie_name" id="cookie_name2" class="form-control"><br><br> <input type="text" placeholder="name" name="cookie_name" id="cookie_name2" class="form-control"><br><br>
<input type="text" placeholder="domain" name="cookie_domain" class="form-control"><br><br> <input type="text" placeholder="domain" name="cookie_domain" class="form-control"><br><br>
<span class="controlgroup"> <span class="controlgroup">
<select name="rewrite" id="rewrite2"> {% set values = dict() %}
<option disabled selected>rewrite/indirect/insert</option> {% set values = {'None':'None','rewrite':'rewrite','indirect':'indirect','insert':'insert'} %}
<option>None</option> {{ select('rewrite2', values=values, first='rewrite/indirect/insert', class='force_close') }}
<option value="rewrite">rewrite</option> {{ checkbox('prefix2', name='prefix', title='This keyword indicates that instead of relying on a dedicated cookie for the persistence, an existing one will be completed', desc='prefix', value='prefix') }}
<option value="indirect">indirect</option> {{ checkbox('nocache2', name='nocache', title='This option is recommended in conjunction with the insert mode when there is a cache between the client and HAProxy', desc='nocache', value='nocache') }}
<option value="insert">insert</option> {{ checkbox('postonly2', name='postonly', title='This option ensures that cookie insertion will only be performed on responses to POST requests', desc='postonly', value='postonly') }}
</select> {{ checkbox('dynamic2', name='dynamic', title='Activate dynamic cookies. When used, a session cookie is dynamically created for each server', desc='dynamic', value='dynamic') }}
<label for="prefix2" title="This keyword indicates that instead of relying on a dedicated cookie for the persistence, an existing one will be completed.">prefix</label>
<input type="checkbox" name="prefix" value="prefix" id="prefix2">
<label for="nocache2" title="This option is recommended in conjunction with the insert mode when there is a cache between the client and HAProxy.">nocache</label>
<input type="checkbox" name="nocache" value="nocache" id="nocache2">
<label for="postonly2" title="This option ensures that cookie insertion will only be performed on responses to POST requests..">postonly</label>
<input type="checkbox" name="postonly" value="postonly" id="postonly2">
<label for="dynamic2" title="Activate dynamic cookies. When used, a session cookie is dynamically created for each server.">dynamic</label>
<input type="checkbox" name="dynamic" value="dynamic" id="dynamic2">
<span id="dynamic_div2" style="display: none;"> <span id="dynamic_div2" style="display: none;">
dynamic-cookie-key: <input type="text" placeholder="your-custom-key" name="dynamic-cookie-key" id="dynamic-cookie-key2" class="form-control"> dynamic-cookie-key: {{ input('dynamic-cookie-key2', name='dynamic-cookie-key', placeholder="your-custom-key") }}
</span> </span>
</span> </span>
</span> </span>
<div id="options-backend-show-div" style="display: none;"> <div id="options-backend-show-div" style="display: none;">
<div style="font-size: 12px; padding-bottom: 10px;"> <div style="font-size: 12px; padding-bottom: 10px;">
<span style="padding-right: 10px;">Start typing options: </span> <span style="padding-right: 10px;">Start typing options: </span>
<input type="text" id="options2" class="form-control"> {{ input('options2') }}
<span style="padding-left: 10px;"> <span style="padding-left: 10px;">
or press down. <a href="http://cbonte.github.io/haproxy-dconv/1.7/configuration.html" target="_blanck" style="color: #23527c" title="HAproxy docs">Read more about options</a> or press down. <a href="http://cbonte.github.io/haproxy-dconv/1.7/configuration.html" target="_blanck" style="color: #23527c" title="HAproxy docs">Read more about options</a>
</span> </span>
@ -666,50 +470,29 @@ h3 {
<tr> <tr>
<td class="addName">Servers:</td> <td class="addName">Servers:</td>
<td class="addOption"> <td class="addOption">
<span id="servers2"> {% include 'include/add_servers.html' %}
<input name="servers" required title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
<input name="server_port" required title="Backend IP" size=1 placeholder="yyy" class="form-control">
<br />
<input name="servers" title="Backend port" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
<input name="server_port" title="Backend port" size=1 placeholder="yyy" class="form-control">
<br />
<input name="servers" title="Backend port" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
<input name="server_port" title="Backend port" size=1 placeholder="yyy" class="form-control">
</span>
<span>
<a class="add-server" id="add-server-input2" title="Add backend server" style="cursor: pointer;"></a>
</span>
</td> </td>
</tr> </tr>
<tr class="advance"> <tr class="advance">
<td class="addName">Check:</td> <td class="addName">Check:</td>
<td class="addOption"> <td class="addOption">
<div> <div>
<label for="controlgroup-backend-show" style="margin-top: 5px;" title="Change default check" >Cusmot check params</label> <label for="controlgroup-backend-show" style="margin-top: 5px;" title="Change default check">Cusmot check params</label>
<input type="checkbox" id="controlgroup-backend-show" name="default-check"> <input type="checkbox" id="controlgroup-backend-show" name="default-check">
<span class="tooltip tooltipTop"> Default params: inter 2000 rise 2 fall 5</span> <span class="tooltip tooltipTop"> Default params: inter 2000 rise 2 fall 5</span>
</div> </div>
<div class="controlgroup" id="controlgroup-backend" style="display: none;"> <div class="controlgroup" id="controlgroup-backend" style="display: none;">
<label for="check-servers-backend" title="Ebable servers check">Check</label> <label for="check-servers-backend" title="Ebable servers check">Check</label>
<input type="checkbox" id="check-servers-backend" name="check-servers" checked value="1"> <input type="checkbox" id="check-servers-backend" name="check-servers" checked value="1">
<select name="inter" id="inter-backend"> {% set values = dict() %}
<option value="inter" disabled selected>inter</option> {% set values = {'1000':'1000','2000':'2000','3000':'3000'} %}
<option value="1000">1000</option> {{ select('inter-backend', values=values, first='inter', class='force_close') }}
<option value="2000">2000</option> {% set values = dict() %}
<option value="3000">3000</option> {% set values = {'1':'1','2':'2','3':'3'} %}
</select> {{ select('rise-backend', name='rise-listen', values=values, first='rise', class='force_close') }}
<select name="rise" id="rise-backend"> {% set values = dict() %}
<option value="rise" disabled selected>rise</option> {% set values = {'4':'4','5':'5','6':'6'} %}
<option value="1">1</option> {{ select('fall-backend', name='fall', values=values, first='fall', class='force_close') }}
<option value="2">2</option>
<option value="3">3</option>
</select>
<select name="fall" id="fall-backend">
<option value="fall" disabled selected>fall</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
</select>
</div> </div>
</td> </td>
</tr> </tr>
@ -768,7 +551,7 @@ h3 {
</select> </select>
</td> </td>
<td valign="top" style="padding-top: 27px;"> <td valign="top" style="padding-top: 27px;">
<input type="text" id="ssl_name" class="form-control"> {{ input('ssl_name') }}
</td> </td>
<td style="padding-top: 15px; padding-bottom: 15px;"> <td style="padding-top: 15px; padding-bottom: 15px;">
<textarea id="ssl_cert" cols="50" rows="5"></textarea><br /><br /> <textarea id="ssl_cert" cols="50" rows="5"></textarea><br /><br />
@ -814,7 +597,7 @@ h3 {
Enter option for save: Enter option for save:
</td> </td>
<td style="width: 77%;"> <td style="width: 77%;">
<input type="text" name="new-option" id="new-option" class="form-control" size="60"> {{ input('new-option', size='60') }}
</td> </td>
<td> <td>
<a class="add-admin" id="add-option-new" title="Add new option" style="cursor: pointer;"></a> <a class="add-admin" id="add-option-new" title="Add new option" style="cursor: pointer;"></a>
@ -866,10 +649,10 @@ h3 {
</tr> </tr>
<tr> <tr>
<td class="padding10 first-collumn"> <td class="padding10 first-collumn">
<input type="text" name="new-saved-servers" id="new-saved-servers" class="form-control" size="15"> {{ input('new-saved-servers', size='15') }}
</td> </td>
<td style="width: 77%;"> <td style="width: 77%;">
<input type="text" name="new-saved-servers-description" id="new-saved-servers-description" class="form-control" size="50"> {{ input('new-saved-servers-description', size='50') }}
</td> </td>
<td> <td>
<a class="add-admin" id="add-saved-server-new" title="Add new server" style="cursor: pointer;"></a> <a class="add-admin" id="add-saved-server-new" title="Add new server" style="cursor: pointer;"></a>
@ -911,14 +694,14 @@ h3 {
<tr> <tr>
<td class="addName">Userlist name:</td> <td class="addName">Userlist name:</td>
<td class="addOption"> <td class="addOption">
<input type="text" name="new_userlist" id="new_userlist" required title="Userlist name" placeholder="basic-auth-list" class="form-control"> {{ input('new_userlist', required='required', title="Userlist name", placeholder="basic-auth-list") }}
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="addName">Groups:</td> <td class="addName">Groups:</td>
<td class="addOption"> <td class="addOption">
<span id="userlist-groups"> <span id="userlist-groups">
<input name="userlist-group" title="User`s group" placeholder="group_name" class="form-control"> {{ input('userlist-group', title="User`s group", placeholder="group_name") }}
</span> </span>
<span> <span>
<a class="add-server" id="add-userlist-group" title="Add extra group" style="cursor: pointer;"></a> <a class="add-server" id="add-userlist-group" title="Add extra group" style="cursor: pointer;"></a>
@ -930,9 +713,9 @@ h3 {
<td class="addName">User:</td> <td class="addName">User:</td>
<td class="addOption"> <td class="addOption">
<span id="userlist-users"> <span id="userlist-users">
<input name="userlist-user" required title="User name" placeholder="user_name" class="form-control"> {{ input('userlist-user', required='required', title="User name", placeholder="user_name") }}
<input name="userlist-password" required title="User password. By default it insecure-password" placeholder="password" class="form-control"> {{ input('userlist-password', required='required', title="User password. By default it insecure-password", placeholder="password") }}
<input name="userlist-user-group" title="User`s group" placeholder="user`s group" class="form-control"> {{ input('userlist-user-group', title="User`s group", placeholder="user`s group") }}
</span> </span>
<span> <span>
<a class="add-server" id="add-userlist-user" title="Add extra user" style="cursor: pointer;"></a> <a class="add-server" id="add-userlist-user" title="Add extra user" style="cursor: pointer;"></a>
@ -957,19 +740,18 @@ h3 {
</a> </a>
</div> </div>
</div> </div>
{% include 'include/del_confirm.html' %}
<div id="dialog-confirm-delete" title="Are you sure you want to delete?" style="display: none;"> <div id="dialog-confirm-cert" title="View certificate " style="display: none;">
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:3px 12px 20px 0;"></span>Deleting all data will be lost?</p>
</div>
<div id="dialog-confirm" title="View certificate " style="display: none;">
<center><pre id="dialog-confirm-body"></pre></center> <center><pre id="dialog-confirm-body"></pre></center>
</div> </div>
<input type="hidden" id="group" value="{{ group }}"> <input type="hidden" id="group" value="{{ group }}">
</div> </div>
</div> </div>
<script> <script>
$( ".force_close" ).selectmenu({ $( function() {
$( ".force_close" ).selectmenu({
width: 180 width: 180
});
}); });
</script> </script>
{% endblock %} {% endblock %}

View File

@ -1,5 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
{% from 'include/input_macros.html' import input %}
<style> <style>
.container { .container {
margin-right: 0; margin-right: 0;
@ -7,9 +8,7 @@
</style> </style>
<script src="/inc/users.js"></script> <script src="/inc/users.js"></script>
<script src="/inc/fontawesome.min.js"></script> <script src="/inc/fontawesome.min.js"></script>
<div id="dialog-confirm" title="Are you sure you want to delete?" style="display: none;"> {% include 'include/del_confirm.html' %}
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:3px 12px 20px 0;"></span>Deleting irreversibly all data will be lost?</p>
</div>
<div id="tabs"> <div id="tabs">
<ul> <ul>
<li><a href="#users">Users</a></li> <li><a href="#users">Users</a></li>
@ -19,11 +18,7 @@
<li><a href="#checker">Checker</a></li> <li><a href="#checker">Checker</a></li>
<li><a href="#settings">Settings</a></li> <li><a href="#settings">Settings</a></li>
<li><a href="#updatehapwi">Update</a></li> <li><a href="#updatehapwi">Update</a></li>
{% if user %} {% include 'include/login.html' %}
<a href=/app/login.py?logout=logout title="Logout, user name: {{ user }}" class="login"> Logout</a>
{% else %}
<a href=/app/login.py title="Login" class="login"> Login</a>
{% endif %}
</ul> </ul>
<div id="users"> <div id="users">
<table class="overview" id="ajax-users"> <table class="overview" id="ajax-users">
@ -64,34 +59,7 @@
</script> </script>
{% for user in users %} {% for user in users %}
<tr id="user-{{user.0}}" class="{{ loop.cycle('odd', 'even') }}"> <tr id="user-{{user.0}}" class="{{ loop.cycle('odd', 'even') }}">
<td class="padding10 first-collumn"> {% include 'include/admin_users.html' %}
{% if user.6 == 1%}
<input type="text" id="login-{{user.0}}" value="{{user.1}}" class="form-control" readonly>
{% else %}
<input type="text" id="login-{{user.0}}" value="{{user.1}}" class="form-control">
{% endif %}
</td>
<td>
{% if user.6 != 1%}
<span title="Change password" style="cursor: pointer">
<img src="/inc/images/edit.png" alt="Edit" width="15" style="margin-bottom: -3px; padding-left: 15px;" onclick="openChangeUserPasswordDialog('{{user.0}}')" />
</span>
{% endif %}
</td>
<td class="checkbox">
{% if user.7 == 1 %}
<label for="activeuser-{{user.0}}"></label><input type="checkbox" id="activeuser-{{user.0}}" checked>
{% else %}
<label for="activeuser-{{user.0}}"></label><input type="checkbox" id="activeuser-{{user.0}}">
{% endif %}
</td>
<td>
{% if user.6 == 1%}
<input type="text" id="email-{{user.0}}" value="{{user.2}}" class="form-control" readonly>
{% else %}
<input type="text" id="email-{{user.0}}" value="{{user.2}}" class="form-control">
{% endif %}
</td>
<td> <td>
<select id="role-{{user.0}}" name="role-{{user.0}}"> <select id="role-{{user.0}}" name="role-{{user.0}}">
<option disabled selected>Choose role</option> <option disabled selected>Choose role</option>
@ -145,7 +113,7 @@
<td class="padding10 first-collumn"> <td class="padding10 first-collumn">
<input type="text" id="name-{{ group.0 }}" value="{{ group.1 }}" class="form-control"> <input type="text" id="name-{{ group.0 }}" value="{{ group.1 }}" class="form-control">
</td> </td>
<td> <td style="width: 100%;">
{% if group.2 != "None" %} {% if group.2 != "None" %}
<input type="text" id="descript-{{ group.0 }}" value="{{ group.2 }}" class="form-control" size="60"> <input type="text" id="descript-{{ group.0 }}" value="{{ group.2 }}" class="form-control" size="60">
{% else %} {% else %}
@ -169,10 +137,10 @@
</tr> </tr>
<tr> <tr>
<td class="padding10 first-collumn"> <td class="padding10 first-collumn">
<input type="text" name="new-group-add" id="new-group-add" class="form-control"> {{ input('new-group-add') }}
</td> </td>
<td> <td>
<input type="text" name="new-desc" id="new-desc" class="form-control" size="100"> {{ input('new-desc', size="60") }}
</td> </td>
<td> <td>
<a class="add-admin" id="add-group" title="Add new group" style="cursor: pointer;"></a> <a class="add-admin" id="add-group" title="Add new group" style="cursor: pointer;"></a>
@ -201,7 +169,6 @@
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
{% for server in servers %} {% for server in servers %}
<tr id="server-{{server.0}}" class="{{ loop.cycle('odd', 'even') }}"> <tr id="server-{{server.0}}" class="{{ loop.cycle('odd', 'even') }}">
<td class="padding10 first-collumn"> <td class="padding10 first-collumn">
@ -225,81 +192,7 @@
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
<td class="checkbox"> {% include 'include/admin_servers.html' %}
{% if server.5 == 1 %}
<label for="enable-{{server.0}}"></label><input type="checkbox" id="enable-{{server.0}}" checked>
{% else %}
<label for="enable-{{server.0}}"></label><input type="checkbox" id="enable-{{server.0}}">
{% endif %}
</td>
<td class="checkbox">
{% if server.4 == 1 %}
<label for="typeip-{{server.0}}"></label><input type="checkbox" id="typeip-{{server.0}}" checked>
{% else %}
<label for="typeip-{{server.0}}"></label><input type="checkbox" id="typeip-{{server.0}}">
{% endif %}
</td>
<td class="checkbox">
{% if server.8 == 1 %}
<label for="alert-{{server.0}}"></label><input type="checkbox" id="alert-{{server.0}}" checked>
{% else %}
<label for="alert-{{server.0}}"></label><input type="checkbox" id="alert-{{server.0}}">
{% endif %}
</td>
<td class="checkbox">
{% if server.9 == 1 %}
<label for="metrics-{{server.0}}"></label><input type="checkbox" id="metrics-{{server.0}}" checked>
{% else %}
<label for="metrics-{{server.0}}"></label><input type="checkbox" id="metrics-{{server.0}}">
{% endif %}
</td>
<td class="checkbox">
{% if server.12 == 1 %}
<label for="active-{{server.0}}"></label><input type="checkbox" id="active-{{server.0}}" checked>
{% else %}
<label for="active-{{server.0}}"></label><input type="checkbox" id="active-{{server.0}}">
{% endif %}
</td>
<td>
<select id="slavefor-{{server.0}}">
<option value="0" selected>Not slave</option>
{% for master in masters %}
{% if master.0 == server.6 %}
<option value="{{master.0}}" selected>{{master.1}}</option>
{% else %}
<option value="{{master.0}}">{{master.1}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td>
<div class="controlgroup">
<select id="credentials-{{server.0}}">
<option disabled selected>Choose credentials</option>
{% for ssh in sshs %}
{% if ssh.0 == server.7 %}
<option value="{{ssh.0}}" selected>{{ssh.1}}</option>
{% else %}
<option value="{{ssh.0}}">{{ssh.1}}</option>
{% endif %}
{% endfor %}
</select>
<button onclick="checkSshConnect('{{server.2}}')" title="Check SSH connect to the server {{server.1}}">check</button>
</div>
</td>
<td>
{% if server.11 != "None" %}
<input type="text" id="desc-{{server.0}}" value="{{server.11}}" size="20" class="form-control">
{% else %}
<input type="text" id="desc-{{server.0}}" value="" size="20" class="form-control">
{% endif %}
</td>
<td>
<a class="add" onclick="cloneServer({{server.0}})" id="clone-{{server.0}}" title="Clone {{server.1}}" style="cursor: pointer;"></a>
</td>
<td>
<a class="delete" onclick="confirmDeleteServer({{server.0}})" title="Delete server {{server.1}}" style="cursor: pointer;"></a>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
@ -378,7 +271,7 @@
</tr> </tr>
<tr> <tr>
<td class="padding10 first-collumn"> <td class="padding10 first-collumn">
<input type="text" name="new-ssh-add" id="new-ssh-add" class="form-control"> {{ input('new-ssh-add') }}
</td> </td>
<td> <td>
<label for="new-ssh_enable">Enable SSH key</label><input type="checkbox" id="new-ssh_enable" checked> <label for="new-ssh_enable">Enable SSH key</label><input type="checkbox" id="new-ssh_enable" checked>
@ -392,9 +285,9 @@
</td> </td>
<td style="padding-top: 15px;"> <td style="padding-top: 15px;">
<p> <p>
<input type="text" id="ssh_user" class="form-control" value="{{ssh_user}}"> {{ input('ssh_user', value=ssh_user) }}
</p> </p>
<input type="password" id="ssh_pass" class="form-control" value="{{ssh_pass}}" style="display: none;"> {{ input('ssh_pass', type='password', value=ssh_pass, style="display: none;") }}
<br> <br>
</td> </td>
<td> <td>
@ -486,10 +379,10 @@
</tr> </tr>
<tr> <tr>
<td class="padding10 first-collumn"> <td class="padding10 first-collumn">
<input type="text" name="telegram-token-add" id="telegram-token-add" class="form-control"> {{ input('telegram-token-add') }}
</td> </td>
<td> <td>
<input type="text" id="telegram-chanel-add" class="form-control"> {{ input('telegram-chanel-add') }}
</td> </td>
<td> <td>
<select id="new-telegram-group-add" name="new-telegram-group-add"> <select id="new-telegram-group-add" name="new-telegram-group-add">
@ -576,7 +469,6 @@
<b>{{new_ver}}</b> <b>{{new_ver}}</b>
</td> </td>
<td> <td>
{% if new_ver_without_dots > current_ver_without_dots and new_ver != "Sorry cannot get current version" %} {% if new_ver_without_dots > current_ver_without_dots and new_ver != "Sorry cannot get current version" %}
<a class="ui-button ui-widget ui-corner-all" id="update_haproxy_wi" title="Update HAProxy">Update</a> <a class="ui-button ui-widget ui-corner-all" id="update_haproxy_wi" title="Update HAProxy">Update</a>
{% endif %} {% endif %}
@ -585,11 +477,9 @@
<div class="add-note addName alert-info" style="width: inherit; margin-right: 15px;"> <div class="add-note addName alert-info" style="width: inherit; margin-right: 15px;">
<b style="font-size: 20px; display: block; padding-bottom: 10px;">Note:</b> <b style="font-size: 20px; display: block; padding-bottom: 10px;">Note:</b>
For update you have to use HAProxy-WI repository. How start use repository read <a href="https://haproxy-wi.org/installation.py" title="HAProxy-WI installation" target="_blank">here</a> For update you have to use HAProxy-WI repository. How start use repository read <a href="https://haproxy-wi.org/installation.py" title="HAProxy-WI installation" target="_blank">here</a>
<br /> <br /><br />
<br />
If server uses proxy to connection Internet add proxy settings in yum.conf If server uses proxy to connection Internet add proxy settings in yum.conf
<br /> <br /><br />
<br />
Read more about update in <a href="https://haproxy-wi.org/updates.py" title="Doc" target="_blank">docs</a> Read more about update in <a href="https://haproxy-wi.org/updates.py" title="Doc" target="_blank">docs</a>
and <a href="https://haproxy-wi.org/changelog.py" title="Changelog" target="_blank">changelog</a> and <a href="https://haproxy-wi.org/changelog.py" title="Changelog" target="_blank">changelog</a>
</div> </div>
@ -598,46 +488,7 @@
</div> </div>
<div id="user-add-table" style="display: none;"> <div id="user-add-table" style="display: none;">
<table class="overview"> <table class="overview">
<tr> {% include 'include/admin_add_user.html' %}
<td colspan="2">
<p class="validateTips alert alert-success">Form fields tag "<span class="need-field">*</span>" are required.</p>
</td>
</tr>
<tr>
<td class="padding20">
New user
<span class="need-field">*</span>
</td>
<td>
<input type="text" name="new-username" id="new-username" class="form-control">
{% if ldap_enable == '1' %}
<a href="#" title="Search user in AD" id="search_ldap_user">Search user in AD</a>
{% endif %}
</td>
</tr>
<tr>
<td class="padding20">
Password
<span class="need-field">*</span>
</td>
<td>
<input type="password" name="new-password" id="new-password" class="form-control">
</td>
</tr>
<tr>
<td class="padding20">Active</td>
<td>
<label for="activeuser"></label><input type="checkbox" id="activeuser" checked>
</td>
</tr>
<tr>
<td class="padding20">
Email
</td>
<td>
<input type="text" name="new-email" id="new-email" class="form-control">
</td>
</tr>
<tr> <tr>
<td class="padding20"> <td class="padding20">
Role Role
@ -670,34 +521,19 @@
</div> </div>
<div id="server-add-table" title="View certificate " style="display: none;"> <div id="server-add-table" title="View certificate " style="display: none;">
<table class="overview"> <table class="overview">
<tr> {% include 'include/admin_add_server.html' %}
<td colspan="2">
<p class="validateTips alert alert-success">Form fields tag "<span class="need-field">*</span>" are required.</p>
</td>
</tr>
<tr> <tr>
<td class="padding20"> <td class="padding20">
New hostname Credentials
<span class="need-field">*</span> <span class="need-field">*</span>
</td> </td>
<td> <td>
<input type="text" name="new-server-add" id="new-server-add" class="form-control"> <select id="credentials" required>
</td> <option disabled selected>Choose credentials</option>
<tr> {% for ssh in sshs %}
<td class="padding20"> <option value="{{ssh.0}}">{{ssh.1}}</option>
IP {% endfor %}
<span class="need-field">*</span> </select>
</td>
<td>
<input type="text" name="new-ip" id="new-ip" size="14" class="form-control">
</td>
<tr>
<td class="padding20" title="SSH port">
Port
<span class="need-field">*</span>
</td>
<td>
<input type="text" name="new-port" id="new-port" size=1 class="form-control" value="22">
</td> </td>
</tr> </tr>
<tr> <tr>
@ -714,99 +550,10 @@
</select> </select>
</td> </td>
</tr> </tr>
<tr>
<td class="padding20">Enable</td>
<td>
<label for="enable"></label><input type="checkbox" id="enable" checked>
</td>
</tr>
<tr>
<td class="padding20" title="Vitrual IP, something like VRRP">Virt</td>
<td>
<label for="typeip"></label><input type="checkbox" id="typeip" name="typeip">
</td>
</tr>
<tr>
<td class="padding20" title="Alert if backend change status">Alert</td>
<td>
<label for="alert"></label><input type="checkbox" id="alert">
</td>
</tr>
<tr>
<td class="padding20" title="Enable save and show metrics">Metrics</td>
<td>
<label for="metrics"></label><input type="checkbox" id="metrics">
</td>
</tr>
<tr>
<td class="padding20" title="Keep start HAProxy service if down">Start</td>
<td>
<label for="active"></label><input type="checkbox" id="active">
</td>
</tr>
<tr>
<td class="padding20" title="Actions with master config will automatically apply on slave">Slave for</td>
<td>
<select id="slavefor">
<option value="0" selected>Not slave</option>
{% for master in masters %}
<option value="{{master.0}}">{{master.1}}</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
<td class="padding20">
Credentials
<span class="need-field">*</span>
</td>
<td>
<select id="credentials" required>
<option disabled selected>Choose credentials</option>
{% for ssh in sshs %}
<option value="{{ssh.0}}">{{ssh.1}}</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
<td class="padding20">Description</td>
<td>
<input type="text" id="desc" size="30" class="form-control">
</td>
</tr>
</table> </table>
</div> </div>
<div id="user-change-password-table" style="display: none;"> {% include 'include/change_pass_form.html' %}
<table class="overview">
<tr>
<td colspan="2">
<p class="validateTips alert alert-success">Enter password and confirm</p>
</td>
</tr>
<tr>
<td class="padding20">
Password
</td>
<td>
<input type="password" name="change-password" id="change-password" class="form-control">
</td>
</tr>
<tr>
<td class="padding20">
Confirm password
</td>
<td>
<input type="password" name="change2-password" id="change2-password" class="form-control">
</td>
</tr>
<tr id="missmatchpass" style="display: none;">
<td colspan="2">
<p class="validateTips alert alert-danger" style="margin-top: 10px;">Passwords are mismatched</p>
</td>
</tr>
</table>
</div>
<style> <style>
.ui-selectmenu-button.ui-button { .ui-selectmenu-button.ui-button {
width: 10em; width: 10em;

View File

@ -72,7 +72,7 @@
{% continue %} {% continue %}
{% endif %} {% endif %}
{% if line.startswith('backend') %} {% if line.startswith('backend') %}
</div><span class="param"> {{ line }} </div><span class="param">{{ line }}
{% if role %} {% if role %}
<span class="accordion-link"> <span class="accordion-link">
<a href="/app/sections.py?serv={{serv}}&section={{ line }}">Edit</a> <a href="/app/sections.py?serv={{serv}}&section={{ line }}">Edit</a>
@ -86,7 +86,7 @@
{% continue %} {% continue %}
{% endif %} {% endif %}
{% if line.startswith('cache') %} {% if line.startswith('cache') %}
</div><span class="param"> {{ line }} </div><span class="param">{{ line }}
{% if role %} {% if role %}
<span class="accordion-link"> <span class="accordion-link">
<a href="/app/sections.py?serv={{serv}}&section={{ line }}">Edit</a> <a href="/app/sections.py?serv={{serv}}&section={{ line }}">Edit</a>
@ -96,7 +96,7 @@
{% continue %} {% continue %}
{% endif %} {% endif %}
{% if line.startswith('peers') %} {% if line.startswith('peers') %}
</div><span class="param"> {{ line }} </div><span class="param">{{ line }}
{% if role %} {% if role %}
<span class="accordion-link"> <span class="accordion-link">
<a href="/app/sections.py?serv={{serv}}&section={{ line }}">Edit</a> <a href="/app/sections.py?serv={{serv}}&section={{ line }}">Edit</a>
@ -106,7 +106,7 @@
{% continue %} {% continue %}
{% endif %} {% endif %}
{% if line.startswith('userlist') %} {% if line.startswith('userlist') %}
</div><span class="param"> {{ line }} </div><span class="param">{{ line }}
{% if role %} {% if role %}
<span class="accordion-link"> <span class="accordion-link">
<a href="/app/sections.py?serv={{serv}}&section={{ line }}">Edit</a> <a href="/app/sections.py?serv={{serv}}&section={{ line }}">Edit</a>
@ -142,7 +142,6 @@
</span><br /> </span><br />
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
{% if configver %} {% if configver %}

View File

@ -3,8 +3,8 @@
<td class="padding10 first-collumn"> <td class="padding10 first-collumn">
<input type="text" id="name-{{ group.0 }}" value="{{ group.1 }}" class="form-control"> <input type="text" id="name-{{ group.0 }}" value="{{ group.1 }}" class="form-control">
</td> </td>
<td> <td style="width: 100%;">
<input type="text" id="descript-{{ group.0 }}" value="{{ group.2 }}" class="form-control" size="100"> <input type="text" id="descript-{{ group.0 }}" value="{{ group.2 }}" class="form-control" size="60">
</td> </td>
<td> <td>
<a class="delete" onclick="removeGroup({{ group.0 }})" style="cursor: pointer;"></a> <a class="delete" onclick="removeGroup({{ group.0 }})" style="cursor: pointer;"></a>

View File

@ -1,5 +1,4 @@
{% for server in servers %} {% for server in servers %}
<tr id="server-{{server.0}}" class="newserver"> <tr id="server-{{server.0}}" class="newserver">
<td class="padding10 first-collumn" style="padding-top: 20px;"> <td class="padding10 first-collumn" style="padding-top: 20px;">
<input type="text" id="hostname-{{server.0}}" value="{{server.1}}" class="form-control"> <input type="text" id="hostname-{{server.0}}" value="{{server.1}}" class="form-control">
@ -26,82 +25,7 @@
{% endfor %} {% endfor %}
</select> </select>
{% endif %} {% endif %}
<td> {% include 'include/admin_servers.html' %}
{% if server.5 == 1 %}
<label for="enable-{{server.0}}"></label><input type="checkbox" id="enable-{{server.0}}" checked>
{% else %}
<label for="enable-{{server.0}}"></label><input type="checkbox" id="enable-{{server.0}}">
{% endif %}
</td>
<td>
{% if server.4 == 1 %}
<label for="typeip-{{server.0}}"></label><input type="checkbox" id="typeip-{{server.0}}" checked>
{% else %}
<label for="typeip-{{server.0}}"></label><input type="checkbox" id="typeip-{{server.0}}">
{% endif %}
</td>
<td>
{% if server.8 == 1 %}
<label for="alert-{{server.0}}"></label><input type="checkbox" id="alert-{{server.0}}" checked>
{% else %}
<label for="alert-{{server.0}}"></label><input type="checkbox" id="alert-{{server.0}}">
{% endif %}
</td>
<td>
{% if server.9 == 1 %}
<label for="metrics-{{server.0}}"></label><input type="checkbox" id="metrics-{{server.0}}" checked>
{% else %}
<label for="metrics-{{server.0}}"></label><input type="checkbox" id="metrics-{{server.0}}">
{% endif %}
</td>
<td>
{% if server.11 == 1 %}
<label for="active-{{server.0}}"></label><input type="checkbox" id="active-{{server.0}}" checked>
{% else %}
<label for="active-{{server.0}}"></label><input type="checkbox" id="active-{{server.0}}">
{% endif %}
</td>
<td>
<select id="slavefor-{{server.0}}">
<option value="0" selected>Not slave</option>
{% for master in masters %}
{% if master.0 == server.6 %}
<option value="{{master.0}}" selected>{{master.1}}</option>
{% else %}
<option value="{{master.0}}">{{master.1}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td>
<div class="controlgroup">
<select id="credentials-{{server.0}}">
<option value="0" selected>Choose credentials</option>
{% for ssh in sshs %}
{% if ssh.0 == server.7 %}
<option value="{{ssh.0}}" selected>{{ssh.1}}</option>
{% else %}
<option value="{{ssh.0}}">{{ssh.1}}</option>
{% endif %}
{% endfor %}
</select>
<button onclick="checkSshConnect('{{server.2}}')" title="Check SSH connect to the server {{server.1}}">check</button>
</div>
</td>
<td>
{% if server.11 != "None" %}
<input type="text" id="desc-{{server.0}}" value="{{server.11}}" size="20" class="form-control">
{% else %}
<input type="text" id="desc-{{server.0}}" value="" size="20" class="form-control">
{% endif %}
</td>
<td>
<a class="add" onclick="cloneServer({{server.0}})" id="clone-{{server.0}}" title="Clone {{server.1}}" style="cursor: pointer;"></a>
</td>
<td>
<a class="delete" onclick="removeServer({{server.0}})" title="Delete server {{server.1}}" style="cursor: pointer;"></a>
</td>
</tr>
<script> <script>
$( function() { $( function() {
$("#servergroup-{{ server.0}}" ).selectmenu({ $("#servergroup-{{ server.0}}" ).selectmenu({

View File

@ -1,25 +1,6 @@
{% for user in users %} {% for user in users %}
<tr id="user-{{user.0}}" class="newuser"> <tr id="user-{{user.0}}" class="newuser">
<td class="padding10 first-collumn"> {% include 'include/admin_users.html' %}
<input type="text" id="login-{{user.0}}" value="{{user.1}}" class="form-control">
</td>
<td>
{% if user.6 != 1%}
<span title="Change password" style="cursor: pointer">
<img src="/inc/images/edit.png" alt="Edit" width="15" style="margin-bottom: -3px; padding-left: 15px;" onclick="openChangeUserPasswordDialog('{{user.0}}')" />
</span>
{% endif %}
</td>
<td class="checkbox">
{% if user.7 == 1 %}
<label for="activeuser-{{user.0}}"></label><input type="checkbox" id="activeuser-{{user.0}}" checked>
{% else %}
<label for="activeuser-{{user.0}}"></label><input type="checkbox" id="activeuser-{{user.0}}">
{% endif %}
</td>
<td>
<input type="text" id="email-{{user.0}}" value="{{user.2}}" class="form-control">
</td>
<td> <td>
<select id="role-{{user.0}}" name="role-{{user.0}}"> <select id="role-{{user.0}}" name="role-{{user.0}}">
<option disabled selected>Choose role</option> <option disabled selected>Choose role</option>

View File

@ -14,7 +14,7 @@
<td> <td>
{% if role <= 1 %} {% if role <= 1 %}
<a id="{{ service.1 }}" class="start-waf" title="Start WAF service"> <a id="{{ service.1 }}" class="start-waf" title="Start WAF service">
<img src=/inc/images/start.png alt="start" class="icon" style="margin-bottom: -2px;"> <img src=/inc/images/start.png alt="start" class="icon" style="margin-bottom: -4px;">
</a> </a>
<a id="{{ service.1 }}" class="stop-waf" title="Stop WAF service"> <a id="{{ service.1 }}" class="stop-waf" title="Stop WAF service">
<img src=/inc/images/stop.png alt="start" class="icon" width="17px"> <img src=/inc/images/stop.png alt="start" class="icon" width="17px">

View File

@ -1,3 +1,4 @@
{% from 'include/input_macros.html' import input %}
<form action="diff.py#diff" method="get"> <form action="diff.py#diff" method="get">
<center> <center>
<h4> <h4>
@ -22,9 +23,8 @@
<option value="{{ file }}">{{ file.split('-', maxsplit=1)[1] }}</option> <option value="{{ file }}">{{ file.split('-', maxsplit=1)[1] }}</option>
{% endfor %} {% endfor %}
</select> </select>
{{ input('serv', value=serv) }}
<input type="hidden" value="{{ serv }}" name="serv"> {{ input('open', type='hidden', value='open') }}
<input type="hidden" value="open" name="open">
<a class="ui-button ui-widget ui-corner-all" id="show" title="Compare" onclick="showCompare()">Show</a> <a class="ui-button ui-widget ui-corner-all" id="show" title="Compare" onclick="showCompare()">Show</a>
</p> </p>
</center> </center>

View File

@ -52,19 +52,19 @@
<nav id="menu"> <nav id="menu">
<ul class="menu"> <ul class="menu">
{% if user %} {% if user %}
<li><a href=/app/overview.py title="Server and service status" class="overview-link">Overview</a></li> <li><a href="/app/overview.py" title="Server and service status" class="overview-link">Overview</a></li>
<li class="p_menu"><a title="Statistics, monitoring and logs" class="stats">Monitoring</a> <li class="p_menu"><a title="Statistics, monitoring and logs" class="stats">Monitoring</a>
<ul class="v_menu"> <ul class="v_menu">
<li><a href=/app/viewsttats.py title="Show stats" class="stats head-submenu">Stats</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/logs.py" title="View logs" class="logs head-submenu"> Logs</a></li>
<li><a href=/app/edit.py title="Runtime API" class="runtime head-submenu">Runtime API</a></li> <li><a href="/app/edit.py" title="Runtime API" class="runtime head-submenu">Runtime API</a></li>
<li><a href=/app/metrics.py title="Metrics" class="metrics head-submenu">Metrics</a></li> <li><a href="/app/metrics.py" title="Metrics" class="metrics head-submenu">Metrics</a></li>
</ul> </ul>
</li> </li>
<li class="p_menu"><a title="Actions with Haproxy configs" class="config-show">Haproxy</a> <li class="p_menu"><a title="Actions with Haproxy configs" class="config-show">Haproxy</a>
<ul class="v_menu"> <ul class="v_menu">
<li><a href=/app/hapservers.py title="Working with Haproxy Configs" class="overview-link head-submenu">Overview</a> </li> <li><a href="/app/hapservers.py" title="Working with Haproxy Configs" class="overview-link head-submenu">Overview</a> </li>
<li><a href=/app/config.py title="Working with HAProxy configs" class="edit head-submenu">Configs</a></li> <li><a href="/app/config.py" title="Working with HAProxy configs" class="edit head-submenu">Configs</a></li>
{% if role <= 2 %} {% if role <= 2 %}
<li><a href="/app/add.py#proxy" title="Add proxy" class="add head-submenu" id="add1">Add proxy</a></li> <li><a href="/app/add.py#proxy" title="Add proxy" class="add head-submenu" id="add1">Add proxy</a></li>
<li><a href="/app/versions.py" title="Actions with configs versions" class="version head-submenu">Versions</a></li> <li><a href="/app/versions.py" title="Actions with configs versions" class="version head-submenu">Versions</a></li>
@ -82,8 +82,8 @@
<li class="p_menu"> <li class="p_menu">
<a title="Keepalived" class="ha">Keepalived</a> <a title="Keepalived" class="ha">Keepalived</a>
<ul class="v_menu"> <ul class="v_menu">
<li><a href=/app/ha.py title="Create HA cluster" class="keepalived head-submenu">HA</a></li> <li><a href="/app/ha.py" title="Create HA cluster" class="keepalived head-submenu">HA</a></li>
<li><a href=/app/keepalivedconfig.py title="Edit keepalived config" class="edit head-submenu">Edit config</a></li> <li><a href="/app/keepalivedconfig.py" title="Edit keepalived config" class="edit head-submenu">Edit config</a></li>
</ul> </ul>
</li> </li>
<li class="p_menu"> <li class="p_menu">
@ -123,11 +123,7 @@
{% if h2 %} {% if h2 %}
<h2> <h2>
{{title}} {{title}}
{% if user %} {% include 'include/login.html' %}
<a href=/app/login.py?logout=logout title="Logout, user name: {{ user }}" class="login"> Logout</a>
{% else %}
<a href=/app/login.py title="Login" class="login"> Login</a>
{% endif %}
{% if autorefresh %} {% if autorefresh %}
<span class="auto-refresh"> <span class="auto-refresh">
<a onclick="pauseAutoRefresh()" class="auto-refresh-pause" style="display: none; margin-top: 4px;"></a> <a onclick="pauseAutoRefresh()" class="auto-refresh-pause" style="display: none; margin-top: 4px;"></a>
@ -212,7 +208,6 @@
{% block content %}{% endblock %} {% block content %}{% endblock %}
<div id="ajax-compare"></div> <div id="ajax-compare"></div>
<div id="ajax"></div> <div id="ajax"></div>
</div> </div>
<div id="show-updates" style="display: none;"> <div id="show-updates" style="display: none;">
<div> <div>

View File

@ -46,13 +46,7 @@
</p> </p>
{% if not aftersave %} {% if not aftersave %}
{% if stderr or error %} {% if stderr or error %}
<div class="alert alert-danger" style="margin-bottom: 10px;"> {% include 'include/errors.html' %}
Some errors:
<br>
<br>
{{stderr}}
{{error}}
</div>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if config %} {% if config %}
@ -79,15 +73,9 @@
{% if aftersave %} {% if aftersave %}
<div class="alert alert-info">New config was saved as: {{ cfg }} </div> <div class="alert alert-info">New config was saved as: {{ cfg }} </div>
{% if stderr or error %} {% if stderr or error %}
<div class="alert alert-danger"> {% include 'include/errors.html' %}
Some errors:
<br>
<br>
{{stderr}}
{{error}}
</div>
{% else %} {% else %}
<div class="alert alert-success">Config ok</div> <div class="alert alert-success">Config is ok</div>
<a href="viewsttats.py?serv={{ serv }}" target="_blank" title="View stats">Go to view stats</a> <a href="viewsttats.py?serv={{ serv }}" target="_blank" title="View stats">Go to view stats</a>
{% endif %} {% endif %}
<script>window.history.pushState("Config", "Config", cur_url[0])</script> <script>window.history.pushState("Config", "Config", cur_url[0])</script>

View File

@ -5,35 +5,18 @@
<p> <p>
<form action="{{ action }}" method="get"> <form action="{{ action }}" method="get">
<a class="ui-button ui-widget ui-corner-all" title="Return back" onclick="history.back()">Back</a> <a class="ui-button ui-widget ui-corner-all" title="Return back" onclick="history.back()">Back</a>
<select autofocus required name="serv" id="{{ select_id }}"> {% include 'include/select.html' %}
<option disabled>Choose server</option>
{% for select in selects %}
{% if select.2 == serv %}
<option value="{{ select.2 }}" selected>{{ select.1 }}</option>
{% else %}
<option value="{{ select.2 }}">{{ select.1 }}</option>
{% endif %}
{% endfor %}
</select>
<button type="submit" value="open" name="open" class="btn btn-default">Open</button> <button type="submit" value="open" name="open" class="btn btn-default">Open</button>
</form> </form>
</p> </p>
{% if not aftersave %} {% if not aftersave %}
{% if stderr or error %} {% if stderr or error %}
<div class="alert alert-danger" style="margin-bottom: 10px;"> {% include 'include/errors.html' %}
Some errors:
<br>
<br>
{{stderr}}
{{error}}
</div>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if open %} {% if open %}
<center> <center>
<h4>Choose old version</h4> <h4>Choose old version</h4>
<form action="configver.py#conf" method="get">
<p> <p>
<select autofocus required name="configver" id="configver"> <select autofocus required name="configver" id="configver">
<option disabled selected>Choose version</option> <option disabled selected>Choose version</option>
@ -49,26 +32,17 @@
<input type="hidden" value="open" name="open"> <input type="hidden" value="open" name="open">
<a class="ui-button ui-widget ui-corner-all" id="show" title="Enter" onclick="showUploadConfig()">Select</a> <a class="ui-button ui-widget ui-corner-all" id="show" title="Enter" onclick="showUploadConfig()">Select</a>
</p> </p>
</form>
</center> </center>
{% endif %} {% endif %}
{% if aftersave %} {% if aftersave %}
<div class="alert alert-info">Uploaded old config ver: {{ configver }} </div> <div class="alert alert-info">Was uploaded old version of config: {{ configver }} </div>
{% if stderr or error %} {% if stderr or error %}
<div class="alert alert-danger"> {% include 'include/errors.html' %}
Some errors:
<br>
<br>
{{stderr}}
{{error}}
</div>
{% else %} {% else %}
<div class="alert alert-success">Config ok</div> <div class="alert alert-success">Config is ok</div>
<a href="viewsttats.py?serv={{ serv }}" target="_blank" title="View stats">Go to view stats</a> <a href="viewsttats.py?serv={{ serv }}" target="_blank" title="View stats">Go to view stats</a>
<script>window.history.pushState("Map", "Map", cur_url[0])</script>
{% endif %} {% endif %}
<script>window.history.pushState("Config", "Config", cur_url[0])</script>
{% endif %} {% endif %}
</center> </center>
{% if aftersave != 1 %} {% if aftersave != 1 %}

View File

@ -5,16 +5,7 @@
<p> <p>
<form action="{{ action }}" method="get"> <form action="{{ action }}" method="get">
<a class="ui-button ui-widget ui-corner-all" title="Return back" onclick="history.back()">Back</a> <a class="ui-button ui-widget ui-corner-all" title="Return back" onclick="history.back()">Back</a>
<select autofocus required name="serv" id="{{ select_id }}"> {% include 'include/select.html' %}
<option disabled>Choose server</option>
{% for select in selects %}
{% if select.2 == serv %}
<option value="{{ select.2 }}" selected>{{ select.1 }}</option>
{% else %}
<option value="{{ select.2 }}">{{ select.1 }}</option>
{% endif %}
{% endfor %}
</select>
<button type="submit" value="open" name="open" class="btn btn-default">Open</button> <button type="submit" value="open" name="open" class="btn btn-default">Open</button>
</form> </form>
{% if not aftersave and not open %} {% if not aftersave and not open %}
@ -43,17 +34,11 @@
</p> </p>
</form> </form>
</center> </center>
{% endif %} {% endif %}
{% if aftersave %} {% if aftersave %}
<div class="alert alert-info"><b>The following files were deleted:</b><br /> </div> <div class="alert alert-info"><b>The following files were deleted:</b><br /> </div>
{% if stderr %} {% if stderr %}
<div class="alert alert-danger"> {% include 'include/errors.html' %}
Some errors:
<br>
<br>
{{stderr}}
</div>
{% else %} {% else %}
<div class="alert alert-success"> <div class="alert alert-success">
{% for f in file %} {% for f in file %}

View File

@ -1,5 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
{% from 'include/input_macros.html' import input, checkbox %}
<script src="/inc/users.js"></script> <script src="/inc/users.js"></script>
<table class="overview"> <table class="overview">
<caption><h3>Create new HA cluster</h3></caption> <caption><h3>Create new HA cluster</h3></caption>
@ -29,18 +30,10 @@
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
<td> <td>{{ input('interface') }}</td>
<input type="text" id="interface" class="form-control"> <td>{{ input('vrrp-ip') }}</td>
</td> <td>{{ checkbox('hap') }}</td>
<td> <td>{{ checkbox('syn_flood', checked='checked') }}</td>
<input type="text" id="vrrp-ip" class="form-control">
</td>
<td>
<label for="hap"></label><input type="checkbox" id="hap">
</td>
<td>
<label for="syn_flood" title="Enable SYN flood protect"><input type="checkbox" id="syn_flood" checked>
</td>
<td> <td>
<a class="ui-button ui-widget ui-corner-all" id="create" title="Create HA configuration">Create</a> <a class="ui-button ui-widget ui-corner-all" id="create" title="Create HA configuration">Create</a>
</td> </td>
@ -75,15 +68,9 @@
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
<td> <td>{{ input('interface-add') }}</td>
<input type="text" id="interface-add" class="form-control"> <td>{{ input('vrrp-ip-add') }}</td>
</td> <td>{{ checkbox('kp') }}</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></td> <td></td>
<td> <td>
<a class="ui-button ui-widget ui-corner-all" id="add-vrrp" title="Add HA configuration">Add</a> <a class="ui-button ui-widget ui-corner-all" id="add-vrrp" title="Add HA configuration">Add</a>

View File

@ -1,7 +1,31 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
{% if serv %}
<style>
@media (max-width: 1280px) {
.div-pannel {
height: 430px !important;
}
}
</style>
{% endif %}
<div id="up-pannel"> <div id="up-pannel">
{% for s in servers %} {% for s in servers %}
{% if serv %}
<link href="/inc/chart.min.css" rel="stylesheet">
<script src="/inc/metrics.js"></script>
<script src="/inc/chart.min.js"></script>
<script>
function showMetrics() {
{% for s in servers %}
getChartData('{{s.2}}')
getWafChartData('{{s.2}}')
{% endfor %}
showOverviewServer('{{s.1}}', '{{s.2}}', '{{s.0}}');
}
showMetrics();
</script>
{% endif %}
<div class="div-pannel" id="div-pannel-{{s.0}}"> <div class="div-pannel" id="div-pannel-{{s.0}}">
<div id="div-server-{{s.0}}" class="div-server"> <div id="div-server-{{s.0}}" class="div-server">
<div class="server-name"> <div class="server-name">
@ -10,9 +34,11 @@
{% else %} {% else %}
<span class="serverDown server-status" title="HAProxy is down"></span> <span class="serverDown server-status" title="HAProxy is down"></span>
{% endif %} {% endif %}
<span title="Show info about {{s.2}}" onclick="showOverviewServer('{{s.1}}', '{{s.2}}', '{{s.0}}')" style="cursor: pointer;"> {% if not serv %}
<a href="/app/hapservers.py?serv={{s.2}}" title="More about {{s.1}}" style="color: #5d9ceb">{{s.1}}</a>
{% else %}
{{s.1}} {{s.1}}
</span> {% endif %}
{% if s.6|int() >= 1 %} {% if s.6|int() >= 1 %}
<img <img
{% if keep_alive|int() >= 1 %} {% if keep_alive|int() >= 1 %}
@ -24,14 +50,14 @@
{% endif %} {% endif %}
{% if role <= 1 %} {% if role <= 1 %}
<span class="server-action"> <span class="server-action">
<a id="{{ s.2 }}" class="start" title="Start HAProxy service"> <a id="start-{{ s.2 }}" class="start" title="Start HAProxy service">
<img src=/inc/images/start.png alt="start" class="icon" style="margin-bottom: -2px;" onclick="confirmAjaxAction('start', 'hap', '{{s.2}}')"> <img src=/inc/images/start.png alt="start" class="icon-hapservs" style="margin-bottom: -2px;" onclick="confirmAjaxAction('start', 'hap', '{{s.2}}')">
</a> </a>
<a id="{{ s.2 }}" class="stop" title="Stop HAProxy service"> <a id="stop-{{ s.2 }}" class="stop" title="Stop HAProxy service">
<img src=/inc/images/stop.png alt="stop" class="icon" width="17px" onclick="confirmAjaxAction('stop', 'hap', '{{s.2}}')"> <img src=/inc/images/stop.png alt="stop" class="icon-hapservs" width="17px" onclick="confirmAjaxAction('stop', 'hap', '{{s.2}}')">
</a> </a>
<a id="{{ s.2 }}" class="restart" title="Restart HAProxy service" onclick="confirmAjaxAction('restart', 'hap', '{{s.2}}')"> <a id="restart-{{ s.2 }}" class="restart" title="Restart HAProxy service" onclick="confirmAjaxAction('restart', 'hap', '{{s.2}}')">
<img src=/inc/images/update.png alt="restart" class="icon"> <img src=/inc/images/update.png alt="restart" class="icon-hapservs">
</a> </a>
</span> </span>
{% endif %} {% endif %}
@ -68,9 +94,21 @@
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
{% if serv %}
<div id="refresh" style="text-align: right;margin-right: 105px;clear: both;display: block;padding-top: 20px;margin-bottom: -25px;" title="Refresh metrics" onclick="showMetrics()">
<img src="/inc/images/update.png" alt="Refresh" class="icon">
</div>
{% for s in servers %}
<div class="chart-container" style="display: block; width: 46%;">
<canvas id="{{s.2}}" role="img"></canvas>
</div>
<div class="chart-container" style="display: block; width: 46%;">
<canvas id="s_{{s.2}}" role="img"></canvas>
</div>
{% endfor %}
{% endif %}
<div id="dialog-confirm" style="display: none;"> <div id="dialog-confirm" style="display: none;">
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:3px 12px 20px 0;"></span>Are you sure?</p> <p><span class="ui-icon ui-icon-alert" style="float:left; margin:3px 12px 20px 0;"></span>Are you sure?</p>
</div> </div>
<script src="/inc/overview.js"></script> <script src="/inc/overview.js"></script>
{% endblock %} {% endblock %}

View File

@ -0,0 +1,135 @@
<div id="create" style="height: 95%;">
<div id="left-collumn">
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create Listen" class="redirectListen span-link">Create Listen</span>
</div>
<div class="server-desc">
A "listen" section defines a complete proxy with its frontend and backend parts combined in one section. It is generally useful for TCP-only traffic.
</div>
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create HTTP Listen" class="redirectListen span-link" id="create-http-listen">Create HTTP Listen</span>
</div>
<div class="server-desc">
Create HTTP proxy
</div>
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create SSL Listen" class="redirectListen span-link" id="create-ssl-listen">Create SSL Listen</span>
</div>
<div class="server-desc">
Create HTTPS Proxy with the SSL termination on HAProxy and SSL offload.
HAProxy will send to backends HTTP traffic. You need have <span title="Upload SSL" class="redirectSsl span-link" style="color: #5d9ceb">uploaded a PEM certificat</span>
</div>
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create SSL Listen" class="redirectListen span-link" id="create-https-listen">Create HTTPS Listen</span>
</div>
<div class="server-desc">
Create HTTPS Proxy without the SSL termination on HAProxy and SSL offload. HAProxy will send to backends HTTPS traffic
</div>
</div>
</div>
</div>
<div id="middle-collumn">
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create Frontend" class="redirectFrontend span-link">Create Frontend</span>
</div>
<div class="server-desc">
A "frontend" section describes a set of listening sockets accepting client connections.
And forwards them to backend
<br />
</div>
</div>
</div>
<div class="div-server">
<div class="server-name">
<span title="Create HTTP Frontend" class="redirectListen span-link" id="create-http-frontend">Create HTTP Frontend</span>
</div>
<div class="server-desc">
Create HTTP Frontend
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create SSL Frontend" class="redirectListen span-link" id="create-ssl-frontend">Create SSL Frontend</span>
</div>
<div class="server-desc">
Create HTTPS Frontend with the SSL termination on HAProxy and SSL offload. HAProxy will send to backends HTTP traffic. You need have <span title="Upload SSL" class="redirectSsl span-link" style="color: #5d9ceb">uploaded a PEM certificat</span>
</div>
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create HTTPS Frontend" class="redirectListen span-link" id="create-https-frontend">Create HTTPS Frontend</span>
</div>
<div class="server-desc">
Create HTTPS Frontend without the SSL termination on HAProxy and SSL offload. HAProxy will send to backends HTTPS traffic
</div>
</div>
</div>
</div>
<div id="right-collumn">
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create Backend" class="redirectBackend span-link">Create Backend</span>
</div>
<div class="server-desc">
A "backend" section describes a set of servers to which the proxy will connect to forward incoming connections.
<br />
<br />
</div>
</div>
</div>
<div class="div-server">
<div class="server-name">
<span title="Create SSL Backend" class="redirectListen span-link" id="create-http-backend">Create HTTP Backend</span>
</div>
<div class="server-desc">
Create HTTP Backend
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create HTTPS Backend" class="redirectListen span-link" id="create-ssl-backend">Create SSL Backend</span>
</div>
<div class="server-desc">
Create HTTPS Backend with the SSL termination on HAProxy and SSL offload. HAProxy will send to backends HTTP traffic. You need have <span title="Upload SSL" class="redirectSsl span-link" style="color: #5d9ceb">uploaded a PEM certificat</span>
</div>
</div>
</div>
<div class="div-pannel">
<div class="div-server">
<div class="server-name">
<span title="Create SSL Backend" class="redirectListen span-link" id="create-https-backend">Create HTTPS Backend</span>
</div>
<div class="server-desc">
Create HTTPS Backend without the SSL termination on HAProxy and SSL offload. HAProxy will send to backends HTTPS traffic
</div>
</div>
</div>
</div>
{% if add %}
<div class="alert alert-success" style="margin-left: 20px; clear: both;">
<h3>{{ add }} was success added</h3>
{{ conf_add }}
</div>
{% endif %}
</div>

View File

@ -0,0 +1,13 @@
<span name="add_servers">
<input name="servers" required title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
<input name="server_port" required title="Backend IP" size=1 placeholder="yyy" class="form-control">
<br />
<input name="servers" title="Backend port" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
<input name="server_port" title="Backend port" size=1 placeholder="yyy" class="form-control">
<br />
<input name="servers" title="Backend port" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
<input name="server_port" title="Backend port" size=1 placeholder="yyy" class="form-control">
</span>
<span>
<a class="add-server" name="add-server-input" title="Add backend server" style="cursor: pointer;"></a>
</span>

View File

@ -0,0 +1,62 @@
{% from 'include/input_macros.html' import input, checkbox %}
<tr>
<td colspan="2">
<p class="validateTips alert alert-success">
Form fields tag "<span class="need-field">*</span>" are required.
</p>
</td>
</tr>
<tr>
<td class="padding20">
New hostname
<span class="need-field">*</span>
</td>
<td>{{ input('new-server-add') }}</td>
<tr>
<td class="padding20">
IP
<span class="need-field">*</span>
</td>
<td>{{ input('new-ip', size='14') }}</td>
<tr>
<td class="padding20" title="SSH port">
Port
<span class="need-field">*</span>
</td>
<td>{{ input('new-port', value='22', size='1') }}</td>
</tr>
<tr>
<td class="padding20">Enable</td>
<td>{{ checkbox('enable', checked='checked') }}</td>
</tr>
<tr>
<td class="padding20" title="Vitrual IP, something like VRRP">Virt</td>
<td>{{ checkbox('typeip') }}</td>
</tr>
<tr>
<td class="padding20" title="Alert if backend change status">Alert</td>
<td>{{ checkbox('alert') }} </td>
</tr>
<tr>
<td class="padding20" title="Enable save and show metrics">Metrics</td>
<td>{{ checkbox('metrics') }}</td>
</tr>
<tr>
<td class="padding20" title="Keep start HAProxy service if down">Start</td>
<td>{{ checkbox('active') }}</td>
</tr>
<tr>
<td class="padding20" title="Actions with master config will automatically apply on slave">Slave for</td>
<td>
<select id="slavefor">
<option value="0" selected>Not slave</option>
{% for master in masters %}
<option value="{{master.0}}">{{master.1}}</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
<td class="padding20">Description</td>
<td>{{ input('desc', size='30') }}</td>
</tr>

View File

@ -0,0 +1,38 @@
{% from 'include/input_macros.html' import input, checkbox %}
<tr>
<td colspan="2">
<p class="validateTips alert alert-success">
Form fields tag "<span class="need-field">*</span>" are required.
</p>
</td>
</tr>
<tr>
<td class="padding20">
New user
<span class="need-field">*</span>
</td>
<td>
{{ input('new-username') }}
{% if ldap_enable == '1' %}
<a href="#" title="Search user in AD" id="search_ldap_user">Search user in AD</a>
{% endif %}
</td>
</tr>
<tr>
<td class="padding20">
Password
<span class="need-field">*</span>
</td>
<td>{{ input('new-password', type='password') }}</td>
</tr>
<tr>
<td class="padding20">Active</td>
<td>{{ checkbox('activeuser', checked='checked') }}</td>
</tr>
<tr>
<td class="padding20">
Email
<span class="need-field">*</span>
</td>
<td>{{ input('new-email') }}</td>
</tr>

View File

@ -0,0 +1,82 @@
{% from 'include/input_macros.html' import input, checkbox %}
<td class="checkbox">
{% set id = 'enable-' + server.0|string() %}
{% if server.5 == 1 %}
{{ checkbox(id, checked='checked') }}
{% else %}
{{ checkbox(id) }}
{% endif %}
</td>
<td class="checkbox">
{% set id = 'typeip-' + server.0|string() %}
{% if server.4 == 1 %}
{{ checkbox(id, checked='checked') }}
{% else %}
{{ checkbox(id) }}
{% endif %}
</td>
<td class="checkbox">
{% set id = 'alert-' + server.0|string() %}
{% if server.8 == 1 %}
{{ checkbox(id, checked='checked') }}
{% else %}
{{ checkbox(id) }}
{% endif %}
</td>
<td class="checkbox">
{% set id = 'metrics-' + server.0|string() %}
{% if server.9 == 1 %}
{{ checkbox(id, checked='checked') }}
{% else %}
{{ checkbox(id) }}
{% endif %}
</td>
<td class="checkbox">
{% set id = 'active-' + server.0|string() %}
{% if server.12 == 1 %}
{{ checkbox(id, checked='checked') }}
{% else %}
{{ checkbox(id) }}
{% endif %}
</td>
<td>
<select id="slavefor-{{server.0}}">
<option value="0" selected>Not slave</option>
{% for master in masters %}
{% if master.0 == server.6 %}
<option value="{{master.0}}" selected>{{master.1}}</option>
{% else %}
<option value="{{master.0}}">{{master.1}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td>
<div class="controlgroup">
<select id="credentials-{{server.0}}">
<option disabled selected>Choose credentials</option>
{% for ssh in sshs %}
{% if ssh.0 == server.7 %}
<option value="{{ssh.0}}" selected>{{ssh.1}}</option>
{% else %}
<option value="{{ssh.0}}">{{ssh.1}}</option>
{% endif %}
{% endfor %}
</select>
<button onclick="checkSshConnect('{{server.2}}')" title="Check SSH connect to the server {{server.1}}">check</button>
</div>
</td>
<td>
{% set id = 'desc-' + server.0|string() %}
{% if server.11 != "None" %}
{{ input(id, value=server.11, size='20') }}
{% else %}
{{ input(id, size='20') }}
{% endif %}
</td>
<td>
<a class="add" onclick="cloneServer({{server.0}})" id="clone-{{server.0}}" title="Clone {{server.1}}" style="cursor: pointer;"></a>
</td>
<td>
<a class="delete" onclick="confirmDeleteServer({{server.0}})" title="Delete server {{server.1}}" style="cursor: pointer;"></a>
</td>

View File

@ -0,0 +1,28 @@
<td class="padding10 first-collumn">
{% if user.6 == 1%}
<input type="text" id="login-{{user.0}}" value="{{user.1}}" class="form-control" readonly>
{% else %}
<input type="text" id="login-{{user.0}}" value="{{user.1}}" class="form-control">
{% endif %}
</td>
<td>
{% if user.6 != 1%}
<span title="Change password" style="cursor: pointer">
<img src="/inc/images/edit.png" alt="Edit" width="15" style="margin-bottom: -3px; padding-left: 15px;" onclick="openChangeUserPasswordDialog('{{user.0}}')" />
</span>
{% endif %}
</td>
<td class="checkbox">
{% if user.7 == 1 %}
<label for="activeuser-{{user.0}}"></label><input type="checkbox" id="activeuser-{{user.0}}" checked>
{% else %}
<label for="activeuser-{{user.0}}"></label><input type="checkbox" id="activeuser-{{user.0}}">
{% endif %}
</td>
<td>
{% if user.6 == 1%}
<input type="text" id="email-{{user.0}}" value="{{user.2}}" class="form-control" readonly>
{% else %}
<input type="text" id="email-{{user.0}}" value="{{user.2}}" class="form-control">
{% endif %}
</td>

View File

@ -0,0 +1,32 @@
{% from 'include/input_macros.html' import input, checkbox %}
<td class="padding10 first-collumn">
{% set login_id = 'login-' + user.0|string() %}
{% if user.6 == 1%}
{{ input(login_id, value=user.1, readonly='readonly') }}
{% else %}
{{ input(login_id, value=user.1) }}
{% endif %}
</td>
<td>
{% if user.6 != 1%}
<span title="Change password" style="cursor: pointer">
<img src="/inc/images/edit.png" alt="Edit" width="15" style="margin-bottom: -3px; padding-left: 15px;" onclick="openChangeUserPasswordDialog('{{user.0}}')" />
</span>
{% endif %}
</td>
<td class="checkbox">
{% set activeuser_id = 'activeuser-' + user.0|string() %}
{% if user.7 == 1 %}
{{ checkbox(activeuser_id, checked='checked') }}
{% else %}
{{ checkbox(activeuser_id) }}
{% endif %}
</td>
<td>
{% set email_id = 'email-' + user.0|string() %}
{% if user.6 == 1%}
{{ input(email_id, value=user.2, readonly='readonly') }}
{% else %}
{{ input(email_id, value=user.2) }}
{% endif %}
</td>

View File

@ -0,0 +1,23 @@
{% from 'include/input_macros.html' import input %}
<div id="user-change-password-table" style="display: none;">
<table class="overview">
<tr>
<td colspan="2">
<p class="validateTips alert alert-success">Enter password and confirm</p>
</td>
</tr>
<tr>
<td class="padding20">Password</td>
<td>{{ input('change-password', type='password') }}</td>
</tr>
<tr>
<td class="padding20">Confirm password</td>
<td>{{ input('change2-password', type='password') }}</td>
</tr>
<tr id="missmatchpass" style="display: none;">
<td colspan="2">
<p class="validateTips alert alert-danger" style="margin-top: 10px;">Passwords are mismatched</p>
</td>
</tr>
</table>
</div>

View File

@ -0,0 +1,3 @@
<div id="dialog-confirm" title="Are you sure you want to delete?" style="display: none;">
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:3px 12px 20px 0;"></span>Deleting irreversibly all data will be lost?</p>
</div>

View File

@ -0,0 +1,6 @@
<div class="alert alert-danger" style="margin-bottom: 10px;">
Some errors:
<br> <br>
{{stderr}}
{{error}}
</div>

View File

@ -0,0 +1,31 @@
{% macro input(id, name='', value='', type='text', size='', readonly='', required='', placeholder='', title='', class='form-control', style='') -%}
{% if name == '' %}
{% set name = id %}
{% endif %}
<input type="{{ type }}" name="{{name}}" value="{{ value|e }}" id="{{ id }}" size="{{size}}" style="{{style}}" {{readonly}} {{required}} placeholder="{{placeholder}}" title="{{title}}" class="{{class}}">
{%- endmacro %}
{%- macro checkbox(id, name='', checked='', title='', value='', desc='') -%}
{% if name == '' %}
{% set name = id %}
{% endif %}
<label for="{{id}}" title="{{title}}">{{desc}}</label><input name="{{name}}" type="checkbox" id="{{id}}" value="{{value|e}}" {{checked}}>
{%- endmacro %}
{%- macro select(id, values, name='', required='', first='', class='', selected='') -%}
{% if name == '' %}
{% set name = id %}
{% endif %}
<select required="{{required}}" name="{{name}}" id="{{id}}" class="{{class}}">
{% if first %}
<option disabled selected>{{first}}</option>
{% endif %}
{% for v, des in values|dictsort(false, 'value') %}
{% if v == selected %}
<option value="{{v}}" selected>{{des}}</option>
{% else %}
<option value="{{v}}">{{des}}</option>
{% endif %}
{% endfor %}
</select>
{%- endmacro %}

View File

@ -0,0 +1,5 @@
{% if user %}
<a href=/app/login.py?logout=logout title="Logout, user name: {{ user }}" class="login"> Logout</a>
{% else %}
<a href=/app/login.py title="Login" class="login"> Login</a>
{% endif %}

View File

@ -0,0 +1,11 @@
<select autofocus required name="serv" id="{{ select_id }}">
<option disabled>Choose server</option>
{% for select in selects %}
{% if select.2 == serv %}
<option value="{{ select.2 }}" selected>{{ select.1 }}</option>
{% else %}
<option value="{{ select.2 }}">{{ select.1 }}</option>
{% endif %}
{% endfor %}
</select>

View File

@ -1,5 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
{% from 'include/input_macros.html' import input %}
<table class="overview"> <table class="overview">
<tr class="overviewHead"> <tr class="overviewHead">
<td class="padding10 first-collumn">New black list</th> <td class="padding10 first-collumn">New black list</th>
@ -9,7 +10,7 @@
</tr> </tr>
<tr> <tr>
<td class="padding10 first-collumn" style="width: 25%;"> <td class="padding10 first-collumn" style="width: 25%;">
Name: <input type="text" id="new_blacklist_name" class="form-control"> Name: {{ input('new_blacklist_name') }}
<button onclick="createList('black')">Create</button> <button onclick="createList('black')">Create</button>
</td> </td>
<td style="width: 30%;"> <td style="width: 30%;">
@ -18,7 +19,7 @@
{% endfor %} {% endfor %}
</td> </td>
<td class="padding10 first-collumn" style="width: 25%;"> <td class="padding10 first-collumn" style="width: 25%;">
Name: <input type="text" id="new_whitelist_name" class="form-control"> Name: {{ input('new_whitelist_name') }}
<button onclick="createList( 'white')">Create</button> <button onclick="createList( 'white')">Create</button>
</td> </td>
<td style="width: 30%;"> <td style="width: 30%;">
@ -27,7 +28,7 @@
{% endfor %} {% endfor %}
</td> </td>
</tr> </tr>
<input type="hidden" id="group" value="{{group}}"> {{ input('group', value=group, type='hidden') }}
</table> </table>
<div class="add-note addName alert-info" style="width: inherit; margin-right: 15px;"> <div class="add-note addName alert-info" style="width: inherit; margin-right: 15px;">
In this section you can create and edit black and white lists. And after use them in the HAProxy configs or in the "Add proxy" pages In this section you can create and edit black and white lists. And after use them in the HAProxy configs or in the "Add proxy" pages
@ -35,6 +36,6 @@
<div id="ajax"></div> <div id="ajax"></div>
<div id="dialog-confirm" title="View certificate " style="display: none;"> <div id="dialog-confirm" title="View certificate " style="display: none;">
<span><b>Note:</b> Each new address should be specified from a new line</span> <span><b>Note:</b> Each new address should be specified from a new line</span>
<textarea id="edit_lists" cols=95 rows=20></textarea> <textarea id="edit_lists" style="width: 100%" rows=20></textarea>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -1,5 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
{% from 'include/input_macros.html' import input %}
<style> <style>
body, .container { body, .container {
background-color: #fff; background-color: #fff;
@ -12,14 +13,6 @@ body, .container {
width: 100% !important; width: 100% !important;
max-width: 100% !important; max-width: 100% !important;
} }
.form-control {
text-align: center;
background-color: #fff;
padding: 10px;
width: 220px;
background-size: 0 !important;
border: 0 !important;
}
#enter { #enter {
width: 220px !important; width: 220px !important;
padding: 10px !important; padding: 10px !important;
@ -32,15 +25,14 @@ body, .container {
{{error}} {{error}}
{{db_create}} {{db_create}}
<div id="login-form" style="padding-top: 40px; padding-bottom: 50px; height: 250px; color: #000;"> <div id="login-form" style="padding-top: 40px; padding-bottom: 50px; height: 250px; color: #000;">
<!-- <span style="font-size: 50px; font-weight: bold; color: #fff;">HAProxy-WI</span> -->
<span id="logo_span"> <span id="logo_span">
<img src="/inc/images/logo_login.png" width="330"> <img src="/inc/images/logo_login.png" width="330">
</span> </span>
<form name="auth" id="auth" action="login.py" class="form-horizontal" method="post" style="margin-top: 40px;left: 0;float: left;margin-left: 93px;"> <form name="auth" id="auth" action="login.py" class="form-horizontal" method="post" style="margin-top: 40px;left: 0;float: left;margin-left: 93px;">
<br> <br>
<input type="text" name="login" id="login" required class="form-control" placeholder="Login"><br /><br /> {{ input('login', class='form-login', placeholder='Login', required='required') }}<br /><br />
<input type="password" name="pass" id="pass" required class="form-control" placeholder="Password"><br /><br /> {{ input('pass', type='password', class='form-login', placeholder='Password', required='required') }}<br /><br />
<input type="hidden" value="{{reff}}" name="ref" id="ref"> {{ input('ref', type='hidden', value=ref) }}
<button type="submit" name="Login" value="Enter" id="enter">Login</button> <button type="submit" name="Login" value="Enter" id="enter">Login</button>
</form> </form>
<div class="alert alert-danger wrong-login"> <div class="alert alert-danger wrong-login">
@ -53,12 +45,4 @@ body, .container {
</div> </div>
<br /><br /> <br /><br />
</center> </center>
<div id="dialog-confirm" title="View certificate " style="display: none;">
<center>
<div id="dialog-confirm-body">Hello! Do not pass by, support the project!
<b><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=5XVQTMKQS57NE&lc=US&Z3JncnB0=" title="Paypal" style="color: red" target="_blank">Paypal</a> or
<a href="https://www.patreon.com/haproxy_wi/overview" title="Patreon" style="color: red" target="_blank">Patreon</a></b>
</div>
</center>
</div>
{% endblock %} {% endblock %}

View File

@ -1,5 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
{% from 'include/input_macros.html' import input, checkbox %}
<script src="/inc/users.js"></script> <script src="/inc/users.js"></script>
<table class="overview"> <table class="overview">
<tr class="overviewHead"> <tr class="overviewHead">
@ -17,16 +18,16 @@
<td class="padding10" style="width: 10%;">Ex for grep</td> <td class="padding10" style="width: 10%;">Ex for grep</td>
<td style="width: 10%;"> <td style="width: 10%;">
<label for="time_range_out_hour" style="padding: 0">Time range:</label> <label for="time_range_out_hour" style="padding: 0">Time range:</label>
<input type="text" id="time_range_out_hour" readonly class="time-range" value="{{hour}}">:<input type="text" id="time_range_out_minut" readonly class="time-range" value="{{minut}}"> - {{ input('time_range_out_hour', value=hour, class='time-range', readonly='readonly') }}:{{ input('time_range_out_minut', value=minut, class='time-range', readonly='readonly') }}
<input type="text" id="time_range_out_hour1" readonly class="time-range" value="{{hour1}}">:<input type="text" id="time_range_out_minut1" readonly class="time-range" value="{{minut1}}"> {{ input('time_range_out_hour1', value=hour1, class='time-range', readonly='readonly') }}:{{ input('time_range_out_minut1', value=minut1, class='time-range', readonly='readonly') }}
</td> </td>
<td style="width: 10%;"> </td> <td style="width: 10%;"> </td>
</tr> </tr>
<tr> <tr>
<td class="padding10 first-collumn" style="width: 10%;"> <td class="padding10 first-collumn" style="width: 10%;">
<form action="" method="get"> <form action="" method="get">
<select autofocus required name="serv" id="{{ select_id }}">
{% if onclick == 'viewLogs()' %} {% if onclick == 'viewLogs()' %}
<select autofocus required name="serv" id="{{ select_id }}">
<option disabled selected>Choose log</option> <option disabled selected>Choose log</option>
{% for select in selects %} {% for select in selects %}
{% if select.0 == serv %} {% if select.0 == serv %}
@ -35,28 +36,21 @@
<option value="{{ select.0 }}">{{ select.1 }}</option> <option value="{{ select.0 }}">{{ select.1 }}</option>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% else %}
<option disabled selected>Choose server</option>
{% for select in selects %}
{% if select.2 == serv %}
<option value="{{ select.2 }}" selected>{{ select.1 }}</option>
{% else %}
<option value="{{ select.2 }}">{{ select.1 }}</option>
{% endif %}
{% endfor %}
{% endif %}
</select> </select>
{% else %}
{% include 'include/select.html' %}
{% endif %}
</td> </td>
{% if onclick != 'viewLogs()' %} {% if onclick != 'viewLogs()' %}
<td> <td>
<label for="waf"></label><input type="checkbox" id="waf"> {{ checkbox('waf') }}
</td> </td>
{% endif %} {% endif %}
<td class="padding10" style="width: 10%;"> <td class="padding10" style="width: 10%;">
<input type="number" name="rows" id="rows" value="{{ rows }}" class="form-control" required> {{ input('rows', type='number', value=rows, required='required') }}
</td> </td>
<td class="padding10" style="width: 10%;"> <td class="padding10" style="width: 10%;">
<input type="text" name="grep" id="grep" class="form-control" value="{{ grep }}" > {{ input('grep', value=grep) }}
</td> </td>
<td class="padding10" style="width: 10%;"> <td class="padding10" style="width: 10%;">
<div id="time-range"></div> <div id="time-range"></div>

View File

@ -27,11 +27,15 @@ th, tr, td {
<script> <script>
function showMetrics() { function showMetrics() {
let metrics = new Promise(
(resolve, reject) => {
{% for s in servers %} {% for s in servers %}
getChartData('{{s.0}}') getChartData('{{s.0}}')
{% endfor %} {% endfor %}
}
showMetrics()
loadMetrics() loadMetrics()
});
metrics.then();
}
showMetrics()
</script> </script>
{% endblock %} {% endblock %}

View File

@ -25,7 +25,7 @@
<tbody id="ajaxstatus"></tbody> <tbody id="ajaxstatus"></tbody>
</table> </table>
<table class="overview-wi" style="height: 170;"> <table class="overview-wi" style="height: 170;">
<tr class="overviewHead" style="height: 43px;"> <tr class="overviewHead" style="height: 40px;">
<td class="padding10 first-collumn-wi"> <td class="padding10 first-collumn-wi">
{% if role <= 1 %} {% if role <= 1 %}
<a href="/app/viewlogs.py?viewlogs=haproxy-wi-{{date}}.log&rows=10&grep=&hour=00&minut=00&hour1=24&minut1=00" title="View HAProxy-WI logs" class="logs_link"> <a href="/app/viewlogs.py?viewlogs=haproxy-wi-{{date}}.log&rows=10&grep=&hour=00&minut=00&hour1=24&minut1=00" title="View HAProxy-WI logs" class="logs_link">
@ -154,7 +154,6 @@
<img src="/inc/images/edit.png" alt="Edit" width="15" style="margin-bottom: -3px;" /> <img src="/inc/images/edit.png" alt="Edit" width="15" style="margin-bottom: -3px;" />
</a> </a>
</td> </td>
<!-- <td class="padding10 second-collumn"> {{ USER.2 }}</td> -->
{% for group in groups %} {% for group in groups %}
{% if USER.5 == group.0|string() %} {% if USER.5 == group.0|string() %}
<td class="third-collumn-wi">{{ group.1 }}</td> <td class="third-collumn-wi">{{ group.1 }}</td>
@ -170,7 +169,6 @@
<img src="/inc/images/edit.png" alt="Edit" width="15" style="margin-bottom: -3px;" /> <img src="/inc/images/edit.png" alt="Edit" width="15" style="margin-bottom: -3px;" />
</a> </a>
</td> </td>
<!-- <td class="padding10"> {{ USER.2 }}</td> -->
{% for group in groups %} {% for group in groups %}
{% if group.0|string() == USER.5 %} {% if group.0|string() == USER.5 %}
<td class="third-collumn-wi">{{ group.1 }}</td> <td class="third-collumn-wi">{{ group.1 }}</td>

View File

@ -1,5 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
{% from 'include/input_macros.html' import input, checkbox %}
<table class="overview"> <table class="overview">
<tr class="overviewHead"> <tr class="overviewHead">
<td class="padding10 first-collumn">Server</td> <td class="padding10 first-collumn">Server</td>
@ -11,16 +12,7 @@
<tr> <tr>
<td class="padding10 first-collumn" style="width: 25%;"> <td class="padding10 first-collumn" style="width: 25%;">
<form action="{{ action }}" method="get" id="runtimeapiform"> <form action="{{ action }}" method="get" id="runtimeapiform">
<select autofocus required id="{{ select_id }}" name="{{ select_id }}"> {% include 'include/select.html' %}
<option disabled>Choose server</option>
{% for select in selects %}
{% if serv == select.2 %}
<option value="{{ select.2 }}" selected>{{ select.1 }}</option>
{% else %}
<option value="{{ select.2 }}">{{ select.1 }}</option>
{% endif %}
{% endfor %}
</select>
</td> </td>
<td style="width: 30%;"> <td style="width: 30%;">
<select required name="servaction" id="servaction"> <select required name="servaction" id="servaction">
@ -34,11 +26,11 @@
</select> </select>
</td> </td>
<td> <td>
<input type="text" name="servbackend" id="servbackend" size=35 title="Frontend, backend/server, show: info, pools or help" required class="form-control" value="{{ servbackend }}"> {{ input('servbackend', value=servbackend, title='Frontend, backend/server, show: info, pools or help', required='required') }}
</td> </td>
<td class="checkbox"> <td class="checkbox">
{% if role <= 2 %} {% if role <= 2 %}
<label for="save"></label><input type="checkbox" name="save" id="save" value="123"> {{ checkbox('save', value='123') }}
{% endif %} {% endif %}
</td> </td>
<td> <td>

View File

@ -12,7 +12,6 @@
<select autofocus required name="section" id="{{ select_id }}"> <select autofocus required name="section" id="{{ select_id }}">
<option disabled>Choose a section</option> <option disabled>Choose a section</option>
{% for s in sections %} {% for s in sections %}
{% if s == section %} {% if s == section %}
<option value="{{ s }}" selected>{{ s }}</option> <option value="{{ s }}" selected>{{ s }}</option>
{% else %} {% else %}
@ -52,15 +51,9 @@
{% if aftersave %} {% if aftersave %}
<div class="alert alert-info">New config was saved as: {{ cfg }} </div> <div class="alert alert-info">New config was saved as: {{ cfg }} </div>
{% if stderr or error %} {% if stderr or error %}
<div class="alert alert-danger"> {% include 'include/errors.html' %}
Some errors:
<br>
<br>
{{ stderr }}
{{ error }}
</div>
{% else %} {% else %}
<div class="alert alert-success">Config ok</div> <div class="alert alert-success">Config is ok</div>
<a href="config.py?serv={{ serv }}" title="Working with HAProxy configs">Configs</a> | <a href="config.py?serv={{ serv }}" title="Working with HAProxy configs">Configs</a> |
<a href="viewsttats.py?serv={{ serv }}" target="_blank" title="View stats">Go to view stats</a> <a href="viewsttats.py?serv={{ serv }}" target="_blank" title="View stats">Go to view stats</a>
{% endif %} {% endif %}

View File

@ -1,14 +1,13 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
{% from 'include/input_macros.html' import input, checkbox, select %}
<style> <style>
.container { .container {
margin-right: 0; margin-right: 0;
} }
</style> </style>
<script src="/inc/users.js"></script> <script src="/inc/users.js"></script>
<div id="dialog-confirm" title="Are you sure you want to delete?" style="display: none;"> {% include 'include/del_confirm.html' %}
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:3px 12px 20px 0;"></span>Deleting irreversibly all data will be lost?</p>
</div>
<input type="hidden" id="new-group" name="new-group" value="{{ group }}"> <input type="hidden" id="new-group" name="new-group" value="{{ group }}">
<input type="hidden" id="new-server-group-add" name="new-server-group-add" value="{{ group }}" > <input type="hidden" id="new-server-group-add" name="new-server-group-add" value="{{ group }}" >
<input type="hidden" id="new-ssh-group-add" name="new-ssh-group-add" value="{{ group }}" > <input type="hidden" id="new-ssh-group-add" name="new-ssh-group-add" value="{{ group }}" >
@ -19,11 +18,7 @@
<li><a href="#ssh">SSH credentials</a></li> <li><a href="#ssh">SSH credentials</a></li>
<li><a href="#checker">Checker</a></li> <li><a href="#checker">Checker</a></li>
<li><a href="#installhaproxy">Install HAProxy</a></li> <li><a href="#installhaproxy">Install HAProxy</a></li>
{% if user %} {% include 'include/login.html' %}
<a href=/app/login.py?logout=logout title="Logout, user name: {{ user }}" class="login"> Logout</a>
{% else %}
<a href=/app/login.py title="Login" class="login"> Login</a>
{% endif %}
</ul> </ul>
<div id="users"> <div id="users">
<table class="overview" id="ajax-users"> <table class="overview" id="ajax-users">
@ -40,35 +35,7 @@
{% for user in users %} {% for user in users %}
{% if user.5 == group %} {% if user.5 == group %}
<tr id="user-{{user.0}}" class="{{ loop.cycle('odd', 'even') }}"> <tr id="user-{{user.0}}" class="{{ loop.cycle('odd', 'even') }}">
<td class="padding10 first-collumn"> {% include 'include/admin_users.html' %}
{% if user.6 == 1%}
<input type="text" id="login-{{user.0}}" value="{{user.1}}" class="form-control" readonly>
{% else %}
<input type="text" id="login-{{user.0}}" value="{{user.1}}" class="form-control">
{% endif %}
<input type="hidden" id="usergroup-{{user.0}}" name="usergroup-{{user.0}}" value="{{ group }}">
</td>
<td>
{% if user.6 != 1%}
<span title="Change password" style="cursor: pointer" class="passwordChange">
<img src="/inc/images/edit.png" alt="Edit" width="15" style="margin-bottom: -3px; padding-left: 15px;" onclick="openChangeUserPasswordDialog('{{user.0}}')" />
</span>
{% endif %}
</td>
<td class="checkbox">
{% if user.7 == 1 %}
<label for="activeuser-{{user.0}}"></label><input type="checkbox" id="activeuser-{{user.0}}" checked>
{% else %}
<label for="activeuser-{{user.0}}"></label><input type="checkbox" id="activeuser-{{user.0}}">
{% endif %}
</td>
<td>
{% if user.6 == 1%}
<input type="text" id="email-{{user.0}}" value="{{user.2}}" class="form-control" readonly>
{% else %}
<input type="text" id="email-{{user.0}}" value="{{user.2}}" class="form-control">
{% endif %}
</td>
<td> <td>
<select id="role-{{user.0}}" name="role-{{user.0}}"> <select id="role-{{user.0}}" name="role-{{user.0}}">
<option disabled selected>Choose role</option> <option disabled selected>Choose role</option>
@ -128,81 +95,7 @@
<td> <td>
<input type="text" id="port-{{server.0}}" value="{{server.10}}" size="1" class="form-control"> <input type="text" id="port-{{server.0}}" value="{{server.10}}" size="1" class="form-control">
</td> </td>
<td class="checkbox"> {% include 'include/admin_servers.html' %}
{% if server.5 == 1 %}
<label for="enable-{{server.0}}"></label><input type="checkbox" id="enable-{{server.0}}" checked>
{% else %}
<label for="enable-{{server.0}}"></label><input type="checkbox" id="enable-{{server.0}}">
{% endif %}
</td>
<td class="checkbox">
{% if server.4 == 1 %}
<label for="typeip-{{server.0}}"></label><input type="checkbox" id="typeip-{{server.0}}" checked>
{% else %}
<label for="typeip-{{server.0}}"></label><input type="checkbox" id="typeip-{{server.0}}">
{% endif %}
</td>
<td class="checkbox">
{% if server.8 == 1 %}
<label for="alert-{{server.0}}"></label><input type="checkbox" id="alert-{{server.0}}" checked>
{% else %}
<label for="alert-{{server.0}}"></label><input type="checkbox" id="alert-{{server.0}}">
{% endif %}
</td>
<td class="checkbox">
{% if server.9 == 1 %}
<label for="metrics-{{server.0}}"></label><input type="checkbox" id="metrics-{{server.0}}" checked>
{% else %}
<label for="metrics-{{server.0}}"></label><input type="checkbox" id="metrics-{{server.0}}">
{% endif %}
</td>
<td class="checkbox">
{% if server.12 == 1 %}
<label for="active-{{server.0}}"></label><input type="checkbox" id="active-{{server.0}}" checked>
{% else %}
<label for="active-{{server.0}}"></label><input type="checkbox" id="active-{{server.0}}">
{% endif %}
</td>
<td>
<select id="slavefor-{{server.0}}">
<option selected value="0">Not slave</option>
{% for master in masters %}
{% if master.0 == server.6 %}
<option value="{{master.0}}" selected>{{master.1}}</option>
{% else %}
<option value="{{master.0}}">{{master.1}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td>
<div class="controlgroup">
<select id="credentials-{{server.0}}">
<option disabled selected>Choose credentials</option>
{% for ssh in sshs %}
{% if ssh.0 == server.7 %}
<option value="{{ssh.0}}" selected>{{ssh.1}}</option>
{% else %}
<option value="{{ssh.0}}">{{ssh.1}}</option>
{% endif %}
{% endfor %}
</select>
<button onclick="checkSshConnect('{{server.2}}')" title="Check SSH connect to the server {{server.1}}">check</button>
</div>
</td>
<td>
{% if server.11 != "None" %}
<input type="text" id="desc-{{server.0}}" value="{{server.11}}" size="30" class="form-control">
{% else %}
<input type="text" id="desc-{{server.0}}" value="" size="30" class="form-control">
{% endif %}
</td>
<td>
<a class="add" onclick="cloneServer({{server.0}})" id="clone-{{server.0}}" title="Clone {{server.1}}" style="cursor: pointer;"></a>
</td>
<td>
<a class="delete" onclick="confirmDeleteServer({{server.0}})" title="Delete server {{server.1}}" style="cursor: pointer;"></a>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
@ -270,16 +163,16 @@
</tr> </tr>
<tr> <tr>
<td class="padding10 first-collumn"> <td class="padding10 first-collumn">
<input type="text" name="new-ssh-add" id="new-ssh-add" class="form-control"> {{ input('new-ssh-add') }}
</td> </td>
<td> <td>
<label for="new-ssh_enable">Enable SSH key</label><input type="checkbox" id="new-ssh_enable" checked> <label for="new-ssh_enable">Enable SSH key</label><input type="checkbox" id="new-ssh_enable" checked>
</td> </td>
<td style="padding-top: 15px;"> <td style="padding-top: 15px;">
<p> <p>
<input type="text" id="ssh_user" class="form-control" value="{{ssh_user}}"> {{ input('ssh_user', value=ssh_user) }}
</p> </p>
<input type="password" id="ssh_pass" class="form-control" value="{{ssh_pass}}" style="display: none;"> {{ input('ssh_pass', type='password', value=ssh_pass, style="display: none;") }}
<br> <br>
</td> </td>
<td> <td>
@ -359,13 +252,13 @@
</tr> </tr>
<tr> <tr>
<td class="padding10 first-collumn"> <td class="padding10 first-collumn">
<input type="text" name="telegram-token-add" id="telegram-token-add" class="form-control"> {{ input('telegram-token-add') }}
{% for group in ssh_group %} {% for group in ssh_group %}
<input type="hidden" id="new-telegram-group-add" name="new-telegram-group-add" value="{{ group.0 }}" > {{ input('new-telegram-group-add', value=group.0) }}
{% endfor %} {% endfor %}
</td> </td>
<td> <td>
<input type="text" id="telegram-chanel-add" class="form-control"> {{ input('telegram-chanel-add') }}
</td> </td>
<td> <td>
<a class="add-admin" id="add-telegram" title="Add new Telegram channel" style="cursor: pointer;"></a> <a class="add-admin" id="add-telegram" title="Add new Telegram channel" style="cursor: pointer;"></a>
@ -387,12 +280,9 @@
</tr> </tr>
<tr> <tr>
<td class="padding10 first-collumn" style="width: 20%;"> <td class="padding10 first-collumn" style="width: 20%;">
<select id="hapver" name="hapver" required> {% set values = dict() %}
<option disabled>Choose HAProxy version</option> {% set values = {'2.0.4-1':'2.0.4-1','2.0.6-1':'2.0.6-1', '2.0.7-1':'2.0.7-1'} %}
<option value="2.0.4-1">2.0.4-1</option> {{ select('hapver', values=values, selected='2.0.7-1', required='required') }}
<option value="2.0.6-1">2.0.6-1</option>
<option value="2.0.7-1" selected>2.0.7-1</option>
</select>
</td> </td>
<td class="padding10 first-collumn"> <td class="padding10 first-collumn">
<select autofocus required name="haproxyaddserv" id="haproxyaddserv"> <select autofocus required name="haproxyaddserv" id="haproxyaddserv">
@ -403,7 +293,7 @@
</select> </select>
</td> </td>
<td> <td>
<label for="syn_flood" title="Enable SYN flood protect"><input type="checkbox" id="syn_flood" checked> {{ checkbox('syn_flood', title="Enable SYN flood protect", checked='checked') }}
</td> </td>
<td> <td>
<a class="ui-button ui-widget ui-corner-all" id="install" title="Install HAProxy">Install</a> <a class="ui-button ui-widget ui-corner-all" id="install" title="Install HAProxy">Install</a>
@ -420,47 +310,7 @@
</div> </div>
<div id="user-add-table" style="display: none;"> <div id="user-add-table" style="display: none;">
<table class="overview"> <table class="overview">
<tr> {% include 'include/admin_add_user.html' %}
<td colspan="2">
<p class="validateTips alert alert-success">Form fields tag "<span class="need-field">*</span>" are required.</p>
</td>
</tr>
<tr>
<td class="padding20">
New user
<span class="need-field">*</span>
</td>
<td>
<input type="text" name="new-username" id="new-username" class="form-control">
{% if ldap_enable == '1' %}
<a href="#" title="Search user in AD" id="search_ldap_user">Search user in AD</a>
{% endif %}
</td>
</tr>
<tr>
<td class="padding20">
Password
<span class="need-field">*</span>
</td>
<td>
<input type="password" name="new-password" id="new-password" class="form-control">
</td>
</tr>
<tr>
<td class="padding20">Active</td>
<td>
<label for="activeuser"></label><input type="checkbox" id="activeuser" checked>
</td>
</tr>
<tr>
<td class="padding20">
Email
</td>
<td>
<input type="text" name="new-email" id="new-email" class="form-control">
</td>
</tr>
<tr>
<td class="padding20"> <td class="padding20">
Role Role
<span class="need-field">*</span> <span class="need-field">*</span>
@ -481,80 +331,7 @@
<div id="server-add-table" style="display: none;"> <div id="server-add-table" style="display: none;">
<form id="server-add-form"> <form id="server-add-form">
<table class="overview"> <table class="overview">
<tr> {% include 'include/admin_add_server.html' %}
<td colspan="2">
<p class="validateTips alert alert-success">Form fields tag "<span class="need-field">*</span>" are required.</p>
</td>
</tr>
<tr>
<td class="padding20">
New hostname
<span class="need-field">*</span>
</td>
<td>
<input type="text" name="new-server-add" id="new-server-add" class="form-control">
</td>
</tr>
<tr>
<td class="padding20">
IP
<span class="need-field">*</span>
</td>
<td>
<input type="text" name="new-ip" id="new-ip" size="14" class="form-control">
<input type="hidden" id="new-sshgroup" name="new-sshgroup" value="{{ group }}" >
</td>
</tr>
<tr>
<td class="padding20" title="SSH port">
Port
<span class="need-field">*</span>
</td>
<td>
<input type="text" name="new-port" id="new-port" size=1 class="form-control" value="22">
</td>
</tr>
<tr>
<td class="padding20">Enable</td>
<td>
<label for="enable"></label><input type="checkbox" id="enable" checked>
</td>
</tr>
<tr>
<td class="padding20" title="Vitrual IP, something like VRRP">Virt</td>
<td>
<label for="typeip"></label><input type="checkbox" id="typeip">
</td>
</tr>
<tr>
<td class="padding20" title="Alert if backend change status">Alert</td>
<td>
<label for="alert"></label><input type="checkbox" id="alert">
</td>
</tr>
<tr>
<td class="padding20" title="Enable save and show metrics">Metrics</td>
<td>
<label for="metrics"></label><input type="checkbox" id="metrics">
</td>
</tr>
<tr>
<td class="padding20" title="Keep start HAProxy service if down">Start</td>
<td>
<label for="active"></label><input type="checkbox" id="active">
</td>
</tr>
<tr>
<td class="padding20" title="Actions with master config will automatically apply on slave">Slave for</td>
<td>
<select id="slavefor">
<option selected value="0">Not slave</option>
{% for master in masters %}
<option value="{{master.0}}">{{master.1}}</option>
{% endfor %}
</select>
</td>
</tr>
<tr> <tr>
<td class="padding20"> <td class="padding20">
Credentials Credentials
@ -571,46 +348,11 @@
</select> </select>
</td> </td>
</tr> </tr>
<tr>
<td class="padding20">Desciption</td>
<td>
<input type="text" id="desc" size="30" class="form-control">
</td>
</tr>
</table> </table>
<input type="submit" tabindex="-1" style="position:absolute; top:-1000px"> <input type="submit" tabindex="-1" style="position:absolute; top:-1000px">
</form> </form>
</div> </div>
<div id="user-change-password-table" style="display: none;"> {% include 'include/change_pass_form.html' %}
<table class="overview">
<tr>
<td colspan="2">
<p class="validateTips alert alert-success">Enter password and confirm</p>
</td>
</tr>
<tr>
<td class="padding20">
Password
</td>
<td>
<input type="password" name="change-password" id="change-password" class="form-control">
</td>
</tr>
<tr>
<td class="padding20">
Confirm password
</td>
<td>
<input type="password" name="change2-password" id="change2-password" class="form-control">
</td>
</tr>
<tr id="missmatchpass" style="display: none;">
<td colspan="2">
<p class="validateTips alert alert-danger" style="margin-top: 10px;">Passwords are mismatched</p>
</td>
</tr>
</table>
</div>
<script> <script>
if($('#new-server-group-add').val() == 1) { if($('#new-server-group-add').val() == 1) {
$('#group_error').css('display', 'block'); $('#group_error').css('display', 'block');

View File

@ -23,10 +23,6 @@
if (cur_url[1]) { if (cur_url[1]) {
showStats(); showStats();
} }
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function wait() { async function wait() {
$('form').append('<input type="hidden" name="serv" value='+$("#serv").val()+'>'); $('form').append('<input type="hidden" name="serv" value='+$("#serv").val()+'>');
$('form').append('<input type="hidden" name="token" value='+$('#token').val()+'>'); $('form').append('<input type="hidden" name="token" value='+$('#token').val()+'>');
@ -43,7 +39,7 @@
$('.v_menu').css('left', '200px'); $('.v_menu').css('left', '200px');
$('table.tbl th.pxname').css('width', '100%'); $('table.tbl th.pxname').css('width', '100%');
$('a.px:link').css('color', '#fff'); $('a.px:link').css('color', '#fff');
$('td').css('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif'); $('td').css('font-family', '-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol');
$('td').css('font-size', '11'); $('td').css('font-size', '11');
$('h1').css('display', 'none'); $('h1').css('display', 'none');
$('td').css('border-color', '#ddd'); $('td').css('border-color', '#ddd');
@ -77,7 +73,6 @@
$('#serv').on('selectmenuchange',function() { $('#serv').on('selectmenuchange',function() {
showStats(); showStats();
}); });
</script> </script>
<link href="/inc/style.css" rel="stylesheet"> <link href="/inc/style.css" rel="stylesheet">
{% endblock %} {% endblock %}

View File

@ -39,7 +39,8 @@ def main():
for serv in need_start: for serv in need_start:
start_worker(serv) start_worker(serv)
waf_servers = sql.select_waf_servers() try:
waf_servers = sql.select_all_waf_servers()
waf_started_workers = get_waf_worker() waf_started_workers = get_waf_worker()
waf_servers_list = [] waf_servers_list = []
@ -56,6 +57,9 @@ def main():
if waf_need_start: if waf_need_start:
for serv in waf_need_start: for serv in waf_need_start:
start_waf_worker(serv) start_waf_worker(serv)
except Exception as e:
funct.logging("localhost", 'Problems with WAF worker metrics '+e, metrics=1)
pass
def start_worker(serv): def start_worker(serv):
port = sql.get_setting('haproxy_sock_port') port = sql.get_setting('haproxy_sock_port')

View File

@ -57,12 +57,7 @@ if serv is not None and form.getvalue('config') is not None:
except: except:
pass pass
MASTERS = sql.is_master(serv) stderr = funct.master_slave_upload_and_restart(serv, configver, just_save=save)
for master in MASTERS:
if master[0] != None:
funct.upload_and_restart(master[0], configver, just_save=save)
stderr = funct.upload_and_restart(serv, configver, just_save=save)
output_from_parsed_template = template.render(h2 = 1, title = "Working with versions HAProxy configs", output_from_parsed_template = template.render(h2 = 1, title = "Working with versions HAProxy configs",

View File

@ -41,4 +41,17 @@
Order Deny,Allow Order Deny,Allow
Deny from all Deny from all
</FilesMatch> </FilesMatch>
<IfModule mod_headers.c>
Header set X-XSS-Protection: 1;
Header set X-Frame-Options: deny
Header set X-Content-Type-Options: nosniff
Header set Strict-Transport-Security: max-age=3600;
Header set Cache-Control no-cache
Header set Expires: 0
<filesMatch ".(ico|css|js|gif|jpeg|jpg|png|svg|woff|ttf|eot)$">
Header set Cache-Control "max-age=86400, public"
</filesMatch>
</IfModule>
</VirtualHost> </VirtualHost>

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View File

@ -264,7 +264,10 @@ $( function() {
} ); } );
}, },
autoFocus: true, autoFocus: true,
minLength: -1 minLength: -1,
select: function( event, ui ) {
$(this).next().next().focus();
}
}); });
$( "#backends" ).autocomplete({ $( "#backends" ).autocomplete({
source: function( request, response ) { source: function( request, response ) {
@ -825,11 +828,8 @@ $( function() {
} ); } );
}); });
var add_server_var = '<br /><input name="servers" title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">: <input name="server_port" title="Backend port" size=1 placeholder="yyy" class="form-control">' var add_server_var = '<br /><input name="servers" title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">: <input name="server_port" title="Backend port" size=1 placeholder="yyy" class="form-control">'
$('#add-server-input').click(function() { $('[name=add-server-input]').click(function() {
$('#servers').append(add_server_var); $("[name=add_servers]").append(add_server_var);
});
$('#add-server-input2').click(function() {
$('#servers2').append(add_server_var);
}); });
var add_userlist_var = '<br /><input name="userlist-user" title="User name" placeholder="user_name" class="form-control"> <input name="userlist-password" required title="User password. By default it insecure-password" placeholder="password" class="form-control"> <input name="userlist-user-group" title="User`s group" placeholder="user`s group" class="form-control">' var add_userlist_var = '<br /><input name="userlist-user" title="User name" placeholder="user_name" class="form-control"> <input name="userlist-password" required title="User password. By default it insecure-password" placeholder="password" class="form-control"> <input name="userlist-user-group" title="User`s group" placeholder="user`s group" class="form-control">'
$('#add-userlist-user').click(function() { $('#add-userlist-user').click(function() {
@ -971,7 +971,7 @@ function createHttps(TabId, proxy) {
history.pushState('Add'+proxy, 'Add'+proxy, 'add.py#'+proxy) history.pushState('Add'+proxy, 'Add'+proxy, 'add.py#'+proxy)
} }
function confirmDeleteOption(id) { function confirmDeleteOption(id) {
$( "#dialog-confirm-delete" ).dialog({ $( "#dialog-confirm" ).dialog({
resizable: false, resizable: false,
height: "auto", height: "auto",
width: 400, width: 400,
@ -1034,7 +1034,7 @@ function updateOptions(id) {
} ); } );
} }
function confirmDeleteSavedServer(id) { function confirmDeleteSavedServer(id) {
$( "#dialog-confirm-delete" ).dialog({ $( "#dialog-confirm" ).dialog({
resizable: false, resizable: false,
height: "auto", height: "auto",
width: 400, width: 400,
@ -1097,3 +1097,34 @@ function updateSavedServer(id) {
} }
} ); } );
} }
function view_ssl(id) {
$.ajax( {
url: "options.py",
data: {
serv: $('#serv5').val(),
getcert: id,
token: $('#token').val()
},
type: "GET",
success: function( data ) {
if (data.indexOf('danger') != '-1') {
$("#ajax-show-ssl").html(data);
} else {
$('.alert-danger').remove();
$('#dialog-confirm-body').text(data);
$( "#dialog-confirm-cert" ).dialog({
resizable: false,
height: "auto",
width: 650,
modal: true,
title: "Certificate from "+$('#serv5').val()+", name: "+id,
buttons: {
Ok: function() {
$( this ).dialog( "close" );
}
}
});
}
}
} );
}

View File

@ -107,7 +107,7 @@ function renderWafChart(data, labels, server) {
options: { options: {
title: { title: {
display: true, display: true,
text: data[1], text: "WAF "+data[1],
fontSize: 20, fontSize: 20,
padding: 0, padding: 0,
}, },

View File

@ -51,14 +51,17 @@ function ajaxActionWafServers(action, id) {
$( function() { $( function() {
$('.start').click(function() { $('.start').click(function() {
var id = $(this).attr('id'); var id = $(this).attr('id');
id = id.split('-')[1]
confirmAjaxAction("start", "hap", id); confirmAjaxAction("start", "hap", id);
}); });
$('.stop').click(function() { $('.stop').click(function() {
var id = $(this).attr('id'); var id = $(this).attr('id');
id = id.split('-')[1]
confirmAjaxAction("stop", "hap", id); confirmAjaxAction("stop", "hap", id);
}); });
$('.restart').click(function() { $('.restart').click(function() {
var id = $(this).attr('id'); var id = $(this).attr('id');
id = id.split('-')[1]
confirmAjaxAction("restart", "hap", id); confirmAjaxAction("restart", "hap", id);
}); });
$('.start-waf').click(function() { $('.start-waf').click(function() {

View File

@ -154,6 +154,12 @@ function startSetInterval(interval) {
intervalId = setInterval('showOverviewWaf()', interval); intervalId = setInterval('showOverviewWaf()', interval);
showOverviewWaf(); showOverviewWaf();
showWafMetrics(); showWafMetrics();
} else if (cur_url[0] == "hapservers.py") {
if(interval < 60000) {
interval = 60000;
}
intervalId = setInterval('showMetrics()', interval);
showMetrics();
} }
} else { } else {
pauseAutoRefresh(); pauseAutoRefresh();
@ -223,8 +229,8 @@ function showOverviewServer(name,ip,id) {
success: function( data ) { success: function( data ) {
$("#ajax-server-"+id).empty(); $("#ajax-server-"+id).empty();
$("#ajax-server-"+id).css('display', 'block'); $("#ajax-server-"+id).css('display', 'block');
$("#ajax-server-"+id).css('background-color', '#f9fff8'); $("#ajax-server-"+id).css('background-color', '#fbfbfb');
$("#ajax-server-"+id).css('border', '1px solid #ddd'); $("#ajax-server-"+id).css('border', '1px solid #A4C7F5');
$(".ajax-server").css('display', 'block'); $(".ajax-server").css('display', 'block');
$(".div-server").css('clear', 'both'); $(".div-server").css('clear', 'both');
$(".div-pannel").css('clear', 'both'); $(".div-pannel").css('clear', 'both');
@ -233,14 +239,6 @@ function showOverviewServer(name,ip,id) {
$(".div-pannel").css('height', '70px'); $(".div-pannel").css('height', '70px');
$("#div-pannel-"+id).insertBefore('#up-pannel') $("#div-pannel-"+id).insertBefore('#up-pannel')
$("#ajax-server-"+id).html(data); $("#ajax-server-"+id).html(data);
$([document.documentElement, document.body]).animate({
scrollTop: $("#ajax-server-"+id).offset().top
}, 200);
$("#ajax-server-"+id).addClass( "update", 1000 );
setTimeout(function() {
$("#ajax-server-"+id).removeClass( "update" );
$("#ajax-server-"+id).css('background-color', '#f9fff8');
}, 2500 );
} }
} ); } );
} }
@ -539,14 +537,6 @@ $( function() {
autoRefreshStyle(autoRefresh); autoRefreshStyle(autoRefresh);
} }
} }
/* $("body").mCustomScrollbar({
theme:"minimal-dark",
scrollInertia:30
});
$(".diff").mCustomScrollbar({
theme:"minimal-dark",
scrollInertia:30
}); */
$( "#tabs" ).tabs(); $( "#tabs" ).tabs();
$( "select" ).selectmenu(); $( "select" ).selectmenu();
@ -682,7 +672,6 @@ $( function() {
} }
}); });
$('#runtimeapiform').submit(function() { $('#runtimeapiform').submit(function() {
showRuntime(); showRuntime();
return false; return false;
@ -735,7 +724,6 @@ $( function() {
} }
}); });
$('#show-updates-button').click(function() { $('#show-updates-button').click(function() {
showUpdates.dialog('open'); showUpdates.dialog('open');
}); });
@ -900,39 +888,26 @@ function replace_text(id_textarea, text_var) {
var text_val = str.substring(0, beg) + str.substring(end, len); var text_val = str.substring(0, beg) + str.substring(end, len);
$(id_textarea).text(text_val); $(id_textarea).text(text_val);
} }
function changeWafMode(id) {
function view_ssl(id) { var waf_mode = $('#'+id+' option:selected').val();
var server_hostname = id.split('_')[0];
$.ajax( { $.ajax( {
url: "options.py", url: "options.py",
data: { data: {
serv: $('#serv5').val(), change_waf_mode: waf_mode,
getcert: id, server_hostname: server_hostname,
token: $('#token').val() token: $('#token').val()
}, },
type: "GET", type: "GET",
success: function( data ) { success: function( data ) {
if (data.indexOf('danger') != '-1') { alert('Do not forget restart WAF server: '+server_hostname)
$("#ajax-show-ssl").html(data); $( '#'+server_hostname+'-select-line' ).addClass( "update", 1000 );
} else { setTimeout(function() {
$('.alert-danger').remove(); $( '#'+server_hostname+'-select-line' ).removeClass( "update" );
$('#dialog-confirm-body').text(data); }, 2500 );
$( "#dialog-confirm" ).dialog({
resizable: false,
height: "auto",
width: 650,
modal: true,
title: "Certificate from "+$('#serv5').val()+", name: "+id,
buttons: {
Ok: function() {
$( this ).dialog( "close" );
}
}
});
}
} }
} ); } );
} }
function createList(color) { function createList(color) {
if(color == 'white') { if(color == 'white') {
list = $('#new_whitelist_name').val() list = $('#new_whitelist_name').val()
@ -1013,24 +988,3 @@ function saveList(action, list, color) {
} }
} ); } );
} }
function changeWafMode(id) {
var waf_mode = $('#'+id+' option:selected').val();
var server_hostname = id.split('_')[0];
$.ajax( {
url: "options.py",
data: {
change_waf_mode: waf_mode,
server_hostname: server_hostname,
token: $('#token').val()
},
type: "GET",
success: function( data ) {
alert('Do not forget restart WAF server: '+server_hostname)
$( '#'+server_hostname+'-select-line' ).addClass( "update", 1000 );
setTimeout(function() {
$( '#'+server_hostname+'-select-line' ).removeClass( "update" );
}, 2500 );
}
} );
}

View File

@ -35,11 +35,15 @@ form {
pre { pre {
padding-left: 15px; padding-left: 15px;
} }
.icon { .icon, .icon-hapservs {
max-width: 20px; max-width: 20px;
margin-left: 2px; margin-left: 2px;
margin-bottom: -3px;
cursor: pointer; cursor: pointer;
} }
.icon-hapservs {
margin-bottom: 0px;
}
.top-menu { .top-menu {
position: absolute; position: absolute;
min-height: calc(99vh - 50px); min-height: calc(99vh - 50px);
@ -141,7 +145,7 @@ pre {
} }
.login { .login {
float: right; float: right;
margin-top: 5px; margin-top: 3px;
margin-left: 14px; margin-left: 14px;
margin-right: 20px; margin-right: 20px;
color: #fff !important; color: #fff !important;
@ -150,7 +154,7 @@ pre {
.auto-refresh { .auto-refresh {
margin-left: auto; margin-left: auto;
float: right; float: right;
margin-top: 5px; margin-top: 3.7px;
margin-right: 5px; margin-right: 5px;
} }
.auto-refresh a { .auto-refresh a {
@ -539,6 +543,14 @@ ul{
transition: background 1s ease-out; transition: background 1s ease-out;
font-size: 15px; font-size: 15px;
} }
.form-login {
text-align: center;
background-color: #fff;
padding: 10px;
width: 220px;
background-size: 0 !important;
border: 0 !important;
}
.ui-button { .ui-button {
padding-left: 10px !important; padding-left: 10px !important;
padding-right: 10px !important; padding-right: 10px !important;
@ -547,7 +559,6 @@ ul{
.ui-state-default { .ui-state-default {
background-color: #EBF1F1 !important; background-color: #EBF1F1 !important;
} }
.ui-state-active { .ui-state-active {
background-color: #4A89D8 !important; background-color: #4A89D8 !important;
border: none !important; border: none !important;
@ -779,12 +790,15 @@ label {
display: inline-block; display: inline-block;
width: 160px; width: 160px;
padding-left: 30px; padding-left: 30px;
padding-top: 27px; padding-top: 35px;
font-size: 1em; font-size: 12px;
float: left;
} }
.top-info { .top-info {
display: inline-block; display: inline-block;
width: 350px; width: 350px;
margin-top: 30px;
font-size: 10px;
} }
.update-icon { .update-icon {
float: right; float: right;
@ -831,7 +845,13 @@ label {
} }
} }
@media (max-width: 1280px) { @media (max-width: 1280px) {
.div-server {
margin-bottom: 30px !important;
}
.ajax-server {
clear: both !important;
margin-left: 20px !important;
}
} }
@media (max-width: 1080px) { @media (max-width: 1080px) {
#logo_span { #logo_span {
@ -849,6 +869,9 @@ label {
.wrong-login { .wrong-login {
margin-right: -50px; margin-right: -50px;
} }
.ajax-server {
width: 750px !important;
}
} }
@media (max-width: 1024px) { @media (max-width: 1024px) {
#logo_span { #logo_span {

View File

@ -52,3 +52,23 @@ function installWaf(ip) {
} }
} ); } );
} }
function changeWafMode(id) {
var waf_mode = $('#'+id+' option:selected').val();
var server_hostname = id.split('_')[0];
$.ajax( {
url: "options.py",
data: {
change_waf_mode: waf_mode,
server_hostname: server_hostname,
token: $('#token').val()
},
type: "GET",
success: function( data ) {
alert('Do not forget restart WAF server: '+server_hostname)
$( '#'+server_hostname+'-select-line' ).addClass( "update", 1000 );
setTimeout(function() {
$( '#'+server_hostname+'-select-line' ).removeClass( "update" );
}, 2500 );
}
} );
}