@Override public void removeInitiator( StorageSystem storage, URI exportMaskId, List<Initiator> initiators, List<URI> targets, TaskCompleter taskCompleter) throws DeviceControllerException { log.info("{} removeInitiator START...", storage.getSerialNumber()); log.info("Export mask id: {}", exportMaskId); log.info("removeInitiator: initiators : {}", initiators); log.info("removeInitiator: targets : {}", targets); try { ExportMask exportMask = dbClient.queryObject(ExportMask.class, exportMaskId); List<Volume> volumeList = new ArrayList<Volume>(); StringMap volumes = exportMask.getUserAddedVolumes(); for (String vol : volumes.values()) { Volume volume = dbClient.queryObject(Volume.class, URI.create(vol)); volumeList.add(volume); } detachVolumesFromInitiators(storage, volumeList, initiators); taskCompleter.ready(dbClient); } catch (final Exception ex) { log.error("Problem in RemoveInitiators: ", ex); ServiceError serviceError = DeviceControllerErrors.cinder.operationFailed("doRemoveInitiators", ex.getMessage()); taskCompleter.error(dbClient, serviceError); } log.info("{} removeInitiator END...", storage.getSerialNumber()); }
@Override public void addVolume( StorageSystem storage, URI exportMaskId, VolumeURIHLU[] volumeURIHLUs, TaskCompleter taskCompleter) throws DeviceControllerException { log.info("{} addVolume START...", storage.getSerialNumber()); log.info("Export mask id: {}", exportMaskId); log.info("addVolume: volume-HLU pairs: {}", volumeURIHLUs); log.info("User assigned HLUs will be ignored as Cinder does not support it."); try { ExportMask exportMask = dbClient.queryObject(ExportMask.class, exportMaskId); List<Volume> volumes = new ArrayList<Volume>(); List<Initiator> initiatorList = new ArrayList<Initiator>(); // map to store target LUN id generated for each volume Map<URI, Integer> volumeToTargetLunMap = new HashMap<URI, Integer>(); StringMap initiators = exportMask.getUserAddedInitiators(); for (VolumeURIHLU volumeURIHLU : volumeURIHLUs) { URI volumeURI = volumeURIHLU.getVolumeURI(); Volume volume = dbClient.queryObject(Volume.class, volumeURI); volumes.add(volume); } for (String ini : initiators.values()) { Initiator initiator = dbClient.queryObject(Initiator.class, URI.create(ini)); initiatorList.add(initiator); } // Map to store volume to initiatorTargetMap Map<Volume, Map<String, List<String>>> volumeToFCInitiatorTargetMap = new HashMap<Volume, Map<String, List<String>>>(); attachVolumesToInitiators( storage, volumes, initiatorList, volumeToTargetLunMap, volumeToFCInitiatorTargetMap, exportMask); // Update targets in the export mask if (!volumeToFCInitiatorTargetMap.isEmpty()) { updateTargetsInExportMask( storage, volumes.get(0), volumeToFCInitiatorTargetMap, initiatorList, exportMask); } updateTargetLunIdInExportMask(volumeToTargetLunMap, exportMask); dbClient.updateAndReindexObject(exportMask); taskCompleter.ready(dbClient); } catch (final Exception ex) { log.error("Problem in AddVolumes: ", ex); ServiceError serviceError = DeviceControllerErrors.cinder.operationFailed("doAddVolumes", ex.getMessage()); taskCompleter.error(dbClient, serviceError); } log.info("{} addVolume END...", storage.getSerialNumber()); }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doExportRemoveVolumes(com.emc.storageos.db.client.model.StorageSystem, * com.emc.storageos.db.client.model.ExportMask, java.util.List, com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void doExportRemoveVolumes( StorageSystem storage, ExportMask exportMask, List<URI> volumes, TaskCompleter taskCompleter) throws DeviceControllerException { log.info("{} doExportRemoveVolume START ...", storage.getSerialNumber()); exportMaskOperationsHelper.removeVolume(storage, exportMask.getId(), volumes, taskCompleter); log.info("{} doExportRemoveVolume END ...", storage.getSerialNumber()); }
@Override public void addInitiator( StorageSystem storage, URI exportMaskId, List<Initiator> initiators, List<URI> targets, TaskCompleter taskCompleter) throws DeviceControllerException { log.info("{} addInitiator START...", storage.getSerialNumber()); log.info("Export mask id: {}", exportMaskId); log.info("addInitiator: initiators : {}", initiators); log.info("addInitiator: targets : {}", targets); try { ExportMask exportMask = dbClient.queryObject(ExportMask.class, exportMaskId); List<Volume> volumeList = new ArrayList<Volume>(); // map to store target LUN id generated for each volume Map<URI, Integer> volumeToTargetLunMap = new HashMap<URI, Integer>(); StringMap volumes = exportMask.getUserAddedVolumes(); for (String vol : volumes.values()) { Volume volume = dbClient.queryObject(Volume.class, URI.create(vol)); volumeList.add(volume); } // Map to store volume to initiatorTargetMap Map<Volume, Map<String, List<String>>> volumeToFCInitiatorTargetMap = new HashMap<Volume, Map<String, List<String>>>(); attachVolumesToInitiators( storage, volumeList, initiators, volumeToTargetLunMap, volumeToFCInitiatorTargetMap, exportMask); // Update targets in the export mask if (!volumeToFCInitiatorTargetMap.isEmpty()) { updateTargetsInExportMask( storage, volumeList.get(0), volumeToFCInitiatorTargetMap, initiators, exportMask); dbClient.updateAndReindexObject(exportMask); } // TODO : update volumeToTargetLunMap in export mask.? // Do we get different LUN ID for the new initiators from the same Host.? taskCompleter.ready(dbClient); } catch (final Exception ex) { log.error("Problem in AddInitiators: ", ex); ServiceError serviceError = DeviceControllerErrors.cinder.operationFailed("doAddInitiators", ex.getMessage()); taskCompleter.error(dbClient, serviceError); } log.info("{} addInitiator END...", storage.getSerialNumber()); }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doExpandVolume(com.emc.storageos.db.client.model.StorageSystem, * com.emc.storageos.db.client.model.StoragePool, com.emc.storageos.db.client.model.Volume, java.lang.Long, * com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void doExpandVolume( StorageSystem storageSystem, StoragePool storagePool, Volume volume, Long size, TaskCompleter taskCompleter) throws DeviceControllerException { log.info( String.format( "Expand Volume Start - Array: %s, Pool: %s, Volume: %s, New size: %d", storageSystem.getSerialNumber(), storagePool.getNativeGuid(), volume.getLabel(), size)); try { HDSApiClient hdsApiClient = hdsApiFactory.getClient( HDSUtils.getHDSServerManagementServerInfo(storageSystem), storageSystem.getSmisUserName(), storageSystem.getSmisPassword()); String systemObjectID = HDSUtils.getSystemObjectID(storageSystem); String asyncTaskMessageId = null; if (volume.getThinlyProvisioned()) { asyncTaskMessageId = hdsApiClient.modifyThinVolume( systemObjectID, HDSUtils.getLogicalUnitObjectId(volume.getNativeId(), storageSystem), size); } if (null != asyncTaskMessageId) { HDSJob expandVolumeJob = new HDSVolumeExpandJob( asyncTaskMessageId, storageSystem.getId(), storagePool.getId(), taskCompleter, "ExpandVolume"); ControllerServiceImpl.enqueueJob(new QueueJob(expandVolumeJob)); } } catch (final InternalException e) { log.error("Problem in doExpandVolume: ", e); taskCompleter.error(dbClient, e); } catch (final Exception e) { log.error("Problem in doExpandVolume: ", e); ServiceError serviceError = DeviceControllerErrors.hds.methodFailed("doExpandVolume", e.getMessage()); taskCompleter.error(dbClient, serviceError); } log.info( String.format( "Expand Volume End - Array: %s, Pool: %s, Volume: %s", storageSystem.getSerialNumber(), storagePool.getNativeGuid(), volume.getLabel())); }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doExportAddInitiator(com.emc.storageos.db.client.model.StorageSystem, * com.emc.storageos.db.client.model.ExportMask, com.emc.storageos.db.client.model.Initiator, java.util.List, * com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void doExportAddInitiator( StorageSystem storage, ExportMask exportMask, Initiator initiator, List<URI> targets, TaskCompleter taskCompleter) throws DeviceControllerException { log.info("{} doExportAddInitiator START ...", storage.getSerialNumber()); exportMaskOperationsHelper.addInitiator( storage, exportMask.getId(), Arrays.asList(initiator), targets, taskCompleter); log.info("{} doExportAddInitiator END ...", storage.getSerialNumber()); }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doExportRemoveInitiators(com.emc.storageos.db.client.model.StorageSystem, * com.emc.storageos.db.client.model.ExportMask, java.util.List, java.util.List, com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void doExportRemoveInitiators( StorageSystem storage, ExportMask exportMask, List<Initiator> initiators, List<URI> targets, TaskCompleter taskCompleter) throws DeviceControllerException { log.info("{} doExportRemoveInitiator START ...", storage.getSerialNumber()); exportMaskOperationsHelper.removeInitiator( storage, exportMask.getId(), initiators, targets, taskCompleter); log.info("{} doExportRemoveInitiator END ...", storage.getSerialNumber()); }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doExportGroupDelete(com.emc.storageos.db.client.model.StorageSystem, * com.emc.storageos.db.client.model.ExportMask, com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void doExportGroupDelete( StorageSystem storage, ExportMask exportMask, TaskCompleter taskCompleter) throws DeviceControllerException { log.info("{} doExportGroupDelete START ...", storage.getSerialNumber()); exportMaskOperationsHelper.deleteExportMask( storage, exportMask.getId(), new ArrayList<URI>(), new ArrayList<URI>(), new ArrayList<Initiator>(), taskCompleter); log.info("{} doExportGroupDelete END ...", storage.getSerialNumber()); }
@Override public void deleteExportMask( StorageSystem storage, URI exportMaskId, List<URI> volumeURIList, List<URI> targetURIList, List<Initiator> initiatorList, TaskCompleter taskCompleter) throws DeviceControllerException { log.info("{} deleteExportMask START...", storage.getSerialNumber()); log.info("Export mask id: {}", exportMaskId); try { // There is no masking concept on Cinder to delete the export mask. // But before marking the task completer as ready, // detach the volumes from the initiators that are there in the export mask. ExportMask exportMask = dbClient.queryObject(ExportMask.class, exportMaskId); List<Volume> volumeList = new ArrayList<Volume>(); StringMap volumes = exportMask.getUserAddedVolumes(); StringMap initiators = exportMask.getUserAddedInitiators(); if (volumes != null) { for (String vol : volumes.values()) { URI volumeURI = URI.create(vol); volumeURIList.add(volumeURI); Volume volume = dbClient.queryObject(Volume.class, volumeURI); volumeList.add(volume); } } if (initiators != null) { for (String ini : initiators.values()) { Initiator initiatorObj = dbClient.queryObject(Initiator.class, URI.create(ini)); initiatorList.add(initiatorObj); } } log.info("deleteExportMask: volumes: {}", volumeURIList); log.info("deleteExportMask: assignments: {}", targetURIList); log.info("deleteExportMask: initiators: {}", initiatorList); detachVolumesFromInitiators(storage, volumeList, initiatorList); taskCompleter.ready(dbClient); } catch (final Exception ex) { log.error("Problem in DetachVolumes: ", ex); ServiceError serviceError = DeviceControllerErrors.cinder.operationFailed("doDetachVolumes", ex.getMessage()); taskCompleter.error(dbClient, serviceError); } log.info("{} deleteExportMask END...", storage.getSerialNumber()); }
@Override public void doExportAddVolumes( StorageSystem storage, ExportMask exportMask, Map<URI, Integer> volumes, TaskCompleter taskCompleter) throws DeviceControllerException { log.info("{} doExportAddVolume START ...", storage.getSerialNumber()); VolumeURIHLU[] volumeLunArray = ControllerUtils.getVolumeURIHLUArray(storage.getSystemType(), volumes, dbClient); exportMaskOperationsHelper.addVolume( storage, exportMask.getId(), volumeLunArray, taskCompleter); log.info("{} doExportAddVolume END ...", storage.getSerialNumber()); }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doExportGroupCreate(com.emc.storageos.db.client.model.StorageSystem, * com.emc.storageos.db.client.model.ExportMask, java.util.Map, java.util.List, java.util.List, * com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void doExportGroupCreate( StorageSystem storage, ExportMask exportMask, Map<URI, Integer> volumeMap, List<Initiator> initiators, List<URI> targets, TaskCompleter taskCompleter) throws DeviceControllerException { log.info("{} doExportGroupCreate START ...", storage.getSerialNumber()); VolumeURIHLU[] volumeLunArray = ControllerUtils.getVolumeURIHLUArray(storage.getSystemType(), volumeMap, dbClient); exportMaskOperationsHelper.createExportMask( storage, exportMask.getId(), volumeLunArray, targets, initiators, taskCompleter); log.info("{} doExportGroupCreate END ...", storage.getSerialNumber()); }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doExpandAsMetaVolume(com.emc.storageos.db.client.model.StorageSystem, * com.emc.storageos.db.client.model.StoragePool, com.emc.storageos.db.client.model.Volume, long, * com.emc.storageos.volumecontroller.impl.smis.MetaVolumeRecommendation, com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void doExpandAsMetaVolume( StorageSystem storageSystem, StoragePool storagePool, Volume metaHead, long size, MetaVolumeRecommendation recommendation, VolumeExpandCompleter volumeCompleter) throws DeviceControllerException { StringBuilder logMsgBuilder = new StringBuilder( String.format( "Expand Meta Volume Start - Array:%s, Pool:%s %n Volume: %s, id: %s", storageSystem.getSerialNumber(), storagePool.getNativeId(), metaHead.getLabel(), metaHead.getId())); log.info(logMsgBuilder.toString()); long metaMemberCapacity = recommendation.getMetaMemberSize(); int metaMemberCount = (int) recommendation.getMetaMemberCount(); MetaVolumeTaskCompleter metaVolumeTaskCompleter = new MetaVolumeTaskCompleter(volumeCompleter); try { // Step 1: create meta members. List<String> newMetaMembers = metaVolumeOperations.createMetaVolumeMembers( storageSystem, storagePool, metaHead, metaMemberCount, metaMemberCapacity, metaVolumeTaskCompleter); log.info("ldevMetaMembers created successfully: {}", newMetaMembers); if (metaVolumeTaskCompleter.getLastStepStatus() == Job.JobStatus.SUCCESS) { metaVolumeOperations.expandMetaVolume( storageSystem, storagePool, metaHead, newMetaMembers, metaVolumeTaskCompleter); } else { ServiceError serviceError = DeviceControllerErrors.hds.jobFailed("LDEV Meta Member creation failed"); volumeCompleter.error(dbClient, serviceError); } } catch (final InternalException e) { log.error("Problem in doExpandAsMetaVolume: ", e); volumeCompleter.error(dbClient, e); } catch (final Exception e) { log.error("Problem in doExpandAsMetaVolume: ", e); ServiceError serviceError = DeviceControllerErrors.hds.methodFailed("doExpandAsMetaVolume", e.getMessage()); volumeCompleter.error(dbClient, serviceError); } }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doCleanupMetaMembers(com.emc.storageos.db.client.model.StorageSystem, * com.emc.storageos.db.client.model.Volume, * com.emc.storageos.volumecontroller.impl.block.taskcompleter.CleanupMetaVolumeMembersCompleter) */ @Override public void doCleanupMetaMembers( StorageSystem storageSystem, Volume volume, CleanupMetaVolumeMembersCompleter cleanupCompleter) throws DeviceControllerException { // Remove meta member volumes from storage device try { log.info( String.format( "doCleanupMetaMembers Start - Array: %s, Volume: %s", storageSystem.getSerialNumber(), volume.getLabel())); // Load meta volume members from WF data String sourceStepId = cleanupCompleter.getSourceStepId(); HDSApiClient hdsApiClient = hdsApiFactory.getClient( HDSUtils.getHDSServerManagementServerInfo(storageSystem), storageSystem.getUsername(), storageSystem.getSmisPassword()); List<String> metaMembers = (ArrayList<String>) WorkflowService.getInstance().loadStepData(sourceStepId); if (metaMembers != null && !metaMembers.isEmpty()) { log.info( String.format( "doCleanupMetaMembers: Members stored for meta volume: %n %s", metaMembers)); // Check if volumes still exist in array and if it is not composite member (already // added to the meta volume) Set<String> volumeIds = new HashSet<String>(); for (String logicalUnitObjectId : metaMembers) { LogicalUnit logicalUnit = hdsApiClient.getLogicalUnitInfo( HDSUtils.getSystemObjectID(storageSystem), logicalUnitObjectId); if (logicalUnit != null) { log.debug( "doCleanupMetaMembers: Volume: " + logicalUnitObjectId + ", Usage of volume: " + logicalUnit.getComposite()); if (logicalUnit.getComposite() != HDSConstants.COMPOSITE_ELEMENT_MEMBER) { volumeIds.add(logicalUnitObjectId); } } } if (volumeIds.isEmpty()) { cleanupCompleter.setSuccess(true); log.info("doCleanupMetaMembers: No meta members to cleanup in array."); } else { log.info( String.format( "doCleanupMetaMembers: Members to cleanup in array: %n %s", volumeIds)); // Prepare parameters and call method to delete meta members from array HDSCleanupMetaVolumeMembersJob hdsJobCompleter = null; // When "cleanup" is separate workflow step, call async (for example rollback // step in volume expand) // Otherwise, call synchronously (for example when cleanup is part of meta // volume create rollback) String asyncMessageId = hdsApiClient.deleteThickLogicalUnits( HDSUtils.getSystemObjectID(storageSystem), volumeIds); if (cleanupCompleter.isWFStep()) { if (asyncMessageId != null) { ControllerServiceImpl.enqueueJob( new QueueJob( new HDSCleanupMetaVolumeMembersJob( asyncMessageId, storageSystem.getId(), volume.getId(), cleanupCompleter))); } } else { // invoke synchronously hdsJobCompleter = new HDSCleanupMetaVolumeMembersJob( asyncMessageId, storageSystem.getId(), volume.getId(), cleanupCompleter); ((HDSMetaVolumeOperations) metaVolumeOperations) .invokeMethodSynchronously(hdsApiFactory, asyncMessageId, hdsJobCompleter); } } } else { log.info( "doCleanupMetaMembers: No meta members stored for meta volume. Nothing to cleanup in array."); cleanupCompleter.setSuccess(true); } } catch (Exception e) { log.error("Problem in doCleanupMetaMembers: ", e); ServiceError error = DeviceControllerErrors.smis.methodFailed("doCleanupMetaMembers", e.getMessage()); cleanupCompleter.setError(error); cleanupCompleter.setSuccess(false); } log.info( String.format( "doCleanupMetaMembers End - Array: %s, Volume: %s", storageSystem.getSerialNumber(), volume.getLabel())); }
/** {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public void processResult(Operation operation, Object resultObj, Map<String, Object> keyMap) throws BaseCollectionException { final Iterator<CIMInstance> it = (Iterator<CIMInstance>) resultObj; profile = (AccessProfile) keyMap.get(Constants.ACCESSPROFILE); try { _newPoolList = new ArrayList<StoragePool>(); _updatePoolList = new ArrayList<StoragePool>(); _dbClient = (DbClient) keyMap.get(Constants.dbClient); _cimClient = (WBEMClient) keyMap.get(Constants._cimClient); _coordinator = (CoordinatorClient) keyMap.get(Constants.COORDINATOR_CLIENT); _eventManager = (RecordableEventManager) keyMap.get(Constants.EVENT_MANAGER); _logger.info("StoragePoolProcessor --- event manager: " + _eventManager); StorageSystem device = getStorageSystem(_dbClient, profile.getSystemId()); if (SupportedProvisioningTypes.NONE .toString() .equalsIgnoreCase(device.getSupportedProvisioningType())) { _logger.info( "Storage System doesn't support volume creations :" + device.getSerialNumber()); return; } Set<String> protocols = (Set<String>) keyMap.get(Constants.PROTOCOLS); Map<URI, StoragePool> poolsToMatchWithVpool = (Map<URI, StoragePool>) keyMap.get(Constants.MODIFIED_STORAGEPOOLS); while (it.hasNext()) { CIMInstance poolInstance = null; try { poolInstance = it.next(); // Supporting both thick and thin pools String[] poolClassNameAndSupportedVolumeTypes = determinePoolClassNameAndSupportedVolumeTypes(poolInstance, device); if (null != poolClassNameAndSupportedVolumeTypes) { String instanceID = getCIMPropertyValue(poolInstance, Constants.INSTANCEID); addPath(keyMap, operation.getResult(), poolInstance.getObjectPath()); StoragePool pool = checkStoragePoolExistsInDB(getNativeIDFromInstance(instanceID), _dbClient, device); createStoragePool( pool, poolInstance, profile, poolClassNameAndSupportedVolumeTypes[0], poolClassNameAndSupportedVolumeTypes[1], protocols, poolsToMatchWithVpool, device); if (DiscoveredDataObject.Type.vnxblock .toString() .equalsIgnoreCase(device.getSystemType())) { addPath(keyMap, Constants.VNXPOOLS, poolInstance.getObjectPath()); } if (DiscoveredDataObject.Type.vmax .toString() .equalsIgnoreCase(device.getSystemType())) { addPath(keyMap, Constants.VMAXPOOLS, poolInstance.getObjectPath()); if (!device.checkIfVmax3()) { addPath(keyMap, Constants.VMAX2POOLS, poolInstance.getObjectPath()); } } // This approach deviates from the existing built plugin framework for plugin // Discovery // To follow the existing pattern, we need to have different SMI-S calls // 1st to get Device StoragePools alone ,and 2nd to get Thin Pools. // Its a tradeoff between whether to go with the current plugin design or // reduce the number of calls to SMI Provider. // I chose the 2nd option. if (!poolClassNameAndSupportedVolumeTypes[0].contains(DEVICE_STORAGE_POOL)) { addPath(keyMap, Constants.THINPOOLS, poolInstance.getObjectPath()); } addPath(keyMap, Constants.DEVICEANDTHINPOOLS, poolInstance.getObjectPath()); } else { _logger.debug( "Skipping Pools other than Unified & Virtual & Device : {}", poolInstance.getObjectPath().toString()); } } catch (Exception e) { _logger.warn( "StoragePool Discovery failed for {}", getCIMPropertyValue(poolInstance, Constants.INSTANCEID), e); } } _dbClient.createObject(_newPoolList); _dbClient.updateAndReindexObject(_updatePoolList); // find the pools not visible in this discovery List<StoragePool> discoveredPools = new ArrayList<StoragePool>(_newPoolList); discoveredPools.addAll(_updatePoolList); List<StoragePool> notVisiblePools = DiscoveryUtils.checkStoragePoolsNotVisible(discoveredPools, _dbClient, device.getId()); for (StoragePool notVisiblePool : notVisiblePools) { poolsToMatchWithVpool.put(notVisiblePool.getId(), notVisiblePool); } // If any storage ports on the storage system are in a transport // zone, there is an implicit connection to the transport zone // varray. We need to add these implicit varray // connections for the new storage pool. StoragePoolAssociationHelper.setStoragePoolVarrays(device.getId(), _newPoolList, _dbClient); } catch (Exception e) { _logger.error("StoragePool Discovery failed --> {}", getMessage(e)); } finally { _newPoolList = null; _updatePoolList = null; } }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doCreateVolumes(com.emc.storageos.db.client.model.StorageSystem, * com.emc.storageos.db.client.model.StoragePool, java.lang.String, java.util.List, * com.emc.storageos.volumecontroller.impl.utils.VirtualPoolCapabilityValuesWrapper, com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void doCreateVolumes( StorageSystem storageSystem, StoragePool storagePool, String opId, List<Volume> volumes, VirtualPoolCapabilityValuesWrapper capabilities, TaskCompleter taskCompleter) throws DeviceControllerException { String label = null; Long capacity = null; boolean isThinVolume = false; boolean opCreationFailed = false; StringBuilder logMsgBuilder = new StringBuilder( String.format( "Create Volume Start - Array:%s, Pool:%s", storageSystem.getSerialNumber(), storagePool.getNativeGuid())); for (Volume volume : volumes) { logMsgBuilder.append( String.format( "%nVolume:%s , IsThinlyProvisioned: %s", volume.getLabel(), volume.getThinlyProvisioned())); if ((label == null) && (volumes.size() == 1)) { String tenantName = ""; try { TenantOrg tenant = dbClient.queryObject(TenantOrg.class, volume.getTenant().getURI()); tenantName = tenant.getLabel(); } catch (DatabaseException e) { log.error("Error lookup TenantOrb object", e); } label = nameGenerator.generate( tenantName, volume.getLabel(), volume.getId().toString(), '-', HDSConstants.MAX_VOLUME_NAME_LENGTH); } if (capacity == null) { capacity = volume.getCapacity(); } isThinVolume = volume.getThinlyProvisioned(); } log.info(logMsgBuilder.toString()); try { multiVolumeCheckForHitachiModel(volumes, storageSystem); HDSApiClient hdsApiClient = hdsApiFactory.getClient( HDSUtils.getHDSServerManagementServerInfo(storageSystem), storageSystem.getSmisUserName(), storageSystem.getSmisPassword()); String systemObjectID = HDSUtils.getSystemObjectID(storageSystem); String poolObjectID = HDSUtils.getPoolObjectID(storagePool); String asyncTaskMessageId = null; // isThinVolume = true, creates VirtualVolumes // isThinVolume = false, creates LogicalUnits if (isThinVolume) { asyncTaskMessageId = hdsApiClient.createThinVolumes( systemObjectID, storagePool.getNativeId(), capacity, volumes.size(), label, QUICK_FORMAT_TYPE, storageSystem.getModel()); } else if (!isThinVolume) { asyncTaskMessageId = hdsApiClient.createThickVolumes( systemObjectID, poolObjectID, capacity, volumes.size(), label, null, storageSystem.getModel(), null); } if (asyncTaskMessageId != null) { HDSJob createHDSJob = (volumes.size() > 1) ? new HDSCreateMultiVolumeJob( asyncTaskMessageId, volumes.get(0).getStorageController(), storagePool.getId(), volumes.size(), taskCompleter) : new HDSCreateVolumeJob( asyncTaskMessageId, volumes.get(0).getStorageController(), storagePool.getId(), taskCompleter); ControllerServiceImpl.enqueueJob(new QueueJob(createHDSJob)); } } catch (final InternalException e) { log.error("Problem in doCreateVolumes: ", e); opCreationFailed = true; taskCompleter.error(dbClient, e); } catch (final Exception e) { log.error("Problem in doCreateVolumes: ", e); opCreationFailed = true; ServiceError serviceError = DeviceControllerErrors.hds.methodFailed("doCreateVolumes", e.getMessage()); taskCompleter.error(dbClient, serviceError); } if (opCreationFailed) { for (Volume vol : volumes) { vol.setInactive(true); dbClient.persistObject(vol); } } logMsgBuilder = new StringBuilder( String.format( "Create Volumes End - Array:%s, Pool:%s", storageSystem.getSerialNumber(), storagePool.getNativeGuid())); for (Volume volume : volumes) { logMsgBuilder.append(String.format("%nVolume:%s", volume.getLabel())); } log.info(logMsgBuilder.toString()); }
@Override public void doModifyVolumes( StorageSystem storage, StoragePool storagePool, String opId, List<Volume> volumes, TaskCompleter taskCompleter) throws DeviceControllerException { StringBuilder logMsgBuilder = new StringBuilder( String.format( "Modify Volume Start - Array:%s, Pool:%s", storage.getSerialNumber(), storagePool.getNativeGuid())); String systemObjectID = HDSUtils.getSystemObjectID(storage); for (Volume volume : volumes) { try { HDSApiClient hdsApiClient = hdsApiFactory.getClient( HDSUtils.getHDSServerManagementServerInfo(storage), storage.getSmisUserName(), storage.getSmisPassword()); logMsgBuilder.append( String.format( "%nVolume:%s , IsThinlyProvisioned: %s, tieringPolicy: %s", volume.getLabel(), volume.getThinlyProvisioned(), volume.getAutoTieringPolicyUri())); LogicalUnit logicalUnit = hdsApiClient.getLogicalUnitInfo( systemObjectID, HDSUtils.getLogicalUnitObjectId(volume.getNativeId(), storage)); String policyName = ControllerUtils.getAutoTieringPolicyName(volume.getId(), dbClient); String autoTierPolicyName = null; if (policyName.equals(Constants.NONE)) { autoTierPolicyName = null; } else { autoTierPolicyName = HitachiTieringPolicy.getPolicy( policyName.replaceAll( HDSConstants.SLASH_OPERATOR, HDSConstants.UNDERSCORE_OPERATOR)) .getKey(); } if (null != logicalUnit && null != logicalUnit.getLdevList() && !logicalUnit.getLdevList().isEmpty()) { Iterator<LDEV> ldevItr = logicalUnit.getLdevList().iterator(); if (ldevItr.hasNext()) { LDEV ldev = ldevItr.next(); String asyncMessageId = hdsApiClient.modifyThinVolumeTieringPolicy( systemObjectID, logicalUnit.getObjectID(), ldev.getObjectID(), autoTierPolicyName); if (null != asyncMessageId) { HDSJob modifyHDSJob = new HDSModifyVolumeJob( asyncMessageId, volume.getStorageController(), taskCompleter, HDSModifyVolumeJob.VOLUME_MODIFY_JOB); ControllerServiceImpl.enqueueJob(new QueueJob(modifyHDSJob)); } } } else { String errorMsg = String.format("No LDEV's found for volume: %s", volume.getId()); log.info(errorMsg); ServiceError serviceError = DeviceControllerErrors.hds.methodFailed("doModifyVolumes", errorMsg); taskCompleter.error(dbClient, serviceError); } } catch (final InternalException e) { log.error("Problem in doModifyVolumes: ", e); taskCompleter.error(dbClient, e); } catch (final Exception e) { log.error("Problem in doModifyVolumes: ", e); ServiceError serviceError = DeviceControllerErrors.hds.methodFailed("doModifyVolumes", e.getMessage()); taskCompleter.error(dbClient, serviceError); } } }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.BlockStorageDevice#doDeleteVolumes(com.emc.storageos.db.client.model.StorageSystem, * java.lang.String, java.util.List, com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void doDeleteVolumes( StorageSystem storageSystem, String opId, List<Volume> volumes, TaskCompleter taskCompleter) throws DeviceControllerException { try { StringBuilder logMsgBuilder = new StringBuilder( String.format("Delete Volume Start - Array:%s", storageSystem.getSerialNumber())); MultiVolumeTaskCompleter multiVolumeTaskCompleter = (MultiVolumeTaskCompleter) taskCompleter; Set<String> thickLogicalUnitIdList = new HashSet<String>(); Set<String> thinLogicalUnitIdList = new HashSet<String>(); HDSApiClient hdsApiClient = hdsApiFactory.getClient( HDSUtils.getHDSServerManagementServerInfo(storageSystem), storageSystem.getSmisUserName(), storageSystem.getSmisPassword()); String systemObjectId = HDSUtils.getSystemObjectID(storageSystem); log.info("volumes size: {}", volumes.size()); for (Volume volume : volumes) { logMsgBuilder.append(String.format("%nVolume:%s", volume.getLabel())); String logicalUnitObjectId = HDSUtils.getLogicalUnitObjectId(volume.getNativeId(), storageSystem); LogicalUnit logicalUnit = hdsApiClient.getLogicalUnitInfo(systemObjectId, logicalUnitObjectId); if (logicalUnit == null) { // related volume state (if any) has been deleted. skip // processing, if already deleted from array. log.info(String.format("Volume %s already deleted: ", volume.getNativeId())); volume.setInactive(true); dbClient.persistObject(volume); VolumeTaskCompleter deleteTaskCompleter = multiVolumeTaskCompleter.skipTaskCompleter(volume.getId()); deleteTaskCompleter.ready(dbClient); continue; } if (volume.getThinlyProvisioned()) { thinLogicalUnitIdList.add(logicalUnitObjectId); } else { thickLogicalUnitIdList.add(logicalUnitObjectId); } } log.info(logMsgBuilder.toString()); if (!multiVolumeTaskCompleter.isVolumeTaskCompletersEmpty()) { if (null != thickLogicalUnitIdList && !thickLogicalUnitIdList.isEmpty()) { String asyncThickLUsJobId = hdsApiClient.deleteThickLogicalUnits(systemObjectId, thickLogicalUnitIdList); if (null != asyncThickLUsJobId) { ControllerServiceImpl.enqueueJob( new QueueJob( new HDSDeleteVolumeJob( asyncThickLUsJobId, volumes.get(0).getStorageController(), taskCompleter))); } } if (null != thinLogicalUnitIdList && !thinLogicalUnitIdList.isEmpty()) { String asyncThinHDSJobId = hdsApiClient.deleteThinLogicalUnits(systemObjectId, thinLogicalUnitIdList); // Not sure whether this really works as tracking two jobs // in single operation. if (null != asyncThinHDSJobId) { ControllerServiceImpl.enqueueJob( new QueueJob( new HDSDeleteVolumeJob( asyncThinHDSJobId, volumes.get(0).getStorageController(), taskCompleter))); } } } else { // If we are here, there are no volumes to delete, we have // invoked ready() for the VolumeDeleteCompleter, and told // the multiVolumeTaskCompleter to skip these completers. // In this case, the multiVolumeTaskCompleter complete() // method will not be invoked and the result is that the // workflow that initiated this delete request will never // be updated. So, here we just call complete() on the // multiVolumeTaskCompleter to ensure the workflow status is // updated. multiVolumeTaskCompleter.ready(dbClient); } } catch (Exception e) { log.error("Problem in doDeleteVolume: ", e); ServiceError error = DeviceControllerErrors.hds.methodFailed("doDeleteVolume", e.getMessage()); taskCompleter.error(dbClient, error); } StringBuilder logMsgBuilder = new StringBuilder( String.format("Delete Volume End - Array: %s", storageSystem.getSerialNumber())); for (Volume volume : volumes) { logMsgBuilder.append(String.format("%nVolume:%s", volume.getLabel())); } log.info(logMsgBuilder.toString()); }