Change log: https://roxy-wi.org/changelog.py#6_0_3
pull/328/head
Pavel Loginov 2022-06-02 12:08:37 +03:00
parent 146422410e
commit 3919bfe76b
21 changed files with 320 additions and 179 deletions

View File

@ -55,46 +55,27 @@ def index():
'haproxy/<id,hostname,ip>/action/stop': 'stop HAProxy service by id or hostname or ip. METHOD: GET', 'haproxy/<id,hostname,ip>/action/stop': 'stop HAProxy service by id or hostname or ip. METHOD: GET',
'haproxy/<id,hostname,ip>/action/restart': 'restart HAProxy service by id or hostname or ip. METHOD: GET', 'haproxy/<id,hostname,ip>/action/restart': 'restart HAProxy service by id or hostname or ip. METHOD: GET',
'haproxy/<id,hostname,ip>/config': 'get HAProxy config from a server by id or hostname or ip. METHOD: GET', 'haproxy/<id,hostname,ip>/config': 'get HAProxy config from a server by id or hostname or ip. METHOD: GET',
'haproxy/<id,hostname,ip>/config': 'upload HAProxy config to a server by id or hostname or ip. Headers: action: ' 'haproxy/<id,hostname,ip>/config': 'upload HAProxy config to a server by id or hostname or ip. Headers: action: save/reload/restart. Body must consist a whole HAProxy config. METHOD: POST',
'save/reload/restart. Body must consist a whole HAProxy config. METHOD: POST', 'haproxy/<id,hostname,ip>/log': 'show HAProxy logs by id or hostname or ip. May to have config next Headers: rows(format INT) default: 10 grep, waf(if needs WAF log) default: 0, start_hour(format: 24) default: 00, start_minute, end_hour(format: 24) default: 24, end_minute. METHOD: GET',
'haproxy/<id,hostname,ip>/log': 'show HAProxy logs by id or hostname or ip. May to have config next Headers: rows(format INT) '
'default: 10 grep, waf(if needs WAF log) default: 0, start_hour(format: 24) default: 00, '
'start_minute, end_hour(format: 24) default: 24, end_minute. METHOD: GET',
'haproxy/<id,hostname,ip>/section': 'show a certain section, headers: section-name. METHOD: GET', 'haproxy/<id,hostname,ip>/section': 'show a certain section, headers: section-name. METHOD: GET',
'haproxy/<id,hostname,ip>/section/add': 'add a section to the HAProxy config by id or hostname or ip. Has to have ' 'haproxy/<id,hostname,ip>/section/add': 'add a section to the HAProxy config by id or hostname or ip. Has to have config header with section and action header for action after upload. Section header must consist type: listen, frontend, etc. Action header accepts next value: save, test, reload and restart. Can be empty for just save. METHOD: POST',
'config header with section and action header for action after upload. ' 'haproxy/<id,hostname,ip>/section/edit': 'edit a section in the HAProxy config by id or hostname or ip. Has to have config header with section, action header for action after upload and body of a new section configuration. Section header must consist type: listen, frontend, etc. Action header accepts next value: save, test, reload and restart. Can be empty for just save. METHOD: POST',
'Section header must consist type: listen, frontend, etc. Action header ' 'haproxy/<id,hostname,ip>/acl': 'add an acl to certain section. Must be JSON body: "section-name", "if", "then", "if_value", "then_value" and "action" for action after upload. Action accepts next value: "save", "test", "reload" and "restart". METHOD: POST',
'accepts next value: save, test, reload and restart. Can be empty for just save. METHOD: POST', 'haproxy/<id,hostname,ip>/acl': 'delete an acl to certain section. Must be JSON body: "section-name", "if", "then", "if_value", "then_value" and "action" for action after upload. Action accepts next value: "save", "test", "reload" and "restart". METHOD: DELETE',
'haproxy/<id,hostname,ip>/section/edit': 'edit a section in the HAProxy config by id or hostname or ip. Has to have '
'config header with section, action header for action after upload and body '
'of a new section configuration. Section header must consist type: listen, '
'frontend, etc. Action header accepts next value: save, test, reload and restart. Can be empty for just save. METHOD: POST',
'haproxy/<id,hostname,ip>/acl': 'add an acl to certain section. Must be JSON body: "section-name", "if", "then", '
'"if_value", "then_value" and "action" for action after upload. Action accepts next '
'value: "save", "test", "reload" and "restart". METHOD: POST',
'haproxy/<id,hostname,ip>/acl': 'delete an acl to certain section. Must be JSON body: "section-name", "if", "then", '
'"if_value", "then_value" and "action" for action after upload. Action accepts next '
'value: "save", "test", "reload" and "restart". METHOD: DELETE',
'nginx/<id,hostname,ip>': 'show info about the NGINX by id or hostname or ip. METHOD: GET', 'nginx/<id,hostname,ip>': 'show info about the NGINX by id or hostname or ip. METHOD: GET',
'nginx/<id,hostname,ip>/status': 'show NGINX status by id or hostname or ip. METHOD: GET', 'nginx/<id,hostname,ip>/status': 'show NGINX status by id or hostname or ip. METHOD: GET',
'nginx/<id,hostname,ip>/action/start': 'start NGINX service by id or hostname or ip. METHOD: GET', 'nginx/<id,hostname,ip>/action/start': 'start NGINX service by id or hostname or ip. METHOD: GET',
'nginx/<id,hostname,ip>/action/stop': 'stop NGINX service by id or hostname or ip. METHOD: GET', 'nginx/<id,hostname,ip>/action/stop': 'stop NGINX service by id or hostname or ip. METHOD: GET',
'nginx/<id,hostname,ip>/action/restart': 'restart NGINX service by id or hostname or ip. METHOD: GET', 'nginx/<id,hostname,ip>/action/restart': 'restart NGINX service by id or hostname or ip. METHOD: GET',
'nginx/<id,hostname,ip>/config': 'get NGINX config from a server by id or hostname or ip. Headers: The full path to a config file, ' 'nginx/<id,hostname,ip>/config': 'get NGINX config from a server by id or hostname or ip. Headers: The full path to a config file, like: /etc/nginx/conf.d/default.conf. METHOD: GET',
'like: /etc/nginx/conf.d/default.conf. METHOD: GET', 'nginx/<id,hostname,ip>/config': 'upload NGINX config to a server by id or hostname or ip. Headers: action: save/reload/restart, config-file: the full path to the config, like /etc/nginx/conf.d/example.com.conf. Body must consist a whole HAProxy config. METHOD: POST',
'nginx/<id,hostname,ip>/config': 'upload NGINX config to a server by id or hostname or ip. Headers: action: save/reload/restart, '
'config-file: the full path to the config, like /etc/nginx/conf.d/example.com.conf. '
'Body must consist a whole HAProxy config. METHOD: POST',
'apache/<id,hostname,ip>': 'show info about the Apache by id or hostname or ip. METHOD: GET', 'apache/<id,hostname,ip>': 'show info about the Apache by id or hostname or ip. METHOD: GET',
'apache/<id,hostname,ip>/status': 'show Apache status by id or hostname or ip. METHOD: GET', 'apache/<id,hostname,ip>/status': 'show Apache status by id or hostname or ip. METHOD: GET',
'apache/<id,hostname,ip>/action/start': 'start Apache service by id or hostname or ip. METHOD: GET', 'apache/<id,hostname,ip>/action/start': 'start Apache service by id or hostname or ip. METHOD: GET',
'apache/<id,hostname,ip>/action/stop': 'stop Apache service by id or hostname or ip. METHOD: GET', 'apache/<id,hostname,ip>/action/stop': 'stop Apache service by id or hostname or ip. METHOD: GET',
'apache/<id,hostname,ip>/action/restart': 'restart Apache service by id or hostname or ip. METHOD: GET', 'apache/<id,hostname,ip>/action/restart': 'restart Apache service by id or hostname or ip. METHOD: GET',
'apache/<id,hostname,ip>/config': 'get Apache config from a server by id or hostname or ip. Headers: The full path to a config file, ' 'apache/<id,hostname,ip>/config': 'get Apache config from a server by id or hostname or ip. Headers: The full path to a config file, like: /etc/httpd/conf.d/default.conf. METHOD: GET',
'like: /etc/httpd/conf.d/default.conf. METHOD: GET', 'apache/<id,hostname,ip>/config': 'upload Apache config to a server by id or hostname or ip. Headers: action: save/reload/restart, config-file: the full path to the config, like /etc/httpd/conf.d/example.com.conf. Body must consist a whole HAProxy config. METHOD: POST',
'apache/<id,hostname,ip>/config': 'upload Apache config to a server by id or hostname or ip. Headers: action: save/reload/restart, config-file: '
'the full path to the config, like /etc/httpd/conf.d/example.com.conf. '
'Body must consist a whole HAProxy config. METHOD: POST',
} }
return dict(help=data) return dict(help=data)

