Beispiel #1
0
class _Reader(io.RawIOBase):
    """ Context Manager to read a snapshot. """
    def __init__(self, process, stream, path, diff, showProgress):
        self.process = process
        self.stream = stream
        self.path = path
        self.diff = diff
        self.bytesRead = None
        self.progress = DisplayProgress() if showProgress else None

    def __enter__(self):
        self.bytesRead = 0
        if self.progress is not None:
            self.progress.open()
        return self

    def __exit__(self, exceptionType, exception, trace):
        self.stream.close()

        if self.progress is not None:
            self.progress.close()

        if self.process is None:
            return

        logger.debug("Waiting for send process to finish...")
        self.process.wait()

        if self.process.returncode != 0:
            logger.error("btrfs send errors")
            for line in self.process.stderr:
                sys.stderr.write(line)

        if exception is None and self.process.returncode != 0:
            raise Exception("send returned error %d. %s may be corrupt." %
                            (self.process.returncode, self.path))

    def read(self, size):
        # If it's the first big chunk (header)
        # Tweak the volume information to match what we expect.
        data = self.stream.read(size)
        if FIXUP_DURING_SEND and self.bytesRead == 0:
            data = send.replaceIDs(
                data,
                self.diff.toUUID,
                self.diff.toGen,
                self.diff.fromUUID,
                self.diff.fromGen,
            )
        self.bytesRead += len(data)
        if self.progress is not None:
            self.progress.update(self.bytesRead)
        return data

    def seek(self, offset, whence):
        self.stream.seek(offset, offset, whence)
        if whence == io.SEEK_SET:
            self.bytesRead = offset
        elif whence == io.SEEK_CUR:
            pass
        elif whence == io.SEEK_END:
            self.bytesRead = None
Beispiel #2
0
class _Reader(io.RawIOBase):

    """ Context Manager to read a snapshot. """

    def __init__(self, process, stream, path, diff, showProgress):
        self.process = process
        self.stream = stream
        self.path = path
        self.diff = diff
        self.bytesRead = None
        self.progress = DisplayProgress() if showProgress else None

    def __enter__(self):
        self.bytesRead = 0
        if self.progress is not None:
            self.progress.open()
        return self

    def __exit__(self, exceptionType, exception, trace):
        self.stream.close()

        if self.progress is not None:
            self.progress.close()

        if self.process is None:
            return

        logger.debug("Waiting for send process to finish...")
        self.process.wait()

        if self.process.returncode != 0:
            logger.error("btrfs send errors")
            for line in self.process.stderr:
                sys.stderr.write(line)

        if exception is None and self.process.returncode != 0:
            raise Exception(
                "send returned error %d. %s may be corrupt."
                % (self.process.returncode, self.path)
            )

    def read(self, size):
        # If it's the first big chunk (header)
        # Tweak the volume information to match what we expect.
        data = self.stream.read(size)
        if FIXUP_DURING_SEND and self.bytesRead == 0:
            data = send.replaceIDs(
                data,
                self.diff.toUUID,
                self.diff.toGen,
                self.diff.fromUUID,
                self.diff.fromGen,
            )
        self.bytesRead += len(data)
        if self.progress is not None:
            self.progress.update(self.bytesRead)
        return data

    def seek(self, offset, whence):
        self.stream.seek(offset, offset, whence)
        if whence == io.SEEK_SET:
            self.bytesRead = offset
        elif whence == io.SEEK_CUR:
            pass
        elif whence == io.SEEK_END:
            self.bytesRead = None
