/* * Copyright (c) 2015 EMC Corporation * All Rights Reserved */ package controllers.compute; import static com.emc.vipr.client.core.util.ResourceUtils.uri; import static com.emc.vipr.client.core.util.ResourceUtils.uris; import java.net.URI; import java.util.Set; import java.util.HashSet; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import com.emc.storageos.db.client.util.NullColumnValueGetter; import com.emc.storageos.model.auth.ACLAssignmentChanges; import com.emc.storageos.model.auth.ACLEntry; import com.emc.storageos.model.host.vcenter.*; import com.emc.storageos.model.tenant.TenantOrgRestRep; import com.google.common.collect.Sets; import controllers.security.Security; import jobs.vipr.TenantsCall; import models.datatable.VCenterDataTable; import models.datatable.VCenterDataTable.VCenterInfo; import org.apache.commons.lang.StringUtils; import org.springframework.util.CollectionUtils; import play.data.binding.As; 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.MessagesUtils; import util.StringOption; import util.TenantUtils; import util.VCenterUtils; import util.VcenterDataCenterUtils; import util.builders.ACLUpdateBuilder; import util.datatable.DataTablesSupport; import util.validation.HostNameOrIpAddress; import com.emc.vipr.client.Task; import com.emc.vipr.client.core.util.ResourceUtils; import com.google.common.collect.Lists; import controllers.Common; import controllers.deadbolt.Restrict; import controllers.deadbolt.Restrictions; import controllers.tenant.TenantSelector; import controllers.util.FlashException; import controllers.util.Models; import controllers.util.ViprResourceController; @With(Common.class) @Restrictions({ @Restrict("TENANT_ADMIN"), @Restrict("SECURITY_ADMIN"), @Restrict("SYSTEM_ADMIN") }) public class VCenters extends ViprResourceController { protected static final String SAVED = "VCenters.saved"; protected static final String DELETED = "VCenters.deleted"; protected static final String UNKNOWN = "VCenters.unknown"; protected static final String MODEL_NAME = "VCenter"; protected static final String DETACH_STORAGE = "VCenters.detachStorage"; public static void list() { renderArgs.put("dataTable", new VCenterDataTable()); TenantSelector.addRenderArgsForVcenterObjects(); renderTenantOptions(); render(); } public static void listJson() { URI tenantId = TenantUtils.getTenantFilter(Models.currentAdminTenantForVcenter()); List<VcenterRestRep> vcenters = VCenterUtils.getVCenters(tenantId); List<VCenterInfo> vcenterInfos = Lists.newArrayList(); for (VcenterRestRep vcenter : vcenters) { vcenterInfos.add(new VCenterInfo(vcenter)); } renderJSON(DataTablesSupport.createJSON(vcenterInfos, params)); } public static void itemsJson(@As(",") String[] ids) { List<VCenterInfo> results = Lists.newArrayList(); if ((ids != null) && (ids.length > 0)) { for (String id : ids) { if (StringUtils.isBlank(id)) { continue; } VcenterRestRep vcenter = VCenterUtils.getVCenter(uri(id)); if (vcenter != null) { results.add(new VCenterInfo(vcenter)); } } } renderJSON(results); } public static void itemDetails(String id) { VcenterRestRep vcenter = VCenterUtils.getVCenter(uri(id)); List<VcenterDataCenterRestRep> dataCenters = VCenterUtils.getDataCentersInVCenter(vcenter, TenantUtils.getTenantFilter(Models.currentAdminTenantForVcenter())); render(vcenter, dataCenters); } public static void create() { VCenterForm vCenter = new VCenterForm(); vCenter.setTenantsForCreation(); renderTenantOptions(); render("@edit", vCenter); } private static void renderTenantOptions() { if (TenantUtils.canReadAllTenantsForVcenters() && VCenterUtils.canUpdateVcenterACLs()) { List<StringOption> tenantOptions = dataObjectOptions(await(new TenantsCall().asPromise())); renderArgs.put("tenantOptions", tenantOptions); List<StringOption> tenantOptionsWithNone = new ArrayList<StringOption>(); tenantOptionsWithNone.add(new StringOption(NullColumnValueGetter.getNullStr().toString(), "None")); tenantOptionsWithNone.addAll(tenantOptions); renderArgs.put("tenantOptionsWithNone", tenantOptionsWithNone); } } public static void getVcenterTenantOptions(String id) { List<TenantOrgRestRep> vCenterTenantOptions = new ArrayList<TenantOrgRestRep>(); if (StringUtils.isBlank(id) || id.equalsIgnoreCase("null")) { renderJSON(vCenterTenantOptions); return; } List<ACLEntry> vcenterAcls = VCenterUtils.getAcl(uri(id)); if (CollectionUtils.isEmpty(vcenterAcls)) { renderJSON(vCenterTenantOptions); return; } addNoneTenantOption(id, vCenterTenantOptions); Iterator<ACLEntry> aclEntryIterator = vcenterAcls.iterator(); while (aclEntryIterator.hasNext()) { ACLEntry aclEntry = aclEntryIterator.next(); if (aclEntry == null) { continue; } TenantOrgRestRep tenantOrgRestRep = TenantUtils.getTenant(aclEntry.getTenant()); if (tenantOrgRestRep != null) { vCenterTenantOptions.add(tenantOrgRestRep); } } renderJSON(vCenterTenantOptions); } private static void addNoneTenantOption(String id, List<TenantOrgRestRep> vCenterTenantOptions) { VcenterRestRep vcenterRestRep = VCenterUtils.getVCenter(uri(id)); if (vcenterRestRep != null && !vcenterRestRep.getCascadeTenancy()) { TenantOrgRestRep noneTenantOption = new TenantOrgRestRep(); noneTenantOption.setName("None"); noneTenantOption.setId(NullColumnValueGetter.getNullURI()); vCenterTenantOptions.add(noneTenantOption); } } public static void editVcenterDataCenter(String vcenterDataCenterId, String tenant) { VcenterDataCenterRestRep vcenterDataCenter = VcenterDataCenterUtils.getDataCenter(uri(vcenterDataCenterId)); if (vcenterDataCenter != null) { try { URI tenantId = NullColumnValueGetter.getNullURI(); if (StringUtils.isNotBlank(tenant)) { tenantId = uri(tenant); } VcenterDataCenterUtils.updateDataCenter(uri(vcenterDataCenterId), tenantId); list(); } catch (Exception e) { flash.error(MessagesUtils.get("validation.vcenter.messageAndError", e.getMessage())); Common.handleError(); } } else { flash.error(MessagesUtils.get(UNKNOWN, vcenterDataCenterId)); list(); } } public static void edit(String id) { VcenterRestRep dbVCenter = VCenterUtils.getVCenter(uri(id)); if (dbVCenter != null) { VCenterForm vCenter = new VCenterForm(dbVCenter); renderTenantOptions(); render(vCenter, dbVCenter); } else { flash.error(MessagesUtils.get(UNKNOWN, id)); list(); } } private static void edit(VCenterForm vcenter) { // Remove password/confirm from params before flashing params.remove("vCenter.password"); params.remove("vCenter.passwordConfirm"); params.flash(); Validation.keep(); if (vcenter.isNew()) { create(); } else { edit(vcenter.id); } } public static void save(VCenterForm vCenter) { vCenter.validate("vCenter"); if (Validation.hasErrors()) { edit(vCenter); } else { Boolean validateConnectionParam = params.get("validateConnection", Boolean.class); boolean validateConnection = validateConnectionParam != null ? validateConnectionParam.booleanValue() : false; vCenter.save(validateConnection); flash.success(MessagesUtils.get(SAVED, vCenter.name)); list(); } } @FlashException("list") public static void delete(@As(",") String[] ids, boolean detachStorage) { for (URI id : ResourceUtils.uris(ids)) { VCenterUtils.deactivateVCenter(id, detachStorage); } flash.success(MessagesUtils.get(DELETED)); 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(); } protected static class DiscoveryOperation implements ResourceIdOperation<Task<VcenterRestRep>> { @Override public Task<VcenterRestRep> performOperation(URI id) throws Exception { return VCenterUtils.discover(id); } } public static class VCenterForm { public static final int DEFAULT_PORT = 443; public String id; public Set<String> tenants; public String tenant; @Required @MaxSize(128) @MinSize(2) public String name; @Required @HostNameOrIpAddress public String hostname; @Required @MaxSize(1024) public String username; @MaxSize(1024) public String password; public String passwordConfirm; @Required @Min(1) public Integer port = DEFAULT_PORT; public Boolean cascadeTenancy = Boolean.FALSE; public VCenterForm() { } public VCenterForm(VcenterRestRep vCenter) { this(); doReadFrom(vCenter); } public void doReadFrom(VcenterRestRep vCenter) { this.id = vCenter.getId().toString(); this.name = vCenter.getName(); this.hostname = vCenter.getIpAddress(); this.username = vCenter.getUsername(); this.port = vCenter.getPortNumber(); this.cascadeTenancy = vCenter.getCascadeTenancy(); doReadAcls(); } public void doReadAcls() { List<ACLEntry> aclEntries = VCenterUtils.getAcl(URI.create(this.id)); if (CollectionUtils.isEmpty(aclEntries)) { if (!CollectionUtils.isEmpty(this.tenants)) { this.tenants.clear(); this.tenant = ""; } return; } this.tenants = new HashSet<String>(); if (aclEntries.size() > 1) { Iterator<ACLEntry> aclIt = aclEntries.iterator(); while (aclIt.hasNext()) { this.tenants.add(aclIt.next().getTenant()); } renderArgs.put("disableCascadeTenancy", true); } else { ACLEntry aclEntry = aclEntries.iterator().next(); this.tenant = aclEntry.getTenant(); this.tenants.add(aclEntry.getTenant()); } } public void doWriteTo(VcenterCreateParam vcenterCreateParam) { doWriteToBase(vcenterCreateParam); vcenterCreateParam.setIpAddress(this.hostname); } public void doWriteTo(VcenterUpdateParam vcenterUpdateParam) { doWriteToBase(vcenterUpdateParam); vcenterUpdateParam.setIpAddress(this.hostname); } public void doWriteToBase(VcenterParam vCenter) { vCenter.setName(this.name); vCenter.setUserName(this.username); if (StringUtils.isNotBlank(this.password)) { vCenter.setPassword(StringUtils.trimToNull(this.password)); } vCenter.setPortNumber(this.port); vCenter.setCascadeTenancy(this.cascadeTenancy); } public ACLAssignmentChanges getAclAssignmentChanges() { Set<String> tenantIds = Sets.newHashSet(); if (this.cascadeTenancy) { if(StringUtils.isNotBlank(this.tenant) && !this.tenant.equalsIgnoreCase(NullColumnValueGetter.getNullStr().toString())) { tenantIds.add(this.tenant); } } else if (!CollectionUtils.isEmpty(this.tenants)) { tenantIds.addAll(this.tenants); } List<ACLEntry> existingAcls = new ArrayList<ACLEntry>(); if (StringUtils.isNotBlank(this.id)) { existingAcls = VCenterUtils.getAcl(URI.create(this.id)); } ACLUpdateBuilder builder = new ACLUpdateBuilder(existingAcls); builder.setTenants(tenantIds); return builder.getACLUpdate(); } public void doValidation(String formName) { if (this.isNew()) { Validation.required(String.format("%s.password", formName), this.password); } boolean hasPassword = StringUtils.isNotBlank(password) || StringUtils.isNotBlank(passwordConfirm); boolean passwordMatches = StringUtils.equals(password, passwordConfirm); if (hasPassword && !passwordMatches) { Validation.addError(String.format("%s.passwordConfirm", formName), "error.password.doNotMatch"); } } public void validate(String formName) { Validation.valid(formName, this); doValidation(formName); } public void save(boolean validateConnection) { if (isNew()) { try { createVCenter(validateConnection); } catch (Exception e) { flash.error(MessagesUtils.get("validation.vcenter.messageAndError", e.getMessage())); Common.handleError(); } } else { try { updateVCenter(validateConnection); } catch (Exception e) { flash.error(MessagesUtils.get("validation.vcenter.messageAndError", e.getMessage())); Common.handleError(); } } } protected Task<VcenterRestRep> createVCenter(boolean validateConnection) { VcenterCreateParam vcenterCreateParam = new VcenterCreateParam(); doWriteTo(vcenterCreateParam); if (Security.isSystemAdmin()) { return VCenterUtils.createVCenter(vcenterCreateParam, validateConnection, getAclAssignmentChanges()); } vcenterCreateParam.setCascadeTenancy(Boolean.TRUE); return VCenterUtils.createVCenter(TenantUtils.getTenantFilter(Models.currentAdminTenantForVcenter()), vcenterCreateParam, validateConnection); } protected Task<VcenterRestRep> updateVCenter(boolean validateConnection) { VcenterUpdateParam vcenterUpdateParam = new VcenterUpdateParam(); doWriteTo(vcenterUpdateParam); if (Security.isSystemAdmin()) { ACLAssignmentChanges aclAssignmentChanges = getAclAssignmentChanges(); return VCenterUtils.updateVCenter(uri(id), vcenterUpdateParam, validateConnection, aclAssignmentChanges); } else { VcenterRestRep vcenterRestRep = VCenterUtils.getVCenter(uri(id)); vcenterUpdateParam.setCascadeTenancy(vcenterRestRep.getCascadeTenancy()); return VCenterUtils.updateVCenter(uri(id), vcenterUpdateParam, validateConnection, null); } } public boolean isNew() { return StringUtils.isBlank(id); } public void setTenantsForCreation() { this.tenants = new HashSet<String>(); if (StringUtils.isNotBlank(Models.currentAdminTenantForVcenter()) && Models.currentAdminTenantForVcenter().equalsIgnoreCase(TenantUtils.getNoTenantSelector())) { List<TenantOrgRestRep> allTenants = TenantUtils.getAllTenants(); Iterator<TenantOrgRestRep> tenantsIterator = allTenants.iterator(); while (tenantsIterator.hasNext()) { TenantOrgRestRep tenant = tenantsIterator.next(); if (tenant == null) { continue; } this.tenants.add(tenant.getId().toString()); this.cascadeTenancy = Boolean.FALSE; } } else if (StringUtils.isNotBlank(Models.currentAdminTenantForVcenter()) && !Models.currentAdminTenantForVcenter().equalsIgnoreCase(TenantUtils.getTenantSelectorForUnassigned())) { this.tenants.clear(); this.tenant = Models.currentAdminTenantForVcenter(); this.cascadeTenancy = Boolean.TRUE; } } } }