View File

@ -723,7 +723,7 @@ def update_db_v_6_0_1(**kwargs):
def update_ver(): def update_ver():
query = Version.update(version='6.0.2.0') query = Version.update(version='6.0.3.0')
try: try:
query.execute() query.execute()
except Exception: except Exception:

View File

@ -251,8 +251,8 @@ def slack_send_mess(mess, **kwargs):
proxy = sql.get_setting('proxy') proxy = sql.get_setting('proxy')
for slack in slacks: for slack in slacks:
slack_token = slack[1] slack_token = slack.token
channel_name = slack[2] channel_name = slack.chanel_name
if proxy is not None and proxy != '' and proxy != 'None': if proxy is not None and proxy != '' and proxy != 'None':
proxies = dict(https=proxy, http=proxy) proxies = dict(https=proxy, http=proxy)
@ -422,7 +422,7 @@ def get_config(server_ip, cfg, **kwargs):
import sql import sql
if kwargs.get("keepalived") or kwargs.get("service") == 'keepalived': if kwargs.get("keepalived") or kwargs.get("service") == 'keepalived':
config_path = "/etc/keepalived/keepalived.conf" config_path = sql.get_setting('keepalived_config_path')
elif ( elif (
kwargs.get("nginx") or kwargs.get("service") == 'nginx' kwargs.get("nginx") or kwargs.get("service") == 'nginx'
or kwargs.get("apache") or kwargs.get("service") == 'apache' or kwargs.get("apache") or kwargs.get("service") == 'apache'
@ -921,7 +921,7 @@ def upload_and_restart(server_ip, cfg, **kwargs):
tmp_file = sql.get_setting('tmp_config_path') + "/" + get_data('config') + ".conf" tmp_file = sql.get_setting('tmp_config_path') + "/" + get_data('config') + ".conf"
elif kwargs.get("keepalived"): elif kwargs.get("keepalived"):
service = 'keepalived' service = 'keepalived'
config_path = "/etc/keepalived/keepalived.conf" config_path = sql.get_setting('keepalived_config_path')
tmp_file = sql.get_setting('tmp_config_path') + "/" + get_data('config') + ".cfg" tmp_file = sql.get_setting('tmp_config_path') + "/" + get_data('config') + ".cfg"
else: else:
service = 'haproxy' service = 'haproxy'
@ -1232,7 +1232,7 @@ def show_haproxy_log(serv, rows=10, waf='0', grep=None, hour='00', minut='00', h
else: else:
exgrep_act = '' exgrep_act = ''
if service == 'nginx' or service == 'haproxy' or service == 'apache': if service in ('nginx', 'haproxy', 'apache', 'keepalived'):
syslog_server_enable = sql.get_setting('syslog_server_enable') syslog_server_enable = sql.get_setting('syslog_server_enable')
if syslog_server_enable is None or syslog_server_enable == 0: if syslog_server_enable is None or syslog_server_enable == 0:
if service == 'nginx': if service == 'nginx':
@ -1240,7 +1240,15 @@ def show_haproxy_log(serv, rows=10, waf='0', grep=None, hour='00', minut='00', h
commands = ["sudo cat %s/%s |tail -%s %s %s" % (local_path_logs, log_file, rows, grep_act, exgrep_act)] commands = ["sudo cat %s/%s |tail -%s %s %s" % (local_path_logs, log_file, rows, grep_act, exgrep_act)]
elif service == 'apache': elif service == 'apache':
local_path_logs = sql.get_setting('apache_path_logs') local_path_logs = sql.get_setting('apache_path_logs')
commands = ["sudo cat %s/%s| awk -F\"/|:\" '$3>\"%s:00\" && $3<\"%s:00\"' |tail -%s %s %s" % (local_path_logs, log_file, date, date1, rows, grep_act, exgrep_act)] commands = [
"sudo cat %s/%s| awk -F\"/|:\" '$3>\"%s:00\" && $3<\"%s:00\"' |tail -%s %s %s" % (local_path_logs, log_file, date, date1, rows, grep_act, exgrep_act)
]
elif service == 'keepalived':
local_path_logs = sql.get_setting('keepalived_path_logs')
commands = [
"sudo cat %s/%s| awk '$3>\"%s:00\" && $3<\"%s:00\"' |tail -%s %s %s" % (
local_path_logs, log_file, date, date1, rows, grep_act, exgrep_act)
]
else: else:
local_path_logs = sql.get_setting('haproxy_path_logs') local_path_logs = sql.get_setting('haproxy_path_logs')
commands = ["sudo cat %s/%s| awk '$3>\"%s:00\" && $3<\"%s:00\"' |tail -%s %s %s" % (local_path_logs, log_file, date, date1, rows, grep_act, exgrep_act)] commands = ["sudo cat %s/%s| awk '$3>\"%s:00\" && $3<\"%s:00\"' |tail -%s %s %s" % (local_path_logs, log_file, date, date1, rows, grep_act, exgrep_act)]
@ -1262,7 +1270,7 @@ def show_haproxy_log(serv, rows=10, waf='0', grep=None, hour='00', minut='00', h
apache_log_path = sql.get_setting('apache_log_path') apache_log_path = sql.get_setting('apache_log_path')
if serv == 'roxy-wi.access.log': if serv == 'roxy-wi.access.log':
cmd = "sudo cat {}| awk -F\"/|:\" '$3>\"{}:00\" && $3<\"{}:00\"' |tail -{} {} {}".format(apache_log_path + "/" + serv, date, date1, rows, grep_act, exgrep_act) cmd = 'sudo cat {}| awk -F"/|:" \'$3>"{}:00" && $3<"{}:00"\' |tail -{} {} {}'.format(apache_log_path + "/" + serv, date, date1, rows, grep_act, exgrep_act)
elif serv == 'roxy-wi.error.log': elif serv == 'roxy-wi.error.log':
cmd = "sudo cat {}| awk '$4>\"{}:00\" && $4<\"{}:00\"' |tail -{} {} {}".format(apache_log_path + "/" + serv, date, date1, rows, grep_act, exgrep_act) cmd = "sudo cat {}| awk '$4>\"{}:00\" && $4<\"{}:00\"' |tail -{} {} {}".format(apache_log_path + "/" + serv, date, date1, rows, grep_act, exgrep_act)
elif serv == 'fail2ban.log': elif serv == 'fail2ban.log':
@ -1319,7 +1327,8 @@ def haproxy_wi_log(**kwargs):
group_grep = '|grep "group: ' + user_group + '"' group_grep = '|grep "group: ' + user_group + '"'
else: else:
group_grep = '' group_grep = ''
cmd = "find " + log_path + "/roxy-wi-* -type f -exec stat --format '%Y :%y %n' '{}' \; | sort -nr | cut -d: -f2- | head -1 |awk '{print $4}' |xargs tail" + group_grep + "|sort -r" cmd = "find " + log_path + "/roxy-wi-* -type f -exec stat --format '%Y :%y %n' '{}' \; | sort -nr | cut -d: -f2- " \
"| head -1 |awk '{print $4}' |xargs tail" + group_grep + "|sort -r"
try: try:
output, stderr = subprocess_execute(cmd) output, stderr = subprocess_execute(cmd)
return output return output
@ -1465,6 +1474,7 @@ def return_nice_path(return_path: str) -> str:
and 'haproxy' not in return_path and 'haproxy' not in return_path
and 'apache2' not in return_path and 'apache2' not in return_path
and 'httpd' not in return_path and 'httpd' not in return_path
and 'keepalived' not in return_path
): ):
return 'error: The path must contain the name of the service. Check it in Roxy-WI settings' return 'error: The path must contain the name of the service. Check it in Roxy-WI settings'
if return_path[-1] != '/': if return_path[-1] != '/':

View File

@ -3,13 +3,15 @@
import os import os
import sys import sys
import funct
import http.cookies import http.cookies
import sql
import create_db
import datetime import datetime
import uuid import uuid
import distro import distro
import sql
import create_db
import funct
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates/'), autoescape=True) env = Environment(loader=FileSystemLoader('templates/'), autoescape=True)
template = env.get_template('login.html') template = env.get_template('login.html')
@ -74,7 +76,7 @@ def send_cookie(login):
try: try:
user_name = sql.get_user_name_by_uuid(user_uuid) user_name = sql.get_user_name_by_uuid(user_uuid)
funct.logging('localhost', ' user: ' + user_name + ', group: ' + user_group + ' log in', haproxywi=1) funct.logging('localhost', ' user: ' + user_name + ', group: ' + user_group + ' login', haproxywi=1)
except Exception: except Exception:
pass pass
print("Content-type: text/html\n") print("Content-type: text/html\n")

View File

@ -148,15 +148,24 @@ if form.getvalue('backend_ip') is not None:
MASTERS = sql.is_master(serv) MASTERS = sql.is_master(serv)
for master in MASTERS: for master in MASTERS:
if master[0] is not None: if master[0] is not None:
cmd = 'echo "set server %s/%s addr %s port %s check-port %s" |nc %s %s' % (backend_backend, backend_server, backend_ip, backend_port, backend_port, master[0], haproxy_sock_port) cmd = 'echo "set server %s/%s addr %s port %s check-port %s" |nc %s %s' % (
backend_backend, backend_server, backend_ip, backend_port, backend_port, master[0], haproxy_sock_port)
output, stderr = funct.subprocess_execute(cmd) output, stderr = funct.subprocess_execute(cmd)
print(output[0]) print(output[0])
funct.logging(master[0], 'IP address and port have been changed. On: {}/{} to {}:{}'.format(backend_backend, backend_server, backend_ip, backend_port), funct.logging(
login=1, keep_history=1, service='haproxy') master[0], 'IP address and port have been changed. On: {}/{} to {}:{}'.format(
backend_backend, backend_server, backend_ip, backend_port
),
login=1, keep_history=1, service='haproxy'
)
cmd = 'echo "set server %s/%s addr %s port %s check-port %s" |nc %s %s' % (backend_backend, backend_server, backend_ip, backend_port, backend_port, serv, haproxy_sock_port) cmd = 'echo "set server %s/%s addr %s port %s check-port %s" |nc %s %s' % (
funct.logging(serv, 'IP address and port have been changed. On: {}/{} to {}:{}'.format(backend_backend, backend_server, backend_ip, backend_port), backend_backend, backend_server, backend_ip, backend_port, backend_port, serv, haproxy_sock_port)
login=1, keep_history=1, service='haproxy') funct.logging(
serv,
'IP address and port have been changed. On: {}/{} to {}:{}'.format(backend_backend, backend_server, backend_ip, backend_port),
login=1, keep_history=1, service='haproxy'
)
output, stderr = funct.subprocess_execute(cmd) output, stderr = funct.subprocess_execute(cmd)
if stderr != '': if stderr != '':
@ -167,7 +176,9 @@ if form.getvalue('backend_ip') is not None:
cfg = configs_dir + serv + "-" + funct.get_data('config') + ".cfg" cfg = configs_dir + serv + "-" + funct.get_data('config') + ".cfg"
error = funct.get_config(serv, cfg) error = funct.get_config(serv, cfg)
cmd = 'string=`grep %s %s -n -A25 |grep "server %s" |head -1|awk -F"-" \'{print $1}\'` && sed -Ei "$( echo $string)s/((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5]):[0-9]+/%s:%s/g" %s' % (backend_backend, cfg, backend_server, backend_ip, backend_port, cfg) cmd = 'string=`grep %s %s -n -A25 |grep "server %s" |head -1|awk -F"-" \'{print $1}\'` ' \
'&& sed -Ei "$( echo $string)s/((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5]):[0-9]+/%s:%s/g" %s' % \
(backend_backend, cfg, backend_server, backend_ip, backend_port, cfg)
output, stderr = funct.subprocess_execute(cmd) output, stderr = funct.subprocess_execute(cmd)
stderr = funct.master_slave_upload_and_restart(serv, cfg, just_save='save') stderr = funct.master_slave_upload_and_restart(serv, cfg, just_save='save')
@ -210,7 +221,8 @@ if form.getvalue('maxconn_frontend') is not None:
cfg = configs_dir + serv + "-" + funct.get_data('config') + ".cfg" cfg = configs_dir + serv + "-" + funct.get_data('config') + ".cfg"
error = funct.get_config(serv, cfg) error = funct.get_config(serv, cfg)
cmd = 'string=`grep %s %s -n -A5 |grep maxcon -n |awk -F":" \'{print $2}\'|awk -F"-" \'{print $1}\'` && sed -Ei "$( echo $string)s/[0-9]+/%s/g" %s' % (frontend, cfg, maxconn, cfg) cmd = 'string=`grep %s %s -n -A5 |grep maxcon -n |awk -F":" \'{print $2}\'|awk -F"-" \'{print $1}\'` ' \
'&& sed -Ei "$( echo $string)s/[0-9]+/%s/g" %s' % (frontend, cfg, maxconn, cfg)
output, stderr = funct.subprocess_execute(cmd) output, stderr = funct.subprocess_execute(cmd)
stderr = funct.master_slave_upload_and_restart(serv, cfg, just_save='save') stderr = funct.master_slave_upload_and_restart(serv, cfg, just_save='save')
print('success: Maxconn for %s has been set to %s ' % (frontend, maxconn)) print('success: Maxconn for %s has been set to %s ' % (frontend, maxconn))
@ -495,12 +507,14 @@ if form.getvalue('action_service') is not None:
elif action == "start": elif action == "start":
cmd = "sudo systemctl enable %s --now" % serv cmd = "sudo systemctl enable %s --now" % serv
if not sql.select_user_status(): if not sql.select_user_status():
print('warning: The service is disabled because you are not subscribed. Read <a href="https://roxy-wi.org/pricing.py" title="Roxy-WI pricing" target="_blank">here</a> about subscriptions') print('warning: The service is disabled because you are not subscribed. Read <a href="https://roxy-wi.org/pricing.py" '
'title="Roxy-WI pricing" target="_blank">here</a> about subscriptions')
sys.exit() sys.exit()
elif action == "restart": elif action == "restart":
cmd = "sudo systemctl restart %s --now" % serv cmd = "sudo systemctl restart %s --now" % serv
if not sql.select_user_status(): if not sql.select_user_status():
print('warning: The service is disabled because you are not subscribed. Read <a href="https://roxy-wi.org/pricing.py" title="Roxy-WI pricing" target="_blank">here</a> about subscriptions') print('warning: The service is disabled because you are not subscribed. Read <a href="https://roxy-wi.org/pricing.py" '
'title="Roxy-WI pricing" target="_blank">here</a> about subscriptions')
sys.exit() sys.exit()
if is_in_docker: if is_in_docker:
cmd = "sudo supervisorctl " + action + " " + serv cmd = "sudo supervisorctl " + action + " " + serv
@ -1277,14 +1291,17 @@ if form.getvalue('master'):
master = form.getvalue('master') master = form.getvalue('master')
slave = form.getvalue('slave') slave = form.getvalue('slave')
ETH = form.getvalue('interface') ETH = form.getvalue('interface')
ETH_SLAVE = form.getvalue('slave_interface')
IP = form.getvalue('vrrpip') IP = form.getvalue('vrrpip')
syn_flood = form.getvalue('syn_flood') syn_flood = form.getvalue('syn_flood')
virt_server = form.getvalue('virt_server') virt_server = form.getvalue('virt_server')
return_to_master = form.getvalue('return_to_master') return_to_master = form.getvalue('return_to_master')
haproxy = form.getvalue('hap') haproxy = form.getvalue('hap')
nginx = form.getvalue('nginx') nginx = form.getvalue('nginx')
router_id = form.getvalue('router_id')
script = "install_keepalived.sh" script = "install_keepalived.sh"
proxy = sql.get_setting('proxy') proxy = sql.get_setting('proxy')
keepalived_path_logs = sql.get_setting('keepalived_path_logs')
ssh_port = 22 ssh_port = 22
ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path(master) ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path(master)
@ -1303,9 +1320,9 @@ if form.getvalue('master'):
os.system("cp scripts/%s ." % script) os.system("cp scripts/%s ." % script)
commands = [ commands = [
"chmod +x " + script + " && ./" + script + " PROXY=" + proxy_serv + " SSH_PORT=" + ssh_port "chmod +x " + script + " && ./" + script + " PROXY=" + proxy_serv + " SSH_PORT=" + ssh_port + " router_id=" + router_id
+ " ETH=" + ETH + " IP=" + str(IP) + " MASTER=MASTER" + " RETURN_TO_MASTER=" + return_to_master + " ETH=" + ETH + " IP=" + str(IP) + " MASTER=MASTER" + " ETH_SLAVE=" + ETH_SLAVE + " keepalived_path_logs=" + keepalived_path_logs
+ " SYN_FLOOD=" + syn_flood + " HOST=" + str(master) + " RETURN_TO_MASTER=" + return_to_master + " SYN_FLOOD=" + syn_flood + " HOST=" + str(master)
+ " USER=" + str(ssh_user_name) + " PASS='" + str(ssh_user_password) + "' KEY=" + str(ssh_key_name) + " USER=" + str(ssh_user_name) + " PASS='" + str(ssh_user_password) + "' KEY=" + str(ssh_key_name)
] ]
@ -1324,10 +1341,13 @@ if form.getvalue('master_slave'):
master = form.getvalue('master_slave') master = form.getvalue('master_slave')
slave = form.getvalue('slave') slave = form.getvalue('slave')
ETH = form.getvalue('interface') ETH = form.getvalue('interface')
ETH_SLAVE = form.getvalue('slave_interface')
IP = form.getvalue('vrrpip') IP = form.getvalue('vrrpip')
syn_flood = form.getvalue('syn_flood') syn_flood = form.getvalue('syn_flood')
router_id = form.getvalue('router_id')
script = "install_keepalived.sh" script = "install_keepalived.sh"
proxy = sql.get_setting('proxy') proxy = sql.get_setting('proxy')
keepalived_path_logs = sql.get_setting('keepalived_path_logs')
ssh_port = 22 ssh_port = 22
ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path(slave) ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path(slave)
@ -1346,9 +1366,10 @@ if form.getvalue('master_slave'):
os.system("cp scripts/%s ." % script) os.system("cp scripts/%s ." % script)
commands = [ commands = [
"chmod +x " + script + " && ./" + script + " PROXY=" + proxy_serv + " SSH_PORT=" + ssh_port "chmod +x " + script + " && ./" + script + " PROXY=" + proxy_serv + " SSH_PORT=" + ssh_port + " router_id=" + router_id
+ " ETH=" + ETH + " IP=" + IP + " MASTER=BACKUP" + " HOST=" + str(slave) + " ETH=" + ETH + " IP=" + IP + " MASTER=BACKUP" + " ETH_SLAVE=" + ETH_SLAVE + " keepalived_path_logs=" + keepalived_path_logs
+ " USER=" + str(ssh_user_name) + " PASS='" + str(ssh_user_password) + "' KEY=" + str(ssh_key_name) + " HOST=" + str(slave) + " USER=" + str(ssh_user_name) + " PASS='" + str(ssh_user_password)
+ "' KEY=" + str(ssh_key_name)
] ]
output, error = funct.subprocess_execute(commands[0]) output, error = funct.subprocess_execute(commands[0])
@ -1363,11 +1384,14 @@ if form.getvalue('masteradd'):
master = form.getvalue('masteradd') master = form.getvalue('masteradd')
slave = form.getvalue('slaveadd') slave = form.getvalue('slaveadd')
ETH = form.getvalue('interfaceadd') ETH = form.getvalue('interfaceadd')
SLAVE_ETH = form.getvalue('slave_interfaceadd')
IP = form.getvalue('vrrpipadd') IP = form.getvalue('vrrpipadd')
router_id = form.getvalue('router_id')
kp = form.getvalue('kp') kp = form.getvalue('kp')
return_to_master = form.getvalue('return_to_master') return_to_master = form.getvalue('return_to_master')
script = "install_keepalived.sh" script = "install_keepalived.sh"
proxy = sql.get_setting('proxy') proxy = sql.get_setting('proxy')
keepalived_path_logs = sql.get_setting('keepalived_path_logs')
ssh_port = 22 ssh_port = 22
ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path(master) ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path(master)
@ -1386,9 +1410,9 @@ if form.getvalue('masteradd'):
ssh_port = str(server[10]) ssh_port = str(server[10])
commands = [ commands = [
"chmod +x " + script + " && ./" + script + " PROXY=" + proxy_serv "chmod +x " + script + " && ./" + script + " PROXY=" + proxy_serv + " SSH_PORT=" + ssh_port + " ETH=" + ETH
+ " SSH_PORT=" + ssh_port + " ETH=" + ETH + " RETURN_TO_MASTER=" + return_to_master + " SLAVE_ETH=" + SLAVE_ETH + " keepalived_path_logs=" + keepalived_path_logs + " RETURN_TO_MASTER=" + return_to_master
+ " IP=" + str(IP) + " MASTER=MASTER" + " RESTART=" + kp + " ADD_VRRP=1 HOST=" + str(master) + " IP=" + str(IP) + " MASTER=MASTER" + " RESTART=" + kp + " ADD_VRRP=1 HOST=" + str(master) + " router_id=" + router_id
+ " USER=" + str(ssh_user_name) + " PASS='" + str(ssh_user_password) + "' KEY=" + str(ssh_key_name) + " USER=" + str(ssh_user_name) + " PASS='" + str(ssh_user_password) + "' KEY=" + str(ssh_key_name)
] ]
@ -1400,10 +1424,13 @@ if form.getvalue('masteradd_slave'):
master = form.getvalue('masteradd_slave') master = form.getvalue('masteradd_slave')
slave = form.getvalue('slaveadd') slave = form.getvalue('slaveadd')
ETH = form.getvalue('interfaceadd') ETH = form.getvalue('interfaceadd')
SLAVE_ETH = form.getvalue('slave_interfaceadd')
IP = form.getvalue('vrrpipadd') IP = form.getvalue('vrrpipadd')
router_id = form.getvalue('router_id')
kp = form.getvalue('kp') kp = form.getvalue('kp')
script = "install_keepalived.sh" script = "install_keepalived.sh"
proxy = sql.get_setting('proxy') proxy = sql.get_setting('proxy')
keepalived_path_logs = sql.get_setting('keepalived_path_logs')
ssh_port = 22 ssh_port = 22
ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path(slave) ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path(slave)
@ -1423,8 +1450,8 @@ if form.getvalue('masteradd_slave'):
commands = [ commands = [
"chmod +x " + script + " && ./" + script + " PROXY=" + proxy_serv "chmod +x " + script + " && ./" + script + " PROXY=" + proxy_serv
+ " SSH_PORT=" + ssh_port + " ETH=" + ETH + " SSH_PORT=" + ssh_port + " ETH=" + ETH + " SLAVE_ETH=" + SLAVE_ETH + " keepalived_path_logs=" + keepalived_path_logs
+ " IP=" + str(IP) + " MASTER=BACKUP" + " RESTART=" + kp + " ADD_VRRP=1 HOST=" + str(slave) + " IP=" + str(IP) + " MASTER=BACKUP" + " RESTART=" + kp + " ADD_VRRP=1 HOST=" + str(slave) + " router_id=" + router_id
+ " USER=" + str(ssh_user_name) + " PASS='" + str(ssh_user_password) + "' KEY=" + str(ssh_key_name) + " USER=" + str(ssh_user_name) + " PASS='" + str(ssh_user_password) + "' KEY=" + str(ssh_key_name)
] ]
@ -2556,7 +2583,7 @@ if form.getvalue('slackdel') is not None:
slack = sql.select_slack(id=slackdel) slack = sql.select_slack(id=slackdel)
slack_name = '' slack_name = ''
for t in slack: for t in slack:
slack_name = t[1] slack_name = t.chanel_name
if sql.delete_slack(slackdel): if sql.delete_slack(slackdel):
print("Ok") print("Ok")
funct.logging('localhost', 'The Slack channel ' + slack_name + ' has been deleted ', haproxywi=1, login=1) funct.logging('localhost', 'The Slack channel ' + slack_name + ' has been deleted ', haproxywi=1, login=1)
@ -3889,7 +3916,7 @@ if form.getvalue('loadservices'):
if form.getvalue('loadchecker'): if form.getvalue('loadchecker'):
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates')) env = Environment(loader=FileSystemLoader('templates'), autoescape=True)
template = env.get_template('ajax/load_telegram.html') template = env.get_template('ajax/load_telegram.html')
services = funct.get_services_status() services = funct.get_services_status()
groups = sql.select_groups() groups = sql.select_groups()

View File

@ -1,3 +1,6 @@
--- ---
- name: restart keepalived - name: restart keepalived
service: name=keepalived state=restarted service: name=keepalived state=restarted
- name: restart rsyslog
service: name=restart state=restarted

View File

@ -3,7 +3,6 @@
package_facts: package_facts:
manager: "auto" manager: "auto"
- name: install EPEL Repository - name: install EPEL Repository
yum: yum:
name: epel-release name: epel-release
@ -16,10 +15,23 @@
http_proxy: "{{PROXY}}" http_proxy: "{{PROXY}}"
https_proxy: "{{PROXY}}" https_proxy: "{{PROXY}}"
- name: Creates log directory
file:
path: "{{keepalived_path_logs}}"
state: directory
- name: Copy keepalived configuration for rsyslog.
template:
src: rsyslog.conf.j2
dest: /etc/rsyslog.d/50-keepalived.conf
mode: 0644
notify: restart rsyslog
- name: Install the latest version of Keepalived - name: Install the latest version of Keepalived
package: package:
name: keepalived name:
- keepalived
- psmisc
state: present state: present
when: "'keepalived' not in ansible_facts.packages" when: "'keepalived' not in ansible_facts.packages"
environment: environment:

View File

@ -1,6 +1,6 @@
vrrp_instance VI_{{IP}} { vrrp_instance VI_{{IP}} {
state {{MASTER}} state {{MASTER}}
interface {{ETH}} interface {% if MASTER == 'MASTER' %}{{ETH}} {% else %} {{ETH_SLAVE}} {% endif %}
virtual_router_id {{ router_id }} virtual_router_id {{ router_id }}
priority {% if RETURN_TO_MASTER == 1 and MASTER == 'MASTER' %}152{% elif MASTER == 'MASTER' and RETURN_TO_MASTER == 0 %}102{% else %}101{%endif%} priority {% if RETURN_TO_MASTER == 1 and MASTER == 'MASTER' %}152{% elif MASTER == 'MASTER' and RETURN_TO_MASTER == 0 %}102{% else %}101{%endif%}

View File

@ -9,7 +9,8 @@ vrrp_script chk_haproxy {
} }
vrrp_instance VI_1 { vrrp_instance VI_1 {
state {{MASTER}} state {{MASTER}}
interface {{ETH}} interface {% if MASTER == 'MASTER' %}{{ETH}} {% else %} {{ETH_SLAVE}} {% endif %}
virtual_router_id {{router_id}} virtual_router_id {{router_id}}
priority {% if RETURN_TO_MASTER == '1' and MASTER == 'MASTER' %}152{% elif MASTER == 'MASTER' and RETURN_TO_MASTER == '0' %}102{% else %}101{%endif%} priority {% if RETURN_TO_MASTER == '1' and MASTER == 'MASTER' %}152{% elif MASTER == 'MASTER' and RETURN_TO_MASTER == '0' %}102{% else %}101{%endif%}

View File

@ -0,0 +1,15 @@
$ModLoad imudp
$UDPServerAddress 127.0.0.1
$UDPServerRun 514
if $programname startswith 'Keepalived_vrrp' then {
if $syslogseverity == 6 then
action(type="omfile" file="{{keepalived_path_logs}}/status.log")
stop
if $syslogseverity <= 3 then
action(type="omfile" file="{{keepalived_path_logs}}/error.log")
stop
if $syslogseverity <= 5 then
action(type="omfile" file="{{keepalived_path_logs}}/status.log")
stop
}

View File

@ -5,19 +5,22 @@ do
VALUE=$(echo $ARGUMENT | cut -f2 -d=) VALUE=$(echo $ARGUMENT | cut -f2 -d=)
case "$KEY" in case "$KEY" in
PROXY) PROXY=${VALUE} ;; PROXY) PROXY=${VALUE} ;;
MASTER) MASTER=${VALUE} ;; MASTER) MASTER=${VALUE} ;;
ETH) ETH=${VALUE} ;; ETH) ETH=${VALUE} ;;
IP) IP=${VALUE} ;; ETH_SLAVE) ETH_SLAVE=${VALUE} ;;
HOST) HOST=${VALUE} ;; keepalived_path_logs) keepalived_path_logs=${VALUE} ;;
USER) USER=${VALUE} ;; IP) IP=${VALUE} ;;
PASS) PASS=${VALUE} ;; HOST) HOST=${VALUE} ;;
KEY) KEY=${VALUE} ;; USER) USER=${VALUE} ;;
router_id) router_id=${VALUE} ;;
PASS) PASS=${VALUE} ;;
KEY) KEY=${VALUE} ;;
SYN_FLOOD) SYN_FLOOD=${VALUE} ;; SYN_FLOOD) SYN_FLOOD=${VALUE} ;;
RESTART) RESTART=${VALUE} ;; RESTART) RESTART=${VALUE} ;;
RETURN_TO_MASTER) RETURN_TO_MASTER=${VALUE} ;; RETURN_TO_MASTER) RETURN_TO_MASTER=${VALUE} ;;
ADD_VRRP) ADD_VRRP=${VALUE} ;; ADD_VRRP) ADD_VRRP=${VALUE} ;;
SSH_PORT) SSH_PORT=${VALUE} ;; SSH_PORT) SSH_PORT=${VALUE} ;;
*) *)
esac esac
done done
@ -31,12 +34,11 @@ export COMMAND_WARNINGS=False
PWD=`pwd` PWD=`pwd`
PWD=$PWD/scripts/ansible/ PWD=$PWD/scripts/ansible/
echo "$HOST ansible_port=$SSH_PORT" > $PWD/$HOST echo "$HOST ansible_port=$SSH_PORT" > $PWD/$HOST
router_id=`echo $((1 + $RANDOM % 255))`
if [[ $KEY == "" ]]; then if [[ $KEY == "" ]]; then
ansible-playbook $PWD/roles/keepalived.yml -e "ansible_user=$USER ansible_ssh_pass='$PASS' variable_host=$HOST SYN_FLOOD=$SYN_FLOOD PROXY=$PROXY MASTER=$MASTER ETH=$ETH IP=$IP RESTART=$RESTART RETURN_TO_MASTER=$RETURN_TO_MASTER ADD_VRRP=$ADD_VRRP router_id=$router_id SSH_PORT=$SSH_PORT" -i $PWD/$HOST ansible-playbook $PWD/roles/keepalived.yml -e "ansible_user=$USER ansible_ssh_pass='$PASS' variable_host=$HOST SYN_FLOOD=$SYN_FLOOD PROXY=$PROXY MASTER=$MASTER ETH=$ETH ETH_SLAVE=$ETH_SLAVE keepalived_path_logs=$keepalived_path_logs IP=$IP RESTART=$RESTART RETURN_TO_MASTER=$RETURN_TO_MASTER ADD_VRRP=$ADD_VRRP router_id=$router_id SSH_PORT=$SSH_PORT" -i $PWD/$HOST
else else
ansible-playbook $PWD/roles/keepalived.yml --key-file $KEY -e "ansible_user=$USER variable_host=$HOST SYN_FLOOD=$SYN_FLOOD PROXY=$PROXY MASTER=$MASTER ETH=$ETH IP=$IP RESTART=$RESTART RETURN_TO_MASTER=$RETURN_TO_MASTER ADD_VRRP=$ADD_VRRP router_id=$router_id SSH_PORT=$SSH_PORT" -i $PWD/$HOST ansible-playbook $PWD/roles/keepalived.yml --key-file $KEY -e "ansible_user=$USER variable_host=$HOST SYN_FLOOD=$SYN_FLOOD PROXY=$PROXY MASTER=$MASTER ETH=$ETH ETH_SLAVE=$ETH_SLAVE keepalived_path_logs=$keepalived_path_logs IP=$IP RESTART=$RESTART RETURN_TO_MASTER=$RETURN_TO_MASTER ADD_VRRP=$ADD_VRRP router_id=$router_id SSH_PORT=$SSH_PORT" -i $PWD/$HOST
fi fi
if [ $? -gt 0 ] if [ $? -gt 0 ]

