This is an automated email from the ASF dual-hosted git repository.

harikrishna-patnala pushed a commit to branch FixMountFormatBackupAndRestore
in repository https://gitbox.apache.org/repos/asf/cloudstack.git

commit 2b82b03002d2f191fefff8530f3877896c447f16
Author: Harikrishna Patnala <[email protected]>
AuthorDate: Tue Mar 10 10:39:04 2026 +0530

    Fix repository mount failure during restore due to path format handling
    
    Restore could fail when the backup repository address was specified in
    formats such as \\server\share. The restore logic built a raw shell
    command which caused backslashes to be interpreted as escape characters,
    resulting in an invalid mount path.
    
    Execute the mount command using Script.executePipedCommands() so the
    repository path is passed as an argument instead of being embedded in a
    shell command string.
---
 .../LibvirtRestoreBackupCommandWrapper.java        | 28 +++++++++++++++-------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRestoreBackupCommandWrapper.java
 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRestoreBackupCommandWrapper.java
index 22dbfbdd67a..2b2e09df690 100644
--- 
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRestoreBackupCommandWrapper.java
+++ 
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRestoreBackupCommandWrapper.java
@@ -45,6 +45,7 @@ import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Objects;
@@ -52,7 +53,6 @@ import java.util.Objects;
 @ResourceWrapper(handles = RestoreBackupCommand.class)
 public class LibvirtRestoreBackupCommandWrapper extends 
CommandWrapper<RestoreBackupCommand, Answer, LibvirtComputingResource> {
     private static final String BACKUP_TEMP_FILE_PREFIX = "csbackup";
-    private static final String MOUNT_COMMAND = "sudo mount -t %s %s %s";
     private static final String UMOUNT_COMMAND = "sudo umount %s";
     private static final String FILE_PATH_PLACEHOLDER = "%s/%s";
     private static final String ATTACH_QCOW2_DISK_COMMAND = " virsh 
attach-disk %s %s %s --driver qemu --subdriver qcow2 --cache none";
@@ -197,7 +197,7 @@ public class LibvirtRestoreBackupCommandWrapper extends 
CommandWrapper<RestoreBa
 
     private String mountBackupDirectory(String backupRepoAddress, String 
backupRepoType, String mountOptions, Integer mountTimeout) {
         String randomChars = RandomStringUtils.random(5, true, false);
-        String mountDirectory = String.format("%s.%s",BACKUP_TEMP_FILE_PREFIX 
, randomChars);
+        String mountDirectory = String.format("%s.%s", 
BACKUP_TEMP_FILE_PREFIX, randomChars);
 
         try {
             mountDirectory = 
Files.createTempDirectory(mountDirectory).toString();
@@ -206,23 +206,35 @@ public class LibvirtRestoreBackupCommandWrapper extends 
CommandWrapper<RestoreBa
             throw new CloudRuntimeException("Failed to create the tmp mount 
directory for restore on the KVM host");
         }
 
-        String mount = String.format(MOUNT_COMMAND, backupRepoType, 
backupRepoAddress, mountDirectory);
-        if ("cifs".equals(backupRepoType)) {
+        if ("cifs".equalsIgnoreCase(backupRepoType)) {
             if (Objects.isNull(mountOptions) || mountOptions.trim().isEmpty()) 
{
                 mountOptions = "nobrl";
             } else {
                 mountOptions += ",nobrl";
             }
         }
+
+        List<String[]> commands = new ArrayList<>();
+        List<String> cmd = new ArrayList<>();
+        cmd.add("sudo");
+        cmd.add("mount");
+        cmd.add("-t");
+        cmd.add(backupRepoType);
+        cmd.add(backupRepoAddress);
+        cmd.add(mountDirectory);
         if (Objects.nonNull(mountOptions) && !mountOptions.trim().isEmpty()) {
-            mount += " -o " + mountOptions;
+            cmd.add("-o");
+            cmd.add(mountOptions);
         }
+        commands.add(cmd.toArray(new String[0]));
 
-        int exitValue = Script.runSimpleBashScriptForExitValue(mount, 
mountTimeout, false);
-        if (exitValue != 0) {
-            logger.error("Failed to mount repository {} of type {} to the 
directory {}", backupRepoAddress, backupRepoType, mountDirectory);
+        Pair<Integer, String> result = Script.executePipedCommands(commands, 
mountTimeout);
+        if (result.first() != 0) {
+            logger.error("Failed to mount repository {} of type {} to the 
directory {}. Error: {}",
+                    backupRepoAddress, backupRepoType, mountDirectory, 
result.second());
             throw new CloudRuntimeException("Failed to mount the backup 
repository on the KVM host");
         }
+
         return mountDirectory;
     }
 

Reply via email to