Changelog: https://roxy-wi.org/changelog#6_2_1
pull/343/head
Pavel Loginov 2022-10-09 13:23:45 +03:00
parent e8cb536604
commit 552ffd9558
5 changed files with 417 additions and 5 deletions

120
app/add_nginx.py Executable file
View File

@ -0,0 +1,120 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import http.cookies
from jinja2 import Environment, FileSystemLoader
import funct
import sql
import modules.roxy_wi_tools as roxy_wi_tools
get_config_var = roxy_wi_tools.GetConfigVar()
form = funct.form
serv = form.getvalue('serv')
print('Content-type: text/html\n')
user, user_id, role, token, servers, user_services = funct.get_users_params(service='nginx')
try:
funct.check_login(user_id, token, service=2)
except Exception as e:
print(f'error {e}')
sys.exit()
funct.page_for_admin(level=3)
if all(v is None for v in [ form.getvalue('upstream'), form.getvalue('generateconfig') ]):
env = Environment(loader=FileSystemLoader('templates/'), autoescape=True)
template = env.get_template('add_nginx.html')
template = template.render(
title="Add: ", role=role, user=user, selects=servers, add=form.getvalue('add'), conf_add=form.getvalue('conf'),
user_services=user_services, token=token
)
print(template)
elif form.getvalue('upstream') is not None:
nginx_dir = sql.get_setting('nginx_dir')
name = form.getlist('name')
new_upstream = form.getvalue('upstream')
ip = ''
port = ''
config_add = ''
servers_split = ''
if new_upstream is not None:
config_add = f'upstream {new_upstream} {{\n'
config_add += f' {form.getvalue("balance")};\n'
config_name = f'upstream_{new_upstream}'
if form.getvalue('keepalive') is not None:
config_add += f' keepalive {form.getvalue("keepalive")};\n'
if form.getvalue('servers') is not None:
servers = form.getlist('servers')
server_port = form.getlist('server_port')
max_fails = form.getlist('max_fails')
fail_timeout = form.getlist('fail_timeout')
i = 0
for server in servers:
try:
max_fails_val = f'max_fails={max_fails[i]}'
except Exception:
max_fails_val = 'max_fails=1'
try:
fail_timeout_val = f'fail_timeout={fail_timeout[i]}'
except Exception:
fail_timeout_val = 'fail_timeout=1'
servers_split += f" server {server}:{server_port[i]} {max_fails_val} {fail_timeout_val}s; \n"
i += 1
config_add += f'{servers_split} }}\n'
if form.getvalue('generateconfig') is None and serv is not 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:
sub_folder = 'conf.d' if 'upstream' in config_name else 'sites-enabled'
service_configs_dir = get_config_var.get_config_var('configs', 'nginx_save_configs_dir')
cfg = f'{service_configs_dir}{serv}-{config_name}.conf'
nginx_dir = funct.return_nice_path(sql.get_setting('nginx_dir'))
config_file_name = f'{nginx_dir}{sub_folder}/{config_name}.conf'
try:
with open(cfg, "w") as conf:
conf.write(config_add)
except IOError:
print("error: Cannot save a new config")
funct.logging(serv, "add_nginx.py add new %s" % config_name)
MASTERS = sql.is_master(serv)
for master in MASTERS:
if master[0] is not None:
slave_output = funct.upload_and_restart(master[0], cfg, nginx=1, config_file_name=config_file_name)
slave_output = '<br>' + master[1] + ':\n' + slave_output
output = funct.upload_and_restart(serv, cfg, just_save="save", nginx=1, config_file_name=config_file_name)
output = '<br>' + server_name + ':\n' + output
output = output + slave_output
if output:
print(output)
else:
print(config_name)
except Exception:
pass
else:
print(config_add)

View File

