Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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 @@ -62,7 +62,7 @@ public interface DeploymentClusterPlanner extends DeploymentPlanner {
"vm.allocation.algorithm",
"Advanced",
"random",
"Order in which hosts within a cluster will be considered for VM/volume allocation. The value can be 'random', 'firstfit', 'userdispersing', 'userconcentratedpod_random', 'userconcentratedpod_firstfit', or 'firstfitleastconsumed'.",
"Order in which hosts within a cluster will be considered for VM allocation. The value can be 'random', 'firstfit', 'userdispersing', 'userconcentratedpod_random', 'userconcentratedpod_firstfit', or 'firstfitleastconsumed'.",
true,
ConfigKey.Scope.Global, null, null, null, null, null,
ConfigKey.Kind.Select,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ public interface VolumeOrchestrationService {
"The maximum size for a volume (in GiB).",
true);

ConfigKey<String> VolumeAllocationAlgorithm = new ConfigKey<>(
String.class,
"volume.allocation.algorithm",
"Advanced",
"random",
"Order in which storage pool within a cluster will be considered for volume allocation. The value can be 'random', 'firstfit', 'userdispersing', 'userconcentratedpod_random', 'userconcentratedpod_firstfit', or 'firstfitleastconsumed'.",
true,
ConfigKey.Scope.Global, null, null, null, null, null,
ConfigKey.Kind.Select,
"random,firstfit,userdispersing,userconcentratedpod_random,userconcentratedpod_firstfit,firstfitleastconsumed");

VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId, Long destPoolClusterId, HypervisorType dataDiskHyperType)
throws ConcurrentOperationException, StorageUnavailableException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2018,7 +2018,9 @@

@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {RecreatableSystemVmEnabled, MaxVolumeSize, StorageHAMigrationEnabled, StorageMigrationEnabled, CustomDiskOfferingMaxSize, CustomDiskOfferingMinSize, VolumeUrlCheck};
return new ConfigKey<?>[] {

Check warning on line 2021 in engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java

View check run for this annotation

Codecov / codecov/patch

engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java#L2021

Added line #L2021 was not covered by tests
RecreatableSystemVmEnabled, MaxVolumeSize, StorageHAMigrationEnabled, StorageMigrationEnabled,
CustomDiskOfferingMaxSize, CustomDiskOfferingMinSize, VolumeUrlCheck, VolumeAllocationAlgorithm};
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,58 +16,57 @@
// under the License.
package org.apache.cloudstack.storage.allocator;

import java.math.BigDecimal;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.naming.ConfigurationException;

import com.cloud.api.query.dao.StoragePoolJoinDao;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.storage.ScopeType;
import com.cloud.storage.StoragePoolStatus;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.collections.CollectionUtils;

import com.cloud.utils.Pair;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;

import com.cloud.capacity.Capacity;
import com.cloud.capacity.dao.CapacityDao;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.StorageUtil;
import com.cloud.storage.Volume;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.AdapterBase;
import com.cloud.vm.DiskProfile;
import com.cloud.vm.VirtualMachineProfile;

import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;

import org.apache.commons.collections.CollectionUtils;

import javax.inject.Inject;
import javax.naming.ConfigurationException;
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class AbstractStoragePoolAllocator extends AdapterBase implements StoragePoolAllocator {

protected BigDecimal storageOverprovisioningFactor = new BigDecimal(1);
protected String allocationAlgorithm = "random";
protected long extraBytesPerVolume = 0;
@Inject protected DataStoreManager dataStoreMgr;
@Inject protected PrimaryDataStoreDao storagePoolDao;
Expand Down Expand Up @@ -95,10 +94,6 @@
String globalStorageOverprovisioningFactor = configs.get("storage.overprovisioning.factor");
storageOverprovisioningFactor = new BigDecimal(NumbersUtil.parseFloat(globalStorageOverprovisioningFactor, 2.0f));
extraBytesPerVolume = 0;
String allocationAlgorithm = configs.get("vm.allocation.algorithm");
if (allocationAlgorithm != null) {
this.allocationAlgorithm = allocationAlgorithm;
}
return true;
}
return false;
Expand Down Expand Up @@ -209,7 +204,7 @@
account = vmProfile.getOwner();
}

