Exemple #1
0
 def test_simple_backup(self):
     node_handler_process = NodeHandlerProcess('localhost',
                                               TestSidecar.PORT,
                                               '/tmp/example',
                                               '/tmp/backup_output/out',
                                               'dummy_checksum')
     sleep(5)
     node_handler_process()
     expected_file = BackupFile.create_from_path('/tmp/example',
                                                 "/tmp/backup_output/out2")
     backup_file = BackupFile("/tmp/backup_output/out")
     self.assertEqual(expected_file.get_hash(), backup_file.get_hash())
Exemple #2
0
 def setUp(self) -> None:
     try:
         from pytest_cov.embed import cleanup_on_sigterm
     except ImportError:
         pass
     else:
         cleanup_on_sigterm()
     shutil.rmtree('/tmp/backup_output', ignore_errors=True)
     os.mkdir('/tmp/backup_output')
     with open('/tmp/example', 'w') as example_file:
         example_file.write("asd")
     BackupFile.create_from_path('/tmp/example', "/tmp/backup_output/out2")
     SidecarProcess.logger = logging.getLogger("dummy")
     self.sidecar_process = SidecarProcess(TestSidecar.PORT, 3)
     self.p = Process(target=self.sidecar_process)
     self.p.start()
Exemple #3
0
 def __call__(self, *args, **kwargs):
     MockNodeHandler.BARRIER.wait()
     bf = BackupFile.create_from_path(MockNodeHandler.PATH_TO_BACKUP,
                                      self.write_file_path)
     if bf.get_hash() == self.previous_checksum:
         open(self.write_file_path + ".SAME", "w").close()
     else:
         open(self.write_file_path + ".CORRECT", "w").close()
Exemple #4
0
 def test_backup_same_checksum(self):
     expected_file = BackupFile.create_from_path('/tmp/example',
                                                 "/tmp/backup_output/out2")
     node_handler_process = NodeHandlerProcess('localhost',
                                               TestSidecar.PORT,
                                               '/tmp/example',
                                               '/tmp/backup_output/out',
                                               expected_file.get_hash())
     sleep(5)
     node_handler_process()
     self.assertTrue(os.path.exists('/tmp/backup_output/out.SAME'))
