package com.emc.storageos.api.service.impl.resource.utils;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.api.service.impl.resource.FileService;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.model.FilePolicy;
import com.emc.storageos.db.client.model.FileShare;
import com.emc.storageos.db.client.model.FileShare.MirrorStatus;
import com.emc.storageos.db.client.model.FileShare.PersonalityTypes;
import com.emc.storageos.db.client.model.PolicyStorageResource;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.db.client.model.VirtualPool;
import com.emc.storageos.volumecontroller.FileControllerConstants;
public class FileSystemReplicationUtils {
private static final Logger _log = LoggerFactory.getLogger(FileService.class);
/**
* Checks to see if the file replication change is supported.
*
* @param currentVpool
* the source virtual pool
* @param newVpool
* the target virtual pool
* @param notSuppReasonBuff
* the not supported reason string buffer
* @return
*/
public static boolean isSupportedFileReplicationCreate(FileShare fs, VirtualPool currentVpool, StringBuffer notSuppReasonBuff) {
_log.info(String.format("Checking isSupportedFileReplicationCreate for Fs [%s] with vpool [%s]...", fs.getLabel(),
currentVpool.getLabel()));
if (!doBasicMirrorValidation(fs, currentVpool, notSuppReasonBuff)) {
return false;
}
// File system should not be the active source file system!!
if (fs.getPersonality() != null
&& fs.getPersonality().equalsIgnoreCase(PersonalityTypes.SOURCE.name())
&& !MirrorStatus.DETACHED.name().equalsIgnoreCase(fs.getMirrorStatus())) {
notSuppReasonBuff
.append(String
.format("File system given in request is an active source file system %s.",
fs.getLabel()));
_log.info(notSuppReasonBuff.toString());
return false;
}
// File system should not have any active mirror copies!!
if (fs.getMirrorfsTargets() != null
&& !fs.getMirrorfsTargets().isEmpty()) {
notSuppReasonBuff
.append(String
.format("File system given in request has active target file system %s.",
fs.getLabel()));
_log.info(notSuppReasonBuff.toString());
return false;
}
return true;
}
/**
* Checks to see if the file replication change is supported.
*
* @param currentVpool
* the source virtual pool
* @param newVpool
* the target virtual pool
* @param notSuppReasonBuff
* the not supported reason string buffer
* @return
*/
public static boolean validateDeleteMirrorCopies(FileShare fs, VirtualPool currentVpool, StringBuffer notSuppReasonBuff) {
_log.info(String.format("Checking validateDeleteMirrorCopies for Fs [%s] ", fs.getLabel()));
if (!doBasicMirrorValidation(fs, currentVpool, notSuppReasonBuff)) {
return false;
}
// File system should not be the failover state
// Failover state, the mirror copy would be in production!!!
if (fs.getPersonality() != null && fs.getPersonality().equalsIgnoreCase(PersonalityTypes.SOURCE.name())
&& (MirrorStatus.FAILED_OVER.name().equalsIgnoreCase(fs.getMirrorStatus())
|| MirrorStatus.SUSPENDED.name().equalsIgnoreCase(fs.getMirrorStatus()))) {
notSuppReasonBuff.append(String.format("File system given in request is in active or failover state %s.",
fs.getLabel()));
_log.info(notSuppReasonBuff.toString());
return false;
}
// File system should not have any active mirror copies!!
if (fs.getMirrorfsTargets() == null || fs.getMirrorfsTargets().isEmpty()) {
notSuppReasonBuff.append(String.format("File system given in request has no active target file system %s.",
fs.getLabel()));
_log.info(notSuppReasonBuff.toString());
return false;
}
return true;
}
/**
* Checks to see if the file replication operation is supported.
*
* @param fs file share object
* @param currentVpool source virtual pool
* @param notSuppReasonBuff the not supported reason string buffer
* @param operation mirror operation to be checked
*/
public static boolean validateMirrorOperationSupported(FileShare fs, StringBuffer notSuppReasonBuff,
String operation) {
_log.info("Checking if mirror operation {} is supported for file system {} ", operation, fs.getLabel());
// Check if the file system is source file system, has some policy attached to it, mirror status is not null
if (fs.getPersonality() == null || !fs.getPersonality().equals(PersonalityTypes.SOURCE.name()) ||
fs.getMirrorStatus() == null || fs.getFilePolicies().isEmpty()) {
notSuppReasonBuff.append(String.format("File system - %s given in request is not having any active replication.",
fs.getLabel()));
_log.info(notSuppReasonBuff.toString());
return false;
}
String currentMirrorStatus = fs.getMirrorStatus();
boolean isSupported = false;
switch (operation) {
// Refresh operation can be performed without any check.
case "refresh":
isSupported = true;
break;
// START operation can be performed only if Mirror status is UNKNOWN
case "start":
if (currentMirrorStatus.equalsIgnoreCase(MirrorStatus.UNKNOWN.toString()))
isSupported = true;
break;
// STOP operation can be performed only if Mirror status is SYNCHRONIZED or IN_SYNC
case "stop":
if (currentMirrorStatus.equalsIgnoreCase(MirrorStatus.SYNCHRONIZED.toString())
|| currentMirrorStatus.equalsIgnoreCase(MirrorStatus.IN_SYNC.toString()))
isSupported = true;
break;
// PAUSE operation can be performed only if Mirror status is SYNCHRONIZED or IN_SYNC
case "pause":
if (currentMirrorStatus.equalsIgnoreCase(MirrorStatus.SYNCHRONIZED.toString())
|| currentMirrorStatus.equalsIgnoreCase(MirrorStatus.IN_SYNC.toString()))
isSupported = true;
break;
// RESUME operation can be performed only if Mirror status is PAUSED.
case "resume":
if (currentMirrorStatus.equalsIgnoreCase(MirrorStatus.PAUSED.toString()))
isSupported = true;
break;
// Fail over can be performed if Mirror status is NOT UNKNOWN or FAILED_OVER.
case "failover":
if (!(currentMirrorStatus.equalsIgnoreCase(MirrorStatus.UNKNOWN.toString())
|| currentMirrorStatus.equalsIgnoreCase(MirrorStatus.FAILED_OVER.toString())))
isSupported = true;
break;
// Fail back can be performed only if Mirror status is FAILED_OVER.
case "failback":
if (currentMirrorStatus.equalsIgnoreCase(MirrorStatus.FAILED_OVER.toString()))
isSupported = true;
break;
}
notSuppReasonBuff.append(String.format(" : file system %s is in %s state", fs.getLabel(), currentMirrorStatus.toUpperCase()));
return isSupported;
}
/**
* Checks to see if the file replication change is supported.
*
* @param fs
* @param currentVpool
* the source virtual pool
* @param notSuppReasonBuff
* the not supported reason string buffer
* @return
*/
public static boolean doBasicMirrorValidation(FileShare fs, VirtualPool currentVpool, StringBuffer notSuppReasonBuff) {
// file system virtual pool must be enabled with replication..
if (!VirtualPool.vPoolSpecifiesFileReplication(currentVpool)) {
notSuppReasonBuff.append(String.format("File replication is not enabled in virtual pool - %s"
+ " of the requested file system -%s ", currentVpool.getLabel(), fs.getLabel()));
_log.info(notSuppReasonBuff.toString());
return false;
}
// File system should not be the target file system..
if (fs.getPersonality() != null && fs.getPersonality().equalsIgnoreCase(PersonalityTypes.TARGET.name())) {
notSuppReasonBuff.append(String.format("File system - %s given in request is an active Target file system.",
fs.getLabel()));
_log.info(notSuppReasonBuff.toString());
return false;
}
return true;
}
/**
* Checks to see if the file replication change is supported.
*
* @param fs
* @param notSuppReasonBuff
* the not supported reason string buffer
* @return
*/
public static boolean filesystemHasActiveReplication(FileShare fs, StringBuffer notSuppReasonBuff,
String deleteType, boolean forceDelete) {
// File system should not be the target file system..
if (fs.getPersonality() != null && fs.getPersonality().equalsIgnoreCase(PersonalityTypes.TARGET.name())) {
notSuppReasonBuff.append(String.format("File system - %s given in request is an active Target file system.",
fs.getLabel()));
_log.info(notSuppReasonBuff.toString());
return true;
}
// File system should not have active replication targets!!
// For resource delete (forceDelete=false)
// For VIPR_ONLY type, till we support ingestion of replication file systems
// avoid deleting file systems if it has active mirrors!!
if (!forceDelete || FileControllerConstants.DeleteTypeEnum.VIPR_ONLY.toString().equalsIgnoreCase(deleteType)) {
if (fs.getMirrorfsTargets() != null && !fs.getMirrorfsTargets().isEmpty()) {
notSuppReasonBuff.append(String.format("File system %s given in request has active target file systems.",
fs.getLabel()));
_log.info(notSuppReasonBuff.toString());
return true;
}
}
return false;
}
public static FilePolicy getReplicationPolicyAppliedOnFS(FileShare fs, DbClient dbClient) {
StringSet existingFSPolicies = fs.getFilePolicies();
List<URI> existingFSPolicyURIs = new ArrayList<>();
for (String filePolicyURI : existingFSPolicies) {
existingFSPolicyURIs.add(URI.create(filePolicyURI));
}
Iterator<FilePolicy> iterator = dbClient.queryIterativeObjects(FilePolicy.class, existingFSPolicyURIs, true);
while (iterator.hasNext()) {
FilePolicy fp = iterator.next();
if (fp.getFilePolicyType().equals(FilePolicy.FilePolicyType.file_replication.name())) {
_log.info("Found replication policy :{} applied to the file system: {}.",
fp.toString(), fs.getId());
return fp;
}
}
return null;
}
public static PolicyStorageResource getEquivalentPolicyStorageResource(FileShare fs, DbClient dbClient) {
FilePolicy fp = getReplicationPolicyAppliedOnFS(fs, dbClient);
if (fp != null) {
StringSet policyStrResources = fp.getPolicyStorageResources();
List<URI> policyStrURIs = new ArrayList<>();
for (String policyStrResource : policyStrResources) {
policyStrURIs.add(URI.create(policyStrResource));
}
Iterator<PolicyStorageResource> iterator = dbClient.queryIterativeObjects(PolicyStorageResource.class, policyStrURIs, true);
while (iterator.hasNext()) {
PolicyStorageResource policyRes = iterator.next();
if (policyRes.getAppliedAt().equals(fs.getId()) && policyRes.getStorageSystem().equals(fs.getStorageDevice())) {
return policyRes;
}
}
}
return null;
}
}