/*
* Copyright (c) 2014 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.volumecontroller.impl.vnxunity;
import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.model.FSExportMap;
import com.emc.storageos.db.client.model.FileExport;
import com.emc.storageos.db.client.model.FileShare;
import com.emc.storageos.db.client.model.Operation;
import com.emc.storageos.db.client.model.QuotaDirectory;
import com.emc.storageos.db.client.model.SMBFileShare;
import com.emc.storageos.db.client.model.Snapshot;
import com.emc.storageos.db.client.model.StorageHADomain;
import com.emc.storageos.db.client.model.StoragePort;
import com.emc.storageos.db.client.model.StorageProtocol;
import com.emc.storageos.db.client.model.StorageSystem;
import com.emc.storageos.db.client.model.StringSet;
import com.emc.storageos.db.client.util.NameGenerator;
import com.emc.storageos.exceptions.DeviceControllerErrors;
import com.emc.storageos.exceptions.DeviceControllerException;
import com.emc.storageos.model.file.ExportRule;
import com.emc.storageos.svcs.errorhandling.model.ServiceError;
import com.emc.storageos.vnxe.VNXeApiClient;
import com.emc.storageos.vnxe.VNXeException;
import com.emc.storageos.vnxe.VNXeUtils;
import com.emc.storageos.vnxe.models.AccessEnum;
import com.emc.storageos.vnxe.models.VNXeBase;
import com.emc.storageos.vnxe.models.VNXeCommandJob;
import com.emc.storageos.vnxe.models.VNXeFSSupportedProtocolEnum;
import com.emc.storageos.vnxe.models.VNXeFileSystem;
import com.emc.storageos.vnxe.models.VNXeFileSystemSnap;
import com.emc.storageos.vnxe.models.VNXeHost;
import com.emc.storageos.vnxe.models.VNXeNfsShare;
import com.emc.storageos.volumecontroller.ControllerException;
import com.emc.storageos.volumecontroller.FileDeviceInputOutput;
import com.emc.storageos.volumecontroller.FileSMBShare;
import com.emc.storageos.volumecontroller.FileShareExport;
import com.emc.storageos.volumecontroller.FileStorageDevice;
import com.emc.storageos.volumecontroller.TaskCompleter;
import com.emc.storageos.volumecontroller.impl.BiosCommandResult;
import com.emc.storageos.volumecontroller.impl.ControllerServiceImpl;
import com.emc.storageos.volumecontroller.impl.job.QueueJob;
import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeCreateFileSystemJob;
import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeCreateFileSystemSnapshotJob;
import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeCreateShareJob;
import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeDeleteFileSystemSnapshotJob;
import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeDeleteShareJob;
import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeExpandFileSystemJob;
import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeExportFileSystemJob;
import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeFSSnapshotTaskCompleter;
import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeFileTaskCompleter;
import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeModifyExportJob;
import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeRestoreFileSystemSnapshotJob;
import com.emc.storageos.volumecontroller.impl.vnxe.job.VNXeUnexportFileSystemJob;
import com.emc.storageos.volumecontroller.impl.vnxunity.job.VNXUnityCreateFileSystemQuotaDirectoryJob;
import com.emc.storageos.volumecontroller.impl.vnxunity.job.VNXUnityDeleteFileSystemQuotaDirectoryJob;
import com.emc.storageos.volumecontroller.impl.vnxunity.job.VNXUnityQuotaDirectoryTaskCompleter;
import com.emc.storageos.volumecontroller.impl.vnxunity.job.VNXUnityUpdateFileSystemQuotaDirectoryJob;
import com.google.common.collect.Sets;
public class VNXUnityFileStorageDevice extends VNXUnityOperations
implements FileStorageDevice {
private static final Logger _logger = LoggerFactory.getLogger(VNXUnityFileStorageDevice.class);
private NameGenerator nameGenerator;
public NameGenerator getNameGenerator() {
return nameGenerator;
}
public void setNameGenerator(NameGenerator nameGenerator) {
this.nameGenerator = nameGenerator;
}
@Override
public BiosCommandResult doCreateFS(StorageSystem storage,
FileDeviceInputOutput fileInOut) throws ControllerException {
_logger.info("creating file system: ", fileInOut.getFsName());
Long fsSize = fileInOut.getFsCapacity();
if (fsSize < 1) {
// Invalid size throw an error
_logger.error("doCreateFS failed : FileSystem size in bytes is not valid {}", fileInOut.getFsCapacity());
ServiceError error = DeviceControllerErrors.vnxe.unableToCreateFileSystem("FileSystem size in bytes is not valid");
return BiosCommandResult.createErrorResult(error);
}
VNXeFileTaskCompleter completer = null;
VNXeApiClient apiClient = getVnxUnityClient(storage);
VNXeCommandJob job = null;
try {
FileShare fs = fileInOut.getFs();
URI port = fs.getStoragePort();
if (port == null) {
_logger.error("No storageport uri found in the fs");
ServiceError error = DeviceControllerErrors.vnxe.unableToCreateFileSystem("No storageport uri found in the fs");
return BiosCommandResult.createErrorResult(error);
}
StoragePort portObj = dbClient.queryObject(StoragePort.class, port);
URI haDomainUri = portObj.getStorageHADomain();
StorageHADomain haDomainObj = dbClient.queryObject(StorageHADomain.class, haDomainUri);
StringSet protocols = fs.getProtocol();
if (protocols.contains(StorageProtocol.File.NFS_OR_CIFS.name())) {
/*
* the protocol is set to NFS_OR_CIFS, only if virtual pool's protocol is not set
* and the pool's protocol is set to NFS_OR_CIFS, since pool's protocol is set based on
* storageHADomain's protocol, setting the protocols to the selected StorageHADomain.
*/
protocols = haDomainObj.getFileSharingProtocols();
}
VNXeFSSupportedProtocolEnum protocolEnum = null;
if (protocols.contains(StorageProtocol.File.NFS.name())
&& protocols.contains(StorageProtocol.File.CIFS.name())) {
protocolEnum = VNXeFSSupportedProtocolEnum.NFS_CIFS;
} else if (protocols.contains(StorageProtocol.File.NFS.name())) {
protocolEnum = VNXeFSSupportedProtocolEnum.NFS;
} else if (protocols.contains(StorageProtocol.File.CIFS.name())) {
protocolEnum = VNXeFSSupportedProtocolEnum.CIFS;
} else {
_logger.error("The protocol is not supported: " + protocols);
ServiceError error = DeviceControllerErrors.vnxe.unableToCreateFileSystem("The protocol is not supported:" + protocols);
return BiosCommandResult.createErrorResult(error);
}
job = apiClient.createFileSystem(fileInOut.getFsName(),
fsSize,
fileInOut.getPoolNativeId(),
haDomainObj.getSerialNumber(),
fileInOut.getThinProvision(),
protocolEnum);
if (job != null) {
_logger.info("opid:" + fileInOut.getOpId());
completer = new VNXeFileTaskCompleter(FileShare.class, fileInOut.getFsId(), fileInOut.getOpId());
if (fileInOut.getFs() == null) {
_logger.error("Could not find the fs object");
}
VNXeCreateFileSystemJob createFSJob = new VNXeCreateFileSystemJob(job.getId(), storage.getId(),
completer, fileInOut.getPoolId());
ControllerServiceImpl.enqueueJob(new QueueJob(createFSJob));
} else {
_logger.error("No job returned from creatFileSystem");
ServiceError error = DeviceControllerErrors.vnxe.unableToCreateFileSystem("No Job returned from createFileSystem");
return BiosCommandResult.createErrorResult(error);
}
} catch (VNXeException e) {
_logger.error("Create file system got an exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("Create file system got an exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("CreateFileSystem", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"Create filesystem job submitted - Array:%s, Pool:%s, fileSystem: %s", storage.getSerialNumber(),
fileInOut.getPoolNativeId(), fileInOut.getFsName()));
_logger.info(logMsgBuilder.toString());
return BiosCommandResult.createPendingResult();
}
@Override
public boolean doCheckFSExists(StorageSystem storage,
FileDeviceInputOutput fileInOut) throws ControllerException {
_logger.info("checking file system existence on array: ", fileInOut.getFsName());
boolean isFSExists = true;
try {
String name = fileInOut.getFsName();
VNXeApiClient apiClient = getVnxUnityClient(storage);
VNXeFileSystem fs = apiClient.getFileSystemByFSName(name);
if (fs != null && (fs.getName().equals(name))) {
isFSExists = true;
} else {
isFSExists = false;
}
} catch (Exception e) {
_logger.error("Querying File System failed with exception:", e);
}
return isFSExists;
}
/*
* To get around the KH API delete file system async issues, using sync call for now.
*/
@Override
public BiosCommandResult doDeleteFS(StorageSystem storage,
FileDeviceInputOutput fileInOut) throws ControllerException {
_logger.info("deleting file system: ", fileInOut.getFsName());
VNXeApiClient apiClient = getVnxUnityClient(storage);
BiosCommandResult result = null;
try {
apiClient.deleteFileSystemSync(fileInOut.getFsNativeId(), fileInOut.getForceDelete());
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"Deleted filesystem - Array:%s, fileSystem: %s", storage.getSerialNumber(),
fileInOut.getFsName()));
_logger.info(logMsgBuilder.toString());
result = BiosCommandResult.createSuccessfulResult();
} catch (VNXeException e) {
_logger.error("Delete file system got the exception", e);
result = BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("Delete file system got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("DeleteFileSystem", ex.getMessage());
result = BiosCommandResult.createErrorResult(error);
}
return result;
}
@Override
public BiosCommandResult doExport(StorageSystem storage,
FileDeviceInputOutput args, List<FileExport> exportList)
throws ControllerException {
_logger.info("exporting the file system: " + args.getFsName());
if (args.getFileObjExports() == null || args.getFileObjExports().isEmpty()) {
args.initFileObjExports();
}
for (FileExport exp : exportList) {
VNXeApiClient apiClient = getVnxUnityClient(storage);
String fsId = args.getFs().getNativeId();
String fsName = args.getFsName();
String permission = exp.getPermissions();
String path = "/";
String subdirName = "";
String mountPathArg = exp.getMountPath();
String comments = exp.getComments();
VNXeCommandJob job = null;
VNXeFileTaskCompleter completer = null;
String exportKey = exp.getFileExportKey();
FileShareExport newExport = new FileShareExport(exp);
try {
AccessEnum access = null;
List<String> roClients = null;
List<String> rwClients = null;
List<String> rootClients = null;
FileExport existingExport = null;
if (args.getFileOperation()) {
FSExportMap exportMap = args.getFileObjExports();
existingExport = exportMap.get(exportKey);
} else {
FSExportMap exportMap = args.getSnapshotExports();
existingExport = exportMap.get(exportKey);
}
if (existingExport != null) {
if (permission.equalsIgnoreCase(FileShareExport.Permissions.rw.name())) {
access = AccessEnum.READWRITE;
if (existingExport.getClients() != null && !existingExport.getClients().isEmpty()) {
if (rwClients == null) {
rwClients = new ArrayList<String>();
}
rwClients.addAll(existingExport.getClients());
}
} else if (permission.equalsIgnoreCase(FileShareExport.Permissions.ro.name())) {
access = AccessEnum.READ;
if (existingExport.getClients() != null && !existingExport.getClients().isEmpty()) {
if (roClients == null) {
roClients = new ArrayList<String>();
}
roClients.addAll(existingExport.getClients());
}
} else if (permission.equalsIgnoreCase(FileShareExport.Permissions.root.name())) {
access = AccessEnum.ROOT;
if (existingExport.getClients() != null && !existingExport.getClients().isEmpty()) {
if (rootClients == null) {
rootClients = new ArrayList<String>();
}
rootClients.addAll(existingExport.getClients());
}
}
}
if (permission.equalsIgnoreCase(FileShareExport.Permissions.rw.name())) {
access = AccessEnum.READWRITE;
if (exp.getClients() != null && !exp.getClients().isEmpty()) {
if (rwClients == null) {
rwClients = new ArrayList<String>();
}
rwClients.addAll(exp.getClients());
}
} else if (permission.equalsIgnoreCase(FileShareExport.Permissions.ro.name())) {
access = AccessEnum.READ;
if (exp.getClients() != null && !exp.getClients().isEmpty()) {
if (roClients == null) {
roClients = new ArrayList<String>();
}
roClients.addAll(exp.getClients());
}
} else if (permission.equalsIgnoreCase(FileShareExport.Permissions.root.name())) {
access = AccessEnum.ROOT;
if (exp.getClients() != null && !exp.getClients().isEmpty()) {
if (rootClients == null) {
rootClients = new ArrayList<String>();
}
rootClients.addAll(exp.getClients());
}
}
if (args.getFileOperation()) {
String mountPathFs = args.getFsMountPath();
if (!mountPathArg.equals(mountPathFs)) {
// subdirectory specified.
subdirName = mountPathArg.substring(mountPathFs.length() + 1);
path += subdirName;
}
String shareName = VNXeUtils.buildNfsShareName(fsName, subdirName);
job = apiClient.exportFileSystem(fsId, roClients, rwClients, rootClients, access, path, shareName, null, comments);
if (job != null) {
completer = new VNXeFileTaskCompleter(FileShare.class, args.getFsId(), args.getOpId());
VNXeExportFileSystemJob exportFSJob = new VNXeExportFileSystemJob(job.getId(), storage.getId(),
completer, newExport, shareName, true);
ControllerServiceImpl.enqueueJob(new QueueJob(exportFSJob));
} else {
_logger.error("No job returned from exportFileSystem");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("exportFileSystem",
"No Job returned from exportFileSystem");
return BiosCommandResult.createErrorResult(error);
}
} else {
String snapId = args.getSnapNativeId();
String snapName = args.getSnapshotName();
String shareName = VNXeUtils.buildNfsShareName(snapName, path);
job = apiClient.createNfsShareForSnap(snapId, roClients, rwClients, rootClients, access, path, shareName, comments);
if (job != null) {
completer = new VNXeFileTaskCompleter(Snapshot.class, args.getSnapshotId(), args.getOpId());
VNXeExportFileSystemJob exportFSJob = new VNXeExportFileSystemJob(job.getId(), storage.getId(),
completer, newExport, shareName, false);
ControllerServiceImpl.enqueueJob(new QueueJob(exportFSJob));
} else {
_logger.error("No job returned from exportFileSystem");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("exportFileSystem",
"No Job returned from exportFileSystem");
return BiosCommandResult.createErrorResult(error);
}
}
} catch (VNXeException e) {
_logger.error("Export file system got the exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("export file system got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("exportFileSystem", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
_logger.info("Export job submitted");
}
return BiosCommandResult.createPendingResult();
}
@Override
public BiosCommandResult doShare(StorageSystem storage,
FileDeviceInputOutput args, SMBFileShare smbFileShare) throws ControllerException {
_logger.info("creating smbShare: " + smbFileShare.getName());
VNXeApiClient apiClient = getVnxUnityClient(storage);
String permission = smbFileShare.getPermission();
String shareName = smbFileShare.getName();
String path = "/";
VNXeCommandJob job = null;
VNXeFileTaskCompleter completer = null;
FileSMBShare newShare = new FileSMBShare(smbFileShare);
String absolutePath = smbFileShare.getPath();
newShare.setStoragePortNetworkId(smbFileShare.getStoragePortNetworkId());
newShare.setStoragePortName(smbFileShare.getStoragePortName());
try {
if (args.getFileOperation()) {
if (newShare.isSubDirPath()) {
String basePath = args.getFsPath();
/*
* The below line will allow us to get the relative path of subdir
* For example: absolutePath = /vnxeShare1/subdir1
* Then, the below line will assign path = subdir
* VNXe takes the relative path of the sub-directory. Not the absolute path
*/
path = "/" + new File(basePath).toURI().relativize(new File(absolutePath).toURI()).getPath();
}
String fsNativeId = args.getFs().getNativeId();
_logger.info("Creating CIFS share for path {}", path);
job = apiClient.createCIFSShare(fsNativeId, shareName, permission, path);
if (job != null) {
newShare.setNetBIOSName(apiClient.getNetBios());
completer = new VNXeFileTaskCompleter(FileShare.class, args.getFsId(), args.getOpId());
VNXeCreateShareJob createShareJob = new VNXeCreateShareJob(job.getId(), storage.getId(),
completer, newShare, true);
ControllerServiceImpl.enqueueJob(new QueueJob(createShareJob));
} else {
_logger.error("No job returned from creaetCifsShare");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("createShare", "No Job returned");
return BiosCommandResult.createErrorResult(error);
}
} else {
// create share for a snapshot
if (newShare.isSubDirPath()) {
String basePath = args.getSnapshotPath();
/*
* The below line will allow us to get the relative path of subdir
* For example: absolutePath = /vnxeShare1/subdir1
* Then, the below line will assign path = subdir
* VNXe takes the relative path of the sub-directory. Not the absolute path
*/
path = "/" + new File(basePath).toURI().relativize(new File(absolutePath).toURI()).getPath();
}
String fsNativeId = args.getFs().getNativeId();
String snapId = args.getSnapNativeId();
job = apiClient.createCifsShareForSnap(snapId, shareName, permission, path, fsNativeId);
if (job != null) {
newShare.setNetBIOSName(apiClient.getNetBios());
completer = new VNXeFileTaskCompleter(Snapshot.class, args.getSnapshotId(), args.getOpId());
VNXeCreateShareJob createShareJob = new VNXeCreateShareJob(job.getId(), storage.getId(),
completer, newShare, false);
ControllerServiceImpl.enqueueJob(new QueueJob(createShareJob));
} else {
_logger.error("No job returned from creaetCifsShare");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("createShare", "No Job returned");
return BiosCommandResult.createErrorResult(error);
}
}
} catch (VNXeException e) {
_logger.error("Create share got the exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("create share got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("create share", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"Create share job submitted - Array:%s, share: %s", storage.getSerialNumber(),
smbFileShare.getName()));
_logger.info(logMsgBuilder.toString());
return BiosCommandResult.createPendingResult();
}
@Override
public BiosCommandResult doDeleteShare(StorageSystem storage,
FileDeviceInputOutput args, SMBFileShare smbFileShare) throws ControllerException {
_logger.info(String.format(String.format("Deleting smbShare: %s, nativeId: %s",
smbFileShare.getName(), smbFileShare.getNativeId())));
VNXeApiClient apiClient = getVnxUnityClient(storage);
String shareId = smbFileShare.getNativeId();
VNXeCommandJob job = null;
VNXeFileTaskCompleter completer = null;
boolean isFile = args.getFileOperation();
FileSMBShare newShare = new FileSMBShare(smbFileShare);
try {
if (isFile) {
String fsId = args.getFs().getNativeId();
job = apiClient.removeCifsShare(shareId, fsId);
} else {
job = apiClient.deleteCifsShareForSnapshot(shareId);
}
if (job != null) {
if (isFile) {
completer = new VNXeFileTaskCompleter(FileShare.class, args.getFsId(), args.getOpId());
} else {
completer = new VNXeFileTaskCompleter(Snapshot.class, args.getSnapshotId(), args.getOpId());
}
VNXeDeleteShareJob deleteShareJob = new VNXeDeleteShareJob(job.getId(), storage.getId(),
completer, newShare, isFile);
ControllerServiceImpl.enqueueJob(new QueueJob(deleteShareJob));
} else {
_logger.error("No job returned from deleteCifsShare");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("deleteShare", "No Job returned");
return BiosCommandResult.createErrorResult(error);
}
} catch (VNXeException e) {
_logger.error("Create share got the exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("delete share got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("create share", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"Delete share job submitted - Array:%s, share: %s", storage.getSerialNumber(),
smbFileShare.getName()));
_logger.info(logMsgBuilder.toString());
return BiosCommandResult.createPendingResult();
}
@Override
public BiosCommandResult doDeleteShares(StorageSystem storage,
FileDeviceInputOutput args) throws ControllerException {
return null;
}
@Override
public BiosCommandResult doUnexport(StorageSystem storage,
FileDeviceInputOutput args, List<FileExport> exportList) throws ControllerException {
_logger.info("unexporting the file system: " + args.getFsName());
boolean isFile = args.getFileOperation();
for (FileExport exp : exportList) {
VNXeApiClient apiClient = getVnxUnityClient(storage);
String vnxeShareId = exp.getIsilonId();
VNXeCommandJob job = null;
VNXeFileTaskCompleter completer = null;
try {
if (isFile) {
String fsId = args.getFs().getNativeId();
job = apiClient.removeNfsShare(vnxeShareId, fsId);
} else {
job = apiClient.deleteNfsShareForSnapshot(vnxeShareId);
}
if (job != null) {
if (isFile) {
completer = new VNXeFileTaskCompleter(FileShare.class, args.getFsId(), args.getOpId());
} else {
completer = new VNXeFileTaskCompleter(Snapshot.class, args.getSnapshotId(), args.getOpId());
}
FileShareExport export = new FileShareExport(exp);
VNXeUnexportFileSystemJob unexportFSJob = new VNXeUnexportFileSystemJob(job.getId(), storage.getId(),
completer, export, export.getPath(), isFile);
ControllerServiceImpl.enqueueJob(new QueueJob(unexportFSJob));
} else {
_logger.error("No job returned from exportFileSystem");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("DeleteFileSystem", "No Job returned from deleteFileSystem");
return BiosCommandResult.createErrorResult(error);
}
} catch (VNXeException e) {
_logger.error("Unexport file system got the exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("Delete file system got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("DeleteFileSystem", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"Unexport filesystem job submitted - Array:%s, fileSystem: %s", storage.getSerialNumber(),
args.getFsName()));
_logger.info(logMsgBuilder.toString());
}
return BiosCommandResult.createPendingResult();
}
@Override
public BiosCommandResult doModifyFS(StorageSystem storage,
FileDeviceInputOutput fd) throws ControllerException {
BiosCommandResult result = new BiosCommandResult();
result.setCommandSuccess(false);
result.setCommandStatus(Operation.Status.error.name());
result.setMessage("Modify FS NOT supported for VNXe.");
return result;
}
@Override
public BiosCommandResult doExpandFS(StorageSystem storage,
FileDeviceInputOutput args) throws ControllerException {
_logger.info("expanding file system: ", args.getFsName());
VNXeApiClient apiClient = getVnxUnityClient(storage);
VNXeCommandJob job = null;
VNXeFileTaskCompleter completer = null;
try {
job = apiClient.expandFileSystem(args.getFsNativeId(), args.getNewFSCapacity());
if (job != null) {
completer = new VNXeFileTaskCompleter(FileShare.class, args.getFsId(), args.getOpId());
VNXeExpandFileSystemJob expandFSJob = new VNXeExpandFileSystemJob(job.getId(), storage.getId(),
completer);
ControllerServiceImpl.enqueueJob(new QueueJob(expandFSJob));
} else {
_logger.error("No job returned from expandFileSystem");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed(
"expandFileSystem", "No Job returned from expandFileSystem");
return BiosCommandResult.createErrorResult(error);
}
} catch (VNXeException e) {
_logger.error("Expand file system got the exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("Expand file system got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("ExpandFileSystem", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"Expand filesystem job submitted - Array:%s, fileSystem: %s, new size: %d", storage.getSerialNumber(),
args.getFsName(), args.getNewFSCapacity()));
_logger.info(logMsgBuilder.toString());
return BiosCommandResult.createPendingResult();
}
@Override
public BiosCommandResult doSnapshotFS(StorageSystem storage,
FileDeviceInputOutput args) throws ControllerException {
_logger.info("creating file system {} snap {} ", args.getFsName(), args.getSnapshotLabel());
VNXeApiClient apiClient = getVnxUnityClient(storage);
VNXeCommandJob job = null;
VNXeFSSnapshotTaskCompleter completer = null;
try {
job = apiClient.createFileSystemSnap(args.getFsNativeId(), args.getSnapshotName());
if (job != null) {
completer = new VNXeFSSnapshotTaskCompleter(Snapshot.class, args.getSnapshotId(), args.getOpId());
VNXeCreateFileSystemSnapshotJob snapJob = new VNXeCreateFileSystemSnapshotJob(job.getId(), storage.getId(),
completer);
ControllerServiceImpl.enqueueJob(new QueueJob(snapJob));
} else {
_logger.error("No job returned from createFileSystemSnap");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed(
"snapshotFileSystem", "No Job returned from createFileSystemSnap");
return BiosCommandResult.createErrorResult(error);
}
} catch (VNXeException e) {
_logger.error("Create file system snapshot got an exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("Create file system snapshot got an exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("CreateFileSystemSnapshot", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"Create filesystem snapshot job submitted - Array:%s, fileSystem: %s", storage.getSerialNumber(),
args.getFsName()));
_logger.info(logMsgBuilder.toString());
return BiosCommandResult.createPendingResult();
}
@Override
public BiosCommandResult doRestoreFS(StorageSystem storage,
FileDeviceInputOutput args) throws ControllerException {
_logger.info("restoring file system {} snap {} ", args.getFsName(), args.getSnapshotLabel());
VNXeApiClient apiClient = getVnxUnityClient(storage);
VNXeCommandJob job = null;
VNXeFSSnapshotTaskCompleter completer = null;
try {
job = apiClient.restoreFileSystemSnap(args.getSnapNativeId());
if (job != null) {
completer = new VNXeFSSnapshotTaskCompleter(Snapshot.class, args.getSnapshotId(), args.getOpId());
VNXeRestoreFileSystemSnapshotJob snapJob = new VNXeRestoreFileSystemSnapshotJob(job.getId(), storage.getId(),
completer);
ControllerServiceImpl.enqueueJob(new QueueJob(snapJob));
} else {
_logger.error("No job returned from restoreFileSystemSnap");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed(
"restoreSnapshotFileSystem", "No Job returned from restoreFileSystemSnap");
return BiosCommandResult.createErrorResult(error);
}
} catch (VNXeException e) {
_logger.error("Restore file system snapshot got the exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("Restore file system snpashot got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("RestoreFileSystemSnapshot", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"Restore filesystem snapshot job submitted - Array:%s, fileSystem: %s, snapshot: %s",
storage.getSerialNumber(), args.getFsName(), args.getSnapshotLabel()));
_logger.info(logMsgBuilder.toString());
return BiosCommandResult.createPendingResult();
}
@Override
public BiosCommandResult doDeleteSnapshot(StorageSystem storage,
FileDeviceInputOutput args) throws ControllerException {
_logger.info("Deleting file system {} snapshot {} ", args.getFsName(), args.getSnapshotLabel());
VNXeApiClient apiClient = getVnxUnityClient(storage);
VNXeCommandJob job = null;
VNXeFileTaskCompleter completer = null;
try {
job = apiClient.deleteFileSystemSnap(args.getSnapNativeId());
if (job != null) {
completer = new VNXeFileTaskCompleter(Snapshot.class, args.getSnapshotId(), args.getOpId());
VNXeDeleteFileSystemSnapshotJob snapJob = new VNXeDeleteFileSystemSnapshotJob(job.getId(), storage.getId(),
completer);
ControllerServiceImpl.enqueueJob(new QueueJob(snapJob));
} else {
_logger.error("No job returned from deleteFileSystemSnap");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed(
"snapshotFileSystem", "No Job returned from deleteFileSystemSnap");
return BiosCommandResult.createErrorResult(error);
}
} catch (VNXeException e) {
_logger.error("Delete file system snapshot got the exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("Delete file system snpashot got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("DeleteFileSystemSnapshot", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"Delete filesystem snapshot job submitted - Array:%s, fileSystem: %s, snapshot: %s", storage.getSerialNumber(),
args.getFsName(), args.getSnapshotName()));
_logger.info(logMsgBuilder.toString());
return BiosCommandResult.createPendingResult();
}
@Override
public void doConnect(StorageSystem storage) throws ControllerException {
try {
_logger.info("doConnect {} - start", storage.getId());
VNXeApiClient client = getVnxUnityClient(storage);
client.getStorageSystem();
String msg = String.format("doConnect %1$s - complete", storage.getId());
_logger.info(msg);
} catch (VNXeException e) {
_logger.error("doConnect failed.", e);
throw DeviceControllerException.exceptions.connectStorageFailed(e);
}
}
@Override
public void doDisconnect(StorageSystem storage) {
try {
_logger.info("doConnect {} - start", storage.getId());
VNXeApiClient client = getVnxUnityClient(storage);
client.logout();
String msg = String.format("doDisconnect %1$s - complete", storage.getId());
_logger.info(msg);
} catch (VNXeException e) {
_logger.error("doDisconnect failed.", e);
throw DeviceControllerException.exceptions.disconnectStorageFailed(e);
}
}
@Override
public BiosCommandResult getPhysicalInventory(StorageSystem storage) {
// TODO Auto-generated method stub
return null;
}
@Override
public BiosCommandResult getFSSnapshotList(StorageSystem storage,
FileDeviceInputOutput fd, List<String> snapshots) throws ControllerException {
_logger.info("getFSSnapshotList {} - start", fd.getFsId());
VNXeApiClient client = getVnxUnityClient(storage);
try {
List<VNXeFileSystemSnap> snaps = client.getFileSystemSnaps(fd.getFsNativeId());
for (VNXeFileSystemSnap snap : snaps) {
snapshots.add(snap.getName());
}
return BiosCommandResult.createSuccessfulResult();
} catch (VNXeException e) {
_logger.error("getFSSnapshotList failed.", e);
return BiosCommandResult.createErrorResult(e);
}
}
@Override
public BiosCommandResult updateExportRules(StorageSystem storage,
FileDeviceInputOutput args) {
// Requested Export Rules
List<ExportRule> exportAdd = args.getExportRulesToAdd();
List<ExportRule> exportDelete = args.getExportRulesToDelete();
List<ExportRule> exportModify = args.getExportRulesToModify();
// To be processed export rules
List<ExportRule> exportsToRemove = new ArrayList<>();
List<ExportRule> exportsToAdd = new ArrayList<>();
List<ExportRule> newExportsForDelete = new ArrayList<>();
VNXeFileTaskCompleter completer = null;
VNXeApiClient apiClient = getVnxUnityClient(storage);
String subDir = args.getSubDirectory();
// ALL EXPORTS
List<ExportRule> exportsToprocess = args.getExistingDBExportRules();
Map<String, ArrayList<ExportRule>> existingExportsMapped = new HashMap();
try {
String exportPath;
if (!args.getFileOperation()) {
exportPath = args.getSnapshotPath();
if (subDir != null
&& subDir.length() > 0) {
exportPath = args.getSnapshotPath() + "/"
+ subDir;
}
} else {
exportPath = args.getFs().getPath();
if (subDir != null
&& subDir.length() > 0) {
exportPath = args.getFs().getPath() + "/"
+ subDir;
}
}
_logger.info("exportPath : {}", exportPath);
args.setExportPath(exportPath);
try {
// add the new export rule from the array into the update request.
Map<String, ExportRule> arrayExportRuleMap = extraExportRuleFromArray(storage, args);
if (!arrayExportRuleMap.isEmpty()) {
if (exportModify != null) {
// merge the end point for which sec flavor is common.
for (ExportRule exportRule : exportModify) {
ExportRule arrayExportRule = arrayExportRuleMap.remove(exportRule.getSecFlavor());
if (arrayExportRule != null) {
if (exportRule.getReadOnlyHosts() != null) {
exportRule.getReadOnlyHosts().addAll(arrayExportRule.getReadOnlyHosts());
} else {
exportRule.setReadOnlyHosts(arrayExportRule.getReadOnlyHosts());
}
if (exportRule.getReadWriteHosts() != null) {
exportRule.getReadWriteHosts().addAll(arrayExportRule.getReadWriteHosts());
} else {
exportRule.setReadWriteHosts(arrayExportRule.getReadWriteHosts());
}
if (exportRule.getRootHosts() != null) {
exportRule.getRootHosts().addAll(arrayExportRule.getRootHosts());
} else {
exportRule.setRootHosts(arrayExportRule.getRootHosts());
}
}
}
// now add the remaining export rule
exportModify.addAll(arrayExportRuleMap.values());
} else {
// if exportModify is null then create a new export rule and add
exportModify = new ArrayList<ExportRule>();
exportModify.addAll(arrayExportRuleMap.values());
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
_logger.error("Not able to fetch latest Export rule from backend array.", e);
}
if (exportsToprocess == null) {
exportsToprocess = new ArrayList<>();
}
_logger.info("Number of existng Rules found {}", exportsToprocess.size());
// Process Exports
for (ExportRule existingRule : exportsToprocess) {
ArrayList<ExportRule> exps = existingExportsMapped.get(existingRule.getExportPath());
if (exps == null) {
exps = new ArrayList<>();
}
exps.add(existingRule);
_logger.info("Checking existing export for {} : exps : {}", existingRule.getExportPath(), exps);
existingExportsMapped.put(existingRule.getExportPath(), exps);
}
// Handle Add export Rules
if (exportAdd != null && !exportAdd.isEmpty()) {
// Check for existing exports for the export path including subdirectory
ArrayList<ExportRule> exps = existingExportsMapped.get(exportPath);
if (exps != null && !exps.isEmpty()) {
_logger.error("Adding export rules is not supported as there can be only one export rule for VNX Unity.");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("updateExportRules",
"Adding export rule is not supported for VNX unity");
return BiosCommandResult.createErrorResult(error);
}
}
// Handle Modified export Rules
if (!exportsToprocess.isEmpty()) {
if (subDir != null && !subDir.isEmpty()) {
for (ExportRule existingRule : exportsToprocess) {
if (existingRule.getExportPath().endsWith("/" + subDir)) {
// Filter for a specific Sub Directory export
_logger.info(
"Updating all subdir exports rules at ViPR and sub directory export at device {}",
subDir);
processModifyRules(exportModify, existingRule, exportsToRemove, exportsToAdd);
} else {
exportsToRemove.add(existingRule);
}
}
// Handle Delete export Rules
if (exportDelete != null && !exportDelete.isEmpty()) {
for (ExportRule existingRule : exportsToprocess) {
if (existingRule.getExportPath().endsWith("/" + subDir)) {
processDeleteRules(exportDelete, existingRule, exportsToRemove, newExportsForDelete);
} else {
exportsToRemove.add(existingRule);
}
}
exportsToAdd.addAll(newExportsForDelete);
}
} else {
for (ExportRule existingRule : exportsToprocess) {
if (existingRule.getExportPath().equalsIgnoreCase(exportPath)) {
processModifyRules(exportModify, existingRule, exportsToRemove, exportsToAdd);
} else {
exportsToRemove.add(existingRule);
}
}
// Handle Delete export Rules
if (exportDelete != null && !exportDelete.isEmpty()) {
for (ExportRule existingRule : exportsToprocess) {
if (existingRule.getExportPath().equalsIgnoreCase(exportPath)) {
processDeleteRules(exportDelete, existingRule, exportsToRemove, newExportsForDelete);
} else {
exportsToRemove.add(existingRule);
}
}
exportsToAdd.addAll(newExportsForDelete);
}
}
// No of exports found to remove from the list
_logger.info("No of exports found to remove from the existing exports list {}", exportsToRemove.size());
exportsToprocess.removeAll(exportsToRemove);
_logger.info("No of exports found to add to the existing exports list {}", exportsToAdd.size());
exportsToprocess.addAll(exportsToAdd);
} else {
// Handle Add Export Rules
// This is valid only if no rules to modify exists
if (exportAdd != null && !exportAdd.isEmpty()) {
for (ExportRule newExport : exportAdd) {
if (args.getFileObjExports() != null) {
Collection<FileExport> expList = args.getFileObjExports().values();
Iterator<FileExport> it = expList.iterator();
FileExport exp = null;
while (it.hasNext()) {
FileExport export = it.next();
if (export.getPath().equalsIgnoreCase(exportPath)) {
exp = export;
}
}
if (exp != null) {
if (exp.getIsilonId() != null) {
newExport.setDeviceExportId(exp.getIsilonId());
}
if (exp.getNativeId() != null) {
newExport.setDeviceExportId(exp.getNativeId());
}
}
}
_logger.info("Add Export Rule {}", newExport);
newExport.setExportPath(exportPath);
exportsToAdd.add(newExport);
}
}
exportsToprocess.addAll(exportsToAdd);
}
_logger.info("exportPath : {}", exportPath);
args.setExportPath(exportPath);
VNXeCommandJob job = null;
for (ExportRule rule : exportsToprocess) {
AccessEnum access = null;
List<String> roHosts = new ArrayList<String>();
List<String> rwHosts = new ArrayList<String>();
List<String> rootHosts = new ArrayList<String>();
String path = "/";
String subdirName = "";
String mountPathFs = args.getFsMountPath();
String shareName = null;
FileShareExport fsExport = null;
boolean isDeleteRule = false;
if (args.getFileObjExports() != null) {
Collection<FileExport> expList = args.getFileObjExports().values();
Iterator<FileExport> it = expList.iterator();
FileExport exp = null;
while (it.hasNext()) {
FileExport export = it.next();
if (export.getPath().equalsIgnoreCase(rule.getExportPath())) {
exp = export;
}
}
fsExport = new FileShareExport(exp);
}
String mountPathArg = rule.getExportPath();
if (rule.getReadWriteHosts() != null && !rule.getReadWriteHosts().isEmpty()) {
access = AccessEnum.READWRITE;
rwHosts.addAll(rule.getReadWriteHosts());
}
if (rule.getReadOnlyHosts() != null && !rule.getReadOnlyHosts().isEmpty()) {
access = AccessEnum.READ;
roHosts.addAll(rule.getReadOnlyHosts());
}
if (rule.getRootHosts() != null && !rule.getRootHosts().isEmpty()) {
access = AccessEnum.ROOT;
rootHosts.addAll(rule.getRootHosts());
}
if (newExportsForDelete.contains(rule)) {
isDeleteRule = true;
}
if (args.getFileOperation()) {
if (!mountPathArg.equals(mountPathFs)) {
// subdirectory specified.
subdirName = mountPathArg.substring(mountPathFs.length() + 1);
path += subdirName;
}
if (isDeleteRule) {
job = apiClient.removeNfsShare(rule.getDeviceExportId(), args.getFs().getNativeId());
if (job != null) {
completer = new VNXeFileTaskCompleter(FileShare.class, args.getFsId(), args.getOpId());
VNXeUnexportFileSystemJob unexportFSJob = new VNXeUnexportFileSystemJob(job.getId(), storage.getId(),
completer, fsExport, args.getExportPath(), true);
ControllerServiceImpl.enqueueJob(new QueueJob(unexportFSJob));
} else {
_logger.error("No job returned from unexport FileSystem");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("UnExportFileSystem",
"No Job returned from UnExportFileSystem");
return BiosCommandResult.createErrorResult(error);
}
} else {
job = apiClient.exportFileSystem(args.getFs().getNativeId(), roHosts, rwHosts, rootHosts, access, path, null,
rule.getDeviceExportId(), null);
if (job != null) {
completer = new VNXeFileTaskCompleter(FileShare.class, args.getFsId(), args.getOpId());
VNXeModifyExportJob modifyExportJob = new VNXeModifyExportJob(job.getId(), storage.getId(),
completer, rule, fsExport, args.getExportPath(), args.getFileOperation(), isDeleteRule, shareName);
ControllerServiceImpl.enqueueJob(new QueueJob(modifyExportJob));
} else {
_logger.error("No job returned from updateExportRules");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("updateExportRules",
"No Job returned from updateExportRules");
return BiosCommandResult.createErrorResult(error);
}
}
} else {
shareName = VNXeUtils.buildNfsShareName(args.getSnapshotName(), path);
if (isDeleteRule) {
job = apiClient.deleteNfsShareForSnapshot(rule.getDeviceExportId());
if (job != null) {
completer = new VNXeFileTaskCompleter(Snapshot.class, args.getSnapshotId(), args.getOpId());
VNXeUnexportFileSystemJob unexportFSJob = new VNXeUnexportFileSystemJob(job.getId(), storage.getId(),
completer, fsExport, rule.getExportPath(), false);
ControllerServiceImpl.enqueueJob(new QueueJob(unexportFSJob));
} else {
_logger.error("No job returned from unexportFileSystem Snapshot");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("UnExportFileSystem",
"No Job returned from UnExportFileSystem");
return BiosCommandResult.createErrorResult(error);
}
} else {
job = apiClient.createNfsShareForSnap(args.getSnapNativeId(), roHosts, rwHosts, rootHosts, access, path, shareName,
null);
if (job != null) {
completer = new VNXeFileTaskCompleter(Snapshot.class, args.getSnapshotId(), args.getOpId());
VNXeModifyExportJob modifyExportJob = new VNXeModifyExportJob(job.getId(), storage.getId(),
completer, rule, fsExport, args.getExportPath(), args.getFileOperation(), isDeleteRule, shareName);
ControllerServiceImpl.enqueueJob(new QueueJob(modifyExportJob));
} else {
_logger.error("No job returned from updateExportRules");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("updateExportRules",
"No Job returned from updateExportRules");
return BiosCommandResult.createErrorResult(error);
}
}
}
}
} catch (VNXeException e) {
_logger.error("updateExportRules got the exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("updateExportRules got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("updateExportRules", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
_logger.info("UpdateExportRules job submitted");
return BiosCommandResult.createPendingResult();
}
private void processModifyRules(List<ExportRule> exportModify, ExportRule existingRule,
List<ExportRule> exportsToRemove, List<ExportRule> exportsToAdd) {
for (ExportRule modifiedrule : exportModify) {
if (modifiedrule.getSecFlavor().equals(
existingRule.getSecFlavor())) {
_logger.info("Modifying Export Rule from {}, To {}",
existingRule, modifiedrule);
// use a separate list to avoid concurrent modification exception for now.
exportsToRemove.add(existingRule);
ExportRule modifyRule = new ExportRule();
copyPropertiesToSave(modifyRule, modifiedrule);
modifyRule.setDeviceExportId(existingRule.getDeviceExportId());
modifyRule.setExportPath(existingRule.getExportPath());
exportsToAdd.add(modifyRule);
break;
}
}
}
private void processDeleteRules(List<ExportRule> exportDelete, ExportRule existingRule,
List<ExportRule> exportsToRemove, List<ExportRule> exportsToAdd) {
for (ExportRule oldExport : exportDelete) {
if (oldExport.getSecFlavor().equals(
existingRule.getSecFlavor())) {
_logger.info("Deleting Export Rule {}", existingRule);
exportsToRemove.add(existingRule);
ExportRule rule = new ExportRule();
rule.setSecFlavor("sys");
rule.setAnon("root");
rule.setExportPath(existingRule.getExportPath());
rule.setDeviceExportId(existingRule.getDeviceExportId());
exportsToAdd.add(rule);
break;
}
}
}
private void copyPropertiesToSave(ExportRule dest, ExportRule orig) {
_logger.info("Origin {}", orig.toString());
dest.setSecFlavor(orig.getSecFlavor());
dest.setAnon(orig.getAnon());
if (orig.getReadOnlyHosts() != null && !orig.getReadOnlyHosts().isEmpty()) {
dest.setReadOnlyHosts(new StringSet(orig.getReadOnlyHosts()));
_logger.info("Read Only Hosts {}", dest.getReadOnlyHosts());
}
if (orig.getReadWriteHosts() != null && !orig.getReadWriteHosts().isEmpty()) {
dest.setReadWriteHosts(new StringSet(orig.getReadWriteHosts()));
_logger.info("Read Write Hosts {}", dest.getReadWriteHosts());
}
if (orig.getRootHosts() != null && !orig.getRootHosts().isEmpty()) {
dest.setRootHosts(new StringSet(orig.getRootHosts()));
_logger.info("Root hosts {}", dest.getRootHosts());
}
_logger.info("Dest After {}", dest.toString());
}
@Override
public BiosCommandResult deleteExportRules(StorageSystem storage,
FileDeviceInputOutput args) {
List<ExportRule> allExports = args.getExistingDBExportRules();
String subDir = args.getSubDirectory();
boolean allDirs = args.isAllDir();
VNXeCommandJob job = null;
VNXeFileTaskCompleter completer = null;
boolean isFile = args.getFileOperation();
boolean ifRulePresent = false;
String exportPath;
String subDirExportPath = "";
subDir = args.getSubDirectory();
if (!args.getFileOperation()) {
exportPath = args.getSnapshotPath();
if (subDir != null
&& subDir.length() > 0) {
subDirExportPath = args.getSnapshotPath() + "/"
+ subDir;
}
} else {
exportPath = args.getFs().getPath();
if (subDir != null
&& subDir.length() > 0) {
subDirExportPath = args.getFs().getPath() + "/"
+ subDir;
}
}
_logger.info("exportPath : {}", exportPath);
args.setExportPath(exportPath);
_logger.info("Number of existing exports found {}", allExports.size());
try {
VNXeApiClient apiClient = getVnxUnityClient(storage);
if (allDirs) {
// ALL EXPORTS
_logger.info(
"Deleting all exports specific to filesystem at device and rules from DB including sub dirs rules and exports");
for (ExportRule rule : allExports) {
FileShareExport fsExport = null;
if (args.getFileObjExports() != null) {
Collection<FileExport> expList = args.getFileObjExports().values();
Iterator<FileExport> it = expList.iterator();
FileExport exp = null;
while (it.hasNext()) {
FileExport export = it.next();
if (export.getPath().equalsIgnoreCase(rule.getExportPath())) {
exp = export;
}
}
fsExport = new FileShareExport(exp);
}
String vnxeShareId = rule.getDeviceExportId();
_logger.info("Delete UnityExport id {} for path {}",
rule.getDeviceExportId(), rule.getExportPath());
if (isFile) {
String fsId = args.getFs().getNativeId();
job = apiClient.removeNfsShare(vnxeShareId, fsId);
} else {
job = apiClient.deleteNfsShareForSnapshot(vnxeShareId);
}
if (job != null) {
if (isFile) {
completer = new VNXeFileTaskCompleter(FileShare.class, args.getFsId(), args.getOpId());
} else {
completer = new VNXeFileTaskCompleter(Snapshot.class, args.getSnapshotId(), args.getOpId());
}
VNXeUnexportFileSystemJob unexportFSJob = new VNXeUnexportFileSystemJob(job.getId(), storage.getId(),
completer, fsExport, rule.getExportPath(), isFile);
ControllerServiceImpl.enqueueJob(new QueueJob(unexportFSJob));
} else {
_logger.error("No job returned from exportFileSystem");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("DeleteFileSystem",
"No Job returned from deleteFileSystem");
return BiosCommandResult.createErrorResult(error);
}
}
} else if (subDir != null && !subDir.isEmpty()) {
// Filter for a specific Sub Directory export
_logger.info("Deleting all subdir exports rules at ViPR and sub directory export at device {}", subDir);
FileShareExport fsExport = null;
String vnxeShareId = null;
if (args.getFileObjExports() != null) {
Collection<FileExport> expList = args.getFileObjExports().values();
Iterator<FileExport> it = expList.iterator();
FileExport exp = null;
while (it.hasNext()) {
FileExport export = it.next();
if (export.getPath().equalsIgnoreCase(subDirExportPath)) {
exp = export;
break;
}
}
fsExport = new FileShareExport(exp);
}
for (ExportRule rule : allExports) {
_logger.info("Delete UnityExport id for path {} f containing subdirectory {}",
rule.getDeviceExportId() + ":" + rule.getExportPath(), subDir);
if (rule.getExportPath().equalsIgnoreCase(subDirExportPath)) {
ifRulePresent = true;
vnxeShareId = rule.getDeviceExportId();
}
}
if (!ifRulePresent) {
if (fsExport != null) {
vnxeShareId = fsExport.getIsilonId();
}
}
_logger.info("Delete UnityExport id {} for path {}",
vnxeShareId, subDirExportPath);
if (isFile) {
String fsId = args.getFs().getNativeId();
job = apiClient.removeNfsShare(vnxeShareId, fsId);
} else {
job = apiClient.deleteNfsShareForSnapshot(vnxeShareId);
}
if (job != null) {
if (isFile) {
completer = new VNXeFileTaskCompleter(FileShare.class, args.getFsId(), args.getOpId());
} else {
completer = new VNXeFileTaskCompleter(Snapshot.class, args.getSnapshotId(), args.getOpId());
}
VNXeUnexportFileSystemJob unexportFSJob = new VNXeUnexportFileSystemJob(job.getId(), storage.getId(),
completer, fsExport, subDirExportPath, isFile);
ControllerServiceImpl.enqueueJob(new QueueJob(unexportFSJob));
} else {
_logger.error("No job returned from exportFileSystem");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("DeleteFileSystem", "No Job returned from deleteFileSystem");
return BiosCommandResult.createErrorResult(error);
}
} else {
// Filter for No SUBDIR - main export rules with no sub dirs
_logger.info("Deleting all export rules from DB and export at device not included sub dirs");
FileShareExport fsExport = null;
String vnxeShareId = null;
if (args.getFileObjExports() != null) {
Collection<FileExport> expList = args.getFileObjExports().values();
Iterator<FileExport> it = expList.iterator();
FileExport exp = null;
while (it.hasNext()) {
FileExport export = it.next();
if (export.getPath().equalsIgnoreCase(exportPath)) {
exp = export;
break;
}
}
fsExport = new FileShareExport(exp);
}
for (ExportRule rule : allExports) {
if (rule.getExportPath().equalsIgnoreCase(exportPath)) {
ifRulePresent = true;
vnxeShareId = rule.getDeviceExportId();
}
}
if (!ifRulePresent) {
if (fsExport != null) {
vnxeShareId = fsExport.getIsilonId();
}
}
_logger.info("Delete UnityExport id {} for path {}",
vnxeShareId, fsExport.getPath());
if (isFile) {
String fsId = args.getFs().getNativeId();
job = apiClient.removeNfsShare(vnxeShareId, fsId);
} else {
job = apiClient.deleteNfsShareForSnapshot(vnxeShareId);
}
if (job != null) {
if (isFile) {
completer = new VNXeFileTaskCompleter(FileShare.class, args.getFsId(), args.getOpId());
} else {
completer = new VNXeFileTaskCompleter(Snapshot.class, args.getSnapshotId(), args.getOpId());
}
VNXeUnexportFileSystemJob unexportFSJob = new VNXeUnexportFileSystemJob(job.getId(), storage.getId(),
completer, fsExport, fsExport.getPath(), isFile);
ControllerServiceImpl.enqueueJob(new QueueJob(unexportFSJob));
} else {
_logger.error("No job returned from exportFileSystem");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("DeleteFileSystem", "No Job returned from deleteFileSystem");
return BiosCommandResult.createErrorResult(error);
}
}
} catch (VNXeException e) {
_logger.error("Unexport file system got the exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("Delete file system got the exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("DeleteFileSystem", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
if (job != null) {
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"Unexport filesystem job submitted - Array:%s, fileSystem: %s", storage.getSerialNumber(),
args.getFsName()));
_logger.info(logMsgBuilder.toString());
return BiosCommandResult.createPendingResult();
} else {
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"No export found - Array:%s, fileSystem: %s", storage.getSerialNumber(),
args.getFsName()));
_logger.info(logMsgBuilder.toString());
return BiosCommandResult.createSuccessfulResult();
}
}
@Override
public BiosCommandResult doCreateQuotaDirectory(StorageSystem storage,
FileDeviceInputOutput args, QuotaDirectory qd) throws ControllerException {
_logger.info("creating Quota Directory: ", args.getQuotaDirectoryName());
VNXUnityQuotaDirectoryTaskCompleter completer = null;
VNXeApiClient apiClient = getVnxUnityClient(storage);
VNXeCommandJob job = null;
try {
Long softLimit = 0L;
Long softGrace = 0L;
Long size = 0L;
if (qd.getSize() == 0) {
size = args.getFsCapacity(); // If quota directory has no size specified, inherit it from the parent fs
// for the calculation of limit sizes
} else {
size = qd.getSize();
}
softLimit = Long.valueOf(qd.getSoftLimit() * size / 100);// conversion from percentage to bytes
// using hard limit
softGrace = Long.valueOf(qd.getSoftGrace() * 24 * 60 * 60); // conversion from days to seconds
job = apiClient.createQuotaDirectory(args.getFsName(), qd.getName(), qd.getSize(), softLimit, softGrace);
if (job != null) {
_logger.info("opid:" + args.getOpId());
completer = new VNXUnityQuotaDirectoryTaskCompleter(QuotaDirectory.class, args.getQuotaDirectory().getId(), args.getOpId());
if (args.getQuotaDirectory() == null) {
_logger.error("Could not find the quota object");
}
VNXUnityCreateFileSystemQuotaDirectoryJob createQuotaJob = new VNXUnityCreateFileSystemQuotaDirectoryJob(job.getId(),
storage.getId(), completer);
ControllerServiceImpl.enqueueJob(new QueueJob(createQuotaJob));
} else {
_logger.error("No job returned from createQuotaDirectory");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("No Job returned from createQuotaDirectory");
return BiosCommandResult.createErrorResult(error);
}
} catch (VNXeException e) {
_logger.error("Create Quota Directory got an exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("Create Quota Directory got an exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("CreateQuotaDirectory", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"Create filesystem job submitted - Array:%s, fileSystem: %s", storage.getSerialNumber(), args.getFsName()));
_logger.info(logMsgBuilder.toString());
return BiosCommandResult.createPendingResult();
}
@Override
public BiosCommandResult doDeleteQuotaDirectory(StorageSystem storage,
FileDeviceInputOutput args) throws ControllerException {
_logger.info("Deleting file system {} quota directory {} ", args.getFsName(), args.getQuotaDirectoryName());
VNXeApiClient apiClient = getVnxUnityClient(storage);
VNXeCommandJob job = null;
VNXUnityQuotaDirectoryTaskCompleter completer = null;
try {
job = apiClient.deleteQuotaDirectory(args.getQuotaDirectoryNativeId());
if (job != null) {
completer = new VNXUnityQuotaDirectoryTaskCompleter(QuotaDirectory.class, args.getQuotaDirectoryId(), args.getOpId());
VNXUnityDeleteFileSystemQuotaDirectoryJob quotaJob = new VNXUnityDeleteFileSystemQuotaDirectoryJob(job.getId(),
storage.getId(), completer);
ControllerServiceImpl.enqueueJob(new QueueJob(quotaJob));
} else {
_logger.error("No job returned from deleteQuotaDirectory");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed(
"DeleteFileSystemQuota", "No Job returned from deleteQuotaDirectory");
return BiosCommandResult.createErrorResult(error);
}
} catch (VNXeException e) {
_logger.error("Delete file system quota directory got an exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("Delete file system quota directory got an exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("DeleteFileSystemQuota", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"Delete filesystem quota job submitted - Array:%s, fileSystem: %s, quota: %s", storage.getSerialNumber(),
args.getFsName(), args.getQuotaDirectoryName()));
_logger.info(logMsgBuilder.toString());
return BiosCommandResult.createPendingResult();
}
/**
* Get the export rule which are present in array but not in CoprHD Database.
*
* @param storage
* @param args
* @return map with security flavor and export rule
*/
private Map<String, ExportRule> extraExportRuleFromArray(StorageSystem storage, FileDeviceInputOutput args) {
// map to store the export rule grouped by sec flavor
Map<String, ExportRule> exportRuleMap = new HashMap<>();
List<VNXeNfsShare> exportsList = new ArrayList<VNXeNfsShare>();
Set<String> arrayReadOnlyHost = new HashSet<>();
Set<String> arrayReadWriteHost = new HashSet<>();
Set<String> arrayRootHost = new HashSet<>();
Set<String> dbReadOnlyHost = new HashSet<>();
Set<String> dbReadWriteHost = new HashSet<>();
Set<String> dbRootHost = new HashSet<>();
// get all export rule from CoprHD data base
List<ExportRule> existingDBExportRules = args.getExistingDBExportRules();
// get the all the export from the storage system.
VNXeApiClient apiClient = getVnxUnityClient(storage);
for (ExportRule exportRule : existingDBExportRules) {
if (exportRule.getReadOnlyHosts() != null) {
dbReadOnlyHost.addAll(exportRule.getReadOnlyHosts());
}
if (exportRule.getReadWriteHosts() != null) {
dbReadWriteHost.addAll(exportRule.getReadWriteHosts());
}
if (exportRule.getRootHosts() != null) {
dbRootHost.addAll(exportRule.getRootHosts());
}
String vnxeExportId = exportRule.getDeviceExportId();
if (vnxeExportId != null) {
List<VNXeNfsShare> vnxeExports = null;
vnxeExports = apiClient.getNfsSharesForFileSystem(args.getFs().getNativeId());
exportsList.addAll(vnxeExports);
for (VNXeNfsShare vnXeNfsShare : vnxeExports) {
List<VNXeBase> hostIdReadOnly = vnXeNfsShare.getReadOnlyHosts();
for (VNXeBase vnXeBase : hostIdReadOnly) {
VNXeHost host = apiClient.getHostById(vnXeBase.getId());
arrayReadOnlyHost.add(host.getName());
}
List<VNXeBase> hostIdReadWrite = vnXeNfsShare.getReadWriteHosts();
for (VNXeBase vnXeBase : hostIdReadWrite) {
VNXeHost host = apiClient.getHostById(vnXeBase.getId());
arrayReadWriteHost.add(host.getName());
}
List<VNXeBase> hostIdRootHost = vnXeNfsShare.getRootAccessHosts();
for (VNXeBase vnXeBase : hostIdRootHost) {
VNXeHost host = apiClient.getHostById(vnXeBase.getId());
arrayRootHost.add(host.getName());
}
}
}
// find out the change between array and CoprHD database.
Set<String> arrayExtraReadOnlyHost = Sets.difference(arrayReadOnlyHost, dbReadOnlyHost);
Set<String> arrayExtraReadWriteHost = Sets.difference(arrayReadWriteHost, dbReadWriteHost);
Set<String> arrayExtraRootHost = Sets.difference(arrayRootHost, dbRootHost);
// if change found update the exportRuleMap
if (!arrayExtraReadOnlyHost.isEmpty() || !arrayExtraReadWriteHost.isEmpty() || !arrayExtraRootHost.isEmpty()) {
ExportRule extraRuleFromArray = new ExportRule();
extraRuleFromArray.setDeviceExportId(exportRule.getDeviceExportId());
extraRuleFromArray.setAnon(exportRule.getAnon());
extraRuleFromArray.setSecFlavor(exportRule.getSecFlavor());
extraRuleFromArray.setExportPath(exportRule.getExportPath());
extraRuleFromArray.setReadOnlyHosts(arrayExtraReadOnlyHost);
extraRuleFromArray.setReadWriteHosts(arrayExtraReadWriteHost);
extraRuleFromArray.setRootHosts(arrayExtraRootHost);
exportRuleMap.put(exportRule.getSecFlavor(), extraRuleFromArray);
}
}
return exportRuleMap;
}
@Override
public BiosCommandResult doUpdateQuotaDirectory(StorageSystem storage, FileDeviceInputOutput args, QuotaDirectory qd)
throws ControllerException {
_logger.info("updating Quota Directory: ", args.getQuotaDirectoryName());
VNXUnityQuotaDirectoryTaskCompleter completer = null;
VNXeApiClient apiClient = getVnxUnityClient(storage);
VNXeCommandJob job = null;
try {
Long softLimit = 0L;
Long softGrace = 0L;
Long size = 0L;
if (qd.getSize() == 0) {
size = args.getFsCapacity(); // If quota directory has no size specified, inherit it from the parent fs
// for the calculation of limit sizes
} else {
size = qd.getSize();
}
softLimit = Long.valueOf(qd.getSoftLimit() * size / 100);// conversion from percentage to bytes
// using hard limit
softGrace = Long.valueOf(qd.getSoftGrace() * 24 * 60 * 60); // conversion from days to seconds
job = apiClient.updateQuotaDirectory(qd.getNativeId(), qd.getSize(), softLimit, softGrace);
if (job != null) {
_logger.info("opid:" + args.getOpId());
completer = new VNXUnityQuotaDirectoryTaskCompleter(QuotaDirectory.class, args.getQuotaDirectory().getId(), args.getOpId());
if (args.getQuotaDirectory() == null) {
_logger.error("Could not find the quota object");
}
VNXUnityUpdateFileSystemQuotaDirectoryJob createQuotaJob = new VNXUnityUpdateFileSystemQuotaDirectoryJob(job.getId(),
storage.getId(), completer);
ControllerServiceImpl.enqueueJob(new QueueJob(createQuotaJob));
} else {
_logger.error("No job returned from createQuotaDirectory");
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("No Job returned from createQuotaDirectory");
return BiosCommandResult.createErrorResult(error);
}
} catch (VNXeException e) {
_logger.error("update Quota Directory got an exception", e);
if (completer != null) {
completer.error(dbClient, e);
}
return BiosCommandResult.createErrorResult(e);
} catch (Exception ex) {
_logger.error("update Quota Directory got an exception", ex);
ServiceError error = DeviceControllerErrors.vnxe.jobFailed("UpdateQuotaDirectory", ex.getMessage());
if (completer != null) {
completer.error(dbClient, error);
}
return BiosCommandResult.createErrorResult(error);
}
StringBuilder logMsgBuilder = new StringBuilder(String.format(
"update quota directory job submitted - Array:%s, fileSystem: %s, Quota Directory: %s", storage.getSerialNumber(),
args.getFsName(), args.getQuotaDirectoryName()));
_logger.info(logMsgBuilder.toString());
return BiosCommandResult.createPendingResult();
}
@Override
public BiosCommandResult updateShareACLs(StorageSystem storage, FileDeviceInputOutput args) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("Add or Update CIFS Share ACLs", "Unity"));
}
@Override
public BiosCommandResult deleteShareACLs(StorageSystem storage, FileDeviceInputOutput args) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("Delete CIFS Share ACLs", "Unity"));
}
@Override
public BiosCommandResult assignFilePolicy(StorageSystem storageObj, FileDeviceInputOutput args) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("Assign File Policy", "Unity"));
}
@Override
public BiosCommandResult unassignFilePolicy(StorageSystem storageObj, FileDeviceInputOutput args) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("Unassign File Policy", "Unity"));
}
@Override
public BiosCommandResult listSanpshotByPolicy(StorageSystem storageObj, FileDeviceInputOutput args) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("List Snapshot By Policy", "Unity"));
}
@Override
public BiosCommandResult updateStorageSystemFileProtectionPolicy(StorageSystem storageObj, FileDeviceInputOutput args) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("Update storage system protection policy", "Unity"));
}
@Override
public BiosCommandResult updateNfsACLs(StorageSystem storage, FileDeviceInputOutput args) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported(" Add or Update NFS Share ACLs", "Unity"));
}
@Override
public BiosCommandResult deleteNfsACLs(StorageSystem storageObj, FileDeviceInputOutput args) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("Delete NFS Share ACLs", "Unity"));
}
@Override
public BiosCommandResult doApplyFilePolicy(StorageSystem storageObj, FileDeviceInputOutput args) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("Assign File Policy", "VNXUnity"));
}
@Override
public BiosCommandResult doUnassignFilePolicy(StorageSystem storage, FileDeviceInputOutput fd) throws ControllerException {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("Unassign File Policy", "Unity"));
}
@Override
public BiosCommandResult checkFilePolicyExistsOrCreate(StorageSystem storageObj, FileDeviceInputOutput args) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("Assign File Policy", "Unity"));
}
@Override
public BiosCommandResult checkFileReplicationPolicyExistsOrCreate(StorageSystem sourceStorageObj, StorageSystem targetStorageObj,
FileDeviceInputOutput sourceSytemArgs, FileDeviceInputOutput targetSytemArgs) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("Assign File Policy", "Unity"));
}
@Override
public BiosCommandResult doStartMirrorLink(StorageSystem system, FileShare source, TaskCompleter completer) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("start the mirror link", "Unity"));
}
@Override
public BiosCommandResult doRefreshMirrorLink(StorageSystem system, FileShare source) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("refresh the mirror link", "Unity"));
}
@Override
public BiosCommandResult doPauseLink(StorageSystem system, FileShare source) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("pause the mirror link", "Unity"));
}
@Override
public BiosCommandResult doResumeLink(StorageSystem system, FileShare target, TaskCompleter completer) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("resume the mirror link", "Unity"));
}
@Override
public BiosCommandResult doFailoverLink(StorageSystem system, FileShare target, TaskCompleter completer) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("failover the mirror link", "Unity"));
}
@Override
public BiosCommandResult checkFilePolicyPathHasResourceLabel(StorageSystem system, FileDeviceInputOutput args) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("check file policy path", "Unity"));
}
@Override
public BiosCommandResult doResyncLink(StorageSystem system, FileShare source, TaskCompleter completer) {
return BiosCommandResult.createErrorResult(
DeviceControllerErrors.vnxe.operationNotSupported("resync the mirror link", "Unity"));
}
}