// Find a host connected and powered on then refresh it public void vcenterClusterSelectHostOperation( URI vcenterId, URI vcenterDataCenterId, URI clusterId, URI[] hostUris, String stepId) { VcenterApiClient vcenterApiClient = null; try { WorkflowStepCompleter.stepExecuting(stepId); VcenterDataCenter vcenterDataCenter = _dbClient.queryObject(VcenterDataCenter.class, vcenterDataCenterId); Cluster cluster = _dbClient.queryObject(Cluster.class, clusterId); Vcenter vcenter = _dbClient.queryObject(Vcenter.class, vcenterId); Collection<Host> hosts = _dbClient.queryObject(Host.class, hostUris); vcenterApiClient = new VcenterApiClient(_coordinator.getPropertyInfo()); vcenterApiClient.setup(vcenter.getIpAddress(), vcenter.getUsername(), vcenter.getPassword()); Host hostForStorageOperations = null; for (Host host : hosts) { try { vcenterApiClient.checkHostConnectedPoweredOn( vcenterDataCenter.getLabel(), cluster.getExternalId(), host.getHostName()); hostForStorageOperations = host; _log.info("Host " + host.getHostName() + " to be used for storage operations"); break; } catch (Exception e) { _log.info( "Host " + host.getHostName() + " not valid for storage operations due to exception " + e.getLocalizedMessage()); } } if (hostForStorageOperations == null) { _log.error( "No host valid for performing storage operations thus cannot perform datastore operations"); throw new Exception( "No host valid for performing storage operations thus cannot perform datastore operations"); } vcenterApiClient.refreshRescanHostStorage( vcenterDataCenter.getLabel(), cluster.getExternalId(), hostForStorageOperations.getHostName()); // persist hostForStorageOperations ID in wf data _workflowService.storeStepData(stepId, hostForStorageOperations.getId()); WorkflowStepCompleter.stepSucceded(stepId); } catch (Exception e) { _log.error("vcenterClusterSelectHostOperation exception " + e); WorkflowStepCompleter.stepFailed( stepId, VcenterControllerException.exceptions.hostException(e.getLocalizedMessage(), e)); } finally { if (vcenterApiClient != null) vcenterApiClient.destroy(); } }
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(); } }
/* * (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())); }
private void createOrUpdateVcenterCluster( boolean createCluster, AsyncTask task, URI clusterUri, URI[] addHostUris, URI[] removeHostUris, URI[] volumeUris) throws InternalException { TaskCompleter completer = null; try { _log.info( "createOrUpdateVcenterCluster " + createCluster + " " + task + " " + clusterUri + " " + addHostUris + " " + removeHostUris); if (task == null) { _log.error("AsyncTask is null"); throw new Exception("AsyncTask is null"); } URI vcenterDataCenterId = task._id; VcenterDataCenter vcenterDataCenter = _dbClient.queryObject(VcenterDataCenter.class, vcenterDataCenterId); if (clusterUri == null) { _log.error("Cluster URI is null"); throw new Exception("Cluster URI is null"); } Cluster cluster = _dbClient.queryObject(Cluster.class, clusterUri); Vcenter vcenter = _dbClient.queryObject(Vcenter.class, vcenterDataCenter.getVcenter()); _log.info( "Request to create or update cluster " + vcenter.getIpAddress() + "/" + vcenterDataCenter.getLabel() + "/" + cluster.getLabel()); Collection<Host> addHosts = new ArrayList<Host>(); if (addHostUris == null || addHostUris.length == 0) { _log.info("Add host URIs is null or empty - Cluster will be created without hosts"); } else { for (URI hostUri : addHostUris) { _log.info("createOrUpdateVcenterCluster " + clusterUri + " with add host " + hostUri); } addHosts = _dbClient.queryObject(Host.class, addHostUris); } Collection<Host> removeHosts = new ArrayList<Host>(); if (removeHostUris == null || removeHostUris.length == 0) { _log.info("Remove host URIs is null or empty - Cluster will have no removed hosts"); } else { for (URI hostUri : removeHostUris) { _log.info("createOrUpdateVcenterCluster " + clusterUri + " with remove host " + hostUri); } removeHosts = _dbClient.queryObject(Host.class, removeHostUris); } Collection<Volume> volumes = new ArrayList<Volume>(); if (volumeUris == null || volumeUris.length == 0) { _log.info("Volume URIs is null or empty - Cluster will be created without datastores"); } else { for (URI volumeUri : volumeUris) { _log.info("createOrUpdateVcenterCluster " + clusterUri + " with volume " + volumeUri); } volumes = _dbClient.queryObject(Volume.class, volumeUris); } completer = new VcenterClusterCompleter( vcenterDataCenterId, task._opId, OperationTypeEnum.CREATE_UPDATE_VCENTER_CLUSTER, "VCENTER_CONTROLLER"); Workflow workflow = _workflowService.getNewWorkflow( this, "CREATE_UPDATE_VCENTER_CLUSTER_WORKFLOW", true, task._opId); String clusterStep = workflow.createStep( "CREATE_UPDATE_VCENTER_CLUSTER_STEP", String.format( "vCenter cluster operation in vCenter datacenter %s", vcenterDataCenterId), null, vcenterDataCenterId, vcenterDataCenterId.toString(), this.getClass(), new Workflow.Method( "createUpdateVcenterClusterOperation", createCluster, vcenter.getId(), vcenterDataCenter.getId(), cluster.getId()), null, null); String lastStep = clusterStep; if (removeHosts.size() > 0) { for (Host host : removeHosts) { String hostStep = workflow.createStep( "VCENTER_CLUSTER_REMOVE_HOST", String.format("vCenter cluster remove host operation %s", host.getId()), clusterStep, vcenterDataCenterId, vcenterDataCenterId.toString(), this.getClass(), new Workflow.Method( "vcenterClusterRemoveHostOperation", vcenter.getId(), vcenterDataCenter.getId(), cluster.getId(), host.getId()), null, null); lastStep = hostStep; // add host will wait on last of these } } if (addHosts.size() > 0) { for (Host host : addHosts) { String hostStep = workflow.createStep( "VCENTER_CLUSTER_ADD_HOST", String.format("vCenter cluster add host operation %s", host.getId()), lastStep, vcenterDataCenterId, vcenterDataCenterId.toString(), this.getClass(), new Workflow.Method( "vcenterClusterAddHostOperation", vcenter.getId(), vcenterDataCenter.getId(), cluster.getId(), host.getId()), null, null); } if (volumes.size() > 0) { // Once all hosts in cluster select a host to use for shared storage operations String selectHostForStorageOperationsStep = workflow.createStep( "VCENTER_CLUSTER_SELECT_HOST", String.format( "vCenter cluster select host for storage operations operation vCenter datacenter %s", vcenterDataCenterId), "VCENTER_CLUSTER_ADD_HOST", vcenterDataCenterId, vcenterDataCenterId.toString(), this.getClass(), new Workflow.Method( "vcenterClusterSelectHostOperation", vcenter.getId(), vcenterDataCenter.getId(), cluster.getId(), addHostUris), null, null); // Do not run datastore creation in parallel // First datastore waits on selectHostForStorageOperationsStep step then next wait on the // previous datastore operation String volumeStep = null; for (Volume volume : volumes) { volumeStep = workflow.createStep( "VCENTER_CLUSTER_CREATE_DATASTORE", String.format("vCenter cluster create datastore operation %s", volume.getId()), volumeStep == null ? selectHostForStorageOperationsStep : volumeStep, vcenterDataCenterId, vcenterDataCenterId.toString(), this.getClass(), new Workflow.Method( "vcenterClusterCreateDatastoreOperation", vcenter.getId(), vcenterDataCenter.getId(), cluster.getId(), volume.getId(), selectHostForStorageOperationsStep), null, null); } } } workflow.executePlan(completer, "Success"); } catch (Exception e) { _log.error("createOrUpdateVcenterCluster caught an exception.", e); ServiceError serviceError = DeviceControllerException.errors.jobFailed(e); completer.error(_dbClient, serviceError); } }
/** * Called to update the job status when the volume expand job completes. * * @param jobContext The job context. */ public void updateStatus(JobContext jobContext) throws Exception { CloseableIterator<CIMObjectPath> associatorIterator = null; CloseableIterator<CIMInstance> instanceIterator = null; JobStatus jobStatus = getJobStatus(); try { if (jobStatus == JobStatus.IN_PROGRESS) { return; } DbClient dbClient = jobContext.getDbClient(); CIMConnectionFactory cimConnectionFactory = jobContext.getCimConnectionFactory(); WBEMClient client = getWBEMClient(dbClient, cimConnectionFactory); // If terminal state update storage pool capacity and remove reservation for volume capacity // from pool's reserved capacity map. if (jobStatus == JobStatus.SUCCESS || jobStatus == JobStatus.FAILED || jobStatus == JobStatus.FATAL_ERROR) { SmisUtils.updateStoragePoolCapacity(dbClient, client, _storagePoolURI); StoragePool pool = dbClient.queryObject(StoragePool.class, _storagePoolURI); StringMap reservationMap = pool.getReservedCapacityMap(); URI volumeId = getTaskCompleter().getId(); // remove from reservation map reservationMap.remove(volumeId.toString()); dbClient.persistObject(pool); } String opId = getTaskCompleter().getOpId(); StringBuilder logMsgBuilder = new StringBuilder( String.format( "Updating status of job %s to %s, task: %s", this.getJobName(), jobStatus.name(), opId)); if (jobStatus == JobStatus.SUCCESS) { VolumeExpandCompleter taskCompleter = (VolumeExpandCompleter) getTaskCompleter(); Volume volume = dbClient.queryObject(Volume.class, taskCompleter.getId()); // set requested capacity volume.setCapacity(taskCompleter.getSize()); // set meta related properties volume.setTotalMetaMemberCapacity(taskCompleter.getTotalMetaMembersSize()); volume.setMetaMemberCount(taskCompleter.getMetaMemberCount()); volume.setMetaMemberSize(taskCompleter.getMetaMemberSize()); volume.setIsComposite(taskCompleter.isComposite()); volume.setCompositionType(taskCompleter.getMetaVolumeType()); // set provisioned capacity associatorIterator = client.associatorNames(getCimJob(), null, SmisConstants.CIM_STORAGE_VOLUME, null, null); if (associatorIterator.hasNext()) { CIMObjectPath volumePath = associatorIterator.next(); CIMInstance volumeInstance = client.getInstance(volumePath, true, false, null); if (volumeInstance != null) { CIMProperty consumableBlocks = volumeInstance.getProperty(SmisConstants.CP_CONSUMABLE_BLOCKS); CIMProperty blockSize = volumeInstance.getProperty(SmisConstants.CP_BLOCK_SIZE); // calculate provisionedCapacity = consumableBlocks * block size Long provisionedCapacity = Long.valueOf(consumableBlocks.getValue().toString()) * Long.valueOf(blockSize.getValue().toString()); volume.setProvisionedCapacity(provisionedCapacity); } // set allocated capacity instanceIterator = client.referenceInstances( volumePath, SmisConstants.CIM_ALLOCATED_FROM_STORAGEPOOL, null, false, SmisConstants.PS_SPACE_CONSUMED); if (instanceIterator.hasNext()) { CIMInstance allocatedFromStoragePoolPath = instanceIterator.next(); CIMProperty spaceConsumed = allocatedFromStoragePoolPath.getProperty(SmisConstants.CP_SPACE_CONSUMED); if (null != spaceConsumed) { volume.setAllocatedCapacity(Long.valueOf(spaceConsumed.getValue().toString())); } } } logMsgBuilder.append( String.format( "%n Capacity: %s, Provisioned capacity: %s, Allocated Capacity: %s", volume.getCapacity(), volume.getProvisionedCapacity(), volume.getAllocatedCapacity())); if (volume.getIsComposite()) { logMsgBuilder.append( String.format( "%n Is Meta: %s, Total meta member capacity: %s, Meta member count %s, Meta member size: %s", volume.getIsComposite(), volume.getTotalMetaMemberCapacity(), volume.getMetaMemberCount(), volume.getMetaMemberSize())); } _log.info(logMsgBuilder.toString()); // Reset list of meta member volumes in the volume if (volume.getMetaVolumeMembers() != null) { volume.getMetaVolumeMembers().clear(); } StorageSystem storageSystem = dbClient.queryObject(StorageSystem.class, volume.getStorageController()); // set the RP tag on the volume if the volume is RP protected if (volume.checkForRp() && storageSystem.getSystemType() != null && storageSystem .getSystemType() .equalsIgnoreCase(DiscoveredDataObject.Type.vmax.toString())) { SmisCommandHelper helper = jobContext.getSmisCommandHelper(); List<CIMObjectPath> volumePathList = new ArrayList<CIMObjectPath>(); volumePathList.add(helper.getVolumeMember(storageSystem, volume)); helper.setRecoverPointTag(storageSystem, volumePathList, true); } dbClient.persistObject(volume); // Reset list of meta members native ids in WF data (when meta is created meta members are // removed from array) WorkflowService.getInstance().storeStepData(opId, new ArrayList<String>()); } } catch (Exception e) { _log.error("Caught an exception while trying to updateStatus for SmisVolumeExpandJob", e); setPostProcessingErrorStatus( "Encountered an internal error during volume expand job status processing : " + e.getMessage()); } finally { _metaVolumeTaskCompleter.setLastStepStatus(jobStatus); if (associatorIterator != null) { associatorIterator.close(); } if (instanceIterator != null) { instanceIterator.close(); } super.updateStatus(jobContext); } }