mirror of
https://github.com/netinvent/npbackup.git
synced 2025-09-03 19:46:45 +08:00
Spellchecking
This commit is contained in:
parent
4705f915a8
commit
087ab80cbf
32 changed files with 106 additions and 116 deletions
|
@ -124,7 +124,7 @@ Link: https://www.virustotal.com/gui/file/48c7d828f878638ccf8736f1b87bccd0f8e544
|
|||
Build type: Standalone
|
||||
Compiler: Nuitka 2.6.4 commercial
|
||||
Backend msvc 143
|
||||
Signes: Yes (EV Code signing certificate)
|
||||
Signed: Yes (EV Code signing certificate)
|
||||
Build target: npbackup-cli.exe
|
||||
Result: No security vendors flagged this file as malicious
|
||||
Link: https://www.virustotal.com/gui/file/50a12c697684194853e6e4ec1778f50f86798d426853c4e0a744f2a5c4d02def
|
12
CHANGELOG
12
CHANGELOG
|
@ -6,7 +6,7 @@
|
|||
- This is a major rewrite that allows using multiple repositories, adds repository groups and implements repository settings inheritance from group settings
|
||||
|
||||
#### Features
|
||||
- New viewer mode allowing to browse/restore restic repositories without any NPBackup configuation
|
||||
- New viewer mode allowing to browse/restore restic repositories without any NPBackup configuration
|
||||
- Allows setting repository via environment variables, config file or directly in GUI
|
||||
- Multi repository support
|
||||
- Group settings for repositories
|
||||
|
@ -46,10 +46,10 @@
|
|||
- Metrics now include auto upgrade state
|
||||
- Dry mode now works for all operations where restic supports dry-mode
|
||||
- Implemented scheduled task creator for Windows & Unix
|
||||
- Added --no-cache option to disable cache for restic operations (neeeded on RO systems)
|
||||
- Added --no-cache option to disable cache for restic operations (needed on RO systems)
|
||||
- Added CRC32 logging for config files in order to know when a file was modified
|
||||
- Missing exclude files will now search in current binary directory for a excludes directory
|
||||
- Splitted releases between legacy and non legacy
|
||||
- Split releases between legacy and non legacy
|
||||
- Updated legacy tcl8.6.13 to tc8.6.15
|
||||
- Updated legacy Python 3.7 to Python 3.9 (with openssl 1.1.1) for x64 linux builds
|
||||
- Upgrade server
|
||||
|
@ -72,7 +72,7 @@
|
|||
- Concurrency checks (pidfile checks) are now directly part of the runner
|
||||
- Allow a 30 seconds grace period for child processes to close before asking them nicely, and than not nicely to quit
|
||||
- Fully refactored prometheus metrics parser to be able to read restic standard or json outputs
|
||||
- Reimplmented auto upgrade after CLI/GUI split
|
||||
- Reimplemented auto upgrade after CLI/GUI split
|
||||
- Added initial tests
|
||||
- Exclude lists have been updated
|
||||
- Removed Windows installer from the project. We need to come up with a better solution
|
||||
|
@ -101,7 +101,7 @@
|
|||
|
||||
## 2.2.0 - rtm - 03/06/2023
|
||||
- Fix potential deadlock in evaluate variables
|
||||
- Fix additionnal parameters should only apply for backup operations
|
||||
- Fix additional parameters should only apply for backup operations
|
||||
- Fix unnecessary exclude statements when no exclusions are given
|
||||
- Added source types (--files-from, --files-from-verbatim and --files-from-raw equivalent)
|
||||
- Add encrypted environment variables support
|
||||
|
@ -195,7 +195,7 @@
|
|||
- Fix config fails when restic password is an int
|
||||
- Fix empty config files did not show a proper error message
|
||||
- Fix various config file malformation will break execution
|
||||
- Fix backup hangs when no restic password is given (restic asks for password in backgroud job)
|
||||
- Fix backup hangs when no restic password is given (restic asks for password in background job)
|
||||
- Fix error message in logs when repo is not initialized
|
||||
|
||||
## v2.2.0 - rc1 - 02/02/2023
|
||||
|
|
|
@ -24,10 +24,10 @@ For the rest of this manual, we'll assume the you use:
|
|||
- Intel: `/usr/local/bin/python3`
|
||||
- ARM: `/opt/homebrew/bin/python3`
|
||||
|
||||
You may also use a python virtual environement (venv) to have a python "sub interpreter", but this is out of scope here too.
|
||||
You may also use a python virtual environment (venv) to have a python "sub interpreter", but this is out of scope here too.
|
||||
|
||||
Once you've got yourself a working Python environment, you should download and extract the NPBackup sources (or clone the git). NPBackup has multiple python dependencies, which are stated in a file named `requirements.txt`.
|
||||
You can install them all toghether by running `python -m pip install -r path/to/requirements.txt` (please note that `path/to/requirements.txt` would give something like `C:\path\to\requirements` on Windows)
|
||||
You can install them all together by running `python -m pip install -r path/to/requirements.txt` (please note that `path/to/requirements.txt` would give something like `C:\path\to\requirements` on Windows)
|
||||
|
||||
Examples:
|
||||
- On Windows: `C:\python310-64\python.exe -m pip install -r c:\npbackup\npbackup\requirements.txt`
|
||||
|
|
|
@ -207,7 +207,7 @@ While admin user experience is important, NPBackup also offers a GUI for end use
|
|||
`npbackup-cli` has all the functions the GUI has, and can run on any headless server.
|
||||
It also has a `--json` parameter which guarantees parseable output.
|
||||
|
||||
You may run operations on multiple repositories, or repositories groups by specifying paramater `--repo-group` or `--repo-name`.
|
||||
You may run operations on multiple repositories, or repositories groups by specifying parameter `--repo-group` or `--repo-name`.
|
||||
`--repo-name` allows to specify one or multiple comma separated repo names, also allows special `__all__` argument which selects all repositories.
|
||||
`--repo-group` allows to specify one or multiple comme separated repo group names, also allows special `__all__` argument which selects all groups.
|
||||
|
||||
|
@ -312,7 +312,7 @@ python.exe -c "from windows_tools.signtool import SignTool; s=SignTool(); s.sign
|
|||
## Misc
|
||||
|
||||
NPBackup supports internationalization and automatically detects system's locale.
|
||||
Still, locale can be overrided via an environment variable, eg on Linux:
|
||||
Still, locale can be overridden via an environment variable, eg on Linux:
|
||||
```
|
||||
export NPBACKUP_LOCALE=en-US
|
||||
```
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
## List of various restic problems encountered while developping NPBackup
|
||||
## List of various restic problems encountered while developing NPBackup
|
||||
|
||||
As of 2024/01/02, version 0.16.2:
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## What's planned / considered post v3
|
||||
|
||||
### Daemon mode (planned)
|
||||
Instead of relying on scheduled tasks, we could launch backup & housekeeping operations as deamon.
|
||||
Instead of relying on scheduled tasks, we could launch backup & housekeeping operations as daemon.
|
||||
Caveats:
|
||||
- We need a windows service (nuitka commercial implements one)
|
||||
- We need to use apscheduler (wait for v4)
|
||||
|
@ -40,7 +40,7 @@ We actually could improve upgrade_server to do so
|
|||
|
||||
### Hyper-V Backup plugin
|
||||
That's another story. Creating snapshots and dumping VM is easy
|
||||
Shall we go that route since alot of good commercial products exist ? Probably not
|
||||
Shall we go that route since a lot of good commercial products exist ? Probably not
|
||||
|
||||
### Full disk cloning
|
||||
Out of scope of NPBackup. There are plenty of good tools out there, designed for that job
|
||||
|
|
|
@ -45,7 +45,7 @@ Using `--show-config` should hide sensitive data, and manager password.
|
|||
|
||||
# NPF-SEC-00009: Option to show sensitive data
|
||||
|
||||
When using `--show-config` or right click `show unecrypted`, we should only show unencrypted config if password is set.
|
||||
When using `--show-config` or right click `show unencrypted`, we should only show unencrypted config if password is set.
|
||||
Environment variable `NPBACKUP_MANAGER_PASSWORD` will be read to verify access, or GUI may ask for password.
|
||||
Also, when wrong password is entered, we should wait in order to reduce brute force attacks.
|
||||
|
||||
|
@ -62,6 +62,6 @@ Using obfuscation() symmetric function in order to not store the bare AES key.
|
|||
|
||||
The PRIVATE directory might contain alternative AES keys and obfuscation functions which should never be bundled for a PyPI release.
|
||||
|
||||
# NPF-SEC-00013: Don't leave encrypted envrionment variables for script usage
|
||||
# NPF-SEC-00013: Don't leave encrypted environment variables for script usage
|
||||
|
||||
Sensitive environment variables aren't available for scripts / additional parameters and will be replaced by a given string from __env__.py
|
|
@ -65,7 +65,7 @@ venv/bin/python upgrade_server/upgrade_server.py -c /etc/npbackup_upgrade_server
|
|||
|
||||
## Create a service
|
||||
|
||||
You can create a systemd service for the upgrade server as `/etc/systemd/system/npbackup_upgrade_server.service`, see the systemd file in the example directoy.
|
||||
You can create a systemd service for the upgrade server as `/etc/systemd/system/npbackup_upgrade_server.service`, see the systemd file in the example directory.
|
||||
|
||||
## Statistics
|
||||
|
||||
|
|
|
@ -380,7 +380,7 @@ def compile(
|
|||
print(f"ERROR: Could not sign: {output}")
|
||||
errors = True
|
||||
elif os.path.isfile(ev_cert_data):
|
||||
print(f"Signing with interal signer {ev_cert_data}")
|
||||
print(f"Signing with internal signer {ev_cert_data}")
|
||||
sign(
|
||||
executable=npbackup_executable,
|
||||
arch=arch,
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
"type": "prometheus",
|
||||
"uid": "${DS_MIMIR}"
|
||||
},
|
||||
"description": "Number of succesful npbackup executions",
|
||||
"description": "Number of successful npbackup executions",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"type": "grafana",
|
||||
"id": "grafana",
|
||||
"name": "Grafana",
|
||||
"version": "11.4.0"
|
||||
"version": "11.5.1"
|
||||
},
|
||||
{
|
||||
"type": "panel",
|
||||
|
@ -158,7 +158,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -248,7 +248,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -274,7 +274,7 @@
|
|||
"type": "prometheus",
|
||||
"uid": "${DS_MIMIR}"
|
||||
},
|
||||
"description": "Number of succesful npbackup executions",
|
||||
"description": "Number of successful npbackup executions",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
|
@ -338,7 +338,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -362,7 +362,7 @@
|
|||
"type": "prometheus",
|
||||
"uid": "${DS_MIMIR}"
|
||||
},
|
||||
"description": "Number of succesful npbackup executions",
|
||||
"description": "Number of successful backup backend executions",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
|
@ -426,7 +426,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -450,7 +450,7 @@
|
|||
"type": "prometheus",
|
||||
"uid": "${DS_MIMIR}"
|
||||
},
|
||||
"description": "Number of succesful npbackup executions",
|
||||
"description": "Number of failed backup backend executions",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
|
@ -510,7 +510,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -590,7 +590,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -672,7 +672,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -754,7 +754,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -836,7 +836,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -918,7 +918,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -1000,7 +1000,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -1082,7 +1082,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -1164,7 +1164,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -1236,11 +1236,12 @@
|
|||
"values": false
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -1328,7 +1329,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -1415,7 +1416,7 @@
|
|||
"textMode": "auto",
|
||||
"wideLayout": true
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -1502,7 +1503,7 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -1615,8 +1616,7 @@
|
|||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "dark-red",
|
||||
"value": null
|
||||
"color": "dark-red"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1650,7 +1650,7 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"pluginVersion": "11.4.0",
|
||||
"pluginVersion": "11.5.1",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
|
@ -1776,8 +1776,7 @@
|
|||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "dark-red",
|
||||
"value": null
|
||||
"color": "dark-red"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1927,8 +1926,7 @@
|
|||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "dark-red",
|
||||
"value": null
|
||||
"color": "dark-red"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -2092,8 +2090,7 @@
|
|||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
|
@ -2199,8 +2196,7 @@
|
|||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
|
@ -2306,8 +2302,7 @@
|
|||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
|
@ -2412,8 +2407,7 @@
|
|||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
|
@ -2518,8 +2512,7 @@
|
|||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
|
@ -2662,8 +2655,7 @@
|
|||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
|
@ -2804,8 +2796,7 @@
|
|||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
|
@ -2909,8 +2900,7 @@
|
|||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
|
@ -3065,8 +3055,8 @@
|
|||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "NPBackup v3 20250211",
|
||||
"title": "Sauvegardes NPBackup v3 20250211",
|
||||
"uid": "XNGJDIgRx",
|
||||
"version": 27,
|
||||
"version": 28,
|
||||
"weekStart": ""
|
||||
}
|
|
@ -21,7 +21,7 @@ NPBACKUP_CONF_FILE_TEMPLATE="${ROOT_DIR}/npbackup-cube.conf.template"
|
|||
NPBACKUP_CONF_FILE="${ROOT_DIR}/npbackup-cube.conf"
|
||||
SNAPSHOT_FAILED_FILE="${ROOT_DIR}/SNAPSHOT_FAILED"
|
||||
|
||||
# Superseed tenants if this is set, else it is extracted from machine name, eg machine.tenant.something
|
||||
# Supersede tenants if this is set, else it is extracted from machine name, eg machine.tenant.something
|
||||
# TENANT_OVERRIDE=netperfect
|
||||
# default tenant if extraction of tenant name failed
|
||||
DEFAULT_TENANT=netperfect
|
||||
|
@ -173,7 +173,7 @@ function remove_snapshot {
|
|||
qemu-img commit -dp "$disk_path" >> "$LOG_FILE" 2>&1
|
||||
log "Note that you will need to modify the XML manually"
|
||||
|
||||
# virsh snapshot delete will erase commited file if exist so we don't need to manually tamper with xml file
|
||||
# virsh snapshot delete will erase committed file if exist so we don't need to manually tamper with xml file
|
||||
virsh snapshot-delete --current $vm
|
||||
# TODO: test2
|
||||
#virsh dumpxml --inactive --security-info "$vm" > "${ROOT_DIR}/$vm.xml.temp"
|
||||
|
@ -248,7 +248,7 @@ function main {
|
|||
# Make sure we remove snapshots no matter what
|
||||
trap 'cleanup' INT HUP TERM QUIT ERR EXIT
|
||||
|
||||
log "#### Make sure all template variables are encypted"
|
||||
log "#### Make sure all template variables are encrypted"
|
||||
"${NPBACKUP_EXECUTABLE}" -c "${NPBACKUP_CONF_FILE_TEMPLATE}" --check-config-file
|
||||
|
||||
log "#### Running backup `date`"
|
||||
|
|
|
@ -9,7 +9,7 @@ backup:
|
|||
- excludes/generic_excludes
|
||||
#- excludes/windows_excludes
|
||||
- excludes/linux_excludes
|
||||
exclude_case_ignore: false # Exclusions will always have case ignored on Windows systems regarless of this setting
|
||||
exclude_case_ignore: false # Exclusions will always have case ignored on Windows systems regardless of this setting
|
||||
one_file_system: true
|
||||
## Paths can contain multiple values, one per line, without quotation marks
|
||||
paths: path_to_directory
|
||||
|
|
|
@ -9,7 +9,7 @@ backup:
|
|||
- excludes/generic_excludes
|
||||
- excludes/windows_excludes
|
||||
#- excludes/linux_excludes
|
||||
exclude_case_ignore: false # Exclusions will always have case ignored on Windows systems regarless of this setting
|
||||
exclude_case_ignore: false # Exclusions will always have case ignored on Windows systems regardless of this setting
|
||||
one_file_system: true
|
||||
## Paths can contain multiple values, one per line, without quotation marks
|
||||
paths: path_to_directory
|
||||
|
|
|
@ -151,7 +151,7 @@
|
|||
?:\Users\*\AppData\LocalLow
|
||||
?:\Users\*\Tracing
|
||||
|
||||
# Generic system file exlusions
|
||||
# Generic system file exclusions
|
||||
**\MSOCache
|
||||
**\MSOCache.*
|
||||
**\Config.Msi
|
||||
|
|
|
@ -8,7 +8,7 @@ __author__ = "Orsiris de Jong"
|
|||
__site__ = "https://www.netperfect.fr/npbackup"
|
||||
__description__ = "NetPerfect Backup Client"
|
||||
__copyright__ = "Copyright (C) 2023-2025 NetInvent"
|
||||
__build__ = "2024101201"
|
||||
__build__ = "2025021901"
|
||||
|
||||
|
||||
import sys
|
||||
|
@ -23,7 +23,7 @@ import json
|
|||
logger = getLogger()
|
||||
|
||||
|
||||
# If set, debugging will be enabled by setting envrionment variable to __SPECIAL_DEBUG_STRING content
|
||||
# If set, debugging will be enabled by setting environment variable to __SPECIAL_DEBUG_STRING content
|
||||
# Else, a simple true or false will suffice
|
||||
__SPECIAL_DEBUG_STRING = ""
|
||||
__debug_os_env = os.environ.get("_DEBUG", "False").strip("'\"")
|
||||
|
@ -57,7 +57,7 @@ _NPBACKUP_ALLOW_AUTOUPGRADE_DEBUG = (
|
|||
|
||||
def exception_to_string(exc):
|
||||
"""
|
||||
Transform a catched exception to a string
|
||||
Transform a caught exception to a string
|
||||
https://stackoverflow.com/a/37135014/2635443
|
||||
"""
|
||||
stack = traceback.extract_stack()[:-3] + traceback.extract_tb(
|
||||
|
|
|
@ -402,7 +402,7 @@ This is free software, and you are welcome to redistribute it under certain cond
|
|||
json_error_logging(False, msg, "critical")
|
||||
sys.exit(71)
|
||||
|
||||
# This must be run before any other command since it's the way we're checking succesful upgrade processes
|
||||
# This must be run before any other command since it's the way we're checking successful upgrade processes
|
||||
# So any pre-upgrade process command shall be bypassed when this is executed
|
||||
if args.check_config_file:
|
||||
json_error_logging(True, "Config file seems valid", "info")
|
||||
|
|
|
@ -23,7 +23,7 @@ from npbackup.core.nuitka_helper import IS_COMPILED
|
|||
|
||||
|
||||
# Python 3.7 versions are considered legacy since they don't support msgspec
|
||||
# Since developpment currently follows Python 3.12, let's consider anything below 3.12 as legacy
|
||||
# Since development currently follows Python 3.12, let's consider anything below 3.12 as legacy
|
||||
IS_LEGACY = True if sys.version_info[1] < 12 else False
|
||||
|
||||
try:
|
||||
|
|
|
@ -593,7 +593,7 @@ def get_repo_config(
|
|||
"""
|
||||
Create inherited repo config
|
||||
Returns a dict containing the repo config, with expanded variables
|
||||
and a dict containing the repo interitance status
|
||||
and a dict containing the repo inheritance status
|
||||
"""
|
||||
|
||||
def inherit_group_settings(
|
||||
|
@ -720,7 +720,7 @@ def get_repo_config(
|
|||
else:
|
||||
_config_inheritance.g(key)[v] = False
|
||||
else:
|
||||
# In other cases, just keep repo confg
|
||||
# In other cases, just keep repo config
|
||||
_config_inheritance.s(key, False)
|
||||
|
||||
return _repo_config, _config_inheritance
|
||||
|
@ -859,7 +859,7 @@ def load_config(config_file: Path) -> Optional[dict]:
|
|||
config_file_is_updated = False
|
||||
|
||||
# Make sure we expand every key that should be a list into a list
|
||||
# We'll use iter_over_keys instead of replace_in_iterable to avoid chaning list contents by lists
|
||||
# We'll use iter_over_keys instead of replace_in_iterable to avoid changing list contents by lists
|
||||
# This basically allows "bad" formatted (ie manually written yaml) to be processed correctly
|
||||
# without having to deal with various errors
|
||||
def _make_struct(key: str, value: Union[str, int, float, dict, list]) -> Any:
|
||||
|
|
|
@ -221,7 +221,7 @@ class NPBackupRunner:
|
|||
self._live_output = False
|
||||
self._json_output = False
|
||||
# struct_output is msgspec.Struct instead of json, which is less memory consuming
|
||||
# struct_output neeeds json_output to be True
|
||||
# struct_output needs json_output to be True
|
||||
self._struct_output = False
|
||||
self._binary = None
|
||||
self._no_cache = False
|
||||
|
@ -551,7 +551,7 @@ class NPBackupRunner:
|
|||
}
|
||||
try:
|
||||
# When running group_runner, we need to extract operation from kwargs
|
||||
# else, operarion is just the wrapped function name
|
||||
# else, operation is just the wrapped function name
|
||||
# pylint: disable=E1101 (no-member)
|
||||
if fn.__name__ == "group_runner":
|
||||
operation = kwargs.get("operation")
|
||||
|
@ -686,7 +686,7 @@ class NPBackupRunner:
|
|||
js = {
|
||||
"result": False,
|
||||
"operation": operation,
|
||||
"reason": f"Runner catched exception: {exception_to_string(exc)}",
|
||||
"reason": f"Runner caught exception: {exception_to_string(exc)}",
|
||||
}
|
||||
return js
|
||||
return False
|
||||
|
@ -804,7 +804,7 @@ class NPBackupRunner:
|
|||
except KeyError:
|
||||
pass
|
||||
except ValueError:
|
||||
self.write_logs("Bogus backend connections value given.", level="erorr")
|
||||
self.write_logs("Bogus backend connections value given.", level="error")
|
||||
try:
|
||||
if self.repo_config.g("backup_opts.priority"):
|
||||
self.restic_runner.priority = self.repo_config.g("backup_opts.priority")
|
||||
|
@ -1490,7 +1490,7 @@ class NPBackupRunner:
|
|||
self.write_logs(msg, level="critical")
|
||||
return self.convert_to_json_output(False, msg)
|
||||
|
||||
# Build policiy from config
|
||||
# Build policy from config
|
||||
policy = {}
|
||||
for entry in ["last", "hourly", "daily", "weekly", "monthly", "yearly"]:
|
||||
value = self.repo_config.g(f"repo_opts.retention_policy.{entry}")
|
||||
|
@ -1551,7 +1551,7 @@ class NPBackupRunner:
|
|||
Runs unlock, check, forget and prune in one go
|
||||
"""
|
||||
self.write_logs("Running housekeeping", level="info")
|
||||
# Add special keywors __no_threads since we're already threaded in housekeeping function
|
||||
# Add special keywords __no_threads since we're already threaded in housekeeping function
|
||||
# Also, pass it as kwargs to make linter happy
|
||||
kwargs = {"__no_threads": True, "__close_queues": False}
|
||||
# pylint: disable=E1123 (unexpected-keyword-arg)
|
||||
|
|
|
@ -46,12 +46,12 @@ def need_upgrade(upgrade_interval: int) -> bool:
|
|||
|
||||
def _get_count(file: str) -> Optional[int]:
|
||||
try:
|
||||
with open(file, "r", encoding="utf-8") as fpr:
|
||||
count = int(fpr.read())
|
||||
with open(file, "r", encoding="utf-8") as fp:
|
||||
count = int(fp.read())
|
||||
return count
|
||||
except OSError as exc:
|
||||
# We may not have read privileges
|
||||
logger.eror(f"Cannot read upgrade counter file {file}: {exc}")
|
||||
logger.error(f"Cannot read upgrade counter file {file}: {exc}")
|
||||
except ValueError as exc:
|
||||
logger.error(f"Bogus upgrade counter in {file}: {exc}")
|
||||
return None
|
||||
|
|
|
@ -201,7 +201,7 @@ def _make_treedata_from_json(ls_result: List[dict]) -> sg.TreeData:
|
|||
{'name': 'xmfbox.tcl', 'type': 'file', 'path': '/C/GIT/npbackup/npbackup.dist/tk/xmfbox.tcl', 'uid': 0, 'gid': 0, 'size': 27064, 'mode': 438, 'permissions': '-rw-rw-rw-', 'mtime': '2022-09-05T14:18:52+02:00', 'atime': '2022-09-05T14:18:52+02:00', 'ctime': '2022-09-05T14:18:52+02:00', 'struct_type': 'node'}
|
||||
]
|
||||
|
||||
Since v3-rc6, we're actually using a msgspec.Struct represenation which uses dot notation, but only on Python 3.8+
|
||||
Since v3-rc6, we're actually using a msgspec.Struct representation which uses dot notation, but only on Python 3.8+
|
||||
We still rely on json for Python 3.7
|
||||
"""
|
||||
treedata = sg.TreeData()
|
||||
|
@ -674,7 +674,7 @@ def _main_gui(viewer_mode: bool):
|
|||
"%Y-%m-%d %H:%M:%S"
|
||||
)
|
||||
else:
|
||||
snapshot_date = "Unparseable"
|
||||
snapshot_date = "Unparsable"
|
||||
snapshot_username = snapshot["username"]
|
||||
snapshot_hostname = snapshot["hostname"]
|
||||
snapshot_id = snapshot["short_id"]
|
||||
|
|
|
@ -79,7 +79,7 @@ def ask_manager_password(manager_password: str) -> bool:
|
|||
def config_gui(full_config: dict, config_file: str):
|
||||
logger.info("Launching configuration GUI")
|
||||
|
||||
# Don't let SimpleGUI handle key errros since we might have new keys in config file
|
||||
# Don't let SimpleGUI handle key errors since we might have new keys in config file
|
||||
sg.set_options(
|
||||
suppress_raise_key_errors=True,
|
||||
suppress_error_popups=True,
|
||||
|
@ -588,7 +588,7 @@ def config_gui(full_config: dict, config_file: str):
|
|||
|
||||
# First we need to clear the whole GUI to reload new values
|
||||
for key in window.AllKeysDict:
|
||||
# We only clear config keys, wihch have '.' separator
|
||||
# We only clear config keys, which have '.' separator
|
||||
if "." in str(key) and not "inherited" in str(key):
|
||||
if isinstance(window[key], sg.Tree):
|
||||
window[key].Update(sg.TreeData())
|
||||
|
@ -909,7 +909,7 @@ def config_gui(full_config: dict, config_file: str):
|
|||
],
|
||||
]
|
||||
|
||||
# We need to set current_manager_password variable to make sure we have sufficient permissions to modifiy settings
|
||||
# We need to set current_manager_password variable to make sure we have sufficient permissions to modify settings
|
||||
full_config.s(
|
||||
f"{object_type}.{object_name}.current_manager_password",
|
||||
full_config.g(f"{object_type}.{object_name}.manager_password"),
|
||||
|
@ -1989,7 +1989,7 @@ Google Cloud storage: GOOGLE_PROJECT_ID GOOGLE_APPLICATION_CREDENTIALS\n\
|
|||
|
||||
def global_options_layout():
|
||||
""" "
|
||||
Returns layout for global options that can't be overrided by group / repo settings
|
||||
Returns layout for global options that can't be overridden by group / repo settings
|
||||
"""
|
||||
identity_col = [
|
||||
[sg.Text(_t("config_gui.available_variables_id"))],
|
||||
|
|
|
@ -318,7 +318,7 @@ def gui_thread_runner(
|
|||
read_queues = read_stdout_queue or read_stderr_queue
|
||||
|
||||
if not read_queues:
|
||||
# Arbitrary wait time so window get's time to get fully drawn
|
||||
# Arbitrary wait time so window gets time to get fully drawn
|
||||
sleep(0.2)
|
||||
break
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@ def restic_json_to_prometheus(
|
|||
found = True
|
||||
break
|
||||
if not found:
|
||||
logger.critical("Bogus data given. No message_type: summmary found")
|
||||
logger.critical("Bogus data given. No message_type: summary found")
|
||||
return False, [], True
|
||||
|
||||
if not isinstance(restic_json, dict):
|
||||
|
|
|
@ -135,7 +135,7 @@ class ResticRunner:
|
|||
|
||||
for env_variable, value in self.environment_variables.items():
|
||||
self.write_logs(
|
||||
f'Setting envrionment variable "{env_variable}"', level="debug"
|
||||
f'Setting environment variable "{env_variable}"', level="debug"
|
||||
)
|
||||
os.environ[env_variable] = value
|
||||
|
||||
|
@ -144,7 +144,7 @@ class ResticRunner:
|
|||
value,
|
||||
) in self.encrypted_environment_variables.items():
|
||||
self.write_logs(
|
||||
f'Setting encrypted envrionment variable "{encrypted_env_variable}"',
|
||||
f'Setting encrypted environment variable "{encrypted_env_variable}"',
|
||||
level="debug",
|
||||
)
|
||||
os.environ[encrypted_env_variable] = value
|
||||
|
@ -359,7 +359,7 @@ class ResticRunner:
|
|||
self.write_logs(
|
||||
"Running in dry mode. No modifications will be done", level="info"
|
||||
)
|
||||
# Replace first occurence of possible operation
|
||||
# Replace first occurrence of possible operation
|
||||
cmd = cmd.replace(operation, f"{operation} --dry-run", 1)
|
||||
|
||||
_cmd = f'"{self._binary}"{additional_parameters}{self.generic_arguments} {cmd}'
|
||||
|
@ -607,7 +607,7 @@ class ResticRunner:
|
|||
Init repository. Let's make sure we always run in JSON mode so we don't need
|
||||
horrendous regexes to find whether initialized
|
||||
|
||||
--json output when inializing:
|
||||
--json output when initializing:
|
||||
{"message_type":"initialized","id":"8daef59e2ac4c86535ae3f7414fcac6534f270077176af3ebddd34c364cac3c2","repository":"c:\\testy"}
|
||||
--json output when already initialized (is not json !!!)
|
||||
"""
|
||||
|
@ -1345,13 +1345,13 @@ class ResticRunner:
|
|||
snapshot_list: List, delta: int = None
|
||||
) -> Tuple[bool, Optional[datetime]]:
|
||||
"""
|
||||
Making the actual comparaison a static method so we can call it from GUI too
|
||||
Making the actual comparison a static method so we can call it from GUI too
|
||||
|
||||
Expects a restic snasphot_list (which is most recent at the end ordered)
|
||||
Returns bool if delta (in minutes) is not reached since last successful backup, and returns the last backup timestamp
|
||||
"""
|
||||
backup_ts = datetime(1, 1, 1, 0, 0)
|
||||
# Don't bother to deal with mising delta or snapshot list
|
||||
# Don't bother to deal with missing delta or snapshot list
|
||||
if not snapshot_list or not delta:
|
||||
return False, backup_ts
|
||||
tz_aware_timestamp = datetime.now(timezone.utc).astimezone()
|
||||
|
@ -1376,7 +1376,7 @@ class ResticRunner:
|
|||
"""
|
||||
Checks if a snapshot exists that is newer that delta minutes
|
||||
Eg: if delta = -60 we expect a snapshot newer than an hour ago, and return True if exists
|
||||
if delta = +60 we expect a snpashot newer than one hour in future (!)
|
||||
if delta = +60 we expect a snapshot newer than one hour in future (!)
|
||||
|
||||
returns True, datetime if exists
|
||||
returns False, datetime if exists but too old
|
||||
|
@ -1386,7 +1386,7 @@ class ResticRunner:
|
|||
kwargs = locals()
|
||||
kwargs.pop("self")
|
||||
|
||||
# Don't bother to deal with mising delta
|
||||
# Don't bother to deal with missing delta
|
||||
if not delta:
|
||||
if self.json_output:
|
||||
msg = "No delta given"
|
||||
|
|
|
@ -62,7 +62,7 @@ def entrypoint(*args, **kwargs):
|
|||
)
|
||||
if not json_output:
|
||||
if not isinstance(result, bool):
|
||||
# We need to temprarily remove the stdout handler
|
||||
# We need to temporarily remove the stdout handler
|
||||
# Since we already get live output from the runner
|
||||
# Unless operation is "ls", because it's too slow for command_runner poller method that allows live_output
|
||||
# But we still need to log the result to our logfile
|
||||
|
|
|
@ -308,8 +308,8 @@ def create_scheduled_task_windows(
|
|||
</Exec>
|
||||
</Actions>
|
||||
</Task>"""
|
||||
# Create task file, without specific encoding in order to use platform prefered encoding
|
||||
# platform prefered encoding is locale.getpreferredencoding() (cp1252 on windows, utf-8 on linux)
|
||||
# Create task file, without specific encoding in order to use platform preferred encoding
|
||||
# platform preferred encoding is locale.getpreferredencoding() (cp1252 on windows, utf-8 on linux)
|
||||
try:
|
||||
# pylint: disable=W1514 (unspecified-encoding)
|
||||
with open(temp_task_file, "w") as file_handle:
|
||||
|
|
|
@ -28,7 +28,7 @@ en:
|
|||
one_per_line: one per line
|
||||
backup_priority: Backup priority
|
||||
additional_parameters: Additional parameters
|
||||
additional_backup_only_parameters: Additional backup only parmameters
|
||||
additional_backup_only_parameters: Additional backup only parameters
|
||||
|
||||
minimum_backup_age: Minimum delay between two backups
|
||||
backup_repo_uri: backup repo URI / path
|
||||
|
@ -55,7 +55,7 @@ en:
|
|||
saved_initial_config: If you saved your configuration, you may now reload this program
|
||||
bogus_config_file: Bogus configuration file found
|
||||
|
||||
encrypted_env_variables: Encrypted envrionment variables
|
||||
encrypted_env_variables: Encrypted environment variables
|
||||
env_variables: Environment variables
|
||||
|
||||
no_runner: Cannot connect to backend. Please see logs
|
||||
|
@ -85,7 +85,7 @@ en:
|
|||
create_backup_scheduled_task_at: Create scheduled backup task every day at
|
||||
create_housekeeping_scheduled_task_at: Create housekeeping scheduled every day at
|
||||
scheduled_task_explanation: Task can run at a given time to run a backup which is great to make server backups, or run every x minutes, but only run actual backup when more than maximum_backup_age minutes was reached, which is the best way to backup laptops which have flexible power on hours.
|
||||
scheduled_task_creation_success: Scheduled task created successfuly
|
||||
scheduled_task_creation_success: Scheduled task created successfully
|
||||
scheduled_task_creation_failure: Scheduled task could not be created. See logs for further info
|
||||
|
||||
machine_identification: Machine identification
|
||||
|
@ -93,7 +93,7 @@ en:
|
|||
machine_group: Machine group
|
||||
|
||||
show_decrypted: Show sensitive data
|
||||
no_manager_password_defined: No manager password defined, cannot show unencrypted. If you just set one, you need to save the confiugration before you can use it
|
||||
no_manager_password_defined: No manager password defined, cannot show unencrypted. If you just set one, you need to save the configuration before you can use it
|
||||
|
||||
# compression
|
||||
auto: Automatic
|
||||
|
@ -114,7 +114,7 @@ en:
|
|||
stdin_from_command: Standard input from command
|
||||
stdin_filename: Optional filename for stdin backed up data
|
||||
|
||||
# retention policiy
|
||||
# retention policy
|
||||
retention_policy: Retention policy
|
||||
keep: Keep
|
||||
last: last snapshots
|
||||
|
|
|
@ -24,7 +24,7 @@ en:
|
|||
old: Old
|
||||
up_to_date: Up to date
|
||||
unknown: Unknown
|
||||
not_connected_yet: Not conntected to repo
|
||||
not_connected_yet: Not connected to repo
|
||||
|
||||
size: Size
|
||||
path: Path
|
||||
|
@ -40,7 +40,7 @@ en:
|
|||
|
||||
is_uptodate: Program Up to date
|
||||
|
||||
succes: Succes
|
||||
succes: Success
|
||||
successfully: successfully
|
||||
failure: Failure
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ def check_private_ev():
|
|||
from PRIVATE._ev_data import AES_EV_KEY
|
||||
from PRIVATE._obfuscation import obfuscation
|
||||
|
||||
print("We have private EV certifcate DATA")
|
||||
print("We have private EV certificate DATA")
|
||||
return obfuscation(AES_EV_KEY)
|
||||
except ImportError as exc:
|
||||
print("ERROR: Cannot load private EV certificate DATA: {}".format(exc))
|
||||
|
|
|
@ -22,7 +22,7 @@ import json
|
|||
logger = getLogger()
|
||||
|
||||
|
||||
# If set, debugging will be enabled by setting envrionment variable to __SPECIAL_DEBUG_STRING content
|
||||
# If set, debugging will be enabled by setting environment variable to __SPECIAL_DEBUG_STRING content
|
||||
# Else, a simple true or false will suffice
|
||||
__SPECIAL_DEBUG_STRING = ""
|
||||
__debug_os_env = os.environ.get("_DEBUG", "False").strip("'\"")
|
||||
|
|
Loading…
Add table
Reference in a new issue