Pavel Loginov 2020-01-12 00:16:27 +03:00
parent d0787a0c77
commit 60d3b0ba30
19 changed files with 869 additions and 92 deletions

View File

@ -458,9 +458,28 @@ def update_db_v_3_8_1(**kwargs):
con.close()
def update_db_v_3_12(**kwargs):
con, cur = get_cur()
sql = """CREATE TABLE IF NOT EXISTS `backups` ( `id` INTEGER NOT NULL, `server` VARCHAR ( 64 ), `rhost` VARCHAR ( 120 ), `rpath` VARCHAR ( 120 ), `type` VARCHAR ( 120 ), `time` VARCHAR ( 120 ), cred INTEGER, `description` VARCHAR ( 120 ), PRIMARY KEY(`id`)); """
try:
cur.execute(sql)
con.commit()
except sqltool.Error as e:
if kwargs.get('silent') != 1:
if e.args[0] == 'duplicate column name: id' or e == "1060 (42S21): Duplicate column name 'id' ":
print('DB was update to 3.12')
else:
print("DB was update to 3.12")
return False
else:
return True
cur.close()
con.close()
def update_ver(**kwargs):
con, cur = get_cur()
sql = """update version set version = '3.11.0.0'; """
sql = """update version set version = '3.12.0.0'; """
try:
cur.execute(sql)
con.commit()
@ -486,6 +505,7 @@ def update_all():
update_db_v_3_4_9_5()
update_db_v_3_5_3()
update_db_v_3_8_1()
update_db_v_3_12()
update_ver()
@ -505,6 +525,7 @@ def update_all_silent():
update_db_v_3_4_9_5(silent=1)
update_db_v_3_5_3(silent=1)
update_db_v_3_8_1(silent=1)
update_db_v_3_12(silent=1)
update_ver()

View File

@ -422,7 +422,10 @@ if form.getvalue('viewlogs') is not None:
grep_act = ''
grep = ''
cmd="cat %s| awk '$3>\"%s:00\" && $3<\"%s:00\"' |tail -%s %s %s" % (log_path + viewlog, date, date1, rows, grep_act, grep)
if viewlog == 'backup.log':
cmd="cat %s| awk '$2>\"%s:00\" && $2<\"%s:00\"' |tail -%s %s %s" % (log_path + viewlog, date, date1, rows, grep_act, grep)
else:
cmd="cat %s| awk '$3>\"%s:00\" && $3<\"%s:00\"' |tail -%s %s %s" % (log_path + viewlog, date, date1, rows, grep_act, grep)
output, stderr = funct.subprocess_execute(cmd)
print(funct.show_log(output))
@ -764,6 +767,75 @@ if form.getvalue('masteradd'):
os.system("rm -f %s" % script)
if form.getvalue('backup') or form.getvalue('deljob') or form.getvalue('backupupdate'):
server = form.getvalue('server')
rpath = form.getvalue('rpath')
time = form.getvalue('time')
type = form.getvalue('type')
rserver = form.getvalue('rserver')
cred = form.getvalue('cred')
deljob = form.getvalue('deljob')
update = form.getvalue('backupupdate')
description = form.getvalue('description')
script = "backup.sh"
ssh_enable, ssh_user_name, ssh_user_password, ssh_key_name = funct.return_ssh_keys_path('localhost', id=int(cred))
if deljob:
time = ''
rpath = ''
type = ''
elif update:
deljob = ''
else:
deljob = ''
if sql.check_exists_backup(server):
print('info: Backup job for %s already exists' % server)
sys.exit()
os.system("cp scripts/%s ." % script)
commands = [ "chmod +x "+script +" && ./"+script +" HOST="+rserver+" SERVER="+server+" TYPE="+type+
" TIME="+time+" RPATH="+rpath+" DELJOB="+deljob+" USER="+str(ssh_user_name)+" KEY="+str(ssh_key_name) ]
output, error = funct.subprocess_execute(commands[0])
if error:
funct.logging('backup', error, haproxywi=1)
print('error: '+error)
else:
for l in output:
if "msg" in l or "FAILED" in l:
try:
l = l.split(':')[1]
l = l.split('"')[1]
print(l+"<br>")
break
except:
print(output)
break
else:
if deljob == '' and update == '':
if sql.insert_backup_job(server, rserver, rpath, type, time, cred, description):
funct.logging('backup ', ' has created a new backup job for server '+server , haproxywi=1, login=1)
import http.cookies
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates/ajax'))
template = env.get_template('new_backup.html')
template = template.render(backups=sql.select_backups(server=server, rserver=rserver), sshs=sql.select_ssh())
print(template)
print('success: Backup job has created<br>')
else:
print('error: Cannot add job into DB<br>')
elif deljob:
sql.delete_backups(deljob)
print('Ok')
funct.logging('backup ', ' has deleted a backup job for server '+server, haproxywi=1, login=1)
elif update:
sql.update_backup(server, rserver, rpath, type, time, cred, description, update)
print('Ok')
funct.logging('backup ', ' has updated a backup job for server '+server, haproxywi=1, login=1)
if form.getvalue('haproxyaddserv'):
funct.install_haproxy(form.getvalue('haproxyaddserv'), syn_flood=form.getvalue('syn_flood'), hapver=form.getvalue('hapver'))

View File

@ -35,6 +35,7 @@ try:
api, stderr = funct.subprocess_execute(cmd)
servers = sql.get_dick_permit()
except:
role = ''
pass

View File

