/*
* Copyright (c) 2014 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.hds.prov.job;
import java.net.URI;
import java.util.Calendar;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.model.BlockSnapshot;
import com.emc.storageos.db.client.model.Snapshot;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.TenantOrg;
import com.emc.storageos.db.client.model.Volume;
import com.emc.storageos.db.client.util.NameGenerator;
import com.emc.storageos.hds.HDSConstants;
import com.emc.storageos.hds.api.HDSApiClient;
import com.emc.storageos.hds.model.LDEV;
import com.emc.storageos.hds.model.LogicalUnit;
import com.emc.storageos.hds.model.ObjectLabel;
import com.emc.storageos.volumecontroller.JobContext;
import com.emc.storageos.volumecontroller.TaskCompleter;
import com.emc.storageos.volumecontroller.impl.ControllerServiceImpl;
import com.emc.storageos.volumecontroller.impl.NativeGUIDGenerator;
import com.emc.storageos.volumecontroller.impl.hds.prov.utils.HDSUtils;
public class HDSBlockCreateSnapshotJob extends HDSJob {
private static final Logger log = LoggerFactory.getLogger(HDSBlockCreateSnapshotJob.class);
// These atomic references are for use in the volume rename step in processVolume
private static final AtomicReference<NameGenerator> _nameGeneratorRef = new AtomicReference<NameGenerator>();
public HDSBlockCreateSnapshotJob(String messageId, URI storageSystem,
TaskCompleter taskCompleter) {
super(messageId, storageSystem, taskCompleter, "CreateBlockSnapshot");
// Keep a reference to these singletons
_nameGeneratorRef.compareAndSet(null,
(NameGenerator) ControllerServiceImpl.getBean("defaultNameGenerator"));
}
@Override
public void updateStatus(JobContext jobContext) throws Exception
{
DbClient dbClient = jobContext.getDbClient();
try {
// Do nothing if the job is not completed yet
if (_status == JobStatus.IN_PROGRESS)
{
return;
}
String opId = getTaskCompleter().getOpId();
StringBuilder logMsgBuilder = new StringBuilder(
String.format("Updating status of job %s to %s", opId, _status.name()));
StorageSystem storageSystem = dbClient.queryObject(StorageSystem.class, getStorageSystemURI());
HDSApiClient hdsApiClient = jobContext.getHdsApiFactory().getClient
(HDSUtils.getHDSServerManagementServerInfo(storageSystem), storageSystem.getSmisUserName(),
storageSystem.getSmisPassword());
URI snapshotId = getTaskCompleter().getId(0);
log.info("snapshotId :{}", snapshotId);
if (_status == JobStatus.SUCCESS)
{
LogicalUnit logicalUnit = (LogicalUnit) _javaResult.getBean("virtualVolume");
BlockSnapshot snapshot = dbClient.queryObject(BlockSnapshot.class, snapshotId);
snapshot.setNativeId(String.valueOf(logicalUnit.getDevNum()));
snapshot.setNativeGuid(NativeGUIDGenerator.generateNativeGuid(storageSystem, snapshot));
snapshot.setInactive(false);
snapshot.setCreationTime(Calendar.getInstance());
long capacityInBytes = Long.valueOf(logicalUnit.getCapacityInKB()) * 1024L;
snapshot.setProvisionedCapacity(capacityInBytes);
snapshot.setAllocatedCapacity(capacityInBytes);
snapshot.setWWN(HDSUtils.generateHitachiWWN(logicalUnit.getObjectID(), String.valueOf(logicalUnit.getDevNum())));
snapshot.setIsSyncActive(true);
dbClient.persistObject(snapshot);
changeSnapshotName(dbClient, hdsApiClient, snapshot);
if (logMsgBuilder.length() != 0)
{
logMsgBuilder.append("\n");
}
logMsgBuilder.append(String.format(
"Created Snapshot successfully .. NativeId: %s, URI: %s", snapshot.getNativeId(),
getTaskCompleter().getId()));
}
else if (_status == JobStatus.FAILED)
{
logMsgBuilder.append("\n");
logMsgBuilder.append(String.format(
"Task %s failed to create volume: %s", opId, getTaskCompleter().getId().toString()));
Snapshot snapshot = dbClient.queryObject(Snapshot.class, snapshotId);
if (snapshot != null) {
snapshot.setInactive(true);
dbClient.persistObject(snapshot);
}
}
log.info(logMsgBuilder.toString());
} catch (Exception e) {
log.error("Caught an exception while trying to updateStatus for HDSBlockCreateSnapshotJob", e);
setErrorStatus("Encountered an internal error during snapshot create job status processing : " + e.getMessage());
} finally {
_postProcessingStatus = JobStatus.SUCCESS;
super.updateStatus(jobContext);
}
}
/**
* Method will modify the name of a given volume to a generate name.
*
* @param dbClient [in] - Client instance for reading/writing from/to DB
* @param client [in] - HDSApiClient used for reading/writing from/to HiCommand DM.
* @param snapshotObj [in] - Volume object
*/
private void changeSnapshotName(DbClient dbClient, HDSApiClient client, BlockSnapshot snapshotObj) {
try {
Volume source = dbClient.queryObject(Volume.class, snapshotObj.getParent());
// Get the tenant name from the volume
TenantOrg tenant = dbClient.queryObject(TenantOrg.class, source.getTenant().getURI());
String tenantName = tenant.getLabel();
// Generate the name, then modify the volume instance
// that was successfully created
if (_nameGeneratorRef.get() == null) {
_nameGeneratorRef.compareAndSet(null,
(NameGenerator) ControllerServiceImpl.getBean("defaultNameGenerator"));
}
String generatedName = _nameGeneratorRef.get().generate(tenantName, snapshotObj.getLabel(),
snapshotObj.getId().toString(), '-', HDSConstants.MAX_VOLUME_NAME_LENGTH);
log.info(String.format("Attempting to add snapshot label %s to %s", generatedName, snapshotObj.getNativeId()));
StorageSystem system = dbClient.queryObject(StorageSystem.class, snapshotObj.getStorageController());
String systemObjectId = HDSUtils.getSystemObjectID(system);
LogicalUnit logicalUnit = client.getLogicalUnitInfo(systemObjectId,
HDSUtils.getLogicalUnitObjectId(snapshotObj.getNativeId(), system));
if (null != logicalUnit && null != logicalUnit.getLdevList() && !logicalUnit.getLdevList().isEmpty()) {
Iterator<LDEV> ldevItr = logicalUnit.getLdevList().iterator();
if (ldevItr.hasNext()) {
LDEV ldev = ldevItr.next();
ObjectLabel objectLabel = client.addVolumeLabel(ldev.getObjectID(), generatedName);
snapshotObj.setDeviceLabel(objectLabel.getLabel());
dbClient.persistObject(snapshotObj);
}
} else {
log.info("No LDEV's found on volume: {}", snapshotObj.getNativeId());
}
log.info(String.format("snapshot label has been added to snapshot %s", snapshotObj.getNativeId()));
} catch (Exception e) {
log.error("Encountered an error while trying to set the snapshot name", e);
}
}
}