Change log: https://roxy-wi.org/changelog.py#6_1
pull/328/head
Pavel Loginov 2022-06-15 10:34:20 +03:00
parent c98011249c
commit 85bcfda2a0
33 changed files with 1272 additions and 282 deletions

View File

@ -362,6 +362,12 @@ if form.getvalue('peers-name') is not None:
config_add = "\n" + name + servers_split
if form.getvalue('generateconfig') is None:
slave_output = ''
try:
server_name = sql.get_hostname_by_server_ip(serv)
except Exception:
server_name = serv
try:
funct.check_is_server_in_group(serv)
if config_add:
@ -380,11 +386,16 @@ if form.getvalue('generateconfig') is None:
MASTERS = sql.is_master(serv)
for master in MASTERS:
if master[0] is not None:
funct.upload_and_restart(master[0], cfg)
slave_output = funct.upload_and_restart(master[0], cfg)
stderr = funct.upload_and_restart(serv, cfg, just_save="save")
if stderr:
print(stderr)
slave_output = '<br>' + master[1] + ':\n' + slave_output
output = funct.upload_and_restart(serv, cfg, just_save="save")
output = '<br>' + server_name + ':\n' + output
output = output + slave_output
if output:
print(output)
else:
print(name)

View File

@ -130,15 +130,14 @@ if serv is not None and form.getvalue('config') is not None:
funct.diff_config(oldcfg, cfg)
try:
os.system("/bin/rm -f " + configs_dir + "*.old")
except Exception as e:
print('error: ' + str(e))
if stderr:
print(stderr)
else:
if save == 'test':
print('Config is ok')
else:
print('Config is ok <br /> Config has been updated')
sys.exit()
template = template.render(

View File

@ -58,8 +58,8 @@ def default_values():
'desc': 'Socket port for HAProxy', 'group': '1'},
{'param': 'haproxy_sock_port', 'value': '1999', 'section': 'haproxy', 'desc': 'HAProxy sock port',
'group': '1'},
{'param': 'apache_log_path', 'value': '/var/log/' + apache_dir + '/', 'section': 'logs', 'desc': 'Path to Apache logs',
'group': '1'},
{'param': 'apache_log_path', 'value': '/var/log/' + apache_dir + '/', 'section': 'logs',
'desc': 'Path to Apache logs. Apache service for Roxy-WI', 'group': '1'},
{'param': 'nginx_path_logs', 'value': '/var/log/nginx/', 'section': 'nginx',
'desc': 'The path for NGINX logs', 'group': '1'},
{'param': 'nginx_stats_user', 'value': 'admin', 'section': 'nginx', 'desc': 'Username for accessing NGINX stats page',
@ -74,8 +74,7 @@ def default_values():
'desc': 'Path to the NGINX directory with config files', 'group': '1'},
{'param': 'nginx_config_path', 'value': '/etc/nginx/nginx.conf', 'section': 'nginx',
'desc': 'Path to the main NGINX configuration file', 'group': '1'},
{'param': 'ldap_enable', 'value': '0', 'section': 'ldap', 'desc': 'Enable LDAP (1 - yes, 0 - no)',
'group': '1'},
{'param': 'ldap_enable', 'value': '0', 'section': 'ldap', 'desc': 'Enable LDAP', 'group': '1'},
{'param': 'ldap_server', 'value': '', 'section': 'ldap', 'desc': 'IP address of the LDAP server', 'group': '1'},
{'param': 'ldap_port', 'value': '389', 'section': 'ldap', 'desc': 'LDAP port (port 389 or 636 is used by default)',
'group': '1'},
@ -90,7 +89,7 @@ def default_values():
{'param': 'ldap_user_attribute', 'value': 'sAMAccountName', 'section': 'ldap',
'desc': 'Attribute to search users by', 'group': '1'},
{'param': 'ldap_search_field', 'value': 'mail', 'section': 'ldap', 'desc': 'User\'s email address', 'group': '1'},
{'param': 'ldap_type', 'value': '0', 'section': 'ldap', 'desc': 'Use LDAPS (1 - yes, 0 - no)', 'group': '1'},
{'param': 'ldap_type', 'value': '0', 'section': 'ldap', 'desc': 'Use LDAPS', 'group': '1'},
{'param': 'smon_check_interval', 'value': '1', 'section': 'monitoring', 'desc': 'Check interval for SMON (in minutes)',
'group': '1'},
{'param': 'port_scan_interval', 'value': '5', 'section': 'monitoring',
@ -132,6 +131,12 @@ def default_values():
'desc': 'Path to the main Keepalived configuration file', 'group': '1'},
{'param': 'keepalived_path_logs', 'value': '/var/log/keepalived/', 'section': 'keepalived',
'desc': 'The path for Keepalived logs', 'group': '1'},
{'param': 'mail_ssl', 'value': '0', 'section': 'mail', 'desc': 'Enable TLS', 'group': '1'},
{'param': 'mail_from', 'value': '', 'section': 'mail', 'desc': 'Address of sender', 'group': '1'},
{'param': 'mail_smtp_host', 'value': '', 'section': 'mail', 'desc': 'SMTP server address', 'group': '1'},
{'param': 'mail_smtp_port', 'value': '25', 'section': 'mail', 'desc': 'SMTP server port', 'group': '1'},
{'param': 'mail_smtp_user', 'value': '', 'section': 'mail', 'desc': 'User for auth', 'group': '1'},
{'param': 'mail_smtp_password', 'value': '', 'section': 'mail', 'desc': 'Password for auth', 'group': '1'},
]
try:
Setting.insert_many(data_source).on_conflict_ignore().execute()
@ -722,8 +727,24 @@ def update_db_v_6_0_1(**kwargs):
print("Updating... DB has been updated to version 6.0.0.0-1")
def update_db_v_6_1_0(**kwargs):
for service_id in range(1, 5):
try:
servers_id = Server.select(Server.server_id).where(Server.type_ip == 0).execute()
for server_id in servers_id:
CheckerSetting.insert(
server_id=server_id, service_id=service_id
).on_conflict_ignore().execute()
except Exception as e:
if kwargs.get('silent') != 1:
if e.args[0] == 'duplicate column name: haproxy' or str(e) == '(1060, "Duplicate column name \'haproxy\'")':
print('Updating... go to version 6.1.0')
else:
print("An error occurred:", e)
def update_ver():
query = Version.update(version='6.0.3.0')
query = Version.update(version='6.1.0.0')
try:
query.execute()
except Exception:
@ -749,6 +770,7 @@ def update_all():
update_db_v_5_4_3_1()
update_db_v_6_0()
update_db_v_6_0_1()
update_db_v_6_1_0()
update_ver()

View File

@ -510,10 +510,26 @@ class GitSetting(BaseModel):
constraints = [SQL('UNIQUE (server_id, service_id)')]
class CheckerSetting(BaseModel):
id = AutoField()
server_id = ForeignKeyField(Server, on_delete='Cascade')
service_id = IntegerField()
email = IntegerField(constraints=[SQL('DEFAULT 1')])
telegram_id = IntegerField(constraints=[SQL('DEFAULT 0')])
slack_id = IntegerField(constraints=[SQL('DEFAULT 0')])
service_alert = IntegerField(constraints=[SQL('DEFAULT 1')])
backend_alert = IntegerField(constraints=[SQL('DEFAULT 1')])
maxconn_alert = IntegerField(constraints=[SQL('DEFAULT 1')])
class Meta:
table_name = 'checker_setting'
constraints = [SQL('UNIQUE (server_id, service_id)')]
def create_tables():
with conn:
conn.create_tables([User, Server, Role, Telegram, Slack, UUID, Token, ApiToken, Groups, UserGroups, ConfigVersion,
Setting, Cred, Backup, Metrics, WafMetrics, Version, Option, SavedServer, Waf, ActionHistory,
PortScannerSettings, PortScannerPorts, PortScannerHistory, ProvidersCreds, ServiceSetting,
ProvisionedServers, MetricsHttpStatus, SMON, WafRules, Alerts, GeoipCodes, NginxMetrics,
SystemInfo, Services, UserName, GitSetting])
SystemInfo, Services, UserName, GitSetting, CheckerSetting])

View File

