/* * 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.DellSCUtil; import com.emc.storageos.driver.dellsc.scapi.StorageCenterAPI; import com.emc.storageos.driver.dellsc.scapi.StorageCenterAPIException; import com.emc.storageos.driver.dellsc.scapi.objects.ScReplay; import com.emc.storageos.driver.dellsc.scapi.objects.ScReplayProfile; 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.StorageVolume; import com.emc.storageos.storagedriver.model.VolumeConsistencyGroup; import com.emc.storageos.storagedriver.model.VolumeSnapshot; import com.emc.storageos.storagedriver.storagecapabilities.CapabilityInstance; import com.emc.storageos.storagedriver.storagecapabilities.StorageCapabilities; /** * Consistency group handling. */ public class DellSCConsistencyGroups { private static final Logger LOG = LoggerFactory.getLogger(DellSCConsistencyGroups.class); private DellSCConnectionManager connectionManager; private DellSCUtil util; /** * Initialize the instance. */ public DellSCConsistencyGroups() { this.connectionManager = DellSCConnectionManager.getInstance(); this.util = DellSCUtil.getInstance(); } /** * Create a consistency group. * * @param volumeConsistencyGroup The group to create. * @return The consistency group creation task. */ public DriverTask createConsistencyGroup(VolumeConsistencyGroup volumeConsistencyGroup) { DellSCDriverTask task = new DellSCDriverTask("createConsistencyGroup"); String ssn = volumeConsistencyGroup.getStorageSystemId(); try { StorageCenterAPI api = connectionManager.getConnection(ssn); ScReplayProfile cg = api.createConsistencyGroup( ssn, volumeConsistencyGroup.getDisplayName()); util.getVolumeConsistencyGroupFromReplayProfile(cg, volumeConsistencyGroup); task.setStatus(TaskStatus.READY); } catch (StorageCenterAPIException | DellSCDriverException dex) { String error = String.format("Error creating CG %s: %s", volumeConsistencyGroup.getDisplayName(), dex); LOG.error(error); task.setFailed(error); } return task; } /** * Add volumes to consistency groups. * * @param volumes The volumes to add. * @param capabilities The requested capabilities. * @return The driver task. */ public DriverTask addVolumesToConsistencyGroup(List<StorageVolume> volumes, StorageCapabilities capabilities) { DellSCDriverTask task = new DellSCDriverTask("addVolumesToCG"); StringBuilder errBuffer = new StringBuilder(); int addCount = 0; for (StorageVolume volume : volumes) { String ssn = volume.getStorageSystemId(); try { StorageCenterAPI api = connectionManager.getConnection(ssn); api.addVolumeToConsistencyGroup(volume.getNativeId(), volume.getConsistencyGroup()); addCount++; } catch (StorageCenterAPIException | DellSCDriverException dex) { String error = String.format( "Error adding volume %s to consistency group: %s", volume.getNativeId(), dex); LOG.warn(error); errBuffer.append(String.format("%s%n", error)); } } task.setMessage(errBuffer.toString()); if (addCount == volumes.size()) { task.setStatus(TaskStatus.READY); } else if (addCount == 0) { task.setStatus(TaskStatus.FAILED); } else { task.setStatus(TaskStatus.PARTIALLY_FAILED); } return task; } /** * Remove volumes from consistency groups. * * @param volumes The volumes. * @param capabilities The requested capabilities. * @return The driver task. */ public DriverTask removeVolumesFromConsistencyGroup(List<StorageVolume> volumes, StorageCapabilities capabilities) { DellSCDriverTask task = new DellSCDriverTask("removeVolumeFromCG"); StringBuilder errBuffer = new StringBuilder(); int removeCount = 0; for (StorageVolume volume : volumes) { String ssn = volume.getStorageSystemId(); try { StorageCenterAPI api = connectionManager.getConnection(ssn); api.removeVolumeFromConsistencyGroup(volume.getNativeId(), volume.getConsistencyGroup()); removeCount++; } catch (StorageCenterAPIException | DellSCDriverException dex) { String error = String.format( "Error adding volume %s to consistency group: %s", volume.getNativeId(), dex); LOG.warn(error); errBuffer.append(String.format("%s%n", error)); } } task.setMessage(errBuffer.toString()); if (removeCount == volumes.size()) { task.setStatus(TaskStatus.READY); } else if (removeCount == 0) { task.setStatus(TaskStatus.FAILED); } else { task.setStatus(TaskStatus.PARTIALLY_FAILED); } return task; } /** * Delete a consistency group. * * @param volumeConsistencyGroup The group to delete. * @return The consistency group delete task. */ public DriverTask deleteConsistencyGroup(VolumeConsistencyGroup volumeConsistencyGroup) { DellSCDriverTask task = new DellSCDriverTask("deleteVolume"); try { StorageCenterAPI api = connectionManager.getConnection(volumeConsistencyGroup.getStorageSystemId()); ScReplayProfile[] cgs = api.getConsistencyGroups(volumeConsistencyGroup.getStorageSystemId()); for (ScReplayProfile cg : cgs) { if (cg.instanceId.equals(volumeConsistencyGroup.getNativeId())) { api.deleteConsistencyGroup(cg.instanceId); break; } } // We either deleted the CG or it was not found, either way we are fine task.setStatus(TaskStatus.READY); } catch (StorageCenterAPIException | DellSCDriverException dex) { String error = String.format("Error deleting CG %s: %s", volumeConsistencyGroup.getDisplayName(), dex); LOG.error(error); task.setFailed(error); } return task; } /** * Create consistency group snapshots. * * @param volumeConsistencyGroup The consistency group. * @param snapshots The snapshots. * @param capabilities The requested capabilities. * @return The create task. */ public DriverTask createConsistencyGroupSnapshot(VolumeConsistencyGroup volumeConsistencyGroup, List<VolumeSnapshot> snapshots, List<CapabilityInstance> capabilities) { DellSCDriverTask task = new DellSCDriverTask("createCGSnapshot"); try { StorageCenterAPI api = connectionManager.getConnection(volumeConsistencyGroup.getStorageSystemId()); // Make sure all of our volumes are active for the automated tests that try to // snap right away before writing anything to them. ScVolume[] volumes = api.getConsistencyGroupVolumes(volumeConsistencyGroup.getNativeId()); for (ScVolume volume : volumes) { api.checkAndInitVolume(volume.instanceId); } ScReplay[] replays = api.createConsistencyGroupSnapshots(volumeConsistencyGroup.getNativeId()); if (populateCgSnapshotInfo(snapshots, replays)) { task.setStatus(TaskStatus.READY); } else { task.setStatus(TaskStatus.PARTIALLY_FAILED); } } catch (StorageCenterAPIException | DellSCDriverException dex) { String error = String.format("Error creating CG snapshots %s: %s", volumeConsistencyGroup.getDisplayName(), dex); LOG.error(error); task.setFailed(error); } return task; } /** * Populates VolumeSnapshot info from CG created replays. * * @param snapshots The expected VolumeSnapshot objects. * @param replays The created replays. * @return True if successful, false if errors encountered. */ private boolean populateCgSnapshotInfo(List<VolumeSnapshot> snapshots, ScReplay[] replays) { boolean complete = true; for (VolumeSnapshot snapshot : snapshots) { boolean found = false; for (ScReplay replay : replays) { if (replay.instanceId.startsWith(snapshot.getParentId())) { // Found match, populate the info util.getVolumeSnapshotFromReplay(replay, snapshot); found = true; break; } } if (!found) { complete = false; LOG.warn("Unable to find snapshot for {}", snapshot.getDisplayName()); } } return complete; } }