/* * Copyright (c) 2016 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.validators.smis; import static com.emc.storageos.db.client.util.CommonTransformerFunctions.fctnDataObjectToForDisplay; import static com.google.common.collect.Collections2.transform; import java.net.URI; import java.util.Collection; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.BlockObject; import com.emc.storageos.db.client.model.BlockSnapshot; import com.emc.storageos.db.client.model.ExportMask; import com.emc.storageos.db.client.model.Initiator; import com.emc.storageos.db.client.model.StorageSystem; import com.emc.storageos.db.client.model.Volume; import com.emc.storageos.volumecontroller.impl.smis.CIMObjectPathFactory; import com.emc.storageos.volumecontroller.impl.smis.SmisCommandHelper; import com.emc.storageos.volumecontroller.impl.utils.ExportMaskUtils; import com.emc.storageos.volumecontroller.impl.validators.ChainingValidator; import com.emc.storageos.volumecontroller.impl.validators.DefaultValidator; import com.emc.storageos.volumecontroller.impl.validators.StorageSystemValidatorFactory; import com.emc.storageos.volumecontroller.impl.validators.ValCk; import com.emc.storageos.volumecontroller.impl.validators.Validator; import com.emc.storageos.volumecontroller.impl.validators.ValidatorConfig; import com.emc.storageos.volumecontroller.impl.validators.ValidatorLogger; import com.emc.storageos.volumecontroller.impl.validators.contexts.ExportMaskValidationContext; import com.emc.storageos.volumecontroller.impl.validators.smis.vmax.ValidateVolumeIdentity; import com.google.common.base.Joiner; import com.google.common.collect.Lists; /** * Abstract factory class for creating SMI-S related validators. The sub-classes should create the {@link ValidatorLogger} and * {@link AbstractSMISValidator} instances. * The theme for each factory method is to use the {@link ValidatorLogger} instance to share with the {@link Validator} * instances. Each validator can use this logger to report validation failures. * {@link DefaultValidator} and {@link ChainingValidator} will throw an exception if the logger * holds any errors. * **/ public abstract class AbstractSMISValidatorFactory implements StorageSystemValidatorFactory { private static final Logger _log = LoggerFactory.getLogger(AbstractSMISValidatorFactory.class); private ValidatorConfig config; private DbClient dbClient; private CIMObjectPathFactory cimPath; private SmisCommandHelper helper; protected static final AbstractSMISValidator truthyValidator = new AbstractSMISValidator() { @Override public boolean validate() throws Exception { return true; } }; public ValidatorConfig getConfig() { return config; } public void setConfig(ValidatorConfig config) { this.config = config; } public DbClient getDbClient() { return dbClient; } public void setDbClient(DbClient dbClient) { this.dbClient = dbClient; } public CIMObjectPathFactory getCimPath() { return cimPath; } public void setCimPath(CIMObjectPathFactory cimPath) { this.cimPath = cimPath; } public SmisCommandHelper getHelper() { return helper; } public void setHelper(SmisCommandHelper helper) { this.helper = helper; } /** * Allow subclasses to provide a Validator for export mask volumes. * * @param ctx ExportMaskValidationContext * @return AbstractSMISValidator */ public abstract AbstractSMISValidator createExportMaskVolumesValidator(ExportMaskValidationContext ctx); /** * Allow subclasses to provide a Validator for export mask initiators. * * @param ctx ExportMaskValidationContext * @return AbstractSMISValidator */ public abstract AbstractSMISValidator createExportMaskInitiatorValidator(ExportMaskValidationContext ctx); /** * Default implementation returns a validator that always passes. * * @param ctx ExportMaskValidationContext * @return AbstractSMISValidator */ public AbstractSMISValidator createMultipleExportMasksForBlockObjectsValidator(ExportMaskValidationContext ctx) { return truthyValidator; } /** * Default implementation returns a validator that always passes. * * @param ctx ExportMaskValidationContext * @return AbstractSMISValidator */ public AbstractSMISValidator createMultipleExportMasksForInitiatorsValidator(ExportMaskValidationContext ctx) { return truthyValidator; } /** * Allow subclasses to return a {@link ValidatorLogger} * * @return ValidatorLogger */ public abstract ValidatorLogger createValidatorLogger(String validatedObjectName, String storageSystemName); @Override public Validator exportMaskDelete(ExportMaskValidationContext ctx) { ValidatorLogger sharedLogger = createValidatorLogger(ctx.getExportMask().forDisplay(), ctx.getStorage().forDisplay()); AbstractSMISValidator volumes = createExportMaskVolumesValidator(ctx); AbstractSMISValidator initiators = createExportMaskInitiatorValidator(ctx); AbstractSMISValidator multiMaskBlockObjects = createMultipleExportMasksForBlockObjectsValidator(ctx); configureValidators(sharedLogger, volumes, initiators, multiMaskBlockObjects); ChainingValidator chain = new ChainingValidator(sharedLogger, config, "Export Mask"); chain.setExceptionContext(ctx); chain.addValidator(volumes); chain.addValidator(initiators); chain.addValidator(multiMaskBlockObjects); return chain; } @Override public Validator removeVolumes(ExportMaskValidationContext ctx) { ValidatorLogger sharedLogger = createValidatorLogger(ctx.getExportMask().forDisplay(), ctx.getStorage().forDisplay()); AbstractSMISValidator initiatorValidator = createExportMaskInitiatorValidator(ctx); AbstractSMISValidator maskValidator = createMultipleExportMasksForBlockObjectsValidator(ctx); configureValidators(sharedLogger, initiatorValidator, maskValidator); ChainingValidator chain = new ChainingValidator(sharedLogger, config, "Export Mask"); chain.setExceptionContext(ctx); chain.addValidator(initiatorValidator); chain.addValidator(maskValidator); return chain; } @Override public Validator removeInitiators(ExportMaskValidationContext ctx) { ValidatorLogger sharedLogger = createValidatorLogger(ctx.getExportMask().forDisplay(), ctx.getStorage().forDisplay()); AbstractSMISValidator volValidator = createExportMaskVolumesValidator(ctx); AbstractSMISValidator initsValidator = createMultipleExportMasksForInitiatorsValidator(ctx); configureValidators(sharedLogger, volValidator, initsValidator); ChainingValidator chain = new ChainingValidator(sharedLogger, config, "Export Mask"); chain.setExceptionContext(ctx); chain.addValidator(volValidator); chain.addValidator(initsValidator); return chain; } @Override public Validator deleteVolumes(StorageSystem storage, Collection<Volume> volumes) { // Generate a friendly volume list for volume validation Collection<String> volNames = transform(volumes, fctnDataObjectToForDisplay()); ValidatorLogger sharedLogger = createValidatorLogger(Joiner.on(",").join(volNames), storage.forDisplay()); AbstractSMISValidator identity = new ValidateVolumeIdentity(storage, volumes); configureValidators(sharedLogger, identity); return new DefaultValidator(identity, config, sharedLogger, ValidatorLogger.VOLUME_TYPE); } @Override public List<Volume> volumes(StorageSystem storageSystem, List<Volume> volumes, boolean delete, boolean remediate, ValCk[] checks) { return null; } @Override public Validator expandVolumes(StorageSystem storage, Volume volume) { ValidatorLogger sharedLogger = createValidatorLogger(volume.forDisplay(), storage.forDisplay()); AbstractSMISValidator identity = new ValidateVolumeIdentity(storage, Lists.newArrayList(volume)); configureValidators(sharedLogger, identity); return new DefaultValidator(identity, config, sharedLogger, ValidatorLogger.VOLUME_TYPE); } @Override public Validator createSnapshot(StorageSystem storage, BlockSnapshot snapshot, Volume volume) { ValidatorLogger sharedLogger = createValidatorLogger(volume.forDisplay(), storage.forDisplay()); AbstractSMISValidator identity = new ValidateVolumeIdentity(storage, Lists.newArrayList(volume)); configureValidators(sharedLogger, identity); return new DefaultValidator(identity, config, sharedLogger, ValidatorLogger.VOLUME_TYPE); } /** * Common configuration for VMAX validators to keep things DRY. * * @param logger ValidatorLogger * @param validators List of AbstractSMISValidator instances */ private void configureValidators(ValidatorLogger logger, AbstractSMISValidator... validators) { EMCRefreshSystemInvoker emcRefreshSystem = new OneTimeEMCRefreshSystem(helper); for (AbstractSMISValidator validator : validators) { validator.setFactory(this); validator.setLogger(logger); validator.setEmcRefreshSystemInvoker(emcRefreshSystem); } } /** * Determines if it should perform initiator validation, given the export mask. * * @param exportMask * export mask * @return true if validation should be performed, false otherwise */ protected boolean performInitiatorValidation(ExportMask exportMask) { // Don't validate against backing masks or RP if we're validating initiators. if (ExportMaskUtils.isBackendExportMask(getDbClient(), exportMask)) { _log.info("validation against backing mask for VPLEX or RP is disabled."); return false; } return true; } @Override public Validator addVolumes(StorageSystem storage, URI exportMaskURI, Collection<Initiator> initiators) { // TODO Auto-generated method stub return null; } @Override public Validator addInitiators(StorageSystem storage, ExportMask exportMask, Collection<URI> volumeURIList) { // TODO Auto-generated method stub return null; } }