/*
* Copyright (c) 2013 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.client.upgrade.callbacks;
import java.net.URI;
import java.util.Iterator;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.model.DataObject.Flag;
import com.emc.storageos.db.client.model.FileShare;
import com.emc.storageos.db.client.model.NamedURI;
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.StringSetUtil;
import com.emc.storageos.svcs.errorhandling.resources.MigrationCallbackException;
/**
* Migration handler to initialize the new DataObject.internalFlags field
*
* The two sub-classes which this is presently needed are FileShare and Volume
* and both must be handled by this single callback.
*
*/
public class DataObjectInternalFlagsInitializer extends BaseCustomMigrationCallback {
private static final Logger log = LoggerFactory.getLogger(DataObjectInternalFlagsInitializer.class);
@Override
public void process() throws MigrationCallbackException {
updateFlagsAndProjectForInternalFileShares();
updateInternalVolumes();
}
/**
* Convert old-style internal object FileShares (with project == null)
* into new-style ones with the constant URN and internal flags
*/
private void updateFlagsAndProjectForInternalFileShares() {
DbClient dbClient = this.getDbClient();
List<URI> fileShareKeys = dbClient.queryByType(FileShare.class, false);
Iterator<FileShare> fileShareObjs =
dbClient.queryIterativeObjects(FileShare.class, fileShareKeys);
while (fileShareObjs.hasNext()) {
FileShare fs = fileShareObjs.next();
log.debug("Examining FileShare (id={}) for upgrade", fs.getId().toString());
if (fs.getProject() == null) {
fs.setProject(new NamedURI(FileShare.INTERNAL_OBJECT_PROJECT_URN, fs.getLabel()));
fs.addInternalFlags(Flag.INTERNAL_OBJECT, Flag.NO_PUBLIC_ACCESS, Flag.NO_METERING);
dbClient.updateAndReindexObject(fs);
log.info("Converted internal FileShare (id={}) to use internal flags", fs.getId().toString());
}
}
}
/**
* Update volumes that need to have the INTERNAL_OBJECT flag set.
*/
private void updateInternalVolumes() {
DbClient dbClient = getDbClient();
List<URI> volumeURIs = dbClient.queryByType(Volume.class, false);
Iterator<Volume> volumes = dbClient.queryIterativeObjects(Volume.class, volumeURIs);
while (volumes.hasNext()) {
Volume volume = volumes.next();
log.debug("Examining volume (id={}) for upgrade", volume.getId().toString());
// Check if the volume has associated volumes. If so,
// this is a VPLEX volume, and we must mark these
// associated backend volumes as internal.
StringSet associatedVolumeIds = volume.getAssociatedVolumes();
if ((associatedVolumeIds != null) && (!associatedVolumeIds.isEmpty())) {
log.info("Backend volumes for VPLEX volume (id={}) must be upgraded", volume.getId().toString());
handleVPlexAssociatedVolumes(associatedVolumeIds);
continue;
}
// Check to see if the personality of the volume is of type "METADATA" if so, this is an
// RP Journal volume and should be marked as internal.
if (volume.getPersonality() != null && volume.getPersonality().equals(Volume.PersonalityTypes.METADATA.toString())) {
log.info("RecoverPoint Journal volume (id={}) must be upgraded", volume.getId().toString());
volume.addInternalFlags(Flag.INTERNAL_OBJECT);
volume.addInternalFlags(Flag.SUPPORTS_FORCE);
dbClient.persistObject(volume);
log.info("Marked RecoverPoint Journal volume (id={}) as internal object that supports force", volume.getId().toString());
}
}
}
/**
* Sets the INTERNAL_OBJECT flag for the passed associated backend volumes
* of a VPLEX volume.
*
* @param associatedVolumes The backend volumes of a VPLEX volume in the
* database.
*/
private void handleVPlexAssociatedVolumes(StringSet associatedVolumeIds) {
List<URI> associatedVolumeURIs = StringSetUtil
.stringSetToUriList(associatedVolumeIds);
List<Volume> associatedVolumes = dbClient.queryObject(Volume.class,
associatedVolumeURIs);
Iterator<Volume> associatedVolumesIter = associatedVolumes.iterator();
while (associatedVolumesIter.hasNext()) {
Volume associatedVolume = associatedVolumesIter.next();
associatedVolume.addInternalFlags(Flag.INTERNAL_OBJECT);
log.info("Marked VPLEX backend volume (id={}) as internal object", associatedVolume.getId().toString());
}
dbClient.persistObject(associatedVolumes);
}
}