mirror of https://github.com/Aidaho12/haproxy-wi
v8.2: Rework backup handling to use server_id instead of server
Refactored code to use `server_id` in place of `server` across various modules to improve clarity and consistency. Updated database migrations, schema definitions, API documentation, and templates accordingly. Additionally, fixed related issues in the backup creation and management logic.pull/399/head
parent
ddaa3bf2dd
commit
bf242a8eb2
|
@ -622,6 +622,33 @@ def update_db_v_8_0_2_1():
|
|||
print("Updating... DB has been updated to version 8.0.2-1")
|
||||
|
||||
|
||||
def update_db_v_8_1():
|
||||
try:
|
||||
migrate(
|
||||
migrator.rename_column('backups', 'server', 'server_id')
|
||||
)
|
||||
except Exception as e:
|
||||
if e.args[0] == 'no such column: "server"' or str(e) == '(1060, no such column: "server")':
|
||||
print("Updating... DB has been updated to version 8.2")
|
||||
elif e.args[0] == "'bool' object has no attribute 'sql'":
|
||||
print("Updating... DB has been updated to version 8.2")
|
||||
else:
|
||||
print("An error occurred:", e)
|
||||
|
||||
def update_db_v_8_1_0_1():
|
||||
try:
|
||||
migrate(
|
||||
migrator.rename_column('s3_backups', 'server', 'server_id')
|
||||
)
|
||||
except Exception as e:
|
||||
if e.args[0] == 'no such column: "server"' or str(e) == '(1060, no such column: "server")':
|
||||
print("Updating... DB has been updated to version 8.2")
|
||||
elif e.args[0] == "'bool' object has no attribute 'sql'":
|
||||
print("Updating... DB has been updated to version 8.2")
|
||||
else:
|
||||
print("An error occurred:", e)
|
||||
|
||||
|
||||
def update_ver():
|
||||
try:
|
||||
Version.update(version='8.1.0').execute()
|
||||
|
@ -650,4 +677,6 @@ def update_all():
|
|||
update_db_v_8()
|
||||
update_db_v_8_0_2()
|
||||
update_db_v_8_0_2_1()
|
||||
update_db_v_8_1()
|
||||
update_db_v_8_1_0_1()
|
||||
update_ver()
|
||||
|
|
|
@ -2,11 +2,17 @@ from app.modules.db.db_model import Backup, S3Backup, GitSetting
|
|||
from app.modules.db.common import out_error
|
||||
from app.modules.roxywi.exception import RoxywiResourceNotFound
|
||||
|
||||
models = {
|
||||
'fs': Backup,
|
||||
's3': S3Backup,
|
||||
'git': GitSetting,
|
||||
}
|
||||
|
||||
def insert_backup_job(server, rserver, rpath, backup_type, time, cred, description):
|
||||
|
||||
def insert_backup_job(server_id, rserver, rpath, backup_type, time, cred, description):
|
||||
try:
|
||||
return Backup.insert(
|
||||
server=server, rhost=rserver, rpath=rpath, type=backup_type, time=time,
|
||||
server_id=server_id, rhost=rserver, rpath=rpath, type=backup_type, time=time,
|
||||
cred_id=cred, description=description
|
||||
).execute()
|
||||
except Exception as e:
|
||||
|
@ -20,9 +26,17 @@ def insert_s3_backup_job(**kwargs):
|
|||
out_error(e)
|
||||
|
||||
|
||||
def update_backup(server, rserver, rpath, backup_type, time, cred, description, backup_id):
|
||||
def update_s3_backup_job(backup_id: int, model: str, **kwargs):
|
||||
model = models[model]
|
||||
try:
|
||||
return model.update(**kwargs).where(model.id == backup_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def update_backup(server_id, rserver, rpath, backup_type, time, cred, description, backup_id):
|
||||
backup_update = Backup.update(
|
||||
server=server, rhost=rserver, rpath=rpath, type=backup_type, time=time,
|
||||
server_id=server_id, rhost=rserver, rpath=rpath, type=backup_type, time=time,
|
||||
cred_id=cred, description=description
|
||||
).where(Backup.id == backup_id)
|
||||
try:
|
||||
|
@ -31,23 +45,14 @@ def update_backup(server, rserver, rpath, backup_type, time, cred, description,
|
|||
out_error(e)
|
||||
|
||||
|
||||
def delete_backups(backup_id: int) -> None:
|
||||
def delete_backup(backup_id: int, model: str) -> None:
|
||||
model = models[model]
|
||||
try:
|
||||
Backup.delete().where(Backup.id == backup_id).execute()
|
||||
model.delete().where(model.id == backup_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def delete_s3_backups(backup_id: int) -> bool:
|
||||
try:
|
||||
S3Backup.delete().where(S3Backup.id == backup_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def insert_new_git(server_id, service_id, repo, branch, period, cred, description) -> int:
|
||||
try:
|
||||
return GitSetting.insert(
|
||||
|
@ -58,13 +63,6 @@ def insert_new_git(server_id, service_id, repo, branch, period, cred, descriptio
|
|||
out_error(e)
|
||||
|
||||
|
||||
def delete_git(git_id: int) -> None:
|
||||
try:
|
||||
GitSetting.delete().where(GitSetting.id == git_id).execute()
|
||||
except Exception as e:
|
||||
out_error(e)
|
||||
|
||||
|
||||
def select_gits(**kwargs):
|
||||
if kwargs.get("server_id") is not None and kwargs.get("service_id") is not None:
|
||||
query = GitSetting.select().where(
|
||||
|
@ -81,8 +79,8 @@ def select_gits(**kwargs):
|
|||
|
||||
|
||||
def select_backups(**kwargs):
|
||||
if kwargs.get("server") is not None and kwargs.get("rserver") is not None:
|
||||
query = Backup.select().where((Backup.server == kwargs.get("server")) & (Backup.rhost == kwargs.get("rserver")))
|
||||
if kwargs.get("backup_id") is not None:
|
||||
query = Backup.select().where(Backup.id == kwargs.get("backup_id"))
|
||||
else:
|
||||
query = Backup.select().order_by(Backup.id)
|
||||
|
||||
|
@ -110,21 +108,10 @@ def select_s3_backups(**kwargs):
|
|||
return query_res
|
||||
|
||||
|
||||
def check_exists_backup(server: str) -> bool:
|
||||
def check_exists_backup(server_id: int, model: str) -> bool:
|
||||
model = models[model]
|
||||
try:
|
||||
backup = Backup.get(Backup.server == server)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
if backup.id is not None:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def check_exists_s3_backup(server: str) -> bool:
|
||||
try:
|
||||
backup = S3Backup.get(S3Backup.server == server)
|
||||
backup = model.get(model.server_id == server_id)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
|
@ -135,11 +122,6 @@ def check_exists_s3_backup(server: str) -> bool:
|
|||
|
||||
|
||||
def get_backup(backup_id: int, model: str) -> Backup:
|
||||
models = {
|
||||
'fs': Backup,
|
||||
's3': S3Backup,
|
||||
'git': GitSetting,
|
||||
}
|
||||
model = models[model]
|
||||
try:
|
||||
return model.get(model.id == backup_id)
|
||||
|
|
|
@ -210,7 +210,7 @@ class Cred(BaseModel):
|
|||
|
||||
class Backup(BaseModel):
|
||||
id = AutoField()
|
||||
server = CharField()
|
||||
server_id = CharField()
|
||||
rhost = CharField()
|
||||
rpath = CharField()
|
||||
type = CharField(column_name='type')
|
||||
|
@ -224,7 +224,7 @@ class Backup(BaseModel):
|
|||
|
||||
class S3Backup(BaseModel):
|
||||
id = AutoField()
|
||||
server = CharField()
|
||||
server_id = CharField()
|
||||
s3_server = CharField()
|
||||
bucket = CharField()
|
||||
secret_key = CharField()
|
||||
|
|
|
@ -4,7 +4,7 @@ from typing import Optional, Annotated, Union, Literal, Any, Dict, List
|
|||
|
||||
from shlex import quote
|
||||
from pydantic_core import CoreSchema, core_schema
|
||||
from pydantic import BaseModel, Base64Str, StringConstraints, IPvAnyAddress, GetCoreSchemaHandler
|
||||
from pydantic import BaseModel, Base64Str, StringConstraints, IPvAnyAddress, GetCoreSchemaHandler, AnyUrl
|
||||
|
||||
DomainName = Annotated[str, StringConstraints(pattern=r"^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z0-9-]{0,61}[a-z0-9]$")]
|
||||
|
||||
|
@ -251,21 +251,21 @@ class SettingsRequest(BaseModel):
|
|||
|
||||
class BackupRequest(BaseModel):
|
||||
cred_id: int
|
||||
server: Union[IPvAnyAddress, DomainName]
|
||||
server_id: int
|
||||
rserver: Optional[Union[IPvAnyAddress, DomainName]] = None
|
||||
description: Optional[EscapedString] = None
|
||||
rpath: Optional[EscapedString] = None
|
||||
type: Optional[EscapedString] = None
|
||||
time: Optional[EscapedString] = None
|
||||
type: Literal['backup', 'synchronization'] = None
|
||||
time: Literal['hourly', 'daily', 'weekly', 'monthly'] = None
|
||||
|
||||
|
||||
class S3BackupRequest(BaseModel):
|
||||
server: Union[IPvAnyAddress, DomainName]
|
||||
s3_server: Optional[Union[IPvAnyAddress, DomainName]] = None
|
||||
server_id: int
|
||||
s3_server: Optional[Union[IPvAnyAddress, AnyUrl]] = None
|
||||
bucket: EscapedString
|
||||
secret_key: Optional[EscapedString] = None
|
||||
access_key: Optional[EscapedString] = None
|
||||
time: Optional[EscapedString] = None
|
||||
time: Literal['hourly', 'daily', 'weekly', 'monthly'] = None
|
||||
description: Optional[EscapedString] = None
|
||||
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import app.modules.db.ha_cluster as ha_sql
|
|||
import app.modules.roxy_wi_tools as roxy_wi_tools
|
||||
from app.modules.roxywi.class_models import ErrorResponse
|
||||
from app.modules.roxywi.exception import RoxywiResourceNotFound, RoxywiGroupMismatch, RoxywiGroupNotFound, \
|
||||
RoxywiPermissionError
|
||||
RoxywiPermissionError, RoxywiConflictError
|
||||
|
||||
get_config_var = roxy_wi_tools.GetConfigVar()
|
||||
|
||||
|
@ -337,5 +337,7 @@ def handler_exceptions_for_json_data(ex: Exception, main_ex_mes: str) -> tuple[d
|
|||
return handle_json_exceptions(ex, 'Resource not found in group'), 404
|
||||
elif isinstance(ex, RoxywiPermissionError):
|
||||
return handle_json_exceptions(ex, 'You cannot edit this resource'), 403
|
||||
elif isinstance(ex, RoxywiConflictError):
|
||||
return handle_json_exceptions(ex, 'Conflict'), 429
|
||||
else:
|
||||
return handle_json_exceptions(ex, main_ex_mes), 500
|
||||
|
|
|
@ -19,10 +19,10 @@ error_mess = common.error_mess
|
|||
get_config = roxy_wi_tools.GetConfigVar()
|
||||
|
||||
|
||||
def return_ssh_keys_path(server_ip: str, **kwargs) -> dict:
|
||||
def return_ssh_keys_path(server_ip: str, cred_id: int = None) -> dict:
|
||||
ssh_settings = {}
|
||||
if kwargs.get('id'):
|
||||
sshs = cred_sql.select_ssh(id=kwargs.get('id'))
|
||||
if cred_id:
|
||||
sshs = cred_sql.select_ssh(id=cred_id)
|
||||
else:
|
||||
sshs = cred_sql.select_ssh(serv=server_ip)
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from docutils.parsers.rst.directives import body
|
||||
from flask import render_template
|
||||
|
||||
import app.modules.db.sql as sql
|
||||
|
@ -10,15 +9,17 @@ import app.modules.server.ssh as ssh_mod
|
|||
import app.modules.roxywi.common as roxywi_common
|
||||
import app.modules.service.installation as installation_mod
|
||||
from app.modules.roxywi.class_models import BackupRequest, IdResponse, IdDataResponse, BaseResponse, S3BackupRequest, GitBackupRequest
|
||||
from app.modules.roxywi.exception import RoxywiConflictError
|
||||
|
||||
|
||||
def create_backup_inv(json_data: BackupRequest, del_id: int = 0) -> None:
|
||||
ssh_settings = ssh_mod.return_ssh_keys_path(str(json_data.server), id=json_data.cred_id)
|
||||
server = server_sql.get_server_by_id(json_data.server_id)
|
||||
ssh_settings = ssh_mod.return_ssh_keys_path(server.ip, json_data.cred_id)
|
||||
inv = {"server": {"hosts": {}}}
|
||||
server_ips = []
|
||||
inv['server']['hosts'][str(json_data.server)] = {
|
||||
inv['server']['hosts'][server.ip] = {
|
||||
'HOST': str(json_data.rserver),
|
||||
"SERVER": str(json_data.server),
|
||||
"SERVER": server.ip,
|
||||
"TYPE": json_data.type,
|
||||
"TIME": json_data.time,
|
||||
"RPATH": json_data.rpath,
|
||||
|
@ -26,7 +27,7 @@ def create_backup_inv(json_data: BackupRequest, del_id: int = 0) -> None:
|
|||
"USER": ssh_settings['user'],
|
||||
"KEY": ssh_settings['key']
|
||||
}
|
||||
server_ips.append(str(json_data.server))
|
||||
server_ips.append(str(server.ip))
|
||||
|
||||
try:
|
||||
installation_mod.run_ansible(inv, server_ips, 'backup')
|
||||
|
@ -35,9 +36,10 @@ def create_backup_inv(json_data: BackupRequest, del_id: int = 0) -> None:
|
|||
|
||||
|
||||
def create_s3_backup_inv(data: S3BackupRequest, tag: str) -> None:
|
||||
server = server_sql.get_server_by_id(data.server_id)
|
||||
inv = {"server": {"hosts": {}}}
|
||||
inv["server"]["hosts"]["localhost"] = {
|
||||
"SERVER": str(data.server),
|
||||
"SERVER": server.hostname,
|
||||
"S3_SERVER": str(data.s3_server),
|
||||
"BUCKET": data.bucket,
|
||||
"SECRET_KEY": data.secret_key,
|
||||
|
@ -54,7 +56,7 @@ def create_s3_backup_inv(data: S3BackupRequest, tag: str) -> None:
|
|||
|
||||
def create_git_backup_inv(data: GitBackupRequest, server_ip: str, service: str, del_job: int = 0) -> None:
|
||||
service_config_dir = sql.get_setting(service + '_dir')
|
||||
ssh_settings = ssh_mod.return_ssh_keys_path(server_ip, id=data.cred_id)
|
||||
ssh_settings = ssh_mod.return_ssh_keys_path(server_ip, data.cred_id)
|
||||
inv = {"server": {"hosts": {}}}
|
||||
inv["server"]["hosts"][server_ip] = {
|
||||
"REPO": data.repo,
|
||||
|
@ -74,43 +76,44 @@ def create_git_backup_inv(data: GitBackupRequest, server_ip: str, service: str,
|
|||
|
||||
|
||||
def create_backup(json_data: BackupRequest, is_api: bool) -> tuple:
|
||||
if backup_sql.check_exists_backup(json_data.server):
|
||||
raise Exception(f'warning: Backup job for {json_data.server} already exists')
|
||||
if backup_sql.check_exists_backup(json_data.server_id, 'fs'):
|
||||
raise RoxywiConflictError('FS backup for this server already exists')
|
||||
|
||||
create_backup_inv(json_data)
|
||||
|
||||
last_id = backup_sql.insert_backup_job(json_data.server, json_data.rserver, json_data.rpath, json_data.type,
|
||||
last_id = backup_sql.insert_backup_job(json_data.server_id, json_data.rserver, json_data.rpath, json_data.type,
|
||||
json_data.time, json_data.cred_id, json_data.description)
|
||||
roxywi_common.logging('backup ', f' a new backup job for server {json_data.server} has been created', roxywi=1, login=1)
|
||||
roxywi_common.logging('backup ', f'A new backup job for server {json_data.server_id} has been created', roxywi=1, login=1)
|
||||
if is_api:
|
||||
return IdResponse(id=last_id).model_dump(mode='json'), 201
|
||||
else:
|
||||
data = render_template(
|
||||
'ajax/new_backup.html',
|
||||
backups=backup_sql.select_backups(server=json_data.server, rserver=json_data.rserver),
|
||||
sshs=cred_sql.select_ssh()
|
||||
backups=backup_sql.select_backups(backup_id=last_id),
|
||||
sshs=cred_sql.select_ssh(),
|
||||
servers=roxywi_common.get_dick_permit(virt=1, disable=0, only_group=1),
|
||||
)
|
||||
return IdDataResponse(data=data, id=last_id).model_dump(mode='json'), 201
|
||||
|
||||
|
||||
def delete_backup(json_data: BackupRequest, backup_id: int) -> tuple:
|
||||
create_backup_inv(json_data, backup_id)
|
||||
backup_sql.delete_backups(backup_id)
|
||||
roxywi_common.logging('backup ', f' a backup job for server {json_data.server} has been deleted', roxywi=1, login=1)
|
||||
create_backup_inv(json_data, 1)
|
||||
backup_sql.delete_backup(backup_id, 'fs')
|
||||
roxywi_common.logging('backup ', f'A backup job for server {json_data.server_id} has been deleted', roxywi=1, login=1)
|
||||
return BaseResponse().model_dump(mode='json'), 204
|
||||
|
||||
|
||||
def update_backup(json_data: BackupRequest, backup_id: int) -> tuple:
|
||||
create_backup_inv(json_data)
|
||||
backup_sql.update_backup(json_data.server, json_data.rserver, json_data.rpath, json_data.type,
|
||||
backup_sql.update_backup(json_data.server_id, json_data.rserver, json_data.rpath, json_data.type,
|
||||
json_data.time, json_data.cred_id, json_data.description, backup_id)
|
||||
roxywi_common.logging('backup ', f' a backup job for server {json_data.server} has been updated', roxywi=1, login=1)
|
||||
roxywi_common.logging('backup ', f'A backup job for server {json_data.server_id} has been updated', roxywi=1, login=1)
|
||||
return BaseResponse().model_dump(mode='json'), 201
|
||||
|
||||
|
||||
def create_s3_backup(data: S3BackupRequest, is_api: bool) -> tuple:
|
||||
if backup_sql.check_exists_s3_backup(data.server):
|
||||
raise Exception(f'Backup job for {data.server} already exists')
|
||||
if backup_sql.check_exists_backup(data.server_id, 's3'):
|
||||
raise RoxywiConflictError('S3 backup for this server already exists')
|
||||
|
||||
try:
|
||||
create_s3_backup_inv(data, 'add')
|
||||
|
@ -119,7 +122,7 @@ def create_s3_backup(data: S3BackupRequest, is_api: bool) -> tuple:
|
|||
|
||||
try:
|
||||
last_id = backup_sql.insert_s3_backup_job(**data.model_dump(mode='json'))
|
||||
roxywi_common.logging('backup ', f'a new S3 backup job for server {data.server} has been created', roxywi=1, login=1)
|
||||
roxywi_common.logging('backup ', f'A new S3 backup job for server {data.server_id} has been created', roxywi=1, login=1)
|
||||
except Exception as e:
|
||||
raise Exception(e)
|
||||
|
||||
|
@ -133,8 +136,8 @@ def create_s3_backup(data: S3BackupRequest, is_api: bool) -> tuple:
|
|||
def delete_s3_backup(data: S3BackupRequest, backup_id: int) -> None:
|
||||
try:
|
||||
create_s3_backup_inv(data, 'delete')
|
||||
backup_sql.delete_s3_backups(backup_id)
|
||||
roxywi_common.logging('backup ', f'a S3 backup job for server {data.server} has been deleted', roxywi=1, login=1)
|
||||
backup_sql.delete_backup(backup_id, 's3')
|
||||
roxywi_common.logging('backup ', f'The S3 backup job for server {data.server_id} has been deleted', roxywi=1, login=1)
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
|
@ -180,7 +183,7 @@ def delete_git_backup(data: GitBackupRequest, backup_id: int) -> tuple:
|
|||
raise Exception(e)
|
||||
|
||||
try:
|
||||
backup_sql.delete_git(backup_id)
|
||||
backup_sql.delete_backup(backup_id, 'git')
|
||||
except Exception as e:
|
||||
raise Exception(e)
|
||||
|
||||
|
|
|
@ -8,19 +8,15 @@
|
|||
path: "{{ RPATH }}/roxy-wi-configs-backup/configs"
|
||||
state: directory
|
||||
owner: "{{ ansible_user }}"
|
||||
when: not DELJOB
|
||||
|
||||
- hosts: localhost
|
||||
become: yes
|
||||
become_method: sudo
|
||||
gather_facts: no
|
||||
tasks:
|
||||
when: not DELJOB and ansible_host != "localhost"
|
||||
- name: Creates backup jobs
|
||||
cron:
|
||||
name: "Roxy-WI Backup configs for server {{ SERVER }} {{ item }}"
|
||||
special_time: "{{ TIME }}"
|
||||
job: "rsync -arv {{ TYPE }} /var/lib/roxy-wi/configs/{{ item }}/{{ SERVER }}* {{ ansible_user }}@{{ HOST }}:{{ RPATH }}/roxy-wi-configs-backup/configs/{{ item }} -e 'ssh -i {{ KEY }} -o StrictHostKeyChecking=no' --log-file=/var/www/haproxy-wi/log/backup.log"
|
||||
job: "rsync -arv {{ TYPE }} /var/lib/roxy-wi/configs/{{ item }}/{{ SERVER }}* {{ USER }}@{{ HOST }}:{{ RPATH }}/roxy-wi-configs-backup/configs/{{ item }} -e 'ssh -i {{ KEY }} -o StrictHostKeyChecking=no' --log-file=/var/www/haproxy-wi/log/backup.log"
|
||||
when: not DELJOB
|
||||
delegate_to: localhost
|
||||
with_items:
|
||||
- kp_config
|
||||
- hap_config
|
||||
|
@ -32,6 +28,7 @@
|
|||
name: "Roxy-WI Backup configs for server {{ SERVER }} {{ item }}"
|
||||
state: absent
|
||||
when: DELJOB
|
||||
delegate_to: localhost
|
||||
with_items:
|
||||
- kp_config
|
||||
- hap_config
|
||||
|
|
|
@ -139,7 +139,7 @@ function addBackup(dialog_id) {
|
|||
valid = valid && checkLength($('#backup-credentials'), "backup credentials", 1);
|
||||
if (valid) {
|
||||
let jsonData = {
|
||||
"server": $('#backup-server').val(),
|
||||
"server_id": $('#backup-server').val(),
|
||||
"rserver": $('#rserver').val(),
|
||||
"rpath": $('#rpath').val(),
|
||||
"type": $('#backup-type').val(),
|
||||
|
@ -175,8 +175,8 @@ function addS3Backup(dialog_id) {
|
|||
valid = valid && checkLength($('#s3_access_key'), "S3 access key", 1);
|
||||
if (valid) {
|
||||
let json_data = {
|
||||
"s3_server": $('#s3-backup-server').val(),
|
||||
"server": $('#s3_server').val(),
|
||||
"s3_server": $('#s3_server').val(),
|
||||
"server_id": $('#s3-backup-server').val(),
|
||||
"bucket": $('#s3_bucket').val(),
|
||||
"secret_key": $('#s3_secret_key').val(),
|
||||
"access_key": $('#s3_access_key').val(),
|
||||
|
@ -332,7 +332,7 @@ function removeBackup(id) {
|
|||
$("#backup-table-" + id).css("background-color", "#f2dede");
|
||||
let jsonData = {
|
||||
"cred_id": $('#backup-credentials-' + id).val(),
|
||||
"server": $('#backup-server-' + id).text(),
|
||||
"server_id": $('#backup-server-id-' + id).val(),
|
||||
}
|
||||
$.ajax({
|
||||
url: api_prefix + "/server/backup/fs/" + id,
|
||||
|
@ -360,7 +360,7 @@ function removeS3Backup(id) {
|
|||
$("#backup-table-s3-" + id).css("background-color", "#f2dede");
|
||||
let jsonData = {
|
||||
"bucket": $('#bucket-' + id).text(),
|
||||
"server": $('#backup-s3-server-' + id).text(),
|
||||
"server_id": $('#backup-s3-server-' + id).text(),
|
||||
}
|
||||
$.ajax({
|
||||
url: api_prefix + "/server/backup/s3/" + id,
|
||||
|
@ -419,7 +419,7 @@ function updateBackup(id) {
|
|||
toastr.error('All fields must be completed');
|
||||
} else {
|
||||
let jsonData = {
|
||||
"server": $('#backup-server-' + id).text(),
|
||||
"server_id": $('#backup-server-id-' + id).val(),
|
||||
"rserver": $('#backup-rserver-' + id).val(),
|
||||
"rpath": $('#backup-rpath-' + id).val(),
|
||||
"type": $('#backup-type-' + id).val(),
|
||||
|
|
|
@ -1,77 +1,54 @@
|
|||
{% for b in backups %}
|
||||
<tr class="newbackup" id="backup-table-{{b.id}}">
|
||||
<td class="padding10 first-collumn">
|
||||
<span id="backup-server-{{b.id}}">{{ b.server }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="backup-rserver-{{b.id}}" value="{{b.rhost}}" size="14" class="form-control">
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="backup-rpath-{{b.id}}" value="{{b.rpath}}" class="form-control">
|
||||
</td>
|
||||
<td>
|
||||
{% set values = {'backup':'backup','synchronization':'synchronization'} %}
|
||||
<select name="backup-type-{{b.id}}" id="backup-type-{{b.id}}" class="force_close">
|
||||
{% for v, des in values|dictsort(false, 'value') %}
|
||||
{% if v == b.backup_type %}
|
||||
<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.id}}" id="backup-time-{{b.id}}" class="force_close">
|
||||
{% for v, des in values|dictsort(false, 'value') %}
|
||||
{% if v == b.time %}
|
||||
<option value="{{v}}" selected>{{des}}</option>
|
||||
{% else %}
|
||||
<option value="{{v}}">{{des}}</option>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<select id="backup-credentials-{{b.id}}" required>
|
||||
<option disabled selected>Choose credentials</option>
|
||||
{% for ssh in sshs %}
|
||||
{% if ssh.key_enabled == 1 %}
|
||||
{% if ssh.id == b.cred %}
|
||||
<option value="{{ssh.id}}" selected="selected">{{ssh.name}}</option>
|
||||
{% else %}
|
||||
<option value="{{ssh.id}}">{{ssh.name}}</option>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
{% if b.description != 'None' %}
|
||||
<input type="text" id="backup-description-{{b.id}}" value="{{b.description.replace("'", "")}}" class="form-control">
|
||||
{% else %}
|
||||
<input type="text" id="backup-description-{{b.id}}" class="form-control">
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a class="add" onclick="cloneBackup({{b.id}})" id="clone-backup{{b.id}}" title="Clone {{b.server}}" style="cursor: pointer;"></a>
|
||||
</td>
|
||||
<td>
|
||||
<a class="delete" onclick="confirmDeleteBackup({{b.id}})" title="Delete backup {{b.server}}" style="cursor: pointer;"></a>
|
||||
</td>
|
||||
</tr>
|
||||
<script>
|
||||
$( function() {
|
||||
$("#backup-time-{{ b.id}}" ).selectmenu({
|
||||
width: 100
|
||||
});
|
||||
$("#backup-type-{{b.id}}" ).selectmenu({
|
||||
width: 130
|
||||
});
|
||||
$("#backup-credentials-{{b.id}}" ).selectmenu({
|
||||
width: 150
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endfor %}
|
||||
{% for s in servers %}
|
||||
{% if b.server_id|string() == s.0|string() %}
|
||||
<tr id="backup-table-{{b.id}}">
|
||||
<td class="padding10 first-collumn">
|
||||
{% set id = 'backup-server-' + b.id|string() %}
|
||||
{{ input('backup-server-id-'+b.id|string(), value=s.0, type='hidden') }}
|
||||
{{ copy_to_clipboard(id=id, value=s.1) }}
|
||||
</td>
|
||||
<td>
|
||||
{{ input('backup-rserver-'+b.id|string(), value=b.rhost, size='14') }}
|
||||
</td>
|
||||
<td>
|
||||
{{ input('backup-rpath-'+b.id|string(), value=b.rpath) }}
|
||||
</td>
|
||||
<td>
|
||||
{% set values = {'backup':'backup','synchronization':'synchronization'} %}
|
||||
{{ select('backup-type-'+b.id|string(), values=values, selected=b.type, required='required', class='force_close') }}
|
||||
</td>
|
||||
<td>
|
||||
{% set values = {'hourly':'hourly','daily':'daily','weekly':'weekly', 'monthly':'monthly'} %}
|
||||
{{ select('backup-time-'+b.id|string(), values=values, selected=b.time, required='required', class='force_close') }}
|
||||
</td>
|
||||
<td>
|
||||
<select id="backup-credentials-{{b.id}}" required>
|
||||
<option disabled selected>------</option>
|
||||
{% for ssh in sshs %}
|
||||
{% if ssh.key_enabled == 1 %}
|
||||
{% if ssh.id == b.cred_id %}
|
||||
<option value="{{ssh.id}}" selected="selected">{{ssh.name}}</option>
|
||||
{% else %}
|
||||
<option value="{{ssh.id}}">{{ssh.name}}</option>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
{% if b.description is not none %}
|
||||
{{ input('backup-description-'+b.id|string(), value=b.description.replace("'", "")) }}
|
||||
{% else %}
|
||||
{{ input('backup-description-'+b.id|string()) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a class="add" onclick="cloneBackup({{b.id}})" id="clone-backup{{b.id}}" title="{{lang.words.clone|title()}} {{b.server_id}}" style="cursor: pointer;"></a>
|
||||
</td>
|
||||
<td>
|
||||
<a class="delete" onclick="confirmDeleteBackup({{b.id}})" title="{{lang.words.delete|title()}} {{lang.words.backup}} {{b.server_id}}" style="cursor: pointer;"></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<select autofocus required name="backup-server" id="backup-server">
|
||||
<option disabled>------</option>
|
||||
{% for s in servers %}
|
||||
<option value="{{ s.2 }}">{{ s.1 }}</option>
|
||||
<option value="{{ s.0 }}">{{ s.1 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<select autofocus required name="s3-backup-server" id="s3-backup-server">
|
||||
<option disabled>------</option>
|
||||
{% for s in servers %}}
|
||||
<option value="{{ s.2 }}">{{ s.1 }}</option>
|
||||
<option value="{{ s.0 }}">{{ s.1 }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
|
|
|
@ -60,59 +60,7 @@
|
|||
<td style="margin-left: 5px;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
{% for b in backups %}
|
||||
{% for s in servers %}
|
||||
{% if b.server in s.2 %}
|
||||
<tr id="backup-table-{{b.id}}">
|
||||
<td class="padding10 first-collumn">
|
||||
{% set id = 'backup-server-' + b.id|string() %}
|
||||
{{ copy_to_clipboard(id=id, value=b.server) }}
|
||||
</td>
|
||||
<td>
|
||||
{{ input('backup-rserver-'+b.id|string(), value=b.rhost, size='14') }}
|
||||
</td>
|
||||
<td>
|
||||
{{ input('backup-rpath-'+b.id|string(), value=b.rpath) }}
|
||||
</td>
|
||||
<td>
|
||||
{% set values = {'backup':'backup','synchronization':'synchronization'} %}
|
||||
{{ select('backup-type-'+b.id|string(), values=values, selected=b.type, required='required', class='force_close') }}
|
||||
</td>
|
||||
<td>
|
||||
{% set values = {'hourly':'hourly','daily':'daily','weekly':'weekly', 'monthly':'monthly'} %}
|
||||
{{ select('backup-time-'+b.id|string(), values=values, selected=b.time, required='required', class='force_close') }}
|
||||
</td>
|
||||
<td>
|
||||
<select id="backup-credentials-{{b.id}}" required>
|
||||
<option disabled selected>------</option>
|
||||
{% for ssh in sshs %}
|
||||
{% if ssh.key_enabled == 1 %}
|
||||
{% if ssh.id == b.cred_id %}
|
||||
<option value="{{ssh.id}}" selected="selected">{{ssh.name}}</option>
|
||||
{% else %}
|
||||
<option value="{{ssh.id}}">{{ssh.name}}</option>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
{% if b.description is not none %}
|
||||
{{ input('backup-description-'+b.id|string(), value=b.description.replace("'", "")) }}
|
||||
{% else %}
|
||||
{{ input('backup-description-'+b.id|string()) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a class="add" onclick="cloneBackup({{b.id}})" id="clone-backup{{b.id}}" title="{{lang.words.clone|title()}} {{b.server}}" style="cursor: pointer;"></a>
|
||||
</td>
|
||||
<td>
|
||||
<a class="delete" onclick="confirmDeleteBackup({{b.id}})" title="{{lang.words.delete|title()}} {{lang.words.backup}} {{b.server}}" style="cursor: pointer;"></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% include 'ajax/new_backup.html' %}
|
||||
</table>
|
||||
<br /><span class="add-button" title="{{lang.words.add|title()}} {{lang.words.w_a}} {{lang.words.new}} {{lang.words.backup}} {{lang.words.job}}" id="add-backup-button">+ {{lang.words.add|title()}} {{lang.words.backup}}</span>
|
||||
<br /><br />
|
||||
|
@ -132,10 +80,10 @@
|
|||
<tbody id="tbody-s3">
|
||||
{% for b in s3_backups %}
|
||||
{% for s in servers %}
|
||||
{% if b.server in s.2 %}
|
||||
{% if b.server_id|string() == s.0|string() %}
|
||||
<tr id="s3-backup-table-{{b.id}}">
|
||||
<td class="padding10 first-collumn">
|
||||
<span id="backup-s3-server-{{b.id}}" style="display: none">{{ b.server }}</span>
|
||||
<span id="backup-s3-server-{{b.id}}" style="display: none">{{ s.0 }}</span>
|
||||
{{s.1}}
|
||||
</td>
|
||||
<td>
|
||||
|
@ -155,10 +103,10 @@
|
|||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a class="add" onclick="cloneS3Backup({{b.id}})" id="clone-s3-backup{{b.id}}" title="{{lang.words.clone|title()}} S3 {{b.server}}" style="cursor: pointer;"></a>
|
||||
<a class="add" onclick="cloneS3Backup({{b.id}})" id="clone-s3-backup{{b.id}}" title="{{lang.words.clone|title()}} S3 {{s.2}}" style="cursor: pointer;"></a>
|
||||
</td>
|
||||
<td>
|
||||
<a class="delete" onclick="confirmDeleteS3Backup({{b.id}})" title="{{lang.words.delete|title()}} S3 {{lang.words.backup}} {{b.server}}" style="cursor: pointer;"></a>
|
||||
<a class="delete" onclick="confirmDeleteS3Backup({{b.id}})" title="{{lang.words.delete|title()}} S3 {{lang.words.backup}} {{s.2}}" style="cursor: pointer;"></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
|
|
@ -89,14 +89,14 @@ class BackupView(MethodView):
|
|||
- cred_id
|
||||
- rhost
|
||||
- rpath
|
||||
- server
|
||||
- server_id
|
||||
- rserver
|
||||
- time
|
||||
- type
|
||||
properties:
|
||||
server:
|
||||
server_id:
|
||||
type: 'string'
|
||||
description: 'The server to be backed up'
|
||||
description: 'The server ID to be backed up'
|
||||
rserver:
|
||||
type: 'string'
|
||||
description: 'The remote server where backup files should be stored'
|
||||
|
@ -153,14 +153,14 @@ class BackupView(MethodView):
|
|||
- cred_id
|
||||
- rhost
|
||||
- rpath
|
||||
- server
|
||||
- server_id
|
||||
- rserver
|
||||
- time
|
||||
- type
|
||||
properties:
|
||||
server:
|
||||
type: 'string'
|
||||
description: 'The server to be backed up'
|
||||
server_id:
|
||||
type: 'integer'
|
||||
description: 'The server ID to be backed up'
|
||||
rserver:
|
||||
type: 'string'
|
||||
description: 'The remote server where backup files should be stored'
|
||||
|
@ -214,9 +214,9 @@ class BackupView(MethodView):
|
|||
schema:
|
||||
type: 'object'
|
||||
properties:
|
||||
server:
|
||||
type: 'string'
|
||||
description: 'The server to be backed up'
|
||||
server_id:
|
||||
type: 'integer'
|
||||
description: 'The server ID to be backed up'
|
||||
cred_id:
|
||||
type: 'string'
|
||||
description: 'Credentials ID for the backup task'
|
||||
|
@ -276,9 +276,9 @@ class S3BackupView(MethodView):
|
|||
secret_key:
|
||||
type: 'string'
|
||||
description: 'The secret key for S3 access'
|
||||
server:
|
||||
type: 'string'
|
||||
description: 'The server that was backed up'
|
||||
server_id:
|
||||
type: 'integer'
|
||||
description: 'The server ID that was backed up'
|
||||
time:
|
||||
type: 'string'
|
||||
description: 'The timing for the S3 backup task'
|
||||
|
@ -308,7 +308,7 @@ class S3BackupView(MethodView):
|
|||
type: 'object'
|
||||
required:
|
||||
- s3_server
|
||||
- server
|
||||
- server_id
|
||||
- bucket
|
||||
- secret_key
|
||||
- access_key
|
||||
|
@ -317,9 +317,9 @@ class S3BackupView(MethodView):
|
|||
s3_server:
|
||||
type: 'string'
|
||||
description: 'The S3 server where the backup should be stored'
|
||||
server:
|
||||
type: 'string'
|
||||
description: 'The server to be backed up'
|
||||
server_id:
|
||||
type: 'integer'
|
||||
description: 'The server ID to be backed up'
|
||||
bucket:
|
||||
type: 'string'
|
||||
description: 'The S3 bucket where the backup should be stored'
|
||||
|
@ -347,6 +347,67 @@ class S3BackupView(MethodView):
|
|||
except Exception as e:
|
||||
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot create S3 backup')
|
||||
|
||||
@validate(body=S3BackupRequest)
|
||||
def put(self, backup_id: int, body: S3BackupRequest):
|
||||
"""
|
||||
Update the S3 backup.
|
||||
---
|
||||
tags:
|
||||
- S3 Backup
|
||||
parameters:
|
||||
- in: path
|
||||
name: backup_id
|
||||
type: 'integer'
|
||||
required: true
|
||||
description: The ID of the specific S3 backup
|
||||
- name: config
|
||||
in: body
|
||||
required: true
|
||||
description: The configuration for S3 backup service
|
||||
schema:
|
||||
type: 'object'
|
||||
required:
|
||||
- s3_server
|
||||
- server_id
|
||||
- bucket
|
||||
- secret_key
|
||||
- access_key
|
||||
- time
|
||||
properties:
|
||||
s3_server:
|
||||
type: 'string'
|
||||
description: 'The S3 server where the backup should be stored'
|
||||
server_id:
|
||||
type: 'integer'
|
||||
description: 'The server ID to be backed up'
|
||||
bucket:
|
||||
type: 'string'
|
||||
description: 'The S3 bucket where the backup should be stored'
|
||||
secret_key:
|
||||
type: 'string'
|
||||
description: 'The secret key for S3 access'
|
||||
access_key:
|
||||
type: 'string'
|
||||
description: 'The access key for S3'
|
||||
time:
|
||||
type: 'string'
|
||||
description: 'The timing for the S3 backup task'
|
||||
enum: [hourly, daily, weekly, monthly]
|
||||
description:
|
||||
type: 'string'
|
||||
description: 'Description for the S3 backup configuration'
|
||||
responses:
|
||||
201:
|
||||
description: Successful operation
|
||||
default:
|
||||
description: Unexpected error
|
||||
"""
|
||||
try:
|
||||
backup_mod.create_s3_backup_inv(body, 'add')
|
||||
backup_sql.update_s3_backup_job(backup_id, 's3')
|
||||
except Exception as e:
|
||||
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot update S3 backup')
|
||||
|
||||
@validate(body=S3BackupRequest)
|
||||
def delete(self, backup_id: int, body: S3BackupRequest):
|
||||
"""
|
||||
|
@ -370,9 +431,9 @@ class S3BackupView(MethodView):
|
|||
bucket:
|
||||
type: 'string'
|
||||
description: 'The S3 bucket where the backup is stored'
|
||||
server:
|
||||
type: 'string'
|
||||
description: 'The server that was backed up'
|
||||
server_id:
|
||||
type: 'integer'
|
||||
description: 'The server ID that was backed up'
|
||||
responses:
|
||||
200:
|
||||
description: Successful operation
|
||||
|
|
|
@ -182,6 +182,7 @@ class ServiceView(MethodView):
|
|||
return ErrorResponse(error='Keepalived service not found').model_dump(mode='json'), 404
|
||||
except Exception as e:
|
||||
return roxywi_common.handler_exceptions_for_json_data(e, 'Cannot get version')
|
||||
data['id'] = f'{server_id}-{service}'
|
||||
return jsonify(data)
|
||||
|
||||
@staticmethod
|
||||
|
|
Loading…
Reference in New Issue