/* * Copyright (c) 2016 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.vnxunity.job; import java.net.URI; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; 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.URIUtil; import com.emc.storageos.db.client.model.BlockObject; import com.emc.storageos.db.client.model.BlockSnapshot; import com.emc.storageos.db.client.model.NamedURI; import com.emc.storageos.db.client.model.OpStatusMap; import com.emc.storageos.db.client.model.StorageSystem; import com.emc.storageos.db.client.model.StringSet; import com.emc.storageos.db.client.model.Volume; import com.emc.storageos.db.client.util.NullColumnValueGetter; import com.emc.storageos.db.client.util.ResourceOnlyNameGenerator; import com.emc.storageos.vnxe.VNXeApiClient; import com.emc.storageos.vnxe.models.ParametersOut; import com.emc.storageos.vnxe.models.Snap; import com.emc.storageos.vnxe.models.VNXeCommandJob; import com.emc.storageos.volumecontroller.JobContext; import com.emc.storageos.volumecontroller.TaskCompleter; import com.emc.storageos.volumecontroller.impl.ControllerUtils; import com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator; import com.emc.storageos.volumecontroller.impl.smis.SmisConstants; import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeJob; public class VNXUnityRestoreSnapshotJob extends VNXeJob { /** * */ private static final long serialVersionUID = 5317802800817893517L; private static final Logger _logger = LoggerFactory.getLogger(VNXUnityRestoreSnapshotJob.class); public VNXUnityRestoreSnapshotJob(String jobId, URI storageSystemUri, TaskCompleter taskCompleter) { super(jobId, storageSystemUri, taskCompleter, "RestoreSnapshot"); } public void updateStatus(JobContext jobContext) throws Exception { DbClient dbClient = jobContext.getDbClient(); try { if (_status == JobStatus.IN_PROGRESS) { return; } String opId = getTaskCompleter().getOpId(); _logger.info(String.format("Updating status of job %s to %s", opId, _status.name())); URI snapId = getTaskCompleter().getId(); BlockSnapshot snapshotObj = dbClient.queryObject(BlockSnapshot.class, snapId); URI projectUri = snapshotObj.getProject().getURI(); StorageSystem storage = dbClient.queryObject(StorageSystem.class, getStorageSystemUri()); if (_status == JobStatus.SUCCESS && snapshotObj != null) { VNXeApiClient vnxeApiClient = getVNXeClient(jobContext); VNXeCommandJob vnxeJob = vnxeApiClient.getJob(getJobIds().get(0)); ParametersOut output = vnxeJob.getParametersOut(); // get the id of the backup snapshot created before restore operation String backUpSnapId = output.getBackup().getId(); Snap backupSnap = vnxeApiClient.getSnapshot(backUpSnapId); if (NullColumnValueGetter.isNotNullValue(snapshotObj.getReplicationGroupInstance())) { List<BlockSnapshot> snapshots = ControllerUtils.getSnapshotsPartOfReplicationGroup(snapshotObj, dbClient); // Create a snapshot corresponding to the backup snap for each volume in the consistency group final List<BlockSnapshot> snapshotList = new ArrayList<BlockSnapshot>(); Map<String, BlockSnapshot> volumeToSnapMap = new HashMap<String, BlockSnapshot>(); int count = 1; String setLabel = backupSnap.getName(); for (BlockSnapshot snapshot : snapshots) { BlockObject parent = BlockObject.fetch(dbClient, snapshot.getParent().getURI()); String label = String.format("%s-%s", setLabel, count++); final BlockSnapshot newSnap = initSnapshot(parent, label, setLabel, projectUri); newSnap.setOpStatus(new OpStatusMap()); snapshotList.add(newSnap); volumeToSnapMap.put(parent.getNativeId(), newSnap); } List<Snap> snaps = vnxeApiClient.getSnapshotsBySnapGroup(backUpSnapId); for (Snap snap : snaps) { String lunId = snap.getLun().getId(); BlockSnapshot snapshot = volumeToSnapMap.get(lunId); snapshot.setReplicationGroupInstance(backUpSnapId); createSnapshot(snapshot, snap, storage, dbClient); } } else { Volume vol = dbClient.queryObject(Volume.class, snapshotObj.getParent()); final BlockSnapshot newSnap = initSnapshot(vol, backupSnap.getName(), backupSnap.getName(), projectUri); createSnapshot(newSnap, backupSnap, storage, dbClient); } getTaskCompleter().ready(dbClient); } else if (_status == JobStatus.FAILED && snapshotObj != null) { _logger.info(String.format( "Task %s failed to restore volume snapshot: %s", opId, snapshotObj.getLabel())); } } catch (Exception e) { _logger.error("Caught an exception while trying to updateStatus for VNXeBlockRestoreSnapshotJob", e); setErrorStatus("Encountered an internal error during snapshot restore job status processing : " + e.getMessage()); } finally { super.updateStatus(jobContext); } } /** * Create the BlockSnapshot in DB * @param snapshot The snapshot to be created * @param unitySnap The VNX Unity snap instance * @param storage The storage system * @param dbClient */ private void createSnapshot(BlockSnapshot snapshot, Snap unitySnap, StorageSystem storage, DbClient dbClient) { snapshot.setNativeId(unitySnap.getId()); snapshot.setNativeGuid(NativeGUIDGenerator.generateNativeGuid(storage, snapshot)); snapshot.setDeviceLabel(unitySnap.getName()); snapshot.setIsSyncActive(true); snapshot.setInactive(false); snapshot.setCreationTime(Calendar.getInstance()); snapshot.setWWN(unitySnap.getAttachedWWN()); snapshot.setAllocatedCapacity(unitySnap.getSize()); snapshot.setProvisionedCapacity(unitySnap.getSize()); dbClient.createObject(snapshot); } /** * Initiate a BlockSnapshot based on its parent * @param blockObj The parent of the BlockSnapshot * @param label The snapshot label * @param setLabel The set of snapshots label * @return */ private BlockSnapshot initSnapshot(final BlockObject blockObj, final String label, final String setLabel, final URI projectUri) { BlockSnapshot createdSnap = new BlockSnapshot(); createdSnap.setId(URIUtil.createId(BlockSnapshot.class)); createdSnap.setConsistencyGroup(blockObj.getConsistencyGroup()); createdSnap.setSourceNativeId(blockObj.getNativeId()); createdSnap.setParent(new NamedURI(blockObj.getId(), label)); createdSnap.setLabel(label); createdSnap.setStorageController(blockObj.getStorageController()); createdSnap.setSystemType(blockObj.getSystemType()); createdSnap.setVirtualArray(blockObj.getVirtualArray()); createdSnap.setProtocol(new StringSet()); createdSnap.getProtocol().addAll(blockObj.getProtocol()); if (blockObj instanceof Volume ) { createdSnap.setProject(new NamedURI(projectUri, label)); } else if (blockObj instanceof BlockSnapshot) { createdSnap.setProject(new NamedURI(projectUri, label)); } createdSnap.setSnapsetLabel(ResourceOnlyNameGenerator.removeSpecialCharsForName(setLabel, SmisConstants.MAX_SNAPSHOT_NAME_LENGTH)); return createdSnap; } }