Allow housekeeping task creation, also fix double unix task entries

This commit is contained in:
deajan 2024-08-26 22:15:32 +02:00
parent eb71a8d2a8
commit 59c69a9b0a
5 changed files with 79 additions and 25 deletions

View file

@ -280,11 +280,18 @@ This is free software, and you are welcome to redistribute it under certain cond
help="Create a new encryption key, requires a file path", help="Create a new encryption key, requires a file path",
) )
parser.add_argument( parser.add_argument(
"--create-scheduled-task", "--create-backup-scheduled-task",
type=str, type=str,
default=None, default=None,
required=False, required=False,
help="Create a scheduled task, specify an argument interval via interval=minutes, or hour=hour,minute=minute for a daily task", help="Create a scheduled backup task, specify an argument interval via interval=minutes, or hour=hour,minute=minute for a daily task",
)
parser.add_argument(
"--create-housekeeping-scheduled-task",
type=str,
default=None,
required=False,
help="Create a scheduled housekeeping task, specify hour=hour,minute=minute for a daily task",
) )
args = parser.parse_args() args = parser.parse_args()
@ -354,22 +361,26 @@ This is free software, and you are welcome to redistribute it under certain cond
json_error_logging(False, msg, "critical") json_error_logging(False, msg, "critical")
sys.exit(71) sys.exit(71)
if args.create_scheduled_task: if args.create_backup_scheduled_task or args.create_housekeeping_scheduled_task:
try: try:
if "interval" in args.create_scheduled_task: if "interval" in args.create_scheduled_task:
interval = args.create_scheduled_task.split("=")[1].strip() interval = args.create_scheduled_task.split("=")[1].strip()
result = create_scheduled_task( result = create_scheduled_task(
config_file, interval_minutes=int(interval) config_file, type="backup", interval_minutes=int(interval)
) )
elif ( elif (
"hour" in args.create_scheduled_task "hour" in args.create_scheduled_task
and "minute" in args.create_scheduled_task and "minute" in args.create_scheduled_task
): ):
if args.create_backup_scheduled_task:
type = "backup"
if args.create_housekeeping_scheduled_task:
type = "housekeeping"
hours, minutes = args.create_scheduled_task.split(",") hours, minutes = args.create_scheduled_task.split(",")
hour = hours.split("=")[1].strip() hour = hours.split("=")[1].strip()
minute = minutes.split("=")[1].strip() minute = minutes.split("=")[1].strip()
result = create_scheduled_task( result = create_scheduled_task(
config_file, hour=int(hour), minute=int(minute) config_file, type=type, hour=int(hour), minute=int(minute)
) )
if not result: if not result:
msg = "Scheduled task creation failed" msg = "Scheduled task creation failed"

View file

