Aidaho 2024-07-16 08:45:28 +03:00
parent 45b964d341
commit e09103de7d
20 changed files with 134 additions and 46 deletions

View File

@ -662,7 +662,7 @@ def update_db_v_7_3_1():
def update_ver(): def update_ver():
try: try:
Version.update(version='7.3.2.0').execute() Version.update(version='7.3.3.0').execute()
except Exception: except Exception:
print('Cannot update version') print('Cannot update version')

View File

@ -291,3 +291,10 @@ def is_master(ip, **kwargs):
out_error(e) out_error(e)
else: else:
return cursor.fetchall() 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)

View File

@ -1,6 +1,6 @@
import os import os
import glob import glob
from typing import Any from typing import Any, Union
from flask import request 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.history as history_sql
import app.modules.db.ha_cluster as ha_sql import app.modules.db.ha_cluster as ha_sql
import app.modules.roxy_wi_tools as roxy_wi_tools 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() get_config_var = roxy_wi_tools.GetConfigVar()
@ -94,7 +95,7 @@ def get_files(folder, file_format, server_ip=None) -> list:
return file 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')) get_date = roxy_wi_tools.GetDate(get_setting('time_zone'))
cur_date_in_log = get_date.return_date('date_in_log') cur_date_in_log = get_date.return_date('date_in_log')
log_path = get_config_var.get_config_var('main', 'log_path') 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: 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) logging(server_ip, f'error: {message}: {ex}', roxywi=1, login=1)
return {'status': 'failed', 'error': f'{message}: {ex}'} 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')

View File

@ -34,6 +34,7 @@ def generate_udp_inv(listener_id: int, action: str) -> object:
"port": listener['port'], "port": listener['port'],
"id": listener['id'], "id": listener['id'],
"config": listener['config'], "config": listener['config'],
"lb_algo": listener['lb_algo'],
} }
return inv, server_ips 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') container_name = sql.get_setting('haproxy_container_name')
haproxy_ver = '2.9.6-1' haproxy_ver = '2.9.6-1'
is_docker = json_data['services']['haproxy']['docker'] is_docker = json_data['services']['haproxy']['docker']
for k, v in json_data['servers'].items(): for k, v in json_data['servers'].items():
if not v['master']: if not v['master']:
slaves.append(v['ip']) slaves.append(v['ip'])
@ -335,6 +335,9 @@ def install_service(service: str, json_data: str) -> object:
try: try:
inv, server_ips = generate_functions[service](json_data, service) 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) service_actions_after_install(server_ips, service, json_data)
return run_ansible(inv, server_ips, service), 201 return run_ansible(inv, server_ips, service), 201
except Exception as e: except Exception as e:

View File

@ -31,6 +31,7 @@ def _validate_form(json_data: json) -> dict:
raise ValueError("error: Invalid form data") raise ValueError("error: Invalid form data")
returned_data['name'] = common.checkAjaxInput(json_data['new-listener-name']) returned_data['name'] = common.checkAjaxInput(json_data['new-listener-name'])
returned_data['desc'] = common.checkAjaxInput(json_data['new-listener-desc']) returned_data['desc'] = common.checkAjaxInput(json_data['new-listener-desc'])
returned_data['lb_algo'] = common.checkAjaxInput(json_data['new-udp-balancer-type'])
try: try:
returned_data['port'] = int(json_data['new-listener-port']) returned_data['port'] = int(json_data['new-listener-port'])
except Exception: except Exception:

View File

@ -30,7 +30,8 @@ def cluster_function(service):
kwargs = { kwargs = {
'clusters': ha_sql.select_clusters(group_id), 'clusters': ha_sql.select_clusters(group_id),
'is_needed_tool': common.is_tool('ansible'), '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) return render_template('ha_cluster.html', **kwargs)

View File

@ -1,6 +1,7 @@
import json 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 flask_login import login_required
from app.routes.server import bp from app.routes.server import bp
@ -39,11 +40,36 @@ def check_ssh(server_ip):
return str(e) return str(e)
@bp.route('/check/server/<server_ip>') @bp.route('/check/server/<int:server_id>')
def check_server(server_ip): def check_server(server_id):
server_ip = common.is_ip_or_dns(server_ip) 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/<server_ip>') @bp.route('/show/if/<server_ip>')

View File

@ -1,5 +1,5 @@
virtual_server {{ vip }} {{ port }} { virtual_server {{ vip }} {{ port }} {
lb_algo rr lb_algo {{ lb_algo }}
lb_kind NAT lb_kind NAT
protocol UDP protocol UDP
delay_loop 10 delay_loop 10

View File

@ -174,9 +174,6 @@ function ajaxActionServices(action, service) {
toastr.success('The ' + service + ' has been ' + action +'ed'); toastr.success('The ' + service + ' has been ' + action +'ed');
loadServices(); loadServices();
} }
},
error: function(){
alert(w.data_error);
} }
} ); } );
} }

View File

