Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ private String mountBackupDirectory(String backupRepoAddress, String backupRepoT
logger.error("Failed to create the tmp mount directory {} for restore", mountDirectory, e);
throw new CloudRuntimeException("Failed to create the tmp mount directory for restore on the KVM host");
}
int exitValue;
try {
String mountPath = Script.getExecutableAbsolutePath("mount");
List<String> mountCmd = new ArrayList<>();
Expand All @@ -221,23 +222,33 @@ private String mountBackupDirectory(String backupRepoAddress, String backupRepoT
mountCmd.add("-o");
mountCmd.add(mountOptions);
}
Script.executeCommand(mountCmd.toArray(new String[0]));
exitValue = Script.executeCommandForExitValue(mountTimeout, mountCmd.toArray(new String[0]));
} catch (Exception e) {
logger.error("Failed to mount repository {} of type {} to the directory {}", backupRepoAddress, backupRepoType, mountDirectory, e);
throw new CloudRuntimeException("Failed to mount the backup repository on the KVM host");
}
if (exitValue != 0) {
logger.error("Failed to mount repository {} of type {} to the directory {}, mount exited with {}", backupRepoAddress,
backupRepoType, mountDirectory, exitValue);
throw new CloudRuntimeException("Failed to mount the backup repository on the KVM host");
}
Comment on lines +230 to +234
return mountDirectory;
}

private void unmountBackupDirectory(String backupDirectory) {
int exitValue;
try {
String umountPath = Script.getExecutableAbsolutePath("umount");
String[] umountCmd = new String[] { "sudo", umountPath, backupDirectory };
Script.executeCommand(umountCmd);
exitValue = Script.executeCommandForExitValue(umountCmd);
} catch (Exception e) {
Comment on lines 241 to 244
logger.error("Failed to unmount backup directory {}", backupDirectory, e);
throw new CloudRuntimeException("Failed to unmount the backup directory");
}
if (exitValue != 0) {
logger.error("Failed to unmount backup directory {}, umount exited with {}", backupDirectory, exitValue);
throw new CloudRuntimeException("Failed to unmount the backup directory");
}
}

private void deleteTemporaryDirectory(String backupDirectory) {
Expand Down Expand Up @@ -276,7 +287,7 @@ private boolean replaceVolumeWithBackup(KVMStoragePoolManager storagePoolMgr, Pr
}

String[] rsyncCmd = new String[] { Script.getExecutableAbsolutePath("rsync"), "-az", backupPath, volumePath };
int exitValue = Script.executeCommandForExitValue(rsyncCmd);
int exitValue = Script.executeCommandForExitValue(timeout, rsyncCmd);
return exitValue == 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,8 @@ public void testExecuteWithMountFailure() throws Exception {
filesMock.when(() -> Files.createTempDirectory(anyString())).thenReturn(tempPath);

try (MockedStatic<Script> scriptMock = mockStatic(Script.class)) {
scriptMock.when(() -> Script.executeCommand(any(String[].class)))
.thenThrow(new RuntimeException("failure")); // Mount failure
scriptMock.when(() -> Script.executeCommandForExitValue(anyLong(), any(String[].class)))
.thenReturn(1); // Mount failure

Answer result = wrapper.execute(command, libvirtComputingResource);

Expand Down Expand Up @@ -404,7 +404,7 @@ public void testExecuteWithRsyncFailure() throws Exception {
.thenAnswer(invocation -> invocation.getArgument(0));
scriptMock.when(() -> Script.executeCommand(any(String[].class)))
.thenReturn(null);
scriptMock.when(() -> Script.executeCommandForExitValue(any(String[].class)))
scriptMock.when(() -> Script.executeCommandForExitValue(anyLong(), any(String[].class)))
.thenAnswer(invocation -> {
if (Arrays.stream(invocation.getArguments()).map(String::valueOf).anyMatch("rsync"::equals)) {
return 1; // Rsync failure
Comment on lines 409 to 410
Expand Down Expand Up @@ -579,4 +579,38 @@ public void testExecuteWithMultipleVolumes() throws Exception {
}
}
}

@Test
public void testMountUsesTheConfiguredTimeout() throws Exception {
when(command.getVmName()).thenReturn("test-vm");
when(command.getBackupPath()).thenReturn("backup/path");
when(command.getBackupRepoAddress()).thenReturn("192.168.1.100:/backup");
when(command.getBackupRepoType()).thenReturn("nfs");
when(command.getMountOptions()).thenReturn("rw");
when(command.getMountTimeout()).thenReturn(30);

try (MockedStatic<Files> filesMock = mockStatic(Files.class)) {
Path tempPath = Mockito.mock(Path.class);
when(tempPath.toString()).thenReturn("/tmp/csbackup.abc123");
filesMock.when(() -> Files.createTempDirectory(anyString())).thenReturn(tempPath);

try (MockedStatic<Script> scriptMock = mockStatic(Script.class)) {
scriptMock.when(() -> Script.getExecutableAbsolutePath(anyString()))
.thenAnswer(invocation -> invocation.getArgument(0));
final long[] mountTimeout = new long[1];
scriptMock.when(() -> Script.executeCommandForExitValue(anyLong(), any(String[].class)))
.thenAnswer(invocation -> {
if (Arrays.stream(invocation.getArguments()).map(String::valueOf).anyMatch("mount"::equals)) {
mountTimeout[0] = invocation.getArgument(0);
return 1; // stop the restore right after the mount
}
return 0;
});

wrapper.execute(command, libvirtComputingResource);

Assert.assertEquals(30 * 1000L, mountTimeout[0]);
}
}
}
}
Loading