/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.smis;
import static com.google.common.collect.Iterators.toArray;
import static com.google.common.collect.Iterators.transform;
import static java.lang.String.format;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import javax.cim.CIMInstance;
import javax.cim.CIMObjectPath;
import javax.cim.CIMProperty;
import javax.wbem.CloseableIterator;
import javax.wbem.WBEMException;
import javax.wbem.client.WBEMClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.cimadapter.connections.cim.CimConnection;
import com.emc.storageos.db.client.model.BlockObject;
import com.emc.storageos.db.client.model.ExportMask;
import com.emc.storageos.db.client.model.RemoteDirectorGroup;
import com.emc.storageos.db.client.model.StoragePool;
import com.emc.storageos.db.client.model.StorageSystem;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
/**
* This class uses WBEM queries to acquire the CIMObjectPath instances directly from the Provider.
*/
public class CIMObjectPathQueryFactory extends AbstractCIMObjectPathFactory {
private static final Logger log = LoggerFactory.getLogger(CIMObjectPathQueryFactory.class);
private static final String QUERY_LANG = "wql";
@Override
public CIMObjectPath getElementCompositionSvcPath(StorageSystem storageDevice) {
String wql = format("SELECT * FROM %s WHERE SystemName like'%s'",
prefixWithParamName(REPLICATION_SERVICE), storageDevice.getSerialNumber());
CIMObjectPath queryClass = getQueryClass(REPLICATION_SERVICE);
CIMObjectPath[] paths = execQuery(storageDevice, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getConfigSvcPath(StorageSystem storageDevice) {
String wql = format("SELECT Name FROM %s WHERE SystemName = '%s'",
prefixWithParamName(STORAGE_CONFIGURATION_SERVICE), getSystemName(storageDevice));
CIMObjectPath queryClass = getQueryClass(STORAGE_CONFIGURATION_SERVICE);
CIMObjectPath[] paths = execQuery(storageDevice, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getStorageSynchronized(StorageSystem sourceSystem, BlockObject source, StorageSystem targetSystem,
BlockObject target) {
return null;
}
@Override
public CIMObjectPath getGroupSynchronized(CIMObjectPath sourceGroup, CIMObjectPath targetGroup) {
return null;
}
@Override
public CIMObjectPath getControllerConfigSvcPath(StorageSystem storageDevice) {
String wql = format("SELECT * FROM %s WHERE SystemName like'%s'",
prefixWithParamName(CONTROLLER_CONFIGURATION_SERVICE), storageDevice.getSerialNumber());
CIMObjectPath queryClass = getQueryClass(CONTROLLER_CONFIGURATION_SERVICE);
CIMObjectPath[] paths = execQuery(storageDevice, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getTierPolicySvcPath(StorageSystem storageDevice) {
String wql = format("SELECT * FROM %s WHERE SystemName like'%s'",
prefixWithParamName(TIER_POLICY_SERVICE), storageDevice.getSerialNumber());
CIMObjectPath queryClass = getQueryClass(TIER_POLICY_SERVICE);
CIMObjectPath[] paths = execQuery(storageDevice, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
/**
* TODO StoragePoolSetting or Tier_policyRule
*/
@Override
public CIMObjectPath getTierPolicyRulePath(StorageSystem storageDevice, String policyName) {
String tierPolicyRuleClazz = storageDevice.checkIfVmax3() ? STORAGE_POOL_SETTING : TIER_POLICY_RULE;
String wql = format("SELECT * FROM %s WHERE SystemName like '%s' AND PolicyRuleName like '%s'",
prefixWithParamName(tierPolicyRuleClazz), storageDevice.getSerialNumber(),
policyName);
CIMObjectPath queryClass = getQueryClass(TIER_POLICY_SERVICE);
CIMObjectPath[] paths = execQuery(storageDevice, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getControllerReplicationSvcPath(StorageSystem storageDevice) {
String wql = format("SELECT * FROM %s WHERE SystemName like '%s'",
prefixWithParamName(REPLICATION_SERVICE), storageDevice.getSerialNumber());
CIMObjectPath queryClass = getQueryClass(REPLICATION_SERVICE);
CIMObjectPath[] paths = execQuery(storageDevice, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getStorageProtectionSvcPath(StorageSystem storageDevice) {
String wql = format("SELECT * FROM %s WHERE SystemName like '%s'",
prefixWithParamName(PROTECTION_SERVICE), storageDevice.getSerialNumber());
CIMObjectPath queryClass = getQueryClass(PROTECTION_SERVICE);
CIMObjectPath[] paths = execQuery(storageDevice, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getReplicationServiceCapabilitiesPath(StorageSystem storageDevice) {
String wql = format("SELECT * FROM %s WHERE InstanceID = '%s'",
prefixWithParamName(REPLICATION_SERVICE_CAPABILTIES), getSystemName(storageDevice));
CIMObjectPath queryClass = getQueryClass(REPLICATION_SERVICE_CAPABILTIES);
CIMObjectPath[] paths = execQuery(storageDevice, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getSeSystemRegistrationService(StorageSystem storage) {
String wql = format("SELECT * FROM %s WHERE SystemName like '%s'",
SE_SYSTEM_REGISTRATION_SERVICE, storage.getSerialNumber());
CIMObjectPath queryClass = getQueryClass(SE_SYSTEM_REGISTRATION_SERVICE);
CIMObjectPath[] paths = execQuery(storage, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath[] getClarProtocolControllers(StorageSystem storageDevice, String protocolControllerName) throws Exception {
String wql = format("SELECT * FROM %s WHERE SystemName like '%s' AND DeviceID like '%s'",
CLAR_LUN_MASKING_SCSI_PROTOCOL_CONTROLLER, storageDevice.getSerialNumber(),
protocolControllerName);
CIMObjectPath queryClass = getQueryClass(CLAR_LUN_MASKING_SCSI_PROTOCOL_CONTROLLER);
CIMObjectPath[] paths = execQuery(storageDevice, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths;
}
@Override
public CIMObjectPath[] getVolumePaths(StorageSystem storageDevice, String[] volumeNames) throws Exception {
ArrayList<CIMObjectPath> theElementsList = new ArrayList<CIMObjectPath>();
for (String volumeName : volumeNames) {
String wql = format("SELECT Name FROM %s WHERE SystemName = '%s' AND DeviceID = '%s'",
prefixWithParamName(STORAGE_VOLUME), getSystemName(storageDevice), volumeName);
CIMObjectPath queryClass = getQueryClass(STORAGE_VOLUME);
CIMObjectPath[] volumePath = execQuery(storageDevice, queryClass, wql);
if (volumePath.length != 1) {
return null;
}
theElementsList.add(volumePath[0]);
}
CIMObjectPath[] volArray = {};
volArray = theElementsList.toArray(volArray);
return volArray;
}
@Override
public CIMObjectPath[] getTargetPortPaths(StorageSystem storageDevice, List<URI> targetURIList) throws Exception {
// Query factory already gets the values from provider, no need to implement.
return null;
}
@Override
public CIMObjectPath[] getInitiatorPaths(StorageSystem storageDevice, String[] initiatorNames) throws Exception {
List<CIMObjectPath> cimPathList = new ArrayList<CIMObjectPath>();
for (String iniName : initiatorNames) {
// TODO
String wql = format("SELECT * FROM %s WHERE InstanceID like '%s'",
CP_SE_STORAGE_HARDWARE_ID, iniName);
CIMObjectPath queryClass = getQueryClass(CP_SE_STORAGE_HARDWARE_ID);
CIMObjectPath[] paths = execQuery(storageDevice, queryClass, wql);
if (paths.length == 0) {
continue;
}
cimPathList.add(paths[0]);
}
CIMObjectPath[] paths = {};
return cimPathList.toArray(paths);
}
@Override
public HashMap<String, CIMObjectPath> getInitiatorToInitiatorPath(StorageSystem storageDevice, List<String> initiatorNames)
throws Exception {
HashMap<String, CIMObjectPath> initiatorToInitiatorPathMap = new HashMap<String, CIMObjectPath>();
for (String iniName : initiatorNames) {
String wql = format("SELECT * FROM %s WHERE InstanceID like '%s'",
CP_SE_STORAGE_HARDWARE_ID, iniName);
CIMObjectPath queryClass = getQueryClass(CP_SE_STORAGE_HARDWARE_ID);
CIMObjectPath[] paths = execQuery(storageDevice, queryClass, wql, true);
if (paths.length == 0) {
continue;
}
initiatorToInitiatorPathMap.put(iniName, paths[0]);
}
return initiatorToInitiatorPathMap;
}
@Override
public CIMObjectPath getMaskingViewPath(StorageSystem storageDevice, String groupName) {
String wql = format("SELECT * FROM %s WHERE SystemName like '%s' AND DeviceID like '%s'",
prefixWithParamName(LUN_MASKING_VIEW), storageDevice.getSerialNumber(), groupName);
CIMObjectPath queryClass = getQueryClass(LUN_MASKING_VIEW);
CIMObjectPath[] paths = execQuery(storageDevice, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getLunMaskingProtocolControllerPath(StorageSystem storage, ExportMask exportMask) {
String wql = format("SELECT * FROM %s WHERE SystemName like '%s' AND DeviceID like '%s'",
prefixWithParamName(LUN_MASKING_SCSI_PROTOCOL_CONTROLLER), storage.getSerialNumber(), exportMask.getNativeId());
CIMObjectPath queryClass = getQueryClass(LUN_MASKING_SCSI_PROTOCOL_CONTROLLER);
CIMObjectPath[] paths = execQuery(storage, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getBlockObjectPath(StorageSystem storage, StorageSystem source, BlockObject blockObject) {
return null;
}
@Override
public CIMObjectPath getMaskingGroupPath(StorageSystem storage, String storageGroupName, MASKING_GROUP_TYPE se_deviceMaskingGroup)
throws Exception {
String wql = format("SELECT * FROM %s WHERE ElementName LIKE '%s'",
prefixWithParamName(se_deviceMaskingGroup.toString()), getSystemName(storage));
CIMObjectPath queryClass = getQueryClass(se_deviceMaskingGroup.toString());
CIMObjectPath[] paths = execQuery(storage, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getBlockObjectPath(StorageSystem storage, BlockObject blockObject) {
String[] properties = new String[] {
CP_CREATION_CLASS_NAME, CP_DEVICE_ID, CP_SYSTEM_CREATION_CLASS_NAME, CP_SYSTEM_NAME
};
String wql = format("SELECT %s FROM %s WHERE %s = '%s' AND %s = '%s'",
Joiner.on(',').join(properties),
prefixWithParamName(STORAGE_VOLUME),
CP_SYSTEM_NAME,
getSystemName(storage),
CP_DEVICE_ID,
blockObject.getNativeId());
CIMObjectPath queryClass = getQueryClass(STORAGE_VOLUME);
CIMObjectPath[] paths = execQuery(storage, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getVolumePath(StorageSystem storage, String nativeId) {
String wql = format("SELECT Name FROM %s WHERE SystemName = '%s' AND DeviceID = '%s'",
prefixWithParamName(STORAGE_VOLUME), getSystemName(storage), nativeId);
CIMObjectPath queryClass = getQueryClass(STORAGE_VOLUME);
CIMObjectPath[] volumePath = execQuery(storage, queryClass, wql);
if (volumePath.length == 0) {
return null;
}
return volumePath[0];
}
@Override
public CIMObjectPath getReplicationGroupPath(StorageSystem storage, String groupName) {
return getReplicationGroupPath(storage, storage.getSerialNumber(), groupName);
}
@Override
public CIMObjectPath getReplicationGroupPath(StorageSystem activeProviderStorageProxy, String serialNumber, String groupName) {
String wql = format("SELECT * FROM %s WHERE InstanceID like '%s' AND ElementName = '%s'",
SE_REPLICATION_GROUP, serialNumber, groupName);
CIMObjectPath queryClass = getQueryClass(SE_REPLICATION_GROUP);
CIMObjectPath[] paths = execQuery(activeProviderStorageProxy, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getReplicationGroupObjectPath(StorageSystem storage, String instanceId) {
// -+1 format is not available for rep groups in 8.0.3
return cimAdapter.getReplicationGroupPath(storage, instanceId);
}
@Override
public CIMObjectPath getSyncAspectPath(StorageSystem storage, String aspectInstanceId) {
String syncAspectPathStr = storage.checkIfVmax3() ? SYMM_SYNCHRONIZATION_ASPECT_FOR_SOURCE : CLAR_SYNCHRONIZATION_ASPECT_FOR_SOURCE;
String wql1 = format("SELECT * FROM %s WHERE InstanceID like '%s' AND InstanceID like '%s'",
syncAspectPathStr, aspectInstanceId, storage.getSerialNumber());
// TODO instanceID is stored in DB, so ideally this should work for V3
// REVIST : This class is not found for V2.
CIMObjectPath queryClass = getQueryClass(syncAspectPathStr);
CIMObjectPath[] paths = execQuery(storage, queryClass, wql1);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getStoragePoolPath(StorageSystem storage, StoragePool storagePool) {
String wql = format("SELECT * FROM %s WHERE InstanceID like '%s' AND InstanceID like '%s'",
storagePool.getPoolClassName(), storagePool.getPoolName(), storage.getSerialNumber());
CIMObjectPath queryClass = getQueryClass(storagePool.getPoolClassName());
CIMObjectPath[] paths = execQuery(storage, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getPoolSettingPath(StorageSystem storage, String poolSettingID) {
String wql = format("SELECT * FROM %s WHERE InstanceID like '%s' AND InstanceID like '%s'",
CLAR_STORAGE_POOL_SETTING, poolSettingID, storage.getSerialNumber());
CIMObjectPath queryClass = getQueryClass(CLAR_STORAGE_POOL_SETTING);
CIMObjectPath[] paths = execQuery(storage, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getSyncSettingsPath(StorageSystem storage, CIMObjectPath volumePath, String aspectInstanceId) {
return null;
}
@Override
public CIMObjectPath getGroupSynchronizedPath(StorageSystem storage, String consistencyGroupName, String snapGroupName) {
return null;
}
@Override
public CIMObjectPath getSyncAspectForSourceGroupPath(StorageSystem storage, String aspectInstanceId) {
String wql = format("SELECT * FROM %s WHERE InstanceID like '%s' AND InstanceID like '%s'",
CLAR_SYNCHRONIZATION_ASPECT_FOR_SOURCE_GROUP, aspectInstanceId, storage.getSerialNumber());
CIMObjectPath queryClass = getQueryClass(CLAR_SYNCHRONIZATION_ASPECT_FOR_SOURCE_GROUP);
CIMObjectPath[] paths = execQuery(storage, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getGroupSynchronizedSettingsPath(StorageSystem storage, String groupName, String settingsInstance) {
return null;
}
@Override
public CIMObjectPath getStorageSystem(StorageSystem storage) {
String wql = format("SELECT * FROM %s WHERE SystemName like'%s'",
prefixWithParamName(STORAGE_SYSTEM), storage.getSerialNumber());
CIMObjectPath queryClass = getQueryClass(STORAGE_VOLUME);
CIMObjectPath[] paths = execQuery(storage, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public String getProcessorName(StorageSystem system, String processorName) {
return null;
}
@Override
public CIMObjectPath objectPath(String namespace, String name, CIMProperty[] keys) {
return null;
}
@Override
public CIMObjectPath objectPath(String instanceId) {
return null;
}
@Override
public CIMObjectPath getStorageHardwareIDManagementService(StorageSystem storage) {
String wql = format("SELECT * FROM %s WHERE SystemName like'%s' AND Name ='%s'",
prefixWithParamName(STORAGE_HARDWARE_ID_MGMT_SVC), storage.getSerialNumber(),
EMC_STORAGE_HARDWARE_ID_MANAGEMENT_SERVICE);
CIMObjectPath queryClass = getQueryClass(STORAGE_HARDWARE_ID_MGMT_SVC);
CIMObjectPath[] paths = execQuery(storage, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMObjectPath getPrivilegeManagementService(StorageSystem storage) {
String wql = format("SELECT * FROM %s WHERE SystemName like'%s' AND Name ='%s'",
prefixWithParamName(CP_CLAR_PRIVILEGE_MGMT_SVC), storage.getSerialNumber(),
EMC_PRIVILEGE_MANAGEMENT_SERVICE);
CIMObjectPath queryClass = getQueryClass(CP_CLAR_PRIVILEGE_MGMT_SVC);
CIMObjectPath[] paths = execQuery(storage, queryClass, wql);
if (paths.length == 0) {
return null;
}
return paths[0];
}
@Override
public CIMInstance getStoragePoolVdevSettings(CIMObjectPath setting) {
return null;
}
@Override
public CIMObjectPath getRemoteReplicationCollection(StorageSystem system, RemoteDirectorGroup group) {
// TODO SRDF chek with Selva, whether he has done any changes.
return null;
}
@Override
public CIMObjectPath getReplicationSettingObjectPathFromDefault(CIMInstance settingInstance) {
// NO change needed only for V3.
return null;
}
private WBEMClient getClient(StorageSystem storageSystem) {
CimConnection connection = cimConnectionFactory.getConnection(storageSystem);
return connection.getCimClient();
}
private CIMObjectPath getQueryClass(String className) {
return new CIMObjectPath(null, null, null, ROOT_EMC_NAMESPACE, prefixWithParamName(className), null);
}
private CIMObjectPath[] execQuery(StorageSystem storageDevice, CIMObjectPath queryClass, String wql) {
log.info("ExecQuery: {}", wql);
CloseableIterator<CIMInstance> instances = null;
try {
long start = System.currentTimeMillis();
instances = getClient(storageDevice).execQuery(queryClass, wql, QUERY_LANG);
log.info("ExecQuery took {}ms", System.currentTimeMillis() - start);
Iterator<CIMObjectPath> transform = transform(instances, getInstanceToObjectPathFn());
return toArray(transform, CIMObjectPath.class);
} catch (WBEMException e) {
log.warn("Failed to perform SMI-S query: {}", wql, e);
} finally {
if (instances != null) {
instances.close();
}
}
return new CIMObjectPath[0];
}
/**
* Overloaded method to execute query and throw exception to caller method if any exception occurred.
*
* @param storageDevice
* @param queryClass
* @param wql
* @param throwException
* @return
* @throws WBEMException
*/
private CIMObjectPath[] execQuery(StorageSystem storageDevice, CIMObjectPath queryClass, String wql, boolean throwException)
throws WBEMException {
log.info("ExecQuery: {}", wql);
CloseableIterator<CIMInstance> instances = null;
try {
long start = System.currentTimeMillis();
instances = getClient(storageDevice).execQuery(queryClass, wql, QUERY_LANG);
log.info("ExecQuery took {}ms", System.currentTimeMillis() - start);
Iterator<CIMObjectPath> transform = transform(instances, getInstanceToObjectPathFn());
return toArray(transform, CIMObjectPath.class);
} catch (WBEMException e) {
log.warn("Failed to perform SMI-S query: {}", wql, e);
if (throwException) {
throw e;
}
} finally {
if (instances != null) {
instances.close();
}
}
return new CIMObjectPath[0];
}
private Function<CIMInstance, CIMObjectPath> getInstanceToObjectPathFn() {
return new Function<CIMInstance, CIMObjectPath>() {
@Override
public CIMObjectPath apply(CIMInstance instance) {
return instance.getObjectPath();
}
};
}
}