mirror of
https://github.com/netinvent/npbackup.git
synced 2025-10-27 13:57:26 +08:00
WIP: Refactor operations GUI
This commit is contained in:
parent
e0f85bacae
commit
a0511ce2a5
6 changed files with 93 additions and 94 deletions
|
|
@ -1,3 +1,17 @@
|
|||
#! /usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of npbackup
|
||||
|
||||
__intname__ = "npbackup.common"
|
||||
__author__ = "Orsiris de Jong"
|
||||
__site__ = "https://www.netperfect.fr/npbackup"
|
||||
__description__ = "NetPerfect Backup Client"
|
||||
__copyright__ = "Copyright (C) 2023 NetInvent"
|
||||
__license__ = "GPL-3.0-only"
|
||||
__build__ = "2023121801"
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from logging import getLogger
|
||||
import ofunctions.logger_utils
|
||||
|
|
@ -6,9 +20,6 @@ import ofunctions.logger_utils
|
|||
logger = getLogger()
|
||||
|
||||
|
||||
EXIT_CODE = 0
|
||||
|
||||
|
||||
def execution_logs(start_time: datetime) -> None:
|
||||
"""
|
||||
Try to know if logger.warning or worse has been called
|
||||
|
|
@ -23,7 +34,6 @@ def execution_logs(start_time: datetime) -> None:
|
|||
So using logger = getLogger("anotherinstance") will create a separate instance from the one we can inspect
|
||||
Makes sense ;)
|
||||
"""
|
||||
global EXIT_CODE
|
||||
|
||||
end_time = datetime.utcnow()
|
||||
|
||||
|
|
@ -33,7 +43,6 @@ def execution_logs(start_time: datetime) -> None:
|
|||
logger_worst_level = flt.worst_level
|
||||
|
||||
log_level_reached = "success"
|
||||
EXIT_CODE = logger_worst_level
|
||||
try:
|
||||
if logger_worst_level >= 40:
|
||||
log_level_reached = "errors"
|
||||
|
|
@ -46,4 +55,5 @@ def execution_logs(start_time: datetime) -> None:
|
|||
end_time - start_time, log_level_reached
|
||||
)
|
||||
)
|
||||
# using sys.exit(code) in a atexit function will swallow the exitcode and render 0
|
||||
# using sys.exit(code) in a atexit function will swallow the exitcode and render 0
|
||||
# Using sys.exit(logger.get_worst_logger_level()) is the way to go, when using ofunctions.logger_utils >= 2.4.1
|
||||
|
|
@ -652,7 +652,8 @@ class NPBackupRunner:
|
|||
return result
|
||||
|
||||
def group_runner(
|
||||
self, operations_config: dict, result_queue: Optional[queue.Queue]
|
||||
self, repo_list: list, operation: str, result_queue: Optional[queue.Queue]
|
||||
) -> bool:
|
||||
print(operations_config)
|
||||
for repo in repo_list:
|
||||
print(f"Running {operation} for repo {repo}")
|
||||
print("run to the hills")
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from typing import List, Optional, Tuple
|
|||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
from logging import getLogger
|
||||
import ofunctions.logger_utils
|
||||
from datetime import datetime
|
||||
import dateutil
|
||||
import queue
|
||||
|
|
@ -57,10 +57,15 @@ from npbackup.customization import (
|
|||
OEM_ICON,
|
||||
)
|
||||
|
||||
|
||||
|
||||
LOG_FILE = os.path.join(CURRENT_DIR, "{}.log".format(__intname__))
|
||||
logger = ofunctions.logger_utils.logger_get_logger(LOG_FILE)
|
||||
|
||||
|
||||
sg.theme(PYSIMPLEGUI_THEME)
|
||||
sg.SetOptions(icon=OEM_ICON)
|
||||
|
||||
logger = getLogger()
|
||||
|
||||
# Let's use mutable to get a cheap way of transfering data from thread to main program
|
||||
# There are no possible race conditions since we don't modifiy the data from anywhere outside the thread
|
||||
|
|
@ -199,21 +204,21 @@ def _gui_update_state(
|
|||
window, current_state: bool, backup_tz: Optional[datetime], snapshot_list: List[str]
|
||||
) -> None:
|
||||
if current_state:
|
||||
window["state-button"].Update(
|
||||
window["--STATE-BUTTON--"].Update(
|
||||
"{}: {}".format(_t("generic.up_to_date"), backup_tz),
|
||||
button_color=GUI_STATE_OK_BUTTON,
|
||||
)
|
||||
elif current_state is False and backup_tz == datetime(1, 1, 1, 0, 0):
|
||||
window["state-button"].Update(
|
||||
window["--STATE-BUTTON--"].Update(
|
||||
_t("generic.no_snapshots"), button_color=GUI_STATE_OLD_BUTTON
|
||||
)
|
||||
elif current_state is False:
|
||||
window["state-button"].Update(
|
||||
window["--STATE-BUTTON--"].Update(
|
||||
"{}: {}".format(_t("generic.too_old"), backup_tz.replace(microsecond=0)),
|
||||
button_color=GUI_STATE_OLD_BUTTON,
|
||||
)
|
||||
elif current_state is None:
|
||||
window["state-button"].Update(
|
||||
window["--STATE-BUTTON--"].Update(
|
||||
_t("generic.not_connected_yet"), button_color=GUI_STATE_UNKNOWN_BUTTON
|
||||
)
|
||||
|
||||
|
|
@ -619,7 +624,7 @@ def _main_gui():
|
|||
[
|
||||
sg.Button(
|
||||
_t("generic.unknown"),
|
||||
key="state-button",
|
||||
key="--STATE-BUTTON--",
|
||||
button_color=("white", "grey"),
|
||||
)
|
||||
],
|
||||
|
|
@ -650,13 +655,13 @@ def _main_gui():
|
|||
)
|
||||
],
|
||||
[
|
||||
sg.Button(_t("main_gui.launch_backup"), key="launch-backup"),
|
||||
sg.Button(_t("main_gui.see_content"), key="see-content"),
|
||||
sg.Button(_t("generic.forget"), key="forget"),
|
||||
sg.Button(_t("main_gui.operations"), key="operations"),
|
||||
sg.Button(_t("generic.configure"), key="configure"),
|
||||
sg.Button(_t("generic.about"), key="about"),
|
||||
sg.Button(_t("generic.quit"), key="-EXIT-"),
|
||||
sg.Button(_t("main_gui.launch_backup"), key="--LAUNCH-BACKUP--"),
|
||||
sg.Button(_t("main_gui.see_content"), key="--SEE-CONTENT--"),
|
||||
sg.Button(_t("generic.forget"), key="--FORGET--"),
|
||||
sg.Button(_t("main_gui.operations"), key="--OPERATIONS--"),
|
||||
sg.Button(_t("generic.configure"), key="--CONFIGURE--"),
|
||||
sg.Button(_t("generic.about"), key="--ABOUT--"),
|
||||
sg.Button(_t("generic.quit"), key="--EXIT--"),
|
||||
],
|
||||
],
|
||||
element_justification="C",
|
||||
|
|
@ -694,7 +699,7 @@ def _main_gui():
|
|||
while True:
|
||||
event, values = window.read(timeout=60000)
|
||||
|
||||
if event in (sg.WIN_X_EVENT, sg.WIN_CLOSED, "-EXIT-"):
|
||||
if event in (sg.WIN_X_EVENT, sg.WIN_CLOSED, "--EXIT--"):
|
||||
break
|
||||
if event == "-active_repo-":
|
||||
active_repo = values["-active_repo-"]
|
||||
|
|
@ -708,7 +713,7 @@ def _main_gui():
|
|||
else:
|
||||
sg.PopupError("Repo not existent in config")
|
||||
continue
|
||||
if event == "launch-backup":
|
||||
if event == "--LAUNCH-BACKUP--":
|
||||
progress_windows_layout = [
|
||||
[
|
||||
sg.Multiline(
|
||||
|
|
@ -762,17 +767,16 @@ def _main_gui():
|
|||
)
|
||||
progress_window.close()
|
||||
continue
|
||||
if event == "see-content":
|
||||
if event == "--SEE-CONTENT--":
|
||||
if not values["snapshot-list"]:
|
||||
sg.Popup(_t("main_gui.select_backup"), keep_on_top=True)
|
||||
continue
|
||||
print(values["snapshot-list"])
|
||||
if len(values["snapshot-list"]) > 1:
|
||||
sg.Popup(_t("main_gui.select_only_one_snapshot"))
|
||||
continue
|
||||
snapshot_to_see = snapshot_list[values["snapshot-list"][0]][0]
|
||||
ls_window(repo_config, snapshot_to_see)
|
||||
if event == "forget":
|
||||
if event == "--FORGET--":
|
||||
if not values["snapshot-list"]:
|
||||
sg.Popup(_t("main_gui.select_backup"), keep_on_top=True)
|
||||
continue
|
||||
|
|
@ -781,14 +785,14 @@ def _main_gui():
|
|||
snapshots_to_forget.append(snapshot_list[row][0])
|
||||
forget_snapshot(repo_config, snapshots_to_forget)
|
||||
# Make sure we trigger a GUI refresh after forgetting snapshots
|
||||
event = "state-button"
|
||||
if event == "operations":
|
||||
full_config = operations_gui(full_config, config_file)
|
||||
event = "state-button"
|
||||
if event == "configure":
|
||||
event = "--STATE-BUTTON--"
|
||||
if event == "--OPERATIONS--":
|
||||
full_config = operations_gui(full_config)
|
||||
event = "--STATE-BUTTON--"
|
||||
if event == "--CONFIGURE--":
|
||||
full_config = config_gui(full_config, config_file)
|
||||
# Make sure we trigger a GUI refresh when configuration is changed
|
||||
event = "state-button"
|
||||
event = "--STATE-BUTTON--"
|
||||
if event == _t("generic.destination"):
|
||||
try:
|
||||
if backend_type:
|
||||
|
|
@ -799,9 +803,9 @@ def _main_gui():
|
|||
sg.PopupNoFrame(destination_string)
|
||||
except (TypeError, KeyError):
|
||||
sg.PopupNoFrame(_t("main_gui.unknown_repo"))
|
||||
if event == "about":
|
||||
if event == "--ABOUT--":
|
||||
_about_gui(version_string, full_config)
|
||||
if event == "state-button":
|
||||
if event == "--STATE-BUTTON--":
|
||||
current_state, backup_tz, snapshot_list = get_gui_data(repo_config)
|
||||
_gui_update_state(window, current_state, backup_tz, snapshot_list)
|
||||
if current_state is None:
|
||||
|
|
@ -815,7 +819,7 @@ def main_gui():
|
|||
)
|
||||
try:
|
||||
_main_gui()
|
||||
sys.exit(npbackup.common.EXIT_CODE)
|
||||
sys.exit(logger.get_worst_logger_level())
|
||||
except _tkinter.TclError as exc:
|
||||
logger.critical(f'Tkinter error: "{exc}". Is this a headless server ?')
|
||||
sys.exit(250)
|
||||
|
|
|
|||
|
|
@ -38,34 +38,28 @@ from npbackup.customization import (
|
|||
logger = getLogger(__intname__)
|
||||
|
||||
|
||||
def add_repo(config_dict: dict) -> dict:
|
||||
pass
|
||||
|
||||
|
||||
def gui_update_state(window, config_dict: dict) -> list:
|
||||
def gui_update_state(window, full_config: dict) -> list:
|
||||
repo_list = []
|
||||
try:
|
||||
for repo_name in config_dict["repos"]:
|
||||
if (
|
||||
config_dict["repos"][repo_name]["repository"]
|
||||
and config_dict["repos"][repo_name]["password"]
|
||||
for repo_name in full_config.g("repos"):
|
||||
repo_config, _ = configuration.get_repo_config(full_config, repo_name)
|
||||
if repo_config.g(f"repo_uri") and (
|
||||
repo_config.g(f"repo_opts.repo_password")
|
||||
or repo_config.g(f"repo_opts.repo_password_command")
|
||||
):
|
||||
backend_type, repo_uri = get_anon_repo_uri(
|
||||
config_dict["repos"][repo_name]["repository"]
|
||||
repo_config.g(f"repo_uri")
|
||||
)
|
||||
repo_list.append([backend_type, repo_uri])
|
||||
else:
|
||||
logger.warning("Incomplete operations repo {}".format(repo_name))
|
||||
except KeyError:
|
||||
logger.info("No operations repos configured")
|
||||
if config_dict["repo"]["repository"] and config_dict["repo"]["password"]:
|
||||
backend_type, repo_uri = get_anon_repo_uri(config_dict["repo"]["repository"])
|
||||
repo_list.append("[{}] {}".format(backend_type, repo_uri))
|
||||
window["repo-list"].update(repo_list)
|
||||
return repo_list
|
||||
|
||||
|
||||
def operations_gui(config_dict: dict, config_file: str) -> dict:
|
||||
def operations_gui(full_config: dict) -> dict:
|
||||
"""
|
||||
Operate on one or multiple repositories
|
||||
"""
|
||||
|
|
@ -102,13 +96,8 @@ def operations_gui(config_dict: dict, config_file: str) -> dict:
|
|||
)
|
||||
],
|
||||
[
|
||||
sg.Button(_t("operations_gui.add_repo"), key="add-repo"),
|
||||
sg.Button(_t("operations_gui.edit_repo"), key="edit-repo"),
|
||||
sg.Button(_t("operations_gui.remove_repo"), key="remove-repo"),
|
||||
],
|
||||
[
|
||||
sg.Button(_t("operations_gui.quick_check"), key="quick-check"),
|
||||
sg.Button(_t("operations_gui.full_check"), key="full-check"),
|
||||
sg.Button(_t("operations_gui.quick_check"), key="--QUICK-CHECK--"),
|
||||
sg.Button(_t("operations_gui.full_check"), key="--FULL-CHECK--"),
|
||||
],
|
||||
[
|
||||
sg.Button(
|
||||
|
|
@ -118,11 +107,11 @@ def operations_gui(config_dict: dict, config_file: str) -> dict:
|
|||
],
|
||||
[
|
||||
sg.Button(
|
||||
_t("operations_gui.standard_prune"), key="standard-prune"
|
||||
_t("operations_gui.standard_prune"), key="--STANDARD-PRUNE--"
|
||||
),
|
||||
sg.Button(_t("operations_gui.max_prune"), key="max-prune"),
|
||||
sg.Button(_t("operations_gui.max_prune"), key="--MAX-PRUNE--"),
|
||||
],
|
||||
[sg.Button(_t("generic.quit"), key="exit")],
|
||||
[sg.Button(_t("generic.quit"), key="--EXIT--")],
|
||||
],
|
||||
element_justification="C",
|
||||
)
|
||||
|
|
@ -144,7 +133,7 @@ def operations_gui(config_dict: dict, config_file: str) -> dict:
|
|||
finalize=True,
|
||||
)
|
||||
|
||||
full_repo_list = gui_update_state(window, config_dict)
|
||||
complete_repo_list = gui_update_state(window, full_config)
|
||||
|
||||
# Auto reisze table to window size
|
||||
window["repo-list"].expand(True, True)
|
||||
|
|
@ -152,34 +141,14 @@ def operations_gui(config_dict: dict, config_file: str) -> dict:
|
|||
while True:
|
||||
event, values = window.read(timeout=60000)
|
||||
|
||||
if event in (sg.WIN_CLOSED, "exit"):
|
||||
if event in (sg.WIN_CLOSED, sg.WIN_X_EVENT, '--EXIT--'):
|
||||
break
|
||||
if event == "add-repo":
|
||||
pass
|
||||
if event in ["add-repo", "remove-repo"]:
|
||||
if not values["repo-list"]:
|
||||
sg.Popup(_t("main_gui.select_backup"), keep_on_top=True)
|
||||
continue
|
||||
if event == "add-repo":
|
||||
config_dict = add_repo(config_dict)
|
||||
# Save to config here #TODO #WIP
|
||||
event == "state-update"
|
||||
elif event == "remove-repo":
|
||||
result = sg.popup(
|
||||
_t("generic.are_you_sure"),
|
||||
custom_text=(_t("generic.yes"), _t("generic.no")),
|
||||
)
|
||||
if result == _t("generic.yes"):
|
||||
# Save to config here #TODO #WIP
|
||||
event == "state-update"
|
||||
if event == "forget":
|
||||
pass
|
||||
if event in [
|
||||
"forget",
|
||||
"quick-check",
|
||||
"full-check",
|
||||
"standard-prune",
|
||||
"max-prune",
|
||||
"--FORGET--",
|
||||
"--QUICK-CHECK--",
|
||||
"--FULL-CHECK--",
|
||||
"--STANDARD-PRUNE--",
|
||||
"--MAX-PRUNE--",
|
||||
]:
|
||||
if not values["repo-list"]:
|
||||
result = sg.popup(
|
||||
|
|
@ -188,14 +157,29 @@ def operations_gui(config_dict: dict, config_file: str) -> dict:
|
|||
)
|
||||
if not result == _t("generic.yes"):
|
||||
continue
|
||||
repos = full_repo_list
|
||||
repos = complete_repo_list
|
||||
else:
|
||||
repos = values["repo-list"]
|
||||
|
||||
result_queue = queue.Queue()
|
||||
runner = NPBackupRunner()
|
||||
runner.group_runner(repos, result_queue)
|
||||
if event == "state-update":
|
||||
full_repo_list = gui_update_state(window, config_dict)
|
||||
print(repos)
|
||||
group_runner_repo_list = [repo_name for backend_type, repo_name in repos]
|
||||
|
||||
if event == '--FORGET--':
|
||||
operation = 'forget'
|
||||
if event == '--QUICK-CHECK--':
|
||||
operation = 'quick_check'
|
||||
if event == '--FULL-CHECK--':
|
||||
operation = 'full_check'
|
||||
if event == '--STANDARD-PRUNE--':
|
||||
operation = 'standard_prune'
|
||||
if event == '--MAX-PRUNE--':
|
||||
operation = 'max_prune'
|
||||
runner.group_runner(group_runner_repo_list, operation, result_queue)
|
||||
event = '---STATE-UPDATE---'
|
||||
if event == "---STATE-UPDATE---":
|
||||
complete_repo_list = gui_update_state(window, full_config)
|
||||
window.close()
|
||||
|
||||
return config_dict
|
||||
return full_config
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ en:
|
|||
only_include: Only include
|
||||
destination_folder: Destination folder
|
||||
backup_state: Backup state
|
||||
backup_list_to: List of backups to
|
||||
backup_list_to: List of backups to repo
|
||||
local_folder: Local folder
|
||||
external_server: external server
|
||||
launch_backup: Launch backup
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ fr:
|
|||
only_include: Inclure seulement
|
||||
destination_folder: Dossier de destination
|
||||
backup_state: Etat de sauvegarde
|
||||
backup_list_to: Liste des sauvegardes vers
|
||||
backup_list_to: Liste des sauvegardes vers le dépot
|
||||
local_folder: Dossier local
|
||||
external_server: serveur externalisé
|
||||
launch_backup: Sauvegarder
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue