You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2016/02/01 18:48:54 UTC
[24/50] brooklyn-server git commit: Adds JMX reachable listener,
for setting service-down
Adds JMX reachable listener, for setting service-down
- adds JmxReachableAdapter, for responding to MBean not-reachable
- adds AbstractPollHelper.polledListeners (rather than
just setting sensors)
- JmxAttributeAdapter:
-- don't wait 15 seconds for MBean to exist during activate
-- and catch exception if connect exception
- tests JmxSensorAdapter for when jmx service/mbean unreachable
- tests/fixes web-apps for kill, that they report service-down
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/79ddd7e9
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/79ddd7e9
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/79ddd7e9
Branch: refs/heads/0.4.0
Commit: 79ddd7e921f6614f706afc5136087b7c685d5b27
Parents: 191fa83
Author: Aled Sage <al...@gmail.com>
Authored: Sat Oct 6 15:30:32 2012 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue Oct 9 10:01:36 2012 +0100
----------------------------------------------------------------------
.../event/adapter/AbstractPollHelper.groovy | 14 +++-
.../event/adapter/AbstractSensorAdapter.groovy | 10 +--
.../event/adapter/JmxAttributeAdapter.groovy | 15 ++--
.../java/brooklyn/event/adapter/JmxHelper.java | 2 +-
.../event/adapter/JmxObjectNameAdapter.groovy | 5 ++
.../event/adapter/JmxReachableAdapter.java | 78 ++++++++++++++++++++
.../event/adapter/SensorRegistry.groovy | 10 +--
.../java/brooklyn/util/GroovyJavaMethods.groovy | 4 +-
.../event/adapter/JmxSensorAdapterTest.groovy | 55 +++++++++++++-
9 files changed, 173 insertions(+), 20 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/79ddd7e9/core/src/main/java/brooklyn/event/adapter/AbstractPollHelper.groovy
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/adapter/AbstractPollHelper.groovy b/core/src/main/java/brooklyn/event/adapter/AbstractPollHelper.groovy
index d412b64..51b3107 100644
--- a/core/src/main/java/brooklyn/event/adapter/AbstractPollHelper.groovy
+++ b/core/src/main/java/brooklyn/event/adapter/AbstractPollHelper.groovy
@@ -18,6 +18,8 @@ public abstract class AbstractPollHelper {
final Map<AttributeSensor, Closure> polledSensors = [:]
+ final List<Closure> polledListeners = []
+
boolean lastWasSuccessful = false;
AbstractSensorAdapter adapter;
@@ -32,6 +34,10 @@ public abstract class AbstractPollHelper {
if (old!=null) log.warn "change of provider (discouraged) for sensor ${s} on ${entity}", new Throwable("path of discouraged change");
}
+ public void addListener(Closure c) {
+ polledListeners.add(c)
+ }
+
ScheduledTask schedule;
protected activatePoll() {
@@ -50,7 +56,7 @@ public abstract class AbstractPollHelper {
}
protected boolean isEmpty() {
- polledSensors.isEmpty();
+ polledSensors.isEmpty() && polledListeners.isEmpty();
}
/** implementation-specific generation of AbstractSensorEvaluationContext which is then typically passed to evaluateSensorsOnPollResponse */
@@ -87,6 +93,12 @@ public abstract class AbstractPollHelper {
void evaluateSensorsOnResponse(AbstractSensorEvaluationContext response) {
polledSensors.each { s, c -> evaluateSensorOnResponse(s, c, response) }
+ polledListeners.each {
+ Object v = response.evaluate({it})
+ if (v != AbstractSensorEvaluationContext.UNSET) {
+ it.call(v)
+ }
+ }
}
Object evaluateSensorOnResponse(Sensor<?> s, Closure c, AbstractSensorEvaluationContext response) {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/79ddd7e9/core/src/main/java/brooklyn/event/adapter/AbstractSensorAdapter.groovy
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/adapter/AbstractSensorAdapter.groovy b/core/src/main/java/brooklyn/event/adapter/AbstractSensorAdapter.groovy
index 4092c01..8107cad 100644
--- a/core/src/main/java/brooklyn/event/adapter/AbstractSensorAdapter.groovy
+++ b/core/src/main/java/brooklyn/event/adapter/AbstractSensorAdapter.groovy
@@ -44,22 +44,22 @@ public abstract class AbstractSensorAdapter {
registry.addActivationLifecycleListeners({ activateAdapter() }, { deactivateAdapter() })
}
- private List<Closure> activationListeners = []
- private List<Closure> deactivationListeners = []
- protected void addActivationLifecycleListeners(Closure onUp, Closure onDown) {
+ private List<Runnable> activationListeners = []
+ private List<Runnable> deactivationListeners = []
+ protected void addActivationLifecycleListeners(Runnable onUp, Runnable onDown) {
activationListeners << onUp
deactivationListeners << onDown
}
protected void activateAdapter() {
if (activated) return; //prevent double activation
if (log.isDebugEnabled()) log.debug "activating adapter {} for {}", this, entity
- activationListeners.each { it.call() }
+ activationListeners.each { it.run() }
activated = true;
}
protected void deactivateAdapter() {
if (log.isDebugEnabled()) log.debug "deactivating adapter {} for {}", this, entity
activated = false;
- deactivationListeners.each { it.call() }
+ deactivationListeners.each { it.run() }
}
protected boolean isConnected() { isActivated() }
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/79ddd7e9/core/src/main/java/brooklyn/event/adapter/JmxAttributeAdapter.groovy
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/adapter/JmxAttributeAdapter.groovy b/core/src/main/java/brooklyn/event/adapter/JmxAttributeAdapter.groovy
index d76be3d..a917ece 100644
--- a/core/src/main/java/brooklyn/event/adapter/JmxAttributeAdapter.groovy
+++ b/core/src/main/java/brooklyn/event/adapter/JmxAttributeAdapter.groovy
@@ -1,5 +1,6 @@
package brooklyn.event.adapter;
+import groovy.time.TimeDuration
import groovy.transform.InheritConstructors
import javax.management.ObjectName
@@ -65,11 +66,15 @@ public class JmxAttributeAdapter extends AbstractSensorAdapter {
@Override
protected void activateAdapter() {
super.activateAdapter();
- if (adapter.checkObjectNameExists(objectName)) {
- if (log.isDebugEnabled())
- log.debug("For $entity ${adapter.helper.url}, MBean ${objectName} exists");
- } else {
- log.warn("For $entity ${adapter.helper.url}, MBean ${objectName} does not yet exist; continuing...");
+ try {
+ if (adapter.checkObjectNameExists(objectName, new TimeDuration(0, 0, 0, 0))) {
+ if (log.isDebugEnabled())
+ log.debug("For $entity ${adapter.helper.url}, MBean ${objectName} exists");
+ } else {
+ log.warn("For $entity ${adapter.helper.url}, MBean ${objectName} does not yet exist; continuing...");
+ }
+ } catch (Exception e) {
+ log.warn("For $entity ${adapter.helper.url}, not reachable for MBean ${objectName}; continuing...", e);
}
}
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/79ddd7e9/core/src/main/java/brooklyn/event/adapter/JmxHelper.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/adapter/JmxHelper.java b/core/src/main/java/brooklyn/event/adapter/JmxHelper.java
index 194833f..9664c4f 100644
--- a/core/src/main/java/brooklyn/event/adapter/JmxHelper.java
+++ b/core/src/main/java/brooklyn/event/adapter/JmxHelper.java
@@ -225,7 +225,7 @@ public class JmxHelper {
int attempt = 0;
while (currentTime <= endMs) {
currentTime = System.currentTimeMillis();
- if (attempt != 0) sleep(100); //sleep 100 to prevent trashing and facilitate interruption
+ if (attempt != 0) sleep(100); //sleep 100 to prevent thrashing and facilitate interruption
if (LOG.isTraceEnabled()) LOG.trace("trying connection to {} at time {}", url, currentTime);
try {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/79ddd7e9/core/src/main/java/brooklyn/event/adapter/JmxObjectNameAdapter.groovy
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/adapter/JmxObjectNameAdapter.groovy b/core/src/main/java/brooklyn/event/adapter/JmxObjectNameAdapter.groovy
index 8a87cf4..d923e45 100644
--- a/core/src/main/java/brooklyn/event/adapter/JmxObjectNameAdapter.groovy
+++ b/core/src/main/java/brooklyn/event/adapter/JmxObjectNameAdapter.groovy
@@ -18,6 +18,11 @@ public class JmxObjectNameAdapter {
this.adapter = adapter;
this.objectName = objectName;
}
+
+ JmxReachableAdapter reachable(Map flags=[:]) {
+ adapter.registry.register(new JmxReachableAdapter(flags, adapter, objectName));
+ }
+
JmxAttributeAdapter attribute(Map flags=[:], String attributeName) {
adapter.registry.register(new JmxAttributeAdapter(flags, adapter, objectName, attributeName));
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/79ddd7e9/core/src/main/java/brooklyn/event/adapter/JmxReachableAdapter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/adapter/JmxReachableAdapter.java b/core/src/main/java/brooklyn/event/adapter/JmxReachableAdapter.java
new file mode 100644
index 0000000..e83b1ab
--- /dev/null
+++ b/core/src/main/java/brooklyn/event/adapter/JmxReachableAdapter.java
@@ -0,0 +1,78 @@
+package brooklyn.event.adapter;
+
+import groovy.lang.Closure;
+
+import java.util.Map;
+
+import javax.management.ObjectName;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.GroovyJavaMethods;
+import brooklyn.util.MutableMap;
+
+import com.google.common.base.Function;
+
+
+/**
+ * Adapter that polls for a JMX attribute.
+ * "Attribute" here refers to the JMX concept, rather than the brooklyn concept.
+ *
+ * @see {@link JmxSensorAdapter} for recommended way of using this
+ */
+public class JmxReachableAdapter extends AbstractSensorAdapter {
+ private static final Logger LOG = LoggerFactory.getLogger(JmxReachableAdapter.class);
+
+ final JmxSensorAdapter adapter;
+ final ObjectName objectName;
+ final ReachablePollHelper poller;
+
+ public JmxReachableAdapter(JmxSensorAdapter adapter, ObjectName objectName) {
+ this(MutableMap.of(), adapter, objectName);
+ }
+ public JmxReachableAdapter(Map flags, JmxSensorAdapter adapter, ObjectName objectName) {
+ super(flags);
+ this.adapter = adapter;
+ adapter.addActivationLifecycleListeners(
+ new Runnable() { public void run() { activateAdapter(); } },
+ new Runnable() { public void run() { deactivateAdapter(); } });
+ poller = new ReachablePollHelper(adapter, objectName);
+ this.objectName = objectName;
+ }
+
+ static class ReachablePollHelper extends AbstractPollHelper {
+ JmxSensorAdapter adapter;
+ ObjectName objectName;
+ ReachablePollHelper(JmxSensorAdapter adapter, ObjectName objectName) {
+ super(adapter);
+ this.adapter = adapter;
+ this.objectName = objectName;
+ }
+ @Override
+ protected AbstractSensorEvaluationContext executePollOnSuccess() {
+ SingleValueResponseContext result = new SingleValueResponseContext();
+ try {
+ result.setValue(adapter.getHelper().findMBean(objectName) != null);
+ } catch (Exception e) {
+ if (LOG.isDebugEnabled()) LOG.debug("Error for "+getEntity()+" "+adapter.getHelper().getUrl()+
+ ", finding MBean "+objectName+"; assuming unreachable", e);
+ result.setValue(false);
+ }
+ return result;
+ }
+ }
+
+ public void poll(Closure listener) {
+ poller.addListener(listener);
+ }
+
+ public void poll(Function<Boolean, Void> listener) {
+ poller.addListener(GroovyJavaMethods.closureFromFunction(listener));
+ }
+
+ @Override
+ protected void activateAdapter() {
+ super.activateAdapter();
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/79ddd7e9/core/src/main/java/brooklyn/event/adapter/SensorRegistry.groovy
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/event/adapter/SensorRegistry.groovy b/core/src/main/java/brooklyn/event/adapter/SensorRegistry.groovy
index 5246ef3..c122afd 100644
--- a/core/src/main/java/brooklyn/event/adapter/SensorRegistry.groovy
+++ b/core/src/main/java/brooklyn/event/adapter/SensorRegistry.groovy
@@ -81,20 +81,20 @@ public class SensorRegistry {
boolean activated = false;
- private List<Closure> activationListeners = []
- private List<Closure> deactivationListeners = []
- void addActivationLifecycleListeners(Closure onUp, Closure onDown) {
+ private List<Runnable> activationListeners = []
+ private List<Runnable> deactivationListeners = []
+ void addActivationLifecycleListeners(Runnable onUp, Runnable onDown) {
activationListeners << onUp
deactivationListeners << onDown
}
public void activateAdapters() {
if (log.isDebugEnabled()) log.debug "activating adapters at sensor registry for {}", this, entity
activated = true;
- activationListeners.each { it.call() }
+ activationListeners.each { it.run() }
}
public void deactivateAdapters() {
if (log.isDebugEnabled()) log.debug "deactivating adapters at sensor registry for {}", this, entity
- deactivationListeners.each { it.call() }
+ deactivationListeners.each { it.run() }
}
public void close() {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/79ddd7e9/core/src/main/java/brooklyn/util/GroovyJavaMethods.groovy
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/util/GroovyJavaMethods.groovy b/core/src/main/java/brooklyn/util/GroovyJavaMethods.groovy
index 24cdb55..edbbd76 100644
--- a/core/src/main/java/brooklyn/util/GroovyJavaMethods.groovy
+++ b/core/src/main/java/brooklyn/util/GroovyJavaMethods.groovy
@@ -13,8 +13,8 @@ import com.google.common.base.Predicate
public class GroovyJavaMethods {
//TODO use named subclasses, would that be more efficient?
-
- // TODO xFromY nethods not in correct class: they are not "handy method available in groovy"?
+
+ // TODO xFromY methods not in correct class: they are not "handy method available in groovy"?
public static Closure closureFromRunnable(final Runnable job) {
return {
if (job in Callable) { return job.call() }
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/79ddd7e9/core/src/test/java/brooklyn/event/adapter/JmxSensorAdapterTest.groovy
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/event/adapter/JmxSensorAdapterTest.groovy b/core/src/test/java/brooklyn/event/adapter/JmxSensorAdapterTest.groovy
index b154822..99351d0 100644
--- a/core/src/test/java/brooklyn/event/adapter/JmxSensorAdapterTest.groovy
+++ b/core/src/test/java/brooklyn/event/adapter/JmxSensorAdapterTest.groovy
@@ -2,7 +2,6 @@ package brooklyn.event.adapter
import static org.testng.Assert.*
-import java.util.Map
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
@@ -60,11 +59,14 @@ public class JmxSensorAdapterTest {
private JmxHelper jmxHelper
private BasicAttributeSensor<Integer> intAttribute = [ Integer, "brooklyn.test.intAttribute", "Brooklyn testing int attribute" ]
+ private BasicAttributeSensor<Boolean> boolAttribute = [ Boolean, "brooklyn.test.boolAttribute", "Brooklyn testing bool attribute" ]
private BasicAttributeSensor<String> stringAttribute = [ String, "brooklyn.test.stringAttribute", "Brooklyn testing string attribute" ]
private BasicAttributeSensor<Map> mapAttribute = [ Map, "brooklyn.test.mapAttribute", "Brooklyn testing map attribute" ]
private String objectName = 'Brooklyn:type=MyTestMBean,name=myname'
+ private String wrongObjectName = 'Brooklyn:type=MyTestMBean,name=wrongname'
private ObjectName jmxObjectName = new ObjectName('Brooklyn:type=MyTestMBean,name=myname')
private String attributeName = 'myattrib'
+ private String wrongAttributeName = 'wrongattrib'
private String opName = 'myop'
@BeforeMethod(alwaysRun=true)
@@ -117,6 +119,57 @@ public class JmxSensorAdapterTest {
}
}
+ @Test
+ public void jmxPollerWillPollEvenIfOnlyConnectsAfterActivatingAdapters() {
+ jmxService.shutdown();
+
+ jmxAdapter.setJmxConnectionTimeout(0);
+ jmxAdapter.objectName(objectName).with {
+ attribute(attributeName).subscribe(intAttribute)
+ }
+ registry.activateAdapters()
+
+ jmxService = new JmxService(entity);
+ GeneralisedDynamicMBean mbean = jmxService.registerMBean(objectName, (attributeName): 42)
+
+ // Retrieves value after JMX Service becomes available
+ TestUtils.executeUntilSucceeds(timeout:TIMEOUT) {
+ assertEquals entity.getAttribute(intAttribute), 42
+ }
+ }
+
+ @Test(enabled=false)
+ public void jmxReachablePollerRespondsToConnectException() {
+ jmxService.shutdown();
+
+ boolean isup = true;
+
+ jmxAdapter.setJmxConnectionTimeout(10);
+ jmxAdapter.objectName(wrongObjectName).with {
+ reachable().poll( { isup = it } )
+ }
+ registry.activateAdapters()
+
+ TestUtils.executeUntilSucceeds(timeout:TIMEOUT) {
+ assertFalse(isup);
+ }
+ }
+
+ @Test
+ public void jmxReachablePollerRespondsToMBeanNotFound() {
+ GeneralisedDynamicMBean mbean = jmxService.registerMBean(objectName, (attributeName): 42)
+ boolean isup = true;
+
+ jmxAdapter.objectName(wrongObjectName).with {
+ reachable().poll( { isup = it } )
+ }
+ registry.activateAdapters()
+
+ TestUtils.executeUntilSucceeds(timeout:TIMEOUT) {
+ assertFalse(isup);
+ }
+ }
+
@Test(expectedExceptions=[IllegalStateException.class])
public void jmxCheckInstanceExistsEventuallyThrowsIfNotFound() {
jmxHelper.connect(TIMEOUT)