/*
* Copyright (c) 2017 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.db.client.upgrade.callbacks;
import java.net.URI;
import java.util.ArrayList;
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.constraint.ContainmentConstraint;
import com.emc.storageos.db.client.constraint.URIQueryResultList;
import com.emc.storageos.db.client.model.FilePolicy;
import com.emc.storageos.db.client.model.FilePolicy.FilePolicyApplyLevel;
import com.emc.storageos.db.client.model.FilePolicy.FilePolicyPriority;
import com.emc.storageos.db.client.model.FilePolicy.FilePolicyType;
import com.emc.storageos.db.client.model.FileReplicaPolicyTarget;
import com.emc.storageos.db.client.model.FileReplicaPolicyTargetMap;
import com.emc.storageos.db.client.model.FileReplicationTopology;
import com.emc.storageos.db.client.model.FileShare;
import com.emc.storageos.db.client.model.FileShare.PersonalityTypes;
import com.emc.storageos.db.client.model.NASServer;
import com.emc.storageos.db.client.model.PhysicalNAS;
import com.emc.storageos.db.client.model.PolicyStorageResource;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.db.client.model.VirtualNAS;
import com.emc.storageos.db.client.model.VirtualPool;
import com.emc.storageos.db.client.model.VirtualPool.FileReplicationType;
import com.emc.storageos.db.client.model.VpoolRemoteCopyProtectionSettings;
import com.emc.storageos.db.client.upgrade.BaseCustomMigrationCallback;
import com.emc.storageos.db.client.util.NullColumnValueGetter;
import com.emc.storageos.svcs.errorhandling.resources.MigrationCallbackException;
/**
* File Protection policies are introduced in 3.6 release.
* Virtual pool replication attributes are moved to file protection policy, Hence
*
* 1. Replication attributes should be converted to FilePolicy(replication).
* 2. If there are any file systems with the replication vpool,
* policy storage resources has to create between policy and file system resource.
*
*
*/
public class VirtualPoolFileReplicationPolicyMigration extends BaseCustomMigrationCallback {
private static final Logger logger = LoggerFactory.getLogger(VirtualPoolFileReplicationPolicyMigration.class);
public static final String FILE_STORAGE_RESOURCE = "FILESTORAGERESOURCE";
public static final String FILE_STORAGE_DEVICE_TYPE = "ISILON";
@Override
public void process() throws MigrationCallbackException {
logger.info("File Virtual pool to file replication policy migration START");
DbClient dbClient = getDbClient();
try {
List<URI> virtualPoolURIs = dbClient.queryByType(VirtualPool.class, true);
Iterator<VirtualPool> virtualPools = dbClient.queryIterativeObjects(VirtualPool.class, virtualPoolURIs, true);
List<VirtualPool> modifiedVpools = new ArrayList<VirtualPool>();
List<FilePolicy> replPolicies = new ArrayList<FilePolicy>();
// Create replication policy from vpool replication attributes
// Identify any file systems created with the replication vpool.
// Establish relation from policy to FilePolicyResource
while (virtualPools.hasNext()) {
VirtualPool virtualPool = virtualPools.next();
if (VirtualPool.Type.file.name().equals(virtualPool.getType())
&& virtualPool.getFileReplicationType() != null
&& !FileReplicationType.NONE.name().equalsIgnoreCase(virtualPool.getFileReplicationType())) {
logger.info("vpool {} has enabled with replication, Creating appropriate file policy.....", virtualPool.getLabel());
// Create replication policy
FilePolicy replPolicy = new FilePolicy();
replPolicy.setId(URIUtil.createId(FilePolicy.class));
replPolicy.setFilePolicyDescription(
"Policy created from virtual pool " + virtualPool.getLabel() + " while system upgrade");
String polName = virtualPool.getLabel() + "_Replication_Policy";
replPolicy.setLabel(polName);
replPolicy.setFilePolicyName(polName);
replPolicy.setLabel(polName);
replPolicy.setFilePolicyType(FilePolicyType.file_replication.name());
replPolicy.setFilePolicyVpool(virtualPool.getId());
// Replication policy was created always at file system level!!
replPolicy.setApplyAt(FilePolicyApplyLevel.file_system.name());
if(virtualPool.getFileReplicationCopyMode().equals(VirtualPool.RPCopyMode.ASYNCHRONOUS.name())){
replPolicy.setFileReplicationCopyMode(FilePolicy.FileReplicationCopyMode.ASYNC.name());
}else{
replPolicy.setFileReplicationCopyMode(FilePolicy.FileReplicationCopyMode.SYNC.name());
}
replPolicy.setFileReplicationType(virtualPool.getFileReplicationType());
replPolicy.setPriority(FilePolicyPriority.Normal.toString());
// Set the policy schedule based on vPool RPO
if (virtualPool.getFrRpoValue() != null && virtualPool.getFrRpoType() != null) {
replPolicy.setScheduleRepeat((long) virtualPool.getFrRpoValue());
replPolicy.setScheduleTime("00:00AM");
replPolicy.setScheduleFrequency(virtualPool.getFrRpoType().toLowerCase());
// Virtual pool was supporting only Minutes/Hours/Days for RPO type
// Day of the week and month is not applicable!!
replPolicy.setScheduleDayOfWeek(NullColumnValueGetter.getNullStr());
replPolicy.setScheduleDayOfMonth(0L);
}
// Create replication topology
// set topology reference to policy
if (FileReplicationType.REMOTE.name().equalsIgnoreCase(virtualPool.getFileReplicationType())) {
logger.info("Creating replication topology for remote replication vpool {} .....", virtualPool.getLabel());
StringSet replicationTopologies = new StringSet();
StringSet targetVarrays = new StringSet();
Map<URI, VpoolRemoteCopyProtectionSettings> remoteSettings = virtualPool.getFileRemoteProtectionSettings(
virtualPool,
dbClient);
if (remoteSettings != null && !remoteSettings.isEmpty()) {
// till now CoprHD supports only single target!!
targetVarrays.add(remoteSettings.keySet().iterator().next().toString());
}
if (virtualPool.getVirtualArrays() != null && !virtualPool.getVirtualArrays().isEmpty()) {
for (String srcvArray : virtualPool.getVirtualArrays()) {
FileReplicationTopology dbReplTopology = new FileReplicationTopology();
dbReplTopology.setId(URIUtil.createId(FileReplicationTopology.class));
dbReplTopology.setPolicy(replPolicy.getId());
dbReplTopology.setSourceVArray(URI.create(srcvArray));
dbReplTopology.setTargetVArrays(targetVarrays);
dbClient.createObject(dbReplTopology);
replicationTopologies.add(dbReplTopology.getId().toString());
}
replPolicy.setReplicationTopologies(replicationTopologies);
logger.info("Created {} replication topologies from vpool {}", replicationTopologies.size(),
virtualPool.getLabel().toString());
}
}
// Fetch if there are any file system were provisioned with the vpool
// if present, link them to replication policy!!
URIQueryResultList resultList = new URIQueryResultList();
dbClient.queryByConstraint(
ContainmentConstraint.Factory.getVirtualPoolFileshareConstraint(virtualPool.getId()), resultList);
for (Iterator<URI> fileShareItr = resultList.iterator(); fileShareItr.hasNext();) {
FileShare fs = dbClient.queryObject(FileShare.class, fileShareItr.next());
if (!fs.getInactive() && fs.getPersonality() != null
&& fs.getPersonality().equalsIgnoreCase(PersonalityTypes.SOURCE.name())) {
StorageSystem system = dbClient.queryObject(StorageSystem.class, fs.getStorageDevice());
updatePolicyStorageResouce(system, replPolicy, fs);
fs.addFilePolicy(replPolicy.getId());
dbClient.updateObject(fs);
}
}
replPolicies.add(replPolicy);
virtualPool.setAllowFilePolicyAtFSLevel(true);
virtualPool.setFileReplicationSupported(true);
modifiedVpools.add(virtualPool);
}
}
// Udate DB
if (!replPolicies.isEmpty()) {
logger.info("Created {} replication policies ", replPolicies.size());
dbClient.createObject(replPolicies);
}
if (!modifiedVpools.isEmpty()) {
logger.info("Modified {} vpools ", modifiedVpools.size());
dbClient.updateObject(modifiedVpools);
}
} catch (Exception ex) {
logger.error("Exception occured while migrating file replication policy for Virtual pools");
logger.error(ex.getMessage(), ex);
}
logger.info("Virtual pool file replication policy migration END");
}
private PhysicalNAS getSystemPhysicalNAS(StorageSystem system) {
List<URI> nasServers = dbClient.queryByType(PhysicalNAS.class, true);
List<PhysicalNAS> phyNasServers = dbClient.queryObject(PhysicalNAS.class, nasServers);
for (PhysicalNAS nasServer : phyNasServers) {
if (nasServer.getStorageDeviceURI().toString().equalsIgnoreCase(system.getId().toString())) {
return nasServer;
}
}
return null;
}
private String generateNativeGuidForFilePolicyResource(StorageSystem device, String nasServer, String policyType,
String path) {
return String.format("%s+%s+%s+%s+%s+%s", FILE_STORAGE_DEVICE_TYPE, device.getSerialNumber(), FILE_STORAGE_RESOURCE,
nasServer, policyType, path);
}
private void updatePolicyStorageResouce(StorageSystem system, FilePolicy filePolicy, FileShare fs) {
logger.info("Creating policy storage resource for storage {} fs {} and policy {} ", system.getLabel(), fs.getLabel(),
filePolicy.getFilePolicyName());
PolicyStorageResource policyStorageResource = new PolicyStorageResource();
policyStorageResource.setId(URIUtil.createId(PolicyStorageResource.class));
policyStorageResource.setFilePolicyId(filePolicy.getId());
policyStorageResource.setStorageSystem(system.getId());
policyStorageResource.setPolicyNativeId(fs.getName());
policyStorageResource.setAppliedAt(fs.getId());
policyStorageResource.setResourcePath(fs.getNativeId());
NASServer nasServer = null;
if (fs.getVirtualNAS() != null) {
nasServer = dbClient.queryObject(VirtualNAS.class, fs.getVirtualNAS());
} else {
// Get the physical NAS for the storage system!!
PhysicalNAS pNAS = getSystemPhysicalNAS(system);
if (pNAS != null) {
nasServer = pNAS;
}
}
if (nasServer != null) {
logger.info("Found NAS server {} ", nasServer.getNasName());
policyStorageResource.setNasServer(nasServer.getId());
policyStorageResource.setNativeGuid(generateNativeGuidForFilePolicyResource(system,
nasServer.getNasName(), filePolicy.getFilePolicyType(), fs.getNativeId()));
}
if (fs.getMirrorfsTargets() != null && !fs.getMirrorfsTargets().isEmpty()) {
String[] targetFSs = fs.getMirrorfsTargets().toArray(new String[fs.getMirrorfsTargets().size()]);
// Today we support single target!!
FileShare fsTarget = dbClient.queryObject(FileShare.class, URI.create(targetFSs[0]));
// In older release, policy name was set to target file system lable!!
policyStorageResource.setPolicyNativeId(fsTarget.getLabel());
// Update the target resource details!!!
FileReplicaPolicyTargetMap fileReplicaPolicyTargetMap = new FileReplicaPolicyTargetMap();
FileReplicaPolicyTarget target = new FileReplicaPolicyTarget();
target.setAppliedAt(filePolicy.getApplyAt());
target.setStorageSystem(fsTarget.getStorageDevice().toString());
target.setPath(fsTarget.getNativeId());
NASServer targetNasServer = null;
if (fsTarget.getVirtualNAS() != null) {
targetNasServer = dbClient.queryObject(VirtualNAS.class, fsTarget.getVirtualNAS());
} else {
StorageSystem targetSystem = dbClient.queryObject(StorageSystem.class, fsTarget.getStorageDevice());
// Get the physical NAS for the storage system!!
PhysicalNAS pNAS = getSystemPhysicalNAS(targetSystem);
if (pNAS != null) {
targetNasServer = pNAS;
}
}
if (targetNasServer != null) {
target.setNasServer(targetNasServer.getId().toString());
}
String key = target.getFileTargetReplicaKey();
fileReplicaPolicyTargetMap.put(key, target);
policyStorageResource.setFileReplicaPolicyTargetMap(fileReplicaPolicyTargetMap);
}
dbClient.createObject(policyStorageResource);
filePolicy.addPolicyStorageResources(policyStorageResource.getId());
filePolicy.addAssignedResources(fs.getId());
logger.info("PolicyStorageResource object created successfully for {} ",
system.getLabel() + policyStorageResource.getAppliedAt());
}
}