From f3f540c291b51cfe3878dbeca3be9647093cbab6 Mon Sep 17 00:00:00 2001 From: Aidaho Date: Wed, 19 Feb 2025 10:49:07 +0300 Subject: [PATCH] v8.1.6: Add UDP listener checker functionality Introduces the ability to enable or disable a checker service for UDP listeners. Includes UI updates, database migration, new API route, and backend logic to handle checker settings on UDP listeners. --- app/api/routes/routes.py | 3 ++- app/create_db.py | 21 ++++++++++++++++++++- app/modules/db/checker.py | 9 ++++++++- app/modules/db/db_model.py | 1 + app/modules/db/udp.py | 9 +++++++++ app/modules/roxywi/class_models.py | 1 + app/modules/server/server.py | 2 ++ app/modules/tools/alerting.py | 6 ++++-- app/static/js/udp.js | 25 +++++++++++++++++++++++++ app/templates/udp/listener.html | 12 ++++++++++++ app/views/udp/views.py | 29 +++++++++++++++++++++++++++++ 11 files changed, 113 insertions(+), 5 deletions(-) diff --git a/app/api/routes/routes.py b/app/api/routes/routes.py index 0c8aa3dd..cd18fe68 100644 --- a/app/api/routes/routes.py +++ b/app/api/routes/routes.py @@ -16,7 +16,7 @@ from app.views.service.lets_encrypt_views import LetsEncryptsView, LetsEncryptVi from app.views.service.haproxy_lists_views import HaproxyListView from app.views.ha.views import HAView, HAVIPView, HAVIPsView from app.views.user.views import UserView, UserGroupView, UserRoles -from app.views.udp.views import UDPListener, UDPListeners, UDPListenerActionView, UDPListenerBackendStatusView +from app.views.udp.views import UDPListener, UDPListeners, UDPListenerActionView, UDPListenerBackendStatusView, UdpListenerCheckerView from app.views.channel.views import ChannelView, ChannelsView from app.views.tools.views import CheckerView from app.views.tools.port_scanner_views import PortScannerView, PortScannerPortsView @@ -60,6 +60,7 @@ bp.add_url_rule('/ha///vips', view_func=HAVIPsView.as_v register_api(UDPListener, 'udp_listener', '//listener', 'listener_id') bp.add_url_rule('//listener//', view_func=UDPListenerActionView.as_view('listener_action'), methods=['GET']) bp.add_url_rule('//listener//', view_func=UDPListenerBackendStatusView.as_view('UDPListenerBackendStatusView'), methods=['GET']) +bp.add_url_rule('//listener//checker/', view_func=UdpListenerCheckerView.as_view('UdpListenerCheckerView'), methods=['POST']) bp.add_url_rule('//listeners', view_func=UDPListeners.as_view('listeners'), methods=['GET']) bp.add_url_rule('/service///install', view_func=InstallGetStatus.as_view('install_status'), methods=['GET']) bp.add_url_rule('/service///install', view_func=InstallGetStatus.as_view('install_status_ip'), methods=['GET']) diff --git a/app/create_db.py b/app/create_db.py index 30ed5d03..f91547f5 100644 --- a/app/create_db.py +++ b/app/create_db.py @@ -703,9 +703,27 @@ def update_db_v_8_1_4(): print("An error occurred:", e) +def update_db_v_8_1_6(): + try: + if mysql_enable: + migrate( + migrator.add_column('udp_balancers', 'is_checker', IntegerField(default=0)), + ) + else: + migrate( + migrator.add_column('udp_balancers', 'is_checker', IntegerField(constraints=[SQL('DEFAULT 0')])), + ) + except Exception as e: + if (e.args[0] == 'duplicate column name: is_checker' or 'column "is_checker" of relation "udp_balancers" already exists' + or str(e) == '(1060, "Duplicate column name \'is_checker\'")'): + print('Updating... DB has been updated to version 8.1.6') + else: + print("An error occurred:", e) + + def update_ver(): try: - Version.update(version='8.1.5').execute() + Version.update(version='8.1.6').execute() except Exception: print('Cannot update version') @@ -737,4 +755,5 @@ def update_all(): update_db_v_8_1_0_3() update_db_v_8_1_2() update_db_v_8_1_4() + update_db_v_8_1_6() update_ver() diff --git a/app/modules/db/checker.py b/app/modules/db/checker.py index f1bf8a80..eec6cb8c 100644 --- a/app/modules/db/checker.py +++ b/app/modules/db/checker.py @@ -1,4 +1,4 @@ -from app.modules.db.db_model import CheckerSetting, Server, ServiceStatus +from app.modules.db.db_model import CheckerSetting, Server, ServiceStatus, UDPBalancer from app.modules.db.common import out_error @@ -146,3 +146,10 @@ def select_all_alerts(group_id: int): return query.execute() except Exception as e: out_error(e) + + +def select_checker_udp_enabled(): + try: + return UDPBalancer.select().where(UDPBalancer.is_checker == 1) + except Exception as e: + out_error(e) diff --git a/app/modules/db/db_model.py b/app/modules/db/db_model.py index f32eb5bf..cbf8656b 100644 --- a/app/modules/db/db_model.py +++ b/app/modules/db/db_model.py @@ -756,6 +756,7 @@ class UDPBalancer(BaseModel): delay_loop = IntegerField(constraints=[SQL('DEFAULT "10"')]) delay_before_retry = IntegerField(constraints=[SQL('DEFAULT "10"')]) retry = IntegerField(constraints=[SQL('DEFAULT "3"')]) + is_checker = IntegerField(constraints=[SQL('DEFAULT "0"')]) class Meta: table_name = 'udp_balancers' diff --git a/app/modules/db/udp.py b/app/modules/db/udp.py index 9ce8e51a..4786bb21 100644 --- a/app/modules/db/udp.py +++ b/app/modules/db/udp.py @@ -3,6 +3,15 @@ from app.modules.db.common import out_error from app.modules.roxywi.exception import RoxywiResourceNotFound, RoxywiGroupNotFound +def select_all_listeners() -> UDPBalancer: + try: + return UDPBalancer.select().execute() + except UDPBalancer.DoesNotExist: + raise RoxywiResourceNotFound + except Exception as e: + out_error(e) + + def select_listeners(group_id: int) -> UDPBalancer: try: return UDPBalancer.select().where(UDPBalancer.group_id == group_id).execute() diff --git a/app/modules/roxywi/class_models.py b/app/modules/roxywi/class_models.py index ec419c66..634506c0 100644 --- a/app/modules/roxywi/class_models.py +++ b/app/modules/roxywi/class_models.py @@ -93,6 +93,7 @@ class UdpListenerRequest(BaseModel): delay_loop: Optional[int] = 10 delay_before_retry: Optional[int] = 10 retry: Optional[int] = 3 + is_checker: Optional[bool] = 0 class UserPost(BaseModel): diff --git a/app/modules/server/server.py b/app/modules/server/server.py index bf46c9af..2da52f4d 100644 --- a/app/modules/server/server.py +++ b/app/modules/server/server.py @@ -1,4 +1,5 @@ import json +import os from flask import render_template @@ -472,6 +473,7 @@ def delete_server(server_id: int) -> None: server_sql.delete_system_info(server_id) service_sql.delete_service_settings(server_id) roxywi_common.logging(server.ip, f'The server {server.hostname} has been deleted', roxywi=1, login=1) + os.system(f'ssh-keygen -R {server.ip}') def server_is_up(server_ip: str) -> str: diff --git a/app/modules/tools/alerting.py b/app/modules/tools/alerting.py index b5427092..3cccc094 100644 --- a/app/modules/tools/alerting.py +++ b/app/modules/tools/alerting.py @@ -54,8 +54,10 @@ def alert_routing( ) -> None: try: subject: str = level + ': ' + mes - server_id: int = server_sql.get_server_by_ip(server_ip).server_id - checker_settings = checker_sql.select_checker_settings_for_server(service_id, server_id) + checker_settings = [] + if service_id != 6: + server_id: int = server_sql.get_server_by_ip(server_ip).server_id + checker_settings = checker_sql.select_checker_settings_for_server(service_id, server_id) except Exception as e: raise Exception(f'Cannot get settings: {e}') diff --git a/app/static/js/udp.js b/app/static/js/udp.js index aebd5e01..c9ca485d 100644 --- a/app/static/js/udp.js +++ b/app/static/js/udp.js @@ -35,6 +35,30 @@ $( function() { $('.check_backends').hide(); } }); + $( ".udp-act-links" ).change(function() { + let id = $(this).attr('id').split('-'); + console.log(id) + console.log('update checker settings ' + id[1]) + let alert_en = 0; + if ($('#alert-' + id[1]).is(':checked')) { + alert_en = 1; + } + $.ajax({ + url: api_prefix + "/udp/listener/" + id[1] + '/checker/' + alert_en, + contentType: "application/json; charset=utf-8", + method: "POST", + success: function (data) { + if (data.status === 'failed') { + toastr.error(data.error); + } else { + $("#server-" + id[1]).addClass("update", 1000); + setTimeout(function () { + $("#server-" + id[1]).removeClass("update"); + }, 2500); + } + } + }); + }); }); function getHAClusterVIPS(cluster_id) { let vip_id = $('#vip'); @@ -384,6 +408,7 @@ function getUDPListener(listener_id, new_listener=false) { } $('#listener-'+listener_id).removeClass('animated-background'); $.getScript(awesome); + $( "input[type=checkbox]" ).checkboxradio(); } } }); diff --git a/app/templates/udp/listener.html b/app/templates/udp/listener.html index 86142283..19977808 100644 --- a/app/templates/udp/listener.html +++ b/app/templates/udp/listener.html @@ -1,5 +1,7 @@ {% import 'languages/'+lang|default('en')+'.html' as lang %} {% from 'include/input_macros.html' import input, checkbox, copy_to_clipboard %} +{% set checker_desc = lang.services.hapservers_desc %} +
@@ -48,6 +50,16 @@ {% endfor %}
+