Changelog: https://roxy-wi.org/changelog#6_3_0
pull/355/head
Pavel Loginov 2 years ago
parent 084b0b65fa
commit c24203e70a

@ -42,34 +42,42 @@ def ssh_connect(server_ip):
def ssh_command(server_ip: str, commands: list, **kwargs):
if server_ip == '':
return 'error: IP cannot be empty'
with ssh_connect(server_ip) as ssh:
for command in commands:
try:
stdin, stdout, stderr = ssh.run_command(command)
except Exception as e:
roxywi_common.logging('Roxy-WI server', f' Something wrong with SSH connection. Probably sudo with password {e}', roxywi=1)
return str(e)
try:
if kwargs.get('raw'):
return stdout.readlines()
if kwargs.get("ip") == "1":
show_ip(stdout)
elif kwargs.get("show_log") == "1":
import modules.roxywi.logs as roxywi_logs
return roxywi_logs.show_log(stdout, grep=kwargs.get("grep"))
elif kwargs.get('return_err') == 1:
return stderr.read().decode(encoding='UTF-8')
else:
return stdout.read().decode(encoding='UTF-8')
except Exception as e:
roxywi_common.logging('Roxy-WI server', f' Something wrong with SSH connection. Probably sudo with password {e}', roxywi=1)
for line in stderr.readlines():
if line:
print(f'error: {line}')
roxywi_common.logging('Roxy-WI server', f' {line}', roxywi=1)
try:
with ssh_connect(server_ip) as ssh:
for command in commands:
try:
stdin, stdout, stderr = ssh.run_command(command)
except Exception as e:
print(f'error: {e}')
roxywi_common.logging('Roxy-WI server', f' Something wrong with SSH connection. Probably sudo with password {e}', roxywi=1)
return str(e)
if stderr:
for line in stderr.readlines():
if line:
print(f'error: {line}')
roxywi_common.logging('Roxy-WI server', f' {line}', roxywi=1)
try:
if kwargs.get('raw'):
return stdout.readlines()
if kwargs.get("ip") == "1":
show_ip(stdout)
elif kwargs.get("show_log") == "1":
import modules.roxywi.logs as roxywi_logs
return roxywi_logs.show_log(stdout, grep=kwargs.get("grep"))
elif kwargs.get('return_err') == 1:
return stderr.read().decode(encoding='UTF-8')
else:
return stdout.read().decode(encoding='UTF-8')
except Exception as e:
roxywi_common.logging('Roxy-WI server', f' Something wrong with SSH connection. Probably sudo with password {e}', roxywi=1)
except Exception as e:
print(e)
roxywi_common.logging('Roxy-WI server',
f' Something wrong with SSH connection. Probably sudo with password {e}', roxywi=1)
return str(e)
def subprocess_execute(cmd):

@ -19,7 +19,8 @@ def show_installation_output(error: str, output: str, service: str) -> bool:
for line in output:
if any(s in line for s in ("Traceback", "FAILED", "error", "ERROR", "UNREACHABLE")):
try:
print(line)
correct_out = line.split('=>')
print(f'error: {correct_out[1]}')
break
except Exception:
print(output)

