DockerEnvironmentBackupManager implements EnvironmentBackupManager { @VisibleForTesting void executeCommand( String[] commandLine, int timeout, String address, String workspaceId, Set<Integer> successResponseCodes) throws TimeoutException, IOException, InterruptedException { final ListLineConsumer outputConsumer = new ListLineConsumer(); Process process = ProcessUtil.executeAndWait(commandLine, timeout, SECONDS, outputConsumer); if (!successResponseCodes.contains(process.exitValue())) { LOG.error( "Error occurred during backup/restore of workspace '{}' on node '{}' : {}", workspaceId, address, outputConsumer.getText()); throw new IOException("Synchronization process failed. Exit code " + process.exitValue()); } } @Inject  DockerEnvironmentBackupManager(
      @Named("machine.backup.backup_script") String backupScript,
      @Named("machine.backup.restore_script") String restoreScript,
      @Named("machine.backup.backup_duration_second") int maxBackupDurationSec,
      @Named("machine.backup.restore_duration_second") int restoreDurationSec,
      @Named("che.user.workspaces.storage") File backupsRootDir,
      WorkspaceIdHashLocationFinder workspaceIdHashLocationFinder,
      @Named("che.workspace.projects.storage") String projectFolderPath,
      WorkspaceManager workspaceManager,
      DockerConnector dockerConnector); @Override void backupWorkspace(String workspaceId); void backupWorkspaceAndCleanup(String workspaceId, String containerId, String nodeHost); void restoreWorkspaceBackup(String workspaceId, String containerId, String nodeHost);  }
@Test(timeOut = 2_000 * 60) public void shouldIgnoreAllNewBackupRequestsIfOldHasNotFinishedYet() throws Exception { injectWorkspaceLock(WORKSPACE_ID); ThreadFreezer backupFreezer = startNewProcessAndFreeze(this::runBackup); executeTaskNTimesSimultaneouslyWithBarrier(this::runBackup); backupFreezer.unfreeze(); awaitFinalization(); verify(backupManager, times(1)) .executeCommand( anyObject(), anyInt(), nullable(String.class), nullable(String.class), anySetOf(Integer.class)); }
@Test(timeOut = 2_000 * 60) public void shouldIgnoreOthersBackupsAndFailOnRestoresWhileBackupInProgress() throws Exception { injectWorkspaceLock(WORKSPACE_ID); ThreadFreezer backupFreezer = startNewProcessAndFreeze(this::runBackup); executeTasksSimultaneouslyWithBarrier( this::runBackup, this::runRestore, this::runBackup, this::runRestore, this::runBackup, this::runRestore, this::runBackup, this::runRestore); backupFreezer.unfreeze(); awaitFinalization(); verify(backupManager, times(1)) .executeCommand( cmdCaptor.capture(), anyInt(), nullable(String.class), nullable(String.class), anySetOf(Integer.class)); assertEquals(cmdCaptor.getValue()[0], BACKUP_SCRIPT); }
@Test(timeOut = 2_000 * 60) public void shouldIgnoreOthersBackupsAndFailOnRestoresWhileRestoreInProgress() throws Exception { ThreadFreezer restoreFreezer = startNewProcessAndFreeze(this::runRestore); executeTasksSimultaneouslyWithBarrier( this::runBackup, this::runRestore, this::runBackup, this::runRestore, this::runBackup, this::runRestore, this::runBackup, this::runRestore); restoreFreezer.unfreeze(); awaitFinalization(); verify(backupManager, times(1)) .executeCommand( cmdCaptor.capture(), anyInt(), nullable(String.class), nullable(String.class), anySetOf(Integer.class)); assertEquals(cmdCaptor.getValue()[0], RESTORE_SCRIPT); }
@Test(timeOut = 2_000 * 60) public void shouldProcessOnlyOneBackupAtTheSameTime() throws Exception { injectWorkspaceLock(WORKSPACE_ID); ThreadFreezer backupFreezer = startNewProcessAndFreeze(this::runBackup); executeTaskNTimesSimultaneouslyWithBarrier(this::runBackup); backupFreezer.unfreeze(); awaitFinalization(); verify(backupManager, times(1)) .executeCommand( cmdCaptor.capture(), anyInt(), nullable(String.class), nullable(String.class), anySetOf(Integer.class)); assertEquals(cmdCaptor.getValue()[0], BACKUP_SCRIPT); }
@Test(timeOut = 2_000 * 60) public void shouldQueuedBackupWithCleanupAfterBackup() throws Exception { injectWorkspaceLock(WORKSPACE_ID); ThreadFreezer backupFreezer = startNewProcessAndFreeze(this::runBackup); executor.execute(this::runBackupWithCleanup); waitUntilWorkspaceLockLockedWithQueueLength(WORKSPACE_ID); backupFreezer.unfreeze(); awaitFinalization(); verify(backupManager, times(2)) .executeCommand( cmdCaptor.capture(), anyInt(), nullable(String.class), nullable(String.class), anySetOf(Integer.class)); assertEquals(cmdCaptor.getValue()[0], BACKUP_SCRIPT); }
@Test(timeOut = 2_000 * 60) public void shouldIgnoreAllBackupsAndFailOnRestoresWhileBackupWithCleanupInQueueAfterBackup() throws Exception { injectWorkspaceLock(WORKSPACE_ID); ThreadFreezer backupFreezer = startNewProcessAndFreeze(this::runBackup); executor.execute(this::runBackupWithCleanup); waitUntilWorkspaceLockLockedWithQueueLength(WORKSPACE_ID); executeTasksSimultaneouslyWithBarrier( this::runBackup, this::runRestore, this::runBackup, this::runRestore, this::runBackup, this::runRestore, this::runBackup, this::runRestore); backupFreezer.unfreeze(); awaitFinalization(); verify(backupManager, times(2)) .executeCommand( cmdCaptor.capture(), anyInt(), nullable(String.class), nullable(String.class), anySetOf(Integer.class)); assertEquals(cmdCaptor.getValue()[0], BACKUP_SCRIPT); }