@ -1921,18 +1921,29 @@ Google Cloud storage: GOOGLE_PROJECT_ID GOOGLE_APPLICATION_CREDENTIALS\n\
) )
], ],
[ [
sg.Text(_t("config_gui.create_scheduled_task_every"), size=(40, 1)), sg.Text(_t("config_gui.create_backup_scheduled_task_every"), size=(40, 1)),
sg.Input(key="scheduled_task_interval", size=(4, 1)), sg.Input(key="scheduled_task_interval", size=(4, 1)),
sg.Text(_t("generic.minutes"), size=(10, 1)), sg.Text(_t("generic.minutes"), size=(10, 1)),
sg.Button(_t("generic.create"), key="create_interval_task"), sg.Button(_t("generic.create"), key="create_backup_interval_task"),
], ],
[ [
sg.Text(_t("config_gui.create_scheduled_task_at"), size=(40, 1)), sg.Text(_t("config_gui.create_backup_scheduled_task_at"), size=(40, 1)),
sg.Input(key="scheduled_task_hour", size=(4, 1)), sg.Input(key="scheduled_task_hour", size=(4, 1)),
sg.Text(_t("generic.hours"), size=(10, 1)), sg.Text(_t("generic.hours"), size=(10, 1)),
sg.Input(key="scheduled_task_minute", size=(4, 1)), sg.Input(key="scheduled_task_minute", size=(4, 1)),
sg.Text(_t("generic.minutes"), size=(10, 1)), sg.Text(_t("generic.minutes"), size=(10, 1)),
sg.Button(_t("generic.create"), key="create_daily_task"), sg.Button(_t("generic.create"), key="create_backup_daily_task"),
],
[
sg.HorizontalSeparator(),
],
[
sg.Text(_t("config_gui.create_housekeeping_scheduled_task_at"), size=(40, 1)),
sg.Input(key="scheduled_task_hour", size=(4, 1)),
sg.Text(_t("generic.hours"), size=(10, 1)),
sg.Input(key="scheduled_task_minute", size=(4, 1)),
sg.Text(_t("generic.minutes"), size=(10, 1)),
sg.Button(_t("generic.create"), key="create_housekeeping_daily_task"),
], ],
] ]
@ -2255,10 +2266,15 @@ Google Cloud storage: GOOGLE_PROJECT_ID GOOGLE_APPLICATION_CREDENTIALS\n\
) )
update_global_gui(full_config, unencrypted=True) update_global_gui(full_config, unencrypted=True)
continue continue
if event in ("create_interval_task", "create_daily_task"): if event in ("create_backup_interval_task", "create_backup_daily_task", "create_housekeeping_daily_task"):
try: try:
if event == "create_housekeeping_daily_task":
type = "housekeeping"
else:
type = "backup"
result = create_scheduled_task( result = create_scheduled_task(
config_file, config_file,
type=type,
values["scheduled_task_interval"], values["scheduled_task_interval"],
values["scheduled_task_hour"], values["scheduled_task_hour"],
values["scheduled_task_minute"], values["scheduled_task_minute"],

View file

@ -7,7 +7,7 @@ __intname__ = "npbackup.task"
__author__ = "Orsiris de Jong" __author__ = "Orsiris de Jong"
__copyright__ = "Copyright (C) 2022-2024 NetInvent" __copyright__ = "Copyright (C) 2022-2024 NetInvent"
__license__ = "GPL-3.0-only" __license__ = "GPL-3.0-only"
__build__ = "2024081901" __build__ = "2024082601"
import sys import sys
@ -24,7 +24,7 @@ logger = getLogger()
def create_scheduled_task( def create_scheduled_task(
config_file: str, interval_minutes: int = None, hour: int = None, minute: int = None config_file: str, type: str, interval_minutes: int = None, hour: int = None, minute: int = None
): ):
""" """
Creates a scheduled task for NPBackup Creates a scheduled task for NPBackup
@ -42,6 +42,10 @@ def create_scheduled_task(
logger.error("Bogus interval given") logger.error("Bogus interval given")
return False return False
if type not in ("backup", "housekeeping"):
logger.error("Undefined task type")
return False
if isinstance(interval_minutes, int) and interval_minutes < 1: if isinstance(interval_minutes, int) and interval_minutes < 1:
logger.error("Bogus interval given") logger.error("Bogus interval given")
return False return False
@ -59,16 +63,17 @@ def create_scheduled_task(
if os.name == "nt": if os.name == "nt":
return create_scheduled_task_windows( return create_scheduled_task_windows(
config_file, CURRENT_EXECUTABLE, interval_minutes, hour, minute config_file, type, CURRENT_EXECUTABLE, interval_minutes, hour, minute
) )
else: else:
return create_scheduled_task_unix( return create_scheduled_task_unix(
config_file, CURRENT_EXECUTABLE, interval_minutes, hour, minute config_file, type, CURRENT_EXECUTABLE, interval_minutes, hour, minute
) )
def create_scheduled_task_unix( def create_scheduled_task_unix(
config_file, config_file,
type,
cli_executable_path, cli_executable_path,
interval_minutes: int = None, interval_minutes: int = None,
hour: int = None, hour: int = None,
@ -80,11 +85,12 @@ def create_scheduled_task_unix(
else: else:
cli_executable_path = f'"{cli_executable_path}"' cli_executable_path = f'"{cli_executable_path}"'
cron_file = "/etc/cron.d/npbackup" cron_file = "/etc/cron.d/npbackup"
if interval_minutes is not None: if interval_minutes is not None:
TASK_ARGS = f'-c "{config_file}" --backup --run-as-cli' TASK_ARGS = f'-c "{config_file}" --{type} --run-as-cli'
trigger = f"*/{interval_minutes} * * * *" trigger = f"*/{interval_minutes} * * * *"
elif hour is not None and minute is not None: elif hour is not None and minute is not None:
TASK_ARGS = f'-c "{config_file}" --backup --force --run-as-cli' TASK_ARGS = f'-c "{config_file}" --{type} --force --run-as-cli'
trigger = f"{minute} {hour} * * * root" trigger = f"{minute} {hour} * * * root"
else: else:
raise ValueError("Bogus trigger given") raise ValueError("Bogus trigger given")
@ -92,9 +98,24 @@ def create_scheduled_task_unix(
crontab_entry = ( crontab_entry = (
f'{trigger} cd "{executable_dir}" && {cli_executable_path} {TASK_ARGS}\n' f'{trigger} cd "{executable_dir}" && {cli_executable_path} {TASK_ARGS}\n'
) )
crontab_file = []
try:
with open(cron_file, "r", encoding="utf-8") as file_handle:
current_crontab = file_handle.readlines()
for line in current_crontab:
if "--{type}" in line:
logger.info("Replacing existing task")
crontab_file.append(crontab_entry)
else:
crontab_file.append(line)
except OSError as exc:
crontab_file.append(crontab_entry)
try: try:
with open(cron_file, "w", encoding="utf-8") as file_handle: with open(cron_file, "w", encoding="utf-8") as file_handle:
file_handle.write(crontab_entry) file_handle.writelines(crontab_file)
except OSError as exc: except OSError as exc:
logger.error("Could not write to file {}: {}".format(cron_file, exc)) logger.error("Could not write to file {}: {}".format(cron_file, exc))
return False return False
@ -104,6 +125,7 @@ def create_scheduled_task_unix(
def create_scheduled_task_windows( def create_scheduled_task_windows(
config_file, config_file,
type,
cli_executable_path, cli_executable_path,
interval_minutes: int = None, interval_minutes: int = None,
hour: int = None, hour: int = None,
@ -117,8 +139,11 @@ def create_scheduled_task_windows(
runner = cli_executable_path runner = cli_executable_path
task_args = "" task_args = ""
temp_task_file = os.path.join(tempfile.gettempdir(), "backup_task.xml") temp_task_file = os.path.join(tempfile.gettempdir(), "backup_task.xml")
task_name = f"{PROGRAM_NAME} {type}"
if interval_minutes is not None: if interval_minutes is not None:
task_args = f'{task_args}-c "{config_file}" --backup --run-as-cli' task_args = f'{task_args}-c "{config_file}" --{type} --run-as-cli'
start_date = datetime.datetime.now().replace(microsecond=0).isoformat() start_date = datetime.datetime.now().replace(microsecond=0).isoformat()
trigger = f"""<TimeTrigger> trigger = f"""<TimeTrigger>
<Repetition> <Repetition>
@ -205,15 +230,15 @@ def create_scheduled_task_windows(
# Setup task # Setup task
command_runner( command_runner(
'schtasks /DELETE /TN "{}" /F'.format(PROGRAM_NAME), 'schtasks /DELETE /TN "{}" /F'.format(task_name),
valid_exit_codes=[0, 1], valid_exit_codes=[0, 1],
windows_no_window=True, windows_no_window=True,
encoding="cp437", encoding="cp437",
) )
logger.info("Creating scheduled task {}".format(PROGRAM_NAME)) logger.info("Creating scheduled task {}".format(task_name))
exit_code, output = command_runner( exit_code, output = command_runner(
'schtasks /CREATE /TN "{}" /XML "{}" /RU System /F'.format( 'schtasks /CREATE /TN "{}" /XML "{}" /RU System /F'.format(
PROGRAM_NAME, temp_task_file task_name, temp_task_file
), ),
windows_no_window=True, windows_no_window=True,
encoding="cp437", encoding="cp437",

View file

@ -78,8 +78,9 @@ en:
auto_upgrade_failed: Auto upgrade procedure failed, see logs for further details auto_upgrade_failed: Auto upgrade procedure failed, see logs for further details
auto_upgrade_disabled: Auto upgrade is disabled or server is not reachable auto_upgrade_disabled: Auto upgrade is disabled or server is not reachable
create_scheduled_task_every: Create scheduled task every create_backup_scheduled_task_every: Create scheduled backup task every
create_scheduled_task_at: Create scheduled task at create_bakcup_scheduled_task_at: Create scheduled backup task every day at
create_housekeeping_schedule_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_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 successfuly
scheduled_task_creation_failure: Scheduled task could not be created. See logs for further info scheduled_task_creation_failure: Scheduled task could not be created. See logs for further info

View file

@ -79,8 +79,9 @@ fr:
auto_upgrade_failed: Procédure de mise à niveau échouée, veuillez consulter les journaux pour plus de détails auto_upgrade_failed: Procédure de mise à niveau échouée, veuillez consulter les journaux pour plus de détails
auto_upgrade_disabled: Mise à niveau automatique désactivée ou serveur injoignable auto_upgrade_disabled: Mise à niveau automatique désactivée ou serveur injoignable
create_scheduled_task_every: Créer une tâche planifiée toutes les create_backup_scheduled_task_every: Créer une tâche planifiée de sauvegarde toutes les
create_scheduled_task_at: Créer une tâche planifiée à create_backup_scheduled_task_at: Créer une tâche planifiée de sauvegarde tous les jours à
create_housekeeping_schedule_task_at: Créer une tpache planifiée de maintenance tous les jours à
scheduled_task_explanation: Les tâches planifiées peuvent être crées à heure fixe pour réaliser des sauvegardes serveur, ou toutes les x minutes, auquel cas la sauvegarde aura lieue uniquement si le temps minimal entre deux sauvegardes est dépassé, ce qui est adapté aux ordinateurs portables qui ont des heures de travail flexibles. scheduled_task_explanation: Les tâches planifiées peuvent être crées à heure fixe pour réaliser des sauvegardes serveur, ou toutes les x minutes, auquel cas la sauvegarde aura lieue uniquement si le temps minimal entre deux sauvegardes est dépassé, ce qui est adapté aux ordinateurs portables qui ont des heures de travail flexibles.
scheduled_task_creation_success: Tâche planifiée crée avec succès scheduled_task_creation_success: Tâche planifiée crée avec succès
scheduled_task_creation_failure: Impossible de créer la tâche planifiée. Veuillez consulter les journaux pour plus de détails scheduled_task_creation_failure: Impossible de créer la tâche planifiée. Veuillez consulter les journaux pour plus de détails