qq_lib.wipe
Utilities for removing the working directory of a qq job.
This module defines the Wiper class, an extension of Navigator responsible for
safely deleting a job's remote working directory once it is no longer needed.
Wiper distinguishes between shared-storage jobs and scratch-based jobs, and
guards against accidental deletion of the job's input directory.
1# Released under MIT License. 2# Copyright (c) 2025-2026 Ladislav Bartos and Robert Vacha Lab 3 4""" 5Utilities for removing the working directory of a qq job. 6 7This module defines the `Wiper` class, an extension of `Navigator` responsible for 8safely deleting a job's remote working directory once it is no longer needed. 9 10`Wiper` distinguishes between shared-storage jobs and scratch-based jobs, and 11guards against accidental deletion of the job's input directory. 12""" 13 14from .wiper import Wiper 15 16__all__ = [ 17 "Wiper", 18]
13class Wiper(Navigator): 14 """ 15 Class to manage deleting working directory of a job. 16 """ 17 18 def ensure_suitable(self) -> None: 19 """ 20 Verify that the job is in a state where its working directory can be deleted. 21 22 Raises: 23 QQNotSuitableError: If the working directory is not expected to exist 24 or if the working directory is the input directory. 25 """ 26 if self._work_dir_is_input_dir(): 27 raise QQNotSuitableError( 28 "Working directory of the job is the input directory of the job. Cannot delete the input directory." 29 ) 30 31 if self._is_queued(): 32 raise QQNotSuitableError( 33 f"Job is {str(self._informer.get_real_state()).lower()} and does not have a working directory yet." 34 ) 35 36 if self._is_running() or self._is_suspended(): 37 raise QQNotSuitableError( 38 f"Job is {str(self._informer.get_real_state()).lower()}. It is not safe to delete the working directory." 39 ) 40 41 if self._is_synchronized(): 42 raise QQNotSuitableError( 43 "Job has been completed and was synchronized: working directory no longer exists." 44 ) 45 46 if self._is_finished(): 47 raise QQNotSuitableError( 48 "It may not be safe to delete the working directory of a successfully finished job. Rerun as 'qq wipe --force' if sure." 49 ) 50 51 if not self.has_destination(): 52 raise QQNotSuitableError("Job does not have a working directory.") 53 54 def wipe(self) -> str: 55 """ 56 Delete the working directory on the computing node. 57 58 Returns: 59 str: The identifier of the job which working directory was deleted. 60 61 Raises: 62 QQError: If the working directory of the job does not exist or cannot be deleted. 63 """ 64 if not self.has_destination(): 65 raise QQError( 66 "Host ('main_node') or working directory ('work_dir') are not defined." 67 ) 68 69 # hint for type checker 70 # work_dir and main_node must be set - we check that in self.hasDestination 71 assert self._work_dir and self._main_node 72 73 # we cannot delete the input directory even if the `--force` flag is used 74 if self._work_dir_is_input_dir(): 75 raise QQError( 76 "Working directory of the job is the input directory of the job. Cannot delete the input directory." 77 ) 78 79 logger.info( 80 f"Deleting working directory '{str(self._work_dir)}' on '{self._main_node}'." 81 ) 82 self._batch_system.delete_remote_dir(self._main_node, self._work_dir) 83 84 return self._informer.info.job_id
Class to manage deleting working directory of a job.
def
ensure_suitable(self) -> None:
18 def ensure_suitable(self) -> None: 19 """ 20 Verify that the job is in a state where its working directory can be deleted. 21 22 Raises: 23 QQNotSuitableError: If the working directory is not expected to exist 24 or if the working directory is the input directory. 25 """ 26 if self._work_dir_is_input_dir(): 27 raise QQNotSuitableError( 28 "Working directory of the job is the input directory of the job. Cannot delete the input directory." 29 ) 30 31 if self._is_queued(): 32 raise QQNotSuitableError( 33 f"Job is {str(self._informer.get_real_state()).lower()} and does not have a working directory yet." 34 ) 35 36 if self._is_running() or self._is_suspended(): 37 raise QQNotSuitableError( 38 f"Job is {str(self._informer.get_real_state()).lower()}. It is not safe to delete the working directory." 39 ) 40 41 if self._is_synchronized(): 42 raise QQNotSuitableError( 43 "Job has been completed and was synchronized: working directory no longer exists." 44 ) 45 46 if self._is_finished(): 47 raise QQNotSuitableError( 48 "It may not be safe to delete the working directory of a successfully finished job. Rerun as 'qq wipe --force' if sure." 49 ) 50 51 if not self.has_destination(): 52 raise QQNotSuitableError("Job does not have a working directory.")
Verify that the job is in a state where its working directory can be deleted.
Raises:
- QQNotSuitableError: If the working directory is not expected to exist or if the working directory is the input directory.
def
wipe(self) -> str:
54 def wipe(self) -> str: 55 """ 56 Delete the working directory on the computing node. 57 58 Returns: 59 str: The identifier of the job which working directory was deleted. 60 61 Raises: 62 QQError: If the working directory of the job does not exist or cannot be deleted. 63 """ 64 if not self.has_destination(): 65 raise QQError( 66 "Host ('main_node') or working directory ('work_dir') are not defined." 67 ) 68 69 # hint for type checker 70 # work_dir and main_node must be set - we check that in self.hasDestination 71 assert self._work_dir and self._main_node 72 73 # we cannot delete the input directory even if the `--force` flag is used 74 if self._work_dir_is_input_dir(): 75 raise QQError( 76 "Working directory of the job is the input directory of the job. Cannot delete the input directory." 77 ) 78 79 logger.info( 80 f"Deleting working directory '{str(self._work_dir)}' on '{self._main_node}'." 81 ) 82 self._batch_system.delete_remote_dir(self._main_node, self._work_dir) 83 84 return self._informer.info.job_id
Delete the working directory on the computing node.
Returns:
str: The identifier of the job which working directory was deleted.
Raises:
- QQError: If the working directory of the job does not exist or cannot be deleted.