/* * Copyright 2016 Dell Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.emc.storageos.driver.dellsc.helpers; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.driver.dellsc.DellSCDriverException; import com.emc.storageos.driver.dellsc.DellSCDriverTask; import com.emc.storageos.driver.dellsc.scapi.SizeUtil; import com.emc.storageos.driver.dellsc.scapi.StorageCenterAPI; import com.emc.storageos.driver.dellsc.scapi.StorageCenterAPIException; import com.emc.storageos.driver.dellsc.scapi.objects.ScCopyMirrorMigrate; import com.emc.storageos.driver.dellsc.scapi.objects.ScVolume; import com.emc.storageos.storagedriver.DriverTask; import com.emc.storageos.storagedriver.DriverTask.TaskStatus; import com.emc.storageos.storagedriver.model.VolumeMirror; import com.emc.storageos.storagedriver.model.VolumeMirror.SynchronizationState; /** * Helper for mirroring operations. */ public class DellSCMirroring { private static final Logger LOG = LoggerFactory.getLogger(DellSCMirroring.class); private DellSCConnectionManager connectionManager; /** * Initialize the instance. */ public DellSCMirroring() { this.connectionManager = DellSCConnectionManager.getInstance(); } /** * Create volume mirrors. * * @param mirrors The volume mirrors to create. * @return The creation task. */ public DriverTask createVolumeMirror(List<VolumeMirror> mirrors) { LOG.info("Creating volume mirror"); DriverTask task = new DellSCDriverTask("createVolumeMirror"); StringBuilder errBuffer = new StringBuilder(); int mirrorsCreated = 0; for (VolumeMirror mirror : mirrors) { LOG.debug("Creating mirror of volume {}", mirror.getParentId()); String ssn = mirror.getStorageSystemId(); try { StorageCenterAPI api = connectionManager.getConnection(ssn); ScVolume srcVol = api.getVolume(mirror.getParentId()); ScVolume destVol = api.createVolume( ssn, mirror.getDisplayName(), srcVol.storageType.instanceId, SizeUtil.byteToMeg( SizeUtil.sizeStrToBytes(srcVol.configuredSize)), null); ScCopyMirrorMigrate scCmm = api.createMirror(ssn, srcVol.instanceId, destVol.instanceId); mirror.setNativeId(scCmm.instanceId); mirror.setSyncState(SynchronizationState.COPYINPROGRESS); mirrorsCreated++; LOG.info("Created volume mirror '{}'", scCmm.instanceId); } catch (StorageCenterAPIException | DellSCDriverException dex) { String error = String.format("Error creating volume mirror %s: %s", mirror.getDisplayName(), dex); LOG.error(error); errBuffer.append(String.format("%s%n", error)); } } task.setMessage(errBuffer.toString()); if (mirrorsCreated == mirrors.size()) { task.setStatus(TaskStatus.READY); } else if (mirrorsCreated == 0) { task.setStatus(TaskStatus.FAILED); } else { task.setStatus(TaskStatus.PARTIALLY_FAILED); } return task; } /** * Delete volume mirror and the destination volume. * * @param mirror The mirror to delete. * @return The delete task. */ public DriverTask deleteVolumeMirror(VolumeMirror mirror) { LOG.info("Deleting volume mirror {}", mirror); DellSCDriverTask task = new DellSCDriverTask("deleteVolumeMirror"); try { StorageCenterAPI api = connectionManager.getConnection(mirror.getStorageSystemId()); ScCopyMirrorMigrate cmm = api.getMirror(mirror.getNativeId()); api.deleteMirror(cmm.instanceId); api.deleteVolume(cmm.destinationVolume.instanceId); task.setStatus(TaskStatus.READY); } catch (StorageCenterAPIException | DellSCDriverException dex) { String error = String.format( "Error deleting volume mirror %s: %s", mirror.getNativeId(), dex); LOG.error(error); task.setFailed(error); } return task; } /** * Delete volume mirror but leave the destination volume intact. * * @param mirrors The mirrors to split. * @return The split task. */ public DriverTask splitVolumeMirror(List<VolumeMirror> mirrors) { LOG.info("Splitting volume mirror"); DellSCDriverTask task = new DellSCDriverTask("splitVolumeMirror"); StringBuilder errBuffer = new StringBuilder(); int mirrorSplit = 0; for (VolumeMirror mirror : mirrors) { try { StorageCenterAPI api = connectionManager.getConnection(mirror.getStorageSystemId()); api.deleteMirror(mirror.getNativeId()); task.setStatus(TaskStatus.READY); mirrorSplit++; } catch (StorageCenterAPIException | DellSCDriverException dex) { String error = String.format("Error splitting volume mirror %s: %s", mirror.getDisplayName(), dex); LOG.error(error); errBuffer.append(String.format("%s%n", error)); } } task.setMessage(errBuffer.toString()); if (mirrorSplit == mirrors.size()) { task.setStatus(TaskStatus.READY); } else if (mirrorSplit == 0) { task.setStatus(TaskStatus.FAILED); } else { task.setStatus(TaskStatus.PARTIALLY_FAILED); } return task; } /** * Resume volume mirrors. Not supported as once a mirror is split, * we no longer have any way of knowing what the target was. * * @param mirrors The mirrors to resume. * @return The mirror task. */ public DriverTask resumeVolumeMirror(List<VolumeMirror> mirrors) { LOG.info("Resuming volume mirror not supported."); DriverTask task = new DellSCDriverTask("resumeVolumeMirror"); task.setStatus(TaskStatus.FAILED); return null; } /** * Restore a volume mirror. * * @param mirrors The mirrors. * @return The driver task. */ public DriverTask restoreVolumeMirror(List<VolumeMirror> mirrors) { LOG.info("Restoring volume mirror not supported"); // Need to determine what this expects. Mirrors are... mirrored. So // nothing to restore to in SC terms. DriverTask task = new DellSCDriverTask("restoreVolumeMirror"); task.setStatus(TaskStatus.FAILED); return null; } }