/* * Copyright (c) 2016 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.validators.smis.vmax; import com.emc.storageos.db.client.model.DataObject; import com.emc.storageos.db.client.model.ExportMask; import com.emc.storageos.db.client.model.StorageSystem; import com.emc.storageos.volumecontroller.impl.smis.SmisConstants; import com.emc.storageos.volumecontroller.impl.validators.ValidatorLogger; import com.emc.storageos.volumecontroller.impl.validators.smis.AbstractSMISValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.cim.CIMInstance; import javax.cim.CIMObjectPath; import javax.wbem.CloseableIterator; import javax.wbem.WBEMException; import java.util.Collection; /** * Abstract template class for validating that a resource has only associated masking views that are * managed by ViPR. */ abstract class AbstractMultipleVmaxMaskValidator<T extends DataObject> extends AbstractSMISValidator { private static final Logger log = LoggerFactory.getLogger(AbstractMultipleVmaxMaskValidator.class); protected StorageSystem storage; protected ExportMask exportMask; protected Collection<T> dataObjects; /** * Default constructor. * * @param storage StorageSystem * @param exportMask ExportMask * @param dataObjects List of dataObjects to check. * May be null, in which case all user added volumes from {@code exportMask} is used. */ AbstractMultipleVmaxMaskValidator(StorageSystem storage, ExportMask exportMask, Collection<T> dataObjects) { this.storage = storage; this.exportMask = exportMask; this.dataObjects = dataObjects; } /** * Validate that for each {@code DataObject}, any associated {@code Symm_LunMaskingView} instances * from {@code storage} are managed by ViPR. * * @return true - errors are logged by the shared {@link ValidatorLogger} * @throws Exception on provider connection failures. */ @Override public boolean validate() throws Exception { // Check for each resource, that only known masks are found to be associated with it on the array for (T dataObject : getDataObjects()) { CIMObjectPath path = getCIMObjectPath(dataObject); if (path == null || getHelper().checkExists(storage, path, false, false) == null) { log.warn("No CIM object path exists for {}", dataObject.getId()); continue; } String friendlyId = getFriendlyId(dataObject); CIMObjectPath mvPath = getCimPath().getMaskingViewPath(storage, exportMask.getMaskName()); CIMInstance mvInstance = getHelper().getInstance(storage, mvPath, false, false, null); CloseableIterator<CIMInstance> assocMasks = null; try { assocMasks = getHelper().getAssociatorInstances(storage, path, null, SmisConstants.SYMM_LUNMASKINGVIEW, null, null, null); while (assocMasks.hasNext()) { CIMInstance assocMask = assocMasks.next(); String name = (String) assocMask.getPropertyValue(SmisConstants.CP_DEVICE_ID); String systemName = (String) assocMask.getPropertyValue(SmisConstants.CP_SYSTEM_NAME); if (exportMask.getMaskName().equals(name) || !systemName.contains(storage.getSerialNumber())) { continue; } log.info("{} has associated mask {}", friendlyId, name); if (!validate(dataObject, mvInstance, assocMask)) { // This will cause DefaultValidator or ChainValidator to throw an exception. getLogger().logDiff(friendlyId, "<associated masks>", exportMask.getMaskName(), name); } } } finally { if (assocMasks != null) { assocMasks.close(); } } } return true; } /** * Compare and validate {@code mask} and {@code assocMask}. * * @param dataObject The DataObject to validate * @param mask The export mask in the ViPR request * @param assocMask An export mask found to be associated with {@code mask}. * @return True if validation passed, false otherwise. */ protected abstract boolean validate(T dataObject, CIMInstance mask, CIMInstance assocMask) throws WBEMException; /** * Returns a friendly ID string for the given {@code dataObject}. * * @param dataObject DataObject * @return A friendly ID */ protected abstract String getFriendlyId(T dataObject); /** * Returns a {@link CIMObjectPath} instance representing the {@link DataObject} * on the SMI-S provider. * * @param obj DataObject * @return CIMObjectPath or null, if no representation is found * @throws Exception on provider connection failures. */ protected abstract CIMObjectPath getCIMObjectPath(T obj) throws Exception; /** * Return a collection of {@link DataObject} based on what was passed into the constructor. * If null was passed in, then this method would be expected to look at the {@link ExportMask} * for objects to return. * * @return Collection of DataObject */ protected abstract Collection<T> getDataObjects(); }