mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	ssvm: pass all accessible secondary storage to ssvm (#7410)
* ssvm: pass all accessible secondary storage to ssvm Fixes #7162 Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> * changes Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> * test Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> * license Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com> --------- Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
		
							parent
							
								
									0d3ac9f8d9
								
							
						
					
					
						commit
						4ef7ebbded
					
				| @ -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("/"); | ||||
| 
 | ||||
|         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 (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); | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|         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 | ||||
|  | ||||
| @ -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), ",")); | ||||
|     } | ||||
| } | ||||
| @ -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 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user