Support timeout configuration for Create and Restore NAS backup (#12964)

* Introduce configurable timeout to Create NAS backup

* use timeout set via "commands.timeout"
This commit is contained in:
Abhisar Sinha 2026-04-10 10:11:54 +05:30 committed by GitHub
parent 4ba4bd33c3
commit 68bd056306
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 26 additions and 13 deletions

View File

@ -88,7 +88,7 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
List<PrimaryDataStoreTO> restoreVolumePools = command.getRestoreVolumePools();
List<String> restoreVolumePaths = command.getRestoreVolumePaths();
Integer mountTimeout = command.getMountTimeout() * 1000;
int timeout = command.getWait();
int timeout = command.getWait() > 0 ? command.getWait() * 1000 : serverResource.getCmdsTimeout();
KVMStoragePoolManager storagePoolMgr = serverResource.getStoragePoolMgr();
List<String> backupFiles = command.getBackupFiles();
@ -270,7 +270,7 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
return replaceBlockDeviceWithBackup(storagePoolMgr, volumePool, volumePath, backupPath, timeout, createTargetVolume, size);
}
int exitValue = Script.runSimpleBashScriptForExitValue(String.format(RSYNC_COMMAND, backupPath, volumePath));
int exitValue = Script.runSimpleBashScriptForExitValue(String.format(RSYNC_COMMAND, backupPath, volumePath), timeout, false);
return exitValue == 0;
}
@ -278,7 +278,7 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
KVMStoragePool volumeStoragePool = storagePoolMgr.getStoragePool(volumePool.getPoolType(), volumePool.getUuid());
QemuImg qemu;
try {
qemu = new QemuImg(timeout * 1000, true, false);
qemu = new QemuImg(timeout, true, false);
String volumeUuid = getVolumeUuidFromPath(volumePath, volumePool);
KVMPhysicalDisk disk = null;
if (createTargetVolume) {

View File

@ -52,6 +52,7 @@ public class LibvirtTakeBackupCommandWrapper extends CommandWrapper<TakeBackupCo
List<PrimaryDataStoreTO> volumePools = command.getVolumePools();
final List<String> volumePaths = command.getVolumePaths();
KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
int timeout = command.getWait() > 0 ? command.getWait() * 1000 : libvirtComputingResource.getCmdsTimeout();
List<String> diskPaths = new ArrayList<>();
if (Objects.nonNull(volumePaths)) {
@ -81,7 +82,7 @@ public class LibvirtTakeBackupCommandWrapper extends CommandWrapper<TakeBackupCo
"-d", diskPaths.isEmpty() ? "" : String.join(",", diskPaths)
});
Pair<Integer, String> result = Script.executePipedCommands(commands, libvirtComputingResource.getCmdsTimeout());
Pair<Integer, String> result = Script.executePipedCommands(commands, timeout);
if (result.first() != 0) {
logger.debug("Failed to take VM backup: " + result.second());

View File

@ -391,7 +391,15 @@ public class LibvirtRestoreBackupCommandWrapperTest {
try (MockedStatic<Script> scriptMock = mockStatic(Script.class)) {
scriptMock.when(() -> Script.runSimpleBashScriptForExitValue(anyString(), anyInt(), any(Boolean.class)))
.thenReturn(0); // Mount success
.thenAnswer(invocation -> {
String command = invocation.getArgument(0);
if (command.contains("mount")) {
return 0; // mount success
} else if (command.contains("rsync")) {
return 1; // Rsync failure
}
return 0; // Other commands success
});
scriptMock.when(() -> Script.runSimpleBashScriptForExitValue(anyString()))
.thenAnswer(invocation -> {
String command = invocation.getArgument(0);
@ -399,8 +407,6 @@ public class LibvirtRestoreBackupCommandWrapperTest {
return 0; // File exists
} else if (command.contains("qemu-img check")) {
return 0; // File is valid
} else if (command.contains("rsync")) {
return 1; // Rsync failure
}
return 0; // Other commands success
});
@ -444,7 +450,15 @@ public class LibvirtRestoreBackupCommandWrapperTest {
try (MockedStatic<Script> scriptMock = mockStatic(Script.class)) {
scriptMock.when(() -> Script.runSimpleBashScriptForExitValue(anyString(), anyInt(), any(Boolean.class)))
.thenReturn(0); // Mount success
.thenAnswer(invocation -> {
String command = invocation.getArgument(0);
if (command.contains("mount")) {
return 0; // Mount success
} else if (command.contains("rsync")) {
return 0; // Rsync success
}
return 0; // Other commands success
});
scriptMock.when(() -> Script.runSimpleBashScriptForExitValue(anyString()))
.thenAnswer(invocation -> {
String command = invocation.getArgument(0);
@ -452,8 +466,6 @@ public class LibvirtRestoreBackupCommandWrapperTest {
return 0; // File exists
} else if (command.contains("qemu-img check")) {
return 0; // File is valid
} else if (command.contains("rsync")) {
return 0; // Rsync success
} else if (command.contains("virsh attach-disk")) {
return 1; // Attach failure
}
@ -539,10 +551,10 @@ public class LibvirtRestoreBackupCommandWrapperTest {
filesMock.when(() -> Files.createTempDirectory(anyString())).thenReturn(tempPath);
try (MockedStatic<Script> scriptMock = mockStatic(Script.class)) {
scriptMock.when(() -> Script.runSimpleBashScriptForExitValue(anyString(), anyInt(), any(Boolean.class)))
.thenReturn(0); // Mount success
scriptMock.when(() -> Script.runSimpleBashScriptForExitValue(anyString()))
.thenReturn(0); // All other commands success
.thenReturn(0); // All commands success
scriptMock.when(() -> Script.runSimpleBashScriptForExitValue(anyString(), anyInt(), any(Boolean.class)))
.thenReturn(0); // All commands success
filesMock.when(() -> Files.deleteIfExists(any(Path.class))).thenReturn(true);