You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2017/09/19 15:07:30 UTC
[4/5] brooklyn-server git commit: Add/test VanillaSoftwareProcess ‘sshMonitoring.enabled’
Add/test VanillaSoftwareProcess ‘sshMonitoring.enabled’
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/509747f9
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/509747f9
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/509747f9
Branch: refs/heads/master
Commit: 509747f95fa10a319549b9e2065f86119c0324cc
Parents: d10282c
Author: Aled Sage <al...@gmail.com>
Authored: Fri Sep 15 09:29:28 2017 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Fri Sep 15 18:58:57 2017 +0100
----------------------------------------------------------------------
.../camp/brooklyn/AbstractYamlTest.java | 31 +-
.../VanillaSoftwareProcessYamlTest.java | 299 +++++++++++++++++++
.../entity/RecordingSensorEventListener.java | 12 +
.../util/core/internal/ssh/ExecCmdAsserts.java | 12 +-
.../software/base/VanillaSoftwareProcess.java | 6 +
.../base/VanillaSoftwareProcessImpl.java | 16 +-
6 files changed, 366 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/509747f9/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
index 6c269d2..3d4bbd2 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractYamlTest.java
@@ -27,6 +27,8 @@ import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
+import javax.annotation.Nullable;
+
import org.apache.brooklyn.api.catalog.BrooklynCatalog;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.entity.Entity;
@@ -58,6 +60,7 @@ import org.apache.brooklyn.util.exceptions.ReferenceWithError;
import org.apache.brooklyn.util.net.Urls;
import org.apache.brooklyn.util.osgi.VersionedName;
import org.apache.brooklyn.util.stream.Streams;
+import org.apache.brooklyn.util.time.Duration;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -138,10 +141,15 @@ public abstract class AbstractYamlTest {
}
protected void waitForApplicationTasks(Entity app) {
+ waitForApplicationTasks(app, null);
+ }
+
+ protected void waitForApplicationTasks(Entity app, @Nullable Duration timeout) {
Set<Task<?>> tasks = BrooklynTaskTags.getTasksInEntityContext(brooklynMgmt.getExecutionManager(), app);
getLogger().info("Waiting on " + tasks.size() + " task(s)");
for (Task<?> t : tasks) {
- t.blockUntilEnded();
+ boolean done = t.blockUntilEnded(timeout);
+ if (!done) throw new RuntimeException("Timeout waiting for task to complete: " + t);
}
}
@@ -174,10 +182,7 @@ public abstract class AbstractYamlTest {
return createAndStartApplication(input, MutableMap.<String,String>of());
}
protected Entity createAndStartApplication(String input, Map<String,?> startParameters) throws Exception {
- EntitySpec<?> spec =
- mgmt().getTypeRegistry().createSpecFromPlan(CampTypePlanTransformer.FORMAT, input, RegisteredTypeLoadingContexts.spec(Application.class), EntitySpec.class);
- final Entity app = brooklynMgmt.getEntityManager().createEntity(spec);
- // start the app (happens automatically if we use camp to instantiate, but not if we use crate spec approach)
+ final Entity app = createApplicationUnstarted(input);
app.invoke(Startable.START, startParameters).get();
return app;
}
@@ -191,12 +196,22 @@ public abstract class AbstractYamlTest {
}
protected Entity createAndStartApplicationAsync(String yaml, Map<String,?> startParameters) throws Exception {
+ final Entity app = createApplicationUnstarted(yaml);
+ // Not calling .get() on task, so this is non-blocking.
+ app.invoke(Startable.START, startParameters);
+ return app;
+ }
+
+ protected Entity createApplicationUnstarted(String... multiLineYaml) throws Exception {
+ return createApplicationUnstarted(joinLines(multiLineYaml));
+ }
+
+ protected Entity createApplicationUnstarted(String yaml) throws Exception {
+ // not starting the app (would have happened automatically if we use camp to instantiate,
+ // but not if we use create spec approach).
EntitySpec<?> spec =
mgmt().getTypeRegistry().createSpecFromPlan(CampTypePlanTransformer.FORMAT, yaml, RegisteredTypeLoadingContexts.spec(Application.class), EntitySpec.class);
final Entity app = brooklynMgmt.getEntityManager().createEntity(spec);
- // start the app (happens automatically if we use camp to instantiate, but not if we use create spec approach).
- // Note calling .get() on task, so this is non-blocking.
- app.invoke(Startable.START, startParameters);
return app;
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/509747f9/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/VanillaSoftwareProcessYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/VanillaSoftwareProcessYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/VanillaSoftwareProcessYamlTest.java
new file mode 100644
index 0000000..27c941a
--- /dev/null
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/VanillaSoftwareProcessYamlTest.java
@@ -0,0 +1,299 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.camp.brooklyn;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.api.sensor.AttributeSensor;
+import org.apache.brooklyn.api.sensor.Sensor;
+import org.apache.brooklyn.core.entity.Attributes;
+import org.apache.brooklyn.core.entity.Entities;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.entity.RecordingSensorEventListener;
+import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.core.sensor.function.FunctionSensor;
+import org.apache.brooklyn.enricher.stock.UpdatingMap;
+import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.core.internal.ssh.ExecCmdAsserts;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool.CustomResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+@Test
+public class VanillaSoftwareProcessYamlTest extends AbstractYamlTest {
+ private static final Logger log = LoggerFactory.getLogger(VanillaSoftwareProcessYamlTest.class);
+
+ public static class MyCallable implements Callable<Object> {
+ public static AtomicReference<Object> val = new AtomicReference<>();
+ public static AtomicReference<CountDownLatch> latch = new AtomicReference<>();
+
+ public static void clear() {
+ val.set(null);
+ latch.set(null);
+ }
+ @Override public Object call() throws Exception {
+ if (latch.get() != null) latch.get().await();
+ return val.get();
+ }
+ }
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ MyCallable.clear();
+ RecordingSshTool.clear();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ MyCallable.clear();
+ RecordingSshTool.clear();
+ }
+
+ @Test
+ public void testSshPolling() throws Exception {
+ Entity app = createAndStartApplication(
+ "location:",
+ " localhost:",
+ " sshToolClass: "+RecordingSshTool.class.getName(),
+ "services:",
+ "- type: "+VanillaSoftwareProcess.class.getName(),
+ " brooklyn.config:",
+ " softwareProcess.serviceProcessIsRunningPollPeriod: 10ms",
+ " checkRunning.command: myCheckRunning",
+ " launch.command: myLaunch");
+ waitForApplicationTasks(app);
+
+ log.info("App started:");
+ Entities.dumpInfo(app);
+
+ VanillaSoftwareProcess entity = (VanillaSoftwareProcess) Iterables.getOnlyElement(app.getChildren());
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, true);
+
+ RecordingSshTool.setCustomResponse(".*myCheckRunning.*", new CustomResponse(1, "simulating not running", ""));
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false);
+
+ RecordingSshTool.clear();
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, true);
+ }
+
+ @Test
+ public void testDisableSshPolling() throws Exception {
+ // driver.isRunning will report failure
+ RecordingSshTool.setCustomResponse(".*myCheckRunning.*", new CustomResponse(1, "simulating not running", ""));
+
+ Entity app = createApplicationUnstarted(
+ "location:",
+ " localhost:",
+ " sshToolClass: "+RecordingSshTool.class.getName(),
+ "services:",
+ "- type: "+VanillaSoftwareProcess.class.getName(),
+ " brooklyn.config:",
+ " softwareProcess.serviceProcessIsRunningPollPeriod: 10ms",
+ " sshMonitoring.enabled: false",
+ " checkRunning.command: myCheckRunning",
+ " launch.command: myLaunch");
+
+ VanillaSoftwareProcess entity = (VanillaSoftwareProcess) Iterables.getOnlyElement(app.getChildren());
+
+ RecordingSensorEventListener<Object> serviceUpListener = subscribe(entity, Attributes.SERVICE_UP);
+ RecordingSensorEventListener<Object> serviceStateListener = subscribe(entity, Attributes.SERVICE_STATE_ACTUAL);
+
+ Task<Void> task = app.invoke(Startable.START, ImmutableMap.of());
+
+ // Should eventually poll for 'checkRunning', before reporting 'up'
+ Asserts.succeedsEventually(new Runnable() {
+ public void run() {
+ ExecCmdAsserts.assertExecHasAtLeastOnce(RecordingSshTool.getExecCmds(), "myCheckRunning");
+ }});
+
+ assertFalse(task.isDone());
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false);
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STARTING);
+
+ // Let startup complete
+ RecordingSshTool.setCustomResponse(".*myCheckRunning.*", new CustomResponse(0, "", ""));
+ waitForApplicationTasks(app);
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, true);
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+
+ // Should never again do ssh-poll of checkRunning
+ RecordingSshTool.clear();
+ Asserts.succeedsContinually(new Runnable() {
+ public void run() {
+ ExecCmdAsserts.assertExecHasNever(RecordingSshTool.getExecCmds(), "myCheckRunning");
+ }});
+
+ // Should not have transitioned through wrong states (e.g. never "on-fire"!)
+ assertEventsEqualEventually(serviceUpListener, ImmutableList.of(false, true), true);
+ assertEventsEqualEventually(serviceStateListener, ImmutableList.of(Lifecycle.CREATED, Lifecycle.STARTING, Lifecycle.RUNNING), true);
+ }
+
+ @Test
+ public void testAlternativeServiceUpPolling() throws Exception {
+ AttributeSensor<Boolean> alternativeUpIndicator = Sensors.newBooleanSensor("myAlternativeUpIndicator");
+ MyCallable.latch.set(new CountDownLatch(1));
+
+ Entity app = createApplicationUnstarted(
+ "location:",
+ " localhost:",
+ " sshToolClass: "+RecordingSshTool.class.getName(),
+ "services:",
+ "- type: "+VanillaSoftwareProcess.class.getName(),
+ " brooklyn.config:",
+ " softwareProcess.serviceProcessIsRunningPollPeriod: 10ms",
+ " sshMonitoring.enabled: false",
+ " checkRunning.command: myCheckRunning",
+ " launch.command: myLaunch",
+ " brooklyn.initializers:",
+ " - type: "+FunctionSensor.class.getName(),
+ " brooklyn.config:",
+ " "+FunctionSensor.SENSOR_PERIOD.getName()+": 10ms",
+ " "+FunctionSensor.SENSOR_NAME.getName()+": " + alternativeUpIndicator.getName(),
+ " "+FunctionSensor.SENSOR_TYPE.getName()+": boolean",
+ " "+FunctionSensor.FUNCTION.getName()+":",
+ " $brooklyn:object:",
+ " type: "+MyCallable.class.getName(),
+ " brooklyn.enrichers:",
+ " - type: " + UpdatingMap.class.getName(),
+ " brooklyn.config:",
+ " enricher.sourceSensor: $brooklyn:sensor(\"" + alternativeUpIndicator.getName() + "\")",
+ " enricher.targetSensor: $brooklyn:sensor(\"service.notUp.indicators\")",
+ " enricher.updatingMap.computing:",
+ " $brooklyn:object:",
+ " type: \"" + Functions.class.getName() + "\"",
+ " factoryMethod.name: \"forMap\"",
+ " factoryMethod.args:",
+ " - false: \"false\"",
+ " true: null",
+ " - \"no value\"");
+
+ VanillaSoftwareProcess entity = (VanillaSoftwareProcess) Iterables.getOnlyElement(app.getChildren());
+
+ RecordingSensorEventListener<Object> serviceUpListener = subscribe(entity, Attributes.SERVICE_UP);
+ RecordingSensorEventListener<Object> serviceStateListener = subscribe(entity, Attributes.SERVICE_STATE_ACTUAL);
+
+ Task<Void> task = app.invoke(Startable.START, ImmutableMap.of());
+
+ // Should eventually poll for 'checkRunning', but just once immediately after doing launch etc
+ Asserts.succeedsEventually(new Runnable() {
+ public void run() {
+ ExecCmdAsserts.assertExecHasOnlyOnce(RecordingSshTool.getExecCmds(), "myCheckRunning");
+ }});
+ RecordingSshTool.clear();
+
+ assertFalse(task.isDone());
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_NOT_UP_INDICATORS, ImmutableMap.of(alternativeUpIndicator.getName(), "no value"));
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false);
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.STARTING);
+
+ // Let the function return 'false'
+ MyCallable.val.set(false);
+ MyCallable.latch.get().countDown();
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_NOT_UP_INDICATORS, ImmutableMap.of(alternativeUpIndicator.getName(), "false"));
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, false);
+ assertFalse(task.isDone());
+
+ // Let startup complete, by the function returning 'true'
+ MyCallable.val.set(true);
+ waitForApplicationTasks(app, Asserts.DEFAULT_LONG_TIMEOUT);
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_UP, true);
+ EntityAsserts.assertAttributeEqualsEventually(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+
+ // Should not have transitioned through wrong states (e.g. never "on-fire"!)
+ assertEventsEqualEventually(serviceUpListener, ImmutableList.of(false, true), true);
+ assertEventsEqualEventually(serviceStateListener, ImmutableList.of(Lifecycle.CREATED, Lifecycle.STARTING, Lifecycle.RUNNING), true);
+
+ ExecCmdAsserts.assertExecHasNever(RecordingSshTool.getExecCmds(), "myCheckRunning");
+ }
+
+ private RecordingSensorEventListener<Object> subscribe(Entity entity, Sensor<?> sensor) {
+ RecordingSensorEventListener<Object> listener = new RecordingSensorEventListener<>();
+ mgmt().getSubscriptionManager().subscribe(MutableMap.of("notifyOfInitialValue", true), entity, sensor, listener);
+ return listener;
+ }
+
+ private void assertEventsEqualEventually(RecordingSensorEventListener<?> listener, Iterable<?> expected, boolean stripLeadingNulls) {
+ Asserts.succeedsEventually(new Runnable() {
+ public void run() {
+ assertIterablesEqual(listener.getEventValues(), (stripLeadingNulls ? leadingNullsStripper() : Functions.identity()), expected);
+ }});
+ }
+
+ private void assertIterablesEqualEventually(Supplier<? extends Iterable<?>> actual, Function<? super List<?>, List<?>> transformer, Iterable<?> expected) {
+ Asserts.succeedsEventually(new Runnable() {
+ public void run() {
+ assertIterablesEqual(actual.get(), transformer, expected);
+ }});
+ }
+
+ private void assertIterablesEqual(Iterable<?> actual, Function<? super List<?>, List<?>> transformer, Iterable<?> expected) {
+ List<?> actualList = (actual instanceof List) ? (List<?>) actual : MutableList.copyOf(actual);
+ List<?> expectedList = (expected instanceof List) ? (List<?>) expected : MutableList.copyOf(expected);
+ String errMsg = "actual="+actualList+"; expected="+expectedList;
+ assertEquals(transformer.apply(actualList), expectedList, errMsg);
+ }
+
+ private Function<List<?>, List<?>> leadingNullsStripper() {
+ return new Function<List<?>, List<?>>() {
+ @Override public List<?> apply(List<?> input) {
+ if (input == null || input.isEmpty() || input.get(0) != null) {
+ return input;
+ }
+ List<Object> result = new ArrayList<>();
+ boolean foundNonNull = false;
+ for (Object element : input) {
+ if (foundNonNull || input != null) {
+ result.add(element);
+ foundNonNull = true;
+ }
+ }
+ return result;
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/509747f9/core/src/test/java/org/apache/brooklyn/core/entity/RecordingSensorEventListener.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/RecordingSensorEventListener.java b/core/src/test/java/org/apache/brooklyn/core/entity/RecordingSensorEventListener.java
index 30d40a2..2c00382 100644
--- a/core/src/test/java/org/apache/brooklyn/core/entity/RecordingSensorEventListener.java
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/RecordingSensorEventListener.java
@@ -35,6 +35,7 @@ import org.testng.Assert;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@@ -92,6 +93,17 @@ public class RecordingSensorEventListener<T> implements SensorEventListener<T>,
}
/**
+ * @return A supplier that returns the latest live read-only view of recorded events.
+ */
+ public Supplier<Iterable<T>> getEventValuesSupplier() {
+ return new Supplier<Iterable<T>>() {
+ @Override public Iterable<T> get() {
+ return getEventValues();
+ }
+ };
+ }
+
+ /**
* @return A static read-only view of event values sorted by the time at which they occurred.
*/
public Iterable<T> getEventValuesSortedByTimestamp() {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/509747f9/core/src/test/java/org/apache/brooklyn/util/core/internal/ssh/ExecCmdAsserts.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/internal/ssh/ExecCmdAsserts.java b/core/src/test/java/org/apache/brooklyn/util/core/internal/ssh/ExecCmdAsserts.java
index 8aab3b0..db2a191 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/internal/ssh/ExecCmdAsserts.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/internal/ssh/ExecCmdAsserts.java
@@ -23,8 +23,10 @@ import java.util.List;
import com.google.common.annotations.Beta;
import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool.ExecCmd;
+import org.apache.brooklyn.util.math.MathPredicates;
@Beta
public class ExecCmdAsserts {
@@ -92,7 +94,15 @@ public class ExecCmdAsserts {
assertExecHasExactly(actuals, expectedCmd, 1);
}
+ public static void assertExecHasAtLeastOnce(List<ExecCmd> actuals, String expectedCmd) {
+ assertExecHasExactly(actuals, expectedCmd, MathPredicates.greaterThanOrEqual(1));
+ }
+
public static void assertExecHasExactly(List<ExecCmd> actuals, String expectedCmd, int expectedCount) {
+ assertExecHasExactly(actuals, expectedCmd, Predicates.equalTo(expectedCount));
+ }
+
+ public static void assertExecHasExactly(List<ExecCmd> actuals, String expectedCmd, Predicate<Integer> countChecker) {
String errMsg = "actuals="+actuals+"; expected="+expectedCmd;
int count = 0;
for (ExecCmd actual : actuals) {
@@ -103,7 +113,7 @@ public class ExecCmdAsserts {
}
}
}
- assertEquals(count, expectedCount, errMsg);
+ assertTrue(countChecker.apply(count), "actualCount="+count+"; expectedCount="+countChecker+"; "+errMsg);
}
public static ExecCmd findExecContaining(List<ExecCmd> actuals, String cmdRegex) {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/509747f9/software/base/src/main/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcess.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcess.java b/software/base/src/main/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcess.java
index a979064..1e41c98 100644
--- a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcess.java
+++ b/software/base/src/main/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcess.java
@@ -20,6 +20,8 @@ package org.apache.brooklyn.entity.software.base;
import org.apache.brooklyn.api.catalog.Catalog;
import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
/**
* A {@link SoftwareProcess} entity that runs commands from an archive.
@@ -56,4 +58,8 @@ import org.apache.brooklyn.api.entity.ImplementedBy;
@Catalog(name="Vanilla Software Process", description="A software process configured with scripts, e.g. for launch, check-running and stop")
@ImplementedBy(VanillaSoftwareProcessImpl.class)
public interface VanillaSoftwareProcess extends AbstractVanillaProcess {
+ ConfigKey<Boolean> USE_SSH_MONITORING = ConfigKeys.newConfigKey(
+ "sshMonitoring.enabled",
+ "SSH monitoring enabled",
+ Boolean.TRUE);
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/509747f9/software/base/src/main/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcessImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcessImpl.java b/software/base/src/main/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcessImpl.java
index 6f1aec0..5fa7b66 100644
--- a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcessImpl.java
+++ b/software/base/src/main/java/org/apache/brooklyn/entity/software/base/VanillaSoftwareProcessImpl.java
@@ -18,20 +18,34 @@
*/
package org.apache.brooklyn.entity.software.base;
+import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic.ServiceNotUpLogic;
public class VanillaSoftwareProcessImpl extends SoftwareProcessImpl implements VanillaSoftwareProcess {
+
@Override
public Class<?> getDriverInterface() {
return VanillaSoftwareProcessDriver.class;
}
+
@Override
protected void connectSensors() {
super.connectSensors();
- connectServiceUpIsRunning();
+ if (isSshMonitoringEnabled()) {
+ connectServiceUpIsRunning();
+ } else {
+ // See SoftwareProcessImpl.waitForEntityStart(). We will already have waited for driver.isRunning.
+ // We will not poll for that again.
+ ServiceNotUpLogic.clearNotUpIndicator(this, SERVICE_PROCESS_IS_RUNNING);
+ }
}
+
@Override
protected void disconnectSensors() {
disconnectServiceUpIsRunning();
super.disconnectSensors();
}
+
+ protected boolean isSshMonitoringEnabled() {
+ return Boolean.TRUE.equals(getConfig(USE_SSH_MONITORING));
+ }
}
\ No newline at end of file