View File

@ -1038,9 +1038,9 @@ def select_telegram(**kwargs):
return query_res return query_res
def insert_new_telegram(token, chanel, group): def insert_new_telegram(token, channel, group):
try: try:
Telegram.insert(token=token, chanel_name=chanel, groups=group).execute() Telegram.insert(token=token, chanel_name=channel, groups=group).execute()
except Exception as e: except Exception as e:
out_error(e) out_error(e)
return False return False
@ -1048,8 +1048,8 @@ def insert_new_telegram(token, chanel, group):
return True return True
def update_telegram(token, chanel, group, telegram_id): def update_telegram(token, channel, group, telegram_id):
telegram_update = Telegram.update(token=token, chanel_name=chanel, groups=group).where(Telegram.id == telegram_id) telegram_update = Telegram.update(token=token, chanel_name=channel, groups=group).where(Telegram.id == telegram_id)
try: try:
telegram_update.execute() telegram_update.execute()
except Exception as e: except Exception as e:

View File

@ -119,6 +119,7 @@
<li><a href="/app/hapservers.py?service=keepalived" title="Overview Keepalived servers" class="overview-link head-submenu">Overview</a> </li> <li><a href="/app/hapservers.py?service=keepalived" title="Overview Keepalived servers" class="overview-link head-submenu">Overview</a> </li>
<li><a href="/app/ha.py" title="Create and configure HA cluster - Roxy-WI" class="keepalived head-submenu">HA</a></li> <li><a href="/app/ha.py" title="Create and configure HA cluster - Roxy-WI" class="keepalived head-submenu">HA</a></li>
<li><a href="/app/config.py?service=keepalived" title="Working with Keepalived configs" class="edit head-submenu">Configs</a></li> <li><a href="/app/config.py?service=keepalived" title="Working with Keepalived configs" class="edit head-submenu">Configs</a></li>
<li><a href="/app/logs.py?service=keepalived" title="Keepalived logs " class="logs head-submenu">Logs</a></li>
<li><a href="/app/versions.py?service=keepalived" title="Working with versions Keepalived configs" class="version head-submenu keepalived_versions">Versions</a></li> <li><a href="/app/versions.py?service=keepalived" title="Working with versions Keepalived configs" class="version head-submenu keepalived_versions">Versions</a></li>
</ul> </ul>
</li> </li>

