From e09103de7da1f40f2b57d036419fd7ec5c929073 Mon Sep 17 00:00:00 2001 From: Aidaho Date: Tue, 16 Jul 2024 08:45:28 +0300 Subject: [PATCH] v7.3.3.0 https://roxy-wi.org/changelog#7_3_3 --- app/create_db.py | 2 +- app/modules/db/server.py | 7 ++ app/modules/roxywi/common.py | 10 ++- app/modules/service/installation.py | 5 +- app/modules/service/udp.py | 1 + app/routes/ha/routes.py | 3 +- app/routes/server/routes.py | 36 +++++++-- .../udp/templates/keepalived-udp.conf.j2 | 2 +- app/static/js/admin/common.js | 3 - app/static/js/admin/server.js | 77 +++++++++++++------ app/static/js/script.js | 5 ++ app/templates/include/admin_servers.html | 3 +- app/templates/languages/en.html | 1 + app/templates/languages/fr.html | 1 + app/templates/languages/pt-br.html | 1 + app/templates/languages/ru.html | 3 +- app/templates/udp/listener.html | 2 +- app/templates/udp/listeners.html | 14 +++- config_other/httpd/roxy-wi.conf | 2 +- config_other/httpd/roxy-wi_deb.conf | 2 +- 20 files changed, 134 insertions(+), 46 deletions(-) diff --git a/app/create_db.py b/app/create_db.py index 1204b64a..3e67b736 100644 --- a/app/create_db.py +++ b/app/create_db.py @@ -662,7 +662,7 @@ def update_db_v_7_3_1(): def update_ver(): try: - Version.update(version='7.3.2.0').execute() + Version.update(version='7.3.3.0').execute() except Exception: print('Cannot update version') diff --git a/app/modules/db/server.py b/app/modules/db/server.py index 8fa606d0..7b782c2d 100644 --- a/app/modules/db/server.py +++ b/app/modules/db/server.py @@ -291,3 +291,10 @@ def is_master(ip, **kwargs): out_error(e) else: return cursor.fetchall() + + +def get_server(server_id: int) -> Server: + try: + return Server.get(Server.server_id == server_id) + except Exception as e: + out_error(e) diff --git a/app/modules/roxywi/common.py b/app/modules/roxywi/common.py index 0f0d08e6..7a555f87 100644 --- a/app/modules/roxywi/common.py +++ b/app/modules/roxywi/common.py @@ -1,6 +1,6 @@ import os import glob -from typing import Any +from typing import Any, Union from flask import request @@ -13,6 +13,7 @@ import app.modules.db.server as server_sql import app.modules.db.history as history_sql import app.modules.db.ha_cluster as ha_sql import app.modules.roxy_wi_tools as roxy_wi_tools +from app.modules.roxywi.class_models import ErrorResponse get_config_var = roxy_wi_tools.GetConfigVar() @@ -94,7 +95,7 @@ def get_files(folder, file_format, server_ip=None) -> list: return file -def logging(server_ip: str, action: str, **kwargs) -> None: +def logging(server_ip: Union[str, int], action: str, **kwargs) -> None: get_date = roxy_wi_tools.GetDate(get_setting('time_zone')) cur_date_in_log = get_date.return_date('date_in_log') log_path = get_config_var.get_config_var('main', 'log_path') @@ -311,3 +312,8 @@ def handle_exceptions(ex: Exception, server_ip: str, message: str, **kwargs: Any def handle_json_exceptions(ex: Exception, message: str, server_ip='Roxy-WI server') -> dict: logging(server_ip, f'error: {message}: {ex}', roxywi=1, login=1) return {'status': 'failed', 'error': f'{message}: {ex}'} + + +def handle_json_exceptions(ex: Exception, message: str, server_ip='Roxy-WI server') -> dict: + logging(server_ip, f'{message}: {ex}', login=1, roxywi=1) + return ErrorResponse(error=f'{message}: {ex}').model_dump(mode='json') diff --git a/app/modules/service/installation.py b/app/modules/service/installation.py index 908a2ca4..dc2f29df 100644 --- a/app/modules/service/installation.py +++ b/app/modules/service/installation.py @@ -34,6 +34,7 @@ def generate_udp_inv(listener_id: int, action: str) -> object: "port": listener['port'], "id": listener['id'], "config": listener['config'], + "lb_algo": listener['lb_algo'], } return inv, server_ips @@ -129,7 +130,6 @@ def generate_haproxy_inv(json_data: json, installed_service: str) -> object: container_name = sql.get_setting('haproxy_container_name') haproxy_ver = '2.9.6-1' is_docker = json_data['services']['haproxy']['docker'] - for k, v in json_data['servers'].items(): if not v['master']: slaves.append(v['ip']) @@ -335,6 +335,9 @@ def install_service(service: str, json_data: str) -> object: try: inv, server_ips = generate_functions[service](json_data, service) + except Exception as e: + roxywi_common.handle_exceptions(e, 'Roxy-WI server', f'Cannot generate inv {service}', roxywi=1) + try: service_actions_after_install(server_ips, service, json_data) return run_ansible(inv, server_ips, service), 201 except Exception as e: diff --git a/app/modules/service/udp.py b/app/modules/service/udp.py index 43a4eacb..4f4ea13f 100644 --- a/app/modules/service/udp.py +++ b/app/modules/service/udp.py @@ -31,6 +31,7 @@ def _validate_form(json_data: json) -> dict: raise ValueError("error: Invalid form data") returned_data['name'] = common.checkAjaxInput(json_data['new-listener-name']) returned_data['desc'] = common.checkAjaxInput(json_data['new-listener-desc']) + returned_data['lb_algo'] = common.checkAjaxInput(json_data['new-udp-balancer-type']) try: returned_data['port'] = int(json_data['new-listener-port']) except Exception: diff --git a/app/routes/ha/routes.py b/app/routes/ha/routes.py index bd9c203e..254e4ddb 100644 --- a/app/routes/ha/routes.py +++ b/app/routes/ha/routes.py @@ -30,7 +30,8 @@ def cluster_function(service): kwargs = { 'clusters': ha_sql.select_clusters(group_id), 'is_needed_tool': common.is_tool('ansible'), - 'user_subscription': roxywi_common.return_user_subscription() + 'user_subscription': roxywi_common.return_user_subscription(), + 'lang': g.user_params['lang'], } return render_template('ha_cluster.html', **kwargs) diff --git a/app/routes/server/routes.py b/app/routes/server/routes.py index 54e8f7b0..148320bc 100644 --- a/app/routes/server/routes.py +++ b/app/routes/server/routes.py @@ -1,6 +1,7 @@ import json +import time -from flask import render_template, request, g, jsonify, abort +from flask import render_template, request, g, jsonify, Response, stream_with_context from flask_login import login_required from app.routes.server import bp @@ -39,11 +40,36 @@ def check_ssh(server_ip): return str(e) -@bp.route('/check/server/') -def check_server(server_ip): - server_ip = common.is_ip_or_dns(server_ip) +@bp.route('/check/server/') +def check_server(server_id): + def get_check(): + while True: + try: + server = server_sql.get_server(server_id) + except Exception as e: + raise e + result = server_mod.server_is_up(server.ip) + status = { + "status": result, + 'name': server.hostname, + 'ip': server.ip, + 'port': server.port, + 'enabled': server.enable, + 'creds_id': server.cred, + 'group_id': server.groups, + 'firewall': server.firewall_enable, + 'slave': server.master, + 'type_ip': server.type_ip, + 'desc': server.desc, + 'protected': server.protected, + } + yield f'data:{json.dumps(status)}\n\n' + time.sleep(60) - return server_mod.server_is_up(server_ip) + response = Response(stream_with_context(get_check()), mimetype="text/event-stream") + response.headers["Cache-Control"] = "no-cache" + response.headers["X-Accel-Buffering"] = "no" + return response @bp.route('/show/if/') diff --git a/app/scripts/ansible/roles/udp/templates/keepalived-udp.conf.j2 b/app/scripts/ansible/roles/udp/templates/keepalived-udp.conf.j2 index 75e5f993..d8fe4d46 100644 --- a/app/scripts/ansible/roles/udp/templates/keepalived-udp.conf.j2 +++ b/app/scripts/ansible/roles/udp/templates/keepalived-udp.conf.j2 @@ -1,5 +1,5 @@ virtual_server {{ vip }} {{ port }} { - lb_algo rr + lb_algo {{ lb_algo }} lb_kind NAT protocol UDP delay_loop 10 diff --git a/app/static/js/admin/common.js b/app/static/js/admin/common.js index 0a110884..d36edbb3 100644 --- a/app/static/js/admin/common.js +++ b/app/static/js/admin/common.js @@ -174,9 +174,6 @@ function ajaxActionServices(action, service) { toastr.success('The ' + service + ' has been ' + action +'ed'); loadServices(); } - }, - error: function(){ - alert(w.data_error); } } ); } diff --git a/app/static/js/admin/server.js b/app/static/js/admin/server.js index c2e0b18d..28233a87 100644 --- a/app/static/js/admin/server.js +++ b/app/static/js/admin/server.js @@ -371,31 +371,58 @@ function showServerInfo(id, ip) { } }); } -function serverIsUp(server_ip, server_id) { - let cur_url = window.location.href.split('/').pop(); - if (cur_url.split('#')[1] == 'servers') { - $.ajax({ - url: "/app/server/check/server/" + server_ip, - success: function (data) { - data = data.replace(/^\s+|\s+$/g, ''); - if (data.indexOf('up') != '-1') { - $('#server_status-' + server_id).removeClass('serverNone'); - $('#server_status-' + server_id).removeClass('serverDown'); - $('#server_status-' + server_id).addClass('serverUp'); - $('#server_status-' + server_id).attr('title', 'Server is reachable'); - } else if (data.indexOf('down') != '-1') { - $('#server_status-' + server_id).removeClass('serverNone'); - $('#server_status-' + server_id).removeClass('serverUp'); - $('#server_status-' + server_id).addClass('serverDown'); - $('#server_status-' + server_id).attr('title', 'Server is unreachable'); - } else { - $('#server_status-' + server_id).removeClass('serverDown'); - $('#server_status-' + server_id).removeClass('serverUp'); - $('#server_status-' + server_id).addClass('serverNone'); - $('#server_status-' + server_id).attr('title', 'Cannot get server status'); - } - } - }); +function serverIsUp(server_id) { + const source = new EventSource(`/app/server/check/server/${server_id}`); + let server_div = $('#server_status-' + server_id); + source.onmessage = function (event) { + let data = JSON.parse(event.data); + if (data.status === 'up') { + server_div.removeClass('serverNone'); + server_div.removeClass('serverDown'); + server_div.addClass('serverUp'); + // server_div.attr('title', 'Server is reachable'); + } else if (data.status === 'down') { + server_div.removeClass('serverNone'); + server_div.removeClass('serverUp'); + server_div.addClass('serverDown'); + // server_div.attr('title', 'Server is unreachable'); + } else { + server_div.removeClass('serverDown'); + server_div.removeClass('serverUp'); + server_div.addClass('serverNone'); + // server_div.attr('title', 'Cannot get server status'); + } + $('#hostname-' + server_id).val(data.name); + $('#ip-' + server_id).val(data.ip); + $('#port-' + server_id).val(data.port); + $('#desc-' + server_id).val(data.desc); + if (data.enabled === 1) { + $('#enable-' + server_id).prop('checked', true); + } else { + $('#enable-' + server_id).prop('checked', false); + } + if (data.protected === 1) { + $('#protected-' + server_id).prop('checked', true); + } else { + $('#protected-' + server_id).prop('checked', false); + } + if (data.type_ip === 1) { + $('#typeip-' + server_id).prop('checked', true); + } else { + $('#typeip-' + server_id).prop('checked', false); + } + $('#typeip-' + server_id).checkboxradio("refresh"); + $('#protected-' + server_id).checkboxradio("refresh"); + $('#enable-' + server_id).checkboxradio("refresh"); + $('#servergroup-' + server_id).val(data.group_id).change(); + $('#credentials-' + server_id).val(data.creds_id).change(); + $('#slavefor-' + server_id).val(data.creds_id).change(); + $('#servergroup-' + server_id).selectmenu("refresh"); + $('#credentials-' + server_id).selectmenu("refresh"); + $('#slavefor-' + server_id).selectmenu("refresh"); + } + source.onerror = function (event) { + server_div.remove(); } } function openChangeServerServiceDialog(server_id) { diff --git a/app/static/js/script.js b/app/static/js/script.js index fc35f294..84d95a31 100644 --- a/app/static/js/script.js +++ b/app/static/js/script.js @@ -326,6 +326,11 @@ $( document ).ajaxSend(function( event, request, settings ) { $( document ).ajaxComplete(function( event, request, settings ) { NProgress.done(); }); +$(document).ajaxError(function myErrorHandler(event, xhr, ajaxOptions, thrownError) { + if (xhr.status != 401) { + toastr.error(xhr.responseJSON.error); + } +}); function showStats() { $.ajax({ url: "/app/stats/view/" + $("#service").val() + "/" + $("#serv").val(), diff --git a/app/templates/include/admin_servers.html b/app/templates/include/admin_servers.html index e1906553..d0ada9c1 100644 --- a/app/templates/include/admin_servers.html +++ b/app/templates/include/admin_servers.html @@ -176,7 +176,6 @@ {% endif %} diff --git a/app/templates/languages/en.html b/app/templates/languages/en.html index 2f29726b..9b56ac5f 100644 --- a/app/templates/languages/en.html +++ b/app/templates/languages/en.html @@ -518,6 +518,7 @@ "save_apply": "Save - means saving the UDP listener settings for Roxy-WI, without changing the component settings on the cluster members or standalone server.
Apply - recreate the UDP listener configuration on the cluster member servers or standalone server.", "listener_ip": "IP for binding UDP Listener. Start typing", "listener_port": "Port for binding UDP Listener", + "balancing_type": "Balancing type", } %} {% set nettools_page = { diff --git a/app/templates/languages/fr.html b/app/templates/languages/fr.html index fdfb16fb..a4fa2a9c 100644 --- a/app/templates/languages/fr.html +++ b/app/templates/languages/fr.html @@ -518,6 +518,7 @@ "save_apply": "Enregistrer - signifie enregistrer les paramètres du Écouteur UDP pour Roxy-WI, sans modifier les paramètres des composants sur les membres du cluster ou serveur autonome.
Appliquer : recréez la configuration du Écouteur UDP sur les serveurs membres du cluster et installez des services supplémentaires ou serveur autonome.", "listener_ip": "IP pour lier l’écouteur UDP. Commencer à écrire", "listener_port": "Port pour lier l'écouteur UDP", + "balancing_type": "Type d'équilibrage", } %} {% set nettools_page = { diff --git a/app/templates/languages/pt-br.html b/app/templates/languages/pt-br.html index f647a510..4852ef48 100644 --- a/app/templates/languages/pt-br.html +++ b/app/templates/languages/pt-br.html @@ -518,6 +518,7 @@ "save_apply": "Salvar - significa salvar as configurações do Ouvinte UDP para Roxy-WI, sem alterar as configurações do componente nos membros do cluster ou servidor independente.
Aplicar – recrie a configuração do Ouvinte UDP nos servidores membros do cluster e instale serviços adicionais ou servidor independente.", "listener_ip": "IP para vincular o ouvinte UDP. Começe a digitar", "listener_port": "Porta para ligação do ouvinte UDP", + "balancing_type": "Tipo de balanceamento", } %} {% set nettools_page = { diff --git a/app/templates/languages/ru.html b/app/templates/languages/ru.html index ec61dc9d..a836da74 100644 --- a/app/templates/languages/ru.html +++ b/app/templates/languages/ru.html @@ -495,7 +495,7 @@ } %} {% set ha_page = { - "ha": "кластер высокой доступности", + "ha": "Кластер высокой доступности", "has": "Кластера высокой доступности", "create_virt_server": "Roxy-WI добавит адрес VRRP в качестве отдельного сервера", "return_master": "Если этот флаг установлен, мастер Keepalived вернет VRRP, когда служба снова запустится", @@ -518,6 +518,7 @@ "save_apply": "Сохранить - подразумевает сохранение настроек UDP слушателя для Roxy-WI, без изменения настроек компонентов на участниках кластера или standalone сервера.
Применить - пересоздать конфигурацию HА кластера на серверах участниках кластера и установит дополнительные сервисы или standalone сервера.", "listener_ip": "IP для привязки UDP Listener. Начните печатать", "listener_port": "Порт для привязки UDP Listener", + "balancing_type": "Тип балансировки", } %} {% set nettools_page = { diff --git a/app/templates/udp/listener.html b/app/templates/udp/listener.html index 6507d7c6..a4fbd171 100644 --- a/app/templates/udp/listener.html +++ b/app/templates/udp/listener.html @@ -12,7 +12,7 @@ {% endif %} -{# #} +
diff --git a/app/templates/udp/listeners.html b/app/templates/udp/listeners.html index 3e63f131..2886e91e 100644 --- a/app/templates/udp/listeners.html +++ b/app/templates/udp/listeners.html @@ -106,13 +106,25 @@ {{ input('new-listener-port', type='number', title=lang.udp_page.listener_port) }} + + + {{lang.udp_page.balancing_type}} + * + + + {% set values = {'rr': 'Round robin', 'wrr': 'Weighted Round Robin', 'lc': 'Least Connection', + 'wlc': 'Weighted Least Connection', 'sh': 'Source Hashing', 'dh': 'Destination Hashing', + 'lblc': 'Locality-Based Least Connection' } %} + {{ select('new-udp-balancer-type', values=values) }} + + {{lang.words.backend|title()}} {{lang.words.servers|title()}} * - + diff --git a/config_other/httpd/roxy-wi.conf b/config_other/httpd/roxy-wi.conf index 144e69e8..8c263a11 100644 --- a/config_other/httpd/roxy-wi.conf +++ b/config_other/httpd/roxy-wi.conf @@ -22,7 +22,7 @@ WSGIDaemonProcess roxy-wi-api display-name=%{GROUP} user=apache group=apache processes=1 threads=5 WSGIScriptAlias /api /var/www/haproxy-wi/api/app.wsgi - WSGIDaemonProcess roxy-wi-app display-name=%{GROUP} user=apache group=apache processes=1 threads=10 + WSGIDaemonProcess roxy-wi-app display-name=%{GROUP} user=apache group=apache processes=5 threads=20 WSGIScriptAlias /app /var/www/haproxy-wi/app/app.wsgi diff --git a/config_other/httpd/roxy-wi_deb.conf b/config_other/httpd/roxy-wi_deb.conf index 003484c9..45f07961 100644 --- a/config_other/httpd/roxy-wi_deb.conf +++ b/config_other/httpd/roxy-wi_deb.conf @@ -22,7 +22,7 @@ WSGIDaemonProcess roxy-wi-api display-name=%{GROUP} user=www-data group=www-data processes=1 threads=5 WSGIScriptAlias /api /var/www/haproxy-wi/api/app.wsgi - WSGIDaemonProcess roxy-wi-app display-name=%{GROUP} user=www-data group=www-data processes=1 threads=10 + WSGIDaemonProcess roxy-wi-app display-name=%{GROUP} user=www-data group=www-data processes=5 threads=20 WSGIScriptAlias /app /var/www/haproxy-wi/app/app.wsgi