@ -984,9 +984,9 @@ def upload_and_restart(server_ip, cfg, **kwargs):
commands = [move_config + reload_or_restart_command]
elif service == "nginx":
if is_docker == '1':
check_config = "sudo docker exec -it exec " + container_name + " nginx -t -q "
check_config = "sudo docker exec -it exec " + container_name + " nginx -t "
else:
check_config = "sudo nginx -t -q "
check_config = "sudo nginx -t "
check_and_move = "sudo mv -f " + tmp_file + " " + config_path + " && " + check_config
if action == "test":
commands = [check_config + " && sudo rm -f " + tmp_file]
@ -998,10 +998,10 @@ def upload_and_restart(server_ip, cfg, **kwargs):
commands[0] += open_port_firewalld(cfg, server_ip=server_ip, service='nginx')
elif service == "apache":
if is_docker == '1':
check_config = "sudo docker exec -it exec " + container_name + " nginx -t -q "
check_config = "sudo docker exec -it exec " + container_name + " sudo apachectl configtest "
else:
check_config = "sudo apachectl configtest "
check_and_move = "sudo mv -f " + tmp_file + " " + config_path # + " && " + check_config
check_and_move = "sudo mv -f " + tmp_file + " " + config_path + " && " + check_config
if action == "test":
commands = [check_config + " && sudo rm -f " + tmp_file]
elif action == "save":
@ -1012,7 +1012,7 @@ def upload_and_restart(server_ip, cfg, **kwargs):
# commands[0] += open_port_firewalld(cfg, server_ip=server_ip, service='nginx')
else:
if is_docker == '1':
check_config = "sudo docker exec -it " + container_name + " haproxy -q -c -f " + tmp_file
check_config = "sudo docker exec -it " + container_name + " haproxy -c -f " + tmp_file
else:
check_config = "sudo " + service_name + " -c -f " + tmp_file
move_config = " && sudo mv -f " + tmp_file + " " + config_path
@ -1075,28 +1075,37 @@ def upload_and_restart(server_ip, cfg, **kwargs):
def master_slave_upload_and_restart(server_ip, cfg, just_save, **kwargs):
import sql
masters = sql.is_master(server_ip)
slave_error = ''
for master in masters:
if master[0] is not None:
slave_error = upload_and_restart(
master[0], cfg, just_save=just_save, nginx=kwargs.get('nginx'),
apache=kwargs.get('apache'), config_file_name=kwargs.get('config_file_name'), slave=1
)
slave_error = master[0] + ': ' + slave_error
slave_output = ''
try:
server_name = sql.get_hostname_by_server_ip(server_ip)
except Exception:
server_name = serv
if kwargs.get('login'):
login = kwargs.get('login')
else:
login = ''
error = upload_and_restart(
for master in masters:
if master[0] is not None:
slv_output = upload_and_restart(
master[0], cfg, just_save=just_save, nginx=kwargs.get('nginx'),
apache=kwargs.get('apache'), config_file_name=kwargs.get('config_file_name'), slave=1
)
slave_output += '<br>' + master[1] + ':\n' + slv_output
output = upload_and_restart(
server_ip, cfg, just_save=just_save, nginx=kwargs.get('nginx'), apache=kwargs.get('apache'),
config_file_name=kwargs.get('config_file_name'), oldcfg=kwargs.get('oldcfg'), login=login
)
error = server_ip + ': ' + error
error = error + slave_error
return error
output = server_name + ':\n' + output
output = output + slave_output
return output
def open_port_firewalld(cfg, server_ip, **kwargs):
@ -2048,3 +2057,88 @@ def is_docker() -> bool:
if re.match("\d+:[\w=]+:/docker(-[ce]e)?/\w+", line):
return True
return False
def send_email(email_to: str, subject: str, message: str) -> None:
import sql
mail_ssl = sql.get_setting('mail_ssl')
mail_from = sql.get_setting('mail_from')
mail_smtp_host = sql.get_setting('mail_smtp_host')
mail_smtp_port = sql.get_setting('mail_smtp_port')
mail_smtp_user = sql.get_setting('mail_smtp_user')
mail_smtp_password = sql.get_setting('mail_smtp_password')
from smtplib import SMTP
try:
from email.MIMEText import MIMEText
except Exception:
from email.mime.text import MIMEText
from email.message import EmailMessage
msg = MIMEText(message)
msg['Subject'] = 'Roxy-WI: ' + subject
msg['From'] = 'Roxy-WI <' + mail_from + '>'
msg['To'] = email_to
try:
smtpObj = SMTP(mail_smtp_host, mail_smtp_port)
if mail_ssl:
smtpObj.starttls()
smtpObj.login(mail_smtp_user, mail_smtp_password)
smtpObj.send_message(msg)
logging('localhost', 'An email has been sent to ' + email_to , haproxywi=1)
except Exception as e:
logging('localhost', 'error: unable to send email: ' + str(e), haproxywi=1)
def send_email_to_server_group(subject: str, mes: str, group_id: int) -> None:
import sql
try:
users_email = sql.select_users_emails_by_group_id(group_id)
for user_email in users_email:
send_email(user_email.email, subject, mes)
except Exception as e:
logging('localhost', 'error: unable to send email: ' + str(e), haproxywi=1)
def alert_routing(
server_ip: str, service_id: int, group_id: int, level: str, mes: str, alert_type: str) -> None:
import json
import sql
subject: str = level + ': ' + mes
server_id: int = sql.select_server_id_by_ip(server_ip)
checker_settings = sql.select_checker_settings_for_server(service_id, server_id)
try:
json_for_sending = {"user_group": group_id, "message": subject}
send_message_to_rabbit(json.dumps(json_for_sending))
except Exception as e:
logging('localhost', 'error: unable to send message: ' + str(e), haproxywi=1)
for setting in checker_settings:
if alert_type == 'service' and setting.service_alert:
telegram_send_mess(mes, telegram_channel_id=setting.telegram_id)
slack_send_mess(mes, slack_channel_id=setting.slack_id)
if setting.email:
send_email_to_server_group(subject, mes, group_id)
if alert_type == 'backend' and setting.backend_alert:
telegram_send_mess(mes, telegram_channel_id=setting.telegram_id)
slack_send_mess(mes, slack_channel_id=setting.slack_id)
if setting.email:
send_email_to_server_group(subject, mes, group_id)
if alert_type == 'maxconn' and setting.maxconn_alert:
telegram_send_mess(mes, telegram_channel_id=setting.telegram_id)
slack_send_mess(mes, slack_channel_id=setting.slack_id)
if setting.email:
send_email_to_server_group(subject, mes, group_id)

View File

@ -102,7 +102,7 @@ def send_cookie(login):
else:
sql.insert_user_name(user_name)
except Exception:
pass
funct.logging('Cannot update sbscription ', str(e), haproxywi=1)
sys.exit()

View File

@ -1798,7 +1798,7 @@ if form.getvalue('haproxyaddserv'):
if form.getvalue('installwaf'):
funct.waf_install(form.getvalue('installwaf'))
if form.getvalue('update_haproxy_wi'):
if form.getvalue('update_roxy_wi'):
service = form.getvalue('service')
services = ['roxy-wi-checker',
'roxy-wi',
@ -1809,7 +1809,7 @@ if form.getvalue('update_haproxy_wi'):
if service not in services:
print('error: ' + service + ' is not part of Roxy-WI')
sys.exit()
funct.update_haproxy_wi(service)
funct.update_roxy_wi(service)
if form.getvalue('metrics_waf'):
sql.update_waf_metrics_enable(form.getvalue('metrics_waf'), form.getvalue('enable'))
@ -2269,7 +2269,7 @@ if form.getvalue('newserver') is not None:
haproxy_config_path = sql.get_setting('haproxy_config_path')
haproxy_dir = sql.get_setting('haproxy_dir')
apache_config_path = sql.get_setting('apache_config_path')
keepalived_config_path = '/etc/keepalived/keepalived.conf'
keepalived_config_path = sql.get_setting('keepalived_config_path')
if funct.is_file_exists(ip, nginx_config_path):
sql.update_nginx(ip)
@ -2289,8 +2289,13 @@ if form.getvalue('newserver') is not None:
if funct.is_service_active(ip, 'firewalld'):
sql.update_firewall(ip)
except Exception:
pass
except Exception as e:
funct.logging('Cannot scan a new server ' + hostname, str(e), haproxywi=1)
try:
sql.insert_new_checker_setting_for_server(ip)
except Exception as e:
funct.logging('Cannot insert Checker settings for ' + hostname, str(e), haproxywi=1)
try:
funct.get_system_info(ip)
@ -2491,7 +2496,11 @@ if form.getvalue('ssh_cert'):
user_group = funct.get_user_group()
name = form.getvalue('name')
try:
key = paramiko.pkey.load_private_key(form.getvalue('ssh_cert'))
except Exception as e:
print('error: Cannot save SSH key file: ', str(e))
full_dir = '/var/www/haproxy-wi/keys/'
ssh_keys = full_dir + name + '.pem'
@ -2515,8 +2524,8 @@ if form.getvalue('ssh_cert'):
# key.write_private_key_file(ssh_keys, password=cloud)
# else:
key.write_private_key_file(ssh_keys)
except IOError as e:
print('error: Cannot save SSH key file. ', str(e))
except Exception as e:
print('error: Cannot save SSH key file: ', str(e))
else:
print('success: SSH key has been saved into: %s ' % ssh_keys)
@ -2614,7 +2623,7 @@ if form.getvalue('updatesettings') is not None:
settings = form.getvalue('updatesettings')
val = form.getvalue('val')
if sql.update_setting(settings, val):
funct.logging('localhost', 'The ' + settings + ' setting has been changed to: ' + val, haproxywi=1, login=1)
funct.logging('localhost', 'The ' + settings + ' setting has been changed to: ' + str(val), haproxywi=1, login=1)
print("Ok")
if form.getvalue('getuserservices'):
@ -3921,19 +3930,32 @@ if form.getvalue('loadchecker'):
services = funct.get_services_status()
groups = sql.select_groups()
page = form.getvalue('page')
try:
user_status, user_plan = funct.return_user_status()
except Exception as e:
user_status, user_plan = 0, 0
funct.logging('localhost', 'Cannot get a user plan: ' + str(e), haproxywi=1)
if user_status:
haproxy_settings = sql.select_checker_settings(1)
nginx_settings = sql.select_checker_settings(2)
keepalived_settings = sql.select_checker_settings(3)
apache_settings = sql.select_checker_settings(4)
if page == 'servers.py':
user_group = funct.get_user_group(id=1)
telegrams = sql.get_user_telegram_by_group(user_group)
slacks = sql.get_user_slack_by_group(user_group)
haproxy_servers = sql.get_dick_permit(haproxy=1, only_group=1)
nginx_servers = sql.get_dick_permit(nginx=1, only_group=1)
apache_servers = sql.get_dick_permit(apache=1, only_group=1)
keepalived_servers = sql.get_dick_permit(keepalived=1, only_group=1)
else:
telegrams = sql.select_telegram()
slacks = sql.select_slack()
haproxy_servers = sql.get_dick_permit(haproxy=1)
nginx_servers = sql.get_dick_permit(nginx=1)
apache_servers = sql.get_dick_permit(apache=1)
keepalived_servers = sql.get_dick_permit(keepalived=1)
else:
telegrams = ''
slacks = ''
@ -3944,6 +3966,14 @@ if form.getvalue('loadchecker'):
slacks=slacks,
user_status=user_status,
user_plan=user_plan,
haproxy_servers=haproxy_servers,
nginx_servers=nginx_servers,
apache_servers=apache_servers,
keepalived_servers=keepalived_servers,
haproxy_settings=haproxy_settings,
nginx_settings=nginx_settings,
keepalived_settings=keepalived_settings,
apache_settings=apache_settings,
page=page)
print(template)
@ -4010,6 +4040,50 @@ if form.getvalue('check_slack'):
mess = 'Test message from Roxy-WI'
funct.slack_send_mess(mess, slack_channel_id=slack_id)
if form.getvalue('check_rabbitmq_alert'):
import json
import http.cookies
try:
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
user_group_id = cookie.get('group')
user_group_id1 = user_group_id.value
except Exception as e:
error = str(e)
print(f'error: Cannot send a message {error}')
try:
json_for_sending = {"user_group": user_group_id1, "message": 'info: Test message'}
funct.send_message_to_rabbit(json.dumps(json_for_sending))
except Exception as e:
error = str(e)
print(f'error: Cannot send a message {error}')
if form.getvalue('check_email_alert'):
import http.cookies
subject = 'test message'
message = 'Test message from Roxy-WI'
try:
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
user_uuid = cookie.get('uuid')
user_uuid_value = user_uuid.value
except Exception as e:
error = str(e)
print(f'error: Cannot send a message {error}')
try:
user_email = sql.select_user_email_by_uuid(user_uuid_value)
except Exception as e:
error = str(e)
print(f'error: Cannot get a user email: {error}')
try:
funct.send_email(user_email, subject, message)
except Exception as e:
error = str(e)
print(f'error: Cannot send a message {error}')
if form.getvalue('getoption'):
group = form.getvalue('getoption')
term = form.getvalue('term')
@ -4360,3 +4434,45 @@ if form.getvalue('show_sub_ovw'):
template = env.get_template('ajax/show_sub_ovw.html')
template = template.render(sub=sql.select_user_all())
print(template)
if form.getvalue('updateHaproxyCheckerSettings'):
setting_id = form.getvalue('updateHaproxyCheckerSettings')
email = form.getvalue('email')
service_alert = form.getvalue('server')
backend_alert = form.getvalue('backend')
maxconn_alert = form.getvalue('maxconn')
telegram_id = form.getvalue('telegram_id')
slack_id = form.getvalue('slack_id')
if sql.update_haproxy_checker_settings(email, telegram_id, slack_id, service_alert, backend_alert,
maxconn_alert, setting_id
):
print('ok')
else:
print('error: Cannot update Checker settings')
if form.getvalue('updateKeepalivedCheckerSettings'):
setting_id = form.getvalue('updateKeepalivedCheckerSettings')
email = form.getvalue('email')
service_alert = form.getvalue('server')
backend_alert = form.getvalue('backend')
telegram_id = form.getvalue('telegram_id')
slack_id = form.getvalue('slack_id')
if sql.update_keepalived_checker_settings(email, telegram_id, slack_id, service_alert, backend_alert, setting_id):
print('ok')
else:
print('error: Cannot update Checker settings')
if form.getvalue('updateServiceCheckerSettings'):
setting_id = form.getvalue('updateServiceCheckerSettings')
email = form.getvalue('email')
service_alert = form.getvalue('server')
telegram_id = form.getvalue('telegram_id')
slack_id = form.getvalue('slack_id')
if sql.update_service_checker_settings(email, telegram_id, slack_id, service_alert, setting_id):
print('ok')
else:
print('error: Cannot update Checker settings')

View File

@ -31,9 +31,9 @@ try:
i += 1
cmd = "ps ax |grep 'metrics_worker\|metrics_waf_worker.py\|metrics_nginx_worker.py'|grep -v grep|grep '%s' |wc -l" % servers_for_grep
cmd = "ps ax |grep '[m]etrics_worker\|[m]etrics_waf_worker.py\|[m]etrics_nginx_worker.py'|grep '%s' |wc -l" % servers_for_grep
metrics_worker, stderr = funct.subprocess_execute(cmd)
cmd = "ps ax |grep 'checker_worker\|checker_nginx'|grep -v grep |grep '%s' |wc -l" % servers_for_grep
cmd = "ps ax |grep '[c]hecker_worker\|[c]hecker_nginx\|[c]hecker_apache\|[c]hecker_keepalived'|grep -v grep |grep '%s' |wc -l" % servers_for_grep
checker_worker, stderr = funct.subprocess_execute(cmd)
i = 0
for s in sql.select_all_alerts(group=user_group):
@ -48,9 +48,9 @@ try:
prometheus = ''
host = ''
else:
cmd = "ps ax |grep 'metrics_worker\|metrics_waf_worker.py\|metrics_nginx_worker.py' |grep -v grep |wc -l"
cmd = "ps ax |grep '[m]etrics_worker\|[m]etrics_waf_worker.py\|[m]etrics_nginx_worker.py' |wc -l"
metrics_worker, stderr = funct.subprocess_execute(cmd)
cmd = "ps ax |grep 'checker_worker\|checker_nginx' |grep -v grep |wc -l"
cmd = "ps ax |grep '[c]hecker_worker\|[c]hecker_nginx\|[c]hecker_apache\|[c]hecker_keepalived' |wc -l"
checker_worker, stderr = funct.subprocess_execute(cmd)
i = 0
for s in sql.select_all_alerts():
@ -61,7 +61,7 @@ try:
for s in is_metrics_workers:
i += 1
is_metrics_worker = i
cmd = "ps ax |grep grafana|grep -v grep|wc -l"
cmd = "ps ax |egrep [g]rafana|wc -l"
grafana, stderr = funct.subprocess_execute(cmd)
host = os.environ.get('HTTP_HOST', '')

View File

@ -22,6 +22,7 @@ error = ""
aftersave = ""
start_line = ""
end_line = ""
warning = ''
try:
user, user_id, role, token, servers, user_services = funct.get_users_params()
@ -73,6 +74,7 @@ if serv is not None and form.getvalue('config') is not None:
stderr = funct.master_slave_upload_and_restart(serv, cfg, just_save=save, oldcfg=oldcfg)
if "is valid" in stderr:
warning = stderr
stderr = ''
funct.diff_config(oldcfg, cfg)
@ -84,6 +86,6 @@ rendered_template = template.render(
h2=1, title="Working with HAProxy config sections", role=role, action="sections.py", user=user, select_id="serv",
serv=serv, aftersave=aftersave, config=config_read, cfg=cfg, selects=servers, stderr=stderr, error=error,
start_line=start_line, end_line=end_line, section=section, sections=sections, is_serv_protected=is_serv_protected,
user_services=user_services, token=token
user_services=user_services, token=token, warning=warning
)
print(rendered_template)

View File

@ -1,4 +1,6 @@
#!/usr/bin/env python3
import pytz
import funct
import sql
from jinja2 import Environment, FileSystemLoader
@ -32,6 +34,6 @@ rendered_template = template.render(
masters=sql.select_servers(get_master_servers=1, uuid=user_id.value), group=user_group,
sshs=sql.select_ssh(group=user_group), token=token, settings=settings, backups=sql.select_backups(),
page="servers.py", geoip_country_codes=geoip_country_codes, user_services=user_services, ldap_enable=ldap_enable,
user_status=user_status, user_plan=user_plan, gits=gits, services=services
user_status=user_status, user_plan=user_plan, gits=gits, services=services, timezones=pytz.all_timezones
)
print(rendered_template)

View File

@ -185,28 +185,23 @@ def add_setting_for_new_group(group_id):
'desc': 'Path to the NGINX directory with config files', 'group': group_id},
{'param': 'nginx_config_path', 'value': '/etc/nginx/nginx.conf', 'section': 'nginx',
'desc': 'Path to the main NGINX configuration file', 'group': group_id},
{'param': 'ldap_enable', 'value': '0', 'section': 'ldap', 'desc': 'Enable LDAP (1 - yes, 0 - no)',
'group': group_id},
{'param': 'ldap_server', 'value': '', 'section': 'ldap', 'desc': 'IP address of the LDAP server',
'group': group_id},
{'param': 'ldap_enable', 'value': '0', 'section': 'ldap', 'desc': 'Enable LDAP', 'group': group_id},
{'param': 'ldap_server', 'value': '', 'section': 'ldap', 'desc': 'IP address of the LDAP server', 'group': group_id},
{'param': 'ldap_port', 'value': '389', 'section': 'ldap',
'desc': 'LDAP port (port 389 or 636 is used by default)',
'group': group_id},
'desc': 'LDAP port (port 389 or 636 is used by default)', 'group': group_id},
{'param': 'ldap_user', 'value': '', 'section': 'ldap',
'desc': 'LDAP username. Format: user@domain.com', 'group': group_id},
{'param': 'ldap_password', 'value': '', 'section': 'ldap', 'desc': 'LDAP password', 'group': group_id},
{'param': 'ldap_base', 'value': '', 'section': 'ldap', 'desc': 'Base domain. Example: dc=domain, dc=com',
'group': group_id},
{'param': 'ldap_domain', 'value': '', 'section': 'ldap', 'desc': 'LDAP domain for logging in',
'group': group_id},
{'param': 'ldap_domain', 'value': '', 'section': 'ldap', 'desc': 'LDAP domain for logging in', 'group': group_id},
{'param': 'ldap_class_search', 'value': 'user', 'section': 'ldap', 'desc': 'Class for searching the user',
'group': group_id},
{'param': 'ldap_user_attribute', 'value': 'sAMAccountName', 'section': 'ldap',
'desc': 'Attribute to search users by', 'group': group_id},
{'param': 'ldap_search_field', 'value': 'mail', 'section': 'ldap',
'desc': 'User\'s email address', 'group': group_id},
{'param': 'ldap_type', 'value': '0', 'section': 'ldap', 'desc': 'Use LDAPS (1 - yes, 0 - no)',
'group': group_id},
{'param': 'ldap_type', 'value': '0', 'section': 'ldap', 'desc': 'Use LDAPS', 'group': group_id},
{'param': 'apache_path_logs', 'value': '/var/log/httpd/', 'section': 'apache',
'desc': 'The path for Apache logs', 'group': group_id},
{'param': 'apache_stats_user', 'value': 'admin', 'section': 'apache',
@ -490,6 +485,15 @@ def select_server_id_by_ip(server_ip):
return server_id
def select_server_group_by_ip(server_ip):
try:
groups = Server.get(Server.ip == server_ip).groups
except Exception as e:
return out_error(e)
else:
return groups
def select_server_ip_by_id(server_id):
try:
server_ip = Server.get(Server.server_id == server_id).ip
@ -3406,3 +3410,108 @@ def delete_git(git_id):
return False
else:
return True
def select_users_emails_by_group_id(group_id: int):
query = User.select(User.email).where((User.groups == group_id) & (User.role != 'guest'))
try:
query_res = query.execute()
except Exception as e:
out_error(e)
return
else:
return query_res
def select_user_email_by_uuid(uuid: str) -> str:
user_id = get_user_id_by_uuid(uuid)
try:
query_res = User.get(User.user_id == user_id).email
except Exception as e:
out_error(e)
return ""
else:
return query_res
def select_checker_settings(service_id: int):
query = CheckerSetting.select().where(CheckerSetting.service_id == service_id)
try:
query_res = query.execute()
except Exception as e:
out_error(e)
return
else:
return query_res
def select_checker_settings_for_server(service_id: int, server_id: int):
query = CheckerSetting.select().where(
(CheckerSetting.service_id == service_id)
& (CheckerSetting.server_id == server_id)
)
try:
query_res = query.execute()
except Exception as e:
out_error(e)
return
else:
return query_res
def insert_new_checker_setting_for_server(server_ip: str) -> None:
try:
server_id = Server.get(Server.ip == server_ip).server_id
except Exception as e:
out_error(e)
for service_id in range(1, 5):
CheckerSetting.insert(
server_id=server_id, service_id=service_id
).on_conflict_ignore().execute()
def update_haproxy_checker_settings(
email: int, telegram_id: int, slack_id: int, service_alert: int, backend_alert: int,
maxconn_alert: int, setting_id: int
) -> bool:
settings_update = CheckerSetting.update(
email=email, telegram_id=telegram_id, slack_id=slack_id, service_alert=service_alert,
backend_alert=backend_alert, maxconn_alert=maxconn_alert
).where(CheckerSetting.id == setting_id)
try:
settings_update.execute()
except Exception:
return False
else:
return True
def update_keepalived_checker_settings(
email: int, telegram_id: int, slack_id: int, service_alert: int, backend_alert: int,
setting_id: int
) -> bool:
settings_update = CheckerSetting.update(
email=email, telegram_id=telegram_id, slack_id=slack_id,
service_alert=service_alert, backend_alert=backend_alert
).where(CheckerSetting.id == setting_id)
try:
settings_update.execute()
except Exception:
return False
else:
return True
def update_service_checker_settings(
email: int, telegram_id: int, slack_id: int, service_alert: int, setting_id: int
) -> bool:
settings_update = CheckerSetting.update(
email=email, telegram_id=telegram_id, slack_id=slack_id, service_alert=service_alert
).where(CheckerSetting.id == setting_id)
try:
settings_update.execute()
except Exception:
return False
else:
return True

View File

@ -111,12 +111,10 @@
<thead>
<tr class="overviewHead">
<td class="padding10 first-collumn" style="width: 25%;">Service</td>
<td class="padding10">Current version</td>
<td class="padding10">Latest version</td>
<td class="padding10"></td>
<td style="width: 100%">
Description
</td>
<td class="padding10" style="width: 10%">Current version</td>
<td class="padding10" style="width: 10%">Latest version</td>
<td style="width: 10%"></td>
<td style="width: 100%">Description</td>
<td><span onclick="loadupdatehapwi()" class="refresh" title="Reload Update"></span></td>
</tr>
</thead>

View File

@ -1,12 +1,33 @@
{% from 'include/input_macros.html' import input, select %}
{% from 'include/input_macros.html' import input, select, checkbox %}
{% if user_status == 0 %}
{% include 'include/no_sub.html' %}
{% else %}
<script>
$( "#checker_tabs" ).tabs();
</script>
<style>
.checker_settings_table {
margin-bottom: 15px;
}
</style>
{% for s in services %}
{% if s.0 == 'roxy-wi-checker' %}
{% if s.3 != '* is not installed' and s.3 != '' %}
{% if s.0 == 'roxy-wi-checker' %}
{% if s.3 == '* is not installed' and s.3 == '' %}
<div style="text-align: center;">
<br />
<h3>You have not installed Backends checker
Read <a href="https://roxy-wi.org/services.py?service=checker#installation" title="Checker installation" style="color: #5d9ceb;" target="_blank">hear</a>
how to install Checker service</h3>
</div>
{% else %}
<div id="checker_tabs">
<ul>
<li><a href="#channels" title="Checker channels - Roxy-WI">Channels</a></li>
<li><a href="#checker_settings" title="Checker settings - Roxy-WI">Settings</a></li>
</ul>
<div id="channels">
<table id="checker_table" class="overview">
<caption><h3>Add Telegram channel</h3></caption>
<caption><h3>Telegram channels</h3></caption>
<tr class="overviewHead" style="width: 50%;">
<td class="padding10 first-collumn" style="width: 25%;">
<span title="Token that has given @father_bot">Token</span>
@ -44,10 +65,10 @@
</td>
{% endif %}
<td>
<button title="Send test message" onclick="checkTelegram({{telegram.id}})">Test</button>
<button title="Send a test message" onclick="checkTelegram({{telegram.id}})">Test</button>
</td>
<td>
<a class="add" onclick="cloneTelegram({{telegram.id}})" id="clone-{{telegram.id}}" title="Clone {{telegram.chanel_name}}" style="cursor: pointer;"></a>
<a class="add" onclick="cloneTelegram({{telegram.id}})" id="clone-{{telegram.id}}" title="Copy the settings from {{telegram.chanel_name}}" style="cursor: pointer;"></a>
</td>
<td>
<a class="delete" onclick="confirmDeleteTelegram({{telegram.id}})" title="Delete channel {{telegram.chanel_name}}" style="cursor: pointer;"></a>
@ -58,7 +79,7 @@
<br /><span class="add-button" title="Add telegram channel" id="add-telegram-button">+ Add</span>
<br /><br />
<table id="checker_slack_table" class="overview">
<caption><h3>Add Slack channel</h3></caption>
<caption><h3>Slack channels</h3></caption>
<tr class="overviewHead" style="width: 50%;">
<td class="padding10 first-collumn" style="width: 25%;">
<span title="Token that has given with APP registration">Token</span>
@ -96,7 +117,7 @@
</td>
{% endif %}
<td>
<button title="Send test message" onclick="checkSlack({{slack.id}})">Test</button>
<button title="Send a test message" onclick="checkSlack({{slack.id}})">Test</button>
</td>
<td>
<a class="add" onclick="cloneSlack({{slack.id}})" id="clone-{{slack.id}}" title="Clone {{slack.chanel_name}}" style="cursor: pointer;"></a>
@ -109,20 +130,304 @@
</table>
<br /><span class="add-button" title="Add Slack channel" id="add-slack-button">+ Add</span>
<br /><br />
<table class="overview">
<caption><h3>Test messages</h3></caption>
<tr class="overviewHead">
<td class="padding10 first-collumn" style="width: 45%">Email</td>
<td style="width: 100%">Web panel</td>
</tr>
<tr>
<td class="padding10 first-collumn">
<button title="Send a test message via Email" onclick="checkEmail()">Test</button>
</td>
<td>
<button title="Send a test message via Web panel" onclick="checkWebPanel()">Test</button>
</td>
</tr>
</table>
<br /><br />
<div id="ajax-telegram"></div>
<div class="add-note alert addName alert-info" style="width: inherit; margin-right: 15px;">
You can read the description of all parameters <a href="https://roxy-wi.org/description.py?description=checker" title="Servers description" target="_blank">here</a>,
How to create and use Telegram bot in this <a href="https://roxy-wi.org/howto.py?howto=checker" title="How to create Telegram bot and use it with Roxy-WI" target="_blank">article</a>,
How to create and use Slack APP in this <a href="https://roxy-wi.org/howto.py?howto=slack" title="How to create Slack APP and use it with Roxy-WI" target="_blank">article</a>
</div>
{% else %}
<div style="text-align: center;">
<br />
<h3>You have not installed Backends checker
Read <a href="https://roxy-wi.org/services.py?service=checker#installation" title="Checker installation" style="color: #5d9ceb;" target="_blank">hear</a>
how to install Checker service</h3>
</div>
<div id="checker_settings">
<table class="overview checker_settings_table" id="checker_haproxy_table">
<caption><h3>HAProxy servers</h3></caption>
<tr class="overviewHead">
<td class="padding10 first-collumn">Server</td>
<td class="first-collumn" title="Alert via Telegram">Telegram</td>
<td class="first-collumn" title="Alert via Slack">Slack</td>
<td class="checkbox-head" style="width: 10%;" title="Alert via email">Email</td>
<td class="checkbox-head" style="width: 10%;" title="Alert about changing service status">Service</td>
<td class="checkbox-head" style="width: 10%;" title="Alert about changing backend status">Backend</td>
<td class="checkbox-head" style="width: 100%;" title="Alert if the number of connections is about to reach the limit">Maxconn</td>
<td><span onclick="loadchecker(1)" class="refresh" title="Reload"></span></td>
</tr>
{% for s in haproxy_servers %}
{% for h in haproxy_settings %}
{% if h.server_id|string() == s.0|string() and h.service_id == 1 %}
<tr id="haproxy_server_tr_id-{{h.id}}">
<td class="padding10 first-collumn" id="haproxy_server_name-{{h.id}}">{{s.1}}</td>
<td id="haproxy_server_telegram-{{h.id}}" title="Alert via this channel">
<select id="haproxy_server_telegram_channel-{{h.id}}">
<option value="0">Disabled</option>
{% for t in telegrams %}
{% if h.telegram_id|int() == t.id|int() %}
<option value="{{t.id}}" selected>{{t.chanel_name}}</option>
{% else %}
<option value="{{t.id}}">{{t.chanel_name}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td id="haproxy_server_slack-{{s.0}}" title="Alert via this channel">
<select id="haproxy_server_slack_channel-{{h.id}}">
<option value="0">Disabled</option>
{% for t in slacks %}
{% if h.slack_id|int() == t.id|int() %}
<option value="{{t.id}}" selected>{{t.chanel_name}}</option>
{% else %}
<option value="{{t.id}}">{{t.chanel_name}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td class="checkbox" title="Alert via email">
{% set id = 'haproxy_server_email-' + h.id|string() %}
{% if h.email == 1 %}
{{ checkbox(id, checked='checked') }}
{% else %}
{{ checkbox(id) }}
{% endif %}
</td>
<td class="checkbox">
{% set id = 'haproxy_server_status-' + h.id|string() %}
{% if h.service_alert == 1 %}
{{ checkbox(id, checked='checked', title='Alert about changing service status') }}
{% else %}
{{ checkbox(id, title='Alert about changing service status') }}
{% endif %}
</td>
<td class="checkbox">
{% set id = 'haproxy_server_backend-' + h.id|string() %}
{% if h.backend_alert == 1 %}
{{ checkbox(id, checked='checked', title='Alert about changing backend status') }}
{% else %}
{{ checkbox(id, title='Alert about changing backend status') }}
{% endif %}
</td>
<td class="checkbox">
{% set id = 'haproxy_server_maxconn-' + h.id|string() %}
{% if h.maxconn_alert == 1 %}
{{ checkbox(id, checked='checked', title='Alert if the number of connections is about to reach the limit') }}
{% else %}
{{ checkbox(id, title='Alert if the number of connections is about to reach the limit') }}
{% endif %}
</td>
<td></td>
</tr>
{% endif %}
{% endfor %}
{% endfor %}
</table>
<table class="overview checker_settings_table" id="checker_nginx_table">
<caption><h3>NGINX servers</h3></caption>
<tr class="overviewHead">
<td class="padding10 first-collumn">Server</td>
<td class="first-collumn" title="Alert via Telegram">Telegram</td>
<td class="first-collumn" title="Alert via Slack">Slack</td>
<td class="checkbox-head" style="width: 10%;" title="Alert via Email">Email</td>
<td class="checkbox-head" style="width: 100%;" title="Alert about changing service status">Service</td>
<td><span onclick="loadchecker(1)" class="refresh" title="Reload"></span></td>
</tr>
{% for s in nginx_servers %}
{% for h in nginx_settings %}
{% if h.server_id|string() == s.0|string() and h.service_id == 2 %}
<tr id="nginx_server_tr_id-{{h.id}}">
<td class="padding10 first-collumn" id="nginx_server_name-{{h.id}}">{{s.1}}</td>
<td id="nginx_server_telegram-{{h.id}}" title="Alert via this channel">
<select id="nginx_server_telegram_channel-{{h.id}}">
<option value="0">Disabled</option>
{% for t in telegrams %}
{% if h.telegram_id|int() == t.id|int() %}
<option value="{{t.id}}" selected>{{t.chanel_name}}</option>
{% else %}
<option value="{{t.id}}">{{t.chanel_name}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td id="nginx_server_slack-{{h.id}}" title="Alert via this channel">
<select id="nginx_server_slack_channel-{{h.id}}">
<option value="0">Disabled</option>
{% for t in slacks %}
{% if h.slack_id|int() == t.id|int() %}
<option value="{{t.id}}" selected>{{t.chanel_name}}</option>
{% else %}
<option value="{{t.id}}">{{t.chanel_name}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td class="checkbox">
{% set id = 'nginx_server_email-' + h.id|string() %}
{% if h.email == 1 %}
{{ checkbox(id, checked='checked', title='Alert via email') }}
{% else %}
{{ checkbox(id, title='Alert via email') }}
{% endif %}
</td>
<td class="checkbox">
{% set id = 'nginx_server_status-' + h.id|string() %}
{% if h.service_alert == 1 %}
{{ checkbox(id, checked='checked', title='Alert about changing service status') }}
{% else %}
{{ checkbox(id, title='Alert about changing service status') }}
{% endif %}
</td>
<td></td>
</tr>
{% endif %}
{% endfor %}
{% endfor %}
</table>
<table class="overview checker_settings_table" id="checker_apache_table">
<caption><h3>Apache servers</h3></caption>
<tr class="overviewHead">
<td class="padding10 first-collumn">Server</td>
<td class="first-collumn" title="Alert via Telegram">Telegram</td>
<td class="first-collumn" title="Alert via Slack">Slack</td>
<td class="checkbox-head" style="width: 10%;">Email</td>
<td class="checkbox-head" style="width: 100%;" title="Alert about changing service status">Service</td>
<td><span onclick="loadchecker(1)" class="refresh" title="Reload"></span></td>
</tr>
{% for s in apache_servers %}
{% for h in apache_settings %}
{% if h.server_id|string() == s.0|string() and h.service_id == 4 %}
<tr id="apache_server_tr_id-{{h.id}}">
<td class="padding10 first-collumn" id="apache_server_name-{{h.id}}">{{s.1}}</td>
<td id="apache_server_telegram-{{h.id}}" title="Alert via this channel">
<select id="apache_server_telegram_channel-{{h.id}}">
<option value="0">Disabled</option>
{% for t in telegrams %}
{% if h.telegram_id|int() == t.id|int() %}
<option value="{{t.id}}" selected>{{t.chanel_name}}</option>
{% else %}
<option value="{{t.id}}">{{t.chanel_name}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td id="apache_server_slack-{{h.id}}" title="Alert via this channel">
<select id="apache_server_slack_channel-{{h.id}}">
<option value="0">Disabled</option>
{% for t in slacks %}
{% if h.slack_id|int() == t.id|int() %}
<option value="{{t.id}}" selected>{{t.chanel_name}}</option>
{% else %}
<option value="{{t.id}}">{{t.chanel_name}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td class="checkbox">
{% set id = 'apache_server_email-' + h.id|string() %}
{% if h.email == 1 %}
{{ checkbox(id, checked='checked', title='Alert via email') }}
{% else %}
{{ checkbox(id, title='Alert via email') }}
{% endif %}
</td>
<td class="checkbox">
{% set id = 'apache_server_status-' + h.id|string() %}
{% if h.service_alert == 1 %}
{{ checkbox(id, checked='checked', title='Alert about changing service status') }}
{% else %}
{{ checkbox(id, title='Alert about changing service status') }}
{% endif %}
</td>
<td></td>
</tr>
{% endif %}
{% endfor %}
{% endfor %}
</table>
<table class="overview checker_settings_table" id="checker_keepalived_table">
<caption><h3>Keepalived servers</h3></caption>
<tr class="overviewHead">
<td class="padding10 first-collumn">Server</td>
<td class="first-collumn" title="Alert via Telegram">Telegram</td>
<td class="first-collumn" title="Alert via Slack">Slack</td>
<td class="checkbox-head" style="width: 10%;">Email</td>
<td class="checkbox-head" style="width: 10%;" title="Alert about changing service status">Service</td>
<td class="checkbox-head" style="width: 100%;" title="Alert about changing Master/Backup status">Status</td>
<td><span onclick="loadchecker(1)" class="refresh" title="Reload"></span></td>
</tr>
{% for s in keepalived_servers %}
{% for h in keepalived_settings %}
{% if h.server_id|string() == s.0|string() and h.service_id == 3 %}
<tr id="keepalived_server_tr_id-{{h.id}}">
<td class="padding10 first-collumn" id="keepalived_server_name-{{h.id}}">{{s.1}}</td>
<td id="keepalived_server_telegram-{{h.id}}" title="Alert via this channel">
<select id="keepalived_server_telegram_channel-{{h.id}}">
<option value="0">Disabled</option>
{% for t in telegrams %}
{% if h.telegram_id|int() == t.id|int() %}
<option value="{{t.id}}" selected>{{t.chanel_name}}</option>
{% else %}
<option value="{{t.id}}">{{t.chanel_name}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td id="keepalived_server_slack-{{h.id}}" title="Alert via this channel">
<select id="keepalived_server_slack_channel-{{h.id}}">
<option value="0">Disabled</option>
{% for t in slacks %}
{% if h.slack_id|int() == t.id|int() %}
<option value="{{t.id}}" selected>{{t.chanel_name}}</option>
{% else %}
<option value="{{t.id}}">{{t.chanel_name}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td class="checkbox">
{% set id = 'keepalived_server_email-' + h.id|string() %}
{% if h.email == 1 %}
{{ checkbox(id, checked='checked', title='Alert via email') }}
{% else %}
{{ checkbox(id, title='Alert via email') }}
{% endif %}
</td>
<td class="checkbox">
{% set id = 'keepalived_server_status-' + h.id|string() %}
{% if h.service_alert == 1 %}
{{ checkbox(id, checked='checked', title='Alert about changing service status') }}
{% else %}
{{ checkbox(id, title='Alert about changing service status') }}
{% endif %}
</td>
<td class="checkbox">
{% set id = 'keepalived_server_backend-' + h.id|string() %}
{% if h.backend_alert == 1 %}
{{ checkbox(id, checked='checked', title='Alert about changing Master/Backup status') }}
{% else %}
{{ checkbox(id, title='Alert about changing Master/Backup status') }}
{% endif %}
</td>
<td></td>
</tr>
{% endif %}
{% endfor %}
{% endfor %}
</table>
</div>
</div>
{% endif %}
{% endif %}
{% endfor %}
{% endif %}

View File

@ -33,7 +33,7 @@
<td></td>
</tr>
{% for s in services %}
{% if s.0 == 'roxy-wi-smon' or s.0 == 'roxy-wi-checker' or s.0 == 'roxy-wi-keep_alive' or s.0 == 'roxy-wi-metrics' or s.0 == 'roxy-wi-portscanner' or s.0 == 'roxy-wi-socket' %}
{% if s.0 in ('roxy-wi-smon', 'roxy-wi-checker', 'roxy-wi-keep_alive', 'roxy-wi-metrics', 'roxy-wi-portscanner', 'roxy-wi-socket') %}
<tr class="{{ loop.cycle('even', 'odd') }}">
{% set is_need_update = 0 %}
{% if s.0 == 'roxy-wi-smon' %}
@ -43,6 +43,7 @@
{% if s.3|float < smon_ver|float %}
{% set is_need_update = 1 %}
{% endif %}
{% set description = 'SMON stands for <b>S</b>imple <b>MON</b>itoring' %}
{% elif s.0 == 'roxy-wi-checker' %}
{% set service_name = 'Checker' %}
{% set service_link = 'checker' %}
@ -50,6 +51,7 @@
{% if s.3|float < checker_ver|float %}
{% set is_need_update = 1 %}
{% endif %}
{% set description = 'Checker is designed for monitoring HAProxy, Nginx, Apache and Keepalived services as well as HAProxy backends' %}
{% elif s.0 == 'roxy-wi-keep_alive' %}
{% set service_name = 'Auto start' %}
{% set service_link = 'auto_start' %}
@ -57,6 +59,7 @@
{% if s.3|float < keep_ver|float %}
{% set is_need_update = 1 %}
{% endif %}
{% set description = 'The Auto Start service allows to restart the HAProxy, NGINX, Apache and Keepalived services if they are down' %}
{% elif s.0 == 'roxy-wi-metrics' %}
{% set service_name = 'Metrics' %}
{% set service_link = 'metrics' %}
@ -64,23 +67,26 @@
{% if s.3|float < metrics_ver|float %}
{% set is_need_update = 1 %}
{% endif %}
{% set description = 'Collects number of connections for HAProxy, NGINX and WAF services' %}
{% elif s.0 == 'roxy-wi-portscanner' %}
{% set service_name = 'Port scanner' %}
{% set service_link = 'portscanner' %}
{% set desc_link = 'https://roxy-wi.org/services.py?service={{service_link}}' %}
{% set desc_link = 'https://roxy-wi.org/services.py?service=' + service_link %}
{% if s.3|float < portscanner_ver|float %}
{% set is_need_update = 1 %}
{% endif %}
{% set description = 'Probes and saves a server or host for open ports' %}
{% elif s.0 == 'roxy-wi-socket' %}
{% set service_name = 'Socket service' %}
{% set service_link = 'socket' %}
{% set desc_link = 'https://roxy-wi.org/services.py?service={{service_link}}' %}
{% set desc_link = 'https://roxy-wi.org/services.py?service=' + service_link %}
{% if s.3|float < socket_ver|float %}
{% set is_need_update = 1 %}
{% endif %}
{% set description = 'Socket is a service for sending alerts and notifications' %}
{% endif %}
<td class="padding10 first-collumn">
{{service_name}}
<a href="{{desc_link}}" title="Read more about {{service_name}}" target="_blank" class="link">{{service_name}}</a>
</td>
<td>
{% if s.3 != '* is not installed' %}
@ -120,13 +126,12 @@
<a class="ui-button ui-widget ui-corner-all" onclick="updateService('{{s.0}}')" title="Update {{service_name}}">Update</a>
{% endif %}
{% else %}
<a href="https://roxy-wi.org/services.py?service={{service_link}}#installation" title="{{service_name}} installation" target="_blank" class="link">Read about installation</a>
<a class="ui-button ui-widget ui-corner-all" onclick="updateService('{{s.0}}')" title="Install {{service_name}}">Install</a>
{% endif %}
</td>
<td>
Read more about <a href="{{desc_link}}" title="Read more about {{service_name}}" target="_blank" class="link">{{service_name}}</a>
<td colspan="2">
{{description}}
</td>
<td></td>
</tr>
{% endif %}
{% endfor %}

View File

@ -24,7 +24,7 @@
<button title="Send test message" onclick="checkSlack({{slack.id}})">Test</button>
</td>
<td>
<a class="add" onclick="cloneSlack({{slack.id}})" id="clone-{{slack.id}}" title="Clone {{slack.chanel_name}}" style="cursor: pointer;"></a>
<a class="add" onclick="cloneSlack({{slack.id}})" id="clone-{{slack.id}}" title="Copy the settings from {{slack.chanel_name}}" style="cursor: pointer;"></a>
</td>
<td>
<a class="delete" onclick="confirmDeleteSlack({{slack.id}})" style="cursor: pointer;"></a>

View File

@ -1,11 +1,11 @@
{% for telegram in telegrams %}
<tr style="width: 50%;" id="telegram-table-{{telegram.id}}" class="newgroup">
<td class="padding10 first-collumn">
<input type="text" id="telegram-token-{{telegram.id}}" class="form-control" value="{{telegram.token}}">
<input type="text" id="telegram-token-{{telegram.id}}" class="form-control" value="{{telegram.token}}" size="30">
<input type="hidden" id="telegramgroup-{{telegram.id}}" name="telegramgroup-{{telegram.id}}">
</td>
<td>
<input type="text" id="telegram-chanel-{{telegram.id}}" class="form-control" value="{{telegram.chanel_name}}">
<input type="text" id="telegram-chanel-{{telegram.id}}" class="form-control" value="{{telegram.chanel_name}}" size="30">
</td>
{% if page != "servers.py" %}
<td>
@ -21,7 +21,7 @@
</td>
{% endif %}
<td>
<button title="Send test message" onclick="checkTelegram({{telegram.id}})">Test</button>
<button title="Send a test message" onclick="checkTelegram({{telegram.id}})">Test</button>
</td>
<td>
<a class="add" onclick="cloneTelegram({{telegram.id}})" id="clone-{{telegram.id}}" title="Clone {{telegram.chanel_name}}" style="cursor: pointer;"></a>

View File

@ -3,6 +3,8 @@
{% set plan = 'Home' %}
{% elif s.Plan == 'company' %}
{% set plan = 'Enterprise' %}
{% elif s.Plan == 'cloud' %}
{% set plan = 'Cloud' %}
{% elif s.Plan == 'support' %}
{% set plan = 'Premium' %}
{% elif s.Plan == 'Trial' %}
@ -32,7 +34,6 @@
</tr>
<tr class="odd">
<td class="padding10 first-collumn-wi">Pay method</td>
<td>
{% if plan == 'Free' %}
N/A

View File

@ -143,8 +143,9 @@
<a title="Servers manage" class="runtime">Servers</a>
<ul class="v_menu">
<li><a href="/app/servers.py#users" title="Servers: Manage users - Roxy-WI" class="users head-submenu">Users</a></li>
<li><a href="/app/servers.py#servers" title="Servers: Manage servers - Roxy-WI" class="runtime head-submenu">Servers</a></li>
<li><a href="/app/servers.py#ssh" title="Servers: Manage SSH credentials - Roxy-WI" class="admin head-submenu">SSH credentials</a></li>
<li><a href="/app/servers.py#servers" title="Servers: Manage servers - Roxy-WI" class="runtime servers head-submenu">Servers</a></li>
<li><a href="/app/servers.py#ssh" title="Servers: Manage SSH credentials - Roxy-WI" class="admin ssh head-submenu">SSH credentials</a></li>
<li><a href="/app/servers.py#checker" title="Servers: Manage Checker - Roxy-WI" class="checker head-submenu">Checker</a></li>
<li><a href="/app/servers.py#settings" title="Servers: Manage Roxy-WI settings - Roxy-WI" class="settings head-submenu">Settings</a></li>
<li><a href="/app/servers.py#installproxy" title="Servers: Proxy service installation - Roxy-WI" class="hap-menu installproxy head-submenu">Proxy installation</a> </li>
<li><a href="/app/servers.py#installmon" title="Servers: Monitoring service installation - Roxy-WI" class="hap1 installmon head-submenu">Monitoring installation</a> </li>
@ -159,9 +160,10 @@
<a title="Admin area" class="admin">Admin area</a>
<ul class="v_menu">
<li><a href="/app/users.py#users" title="Admin area: Manage users - Roxy-WI" class="users head-submenu">Users</a></li>
<li><a href="/app/users.py#groups" title="Admin area: Manage groups - Roxy-WI" class="group head-submenu">Groups</a></li>
<li><a href="/app/users.py#servers" title="Admin area: Manage servers - Roxy-WI" class="runtime head-submenu">Servers</a></li>
<li><a href="/app/users.py#ssh" title="Admin area: Manage SSH credentials - Roxy-WI" class="admin head-submenu">SSH credentials</a></li>
<li><a href="/app/users.py#groups" title="Admin area: Manage groups - Roxy-WI" class="group groups head-submenu">Groups</a></li>
<li><a href="/app/users.py#servers" title="Admin area: Manage servers - Roxy-WI" class="runtime servers head-submenu">Servers</a></li>
<li><a href="/app/users.py#ssh" title="Admin area: Manage SSH credentials - Roxy-WI" class="admin ssh head-submenu">SSH credentials</a></li>
<li><a href="/app/users.py#checker" title="Admin area: Checker - Roxy-WI" class="checker head-submenu">Checker</a></li>
<li><a href="/app/users.py#settings" title="Admin area: Manage Roxy-WI settings - Roxy-WI" class="settings head-submenu">Settings</a></li>
<li><a href="/app/users.py#services" title="Admin area: Manage Roxy-WI services - Roxy-WI" class="services head-submenu">Services</a></li>
<li><a href="/app/viewlogs.py" title="Admin area: View internal logs - Roxy-WI" class="logs head-submenu">Internal logs</a></li>

View File

@ -168,7 +168,7 @@
<a class="info" onclick="showServerInfo('{{server.0}}', '{{server.2}}')" id="server_info_link-{{server.0}}" title="Show server info" style="cursor: pointer; color: var(--green-color)"></a>
</td>
<td>
<a class="add" onclick="cloneServer({{server.0}})" id="clone-{{server.0}}" title="Clone {{server.1}}" style="cursor: pointer;"></a>
<a class="add" onclick="cloneServer({{server.0}})" id="clone-{{server.0}}" title="Copy the settings from {{server.1}}" style="cursor: pointer;"></a>
</td>
<td>
<a class="delete" onclick="confirmDeleteServer({{server.0}})" title="Delete server {{server.1}}" style="cursor: pointer;"></a>

View File

@ -2,7 +2,7 @@
<tbody>
{% set section = namespace(section='') %}
{% for set in settings %}
{% if page == "servers.py" and (set.section == 'monitoring' or set.section == 'rabbitmq') %}
{% if page == "servers.py" and (set.section in ('monitoring', 'rabbitmq', 'mail')) %}
<!-- continue -->
{% else %}
{% if section.section|string() != set.section|string() %}
@ -27,18 +27,33 @@
{{set.param}}
</td>
<td class="addOption">
{% if set.param in ('ldap_password', 'stats_password', 'nginx_stats_password', 'apache_stats_password', 'rabbitmq_password') %}
{% if set.param in ('ldap_password', 'stats_password', 'nginx_stats_password', 'apache_stats_password', 'rabbitmq_password', 'mail_smtp_password') %}
{% if set.value is none %}
{{ input(set.param, size='25', type='password') }}
{% else %}
{{ input(set.param, size='25', type='password', placeholder='*****') }}
{{ input(set.param, size='25', type='password', placeholder='******') }}
{% endif %}
{% elif set.param in ('nginx_stats_port', 'session_ttl', 'token_ttl', 'stats_port', 'haproxy_sock_port',
'ldap_type', 'ldap_port', 'ldap_enable', 'log_time_storage', 'syslog_server_enable', 'smon_check_interval',
'checker_check_interval', 'port_scan_interval', 'smon_keep_history_range', 'checker_keep_history_range',
'portscanner_keep_history_range', 'haproxy_enterprise', 'checker_maxconn_threshold', 'apache_stats_port') %}
'ldap_port', 'log_time_storage', 'smon_check_interval', 'checker_check_interval', 'port_scan_interval',
'smon_keep_history_range', 'checker_keep_history_range', 'portscanner_keep_history_range',
'checker_maxconn_threshold', 'apache_stats_port', 'mail_smtp_port', 'rabbitmq_port') %}
{{ input(set.param, value=set.value, style='width: 210px;', type='number') }}
{% elif set.param == 'time_zone' %}
<select name="{{set.param}}" id="{{set.param}}" style="width: 215px;">
{% for zone in timezones %}
{% if set.value == zone %}
<option value="{{zone}}" selected>{{zone}}</option>
{% else %}
<option value="{{zone}}">{{zone}}</option>
{% endif %}
{% endfor %}
</select>
{% elif set.param in ('ldap_type', 'ldap_enable', 'syslog_server_enable', 'mail_ssl') %}
{% if set.value|int() == 1 %}
{{ checkbox(set.param, checked='checked', style='margin: 0') }}
{% else %}
{{ checkbox(set.param, style='margin: 0') }}
{% endif %}
{% else %}
{% if set.value is none %}
{{ input(set.param, size='25') }}
@ -55,3 +70,9 @@
{% endfor %}
</tbody>
</table>
<script>
$(document).ready(function() {
$("#time_zone").selectmenu("destroy");
$('#time_zone').select2();
});
</script>

View File

@ -10,7 +10,7 @@
<td style="width: 25%;">Group</td>
{% endif %}
<td style="width: 100%;" class="help_cursor">
<span title="Enter SSH user name. If SSH key disabled, enter password for SSH user">Credentials</span>
<span title="Enter SSH user name. If SSH key disabled, enter password for SSH user">User name</span>
</td>
<td></td>
</tr>
@ -46,9 +46,9 @@
{{ input(id, value=ssh.username, title='SSH user name') }}
</p>
{% if ssh.enable == 1 %}
<input type="password" id="ssh_pass-{{ssh.id}}" class="form-control" placeholder="*****" style="display: none;" autocomplete="new-password">
<input type="password" id="ssh_pass-{{ssh.id}}" class="form-control" title="User password, if SSH key is disabled" placeholder="*****" style="display: none;" autocomplete="new-password">
{% else %}
<input type="password" id="ssh_pass-{{ssh.id}}" class="form-control" placeholder="*****" autocomplete="new-password">
<input type="password" id="ssh_pass-{{ssh.id}}" class="form-control" title="User password, if SSH key is disabled" placeholder="*****" autocomplete="new-password">
{% endif %}
<br>
</td>

View File

@ -85,7 +85,7 @@
<a href="history.py?service=user&user_id={{user.user_id}}" title="View history for this user" class="history"></a>
</td>
<td>
<a class="add" onclick="cloneUser({{user.user_id}})" id="clone-{{user.user_id}}" title="Clone {{user.1}}" style="cursor: pointer;"></a>
<a class="add" onclick="cloneUser({{user.user_id}})" id="clone-{{user.user_id}}" title="Copy the settings from {{user.1}}" style="cursor: pointer;"></a>
</td>
<td>
<a class="delete" onclick="confirmDeleteUser({{user.user_id}})" title="Delete user {{user.1}}" style="cursor: pointer;"></a>

View File

@ -141,14 +141,14 @@
{% endif %}
<tr>
<td class="padding20">
Credentials
User name
<span class="need-field">*</span>
</td>
<td>
<p style="width: 100px;">
{{ input('ssh_user', value=ssh_user, title='SSH user name') }}
{{ input('ssh_user', value=ssh_user, title='SSH username') }}
</p>
{{ input('ssh_pass', type='password', style="display: none;", title='SSH password') }}
{{ input('ssh_pass', type='password', style="display: none;", title="User password, if SSH key is disabled") }}
</td>
</tr>
</table>

View File

@ -8,14 +8,14 @@
<input type="{{ type }}" name="{{name}}" value="{{ value|e }}" id="{{ id }}" size="{{size}}" style="{{style}}" {{readonly}} {{required}} {{autofocus}} placeholder="{{placeholder}}" title="{{title}}" class="{{class}}" autocomplete="off" />
{%- endmacro %}
{%- macro checkbox(id, name='', checked='', title='', value='', desc='', disabled='') -%}
{%- macro checkbox(id, name='', checked='', title='', value='', desc='', disabled='', style='') -%}
{% if name == '' %}
{% set name = id %}
{% endif %}
{% if disabled == 'true' %}
{% set disabled = 'disabled' %}
{% endif %}
<label for="{{id}}" title="{{title}}" class="{{id}}">{{desc}}</label><input name="{{name}}" type="checkbox" id="{{id}}" value="{{value|e}}" {{checked}} {{disabled}} />
<label for="{{id}}" title="{{title}}" class="{{id}}" style="{{style}}">{{desc}}</label><input name="{{name}}" type="checkbox" id="{{id}}" value="{{value|e}}" {{checked}} {{disabled}} />
{%- endmacro %}
{%- macro select(id, values, name='', required='', first='', class='', selected='', disabled='true') -%}

View File

@ -1,7 +1,7 @@
<tr>
<td colspan="2">
<p class="validateTips alert alert-success">
Fields marked "<span class="need-field">*</span>" are required.
Fields marked with "<span class="need-field">*</span>" are required.
</p>
</td>
</tr>

View File

@ -70,6 +70,9 @@
{% include 'include/errors.html' %}
{% else %}
<div class="alert alert-success">Config is ok</div>
{% if warning %}
<div class="alert alert-warning">{{warning}}</div>
{% endif %}
<a href="config.py?serv={{ serv }}" title="Working with HAProxy config">Config</a> |
<a href="viewsttats.py?serv={{ serv }}" target="_blank" title="View stats">Go to stats</a>
{% endif %}

View File

@ -1,5 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import pytz
import funct
import sql
from jinja2 import Environment, FileSystemLoader
@ -18,7 +20,6 @@ try:
users = sql.select_users()
settings = sql.get_setting('', all=1)
ldap_enable = sql.get_setting('ldap_enable')
grafana, stderr = funct.subprocess_execute("systemctl is-active grafana-server")
services = sql.select_services()
gits = sql.select_gits()
except Exception:
@ -33,8 +34,8 @@ except Exception as e:
rendered_template = template.render(
title="Admin area: Manage users", role=role, user=user, users=users, groups=sql.select_groups(),
servers=sql.select_servers(full=1), roles=sql.select_roles(), masters=sql.select_servers(get_master_servers=1),
sshs=sql.select_ssh(), token=token, settings=settings, backups=sql.select_backups(), grafana=''.join(grafana),
sshs=sql.select_ssh(), token=token, settings=settings, backups=sql.select_backups(),
page="users.py", user_services=user_services, ldap_enable=ldap_enable, user_status=user_status,
user_plan=user_plan, gits=gits, services=services
user_plan=user_plan, gits=gits, services=services, timezones=pytz.all_timezones
)
print(rendered_template)

View File

@ -1660,7 +1660,7 @@ function saveList(action, list, color) {
}
function deleteList(list, color) {
var serv = $( "#serv-"+color+"-list option:selected" ).val();
if (serv == 'Choose server') {
if (serv == '------') {
toastr.warning('Choose a server before deleting');
} else {
$.ajax({
@ -1810,16 +1810,15 @@ function addProxy(form_name) {
data: frm.serialize(),
type: frm.attr('method'),
success: function( data ) {
data = data.replace(/\s+/g, ' ');
if (data.indexOf('error: ') != '-1' || data.indexOf('Fatal') != '-1') {
toastr.clear();
toastr.error(data);
returnNiceCheckingConfig(data);
} else if (data == '') {
toastr.clear();
toastr.error('error: Proxy cannot be empty');
} else {
toastr.clear();
toastr.success('Section: <b>' + data + '</b> has been added. Do not forget to restart the server');
returnNiceCheckingConfig(data);
toastr.info('Section has been added. Do not forget to restart the server');
var ip = frm.find('select[name=serv]').val();
localStorage.setItem('restart', ip);
resetProxySettings();

View File

@ -62,10 +62,7 @@ $( function() {
type: frm.attr('method'),
success: function( data ) {
data = data.replace('\n', '<br>');
if (data.indexOf('error: ') != '-1' || data.indexOf('Fatal') != '-1' || data.indexOf('Error') != '-1' || data.indexOf('failed ') != '-1' || data.indexOf('emerg] ') != '-1') {
toastr.clear();
toastr.error(data);
} else if (data.indexOf(service + ': command not found') != '-1') {
if (data.indexOf(service + ': command not found') != '-1') {
try {
var service = findGetParameter('service');
toastr.error('Cannot save config. There is no ' + service);
@ -74,7 +71,7 @@ $( function() {
}
} else {
toastr.clear();
toastr.success(data);
returnNiceCheckingConfig(data);
}
}
});

View File

@ -220,13 +220,10 @@ $( function() {
data = data.replace(/^\s+|\s+$/g,'');
if(data.indexOf('keepalived:') != '-1') {
$('#cur_master_ver').text('Keepalived has not installed');
$('#create').prop('disabled', false);
$('#create').attr('title', 'Create HA cluster');
} else {
$('#cur_master_ver').text(data);
$('#cur_master_ver').css('font-weight', 'bold');
$('#create').prop('disabled', true);
$('#create').attr('title', 'Keepalived has been alredy installed. You cannot create a new HA Cluster');
}
}
} );
@ -244,13 +241,10 @@ $( function() {
data = data.replace(/^\s+|\s+$/g,'');
if(data.indexOf('keepalived:') != '-1') {
$('#cur_slave_ver').text('Keepalived has not installed');
$('#create').prop('disabled', false);
$('#create').attr('title', 'Create HA cluster');
} else {
$('#cur_slave_ver').text(data);
$('#cur_slave_ver').css('font-weight', 'bold');
$('#create').prop('disabled', true);
$('#create').attr('title', 'Keepalived has been alredy installed. You cannot create a new HA Cluster');
}
}
} );
@ -268,13 +262,10 @@ $( function() {
data = data.replace(/^\s+|\s+$/g,'');
if(data.indexOf('keepalived:') != '-1') {
$('#cur_master_ver-add').text('Keepalived has not installed');
$('#add-vrrp').prop('disabled', true);
$('#add-vrrp').attr('title', 'Add a HA configuration');
} else {
$('#cur_master_ver-add').text(data);
$('#cur_master_ver-add').css('font-weight', 'bold');
$('#add-vrrp').prop('disabled', false);
$('#add-vrrp').attr('title', 'Keepalived has been alredy installed. You cannot add a new HA configuration');
}
}
} );
@ -292,13 +283,10 @@ $( function() {
data = data.replace(/^\s+|\s+$/g,'');
if(data.indexOf('keepalived:') != '-1') {
$('#cur_slave_ver-add').text('Keepalived has not installed');
$('#add-vrrp').prop('disabled', true);
$('#add-vrrp').attr('title', 'Add a HA configuration');
} else {
$('#cur_slave_ver-add').text(data);
$('#cur_slave_ver-add').css('font-weight', 'bold');
$('#add-vrrp').prop('disabled', false);
$('#add-vrrp').attr('title', 'Keepalived has been alredy installed. You cannot add a new HA configuration');
}
}
} );

View File

@ -23,7 +23,7 @@ function show_current_page(id) {
id.parent().children().css('margin-left', '-20px');
id.parent().find('a').css('padding-left', '20px');
id.find('a').css('padding-left', '30px');
id.find('a').css('border-left', '4px solid #5D9CEB');
id.find('a').css('border-left', '4px solid var(--right-menu-blue-rolor)');
}
$( function() {
$('.menu li ul li').each(function () {
@ -983,9 +983,9 @@ $( function() {
$( ".users" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('padding-left', '20px')
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).children(".users").css('padding-left', '30px');
$(this).children(".users").css('border-left', '4px solid #5D9CEB');
$(this).children(".users").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
$( "#tabs" ).tabs( "option", "active", 0 );
} );
@ -993,55 +993,65 @@ $( function() {
$( ".group" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('padding-left', '20px')
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).children(".group").css('padding-left', '30px');
$(this).children(".group").css('border-left', '4px solid #5D9CEB');
$(this).children(".group").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
$( "#tabs" ).tabs( "option", "active", 1 );
} );
$( ".runtime" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).find('a').css('padding-left', '20px')
$(this).children(".runtime").css('padding-left', '30px');
$(this).children(".runtime").css('border-left', '4px solid #5D9CEB');
$(this).children(".runtime").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
$( "#tabs" ).tabs( "option", "active", 2 );
} );
$( ".admin" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('padding-left', '20px')
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).children(".admin").css('padding-left', '30px');
$(this).children(".admin").css('border-left', '4px solid #5D9CEB');
$(this).children(".admin").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
$( "#tabs" ).tabs( "option", "active", 3 );
} );
$( ".checker" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).find('a').css('padding-left', '20px')
$(this).children(".checker").css('padding-left', '30px');
$(this).children(".checker").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
loadchecker();
$( "#tabs" ).tabs( "option", "active", 4 );
} );
$( ".settings" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).find('a').css('padding-left', '20px')
$(this).children(".settings").css('padding-left', '30px');
$(this).children(".settings").css('border-left', '4px solid #5D9CEB');
$(this).children(".settings").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
$( "#tabs" ).tabs( "option", "active", 6 );
} );
$( ".services" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).find('a').css('padding-left', '20px')
$(this).children(".services").css('padding-left', '30px');
$(this).children(".services").css('border-left', '4px solid #5D9CEB');
$(this).children(".services").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
loadServices();
$( "#tabs" ).tabs( "option", "active", 7 );
} );
$( ".updatehapwi" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).find('a').css('padding-left', '20px')
$(this).children(".updatehapwi").css('padding-left', '30px');
$(this).children(".updatehapwi").css('border-left', '4px solid #5D9CEB');
$(this).children(".updatehapwi").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
$( "#tabs" ).tabs( "option", "active", 8 );
loadupdatehapwi();
@ -1050,54 +1060,64 @@ $( function() {
$( ".runtime" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('padding-left', '20px')
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).children(".runtime").css('padding-left', '30px');
$(this).children(".runtime").css('border-left', '4px solid #5D9CEB');
$(this).children(".runtime").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
$( "#tabs" ).tabs( "option", "active", 1 );
} );
$( ".admin" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).find('a').css('padding-left', '20px')
$(this).children(".admin").css('padding-left', '30px');
$(this).children(".admin").css('border-left', '4px solid #5D9CEB');
$(this).children(".admin").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
$( "#tabs" ).tabs( "option", "active", 2 );
} );
$( ".checker" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).find('a').css('padding-left', '20px')
$(this).children(".checker").css('padding-left', '30px');
$(this).children(".checker").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
loadchecker();
$( "#tabs" ).tabs( "option", "active", 3 );
} );
$( ".settings" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).find('a').css('padding-left', '20px')
$(this).children(".settings").css('padding-left', '30px');
$(this).children(".settings").css('border-left', '4px solid #5D9CEB');
$(this).children(".settings").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
$( "#tabs" ).tabs( "option", "active", 4 );
} );
$( ".installproxy" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('padding-left', '20px')
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).children(".installproxy").css('padding-left', '30px');
$(this).children(".installproxy").css('border-left', '4px solid #5D9CEB');
$(this).children(".installproxy").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
$( "#tabs" ).tabs( "option", "active", 5 );
} );
$( ".installmon" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('padding-left', '20px')
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).children(".installmon").css('padding-left', '30px');
$(this).children(".installmon").css('border-left', '4px solid #5D9CEB');
$(this).children(".installmon").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
$( "#tabs" ).tabs( "option", "active", 6 );
} );
$( ".backup" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('padding-left', '20px')
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).children(".backup").css('padding-left', '30px');
$(this).children(".backup").css('border-left', '4px solid #5D9CEB');
$(this).children(".backup").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
$( "#tabs" ).tabs( "option", "active", 7 );
} );
@ -1413,3 +1433,43 @@ function waitForElm(selector) {
function randomIntFromInterval(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
const removeEmptyLines = str => str.split(/\r?\n/).filter(line => line.trim() !== '').join('\n');
function returnNiceCheckingConfig(data) {
if (data.indexOf('sudo: firewall-cmd: command not found') != '-1') {
data = data.replaceAll('sudo: firewall-cmd: command not found\n', '');
data = data.replaceAll('sudo: firewall-cmd: command not found', '');
toastr.warning('The Firewalld service is not enabled. You should disable this setting for this server or enable the firewalld service on the server.')
}
data = data.replaceAll('Configuration file is valid', '');
data = data.replaceAll('Warnings were found.', '');
data = data.replaceAll('nginx: the configuration file /etc/nginx/nginx.conf syntax is ok', '');
data = data.replaceAll('nginx: configuration file /etc/nginx/nginx.conf test is successful', '');
data = data.replaceAll('Syntax OK', '');
output = data.split('<br>')
var alerts = []
alerts.push(output[0] + '\n' + output[1]);
try {
for (var i = 0; i < output.length; i++) {
if (i > 1) {
if (output[i] !== undefined) {
alerts.push(output[i])
}
}
}
} catch (err) {
console.log(err);
}
alerts.forEach((element) => {
if (element.indexOf('error: ') != '-1' || element.indexOf('Fatal') != '-1' || element.indexOf('Error') != '-1' || element.indexOf('failed ') != '-1' || element.indexOf('emerg] ') != '-1' || element.indexOf('Syntax error ') != '-1') {
toastr.error('<pre style="padding: 0; margin: 0;">' + element + '</pre>');
toastr.info('Config not applied');
return
} else {
toastr.success('<b>Configuration file is valid</b>');
}
if (element.indexOf('[WARNING]') != '-1' || element.indexOf('[ALER]') != '-1' || element.indexOf('[warn]') != '-1') {
element = removeEmptyLines(element);
toastr.warning('<pre style="padding: 0; margin: 0;">' + element + '</pre>')
}
})
}

View File

@ -5,6 +5,7 @@
--link-dark-blue: #23527c;
--light-blue-color: #d1ecf1;
--menu-color: #06212a;
--right-menu-blue-rolor: #5D9CEB;
}
html {
font-size: 10px;

View File

@ -607,9 +607,22 @@ $( function() {
updateSSH(id[1])
sshKeyEnableShow(id[1])
});
$( "#settings select" ).on('select2:select',function() {
var id = $(this).attr('id');
var val = $(this).val();
updateSettings(id, val);
updateSettings(id[1])
});
$( "#settings input" ).change(function() {
var id = $(this).attr('id');
var val = $(this).val();
if($('#'+id).is(':checkbox')) {
if ($('#'+id).is(':checked')){
val = 1;
} else {
val = 0;
}
}
updateSettings(id, val);
});
$('#new-ssh_enable').click(function() {
@ -655,6 +668,38 @@ $( function() {
$('.services_for_scan').show();
}
});
$( "#checker_haproxy_table select" ).on('selectmenuchange',function() {
var id = $(this).attr('id').split('-');
updateHaproxyCheckerSettings(id[1])
});
$( "#checker_haproxy_table input" ).change(function() {
var id = $(this).attr('id').split('-');
updateHaproxyCheckerSettings(id[1])
});
$( "#checker_nginx_table select" ).on('selectmenuchange',function() {
var id = $(this).attr('id').split('-');
updateServiceCheckerSettings(id[1], 'nginx')
});
$( "#checker_nginx_table input" ).change(function() {
var id = $(this).attr('id').split('-');
updateServiceCheckerSettings(id[1], 'nginx')
});
$( "#checker_apache_table select" ).on('selectmenuchange',function() {
var id = $(this).attr('id').split('-');
updateServiceCheckerSettings(id[1], 'apache')
});
$( "#checker_apache_table input" ).change(function() {
var id = $(this).attr('id').split('-');
updateServiceCheckerSettings(id[1], 'apache')
});
$( "#checker_keepalived_table select" ).on('selectmenuchange',function() {
var id = $(this).attr('id').split('-');
updateKeepalivedCheckerSettings(id[1])
});
$( "#checker_keepalived_table input" ).change(function() {
var id = $(this).attr('id').split('-');
updateKeepalivedCheckerSettings(id[1])
});
$('#search_ldap_user').click(function() {
var valid = true;
toastr.clear();
@ -756,17 +801,40 @@ $( function() {
});
$("#tabs ul li").click(function() {
var activeTab = $(this).find("a").attr("href");
var activeTabClass = activeTab.replace('#', '');
$('.menu li ul li').each(function () {
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).find('a').css('padding-left', '20px')
$(this).children("."+activeTabClass).css('padding-left', '30px');
$(this).children("."+activeTabClass).css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
if (activeTab == '#services') {
loadServices();
} else if (activeTab == '#updatehapwi') {
loadupdatehapwi();
} else if (activeTab == '#checker'){
loadchecker();
} else if (activeTab == '#openvpn'){
loadopenvpn();
}
});
$("#checker_tabs ul li").click(function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).find('a').css('padding-left', '20px')
$(this).children(".checker").css('padding-left', '30px');
$(this).children(".checker").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
});
$("#backup_tabs ul li").click(function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('border-left', '0px solid var(--right-menu-blue-rolor)');
$(this).find('a').css('padding-left', '20px')
$(this).children(".backup").css('padding-left', '30px');
$(this).children(".backup").css('border-left', '4px solid var(--right-menu-blue-rolor)');
});
});
$('#nginx-section-head').click(function () {
hideAndShowSettings('nginx');
});
@ -794,6 +862,9 @@ $( function() {
$('#keepalived-section-head').click(function () {
hideAndShowSettings('keepalived');
});
$('#mail-section-head').click(function () {
hideAndShowSettings('mail');
});
} );
function hideAndShowSettings(section) {
var ElemId = $('#' + section + '-section-h3');
@ -1089,6 +1160,10 @@ function addTelegram(dialog_id) {
if (data.indexOf('error:') != '-1') {
toastr.error(data);
} else {
var getId = new RegExp('telegram-table-[0-9]+');
var id = data.match(getId) + '';
id = id.split('-').pop();
$('select:regex(id, telegram_channel)').append('<option value=' + id + '>' + $('#telegram-chanel-add').val() + '</option>').selectmenu("refresh");
common_ajax_action_after_success(dialog_id, 'newgroup', 'checker_table', data);
$( "input[type=submit], button" ).button();
$( "input[type=checkbox]" ).checkboxradio();
@ -1121,6 +1196,10 @@ function addSlack(dialog_id) {
if (data.indexOf('error:') != '-1') {
toastr.error(data);
} else {
var getId = new RegExp('slack-table-[0-9]+');
var id = data.match(getId) + '';
id = id.split('-').pop();
$('select:regex(id, slack_channel)').append('<option value=' + id + '>' + $('#slack-chanel-add').val() + '</option>').selectmenu("refresh");
common_ajax_action_after_success(dialog_id, 'newgroup', 'checker_slack_table', data);
$( "input[type=submit], button" ).button();
$( "input[type=checkbox]" ).checkboxradio();
@ -2243,7 +2322,7 @@ function updateService(service) {
$.ajax( {
url: "options.py",
data: {
update_haproxy_wi: 1,
update_roxy_wi: 1,
service: service,
token: $('#token').val()
},
@ -2257,16 +2336,16 @@ function updateService(service) {
toastr.success(service + ' has been updated');
} else if (data.indexOf('Unauthorized') != '-1') {
toastr.clear();
toastr.error('It seems like Unauthorized in the Roxy-WI repository. How to get Roxy-WI auth you can read <b><a href="https://haproxy-wi.org/installation.py" title="How to get Roxy-WI auth">hear</a></b>');
toastr.error('It seems like Unauthorized in the Roxy-WI repository. How to get Roxy-WI auth you can read <b><a href="https://roxy-wi.org/installation.py" title="How to get Roxy-WI auth">hear</a></b>');
} else if (data.indexOf('but not installed') != '-1') {
toastr.clear();
toastr.error('There is settings for Roxy-WI repository, but Roxy-WI is installed without repository. Please reinstall with yum');
} else if (data.indexOf('No Match for argument') != '-1') {
toastr.clear();
toastr.error('It seems like Roxy-WI repository is not set. Please read docs for <b><a href="https://haproxy-wi.org/updates.py">detail</a></b>');
toastr.error('It seems like Roxy-WI repository is not set. Please read docs for <b><a href="https://roxy-wi.org/updates.py">detail</a></b>');
} else if (data.indexOf('password for') != '-1') {
toastr.clear();
toastr.error('It seems like apache user needs to be add to sudoers. Please read docs for <b><a href="https://haproxy-wi.org/updates.py">detail</a></b>');
toastr.error('It seems like apache user needs to be add to sudoers. Please read docs for <b><a href="https://roxy-wi.org/updates.py">detail</a></b>');
} else if (data.indexOf('No packages marked for update') != '-1') {
toastr.clear();
toastr.info('It seems like the lastest version Roxy-WI is installed');
@ -2478,7 +2557,7 @@ function loadupdatehapwi() {
}
} );
}
function loadchecker() {
function loadchecker(tab = 0) {
$.ajax({
url: "options.py",
data: {
@ -2495,8 +2574,10 @@ function loadchecker() {
$('#checker').html(data);
$( "select" ).selectmenu();
$("button").button();
$( "input[type=checkbox]" ).checkboxradio();
$.getScript('/inc/users.js');
$.getScript(awesome);
$( "#checker_tabs" ).tabs( "option", "active", tab );
}
}
} );
@ -2607,3 +2688,160 @@ function showServerInfo(id, ip) {
$('#server_info_link-'+id).attr('title', 'Show System info');
}
}
function updateHaproxyCheckerSettings(id) {
toastr.clear();
let email = 0;
let server = 0;
let backend = 0;
let maxconn = 0;
if ($('#haproxy_server_email-'+id).is(':checked')) {
email = '1';
}
if ($('#haproxy_server_status-'+id).is(':checked')) {
server = '1';
}
if ($('#haproxy_server_backend-'+id).is(':checked')) {
backend = '1';
}
if ($('#haproxy_server_maxconn-'+id).is(':checked')) {
maxconn = '1';
}
$.ajax( {
url: "options.py",
data: {
updateHaproxyCheckerSettings: id,
email: email,
server: server,
backend: backend,
maxconn: maxconn,
telegram_id: $('#haproxy_server_telegram_channel-'+id+' option:selected' ).val(),
slack_id: $('#haproxy_server_slack_channel-'+id+' option:selected').val(),
token: $('#token').val()
},
type: "POST",
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') {
toastr.error(data);
} else if (data.indexOf('ok') != '-1') {
toastr.clear();
$("#haproxy_server_tr_id-"+id).addClass( "update", 1000 );
setTimeout(function() {
$( "#haproxy_server_tr_id-"+id ).removeClass( "update" );
}, 2500 );
}
}
} );
}
function updateKeepalivedCheckerSettings(id) {
toastr.clear();
let email = 0;
let server = 0;
let backend = 0;
if ($('#keepalived_server_email-'+id).is(':checked')) {
email = '1';
}
if ($('#keepalived_server_status-'+id).is(':checked')) {
server = '1';
}
if ($('#keepalived_server_backend-'+id).is(':checked')) {
backend = '1';
}
$.ajax( {
url: "options.py",
data: {
updateKeepalivedCheckerSettings: id,
email: email,
server: server,
backend: backend,
telegram_id: $('#keepalived_server_telegram_channel-'+id+' option:selected' ).val(),
slack_id: $('#keepalived_server_slack_channel-'+id+' option:selected').val(),
token: $('#token').val()
},
type: "POST",
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') {
toastr.error(data);
} else if (data.indexOf('ok') != '-1') {
toastr.clear();
$("#keepalived_server_tr_id-"+id).addClass( "update", 1000 );
setTimeout(function() {
$( "#keepalived_server_tr_id-"+id ).removeClass( "update" );
}, 2500 );
}
}
} );
}
function updateServiceCheckerSettings(id, service_name) {
toastr.clear();
let email = 0;
let server = 0;
if ($('#'+service_name+'_server_email-'+id).is(':checked')) {
email = '1';
}
if ($('#'+service_name+'_server_status-'+id).is(':checked')) {
server = '1';
}
$.ajax( {
url: "options.py",
data: {
updateServiceCheckerSettings: id,
email: email,
server: server,
telegram_id: $('#'+service_name+'_server_telegram_channel-'+id+' option:selected' ).val(),
slack_id: $('#'+service_name+'_server_slack_channel-'+id+' option:selected').val(),
token: $('#token').val()
},
type: "POST",
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('unique') != '-1') {
toastr.error(data);
} else if (data.indexOf('ok') != '-1') {
toastr.clear();
$('#'+service_name+'_server_tr_id-'+id).addClass( "update", 1000 );
setTimeout(function() {
$('#'+service_name+'_server_tr_id-'+id ).removeClass( "update" );
}, 2500 );
}
}
} );
}
function checkWebPanel() {
$.ajax({
url: "options.py",
data: {
check_rabbitmq_alert: 1,
token: $('#token').val()
},
type: "POST",
success: function (data) {
data = data.replace(/\s+/g, ' ');
if (data.indexOf('error:') != '-1' || data.indexOf('error_code') != '-1') {
toastr.error(data);
} else {
toastr.success('Test message has been sent');
}
}
});
}
function checkEmail() {
$.ajax({
url: "options.py",
data: {
check_email_alert: 1,
token: $('#token').val()
},
type: "POST",
success: function (data) {
data = data.replace(/\s+/g, ' ');
if (data.indexOf('error:') != '-1' || data.indexOf('error_code') != '-1') {
toastr.error(data);
} else {
toastr.success('Test message has been sent');
}
}
});
}