@ -0,0 +1,97 @@
{% extends "base.html" %}
{% block content %}
{% from 'include/input_macros.html' import input, checkbox, select %}
{% set balance_params = dict() %}
{% set balance_params = {'ip_hash':'ip_hash','least_conn':'least_conn','random':'random'} %}
<script src="/inc/add_nginx.js"></script>
<div id="tabs">
<ul>
<li><a href="#create" title="Add proxy: Create proxy - Roxy-WI">Create proxy</a></li>
<li><a href="#upstream" title="Add proxy: Create Upstream - Roxy-WI">Upstream</a></li>
{% include 'include/login.html' %}
</ul>
<ul id='browse_histroy'></ul>
{% include 'include/add_nginx_proxy.html' %}
<div id="upstream">
<form name="add-upstream" id="add-upstream" action="/app/add_nginx.py" method="post">
<table class="add-table">
<caption><h3>Add upstream</h3></caption>
<tr>
<td class="addName">Select a server: </td>
<td class="addOption">
<select required name="serv" id="serv">
<option disabled selected>------</option>
{% for select in selects %}
<option value="{{ select.2 }}">{{ select.1 }}</option>
{% endfor %}
</select>
<div class="tooltip tooltipTop"><b>Note:</b> If you re-configure the master server, the slave server will be re-configured automatically</div>
</td>
<td rowspan="5" class="add-note addName alert-info">
The upstream module is used to define groups of servers.
<br /><br />
Defines a group of servers. Servers can listen on different ports. In addition, servers listening on TCP and UNIX-domain sockets can be mixed..
<br /><br />
By default, requests are distributed between the servers using a weighted round-robin balancing method.
</td>
</tr>
<tr>
<td class="addName">Name:</td>
<td class="addOption">
{{ input('name', name='upstream', title="Name upstream", placeholder="backend_servers", required='required') }}
</td>
</tr>
<tr class="advance">
<td class="addName">Balance: </td>
<td class="addOption">
{{ select('balance', values=balance_params, selected='least_conn', required='required', class='force_close') }}
</td>
</tr>
<tr class="advance">
<td class="addName"><span title="Activates the cache for connections to upstream servers.">Keepalive:</span></td>
<td class="addOption">
{{ input('name', name='keepalive', title="Activates the cache for connections to upstream servers.", placeholder="32") }}
</td>
</tr>
<tr>
<td class="addName">Servers:</td>
<td class="addOption">
{% include 'include/add_nginx_servers.html' %}
</td>
</tr>
<tr class="advance-show">
<td class="addOption" colspan="2">
<button title="Show full list of settings" class="row-down advance-show-button">Show Advanced settings</button>
<button title="Hide full list of settings" class="row-up advance-hide-button" style="display: none">Hide Advanced settings</button>
</td>
</tr>
<tr>
<td class="addButton">
<a class="ui-button ui-widget ui-corner-all" title="Add Backend" onclick="addProxy('add-upstream')">Add Upstream</a>
</td>
<td class="addButton">
<a class="ui-button ui-widget ui-corner-all" title="Generate and display config" onclick="generateConfig('add-upstream')">Generate config</a>
</td>
</tr>
</table>
</form>
</div>
<div id="dialog-confirm-cert-edit" title="View certificate " style="display: none;">
<span><b>Note:</b> Each new address must be specified from a new line</span>
<textarea id="edit_lists" style="width: 100%" rows=20></textarea>
</div>
<div id="dialog-confirm-cert" title="View certificate " style="display: none;">
<pre id="dialog-confirm-body"></pre>
</div>
<input type="hidden" id="group" value="{{ group }}">
</div>
<script>
$( function() {
if (window.matchMedia('(max-width: 1280px)').matches || window.matchMedia('(max-width: 1024px)').matches || window.matchMedia('(max-width: 667px)').matches) {
$( "select" ).selectmenu({
width: 150
});
}
});
</script>
{% endblock %}

View File

