def entry(self, date="", repo=""): # Validate date try: entryTime = rdw_helpers.rdwTime() entryTime.initFromString(date) except ValueError: return self.writeErrorPage("Invalid date parameter.") if not repo: userRepos = self.userDB.getUserRepoPaths(self.getUsername()) # Set the start and end time to be the start and end of the day, respectively, to get all entries for that day startTime = rdw_helpers.rdwTime() startTime.timeInSeconds = entryTime.timeInSeconds startTime.tzOffset = entryTime.tzOffset endTime = rdw_helpers.rdwTime() endTime.timeInSeconds = entryTime.timeInSeconds endTime.tzOffset = entryTime.tzOffset startTime.setTime(0, 0, 0) endTime.setTime(23, 59, 59) userMessages = self._getUserMessages(userRepos, True, False, startTime, endTime) else: # Validate repo parameter if not repo: return self.writeErrorPage("Backup location not specified.") if not repo in self.userDB.getUserRepoPaths(self.getUsername()): return self.writeErrorPage("Access is denied.") try: rdw_helpers.ensurePathValid(repo) except rdw_helpers.accessDeniedError, error: return self.writeErrorPage(str(error)) userMessages = self._getUserMessages([repo], False, True, entryTime, entryTime)
def testGetBackupHistory(self): entries = getBackupHistory(self.destDir) assert len(entries) == 3 for entry in entries: assert entry.errors == "" assert entries[0].size == 15 assert entries[1].size == 56 assert entries[2].size == 23 lastEntry = getLastBackupHistoryEntry(self.destDir) assert lastEntry.size == 23 # Test that timezone differences are ignored historyAsOf = lastEntry.date.getUrlString() if "+" in historyAsOf: historyAsOf = historyAsOf.replace("+", "-") else: historyAsOf = historyAsOf[:19] + "+" + historyAsOf[20:] lastBackupTime = rdw_helpers.rdwTime() lastBackupTime.initFromString(historyAsOf) entries = getBackupHistorySinceDate(self.destDir, lastBackupTime) assert len(entries) == 1 # Test that no backups are returned one second after the last backup historyAsOf = historyAsOf[:18] + "1" + historyAsOf[19:] postBackupTime = rdw_helpers.rdwTime() postBackupTime.initFromString(historyAsOf) assert lastBackupTime.getLocalSeconds() + 1 == postBackupTime.getLocalSeconds() entries = getBackupHistorySinceDate(self.destDir, postBackupTime) assert len(entries) == 0
def testGetBackupHistory(self): tests = self.getBackupTests() for testDir in tests: # Get a list of backup entries for the root folder origBackupDir = joinPaths(self.masterDirPath, testDir) backupStates = self.getBackupStates(origBackupDir) backupStates.sort(lambda x, y: cmp(x, y)) rdiffDestDir = joinPaths(self.destRoot, testDir) entries = getBackupHistory(rdiffDestDir) assert len(entries) == len(backupStates) backupNum = 0 for backup in backupStates: origBackupStateDir = joinPaths(origBackupDir, backup) totalBackupSize = 0 for file in os.listdir(origBackupStateDir): totalBackupSize = totalBackupSize + os.lstat(joinPaths(origBackupStateDir, file))[6] #TODO: fix this to handle subdirs #assert totalBackupSize == entries[backupNum].size, "Calculated: "+str(totalBackupSize)+" Reported: "+str(entries[backupNum].size)+" State: "+str(backupNum) backupNum = backupNum + 1 # Test that the last backup entry works correctly lastEntry = getLastBackupHistoryEntry(rdiffDestDir) lastBackupTime = rdw_helpers.rdwTime() lastBackupTime.initFromString(backupStates[-1]) assert lastEntry.date == lastBackupTime # Test that timezone differences are ignored historyAsOf = lastEntry.date.getUrlString() # if "+" in historyAsOf: # historyAsOf = historyAsOf.replace("+", "-") # else: # historyAsOf = historyAsOf[:19] + "+" + historyAsOf[20:] lastBackupTime = rdw_helpers.rdwTime() lastBackupTime.initFromString(historyAsOf) entries = getBackupHistorySinceDate(rdiffDestDir, lastBackupTime) assert len(entries) == 1 # Test that no backups are returned one second after the last backup historyAsOf = historyAsOf[:18] + "1" + historyAsOf[19:] postBackupTime = rdw_helpers.rdwTime() postBackupTime.initFromString(historyAsOf) assert lastBackupTime.getLocalSeconds() + 1 == postBackupTime.getLocalSeconds() entries = getBackupHistorySinceDate(rdiffDestDir, postBackupTime) assert len(entries) == 0
def _getUserMessagesForDay(self, date): userRepos = self.getUserDB().getUserRepoPaths(self.getUsername()) # Set the start and end time to be the start and end of the day, respectively, to get all entries for that day startTime = rdw_helpers.rdwTime() startTime.timeInSeconds = date.timeInSeconds startTime.tzOffset = date.tzOffset startTime.setTime(0, 0, 0) endTime = rdw_helpers.rdwTime() endTime.timeInSeconds = date.timeInSeconds endTime.tzOffset = date.tzOffset endTime.setTime(23, 59, 59) return self._getUserMessages(userRepos, True, False, startTime, endTime)
def _getOldRepoInfo(self, repoName, repoPath, notifySettings, isAdminMonitoring): if isAdminMonitoring: maxAge = notifySettings['adminMaxAge'] else: maxAge = notifySettings['anyRepoMaxAge'] if not maxAge: maxAge = notifySettings['repos'][repoName] if maxAge == 0: return None try: lastBackup = librdiff.getLastBackupHistoryEntry(repoPath, False) except librdiff.FileError: return { "repo" : repoName, "lastBackupDate" : "never", "maxAge" : maxAge } except Exception: rdw_logging.log_exception() rdw_logging.log('(Previous exception occurred for repo %s.)' % repoPath) else: if lastBackup: oldestGoodBackupTime = rdw_helpers.rdwTime() oldestGoodBackupTime.initFromMidnightUTC(-maxAge) if lastBackup.date < oldestGoodBackupTime: return { "repo" : repoName, "lastBackupDate" : lastBackup.date.getDisplayString(), "maxAge" : maxAge } return None
def _getRecentUserMessages(self, failuresOnly): userRepos = self.getUserDB().getUserRepoPaths(self.getUsername()) asOfDate = rdw_helpers.rdwTime() asOfDate.initFromMidnightUTC(-5) return self._getUserMessages(userRepos, not failuresOnly, True, asOfDate, None)
def _get_recent_user_messages(self, failuresOnly): user_repos = self.app.userdb.get_repos(self.app.currentuser.username) asOfDate = rdw_helpers.rdwTime() asOfDate.initFromMidnightUTC(-5) return self._getUserMessages(user_repos, not failuresOnly, True, asOfDate, None)
class rdiffRestorePage(page_main.rdiffPage): def index(self, repo, path, date): repo = rdw_helpers.decodeUrl(repo) path = rdw_helpers.decodeUrl(path) date = rdw_helpers.decodeUrl(date) try: rdw_helpers.ensurePathValid(repo) rdw_helpers.ensurePathValid(path) except rdw_helpers.accessDeniedError, error: return self.writeErrorPage(str(error)) if not repo: return self.writeErrorPage("Backup location not specified.") if not repo in self.userDB.getUserRepoPaths(self.getUsername()): return self.writeErrorPage("Access is denied.") if librdiff.backupIsInProgress(rdw_helpers.joinPaths(self.userDB.getUserRoot(self.getUsername()), repo)): return self.writeErrorPage("A backup is currently in progress to this location. Restores are disabled until this backup is complete.") try: restoreTime = rdw_helpers.rdwTime() restoreTime.initFromString(date) (path, file) = os.path.split(path) if not file: file = path path = "/" filePath = librdiff.restoreFileOrDir(rdw_helpers.joinPaths(self.userDB.getUserRoot(self.getUsername()), repo), path, file, restoreTime) except librdiff.FileError, error: return self.writeErrorPage(error.getErrorString())
def testGetDirEntries(self): tests = self.getBackupTests() for testDir in tests: # Get a list of backup entries for the root folder rdiffDestDir = joinPaths(self.destRoot, testDir) entries = getDirEntries(rdiffDestDir, "/") # Go back through all backup states and make sure that the backup entries match the files that exist origStateDir = joinPaths(self.masterDirPath, testDir) backupStates = self.getBackupStates(origStateDir) backupStates.sort(lambda x, y: cmp(x, y)) for backupState in backupStates: backupTime = rdw_helpers.rdwTime() backupTime.initFromString(backupState) # Go through each file, and make sure we have a backup entry for this file and date origStateDir = joinPaths(self.masterDirPath, testDir, backupState) files = self.getBackupStates(origStateDir) for file in files: origFilePath = joinPaths(origStateDir, file) entry = getMatchingDirEntry(entries, file) assertionErrorMessage = "backupTime "+backupTime.getDisplayString()+" not found in backup entries for backup test \""+testDir+"\" for file \""+file+"\". Returned changeDates:" for changeDate in entry.changeDates: assertionErrorMessage = assertionErrorMessage + "\n"+changeDate.getDisplayString() assertionErrorMessage = assertionErrorMessage + "\nIncrements dir: "+str(os.listdir(joinPaths(rdiffDestDir, "rdiff-backup-data", "increments"))) for entryDate in entry.changeDates: if backupTime.getSeconds() == entryDate.getSeconds(): if self.fileChangedBetweenBackups(testDir, entry.name, backupState, backupStates): assert False, assertionErrorMessage break else: if not self.fileChangedBetweenBackups(testDir, entry.name, backupState, backupStates): assert False or False, assertionErrorMessage assert os.path.isdir(origFilePath) == entry.isDir
def setUp(self): # The temp dir on Mac OS X is a symlink; expand it because of validation against symlinks in paths self.destRoot = joinPaths(os.path.realpath(tempfile.gettempdir()), "rdiffWeb") self.masterDirPath = joinPaths( "..", "tests" ) # TODO: do this right, including tying tests into "python setup.py test" self.tearDown() os.makedirs(self.destRoot) # Set up each scenario tests = self.getBackupTests() for testDir in tests: # Iterate through the backup states origStateDir = joinPaths(self.masterDirPath, testDir) backupStates = self.getBackupStates(origStateDir) backupStates.sort(lambda x, y: cmp(x, y)) for backupState in backupStates: # Try to parse the folder name as a date. If we can't, raise backupTime = rdw_helpers.rdwTime() backupTime.initFromString(backupState) # Backup the data as it should be at that state #print " State", backupState runRdiff(joinPaths(origStateDir, backupState), joinPaths(self.destRoot, testDir), backupTime)
class rdiffRestorePage(page_main.rdiffPage): _cp_config = {"response.stream": True, "response.timeout": 3000} def index(self, repo, path, date): try: self.validateUserPath(rdw_helpers.joinPaths(repo, path)) except rdw_helpers.accessDeniedError, error: return self.writeErrorPage(str(error)) if not repo: return self.writeErrorPage("Backup location not specified.") if not repo in self.getUserDB().getUserRepoPaths(self.getUsername()): return self.writeErrorPage("Access is denied.") if librdiff.backupIsInProgressForRepo( rdw_helpers.joinPaths( self.getUserDB().getUserRoot(self.getUsername()), repo)): return self.writeErrorPage( "A backup is currently in progress to this location. Restores are disabled until this backup is complete." ) try: restoreTime = rdw_helpers.rdwTime() restoreTime.initFromString(date) (path, file) = os.path.split(path) if not file: file = path path = "/" fullPath = rdw_helpers.joinPaths( self.getUserDB().getUserRoot(self.getUsername()), repo) useZipFormat = self.getUserDB().useZipFormat(self.getUsername()) filePath = librdiff.restoreFileOrDir(fullPath, path, file, restoreTime, useZipFormat) except librdiff.FileError, error: return self.writeErrorPage(error.getErrorString())
def testRestoreFile(self): tests = self.getBackupTests() for testDir in tests: # Get a list of backup entries for the root folder rdiffDestDir = joinPaths(self.destRoot, testDir) entries = getDirEntries(rdiffDestDir, "/") # Go back through all backup states and make sure that the backup entries match the files that exist origStateDir = joinPaths(self.masterDirPath, testDir) backupStates = self.getBackupStates(origStateDir) backupStates.sort(lambda x, y: cmp(x, y)) for backupState in backupStates: backupTime = rdw_helpers.rdwTime() backupTime.initFromString(backupState) # Go through each file, and make sure that the restored file looks the same as the orig file origStateDir = joinPaths(self.masterDirPath, testDir, backupState) files = self.getBackupStates(origStateDir) for file in files: origFilePath = joinPaths(origStateDir, file) if not os.path.isdir(origFilePath): restoredFilePath = restoreFileOrDir( rdiffDestDir, "/", file, backupTime) assert open(restoredFilePath, "r").read() == open(origFilePath, "r").read() os.remove(restoredFilePath)
def sendEmails(self): for user in self.userDB.getUserList(): userRepos = self.userDB.getUserRepoPaths(user) oldRepos = [] for repo in userRepos: maxDaysOld = self.userDB.getRepoMaxAge(user, repo) if maxDaysOld != 0: # get the last backup date try: lastBackup = librdiff.getLastBackupHistoryEntry(rdw_helpers.joinPaths(self.userDB.getUserRoot(user), repo), False) except librdiff.FileError: pass # Skip repos that have never been successfully backed up else: if lastBackup: oldestGoodBackupTime = rdw_helpers.rdwTime() oldestGoodBackupTime.initFromMidnightUTC(-maxDaysOld) if lastBackup.date < oldestGoodBackupTime: oldRepos.append({"repo" : repo, "lastBackupDate" : lastBackup.date.getDisplayString(), "maxAge" : maxDaysOld }) if oldRepos: userEmailAddress = self.userDB.getUserEmail(user) emailText = rdw_helpers.compileTemplate("email_notification.txt", repos=oldRepos, sender=self._getEmailSender(), user=user) session = smtplib.SMTP(self._getEmailHost()) session.login(self._getEmailUsername(), self._getEmailPassword()) smtpresult = session.sendmail(self._getEmailSender(), userEmailAddress.split(";"), emailText) session.quit()
def entry(self, path_b=b"", date=""): assert isinstance(path_b, str) assert isinstance(date, unicode) # Validate date try: entry_time = rdw_helpers.rdwTime() entry_time.initFromInt(int(date)) except ValueError: logger.exception("invalid date") return self._compile_error_template(_("Invalid date.")) if not path_b: userMessages = self._get_user_messages_for_day(entry_time) else: # Validate repo parameter try: repo_obj = self.validate_user_path(path_b)[0] except librdiff.FileError as e: logger.exception("invalid user path") return self._compile_error_template(unicode(e)) userMessages = self._getUserMessages( [repo_obj.path], False, True, entry_time, entry_time) return self._compileStatusPageTemplate(False, userMessages, False)
def index(self, path_b=b"", date="", usetar=""): assert isinstance(path_b, str) assert isinstance(date, unicode) assert isinstance(usetar, unicode) logger.debug("restoring [%s][%s]" % (decode_s(path_b, "replace"), date)) # The path_b wont have leading and trailing "/". (path_b, file_b) = os.path.split(path_b) if not path_b: path_b = file_b file_b = b"" # Check user access to repo / path. try: (repo_obj, path_obj) = self.validate_user_path(path_b) except librdiff.FileError as e: logger.exception("invalid user path") return self._compile_error_template(unicode(e)) # Get the restore date try: restore_date = rdw_helpers.rdwTime() restore_date.initFromInt(int(date)) except: logger.warn("invalid date %s" % date) return self._compile_error_template(_("Invalid date.")) try: # Get if backup in progress if repo_obj.in_progress: return self._compile_error_template( _( """A backup is currently in progress to this repository. Restores are disabled until this backup is complete.""" ) ) # Restore the file file_path_b = path_obj.restore(file_b, restore_date, usetar != "T") except librdiff.FileError as e: logger.exception("fail to restore") return self._compile_error_template(unicode(e)) except ValueError: logger.exception("fail to restore") return self._compile_error_template(_("Fail to restore.")) # The restored file path need to be deleted when the user is finish # downloading. The auto-delete tool, will do it if we give him a file # to delete. cherrypy.request._autodelete_dir = file_path_b # The file name return by rdiff-backup is in bytes. We do not process # it. Cherrypy seams to handle it any weird encoding from this point. logger.info("restored file [%s]" % decode_s(file_path_b, "replace")) filename = os.path.basename(file_path_b) # Escape quotes in filename filename = filename.replace(b'"', b'\\"') return serve_file(file_path_b, None, disposition=b"attachment", name=filename)
def _get_user_messages_for_day(self, date): userRepos = self.app.userdb.get_repos(self.app.currentuser.username) # Set the start and end time to be the start and end of the day, # respectively, to get all entries for that day startTime = rdw_helpers.rdwTime() startTime.timeInSeconds = date.timeInSeconds startTime.tzOffset = date.tzOffset startTime.setTime(0, 0, 0) endTime = rdw_helpers.rdwTime() endTime.timeInSeconds = date.timeInSeconds endTime.tzOffset = date.tzOffset endTime.setTime(23, 59, 59) return self._getUserMessages(userRepos, True, False, startTime, endTime)
def getDate(self): timeString = self.getDateString() returnTime = rdw_helpers.rdwTime() try: returnTime.loadFromString(timeString) return returnTime except ValueError: return None
def getDate(self): timeString = self.getDateString() returnTime = rdw_helpers.rdwTime() try: returnTime.initFromString(timeString) return returnTime except ValueError: return None
def _getFirstBackupAfterDate(self, date): """ Iterates the mirror_metadata files in the rdiff data dir """ if not self.backupTimes: return rdw_helpers.rdwTime() if not date: return self.backupTimes[0] index = bisect.bisect_right(self.backupTimes, date) if index >= len(self.backupTimes): return self.backupTimes[-1] return self.backupTimes[index]
def _parseDate(self, filename): """Return a date object from a filename.""" # Parse the date of the file filename = self._removeSuffix(filename) filename = rsplit(filename, ".", 1)[1] time = rdw_helpers.rdwTime() try: time.initFromString(filename) return time except ValueError: return None
def _getFirstBackupAfterDate(self, date): """ Iterates the mirror_metadata files in the rdiff data dir """ backupFiles = filter(lambda x: x.startswith("mirror_metadata"), self.dataDirEntries) backupFiles.sort() for backup in backupFiles: backupTimeString = rsplit(backup, ".", 3)[1] backupTime = rdw_helpers.rdwTime() backupTime.initFromString(backupTimeString) if not date or backupTime > date: return backupTime return backupFiles[-1]
def date(self): # Remove suffix from filename filename = self._remove_suffix(self.name) # Remove prefix from filename date_string = filename.rsplit(b".", 1)[-1] return_time = rdw_helpers.rdwTime() try: return_time.initFromString(date_string) return return_time except ValueError: return None
def extract_date(filename): """ Extract date from rdiff-backup filenames. """ # Remove suffix from filename filename = IncrementEntry._remove_suffix(filename) # Remove prefix from filename date_string = filename.rsplit(b".", 1)[-1] return_time = rdw_helpers.rdwTime() try: return_time.initFromString(date_string) return return_time except ValueError: return None
def _getUserMessages(self): userRoot = self.userDB.getUserRoot(self.getUsername()) userRepos = self.userDB.getUserRepoPaths(self.getUsername()) asOfDate = rdw_helpers.rdwTime() asOfDate.initFromMidnightUTC(-5) # build list of all backups allBackups = [] repoErrors = [] for repo in userRepos: try: backups = librdiff.getBackupHistorySinceDate(rdw_helpers.joinPaths(userRoot, repo), asOfDate) allBackups += [{"repo": repo, "date": backup.date, "displayDate": backup.date.getDisplayString(), "size": rdw_helpers.formatFileSizeStr(backup.size), "errors": backup.errors} for backup in backups] except librdiff.FileError, error: repoErrors.append({"repo": repo, "error": error.getErrorString()})
def sendEmails(self): for user in self.userDB.getUserList(): userRepos = self.userDB.getUserRepoPaths(user) oldRepos = [] for repo in userRepos: maxDaysOld = self.userDB.getRepoMaxAge(user, repo) if maxDaysOld != 0: # get the last backup date try: lastBackup = librdiff.getLastBackupHistoryEntry( rdw_helpers.joinPaths( self.userDB.getUserRoot(user), repo), False) except librdiff.FileError: pass # Skip repos that have never been successfully backed up else: if lastBackup: oldestGoodBackupTime = rdw_helpers.rdwTime() oldestGoodBackupTime.initFromMidnightUTC( -maxDaysOld) if lastBackup.date < oldestGoodBackupTime: oldRepos.append({ "repo": repo, "lastBackupDate": lastBackup.date.getDisplayString(), "maxAge": maxDaysOld }) if oldRepos: userEmailAddress = self.userDB.getUserEmail(user) emailText = rdw_helpers.compileTemplate( "email_notification.txt", repos=oldRepos, sender=self._getEmailSender(), user=user) session = smtplib.SMTP(self._getEmailHost()) session.login(self._getEmailUsername(), self._getEmailPassword()) smtpresult = session.sendmail(self._getEmailSender(), userEmailAddress.split(";"), emailText) session.quit()
def emailNotifications(): emailHost = getEmailHost() emailSender = getEmailSender() emailUsername = getEmailUsername() emailPassword = getEmailPassword() dbBackend = db.userDB().getUserDBModule() for user in dbBackend.getUserList(): userRepos = dbBackend.getUserRepoPaths(user) oldRepos = [] for repo in userRepos: maxDaysOld = dbBackend.getRepoMaxAge(user, repo) if maxDaysOld != 0: # get the last backup date try: lastBackup = librdiff.getLastBackupHistoryEntry(rdw_helpers.joinPaths(dbBackend.getUserRoot(user), repo), False) except librdiff.FileError: pass # Skip repos that have never been successfully backed up else: if lastBackup: oldestGoodBackupTime = rdw_helpers.rdwTime() oldestGoodBackupTime.initFromMidnightUTC(-maxDaysOld) if lastBackup.date < oldestGoodBackupTime: oldRepos.append({"repo" : repo, "lastBackupDate" : lastBackup.date.getDisplayString(), "maxAge" : maxDaysOld }) if oldRepos: userEmailAddress = dbBackend.getUserEmail(user) emailText = rdw_helpers.compileTemplate("email_notification.txt", repos=oldRepos, sender=emailSender, user=user) session = smtplib.SMTP(emailHost) session.login(emailUsername, emailPassword) smtpresult = session.sendmail(emailSender, userEmailAddress.split(";"), emailText) if smtpresult: error = "" for recipient in smtpresult.keys(): error = """Could not delivery mail to: %s Server said: %s %s %s""" % (recipient, smtpresult[recipient][0], smtpresult[recipient][1], error) raise smtplib.SMTPException, error session.quit()
def entry(self, date="", repo=""): # Validate date try: entryTime = rdw_helpers.rdwTime() entryTime.initFromString(date) except ValueError: return self.writeErrorPage("Invalid date parameter.") if not repo: userMessages = self._getUserMessagesForDay(entryTime) else: # Validate repo parameter if not repo in self.userDB.getUserRepoPaths(self.getUsername()): return self.writeErrorPage("Access is denied.") try: self.validateUserPath(repo) except rdw_helpers.accessDeniedError, error: return self.writeErrorPage(str(error)) userMessages = self._getUserMessages([repo], False, True, entryTime, entryTime)
def entry(self, date="", repo=""): # Validate date try: entryTime = rdw_helpers.rdwTime() entryTime.initFromString(date) except ValueError: return self.writeErrorPage("Invalid date parameter.") if not repo: userMessages = self._getUserMessagesForDay(entryTime) else: # Validate repo parameter if not repo in self.getUserDB().getUserRepoPaths(self.getUsername()): return self.writeErrorPage("Access is denied.") try: self.validateUserPath(repo) except rdw_helpers.accessDeniedError, error: return self.writeErrorPage(str(error)) userMessages = self._getUserMessages([repo], False, True, entryTime, entryTime)
def setUp(self): # The temp dir on Mac OS X is a symlink; expand it because of validation against symlinks in paths self.destRoot = joinPaths(os.path.realpath(tempfile.gettempdir()), "rdiffWeb") self.masterDirPath = joinPaths("..", "tests") # TODO: do this right, including tying tests into "python setup.py test" self.tearDown() os.makedirs(self.destRoot) # Set up each scenario tests = self.getBackupTests() for testDir in tests: # Iterate through the backup states origStateDir = joinPaths(self.masterDirPath, testDir) backupStates = self.getBackupStates(origStateDir) backupStates.sort(lambda x, y: cmp(x, y)) for backupState in backupStates: # Try to parse the folder name as a date. If we can't, raise backupTime = rdw_helpers.rdwTime() backupTime.initFromString(backupState) # Backup the data as it should be at that state #print " State", backupState runRdiff(joinPaths(origStateDir, backupState), joinPaths(self.destRoot, testDir), backupTime)
class rdiffHistoryPage(page_main.rdiffPage): def index(self, repo, date=''): try: self.validateUserPath(repo) except rdw_helpers.accessDeniedError, error: return self.writeErrorPage(str(error)) if not repo: return self.writeErrorPage("Backup location not specified.") if not repo in self.getUserDB().getUserRepoPaths(self.getUsername()): return self.writeErrorPage("Access is denied.") if cherrypy.request.method == 'POST': if not date: return self.writeErrorPage("No deletion date was specified.") deleteTime = rdw_helpers.rdwTime() deleteTime.initFromString(date) repoPath = joinPaths( self.getUserDB().getUserRoot(self.getUsername()), repo) try: librdiff.removeRepoHistory(repoPath, deleteTime) except librdiff.FileError, error: return self.writeErrorPage(error.getErrorString())
class rdiffRestorePage(page_main.rdiffPage): def index(self, repo, path, date): repo = rdw_helpers.decodeUrl(repo) path = rdw_helpers.decodeUrl(path) date = rdw_helpers.decodeUrl(date) try: rdw_helpers.ensurePathValid(repo) rdw_helpers.ensurePathValid(path) except rdw_helpers.accessDeniedError, error: return self.writeErrorPage(str(error)) if not repo: return self.writeErrorPage("Backup location not specified.") if not repo in self.userDB.getUserRepoPaths(self.getUsername()): return self.writeErrorPage("Access is denied.") try: restoreTime = rdw_helpers.rdwTime() restoreTime.loadFromString(date) (path, file) = os.path.split(path) if not file: file = path path = "/" filePath = librdiff.restoreFile(rdw_helpers.joinPaths(self.userDB.getUserRoot(self.getUsername()), repo), path, file, restoreTime) except librdiff.FileError, error: return self.writeErrorPage(error.getErrorString())
def testRestoreFile(self): tests = self.getBackupTests() for testDir in tests: # Get a list of backup entries for the root folder rdiffDestDir = joinPaths(self.destRoot, testDir) entries = getDirEntries(rdiffDestDir, "/") # Go back through all backup states and make sure that the backup entries match the files that exist origStateDir = joinPaths(self.masterDirPath, testDir) backupStates = self.getBackupStates(origStateDir) backupStates.sort(lambda x, y: cmp(x, y)) for backupState in backupStates: backupTime = rdw_helpers.rdwTime() backupTime.initFromString(backupState) # Go through each file, and make sure that the restored file looks the same as the orig file origStateDir = joinPaths(self.masterDirPath, testDir, backupState) files = self.getBackupStates(origStateDir) for file in files: origFilePath = joinPaths(origStateDir, file) if not os.path.isdir(origFilePath): restoredFilePath = restoreFileOrDir(rdiffDestDir, "/", file, backupTime) assert open(restoredFilePath, "r").read() == open(origFilePath, "r").read() os.remove(restoredFilePath)
def _getRecentUserMessages(self): userRepos = self.userDB.getUserRepoPaths(self.getUsername()) asOfDate = rdw_helpers.rdwTime() asOfDate.initFromMidnightUTC(-5) return self._getUserMessages(userRepos, True, True, asOfDate, None)