Exemple #5
0
    def __handle_client_connection(client_sock, backup_no: int):
        """
        Read message from a specific client socket and closes the socket

        If a problem arises in the communication with the client, the
        client socket will also be closed
        """
        socket_transferer = BlockingSocketTransferer(client_sock)
        try:
            msg = socket_transferer.receive_plain_text()
            msg = json.loads(msg)
            path, previous_checksum = msg['path'], msg['checksum']
            SidecarProcess.logger.debug("Previous checksum for path %s is '%s'" % (path, previous_checksum))
        except (OSError, TimeoutError) as e:
            SidecarProcess.logger.exception("Error while reading socket %s: %s" % (client_sock, e))
            socket_transferer.abort()
            return
        try:
            backup_file = BackupFile.create_from_path(path, TMP_BACKUP_PATH % backup_no)
        except Exception:
            SidecarProcess.logger.exception("Error while making backup file")
            socket_transferer.abort()
            return
        file_checksum = backup_file.get_hash()
        if file_checksum == previous_checksum:
            SidecarProcess.logger.info("Previous checksum equals to actual data, skipping backup")
            socket_transferer.send_plain_text("SAME")
            socket_transferer.abort()
            return
        else:
            socket_transferer.send_plain_text("DIFF")
        try:
            socket_transferer.send_file(TMP_BACKUP_PATH % backup_no)
            SidecarProcess.logger.debug("Backup file sent")
            socket_transferer.send_plain_text(file_checksum)
        except Exception as e:
            SidecarProcess.logger.exception("Error while writing socket %s: %s" % (client_sock, e))
            socket_transferer.abort()
            return
        finally:
            socket_transferer.close()
        return
 def _dispatch_running_tasks(self):
     """
     Handles running tasks
     """
     now_running_tasks = {}
     for node_data, task in self.running_tasks.items():
         if not task.is_running():
             if task.backup_is_correct():
                 ft = FinishedTask(
                     result_path=task.write_file_path,
                     kb_size=os.path.getsize(task.write_file_path) / 1024,
                     timestamp=datetime.now(),
                     checksum=BackupFile(task.write_file_path).get_hash())
                 self.database.register_finished_task(
                     node_data[0], node_data[1], ft)
                 BackupScheduler.logger.info(
                     "Backup for node %s and path %s finished succesfully" %
                     node_data)
                 self._reload_schedule()
                 self._clean_backup_path()
             elif task.backup_is_same():
                 ft = self.database.get_node_finished_tasks(
                     node_data[0], node_data[1])[0]
                 ft = FinishedTask(result_path=ft.result_path,
                                   kb_size=ft.kb_size,
                                   timestamp=datetime.now(),
                                   checksum=ft.checksum)
                 self.database.register_finished_task(
                     node_data[0], node_data[1], ft)
                 BackupScheduler.logger.info(
                     "Backup for node %s and path %s finished succesfully" %
                     node_data)
                 self._reload_schedule()
                 self._clean_backup_path()
             else:
                 BackupScheduler.logger.error(
                     "Backup for node %s and path %s failed" % node_data)
         else:
             now_running_tasks[node_data] = task
     self.running_tasks = now_running_tasks
    def __call__(self) -> NoReturn:
        """
        Code for running the handler in a new process

        The process works this way:
            1. Connects to node sidecar asking for node_path compressed
            2. If the backup is the same as previous checksum, writes a .SAME file
            3. Downloads the file saving it in write file path
                3.1. At start it writes an empty file named self.write_file_path but ending with .WIP
                3.2. Starts saving the backup in a file located in self.write_file_path
                3.3. When the backup is saved saves an empty file named self.write_file_path but ending with .CORRECT
                3.4. Deletes the .WIP file
            4. Seppuku
        """
        NodeHandlerProcess.logger.debug(
            "Starting node handler for node %s:%d and path %s" %
            (self.node_address, self.node_port, self.node_path))
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            sock.connect((self.node_address, self.node_port))
            socket_transferer = BlockingSocketTransferer(sock)
            socket_transferer.send_plain_text(
                json.dumps({
                    "checksum": self.previous_checksum,
                    "path": self.node_path
                }))
        except Exception as e:
            NodeHandlerProcess.logger.exception(
                "Error while writing socket %s: %s" % (sock, e))
            NodeHandlerProcess.logger.info(
                "Terminating handler for node %s:%d and path %s" %
                (self.node_address, self.node_port, self.node_path))
            return
        msg = socket_transferer.receive_plain_text()
        if msg == "SAME":
            NodeHandlerProcess.logger.debug("The backup was the same")
            NodeHandlerProcess.logger.info(
                "Terminating handler for node %s:%d and path %s" %
                (self.node_address, self.node_port, self.node_path))
            open(SAME_FILE_FORMAT % self.write_file_path, 'w').close()
            return
        if msg == "ABORT":
            NodeHandlerProcess.logger.error("Abort order sent from sidecar")
            NodeHandlerProcess.logger.info(
                "Terminating handler for node %s:%d and path %s" %
                (self.node_address, self.node_port, self.node_path))
            return
        open(WIP_FILE_FORMAT % self.write_file_path, 'w').close()
        data_file = open(self.write_file_path, 'ab')
        try:
            socket_transferer.receive_file_data(data_file)
            NodeHandlerProcess.logger.debug("File data received")
            checksum = socket_transferer.receive_plain_text()
        except Exception as e:
            NodeHandlerProcess.logger.exception(
                "Error while reading socket %s: %s" % (sock, e))
            NodeHandlerProcess.logger.info(
                "Terminating handler for node %s:%d and path %s" %
                (self.node_address, self.node_port, self.node_path))
            return
        data_file.close()
        backup_file = BackupFile(self.write_file_path)
        if backup_file.get_hash() == checksum:
            NodeHandlerProcess.logger.debug("Backup checksum: %s" % checksum)
        else:
            NodeHandlerProcess.logger.error(
                "Error verifying checksum. Local: %s vs Server: %s" %
                (backup_file.get_hash(), checksum))
            return
        open(CORRECT_FILE_FORMAT % self.write_file_path, 'w').close()
        os.remove(WIP_FILE_FORMAT % self.write_file_path)
        NodeHandlerProcess.logger.info(
            "Terminating handler for node %s:%d and path %s" %
            (self.node_address, self.node_port, self.node_path))
Exemple #8
0
 def test_generate_different_same_hash(self):
     backup_file = BackupFile.create_from_path('/tmp/test_path',
                                               '/tmp/file.tgz')
     backup_file2 = BackupFile.create_from_path('/tmp/test_path',
                                                '/tmp/file2.tgz')
     self.assertEqual(backup_file2.get_hash(), backup_file.get_hash())
Exemple #9
0
 def test_load_and_create_same_hash(self):
     backup_file = BackupFile.create_from_path('/tmp/test_path',
                                               '/tmp/file.tgz')
     backup_file2 = BackupFile('/tmp/file.tgz')
     self.assertEqual(backup_file2.get_hash(), backup_file.get_hash())