/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.client.upgrade.callbacks;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.URIUtil;
import com.emc.storageos.db.client.model.BlockSnapshot;
import com.emc.storageos.db.client.model.BlockSnapshotSession;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.db.client.model.Volume;
import com.emc.storageos.db.client.upgrade.BaseCustomMigrationCallback;
import com.emc.storageos.db.client.util.NullColumnValueGetter;
import com.emc.storageos.svcs.errorhandling.resources.MigrationCallbackException;
/**
* Migration callback creates a BlockSnapshotSession instance for each VMAX BlockSnapshot and
* adds the BlockSnapshot to the linked targets list of the newly created BlockSnapshotSession.
*/
public class BlockSnapshotSessionMigration extends BaseCustomMigrationCallback {
// A reference to a logger.
private static final Logger s_logger = LoggerFactory.getLogger(BlockSnapshotSessionMigration.class);
private static final String SMIS80_DELIMITER_REGEX = "-\\+-";
/**
* {@inheritDoc}
*/
@Override
public void process() throws MigrationCallbackException {
s_logger.info("Executing BlockSnapshotSession migration callback.");
try {
DbClient dbClient = getDbClient();
List<BlockSnapshotSession> snapshotSessions = new ArrayList<BlockSnapshotSession>();
Map<URI, Map<String, BlockSnapshotSession>> groupSessionMap = new HashMap<>();
List<URI> snapshotURIs = dbClient.queryByType(BlockSnapshot.class, true);
Iterator<BlockSnapshot> snapshotsIter = dbClient.queryIterativeObjects(BlockSnapshot.class, snapshotURIs, true);
while (snapshotsIter.hasNext()) {
BlockSnapshot snapshot = snapshotsIter.next();
if (isSnapshotSessionSupported(snapshot)) {
// Check if this is a group snapshot.
URI cgURI = snapshot.getConsistencyGroup();
if (NullColumnValueGetter.isNullURI(cgURI)) {
// The storage system for the single volume snapshot supports
// snapshot sessions, then we need to prepare and create a
// snapshot session for that snapshot and add the snapshot as
// a linked target for the session.
BlockSnapshotSession snapshotSession = prepareSnapshotSession(snapshot);
snapshotSessions.add(snapshotSession);
} else {
// Create the group session if necessary and add the snapshot as a
// linked target for that group session.
String settingsInstance = snapshot.getSettingsInstance();
Map<String, BlockSnapshotSession> grpSnapshotSessions = groupSessionMap.get(cgURI);
if (grpSnapshotSessions != null) {
BlockSnapshotSession snapshotSession = grpSnapshotSessions.get(settingsInstance);
if (snapshotSession == null) {
snapshotSession = prepareSnapshotSession(snapshot);
grpSnapshotSessions.put(settingsInstance, snapshotSession);
snapshotSessions.add(snapshotSession);
} else {
StringSet linkedTargets = snapshotSession.getLinkedTargets();
linkedTargets.add(snapshot.getId().toString());
}
} else {
grpSnapshotSessions = new HashMap<String, BlockSnapshotSession>();
groupSessionMap.put(cgURI, grpSnapshotSessions);
BlockSnapshotSession snapshotSession = prepareSnapshotSession(snapshot);
grpSnapshotSessions.put(settingsInstance, snapshotSession);
snapshotSessions.add(snapshotSession);
}
}
}
}
if (!snapshotSessions.isEmpty()) {
dbClient.createObject(snapshotSessions);
}
} catch (Exception e) {
s_logger.error("Caught exception during BlockSnapshotSession migration", e);
}
}
/**
* Determines if the storage system for the passed BlockSnapshot instance supports
* snapshot sessions.
*
* @param snapshot A reference to the snapshot.
*
* @return true if the system for the passed snapshot supports snapshot sessions, false otherwise.
*/
private boolean isSnapshotSessionSupported(BlockSnapshot snapshot) {
boolean isSupported = false;
URI systemURI = snapshot.getStorageController();
StorageSystem system = dbClient.queryObject(StorageSystem.class, systemURI);
if ((system != null) && (system.checkIfVmax3())) {
s_logger.info("BlockSnapshotSession supported for snapshot {}:{}", snapshot.getId(), snapshot.getLabel());
isSupported = true;
}
return isSupported;
}
/**
* Prepare the ViPR BlockSnapshotSession instance for the pass BlockSnapshot instance.
*
* @param snapshot A reference to the snapshot.
*
* @return A reference to the newly created snapshot session.
*/
private BlockSnapshotSession prepareSnapshotSession(BlockSnapshot snapshot) {
s_logger.info("Prepare BlockSnapshotSession for snapshot {}", snapshot.getId());
BlockSnapshotSession snapshotSession = new BlockSnapshotSession();
URI snapSessionURI = URIUtil.createId(BlockSnapshotSession.class);
snapshotSession.setId(snapSessionURI);
snapshotSession.setSessionLabel(getSessionLabelFromSettingsInstance(snapshot));
URI cgURI = snapshot.getConsistencyGroup();
if (NullColumnValueGetter.isNullURI(cgURI)) {
snapshotSession.setParent(snapshot.getParent());
snapshotSession.setLabel(snapshot.getLabel());
} else {
snapshotSession.setConsistencyGroup(cgURI);
snapshotSession.setLabel(snapshot.getSnapsetLabel());
Volume parent = getDbClient().queryObject(Volume.class, snapshot.getParent());
if (parent != null) {
snapshotSession.setReplicationGroupInstance(parent.getReplicationGroupInstance());
snapshotSession.setSessionSetName(parent.getReplicationGroupInstance());
}
}
snapshotSession.setProject(snapshot.getProject());
snapshotSession.setStorageController(snapshot.getStorageController());
snapshotSession.setSessionInstance(snapshot.getSettingsInstance());
StringSet linkedTargets = new StringSet();
linkedTargets.add(snapshot.getId().toString());
snapshotSession.setLinkedTargets(linkedTargets);
return snapshotSession;
}
/**
* Gets the session label from settings instance.
*
* @param snapshot the snapshot
* @return the session label from settings instance
*/
private String getSessionLabelFromSettingsInstance(BlockSnapshot snapshot) {
String sessionLabel = null;
String settingsInstance = snapshot.getSettingsInstance();
if (settingsInstance != null && !settingsInstance.isEmpty()) {
String[] instanceArray = settingsInstance.split(SMIS80_DELIMITER_REGEX);
sessionLabel = instanceArray[3];
}
return sessionLabel;
}
}