/*
* Copyright (c) 2014 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.server.upgrade.impl.callback;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.junit.Assert;
import org.junit.BeforeClass;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.model.ExportGroup;
import com.emc.storageos.db.client.model.ExportMask;
import com.emc.storageos.db.client.model.Host;
import com.emc.storageos.db.client.model.Initiator;
import com.emc.storageos.db.client.model.StoragePort;
import com.emc.storageos.db.client.model.StringMap;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.db.client.model.StringSetMap;
import com.emc.storageos.db.client.model.ExportGroup.ExportGroupType;
import com.emc.storageos.db.client.upgrade.BaseCustomMigrationCallback;
import com.emc.storageos.db.client.upgrade.callbacks.InitiatorHostMigration;
import com.emc.storageos.db.server.DbsvcTestBase;
import com.emc.storageos.db.server.upgrade.DbSimpleMigrationTestBase;
import com.emc.storageos.volumecontroller.impl.utils.ExportMaskUtils;
public class DbInitiatorHostMigrationTest extends DbSimpleMigrationTestBase {
@BeforeClass
public static void setup() throws IOException {
customMigrationCallbacks.put("1.1", new ArrayList<BaseCustomMigrationCallback>() {
{
add(new InitiatorHostMigration());
}
});
DbsvcTestBase.setup();
}
@Override
protected String getSourceVersion() {
return "1.1";
}
@Override
protected String getTargetVersion() {
return "2.0";
}
private List<Initiator> oldInitiators = new ArrayList<Initiator>();
private Set<String> newInitiators = new HashSet<String>();
private List<Initiator> oldSingleInitiators = new ArrayList<Initiator>();
private Set<String> newSingleInitiators = new HashSet<String>();
private URI missingMaskURI = null;
@Override
protected void prepareData() throws Exception {
// Create 2 initiators with a host and 2 initiators with a null host. One initiator from each has the same port name as another
// initiator.
// Create 2 export groups, one with initiators with a host and one with initiators without a host.
Initiator oldInitiator00 = createInitiator(URI.create("null"), "10:00:00:00:00", "old-0");
Initiator oldInitiator01 = createInitiator(URI.create("null"), "10:00:00:00:01", "old-1");
Initiator newInitiator00 = createInitiator(URIUtil.createId(Host.class), "10:00:00:00:00", "new-0");
Initiator newInitiator01 = createInitiator(URIUtil.createId(Host.class), "10:00:00:00:01", "new-1");
newInitiators.add(newInitiator00.getId().toString());
newInitiators.add(newInitiator01.getId().toString());
oldInitiators.add(oldInitiator00);
oldInitiators.add(oldInitiator01);
createExportGroup(oldInitiators, "old-export");
List<Initiator> validInitiators = new ArrayList<Initiator>();
validInitiators.add(newInitiator00);
validInitiators.add(newInitiator01);
createExportGroup(validInitiators, "new-export");
// Create an initiator with a host and an initiator without a host.
// Create an export group with the initiator without the host.
Initiator oldSingleInitiator = createInitiator(URI.create("null"), "10:00:00:00:99", "old-99");
oldSingleInitiators.add(oldSingleInitiator);
Initiator newSingleInitiator = createInitiator(URIUtil.createId(Host.class), "10:00:00:00:99", "new-99");
newSingleInitiators.add(newSingleInitiator.getId().toString());
createExportGroup(oldSingleInitiators, "old-exportWithSingleInitiator");
// Create Export Group with mask that doesn't exist
ExportGroup exportGroupMissingMask = createExportGroup(oldSingleInitiators, "exportGroupMissingMask");
missingMaskURI = URIUtil.createId(ExportMask.class);
exportGroupMissingMask.addExportMask(missingMaskURI);
_dbClient.updateObject(exportGroupMissingMask);
}
@Override
protected void verifyResults() throws Exception {
List<URI> list = _dbClient.queryByType(ExportGroup.class, true);
int count = 0;
Iterator<ExportGroup> objs = _dbClient.queryIterativeObjects(ExportGroup.class, list);
while (objs.hasNext()) {
ExportGroup exportGroup = objs.next();
count++;
if (exportGroup.getLabel().equalsIgnoreCase("old-export")) {
Assert.assertEquals(newInitiators.size(), exportGroup.getInitiators().size());
Assert.assertTrue(exportGroup.getInitiators().containsAll(newInitiators));
validateExportMask(ExportMaskUtils.getExportMasks(_dbClient, exportGroup), newInitiators);
} else if (exportGroup.getLabel().equalsIgnoreCase("new-export")) {
Assert.assertEquals(newInitiators.size(), exportGroup.getInitiators().size());
Assert.assertTrue(exportGroup.getInitiators().containsAll(newInitiators));
validateExportMask(ExportMaskUtils.getExportMasks(_dbClient, exportGroup), newInitiators);
} else if (exportGroup.getLabel().equalsIgnoreCase("old-exportWithSingleInitiator")) {
Assert.assertEquals(newSingleInitiators.size(), exportGroup.getInitiators().size());
Assert.assertTrue(exportGroup.getInitiators().containsAll(newSingleInitiators));
validateExportMask(ExportMaskUtils.getExportMasks(_dbClient, exportGroup), newSingleInitiators);
} else if (exportGroup.getLabel().equalsIgnoreCase("exportGroupMissingMask")) {
Assert.assertEquals(newSingleInitiators.size(), exportGroup.getInitiators().size());
Assert.assertTrue(exportGroup.getInitiators().containsAll(newSingleInitiators));
Assert.assertTrue(ExportMaskUtils.getExportMasks(_dbClient, exportGroup).size() == 2);
exportGroup.removeExportMask(missingMaskURI);
_dbClient.updateAndReindexObject(exportGroup);
Assert.assertTrue(ExportMaskUtils.getExportMasks(_dbClient, exportGroup).size() == 1);
validateExportMask(ExportMaskUtils.getExportMasks(_dbClient, exportGroup), newSingleInitiators);
} else {
Assert.fail("Found export group that wasn't created in this test");
}
}
Assert.assertTrue("We should still have " + 4 + " " + ExportGroup.class.getSimpleName() + " after migration, not " + count,
count == 4);
// duplicate initiators should now be marked as inactive
for (Initiator initiator : oldInitiators) {
Initiator dbInitiator = _dbClient.queryObject(Initiator.class, initiator.getId());
Assert.assertTrue(dbInitiator.getInactive());
}
for (Initiator initiator : oldSingleInitiators) {
Initiator dbInitiator = _dbClient.queryObject(Initiator.class, initiator.getId());
Assert.assertTrue(dbInitiator.getInactive());
}
// other valid initiators should be still active
for (String id : newInitiators) {
Initiator dbInitiator = _dbClient.queryObject(Initiator.class, URI.create(id));
Assert.assertFalse(dbInitiator.getInactive());
}
for (String id : newSingleInitiators) {
Initiator dbInitiator = _dbClient.queryObject(Initiator.class, URI.create(id));
Assert.assertFalse(dbInitiator.getInactive());
}
}
private Initiator createInitiator(URI host, String port, String label) {
Initiator initiator = new Initiator();
initiator.setId(URIUtil.createId(Initiator.class));
initiator.setHost(host);
initiator.setInitiatorPort(port);
initiator.setLabel(label);
_dbClient.createObject(initiator);
return initiator;
}
private ExportGroup createExportGroup(List<Initiator> initiators, String label) {
StringSet initiatorIds = new StringSet();
for (Initiator initiator : initiators) {
initiatorIds.add(initiator.getId().toString());
}
ExportGroup exportGroup = new ExportGroup();
exportGroup.setId(URIUtil.createId(ExportGroup.class));
exportGroup.setInitiators(initiatorIds);
exportGroup.setLabel(label);
exportGroup.setType(ExportGroupType.Host.toString());
ExportMask mask = createExportMask(initiators);
StringSet masks = new StringSet();
masks.add(mask.getId().toString());
exportGroup.setExportMasks(masks);
_dbClient.createObject(exportGroup);
return exportGroup;
}
private ExportMask createExportMask(List<Initiator> initiators) {
StringSet initiatorIds = new StringSet();
for (Initiator initiator : initiators) {
initiatorIds.add(initiator.getId().toString());
}
StringMap userAdded = new StringMap();
for (Initiator initiator : initiators) {
userAdded.put(initiator.getInitiatorPort().replaceAll(":", ""), initiator.getId().toString());
}
StringSetMap zoningMap = new StringSetMap();
StoragePort port = new StoragePort();
port.setId(URIUtil.createId(StoragePort.class));
StringSet portMap = new StringSet();
portMap.add(port.getId().toString());
zoningMap.put(initiators.get(0).getId().toString(), portMap);
ExportMask mask = new ExportMask();
mask.setId(URIUtil.createId(ExportMask.class));
mask.setInitiators(initiatorIds);
mask.setUserAddedInitiators(userAdded);
mask.setZoningMap(zoningMap);
_dbClient.createObject(mask);
return mask;
}
private void validateExportMask(List<ExportMask> exportMasks, Set<String> initiators) {
for (ExportMask mask : exportMasks) {
Assert.assertNotNull(mask);
Assert.assertEquals(initiators.size(), mask.getInitiators().size());
Assert.assertTrue(mask.getInitiators().containsAll(initiators));
Assert.assertEquals(initiators.size(), mask.getUserAddedInitiators().size());
Assert.assertTrue(mask.getUserAddedInitiators().values().containsAll(initiators));
Assert.assertTrue(initiators.containsAll(mask.getZoningMap().keySet()));
}
}
}