/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.providerfinders;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.cim.CIMObjectPath;
import javax.wbem.WBEMException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.model.StorageProvider;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.util.CommonTransformerFunctions;
import com.emc.storageos.volumecontroller.impl.smis.CIMObjectPathFactory;
import com.emc.storageos.volumecontroller.impl.smis.SmisCommandHelper;
import com.google.common.collect.Collections2;
/**
* FindProviderStrategyByCG returns
* storage system (as is) if CG is found on its active provider,
* or storage system (updated with provider info) if CG is found on its passive provider,
* or null (if CG is not found on any of its provider).
*/
public class FindProviderStrategyByCG implements FindProviderStrategy {
private static final Logger log = LoggerFactory.getLogger(FindProviderStrategyByCG.class);
private DbClient dbClient;
private StorageSystem system;
private String groupName;
private SmisCommandHelper helper;
private CIMObjectPathFactory cimPathFactory;
public FindProviderStrategyByCG(DbClient dbClient, StorageSystem system, String groupName,
SmisCommandHelper helper, CIMObjectPathFactory cimPathFactory) {
this.dbClient = dbClient;
this.system = system;
this.groupName = groupName;
this.helper = helper;
this.cimPathFactory = cimPathFactory;
}
@Override
public StorageSystem find() {
// first check if active Provider has CG.
// Do not unnecessarily check on passive providers when active provider has it.
CIMObjectPath cimPath = cimPathFactory.getReplicationGroupPath(system, groupName);
if (null == cimPath) {
log.warn("Replication Group {} not found in Provider {}", groupName, system.getActiveProviderURI());
} else {
return system;
}
Set<URI> providerUris = new HashSet<URI>();
if (null != system.getProviders()) {
providerUris.addAll(Collections2.transform(system.getProviders(),
CommonTransformerFunctions.FCTN_STRING_TO_URI));
}
/**
* Check which of the passive SMI-S provider has CG available on it.
* This may be required when the active Provider for a system changes.
*
* Get all providers managing this system
* for each provider (except active provider)
* get 1 storage system which is actively managed by this provider
* (list should contain unique systems (except this.system))
* look for the group name for this system
*/
List<String> storageSystemUriStrs = new ArrayList<String>();
List<StorageSystem> passiveProviderSystems = new ArrayList<StorageSystem>();
// add source system so that we will take other system reference on passive provider
storageSystemUriStrs.add(system.getId().toString());
providerUris.remove(system.getActiveProviderURI());
if (!providerUris.isEmpty()) {
List<StorageProvider> passiveSmisProviderList = dbClient.queryObject(StorageProvider.class, providerUris);
for (StorageProvider provider : passiveSmisProviderList) {
if (null != provider.getStorageSystems()) {
for (String systemUriStr : provider.getStorageSystems()) {
if (!storageSystemUriStrs.contains(systemUriStr)) {
StorageSystem passiveProviderSystem = dbClient.queryObject(StorageSystem.class, URI.create(systemUriStr));
if (provider.getId().toString().equalsIgnoreCase(passiveProviderSystem.getActiveProviderURI().toString())) {
storageSystemUriStrs.add(systemUriStr);
passiveProviderSystems.add(passiveProviderSystem);
break;
}
}
}
}
}
}
// Each Storage System in turn refers to a Provider, we loop through each Storage System
// check whether CG is found.
StorageSystem systemWithCGFound = null;
for (StorageSystem passiveProviderSystem : passiveProviderSystems) {
cimPath = cimPathFactory.getReplicationGroupPath(passiveProviderSystem, system.getSerialNumber(), groupName);
if (null == cimPath) {
log.warn("Replication Group {} not found in Provider {}", groupName, passiveProviderSystem.getActiveProviderURI());
continue;
}
systemWithCGFound = passiveProviderSystem;
break;
}
// make this passive provider with CG active for this system
// Scanner process does not change active provider as long as the previous one is UP.
// So, there won't be conflict if we update it here.
if (systemWithCGFound != null) {
URI providerURI = systemWithCGFound.getActiveProviderURI();
log.info("Passive provider {} with Replication Group found. Making it active for system {}",
providerURI, system.getId());
StorageProvider provider = dbClient.queryObject(StorageProvider.class, providerURI);
system.setActiveProviderURI(providerURI);
system.setSmisPassword(provider.getPassword());
system.setSmisPortNumber(provider.getPortNumber());
system.setSmisProviderIP(provider.getIPAddress());
system.setSmisUserName(provider.getUserName());
system.setSmisUseSSL(provider.getUseSSL());
dbClient.persistObject(system);
log.info("Active provider for system {} has changed to {}.",
system.getId(), system.getActiveProviderURI());
// refresh SMI-S provider so that the current active provider (P1) is aware of changes made by previous active provider (P2).
// (For instance, addVolume to CG - Volume created in P2 needs to be available in P1)
try {
helper.callRefreshSystem(system, null);
} catch (WBEMException e) {
log.error("EMCRefresh against StorageSystem {} failed.", system.getNativeGuid(), e);
}
return system;
}
return null;
}
}