View File

@ -17,9 +17,9 @@
<td class="padding10 first-collumn">Master</td> <td class="padding10 first-collumn">Master</td>
<td class="padding10 first-collumn">Current installation</td> <td class="padding10 first-collumn">Current installation</td>
<td>Slave</td> <td>Slave</td>
<td><span title="Interface for VRRP address">Interface</span></td> <td><span title="Interface for VRRP address on a Master slave">Master Interface</span></td>
<td><span title="Interface for VRRP address on a Slave server">Slave Interface</span></td>
<td>VRRP IP</td> <td>VRRP IP</td>
<td class="checkbox-head help_cursor"><span title="Roxy-WI will add VRRP address as a separated server">Add VIRT</span></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
@ -41,13 +41,13 @@
{% endfor %} {% endfor %}
</select> </select>
</td> </td>
<td>{{ input('interface', size='7', title='Interface for VRRP address') }}</td> <td>{{ input('interface', size='7', title='Interface for VRRP address on a Master server') }}</td>
<td>{{ input('slave_interface', size='7', title='Interface for VRRP address a Slave server') }}</td>
<td>{{ input('vrrp-ip', size='14') }}</td> <td>{{ input('vrrp-ip', size='14') }}</td>
<td class="checkbox help_cursor">{{ checkbox('virt_server', title='Roxy-WI will add VRRP address as a separated server', checked='checked') }}</td>
</tr> </tr>
<tr class="overviewHead"> <tr class="overviewHead">
<td class="padding10 first-collumn"></td> <td class="padding10 first-collumn"></td>
<td></td> <td class="checkbox-head help_cursor"><span title="Roxy-WI will add VRRP address as a separated server">Add VIRT</span></td>
<td class="padding10 syn-flood-protection-field help_cursor" title="If checked, Keepalived master will reclaim VRRP after recovered">Return to Master state</td> <td class="padding10 syn-flood-protection-field help_cursor" title="If checked, Keepalived master will reclaim VRRP after recovered">Return to Master state</td>
<td class="checkbox-head">SYN-flood protection</td> <td class="checkbox-head">SYN-flood protection</td>
<td class="checkbox-head help_cursor" style="padding: 10px 10px 10px 0;"><span title="Roxy-WI will try to install HAProxy">HAProxy</span></td> <td class="checkbox-head help_cursor" style="padding: 10px 10px 10px 0;"><span title="Roxy-WI will try to install HAProxy">HAProxy</span></td>
@ -59,7 +59,7 @@
</tr> </tr>
<tr> <tr>
<td class="padding10 first-collumn"></td> <td class="padding10 first-collumn"></td>
<td></td> <td class="checkbox help_cursor">{{ checkbox('virt_server', title='Roxy-WI will add VRRP address as a separated server', checked='checked') }}</td>
<td class="checkbox-head syn-flood-protection-field help_cursor">{{ checkbox('return_to_master', checked='checked') }}</td> <td class="checkbox-head syn-flood-protection-field help_cursor">{{ checkbox('return_to_master', checked='checked') }}</td>
<td class="syn-flood-protection-field">{{ checkbox('syn_flood') }}</td> <td class="syn-flood-protection-field">{{ checkbox('syn_flood') }}</td>
<td class="checkbox help_cursor" style="padding: 10px 10px 10px 15px;">{{ checkbox('hap', title='Roxy-WI will try to install HAProxy') }}</td> <td class="checkbox help_cursor" style="padding: 10px 10px 10px 15px;">{{ checkbox('hap', title='Roxy-WI will try to install HAProxy') }}</td>
@ -80,11 +80,9 @@
<td class="padding10 first-collumn">Master</td> <td class="padding10 first-collumn">Master</td>
<td class="padding10 first-collumn">Current installation</td> <td class="padding10 first-collumn">Current installation</td>
<td>Slave</td> <td>Slave</td>
<td><span title="Interface for VRRP address">Interface</span></td> <td><span title="Interface for VRRP address on a Master Server">Master Interface</span></td>
<td><span title="Interface for VRRP address on a Slave Server">Slave Interface</span></td>
<td>VRRP IP</td> <td>VRRP IP</td>
<td class="checkbox-head"><span title="If checked Roxy-WI will restart Keepalived">Restart</span></td>
<td class="checkbox-head help_cursor" title="If checked, Keepalived master will reclaim VRRP after recovered">Return to Master state</td>
<td></td>
</tr> </tr>
<tr> <tr>
<td class="padding10 first-collumn" id="cur_master_ver-add"></td> <td class="padding10 first-collumn" id="cur_master_ver-add"></td>
@ -106,8 +104,24 @@
</select> </select>
</td> </td>
<td>{{ input('interface-add', size='7', title='Interface for VRRP address') }}</td> <td>{{ input('interface-add', size='7', title='Interface for VRRP address') }}</td>
<td>{{ input('slave_interface-add', size='7', title='Interface for VRRP address') }}</td>
<td>{{ input('vrrp-ip-add', size='14') }}</td> <td>{{ input('vrrp-ip-add', size='14') }}</td>
<td class="checkbox help_cursor">{{ checkbox('kp', title='If checked Roxy-WI will restart Keepalived') }}</td> </tr>
<tr class="overviewHead">
<td></td>
<td></td>
<td></td>
<td></td>
<td class="padding10 first-collumn checkbox-head"><span title="If checked Roxy-WI will restart Keepalived">Restart</span></td>
<td class="checkbox-head help_cursor" title="If checked, Keepalived master will reclaim VRRP after recovered">Return to Master state</td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="padding10 first-collumn checkbox help_cursor">{{ checkbox('kp', title='If checked Roxy-WI will restart Keepalived') }}</td>
<td class="syn-flood-protection-field">{{ checkbox('add_return_to_master', checked='checked') }}</td> <td class="syn-flood-protection-field">{{ checkbox('add_return_to_master', checked='checked') }}</td>
<td> <td>
<button id="add-vrrp" title="Add a HA configuration" style="width: 70px;">Add</button> <button id="add-vrrp" title="Add a HA configuration" style="width: 70px;">Add</button>