@ -1,7 +1,7 @@
<html lang="en">
<head>
<title>{{title}}</title>
<meta charset="UTF-8">
<meta charset="UTF-8">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
@ -56,12 +56,12 @@
<a href="https://roxy-wi.org" title="Roxy-WI site" target="_blank">
<img src="/inc/images/logo_menu.png" alt="logo" width="110" />
</a>
</span>
</div>
</span>
</div>
<div id="top-link" class="top-link">
<nav id="menu">
<ul class="menu">
{% if user %}
{% if user %}
<li><a href="/app/overview.py" title="Server and service status" class="overview-link">Overview</a></li>
{% if '1' in user_services %}
<li class="p_menu">
@ -93,8 +93,9 @@
<li><a href="/app/logs.py?service=nginx" title="NGINX logs " class="logs head-submenu">Logs</a></li>
<li><a href="/app/metrics.py?service=nginx" title="NGINX's metrics" class="metrics head-submenu">Metrics</a></li>
{% if role <= 3 %}
<li><a href="/app/add_nginx.py#proxy" title="Add proxy: Create proxy" class="add-proxy head-submenu">Add proxy</a></li>
<li><a href="/app/versions.py?service=nginx" title="Working with versions NGINX configs" class="version head-submenu">Versions</a></li>
<li><a href="/app/add.py?service=nginx#ssl" title="Add proxy: Upload SSL certificates" class="cert head-submenu" id="add3">SSL</a></li>
<li><a href="/app/add.py?service=nginx#ssl" title="Add proxy: Upload SSL certificates" class="cert head-submenu">SSL</a></li>
<li><a href="/app/waf.py?service=nginx" title="Web application firewall" class="waf-menu head-submenu">WAF</a> </li>
{% endif %}
</ul>

View File

@ -0,0 +1,32 @@
{% if add %}
<div class="alert alert-success" style="position: absolute;top: 45px;left: 5px;">
<div id="close">
<span title="Close" style="cursor: pointer; float: right;">X</span>
</div>
<h3>{{ add }} was success added</h3>
{{ conf_add }}
</div>
<script>
$('#close').click(function(){
$('.alert-success').remove();
});
</script>
{% endif %}
<div id="create" style="margin-top: 20px;">
<div id="left-collumn">
<div class="div-pannel">
<div class="div-server add-proxy-listen-head">
<div class="server-name">
<span title="Create Upstream" class="redirectUpstream span-link">Create Upstream</span>
</div>
<div class="server-desc add_proxy">
The upstream module is used to define groups of servers.
</div>
</div>
</div>
</div>
<div id="middle-collumn">
</div>
<div id="right-collumn">
</div>
</div>

162
inc/add_nginx.js Normal file
View File

