@Override public void process() { DbClient dbClient = getDbClient(); List<URI> volumeURIs = dbClient.queryByType(Volume.class, false); Iterator<Volume> volumesIter = dbClient.queryIterativeObjects(Volume.class, volumeURIs); while (volumesIter.hasNext()) { Volume volume = volumesIter.next(); URI systemURI = volume.getStorageController(); if (!NullColumnValueGetter.isNullURI(systemURI)) { StorageSystem system = dbClient.queryObject(StorageSystem.class, systemURI); if ((system != null) && (DiscoveredDataObject.Type.vplex.name().equals(system.getSystemType()))) { // This is a VPLEX volume. If not already set, // set the protocols to FC. StringSet protocols = volume.getProtocol(); if (protocols == null) { protocols = new StringSet(); protocols.add(StorageProtocol.Block.FC.name()); volume.setProtocol(protocols); dbClient.persistObject(volume); } } } } }
@Override protected void setProtocol(StoragePool pool, Volume volume, VirtualPool vPool) { if (null == volume.getProtocol()) { volume.setProtocol(new StringSet()); } volume.getProtocol().addAll(vPool.getProtocols()); }
/** {@inheritDoc} */ @Override public void validateSnapshotCreateRequest(Volume requestedVolume, List<Volume> volumesToSnap) { // For VMAX3 you cannot have active snap and full copy sessions, // so verify there are no active full copies for the volume. for (Volume volumeToSnap : volumesToSnap) { // Check if the volume to snap is an active full copy. if ((BlockFullCopyUtils.isVolumeFullCopy(volumeToSnap, _dbClient)) && (!BlockFullCopyUtils.isFullCopyDetached(volumeToSnap, _dbClient)) && (!BlockFullCopyUtils.isFullCopyInactive(volumeToSnap, _dbClient))) { throw APIException.badRequests.noSnapshotsForVMAX3VolumeWithActiveFullCopy(); } // Now check if the volume to be snapped is a full copy source // that has active full copies. StringSet fullCopyIds = volumeToSnap.getFullCopies(); if ((fullCopyIds != null) && (!fullCopyIds.isEmpty())) { Iterator<String> fullCopyIdsIter = fullCopyIds.iterator(); while (fullCopyIdsIter.hasNext()) { URI fullCopyURI = URI.create(fullCopyIdsIter.next()); Volume fullCopyVolume = _dbClient.queryObject(Volume.class, fullCopyURI); if ((fullCopyVolume != null) && (!fullCopyVolume.getInactive()) && (!BlockFullCopyUtils.isFullCopyDetached(fullCopyVolume, _dbClient)) && (!BlockFullCopyUtils.isFullCopyInactive(fullCopyVolume, _dbClient))) { throw APIException.badRequests.noSnapshotsForVMAX3VolumeWithActiveFullCopy(); } } } } }
/** * Validate the Target Volume VirtualArray with the Source Volume VPool VirtualArray. * * @param type * @param unManagedVolume * @param virtualArray */ private void validateTargetVolumeVpoolWithSourceVolume( UnManagedVolume unManagedVolume, VirtualArray virtualArray) { String sourceUnManagedVolumeId = PropertySetterUtil.extractValueFromStringSet( SupportedVolumeInformation.REMOTE_MIRROR_SOURCE_VOLUME.toString(), unManagedVolume.getVolumeInformation()); String sourceVolumeId = sourceUnManagedVolumeId.replace( VolumeIngestionUtil.UNMANAGEDVOLUME, VolumeIngestionUtil.VOLUME); List<URI> sourceUris = _dbClient.queryByConstraint( AlternateIdConstraint.Factory.getVolumeNativeGuidConstraint(sourceVolumeId)); if (sourceUris.isEmpty()) { _logger.info( "Source {} Not found for target {}", sourceVolumeId, unManagedVolume.getNativeGuid()); } else { // if source volume is ingested, then Volume sourceVolume = _dbClient.queryObject(Volume.class, sourceUris.get(0)); // check whether the source Volume's VPool is actually having this // target Volume's varray // specified as remote VirtualPool sourceVPool = _dbClient.queryObject(VirtualPool.class, sourceVolume.getVirtualPool()); Map<URI, VpoolRemoteCopyProtectionSettings> settings = sourceVPool.getRemoteProtectionSettings(sourceVPool, _dbClient); if (null == settings || settings.isEmpty() || !settings.containsKey(virtualArray.getId())) { _logger.info( "Target Volume's VArray {} is not matching already ingested source volume virtual pool's remote VArray ", virtualArray.getId()); throw IngestionException.exceptions.unmanagedSRDFTargetVolumeVArrayMismatch( unManagedVolume.getLabel(), sourceVolume.getVirtualArray().toString()); } } }
/** * Prepare the ViPR BlockSnapshotSession instance for the pass BlockSnapshot instance. * * @param snapshot A reference to the snapshot. * @return A reference to the newly created snapshot session. */ private BlockSnapshotSession prepareSnapshotSession(BlockSnapshot snapshot) { s_logger.info("Prepare BlockSnapshotSession for snapshot {}", snapshot.getId()); BlockSnapshotSession snapshotSession = new BlockSnapshotSession(); URI snapSessionURI = URIUtil.createId(BlockSnapshotSession.class); snapshotSession.setId(snapSessionURI); snapshotSession.setSessionLabel(getSessionLabelFromSettingsInstance(snapshot)); URI cgURI = snapshot.getConsistencyGroup(); if (NullColumnValueGetter.isNullURI(cgURI)) { snapshotSession.setParent(snapshot.getParent()); snapshotSession.setLabel(snapshot.getLabel()); } else { snapshotSession.setConsistencyGroup(cgURI); snapshotSession.setLabel(snapshot.getSnapsetLabel()); Volume parent = getDbClient().queryObject(Volume.class, snapshot.getParent()); if (parent != null) { snapshotSession.setReplicationGroupInstance(parent.getReplicationGroupInstance()); snapshotSession.setSessionSetName(parent.getReplicationGroupInstance()); } } snapshotSession.setProject(snapshot.getProject()); snapshotSession.setStorageController(snapshot.getStorageController()); snapshotSession.setSessionInstance(snapshot.getSettingsInstance()); StringSet linkedTargets = new StringSet(); linkedTargets.add(snapshot.getId().toString()); snapshotSession.setLinkedTargets(linkedTargets); return snapshotSession; }
/** * Validate the SourceVolume VArray details with ingested target volumes VArray. * * @param unManagedVolume * @param VirtualPool * @return */ private void validateSourceVolumeVarrayWithTargetVPool( UnManagedVolume unManagedVolume, VirtualPool sourceVPool) { StringSetMap unManagedVolumeInformation = unManagedVolume.getVolumeInformation(); // find whether all targets are ingested StringSet targetUnManagedVolumeGuids = unManagedVolumeInformation.get(SupportedVolumeInformation.REMOTE_MIRRORS.toString()); if (null != targetUnManagedVolumeGuids && !targetUnManagedVolumeGuids.isEmpty()) { StringSet targetVolumeNativeGuids = VolumeIngestionUtil.getListofVolumeIds(targetUnManagedVolumeGuids); // check whether target exists List<URI> targetUris = VolumeIngestionUtil.getVolumeUris(targetVolumeNativeGuids, _dbClient); if (null == targetUris || targetUris.isEmpty()) { _logger.info( "None of the targets ingested for source volume: {}", unManagedVolume.getNativeGuid()); } else { List<Volume> targetVolumes = _dbClient.queryObject(Volume.class, targetUris); for (Volume targetVolume : targetVolumes) { Map<URI, VpoolRemoteCopyProtectionSettings> settings = sourceVPool.getRemoteProtectionSettings(sourceVPool, _dbClient); if (null == settings || settings.size() == 0 || !settings.containsKey(targetVolume.getVirtualArray())) { _logger.info( "Target Volume's VArray {} is not matching already ingested source volume virtual pool's remote VArray {}", targetVolume.getVirtualArray(), Joiner.on(",").join(settings.keySet())); throw IngestionException.exceptions.unmanagedSRDFSourceVolumeVArrayMismatch( unManagedVolume.getLabel(), targetVolume.getVirtualArray().toString()); } } } } }
/** * Verify the RP+VPlex consistency group and its volumes have been properly migrated. * * @throws Exception */ private void verifyRpVplexConsistencyGroupMigration() throws Exception { log.info("Verifying RP+VPlex BlockConsistencyGroup and associated volume migration."); List<BlockObject> blockObjects = new ArrayList<BlockObject>(); BlockConsistencyGroup rpVplexPrimaryCg = _dbClient.queryObject(BlockConsistencyGroup.class, rpVplexPrimaryConsistencyGroupURI); // Verify the RP+VPLEX consistency group was properly migrated verifyConsistencyGroupMigration(rpVplexPrimaryCg, Types.RP.name(), Types.VPLEX.name()); Assert.assertNotNull( "The RP+VPlex BlockConsistencyGroup.systemConsistencyGroups field should be populated.", rpVplexPrimaryCg.getSystemConsistencyGroups()); Assert.assertNotNull( "The RP+VPlex BlockConsistencyGroup.systemConsistencyGroups field should contain an entry for " + protectionSystemURI.toString(), rpVplexPrimaryCg.getSystemConsistencyGroups().get(protectionSystemURI.toString())); Assert.assertTrue( "The RP+VPlex BlockConsistencyGroup.systemConsistencyGroups field should contain a mapping for " + protectionSystemURI.toString() + "-> ViPR-" + rpVplexPrimaryCg.getLabel(), rpVplexPrimaryCg .getSystemConsistencyGroups() .get(protectionSystemURI.toString()) .contains("ViPR-" + rpVplexPrimaryCg.getLabel())); // Verify that primary CG has a mapping reference for each of the VPlex storage system/cg name. for (URI rpVplexVolumeId : rpVplexVolumeToCgMapping.keySet()) { Volume rpVplexVolume = _dbClient.queryObject(Volume.class, rpVplexVolumeId); blockObjects.add(rpVplexVolume); // Get the VPlex consistency group URI cgUri = rpVplexVolumeToCgMapping.get(rpVplexVolumeId); BlockConsistencyGroup vplexCg = _dbClient.queryObject(BlockConsistencyGroup.class, cgUri); String cgName = vplexCg.getLabel(); String clusterName = getVPlexClusterFromVolume(rpVplexVolume); String storageSystem = rpVplexVolume.getStorageController().toString(); String clusterCgName = BlockConsistencyGroupUtils.buildClusterCgName(clusterName, cgName); // Verify that primary CG contains the correct mapping Assert.assertTrue( "The RP+VPlex BlockConsistencyGroup.systemConsistencyGroups field should contain a mapping for " + storageSystem + "->" + clusterCgName, rpVplexPrimaryCg.getSystemConsistencyGroups().get(storageSystem).contains(clusterCgName)); // Verify that the VPlex CG has been marked for deletion Assert.assertTrue( "The VPlex BlockConsistencyGroup " + vplexCg.getLabel() + "should be inactive.", vplexCg.getInactive()); } // Verify the volume migration took place correctly verifyBlockObjects(blockObjects); }
/** * Remove application from the volume applicationIds attribute * * @param voluri The volumes that will be updated * @param dbClient */ protected void removeApplicationFromVolume(URI voluri, DbClient dbClient) { Volume volume = dbClient.queryObject(Volume.class, voluri); String appId = getId().toString(); StringSet appIds = volume.getVolumeGroupIds(); if (appIds != null) { appIds.remove(appId); } dbClient.updateObject(volume); }
/** * Convenience method that adds volumes to a protection set. * * @param protectionSetURI * @param volumes */ private void addVolumesToProtectionSet(URI protectionSetURI, List<Volume> volumes) { ProtectionSet protectionSet = _dbClient.queryObject(ProtectionSet.class, protectionSetURI); StringSet vols = new StringSet(); for (Volume volume : volumes) { vols.add(volume.getId().toString()); } protectionSet.setVolumes(vols); _dbClient.persistObject(protectionSet); }
/** * Gets the VPlex cluster Id for a given VPlex virtual volume. * * @param virtualVolume * @return */ private String getVPlexClusterFromVolume(Volume virtualVolume) { String clusterId = null; if (virtualVolume != null && virtualVolume.getNativeId() != null) { String[] nativeIdSplit = virtualVolume.getNativeId().split("/"); clusterId = nativeIdSplit[2]; } return clusterId; }
/* * (non-Javadoc) * * @see com.emc.storageos.volumecontroller.CloneOperations#detachSingleClone( * com.emc.storageos.db.client.model.StorageSystem, * java.net.URI, * com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void detachSingleClone( StorageSystem storageSystem, URI cloneVolume, TaskCompleter taskCompleter) { // Not Supported Volume clone = dbClient.queryObject(Volume.class, cloneVolume); clone.setAssociatedSourceVolume(NullColumnValueGetter.getNullURI()); clone.setReplicaState(ReplicationState.DETACHED.name()); dbClient.persistObject(clone); taskCompleter.ready(dbClient); }
/* * (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())); }
@Override protected Volume.VolumeAccessState getVolumeAccessStateForSuccess(Volume v) { if (!NullColumnValueGetter.isNullValue(v.getSrdfCopyMode()) && Mode.ACTIVE.equals(Mode.valueOf(v.getSrdfCopyMode())) && v.getPersonality().equals(Volume.PersonalityTypes.TARGET.toString())) { // For Active mode target access state is always updated from the provider // after each operation so just use that. return Volume.VolumeAccessState.getVolumeAccessState(v.getAccessState()); } else { return Volume.VolumeAccessState.READWRITE; } }
private void handleBlockVolumeErrors(DbClient dbClient) { for (VolumeDescriptor volumeDescriptor : VolumeDescriptor.getDescriptors(_volumeDescriptors, VolumeDescriptor.Type.BLOCK_DATA)) { Volume volume = dbClient.queryObject(Volume.class, volumeDescriptor.getVolumeURI()); if (volume != null && (volume.getNativeId() == null || volume.getNativeId().equals(""))) { _log.info("No native id was present on volume {}, marking inactive", volume.getLabel()); dbClient.markForDeletion(volume); } } }
/* * (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); } }
/** * Detaches volumes from initiators. * * @param storage the storage * @param volumes the volumes * @param initiators the initiators * @throws Exception the exception */ private void detachVolumesFromInitiators( StorageSystem storage, List<Volume> volumes, List<Initiator> initiators) throws Exception { CinderEndPointInfo ep = CinderUtils.getCinderEndPoint(storage.getActiveProviderURI(), dbClient); log.debug("Getting the cinder APi for the provider with id {}", storage.getActiveProviderURI()); CinderApi cinderApi = cinderApiFactory.getApi(storage.getActiveProviderURI(), ep); List<Initiator> iSCSIInitiators = new ArrayList<Initiator>(); List<Initiator> fcInitiators = new ArrayList<Initiator>(); splitInitiatorsByProtocol(initiators, iSCSIInitiators, fcInitiators); String host = getHostNameFromInitiators(initiators); Map<String, String[]> mapSettingVsValues = getFCInitiatorsArray(fcInitiators); String[] fcInitiatorsWwpns = mapSettingVsValues.get(WWPNS); String[] fcInitiatorsWwnns = mapSettingVsValues.get(WWNNS); for (Volume volume : volumes) { // cinder generated volume ID String volumeId = volume.getNativeId(); // for iSCSI for (Initiator initiator : iSCSIInitiators) { String initiatorPort = initiator.getInitiatorPort(); log.debug( String.format( "Detaching volume %s ( %s ) from initiator %s on Openstack cinder node", volumeId, volume.getId(), initiatorPort)); cinderApi.detachVolume(volumeId, initiatorPort, null, null, host); // TODO : Do not use Job to poll status till we figure out how // to get detach status. /* * CinderJob detachJob = new CinderDetachVolumeJob(volumeId, * volume.getLabel(), storage.getId(), * CinderConstants.ComponentType.volume.name(), ep, * taskCompleter); ControllerServiceImpl.enqueueJob(new * QueueJob(detachJob)); */ } // for FC if (fcInitiatorsWwpns.length > 0) { log.debug( String.format( "Detaching volume %s ( %s ) from initiator %s on Openstack cinder node", volumeId, volume.getId(), fcInitiatorsWwpns)); cinderApi.detachVolume(volumeId, null, fcInitiatorsWwpns, fcInitiatorsWwnns, host); } // If ITLs are added, remove them removeITLsFromVolume(volume); } }
/** * Return the rdfGroupId based on the personality. For source volume, we will not have RDFGroup * hence we should get it from its targets. * * @param unManagedVolumeInformation * @return */ private URI getRDFGroupBasedOnPersonality(StringSetMap unManagedVolumeInformation) { String type = PropertySetterUtil.extractValueFromStringSet( SupportedVolumeInformation.REMOTE_VOLUME_TYPE.toString(), unManagedVolumeInformation); URI rdfGroupId = null; if (RemoteMirrorObject.Types.SOURCE.toString().equalsIgnoreCase(type)) { StringSet targetUnManagedVolumeGuids = unManagedVolumeInformation.get(SupportedVolumeInformation.REMOTE_MIRRORS.toString()); if (null != targetUnManagedVolumeGuids && !targetUnManagedVolumeGuids.isEmpty()) { StringSet targetVolumeNativeGuids = VolumeIngestionUtil.getListofVolumeIds(targetUnManagedVolumeGuids); List<URI> targetUris = VolumeIngestionUtil.getVolumeUris(targetVolumeNativeGuids, _dbClient); if (null == targetUris || targetUris.isEmpty()) { List<URI> unmanagedTargetVolumes = VolumeIngestionUtil.getUnManagedVolumeUris(targetUnManagedVolumeGuids, _dbClient); for (URI targetUmv : unmanagedTargetVolumes) { _logger.info("RDFGroup Found using unmanaged Target volume {}", targetUmv); UnManagedVolume umv = _dbClient.queryObject(UnManagedVolume.class, targetUmv); rdfGroupId = URI.create( PropertySetterUtil.extractValueFromStringSet( SupportedVolumeInformation.REMOTE_MIRROR_RDF_GROUP.toString(), umv.getVolumeInformation())); break; } } else { // If targets are already ingested. List<Volume> targetVolumes = _dbClient.queryObject(Volume.class, targetUris); if (null != targetVolumes && !targetVolumes.isEmpty()) { for (Volume targetVolume : targetVolumes) { _logger.info( "RDFGroup Found for using ingested Target volumes {}.", targetVolume.getNativeGuid()); rdfGroupId = targetVolume.getSrdfGroup(); break; } } } } } else if (RemoteMirrorObject.Types.TARGET.toString().equalsIgnoreCase(type)) { rdfGroupId = URI.create( PropertySetterUtil.extractValueFromStringSet( SupportedVolumeInformation.REMOTE_MIRROR_RDF_GROUP.toString(), unManagedVolumeInformation)); } return rdfGroupId; }
/** * Add the application to the volume applicationIds attribute * * @param voluri The volume that will be updated * @param dbClient */ protected void addApplicationToVolume(URI voluri, DbClient dbClient) { Volume volume = dbClient.queryObject(Volume.class, voluri); StringSet applications = volume.getVolumeGroupIds(); if (applications == null) { applications = new StringSet(); } applications.add(getId().toString()); volume.setVolumeGroupIds(applications); dbClient.updateObject(volume); // handle clones StringSet fullCopies = volume.getFullCopies(); List<Volume> fullCopiesToUpdate = new ArrayList<Volume>(); if (fullCopies != null && !fullCopies.isEmpty()) { for (String fullCopyId : fullCopies) { Volume fullCopy = dbClient.queryObject(Volume.class, URI.create(fullCopyId)); if (fullCopy != null && NullColumnValueGetter.isNullValue(fullCopy.getFullCopySetName())) { fullCopy.setFullCopySetName(fullCopy.getReplicationGroupInstance()); fullCopiesToUpdate.add(fullCopy); } } } if (!fullCopiesToUpdate.isEmpty()) { dbClient.updateObject(fullCopiesToUpdate); } }
/** * Create Initiator Target LUN Mapping as an extension in volume object * * @param volume - volume in which ITL to be added * @param exportMask - exportMask in which the volume is to be added * @param targetLunId - integer value of host LUN id on which volume is accessible. */ private void storeITLMappingInVolume( Map<URI, Integer> volumeToTargetLunMap, ExportMask exportMask) { log.debug("START - createITLMappingInVolume"); for (URI volumeURI : volumeToTargetLunMap.keySet()) { Integer targetLunId = volumeToTargetLunMap.get(volumeURI); Volume volume = dbClient.queryObject(Volume.class, volumeURI); StringSetMap zoningMap = exportMask.getZoningMap(); Set<String> zoningMapKeys = zoningMap.keySet(); int initiatorIndex = 0; for (String initiator : zoningMapKeys) { Initiator initiatorObj = dbClient.queryObject(Initiator.class, URI.create(initiator)); String initiatorWWPN = initiatorObj.getInitiatorPort().replaceAll(CinderConstants.COLON, ""); StringSet targetPorts = zoningMap.get(initiator); int targetIndex = 0; for (String target : targetPorts) { StoragePort targetPort = dbClient.queryObject(StoragePort.class, URI.create(target)); String targetPortWWN = targetPort.getPortNetworkId().replaceAll(CinderConstants.COLON, ""); // Format is - <InitiatorWWPN>-<TargetWWPN>-<LunId> String itl = initiatorWWPN + "-" + targetPortWWN + "-" + String.valueOf(targetLunId); // ITL keys will be formed as ITL-00, ITL-01, ITL-10, ITL-11 so on String itlKey = CinderConstants.PREFIX_ITL + String.valueOf(initiatorIndex) + String.valueOf(targetIndex); log.info(String.format("Adding ITL %s with key %s", itl, itlKey)); StringMap extensionsMap = volume.getExtensions(); if (null == extensionsMap) { extensionsMap = new StringMap(); extensionsMap.put(itlKey, itl); volume.setExtensions(extensionsMap); } else { volume.getExtensions().put(itlKey, itl); } targetIndex++; } initiatorIndex++; } dbClient.updateAndReindexObject(volume); } log.debug("END - createITLMappingInVolume"); }
/** * Convenience method that creates the BlockObject Volume data. * * @param volumeName * @param numTargets */ private List<Volume> createBlockVolumes(String volumeName, int numVolumes, URI storageSystem) { List<Volume> volumes = new ArrayList<Volume>(); for (int i = 1; i <= numVolumes; i++) { Volume volume = new Volume(); URI volumeURI = URIUtil.createId(Volume.class); blockVolumeURIs.add(volumeURI); volume.setId(volumeURI); volume.setLabel(volumeName + i); volume.setStorageController(storageSystem); _dbClient.createObject(volume); volumes.add(volume); } return volumes; }
public void vcenterClusterCreateDatastoreOperation( URI vcenterId, URI vcenterDataCenterId, URI clusterId, URI volumeId, String selectHostStepId, String stepId) { VcenterApiClient vcenterApiClient = null; try { WorkflowStepCompleter.stepExecuting(stepId); URI hostId = (URI) _workflowService.loadStepData(selectHostStepId); if (hostId == null) { _log.error("Workflow loadStepData on " + selectHostStepId + " is null"); throw new Exception("Workflow loadStepData on " + selectHostStepId + " is null"); } VcenterDataCenter vcenterDataCenter = _dbClient.queryObject(VcenterDataCenter.class, vcenterDataCenterId); Cluster cluster = _dbClient.queryObject(Cluster.class, clusterId); Vcenter vcenter = _dbClient.queryObject(Vcenter.class, vcenterId); Host host = _dbClient.queryObject(Host.class, hostId); Volume volume = _dbClient.queryObject(Volume.class, volumeId); vcenterApiClient = new VcenterApiClient(_coordinator.getPropertyInfo()); vcenterApiClient.setup(vcenter.getIpAddress(), vcenter.getUsername(), vcenter.getPassword()); String key = vcenterApiClient.createDatastore( vcenterDataCenter.getLabel(), cluster.getExternalId(), host.getHostName(), volume.getWWN(), volume.getLabel()); _log.info("Successfully created or located datastore " + volume.getLabel() + " " + key); host.setVcenterDataCenter(vcenterDataCenter.getId()); _dbClient.updateAndReindexObject(host); WorkflowStepCompleter.stepSucceded(stepId); } catch (Exception e) { _log.error("vcenterClusterCreateDatastoreOperation exception " + e); WorkflowStepCompleter.stepFailed( stepId, VcenterControllerException.exceptions.hostException(e.getLocalizedMessage(), e)); } finally { if (vcenterApiClient != null) vcenterApiClient.destroy(); } }
/** {@inheritDoc} */ @Override public VolumeRestRep checkProgress(URI sourceURI, Volume fullCopyVolume) { // Get the native backend full copy volume for this VPLEX // full copy volume. Volume nativeFullCopyVolume = VPlexUtil.getVPLEXBackendVolume(fullCopyVolume, true, _dbClient); // Call super to check the progress of the backend full // copy volume. Integer percentSynced = getSyncPercentage(nativeFullCopyVolume.getAssociatedSourceVolume(), nativeFullCopyVolume); // The synchronization progress of the VPLEX full copy is that // of the backend full copy. VolumeRestRep volumeRestRep = BlockMapper.map(_dbClient, fullCopyVolume); volumeRestRep.getProtection().getFullCopyRep().setPercentSynced(percentSynced); return volumeRestRep; }
private void updateStorageVolume( CIMInstance volumeInstance, Volume storageVolume, Map<String, Object> keyMap) throws IOException { storageVolume.setAllocatedCapacity( Long.parseLong(getCIMPropertyValue(volumeInstance, EMC_ALLOCATED_CAPACITY))); storageVolume.setProvisionedCapacity(returnProvisionedCapacity(volumeInstance, keyMap)); // If meta volume was ingested prior to upgrade to 2.2 it won't have // 'isComposite' set. We need to check // cim instance here to see if the volume is meta volume and set it in // the volume instance. if (isComposite(volumeInstance) && !storageVolume.getIsComposite()) { storageVolume.setIsComposite(true); _logger.info("Set volume {} to composite (meta volume)", storageVolume.getId()); } _updateVolumes.add(storageVolume); }
/** {@inheritDoc} */ @Override public void validateFullCopyCreateRequest(List<BlockObject> fcSourceObjList, int count) { if (fcSourceObjList.size() > 0) { URI fcSourceObjURI = fcSourceObjList.get(0).getId(); if (URIUtil.isType(fcSourceObjURI, BlockSnapshot.class)) { // Currently you cannot create a full copy of a VPLEX snapshot. throw APIException.badRequests.cantCreateFullCopyForVPlexSnapshot(); } else { // Call super first. super.validateFullCopyCreateRequest(fcSourceObjList, count); // Platform specific checks. for (BlockObject fcSourceObj : fcSourceObjList) { Volume fcSourceVolume = (Volume) fcSourceObj; StorageSystem system = _dbClient.queryObject(StorageSystem.class, fcSourceVolume.getStorageController()); if (DiscoveredDataObject.Type.vplex.name().equals(system.getSystemType())) { // If the volume is a VPLEX volume, then we need to be sure that // storage pool of the source backend volume of the VPLEX volume, // which is volume used to create the native full copy, supports // full copy. Volume srcBackendVolume = VPlexUtil.getVPLEXBackendVolume(fcSourceVolume, true, _dbClient, true); StoragePool storagePool = _dbClient.queryObject(StoragePool.class, srcBackendVolume.getPool()); verifyFullCopySupportedForStoragePool(storagePool); // If the full copy source is itself a full copy, it is not // detached, and the native full copy i.e., the source side // backend volume, is VNX, then creating a full copy of the // volume will fail. As such, we prevent it. if ((BlockFullCopyUtils.isVolumeFullCopy(fcSourceVolume, _dbClient)) && (!BlockFullCopyUtils.isFullCopyDetached(fcSourceVolume, _dbClient))) { URI backendSystemURI = srcBackendVolume.getStorageController(); StorageSystem backendSystem = _dbClient.queryObject(StorageSystem.class, backendSystemURI); if (DiscoveredDataObject.Type.vnxblock.name().equals(backendSystem.getSystemType())) { throw APIException.badRequests.cantCreateFullCopyOfVPlexFullCopyUsingVNX(); } } } } } } }
@Override public void injectColumnsDetails(Stat statObj, DbClient client) throws Exception { ProtectionSystem protectionObj = client.queryObject(ProtectionSystem.class, statObj.getResourceId()); // Given a protection system, find a volume protected by this protection system, // and then extract the project and vpool Volume protectedVolume = null; URIQueryResultList resultList = new URIQueryResultList(); client.queryByConstraint( ContainmentConstraint.Factory.getProtectionSystemVolumesConstraint(protectionObj.getId()), resultList); for (Iterator<URI> volumeItr = resultList.iterator(); volumeItr.hasNext(); ) { Volume volume = client.queryObject(Volume.class, volumeItr.next()); if (volume.getProtectionController().equals(protectionObj.getId())) { protectedVolume = volume; break; } } if (protectedVolume != null) { _logger.info( "Found volume " + protectedVolume.getWWN() + " protected by this protection controller. Get the Cos/Project/Tenant."); statObj.setProject(protectedVolume.getProject().getURI()); statObj.setVirtualPool(protectedVolume.getVirtualPool()); statObj.setTenant(protectedVolume.getTenant().getURI()); } else { statObj.setProject(null); statObj.setVirtualPool(null); statObj.setTenant(null); throw new SMIPluginException( "Cassandra Database Insertion Error. Cannot identify Project/CoS/Tenant for ProtectionSystem", -1); } }
/** * Remove the list of ITLs from the volume extensions * * @param volume * @return */ private void removeITLsFromVolume(Volume volume) { StringMap extensions = volume.getExtensions(); Set<Map.Entry<String, String>> mapEntries = extensions.entrySet(); for (Iterator<Map.Entry<String, String>> it = mapEntries.iterator(); it.hasNext(); ) { Map.Entry<String, String> entry = it.next(); if (entry.getKey().startsWith(CinderConstants.PREFIX_ITL)) { it.remove(); } } }
@Override public void createGroupSnapshots( StorageSystem storage, List<URI> snapshotList, Boolean createInactive, Boolean readOnly, TaskCompleter taskCompleter) throws DeviceControllerException { try { URI snapshot = snapshotList.get(0); BlockSnapshot snapshotObj = _dbClient.queryObject(BlockSnapshot.class, snapshot); Volume volume = _dbClient.queryObject(Volume.class, snapshotObj.getParent()); TenantOrg tenant = _dbClient.queryObject(TenantOrg.class, volume.getTenant().getURI()); String tenantName = tenant.getLabel(); String snapLabelToUse = _nameGenerator.generate( tenantName, snapshotObj.getLabel(), snapshot.toString(), '-', SmisConstants.MAX_SNAPSHOT_NAME_LENGTH); String groupName = getConsistencyGroupName(snapshotObj); VNXeApiClient apiClient = getVnxeClient(storage); VNXeCommandJob job = apiClient.createLunGroupSnap(groupName, snapLabelToUse); if (job != null) { ControllerServiceImpl.enqueueJob( new QueueJob( new VNXeBlockCreateCGSnapshotJob( job.getId(), storage.getId(), !createInactive, taskCompleter))); } } catch (VNXeException e) { _log.error("Create volume snapshot got the exception", e); taskCompleter.error(_dbClient, e); } catch (Exception ex) { _log.error("Create volume snapshot got the exception", ex); ServiceError error = DeviceControllerErrors.vnxe.jobFailed("CreateCGSnapshot", ex.getMessage()); taskCompleter.error(_dbClient, error); } }
/** * Verify the VPlex consistency group and its volumes have been properly migrated. * * @throws Exception */ private void verifyVplexConsistencyGroupMigration() throws Exception { log.info("Verifying VPlex BlockConsistencyGroup and associated volume migration."); BlockConsistencyGroup vplexCg = _dbClient.queryObject(BlockConsistencyGroup.class, vplexConsistencyGroupURI); Iterator<Volume> vplexVolumeItr = _dbClient.queryIterativeObjects(Volume.class, vplexVolumeURIs); // Verify the VPLEX consistency group was properly migrated verifyConsistencyGroupMigration(vplexCg, Types.VPLEX.name()); while (vplexVolumeItr.hasNext()) { Volume vplexVolume = vplexVolumeItr.next(); // Get the VPlex consistency group String cgName = vplexCg.getLabel(); String clusterName = getVPlexClusterFromVolume(vplexVolume); String storageSystem = vplexVolume.getStorageController().toString(); String clusterCgName = BlockConsistencyGroupUtils.buildClusterCgName(clusterName, cgName); // Verify that primary CG contains the correct mapping Assert.assertNotNull( "The VPlex BlockConsistencyGroup.vplexStorageSystemToCg field should be populated.", vplexCg.getSystemConsistencyGroups()); Assert.assertTrue( "The VPlex BlockConsistencyGroup.vplexStorageSystemToCg should contain a key for storage system " + storageSystem, vplexCg.getSystemConsistencyGroups().containsKey(storageSystem)); Assert.assertTrue( "The VPlex BlockConsistencyGroup.vplexStorageSystemToCg field should contain a mapping for " + storageSystem + "->" + clusterCgName, vplexCg.getSystemConsistencyGroups().get(storageSystem).contains(clusterCgName)); } // Verify the volume migration took place correctly List<BlockObject> blockObjects = new ArrayList<BlockObject>(); while (vplexVolumeItr.hasNext()) { blockObjects.add(vplexVolumeItr.next()); } verifyBlockObjects(blockObjects); }
/* * (non-Javadoc) * * @see * com.emc.storageos.volumecontroller.BlockStorageDevice#doWaitForSynchronized * (java.lang.Class, com.emc.storageos.db.client.model.StorageSystem, * java.net.URI, com.emc.storageos.volumecontroller.TaskCompleter) */ @Override public void doWaitForSynchronized( Class<? extends BlockObject> clazz, StorageSystem storageObj, URI target, TaskCompleter completer) { log.info("START waitForSynchronized for {}", target); try { Volume targetObj = dbClient.queryObject(Volume.class, target); // Source could be either Volume or BlockSnapshot BlockObject sourceObj = BlockObject.fetch(dbClient, targetObj.getAssociatedSourceVolume()); // We split the pair which causes the data to be synchronized. // When the split is complete that data is synchronized. HDSApiClient hdsApiClient = hdsApiFactory.getClient( HDSUtils.getHDSServerManagementServerInfo(storageObj), storageObj.getSmisUserName(), storageObj.getSmisPassword()); HDSApiProtectionManager hdsApiProtectionManager = hdsApiClient.getHdsApiProtectionManager(); String replicationGroupObjectID = hdsApiProtectionManager.getReplicationGroupObjectId(); ReplicationInfo replicationInfo = hdsApiProtectionManager.getReplicationInfoFromSystem( sourceObj.getNativeId(), targetObj.getNativeId()) .first; hdsApiProtectionManager.modifyShadowImagePair( replicationGroupObjectID, replicationInfo.getObjectID(), HDSApiProtectionManager.ShadowImageOperationType.split); // Update state in case we are waiting for synchronization // after creation of a new full copy that was not created // inactive. String state = targetObj.getReplicaState(); if (!ReplicationState.SYNCHRONIZED.name().equals(state)) { targetObj.setSyncActive(true); targetObj.setReplicaState(ReplicationState.SYNCHRONIZED.name()); dbClient.persistObject(targetObj); } // Queue job to wait for replication status to move to split. ControllerServiceImpl.enqueueJob( new QueueJob( new HDSReplicationSyncJob( storageObj.getId(), sourceObj.getNativeId(), targetObj.getNativeId(), ReplicationStatus.SPLIT, completer))); } catch (Exception e) { log.error("Exception occurred while waiting for synchronization", e); ServiceError serviceError = DeviceControllerException.errors.jobFailed(e); completer.error(dbClient, serviceError); } log.info("completed doWaitForSynchronized"); }
/** Create RP BlockConsistencyGroup objects for each ProtectionSet. */ private void createRpBlockConsistencyGroups() { DbClient dbClient = this.getDbClient(); List<URI> protectionSetURIs = dbClient.queryByType(ProtectionSet.class, false); Iterator<ProtectionSet> protectionSets = dbClient.queryIterativeObjects(ProtectionSet.class, protectionSetURIs); while (protectionSets.hasNext()) { ProtectionSet ps = protectionSets.next(); Project project = dbClient.queryObject(Project.class, ps.getProject()); BlockConsistencyGroup cg = new BlockConsistencyGroup(); cg.setId(URIUtil.createId(BlockConsistencyGroup.class)); cg.setLabel(ps.getLabel()); cg.setDeviceName(ps.getLabel()); cg.setType(BlockConsistencyGroup.Types.RP.toString()); cg.setProject(new NamedURI(project.getId(), ps.getLabel())); cg.setTenant(new NamedURI(project.getTenantOrg().getURI(), ps.getLabel())); dbClient.createObject(cg); log.debug( "Created ConsistencyGroup (id={}) based on ProtectionSet (id={})", cg.getId().toString(), ps.getId().toString()); // Organize the volumes by replication set for (String protectionVolumeID : ps.getVolumes()) { URI uri = URI.create(protectionVolumeID); Volume protectionVolume = dbClient.queryObject(Volume.class, uri); protectionVolume.addConsistencyGroup(cg.getId().toString()); dbClient.persistObject(protectionVolume); log.debug( "Volume (id={}) added to ConsistencyGroup (id={})", protectionVolume.getId().toString(), cg.getId().toString()); } } }