class DeleteOperation(Operation): """Delete a file or a directory. Please note that, for obvious reasons, failures cannot be undone. This operation will stop at the first encountered error""" __slots__ = "_path" # the path to delete name = "DeleteOperation" def __init__(self, transaction, path): super(DeleteOperation, self).__init__(transaction) self._path = Path(path) def apply(self): if self._dry_run(): return if self._path.isdir(): self.log.info("Deleting directory %s", self._path) self._path.rmtree() else: self.log.info("Deleting file %s", self._path) self._path.remove() # END perform actual removal def rollback(self): self.log.info("Deletion of filesystem items cannot be rolled back")
def _cleanup(self): """Remove all files created by us""" if self._generated_file: self._generated_file.close() file_path = Path(self._generated_file.name) if file_path.isfile(): file_path.remove() # end delete file self._generated_file = None
def communicate(self, process): # another test runs in here, but has no channel configured if process.stdout is None: return super(TestCommunicatorDelegate, self).communicate(process) # handle other test try: # output should be marker file err_lines = process.stderr.readlines() assert not err_lines lines = process.stdout.readlines() assert len(lines) == 1 tmpfile = Path(lines[0].decode().strip()) tmpfile.remove() finally: res = super(TestCommunicatorDelegate, self).communicate(process) assert res.returncode == 0, "There should have been no error" return res
class CreateFSItemOperation(FSOperationBase): """Create a directory or file with the given access permissions and ownership. In case of a file, you may specify an initial content. For this operation to succeed, the destination path must not exist yet!""" __slots__ = ("_path", "_content", "_mode", "_uid", "_gid") name = "CreateFSItem" def __init__(self, transaction, path, initial_file_content=None, mode=None, uid=None, gid=None): """Initialize the operation with a path to create. If initial_file_content is set, to a string, it will be written in binary mode to a file. If it is unset, a directory will be created. Non-existing parent-directories will be created. After creation, the mode will be set if not None, and uid and gid will be set as well to the given numerical ID if of of them is not None""" super(CreateFSItemOperation, self).__init__(transaction) self._assert_posix() self._path = Path(path) self._content = initial_file_content self._mode = mode self._uid = uid self._gid = gid def apply(self): if self._content and self._path.isdir() or not self._content and self._path.isfile(): raise AssertionError( "Cannot create item of type directory or file as the an equally named item of different type exists") # END sanity check if self._dry_run(): return if self._path.exists(): return # end ignore existing items of the same type # we don't do it the most efficient way, as we could specify certain things in # at creation. For now, we don't do it though as it shouldn't matter if self._content: self.log.info("creating file %s", self._path) self._path.write_bytes(self._content) else: self.log.info("creating directory %s", self._path) self._path.makedirs() # END initial creation self._operation_performed = True if self._mode is not None: self._path.chmod(self._mode) # END handle mode self.set_user_group(self._path, self._gid, self._uid) def rollback(self): try: if not self._operation_performed or not self._path.exists(): return if self._content: self.log.info("Removing file %s", self._path) self._path.remove() else: self.log.info("Removing single directory %s", self._path) self._path.rmdir() # END handle removal, safely as we don't recursively delete anything finally: self._reset_state()