/*
* Copyright (c) 2015 EMC Corporation
* All Rights Reserved
*/
package controllers.arrays;
import static com.emc.vipr.client.core.util.ResourceUtils.id;
import static com.emc.vipr.client.core.util.ResourceUtils.uri;
import static com.emc.vipr.client.core.util.ResourceUtils.uris;
import static controllers.security.Security.isProjectAdmin;
import static controllers.security.Security.isTenantAdmin;
import static util.BourneUtil.getViprClient;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
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 java.util.TreeSet;
import org.apache.commons.lang.StringUtils;
import com.emc.storageos.db.client.model.DiscoveredDataObject;
import com.emc.storageos.db.client.util.EndpointUtility;
import com.emc.storageos.model.NamedRelatedResourceRep;
import com.emc.storageos.model.pools.StoragePoolRestRep;
import com.emc.storageos.model.pools.StoragePoolUpdate;
import com.emc.storageos.model.ports.StoragePortRequestParam;
import com.emc.storageos.model.ports.StoragePortRestRep;
import com.emc.storageos.model.ports.StoragePortUpdate;
import com.emc.storageos.model.project.ProjectRestRep;
import com.emc.storageos.model.project.VirtualNasParam;
import com.emc.storageos.model.smis.StorageProviderRestRep;
import com.emc.storageos.model.storagesystem.type.StorageSystemTypeRestRep;
import com.emc.storageos.model.systems.StorageSystemRequestParam;
import com.emc.storageos.model.systems.StorageSystemRestRep;
import com.emc.storageos.model.systems.StorageSystemUpdateRequestParam;
import com.emc.storageos.model.valid.Endpoint;
import com.emc.storageos.model.vnas.VirtualNASRestRep;
import com.emc.vipr.client.Task;
import com.google.common.collect.Lists;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import controllers.Common;
import controllers.arrays.StorageProviders.StorageProviderForm;
import controllers.deadbolt.Restrict;
import controllers.deadbolt.Restrictions;
import controllers.util.FlashException;
import controllers.util.ViprResourceController;
import models.BlockProtocols;
import models.PoolTypes;
import models.RegistrationStatus;
import models.StorageProviderTypes;
import models.StorageSystemTypes;
import models.datatable.StoragePoolDataTable;
import models.datatable.StoragePoolDataTable.StoragePoolInfo;
import models.datatable.StoragePortDataTable;
import models.datatable.StoragePortDataTable.StoragePortInfo;
import models.datatable.StorageSystemDataTable;
import models.datatable.StorageSystemDataTable.StorageSystemInfo;
import models.datatable.VirtualNasServerDataTable;
import models.datatable.VirtualNasServerDataTable.VirtualNasServerInfo;
import play.data.binding.As;
import play.data.validation.Max;
import play.data.validation.MaxSize;
import play.data.validation.Min;
import play.data.validation.MinSize;
import play.data.validation.Required;
import play.data.validation.Validation;
import play.mvc.With;
import util.BourneUtil;
import util.EnumOption;
import util.MessagesUtils;
import util.StoragePoolUtils;
import util.StoragePortUtils;
import util.StorageSystemUtils;
import util.StringOption;
import util.TenantUtils;
import util.VCenterUtils;
import util.datatable.DataTablesSupport;
import util.validation.HostNameOrIpAddress;
@With(Common.class)
@Restrictions({ @Restrict("SYSTEM_ADMIN"), @Restrict("RESTRICTED_SYSTEM_ADMIN") })
public class StorageSystems extends ViprResourceController {
protected static final String SAVED_ARRAY = "StorageSystems.savedArray";
protected static final String SAVED_SMIS = "StorageSystems.savedSMIS";
protected static final String DELETED_SUCCESS = "StorageSystems.deleted.success";
protected static final String DELETED_ERROR = "StorageSystems.deleted.error";
protected static final String UNKNOWN = "StorageSystems.unknown";
protected static final String NAME_NOT_AVAILABLE = "StorageSystems.nameNotAvailable";
protected static final String SAVED_POOL = "StorageSystems.savedPool";
protected static final String DEREGISTER_SUCCESS = "PhysicalAssets.deregistration.success";
protected static final String DEREGISTER_ERROR = "PhysicalAssets.deregistration.error";
protected static final String REGISTER_SUCCESS = "PhysicalAssets.registration.success";
protected static final String REGISTER_ERROR = "PhysicalAssets.registration.error";
protected static final String UNKNOWN_PORT = "storageArrayPort.unknown";
protected static final String NOT_REGISTERED = "StorageSystems.not.registered";
protected static final String PARSE_ERROR = "storageArray.parseError";
protected static final String SECONDARY_DETAIL_MISSING = "storageArray.secondaryHost.secondaryPort.missing";
protected static final String SECONDARY_USER_MISSING = "storageArray.secondaryName.missing";
protected static final String SCALEIO = "scaleio";
protected static final String VMAX = "vmax";
private static final String EXPECTED_GEO_VERSION_FOR_VNAS_SUPPORT = "2.4";
private static final String HTTPS = "https";
private static final String VIPR_START_GUIDE = "VIPR_START_GUIDE";
private static final String GUIDE_DATA = "GUIDE_DATA";
private static final String STORAGE_SYSTEMS = "storage_systems";
private static final String GUIDE_VISIBLE = "guideVisible";
private static final String GUIDE_COMPLETED_STEP = "completedSteps";
private static final String SMIS_VMAX = "StorageSystemType.STORAGE_PROVIDER.vmax";
// key: storage system type, value: storage provider type
private static Map<String, String> nonNativeSystemProviderMap = new HashMap<String, String>();
private static void buildSouthBoundTypeMap() {
nonNativeSystemProviderMap.clear();
Map<String, StorageSystemTypeRestRep> typeMap = StorageSystemTypes.buildTypeMap();
for (StorageSystemTypeRestRep type : typeMap.values()) {
if (type.isNative() || type.getManagedBy() == null) {
continue;
}
nonNativeSystemProviderMap.put(type.getStorageTypeName(),
typeMap.get(type.getManagedBy()).getStorageTypeName());
}
}
private static void addReferenceData() {
renderArgs.put("storageArrayTypeList", StorageSystemTypes.getStorageTypeOptions());
renderArgs.put("smisStorageSystemTypeList", StorageProviderTypes.getProviderOption());
renderArgs.put("nonSmisStorageSystemTypeList", StorageSystemTypes.getStorageTypeOptions());
renderArgs.put("sslDefaultStorageSystemList", StorageProviderTypes.getProvidersWithSSL());
renderArgs.put("nonSSLStorageSystemList", StorageProviderTypes.getProvidersWithoutSSL());
List<EnumOption> defaultStorageArrayPortMap = StorageProviderTypes.getStoragePortMap();
renderArgs.put("defaultStorageArrayPortMap", defaultStorageArrayPortMap);
}
private static void addReferenceDataAllFlash() {
renderArgs.put("storageArrayTypeList", StorageSystemTypes.getAllFlashStorageTypeOptions());
renderArgs.put("smisStorageSystemTypeList", StorageProviderTypes.getProviderOption());
renderArgs.put("nonSmisStorageSystemTypeList", StorageSystemTypes.getStorageTypeOptions());
renderArgs.put("sslDefaultStorageSystemList", StorageProviderTypes.getProvidersWithSSL());
renderArgs.put("nonSSLStorageSystemList", StorageProviderTypes.getProvidersWithoutSSL());
List<EnumOption> defaultStorageArrayPortMap = StorageProviderTypes.getStoragePortMap();
renderArgs.put("defaultStorageArrayPortMap", defaultStorageArrayPortMap);
}
public static void list() {
renderArgs.put("dataTable", new StorageSystemsDataTable());
render();
}
public static class StorageSystemsDataTable extends StorageSystemDataTable {
public StorageSystemsDataTable() {
addColumn("actions").setRenderFunction("renderButtonBar");
sortAllExcept("actions");
}
}
public static void discoveryCheckJson(@As(",") String[] ids) {
List<String> failedDiscovery = new ArrayList<String>();
for (String id : ids) {
StorageSystemRestRep storageSystem = StorageSystemUtils
.getStorageSystem(id);
if (storageSystem == null || storageSystem.getRegistrationStatus().equals("UNREGISTERED")) {
// ignore for now
continue;
}
if (!storageSystem.getDiscoveryJobStatus().equals("COMPLETE")) {
failedDiscovery.add(storageSystem.getName());
continue;
}
}
renderJSON(failedDiscovery);
}
public static void listJson() {
performListJson(StorageSystemUtils.getStorageSystems(),
new JsonItemOperation());
}
public static void itemsJson(@As(",") String[] ids) {
itemsJson(uris(ids));
}
private static void itemsJson(List<URI> ids) {
performItemsJson(StorageSystemUtils.getStorageSystems(ids),
new JsonItemOperation());
}
public static void itemDetails(String id) {
StorageSystemRestRep storageSystem = StorageSystemUtils
.getStorageSystem(id);
if (storageSystem == null) {
error(MessagesUtils.get(UNKNOWN, id));
}
StorageProviderRestRep smisProvider = StorageSystemUtils
.getStorageProvider(storageSystem);
Map<String, Set<NamedRelatedResourceRep>> connectivityMap = StorageSystemUtils
.getProtectionConnectivityMap(storageSystem);
render(storageSystem, smisProvider, connectivityMap);
}
public static void create() {
// Check add is called from guide wizard, yes only AFA
JsonObject jobject = getCookieAsJson(VIPR_START_GUIDE);
String isGuideAdd = null;
if (jobject != null && jobject.get(GUIDE_VISIBLE) != null) {
isGuideAdd = jobject.get(GUIDE_VISIBLE).getAsString();
}
if (isGuideAdd != null && StringUtils.equalsIgnoreCase(isGuideAdd, "true")) {
addReferenceDataAllFlash();
} else {
addReferenceData();
}
StorageSystemForm storageArray = new StorageSystemForm();
// put all "initial create only" defaults here rather than field initializers
storageArray.type = StorageSystemTypes.VMAX;
storageArray.useSSL = true;
storageArray.userName = "";
storageArray.smisProviderUseSSL = false;
render("@edit", storageArray);
}
public static void createAllFlash() {
addReferenceDataAllFlash();
StorageSystemForm storageArray = new StorageSystemForm();
// put all "initial create only" defaults here rather than field initializers
storageArray.type = StorageSystemTypes.VMAX;
storageArray.useSSL = true;
storageArray.userName = "";
storageArray.smisProviderUseSSL = true;
render("@edit", storageArray);
}
@FlashException("list")
public static void edit(String id) {
addReferenceData();
StorageSystemRestRep storageSystem = StorageSystemUtils
.getStorageSystem(id);
if (storageSystem != null) {
StorageSystemForm storageArray = new StorageSystemForm(
storageSystem);
if (storageArray.type.equals(SCALEIO)) {
renderArgs.put("storageArrayTypeList",
StorageProviderTypes.getProviderOption());
}
if (storageArray.type.equals("xtremio")) {
renderArgs.put("storageArrayTypeList",
StorageProviderTypes.getProviderOption());
}
if (storageArray.unregistered) {
flash.put("warning",
MessagesUtils.get(NOT_REGISTERED, storageArray.name));
}
if (storageArray.type.equals(VMAX)) {
@SuppressWarnings("unchecked")
List<StringOption> options = (List<StringOption>) renderArgs.get("storageArrayTypeList");
options.add(new StringOption(VMAX, MessagesUtils.get(SMIS_VMAX)));
@SuppressWarnings("unchecked")
List<StringOption> smisOptions = (List<StringOption>) renderArgs.get("smisStorageSystemTypeList");
smisOptions.add(new StringOption(VMAX, MessagesUtils.get(SMIS_VMAX)));
}
render(storageArray);
} else {
flash.error(MessagesUtils.get(UNKNOWN, id));
list();
}
}
public static void editSmisProvider(String id) {
Common.setReferrer(Common.reverseRoute(StorageSystems.class, "list"));
StorageProviders.edit(id);
}
@FlashException(keep = true, referrer = { "create", "edit" })
public static void save(StorageSystemForm storageArray) {
storageArray.validate("storageArray");
if (Validation.hasErrors()) {
Common.handleError();
}
Task<?> sp = storageArray.save();
String message = storageArray.isStorageProviderManaged()
&& StringUtils.isEmpty(storageArray.id) ? MessagesUtils.get(
SAVED_SMIS, storageArray.name) : MessagesUtils.get(SAVED_ARRAY, storageArray.name);
flash.success(message);
// check if checklist is running on this step
JsonObject jobject = getCookieAsJson(VIPR_START_GUIDE);
if (jobject != null && jobject.get(GUIDE_COMPLETED_STEP) != null && jobject.get(GUIDE_VISIBLE) != null) {
if (jobject.get(GUIDE_COMPLETED_STEP).getAsInt() == 3
&& jobject.get(GUIDE_VISIBLE).getAsBoolean()) {
JsonObject dataObject = getCookieAsJson(GUIDE_DATA);
JsonArray storage_systems = dataObject
.getAsJsonArray(STORAGE_SYSTEMS);
if (storage_systems == null) {
storage_systems = new JsonArray();
}
JsonObject storage = new JsonObject();
storage.addProperty("id", sp.getResourceId().toString());
storage.addProperty("name", storageArray.name);
storage_systems.add(storage);
dataObject.add(STORAGE_SYSTEMS, storage_systems);
saveJsonAsCookie(GUIDE_DATA, dataObject);
list();
}
}
// TODO: cleanup referrer
if (StringUtils.isNotEmpty(storageArray.referrerUrl)) {
redirect(storageArray.referrerUrl);
}
list();
}
public static void delete(@As(",") String[] ids) {
delete(uris(ids));
}
private static void delete(List<URI> ids) {
List<StorageSystemRestRep> storageSystems = StorageSystemUtils
.getStorageSystems(ids);
performSuccessFail(storageSystems, new DeleteOperation(),
DELETED_SUCCESS, DELETED_ERROR);
list();
}
public static void introspect(@As(",") String[] ids) {
introspect(uris(ids));
}
private static void introspect(List<URI> ids) {
performSuccess(ids, new DiscoveryOperation(), DISCOVERY_STARTED);
list();
}
public static void deregisterArrays(@As(",") String[] ids) {
deregisterArrays(uris(ids));
}
private static void deregisterArrays(List<URI> ids) {
performSuccessFail(ids, new DeregisterOperation(), DEREGISTER_SUCCESS,
DEREGISTER_ERROR);
list();
}
public static void registerArrays(@As(",") String[] ids) {
registerArrays(uris(ids));
}
private static void registerArrays(List<URI> ids) {
performSuccessFail(ids, new RegisterOperation(), REGISTER_SUCCESS,
REGISTER_ERROR);
list();
}
//
// begin Storage Array > Port functionality
//
public static void deregisterPorts(@As(",") String[] ids, String arrayId) {
deregisterPorts(uris(ids), arrayId);
}
private static void deregisterPorts(List<URI> ids, String arrayId) {
performSuccessFail(ids, new DeregisterPortOperation(),
DEREGISTER_SUCCESS, DEREGISTER_ERROR);
ports(arrayId);
}
public static void registerPorts(@As(",") String[] ids, String arrayId) {
registerPorts(uris(ids), arrayId);
}
private static void registerPorts(List<URI> ids, String arrayId) {
performSuccessFail(ids, new RegisterPortOperation(arrayId),
REGISTER_SUCCESS, REGISTER_ERROR);
ports(arrayId);
}
public static void untagAsDRPorts(@As(",") String[] ids, String arrayId) {
Set<String> removeTags = new HashSet<String>();
removeTags.add("dr_port");
for (int i = 0; i < ids.length; i++) {
BourneUtil.getViprClient().storagePorts().removeTags(uri(ids[i]), removeTags);
}
ports(arrayId);
}
public static void tagAsDRPorts(@As(",") String[] ids, String arrayId) {
Set<String> addTags = new HashSet<String>();
addTags.add("dr_port");
for (int i = 0; i < ids.length; i++) {
BourneUtil.getViprClient().storagePorts().addTags(uri(ids[i]), addTags);
}
ports(arrayId);
}
public static void arrayPortsJson(String id) {
List<StoragePortInfo> results = Lists.newArrayList();
List<StoragePortRestRep> storagePorts = StoragePortUtils
.getStoragePorts(id);
for (StoragePortRestRep storagePort : storagePorts) {
results.add(new StoragePortInfo(storagePort));
}
renderJSON(DataTablesSupport.createJSON(results, params));
}
public static void metricDetails(String id) {
StoragePortRestRep port = StoragePortUtils.getStoragePort(id);
render(port);
}
public static void ports(String id) {
addReferenceData();
StorageSystemRestRep storageSystem = StorageSystemUtils
.getStorageSystem(id);
if (storageSystem == null) {
flash.error(MessagesUtils.get(UNKNOWN, id));
list();
}
StorageArrayPortDataTable dataTable = new StorageArrayPortDataTable(
storageSystem);
render("@listPorts", storageSystem, dataTable);
}
public static void createPort(String id) {
StorageSystemRestRep storageSystem = StorageSystemUtils
.getStorageSystem(id);
StringOption[] portTypeOptions = {
new StringOption("", ""),
new StringOption("IP", StringOption.getDisplayValue("IP",
"storageArrayPort.portTypes")),
new StringOption("FC", StringOption.getDisplayValue("FC",
"storageArrayPort.portTypes")), };
renderArgs.put("portTypeOptions", Arrays.asList(portTypeOptions));
render(storageSystem);
}
public static void editPort(String id, String portId) {
StoragePortRestRep storagePort = StoragePortUtils
.getStoragePort(portId);
if (storagePort == null) {
flash.error(MessagesUtils.get(UNKNOWN_PORT, portId));
ports(id);
}
URI storageSystemId = id(storagePort.getStorageDevice());
StorageSystemRestRep storageSystem = StorageSystemUtils
.getStorageSystem(storageSystemId);
if (storageSystem == null) {
flash.error(MessagesUtils.get(UNKNOWN, storageSystemId));
list();
}
if (RegistrationStatus.isUnregistered(storageSystem
.getRegistrationStatus())) {
flash.put("warning",
MessagesUtils.get(NOT_REGISTERED, storageSystem.getName()));
}
StorageArrayPortForm storageArrayPort = new StorageArrayPortForm();
storageArrayPort.readFrom(storagePort);
render(storageArrayPort, storagePort, storageSystem);
}
@FlashException(keep = true, referrer = { "ports" })
public static void savePort(StorageArrayPortForm storageArrayPort) {
storageArrayPort.validate("storageArrayPort");
if (Validation.hasErrors()) {
Common.handleError();
}
StoragePortRestRep port = storageArrayPort.save();
flash.success(MessagesUtils.get(SAVED_POOL, port.getPortName()));
ports(stringId(port.getStorageDevice()));
}
//
// begin Storage Array > Pool functionality
//
public static void deregisterPools(@As(",") String[] ids, String arrayId) {
deregisterPools(uris(ids), arrayId);
}
private static void deregisterPools(List<URI> ids, String arrayId) {
performSuccess(ids, new DeregisterPoolOperation(), DEREGISTER_SUCCESS);
pools(arrayId);
}
public static void registerPools(@As(",") String[] ids, String arrayId) {
registerPools(uris(ids), arrayId);
}
private static void registerPools(List<URI> ids, String arrayId) {
performSuccess(ids, new RegisterPoolOperation(arrayId),
REGISTER_SUCCESS);
pools(arrayId);
}
public static void arrayPoolsJson(String id) {
List<StoragePoolInfo> results = Lists.newArrayList();
List<StoragePoolRestRep> storagePools = StoragePoolUtils
.getStoragePools(id);
for (StoragePoolRestRep storagePool : storagePools) {
if (!DiscoveredDataObject.DiscoveryStatus.NOTVISIBLE.name().equals(
storagePool.getDiscoveryStatus())) {
results.add(new StoragePoolInfo(storagePool));
}
}
renderJSON(DataTablesSupport.createJSON(results, params));
}
public static void pools(String id) {
addReferenceData();
StorageSystemRestRep storageSystem = StorageSystemUtils
.getStorageSystem(id);
StorageArrayPoolDataTable dataTable = new StorageArrayPoolDataTable();
if (StorageSystemTypes.isFileStorageSystem(storageSystem
.getSystemType())) {
dataTable.configureForFile();
}
if (StorageSystemTypes.isECS(storageSystem.getSystemType())) {
dataTable.configureForECS();
}
render("@listPools", storageSystem, dataTable);
}
public static void virtualNasServers(String id) {
addReferenceData();
StorageSystemRestRep storageSystem = StorageSystemUtils
.getStorageSystem(id);
VirtualNasServerDataTable dataTable;
if (isTenantAdmin() || isProjectAdmin()) {
dataTable = new VirtualNasServerDataTable();
} else {
dataTable = new VirtualNasForNonProjectAdminDataTable();
}
renderArgs.put("storageId", id);
renderArgs
.put("expectedGeoVersion",
VCenterUtils
.checkCompatibleVDCVersion(EXPECTED_GEO_VERSION_FOR_VNAS_SUPPORT));
render("@listVirtualNasServers", storageSystem, dataTable);
}
public static class VirtualNasForNonProjectAdminDataTable extends
VirtualNasServerDataTable {
public VirtualNasForNonProjectAdminDataTable() {
alterColumn("project").hidden();
}
}
@FlashException(keep = true, referrer = { "virtualNasServers" })
public static void associateProject(String nasIds, String projectIds,
String storageId) throws Exception {
boolean error = false;
Set<String> vnasServers = new TreeSet<String>();
String[] projectIdArray = null;
if (nasIds != null && !nasIds.isEmpty()) {
String[] nasArray = nasIds.split(",");
Collections.addAll(vnasServers, nasArray);
}
if (projectIds != null && !projectIds.isEmpty()) {
projectIds = projectIds.trim();
projectIdArray = projectIds.split(",");
}
VirtualNasParam vNasParam = new VirtualNasParam();
vNasParam.setVnasServers(vnasServers);
if (projectIdArray != null && projectIdArray.length > 0) {
for (int i = 0; i < projectIdArray.length; i++) {
try {
getViprClient().virtualNasServers().assignVnasServers(
uri(projectIdArray[i].trim()), vNasParam);
} catch (Exception e) {
error = true;
continue;
}
}
if (error) {
String errorMsg = "Some Virtual NAS servers could not be associated with selected project(s). Please check the API logs for more information.";
throw new Exception(errorMsg);
}
}
virtualNasServers(storageId);
}
@FlashException(keep = true, referrer = { "virtualNasServers" })
public static void dissociateProject(
@As(",") String[] projectIdsToDissociate, String nasIds,
String storageId) {
if (projectIdsToDissociate != null && projectIdsToDissociate.length > 0) {
for (String projectId : projectIdsToDissociate) {
Set<String> vNASSet = new HashSet<String>();
vNASSet.add(nasIds);
VirtualNasParam vNasParam = new VirtualNasParam();
vNasParam.setVnasServers(vNASSet);
getViprClient().virtualNasServers().unassignVnasServers(
uri(projectId), vNasParam);
}
}
virtualNasServers(storageId);
}
public static void virtualNasServersJson(String storageId) {
List<VirtualNasServerInfo> results = Lists.newArrayList();
List<VirtualNASRestRep> vNasServers = getViprClient()
.virtualNasServers().getByStorageSystem(uri(storageId));
boolean isProjectAccessible = false;
if (isTenantAdmin() || isProjectAdmin()) {
isProjectAccessible = true;
}
for (VirtualNASRestRep vNasServer : vNasServers) {
results.add(new VirtualNasServerInfo(vNasServer,
isProjectAccessible));
}
renderArgs.put("storageId", storageId);
renderArgs
.put("expectedGeoVersion",
VCenterUtils
.checkCompatibleVDCVersion(EXPECTED_GEO_VERSION_FOR_VNAS_SUPPORT));
renderJSON(DataTablesSupport.createJSON(results, params));
}
public static void getProjectsForNas() {
List<URI> tenants = Lists.newArrayList();
List<StringOption> allTenants = TenantUtils.getUserSubTenantOptions();
Iterator<StringOption> tenantsIterator = allTenants.iterator();
while (tenantsIterator.hasNext()) {
StringOption tenant = tenantsIterator.next();
if (tenant == null) {
continue;
}
tenants.add(uri(tenant.id));
}
List<StringOption> projectTenantOptions = Lists.newArrayList();
for (URI tenantId : tenants) {
String tenantName = getViprClient().tenants().get(tenantId)
.getName();
List<String> projectOptions = Lists.newArrayList();
List<ProjectRestRep> projects = getViprClient().projects()
.getByTenant(tenantId);
for (ProjectRestRep project : projects) {
projectOptions.add(project.getId().toString() + "~~~"
+ project.getName());
}
projectTenantOptions.add(new StringOption(
projectOptions.toString(), tenantName));
}
renderJSON(projectTenantOptions);
}
public static void vNasMoreDetails(String id) {
id = id.substring(0, id.indexOf("~~~"));
List<URI> ids = Lists.newArrayList();
ids.add(uri(id));
List<VirtualNASRestRep> vNasRep = getViprClient().virtualNasServers()
.getByIds(ids);
VirtualNASRestRep vNas = new VirtualNASRestRep();
if (!vNasRep.isEmpty()) {
vNas = vNasRep.get(0);
}
render(vNas);
}
public static void editPool(String id, String poolId) {
StoragePoolRestRep storagePool = StoragePoolUtils
.getStoragePool(poolId);
StorageSystemRestRep storageSystem = StorageSystemUtils
.getStorageSystem(id(storagePool.getStorageSystem()));
if (RegistrationStatus.isUnregistered(storageSystem
.getRegistrationStatus())) {
flash.put("warning",
MessagesUtils.get(NOT_REGISTERED, storageSystem.getName()));
}
StorageArrayPoolForm storageArrayPool = new StorageArrayPoolForm();
storageArrayPool.readFrom(storagePool);
render(storageArrayPool, storagePool, storageSystem);
}
@FlashException(keep = true, referrer = { "editPool" })
public static void savePool(StorageArrayPoolForm storageArrayPool) {
storageArrayPool.validate("storageArrayPool");
if (Validation.hasErrors()) {
Common.handleError();
}
StoragePoolRestRep pool = storageArrayPool.save();
flash.success(MessagesUtils.get(SAVED_POOL, pool.getPoolName()));
pools(stringId(pool.getStorageSystem()));
}
public static class StorageArrayPoolForm {
public String storageArrayId;
public String id;
@MaxSize(128)
@MinSize(2)
public String name;
@Required
@Min(0)
@Max(100)
public Integer maxPoolUtilizationPercentage;
@Min(0)
public Integer maxThinPoolSubscriptionPercentage;
@Min(0)
public Integer resourceLimit;
public String poolType;
public boolean supportsThinProvisioning;
public StorageArrayPoolForm() {
}
public void readFrom(StoragePoolRestRep storagePool) {
this.storageArrayId = stringId(storagePool.getStorageSystem());
this.id = stringId(storagePool);
this.name = storagePool.getPoolName();
this.maxPoolUtilizationPercentage = storagePool
.getMaxPoolUtilizationPercentage();
if ((storagePool.getMaxResources() != null)
&& (storagePool.getMaxResources() > -1)) {
this.resourceLimit = storagePool.getMaxResources();
}
this.poolType = storagePool.getPoolServiceType();
this.supportsThinProvisioning = StoragePoolUtils
.supportsThinProvisioning(storagePool);
if (supportsThinProvisioning) {
this.maxThinPoolSubscriptionPercentage = storagePool
.getMaxThinPoolSubscriptionPercentage();
}
}
public StoragePoolRestRep save() {
return update();
}
private StoragePoolRestRep update() {
StoragePoolUpdate storagePoolParam = new StoragePoolUpdate();
storagePoolParam
.setMaxPoolUtilizationPercentage(this.maxPoolUtilizationPercentage);
if (maxThinPoolSubscriptionPercentage != null) {
storagePoolParam
.setMaxThinPoolSubscriptionPercentage(this.maxThinPoolSubscriptionPercentage);
}
if ((resourceLimit != null) && (resourceLimit > -1)) {
storagePoolParam.setMaxResources(this.resourceLimit);
storagePoolParam.setIsUnlimitedResourcesSet(false);
} else {
storagePoolParam.setMaxResources(null);
storagePoolParam.setIsUnlimitedResourcesSet(true);
}
return StoragePoolUtils.update(id, storagePoolParam);
}
public void validate(String fieldName) {
Validation.valid(fieldName, this);
}
}
public static class StorageArrayPortForm {
public URI storageArrayId;
public URI id;
@Required
@MinSize(2)
@MaxSize(128)
public String name;
@Required
public String portType;
@Required
public String port;
public void readFrom(StoragePortRestRep storagePort) {
storageArrayId = storagePort.getStorageDevice().getId();
id = storagePort.getId();
name = storagePort.getPortName();
portType = storagePort.getTransportType();
port = storagePort.getPortNetworkId();
}
public StoragePortRestRep save() {
return (id == null) ? create() : update();
}
private StoragePortRestRep create() {
StoragePortRequestParam storagePortParam = new StoragePortRequestParam();
storagePortParam.setName(name);
storagePortParam.setTransportType(portType);
storagePortParam.setPortNetworkId(port);
return StoragePortUtils.create(storageArrayId, storagePortParam);
}
private StoragePortRestRep update() {
StoragePortUpdate storagePortParam = new StoragePortUpdate();
storagePortParam.setPortNetworkId(port);
return StoragePortUtils.update(id, storagePortParam);
}
public void validate(String fieldName) {
Validation.valid(fieldName, this);
if (BlockProtocols.isFC(portType)) {
if (port != null
&& !EndpointUtility.isValidEndpoint(port,
Endpoint.EndpointType.WWN)) {
Validation.addError(fieldName + ".port",
"storageArrayPort.port.invalidWWN");
}
} else {
boolean valid = EndpointUtility.isValidEndpoint(port,
Endpoint.EndpointType.IQN);
if (!valid) {
Validation.addError(fieldName + ".port",
"storageArrayPort.port.invalidIQN");
}
}
}
}
// Suppressing Sonar violation of Password Hardcoded. Password is not
// hardcoded here.
@SuppressWarnings("squid:S2068")
public static class StorageSystemForm {
public String id;
@Required
public String type;
@MaxSize(2048)
@Required
public String name;
@Required
@HostNameOrIpAddress
public String ipAddress;
@Required
public Integer portNumber;
@MaxSize(2048)
public String userName;
@MaxSize(2048)
public String userPassword;
@MaxSize(2048)
public String confirmPassword;
@MaxSize(2048)
public String secondaryUsername = "";
@MaxSize(2048)
public String secondaryPassword = "";
@MaxSize(2048)
public String secondaryPasswordConfirm = "";
public String elementManagerURL;
public String secretKey;
public Boolean useSSL;
public Integer resourceLimit;
public String resourceType;
public boolean unlimitResource;
public boolean supportsSoftLimit;
public boolean supportsNotificationLimit;
//
// a flag to set if unlimitResource control was previously visible.
// This is used upon save failure for UI to correctly recover
// UnlimitResource control
// state after save failure.
//
public boolean unlimitResourceWasVisible;
//
// onboard smis provider attributes
//
public String smisProviderIpAddress;
public Integer smisProviderPortNumber;
public String smisProviderUserName;
public String smisProviderUserPassword;
public String smisProviderConfirmPassword;
public boolean smisProviderUseSSL;
public String referrerUrl;
public boolean unregistered;
@MaxSize(2048)
public String hyperScaleUsername;
@MaxSize(2048)
public String hyperScalePassword = "";
@MaxSize(2048)
public String hyperScalePasswordConfirm = "";
public String hyperScaleHost;
public String hyperScalePort;
public URL url;
public String secondaryURL;
public StorageSystemForm() {
this.userPassword = "";
this.confirmPassword = "";
this.smisProviderUserPassword = "";
this.smisProviderConfirmPassword = "";
}
public StorageSystemForm(StorageSystemRestRep storageArray) {
this.id = storageArray.getId().toString();
this.name = StorageSystemUtils.getName(storageArray);
this.type = storageArray.getSystemType();
this.supportsSoftLimit = storageArray.getSupportsSoftLimit();
this.supportsNotificationLimit = storageArray
.getSupportsNotificationLimit();
// VNX Block uses the same select option as VMAX
if (StorageSystemTypes.isVnxBlock(type)) {
this.type = StorageSystemTypes.VMAX;
}
this.resourceType = PoolTypes.fromStorageSystemType(storageArray
.getSystemType());
this.userName = storageArray.getUsername();
this.resourceLimit = storageArray.getMaxResources() != null ? storageArray
.getMaxResources() : 0;
this.unlimitResource = this.unlimitResourceWasVisible = this.resourceLimit != null
&& this.resourceLimit == -1;
this.unregistered = RegistrationStatus.isUnregistered(storageArray
.getRegistrationStatus());
if (isStorageProviderManaged()) {
this.useSSL = storageArray.getSmisUseSSL();
this.portNumber = storageArray.getSmisPortNumber();
this.ipAddress = storageArray.getSmisProviderIP();
} else {
this.portNumber = storageArray.getPortNumber();
this.ipAddress = storageArray.getIpAddress();
this.smisProviderIpAddress = storageArray.getSmisProviderIP();
this.smisProviderPortNumber = storageArray.getSmisPortNumber();
this.smisProviderUseSSL = storageArray.getSmisUseSSL();
this.smisProviderUserName = storageArray.getSmisUserName();
}
}
public boolean isNew() {
return StringUtils.isBlank(id);
}
public Task<StorageSystemRestRep> update() {
StorageSystemUpdateRequestParam storageArray = new StorageSystemUpdateRequestParam();
storageArray.setName(name);
// if unlimit resources was unchecked, set the given limit
if (!unlimitResource) {
storageArray.setMaxResources(resourceLimit);
storageArray.setIsUnlimitedResourcesSet(false);
// allow changing back to unlimited
} else {
storageArray.setIsUnlimitedResourcesSet(true);
storageArray.setMaxResources(null);
}
if (isVnxFile()) {
storageArray.setSmisProviderIP(smisProviderIpAddress);
storageArray.setSmisPortNumber(smisProviderPortNumber);
storageArray.setSmisUseSSL(smisProviderUseSSL);
storageArray.setSmisPassword(StringUtils
.trimToNull(smisProviderUserPassword));
storageArray.setSmisUserName(StringUtils
.trimToNull(smisProviderUserName));
}
if (!isStorageProviderManaged()) {
storageArray.setIpAddress(ipAddress);
storageArray.setPortNumber(portNumber);
storageArray.setPassword(StringUtils.trimToNull(userPassword));
storageArray.setUserName(StringUtils.trimToNull(userName));
}
if (isScaleIOApi()) {
storageArray.setPassword(secondaryPassword);
}
if (isCeph()) {
storageArray.setPassword(StringUtils.trimToNull(secretKey));
}
return StorageSystemUtils.update(id, storageArray);
}
public Task<StorageSystemRestRep> create() {
StorageSystemRequestParam storageArray = new StorageSystemRequestParam();
storageArray.setName(name);
storageArray.setSystemType(type);
storageArray.setPassword(userPassword);
storageArray.setUserName(userName);
storageArray.setPortNumber(portNumber);
storageArray.setIpAddress(ipAddress);
// storageArray.setRegistrationMode(RegistrationMode.SYSTEM);
if (isVnxFile()) {
storageArray.setSmisPassword(smisProviderUserPassword);
storageArray.setSmisUserName(smisProviderUserName);
storageArray.setSmisPortNumber(smisProviderPortNumber);
storageArray.setSmisProviderIP(smisProviderIpAddress);
storageArray.setSmisUseSSL(smisProviderUseSSL);
}
if (isScaleIOApi()) {
storageArray.setPassword(secondaryPassword);
}
return StorageSystemUtils.create(storageArray);
}
public Task<StorageProviderRestRep> createStorageProvider() {
StorageProviderForm storageProviderForm = new StorageProviderForm();
storageProviderForm.name = this.name;
storageProviderForm.password = this.userPassword;
storageProviderForm.userName = this.userName;
storageProviderForm.useSSL = this.useSSL;
storageProviderForm.ipAddress = this.ipAddress;
storageProviderForm.portNumber = this.portNumber;
storageProviderForm.interfaceType = mapProviderType(this.type);
storageProviderForm.secondaryUsername = this.secondaryUsername;
storageProviderForm.secondaryPassword = this.secondaryPassword;
storageProviderForm.elementManagerURL = this.elementManagerURL;
storageProviderForm.secretKey = this.secretKey;
storageProviderForm.secondaryURL = this.secondaryURL;
return storageProviderForm.create();
}
private String mapProviderType(String type) {
String providerType = StorageProviderTypes.fromStorageArrayType(type);
if (providerType != null) {
return providerType;
}
return nonNativeSystemProviderMap.get(type);
}
public void setSecondaryParameters() {
if (StringUtils.isNotEmpty(this.hyperScaleUsername)) {
this.secondaryUsername = this.hyperScaleUsername;
}
if (StringUtils.isNotEmpty(this.hyperScalePassword)) {
this.secondaryPassword = this.hyperScalePassword;
}
if (StringUtils.isNotEmpty(this.hyperScalePasswordConfirm)) {
this.secondaryPasswordConfirm = this.hyperScalePasswordConfirm;
}
if (StringUtils.isNotEmpty(this.hyperScaleHost) && StringUtils.isNotEmpty(this.hyperScalePort)) {
try {
url = new URL(HTTPS, this.hyperScaleHost, Integer.parseInt(this.hyperScalePort), "");
} catch (Exception e) {
flash.error(MessagesUtils.get(PARSE_ERROR));
}
this.secondaryURL = url.toString();
}
}
public Task<?> save() {
setSecondaryParameters();
buildSouthBoundTypeMap();
if (isNew()) {
if (isStorageProviderManaged()) {
return createStorageProvider();
} else {
return create();
}
} else {
return update();
}
}
public void validate(String fieldName) {
Validation.valid(fieldName, this);
if (isVnxFile()) {
Validation.required(fieldName + ".smisProviderIpAddress",
this.smisProviderIpAddress);
Validation.required(fieldName + ".smisProviderPortNumber",
this.smisProviderPortNumber);
}
if (isNew()) {
if (isCeph()) {
Validation.required(fieldName + ".userName", this.userName);
Validation.required(fieldName + ".secretKey", this.secretKey);
} else if (isScaleIOApi()) {
Validation.required(fieldName + ".secondaryUsername",
this.secondaryUsername);
Validation.required(fieldName + ".secondaryPassword",
this.secondaryPassword);
Validation.required(
fieldName + ".secondaryPasswordConfirm",
this.secondaryPasswordConfirm);
} else {
Validation.required(fieldName + ".userName", this.userName);
Validation.required(fieldName + ".userPassword",
this.userPassword);
Validation.required(fieldName + ".confirmPassword",
this.confirmPassword);
if (isVnxFile()) {
Validation.required(
fieldName + ".smisProviderUserName",
this.smisProviderUserName);
Validation.required(fieldName
+ ".smisProviderUserPassword",
this.smisProviderUserPassword);
Validation.required(fieldName
+ ".smisProviderConfirmPassword",
this.smisProviderConfirmPassword);
}
if (isScaleIO()
&& !isMatchingPasswords(secondaryPassword,
secondaryPasswordConfirm)) {
Validation
.addError(
fieldName + ".secondaryPasswordConfirm",
MessagesUtils
.get("storageArray.secondaryPassword.confirmPassword.not.match"));
}
}
} else {
if (!unlimitResource) {
Validation.required(fieldName + ".resourceLimit",
this.resourceLimit);
Validation.min(fieldName + ".resourceLimit",
this.resourceLimit, 0);
}
}
if (!isScaleIOApi()
&& !isMatchingPasswords(userPassword, confirmPassword)) {
Validation.addError(fieldName + ".confirmPassword",
MessagesUtils
.get("storageArray.confirmPassword.not.match"));
}
if (isVnxFile()) {
if (!isMatchingPasswords(smisProviderUserPassword,
smisProviderConfirmPassword)) {
Validation.addError(fieldName
+ ".smisProviderConfirmPassword", MessagesUtils
.get("storageArray.confirmPassword.not.match"));
}
Validation.required(fieldName + ".smisProviderIpAddress",
this.smisProviderIpAddress);
Validation.required(fieldName + ".smisProviderPortNumber",
this.smisProviderPortNumber);
}
if (isXIV()) {
if ((StringUtils.isNotEmpty(this.hyperScaleHost) && StringUtils.isNotEmpty(this.hyperScalePort))) {
if (StringUtils.isEmpty(hyperScaleUsername)) {
Validation.addError(fieldName + ".hyperScaleUsername", MessagesUtils
.get(SECONDARY_USER_MISSING));
}
} else if (!(StringUtils.isEmpty(this.hyperScaleHost) && StringUtils.isEmpty(this.hyperScalePort))) {
Validation.addError(fieldName + ".hyperScaleHost", MessagesUtils
.get(SECONDARY_DETAIL_MISSING));
Validation.addError(fieldName + ".hyperScalePort", MessagesUtils
.get(SECONDARY_DETAIL_MISSING));
}
if (StringUtils.isNotEmpty(this.hyperScaleUsername)) {
if ((StringUtils.isEmpty(this.hyperScaleHost) || StringUtils.isEmpty(this.hyperScalePort))) {
Validation.addError(fieldName + ".hyperScaleHost", MessagesUtils
.get(SECONDARY_DETAIL_MISSING));
Validation.addError(fieldName + ".hyperScalePort", MessagesUtils
.get(SECONDARY_DETAIL_MISSING));
}
}
}
}
private boolean isMatchingPasswords(String password, String confirm) {
return StringUtils.equals(StringUtils.trimToEmpty(password),
StringUtils.trimToEmpty(confirm));
}
private boolean isStorageProviderManaged() {
return StorageSystemTypes.isStorageProvider(type) || nonNativeSystemProviderMap.containsKey(type);
}
private boolean isVnxFile() {
return StorageSystemTypes.isVnxFile(type);
}
private boolean isScaleIO() {
return StorageSystemTypes.isScaleIO(type);
}
private boolean isScaleIOApi() {
return StorageSystemTypes.isScaleIOApi(type);
}
private boolean isXIV() {
return StorageSystemTypes.isXIV(type);
}
private boolean isIsilon() {
return StorageSystemTypes.isIsilon(type);
}
private boolean isCeph() {
return StorageSystemTypes.isCeph(type);
}
}
protected static class JsonItemOperation implements
ResourceValueOperation<StorageSystemInfo, StorageSystemRestRep> {
@Override
public StorageSystemInfo performOperation(
StorageSystemRestRep storageSystem) throws Exception {
return new StorageSystemInfo(storageSystem);
}
}
protected static class DeleteOperation
implements
ResourceValueOperation<Task<StorageSystemRestRep>, StorageSystemRestRep> {
@Override
public Task<StorageSystemRestRep> performOperation(
StorageSystemRestRep storageSystem) throws Exception {
if (RegistrationStatus.isRegistered(storageSystem
.getRegistrationStatus())) {
StorageSystemUtils.deregister(id(storageSystem));
}
Task<StorageSystemRestRep> task = StorageSystemUtils
.deactivate(id(storageSystem));
return task;
}
}
protected static class DiscoveryOperation implements
ResourceIdOperation<Task<StorageSystemRestRep>> {
@Override
public Task<StorageSystemRestRep> performOperation(URI id)
throws Exception {
Task<StorageSystemRestRep> task = StorageSystemUtils.discover(id);
return task;
}
}
protected static class DeregisterOperation implements
ResourceIdOperation<StorageSystemRestRep> {
@Override
public StorageSystemRestRep performOperation(URI id) throws Exception {
return StorageSystemUtils.deregister(id);
}
}
protected static class RegisterOperation implements
ResourceIdOperation<StorageSystemRestRep> {
@Override
public StorageSystemRestRep performOperation(URI id) throws Exception {
return StorageSystemUtils.register(id);
}
}
protected static class DeregisterPortOperation implements
ResourceIdOperation<Void> {
@Override
public Void performOperation(URI id) throws Exception {
StoragePortUtils.deregister(id);
return null;
}
}
protected static class RegisterPortOperation implements
ResourceIdOperation<Void> {
private URI arrayId;
public RegisterPortOperation(String arrayId) {
this.arrayId = uri(arrayId);
}
@Override
public Void performOperation(URI id) throws Exception {
StoragePortUtils.register(id, arrayId);
return null;
}
}
protected static class DeregisterPoolOperation implements
ResourceIdOperation<Void> {
@Override
public Void performOperation(URI id) throws Exception {
StoragePoolUtils.deregister(id);
return null;
}
}
protected static class RegisterPoolOperation implements
ResourceIdOperation<Void> {
private URI arrayId;
public RegisterPoolOperation(String arrayId) {
this.arrayId = uri(arrayId);
}
@Override
public Void performOperation(URI id) throws Exception {
StoragePoolUtils.deregister(id);
StoragePoolUtils.register(id, arrayId);
return null;
}
}
public static class StorageArrayPoolDataTable extends StoragePoolDataTable {
public StorageArrayPoolDataTable() {
alterColumn("name").setRenderFunction(
"renderStorageArrayPoolEditLink");
alterColumn("storageSystem").hidden();
}
public void configureForFile() {
alterColumns("driveTypes", "subscribedCapacity").hidden();
}
public void configureForECS() {
alterColumns("registrationStatus", "storageSystem", "volumeTypes",
"driveTypes").hidden();
alterColumn("status").setVisible(true);
}
}
public static class StorageArrayPortDataTable extends StoragePortDataTable {
public StorageArrayPortDataTable(StorageSystemRestRep storageSystem) {
alterColumn("name").setRenderFunction(
"renderStorageArrayPortEditLink");
if (StorageSystemTypes.isBlockStorageSystem(storageSystem
.getSystemType())) {
alterColumn("iqn").hidden();
}
if (StorageSystemTypes.isECS(storageSystem.getSystemType())) {
alterColumns("portGroup", "iqn", "alias").hidden();
}
if (StorageSystemTypes.isIsilon((storageSystem.getSystemType()))) {
alterColumns("isDRPort").setVisible(true);
}
}
}
}