View File

@ -278,9 +278,7 @@
{% if service != 'keepalived' and service != 'apache' %} {% if service != 'keepalived' and service != 'apache' %}
<a href="/app/viewsttats.py?service={{service}}&serv={{s.2}}" class="ui-button ui-widget ui-corner-all" title="View {{service}} statistics">Stat</a> <a href="/app/viewsttats.py?service={{service}}&serv={{s.2}}" class="ui-button ui-widget ui-corner-all" title="View {{service}} statistics">Stat</a>
{% endif %} {% endif %}
{% if service != 'keepalived' %}
<a href="/app/logs.py?service={{service}}&serv={{s.2}}&rows=10&grep=&hour=00&minut=00&hour1=24&minut1=00" class="ui-button ui-widget ui-corner-all" title="View {{service}} logs">Logs</a> <a href="/app/logs.py?service={{service}}&serv={{s.2}}&rows=10&grep=&hour=00&minut=00&hour1=24&minut1=00" class="ui-button ui-widget ui-corner-all" title="View {{service}} logs">Logs</a>
{% endif %}
{% if role <= 2 %} {% if role <= 2 %}
<a href="/app/versions.py?service={{service}}&serv={{s.2}}&open=open" class="ui-button ui-widget ui-corner-all" title="View/Rollback to previous config">Versions</a> <a href="/app/versions.py?service={{service}}&serv={{s.2}}&open=open" class="ui-button ui-widget ui-corner-all" title="View/Rollback to previous config">Versions</a>
{% endif %} {% endif %}

