/* * Copyright (c) 2008-2013 EMC Corporation * All Rights Reserved */ package com.emc.storageos.api.service.impl.resource; import java.net.URI; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Context; import javax.ws.rs.core.SecurityContext; import javax.ws.rs.core.UriInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import com.emc.storageos.Controller; import com.emc.storageos.api.service.authorization.PermissionsHelper; import com.emc.storageos.api.service.impl.resource.utils.AsynchJobExecutorService; import com.emc.storageos.api.service.impl.resource.utils.BlockServiceUtils; import com.emc.storageos.coordinator.client.service.CoordinatorClient; import com.emc.storageos.coordinator.exceptions.RetryableCoordinatorException; import com.emc.storageos.db.client.DbClient; import com.emc.storageos.db.client.constraint.AlternateIdConstraint; import com.emc.storageos.db.client.constraint.Constraint; import com.emc.storageos.db.client.constraint.ContainmentConstraint; import com.emc.storageos.db.client.constraint.ContainmentPermissionsConstraint; import com.emc.storageos.db.client.constraint.ContainmentPrefixConstraint; import com.emc.storageos.db.client.constraint.NamedElementQueryResultList; import com.emc.storageos.db.client.constraint.PrefixConstraint; import com.emc.storageos.db.client.constraint.URIQueryResultList; import com.emc.storageos.db.client.model.AbstractDiscoveredTenantResource; import com.emc.storageos.db.client.model.AbstractTenantResource; import com.emc.storageos.db.client.model.DataObject; import com.emc.storageos.db.client.model.DiscoveredComputeSystemWithAcls; import com.emc.storageos.db.client.model.Project; import com.emc.storageos.db.client.model.Task; import com.emc.storageos.db.client.model.TenantOrg; import com.emc.storageos.db.client.model.Vcenter; import com.emc.storageos.db.client.util.CustomQueryUtility; import com.emc.storageos.db.client.util.DataObjectUtils; import com.emc.storageos.db.client.util.NullColumnValueGetter; import com.emc.storageos.db.common.DbDependencyPurger; import com.emc.storageos.db.exceptions.DatabaseException; import com.emc.storageos.model.NamedRelatedResourceRep; import com.emc.storageos.model.RestLinkRep; import com.emc.storageos.model.tenant.TenantOrgList; import com.emc.storageos.plugins.common.Constants; import com.emc.storageos.security.audit.AuditLogManager; import com.emc.storageos.security.authentication.InterNodeHMACAuthFilter; import com.emc.storageos.security.authentication.StorageOSUser; import com.emc.storageos.security.authorization.ACL; import com.emc.storageos.security.authorization.PermissionsKey; import com.emc.storageos.security.authorization.Role; import com.emc.storageos.security.geo.GeoDependencyChecker; import com.emc.storageos.services.OperationTypeEnum; import com.emc.storageos.svcs.errorhandling.resources.APIException; import com.sun.jersey.api.NotFoundException; /** * Base resource with common dependencies and convenience methods */ public abstract class ResourceService { public final static URI INTERNAL_DATASVC_USER = URI.create("datasvc"); public final static String VDC_ID_QUERY_PARAM = "vdc-id"; public final static String TENANT_ID_QUERY_PARAM = "tenant-id"; protected final static String CONTROLLER_SVC = "controllersvc"; protected final static String CONTROLLER_SVC_VER = "1"; protected static final String DATAOBJECT_NAME_FIELD = "label"; @SuppressWarnings("unused") private final static Logger _log = LoggerFactory.getLogger(ResourceService.class); @Autowired protected PermissionsHelper _permissionsHelper = null; @Autowired protected GeoDependencyChecker geoDependencyChecker; @Autowired protected DbDependencyPurger _dbPurger; @Autowired protected AsynchJobExecutorService _asynchJobService; @Autowired protected AuditLogManager _auditMgr; @Context protected SecurityContext sc; @Context protected UriInfo uriInfo; @Context protected HttpServletRequest _request; protected CoordinatorClient _coordinator; protected DbClient _dbClient; public void setDbClient(DbClient dbClient) { _dbClient = dbClient; } public void setCoordinator(CoordinatorClient locator) { _coordinator = locator; } protected String getServiceType() { throw new UnsupportedOperationException("Not implemented in current service"); } /** * Check if a resource can be inactivated safely * * @param object Reference to object to verify. * * @return detail type of the dependency if exist, null otherwise * * @throws DatabaseException for db errors */ protected <T extends DataObject> String checkForDelete(T object) { return checkForDelete(object, null); } /** * Check if a resource can be inactivated safely * * @param object Reference to object to verify. * @param excludeTypes optional list of classes that can be excluded as dependency * * @return detail type of the dependency if exist, null otherwise * * @throws DatabaseException for db errors */ protected <T extends DataObject> String checkForDelete(T object, List<Class<? extends DataObject>> excludeTypes) { Class<? extends DataObject> clazz = object.getClass(); URI id = object.getId(); // COP-21194: Task references should be ignored always for delete operations of resource List<Class<? extends DataObject>> excludes = new ArrayList<Class<? extends DataObject>>(); if (excludeTypes != null) { excludes.addAll(excludeTypes); } excludes.add(Task.class); String depMsg = geoDependencyChecker.checkDependencies(id, clazz, true, excludes); if (depMsg != null) { return depMsg; } return object.canBeDeleted(); } /** * Check if a resource with the same name exists * * @param name */ protected <T extends DataObject> List<T> listFileSystemsWithLabelName(String name, Class<T> type, URI parentToScope, String parentFieldName) { List<T> objectList = new ArrayList<T>(); if (parentToScope != null && parentFieldName != null) { objectList = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, type, ContainmentPrefixConstraint.Factory.getFullMatchConstraint(type, parentFieldName, parentToScope, name)); } else { objectList = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, type, PrefixConstraint.Factory.getFullMatchConstraint(type, DATAOBJECT_NAME_FIELD, name)); } return objectList; } /** * Check if a resource with the same name exists * * @param name */ public static <T extends DataObject> void checkForDuplicateName(String name, Class<T> type, URI parentToScope, String parentFieldName, DbClient dbClient) { List<T> objectList = new ArrayList<T>(); if (parentToScope != null && parentFieldName != null) { objectList = CustomQueryUtility.queryActiveResourcesByConstraint(dbClient, type, ContainmentPrefixConstraint.Factory.getFullMatchConstraint(type, parentFieldName, parentToScope, name)); } else { objectList = CustomQueryUtility.queryActiveResourcesByConstraint(dbClient, type, PrefixConstraint.Factory.getFullMatchConstraint(type, DATAOBJECT_NAME_FIELD, name)); } if (!objectList.isEmpty()) { throw APIException.badRequests.duplicateLabel(name); } } /** * Check if a resource with the same name exists at zone level * * @param name */ protected void checkForDuplicateName(String name, Class<? extends DataObject> type) { checkForDuplicateName(name, type, null, null, _dbClient); } /** * Check if a tenant with the same namespace exists * @param namespace namespace of the tenant */ public void checkForDuplicateNamespace(String namespace) { TenantOrgList list = new TenantOrgList(); //Verify with root tenant if current is not root TenantOrg rootTenant = _permissionsHelper.getRootTenant(); if (rootTenant.getNamespace() != null && rootTenant.getNamespace().equalsIgnoreCase(namespace)) { throw APIException.badRequests.duplicateNamespace(namespace); } NamedElementQueryResultList subtenants = new NamedElementQueryResultList(); _dbClient.queryByConstraint(ContainmentConstraint.Factory .getTenantOrgSubTenantConstraint(rootTenant.getId()), subtenants); for (NamedElementQueryResultList.NamedElement el : subtenants) { TenantOrg currTenant = _dbClient.queryObject(TenantOrg.class, el.getId()); if (currTenant.getNamespace() != null && currTenant.getNamespace().equalsIgnoreCase(namespace)) { throw APIException.badRequests.duplicateNamespace(namespace); } } } /** * Looks up controller dependency for given hardware type. * If cannot locate controller for defined hardware type, lookup controller for * EXTERNALDEVICE. * * @param clazz controller interface * @param hw hardware name * @param <T> * @return */ protected <T extends Controller> T getController(Class<T> clazz, String hw) { T controller; try { controller = _coordinator.locateService( clazz, CONTROLLER_SVC, CONTROLLER_SVC_VER, hw, clazz.getSimpleName()); } catch (RetryableCoordinatorException rex) { controller = _coordinator.locateService( clazz, CONTROLLER_SVC, CONTROLLER_SVC_VER, Constants.EXTERNALDEVICE, clazz.getSimpleName()); } return controller; } /** * Get StorageOSUser from the security context * * @return */ protected StorageOSUser getUserFromContext() { if (!hasValidUserInContext()) { throw APIException.forbidden.invalidSecurityContext(); } return (StorageOSUser) sc.getUserPrincipal(); } /** * Determine if the security context has a valid StorageOSUser object * * @return true if the StorageOSUser is present */ protected boolean hasValidUserInContext() { if ((sc != null) && (sc.getUserPrincipal() instanceof StorageOSUser)) { return true; } else { return false; } } // Helper function to check if the user has authorization to access the project // This is used by all search functions protected boolean isAuthorized(URI projectUri) { final StorageOSUser user = getUserFromContext(); if (_permissionsHelper == null) { return false; } Project project = _permissionsHelper.getObjectById(projectUri, Project.class); if (project == null) { return false; } if ((_permissionsHelper.userHasGivenRole(user, project.getTenantOrg().getURI(), Role.SYSTEM_MONITOR, Role.TENANT_ADMIN) || _permissionsHelper.userHasGivenACL(user, projectUri, ACL.ANY))) { return true; } else { return false; } } protected RestLinkRep getCurrentSelfLink() { try { return new RestLinkRep("self", new URI("/" + uriInfo.getPath())); } catch (Exception ex) { return new RestLinkRep("self", null); } } /** * Returns the instance of DataObject for the given id and class. It * throws {@link com.emc.storageos.svcs.errorhandling.resources.BadRequestException} when id is not a valid * URI or when the object has been marked for deletion and checkInactive * is true. Throws {@link NotFoundException} when the object has been delete. * * @param id the URN of a ViPR object to be fetched. * @param checkInactive a flag to indicate if the object inactive flag should be * checked. In general, this check should be performed when the object * is going to be modified or deleted. * @return the instance of dataobject for the given id. */ protected <T extends DataObject> T queryObject(Class<T> clzz, URI id, boolean checkInactive) { ArgValidator.checkUri(id); T dataObject = _dbClient.queryObject(clzz, id); ArgValidator.checkEntity(dataObject, id, isIdEmbeddedInURL(id), checkInactive); return dataObject; } /** * Check all path parameters for the specified id * * @param id the URN of a ViPR Entity to check * @return true if the id is in the path */ protected boolean isIdEmbeddedInURL(final URI id) { return BlockServiceUtils.isIdEmbeddedInURL(id, uriInfo); } /** * This function is to retrieve the children of a given class. * * @param id the URN of parent * @param clzz the child class * @param nameField the name of the field of the child class that will be displayed as * name in {@link NamedRelatedResourceRep}. Note this field should be a required * field because, objects for which this field is null will not be returned by * this function. * @param linkField the name of the field in the child class that stored the parent id * @return a list of children of tenant for the given class */ protected <T extends DataObject> List<NamedElementQueryResultList.NamedElement> listChildren(URI id, Class<T> clzz, String nameField, String linkField) { @SuppressWarnings("deprecation") List<URI> uris = _dbClient.queryByConstraint( ContainmentConstraint.Factory.getContainedObjectsConstraint(id, clzz, linkField)); if (uris != null && !uris.isEmpty()) { Iterator<T> dataObjects = _dbClient.queryIterativeObjectField(clzz, nameField, uris); List<NamedElementQueryResultList.NamedElement> elements = new ArrayList<NamedElementQueryResultList.NamedElement>(); while (dataObjects.hasNext()) { T dataObject = dataObjects.next(); Object name = DataObjectUtils.getPropertyValue(clzz, dataObject, nameField); elements.add(NamedElementQueryResultList.NamedElement.createElement( dataObject.getId(), name == null ? "" : name.toString())); } return elements; } else { return new ArrayList<NamedElementQueryResultList.NamedElement>(); } } /** * A utility function that checks of an alternate ID uniqueness constraints * will be violated when an object is created or modified. * * @param type The class of object being validated * @param fieldName the name of the alternate ID field * @param value the value being checked * @param entityName the name of the entity to be used in the error message */ protected <T extends DataObject> void checkDuplicateAltId(Class<T> type, String fieldName, String value, String entityName) { checkDuplicateAltId(type, fieldName, value, entityName, null); } /** * A utility function that checks of an alternate ID uniqueness constraints * will be violated when an object is created or modified. * * @param type The class of object being validated * @param fieldName the name of the alternate ID field * @param value the value being checked * @param entityName the name of the entity to be used in the error message * @param errorFriendlyFieldName - user friendly value of fieldName to put in error message * (Example 'Initiator Port' rather than 'iniport'). */ protected <T extends DataObject> void checkDuplicateAltId(Class<T> type, String fieldName, String value, String entityName, String errorFriendlyFieldName) { List<T> objectList = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, type, AlternateIdConstraint.Factory.getConstraint(type, fieldName, value)); if (!objectList.isEmpty()) { if (errorFriendlyFieldName == null) { throw APIException.badRequests.duplicateEntityWithField(entityName, fieldName); } else { throw APIException.badRequests.duplicateEntityWithField(entityName, errorFriendlyFieldName); } } } /** * A utility function that checks for label uniqueness constraint for a single * class type. * * @param type The class of object being validated * @param value the value of label being checked */ protected <T extends DataObject> void checkDuplicateLabel(Class<T> type, String value) { List<T> objectList = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, type, PrefixConstraint.Factory.getFullMatchConstraint(type, DATAOBJECT_NAME_FIELD, value)); if (!objectList.isEmpty()) { throw APIException.badRequests.duplicateLabel(value); } } /** * For some object such as vcenter clusters and vcenter data centers, the name * must be unique within the children of the same parent. * * @param id the URN of the parent object * @param clzz the class of the child object * @param nameField the field in the child object that needs to be unique * @param linkField the field in the child class that references the parent * @param value the value being checked * @param dbClient an instance of {@link DbClient} */ protected void checkDuplicateChildName(URI id, Class<? extends DataObject> clzz, String nameField, String linkField, String value, DbClient dbClient) { URIQueryResultList uris = new URIQueryResultList(); dbClient.queryByConstraint( ContainmentConstraint.Factory.getContainedObjectsConstraint(id, clzz, linkField), uris); Iterator<?> objs = dbClient.queryIterativeObjects(clzz, uris); while (objs.hasNext()) { DataObject obj = (DataObject) objs.next(); if (value.equals(obj.getLabel()) && !obj.getInactive()) { throw APIException.badRequests.duplicateChildForParent(id); } } } /** * For two URIs which can be null as defined in {@link NullColumnValueGetter#getNullURI()}, * compare the two URI and return true if they are both null or both not null but equal. * * @param uri1 the first URI * @param uri2 the second URI * @return true if both URIs are null as defined in {@link NullColumnValueGetter#getNullURI()} or both are equal. */ protected boolean areEqual(URI uri1, URI uri2) { if (NullColumnValueGetter.isNullURI(uri1)) { return NullColumnValueGetter.isNullURI(uri2); } else { return uri1.equals(uri2); } } /** * Record audit log for services * * @param opType audit event type (e.g. CREATE_VPOOL|TENANT etc.) * @param operationalStatus Status of operation (true|false) * @param operationStage Stage of operation. * For sync operation, it should be null; * For async operation, it should be "BEGIN" or "END"; * @param descparams Description paramters */ protected void auditOp(OperationTypeEnum opType, boolean operationalStatus, String operationStage, Object... descparams) { URI tenantId; URI username; if (!hasValidUserInContext() && InterNodeHMACAuthFilter.isInternalRequest(_request)) { // use default values for internal datasvc requests that lack a user context tenantId = _permissionsHelper.getRootTenant().getId(); username = INTERNAL_DATASVC_USER; } else { tenantId = URI.create(getUserFromContext().getTenantId()); username = URI.create(getUserFromContext().getName()); } _auditMgr.recordAuditLog(tenantId, username, getServiceType(), opType, System.currentTimeMillis(), operationalStatus ? AuditLogManager.AUDITLOG_SUCCESS : AuditLogManager.AUDITLOG_FAILURE, operationStage, descparams); } /** * Checks if the user is authorized to view resources in a tenant organization. The * user can see resources if: * <ul> * <li>The user is in the tenant organization</li> * <li>The user has SYSTEM_ADMIN or SYSTEM_MONITOR role</li> * <li>the user has TENANT_ADMIN role to this tenant organization even if the user is in another tenant org</li> * </ul> * * @param tenantId the tenant organization URI * @param user the user */ protected void verifyAuthorizedInTenantOrg(URI tenantId, StorageOSUser user) { if (!(tenantId.toString().equals(user.getTenantId()) || isSystemAdminOrMonitorUser() || _permissionsHelper.userHasGivenRole(user, tenantId, Role.TENANT_ADMIN))) { throw APIException.forbidden.insufficientPermissionsForUser(user.getName()); } } /** * A utility function to check if the context user has system admin or monitor role. * * @return True if if the context user has system admin or monitor role. */ protected boolean isSystemAdminOrMonitorUser() { return _permissionsHelper.userHasGivenRole( getUserFromContext(), null, Role.SYSTEM_ADMIN, Role.SYSTEM_MONITOR); } /** * A utility function to check if the context user has system admin or monitor role and * throws an exception when the check fails. */ protected void verifySystemAdminOrMonitorUser() { if (!isSystemAdminOrMonitorUser()) { throw APIException.forbidden .insufficientPermissionsForUser(getUserFromContext().getName()); } } /** * This function is to retrieve the name and id list of a class of objects. * * @param clazz the class objects to retrieved. * @param nameField the name of the field of the class that will be displayed as * name in {@link NamedRelatedResourceRep}. Note this field should be a required * field because, objects for which this field is null will not be returned by * this function. * @return a name and id list of a given class */ protected <T extends DataObject> List<NamedElementQueryResultList.NamedElement> listDataObjects(Class<T> clazz, String nameField) { List<T> dataObjects = getDataObjects(clazz); if (!CollectionUtils.isEmpty(dataObjects)) { return getNamedElementsList(clazz, nameField, dataObjects); } else { return new ArrayList<NamedElementQueryResultList.NamedElement>(); } } /** * This function is to get the name and id list of a class from the list of given objects. * * @param clazz the class objects to retrieved. * @param nameField the name of the field of the class that will be displayed as * name in {@link NamedRelatedResourceRep}. Note this field should be a required * field because, objects for which this field is null will not be returned by * this function. * @param dataObjects all the data objects of the class to which the name and id pair list * is created. * @return a name and id list of a given class. */ protected <T extends DataObject> List<NamedElementQueryResultList.NamedElement> getNamedElementsList(Class<T> clazz, String nameField, List<T> dataObjects) { List<NamedElementQueryResultList.NamedElement> elements = new ArrayList<NamedElementQueryResultList.NamedElement>( dataObjects.size()); for (T dataObject : dataObjects) { Object name = DataObjectUtils.getPropertyValue(clazz, dataObject, nameField); elements.add(NamedElementQueryResultList.NamedElement.createElement( dataObject.getId(), name == null ? "" : name.toString())); } return elements; } /** * Filters the data objects with no configured acls from the given list of objects. * From the filtered list, creates the name and id pair elements. * * @param clazz class objects to be filtered. * @param nameField name field of the objects. * @param dataObjects list of data objects to be filtered with no acls. * @return a name and id list of a given class with no acls. */ protected <T extends DiscoveredComputeSystemWithAcls> List<NamedElementQueryResultList.NamedElement> getNamedElementsWithNoAcls( Class<T> clazz, String nameField, List<T> dataObjects) { List<NamedElementQueryResultList.NamedElement> elements = new ArrayList<NamedElementQueryResultList.NamedElement>( dataObjects.size()); for (T dataObject : dataObjects) { if (CollectionUtils.isEmpty(dataObject.getAcls())) { Object name = DataObjectUtils.getPropertyValue(clazz, dataObject, nameField); elements.add(NamedElementQueryResultList.NamedElement.createElement( dataObject.getId(), name == null ? "" : name.toString())); } } return elements; } /** * Get the data object of a type. * * @param clazz of objects to be retrieved. * @return list of all the objects of type clazz. */ protected <T extends DataObject> List<T> getDataObjects(Class<T> clazz) { @SuppressWarnings("deprecation") List<URI> uris = _dbClient.queryByType(clazz, true); List<T> dataObjects = null; if (uris != null) { dataObjects = _dbClient.queryObject(clazz, uris); } return dataObjects; } /** * Retrieves the list of NamedElements of the data objects with acls * and the list is filtered based on the tenant information. * * @param tenantId the URN of parent * @param clzz the child class * @param nameField the name of the field of the child class that will be displayed as * name in {@link NamedRelatedResourceRep}. Note this field should be a required * field because, objects for which this field is null will not be returned by * this function. * @return a list of NamedElements filtered by tenant. */ protected <T extends DiscoveredComputeSystemWithAcls> List<NamedElementQueryResultList.NamedElement> listChildrenWithAcls(URI tenantId, Class<T> clzz, String nameField) { Iterator<T> dataObjects = getDiscoveredComputeObjects(tenantId, clzz); List<NamedElementQueryResultList.NamedElement> elements = new ArrayList<NamedElementQueryResultList.NamedElement>(); while (dataObjects.hasNext()) { T dataObject = dataObjects.next(); Object name = DataObjectUtils.getPropertyValue(Vcenter.class, dataObject, nameField); elements.add(NamedElementQueryResultList.NamedElement.createElement( dataObject.getId(), name == null ? "" : name.toString())); } return elements; } /** * Retrieves the list of objects with acls based on the tenant information. * * @param tenantId to used to filter the objects. * @param clzz class of objects. * @return the filtered list of objects with acls. */ protected <T extends DiscoveredComputeSystemWithAcls> Iterator<T> getDiscoveredComputeObjects(URI tenantId, Class<T> clzz) { PermissionsKey permissionKey = new PermissionsKey(PermissionsKey.Type.TENANT, tenantId.toString()); URIQueryResultList resultURIs = new URIQueryResultList(); Constraint aclConstraint = ContainmentPermissionsConstraint.Factory.getDiscoveredObjsWithPermissionsConstraint( permissionKey.toString(), Vcenter.class); _dbClient.queryByConstraint(aclConstraint, resultURIs); List<URI> uris = new ArrayList<URI>(); for (URI result : resultURIs) { uris.add(result); } Iterator<T> dataObjects = new ArrayList<T>().iterator(); if (uris != null && !uris.isEmpty()) { dataObjects = _dbClient.queryIterativeObjectField(clzz, DATAOBJECT_NAME_FIELD, uris); } return dataObjects; } /** * Filters the named element list of abstract tenant resources * like vCenterDataCenter and Cluster by its tenant. * * @param tenantId will be filtered based on this tenantId. * @param elements List of named elements of all the active abstract tenant * resources to be filtered based on the tenant. * @return returns the filtered element list based on the tenant. */ protected <T extends AbstractTenantResource> List<NamedElementQueryResultList.NamedElement> filterTenantResourcesByTenant(URI tenantId, Class<T> clazz, List<NamedElementQueryResultList.NamedElement> elements) { if (CollectionUtils.isEmpty(elements)) { return elements; } URI localTenantId = tenantId; // The the requested tenant is null or "No-Filter", return all the vCenters. if (NullColumnValueGetter.isNullURI(localTenantId) || AbstractTenantResource.NO_TENANT_SELECTOR.equalsIgnoreCase(localTenantId.toString())) { return elements; } // If the filter tenantId is "Not-Assigned" modify the search tenantId to null. if (AbstractDiscoveredTenantResource.TENANT_SELECTOR_FOR_UNASSIGNED.equalsIgnoreCase(localTenantId.toString())) { localTenantId = NullColumnValueGetter.getNullURI(); } Iterator<NamedElementQueryResultList.NamedElement> elementIterator = elements.iterator(); while (elementIterator.hasNext()) { NamedElementQueryResultList.NamedElement element = elementIterator.next(); if (element == null) { continue; } T dataCenter = _dbClient.queryObject(clazz, element.getId()); if (dataCenter == null) { continue; } // The vCenters tenant if (areEqual(localTenantId, dataCenter.getTenant())) { continue; } elementIterator.remove(); } return elements; } /** * Filters the named element list of abstract discovered tenant resources * like vCenter and Host by its tenant. * * @param tenantId will be filtered based on this tenantId. * @param elements List of named elements of all the active abstract discovered, * tenant resources to be filtered based on the tenant. * @return returns the filtered element list based on the tenant. */ protected <T extends AbstractDiscoveredTenantResource> List<NamedElementQueryResultList.NamedElement> filterDiscoveredTenantResourcesByTenant(URI tenantId, Class<T> clazz, List<NamedElementQueryResultList.NamedElement> elements) { if (CollectionUtils.isEmpty(elements)) { return elements; } URI localTenantId = tenantId; // The the requested tenant is null or ALL, return all the vCenters. if (NullColumnValueGetter.isNullURI(localTenantId) || AbstractDiscoveredTenantResource.NO_TENANT_SELECTOR.equalsIgnoreCase(localTenantId.toString())) { return elements; } // If the filter tenantId is "NONE" modify the search tenantId to null. if (AbstractDiscoveredTenantResource.TENANT_SELECTOR_FOR_UNASSIGNED.equalsIgnoreCase(localTenantId.toString())) { localTenantId = NullColumnValueGetter.getNullURI(); } Iterator<NamedElementQueryResultList.NamedElement> elementIterator = elements.iterator(); while (elementIterator.hasNext()) { NamedElementQueryResultList.NamedElement element = elementIterator.next(); if (element == null) { continue; } T dataCenter = _dbClient.queryObject(clazz, element.getId()); if (dataCenter == null) { continue; } // The vCenters tenant if (areEqual(localTenantId, dataCenter.getTenant())) { continue; } elementIterator.remove(); } return elements; } /** * Filters the named element list of abstract discovered tenant resources * like vCenter and Host by its tenant. * * @param tenantId will be filtered based on this tenantId. * @param clazz class of the resource to be filtered. * @param nameField label field of the resource. * @param linkField name of the parent link field. * @return returns the filtered element list based on the tenant. */ protected <T extends DataObject> List<NamedElementQueryResultList.NamedElement> filterTenantResourcesByTenant(URI tenantId, Class<T> clazz, String nameField, String linkField) { List<NamedElementQueryResultList.NamedElement> elements; URI localTenantId = tenantId; // The the requested tenant is null or ALL, return all the vCenters. if (NullColumnValueGetter.isNullURI(localTenantId) || AbstractDiscoveredTenantResource.NO_TENANT_SELECTOR.equalsIgnoreCase(localTenantId.toString())) { elements = listDataObjects(clazz, nameField); return elements; } // If the filter tenantId is "NONE" modify the search tenantId to null. if (AbstractDiscoveredTenantResource.TENANT_SELECTOR_FOR_UNASSIGNED.equalsIgnoreCase(localTenantId.toString())) { localTenantId = NullColumnValueGetter.getNullURI(); } elements = listChildren(localTenantId, clazz, nameField, linkField); return elements; } }