Esempio n. 1
0
    def revertAs(self, snapshot, directory, targetdir):
        """
        Revert a directory to its snapshot date state into a directory.
        We will restore the directory starting from the base snapshot to the selected one and clean the restore directory each time.
        @param snapshot : The snapshot from which to revert
        @param dir : the dir to revert, use self._fop.pathsep for the whole snapshot
        @param targetdir: The dir in which to restore files
        """
        if not snapshot:
            raise exceptions.SBException("Please provide a Snapshot")
        if not directory:
            raise exceptions.SBException("Please provide a File/directory")

        snpman = SnapshotManager.SnapshotManager(
            self._fop.get_dirname(snapshot.getPath()))
        history = snpman.getSnpHistory(snapshot)
        history.reverse()
        _cnt = 0
        for snp in history:
            self.logger.debug("Restoring '%(dirname)s' from snapshot '%(snapshotname)s'"\
                              % { "dirname" : directory, "snapshotname" : snp.getName() })
            _bak = False
            if _cnt == 0:
                _bak = True
            _cnt += 1

            self.restoreAs(snp,
                           directory,
                           targetdir,
                           backupFlag=_bak,
                           failOnNotFound=False)
    def __check_target(self):
        assert self.__fam_target_hdl.is_initialized(
        ), "File access manager not initialized"

        # TODO: Improve handling of original and modified target paths. Support display names for state (improved user interaction)
        _target_display_name = self.__fam_target_hdl.query_dest_display_name()
        self.__state.set_target(_target_display_name)
        self.logger.info(_("Backup destination: %s") % _target_display_name)

        # Check if the target dir exists, but Do not create any directories.
        if not self.__fam_target_hdl.dest_path_exists():
            self.logger.warning(_("Unable to find destination directory."))
            self.__state.set_state('target-not-found')

            if self.__use_indicator and self.__dbus_conn is not None:
                _time = 0
                _retry = constants.RETRY_UNKNOWN

                while (_time <= constants.TIMEOUT_RETRY_TARGET_CHECK_SECONDS):
                    time.sleep(constants.INTERVAL_RETRY_TARGET_CHECK_SECONDS)
                    _time = _time + constants.INTERVAL_RETRY_TARGET_CHECK_SECONDS
                    #TODO: put the get_retry_target.. into State?
                    _retry = self.__dbus_conn.get_retry_target_check()
                    if _retry == constants.RETRY_FALSE:
                        raise exceptions.BackupCanceledError

                    elif _retry == constants.RETRY_TRUE:
                        if self.__fam_target_hdl.dest_path_exists():
                            pass
                        else:
                            self.logger.warning(
                                _("Unable to find destination directory even after retry."
                                  ))
                            raise exceptions.SBException(_("Target directory '%(target)s' does not exist.")\
                                            % {"target" : _target_display_name})
                        break
                    else:
                        pass

            else:
                raise exceptions.SBException(_("Target directory '%(target)s' does not exist.")\
                                % {"target" : _target_display_name})

        try:
            self.__fam_target_hdl.test_destination()
        except exceptions.FileAccessException, error:
            self.logger.error(_("Unable to access destination: %s") % (error))
            raise error
Esempio n. 3
0
    def umount(self, mounteddir):
        """
        Default behaviour is to unmount with fuse
        """
        if os.path.ismount(mounteddir):
            self.logger.debug("Unmounting `%s`" % mounteddir)
            # Create output and error log file
            outptr, outFile = tempfile.mkstemp(prefix="fuseUmount_output_")
            errptr, errFile = tempfile.mkstemp(prefix="fuseUmount_error_")

            # Call the subprocess using convenience method using lazy umount
            retval = subprocess.call(["fusermount", "-u", "-z", mounteddir], 0,
                                     None, None, outptr, errptr)

            # Close log handles
            os.close(errptr)
            os.close(outptr)
            outStr, errStr = local_file_utils.readfile(
                outFile), local_file_utils.readfile(errFile)
            local_file_utils.delete(outFile)
            local_file_utils.delete(errFile)

            self.logger.debug("fusermount output:\n%s\n%s" % (outStr, errStr))

            if retval != 0:
                raise exceptions.SBException("Unable to unmount `%s`: %s" %
                                             (mounteddir, errStr))
            else:
                self.logger.info("Successfully unmounted: `%s`" % mounteddir)
        else:
            self.logger.warning("Unable to unmount `%s`: not mounted" %
                                mounteddir)