Beispiel #3
0
class _Writer(io.RawIOBase):
    """ Context Manager to write a snapshot. """
    def __init__(self, process, stream, path, diff, showProgress):
        self.process = process
        self.stream = stream
        self.path = path
        self.diff = diff
        self.bytesWritten = None
        self.progress = DisplayProgress(diff.size) if showProgress else None

    def __enter__(self):
        self.bytesWritten = 0
        if self.progress is not None:
            self.progress.open()
        return self

    def __exit__(self, exceptionType, exception, trace):
        self.stream.close()

        if self.progress is not None:
            self.progress.close()

        if self.process is None:
            return

        logger.debug("Waiting for receive process to finish...")
        self.process.wait()

        if exception is None and self.process.returncode == 0:
            # Fixup with SET_RECEIVED_SUBVOL
            if FIXUP_AFTER_RECEIVE:
                received = btrfs.SnapShot(self.path)
                received.SET_RECEIVED_SUBVOL(
                    uuid=self.diff.toUUID,
                    stransid=self.diff.toGen,
                )
            return

        if self.process.returncode != 0:
            logger.error("btrfs receive errors")
            for line in self.process.stderr:
                sys.stderr.write(line)

        if os.path.exists(self.path):
            # This tries to mark partial (failed) transfers.

            partial = self.path + ".part"

            if os.path.exists(partial):
                partial = self.path + "_" + datetime.datetime.now().isoformat(
                ) + ".part"

            os.rename(self.path, partial)
            logger.debug("Renamed %s to %s", self.path, partial)

        if exception is None:
            raise Exception("receive %s returned error %d." % (
                self.path,
                self.process.returncode,
            ))

    def write(self, data):
        # If it's the first big chunk (header)
        # Tweak the volume information to match what we expect.
        if FIXUP_DURING_RECEIVE and self.bytesWritten == 0:
            data = send.replaceIDs(
                data,
                self.diff.toUUID,
                self.diff.toGen,
                self.diff.fromUUID,
                self.diff.fromGen,
            )
        self.stream.write(data)
        self.bytesWritten += len(data)
        if self.progress is not None:
            self.progress.update(self.bytesWritten)
Beispiel #4
0
class _Writer(io.RawIOBase):

    """ Context Manager to write a snapshot. """

    def __init__(self, process, stream, path, diff, showProgress):
        self.process = process
        self.stream = stream
        self.path = path
        self.diff = diff
        self.bytesWritten = None
        self.progress = DisplayProgress(diff.size) if showProgress else None

    def __enter__(self):
        self.bytesWritten = 0
        if self.progress is not None:
            self.progress.open()
        return self

    def __exit__(self, exceptionType, exception, trace):
        self.stream.close()

        if self.progress is not None:
            self.progress.close()

        if self.process is None:
            return

        logger.debug("Waiting for receive process to finish...")
        self.process.wait()

        if exception is None and self.process.returncode == 0:
            # Fixup with SET_RECEIVED_SUBVOL
            if FIXUP_AFTER_RECEIVE:
                received = btrfs.SnapShot(self.path)
                received.SET_RECEIVED_SUBVOL(
                    uuid=self.diff.toUUID,
                    stransid=self.diff.toGen,
                )
            return

        if self.process.returncode != 0:
            logger.error("btrfs receive errors")
            for line in self.process.stderr:
                sys.stderr.write(line)

        if os.path.exists(self.path):
            # This tries to mark partial (failed) transfers.

            partial = self.path + ".part"

            if os.path.exists(partial):
                partial = self.path + "_" + datetime.datetime.now().isoformat() + ".part"

            os.rename(self.path, partial)
            logger.debug("Renamed %s to %s", self.path, partial)

        if exception is None:
            raise Exception(
                "receive %s returned error %d."
                % (self.path, self.process.returncode, )
            )

    def write(self, data):
        # If it's the first big chunk (header)
        # Tweak the volume information to match what we expect.
        if FIXUP_DURING_RECEIVE and self.bytesWritten == 0:
            data = send.replaceIDs(
                data,
                self.diff.toUUID,
                self.diff.toGen,
                self.diff.fromUUID,
                self.diff.fromGen,
            )
        self.stream.write(data)
        self.bytesWritten += len(data)
        if self.progress is not None:
            self.progress.update(self.bytesWritten)