/* * Copyright (c) 2015 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 org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.model.BlockObject; import com.emc.storageos.db.client.model.ExportGroup; import com.emc.storageos.db.client.model.ExportMask; import com.emc.storageos.db.client.model.Operation; import com.emc.storageos.exceptions.DeviceControllerException; import com.emc.storageos.svcs.errorhandling.model.ServiceCoded; /** * This is a very specialized completer for use only by the VPlex Backend Manager. * It deletes a volume out of the ExportMask/ExportGroup, but will not delete the ExportMask, * even if it has no volumes, unless it was externally created (i.e. createdBySystem == false) * This is because the ExportMask may be reusued at a later time * if volumes are subsequently created by the VPlex on that Storage Array. */ public class ExportMaskOnlyRemoveVolumeCompleter extends ExportTaskCompleter { private static final Logger _log = LoggerFactory.getLogger(ExportMaskOnlyRemoveVolumeCompleter.class); private List<URI> _volumes; // URI of volumes being removed /** * Constructor for ExportMaskRemoveVolumeCompleter. * * @param egUri -- ExportGroup URI * @param emUri -- ExportMask URI * @param volumes -- List<URI> of volumes being removed. * @param task -- API task id. */ public ExportMaskOnlyRemoveVolumeCompleter(URI egUri, URI emUri, List<URI> volumes, String task) { super(ExportGroup.class, egUri, emUri, task); _volumes = new ArrayList<URI>(); _volumes.addAll(volumes); } @Override protected void complete(DbClient dbClient, Operation.Status status, ServiceCoded coded) throws DeviceControllerException { try { ExportGroup exportGroup = dbClient.queryObject(ExportGroup.class, getId()); ExportMask exportMask = (getMask() != null) ? dbClient.queryObject(ExportMask.class, getMask()) : null; for (URI volumeURI : _volumes) { BlockObject volume = BlockObject.fetch(dbClient, volumeURI); if (exportMask != null && status == Operation.Status.ready) { exportMask.removeFromUserCreatedVolumes(volume); exportMask.removeVolume(volume.getId()); exportGroup.removeVolume(volume.getId()); } } // If ViPR did not create the ExportMask, mark the ExportMask and // ExportGroup for deletion if and when they are empty. if (exportMask.getCreatedBySystem() == false && (exportMask.getVolumes() == null || exportMask.getVolumes().isEmpty())) { dbClient.markForDeletion(exportMask); dbClient.markForDeletion(exportGroup); } else { // If the ExportGroup does not contain the exportMask, add it back. exportGroup.addExportMask(getMask()); dbClient.updateObject(exportMask); dbClient.updateObject(exportGroup); } _log.info(String.format( "Done ExportMaskOnlyRemoveVolume - Id: %s, OpId: %s, status: %s", getId().toString(), getOpId(), status.name())); } catch (Exception e) { _log.error(String.format( "Failed updating status for ExportMaskOnlyRemoveVolume - Id: %s, OpId: %s", getId().toString(), getOpId()), e); } finally { super.complete(dbClient, status, coded); } } }