Esempio n. 4
0
    def __collect_files(self):
        """Fill snapshot's include and exclude lists and retrieve some information
        about the snapshot (uncompressed size, file count).
        """
        self.logger.info(_("Inspect file system and collect file infos"))
        _collector = self.__create_collector_obj()
        _collector.collect_files()
        _stats = _collector.get_stats()
        _snpsize = _stats.get_size_payload() + _stats.get_size_overhead(size_per_item = constants.TAR_BLOCKSIZE)

        self.__state.set_space_required(_snpsize)
        self.__snapshot.set_space_required(_snpsize)
        _sizefs, _freespace = self.__fam_target_hdl.query_dest_fs_info()

        _snpsize_hr = util.get_humanreadable_size_str(size_in_bytes = _snpsize, binary_prefixes = True)
        self.logger.info(_("Summary of backup"))
        self.logger.info(_("Number of directories: %s.") % _stats.get_count_dirs())
        self.logger.info(_("Total number of files: %s.") % _stats.get_count_files_total())
        self.logger.info(_("Number of symlinks: %s.") % _stats.get_count_symlinks())
        self.logger.info(_("Number of files included in snapshot: %s.") % _stats.get_count_files_incl())
        self.logger.info(_("Number of new files (also included): %s.") % _stats.get_count_files_new())
        self.logger.info(_("Number of files skipped in incremental snapshot: %s.") % _stats.get_count_files_skip())
        self.logger.info(_("Number of items forced to be excluded: %s.") % _stats.get_count_items_excl_forced())
        self.logger.info(_("Number of items to be excluded by config: %s.") % _stats.get_count_items_excl_config())
        self.logger.info(_("Maximum free size required is '%s'.") % _snpsize_hr)

        if _freespace == constants.FREE_SPACE_UNKNOWN:
            self.logger.warning("Unable to query available space on target: Operation not supported")
        else:
            _freespace_hr = util.get_humanreadable_size_str(size_in_bytes = _freespace, binary_prefixes = True)
            self.logger.info(_("Available disk size is '%s'.") % _freespace_hr)
            if _freespace <= _snpsize:
                raise exceptions.SBException(_("Not enough free space in the target directory for the planned backup (free: %(freespace)s, required: %(neededspace)s).")\
                                               % { 'freespace' : _freespace_hr, 'neededspace' : _snpsize_hr})
Esempio n. 5
0
 def checkifmounted(self, source, mountbase):
     """
     Should check if the source is mounted.
     Note : you should use os.path.ismount(path) method for that, after determining the name of the mount point.
     @return: True if it is, False if not
     """
     raise exceptions.SBException(
         "'Check if mounted' Not implemented for this plugin")
Esempio n. 6
0
 def match_scheme_full(self, remoteSource):
     """
     Try to match the scheme of the remoteSource.
     @param remoteSource: The remote path
     @return: True if the scheme matches the one for this 
     @rtype: boolean
     """
     raise exceptions.SBException(
         "'match_scheme_full' Not implemented for this plugin")
Esempio n. 7
0
 def mount(self, source, mountbase):
     """
     Mount the source intor the mountbase dir . This method should create a mount point to mount the source. 
     The name of the mount point should be very expressive so that we avoid collision with other mount points
     This method will return a tuple (baseRemoteSource, mountpoint, pathinside) where
     - baseRemoteSource is the substring that represent the mount source (usually at the start of the source). The match_scheme_full method should be able to match it
     - mountpoint is the mount point of this baseRemoteSource.
     - pathinside is the path inside the remote source 
     [Use case]
     The mount function is called once with "sch://server/path/to/dir" and the plugin mounts "sch://server" to "/mnt/sch_server". 
     Then the return value would be ("sch://server","/mnt/sch_server","path/to/dir")
     @param source: The remote path
     @param mountbase: The mount points base dir
     @return: The tuple (baseRemoteSource, mountpoint, pathinside)
     @rtype: tuple
     """
     raise exceptions.SBException("'mount' Not implemented for this plugin")
Esempio n. 8
0
def readlineNULSep(fd, fd1):
    """
    Iterator that read a NUL separeted file as lines 
    @param fd: File descriptor
    @return: the gotten line
    @rtype: String
    """
    _continue = 0

    while _continue < 2:
        c = fd.read(1)
        currentline = ''

        while c:
            if c == '\0':
                # we got a line
                break
            currentline += c
            c = fd.read(1)
        else:
            # c is None
            # This else correspond to the while statement
            _continue += 1

        c1 = fd1.read(1)
        currentline1 = ''

        while c1:
            if c1 == '\0':
                # we got a line
                break
            c1 = fd1.read(1)
            currentline1 += c1
        else:
            # c1 is None
            # This else correspond to the while statement
            _continue += 1

        if _continue == 1:
            raise exceptions.SBException(\
                                "The length of flist and Fprops are not equals")
        yield (currentline, currentline1)
Esempio n. 9
0
 def match_scheme(self, remoteSource):
     raise exceptions.SBException(
         "'match_scheme' Not implemented for this plugin")
