def validate_checksum(self, relative_path, expected_md5_hex): path = os.path.join(self.args.backup_base, relative_path) current_md5 = file_util.file_md5(path) if current_md5 == expected_md5_hex: self.log.debug("Backup file %s matches expected md5 "\ "%s", path, expected_md5_hex) return True self.log.warn("Backup file %s does not match expected md5 "\ "%s, got %s", path, expected_md5_hex, current_md5) return False
def _should_restore(self): """Determines if the :attr:`backup_file` should be restored. """ dest_path = os.path.join(self.args.data_dir, self.backup_file.restore_path) if not os.path.exists(dest_path): # no file, lets restore return RestoreResult(should_restore=True, restore_reason="No File", restore_path=dest_path, source_path=self.backup_file.backup_path) if self.args.no_checksum: # exsisting file and no checksum, do not restore return RestoreResult( should_restore=True, restore_reason="Existing file (Not checksummed)", restore_path=dest_path, source_path=self.backup_file.backup_path) existing_md5 = file_util.file_md5(dest_path) if existing_md5 == self.backup_file.md5: return RestoreResult(should_restore=False, restore_reason="Existing file (Checksummed)", restore_path=dest_path, source_path=self.backup_file.backup_path) # move the current file to # $data_dir/../cassback-corrupt/keyspace/$file_name _, file_name = os.path.split(dest_path) corrupt_path = os.path.join(*(self.args.data_dir, "..", "cassback-corrupt", self.backup_file.component.keyspace, file_name)) file_util.ensure_dir(os.path.dirname(corrupt_path)) self.log.info("Moving existing corrupt file %s to %s", dest_path, corrupt_path) shutil.move(dest_path, corrupt_path) return RestoreResult(should_restore=True, restore_reason="Existing file corrupt", restore_path=dest_path, corrupt_path=corrupt_path, source_path=self.backup_file.backup_path)
def _should_restore(self): """Determines if the :attr:`backup_file` should be restored. """ dest_path = os.path.join(self.args.data_dir, self.backup_file.restore_path) if not os.path.exists(dest_path): # no file, lets restore return RestoreResult(should_restore=True, restore_reason="No File", restore_path=dest_path, source_path=self.backup_file.backup_path) if self.args.no_checksum: # exsisting file and no checksum, do not restore return RestoreResult(should_restore=True, restore_reason="Existing file (Not checksummed)", restore_path=dest_path, source_path=self.backup_file.backup_path) existing_md5 = file_util.file_md5(dest_path) if existing_md5 == self.backup_file.md5: return RestoreResult(should_restore=False, restore_reason="Existing file (Checksummed)", restore_path=dest_path, source_path=self.backup_file.backup_path) # move the current file to # $data_dir/../cassback-corrupt/keyspace/$file_name _, file_name = os.path.split(dest_path) corrupt_path = os.path.join(*(self.args.data_dir, "..", "cassback-corrupt", self.backup_file.component.keyspace, file_name)) file_util.ensure_dir(os.path.dirname(corrupt_path)) self.log.info("Moving existing corrupt file %s to %s", dest_path, corrupt_path) shutil.move(dest_path, corrupt_path) return RestoreResult(should_restore=True, restore_reason="Existing file corrupt", restore_path=dest_path, corrupt_path=corrupt_path, source_path=self.backup_file.backup_path)
def __call__(self): """Run the restore operation and store the result.""" op_result = self._should_restore() if not op_result.should_restore: self.log.info("Skipping file %s because %s", self.backup_file, op_result.restore_reason) return op_result self.log.info("Restoring file %s because %s", self.backup_file, op_result.restore_reason) try: restore_path = self.endpoint.restore_file(self.backup_file, self.args.data_dir) except (EnvironmentError) as e: if e.errno != errno.ENOENT: raise # source file was missing op_result.failed_reason = "Source file missing" return op_result # Until I change the endpoint lets check this assert restore_path == op_result.restore_path self.log.info("Restored file %s to %s", self.backup_file, op_result.restore_path) if not self.args.no_chown: self._chown_restored_file(op_result) if not self.args.no_chmod: self._chmod_restored_file(op_result) if self.args.no_checksum: self.log.debug("Restored file at %s was not checksumed", op_result.restore_path) return op_result existing_md5 = file_util.file_md5(op_result.restore_path) if existing_md5 != self.backup_file.md5: # Better handling ? self.log.error("Restored file %s has MD5 %s, expected %s", op_result.restore_path, existing_md5, self.backup_file.md5) self.log.info("Deleting corrupt restored file %s", op_result.restore_path) try: os.remove(op_result.restore_path) except (Exception): self.log.error("Error deleting corrupt restored file %s", op_result.restore_path, exc_info=True) print "Error deleting corrupt restored file %s" % ( op_result.restore_path) os.kill(os.getpid(), signal.SIGKILL) if self.args.fail_if_corrupt: # This is probably the wrong thing to do print "Restored file %s has MD5 %s, expected %s" % ( op_result.restore_path, existing_md5, self.backup_file.md5) print "Killing self." os.kill(os.getpid(), signal.SIGKILL) op_result.failed_reason = "Restored File corrupt" return op_result