/*
* RHQ Management Platform
* Copyright (C) 2005-2008 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, version 2, as
* published by the Free Software Foundation, and/or the GNU Lesser
* General Public License, version 2.1, also as published by the Free
* Software Foundation.
*
* 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 and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser 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.core.domain.resource.test;
import java.util.List;
import java.util.Random;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import org.testng.annotations.Test;
import org.rhq.core.domain.alert.Alert;
import org.rhq.core.domain.alert.AlertDampening;
import org.rhq.core.domain.alert.AlertDampening.Category;
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.measurement.Availability;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.measurement.MeasurementSchedule;
import org.rhq.core.domain.measurement.NumericType;
import org.rhq.core.domain.measurement.ResourceAvailability;
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.composite.ProblemResourceComposite;
import org.rhq.core.domain.test.AbstractEJB3Test;
@Test(groups = "integration.ejb3")
public class ProblemResourceTest extends AbstractEJB3Test {
private long now;
private long fiveMinutesAgo;
private ResourceType platformType;
private Resource platform;
private Resource platform2;
private MeasurementDefinition measDef;
private MeasurementSchedule measSched;
private MeasurementSchedule measSched2;
private AlertDefinition alertDef;
private AlertDefinition alertDef2;
private EntityManager entityManager;
private List<ProblemResourceComposite> results;
public void testProblemResourcesAlert() throws Throwable {
getTransactionManager().begin();
entityManager = getEntityManager();
try {
setupResources(entityManager);
assert entityManager.find(Resource.class, platform.getId()) != null : "Did not setup platform - cannot test";
assertResults(entityManager, fiveMinutesAgo, 0);
assertCount(entityManager, fiveMinutesAgo, 0);
Alert alert = new Alert(alertDef, now - 10000);
entityManager.persist(alert);
//commitAndBegin();
results = assertResults(entityManager, fiveMinutesAgo, 1);
assertCount(entityManager, fiveMinutesAgo, 1);
assertComposite(results.get(0), platform, 1);
Alert alert2 = new Alert(alertDef2, now - 5000);
entityManager.persist(alert2);
//commitAndBegin();
results = assertResults(entityManager, fiveMinutesAgo, 2);
assertCount(entityManager, fiveMinutesAgo, 2);
int platform1Index = (results.get(0).getResourceId() == platform.getId()) ? 0 : 1;
int platform2Index = 1 - platform1Index;
assertComposite(results.get(platform1Index), platform, 1);
assertComposite(results.get(platform2Index), platform2, 1);
Alert alert3 = new Alert(alertDef2, now);
entityManager.persist(alert3);
//commitAndBegin();
results = assertResults(entityManager, fiveMinutesAgo, 2);
assertCount(entityManager, fiveMinutesAgo, 2);
platform1Index = (results.get(0).getResourceId() == platform.getId()) ? 0 : 1;
platform2Index = 1 - platform1Index;
assertComposite(results.get(platform1Index), platform, 1);
assertComposite(results.get(platform2Index), platform2, 2);
deleteResources();
} catch (Throwable t) {
dumpResults("testProblemResourcesAlert");
throw t;
} finally {
getTransactionManager().rollback();
}
}
/**
* The Alert resource queries will also return resources that are currently down.
*
* @throws Throwable
*/
public void testProblemResourcesAvailability() throws Throwable {
getTransactionManager().begin();
entityManager = getEntityManager();
try {
setupResources(entityManager);
assert entityManager.find(Resource.class, platform.getId()) != null : "Did not setup platform - cannot test";
assertResults(entityManager, fiveMinutesAgo, 0);
assertCount(entityManager, fiveMinutesAgo, 0);
ResourceAvailability resourceAvail = new ResourceAvailability(platform, AvailabilityType.DOWN);
entityManager.persist(resourceAvail);
Availability avail = new Availability(platform, AvailabilityType.DOWN);
entityManager.persist(avail);
//commitAndBegin();
results = assertResults(entityManager, fiveMinutesAgo, 1);
assertCount(entityManager, fiveMinutesAgo, 1);
assertComposite(results.get(0), platform, 0);
assert results.get(0).getAvailabilityType() == AvailabilityType.DOWN;
assertComposite(results.get(0), platform, 0);
assert results.get(0).getAvailabilityType() == AvailabilityType.DOWN;
ResourceAvailability resourceAvail2 = new ResourceAvailability(platform2, AvailabilityType.DOWN);
entityManager.persist(resourceAvail2);
Availability avail2 = new Availability(platform2, null, AvailabilityType.DOWN);
entityManager.persist(avail2);
//commitAndBegin();
results = assertResults(entityManager, fiveMinutesAgo, 2);
assertCount(entityManager, fiveMinutesAgo, 2);
int platform1Index = (results.get(0).getResourceId() == platform.getId()) ? 0 : 1;
int platform2Index = 1 - platform1Index;
assertComposite(results.get(platform1Index), platform, 0);
assert results.get(platform1Index).getAvailabilityType() == AvailabilityType.DOWN;
assertComposite(results.get(platform2Index), platform2, 0);
assert results.get(platform2Index).getAvailabilityType() == AvailabilityType.DOWN;
platform1Index = (results.get(0).getResourceId() == platform.getId()) ? 0 : 1;
platform2Index = 1 - platform1Index;
assertComposite(results.get(platform1Index), platform, 0);
assert results.get(platform1Index).getAvailabilityType() == AvailabilityType.DOWN;
assertComposite(results.get(platform2Index), platform2, 0);
assert results.get(platform2Index).getAvailabilityType() == AvailabilityType.DOWN;
deleteResources();
} catch (Throwable t) {
dumpResults("testProblemResourcesAvailability");
throw t;
} finally {
getTransactionManager().rollback();
}
}
@SuppressWarnings("unchecked")
private List<ProblemResourceComposite> assertResults(EntityManager em, long oldest, long expectedSize) {
Query q = em.createNamedQuery(Resource.QUERY_FIND_PROBLEM_RESOURCES_ALERT_ADMIN);
q.setParameter("oldest", oldest);
List<ProblemResourceComposite> resultList = q.getResultList();
assert resultList.size() == expectedSize : "List was to be size=" + expectedSize + " but was " + resultList;
return resultList;
}
private int assertCount(EntityManager em, long oldest, long expectedCount) {
Query q = em.createNamedQuery(Resource.QUERY_FIND_PROBLEM_RESOURCES_ALERT_COUNT_ADMIN);
q.setParameter("oldest", oldest);
int count = ((Number) q.getSingleResult()).intValue();
assert count == expectedCount : "Expected the count to be " + expectedCount + " but was " + count;
return count;
}
private void assertComposite(ProblemResourceComposite composite, Resource plat, int alertCount) {
assert composite.getResourceId() == plat.getId() : "Expected id " + plat.getId() + ", got "
+ composite.getResourceId();
assert composite.getResourceName().equals(plat.getName()) : "Expected name " + plat.getName() + ", got "
+ composite.getResourceName();
assert composite.getNumAlerts() == alertCount : "Expected " + alertCount + " alerts, got "
+ composite.getNumAlerts();
}
private void setupResources(EntityManager em) {
now = System.currentTimeMillis();
fiveMinutesAgo = now - (5 * 60 * 1000);
platformType = new ResourceType("testplatPR", "p", ResourceCategory.PLATFORM, null);
em.persist(platformType);
platform = new Resource("platform1", "testProblemResources Platform One", platformType);
platform.setUuid("" + new Random().nextInt());
platform.setInventoryStatus(InventoryStatus.COMMITTED);
em.persist(platform);
platform2 = new Resource("platform2", "testProblemResources Platform Two", platformType);
platform2.setUuid("" + new Random().nextInt());
platform2.setInventoryStatus(InventoryStatus.COMMITTED);
em.persist(platform2);
measDef = new MeasurementDefinition(platformType, "testProblemResourcesMeasurement");
measDef.setDefaultOn(true);
measDef.setDisplayName("testProblemResources Measurement Display Name");
measDef.setMeasurementType(NumericType.DYNAMIC);
em.persist(measDef);
measSched = new MeasurementSchedule(measDef, platform);
measSched.setEnabled(true);
platform.addSchedule(measSched);
measDef.addSchedule(measSched);
em.persist(measSched);
measSched2 = new MeasurementSchedule(measDef, platform2);
measSched2.setEnabled(true);
platform2.addSchedule(measSched2);
measDef.addSchedule(measSched2);
em.persist(measSched2);
alertDef = new AlertDefinition();
alertDef.setName("PRAlertDef1");
alertDef.setResource(platform);
alertDef.setPriority(AlertPriority.MEDIUM);
alertDef.setAlertDampening(new AlertDampening(Category.NONE));
alertDef.setConditionExpression(BooleanExpression.ALL);
alertDef.setRecoveryId(0);
em.persist(alertDef);
alertDef2 = new AlertDefinition();
alertDef2.setName("PRAlertDef2");
alertDef2.setResource(platform2);
alertDef2.setPriority(AlertPriority.MEDIUM);
alertDef2.setAlertDampening(new AlertDampening(Category.NONE));
alertDef2.setConditionExpression(BooleanExpression.ALL);
alertDef2.setRecoveryId(0);
em.persist(alertDef2);
}
/**
* Use this mainly when debugging and using {@link #commitAndBegin()} - this will help clean out things.
*/
private void deleteResources() {
Object doomed;
try {
if ((doomed = entityManager.find(AlertDefinition.class, alertDef.getId())) != null) {
entityManager.remove(doomed);
}
if ((doomed = entityManager.find(AlertDefinition.class, alertDef2.getId())) != null) {
entityManager.remove(doomed);
}
if ((doomed = entityManager.find(MeasurementSchedule.class, measSched.getId())) != null) {
entityManager.remove(doomed);
}
if ((doomed = entityManager.find(MeasurementSchedule.class, measSched2.getId())) != null) {
entityManager.remove(doomed);
}
if ((doomed = entityManager.find(MeasurementDefinition.class, measDef.getId())) != null) {
entityManager.remove(doomed);
}
if ((doomed = entityManager.find(Resource.class, platform.getId())) != null) {
entityManager.remove(doomed);
}
if ((doomed = entityManager.find(Resource.class, platform2.getId())) != null) {
entityManager.remove(doomed);
}
if ((doomed = entityManager.find(ResourceType.class, platformType.getId())) != null) {
entityManager.remove(doomed);
}
} catch (Exception e) {
System.out.println("Cannot delete test resources, database still has test data in it");
e.printStackTrace();
}
}
private void dumpResults(String msg) {
// System.out.println( "-----" + msg + "-----" );
// if ( results != null )
// {
// System.out.println( "LAST [" + results.size() + "] RESULTS WERE:" );
// for ( ProblemResourceComposite problem : results )
// {
// System.out.println( "PROBLEM-->" + problem );
// Resource r = entityManager.find( Resource.class, problem.getResourceId() );
// if ( r == null )
// {
// continue;
// }
//
// System.out.println( "RESOURCE--> name=" + r.getName() );
// System.out.println( "RESOURCE--> availability=" + r.getAvailability() );
// if ( r.getAlertDefinitions() != null )
// {
// for ( AlertDefinition def : r.getAlertDefinitions() )
// {
// System.out.println( "RESOURCE--> alerts: " + def.getAlerts() );
// }
// }
// }
// }
// else
// {
// System.out.println( "NO RESULTS AVAILABLE" );
// }
printHierarchies();
}
// commitAndBegin, commit, begin are used mainly when testing in a debugger
// so you can commit the data, and examine it in an external SQL tool without
// worrying about transactions timing out within the paused test thread.
private void commitAndBegin() throws Exception {
commit();
begin(); // put a breakpoint here and call commitAndBegin at a place where you want to pause the test
}
private void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
SystemException {
entityManager.flush();
getTransactionManager().commit();
}
private void begin() throws NotSupportedException, SystemException {
getTransactionManager().begin();
entityManager = getEntityManager();
}
private void printHierarchies() {
System.out.println("---hierarchy START---");
printPlatform(platform);
printPlatform(platform2);
System.out.println("---hierarchy END---");
}
private void printPlatform(Resource plat) {
plat = entityManager.merge(plat);
System.out.println(plat);
for (AlertDefinition def : plat.getAlertDefinitions()) {
System.out.println(" " + def);
for (Alert a : def.getAlerts()) {
System.out.println(" " + a);
}
}
}
}