@ -0,0 +1,36 @@
- hosts: backup
become: yes
become_method: sudo
gather_facts: no
tasks:
- name: Creates directory
file:
path: "{{ RPATH }}/haproxy-wi-configs-backup/configs"
state: directory
owner: "{{ ansible_user }}"
when: DELJOB|length == 0
- hosts: haproxy_wi
become: yes
become_method: sudo
gather_facts: no
tasks:
- name: Creates backup jobs
cron:
name: "Backup HAProxy configs for user {{ SERVER }} {{ item }}"
special_time: "{{ TIME }}"
job: "rsync -arv {{ TYPE }} /var/www/haproxy-wi/configs/{{ item }}/{{ SERVER }}* {{ ansible_user }}@{{ HOST }}:{{ RPATH }}/haproxy-wi-configs-backup/configs/{{ item }} -e 'ssh -i {{ KEY }} -o StrictHostKeyChecking=no' --log-file=/var/www/haproxy-wi/log/backup.log"
when: DELJOB|length == 0
with_items:
- kp_config
- hap_config
- name: Removes backup jobs
cron:
name: "Backup HAProxy configs for user {{ SERVER }} {{ item }}"
state: absent
when: DELJOB|length > 0
with_items:
- kp_config
- hap_config

42
app/scripts/backup.sh Normal file
View File

@ -0,0 +1,42 @@
#!/bin/bash
for ARGUMENT in "$@"
do
KEY=$(echo $ARGUMENT | cut -f1 -d=)
VALUE=$(echo $ARGUMENT | cut -f2 -d=)
case "$KEY" in
RPATH) RPATH=${VALUE} ;;
TIME) TIME=${VALUE} ;;
TYPE) TYPE=${VALUE} ;;
HOST) HOST=${VALUE} ;;
SERVER) SERVER=${VALUE} ;;
USER) USER=${VALUE} ;;
KEY) KEY=${VALUE} ;;
DELJOB) DELJOB=${VALUE} ;;
*)
esac
done
export ANSIBLE_HOST_KEY_CHECKING=False
export ANSIBLE_DISPLAY_SKIPPED_HOSTS=False
PWD=`pwd`
PWD=$PWD/scripts/ansible/
echo '[backup]' > $PWD/$HOST
echo $HOST >> $PWD/$HOST
echo '[haproxy_wi]' >> $PWD/$HOST
echo 'localhost' >> $PWD/$HOST
if [[ $TYPE == 'synchronization' ]]; then
TYPE='--delete'
else
TYPE=''
fi
ansible-playbook $PWD/roles/backup.yml --key-file $KEY -e "ansible_user=$USER variable_host=$HOST RPATH=$RPATH TYPE=$TYPE TIME=$TIME HOST=$HOST SERVER=$SERVER KEY=$KEY DELJOB=$DELJOB" -i $PWD/$HOST
if [ $? -gt 0 ]
then
echo "error: Can't create backup job"
exit 1
fi
rm -f $PWD/$HOST

View File

@ -621,6 +621,90 @@ def update_ssh(id, name, enable, group, username, password):
con.close()
def insert_backup_job(server, rserver, rpath, type, time, cred, description):
con, cur = get_cur()
sql = """insert into backups(server, rhost, rpath, type, time, cred, description) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s') """ % (server, rserver, rpath, type, time, cred, description)
try:
cur.execute(sql)
con.commit()
except sqltool.Error as e:
out_error(e)
con.rollback()
return False
else:
return True
cur.close()
con.close()
def select_backups(**kwargs):
con, cur = get_cur()
sql = """select * from backups ORDER BY id"""
if kwargs.get("server") is not None and kwargs.get("rserver") is not None:
sql = """select * from backups where server='%s' and rhost = '%s' """ % (kwargs.get("server"), kwargs.get("rserver"))
try:
cur.execute(sql)
except sqltool.Error as e:
out_error(e)
else:
return cur.fetchall()
cur.close()
con.close()
def update_backup(server, rserver, rpath, type, time, cred, description, id):
con, cur = get_cur()
sql = """update backups set server = '%s',
rhost = '%s',
rpath = '%s',
type = '%s',
time = '%s',
cred = '%s',
description = '%s' where id = '%s' """ % (server, rserver, rpath, type, time, cred, description, id)
try:
cur.execute(sql)
con.commit()
except sqltool.Error as e:
out_error(e)
con.rollback()
return False
else:
return True
cur.close()
con.close()
def delete_backups(id):
con, cur = get_cur()
sql = """ delete from backups where id = %s """ % (id)
try:
cur.execute(sql)
con.commit()
except sqltool.Error as e:
out_error(e)
con.rollback()
else:
return True
cur.close()
con.close()
def check_exists_backup(server):
con, cur = get_cur()
sql = """ select id from backups where server = '%s' """ % server
try:
cur.execute(sql)
except sqltool.Error as e:
out_error(e)
else:
for s in cur.fetchall():
if s[0] is not None:
return True
else:
return False
cur.close()
con.close()
def show_update_ssh(name, page):
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates/ajax'))

View File