@ -0,0 +1,162 @@
$( function() {
$(".redirectUpstream").on("click", function () {
resetProxySettings();
$("#tabs").tabs("option", "active", 1);
$("#serv").selectmenu("open");
});
$( "#serv" ).on('selectmenuchange',function() {
$('#name').focus();
});
var add_server_var = '<br /><input name="servers" title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server" style="margin: 2px 0 4px 0;">: ' +
'<input name="server_port" required title="Backend port" size=3 placeholder="yyy" class="form-control second-server add_server_number" type="number"> ' +
'max_fails check: <input name="max_fails" required title="By default, the number of unsuccessful attempts is set to 1" size=5 value="1" class="form-control add_server_number" type="number">' +
' fail_timeout: <input name="fail_timeout" required title="By default, the number of unsuccessful attempts is set to 1" size=5 value="1" class="form-control add_server_number" type="number">s'
$('[name=add-server-input]').click(function() {
$("[name=add_servers]").append(add_server_var);
changePortCheckFromServerPort();
});
$('.advance-show-button').click(function() {
$('.advance').fadeIn();
$('.advance-show-button').css('display', 'none');
$('.advance-hide-button').css('display', 'block');
return false;
});
$('.advance-hide-button').click(function() {
$('.advance').fadeOut();
$('.advance-show-button').css('display', 'block');
$('.advance-hide-button').css('display', 'none');
return false;
});
});
function resetProxySettings() {
$('[name=upstream]').val('');
$('input:checkbox').prop("checked", false);
$('[name=check-servers]').prop("checked", true);
$('input:checkbox').checkboxradio("refresh");
$('.advance-show').fadeIn();
$('.advance').fadeOut();
$('[name=mode').val('http');
$('select').selectmenu('refresh');
$("#path-cert-listen").attr('required', false);
$("#path-cert-frontend").attr('required', false);
// replace_text("#optionsInput", ssl_offloading_var);
// replace_text("#optionsInput1", ssl_offloading_var);
}
function checkIsServerFiled(select_id, message = 'Select a server first') {
if ($(select_id).val() == null || $(select_id).val() == '') {
toastr.warning(message);
return false;
}
return true;
}
function generateConfig(form_name) {
var frm = $('#'+form_name);
if (form_name == 'add-upstream') {
serv = '#serv'
name_id = '#name'
}
if(!checkIsServerFiled(serv)) return false;
if(!checkIsServerFiled(name_id, 'The name cannot be empty')) return false;
var input = $("<input>")
.attr("name", "generateconfig").val("1").attr("type", "hidden").attr("id", "generateconfig");
$('#'+form_name +' input[name=acl_then_value]').each(function(){
if (!$(this).val()){
$(this).val('IsEmptY')
}
});
$('#'+form_name +' input[name=ip]').each(function(){
if (!$(this).val()){
$(this).val('IsEmptY')
}
});
$('#'+form_name +' input[name=port]').each(function(){
if (!$(this).val()){
$(this).val('IsEmptY')
}
});
frm.append(input);
$.ajax({
url: frm.attr('action'),
data: frm.serialize(),
type: frm.attr('method'),
success: function (data) {
if (data.indexOf('error: ') != '-1' || data.indexOf('Fatal') != '-1') {
toastr.clear();
toastr.error(data);
} else {
$('#dialog-confirm-body').text(data);
$("#dialog-confirm-cert").dialog({
resizable: false,
height: "auto",
width: 650,
modal: true,
title: "Generated config",
buttons: {
Ok: function () {
$(this).dialog("close");
}
}
});
}
}
});
$("#generateconfig").remove();
$('#'+form_name +' input[name=ip]').each(function(){
if ($(this).val() == 'IsEmptY'){
$(this).val('')
}
});
$('#'+form_name +' input[name=port]').each(function(){
if ($(this).val() == 'IsEmptY'){
$(this).val('')
}
});
}
function addProxy(form_name) {
var frm = $('#'+form_name);
if (form_name == 'add-upstream') {
serv = '#serv'
name_id = '#name'
}
if(!checkIsServerFiled(serv)) return false;
if(!checkIsServerFiled(name_id, 'The name cannot be empty')) return false;
$('#'+form_name +' input[name=ip]').each(function(){
if ($(this).val().length === 0){
$(this).val('IsEmptY')
}
});
$('#'+form_name +' input[name=port]').each(function(){
if ($(this).val().length === 0){
$(this).val('IsEmptY')
}
});
$.ajax({
url: frm.attr('action'),
data: frm.serialize(),
type: frm.attr('method'),
success: function( data ) {
data = data.replace(/\n/g, "<br>");
if (data.indexOf('error: ') != '-1' || data.indexOf('Fatal') != '-1') {
returnNiceCheckingConfig(data);
} else if (data == '') {
toastr.clear();
toastr.error('error: Proxy cannot be empty');
} else {
toastr.clear();
returnNiceCheckingConfig(data);
toastr.info('Section has been added. Do not forget to restart the server');
resetProxySettings();
}
}
});
$('#'+form_name +' input[name=ip]').each(function(){
if ($(this).val() == 'IsEmptY'){
$(this).val('')
}
});
$('#'+form_name +' input[name=port]').each(function(){
if ($(this).val() == 'IsEmptY'){
$(this).val('')
}
});
}