def test_backup(self, backup_lock_mock, archive_wal_mock, backup_manager_mock, dir_mock, check_mock, capsys): """ :param backup_lock_mock: mock ServerBackupLock :param archive_wal_mock: mock archive_wal server method :param backup_manager_mock: mock BackupManager.backup :param dir_mock: mock _make_directories :param check_mock: mock check """ # Create server server = build_real_server() dir_mock.side_effect = OSError() server.backup() out, err = capsys.readouterr() assert 'failed to create' in err dir_mock.side_effect = None server.backup() backup_manager_mock.assert_called_once_with() archive_wal_mock.assert_called_once_with(verbose=False) backup_manager_mock.side_effect = LockFileBusy() server.backup() out, err = capsys.readouterr() assert 'Another backup process is running' in err backup_manager_mock.side_effect = LockFilePermissionDenied() server.backup() out, err = capsys.readouterr() assert 'Permission denied, unable to access' in err
def acquire(self, raise_if_fail=None, wait=None, update_pid=True): """ Creates and holds on to the lock file. When raise_if_fail, a LockFileBusy is raised if the lock is held by someone else and a LockFilePermissionDenied is raised when the user executing barman have insufficient rights for the creation of a LockFile. Returns True if lock has been successfully acquired, False otherwise. :param bool raise_if_fail: If True raise an exception on failure :param bool wait: If True issue a blocking request :param bool update_pid: Whether to write our pid in the lockfile :returns bool: whether the lock has been acquired """ if self.fd: return True fd = None # method arguments take precedence on class parameters raise_if_fail = raise_if_fail \ if raise_if_fail is not None else self.raise_if_fail wait = wait if wait is not None else self.wait try: # 384 is 0600 in octal, 'rw-------' fd = os.open(self.filename, os.O_CREAT | os.O_RDWR, 384) flags = fcntl.LOCK_EX if not wait: flags |= fcntl.LOCK_NB fcntl.flock(fd, flags) if update_pid: # Once locked, replace the content of the file os.lseek(fd, 0, os.SEEK_SET) os.write(fd, ("%s\n" % os.getpid()).encode('ascii')) # Truncate the file at the current position os.ftruncate(fd, os.lseek(fd, 0, os.SEEK_CUR)) self.fd = fd return True except (OSError, IOError) as e: if fd: os.close(fd) # let's not leak file descriptors if raise_if_fail: if e.errno in (errno.EAGAIN, errno.EWOULDBLOCK): raise LockFileBusy(self.filename) elif e.errno == errno.EACCES: raise LockFilePermissionDenied(self.filename) else: raise else: return False