@ -751,6 +751,11 @@ $( function() {
$( ".force_close" ).selectmenu({
width: 180
});
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,6 +1,6 @@
{% extends "base.html" %}
{% block content %}
{% from 'include/input_macros.html' import input %}
{% from 'include/input_macros.html' import input, select %}
<style>
.container {
margin-right: 0;
@ -18,6 +18,7 @@
<li><a href="#checker">Checker</a></li>
<li><a href="#settings">Settings</a></li>
<li><a href="#updatehapwi">Update</a></li>
<li><a href="#backup">Backup</a></li>
{% include 'include/login.html' %}
</ul>
<div id="users">
@ -55,6 +56,24 @@
width: 150
});
{% endfor %}
{% for ssh in sshs %}
if (window.matchMedia('(max-width: 1280px)').matches) {
$("#sshgroup-{{ ssh.0}}" ).selectmenu({
width: 100
});
}
{% endfor %}
{% for server in backups %}
$("#backup-time-{{ server.0}}" ).selectmenu({
width: 100
});
$("#backup-type-{{server.0}}" ).selectmenu({
width: 130
});
$("#backup-credentials-{{server.0}}" ).selectmenu({
width: 150
});
{% endfor %}
});
</script>
{% for user in users %}
@ -485,6 +504,32 @@
</div>
<div id="ajax-update"></div>
</div>
<div id="backup">
<table class="overview" id="ajax-backup-table">
<tr class="overviewHead">
<td class="padding10 first-collumn">Servers</td>
<td class="padding10">Remote server</td>
<td class="padding10">Remote folder</td>
<td class="padding10">Backup type</td>
<td class="padding10">Period time</td>
<td class="padding10">Credentials</td>
<td class="padding10">Description</td>
<td></td>
<td></td>
</tr>
{% for b in backups %}
{% include 'include/admin_backup.html' %}
{% endfor %}
</table>
<br /><span class="add-button" title="Add a new backup job" id="add-backup-button">+ Add a new backup job</span>
<br /><br />
<div id="ajax-backup"></div>
<div class="add-note addName alert-info" style="width: inherit; margin-right: 15px;">
You can read the description of all parameters <a href="https://haproxy-wi.org/description.py?description=backup" title="Backup description" target="_blank">here</a>
</div>
</div>
</div>
<div id="user-add-table" style="display: none;">
<table class="overview">
@ -519,7 +564,7 @@
</tr>
</table>
</div>
<div id="server-add-table" title="View certificate " style="display: none;">
<div id="server-add-table" title="Add a new server " style="display: none;">
<table class="overview">
{% include 'include/admin_add_server.html' %}
<tr>
@ -553,6 +598,33 @@
</table>
</div>
<div id="backup-add-table" title="Add a new backup job " style="display: none;">
<table class="overview">
{% include 'include/add_backup.html' %}
<tr>
<td class="padding20">
Credentials for remote server
<span class="need-field">*</span>
</td>
<td>
<select id="backup-credentials" required>
<option disabled selected>Choose credentials</option>
{% for ssh in sshs %}
<option value="{{ssh.0}}">{{ssh.1}}</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
<td class="padding20">
Description
</td>
<td>
{{ input('backup-description', size='30') }}
</td>
</tr>
</table>
</div>
{% include 'include/change_pass_form.html' %}
<style>
.ui-selectmenu-button.ui-button {

View File

@ -0,0 +1,77 @@
{% for b in backups %}
<tr class="newbackup" id="backup-table-{{b.0}}">
<td class="padding10 first-collumn">
<span id="backup-server-{{b.0}}">{{ b.1 }}</span>
</td>
<td>
<input type="text" id="backup-rserver-{{b.0}}" value="{{b.2}}" size="14" class="form-control">
</td>
<td>
<input type="text" id="backup-rpath-{{b.0}}" value="{{b.3}}" class="form-control">
</td>
<td>
{% set values = {'backup':'backup','synchronization':'synchronization'} %}
<select name="backup-type-{{b.0}}" id="backup-type-{{b.0}}" class="force_close">
{% for v, des in values|dictsort(false, 'value') %}
{% if v == b.4 %}
<option value="{{v}}" selected>{{des}}</option>
{% else %}
<option value="{{v}}">{{des}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td>
{% set values = {'hourly':'hourly','daily':'daily','weekly':'weekly', 'monthly':'monthly'} %}
<select name="backup-time-{{b.0}}" id="backup-time-{{b.0}}" class="force_close">
{% for v, des in values|dictsort(false, 'value') %}
{% if v == b.5 %}
<option value="{{v}}" selected>{{des}}</option>
{% else %}
<option value="{{v}}">{{des}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td>
<select id="backup-credentials-{{b.0}}" required>
<option disabled selected>Choose credentials</option>
{% for ssh in sshs %}
{% if ssh.2 == 1 %}
{% if ssh.0 == b.6 %}
<option value="{{ssh.0}}" selected="selected">{{ssh.1}}</option>
{% else %}
<option value="{{ssh.0}}">{{ssh.1}}</option>
{% endif %}
{% endif %}
{% endfor %}
</select>
</td>
<td>
{% if b.7 != 'None' %}
<input type="text" id="backup-description-{{b.0}}" value="{{b.7}}" class="form-control">
{% else %}
<input type="text" id="backup-description-{{b.0}}" class="form-control">
{% endif %}
</td>
<td>
<a class="add" onclick="cloneBackup({{b.0}})" id="clone-backup{{b.0}}" title="Clone {{b.1}}" style="cursor: pointer;"></a>
</td>
<td>
<a class="delete" onclick="confirmDeleteBackup({{b.0}})" title="Delete backup {{b.1}}" style="cursor: pointer;"></a>
</td>
</tr>
<script>
$( function() {
$("#backup-time-{{ b.0}}" ).selectmenu({
width: 100
});
$("#backup-type-{{b.0}}" ).selectmenu({
width: 130
});
$("#backup-credentials-{{b.0}}" ).selectmenu({
width: 150
});
});
</script>
{% endfor %}

View File

@ -0,0 +1,75 @@
{% for b in backups %}
<tr class="newbackup" id="backup-table-{{b.0}}">
<td class="padding10 first-collumn">
<span id="backup-server-{{b.0}}">{{ b.1 }}</span>
</td>
<td>
<input type="text" id="backup-rserver-{{b.0}}" value="{{b.2}}" size="14" class="form-control">
</td>
<td>
<input type="text" id="backup-rpath-{{b.0}}" value="{{b.3}}" class="form-control">
</td>
<td>
{% set values = {'backup':'backup','synchronization':'synchronization'} %}
<select name="backup-type-{{b.0}}" id="backup-type-{{b.0}}" class="force_close">
{% for v, des in values|dictsort(false, 'value') %}
{% if v == b.4 %}
<option value="{{v}}" selected>{{des}}</option>
{% else %}
<option value="{{v}}">{{des}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td>
{% set values = {'hourly':'hourly','daily':'daily','weekly':'weekly', 'monthly':'monthly'} %}
<select name="backup-time-{{b.0}}" id="backup-time-{{b.0}}" class="force_close">
{% for v, des in values|dictsort(false, 'value') %}
{% if v == b.5 %}
<option value="{{v}}" selected>{{des}}</option>
{% else %}
<option value="{{v}}">{{des}}</option>
{% endif %}
{% endfor %}
</select>
</td>
<td>
<select id="backup-credentials-{{b.0}}" required>
<option disabled selected>Choose credentials</option>
{% for ssh in sshs %}
{% if ssh.2 == 1 %}
{% if ssh.0 == b.6 %}
<option value="{{ssh.0}}" selected="selected">{{ssh.1}}</option>
{% else %}
<option value="{{ssh.0}}">{{ssh.1}}</option>
{% endif %}
{% endif %}
{% endfor %}
</select>
</td>
<td>
{% if b.7 != 'None' %}
<input type="text" id="backup-description-{{b.0}}" value="{{b.7}}" class="form-control">
{% endif %}
</td>
<td>
<a class="add" onclick="cloneBackup({{b.0}})" id="clone-backup{{b.0}}" title="Clone {{b.1}}" style="cursor: pointer;"></a>
</td>
<td>
<a class="delete" onclick="confirmDeleteBackup({{b.0}})" title="Delete backup {{b.1}}" style="cursor: pointer;"></a>
</td>
</tr>
<script>
$( function() {
$("#backup-time-{{ b.0}}" ).selectmenu({
width: 100
});
$("#backup-type-{{b.0}}" ).selectmenu({
width: 130
});
$("#backup-credentials-{{b.0}}" ).selectmenu({
width: 150
});
});
</script>
{% endfor %}

View File

@ -93,6 +93,7 @@
<li><a href="/app/servers.py#servers" title="Server manage" class="runtime head-submenu">Servers</a></li>
<li><a href="/app/servers.py#ssh" title="Manage SSH credentials" class="admin head-submenu">SSH credentials</a></li>
<li><a href="/app/servers.py#installhaproxy" title="Installation HAProxy" class="hap head-submenu">Installation</a> </li>
<li><a href="/app/servers.py#backup" title="Backups HAProxy's config files" class="backup head-submenu">Backups</a> </li>
</ul>
</li>
{% endif %}

View File

@ -46,7 +46,7 @@
</script>
{% endif %}
<div class="div-pannel" id="div-pannel-{{s.0}}">
<div id="div-server-{{s.0}}" class="div-server">
<div id="div-server-{{s.0}}" class="div-server-hapwi">
<div class="server-name">
{% if s.5 != False %}
<span class="serverUp server-status" title="{{s.5.0.2}}"></span>

View File

@ -0,0 +1,53 @@
<tr>
<td class="padding20" style="width: 40%;">
Choose server for backup
<span class="need-field">*</span>
</td>
<td>
<select autofocus required name="backup-server" id="backup-server">
<option disabled>Choose server</option>
{% for s in servers %}}
<option value="{{ s.2 }}">{{ s.1 }}</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
<td class="padding20">
Enter backup server
<span class="need-field">*</span>
</td>
<td>
{{ input('rserver', size='30', placeholder="172.0.0.1", required="required") }}
</td>
</tr>
<tr>
<td class="padding20">
Enter remote folder
<span class="need-field">*</span>
</td>
<td>
{{ input('rpath', size='30', placeholder="/var/backups", required="required") }}
</td>
</tr>
<tr>
<td class="padding20">
Backup type
<span class="need-field">*</span>
</td>
<td>
{% set values = {'backup':'backup','synchronization':'synchronization'} %}
{{ select('backup-type', values=values, selected='backup', required='required', class='force_close') }}
</td>
</tr>
<tr>
<td class="padding20">
Period time
<span class="need-field">*</span>
</td>
<td>
{% set values = {'hourly':'hourly','daily':'daily','weekly':'weekly', 'monthly':'monthly'} %}
{{ select('backup-time', values=values, selected='weekly', required='required', class='force_close') }}
</td>
</tr>

View File

@ -0,0 +1,48 @@
<tr id="backup-table-{{b.0}}">
<td class="padding10 first-collumn">
<span id="backup-server-{{b.0}}">{{ b.1 }}</span>
</td>
<td>
{{ input('backup-rserver-'+b.0|string(), value=b.2, size='14') }}
</td>
<td>
{{ input('backup-rpath-'+b.0|string(), value=b.3) }}
</td>
<td>
{% set values = {'backup':'backup','synchronization':'synchronization'} %}
{{ select('backup-type-'+b.0|string(), values=values, selected=b.4, required='required', class='force_close') }}
</td>
<td>
{% set values = {'hourly':'hourly','daily':'daily','weekly':'weekly', 'monthly':'monthly'} %}
{{ select('backup-time-'+b.0|string(), values=values, selected=b.5, required='required', class='force_close') }}
</td>
<td>
<select id="backup-credentials-{{b.0}}" required>
<option disabled selected>Choose credentials</option>
{% for ssh in sshs %}
{% if ssh.2 == 1 %}
{% if ssh.0 == b.6 %}
<option value="{{ssh.0}}" selected="selected">{{ssh.1}}</option>
{% else %}
<option value="{{ssh.0}}">{{ssh.1}}</option>
{% endif %}
{% endif %}
{% endfor %}
</select>
</td>
<td>
{% if b.7 != 'None' %}
{{ input('backup-description-'+b.0|string(), value=b.7) }}
{% else %}
{{ input('backup-description-'+b.0|string()) }}
{% endif %}
</td>
<td>
<a class="add" onclick="cloneBackup({{b.0}})" id="clone-backup{{b.0}}" title="Clone {{b.1}}" style="cursor: pointer;"></a>
</td>
<td>
<a class="delete" onclick="confirmDeleteBackup({{b.0}})" title="Delete backup {{b.1}}" style="cursor: pointer;"></a>
</td>
</tr>

View File

@ -18,6 +18,7 @@
<li><a href="#ssh">SSH credentials</a></li>
<li><a href="#checker">Checker</a></li>
<li><a href="#installhaproxy">Install HAProxy</a></li>
<li><a href="#backup">Backup</a></li>
{% include 'include/login.html' %}
</ul>
<div id="users">
@ -306,6 +307,35 @@
<div id="ajax"></div>
</div>
<div id="backup">
<table class="overview" id="ajax-backup-table">
<tr class="overviewHead">
<td class="padding10 first-collumn">Servers</td>
<td class="padding10">Remote server</td>
<td class="padding10">Remote folder</td>
<td class="padding10">Backup type</td>
<td class="padding10">Period time</td>
<td class="padding10">Credentials</td>
<td class="padding10">Description</td>
<td></td>
<td></td>
</tr>
{% for b in backups %}
{% for s in servers %}
{% if b.1 in s.2 %}
{% include 'include/admin_backup.html' %}
{% endif %}
{% endfor %}
{% endfor %}
</table>
<br /><span class="add-button" title="Add a new backup job" id="add-backup-button">+ Add a new backup job</span>
<br /><br />
<div id="ajax-backup"></div>
<div class="add-note addName alert-info" style="width: inherit; margin-right: 15px;">
You can read the description of all parameters <a href="https://haproxy-wi.org/description.py?description=backup" title="Backup description" target="_blank">here</a>
</div>
</div>
</div>
<div id="group_error" style="display: none;">
<div class="alert alert-danger">
@ -355,50 +385,10 @@
</table>
<input type="submit" tabindex="-1" style="position:absolute; top:-1000px">
</form>
<div id="backup-add-table" title="Add a new backup job " style="display: none;">
</div>
<div id="backup-add-table" title="Add a new backup job " style="display: none;">
<table class="overview">
<tr>
<td class="padding20" style="width: 40%;">
Choose server for backup
<span class="need-field">*</span>
</td>
<td>
<select autofocus required name="backup-server" id="backup-server">
<option disabled>Choose server</option>
{% for s in servers %}}
<option value="{{ s.2 }}">{{ s.1 }}</option>
{% endfor %}
</select>
</td>
<tr>
<td class="padding20">
Enter backup server
<span class="need-field">*</span>
</td>
<td>
{{ input('rserver', size='30', placeholder="172.0.0.1", required="required") }}
</td>
<tr>
<tr>
<td class="padding20">
Enter remote folder
<span class="need-field">*</span>
</td>
<td>
{{ input('rpath', size='30', placeholder="/var/backups", required="required") }}
</td>
<tr>
<tr>
<td class="padding20">
Period time
<span class="need-field">*</span>
</td>
<td>
{% set values = {'hourly':'hourly','daily':'daily','weekly':'weekly', 'monthly':'monthly'} %}
{{ select('backup-time', values=values, selected='weekly', required='required', class='force_close') }}
</td>
</tr>
</tr>
{% include 'include/add_backup.html' %}
<tr>
<td class="padding20">
Credentials for remote server
@ -424,7 +414,6 @@
</td>
<tr>
</table>
</div>
</div>
{% include 'include/change_pass_form.html' %}
<script>
@ -464,6 +453,11 @@
width: 150
});
{% endfor %}
{% for ssh in sshs %}
$("#sshgroup-{{ ssh.0}}" ).selectmenu({
width: 150
});
{% endfor %}
});
</script>
<style>

