Aidaho 2024-09-03 12:09:03 +03:00
parent 69e5c2cca9
commit 6d11d04577
14 changed files with 242 additions and 97 deletions

View File

@ -521,7 +521,8 @@ def del_ssl_cert(server_ip: str, cert_id: str) -> str:
def upload_ssl_cert(server_ip: str, ssl_name: str, ssl_cont: str) -> str: def upload_ssl_cert(server_ip: str, ssl_name: str, ssl_cont: str) -> str:
cert_path = sql.get_setting('cert_path') cert_path = sql.get_setting('cert_path')
tmp_path = sql.get_setting('tmp_config_path') tmp_path = sql.get_setting('tmp_config_path')
slave_output = '' output = []
server_ip = str(server_ip)
if ssl_name is None: if ssl_name is None:
return 'error: Please enter a desired name' return 'error: Please enter a desired name'
@ -539,12 +540,13 @@ def upload_ssl_cert(server_ip: str, ssl_name: str, ssl_cont: str) -> str:
for master in masters: for master in masters:
if master[0] is not None: if master[0] is not None:
config_mod.upload(master[0], f'{cert_path}/{name}', path_to_file) config_mod.upload(master[0], f'{cert_path}/{name}', path_to_file)
slave_output += f'success: the SSL file has been uploaded to {master[0]} into: {cert_path}/{name} \n' output.append(f'success: the SSL file has been uploaded to {master[0]} into: {cert_path}/{name}')
try: try:
config_mod.upload(server_ip, f'{cert_path}/{name}', path_to_file) config_mod.upload(server_ip, f'{cert_path}/{name}', path_to_file)
output.append(f'success: the SSL file has been uploaded to {server_ip} into: {cert_path}/{name}')
except Exception as e: except Exception as e:
roxywi_common.logging('Roxy-WI server', str(e), roxywi=1) roxywi_common.logging('Roxy-WI server', str(e), roxywi=1)
return f'error: cannot upload SSL cert: {e}' return f'error: cannot upload SSL cert: {e}'
roxywi_common.logging(server_ip, f"add#ssl uploaded a new SSL cert {name}", roxywi=1, login=1) roxywi_common.logging(server_ip, f"add#ssl uploaded a new SSL cert {name}", roxywi=1, login=1)
return f'success: the SSL file has been uploaded to {server_ip} into: {cert_path}/{name} \n {slave_output}' return output

View File

@ -1,27 +1,24 @@
from app.modules.db.db_model import SavedServer, Option from app.modules.db.db_model import SavedServer, Option
from app.modules.db.common import out_error from app.modules.db.common import out_error
from app.modules.roxywi.exception import RoxywiResourceNotFound
def update_saved_server(server, description, saved_id): def update_saved_server(server, description, saved_id):
query_update = SavedServer.update(server=server, description=description).where(SavedServer.id == saved_id)
try: try:
query_update.execute() SavedServer.update(server=server, description=description).where(SavedServer.id == saved_id).execute()
except SavedServer.DoesNotExist:
raise RoxywiResourceNotFound
except Exception as e: except Exception as e:
out_error(e) out_error(e)
return False
else:
return True
def delete_saved_server(saved_id): def delete_saved_server(saved_id):
query = SavedServer.delete().where(SavedServer.id == saved_id)
try: try:
query.execute() SavedServer.delete().where(SavedServer.id == saved_id).execute()
except SavedServer.DoesNotExist:
raise RoxywiResourceNotFound
except Exception as e: except Exception as e:
out_error(e) out_error(e)
return False
else:
return True
def delete_option(option_id): def delete_option(option_id):

View File

@ -17,6 +17,8 @@ class EscapedString(str):
if isinstance(field_value, str): if isinstance(field_value, str):
if cls.pattern.search(field_value): if cls.pattern.search(field_value):
return re.sub(cls.pattern, '', field_value) return re.sub(cls.pattern, '', field_value)
elif '..' in field_value:
raise ValueError('nice try')
elif field_value == '': elif field_value == '':
return field_value return field_value
else: else:
@ -275,3 +277,14 @@ class PortScannerRequest(BaseModel):
enabled: Optional[bool] = 1 enabled: Optional[bool] = 1
history: Optional[bool] = 1 history: Optional[bool] = 1
notify: Optional[bool] = 1 notify: Optional[bool] = 1
class SSLCertUploadRequest(BaseModel):
server_ip: Union[IPvAnyAddress, DomainName]
name: EscapedString
cert: EscapedString
class SavedServerRequest(BaseModel):
server: EscapedString
description: Optional[EscapedString] = None

