/* * Copyright (c) 2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl.vnxe.job; import java.net.URI; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.Iterator; 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.constraint.AlternateIdConstraint; import com.emc.storageos.db.client.constraint.URIQueryResultList; 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.ResourceOnlyNameGenerator; import com.emc.storageos.vnxe.VNXeApiClient; import com.emc.storageos.vnxe.models.ParametersOut; import com.emc.storageos.vnxe.models.VNXeCommandJob; import com.emc.storageos.vnxe.models.VNXeLun; import com.emc.storageos.vnxe.models.VNXeLunGroupSnap; import com.emc.storageos.vnxe.models.VNXeLunSnap; import com.emc.storageos.volumecontroller.JobContext; import com.emc.storageos.volumecontroller.TaskCompleter; import com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator; import com.emc.storageos.volumecontroller.impl.smis.SmisConstants; public class VNXeBlockRestoreSnapshotJob extends VNXeJob { private static final long serialVersionUID = -1641333012646703948L; private static final Logger _logger = LoggerFactory.getLogger(VNXeBlockRestoreSnapshotJob.class); public VNXeBlockRestoreSnapshotJob(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); 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(); if (snapshotObj.getConsistencyGroup() != null) { VNXeLunGroupSnap backupSnap = vnxeApiClient.getLunGroupSnapshot(backUpSnapId); List<VNXeLun> groupLuns = vnxeApiClient.getLunByStorageResourceId(backupSnap.getStorageResource().getId()); // Create a snapshot corresponding to the backup snap for each volume in the consistency group URI cgID = snapshotObj.getConsistencyGroup(); List<Volume> cgVolumes = getCGVolumes(cgID.toString(), dbClient); final List<BlockSnapshot> snapshotList = new ArrayList<BlockSnapshot>(); Map<String, BlockSnapshot> volumeToSnapMap = new HashMap<String, BlockSnapshot>(); for (Volume vol : cgVolumes) { final BlockSnapshot newSnap = getSnapshotFromVol(vol, backupSnap.getName()); newSnap.setOpStatus(new OpStatusMap()); snapshotList.add(newSnap); volumeToSnapMap.put(vol.getNativeId(), newSnap); } // Add vnxe information to the new snapshots for (VNXeLun groupLun : groupLuns) { BlockSnapshot snapshot = volumeToSnapMap.get(groupLun.getId()); if (snapshot == null) { _logger.info("No snapshot found for the vnxe lun - ", groupLun.getId()); continue; } snapshot.setNativeId(backUpSnapId); snapshot.setReplicationGroupInstance(backUpSnapId); processSnapshot(snapshot, storage, groupLun, dbClient); } dbClient.createObject(snapshotList); } else { VNXeLunSnap backupSnap = vnxeApiClient.getLunSnapshot(backUpSnapId); VNXeLun lun = vnxeApiClient.getLun(backupSnap.getLun().getId()); Volume vol = dbClient.queryObject(Volume.class, snapshotObj.getParent()); final BlockSnapshot newSnap = getSnapshotFromVol(vol, backupSnap.getName()); newSnap.setNativeId(backUpSnapId); processSnapshot(newSnap, storage, lun, 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); } } private BlockSnapshot getSnapshotFromVol(final Volume volume, final String label) { BlockSnapshot createdSnap = new BlockSnapshot(); createdSnap.setId(URIUtil.createId(BlockSnapshot.class)); createdSnap.setConsistencyGroup(volume.getConsistencyGroup()); createdSnap.setSourceNativeId(volume.getNativeId()); createdSnap.setParent(new NamedURI(volume.getId(), label)); createdSnap.setLabel(label); createdSnap.setStorageController(volume.getStorageController()); createdSnap.setSystemType(volume.getSystemType()); createdSnap.setVirtualArray(volume.getVirtualArray()); createdSnap.setProtocol(new StringSet()); createdSnap.getProtocol().addAll(volume.getProtocol()); createdSnap.setProject(new NamedURI(volume.getProject().getURI(), label)); createdSnap.setSnapsetLabel(ResourceOnlyNameGenerator.removeSpecialCharsForName(label, SmisConstants.MAX_SNAPSHOT_NAME_LENGTH)); return createdSnap; } private void processSnapshot(BlockSnapshot snapshot, StorageSystem storage, VNXeLun lun, DbClient dbClient) { snapshot.setNativeGuid(NativeGUIDGenerator.generateNativeGuid(storage, snapshot)); snapshot.setDeviceLabel(lun.getName()); snapshot.setIsSyncActive(true); snapshot.setInactive(false); snapshot.setCreationTime(Calendar.getInstance()); snapshot.setWWN(lun.getSnapWwn()); snapshot.setAllocatedCapacity(lun.getSnapsSizeAllocated()); snapshot.setProvisionedCapacity(lun.getSnapsSize()); _logger.info(String.format("Going to set blocksnapshot %1$s nativeId to %2$s (%3$s). Associated lun is %4$s (%5$s)", snapshot.getId().toString(), lun.getStorageResource().getId(), snapshot.getLabel(), lun.getId(), lun.getName())); } private List<Volume> getCGVolumes(String cgID, DbClient dbClient) { List<Volume> volumes = new ArrayList<Volume>(); final URIQueryResultList uriQueryResultList = new URIQueryResultList(); dbClient.queryByConstraint(AlternateIdConstraint.Factory .getBlockObjectsByConsistencyGroup(cgID), uriQueryResultList); Iterator<Volume> volumeIterator = dbClient.queryIterativeObjects(Volume.class, uriQueryResultList); while (volumeIterator.hasNext()) { Volume next = volumeIterator.next(); if (!next.getInactive()) { volumes.add(next); } } return volumes; } }