/*
* Copyright (c) 2014 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.server.upgrade.impl.callback;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.model.DiscoveredDataObject;
import com.emc.storageos.db.client.model.HostInterface;
import com.emc.storageos.db.client.model.StoragePool;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.db.client.model.VirtualPool;
import com.emc.storageos.db.client.upgrade.BaseCustomMigrationCallback;
import com.emc.storageos.db.client.upgrade.callbacks.ScaleIOPoolAndStorageSystemMigration;
import com.emc.storageos.db.server.DbsvcTestBase;
import com.emc.storageos.db.server.upgrade.DbSimpleMigrationTestBase;
import org.junit.BeforeClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
/**
* Test upgrade of SIO components. In 2.0 SIO implementation assumed that
* the StoragePools were creating thin volumes, in actuality it was creating
* thick. SIO 1.30+ adds supports for thin provisioned volumes, so we need to
* change all StoragePools to indicate that they support only THICK volumes.
*/
public class ScaleIOPoolAndStorageSystemMigrationTest extends DbSimpleMigrationTestBase {
private static final Logger log = LoggerFactory.getLogger(ScaleIOPoolAndStorageSystemMigrationTest.class);
private static volatile StorageSystem sioStorageSystem;
private static volatile StorageSystem otherStorageSystem;
private static volatile VirtualPool sioVP;
private static volatile VirtualPool otherVP;
private static List<URI> storagePoolURIs = new ArrayList<>();
@BeforeClass
public static void setup() throws IOException {
customMigrationCallbacks.put("2.0", new ArrayList<BaseCustomMigrationCallback>() {
private static final long serialVersionUID = 1L;
{
add(new ScaleIOPoolAndStorageSystemMigration());
}
});
DbsvcTestBase.setup();
}
@Override
protected String getSourceVersion() {
return "2.0";
}
@Override
protected String getTargetVersion() {
return "2.1";
}
@Override
protected void prepareData() throws Exception {
createStorageSystems();
createStoragePools();
createVirtualPools();
}
@Override
protected void verifyResults() throws Exception {
StorageSystem checkSioStorageSystem = _dbClient.queryObject(StorageSystem.class, sioStorageSystem.getId());
assertNotNull(checkSioStorageSystem);
assertEquals(checkSioStorageSystem.getLabel(), checkSioStorageSystem.getNativeGuid());
StorageSystem checkOtherStorageSystem = _dbClient.queryObject(StorageSystem.class, otherStorageSystem.getId());
assertNotNull(checkOtherStorageSystem);
VirtualPool checkSioVirtualPool = _dbClient.queryObject(VirtualPool.class, sioVP.getId());
assertNotNull(checkSioVirtualPool);
assertEquals(checkSioVirtualPool.getSupportedProvisioningType(), VirtualPool.ProvisioningType.Thick.name());
VirtualPool checkOtherVirtualPool = _dbClient.queryObject(VirtualPool.class, otherVP.getId());
assertNotNull(checkOtherVirtualPool);
assertEquals(checkOtherVirtualPool.getSupportedProvisioningType(), VirtualPool.ProvisioningType.Thin.name());
for (URI uri : storagePoolURIs) {
StoragePool pool = _dbClient.queryObject(StoragePool.class, uri);
assertNotNull("StoragePool is not in database ", pool);
if (pool.getStorageDevice().equals(sioStorageSystem.getId())) {
// Validate that migration was applied for the objects
assertTrue(String.format("StoragePool nativeGuid is %s different from expected %s",
pool.getNativeGuid(), pool.getNativeId()),
pool.getNativeGuid().equals(pool.getNativeId()));
assertTrue(String.format("StoragePool %s should be THICK", pool.getNativeId()),
pool.getSupportedResourceTypes().equals(StoragePool.SupportedResourceTypes.THICK_ONLY.name()));
assertStoragePoolValue("maximumThickVolumeSize", 1048576, pool.getMaximumThickVolumeSize());
assertStoragePoolValue("minimumThickVolumeSize", 1, pool.getMinimumThickVolumeSize());
assertStoragePoolValue("maximumThinVolumeSize", 0, pool.getMaximumThinVolumeSize());
assertStoragePoolValue("minimumThickVolumeSize", 0, pool.getMinimumThinVolumeSize());
} else {
assertStoragePoolValue("maximumThinVolumeSize", 999999L, pool.getMaximumThinVolumeSize());
assertStoragePoolValue("minimumThickVolumeSize", 500L, pool.getMinimumThinVolumeSize());
}
}
}
private void assertStoragePoolValue(String name, Object expected, Object actual) {
assertTrue(String.format("StoragePool parameter %s should be %s, but is %s", name,
expected.toString(), actual.toString()),
actual.toString().equals(expected.toString()));
}
private void createStorageSystems() {
sioStorageSystem = new StorageSystem();
sioStorageSystem.setId(URIUtil.createId(StorageSystem.class));
sioStorageSystem.setSystemType(DiscoveredDataObject.Type.scaleio.name());
sioStorageSystem.setLabel("SCALEIO+0aa00bb00cc00dd0+PD-1");
sioStorageSystem.setNativeGuid("SCALEIO+0aa00bb00cc00dd0+PD-1");
sioStorageSystem.setIpAddress("10.1.123.123");
sioStorageSystem.setModel("ScaleIO ECS");
sioStorageSystem.setFirmwareVersion("1.20.1.22");
_dbClient.createObject(sioStorageSystem);
otherStorageSystem = new StorageSystem();
otherStorageSystem.setId(URIUtil.createId(StorageSystem.class));
otherStorageSystem.setSystemType(DiscoveredDataObject.Type.vmax.name());
otherStorageSystem.setLabel("SYMMETRIX+0001230002300");
otherStorageSystem.setNativeGuid("SYMMETRIX+0001230002300");
otherStorageSystem.setIpAddress("10.1.123.124");
otherStorageSystem.setModel("VMAX40K");
otherStorageSystem.setFirmwareVersion("5977.22");
_dbClient.createObject(otherStorageSystem);
}
private void createStoragePools() {
String installationId = "0aa00bb00cc00dd0";
String protectionDomain = "PD-1";
for (int i = 0; i < 5; i++) {
String spName = String.format("TestSIO-Pool-%d", i);
StoragePool pool = new StoragePool();
URI id = URIUtil.createId(StoragePool.class);
pool.setId(id);
pool.setPoolName(spName);
pool.setNativeId(String.format("%s-%s-%s", installationId, protectionDomain, spName));
pool.setNativeGuid(String.format("%s-%s", protectionDomain, spName));
pool.setStorageDevice(sioStorageSystem.getId());
pool.setPoolServiceType(StoragePool.PoolServiceType.block.toString());
pool.setOperationalStatus(StoragePool.PoolOperationalStatus.READY.name());
pool.setThinVolumePreAllocationSupported(false);
pool.addDriveTypes(Collections.singleton(StoragePool.SupportedDriveTypeValues.SATA.name()));
StringSet copyTypes = new StringSet();
copyTypes.add(StoragePool.CopyTypes.ASYNC.name());
copyTypes.add(StoragePool.CopyTypes.UNSYNC_UNASSOC.name());
pool.setSupportedCopyTypes(copyTypes);
pool.setMaximumThinVolumeSize(1048576L);
pool.setMinimumThinVolumeSize(1L);
storagePoolURIs.add(id);
}
// Other StoragePools
for (int i = 0; i < 5; i++) {
String spName = String.format("TestOther-Pool-%d", i);
StoragePool pool = new StoragePool();
URI id = URIUtil.createId(StoragePool.class);
pool.setId(id);
pool.setPoolName(spName);
pool.setNativeId(String.format("%s-%s-%s", installationId, protectionDomain, spName));
pool.setNativeGuid(String.format("%s-%s", protectionDomain, spName));
pool.setStorageDevice(otherStorageSystem.getId());
pool.setPoolServiceType(StoragePool.PoolServiceType.block.toString());
pool.setOperationalStatus(StoragePool.PoolOperationalStatus.READY.name());
pool.setThinVolumePreAllocationSupported(false);
pool.addDriveTypes(Collections.singleton(StoragePool.SupportedDriveTypeValues.SATA.name()));
StringSet copyTypes = new StringSet();
copyTypes.add(StoragePool.CopyTypes.ASYNC.name());
copyTypes.add(StoragePool.CopyTypes.UNSYNC_UNASSOC.name());
pool.setSupportedCopyTypes(copyTypes);
pool.setMaximumThinVolumeSize(999999L);
pool.setMinimumThinVolumeSize(500L);
storagePoolURIs.add(id);
}
}
private void createVirtualPools() throws InstantiationException, IllegalAccessException {
StringSet sioProtos = new StringSet();
sioProtos.add(HostInterface.Protocol.ScaleIO.name());
sioVP = new VirtualPool();
sioVP.setId(URIUtil.createId(VirtualPool.class));
sioVP.setLabel("SIO-VirtualPool");
sioVP.addProtocols(sioProtos);
sioVP.setSupportedProvisioningType(VirtualPool.ProvisioningType.Thin.name());
_dbClient.createObject(sioVP);
StringSet otherProtos = new StringSet();
otherProtos.add(HostInterface.Protocol.ScaleIO.name());
otherVP = new VirtualPool();
otherVP.setId(URIUtil.createId(VirtualPool.class));
otherVP.setLabel("other-VirtualPool");
otherVP.addProtocols(otherProtos);
otherVP.setSupportedProvisioningType(VirtualPool.ProvisioningType.Thin.name());
_dbClient.createObject(otherVP);
}
}