/*
* RHQ Management Platform
* Copyright (C) 2005-2010 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.enterprise.server.test;
import java.util.List;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.authz.Role;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
import org.rhq.core.domain.configuration.definition.PropertySimpleType;
import org.rhq.core.domain.configuration.group.GroupPluginConfigurationUpdate;
import org.rhq.core.domain.configuration.group.GroupResourceConfigurationUpdate;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.resource.Agent;
import org.rhq.core.domain.resource.InventoryStatus;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceCategory;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.configuration.ConfigurationManagerLocal;
import org.rhq.enterprise.server.resource.ResourceManagerLocal;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.util.SessionTestHelper;
public abstract class LargeGroupTestBase extends AbstractEJB3Test {
// for plugin configuration
protected static final String PC_PROP1_NAME = "LargeGroupTest pc prop1";
protected static final String PC_PROP1_VALUE = "LargeGroupTest pc property one";
protected static final String PC_PROP2_NAME = "LargeGroupTest pc prop2";
// for resource configuration
protected static final String RC_PROP1_NAME = "LargeGroupTest rc prop1";
protected static final String RC_PROP1_VALUE = "LargeGroupTest rc property one";
protected static final String RC_PROP2_NAME = "LargeGroupTest rc prop2";
protected ConfigurationManagerLocal configurationManager;
protected ResourceManagerLocal resourceManager;
protected ResourceGroupManagerLocal resourceGroupManager;
protected SubjectManagerLocal subjectManager;
protected class LargeGroupEnvironment {
public Agent agent;
public Resource platformResource; // all if its children will be members of the compatible group
public ResourceType platformType;
public ResourceType serverType;
public ConfigurationDefinition serverPluginConfiguration;
public ConfigurationDefinition serverResourceConfiguration;
public ResourceGroup compatibleGroup;
public Subject normalSubject; // user with a role that has access to the group
public Role normalRole; // role with permissions on the group
public Subject unauthzSubject; // a subject with no authorization to do anything
public LargeGroupEnvironment() {
}
/**
* Stores references to the existing lge's resource types' metadata but nothing else.
* @param lge the object whose platformType and serverType are stored in the new lge object
*/
public LargeGroupEnvironment(LargeGroupEnvironment lge) {
if (lge != null) {
this.platformType = lge.platformType;
this.serverType = lge.serverType;
this.serverPluginConfiguration = lge.serverPluginConfiguration;
this.serverResourceConfiguration = lge.serverResourceConfiguration;
}
}
}
@Override
protected void beforeMethod() throws Exception {
configurationManager = LookupUtil.getConfigurationManager();
resourceManager = LookupUtil.getResourceManager();
resourceGroupManager = LookupUtil.getResourceGroupManager();
subjectManager = LookupUtil.getSubjectManager();
TestServerCommunicationsService agentServiceContainer = prepareForTestAgents();
setupMockAgentServices(agentServiceContainer);
prepareScheduler();
}
@Override
protected void afterMethod() throws Exception {
try {
unprepareForTestAgents();
} finally {
unprepareScheduler();
}
}
protected abstract void setupMockAgentServices(TestServerCommunicationsService agentServiceContainer);
/**
* Creates a compatible group of the given size. This also creates a normal user and a role
* and makes sure that user can access the group that was created. The role will be assigned the
* given permissions and that role be placed on the new group and the new user.
*
* @param groupSize the number of members to create and put into the compatible group that is created.
* @param permissions permissions to grant the new user via the new role.
* @return information about the entities that were created
*/
protected LargeGroupEnvironment createLargeGroupWithNormalUserRoleAccess(final int groupSize,
final Permission... permissions) {
return createLargeGroupWithNormalUserRoleAccess(null, groupSize, 0, 0, 0, permissions);
}
protected LargeGroupEnvironment createLargeGroupWithNormalUserRoleAccess(LargeGroupEnvironment largeGroupEnv,
final int groupSize, final int down, final int unknown, final int disabled, final Permission... permissions) {
return createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(largeGroupEnv, groupSize, down, unknown,
disabled, 0, permissions);
}
/**
* Creates a compatible group of the given size. This also creates a normal user and a role
* and makes sure that user can access the group that was created. The role will be assigned the
* given permissions and that role be placed on the new group and the new user.
*
* If lge is not null, that means we already have resource types created. We'll reuse those types.
*
* @param largeGroupEnv an already-created large group environment object (may be null)
* @param groupSize the number of members to create and put into the compatible group that is created.
* @param down number of resources that are to be set as DOWN
* @param unknown number of resources whose availability status is to be marked as UNKNOWN
* @param disabled number of resources that are to be set as DISABLED
* @param uncommitted number of resources whose inventory status is not COMMITTED (will be NEW instead)
* @param permissions permissions to grant the new user via the new role.
* @return information about the entities that were created
*/
protected LargeGroupEnvironment createLargeGroupWithNormalUserRoleAccessWithInventoryStatus(
LargeGroupEnvironment largeGroupEnv, final int groupSize, final int down, final int unknown,
final int disabled, final int uncommitted, final Permission... permissions) {
System.out.println("=====Creating a group with [" + groupSize + "] members");
final LargeGroupEnvironment lge = new LargeGroupEnvironment(largeGroupEnv);
executeInTransaction(false, new TransactionCallback() {
public void execute() throws Exception {
// create the agent where all resources will be housed
lge.agent = SessionTestHelper.createNewAgent(em, "LargeGroupTestAgent");
// create the platform resource type and server resource type
// the server type will have both a plugin configuration definition and resource config def
if (lge.platformType == null) {
lge.platformType = new ResourceType("LargeGroupTestPlatformType", "testPlugin",
ResourceCategory.PLATFORM, null);
em.persist(lge.platformType);
} else {
lge.platformType = em.find(ResourceType.class, lge.platformType.getId());
}
if (lge.serverType == null) {
lge.serverType = new ResourceType("LargeGroupTestServerType", "testPlugin",
ResourceCategory.SERVER, lge.platformType);
lge.serverPluginConfiguration = new ConfigurationDefinition("LargeGroupTestPCDef", "pc desc");
lge.serverPluginConfiguration.put(new PropertyDefinitionSimple(PC_PROP1_NAME, "pc prop1desc",
false, PropertySimpleType.STRING));
lge.serverPluginConfiguration.put(new PropertyDefinitionSimple(PC_PROP2_NAME, "pc prop2desc",
false, PropertySimpleType.STRING));
lge.serverType.setPluginConfigurationDefinition(lge.serverPluginConfiguration);
lge.serverResourceConfiguration = new ConfigurationDefinition("LargeGroupTestRCDef", "rc desc");
lge.serverResourceConfiguration.put(new PropertyDefinitionSimple(RC_PROP1_NAME, "rc prop1desc",
false, PropertySimpleType.STRING));
lge.serverResourceConfiguration.put(new PropertyDefinitionSimple(RC_PROP2_NAME, "rc prop2desc",
false, PropertySimpleType.STRING));
lge.serverType.setResourceConfigurationDefinition(lge.serverResourceConfiguration);
em.persist(lge.serverType);
em.flush();
} else {
lge.serverType = em.find(ResourceType.class, lge.serverType.getId());
}
// create our platform - all of our server resources will have this as their parent
lge.platformResource = SessionTestHelper.createNewResource(em, "LargeGroupTestPlatform",
lge.platformType);
lge.platformResource.setAgent(lge.agent);
// create our subject and role
lge.normalSubject = new Subject("LargeGroupTestSubject" + System.currentTimeMillis(), true, false);
lge.normalRole = SessionTestHelper.createNewRoleForSubject(em, lge.normalSubject, "LargeGroupTestRole",
permissions);
// create our unauthorized subject
lge.unauthzSubject = SessionTestHelper.createNewSubject(em, "LargeGroupTestSubjectUnauth");
// create our compatible group
lge.compatibleGroup = SessionTestHelper.createNewCompatibleGroupForRole(em, lge.normalRole,
"LargeGroupTestCompatGroup", lge.serverType);
// create our many server resources
int downCount = down;
int unknownCount = unknown;
int disabledCount = disabled;
int uncommittedCount = uncommitted;
System.out.print("=====> Creating member Resources (this might take some time)...");
for (int i = 1; i <= groupSize; i++) {
AvailabilityType avail;
InventoryStatus inventoryStatus = InventoryStatus.COMMITTED;
if (downCount > 0) {
avail = AvailabilityType.DOWN;
downCount--;
} else if (unknownCount > 0) {
avail = AvailabilityType.UNKNOWN;
unknownCount--;
} else if (disabledCount > 0) {
avail = AvailabilityType.DISABLED;
disabledCount--;
} else if (uncommittedCount > 0) {
avail = AvailabilityType.UNKNOWN;
inventoryStatus = InventoryStatus.NEW;
uncommittedCount--;
} else {
avail = AvailabilityType.UP;
}
Resource res = SessionTestHelper.createNewResourceForGroup(em, lge.compatibleGroup,
"LargeGroupTestServer", lge.serverType, avail, (i % 100) == 0);
res.setAgent(lge.agent);
res.setInventoryStatus(inventoryStatus);
lge.platformResource.addChildResource(res);
// give it an initial plugin configuration
Configuration pc = new Configuration();
pc.put(new PropertySimple(PC_PROP1_NAME, PC_PROP1_VALUE));
pc.put(new PropertySimple(PC_PROP2_NAME, res.getId()));
em.persist(pc);
res.setPluginConfiguration(pc);
if ((i % 100) == 0) {
System.out.print(i);
} else if ((i % 10) == 0) {
System.out.print('.');
}
}
System.out.println(" Done.");
em.flush();
em.clear();
}
});
System.out.println("=====Created group [" + lge.compatibleGroup.getName() + "] with ["
+ lge.platformResource.getChildResources().size() + "] members");
return lge;
}
protected void tearDownLargeGroupWithNormalUserRoleAccess(final LargeGroupEnvironment lge) throws Exception {
tearDownLargeGroupWithNormalUserRoleAccess(lge, false);
}
/**
* Purges all the entities that were created by the
* {@link #createLargeGroupWithNormalUserRoleAccess(int, org.rhq.core.domain.authz.Permission...)} method.
* This includes the user, role, agent and all resources, along with the group itself.
*
* @param lge contains information that was created which needs to be deleted
* @param keepTypes if true, do not delete the resource types
*/
protected void tearDownLargeGroupWithNormalUserRoleAccess(final LargeGroupEnvironment lge, boolean keepTypes)
throws Exception {
System.out.println("=====Cleaning up test data from " + this.getClass().getSimpleName());
// purge the group itself
resourceGroupManager.deleteResourceGroup(getOverlord(), lge.compatibleGroup.getId());
// purge all resources by performing in-band and out-of-band work in quick succession.
// this takes a long time but trying to get this right using native queries is hard to get right so just do it this way.
// only need to delete the platform which will delete all children servers AND the agent itself
System.out.print("=====> Removing member Resources (this might take some time)...");
final List<Integer> deletedIds = resourceManager.uninventoryResource(getOverlord(),
lge.platformResource.getId());
for (int i = 1, deletedIdsSize = deletedIds.size(); i <= deletedIdsSize; i++) {
Integer deletedResourceId = deletedIds.get(i - 1);
resourceManager.uninventoryResourceAsyncWork(getOverlord(), deletedResourceId);
if ((i % 100) == 0) {
System.out.print(i);
} else if ((i % 10) == 0) {
System.out.print('.');
}
}
System.out.println(" Done.");
// purge the users and role
executeInTransaction(false, new TransactionCallback() {
public void execute() throws Exception {
lge.normalRole = em.getReference(Role.class, lge.normalRole.getId());
lge.normalSubject = em.getReference(Subject.class, lge.normalSubject.getId());
lge.unauthzSubject = em.getReference(Subject.class, lge.unauthzSubject.getId());
em.remove(lge.normalRole);
em.remove(lge.normalSubject);
em.remove(lge.unauthzSubject);
}
});
if (!keepTypes) {
// purge the resource types
executeInTransaction(false, new TransactionCallback() {
public void execute() throws Exception {
ResourceType pType = em.getReference(ResourceType.class, lge.platformResource.getResourceType()
.getId());
ResourceType sType = em.getReference(ResourceType.class, lge.compatibleGroup.getResourceType()
.getId());
em.remove(sType);
em.remove(pType);
}
});
}
System.out.println("=====Cleaned up test data from " + this.getClass().getSimpleName());
}
/**
* Given the id of a compatible group, this will return the status of the update.
*
* @param groupId compatible group ID
* @return status, or null if not known
*/
protected ConfigurationUpdateStatus getGroupPluginConfigurationStatus(final int groupId) {
return executeInTransaction(false, new TransactionCallbackReturnable<ConfigurationUpdateStatus>() {
public ConfigurationUpdateStatus execute() throws Exception {
try {
Query query = em.createNamedQuery(GroupPluginConfigurationUpdate.QUERY_FIND_LATEST_BY_GROUP_ID);
query.setParameter("groupId", groupId);
GroupPluginConfigurationUpdate latestConfigGroupUpdate = (GroupPluginConfigurationUpdate) query
.getSingleResult();
return latestConfigGroupUpdate.getStatus();
} catch (NoResultException nre) {
// The group resource config history is empty, so there's obviously no update in progress.
return null;
}
}
});
}
/**
* Given the id of a compatible group, this will return the status of the update.
*
* @param groupId compatible group ID
* @return status, or null if not known
*/
protected ConfigurationUpdateStatus getGroupResourceConfigurationStatus(final int groupId) {
return executeInTransaction(false, new TransactionCallbackReturnable<ConfigurationUpdateStatus>() {
public ConfigurationUpdateStatus execute() throws Exception {
try {
Query query = em.createNamedQuery(GroupResourceConfigurationUpdate.QUERY_FIND_LATEST_BY_GROUP_ID);
query.setParameter("groupId", groupId);
GroupResourceConfigurationUpdate latestConfigGroupUpdate = (GroupResourceConfigurationUpdate) query
.getSingleResult();
return latestConfigGroupUpdate.getStatus();
} catch (NoResultException nre) {
// The group resource config history is empty, so there's obviously no update in progress.
return null;
}
}
});
}
/**
* Obtain the overlord user.
* @return overlord
*/
protected Subject getOverlord() {
return subjectManager.getOverlord();
}
}