View File

@ -17,7 +17,7 @@
<div class="div-pannel"> <div class="div-pannel">
<div class="div-server add-proxy-listen-head"> <div class="div-server add-proxy-listen-head">
<div class="server-name"> <div class="server-name">
<span title="Create Listen" class="redirectListen span-link">Create Listen</span> <span title="Create Listener" class="redirectListen span-link">Create Listener</span>
</div> </div>
<div class="server-desc add_proxy"> <div class="server-desc add_proxy">
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. 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.
@ -27,7 +27,7 @@
<div class="div-pannel"> <div class="div-pannel">
<div class="div-server add-proxy-listen-head"> <div class="div-server add-proxy-listen-head">
<div class="server-name"> <div class="server-name">
<span title="Create HTTP Listen" class="redirectListen span-link" id="create-http-listen">Create HTTP Listen</span> <span title="Create HTTP Listener" class="redirectListen span-link" id="create-http-listen">Create HTTP Listener</span>
</div> </div>
<div class="server-desc"> <div class="server-desc">
Create HTTP proxy Create HTTP proxy
@ -37,7 +37,7 @@
<div class="div-pannel"> <div class="div-pannel">
<div class="div-server add-proxy-listen-head"> <div class="div-server add-proxy-listen-head">
<div class="server-name"> <div class="server-name">
<span title="Create SSL Listen" class="redirectListen span-link" id="create-ssl-listen">Create SSL Listen</span> <span title="Create SSL Listener" class="redirectListen span-link" id="create-ssl-listen">Create SSL Listener</span>
</div> </div>
<div class="server-desc add_proxy"> <div class="server-desc add_proxy">
Create HTTPS Proxy with the SSL termination on HAProxy and SSL offload. Create HTTPS Proxy with the SSL termination on HAProxy and SSL offload.
@ -48,7 +48,7 @@
<div class="div-pannel"> <div class="div-pannel">
<div class="div-server add-proxy-listen-head"> <div class="div-server add-proxy-listen-head">
<div class="server-name"> <div class="server-name">
<span title="Create SSL Listen" class="redirectListen span-link" id="create-https-listen">Create HTTPS Listen</span> <span title="Create SSL Listener" class="redirectListen span-link" id="create-https-listen">Create HTTPS Listener</span>
</div> </div>
<div class="server-desc add_proxy"> <div class="server-desc add_proxy">
Create HTTPS Proxy without the SSL termination on HAProxy and SSL offload. HAProxy will send to backends HTTPS traffic Create HTTPS Proxy without the SSL termination on HAProxy and SSL offload. HAProxy will send to backends HTTPS traffic

