package org.ovirt.engine.core.bll.storage.pool;
import static org.apache.commons.collections.CollectionUtils.isEqualCollection;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.ovirt.engine.core.utils.MockConfigRule.mockConfig;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.ovirt.engine.core.bll.BaseCommandTest;
import org.ovirt.engine.core.bll.ValidateTestUtils;
import org.ovirt.engine.core.bll.ValidationResult;
import org.ovirt.engine.core.bll.network.cluster.ManagementNetworkUtil;
import org.ovirt.engine.core.bll.utils.VersionSupport;
import org.ovirt.engine.core.bll.validator.NetworkValidator;
import org.ovirt.engine.core.bll.validator.storage.StoragePoolValidator;
import org.ovirt.engine.core.common.action.StoragePoolManagementParameter;
import org.ovirt.engine.core.common.businessentities.Cluster;
import org.ovirt.engine.core.common.businessentities.StorageDomain;
import org.ovirt.engine.core.common.businessentities.StorageDomainStatic;
import org.ovirt.engine.core.common.businessentities.StorageDomainStatus;
import org.ovirt.engine.core.common.businessentities.StoragePool;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.businessentities.network.Network;
import org.ovirt.engine.core.common.businessentities.storage.StorageType;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.errors.EngineMessage;
import org.ovirt.engine.core.common.utils.Pair;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.compat.Version;
import org.ovirt.engine.core.dao.ClusterDao;
import org.ovirt.engine.core.dao.StorageDomainStaticDao;
import org.ovirt.engine.core.dao.StoragePoolDao;
import org.ovirt.engine.core.dao.VdsDao;
import org.ovirt.engine.core.dao.network.NetworkDao;
import org.ovirt.engine.core.utils.MockConfigRule;
public class UpdateStoragePoolCommandTest extends BaseCommandTest {
private static final Version VERSION_1_0 = new Version(1, 0);
private static final Version VERSION_1_1 = new Version(1, 1);
private static final Version VERSION_1_2 = new Version(1, 2);
private static final Version VERSION_2_0 = new Version(2, 0);
private static final Set<Version> SUPPORTED_VERSIONS =
new HashSet<>(Arrays.asList(VERSION_1_0, VERSION_1_1, VERSION_1_2));
private static final Guid DEFAULT_CLUSTER_ID = Guid.newGuid();
private static final Guid NON_DEFAULT_CLUSTER_ID = Guid.newGuid();
@ClassRule
public static MockConfigRule mcr = new MockConfigRule(
mockConfig(ConfigValues.AutoRegistrationDefaultClusterID, DEFAULT_CLUSTER_ID),
mockConfig(ConfigValues.StoragePoolNameSizeLimit, 10),
mockConfig(ConfigValues.SupportedClusterLevels, SUPPORTED_VERSIONS)
);
@Spy
@InjectMocks
private UpdateStoragePoolCommand<StoragePoolManagementParameter> cmd =
new UpdateStoragePoolCommand<>(new StoragePoolManagementParameter(createStoragePool()), null);
@Mock
private StoragePoolDao spDao;
@Mock
private StorageDomainStaticDao sdDao;
@Mock
private ClusterDao clusterDao;
@Mock
private VdsDao vdsDao;
@Mock
private NetworkDao networkDao;
@Mock
private ManagementNetworkUtil managementNetworkUtil;
private StoragePoolValidator poolValidator;
@Before
public void setUp() {
when(spDao.get(any())).thenReturn(createStoragePool());
when(clusterDao.getAllForStoragePool(any())).thenReturn(createClusterList());
// Spy the StoragePoolValidator:
poolValidator = spy(new StoragePoolValidator(cmd.getStoragePool()));
doReturn(ValidationResult.VALID).when(poolValidator).isNotLocalfsWithDefaultCluster();
doReturn(poolValidator).when(cmd).createStoragePoolValidator();
}
@Test
public void happyPath() {
ValidateTestUtils.runAndAssertValidateSuccess(cmd);
}
@Test
public void nameExists() {
newPoolNameIsAlreadyTaken();
ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_STORAGE_POOL_NAME_ALREADY_EXIST);
}
@Test
public void hasLocalDomain() {
StorageDomainStatic sdc = new StorageDomainStatic();
sdc.setStorageType(StorageType.LOCALFS);
StoragePool existingSp = createStoragePool();
existingSp.setIsLocal(true);
when(spDao.get(any())).thenReturn(existingSp);
when(sdDao.getAllForStoragePool(any())).thenReturn(Collections.singletonList(sdc));
ValidateTestUtils.runAndAssertValidateFailure(cmd,
EngineMessage.ERROR_CANNOT_CHANGE_STORAGE_POOL_TYPE_WITH_LOCAL);
}
@Test
public void hasSharedDomain() {
StorageDomainStatic sdc = new StorageDomainStatic();
sdc.setStorageType(StorageType.NFS);
when(sdDao.getAllForStoragePool(any())).thenReturn(Collections.singletonList(sdc));
ValidateTestUtils.runAndAssertValidateSuccess(cmd);
}
@Test
public void hasNoStorageDomains() {
ValidateTestUtils.runAndAssertValidateSuccess(cmd);
}
@Test
public void hasMultipleClustersForLocalDC() {
List<Cluster> clusters = Arrays.asList(new Cluster(), new Cluster());
when(clusterDao.getAllForStoragePool(any())).thenReturn(clusters);
cmd.getStoragePool().setIsLocal(true);
ValidateTestUtils.runAndAssertValidateFailure(cmd,
EngineMessage.CLUSTER_CANNOT_ADD_MORE_THEN_ONE_HOST_TO_LOCAL_STORAGE);
}
@Test
public void hasMultipleHostsForLocalDC() {
when(sdDao.getAllForStoragePool(any())).thenReturn(Collections.emptyList());
List<VDS> hosts = Arrays.asList(new VDS(), new VDS());
when(vdsDao.getAllForStoragePool(any())).thenReturn(hosts);
cmd.getStoragePool().setIsLocal(true);
ValidateTestUtils.runAndAssertValidateFailure(cmd,
EngineMessage.VDS_CANNOT_ADD_MORE_THEN_ONE_HOST_TO_LOCAL_STORAGE);
}
@Test
public void unsupportedVersion() {
cmd.getStoragePool().setCompatibilityVersion(VERSION_2_0);
ValidateTestUtils.runAndAssertValidateFailure(cmd, VersionSupport.getUnsupportedVersionMessage());
}
@Test
public void lowerVersionNoHostsNoNetwork() {
cmd.getStoragePool().setCompatibilityVersion(VERSION_1_0);
addNonDefaultClusterToPool();
ValidateTestUtils.runAndAssertValidateSuccess(cmd);
}
@Test
public void lowerVersionHostsNoNetwork() {
cmd.getStoragePool().setCompatibilityVersion(VERSION_1_0);
addNonDefaultClusterToPool();
addHostsToCluster();
ValidateTestUtils.runAndAssertValidateSuccess(cmd);
}
@Test
public void lowerVersionNoHostsWithNetwork() {
cmd.getStoragePool().setCompatibilityVersion(VERSION_1_0);
addNonDefaultClusterToPool();
addNonManagementNetworkToPool();
ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_CANNOT_DECREASE_DATA_CENTER_COMPATIBILITY_VERSION);
}
@Test
public void lowerVersionMgmtNetworkAndRegularNetworks() {
cmd.getStoragePool().setCompatibilityVersion(VERSION_1_0);
addNonDefaultClusterToPool();
addManagementNetworkToPool();
addNonManagementNetworksToPool(2);
setupNetworkValidator(true);
ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_CANNOT_DECREASE_DATA_CENTER_COMPATIBILITY_VERSION);
}
@Test
public void lowerVersionHostsAndNetwork() {
cmd.getStoragePool().setCompatibilityVersion(VERSION_1_0);
addNonDefaultClusterToPool();
addHostsToCluster();
addNonManagementNetworkToPool();
ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_CANNOT_DECREASE_DATA_CENTER_COMPATIBILITY_VERSION);
}
@Test
public void lowerVersionMgmtNetworkSupportedFeatures() {
cmd.getStoragePool().setCompatibilityVersion(VERSION_1_0);
addNonDefaultClusterToPool();
addManagementNetworksToPool(2);
setupNetworkValidator(true);
ValidateTestUtils.runAndAssertValidateSuccess(cmd);
}
@Test
public void lowerVersionMgmtNetworkNonSupportedFeatures() {
cmd.getStoragePool().setCompatibilityVersion(VERSION_1_0);
addNonDefaultClusterToPool();
addManagementNetworksToPool(2);
setupNetworkValidator(false);
ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_CANNOT_DECREASE_DATA_CENTER_COMPATIBILITY_VERSION);
}
@Test
public void versionHigherThanCluster() {
cmd.getStoragePool().setCompatibilityVersion(VERSION_1_2);
ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ERROR_CANNOT_UPDATE_STORAGE_POOL_COMPATIBILITY_VERSION_BIGGER_THAN_CLUSTERS);
}
@Test
public void testValidateAllClustersLevel() {
cmd.getStoragePool().setCompatibilityVersion(VERSION_1_2);
List<Cluster> clusterList = createClusterList();
// Create new supported cluster.
Cluster secondCluster = new Cluster();
secondCluster.setCompatibilityVersion(VERSION_1_2);
secondCluster.setName("secondCluster");
clusterList.add(secondCluster);
// Create new unsupported cluster.
Cluster thirdCluster = new Cluster();
thirdCluster.setCompatibilityVersion(VERSION_1_1);
thirdCluster.setName("thirdCluster");
clusterList.add(thirdCluster);
// Test upgrade
when(clusterDao.getAllForStoragePool(any())).thenReturn(clusterList);
assertFalse(cmd.checkAllClustersLevel());
List<String> messages = cmd.getReturnValue().getValidationMessages();
assertTrue(messages.contains(EngineMessage.ERROR_CANNOT_UPDATE_STORAGE_POOL_COMPATIBILITY_VERSION_BIGGER_THAN_CLUSTERS.toString()));
assertTrue(messages.get(0).contains("firstCluster"));
assertFalse(messages.get(0).contains("secondCluster"));
assertTrue(messages.get(0).contains("thirdCluster"));
}
@Test
public void poolHasDefaultCluster() {
mcr.mockConfigValue(ConfigValues.AutoRegistrationDefaultClusterID, DEFAULT_CLUSTER_ID);
addDefaultClusterToPool();
doReturn(new ValidationResult
(EngineMessage.ACTION_TYPE_FAILED_STORAGE_POOL_WITH_DEFAULT_CLUSTER_CANNOT_BE_LOCALFS))
.when(poolValidator).isNotLocalfsWithDefaultCluster();
ValidateTestUtils.runAndAssertValidateFailure(cmd, EngineMessage.ACTION_TYPE_FAILED_STORAGE_POOL_WITH_DEFAULT_CLUSTER_CANNOT_BE_LOCALFS);
}
@Test
public void syncLunsForStorageDomainsNoActiveDomain() {
List<StorageDomain> storageDomains = Arrays.asList(
createStorageDomainForSyncLuns(StorageType.ISCSI, StorageDomainStatus.Maintenance, false),
createStorageDomainForSyncLuns(StorageType.ISCSI, StorageDomainStatus.Locked, false));
assertTrue(cmd.syncLunsForStorageDomains(storageDomains).isEmpty());
}
@Test
public void syncLunsForStorageDomainsNoBlockDomain() {
List<StorageDomain> storageDomains = Arrays.asList(
createStorageDomainForSyncLuns(StorageType.NFS, StorageDomainStatus.Active, false),
createStorageDomainForSyncLuns(StorageType.GLANCE, StorageDomainStatus.Active, false));
assertTrue(cmd.syncLunsForStorageDomains(storageDomains).isEmpty());
}
@Test
public void syncLunsForStorageDomainsNoDomain() {
assertTrue(cmd.syncLunsForStorageDomains(Collections.emptyList()).isEmpty());
}
@Test
public void syncLunsForStorageDomainsWithFailedToSyncDomains() {
StorageDomain failedToSyncStorageDomain1 =
createStorageDomainForSyncLuns(StorageType.ISCSI, StorageDomainStatus.Active, false);
StorageDomain failedToSyncStorageDomain2 =
createStorageDomainForSyncLuns(StorageType.FCP, StorageDomainStatus.Active, false);
List<StorageDomain> storageDomains = Arrays.asList(failedToSyncStorageDomain1, failedToSyncStorageDomain2,
createStorageDomainForSyncLuns(StorageType.ISCSI, StorageDomainStatus.Active, true));
assertTrue(isEqualCollection(cmd.syncLunsForStorageDomains(storageDomains),
Arrays.asList(failedToSyncStorageDomain1.getId(), failedToSyncStorageDomain2.getId())));
}
@Test
public void syncLunsForStorageDomainsAllActiveBlockDomainsWereSynced() {
List<StorageDomain> storageDomains = Arrays.asList(
createStorageDomainForSyncLuns(StorageType.ISCSI, StorageDomainStatus.Active, true),
createStorageDomainForSyncLuns(StorageType.FCP, StorageDomainStatus.Locked, false),
createStorageDomainForSyncLuns(StorageType.FCP, StorageDomainStatus.Active, true));
assertTrue(cmd.syncLunsForStorageDomains(storageDomains).isEmpty());
}
private StorageDomain createStorageDomainForSyncLuns(StorageType storageType, StorageDomainStatus status,
boolean canSync) {
StorageDomain domain = new StorageDomain();
domain.setId(Guid.newGuid());
domain.setStorageType(storageType);
domain.setStatus(status);
doReturn(new Pair<>(canSync, domain.getId())).when(cmd).syncDomainLuns(eq(domain));
return domain;
}
private void newPoolNameIsAlreadyTaken() {
when(spDao.get(any())).thenReturn(new StoragePool());
List<StoragePool> storagePoolList = new ArrayList<>();
storagePoolList.add(createStoragePool());
when(spDao.getByName(anyString(), anyBoolean())).thenReturn(new ArrayList<>(storagePoolList));
}
private static StoragePool createStoragePool() {
StoragePool pool = new StoragePool();
pool.setId(Guid.newGuid());
pool.setName("Default");
pool.setCompatibilityVersion(VERSION_1_1);
return pool;
}
private static List<Cluster> createClusterList() {
List<Cluster> clusters = new ArrayList<>();
Cluster cluster = new Cluster();
cluster.setCompatibilityVersion(VERSION_1_0);
cluster.setName("firstCluster");
clusters.add(cluster);
return clusters;
}
private void addDefaultClusterToPool() {
Cluster defaultCluster = new Cluster();
defaultCluster.setCompatibilityVersion(VERSION_1_1);
defaultCluster.setId(DEFAULT_CLUSTER_ID);
List<Cluster> clusters = new ArrayList<>();
clusters.add(defaultCluster);
when(clusterDao.getAllForStoragePool(any())).thenReturn(clusters);
}
private void addNonDefaultClusterToPool() {
Cluster defaultCluster = new Cluster();
defaultCluster.setCompatibilityVersion(VERSION_1_1);
defaultCluster.setId(NON_DEFAULT_CLUSTER_ID);
List<Cluster> clusters = new ArrayList<>();
clusters.add(defaultCluster);
when(clusterDao.getAllForStoragePool(any())).thenReturn(clusters);
}
private void addHostsToCluster() {
VDS host = new VDS();
List<VDS> hosts = new ArrayList<>();
hosts.add(host);
when(vdsDao.getAllForStoragePool(any())).thenReturn(hosts);
}
private void addManagementNetworkToPool() {
addManagementNetworksToPool(1);
}
private void addManagementNetworksToPool(int numberOfNetworks) {
addNetworksToPool(numberOfNetworks, true);
}
private Network createNetwork(Guid networkId) {
Network network = new Network();
network.setId(networkId);
return network;
}
private void setupNetworkValidator(boolean valid) {
NetworkValidator validator = mock(NetworkValidator.class);
when(validator.canNetworkCompatibilityBeDecreased()).thenReturn(valid);
when(cmd.getNetworkValidator(any())).thenReturn(validator);
}
private void addNonManagementNetworkToPool() {
addNonManagementNetworksToPool(1);
}
private void addNonManagementNetworksToPool(int numberOfNetworks) {
addNetworksToPool(numberOfNetworks, false);
}
private void addNetworksToPool(int numberOfNetworks, boolean isManagement) {
List<Network> allDcNetworks = new ArrayList<>();
for (int i = 0; i < numberOfNetworks; i++) {
final Guid networkId = Guid.newGuid();
Network network = createNetwork(networkId);
network.setId(networkId);
allDcNetworks.add(network);
when(managementNetworkUtil.isManagementNetwork(networkId)).thenReturn(isManagement);
}
when(networkDao.getAllForDataCenter(any())).thenReturn(allDcNetworks);
}
}