/* * Copyright (c) 2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.block.taskcompleter; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.Operation; import com.emc.storageos.db.client.model.Volume; import com.emc.storageos.db.client.util.NullColumnValueGetter; import com.emc.storageos.services.OperationTypeEnum; import com.emc.storageos.svcs.errorhandling.model.ServiceCoded; import com.emc.storageos.util.VPlexUtil; public class VolumeVpoolAutoTieringPolicyChangeTaskCompleter extends VolumeVpoolChangeTaskCompleter { private static final Logger _logger = LoggerFactory .getLogger(VolumeVpoolAutoTieringPolicyChangeTaskCompleter.class); /** * If volumes are from different storage system and if the target vPool has * unique AutoTieringPolicy flag enabled, each volume will have policy URI * associated with its own system. */ private Map<URI, URI> oldVolToPolicyMap; public VolumeVpoolAutoTieringPolicyChangeTaskCompleter(URI volumeURI, URI oldVpool, Map<URI, URI> oldVolToPolicyMap, String task) { super(volumeURI, oldVpool, task); this.oldVolToPolicyMap = oldVolToPolicyMap; } public VolumeVpoolAutoTieringPolicyChangeTaskCompleter(List<URI> volumeURIs, URI oldVpool, Map<URI, URI> oldVolToPolicyMap, String task) { super(volumeURIs, oldVpool, task); this.oldVolToPolicyMap = oldVolToPolicyMap; } @Override protected void complete(DbClient dbClient, Operation.Status status, ServiceCoded serviceCoded) { switch (status) { case error: _log.error( "An error occurred during virtual pool change " + "- restore the old auto tiering policy to the volume(s): {}", serviceCoded.getMessage()); List<Volume> volumesToUpdate = new ArrayList<Volume>(); for (URI id : getIds()) { Volume volume = dbClient.queryObject(Volume.class, id); _log.info("rolling back auto tiering policy on volume {}({})", id, volume.getLabel()); URI policyURI = oldVolToPolicyMap.get(id); if (policyURI == null) { policyURI = NullColumnValueGetter.getNullURI(); } volume.setAutoTieringPolicyUri(policyURI); _log.info("set volume's auto tiering policy back to {}", policyURI); volumesToUpdate.add(volume); rollBackPolicyOnVplexBackendVolume(volume, volumesToUpdate, dbClient); } dbClient.updateObject(volumesToUpdate); break; case ready: // The new auto tiering policy has already been stored in the volume // in BlockDeviceExportController. // record event. OperationTypeEnum opType = OperationTypeEnum.CHANGE_VOLUME_AUTO_TIERING_POLICY; try { boolean opStatus = (Operation.Status.ready == status) ? true : false; String evType = opType.getEvType(opStatus); String evDesc = opType.getDescription(); for (URI id : getIds()) { recordBourneVolumeEvent(dbClient, id, evType, status, evDesc); } } catch (Exception ex) { _logger.error( "Failed to record block volume operation {}, err: {}", opType.toString(), ex); } break; default: break; } super.complete(dbClient, status, serviceCoded); } /** * Roll back policy on vplex backend volumes. */ private void rollBackPolicyOnVplexBackendVolume(Volume volume, List<Volume> volumesToUpdate, DbClient dbClient) { // Check if it is a VPlex volume, and get backend volumes Volume backendSrc = VPlexUtil.getVPLEXBackendVolume(volume, true, dbClient, false); if (backendSrc != null) { _log.info("rolling back auto tiering policy on VPLEX backend source volume {}({})", backendSrc.getId(), backendSrc.getLabel()); URI policyURI = oldVolToPolicyMap.get(backendSrc.getId()); if (policyURI == null) { policyURI = NullColumnValueGetter.getNullURI(); } backendSrc.setAutoTieringPolicyUri(policyURI); _log.info("set volume's auto tiering policy back to {}", policyURI); volumesToUpdate.add(backendSrc); // VPlex volume, check if it is distributed Volume backendHa = VPlexUtil.getVPLEXBackendVolume(volume, false, dbClient, false); if (backendHa != null) { _log.info("rolling back auto tiering policy on VPLEX backend distributed volume {}({})", backendHa.getId(), backendHa.getLabel()); policyURI = oldVolToPolicyMap.get(backendHa.getId()); if (policyURI == null) { policyURI = NullColumnValueGetter.getNullURI(); } backendHa.setAutoTieringPolicyUri(policyURI); _log.info("set volume's auto tiering policy back to {}", policyURI); volumesToUpdate.add(backendHa); } } } }