View File

@ -59,8 +59,8 @@
<td class="padding10 first-collumn" style="width: 20%;"> <td class="padding10 first-collumn" style="width: 20%;">
{% set values = dict() %} {% set values = dict() %}
{% set values = {'2.0.5-1':'2.0.5-1','2.2.4-1':'2.2.4-1','2.3.0-1':'2.3.0-1','2.3.10-1':'2.3.10-1', {% set values = {'2.0.5-1':'2.0.5-1','2.2.4-1':'2.2.4-1','2.3.0-1':'2.3.0-1','2.3.10-1':'2.3.10-1',
'2.4.0-1':'2.4.0-1','2.4.9-1':'2.4.9-1','2.4.15-1':'2.4.15-1','2.5.1-1':'2.5.1-1'} %} '2.4.0-1':'2.4.0-1','2.4.9-1':'2.4.9-1','2.4.15-1':'2.4.15-1','2.5.1-1':'2.5.1-1','2.6.0-1':'2.6.0-1'} %}
{{ select('hapver', values=values, selected='2.5.1-1', required='required') }} {{ select('hapver', values=values, selected='2.6.0-1', required='required') }}
</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">

View File

@ -2005,4 +2005,4 @@ function checkIsServerFiled(select_id, message = 'Select a server first') {
return false; return false;
} }
return true; return true;
} }

165
inc/ha.js
View File

