forked from Github/Axter-Stash
Separated example and unit test task to separate files.
This commit is contained in:
@@ -9,7 +9,13 @@ import watchdog # pip install watchdog # https://pythonhosted.org/watchdog/
|
||||
from watchdog.observers import Observer # This is also needed for event attributes
|
||||
from threading import Lock, Condition
|
||||
from multiprocessing import shared_memory
|
||||
from filemonitor_config import config # Import settings from filemonitor_config.py
|
||||
from filemonitor_config import config
|
||||
from filemonitor_task_examples import task_examples
|
||||
from filemonitor_self_unit_test import self_unit_test
|
||||
|
||||
config['task_scheduler'] = config['task_scheduler'] + task_examples['task_scheduler']
|
||||
if self_unit_test['selfUnitTest']:
|
||||
config['task_scheduler'] = config['task_scheduler'] + self_unit_test['task_scheduler']
|
||||
|
||||
CONTINUE_RUNNING_SIG = 99
|
||||
STOP_RUNNING_SIG = 32
|
||||
@@ -74,11 +80,6 @@ fileExtTypes = stash.pluginConfig['fileExtTypes'].split(",") if stash.pluginConf
|
||||
includePathChanges = stash.pluginConfig['includePathChanges'] if len(stash.pluginConfig['includePathChanges']) > 0 else stash.STASH_PATHS
|
||||
excludePathChanges = stash.pluginConfig['excludePathChanges']
|
||||
|
||||
|
||||
stash.Trace(f"(apiKey={stash.API_KEY})")
|
||||
stash.Trace(f"(includePathChanges={includePathChanges})")
|
||||
|
||||
|
||||
if stash.DRY_RUN:
|
||||
stash.Log("Dry run mode is enabled.")
|
||||
stash.Trace(f"(SCAN_MODIFIED={SCAN_MODIFIED}) (SCAN_ON_ANY_EVENT={SCAN_ON_ANY_EVENT}) (RECURSIVE={RECURSIVE})")
|
||||
@@ -88,7 +89,6 @@ StartFileMonitorAsAServiceTaskName = "Start Library Monitor Service"
|
||||
StartFileMonitorAsAPluginTaskID = "start_library_monitor"
|
||||
StartFileMonitorAsAServiceTaskID = "start_library_monitor_service"
|
||||
|
||||
|
||||
FileMonitorPluginIsOnTaskQue = stash.CALLED_AS_STASH_PLUGIN
|
||||
StopLibraryMonitorWaitingInTaskQueue = False
|
||||
JobIdInTheQue = 0
|
||||
@@ -211,25 +211,7 @@ class StashScheduler: # Stash Scheduler
|
||||
elif task['task'] == "Generate":
|
||||
result = stash.metadata_generate()
|
||||
elif task['task'] == "Backup":
|
||||
stash.LogOnce("Note: Backup task does not get listed in the Task Queue, but user can verify that it started by looking in the Stash log file as an INFO level log line.")
|
||||
result = stash.backup_database()
|
||||
maximumBackup = stash.pluginSettings['zmaximumBackups']
|
||||
stash.Trace(f"maximumBackup={maximumBackup}")
|
||||
if "maxBackups" in task:
|
||||
maximumBackup = task['maxBackups']
|
||||
stash.Trace(f"maximumBackup={maximumBackup}")
|
||||
if isinstance(maximumBackup,str):
|
||||
maximumBackup = int(maximumBackup)
|
||||
if maximumBackup < 2:
|
||||
stash.TraceOnce(f"Skipping DB backup file trim because zmaximumBackups={maximumBackup}. Value has to be greater than 1.")
|
||||
elif 'backupDirectoryPath' in stash.STASH_CONFIGURATION:
|
||||
if len(stash.STASH_CONFIGURATION['backupDirectoryPath']) < 5:
|
||||
stash.TraceOnce(f"Skipping DB backup file trim because backupDirectoryPath length is to short. Len={len(stash.STASH_CONFIGURATION['backupDirectoryPath'])}. Only support length greater than 4 characters.")
|
||||
elif os.path.exists(stash.STASH_CONFIGURATION['backupDirectoryPath']):
|
||||
stash.LogOnce(f"Checking quantity of DB backups if path {stash.STASH_CONFIGURATION['backupDirectoryPath']} exceeds {maximumBackup} backup files.")
|
||||
self.trimDbFiles(stash.STASH_CONFIGURATION['backupDirectoryPath'], maximumBackup)
|
||||
else:
|
||||
stash.TraceOnce(f"Skipping DB backup file trim because backupDirectoryPath does NOT exist. backupDirectoryPath={stash.STASH_CONFIGURATION['backupDirectoryPath']}")
|
||||
result = self.runBackupTask(task)
|
||||
elif task['task'] == "Scan":
|
||||
result = stash.metadata_scan(paths=targetPaths)
|
||||
elif task['task'] == "Auto Tag":
|
||||
@@ -261,94 +243,138 @@ class StashScheduler: # Stash Scheduler
|
||||
Msg = task['msg']
|
||||
result = stash.TraceOnce(Msg)
|
||||
elif task['task'] == "CheckStashIsRunning":
|
||||
try:
|
||||
result = stash.stash_version()
|
||||
except:
|
||||
pass
|
||||
# Note: Can not call stash.Error if Stash is not running, because that might throw another exception.
|
||||
stash.Trace("Failed to get response from Stash.")
|
||||
if platform.system() == "Windows":
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-win.exe"]
|
||||
elif platform.system() == "Darwin": # MacOS
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep} stash-macos "]
|
||||
elif platform.system().lower().startswith("linux"):
|
||||
# ToDo: Need to verify this method will work for (stash-linux-arm32v6, stash-linux-arm32v7, and stash-linux-arm64v8)
|
||||
if platform.system().lower().find("32v6") > -1:
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux-arm32v6"]
|
||||
elif platform.system().lower().find("32v7") > -1:
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux-arm32v7"]
|
||||
elif platform.system().lower().find("64v8 ") > -1:
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux-arm64v8"]
|
||||
else:
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux"]
|
||||
elif platform.system().lower().startswith("freebsd"):
|
||||
args = [f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-freebsd"]
|
||||
elif 'command' not in task or task['command'] == "":
|
||||
stash.Trace("Error: Can not start Stash, because failed to determine platform OS. As a workaround, add 'command' field to this task.")
|
||||
return
|
||||
if 'command' in task and task['command'] != "":
|
||||
cmd = task['command'].replace("<stash_path>", f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}")
|
||||
args = [cmd]
|
||||
result = f"Execute process PID = {stash.ExecuteProcess(args)}"
|
||||
time.sleep(10)
|
||||
if "RunAfter" in task and len(task['RunAfter']) > 0:
|
||||
for runAfterTask in task['RunAfter']:
|
||||
self.runTask(runAfterTask)
|
||||
result = self.checkStashIsRunning(task)
|
||||
elif task['task'] == "python":
|
||||
if 'script' in task and task['script'] != "":
|
||||
script = task['script'].replace("<plugin_path>", f"{pathlib.Path(__file__).resolve().parent}{os.sep}")
|
||||
stash.Log(f"Executing python script {script}.")
|
||||
args = [script]
|
||||
if 'args' in task and len(task['args']) > 0:
|
||||
args = args + [task['args']]
|
||||
detached = True
|
||||
if 'detach' in task:
|
||||
detached = task['detach']
|
||||
result = f"Python process PID = {stash.ExecutePythonScript(args, ExecDetach=detached)}"
|
||||
else:
|
||||
stash.Error(f"Can not run task '{task['task']}', because it's missing 'script' field.")
|
||||
result = self.runPythonScript(task)
|
||||
elif task['task'] == "execute":
|
||||
if 'command' in task and task['command'] != "":
|
||||
cmd = task['command'].replace("<plugin_path>", f"{pathlib.Path(__file__).resolve().parent}{os.sep}")
|
||||
args = [cmd]
|
||||
if 'args' in task and len(task['args']) > 0:
|
||||
args = args + [task['args']]
|
||||
stash.Log(f"Executing command arguments {args}.")
|
||||
result = f"Execute process PID = {stash.ExecuteProcess(args)}"
|
||||
else:
|
||||
stash.Error(f"Can not run task '{task['task']}', because it's missing 'command' field.")
|
||||
result = self.runExecuteProcessTask(task)
|
||||
else:
|
||||
# ToDo: Add code to check if plugin is installed.
|
||||
try:
|
||||
if 'pluginId' in task and task['pluginId'] != "":
|
||||
invalidDir = False
|
||||
validDirMsg = ""
|
||||
if 'validateDir' in task and task['validateDir'] != "":
|
||||
invalidDir = True
|
||||
communityPluginPath = f"{stash.PLUGINS_PATH}{os.sep}community{os.sep}{task['validateDir']}"
|
||||
basePluginPath = f"{stash.PLUGINS_PATH}{os.sep}{task['validateDir']}"
|
||||
if os.path.exists(communityPluginPath):
|
||||
invalidDir = False
|
||||
validDirMsg = f"Valid path in {communityPluginPath}"
|
||||
elif os.path.exists(basePluginPath):
|
||||
invalidDir = False
|
||||
validDirMsg = f"Valid path in {basePluginPath}"
|
||||
if invalidDir:
|
||||
stash.Error(f"Could not run task '{task['task']}' because sub directory '{task['validateDir']}' does not exist under path '{stash.PLUGINS_PATH}'")
|
||||
else:
|
||||
stash.Trace(f"Running plugin task pluginID={task['pluginId']}, task name = {task['task']}. {validDirMsg}")
|
||||
stash.run_plugin_task(plugin_id=task['pluginId'], task_name=task['task'])
|
||||
else:
|
||||
stash.Error(f"Can not run task '{task['task']}', because it's an invalid task.")
|
||||
stash.LogOnce(f"If task '{task['task']}' is supposed to be a built-in task, check for correct task name spelling.")
|
||||
stash.LogOnce(f"If task '{task['task']}' is supposed to be a plugin, make sure to include the pluginId field in the task. task={task}")
|
||||
except Exception as e:
|
||||
stash.LogOnce(f"Failed to call plugin {task['task']} with plugin-ID {task['pluginId']}. Error: {e}")
|
||||
pass
|
||||
result = self.runPluginTask(task)
|
||||
|
||||
if result:
|
||||
stash.Trace(f"Task '{task['task']}' result={result}")
|
||||
|
||||
def runExecuteProcessTask(self, task):
|
||||
if 'command' in task and task['command'] != "":
|
||||
cmd = task['command'].replace("<plugin_path>", f"{pathlib.Path(__file__).resolve().parent}{os.sep}")
|
||||
args = [cmd]
|
||||
if 'args' in task and len(task['args']) > 0:
|
||||
args = args + [task['args']]
|
||||
stash.Log(f"Executing command arguments {args}.")
|
||||
return f"Execute process PID = {stash.ExecuteProcess(args)}"
|
||||
else:
|
||||
stash.Error(f"Can not run task '{task['task']}', because it's missing 'command' field.")
|
||||
return None
|
||||
|
||||
def runPythonScript(self, task):
|
||||
if 'script' in task and task['script'] != "":
|
||||
script = task['script'].replace("<plugin_path>", f"{pathlib.Path(__file__).resolve().parent}{os.sep}")
|
||||
stash.Log(f"Executing python script {script}.")
|
||||
args = [script]
|
||||
if 'args' in task and len(task['args']) > 0:
|
||||
args = args + [task['args']]
|
||||
detached = True
|
||||
if 'detach' in task:
|
||||
detached = task['detach']
|
||||
return f"Python process PID = {stash.ExecutePythonScript(args, ExecDetach=detached)}"
|
||||
else:
|
||||
stash.Error(f"Can not run task '{task['task']}', because it's missing 'script' field.")
|
||||
return None
|
||||
|
||||
def runPluginTask(self, task):
|
||||
# ToDo: Add code to check if plugin is installed.
|
||||
try:
|
||||
if 'pluginId' in task and task['pluginId'] != "":
|
||||
invalidDir = False
|
||||
validDirMsg = ""
|
||||
if 'validateDir' in task and task['validateDir'] != "":
|
||||
invalidDir = True
|
||||
communityPluginPath = f"{stash.PLUGINS_PATH}{os.sep}community{os.sep}{task['validateDir']}"
|
||||
basePluginPath = f"{stash.PLUGINS_PATH}{os.sep}{task['validateDir']}"
|
||||
if os.path.exists(communityPluginPath):
|
||||
invalidDir = False
|
||||
validDirMsg = f"Valid path in {communityPluginPath}"
|
||||
elif os.path.exists(basePluginPath):
|
||||
invalidDir = False
|
||||
validDirMsg = f"Valid path in {basePluginPath}"
|
||||
if invalidDir:
|
||||
stash.Error(f"Could not run task '{task['task']}' because sub directory '{task['validateDir']}' does not exist under path '{stash.PLUGINS_PATH}'")
|
||||
else:
|
||||
stash.Trace(f"Running plugin task pluginID={task['pluginId']}, task name = {task['task']}. {validDirMsg}")
|
||||
return stash.run_plugin_task(plugin_id=task['pluginId'], task_name=task['task'])
|
||||
else:
|
||||
stash.Error(f"Can not run task '{task['task']}', because it's an invalid task.")
|
||||
stash.LogOnce(f"If task '{task['task']}' is supposed to be a built-in task, check for correct task name spelling.")
|
||||
stash.LogOnce(f"If task '{task['task']}' is supposed to be a plugin, make sure to include the pluginId field in the task. task={task}")
|
||||
except Exception as e:
|
||||
stash.LogOnce(f"Failed to call plugin {task['task']} with plugin-ID {task['pluginId']}. Error: {e}")
|
||||
pass
|
||||
return None
|
||||
|
||||
def checkStashIsRunning(self, task):
|
||||
try:
|
||||
result = stash.stash_version()
|
||||
except:
|
||||
pass
|
||||
stash.Error("Failed to get response from Stash.")
|
||||
if platform.system() == "Windows":
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-win.exe"
|
||||
elif platform.system() == "Darwin": # MacOS
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep} stash-macos "
|
||||
elif platform.system().lower().startswith("linux"):
|
||||
# ToDo: Need to verify this method will work for (stash-linux-arm32v6, stash-linux-arm32v7, and stash-linux-arm64v8)
|
||||
if platform.system().lower().find("32v6") > -1:
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux-arm32v6"
|
||||
elif platform.system().lower().find("32v7") > -1:
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux-arm32v7"
|
||||
elif platform.system().lower().find("64v8 ") > -1:
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux-arm64v8"
|
||||
else:
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-linux"
|
||||
elif platform.system().lower().startswith("freebsd"):
|
||||
execPath = f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}stash-freebsd"
|
||||
elif 'command' not in task or task['command'] == "":
|
||||
stash.Error("Can not start Stash, because failed to determine platform OS. As a workaround, add 'command' field to this task.")
|
||||
return None
|
||||
|
||||
if 'command' in task and task['command'] != "":
|
||||
cmd = task['command'].replace("<stash_path>", f"{pathlib.Path(stash.PLUGINS_PATH).resolve().parent}{os.sep}")
|
||||
args = [cmd]
|
||||
else:
|
||||
if os.path.isfile(execPath):
|
||||
args = [execPath]
|
||||
else:
|
||||
stash.Error("Could not start Stash, because could not find executable Stash file '{execPath}'")
|
||||
return None
|
||||
result = f"Execute process PID = {stash.ExecuteProcess(args)}"
|
||||
time.sleep(10)
|
||||
if "RunAfter" in task and len(task['RunAfter']) > 0:
|
||||
for runAfterTask in task['RunAfter']:
|
||||
self.runTask(runAfterTask)
|
||||
return result
|
||||
|
||||
def runBackupTask(self, task):
|
||||
stash.LogOnce("Note: Backup task does not get listed in the Task Queue, but user can verify that it started by looking in the Stash log file as an INFO level log line.")
|
||||
result = stash.backup_database()
|
||||
maximumBackup = stash.pluginSettings['zmaximumBackups']
|
||||
stash.Trace(f"maximumBackup={maximumBackup}")
|
||||
if "maxBackups" in task:
|
||||
maximumBackup = task['maxBackups']
|
||||
stash.Trace(f"maximumBackup={maximumBackup}")
|
||||
if isinstance(maximumBackup,str):
|
||||
maximumBackup = int(maximumBackup)
|
||||
if maximumBackup < 2:
|
||||
stash.TraceOnce(f"Skipping DB backup file trim because zmaximumBackups={maximumBackup}. Value has to be greater than 1.")
|
||||
elif 'backupDirectoryPath' in stash.STASH_CONFIGURATION:
|
||||
if len(stash.STASH_CONFIGURATION['backupDirectoryPath']) < 5:
|
||||
stash.TraceOnce(f"Skipping DB backup file trim because backupDirectoryPath length is to short. Len={len(stash.STASH_CONFIGURATION['backupDirectoryPath'])}. Only support length greater than 4 characters.")
|
||||
elif os.path.exists(stash.STASH_CONFIGURATION['backupDirectoryPath']):
|
||||
stash.LogOnce(f"Checking quantity of DB backups if path {stash.STASH_CONFIGURATION['backupDirectoryPath']} exceeds {maximumBackup} backup files.")
|
||||
self.trimDbFiles(stash.STASH_CONFIGURATION['backupDirectoryPath'], maximumBackup)
|
||||
else:
|
||||
stash.TraceOnce(f"Skipping DB backup file trim because backupDirectoryPath does NOT exist. backupDirectoryPath={stash.STASH_CONFIGURATION['backupDirectoryPath']}")
|
||||
return result
|
||||
|
||||
def trimDbFiles(self, dbPath, maxFiles):
|
||||
if not os.path.exists(dbPath):
|
||||
stash.LogOnce(f"Exiting trimDbFiles, because path {dbPath} does not exists.")
|
||||
|
||||
Reference in New Issue
Block a user