@ -371,31 +371,58 @@ function showServerInfo(id, ip) {
} }
}); });
} }
function serverIsUp(server_ip, server_id) { function serverIsUp(server_id) {
let cur_url = window.location.href.split('/').pop(); const source = new EventSource(`/app/server/check/server/${server_id}`);
if (cur_url.split('#')[1] == 'servers') { let server_div = $('#server_status-' + server_id);
$.ajax({ source.onmessage = function (event) {
url: "/app/server/check/server/" + server_ip, let data = JSON.parse(event.data);
success: function (data) { if (data.status === 'up') {
data = data.replace(/^\s+|\s+$/g, ''); server_div.removeClass('serverNone');
if (data.indexOf('up') != '-1') { server_div.removeClass('serverDown');
$('#server_status-' + server_id).removeClass('serverNone'); server_div.addClass('serverUp');
$('#server_status-' + server_id).removeClass('serverDown'); // server_div.attr('title', 'Server is reachable');
$('#server_status-' + server_id).addClass('serverUp'); } else if (data.status === 'down') {
$('#server_status-' + server_id).attr('title', 'Server is reachable'); server_div.removeClass('serverNone');
} else if (data.indexOf('down') != '-1') { server_div.removeClass('serverUp');
$('#server_status-' + server_id).removeClass('serverNone'); server_div.addClass('serverDown');
$('#server_status-' + server_id).removeClass('serverUp'); // server_div.attr('title', 'Server is unreachable');
$('#server_status-' + server_id).addClass('serverDown');
$('#server_status-' + server_id).attr('title', 'Server is unreachable');
} else { } else {
$('#server_status-' + server_id).removeClass('serverDown'); server_div.removeClass('serverDown');
$('#server_status-' + server_id).removeClass('serverUp'); server_div.removeClass('serverUp');
$('#server_status-' + server_id).addClass('serverNone'); server_div.addClass('serverNone');
$('#server_status-' + server_id).attr('title', 'Cannot get server status'); // 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) { function openChangeServerServiceDialog(server_id) {

View File

@ -326,6 +326,11 @@ $( document ).ajaxSend(function( event, request, settings ) {
$( document ).ajaxComplete(function( event, request, settings ) { $( document ).ajaxComplete(function( event, request, settings ) {
NProgress.done(); NProgress.done();
}); });
$(document).ajaxError(function myErrorHandler(event, xhr, ajaxOptions, thrownError) {
if (xhr.status != 401) {
toastr.error(xhr.responseJSON.error);
}
});
function showStats() { function showStats() {
$.ajax({ $.ajax({
url: "/app/stats/view/" + $("#service").val() + "/" + $("#serv").val(), url: "/app/stats/view/" + $("#service").val() + "/" + $("#serv").val(),

View File

@ -176,7 +176,6 @@
{% endif %} {% endif %}
<script> <script>
{%- for server in servers %} {%- for server in servers %}
setInterval(serverIsUp, 18000, '{{server.2}}', '{{server.0}}'); serverIsUp('{{server.0}}');
serverIsUp('{{server.2}}', '{{server.0}}');
{%- endfor %} {%- endfor %}
</script> </script>

View File

@ -518,6 +518,7 @@
"save_apply": "<b>Save</b> - means saving the UDP listener settings for Roxy-WI, without changing the component settings on the cluster members or standalone server. <br /> <b>Apply</b> - recreate the UDP listener configuration on the cluster member servers or standalone server.", "save_apply": "<b>Save</b> - means saving the UDP listener settings for Roxy-WI, without changing the component settings on the cluster members or standalone server. <br /> <b>Apply</b> - recreate the UDP listener configuration on the cluster member servers or standalone server.",
"listener_ip": "IP for binding UDP Listener. Start typing", "listener_ip": "IP for binding UDP Listener. Start typing",
"listener_port": "Port for binding UDP Listener", "listener_port": "Port for binding UDP Listener",
"balancing_type": "Balancing type",
} }
%} %}
{% set nettools_page = { {% set nettools_page = {

View File

@ -518,6 +518,7 @@
"save_apply": "<b>Enregistrer</b> - 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. <br /> <b>Appliquer </b>: recréez la configuration du Écouteur UDP sur les serveurs membres du cluster et installez des services supplémentaires ou serveur autonome.", "save_apply": "<b>Enregistrer</b> - 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. <br /> <b>Appliquer </b>: 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_ip": "IP pour lier lécouteur UDP. Commencer à écrire",
"listener_port": "Port pour lier l'écouteur UDP", "listener_port": "Port pour lier l'écouteur UDP",
"balancing_type": "Type d'équilibrage",
} }
%} %}
{% set nettools_page = { {% set nettools_page = {

View File

@ -518,6 +518,7 @@
"save_apply": "<b>Salvar</b> - 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. <br /> <b>Aplicar</b> recrie a configuração do Ouvinte UDP nos servidores membros do cluster e instale serviços adicionais ou servidor independente.", "save_apply": "<b>Salvar</b> - 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. <br /> <b>Aplicar</b> 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_ip": "IP para vincular o ouvinte UDP. Começe a digitar",
"listener_port": "Porta para ligação do ouvinte UDP", "listener_port": "Porta para ligação do ouvinte UDP",
"balancing_type": "Tipo de balanceamento",
} }
%} %}
{% set nettools_page = { {% set nettools_page = {

View File

@ -495,7 +495,7 @@
} }
%} %}
{% set ha_page = { {% set ha_page = {
"ha": "кластер высокой доступности", "ha": "Кластер высокой доступности",
"has": "Кластера высокой доступности", "has": "Кластера высокой доступности",
"create_virt_server": "Roxy-WI добавит адрес VRRP в качестве отдельного сервера", "create_virt_server": "Roxy-WI добавит адрес VRRP в качестве отдельного сервера",
"return_master": "Если этот флаг установлен, мастер Keepalived вернет VRRP, когда служба снова запустится", "return_master": "Если этот флаг установлен, мастер Keepalived вернет VRRP, когда служба снова запустится",
@ -518,6 +518,7 @@
"save_apply": "<b>Сохранить</b> - подразумевает сохранение настроек UDP слушателя для Roxy-WI, без изменения настроек компонентов на участниках кластера или standalone сервера. <br /> <b>Применить</b> - пересоздать конфигурацию HА кластера на серверах участниках кластера и установит дополнительные сервисы или standalone сервера.", "save_apply": "<b>Сохранить</b> - подразумевает сохранение настроек UDP слушателя для Roxy-WI, без изменения настроек компонентов на участниках кластера или standalone сервера. <br /> <b>Применить</b> - пересоздать конфигурацию HА кластера на серверах участниках кластера и установит дополнительные сервисы или standalone сервера.",
"listener_ip": "IP для привязки UDP Listener. Начните печатать", "listener_ip": "IP для привязки UDP Listener. Начните печатать",
"listener_port": "Порт для привязки UDP Listener", "listener_port": "Порт для привязки UDP Listener",
"balancing_type": "Тип балансировки",
} }
%} %}
{% set nettools_page = { {% set nettools_page = {

View File

@ -12,7 +12,7 @@
<a class="edit" onclick="createUDPListener(true, '{{listener.id}}')"></a> <a class="edit" onclick="createUDPListener(true, '{{listener.id}}')"></a>
<a class="delete" onclick="confirmDeleteListener('{{listener.id}}')"></a> <a class="delete" onclick="confirmDeleteListener('{{listener.id}}')"></a>
{% endif %} {% endif %}
{# <a href="{{ url_for('main.service_history', service='cluster', server_ip=listener.id) }}" title="{{lang.words.view|title()}} {{lang.words.history3}} {{listener.name}}" class="history" style="margin: 0 5px 0 10px;"></a>#} <a href="{{ url_for('main.service_history', service='udp', server_ip=listener.id) }}" title="{{lang.words.view|title()}} {{lang.words.history3}} {{listener.name}}" class="history" style="margin: 0 5px 0 10px;"></a>
</span> </span>
</div> </div>
<div class="server-desc"> <div class="server-desc">

View File

@ -106,13 +106,25 @@
{{ input('new-listener-port', type='number', title=lang.udp_page.listener_port) }} {{ input('new-listener-port', type='number', title=lang.udp_page.listener_port) }}
</td> </td>
</tr> </tr>
<tr>
<td class="padding20">
{{lang.udp_page.balancing_type}}
<span class="need-field">*</span>
</td>
<td>
{% 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) }}
</td>
</tr>
<tr> <tr>
<td class="padding20"> <td class="padding20">
{{lang.words.backend|title()}} {{lang.words.servers|title()}} {{lang.words.backend|title()}} {{lang.words.servers|title()}}
<span class="need-field">*</span> <span class="need-field">*</span>
</td> </td>
<td id="new-udp-servers-td"> <td id="new-udp-servers-td">
<a class="link add-server" id="frontend_add_acl" title="{{lang.words.add|title()}} ACL" style="cursor: pointer; display: none;"></a> <a class="link add-server" id="frontend_add_acl" title="{{lang.words.add|title()}} {{ lang.words.backend }} {{ lang.words.server }}" style="cursor: pointer; display: none;"></a>
</td> </td>
</tr> </tr>
<tr> <tr>

View File

@ -22,7 +22,7 @@
WSGIDaemonProcess roxy-wi-api display-name=%{GROUP} user=apache group=apache processes=1 threads=5 WSGIDaemonProcess roxy-wi-api display-name=%{GROUP} user=apache group=apache processes=1 threads=5
WSGIScriptAlias /api /var/www/haproxy-wi/api/app.wsgi 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 WSGIScriptAlias /app /var/www/haproxy-wi/app/app.wsgi
<Directory /var/www/haproxy-wi/app/> <Directory /var/www/haproxy-wi/app/>

View File

@ -22,7 +22,7 @@
WSGIDaemonProcess roxy-wi-api display-name=%{GROUP} user=www-data group=www-data processes=1 threads=5 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 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 WSGIScriptAlias /app /var/www/haproxy-wi/app/app.wsgi
<Directory /var/www/haproxy-wi/app/> <Directory /var/www/haproxy-wi/app/>