pools = reorderStoragePoolsBasedOnAlgorithm(pools, plan, account);
pools = reorderStoragePoolsBasedOnAlgorithm(pools, plan, account, VolumeOrchestrationService.VolumeAllocationAlgorithm.value());

Check warning on line 207 in engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java

View check run for this annotation

Codecov / codecov/patch

engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java#L207

Added line #L207 was not covered by tests

if (vmProfile.getVirtualMachine() == null) {
if (logger.isTraceEnabled()) {
Expand All @@ -226,17 +221,16 @@
return pools;
}

List<StoragePool> reorderStoragePoolsBasedOnAlgorithm(List<StoragePool> pools, DeploymentPlan plan, Account account) {
logger.debug(String.format("Using allocation algorithm [%s] to reorder pools.", allocationAlgorithm));

if (allocationAlgorithm.equals("random") || allocationAlgorithm.equals("userconcentratedpod_random") || (account == null)) {
List<StoragePool> reorderStoragePoolsBasedOnAlgorithm(List<StoragePool> pools, DeploymentPlan plan, Account account, String volumeAllocationAlgorithm) {
logger.debug("Using volume allocation algorithm {} to reorder pools.", volumeAllocationAlgorithm);
if (volumeAllocationAlgorithm.equals("random") || volumeAllocationAlgorithm.equals("userconcentratedpod_random") || (account == null)) {
reorderRandomPools(pools);
} else if (StringUtils.equalsAny(allocationAlgorithm, "userdispersing", "firstfitleastconsumed")) {
} else if (StringUtils.equalsAny(volumeAllocationAlgorithm, "userdispersing", "firstfitleastconsumed")) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Using reordering algorithm [%s]", allocationAlgorithm));
logger.trace("Using reordering algorithm {}", volumeAllocationAlgorithm);

Check warning on line 230 in engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java

View check run for this annotation

Codecov / codecov/patch

engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java#L230

Added line #L230 was not covered by tests
}

if (allocationAlgorithm.equals("userdispersing")) {
if (volumeAllocationAlgorithm.equals("userdispersing")) {
pools = reorderPoolsByNumberOfVolumes(plan, pools, account);
} else {
pools = reorderPoolsByCapacity(plan, pools);
Expand All @@ -248,7 +242,7 @@
void reorderRandomPools(List<StoragePool> pools) {
StorageUtil.traceLogStoragePools(pools, logger, "pools to choose from: ");
if (logger.isTraceEnabled()) {
logger.trace(String.format("Shuffle this so that we don't check the pools in the same order. Algorithm == '%s' (or no account?)", allocationAlgorithm));
logger.trace("Shuffle this so that we don't check the pools in the same order. Algorithm == 'random' (or no account?)");

Check warning on line 245 in engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java

View check run for this annotation

Codecov / codecov/patch

engine/storage/src/main/java/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java#L245

Added line #L245 was not covered by tests
}
StorageUtil.traceLogStoragePools(pools, logger, "pools to shuffle: ");
Collections.shuffle(pools, secureRandom);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,27 @@
// under the License.
package org.apache.cloudstack.storage.allocator;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.naming.ConfigurationException;

import com.cloud.storage.VolumeApiServiceImpl;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.springframework.stereotype.Component;

import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.offering.ServiceOffering;
import com.cloud.storage.ScopeType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.VolumeApiServiceImpl;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.vm.DiskProfile;
import com.cloud.vm.VirtualMachineProfile;

import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;

import org.springframework.stereotype.Component;

import javax.inject.Inject;
import javax.naming.ConfigurationException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Component
public class ClusterScopeStoragePoolAllocator extends AbstractStoragePoolAllocator {

Expand Down Expand Up @@ -116,14 +116,6 @@ protected List<StoragePool> select(DiskProfile dskCh, VirtualMachineProfile vmPr
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
super.configure(name, params);

if (configDao != null) {
Map<String, String> configs = configDao.getConfiguration(params);
String allocationAlgorithm = configs.get("vm.allocation.algorithm");
if (allocationAlgorithm != null) {
this.allocationAlgorithm = allocationAlgorithm;
}
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@
package org.apache.cloudstack.storage.allocator;


import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.storage.Storage;
import com.cloud.storage.StoragePool;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account;
import com.cloud.vm.DiskProfile;
import com.cloud.vm.VirtualMachineProfile;

import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
Expand All @@ -34,14 +37,12 @@
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.storage.Storage;
import com.cloud.storage.StoragePool;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account;
import com.cloud.vm.DiskProfile;
import com.cloud.vm.VirtualMachineProfile;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class AbstractStoragePoolAllocatorTest {
Expand Down Expand Up @@ -74,25 +75,23 @@ public void tearDown() {

@Test
public void reorderStoragePoolsBasedOnAlgorithm_random() {
allocator.reorderStoragePoolsBasedOnAlgorithm(pools, plan, account);
allocator.reorderStoragePoolsBasedOnAlgorithm(pools, plan, account, "random");
Mockito.verify(allocator, Mockito.times(0)).reorderPoolsByCapacity(plan, pools);
Mockito.verify(allocator, Mockito.times(0)).reorderPoolsByNumberOfVolumes(plan, pools, account);
Mockito.verify(allocator, Mockito.times(1)).reorderRandomPools(pools);
}

@Test
public void reorderStoragePoolsBasedOnAlgorithm_userdispersing() {
allocator.allocationAlgorithm = "userdispersing";
Mockito.doReturn(pools).when(allocator).reorderPoolsByNumberOfVolumes(plan, pools, account);
allocator.reorderStoragePoolsBasedOnAlgorithm(pools, plan, account);
allocator.reorderStoragePoolsBasedOnAlgorithm(pools, plan, account,"userdispersing");
Mockito.verify(allocator, Mockito.times(0)).reorderPoolsByCapacity(plan, pools);
Mockito.verify(allocator, Mockito.times(1)).reorderPoolsByNumberOfVolumes(plan, pools, account);
Mockito.verify(allocator, Mockito.times(0)).reorderRandomPools(pools);
}

@Test
public void reorderStoragePoolsBasedOnAlgorithm_userdispersing_reorder_check() {
allocator.allocationAlgorithm = "userdispersing";
allocator.volumeDao = volumeDao;

when(plan.getDataCenterId()).thenReturn(1l);
Expand All @@ -104,7 +103,7 @@ public void reorderStoragePoolsBasedOnAlgorithm_userdispersing_reorder_check() {
poolIds.add(9l);
when(volumeDao.listPoolIdsByVolumeCount(1l,1l,1l,1l)).thenReturn(poolIds);

List<StoragePool> reorderedPools = allocator.reorderStoragePoolsBasedOnAlgorithm(pools, plan, account);
List<StoragePool> reorderedPools = allocator.reorderStoragePoolsBasedOnAlgorithm(pools, plan, account, "userdispersing");
Assert.assertEquals(poolIds.size(),reorderedPools.size());

Mockito.verify(allocator, Mockito.times(0)).reorderPoolsByCapacity(plan, pools);
Expand All @@ -115,9 +114,8 @@ public void reorderStoragePoolsBasedOnAlgorithm_userdispersing_reorder_check() {

@Test
public void reorderStoragePoolsBasedOnAlgorithm_firstfitleastconsumed() {
allocator.allocationAlgorithm = "firstfitleastconsumed";
Mockito.doReturn(pools).when(allocator).reorderPoolsByCapacity(plan, pools);
allocator.reorderStoragePoolsBasedOnAlgorithm(pools, plan, account);
allocator.reorderStoragePoolsBasedOnAlgorithm(pools, plan, account, "firstfitleastconsumed");
Mockito.verify(allocator, Mockito.times(1)).reorderPoolsByCapacity(plan, pools);
Mockito.verify(allocator, Mockito.times(0)).reorderPoolsByNumberOfVolumes(plan, pools, account);
Mockito.verify(allocator, Mockito.times(0)).reorderRandomPools(pools);
Expand Down
Loading
Loading