View File

@ -36,6 +36,10 @@ def generate_udp_inv(listener_id: int, action: str) -> object:
"id": listener['id'], "id": listener['id'],
"config": listener['config'], "config": listener['config'],
"lb_algo": listener['lb_algo'], "lb_algo": listener['lb_algo'],
"check_enabled": listener['check_enabled'],
"delay_before_retry": listener['delay_before_retry'],
"delay_loop": listener['delay_loop'],
"retry": listener['retry'],
} }
return inv, server_ips return inv, server_ips

View File

@ -2,7 +2,9 @@ import os
from flask import render_template, request, jsonify, redirect, url_for, g from flask import render_template, request, jsonify, redirect, url_for, g
from flask_jwt_extended import jwt_required, get_jwt from flask_jwt_extended import jwt_required, get_jwt
from flask_pydantic import validate
from app.modules.roxywi.class_models import SSLCertUploadRequest, DataStrResponse, SavedServerRequest, BaseResponse
from app.routes.add import bp from app.routes.add import bp
import app.modules.db.sql as sql import app.modules.db.sql as sql
import app.modules.db.add as add_sql import app.modules.db.add as add_sql
@ -516,43 +518,40 @@ def delete_option(option_id):
@bp.route('/server/get/<int:group>') @bp.route('/server/get/<int:group>')
def get_saved_server(group): def get_saved_server(group):
term = request.args.get('term') term = common.checkAjaxInput(request.args.get('term'))
return jsonify(add_mod.get_saved_servers(group, term)) return jsonify(add_mod.get_saved_servers(group, term))
@bp.post('/server/save') @bp.post('/server')
@get_user_params() @get_user_params()
def save_saved_server(): @validate(body=SavedServerRequest)
server = common.checkAjaxInput(request.form.get('server')) def saved_server(body: SavedServerRequest):
group = g.user_params['group_id'] group = g.user_params['group_id']
desc = common.checkAjaxInput(request.form.get('desc'))
return add_mod.create_saved_server(server, group, desc)
@bp.post('/server/update')
def update_saved_server():
server = common.checkAjaxInput(request.form.get('server'))
server_id = int(request.form.get('id'))
desc = common.checkAjaxInput(request.form.get('desc'))
try: try:
add_sql.update_saved_server(server, desc, server_id) data = add_mod.create_saved_server(body.server, group, body.description)
return DataStrResponse(data=data).model_dump(mode='json'), 201
except Exception as e: except Exception as e:
return str(e) return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot create server')
else:
return 'ok'
@bp.route('/server/delete/<int:server_id>') @bp.put('/server/<int:server_id>')
@validate(body=SavedServerRequest)
def update_saved_server(server_id: int, body: SavedServerRequest):
try:
add_sql.update_saved_server(body.server, body.description, server_id)
return BaseResponse().model_dump(mode='json'), 201
except Exception as e:
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot update server')
@bp.delete('/server/<int:server_id>')
def delete_saved_server(server_id): def delete_saved_server(server_id):
try: try:
add_sql.delete_saved_server(server_id) add_sql.delete_saved_server(server_id)
return BaseResponse().model_dump(mode='json'), 204
except Exception as e: except Exception as e:
return str(e) return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot delete server')
else:
return 'ok'
@bp.route('/certs/<server_ip>') @bp.route('/certs/<server_ip>')
@ -572,12 +571,13 @@ def get_cert(server_ip, cert_id):
@bp.post('/cert/add') @bp.post('/cert/add')
def upload_cert(): @validate(body=SSLCertUploadRequest)
server_ip = common.is_ip_or_dns(request.form.get('serv')) def upload_cert(body: SSLCertUploadRequest):
ssl_name = request.form.get('ssl_name') try:
ssl_cont = request.form.get('ssl_cert') data = add_mod.upload_ssl_cert(body.server_ip, body.name, body.cert)
return jsonify(data), 201
return add_mod.upload_ssl_cert(server_ip, ssl_name, ssl_cont) except Exception as e:
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot upload SSL certificate')
@bp.route('/cert/get/raw/<server_ip>/<cert_id>') @bp.route('/cert/get/raw/<server_ip>/<cert_id>')

View File