@ -88,7 +88,7 @@
{% set values = {'http':'http','tcp':'tcp'} %}
{{ select('listen-mode-select', name='mode', values=values, selected='http', required='required', class='force_close') }}
<span id="https-listen-span">
<label for="https-listen" style="margin-top: 5px;" title="Enable SSL Offloading">SSL Offloading</label>
<label for="https-listen" style="margin-top: 5px;" title="Enable SSL Offloading" data-help="The term SSL termination means that you are performing all encryption and decryption at the edge of your network, such as at the load balancer.">SSL Offloading</label>
<input type="checkbox" id="https-listen" name="ssl" value="https" >
</span>
<div id="https-hide-listen" style="display: none;">
@ -149,25 +149,28 @@
</td>
</tr>
<tr class="advance">
<td class="addName"><span title="Cache support start 1.8 and latter">Web acceleration(?):</span></td>
<td class="addName"><span title="Cache support start 1.8 and latter" class="help_cursor">Web acceleration:</span></td>
<td class="addOption">
<span class="controlgroup">
{{ checkbox('compression', title='Enable Compression', value='1', desc='Compression') }}
{{ checkbox('compression', title='HTTP compression allows you to shrink the body of a response before it is relayed to a client, which results in using less network bandwidth per request. From a client\'s perspective, this reduces latency.',
value='1', desc='Compression') }}
{{ checkbox('cache', title='Enable cache', value='2', desc='Cache') }}
{{ checkbox('ssl_offloading', title='Enable redirect from HTTP to HTTPS', desc='HTTP->HTTPS') }}
{{ checkbox('ssl_offloading', title='Enable redirection from HTTP scheme to HTTPS scheme', desc='HTTP->HTTPS') }}
</span>
</td>
</tr>
<tr class="advance">
<td class="addName"><span title="Web application firewall">WAF(?):</span></td>
<td class="addName"><span title="Web application firewall" class="help_cursor">WAF:</span></td>
<td class="addOption">
<span class="controlgroup">
{{ checkbox('slow_atack', title='Slow attack protect', desc='Slow attack') }}
{{ checkbox('slow_atack', title='In a Slow POST attack, an attacker begins by sending a legitimate HTTP POST header to a Web server, exactly as they would under normal circumstances. The header specifies the exact size of the message body that will then follow. However, that message body is then sent at an alarmingly low rate sometimes as slow as 1 byte per approximately two minutes.',
desc='Slow attack') }}
{{ checkbox('ddos', title='DDOS attack protect', desc='DDOS') }}
{{ checkbox('whitelist_checkbox', title='Add whitelist', desc='Whitelist') }}
{{ checkbox('blacklist_checkbox', title='Add blacklist', desc='Blacklist') }}
{{ checkbox('waf', title='Web application firewall', desc='WAF', value='1') }}
{{ checkbox('antibot', title='Antibot Protection', desc='Antibot', value='1') }}
{{ checkbox('antibot', title='Unfortunately, a large portion of bots are used for malicious reasons. Their intentions include web scraping, spamming, request flooding, brute forcing, and vulnerability scanning. For example, bots may scrape your price lists so that competitors can consistently undercut you or build a competitive solution using your data. Or they may try to locate forums and comment sections where they can post spam. At other times, theyre scanning your site looking for security weaknesses.',
desc='Antibot', value='1') }}
</span>
<div id="blacklist-hide" style="display: none;">
<br /><span class="tooltip tooltipTop">Enter a blacklist name, or press the "down" button:</span><br />
@ -183,12 +186,30 @@
<td class="addName">Options:</td>
<td class="addOption">
<span class="controlgroup">
{{ checkbox('forward_for', title='Option Forward for if none', desc='Forward for') }}
{{ checkbox('redispatch', title='Enable Redispatch', desc='Redispatch') }}
{{ checkbox('forward_for', title='When HAProxy Enterprise proxies a TCP connection, it overwrites the client\'s source IP address with its own when communicating with the backend server. However, when relaying HTTP messages, it can store the client\'s address in the HTTP header X-Forwarded-For. The backend server can then be configured to read the value from that header to retrieve the client\'s IP address.',
desc='Forward for') }}
{{ checkbox('redispatch', title='In HTTP mode, if a server designated by a cookie is down, clients may
definitely stick to it because they cannot flush the cookie, so they will not
be able to access the service anymore.
Specifying "option redispatch" will allow the proxy to break their
persistence and redistribute them to a working server.
It also allows to retry connections to another server in case of multiple
connection failures. Of course, it requires having "retries" set to a nonzero
value.', desc='Redispatch') }}
{% set values = dict() %}
{% set values = {'Off':'Off','Server only':'Server only','Force close':'Force close','Pretend keep alive':'Pretend keep alive'} %}
{{ select('force_close', values=values, first='Force HTTP close', class='force_close') }}
{{ checkbox('cookie', title='Set cookie', desc='Set cookie', value='1') }}
{{ select('force_close', values=values, first='Force HTTP close', title='Since HAProxy works in reverse-proxy mode, the servers see its IP address as
their client address. This is sometimes annoying when the client\'s IP address
is expected in server logs. To solve this problem, the well-known HTTP header
"X-Forwarded-For" may be added by HAProxy to all requests sent to the server.
This header contains a value representing the client\'s IP address. Since this
header is always appended at the end of the existing header list, the server
must be configured to always use the last occurrence of this header only. See
the server\'s manual to find how to enable use of this standard header. Note
that only the last occurrence of the header must be used, since it is really
possible that the client has already brought one.', class='force_close') }}
{{ checkbox('cookie', title='To send a client to the same server where they were sent previously in order to reuse a session on that server, you can enable cookie-based session persistence. Add a cookie directive to the backend section and set the cookie parameter to a unique value on each server line.',
desc='Set cookie', value='1') }}
{{ checkbox('options-listen-show', title='Set options manually', desc='Set options') }}
</span>
<br>
@ -255,7 +276,8 @@
{{ select('fall-listen', name='fall', values=values, first='fall', class='force_close') }}
</div>
<div style="display: block">
{{ checkbox('circuit_breaking_listen', name="circuit_breaking", desc='Circuit Breaking', title='Enable Circuit Breaking', value='1') }}
{{ checkbox('circuit_breaking_listen', name="circuit_breaking", desc='Circuit Breaking', title='Circuit breaker is a design pattern which is used to detect failures and encapsulates the logic of preventing a failure from constantly recurring. The circuit breaker design pattern works much like an electrical circuit breaker which is intended to “trip” or open the circuit when failure is detected.',
value='1') }}
</div>
<div id="circuit_breaking_listen_div" style="display: none">
Observe:
@ -263,7 +285,7 @@
error-limit: {{ input('circuit_breaking_error_limit', type='number', value='50', style='width: 50px;') }}
on-error:
{{ select('circuit_breaking_on_error', values=on_error, class='force_close') }}
<div class="tooltip tooltipTop">Read more about Circuit Breaking <a href="https://roxy-wi.org/description.py?description=circuit_breaking" title="Circuit Breaking" target="_blank">here</a></div>
<div class="tooltip tooltipTop">Read more about Circuit Breaking <a href="https://roxy-wi.org/description/circuit-breaking" title="Circuit Breaking" target="_blank">here</a></div>
</div>
</td>
</tr>
@ -340,8 +362,8 @@
{% set values = {'http':'http','tcp':'tcp'} %}
{{ select('frontend-mode-select', name='mode', values=values, selected='http', required='required', class='force_close') }}
<span id="https-frontend-span">
<label for="https-frontend" style="margin-top: 5px;" title="Enable SSL Offloading">SSL Offloading</label>
<input type="checkbox" id="https-frontend" name="ssl" value="https">
{{ checkbox('https-frontend', title='The term SSL termination means that you are performing all encryption and decryption at the edge of your network, such as at the load balancer.', desc='SSL Offloading') }}
</span>
<div id="https-hide-frontend" style="display: none;">
<br /><span class="tooltip tooltipTop">Enter a name of pem file, or press the "down" button:</span><br />
@ -381,25 +403,28 @@
</td>
</tr>
<tr class="advance">
<td class="addName"><span title="Cache support start 1.8 and latter">Web acceleration(?):</span></td>
<td class="addName"><span title="Cache support start 1.8 and latter" class="help_cursor">Web acceleration:</span></td>
<td class="addOption">
<span class="controlgroup">
{{ checkbox('compression2', name="compression", title='Enable Compression', value='1', desc='Compression') }}
{{ checkbox('compression2', name="compression", title='HTTP compression allows you to shrink the body of a response before it is relayed to a client, which results in using less network bandwidth per request. From a client\'s perspective, this reduces latency.',
value='1', desc='Compression') }}
{{ checkbox('cache2', name="cache", title='Enable cache', value='2', desc='Cache') }}
{{ checkbox('ssl_offloading1', title='Enable redirect from HTTP to HTTPS', desc='HTTP->HTTPS') }}
{{ checkbox('ssl_offloading1', title='Enable redirection from HTTP scheme to HTTPS scheme', desc='HTTP->HTTPS') }}
</span>
</td>
</tr>
<tr class="advance">
<td class="addName"><span title="Web application firewall">WAF(?):</span></td>
<td class="addName"><span title="Web application firewall" class="help_cursor">WAF:</span></td>
<td class="addOption">
<span class="controlgroup">
{{ checkbox('slow_atack1', title='Slow attack protect', desc='Slow attack') }}
{{ checkbox('slow_atack1', title='In a Slow POST attack, an attacker begins by sending a legitimate HTTP POST header to a Web server, exactly as they would under normal circumstances. The header specifies the exact size of the message body that will then follow. However, that message body is then sent at an alarmingly low rate sometimes as slow as 1 byte per approximately two minutes.',
desc='Slow attack') }}
{{ checkbox('ddos1', title='DDOS attack protect', desc='DDOS') }}
{{ checkbox('whitelist_checkbox1', title='Add whitelist', desc='Whitelist') }}
{{ checkbox('blacklist_checkbox1', title='Add blacklist', desc='Blacklist') }}
{{ checkbox('waf2', name='waf', title='Web application firewall', desc='WAF', value='1') }}
{{ checkbox('antibot1', title='Antibot Protection', desc='Antibot', value='1') }}
{{ checkbox('antibot1', title='Unfortunately, a large portion of bots are used for malicious reasons. Their intentions include web scraping, spamming, request flooding, brute forcing, and vulnerability scanning. For example, bots may scrape your price lists so that competitors can consistently undercut you or build a competitive solution using your data. Or they may try to locate forums and comment sections where they can post spam. At other times, theyre scanning your site looking for security weaknesses.',
desc='Antibot', value='1') }}
</span>
<div id="blacklist-hide1" style="display: none;">
<br /><span class="tooltip tooltipTop">Enter a blacklist name, or press the "down" button::</span><br />
@ -415,10 +440,20 @@
<td class="addName">Options:</td>
<td class="addOption">
<span class="controlgroup">
{{ checkbox('forward_for1', title='Option Forward for if none', desc='Forward for') }}
{{ checkbox('forward_for1', title='When HAProxy Enterprise proxies a TCP connection, it overwrites the client\'s source IP address with its own when communicating with the backend server. However, when relaying HTTP messages, it can store the client\'s address in the HTTP header X-Forwarded-For. The backend server can then be configured to read the value from that header to retrieve the client\'s IP address.',
desc='Forward for') }}
{% set values = dict() %}
{% set values = {'Off':'Off','Server only':'Server only','Force close':'Force close','Pretend keep alive':'Pretend keep alive'} %}
{{ select('force_close', values=values, first='Force HTTP close', class='force_close') }}
{{ select('force_close', values=values, first='Force HTTP close', title='Since HAProxy works in reverse-proxy mode, the servers see its IP address as
their client address. This is sometimes annoying when the client\'s IP address
is expected in server logs. To solve this problem, the well-known HTTP header
"X-Forwarded-For" may be added by HAProxy to all requests sent to the server.
This header contains a value representing the client\'s IP address. Since this
header is always appended at the end of the existing header list, the server
must be configured to always use the last occurrence of this header only. See
the server\'s manual to find how to enable use of this standard header. Note
that only the last occurrence of the header must be used, since it is really
possible that the client has already brought one.', class='force_close') }}
{{ checkbox('options-frontend-show', title='Set options manually', desc='Set options') }}
</span>
<div id="options-frontend-show-div" style="display: none;">
@ -440,7 +475,7 @@
<tr>
<td class="addName">Default backend</td>
<td class="addOption">
{{ input('backends', name='backends', placeholder="some_backend", size='30') }}
{{ input('backends', name='backends', placeholder="some_backend", size='30', title='If no condition is valid, the backend defined with "default_backend" will be used. If no default backend is defined, either the servers in the same section are used (in case of a "listen" section) or, in case of a frontend, no server is used and a 503 service unavailable response is returned.') }}
<div class="tooltip tooltipTop">
<b>Note</b>. If you want to use the default backend, <span title="Create backend" class="redirectBackend link">backend must exist</span>.
</div>
@ -557,12 +592,13 @@
</td>
</tr>
<tr class="advance">
<td class="addName"><span title="Cache support start 1.8 and latter">Web acceleration(?):</span></td>
<td class="addName"><span title="Cache support start 1.8 and latter" class="help_cursor">Web acceleration:</span></td>
<td class="addOption">
<span class="controlgroup">
{{ checkbox('compression3', name="compression", title='Enable Compression', value='1', desc='Compression') }}
{{ checkbox('compression3', name="compression", title='HTTP compression allows you to shrink the body of a response before it is relayed to a client, which results in using less network bandwidth per request. From a client\'s perspective, this reduces latency.',
value='1', desc='Compression') }}
{{ checkbox('cache3', name="cache", title='Enable cache', value='2', desc='Cache') }}
{{ checkbox('ssl_offloading2', title='Enable SSL Offloading', desc='SSL Offloading') }}
{{ checkbox('ssl_offloading2', title='The term SSL termination means that you are performing all encryption and decryption at the edge of your network, such as at the load balancer.', desc='SSL Offloading') }}
</span>
</td>
</tr>
@ -570,12 +606,21 @@
<td class="addName">Options:</td>
<td class="addOption">
<span class="controlgroup">
{{ checkbox('forward_for2', title='Option Forward for if none', desc='Forward for') }}
{{ checkbox('redispatch2', title='Enable Redispatch', desc='Redispatch') }}
{{ checkbox('forward_for2', title='When HAProxy Enterprise proxies a TCP connection, it overwrites the client\'s source IP address with its own when communicating with the backend server. However, when relaying HTTP messages, it can store the client\'s address in the HTTP header X-Forwarded-For. The backend server can then be configured to read the value from that header to retrieve the client\'s IP address.',
desc='Forward for') }}
{{ checkbox('redispatch2', title='In HTTP mode, if a server designated by a cookie is down, clients may
definitely stick to it because they cannot flush the cookie, so they will not
be able to access the service anymore.
Specifying "option redispatch" will allow the proxy to break their
persistence and redistribute them to a working server.
It also allows to retry connections to another server in case of multiple
connection failures. Of course, it requires having "retries" set to a nonzero
value.', desc='Redispatch') }}
{% set values = dict() %}
{% set values = {'Off':'Off','Server only':'Server only','Force close':'Force close','Pretend keep alive':'Pretend keep alive'} %}
{{ select('force_close', values=values, first='Force HTTP close', class='force_close') }}
{{ checkbox('cookie2', title='Set cookie', desc='Set cookie', value='1') }}
{{ select('force_close', values=values, first='Force HTTP close', title='123', class='force_close') }}
{{ checkbox('cookie2', title='To send a client to the same server where they were sent previously in order to reuse a session on that server, you can enable cookie-based session persistence. Add a cookie directive to the backend section and set the cookie parameter to a unique value on each server line.',
desc='Set cookie', value='1') }}
{{ checkbox('options-backend-show', title='Set options manually', desc='Set options') }}
</span>
<br>
@ -642,7 +687,8 @@
{{ select('fall-backend', name='fall', values=values, first='fall', class='force_close') }}
</div>
<div style="display: block">
{{ checkbox('circuit_breaking_backend', name="circuit_breaking", desc='Circuit Breaking', title='Enable Circuit Breaking', value='1') }}
{{ checkbox('circuit_breaking_backend', name="circuit_breaking", desc='Circuit Breaking', title='Circuit breaker is a design pattern which is used to detect failures and encapsulates the logic of preventing a failure from constantly recurring. The circuit breaker design pattern works much like an electrical circuit breaker which is intended to “trip” or open the circuit when failure is detected.',
value='1') }}
</div>
<div id="circuit_breaking_backend_div" style="display: none">
Observe:
@ -650,7 +696,7 @@
error-limit: {{ input('circuit_breaking_error_limit', type='number', value='50', style='width: 50px;') }}
on-error:
{{ select('circuit_breaking_on_error', values=on_error, class='force_close') }}
<div class="tooltip tooltipTop">Read more about Circuit Breaking <a href="https://roxy-wi.org/description.py?description=circuit_breaking" title="Circuit Breaking" target="_blank">here</a></div>
<div class="tooltip tooltipTop">Read more about Circuit Breaking <a href="https://roxy-wi.org/description/circuit-breaking" title="Circuit Breaking" target="_blank">here</a></div>
</div>
</td>
</tr>
@ -1120,9 +1166,10 @@ var serv_ports = $('.send_proxy');
for (var i = 0; i <= serv_ports.length; i++) {
var uniqId = makeid(3);
$(serv_ports[i]).append('<label for="' + uniqId + '" class="send_proxy_label" title="Set send-proxy for this server">send-proxy</label><input type="checkbox" name="send_proxy" value="1" id="' + uniqId + '">');
$(serv_ports[i]).append('<label for="' + uniqId + '" class="send_proxy_label" title="Set send-proxy for this server" data-help="The Send-proxy parameter enforces the use of the PROXY protocol over any connection established to this server. The PROXY protocol informs the other end about the layer 3/4 addresses of the incoming connection so that it can know the client\'s address or the public address it accessed to, whatever the upper-layer protocol.">send-proxy</label><input type="checkbox" name="send_proxy" value="1" id="' + uniqId + '">');
var uniqId = makeid(3);
$(serv_ports[i]).append('<label for="' + uniqId + '" class="send_proxy_label" title="Set this server as backup server">backup</label><input type="checkbox" name="backup" value="1" id="' + uniqId + '">');
$(serv_ports[i]).append('<label for="' + uniqId + '" class="send_proxy_label" title="Set this server as backup server" data-help="When all servers in a farm are down, we want to redirect traffic to a backup server which delivers either sorry pages or a degraded mode of the application.\n' +
'This can be done easily in HAProxy by adding the keyword backup on the server line. If multiple backup servers are configured, only the first active one is used.">backup</label><input type="checkbox" name="backup" value="1" id="' + uniqId + '">');
}
</script>
{% endblock %}

@ -48,9 +48,9 @@
</td>
</tr>
<tr class="advance">
<td class="addName"><span title="Activates the cache for connections to upstream servers.">Keepalive:</span></td>
<td class="addName"><span title="Activates the cache for connections to upstream servers." data-help="The connections parameter sets the maximum number of idle keepalive connections to upstream servers that are preserved in the cache of each worker process. When this number is exceeded, the least recently used connections are closed.">Keepalive:</span></td>
<td class="addOption">
{{ input('name', name='keepalive', title="Activates the cache for connections to upstream servers.", placeholder="32") }}
{{ input('name', name='keepalive', title="The connections parameter sets the maximum number of idle keepalive connections to upstream servers that are preserved in the cache of each worker process. When this number is exceeded, the least recently used connections are closed.", placeholder="32") }}
</td>
</tr>
<tr>

@ -49,6 +49,9 @@
{% if role <= 3 %}
<a class="ui-button ui-widget ui-corner-all" title="Show versions" onclick="openVersions()">Versions</a>
{% endif %}
{% if role <= 2 %}
<a href="/app/servers.py#backup" class="ui-button ui-widget ui-corner-all" title="Git">Git</a>
{% endif %}
</form>
</p>
<div id="ajax-config_file_name"></div>
@ -93,13 +96,13 @@
</center>
<script>
if (cur_url[1].split('&')[2] == 'showMap') {
showMap();
showMap();
}
if (cur_url[1].split('&')[1] == 'showCompare' || cur_url[1].split('&')[2] == 'showCompare') {
showCompareConfigs();
showCompareConfigs();
}
if (cur_url[1].split('&')[2] == 'showConfig') {
showConfig();
showConfig();
}
if (cur_url[1].split('&')[2] == 'showConfigFiles') {
showConfigFiles();

@ -6,18 +6,18 @@
<span name="add_servers">
<input name="servers" required title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
<input name="server_port" required title="Backend port" size=8 placeholder="yyy" class="form-control add_server_number" type="number">
<span name="max_fails">max_fails:</span> <input name="max_fails" required title="By default, the number of unsuccessful attempts is set to 1" size=8 class="form-control add_server_number" value="1" type="number">
<span name="fail_timeout">fail_timeout:</span> <input name="fail_timeout" required title="By default, the number of unsuccessful attempts is set to 1s" size=8 value="1" class="form-control add_server_number" type="number">s
<span name="max_fails">max_fails:</span> <input name="max_fails" required title="By default, the number of unsuccessful attempts is set to 1" data-help="sets the number of unsuccessful attempts to communicate with the server that should happen in the duration set by the fail_timeout parameter to consider the server unavailable for a duration also set by the fail_timeout parameter. By default, the number of unsuccessful attempts is set to 1." size=8 class="form-control add_server_number" value="1" type="number">
<span name="fail_timeout">fail_timeout:</span> <input name="fail_timeout" required title="By default, the number of unsuccessful attempts is set to 1s" size=8 value="1" class="form-control add_server_number" type="number" data-help="The time during which the specified number of unsuccessful attempts to communicate with the server should happen to consider the server unavailable; and the period of time the server will be considered unavailable.">s
<br />
<input name="servers" title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server"><span class="second-server">:</span>
<input name="server_port" title="Backend port" size=8 placeholder="yyy" class="form-control second-server add_server_number" type="number">
<span name="max_fails">max_fails:</span> <input name="max_fails" required title="By default, the number of unsuccessful attempts is set to 1" size=8 class="form-control add_server_number" value="1" type="number">
<span name="fail_timeout">fail_timeout:</span> <input name="fail_timeout" required title="By default, the number of unsuccessful attempts is set to 1" size=8 value="1" class="form-control add_server_number" type="number">s
<span name="max_fails">max_fails:</span> <input name="max_fails" required title="By default, the number of unsuccessful attempts is set to 1" data-help="sets the number of unsuccessful attempts to communicate with the server that should happen in the duration set by the fail_timeout parameter to consider the server unavailable for a duration also set by the fail_timeout parameter. By default, the number of unsuccessful attempts is set to 1." size=8 class="form-control add_server_number" value="1" type="number">
<span name="fail_timeout">fail_timeout:</span> <input name="fail_timeout" required title="By default, the number of unsuccessful attempts is set to 1" size=8 value="1" class="form-control add_server_number" type="number" data-help="The time during which the specified number of unsuccessful attempts to communicate with the server should happen to consider the server unavailable; and the period of time the server will be considered unavailable.">s
<br />
<input name="servers" title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server"><span class="second-server">:</span>
<input name="server_port" title="Backend port" size=3 placeholder="yyy" class="form-control second-server add_server_number" type="number">
<span name="max_fails">max_fails:</span> <input name="max_fails" required title="By default, the number of unsuccessful attempts is set to 1" size=8 class="form-control add_server_number" value="1" type="number">
<span name="fail_timeout">fail_timeout:</span> <input name="fail_timeout" required title="By default, the number of unsuccessful attempts is set to 1" size=8 value="1" class="form-control add_server_number" type="number">s
<span name="max_fails">max_fails:</span> <input name="max_fails" required title="By default, the number of unsuccessful attempts is set to 1" data-help="sets the number of unsuccessful attempts to communicate with the server that should happen in the duration set by the fail_timeout parameter to consider the server unavailable for a duration also set by the fail_timeout parameter. By default, the number of unsuccessful attempts is set to 1." size=8 class="form-control add_server_number" value="1" type="number">
<span name="fail_timeout">fail_timeout:</span> <input name="fail_timeout" required title="By default, the number of unsuccessful attempts is set to 1" size=8 value="1" class="form-control add_server_number" type="number" data-help="The time during which the specified number of unsuccessful attempts to communicate with the server should happen to consider the server unavailable; and the period of time the server will be considered unavailable.">s
</span>
<span>
<a class="link add-server backend_server" name="add-server-input" title="Add upstream" style="cursor: pointer;"></a>

@ -8,20 +8,20 @@
<input name="template-number" class="prefix form-control" title="servers num" value="3" type="number" style="width: 35px; display: none;">
<input name="servers" required title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control">:
<input name="server_port" required title="Backend port" size=8 placeholder="yyy" class="form-control add_server_number" type="number">
<span name="port_check_text">port check:</span> <input name="port_check" required title="Port for checking" size=8 class="form-control add_server_number" type="number">
<span name="maxconn_name">maxconn:</span> <input name="server_maxconn" required title="Maxconn. Default 200" size=8 value="200" class="form-control add_server_number" type="number">
<span name="port_check_text">port check:</span> <input name="port_check" required title="Port for checking" data-help="A basic TCP-layer health check tries to connect to the server's TCP port. The check is valid when the server answers with a SYN/ACK packet." size=8 class="form-control add_server_number" type="number">
<span name="maxconn_name">maxconn:</span> <input name="server_maxconn" required title="Maxconn. Default 200" data-help="The total number of connections allowed, process-wide. This stops the process from accepting too many connections at once, which safeguards it from running out of memory." size=8 value="200" class="form-control add_server_number" type="number">
<span class="send_proxy"></span>
<br />
<input name="servers" title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server"><span class="second-server">:</span>
<input name="server_port" title="Backend port" size=8 placeholder="yyy" class="form-control second-server add_server_number" type="number">
<span name="port_check_text">port check:</span> <input name="port_check" required title="Port for checking" size=8 class="form-control add_server_number" type="number">
<span name="maxconn_name">maxconn:</span> <input name="server_maxconn" required title="Maxconn. Default 200" size=8 value="200" class="form-control add_server_number" type="number">
<span name="port_check_text">port check:</span> <input name="port_check" required title="Port for checking" data-help="A basic TCP-layer health check tries to connect to the server's TCP port. The check is valid when the server answers with a SYN/ACK packet." size=8 class="form-control add_server_number" type="number">
<span name="maxconn_name">maxconn:</span> <input name="server_maxconn" required title="Maxconn. Default 200" data-help="The total number of connections allowed, process-wide. This stops the process from accepting too many connections at once, which safeguards it from running out of memory." size=8 value="200" class="form-control add_server_number" type="number">
<span class="send_proxy"></span>
<br />
<input name="servers" title="Backend IP" size=14 placeholder="xxx.xxx.xxx.xxx" class="form-control second-server"><span class="second-server">:</span>
<input name="server_port" title="Backend port" size=3 placeholder="yyy" class="form-control second-server add_server_number" type="number">
<span name="port_check_text">port check:</span> <input name="port_check" required title="Port for checking" size=8 class="form-control add_server_number" type="number">
<span name="maxconn_name">maxconn:</span> <input name="server_maxconn" required title="Maxconn. Default 200" size=8 value="200" class="form-control add_server_number" type="number">
<span name="port_check_text">port check:</span> <input name="port_check" required title="Port for checking" data-help="A basic TCP-layer health check tries to connect to the server's TCP port. The check is valid when the server answers with a SYN/ACK packet." size=8 class="form-control add_server_number" type="number">
<span name="maxconn_name">maxconn:</span> <input name="server_maxconn" required title="Maxconn. Default 200" data-help="The total number of connections allowed, process-wide. This stops the process from accepting too many connections at once, which safeguards it from running out of memory." size=8 value="200" class="form-control add_server_number" type="number">
<span class="send_proxy"></span>
</span>
<span>

@ -5,7 +5,7 @@
{# {% if readonly == '' %}
{% set readonly = 'readonly onfocus=this.removeAttribute(\'readonly\');' %}
{% endif %} #}
<input type="{{ type }}" name="{{name}}" value="{{ value|e }}" id="{{ id }}" size="{{size}}" style="{{style}}" {{readonly}} {{required}} {{autofocus}} placeholder="{{placeholder}}" title="{{title}}" class="{{class}}" autocomplete="off" />
<input type="{{ type }}" name="{{name}}" value="{{ value|e }}" id="{{ id }}" data-help="{{title}}" size="{{size}}" style="{{style}}" {{readonly}} {{required}} {{autofocus}} placeholder="{{placeholder}}" title="{{title}}" class="{{class}}" autocomplete="off" />
{%- endmacro %}
{%- macro checkbox(id, name='', checked='', title='', value='', desc='', disabled='', style='') -%}
@ -15,10 +15,10 @@
{% if disabled == 'true' %}
{% set disabled = 'disabled' %}
{% endif %}
<label for="{{id}}" title="{{title}}" class="{{id}}" style="{{style}}">{{desc}}</label><input name="{{name}}" type="checkbox" id="{{id}}" value="{{value|e}}" {{checked}} {{disabled}} />
<label for="{{id}}" title="{{title}}" class="{{id}}" style="{{style}}" data-help="{{title}}">{{desc}}</label><input name="{{name}}" type="checkbox" id="{{id}}" value="{{value|e}}" {{checked}} {{disabled}} />
{%- endmacro %}
{%- macro select(id, values, name='', required='', first='', class='', selected='', disabled='true') -%}
{%- macro select(id, values, name='', required='', first='', class='', selected='', title='', disabled='true') -%}
{% if name == '' %}
{% set name = id %}
{% endif %}
@ -27,7 +27,7 @@
{% else %}
{% set disabled = '' %}
{% endif %}
<select {{required}} name="{{name}}" id="{{id}}" class="{{class}}">
<select {{required}} name="{{name}}" id="{{id}}" title="{{title}}" data-help="{{title}}" class="{{class}}">
{% if first %}
<option {{disabled}} selected>{{first}}</option>
{% endif %}

@ -37,7 +37,8 @@ $( function() {
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('Failed') != '-1') {
toastr.error(data);
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else {
response(data.split(" "));
}
@ -59,7 +60,8 @@ $( function() {
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('Failed') != '-1') {
toastr.error(data);
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else {
response(data.split(" "));
}
@ -218,7 +220,10 @@ $( function() {
type: "POST",
success: function( data ) {
data = data.replace(/^\s+|\s+$/g,'');
if(data.indexOf('keepalived:') != '-1') {
if (data.indexOf('error:') != '-1') {
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else if(data.indexOf('keepalived:') != '-1') {
$('#cur_master_ver').text('Keepalived has not installed');
$('#create').attr('title', 'Create HA cluster');
} else {
@ -239,7 +244,10 @@ $( function() {
type: "POST",
success: function( data ) {
data = data.replace(/^\s+|\s+$/g,'');
if(data.indexOf('keepalived:') != '-1') {
if (data.indexOf('error:') != '-1') {
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else if(data.indexOf('keepalived:') != '-1') {
$('#cur_slave_ver').text('Keepalived has not installed');
$('#create').attr('title', 'Create HA cluster');
} else {
@ -260,7 +268,10 @@ $( function() {
type: "POST",
success: function( data ) {
data = data.replace(/^\s+|\s+$/g,'');
if(data.indexOf('keepalived:') != '-1') {
if (data.indexOf('error:') != '-1') {
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else if(data.indexOf('keepalived:') != '-1') {
$('#cur_master_ver-add').text('Keepalived has not installed');
$('#add-vrrp').attr('title', 'Add a HA configuration');
} else {
@ -281,7 +292,10 @@ $( function() {
type: "POST",
success: function( data ) {
data = data.replace(/^\s+|\s+$/g,'');
if(data.indexOf('keepalived:') != '-1') {
if (data.indexOf('error:') != '-1') {
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else if(data.indexOf('keepalived:') != '-1') {
$('#cur_slave_ver-add').text('Keepalived has not installed');
$('#add-vrrp').attr('title', 'Add a HA configuration');
} else {
@ -314,7 +328,8 @@ function add_master_addr(kp, router_id) {
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('UNREACHABLE') != '-1' || data.indexOf('FAILED') != '-1') {
showProvisioningError(data, '#creating-master-add', '#wait-mess-add', '#creating-error-add');
var p_err = show_pretty_ansible_error(data);
showProvisioningError(p_err + '<br><br>', '#creating-master-add', '#wait-mess-add', '#creating-error-add');
} else if (data == '' ){
showProvisioningWarning('#creating-master-add', 'master Keepalived', '#creating-warning-add', '#wait_mess-add');
} else if (data.indexOf('success') != '-1' ){
@ -340,7 +355,8 @@ function add_slave_addr(kp, router_id) {
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('UNREACHABLE') != '-1' || data.indexOf('FAILED') != '-1') {
showProvisioningError(data, '#creating-slave-add', '#wait-mess-add', '#creating-error-add');
var p_err = show_pretty_ansible_error(data);
showProvisioningError(p_err + '<br><br>', '#creating-slave-add', '#wait-mess-add', '#creating-error-add');
} else if (data == '' ){
showProvisioningWarning('#creating-slave-add', 'master Keepalived', '#creating-warning-add', '#wait_mess-add');
} else if (data.indexOf('success') != '-1' ){
@ -393,7 +409,8 @@ function create_master_keepalived(hap, nginx, syn_flood, router_id) {
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
showProvisioningError(data, '#creating-master', '#wait-mess', '#creating-error');
var p_err = show_pretty_ansible_error(data);
showProvisioningError(p_err + '<br><br>', '#creating-master', '#wait-mess', '#creating-error');
} else if (data == '' ){
showProvisioningWarning(step_id, 'master Keepalived', '#creating-warning', '#wait_mess');
} else if (data.indexOf('success') != '-1' ){
@ -446,7 +463,8 @@ function create_slave_keepalived(hap, nginx, syn_flood, router_id) {
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
showProvisioningError(data, '#creating-slave', '#wait-mess', '#creating-error');
var p_err = show_pretty_ansible_error(data);
showProvisioningError(p_err + '<br><br>', '#creating-slave', '#wait-mess', '#creating-error');
} else if (data == '' ){
showProvisioningWarning(step_id, 'slave Keepalived', '#creating-warning', '#wait_mess');
} else if (data.indexOf('success') != '-1' ){
@ -492,7 +510,8 @@ function create_keep_alived_hap(nginx, server, docker) {
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
showProvisioningError(data, step_id, '#wait-mess', '#creating-error');
var p_err = show_pretty_ansible_error(data);
showProvisioningError(p_err + '<br><br>', step_id, '#wait-mess', '#creating-error');
} else if (data == '' ){
showProvisioningWarning(step_id, install_step, '#creating-warning', '#wait_mess');
} else if (data.indexOf('success') != '-1' ){
@ -529,7 +548,8 @@ function create_keep_alived_nginx(server, docker) {
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
showProvisioningError(data, step_id, '#wait-mess', '#creating-error');
var p_err = show_pretty_ansible_error(data);
showProvisioningError(p_err + '<br><br>', step_id, '#wait-mess', '#creating-error');
} else if (data == '' ){
showProvisioningWarning(step_id, install_step, '#creating-warning', '#wait_mess');
} else if (data.indexOf('success') != '-1' ){

@ -758,7 +758,11 @@ $( function() {
$( "#tabs" ).tabs();
$( "select" ).selectmenu();
//$( "[title]" ).tooltip();
$( "[title]" ).tooltip({
"content": function(){
return $(this).attr("data-help");
}
});
$( "input[type=submit], button" ).button();
$( "input[type=checkbox]" ).checkboxradio();
$( ".controlgroup" ).controlgroup();
@ -1592,3 +1596,12 @@ function sendGet(page) {
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.send(null);
}
function show_pretty_ansible_error(data) {
try {
data = data.split('error: ');
var p_err = JSON.parse(data[1]);
return p_err['msg'];
} catch (e) {
return data;
}
}

@ -1,5 +1,4 @@
var awesome = "/inc/fontawesome.min.js"
$( function() {
$( "#backup_tabs" ).tabs();
$('#install').click(function() {
@ -31,7 +30,8 @@ $( function() {
data = data.replace(/\s+/g,' ');
$("#ajax").html('')
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
toastr.error(data);
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else if (data.indexOf('success') != '-1' ){
toastr.remove();
toastr.success(data);
@ -75,7 +75,8 @@ $( function() {
$("#ajax").html('')
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
toastr.clear();
toastr.error(data);
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else if (data.indexOf('success') != '-1' ){
toastr.clear();
toastr.success(data);
@ -105,7 +106,8 @@ $( function() {
$("#ajaxmon").html('');
if (data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1' || data.indexOf('ERROR') != '-1') {
toastr.clear();
toastr.error(data);;
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else if (data.indexOf('success') != '-1' ){
toastr.clear();
toastr.success(data);
@ -140,7 +142,8 @@ $( function() {
$("#ajaxmon").html('');
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
toastr.clear();
toastr.error(data);
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else if (data.indexOf('success') != '-1' ){
toastr.clear();
toastr.success(data);
@ -177,10 +180,12 @@ $( function() {
data = data.replace(/\s+/g,' ');
$("#ajaxmon").html('');
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
toastr.error(data);
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else if (data.indexOf('success') != '-1' ){
toastr.clear();
toastr.success(data);
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
$('#cur_nginx_exp_ver').text('NGINX exporter is installed');
$("#nginx_exp_addserv").trigger( "selectmenuchange" );
} else if (data.indexOf('Info') != '-1' ){
@ -214,7 +219,8 @@ $( function() {
data = data.replace(/\s+/g,' ');
$("#ajaxmon").html('');
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
toastr.error(data);
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else if (data.indexOf('success') != '-1' ){
toastr.clear();
toastr.success(data);
@ -250,7 +256,8 @@ $( function() {
data = data.replace(/\s+/g,' ');
$("#ajaxmon").html('');
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1' || data.indexOf('UNREACHABLE') != '-1') {
toastr.error(data);
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else if (data.indexOf('success') != '-1' ){
toastr.clear();
toastr.success(data);
@ -833,7 +840,8 @@ $( function() {
$("#ajax-geoip").html('')
if (data.indexOf('error:') != '-1' || data.indexOf('FAILED') != '-1') {
toastr.clear();
toastr.error(data);
var p_err = show_pretty_ansible_error(data);
toastr.error(p_err);
} else if (data.indexOf('success:') != '-1' ){
toastr.clear();
toastr.success(data);

Loading…
Cancel
Save