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

weizhou pushed a commit to branch 4.18
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/4.18 by this push:
     new 4ef7ebbded8 ssvm: pass all accessible secondary storage to ssvm (#7410)
4ef7ebbded8 is described below

commit 4ef7ebbded87bcc5db04678d0b63e590aca7e128
Author: Abhishek Kumar <[email protected]>
AuthorDate: Mon Jun 12 12:32:42 2023 +0530

    ssvm: pass all accessible secondary storage to ssvm (#7410)
    
    * ssvm: pass all accessible secondary storage to ssvm
    
    Fixes #7162
    
    Signed-off-by: Abhishek Kumar <[email protected]>
    
    * changes
    
    Signed-off-by: Abhishek Kumar <[email protected]>
    
    * test
    
    Signed-off-by: Abhishek Kumar <[email protected]>
    
    * license
    
    Signed-off-by: Abhishek Kumar <[email protected]>
    
    ---------
    
    Signed-off-by: Abhishek Kumar <[email protected]>
---
 .../SecondaryStorageManagerImpl.java               | 49 ++++++++----
 .../SecondaryStorageManagerImplTest.java           | 89 ++++++++++++++++++++++
 systemvm/agent/scripts/ssvm-check.sh               | 27 ++++---
 3 files changed, 139 insertions(+), 26 deletions(-)

diff --git 
a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java
 
b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java
index aa03211d9c0..f93d3e28a38 100644
--- 
a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java
+++ 
b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java
@@ -26,6 +26,7 @@ import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
@@ -1065,11 +1066,12 @@ public class SecondaryStorageManagerImpl extends 
ManagerBase implements Secondar
         Map<String, String> details = 
_vmDetailsDao.listDetailsKeyPairs(vm.getId());
         vm.setDetails(details);
 
-        DataStore secStore = 
_dataStoreMgr.getImageStoreWithFreeCapacity(dest.getDataCenter().getId());
-        if (secStore == null) {
+        List<DataStore> secStores= 
_dataStoreMgr.listImageStoresWithFreeCapacity(dest.getDataCenter().getId());
+        if (CollectionUtils.isEmpty(secStores)) {
             s_logger.warn(String.format("Unable to finalize virtual machine 
profile [%s] as it has no secondary storage available to satisfy storage needs 
for zone [%s].", profile.toString(), dest.getDataCenter().getUuid()));
             return false;
         }
+        Collections.shuffle(secStores);
 
         final Map<String, String> sshAccessDetails = 
_networkMgr.getSystemVMAccessDetails(profile.getVirtualMachine());
         final Map<String, String> ipAddressDetails = new 
HashMap<>(sshAccessDetails);
@@ -1163,7 +1165,7 @@ public class SecondaryStorageManagerImpl extends 
ManagerBase implements Secondar
         if (dc.getDns2() != null) {
             buf.append(" dns2=").append(dc.getDns2());
         }
-        String nfsVersion = imageStoreDetailsUtil != null ? 
imageStoreDetailsUtil.getNfsVersion(secStore.getId()) : null;
+        String nfsVersion = imageStoreDetailsUtil != null ? 
imageStoreDetailsUtil.getNfsVersion(secStores.get(0).getId()) : null;
         buf.append(" nfsVersion=").append(nfsVersion);
         buf.append(" 
keystore_password=").append(VirtualMachineGuru.getEncodedString(PasswordGenerator.generateRandomPassword(16)));
         String bootArgs = buf.toString();
@@ -1175,27 +1177,44 @@ public class SecondaryStorageManagerImpl extends 
ManagerBase implements Secondar
         s_logger.debug(String.format("Setting UseHttpsToUpload config on 
cmdline with [%s] value.", useHttpsToUpload));
         buf.append(" useHttpsToUpload=").append(useHttpsToUpload);
 
-        addSecondaryStorageServerAddressToBuffer(buf, secStore, vmName);
+        addSecondaryStorageServerAddressToBuffer(buf, secStores, vmName);
 
         return true;
     }
 
     /**
-     * Adds the secondary storage address to the buffer if it is in the 
following pattern: <protocol>//<address>/...
+     * Adds the secondary storages address to the buffer if it is in the 
following pattern: <protocol>//<address>/...
      */
-    protected void addSecondaryStorageServerAddressToBuffer(StringBuilder 
buffer, DataStore dataStore, String vmName) {
-        String url = dataStore.getTO().getUrl();
-        String[] urlArray = url.split("/");
+    protected void addSecondaryStorageServerAddressToBuffer(StringBuilder 
buffer, List<DataStore> dataStores, String vmName) {
+        List<String> addresses = new ArrayList<>();
+        for (DataStore dataStore: dataStores) {
+            String url = dataStore.getTO().getUrl();
+            String[] urlArray = url.split("/");
+
+            if (s_logger.isDebugEnabled()) {
+                s_logger.debug(String.format("Found [%s] as secondary storage 
[%s] URL for SSVM [%s].", dataStore.getName(), url, vmName));
+            }
+            if (ArrayUtils.getLength(urlArray) < 3) {
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug(String.format("Could not retrieve secondary 
storage [%s] address from URL [%s] of SSVM [%s].", dataStore.getName(), url, 
vmName));
+                }
+                continue;
+            }
+
+            String address = urlArray[2];
+            s_logger.info(String.format("Using [%s] as address of secondary 
storage [%s] of SSVM [%s].", address, dataStore.getName(), vmName));
+            if (!addresses.contains(address)) {
+                addresses.add(address);
+            }
 
-        s_logger.debug(String.format("Found [%s] as secondary storage's URL 
for SSVM [%s].", url, vmName));
-        if (ArrayUtils.getLength(urlArray) < 3) {
-            s_logger.debug(String.format("Could not retrieve secondary storage 
address from URL [%s] of SSVM [%s].", url, vmName));
+        }
+        if (addresses.isEmpty()) {
+            if (s_logger.isDebugEnabled()) {
+                s_logger.debug(String.format("No address found for the 
secondary storages: [%s] of SSVM: [%s]", 
StringUtils.join(dataStores.stream().map(DataStore::getName).collect(Collectors.toList()),
 ","), vmName));
+            }
             return;
         }
-
-        String address = urlArray[2];
-        s_logger.info(String.format("Using [%s] as address of secondary 
storage of SSVM [%s].", address, vmName));
-            buffer.append(" secondaryStorageServerAddress=").append(address);
+        buffer.append(" 
secondaryStorageServerAddress=").append(StringUtils.join(addresses, ","));
     }
 
     @Override
diff --git 
a/services/secondary-storage/controller/src/test/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImplTest.java
 
b/services/secondary-storage/controller/src/test/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImplTest.java
new file mode 100644
index 00000000000..6df205e1aac
--- /dev/null
+++ 
b/services/secondary-storage/controller/src/test/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImplTest.java
@@ -0,0 +1,89 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.secondarystorage;
+
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.utils.net.NetUtils;
+import com.google.common.net.InetAddresses;
+
+@RunWith(MockitoJUnitRunner.class)
+public class SecondaryStorageManagerImplTest {
+    private final SecureRandom secureRandom = new SecureRandom();
+
+    @Spy
+    @InjectMocks
+    private SecondaryStorageManagerImpl secondaryStorageManager;
+
+    private List<DataStore> 
mockDataStoresForTestAddSecondaryStorageServerAddressToBuffer(List<String> 
addresses) {
+        List<DataStore> dataStores = new ArrayList<>();
+        for (String address: addresses) {
+            DataStore dataStore = Mockito.mock(DataStore.class);
+            DataStoreTO dataStoreTO = Mockito.mock(DataStoreTO.class);
+            
Mockito.when(dataStoreTO.getUrl()).thenReturn(NetUtils.isValidIp4(address) ? 
String.format("http://%s";, address) : address);
+            Mockito.when(dataStore.getTO()).thenReturn(dataStoreTO);
+            dataStores.add(dataStore);
+        }
+        return dataStores;
+    }
+
+    private void runAddSecondaryStorageServerAddressToBufferTest(List<String> 
addresses, String expected) {
+        List<DataStore> dataStores = 
mockDataStoresForTestAddSecondaryStorageServerAddressToBuffer(addresses);
+        StringBuilder builder = new StringBuilder();
+        
secondaryStorageManager.addSecondaryStorageServerAddressToBuffer(builder, 
dataStores, "VM");
+        String result = builder.toString();
+        result = result.contains("=") ? result.split("=")[1] : null;
+        Assert.assertEquals(expected, result);
+    }
+
+    @Test
+    public void testAddSecondaryStorageServerAddressToBufferDifferentAddress() 
{
+        String randomIp1 = 
InetAddresses.fromInteger(secureRandom.nextInt()).getHostAddress();
+        String randomIp2 = 
InetAddresses.fromInteger(secureRandom.nextInt()).getHostAddress();
+        List<String> addresses = List.of(randomIp1, randomIp2);
+        String expected = StringUtils.join(addresses, ",");
+        runAddSecondaryStorageServerAddressToBufferTest(addresses, expected);
+    }
+
+    @Test
+    public void testAddSecondaryStorageServerAddressToBufferSameAddress() {
+        String randomIp1 = 
InetAddresses.fromInteger(secureRandom.nextInt()).getHostAddress();
+        List<String> addresses = List.of(randomIp1, randomIp1);
+        runAddSecondaryStorageServerAddressToBufferTest(addresses, randomIp1);
+    }
+
+    @Test
+    public void testAddSecondaryStorageServerAddressToBufferInvalidAddress() {
+        String randomIp1 = 
InetAddresses.fromInteger(secureRandom.nextInt()).getHostAddress();
+        String randomIp2 = 
InetAddresses.fromInteger(secureRandom.nextInt()).getHostAddress();
+        List<String> addresses = List.of(randomIp1, "garbage", randomIp2);
+        runAddSecondaryStorageServerAddressToBufferTest(addresses, 
StringUtils.join(List.of(randomIp1, randomIp2), ","));
+    }
+}
diff --git a/systemvm/agent/scripts/ssvm-check.sh 
b/systemvm/agent/scripts/ssvm-check.sh
index 5fdc244debd..b2721a93b3f 100644
--- a/systemvm/agent/scripts/ssvm-check.sh
+++ b/systemvm/agent/scripts/ssvm-check.sh
@@ -101,7 +101,7 @@ then
 else
     echo "ERROR: Storage $storage is not currently mounted"
     echo "Verifying if we can at least ping the storage"
-    STORAGE_ADDRESS=`grep "secondaryStorageServerAddress" $CMDLINE | sed -E 
's/.*secondaryStorageServerAddress=([^ ]*).*/\1/g'`
+    STORAGE_ADDRESSES=`grep "secondaryStorageServerAddress" $CMDLINE | sed -E 
's/.*secondaryStorageServerAddress=([^ ]*).*/\1/g'`
 
     if [[ -z "$STORAGE_ADDRESS" ]]
     then
@@ -117,16 +117,21 @@ else
         route -n
       fi
     else
-      echo "Storage address is $STORAGE_ADDRESS, trying to ping it"
-      ping -c 2  $STORAGE_ADDRESS
-      if [ $? -eq 0 ]
-      then
-        echo "Good: Can ping $storage storage address"
-      else
-        echo "WARNING: Cannot ping $storage storage address"
-        echo routing table follows
-        route -n
-      fi
+      echo "Storage address(s): $STORAGE_ADDRESSES, trying to ping"
+      STORAGE_ADDRESS_LIST=$(echo $STORAGE_ADDRESSES | tr ",")
+      for STORAGE_ADDRESS in $STORAGE_ADDRESS_LIST
+      do
+        echo "Pinging storage address: $STORAGE_ADDRESS"
+        ping -c 2  $STORAGE_ADDRESS
+        if [ $? -eq 0 ]
+        then
+          echo "Good: Can ping $storage storage address"
+        else
+          echo "WARNING: Cannot ping $storage storage address"
+          echo routing table follows
+          route -n
+        fi
+      done
     fi
 
 fi

Reply via email to