@ -2,18 +2,22 @@ virtual_server {{ vip }} {{ port }} {
lb_algo {{ lb_algo }} lb_algo {{ lb_algo }}
lb_kind NAT lb_kind NAT
protocol UDP protocol UDP
delay_loop 10 {% if check_enabled %}
delay_before_retry 10 delay_loop {{ delay_loop }}
retry 3 delay_before_retry {{ delay_before_retry }}
retry {{ retry }}
{% endif %}
{% for server in config %} {% for server in config %}
real_server {{ server.backend_ip }} {{ server.port }} { real_server {{ server.backend_ip }} {{ server.port }} {
weight {{ server.weight }} weight {{ server.weight }}
{% if check_enabled %}
MISC_CHECK { MISC_CHECK {
misc_path "{{ service_dir }}/checks/udp_check.sh {{ server.backend_ip }} {{ server.port }}" misc_path "{{ service_dir }}/checks/udp_check.sh {{ server.backend_ip }} {{ server.port }}"
misc_timeout 5 misc_timeout 5
} }
{% endif %}
} }
{% endfor %} {% endfor %}
} }

View File

@ -501,17 +501,18 @@ $( function() {
}); });
$('#add-saved-server-new').click(function () { $('#add-saved-server-new').click(function () {
$.ajax({ $.ajax({
url: "/add/server/save", url: "/add/server",
data: { data: JSON.stringify({
server: $('#new-saved-servers').val(), server: $('#new-saved-servers').val(),
desc: $('#new-saved-servers-description').val() description: $('#new-saved-servers-description').val()
}, }),
type: "POST", type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) { success: function (data) {
if (data.indexOf('error:') != '-1') { if (data.status === 'failed') {
toastr.error(data); toastr.error(data);
} else { } else {
$("#servers_table").append(data); $("#servers_table").append(data.data);
setTimeout(function () { setTimeout(function () {
$(".newsavedserver").removeClass("update"); $(".newsavedserver").removeClass("update");
}, 2500); }, 2500);
@ -866,22 +867,25 @@ $( function() {
if (!checkIsServerFiled('#serv4')) return false; if (!checkIsServerFiled('#serv4')) return false;
if (!checkIsServerFiled('#ssl_name', 'Enter the Certificate name')) return false; if (!checkIsServerFiled('#ssl_name', 'Enter the Certificate name')) return false;
if (!checkIsServerFiled('#ssl_cert', 'Paste the contents of the certificate file')) return false; if (!checkIsServerFiled('#ssl_cert', 'Paste the contents of the certificate file')) return false;
let jsonData = {
server_ip: $('#serv4').val(),
cert: $('#ssl_cert').val(),
name: $('#ssl_name').val()
}
$.ajax({ $.ajax({
url: "/add/cert/add", url: "/add/cert/add",
data: { data: JSON.stringify(jsonData),
serv: $('#serv4').val(), contentType: "application/json; charset=utf-8",
ssl_cert: $('#ssl_cert').val(),
ssl_name: $('#ssl_name').val()
},
type: "POST", type: "POST",
success: function (data) { success: function (data) {
data = data.split("\n"); if (data.error === 'failed') {
for (i = 0; i < data.length; i++) { toastr.error(data.error);
if (data[i]) { } else {
if (data[i].indexOf('error: ') != '-1' || data[i].indexOf('Errno') != '-1') { for (let i = 0; i < data.length; i++) {
toastr.error(data[i]); if (data[i]) {
} else { if (data[i].indexOf('error: ') != '-1' || data[i].indexOf('Errno') != '-1') {
if (data[i] != '\n') { toastr.error(data[i]);
} else {
toastr.success(data[i]); toastr.success(data[i]);
} }
} }
@ -1379,31 +1383,38 @@ function confirmDeleteSavedServer(id) {
}); });
} }
function removeSavedServer(id) { function removeSavedServer(id) {
$("#servers-saved-"+id).css("background-color", "#f2dede"); $("#servers-saved-" + id).css("background-color", "#f2dede");
$.ajax( { $.ajax({
url: "/add/server/delete/"+id, url: "/add/server/" + id,
success: function( data ) { type: "DELETE",
data = data.replace(/\s+/g,' '); contentType: "application/json; charset=utf-8",
if(data.indexOf('ok') != '-1') { statusCode: {
$("#servers-saved-"+id).remove(); 204: function (xhr) {
$("#servers-saved-" + id).remove();
},
404: function (xhr) {
$("#servers-saved-" + id).remove();
}
},
success: function (data) {
if (data) {
if (data.status === "failed") {
toastr.error(data);
}
} }
} }
} ); });
} }
function updateSavedServer(id) { function updateSavedServer(id) {
toastr.clear(); toastr.clear();
$.ajax( { $.ajax( {
url: "/add/server/update", url: "/add/server/" + id,
data: { type: "PUT",
server: $('#servers-ip-'+id).val(), data: JSON.stringify({"server": $('#servers-ip-'+id).val(), description: $('#servers-desc-'+id).val(),}),
desc: $('#servers-desc-'+id).val(), contentType: "application/json; charset=utf-8",
id: id,
},
type: "POST",
success: function( data ) { success: function( data ) {
data = data.replace(/\s+/g,' '); if (data.status === 'failed') {
if (data.indexOf('error:') != '-1') { toastr.error(data.error);
toastr.error(data);
} else { } else {
$("#servers-saved-"+id).addClass( "update", 1000 ); $("#servers-saved-"+id).addClass( "update", 1000 );
setTimeout(function() { setTimeout(function() {

View File

@ -28,6 +28,13 @@ $( function() {
$('#new-listener-port').focus(); $('#new-listener-port').focus();
} }
}); });
$('#check_enabled').click(function () {
if ($('#check_enabled').is(':checked')) {
$('.check_backends').show();
} else {
$('.check_backends').hide();
}
});
}); });
function getHAClusterVIPS(cluster_id) { function getHAClusterVIPS(cluster_id) {
let vip_id = $('#vip'); let vip_id = $('#vip');
@ -76,9 +83,20 @@ function createUDPListener(edited=false, listener_id=0, clean=true) {
$('#name').val(data.name.replaceAll("'", "")); $('#name').val(data.name.replaceAll("'", ""));
$('#new-listener-type').val(place); $('#new-listener-type').val(place);
$('#port').val(data.port); $('#port').val(data.port);
$('#delay_loop').val(data.delay_loop);
$('#delay_before_retry').val(data.delay_before_retry);
$('#retry').val(data.retry);
$('#lb_algo').val(data.lb_algo).change(); $('#lb_algo').val(data.lb_algo).change();
$('#lb_algo').selectmenu('refresh'); $('#lb_algo').selectmenu('refresh');
$('#desc').val(data.description.replaceAll("'", "")); $('#desc').val(data.description.replaceAll("'", ""));
if (data.check_enabled) {
$('#check_enabled').prop('checked', true);
$('.check_backends').show();
} else {
$('#check_enabled').prop('checked', false);
$('.check_backends').hide();
}
$("#check_enabled").checkboxradio("refresh");
if (place === 'cluster') { if (place === 'cluster') {
$.when(getHAClusterVIPS(data.cluster_id)).done(function () { $.when(getHAClusterVIPS(data.cluster_id)).done(function () {
$("#vip option").filter(function () { $("#vip option").filter(function () {
@ -99,7 +117,7 @@ function createUDPListener(edited=false, listener_id=0, clean=true) {
$('#new-udp-servers-td').append('<a class="link add-server" title="Add backend server" onclick="createBackendServer()"></a>'); $('#new-udp-servers-td').append('<a class="link add-server" title="Add backend server" onclick="createBackendServer()"></a>');
data.config = JSON.stringify(data.config); data.config = JSON.stringify(data.config);
let config = JSON.parse(data.config) let config = JSON.parse(data.config)
for(let server of config) { for (let server of config) {
createBackendServer(server.backend_ip, server.port, server.weight); createBackendServer(server.backend_ip, server.port, server.weight);
} }
} }
@ -262,10 +280,15 @@ function getFormData($form) {
let unindexed_array = $form.serializeArray(); let unindexed_array = $form.serializeArray();
let indexed_array = {}; let indexed_array = {};
indexed_array['config'] = []; indexed_array['config'] = [];
indexed_array['check_enabled'] = 0;
$.map(unindexed_array, function (n, i) { $.map(unindexed_array, function (n, i) {
if (n['name'] === 'serv') { if (n['name'] === 'serv') {
indexed_array['server_id'] = n['value']; indexed_array['server_id'] = n['value'];
} else if (n['name'] === 'check_enabled') {
if ($('#check_enabled').is(':checked')) {
indexed_array['check_enabled'] = 1;
}
} else { } else {
indexed_array[n['name']] = n['value']; indexed_array[n['name']] = n['value'];
} }
@ -324,15 +347,7 @@ function saveUdpListener(jsonData, dialog_id, listener_id=0, edited=0, reconfigu
listener_id = data.id; listener_id = data.id;
getUDPListener(listener_id, true); getUDPListener(listener_id, true);
} }
// if (reconfigure) { dialog_id.dialog("close");
// NProgress.start();
// $.when(Reconfigure(listener_id)).done(function () {
// dialog_id.dialog("close");
// NProgress.done();
// });
// } else {
dialog_id.dialog("close");
// }
toastr.success('Listener ' + data.status); toastr.success('Listener ' + data.status);
} }
} }
@ -421,9 +436,15 @@ function clearListenerDialog(edited=0) {
$('#new-listener-desc').val(''); $('#new-listener-desc').val('');
$('#new-udp-ip').val(''); $('#new-udp-ip').val('');
$('#vrrp-ip').prop("readonly", false); $('#vrrp-ip').prop("readonly", false);
$('#delay_loop').val(10);
$('#delay_before_retry').val(10);
$('#retry').val(3);
$('#new-listener-port').val(''); $('#new-listener-port').val('');
$("#cluster_id").attr('disabled', false); $("#cluster_id").attr('disabled', false);
$("#serv").attr('disabled', false); $("#serv").attr('disabled', false);
$('#check_enabled').prop('checked', true);
$('.check_backends').show();
$("#check_enabled").checkboxradio("refresh");
clearUdpVip() clearUdpVip()
$('#new-udp-servers-td').empty(); $('#new-udp-servers-td').empty();
$('#new-udp-servers-td').append('<a class="link add-server" title="Add backend server" onclick="createBackendServer()"></a>'); $('#new-udp-servers-td').append('<a class="link add-server" title="Add backend server" onclick="createBackendServer()"></a>');

View File

@ -519,6 +519,13 @@
"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", "balancing_type": "Balancing type",
"check_backends": "Enable backends checking",
"retry": "Number of retries",
"retry_title": "Maximum number of retries",
"delay_before_retry_title": "Delay between two successive retries",
"delay_before_retry": "Delay between retries",
"delay_loop_title": "Specify in seconds the interval between checks",
"delay_loop": "Interval between checks",
} }
%} %}
{% set nettools_page = { {% set nettools_page = {

View File

@ -519,6 +519,13 @@
"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", "balancing_type": "Type d'équilibrage",
"check_backends": "Enable backends checking",
"retry": "Nombre de tentatives",
"retry_title": "Nombre maximal de tentatives",
"delay_before_retry_title": "Délai entre deux tentatives successives",
"delay_before_retry": "Délai entre les tentatives",
"delay_loop_title": "Spécifiez en secondes l'intervalle entre les contrôles",
"delay_loop": "Intervalle entre les contrôles",
} }
%} %}
{% set nettools_page = { {% set nettools_page = {

View File

@ -519,6 +519,13 @@
"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", "balancing_type": "Tipo de balanceamento",
"check_backends": "Enable backends checking",
"retry": "Número de tentativas",
"retry_title": "Número máximo de tentativas",
"delay_before_retry_title": "Atraso entre duas tentativas sucessivas",
"delay_before_retry": "Atraso entre tentativas",
"delay_loop_title": "Especifique em segundos o intervalo entre verificações",
"delay_loop": "Intervalo entre verificações",
} }
%} %}
{% set nettools_page = { {% set nettools_page = {

View File

@ -519,6 +519,13 @@
"listener_ip": "IP для привязки UDP Listener. Начните печатать", "listener_ip": "IP для привязки UDP Listener. Начните печатать",
"listener_port": "Порт для привязки UDP Listener", "listener_port": "Порт для привязки UDP Listener",
"balancing_type": "Тип балансировки", "balancing_type": "Тип балансировки",
"check_backends": "Enable backends checking",
"retry": "Количество повторных попыток",
"retry_title": "Максимальное количество повторных попыток",
"delay_before_retry_title": "Задержка между двумя последовательными попытками",
"delay_before_retry": "Задержка между повторными попытками",
"delay_loop_title": "Укажите в секундах интервал между проверками",
"delay_loop": "Интервал между проверками",
} }
%} %}
{% set nettools_page = { {% set nettools_page = {

View File

@ -128,6 +128,39 @@
<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> <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>
<td class="padding20">
{{ lang.udp_page.check_backends }}
<span class="need-field">*</span>
</td>
<td>
{{ checkbox('check_enabled', title=lang.udp_page.check_backends, checked='checked') }}
</td>
</tr>
<tr class="check_backends">
<td class="padding20">
{{ lang.udp_page.delay_loop }}
</td>
<td>
{{ input('delay_loop', title=lang.udp_page.delay_loop_title, value='10', type='number') }}
</td>
</tr>
<tr class="check_backends">
<td class="padding20">
{{ lang.udp_page.delay_before_retry }}
</td>
<td>
{{ input('delay_before_retry', title=lang.udp_page.delay_before_retry_title, value='10', type='number') }}
</td>
</tr>
<tr class="check_backends">
<td class="padding20">
{{ lang.udp_page.retry }}
</td>
<td>
{{ input('retry', title=lang.udp_page.retry_title, value='3', type='number') }}
</td>
</tr>
<tr> <tr>
<td class="padding20"> <td class="padding20">
{{lang.words.desc|title()}} {{lang.words.desc|title()}}

View File

@ -166,10 +166,10 @@ class UDPListener(MethodView):
name: name:
type: string type: string
cluster_id: cluster_id:
type: int type: integer
description: Cluster ID where the UDP listener is located. Must be determined if server_id empty description: Cluster ID where the UDP listener is located. Must be determined if server_id empty
server_id: server_id:
type: int type: integer
description: Standalone mode. Server ID where the UDP listener is located. Must be determined if cluster_id empty description: Standalone mode. Server ID where the UDP listener is located. Must be determined if cluster_id empty
group_id: group_id:
type: string type: string
@ -180,6 +180,22 @@ class UDPListener(MethodView):
description: "'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'" description: "'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'"
schema: schema:
enum: [rr, wrr, lc, wlc, sh, dh, wlc, lblc] enum: [rr, wrr, lc, wlc, sh, dh, wlc, lblc]
check_enabled:
type: integer
default: 1
description: Enable backend servers checking
delay_before_retry:
type: integer
default: 10
description: Delay between two successive retries
delay_loop:
type: integer
default: 10
description: Specify in seconds the interval between checks
retry:
type: integer
default: 3
description: Maximum number of retries before mark a backend server as down
description: description:
type: string type: string
vip: vip:
@ -254,10 +270,10 @@ class UDPListener(MethodView):
name: name:
type: string type: string
cluster_id: cluster_id:
type: int type: integer
description: Cluster ID where the UDP listener is located. Must be determined if server_id empty description: Cluster ID where the UDP listener is located. Must be determined if server_id empty
server_id: server_id:
type: int type: integer
description: Standalone mode. Server ID where the UDP listener is located. Must be determined if cluster_id empty description: Standalone mode. Server ID where the UDP listener is located. Must be determined if cluster_id empty
group_id: group_id:
type: string type: string
@ -268,6 +284,22 @@ class UDPListener(MethodView):
description: "'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'" description: "'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'"
schema: schema:
enum: [rr, wrr, lc, wlc, sh, dh, wlc, lblc] enum: [rr, wrr, lc, wlc, sh, dh, wlc, lblc]
check_enabled:
type: integer
default: 1
description: Enable backend servers checking
delay_before_retry:
type: integer
default: 10
description: Delay between two successive retries
delay_loop:
type: integer
default: 10
description: Specify in seconds the interval between checks
retry:
type: integer
default: 3
description: Maximum number of retries before mark a backend server as down
description: description:
type: string type: string
vip: vip:
@ -418,11 +450,11 @@ class UDPListeners(MethodView):
try: try:
group_id = SupportClass.return_group_id(query) group_id = SupportClass.return_group_id(query)
except Exception as e: except Exception as e:
return roxywi_common.handle_json_exceptions(e, f'Cannot get UDP listeners') return roxywi_common.handle_json_exceptions(e, 'Cannot get UDP listeners')
try: try:
listeners = udp_sql.select_listeners(group_id) listeners = udp_sql.select_listeners(group_id)
except Exception as e: except Exception as e:
return roxywi_common.handle_json_exceptions(e, f'Cannot get UDP listeners') return roxywi_common.handle_json_exceptions(e, 'Cannot get UDP listeners')
return jsonify([model_to_dict(listener, recurse=False) for listener in listeners]) return jsonify([model_to_dict(listener, recurse=False) for listener in listeners])