/*
* RHQ Management Platform
* Copyright (C) 2005-2014 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.enterprise.server.alert;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.TypedQuery;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.testng.annotations.Test;
import org.rhq.core.domain.alert.AlertCondition;
import org.rhq.core.domain.alert.AlertConditionCategory;
import org.rhq.core.domain.alert.AlertConditionOperator;
import org.rhq.core.domain.alert.AlertDampening;
import org.rhq.core.domain.alert.AlertDefinition;
import org.rhq.core.domain.alert.AlertPriority;
import org.rhq.core.domain.alert.BooleanExpression;
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.criteria.AlertDefinitionCriteria;
import org.rhq.core.domain.resource.Resource;
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.authz.RoleManagerLocal;
import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.test.TransactionCallback;
import org.rhq.enterprise.server.test.TransactionCallbackReturnable;
import org.rhq.enterprise.server.util.BatchIterator;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.util.ResourceTreeHelper;
import org.rhq.enterprise.server.util.SessionTestHelper;
/**
* @author Thomas Segismont
*/
@Test(groups = "alert")
public class GroupAlertDefinitionManagerBeanTest extends AbstractEJB3Test {
private static final Log LOG = LogFactory.getLog(GroupAlertDefinitionManagerBeanTest.class);
public static final int NUMBER_OF_RESOURCES_TO_CREATE = 3753;
final private String prefix = this.getClass().getSimpleName() + "_";
final private String subjectName = prefix + "subject";
final private String roleName = prefix + "role";
final private String groupName = prefix + "group";
final private String resourceName = prefix + "resource";
private SubjectManagerLocal subjectManager;
private RoleManagerLocal roleManager;
private ResourceGroupManagerLocal resourceGroupManager;
private GroupAlertDefinitionManagerLocal groupAlertDefinitionManager;
private AlertDefinitionManagerLocal alertDefinitionManager;
private TestData testData;
@Override
protected void beforeMethod() throws Exception {
subjectManager = LookupUtil.getSubjectManager();
roleManager = LookupUtil.getRoleManager();
resourceGroupManager = LookupUtil.getResourceGroupManager();
groupAlertDefinitionManager = LookupUtil.getGroupAlertDefinitionManager();
alertDefinitionManager = LookupUtil.getAlertDefinitionManager();
createTestData();
prepareScheduler();
}
/**
* Bug 738799 - deleting a group alertdef containing >1000 member alertdefs fails with
* "SQLException: ORA-01795: maximum number of expressions in a list is 1000" error
* https://bugzilla.redhat.com/show_bug.cgi?id=738799
* (jshaughn 6/16/2014): make sure this works when called through the alert def remote, which now calls
* into the local.
*/
public void testBug738799() {
List<Integer> childDefIds = getChildrenAlertDefinitionIds(testData.getGroupAlertDefinitionId());
assertEquals(testData.getResources().size(), childDefIds.size());
int modified = alertDefinitionManager.removeAlertDefinitions(testData.getSubject(),
new int[] { testData.getGroupAlertDefinitionId() });
assertEquals(modified, 1);
childDefIds = getChildrenAlertDefinitionIds(testData.getGroupAlertDefinitionId());
assertEquals(0, childDefIds.size());
BatchIterator<Integer> childDefIdsBatchIterator = new BatchIterator<Integer>(childDefIds);
for (List<Integer> childDefIdsBatch : childDefIdsBatchIterator) {
AlertDefinitionCriteria criteria = new AlertDefinitionCriteria();
criteria.addFilterIds(childDefIdsBatch.toArray(new Integer[childDefIdsBatch.size()]));
List<AlertDefinition> remainingChildDefs = alertDefinitionManager.findAlertDefinitionsByCriteria(
testData.getSubject(), criteria);
assertEquals(0, remainingChildDefs.size());
}
}
@Override
protected void afterMethod() throws Exception {
try {
deleteTestData();
} finally {
testData = null;
unprepareScheduler();
}
}
private void createTestData() throws Exception {
testData = executeInTransaction(false, new TransactionCallbackReturnable<TestData>() {
@Override
public TestData execute() throws Exception {
TestData newTestData = new TestData();
Subject subject = SessionTestHelper.createNewSubject(em, subjectName);
newTestData.setSubject(subject);
Role role = SessionTestHelper.createNewRoleForSubject(em, subject, roleName, Permission.MANAGE_ALERTS,
Permission.MANAGE_SETTINGS, Permission.MANAGE_INVENTORY);
newTestData.setRole(role);
ResourceType resourceType = SessionTestHelper.createNewResourceType(em);
newTestData.setResourceType(resourceType);
ResourceGroup resourceGroup = new ResourceGroup(groupName, resourceType);
resourceGroup = resourceGroupManager.createResourceGroup(subject, resourceGroup);
newTestData.setResourceGroup(resourceGroup);
roleManager.setAssignedResourceGroups(subjectManager.getOverlord(), role.getId(),
new int[] { resourceGroup.getId() });
return newTestData;
}
});
testData.setResources(new ArrayList<Resource>(NUMBER_OF_RESOURCES_TO_CREATE));
while (testData.getResources().size() < NUMBER_OF_RESOURCES_TO_CREATE) {
executeInTransaction(false, new TransactionCallback() {
// Create resources in batches to avoid too big transactions
@Override
public void execute() throws Exception {
for (int i = 0; i < 50 && testData.getResources().size() < NUMBER_OF_RESOURCES_TO_CREATE; i++) {
testData.getResources().add(
SessionTestHelper.createNewResource(em, resourceName, testData.getResourceType()));
}
}
});
if (LOG.isDebugEnabled()) {
LOG.debug(testData.getResources().size() + " resources created");
}
}
int[] resourceIds = new int[testData.getResources().size()];
for (int i = 0; i < testData.getResources().size(); i++) {
resourceIds[i] = testData.getResources().get(i).getId();
}
resourceGroupManager.setAssignedResources(testData.getSubject(), testData.getResourceGroup().getId(),
resourceIds, true);
testData.setGroupAlertDefinitionId(createGroupAlertDefinition(testData.getSubject(),
testData.getResourceGroup()).getId());
}
private AlertDefinition createGroupAlertDefinition(Subject subject, ResourceGroup resourceGroup) {
AlertDefinition alertDefinition = new AlertDefinition();
alertDefinition.setName(AlertConditionOperator.AVAIL_GOES_UP.name());
alertDefinition.setPriority(AlertPriority.MEDIUM);
alertDefinition.setAlertDampening(new AlertDampening(AlertDampening.Category.NONE));
alertDefinition.setConditionExpression(BooleanExpression.ANY);
alertDefinition.setRecoveryId(0);
alertDefinition.setGroup(resourceGroup);
alertDefinition.setEnabled(true);
AlertCondition alertCondition = new AlertCondition(alertDefinition, AlertConditionCategory.AVAILABILITY);
alertCondition.setName(AlertConditionOperator.AVAIL_GOES_UP.name());
alertDefinition.addCondition(alertCondition);
groupAlertDefinitionManager.createGroupAlertDefinitions(subject, alertDefinition, resourceGroup.getId());
return alertDefinition;
}
private void deleteTestData() throws Exception {
if (testData != null) {
groupAlertDefinitionManager.removeGroupAlertDefinitions(subjectManager.getOverlord(),
new Integer[] { testData.getGroupAlertDefinitionId() });
resourceGroupManager.deleteResourceGroup(subjectManager.getOverlord(), testData.getResourceGroup().getId());
alertDefinitionManager.purgeUnusedAlertDefinitions();
for (Resource resource : testData.getResources()) {
removeEntity(Resource.class, resource.getId());
}
removeEntity(ResourceType.class, testData.getResourceType().getId());
subjectManager.deleteSubjects(subjectManager.getOverlord(), new int[] { testData.getSubject().getId() });
roleManager.deleteRoles(subjectManager.getOverlord(), new int[] { testData.getRole().getId() });
}
}
private void removeEntity(final Class<?> entityClass, final Object entityId) {
try {
executeInTransaction(false, new TransactionCallback() {
@Override
public void execute() throws Exception {
Object object = em.find(entityClass, entityId);
if (object instanceof Resource) {
ResourceTreeHelper.deleteResource(em, (Resource) object);
} else {
em.remove(object);
em.flush();
}
}
});
} catch (Exception e) {
LOG.error("Failed to delete object from database: " + entityClass + "[id=" + entityId + "]", e);
}
}
private List<Integer> getChildrenAlertDefinitionIds(final int groupAlertDefinitionId) {
return executeInTransaction(false, new TransactionCallbackReturnable<List<Integer>>() {
@Override
public List<Integer> execute() throws Exception {
TypedQuery<Integer> query = getEntityManager().createNamedQuery(
AlertDefinition.QUERY_FIND_BY_GROUP_ALERT_DEFINITION_ID, Integer.class);
query.setParameter("groupAlertDefinitionId", groupAlertDefinitionId);
return query.getResultList();
}
});
}
private static final class TestData {
private Subject subject;
private Role role;
private ResourceType resourceType;
private ResourceGroup resourceGroup;
private List<Resource> resources;
private int groupAlertDefinitionId;
private Subject getSubject() {
return subject;
}
private void setSubject(Subject subject) {
this.subject = subject;
}
private Role getRole() {
return role;
}
private void setRole(Role role) {
this.role = role;
}
private ResourceType getResourceType() {
return resourceType;
}
private void setResourceType(ResourceType resourceType) {
this.resourceType = resourceType;
}
private ResourceGroup getResourceGroup() {
return resourceGroup;
}
private void setResourceGroup(ResourceGroup resourceGroup) {
this.resourceGroup = resourceGroup;
}
private List<Resource> getResources() {
return resources;
}
private void setResources(List<Resource> resources) {
this.resources = resources;
}
private int getGroupAlertDefinitionId() {
return groupAlertDefinitionId;
}
private void setGroupAlertDefinitionId(int groupAlertDefinitionId) {
this.groupAlertDefinitionId = groupAlertDefinitionId;
}
}
}