Esempio n. 10
0
 def getdoc(self):
     """
     This method should give a little documentation about the schema used for this plugin.
     @return: The schema doc (eg. return 'example : sch://user:password@server/dir')
     """
     raise exceptions.SBException("Help not implemented for this plugin")
Esempio n. 11
0
    def restoreAs(self,
                  snapshot,
                  _file,
                  target,
                  backupFlag=True,
                  failOnNotFound=True):
        """
        Restore one file or directory from the backup tdir with name
        file to target (or to its old location if None if given to target).
        All existing files must be moved to a "*.before_restore_$time" files.
        @param snapshot:
        @param file:
        @param target: where to restore given file/dir (not the backup destination/snapshot dir)
        @param backupFlag: Set to false to make no backup when restoring (default = True)
        @param failOnNotFound: set to False if we don't want to fail if a file is not found (default is True)

        :todo: Re-factor and simplify!
        """
        if snapshot is None:
            raise exceptions.SBException("Please provide a Snapshot")
        if _file is None:
            raise exceptions.SBException("Please provide a File/directory")

        _file = "%s%s" % (self._fop.pathsep, _file.lstrip(self._fop.pathsep))

        self.logger.debug("Restore as\n\tsnapshot: `%s`\n\tfile (path in snapshot): `%s`\n\trestore target: `%s`"\
                          % (snapshot, _file, target))

        if not snapshot.getSnapshotFileInfos().hasPath(
                _file) and not snapshot.getSnapshotFileInfos().hasFile(_file):
            if failOnNotFound:
                raise exceptions.SBException(
                    _("File '%s' not found in the backup snapshot files list")
                    % _file)
            else:
                self.logger.warning(_("File '%(filename)s' not found in snapshot's [%(snapshotname)s] files list, Skipped.")\
                                    % {"filename": _file, "snapshotname" : snapshot.getName()})
                return

        _snpname = self._fop.get_basename(snapshot.getName())
        _arname = self._fop.get_basename(snapshot.getArchive())
        _larpath = self.__fam_target_hdl.get_eff_fullpath(_snpname, _arname)
        self.logger.debug("eff. local path to archive: %s" % _larpath)

        suffix = None
        if backupFlag:
            now = datetime.datetime.now().isoformat("_").replace(":", ".")
            suffix = ".before_restore_" + now

        if target and self._fop.path_exists(target):
            self.logger.debug("Restore target is given and exists")
            if self._fop.is_dir(target) is True:
                self.logger.debug(
                    "Restore target is a directory (i.e. we extract into a directory)"
                )

                #create a temp dir, extract inside then move the content
                _tmpdir = tempfile.mkdtemp(dir=target,
                                           prefix='sbackup-restore_')
                self.logger.debug("Restore tempdir: `%s`" % _tmpdir)

                tar.extract(snapshot.getArchive(),
                            _larpath,
                            _file,
                            _tmpdir,
                            bckupsuffix=suffix,
                            splitsize=snapshot.getSplitedSize())

                _file_in_target = self._fop.joinpath(
                    target, self._fop.get_basename(_file))
                _file_in_tmpdir = self._fop.joinpath(_tmpdir, _file)

                self.logger.debug("File in restore target: `%s`" %
                                  _file_in_target)
                self.logger.debug("File in restore tempdir: `%s`" %
                                  _file_in_tmpdir)

                if backupFlag:
                    if self._fop.path_exists(_file_in_target):
                        self._fop.force_move(
                            _file_in_target,
                            "%s%s" % (_file_in_target, suffix))

                self._fop.force_move(_file_in_tmpdir, _file_in_target)
                self._fop.force_delete(_tmpdir)
            else:
                #the target is a file (i.e. the backuped file is restored under new name
                parent = self._fop.get_dirname(target)
                tar.extract(snapshot.getArchive(),
                            _larpath,
                            _file,
                            parent,
                            bckupsuffix=suffix,
                            splitsize=snapshot.getSplitedSize())
        else:
            # target is set to None or target not exists
            if target and not self._fop.path_exists(target):
                #target != None but target doesn't exists
                self._fop.makedirs(target)
                tar.extract(snapshot.getArchive(),
                            _larpath,
                            _file,
                            target,
                            splitsize=snapshot.getSplitedSize())
            else:
                # Target = None , extract at the place it belongs
                if self._fop.path_exists(_file):
                    # file exist:
                    tar.extract(snapshot.getArchive(),
                                _larpath,
                                _file,
                                target,
                                bckupsuffix=suffix,
                                splitsize=snapshot.getSplitedSize())
                else:
                    # file doesn't exist nothing to move, just extract
                    tar.extract(snapshot.getArchive(),
                                _larpath,
                                _file,
                                target,
                                splitsize=snapshot.getSplitedSize())