View File

@ -92,6 +92,11 @@
font-family: "Font Awesome 5 Solid";
content: "\f074";
}
.backup::before {
display: none;
font-family: "Font Awesome 5 Solid";
content: "\f24d";
}
.ha::before {
display: none;
font-family: "Font Awesome 5 Solid";

View File

@ -722,6 +722,15 @@ $( function() {
});
$( "#tabs" ).tabs( "option", "active", 4 );
} );
$( ".backup" ).on( "click", function() {
$('.menu li ul li').each(function () {
$(this).find('a').css('padding-left', '20px')
$(this).find('a').css('border-left', '0px solid #5D9CEB');
$(this).children(".backup").css('padding-left', '30px');
$(this).children(".backup").css('border-left', '4px solid #5D9CEB');
});
$( "#tabs" ).tabs( "option", "active", 5 );
} );
}
}
$( "#haproxyaddserv" ).on('selectmenuchange',function() {

View File

@ -744,7 +744,7 @@ label {
#up-pannel {
margin-top: 15px;
}
.div-server {
.div-server, .div-server-hapwi {
background-color: #fbfbfb;
border: 1px solid #A4C7F5;
height: 153px;
@ -759,6 +759,9 @@ label {
display: block;
float: left;
}
.div-server {
height: 95px;
}
.div-backends {
width: 89.3%;
}
@ -854,6 +857,9 @@ label {
#logo_span {
margin-left: 17%;
}
#create {
margin-top: 20px;
}
}
@media (max-width: 1900px) {
@ -872,11 +878,15 @@ label {
}
.div-server {
margin-bottom: 30px !important;
width: 43%;
height: 100px;
}
}
@media (max-width: 1280px) {
.div-server {
margin-bottom: 30px !important;
width: 90%;
height: 70px;
}
.ajax-server {
clear: both !important;
@ -885,6 +895,12 @@ label {
.div-backends {
width: 84.6% !important
}
#ssl_name {
width: 100px;
}
.form-control {
width: 120px;
}
}
@media (max-width: 1080px) {
#logo_span {
@ -912,6 +928,9 @@ label {
.div-backends {
width: 84.6% !important
}
#ssl_cert {
width: 60%;
}
}
@media (max-width: 1024px) {
#logo_span {
@ -922,16 +941,9 @@ label {
height: 410px;
width: 95%;
}
.overview-wi {
width: 95%;
max-width: 95%;
}
.wrong-login {
margin-right: -150px;
}
.ajax-server {
width: 88% !important;
}
.haproxy-info {
width: 120px;
padding-left: 10px;
@ -945,6 +957,7 @@ label {
#grep {
width: 100px;
}
}
@media (max-width: 768px) {
#logo_span {
@ -956,10 +969,6 @@ label {
height: 410px;
width: 95%;
}
.overview-wi {
width: 95%;
max-width: 95%;
}
.wrong-login {
margin-right: -260px;
}
@ -969,8 +978,8 @@ label {
.overview h3 {
width: 46.4% !important;
}
.ajax-server {
width: 88% !important;
.div-server {
height: 90px;
}
.haproxy-info {
width: 120px;
@ -996,16 +1005,9 @@ label {
height: 410px;
width: 95%;
}
.overview-wi {
width: 95%;
max-width: 95%;
}
.wrong-login {
margin-right: -210px;
}
.ajax-server {
width: 88% !important;
}
.haproxy-info {
width: 120px;
padding-left: 10px;

View File

@ -85,16 +85,16 @@ $( function() {
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error') != '-1' || data.indexOf('alert') != '-1' || data.indexOf('FAILED') != '-1') {
$("#ajax").html('<div class="alert alert-danger">'+data+'</data>');
$("#ajax").html('<div class="alert alert-danger">'+data+'</div>');
} else if (data.indexOf('info') != '-1' ){
$("#ajax").html('<div class="alert alert-info">'+data+'</data>');
$("#ajax").html('<div class="alert alert-info">'+data+'</div>');
} else if (data.indexOf('success') != '-1' ){
$('.alert-danger').remove();
$("#ajax").html('<div class="alert alert-success">'+data+'</data>');
$("#ajax").html('<div class="alert alert-success">'+data+'</div>');
} else {
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax").html('<div class="alert alert-info">'+data+'</data>');
$("#ajax").html('<div class="alert alert-info">'+data+'</div>');
}
}
} );
@ -129,14 +129,14 @@ $( function() {
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error') != '-1') {
$("#ajax").html('<div class="alert alert-danger">'+data+'</data>');
$("#ajax").html('<div class="alert alert-danger">'+data+'</div>');
} else if (data.indexOf('success') != '-1'){
$('.alert-danger').remove();
$("#ajax").html('<div class="alert alert-success">'+data+'</data>');
$("#ajax").html('<div class="alert alert-success">'+data+'</div>');
} else {
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax").html('<div class="alert alert-info">'+data+'</data>');
$("#ajax").html('<div class="alert alert-info">'+data+'</div>');
}
}
} );
@ -161,19 +161,19 @@ $( function() {
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error') != '-1' || data.indexOf('FAILED') != '-1') {
$("#ajax").html('<div class="alert alert-danger">'+data+'</data>');
$("#ajax").html('<div class="alert alert-danger">'+data+'</div>');
} else if (data.indexOf('success') != '-1' ){
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax").html('<div class="alert alert-success">'+data+'</data>');
$("#ajax").html('<div class="alert alert-success">'+data+'</div>');
} else if (data.indexOf('Info') != '-1' ){
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax").html('<div class="alert alert-info">'+data+'</data>');
$("#ajax").html('<div class="alert alert-info">'+data+'</div>');
} else {
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax").html('<div class="alert alert-info">'+data+'</data>');
$("#ajax").html('<div class="alert alert-info">'+data+'</div>');
}
}
} );
@ -191,47 +191,47 @@ $( function() {
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error') != '-1' || data.indexOf('Failed') != '-1') {
$("#ajax").html('<div class="alert alert-danger">'+data+'</data>');
$("#ajax").html('<div class="alert alert-danger">'+data+'</div>');
} else if (data.indexOf('Complete!') != '-1'){
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax-update").html('<div class="alert alert-success">Update was success!</data>');
$("#ajax-update").html('<div class="alert alert-success">Update was success!</div>');
} else if (data.indexOf('Unauthorized') != '-1') {
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax-update").html('<div class="alert alert-danger">It is seems like you Unauthorized in the HAProxy-WI repository. How to get HAProxy-WI auth you can read <a href="https://haproxy-wi.org/installation.py" title="How to get HAProxy-WI auth">hear</a> </data>');
$("#ajax-update").html('<div class="alert alert-danger">It is seems like you Unauthorized in the HAProxy-WI repository. How to get HAProxy-WI auth you can read <a href="https://haproxy-wi.org/installation.py" title="How to get HAProxy-WI auth">hear</a> </div>');
} else if (data.indexOf('but not installed') != '-1') {
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax-update").html('<div class="alert alert-warning">You have settings for HAProxy-WI repository, but installed HAProxy-WI without repository. Please reinstall with yum or use update.sh</data>');
$("#ajax-update").html('<div class="alert alert-warning">You have settings for HAProxy-WI repository, but installed HAProxy-WI without repository. Please reinstall with yum or use update.sh</div>');
} else if (data.indexOf('No Match for argument') != '-1') {
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax-update").html('<div class="alert alert-warning">It is seems like you do not have HAProxy-WI repository settings. Please read docs for<a href="https://haproxy-wi.org/updates.py">detail</a></data>');
$("#ajax-update").html('<div class="alert alert-warning">It is seems like you do not have HAProxy-WI repository settings. Please read docs for<a href="https://haproxy-wi.org/updates.py">detail</a></div>');
} else if (data.indexOf('password for') != '-1') {
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax-update").html('<div class="alert alert-warning">It is seems like you need add Apache user to sudoers. Please read docs for<a href="https://haproxy-wi.org/updates.py">detail</a></data>');
$("#ajax-update").html('<div class="alert alert-warning">It is seems like you need add Apache user to sudoers. Please read docs for<a href="https://haproxy-wi.org/updates.py">detail</a></div>');
} else if (data.indexOf('No packages marked for update') != '-1') {
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax-update").html('<div class="alert alert-info">It is seems like you have the lastest version HAProxy-WI</data>');
$("#ajax-update").html('<div class="alert alert-info">It is seems like you have the lastest version HAProxy-WI</div>');
} else if (data.indexOf('Connection timed out') != '-1') {
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax-update").html('<div class="alert alert-danger">Cannot connect to HAProxy-WI repository. Connection timed out</data>');
$("#ajax-update").html('<div class="alert alert-danger">Cannot connect to HAProxy-WI repository. Connection timed out</div>');
} else if (data.indexOf('--disable') != '-1') {
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax-update").html('<div class="alert alert-danger">It is seems like you have problem with your repositorys.</data>');
$("#ajax-update").html('<div class="alert alert-danger">It is seems like you have problem with your repositorys.</div>');
} else if (data.indexOf('Unauthorized') != '-1') {
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax-update").html('<div class="alert alert-danger">It is seems like you Unauthorized in the HAProxy-WI repository.</data>');
$("#ajax-update").html('<div class="alert alert-danger">It is seems like you Unauthorized in the HAProxy-WI repository.</div>');
} else if (data.indexOf('Error: Package') != '-1') {
$('.alert-danger').remove();
$('.alert-warning').remove();
$("#ajax-update").html('<div class="alert alert-danger">'+data+'</data>');
$("#ajax-update").html('<div class="alert alert-danger">'+data+'</div>');
}
}
} );
@ -421,6 +421,34 @@ $( function() {
$('#telegram-add-table').show("blind", "fast");
}
});
var addBackupDialog = $( "#backup-add-table" ).dialog({
autoOpen: false,
resizable: false,
height: "auto",
width: 600,
modal: true,
title: "Create a new backup job",
show: {
effect: "fade",
duration: 200
},
hide: {
effect: "fade",
duration: 200
},
buttons: {
"Add": function() {
addBackup();
},
Cancel: function() {
$( this ).dialog( "close" );
clearTips();
}
}
});
$('#add-backup-button').click(function() {
addBackupDialog.dialog('open');
});
$( "#ajax-users input" ).change(function() {
var id = $(this).attr('id').split('-');
updateUser(id[1])
@ -476,6 +504,14 @@ $( function() {
var id = $(this).attr('id').split('-');
updateTelegram(id[1])
});
$( "#ajax-backup-table input" ).change(function() {
var id = $(this).attr('id').split('-');
updateBackup(id[2])
});
$( "#ajax-backup-table select" ).on('selectmenuchange',function() {
var id = $(this).attr('id').split('-');
updateBackup(id[2])
});
$('#search_ldap_user').click(function() {
var valid = true;
$('#error').remove();
@ -658,6 +694,58 @@ function addServer() {
$( "#server-add-table" ).dialog("close" );
}
}
function addBackup() {
var valid = true;
$('#error').remove();
allFields = $( [] ).add( $('#backup-server') ).add( $('#rserver') ).add( $('#rpath') ).add( $('#backup-time') ).add( $('#backup-credentials') )
allFields.removeClass( "ui-state-error" );
valid = valid && checkLength( $('#backup-server'), "backup server ", 1 );
valid = valid && checkLength( $('#rserver'), "remote server", 1 );
valid = valid && checkLength( $('#rpath'), "remote path", 1 );
valid = valid && checkLength( $('#backup-time'), "backup time", 1 );
valid = valid && checkLength( $('#backup-credentials'), "backup credentials", 1 );
if (valid) {
$.ajax( {
url: "options.py",
data: {
backup: '1',
server: $('#backup-server').val(),
rserver: $('#rserver').val(),
rpath: $('#rpath').val(),
type: $('#backup-type').val(),
time: $('#backup-time').val(),
cred: $('#backup-credentials').val(),
description: $('#backup-description').val(),
token: $('#token').val()
},
type: "POST",
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error') != '-1') {
$("#ajax-backup").html('<div class="alert alert-danger" style="width: 50%;">'+data+'</div><br /><br />');
$('#errorMess').click(function() {
$('#error').remove();
$('.alert-danger').remove();
});
} else if (data.indexOf('success') != '-1') {
$('.alert-danger').remove();
$("#ajax-backup-table").append(data);
$(".newbackup").addClass( "update", 1000 );
setTimeout(function() {
$( ".newbackup" ).removeClass( "update" );
}, 2500 );
$( "select" ).selectmenu();
$.getScript(awesome);
} else if (data.indexOf('info') != '-1') {
$('.alert-danger').remove();
$("#ajax-backup").html('<div class="alert alert-info">'+data+'</div><br />');
}
}
} );
clearTips();
$( "#backup-add-table" ).dialog("close" );
}
}
function updateSettings(param, val) {
$('.alert-danger').remove();
$.ajax( {
@ -791,6 +879,24 @@ function confirmDeleteTelegram(id) {
}
});
}
function confirmDeleteBackup(id) {
$( "#dialog-confirm" ).dialog({
resizable: false,
height: "auto",
width: 400,
modal: true,
title: "Are you sure you want to delete job for" +$('#backup-server-'+id).val() + "?",
buttons: {
"Delete": function() {
$( this ).dialog( "close" );
removeBackup(id);
},
Cancel: function() {
$( this ).dialog( "close" );
}
}
});
}
function cloneServer(id) {
$( "#add-server-button" ).trigger( "click" );
if ($('#enable-'+id).is(':checked')) {
@ -857,6 +963,17 @@ function cloneTelegram(id) {
$('#telegram-token-add').val($('#telegram-token-'+id).val())
$('#telegram-chanel-add').val($('#telegram-chanel-'+id).val())
}
function cloneBackup(id) {
$( "#add-backup-button" ).trigger( "click" );
$('#rserver').val($('#backup-rserver-'+id).val())
$('#rpath').val($('#backup-rpath-'+id).val())
$('#backup-type').val($('#backup-type-'+id+' option:selected').val()).change()
$('#backup-type').selectmenu("refresh");
$('#backup-time').val($('#backup-time-'+id+' option:selected').val()).change()
$('#backup-time').selectmenu("refresh");
$('#backup-credentials').val($('#backup-credentials-'+id+' option:selected').val()).change()
$('#backup-credentials').selectmenu("refresh");
}
function removeUser(id) {
$("#user-"+id).css("background-color", "#f2dede");
$.ajax( {
@ -946,6 +1063,26 @@ function removeTelegram(id) {
}
} );
}
function removeBackup(id) {
$("#backup-table-"+id).css("background-color", "#f2dede");
$.ajax( {
url: "options.py",
data: {
deljob: id,
cred: $('#backup-credentials-'+id).val(),
server: $('#backup-server-'+id).text(),
rserver: $('#backup-rserver-'+id).val(),
token: $('#token').val()
},
type: "POST",
success: function( data ) {
data = data.replace(/\s+/g,' ');
if(data.indexOf('Ok') != '-1') {
$("#backup-table-"+id).remove();
}
}
} );
}
function updateUser(id) {
$('.alert-danger').remove();
cur_url[0] = cur_url[0].split('#')[0]
@ -1181,6 +1318,49 @@ function updateTelegram(id) {
}
} );
}
function updateBackup(id) {
$('#error').remove();
if ($( "#backup-type-"+id+" option:selected" ).val() == "Choose server" || $('#backup-rserver-'+id).val() == '' || $('#backup-rpath-'+id).val() == '') {
$("#ajax-backup").html('<div class="alert alert-danger" style="margin: 10px;">All fields must be completed</div>');
} else {
console.log($('#backup-credentials-'+id).val())
console.log($('#backup-rpath-'+id).val())
console.log($('#backup-type-'+id).val())
console.log($('#backup-server-'+id).text())
console.log($('#backup-rserver-'+id).val())
$.ajax( {
url: "options.py",
data: {
backupupdate: id,
server: $('#backup-server-'+id).text(),
rserver: $('#backup-rserver-'+id).val(),
rpath: $('#backup-rpath-'+id).val(),
type: $('#backup-type-'+id).val(),
time: $('#backup-time-'+id).val(),
cred: $('#backup-credentials-'+id).val(),
description: $('#backup-description-'+id).val(),
token: $('#token').val()
},
type: "POST",
success: function( data ) {
data = data.replace(/\s+/g,' ');
if (data.indexOf('error') != '-1') {
$("#ajax-backup").html('<div class="alert alert-danger" style="margin: 10px;">'+data+'</div>');
$('#errorMess').click(function() {
$('#error').remove();
$('.alert-danger').remove();
});
} else {
$('.alert-danger').remove();
$("#backup-table-"+id).addClass( "update", 1000 );
setTimeout(function() {
$( "#backup-table-"+id ).removeClass( "update" );
}, 2500 );
}
}
} );
}
}
function showApacheLog(serv) {
var rows = $('#rows').val()
var grep = $('#grep').val()