/** * Record storage pool alert/event * * @param storagePoolEventType * @param pool * @param description * @param eventType */ private static void recordBourneStoragePoolEvent( RecordableEventManager.EventType storagePoolEventType, StoragePool pool, String description, RecordType eventType, DbClient dbClient, RecordableEventManager eventManager) { RecordableBourneEvent event = ControllerUtils.convertToRecordableBourneEvent( pool, storagePoolEventType.toString(), description, "", dbClient, ControllerUtils.BLOCK_EVENT_SERVICE, eventType.toString(), ControllerUtils.BLOCK_EVENT_SOURCE); try { eventManager.recordEvents(event); _logger.info( "ViPR {} event recorded. Description: {}", event.getType(), event.getDescription()); } catch (Exception ex) { _logger.error( String.format( "Failed to record event %s. Event description: %s.", event.getType(), event.getDescription()), ex); } }
@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()); }
@Override public void deleteGroupSnapshots(StorageSystem storage, URI snapshot, TaskCompleter taskCompleter) throws DeviceControllerException { try { List<BlockSnapshot> snapshots = _dbClient.queryObject(BlockSnapshot.class, Arrays.asList(snapshot)); BlockSnapshot snapshotObj = snapshots.get(0); VNXeApiClient apiClient = getVnxeClient(storage); VNXeLunGroupSnap lunGroupSnap = apiClient.getLunGroupSnapshot(snapshotObj.getReplicationGroupInstance()); if (lunGroupSnap != null) { VNXeCommandJob job = apiClient.deleteLunGroupSnap(lunGroupSnap.getId()); if (job != null) { ControllerServiceImpl.enqueueJob( new QueueJob( new VNXeBlockDeleteSnapshotJob(job.getId(), storage.getId(), taskCompleter))); } else { // Should not take this path, but treat as an error if we do // happen to get a null job due to some error in the client. _log.error("Unexpected null job from VNXe client call to delete group snapshot."); ServiceCoded sc = DeviceControllerExceptions.vnxe.nullJobForDeleteGroupSnapshot( snapshotObj.forDisplay(), snapshotObj.getReplicationGroupInstance()); taskCompleter.error(_dbClient, sc); } } else { // Treat as in the single volume snapshot case and presume // the group snapshot has already been deleted. List<BlockSnapshot> grpSnapshots = ControllerUtils.getSnapshotsPartOfReplicationGroup(snapshotObj, _dbClient); for (BlockSnapshot grpSnapshot : grpSnapshots) { grpSnapshot.setInactive(true); grpSnapshot.setIsSyncActive(false); } _dbClient.updateObject(grpSnapshots); taskCompleter.ready(_dbClient); } } catch (VNXeException e) { _log.error("Delete group snapshot got the exception", e); taskCompleter.error(_dbClient, e); } catch (Exception ex) { _log.error("Delete group snapshot got the exception", ex); ServiceError error = DeviceControllerErrors.vnxe.jobFailed("DeletGroupSnapshot", ex.getMessage()); taskCompleter.error(_dbClient, error); } }
/* * (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()); }
/** * Add the application to the volume applicationIds attribute * * @param voluri The volumes that will be updated * @param dbClient */ private void addApplicationToVolume(Volume volume, DbClient dbClient) { StringSet applications = volume.getVolumeGroupIds(); if (applications == null) { applications = new StringSet(); } applications.add(getId().toString()); volume.setVolumeGroupIds(applications); dbClient.updateObject(volume); // Once volumes in VNX CG are added to an application, the CG's arrayConsistency // should turn to false if (volume.isInCG() && ControllerUtils.isVnxVolume(volume, dbClient)) { URI cguri = volume.getConsistencyGroup(); BlockConsistencyGroup cg = dbClient.queryObject(BlockConsistencyGroup.class, cguri); if (cg.getArrayConsistency()) { log.info("Updated consistency group arrayConsistency"); cg.setArrayConsistency(false); dbClient.updateObject(cg); } } }
/** * Create a nice event based on the TransportZone * * @param tz Network for which the event is about * @param type Type of event such as updated, created, removed * @param description Description for the event if needed */ private void recordTransportZoneEvent(Network tz, String type, String description) { if (tz == null) { _log.error("Invalid Network event"); return; } // TODO fix the bogus user ID once we have AuthZ working RecordableBourneEvent event = ControllerUtils.convertToRecordableBourneEvent( tz, type, description, null, dbClient, EVENT_SERVICE_TYPE, RecordType.Event.name(), EVENT_SERVICE_SOURCE); try { _evtMgr.recordEvents(event); } catch (Exception ex) { _log.error("Failed to record event. Event description: {}. Error: {}.", description, ex); } }
@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); } } }
/** * Create StoragePool Record, if not present already, else update only the properties. * * @param pool * @param poolInstance * @param profile * @param poolClassName * @param supportedVolumeTypes * @param protocols * @param poolsToMatchWithVpool * @throws URISyntaxException * @throws IOException */ private void createStoragePool( StoragePool pool, CIMInstance poolInstance, AccessProfile profile, String poolClassName, String supportedVolumeTypes, Set<String> protocols, Map<URI, StoragePool> poolsToMatchWithVpool, StorageSystem device) throws URISyntaxException, IOException { boolean newPool = false; boolean modifiedPool = false; // indicates whether to add to modified pools list or not if (null == pool) { String instanceID = getCIMPropertyValue(poolInstance, Constants.INSTANCEID); String nativeIdFromInstance = getNativeIDFromInstance(instanceID); newPool = true; pool = new StoragePool(); pool.setId(URIUtil.createId(StoragePool.class)); pool.setPoolName(getCIMPropertyValue(poolInstance, POOL_ID)); pool.setNativeId(nativeIdFromInstance); pool.setStorageDevice(profile.getSystemId()); pool.setPoolServiceType(PoolServiceType.block.toString()); String poolNativeGuid = NativeGUIDGenerator.generateNativeGuid(_dbClient, pool); pool.setNativeGuid(poolNativeGuid); pool.setLabel(poolNativeGuid); // setting default values on Pool Creation for VMAX and VNX pool.setMaximumThickVolumeSize(0L); pool.setMinimumThickVolumeSize(0L); pool.setMaximumThinVolumeSize(0L); pool.setMinimumThinVolumeSize(0L); if (device.getAutoTieringEnabled()) { pool.setAutoTieringEnabled(Boolean.TRUE); } else { pool.setAutoTieringEnabled(Boolean.FALSE); } _logger.info( String.format( "Maximum default limits for volume capacity in storage pool %s / %s : \n " + "max thin volume capacity: %s, max thick volume capacity: %s ", pool.getPoolName(), pool.getId(), pool.getMaximumThinVolumeSize(), pool.getMaximumThickVolumeSize())); // set default utilization/subscription limits double poolSubscriptionPercent = CapacityMatcher.getMaxPoolSubscriptionPercentage(pool, _coordinator); double poolUtilizationPercent = CapacityMatcher.getMaxPoolUtilizationPercentage(pool, _coordinator); pool.setMaxThinPoolSubscriptionPercentage((int) poolSubscriptionPercent); pool.setMaxPoolUtilizationPercentage((int) poolUtilizationPercent); } String maxSubscriptionPercent = getCIMPropertyValue(poolInstance, SmisConstants.CP_EMCMAXSUBSCRIPTIONPERCENT); _logger.info( String.format( "Discovered maximum subscription percent of storage pool %s from array : %s ", pool.getPoolName(), maxSubscriptionPercent)); // null value indicates "not available". Integer newMaxSubscriptionPercentFromArray = maxSubscriptionPercent == null ? null : new Integer(maxSubscriptionPercent); _logger.info( String.format( "New maximum subscription percent of storage pool %s from array : %s ", pool.getPoolName(), newMaxSubscriptionPercentFromArray)); processMaxSubscriptionPercent( newMaxSubscriptionPercentFromArray, pool, _dbClient, _eventManager); String subscribedCapacity = getCIMPropertyValue(poolInstance, SmisConstants.CP_SUBSCRIBEDCAPACITY); if (null != subscribedCapacity) { pool.setSubscribedCapacity(ControllerUtils.convertBytesToKBytes(subscribedCapacity)); } pool.setFreeCapacity(SmisUtils.getFreeCapacity(poolInstance)); pool.setTotalCapacity(SmisUtils.getTotalCapacity(poolInstance)); pool.setPoolClassName(poolClassName); pool.setSupportedResourceTypes(supportedVolumeTypes); String operationalStatus = determineOperationalStatus(poolInstance); if (!newPool && (ImplicitPoolMatcher.checkPoolPropertiesChanged( pool.getOperationalStatus(), operationalStatus) || ImplicitPoolMatcher.checkPoolPropertiesChanged(pool.getProtocols(), protocols) || ImplicitPoolMatcher.checkPoolPropertiesChanged( pool.getCompatibilityStatus(), DiscoveredDataObject.CompatibilityStatus.COMPATIBLE.name()) || ImplicitPoolMatcher.checkPoolPropertiesChanged( pool.getDiscoveryStatus(), DiscoveredDataObject.DiscoveryStatus.VISIBLE.name()))) { modifiedPool = true; } pool.addProtocols(protocols); pool.setOperationalStatus(operationalStatus); pool.setCompatibilityStatus(DiscoveredDataObject.CompatibilityStatus.COMPATIBLE.name()); pool.setDiscoveryStatus(DiscoveredDataObject.DiscoveryStatus.VISIBLE.name()); Set<String> diskDrives = new HashSet<String>(); String driveTypes = getCIMPropertyValue(poolInstance, EMC_DRIVE_TYPE); if (null != driveTypes) { String driveTypesArr[] = driveTypes.split(SPACE_STR_DELIM); if (device.checkIfVmax3() && driveTypesArr.length == 1 && driveTypesArr[0].equals(MIXED_DRIVE_TYPE)) { driveTypesArr = getVMAX3PoolDriveTypes(device, poolInstance); } for (String driveType : driveTypesArr) { String driveDisplayName = SupportedDriveTypeValues.getDiskDriveDisplayName(driveType); if (null == driveDisplayName) { _logger.warn( "UnSupported DiskDrive Type : {} resulting in drives not getting discovered for this pool: {}", driveType, getCIMPropertyValue(poolInstance, Constants.INSTANCEID)); continue; } diskDrives.add(driveDisplayName); } if (!newPool && !modifiedPool && ImplicitPoolMatcher.checkPoolPropertiesChanged( pool.getSupportedDriveTypes(), diskDrives)) { modifiedPool = true; } pool.addDriveTypes(diskDrives); } _logger.info("Discovered disk drives:[{}] for pool id:{}", driveTypes, pool.getId()); if (newPool) { _newPoolList.add(pool); // add new pools to modified pools list to consider them for implicit pool matching. if (!poolsToMatchWithVpool.containsKey(pool.getId())) { poolsToMatchWithVpool.put(pool.getId(), pool); } } else { _updatePoolList.add(pool); // add to modified pool list if pool's property which is required for vPool matcher, has // changed. // No need to check whether the pool is already there in the list here // because this processor is the first to discover pools. if (modifiedPool && !poolsToMatchWithVpool.containsKey(pool.getId())) { poolsToMatchWithVpool.put(pool.getId(), pool); } } }