/*
* Copyright (c) 2014 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.vnxe.job;
import java.net.URI;
import java.util.List;
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.ContainmentConstraint;
import com.emc.storageos.db.client.model.FSExportMap;
import com.emc.storageos.db.client.model.FileExport;
import com.emc.storageos.db.client.model.FileExportRule;
import com.emc.storageos.db.client.model.FileShare;
import com.emc.storageos.db.client.model.Snapshot;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.db.client.util.CustomQueryUtility;
import com.emc.storageos.services.OperationTypeEnum;
import com.emc.storageos.util.ExportUtils;
import com.emc.storageos.vnxe.VNXeApiClient;
import com.emc.storageos.vnxe.models.VNXeNfsShare;
import com.emc.storageos.volumecontroller.FileShareExport;
import com.emc.storageos.volumecontroller.JobContext;
import com.emc.storageos.volumecontroller.TaskCompleter;
import com.emc.storageos.volumecontroller.impl.FileDeviceController;
public class VNXeExportFileSystemJob extends VNXeJob {
private static final long serialVersionUID = 1L;
private static final Logger _logger = LoggerFactory.getLogger(VNXeExportFileSystemJob.class);
private FileShareExport exportInfo;
private boolean isFile;
private String shareName;
public VNXeExportFileSystemJob(String jobId, URI storageSystemUri,
TaskCompleter taskCompleter, FileShareExport export, String shareName, boolean isFile) {
super(jobId, storageSystemUri, taskCompleter, "exportFileSystem");
this.exportInfo = export;
this.isFile = isFile;
this.shareName = shareName;
}
/**
* Called to update the job status when the export file system job completes.
*
* @param jobContext The job context.
*/
@Override
public void updateStatus(JobContext jobContext) throws Exception {
DbClient dbClient = jobContext.getDbClient();
try {
if (_status == JobStatus.IN_PROGRESS) {
return;
}
VNXeApiClient vnxeApiClient = getVNXeClient(jobContext);
String opId = getTaskCompleter().getOpId();
StringBuilder logMsgBuilder = new StringBuilder(String.format("Updating status of job %s to %s", opId, _status.name()));
FileShare fsObj = null;
Snapshot snapObj = null;
URI objId = getTaskCompleter().getId();
StorageSystem storageObj = dbClient.queryObject(StorageSystem.class, getStorageSystemUri());
if (_status == JobStatus.SUCCESS) {
_isSuccess = true;
FileExport newExport = exportInfo.getFileExport();
newExport.setMountPoint(ExportUtils.getFileMountPoint(exportInfo.getStoragePort(), exportInfo.getMountPath()));
if (isFile) {
fsObj = dbClient.queryObject(FileShare.class, objId);
updateFSExport(fsObj, dbClient, vnxeApiClient, newExport);
} else {
snapObj = updateSnapExport(dbClient, vnxeApiClient, newExport);
fsObj = dbClient.queryObject(FileShare.class, snapObj.getParent().getURI());
}
} else if (_status == JobStatus.FAILED) {
// cleanupFSExport(fsObj, dbClient);
logMsgBuilder.append("\n");
logMsgBuilder.append(String.format(
"Task %s failed to export file system: %s", opId, objId.toString()));
}
_logger.info(logMsgBuilder.toString());
if (isFile) {
fsObj = dbClient.queryObject(FileShare.class, objId);
FileDeviceController.recordFileDeviceOperation(dbClient, OperationTypeEnum.EXPORT_FILE_SYSTEM,
_isSuccess, logMsgBuilder.toString(), "", fsObj, storageObj);
} else {
snapObj = dbClient.queryObject(Snapshot.class, objId);
fsObj = dbClient.queryObject(FileShare.class, snapObj.getParent().getURI());
FileDeviceController.recordFileDeviceOperation(dbClient, OperationTypeEnum.EXPORT_FILE_SNAPSHOT,
_isSuccess, logMsgBuilder.toString(), "", snapObj, fsObj, storageObj);
}
} catch (Exception e) {
_logger.error("Caught an exception while trying to updateStatus for VNXeExportFIleSystemJob", e);
setErrorStatus("Encountered an internal error during file system export job status processing : " + e.getMessage());
} finally {
super.updateStatus(jobContext);
}
}
/**
* update FileShare after exported in VNXe
*
* @param fsOjb fileShare object in vipr
* @param dbClient DbClient
* @param vnxeApiClient VNXeApiClient
*/
private void updateFSExport(FileShare fsObj, DbClient dbClient, VNXeApiClient apiClient, FileExport newExport) {
_logger.info("upading file export. ");
FSExportMap exports = fsObj.getFsExports();
if (exports == null) {
exports = new FSExportMap();
}
VNXeNfsShare nfsShare = apiClient.findNfsShare(fsObj.getNativeId(), shareName);
String nfsShareId = nfsShare.getId();
newExport.setIsilonId(nfsShareId);
exports.put(newExport.getFileExportKey(), newExport);
fsObj.setFsExports(exports);
updateExportRules(fsObj.getId(), newExport, dbClient);
dbClient.persistObject(fsObj);
}
private void updateExportRules(URI uri, FileExport fileExport, DbClient dbClient) {
List<FileExportRule> existingRules = queryFileExports(uri, dbClient);
FileExportRule newRule = getFileExportRule(uri, fileExport);
if (existingRules != null && existingRules.isEmpty()) {
newRule.setId(URIUtil.createId(FileExportRule.class));
_logger.info("No Existing rules available for this FS Export and so creating the rule now {}", newRule);
dbClient.createObject(newRule);
}
else {
_logger.debug("Checking inside for ExitingRule(s) available for this export");
boolean isRuleFound = false;
for (FileExportRule rule : existingRules) {
_logger.debug("Available Export Rule {} - Matching with New Rule {}", rule, newRule);
if (newRule.getFsExportIndex() != null && rule.getFsExportIndex().equals(newRule.getFsExportIndex())) {
isRuleFound = true;
_logger.info("Match Found : Skipping this Rule as alreday available {}", newRule);
break;
}
}
if (!isRuleFound) {
_logger.info("Creating new Export Rule {}", newRule);
newRule.setId(URIUtil.createId(FileExportRule.class));
dbClient.createObject(newRule);
}
}
}
private FileExportRule getFileExportRule(URI uri, FileExport fileExport) {
FileExportRule rule = new FileExportRule();
rule.setAnon(fileExport.getRootUserMapping());
rule.setExportPath(fileExport.getPath());
if (!isFile)
{
rule.setSnapshotId(uri);
} else {
rule.setFileSystemId(uri);
}
rule.setSecFlavor(fileExport.getSecurityType());
if (fileExport.getPermissions().equals(FileShareExport.Permissions.ro.name())
&& fileExport.getClients() != null && !fileExport.getClients().isEmpty()) {
rule.setReadOnlyHosts(new StringSet(fileExport.getClients()));
}
if (fileExport.getPermissions().equals(FileShareExport.Permissions.rw.name())
&& fileExport.getClients() != null && !fileExport.getClients().isEmpty()) {
rule.setReadWriteHosts(new StringSet(fileExport.getClients()));
}
if (fileExport.getPermissions().equals(FileShareExport.Permissions.root.name())
&& fileExport.getClients() != null && !fileExport.getClients().isEmpty()) {
rule.setRootHosts(new StringSet(fileExport.getClients()));
}
rule.setMountPoint(fileExport.getMountPoint());
_logger.info("Generating FileExportRule IsilonId ? {}", fileExport.getIsilonId());
if (fileExport.getIsilonId() != null) {
rule.setDeviceExportId(fileExport.getIsilonId());
}
return rule;
}
private List<FileExportRule> queryFileExports(URI uri, DbClient dbClient)
{
List<FileExportRule> fileExportRules = null;
try {
ContainmentConstraint containmentConstraint;
if (isFile) {
_logger.info("Querying all ExportRules Using FsId {}", uri);
containmentConstraint = ContainmentConstraint.Factory.getFileExportRulesConstraint(uri);
} else {
_logger.info("Querying all ExportRules Using Snapshot Id {}", uri);
containmentConstraint = ContainmentConstraint.Factory.getSnapshotExportRulesConstraint(uri);
}
fileExportRules = CustomQueryUtility.queryActiveResourcesByConstraint(dbClient, FileExportRule.class,
containmentConstraint);
} catch (Exception e) {
_logger.error("Error while querying {}", e);
}
return fileExportRules;
}
/**
* update snapshot if the export job is for snapshot export
*
* @param dbClient
* @param apiClient
* @return Snapshot instance
*/
private Snapshot updateSnapExport(DbClient dbClient, VNXeApiClient apiClient, FileExport newExport) {
_logger.info("upading snap export. ");
URI snapId = getTaskCompleter().getId();
Snapshot snapObj = dbClient.queryObject(Snapshot.class, snapId);
FSExportMap exports = snapObj.getFsExports();
if (exports == null) {
exports = new FSExportMap();
}
VNXeNfsShare nfsShare = apiClient.findSnapNfsShare(snapObj.getNativeId(), shareName);
String nfsShareId = nfsShare.getId();
newExport.setIsilonId(nfsShareId);
exports.put(newExport.getFileExportKey(), newExport);
snapObj.setFsExports(exports);
updateExportRules(snapObj.getId(), newExport, dbClient);
dbClient.persistObject(snapObj);
return snapObj;
}
}