@ -3,7 +3,94 @@ $( function() {
width: 180 width: 180
}); });
var ipformat = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; var ipformat = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
$( "#interface" ).autocomplete({
source: function( request, response ) {
$.ajax( {
url: "options.py",
data: {
showif:1,
serv: $("#master").val(),
token: $('#token').val()
},
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('Failed') != '-1') {
toastr.error(data);
} else {
response(data.split(" "));
}
}
} );
},
autoFocus: true,
minLength: -1
});
$( "#interface-add" ).autocomplete({
source: function( request, response ) {
$.ajax( {
url: "options.py",
data: {
showif:1,
serv: $("#master-add").val(),
token: $('#token').val()
},
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('Failed') != '-1') {
toastr.error(data);
} else {
response(data.split(" "));
}
}
} );
},
autoFocus: true,
minLength: -1
});
$( "#slave_interface" ).autocomplete({
source: function( request, response ) {
$.ajax( {
url: "options.py",
data: {
showif:1,
serv: $("#slave").val(),
token: $('#token').val()
},
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('Failed') != '-1') {
toastr.error(data);
} else {
response(data.split(" "));
}
}
} );
},
autoFocus: true,
minLength: -1
});
$( "#slave_interface-add" ).autocomplete({
source: function( request, response ) {
$.ajax( {
url: "options.py",
data: {
showif:1,
serv: $("#slave").val(),
token: $('#token').val()
},
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('Failed') != '-1') {
toastr.error(data);
} else {
response(data.split(" "));
}
}
} );
},
autoFocus: true,
minLength: -1
});
var server_creating = $( "#server_creating" ).dialog({ var server_creating = $( "#server_creating" ).dialog({
autoOpen: false, autoOpen: false,
width: 574, width: 574,
@ -38,18 +125,26 @@ $( function() {
kp = '0'; kp = '0';
} }
$("#ajax").html('') $("#ajax").html('')
if( $("#master-add").val() == "" || $("#slave-add").val() == "" || $("#interface-add").val() == "" || if( $("#master-add").val() == "") {
$("#vrrp-ip-add").val() == "") { toastr.warning('Select a Master server');
toastr.warning('Please fill in all fields') } else if($("#slave-add").val() == ""){
} else if(! $("#vrrp-ip-add").val().match(ipformat)) { toastr.warning('Select a Slave server');
toastr.warning('Please enter IP in "VRRP IP" field') } else if($("#interface-add").val() == "") {
} else { toastr.warning('Please enter the master interface name')
$("#wait-mess-add").html(wait_mess); } else if ($("#vrrp-ip-add").val() == "") {
address_add.dialog('open'); toastr.warning('Please enter IP in "VRRP IP" field')
add_master_addr(kp); } else if(! $("#vrrp-ip-add").val().match(ipformat)) {
$.getScript("/inc/fontawesome.min.js"); toastr.warning('Please enter IP in "VRRP IP" field')
add_slave_addr(kp); } else if($("#slave_interface-add") == '') {
} toastr.warning('Please enter the slave interface name')
} else {
$("#wait-mess-add").html(wait_mess);
address_add.dialog('open');
const router_id = randomIntFromInterval(1, 255);
add_master_addr(kp, router_id);
$.getScript("/inc/fontawesome.min.js");
add_slave_addr(kp, router_id);
}
}); });
$('#create').click(function() { $('#create').click(function() {
var hap = 0; var hap = 0;
@ -65,19 +160,27 @@ $( function() {
syn_flood = '1'; syn_flood = '1';
} }
$("#ajax").html('') $("#ajax").html('')
if( $("#master").val() == "" || $("#slave").val() == "" || $("#interface").val() == "" || if( $("#master").val() === null){
$("#vrrp-ip").val() == "") { toastr.warning('Select a Master server');
toastr.warning('Please fill in all fields'); } else if($("#slave").val() === null) {
} else if(! $("#vrrp-ip").val().match(ipformat)) { toastr.warning('Select a Slave server');
toastr.warning('Please enter IP in "VRRP IP" field'); } else if($("#interface").val() == "") {
} else if ($("#master").val() == $("#slave").val() ){ toastr.warning('Please enter the master interface name');
toastr.warning('Master and slave must be diff servers'); } else if($("#vrrp-ip").val() == "") {
} else { toastr.warning('Please enter IP in "VRRP IP" field');
} else if(! $("#vrrp-ip").val().match(ipformat)) {
toastr.warning('Please enter IP in "VRRP IP" field');
} else if($("#slave_interface").val() == '') {
toastr.warning('Please enter the slave interface name');
} else if ($("#master").val() == $("#slave").val() ){
toastr.warning('Master and slave must be diff servers');
} else {
$("#wait-mess").html(wait_mess); $("#wait-mess").html(wait_mess);
server_creating.dialog('open'); server_creating.dialog('open');
create_master_keepalived(hap, nginx, syn_flood); const router_id = randomIntFromInterval(1, 255);
create_master_keepalived(hap, nginx, syn_flood, router_id);
$.getScript("/inc/fontawesome.min.js"); $.getScript("/inc/fontawesome.min.js");
create_slave_keepalived(hap, nginx, syn_flood); create_slave_keepalived(hap, nginx, syn_flood, router_id);
if (hap == '1') { if (hap == '1') {
$('#haproxy_installing_div').show(); $('#haproxy_installing_div').show();
} }
@ -201,7 +304,7 @@ $( function() {
} ); } );
}); });
}); });
function add_master_addr(kp) { function add_master_addr(kp, router_id) {
return_to_master = 0 return_to_master = 0
if ($('#add_return_to_master').is(':checked')) { if ($('#add_return_to_master').is(':checked')) {
return_to_master = '1'; return_to_master = '1';
@ -212,9 +315,11 @@ function add_master_addr(kp) {
masteradd: $('#master-add').val(), masteradd: $('#master-add').val(),
slaveadd: $('#slave-add').val(), slaveadd: $('#slave-add').val(),
interfaceadd: $("#interface-add").val(), interfaceadd: $("#interface-add").val(),
slave_interfaceadd: $("#slave_interface-add").val(),
vrrpipadd: $('#vrrp-ip-add').val(), vrrpipadd: $('#vrrp-ip-add').val(),
return_to_master: return_to_master, return_to_master: return_to_master,
kp: kp, kp: kp,
router_id: router_id,
token: $('#token').val() token: $('#token').val()
}, },
type: "POST", type: "POST",
@ -230,15 +335,17 @@ function add_master_addr(kp) {
} }
} ); } );
} }
function add_slave_addr(kp) { function add_slave_addr(kp, router_id) {
$.ajax( { $.ajax( {
url: "options.py", url: "options.py",
data: { data: {
masteradd_slave: $('#master-add').val(), masteradd_slave: $('#master-add').val(),
slaveadd: $('#slave-add').val(), slaveadd: $('#slave-add').val(),
interfaceadd: $("#interface-add").val(), interfaceadd: $("#interface-add").val(),
slave_interfaceadd: $("#slave_interface-add").val(),
vrrpipadd: $('#vrrp-ip-add').val(), vrrpipadd: $('#vrrp-ip-add').val(),
kp: kp, kp: kp,
router_id: router_id,
token: $('#token').val() token: $('#token').val()
}, },
type: "POST", type: "POST",
@ -254,7 +361,7 @@ function add_slave_addr(kp) {
} }
} ); } );
} }
function create_master_keepalived(hap, nginx, syn_flood) { function create_master_keepalived(hap, nginx, syn_flood, router_id) {
if (hap == '0' && nginx == '0') { if (hap == '0' && nginx == '0') {
var progress_value = '50'; var progress_value = '50';
} else if (hap == '1' || nginx == '0') { } else if (hap == '1' || nginx == '0') {
@ -284,12 +391,14 @@ function create_master_keepalived(hap, nginx, syn_flood) {
master: $('#master').val(), master: $('#master').val(),
slave: $('#slave').val(), slave: $('#slave').val(),
interface: $("#interface").val(), interface: $("#interface").val(),
slave_interface: $("#slave_interface").val(),
vrrpip: $('#vrrp-ip').val(), vrrpip: $('#vrrp-ip').val(),
return_to_master: return_to_master, return_to_master: return_to_master,
hap: hap, hap: hap,
nginx: nginx, nginx: nginx,
syn_flood: syn_flood, syn_flood: syn_flood,
virt_server: virt_server, virt_server: virt_server,
router_id: router_id,
token: $('#token').val() token: $('#token').val()
}, },
type: "POST", type: "POST",
@ -315,7 +424,7 @@ function create_master_keepalived(hap, nginx, syn_flood) {
} }
} ); } );
} }
function create_slave_keepalived(hap, nginx, syn_flood) { function create_slave_keepalived(hap, nginx, syn_flood, router_id) {
if (hap == '0' && nginx == '0') { if (hap == '0' && nginx == '0') {
var progress_value = '100'; var progress_value = '100';
} else if (hap == '1' || nginx == '0') { } else if (hap == '1' || nginx == '0') {
@ -337,10 +446,12 @@ function create_slave_keepalived(hap, nginx, syn_flood) {
master_slave: $('#master').val(), master_slave: $('#master').val(),
slave: $('#slave').val(), slave: $('#slave').val(),
interface: $("#interface").val(), interface: $("#interface").val(),
slave_interface: $("#slave_interface").val(),
vrrpip: $('#vrrp-ip').val(), vrrpip: $('#vrrp-ip').val(),
hap: hap, hap: hap,
nginx: nginx, nginx: nginx,
syn_flood: syn_flood, syn_flood: syn_flood,
router_id: router_id,
token: $('#token').val() token: $('#token').val()
}, },
type: "POST", type: "POST",

View File

@ -46,6 +46,8 @@ $( function() {
show_current_page($(this)) show_current_page($(this))
} else if(cur_url[0] == 'logs.py' && cur_url[1].split('&')[0] == 'service=apache' && link2 == 'logs.py?service=apache'){ } else if(cur_url[0] == 'logs.py' && cur_url[1].split('&')[0] == 'service=apache' && link2 == 'logs.py?service=apache'){
show_current_page($(this)) show_current_page($(this))
} else if(cur_url[0] == 'logs.py' && cur_url[1].split('&')[0] == 'service=keepalived' && link2 == 'logs.py?service=keepalived'){
show_current_page($(this))
} else if(cur_url[0] == 'hapservers.py' && cur_url[1].split('&')[0] == 'service=nginx' && link2 == 'hapservers.py?service=nginx'){ } else if(cur_url[0] == 'hapservers.py' && cur_url[1].split('&')[0] == 'service=nginx' && link2 == 'hapservers.py?service=nginx'){
show_current_page($(this)) show_current_page($(this))
} else if(cur_url[0] == 'hapservers.py' && cur_url[1].split('&')[0] == 'service=keepalived' && link2 == 'hapservers.py?service=keepalived'){ } else if(cur_url[0] == 'hapservers.py' && cur_url[1].split('&')[0] == 'service=keepalived' && link2 == 'hapservers.py?service=keepalived'){
@ -1408,3 +1410,6 @@ function waitForElm(selector) {
}); });
}); });
} }
function randomIntFromInterval(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min)
}

View File

@ -2,50 +2,6 @@ var awesome = "/inc/fontawesome.min.js"
$( function() { $( function() {
$( "#backup_tabs" ).tabs(); $( "#backup_tabs" ).tabs();
$( "#interface" ).autocomplete({
source: function( request, response ) {
$.ajax( {
url: "options.py",
data: {
showif:1,
serv: $("#master").val(),
token: $('#token').val()
},
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('Failed') != '-1') {
toastr.error(data);
} else {
response(data.split(" "));
}
}
} );
},
autoFocus: true,
minLength: -1
});
$( "#interface-add" ).autocomplete({
source: function( request, response ) {
$.ajax( {
url: "options.py",
data: {
showif:1,
serv: $("#master-add").val(),
token: $('#token').val()
},
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('Failed') != '-1') {
toastr.error(data);
} else {
response(data.split(" "));
}
}
} );
},
autoFocus: true,
minLength: -1
});
$('#install').click(function() { $('#install').click(function() {
$("#ajax").html('') $("#ajax").html('')
var syn_flood = 0; var syn_flood = 0;
@ -835,6 +791,9 @@ $( function() {
$('#apache-section-head').click(function () { $('#apache-section-head').click(function () {
hideAndShowSettings('apache'); hideAndShowSettings('apache');
}); });
$('#keepalived-section-head').click(function () {
hideAndShowSettings('keepalived');
});
} ); } );
function hideAndShowSettings(section) { function hideAndShowSettings(section) {
var ElemId = $('#' + section + '-section-h3'); var ElemId = $('#' + section + '-section-h3');