SLIDER-202 Monkey implemented but not conditional/integrated

Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/b111268a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/b111268a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/b111268a

Branch: refs/heads/develop
Commit: b111268af07a75797c9f56b3ab96c0dd052a62a8
Parents: c951e25
Author: Steve Loughran <ste...@apache.org>
Authored: Wed Aug 13 12:00:27 2014 +0100
Committer: Steve Loughran <ste...@apache.org>
Committed: Wed Aug 13 12:00:27 2014 +0100

----------------------------------------------------------------------
 .../server/appmaster/SliderAppMaster.java       | 52 +++++++++++----
 .../server/appmaster/actions/ActionHalt.java    |  4 +-
 .../appmaster/actions/ActionKillContainer.java  | 51 +++++++++++++++
 .../server/appmaster/monkey/ChaosEntry.java     | 53 ++++++++++++++-
 .../server/appmaster/monkey/ChaosKillAM.java    | 48 ++++++++++++++
 .../appmaster/monkey/ChaosKillContainer.java    | 68 ++++++++++++++++++++
 .../appmaster/monkey/ChaosMonkeyService.java    | 41 ++++++++----
 .../appmaster/monkey/MonkeyPlayAction.java      | 48 ++++++++++++++
 .../slider/server/appmaster/state/AppState.java | 14 +++-
 .../standalone/TestStandaloneAgentAM.groovy     |  2 +-
 10 files changed, 346 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b111268a/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
index 1135a58..ee0e59e 100644
--- 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
+++ 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java
@@ -97,6 +97,7 @@ import org.apache.slider.providers.ProviderService;
 import org.apache.slider.providers.SliderProviderFactory;
 import org.apache.slider.providers.slideram.SliderAMClientProvider;
 import org.apache.slider.providers.slideram.SliderAMProviderService;
+import org.apache.slider.server.appmaster.actions.ActionKillContainer;
 import org.apache.slider.server.appmaster.actions.QueueExecutor;
 import org.apache.slider.server.appmaster.actions.ActionHalt;
 import org.apache.slider.server.appmaster.actions.QueueService;
@@ -104,6 +105,9 @@ import 
org.apache.slider.server.appmaster.actions.ActionStopSlider;
 import org.apache.slider.server.appmaster.actions.AsyncAction;
 import org.apache.slider.server.appmaster.actions.RenewingAction;
 import org.apache.slider.server.appmaster.actions.ResetFailureWindow;
+import org.apache.slider.server.appmaster.monkey.ChaosKillAM;
+import org.apache.slider.server.appmaster.monkey.ChaosKillContainer;
+import org.apache.slider.server.appmaster.monkey.ChaosMonkeyService;
 import org.apache.slider.server.appmaster.operations.AsyncRMOperationHandler;
 import 
org.apache.slider.server.appmaster.operations.ProviderNotifyingOperationHandler;
 import org.apache.slider.server.appmaster.rpc.RpcBinder;
@@ -112,7 +116,6 @@ import 
org.apache.slider.server.appmaster.rpc.SliderClusterProtocolPBImpl;
 import org.apache.slider.server.appmaster.operations.AbstractRMOperation;
 import org.apache.slider.server.appmaster.state.AppState;
 import org.apache.slider.server.appmaster.state.ContainerAssignment;
-import org.apache.slider.server.appmaster.operations.ContainerReleaseOperation;
 import org.apache.slider.server.appmaster.state.ProviderAppState;
 import org.apache.slider.server.appmaster.operations.RMOperationHandler;
 import org.apache.slider.server.appmaster.state.RoleInstance;
@@ -147,7 +150,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutorService;
@@ -301,6 +303,11 @@ public class SliderAppMaster extends 
AbstractSliderLaunchedService
   private ContainerId appMasterContainerID;
 
   /**
+   * Monkey Service -may be null
+   */
+  private ChaosMonkeyService monkey;
+  
+  /**
    * ProviderService of this cluster
    */
   @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
@@ -780,6 +787,8 @@ public class SliderAppMaster extends 
AbstractSliderLaunchedService
     // starts the node review process
     launchProviderService(instanceDefinition, confDir);
 
+    // chaos monkey
+    maybeStartMonkey();
 
     try {
       //now block waiting to be told to exit the process
@@ -1103,7 +1112,7 @@ public class SliderAppMaster extends 
AbstractSliderLaunchedService
     }
     
     //for all the operations, exec them
-    rmOperationHandler.execute(operations);
+    executeRMOperations(operations);
     log.info("Diagnostics: " + getContainerDiagnosticInfo());
   }
 
@@ -1221,7 +1230,7 @@ public class SliderAppMaster extends 
AbstractSliderLaunchedService
       // tell the provider
       providerRMOperationHandler.execute(allOperations);
       //now apply the operations
-      rmOperationHandler.execute(allOperations);
+      executeRMOperations(allOperations);
       return !allOperations.isEmpty();
     } catch (TriggerClusterTeardownException e) {
 
@@ -1237,7 +1246,7 @@ public class SliderAppMaster extends 
AbstractSliderLaunchedService
    */
   private void releaseAllContainers() {
     //now apply the operations
-    rmOperationHandler.execute(appState.releaseAllContainers());
+    executeRMOperations(appState.releaseAllContainers());
   }
 
   /**
@@ -1441,19 +1450,17 @@ public class SliderAppMaster extends 
AbstractSliderLaunchedService
     //throws NoSuchNodeException if it is missing
     RoleInstance instance =
       appState.getLiveInstanceByContainerID(containerID);
-    List<AbstractRMOperation> opsList =
-      new LinkedList<>();
-    ContainerReleaseOperation release =
-      new ContainerReleaseOperation(instance.getId());
-    opsList.add(release);
-    //now apply the operations
-    rmOperationHandler.execute(opsList);
+    queue(new ActionKillContainer(instance.getId(), 0, TimeUnit.MILLISECONDS));
     Messages.KillContainerResponseProto.Builder builder =
       Messages.KillContainerResponseProto.newBuilder();
     builder.setSuccess(true);
     return builder.build();
   }
 
+  public void executeRMOperations(List<AbstractRMOperation> operations) {
+    rmOperationHandler.execute(operations);
+  }
+
   @Override
   public Messages.AMSuicideResponseProto amSuicide(
       Messages.AMSuicideRequestProto request)
@@ -1462,7 +1469,8 @@ public class SliderAppMaster extends 
AbstractSliderLaunchedService
     String text = request.getText();
     int delay = request.getDelay();
     log.info("AM Suicide with signal {}, message {} delay = {}", signal, text, 
delay);
-    ActionHalt action = new ActionHalt(signal, text, delay);
+    ActionHalt action = new ActionHalt(signal, text, delay,
+        TimeUnit.MILLISECONDS);
     schedule(action);
     return Messages.AMSuicideResponseProto.getDefaultInstance();
   }
@@ -1537,7 +1545,7 @@ public class SliderAppMaster extends 
AbstractSliderLaunchedService
         containerId);
     RoleInstance activeContainer = appState.getActiveContainer(containerId);
     if (activeContainer != null) {
-      rmOperationHandler.execute(appState.releaseContainer(containerId));
+      executeRMOperations(appState.releaseContainer(containerId));
       // ask for more containers if needed
       log.info("Container released; triggering review");
       reviewRequestAndReleaseNodes();
@@ -1725,6 +1733,22 @@ public class SliderAppMaster extends 
AbstractSliderLaunchedService
     signalAMComplete(exitCode, exception.toString());
   }
   
+  public boolean maybeStartMonkey() {
+    monkey = new ChaosMonkeyService(metrics, actionQueues);
+    int amKillProbability = 100;
+    int containerKillProbability = 200;
+    monkey.addTarget("AM killer", 
+        new ChaosKillAM(this, actionQueues, -1),
+        amKillProbability);
+    monkey.addTarget("Container killer", 
+        new ChaosKillContainer(this, actionQueues),
+        amKillProbability);
+    initAndAddService(monkey);
+    // and schedule it
+    schedule(monkey.getChaosAction(60, TimeUnit.SECONDS));
+    return true;
+  }
+  
   /**
    * This is the main entry point for the service launcher.
    * @param args command line arguments.

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b111268a/slider-core/src/main/java/org/apache/slider/server/appmaster/actions/ActionHalt.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/actions/ActionHalt.java
 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/actions/ActionHalt.java
index b46a791..c21e249 100644
--- 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/actions/ActionHalt.java
+++ 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/actions/ActionHalt.java
@@ -22,6 +22,8 @@ import org.apache.hadoop.util.ExitUtil;
 import org.apache.slider.server.appmaster.SliderAppMaster;
 import org.apache.slider.server.appmaster.state.AppState;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * Exit a JVM halt.
  * @see ExitUtil#halt(int, String) 
@@ -34,7 +36,7 @@ public class ActionHalt extends AsyncAction {
   public ActionHalt(
       int status,
       String text,
-      long delay) {
+      long delay, TimeUnit timeUnit) {
     super("Halt", delay, ActionAttributes.HALTS_CLUSTER);
     this.status = status;
     this.text = text;

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b111268a/slider-core/src/main/java/org/apache/slider/server/appmaster/actions/ActionKillContainer.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/actions/ActionKillContainer.java
 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/actions/ActionKillContainer.java
new file mode 100644
index 0000000..7668bd5
--- /dev/null
+++ 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/actions/ActionKillContainer.java
@@ -0,0 +1,51 @@
+/*
+ * 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.slider.server.appmaster.actions;
+
+import org.apache.hadoop.yarn.api.records.ContainerId;
+import org.apache.slider.server.appmaster.SliderAppMaster;
+import org.apache.slider.server.appmaster.operations.AbstractRMOperation;
+import org.apache.slider.server.appmaster.operations.ContainerReleaseOperation;
+import org.apache.slider.server.appmaster.state.AppState;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+public class ActionKillContainer extends AsyncAction {
+
+  private final ContainerId containerId;
+  
+  public ActionKillContainer(ContainerId containerId, long delay,
+      TimeUnit timeUnit) {
+    super("kill container", delay, timeUnit);
+    this.containerId = containerId;
+  }
+
+  @Override
+  public void execute(SliderAppMaster appMaster,
+      QueueAccess queueService,
+      AppState appState) throws Exception {
+    List<AbstractRMOperation> opsList = new LinkedList<>();
+    ContainerReleaseOperation release = new 
ContainerReleaseOperation(containerId);
+    opsList.add(release);
+    //now apply the operations
+    appMaster.executeRMOperations(opsList);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b111268a/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosEntry.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosEntry.java
 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosEntry.java
index 779cca1..13bda57 100644
--- 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosEntry.java
+++ 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosEntry.java
@@ -18,18 +18,67 @@
 
 package org.apache.slider.server.appmaster.monkey;
 
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.MetricRegistry;
+import com.google.common.base.Preconditions;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 /**
  * Entry in the chaos list
  */
 public class ChaosEntry {
-  
+
+  protected static final Logger log =
+      LoggerFactory.getLogger(ChaosEntry.class);
   public final String name;
   public final ChaosTarget target;
   public final long probability;
 
-  public ChaosEntry(String name, ChaosTarget target, long probability) {
+  private final MetricRegistry metrics;
+  private final Counter invocationCounter;
+
+
+  /**
+   * Constructor -includes validaton of all arguments
+   * @param name
+   * @param target
+   * @param probability
+   */
+  public ChaosEntry(String name, ChaosTarget target, long probability,
+      MetricRegistry metrics) {
+    Preconditions.checkArgument(!StringUtils.isEmpty(name), "missing name");
+    Preconditions.checkArgument(target != null, "null target");
+    Preconditions.checkArgument(probability > 0, "negative probability");
+    Preconditions.checkArgument(probability < 10000, "probability over 100%");
     this.name = name;
     this.target = target;
     this.probability = probability;
+    this.metrics = metrics;
+    invocationCounter =
+        metrics.counter(MetricRegistry.name(ChaosEntry.class, name));
+  }
+
+  /**
+   * Trigger the chaos action
+   */
+  public void invokeChaos() {
+    log.info("Invoking {}", name);
+    invocationCounter.inc();
+    target.chaosAction();
+  }
+
+  /**
+   * Invoke Chaos if the trigger value is in range of the probability
+   * @param trigger trigger value, 0-10K
+   * @return true if the chaos method was invoked
+   */
+  public boolean maybeInvokeChaos(long trigger) {
+    if (probability < 0) {
+      invokeChaos();
+      return true;
+    }
+    return false;
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b111268a/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosKillAM.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosKillAM.java
 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosKillAM.java
new file mode 100644
index 0000000..c464ac3
--- /dev/null
+++ 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosKillAM.java
@@ -0,0 +1,48 @@
+/*
+ * 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.slider.server.appmaster.monkey;
+
+import org.apache.slider.server.appmaster.SliderAppMaster;
+import org.apache.slider.server.appmaster.actions.ActionHalt;
+import org.apache.slider.server.appmaster.actions.QueueAccess;
+
+import java.util.concurrent.TimeUnit;
+
+public class ChaosKillAM implements ChaosTarget {
+
+  private final SliderAppMaster appMaster;
+  private final QueueAccess queues;
+  private final int exitCode;
+
+  public ChaosKillAM(SliderAppMaster appMaster,
+      QueueAccess queues, int exitCode) {
+    this.appMaster = appMaster;
+    this.queues = queues;
+    this.exitCode = exitCode;
+  }
+
+  /**
+   * Trigger a delayed halt
+   */
+  @Override
+  public void chaosAction() {
+    queues.schedule(new ActionHalt(exitCode, "Chaos invoked halt", 1000,
+        TimeUnit.MILLISECONDS));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b111268a/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosKillContainer.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosKillContainer.java
 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosKillContainer.java
new file mode 100644
index 0000000..0ffcc8a
--- /dev/null
+++ 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosKillContainer.java
@@ -0,0 +1,68 @@
+/*
+ * 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.slider.server.appmaster.monkey;
+
+import org.apache.slider.server.appmaster.SliderAppMaster;
+import org.apache.slider.server.appmaster.actions.ActionKillContainer;
+import org.apache.slider.server.appmaster.actions.QueueAccess;
+import org.apache.slider.server.appmaster.state.RoleInstance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Kill a container
+ */
+public class ChaosKillContainer implements ChaosTarget {
+  protected static final Logger log =
+      LoggerFactory.getLogger(ChaosKillContainer.class);
+  private final SliderAppMaster appMaster;
+  private final QueueAccess queues;
+  private final Random random = new Random();
+
+  public ChaosKillContainer(SliderAppMaster appMaster,
+      QueueAccess queues) {
+    this.appMaster = appMaster;
+    this.queues = queues;
+  }
+
+  /**
+   * Trigger a container kill halt
+   */
+  
+  @Override
+  public void chaosAction() {
+    List<RoleInstance> liveContainers =
+        appMaster.getAppState().cloneLiveContainerInfoList();
+    int size = liveContainers.size();
+    if (size == 0) {
+      log.info("No containers to kill");
+      return;
+    }
+    int target = random.nextInt(size);
+    RoleInstance roleInstance = liveContainers.get(target);
+    log.info("Killing {}", roleInstance);
+
+    queues.schedule(new ActionKillContainer(roleInstance.getId(),
+        100, TimeUnit.MILLISECONDS));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b111268a/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosMonkeyService.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosMonkeyService.java
 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosMonkeyService.java
index 7c5638c..c525d02 100644
--- 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosMonkeyService.java
+++ 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/ChaosMonkeyService.java
@@ -19,15 +19,20 @@
 package org.apache.slider.server.appmaster.monkey;
 
 import com.codahale.metrics.MetricRegistry;
-import com.google.common.base.Preconditions;
 import org.apache.hadoop.service.AbstractService;
+import org.apache.slider.server.appmaster.actions.AsyncAction;
 import org.apache.slider.server.appmaster.actions.QueueAccess;
+import org.apache.slider.server.appmaster.actions.RenewingAction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
+/**
+ * A chaos monkey service which will invoke ChaosTarget events 
+ */
 public class ChaosMonkeyService extends AbstractService {
   protected static final Logger log =
       LoggerFactory.getLogger(ChaosMonkeyService.class);
@@ -36,25 +41,33 @@ public class ChaosMonkeyService extends AbstractService {
 
   private static final List<ChaosEntry> chaosEntries =
       new ArrayList<ChaosEntry>();
-      
+
   public ChaosMonkeyService(MetricRegistry metrics, QueueAccess queues) {
     super("ChaosMonkeyService");
     this.metrics = metrics;
     this.queues = queues;
   }
 
-  
-  @Override
-  protected void serviceStart() throws Exception {
-    super.serviceStart();
-    
+
+  public synchronized void addTarget(String name,
+      ChaosTarget target,
+      long probability) {
+
+    chaosEntries.add(new ChaosEntry(name, target, probability, metrics));
+  }
+
+  public void play() {
+
   }
-  
-  
-  public synchronized void addTarget(ChaosTarget target,  long probability) {
-    Preconditions.checkArgument(target != null, "null target");
-    Preconditions.checkArgument(probability > 0, "negative probability");
-    Preconditions.checkArgument(probability > 10000, "probability over 100%");
+
+  public RenewingAction<MonkeyPlayAction> getChaosAction(long time, TimeUnit 
timeUnit) {
+    RenewingAction<MonkeyPlayAction> action = new RenewingAction<>(
+        new MonkeyPlayAction(this, 0, TimeUnit.MILLISECONDS),
+        time,
+        time,
+        timeUnit,
+        0
+    );
+    return action;
   }
-  
 }

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b111268a/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/MonkeyPlayAction.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/MonkeyPlayAction.java
 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/MonkeyPlayAction.java
new file mode 100644
index 0000000..20e4466
--- /dev/null
+++ 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/monkey/MonkeyPlayAction.java
@@ -0,0 +1,48 @@
+/*
+ * 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.slider.server.appmaster.monkey;
+
+import org.apache.slider.server.appmaster.SliderAppMaster;
+import org.apache.slider.server.appmaster.actions.AsyncAction;
+import org.apache.slider.server.appmaster.actions.QueueAccess;
+import org.apache.slider.server.appmaster.state.AppState;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Queueable action which calls {@link ChaosMonkeyService#play()} when
+ * executed.
+ */
+public class MonkeyPlayAction extends AsyncAction {
+
+  private final ChaosMonkeyService monkey;
+
+  public MonkeyPlayAction(ChaosMonkeyService monkey, long delay,
+      TimeUnit timeUnit) {
+    super("chaos monkey", delay, timeUnit);
+    this.monkey = monkey;
+  }
+
+  @Override
+  public void execute(SliderAppMaster appMaster,
+      QueueAccess queueService,
+      AppState appState) throws Exception {
+    monkey.play();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b111268a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
----------------------------------------------------------------------
diff --git 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
index 48f97bb..d616678 100644
--- 
a/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
+++ 
b/slider-core/src/main/java/org/apache/slider/server/appmaster/state/AppState.java
@@ -101,7 +101,7 @@ public class AppState {
    * Flag set to indicate the application is live -this only happens
    * after the buildInstance operation
    */
-  boolean applicationLive = false;
+  private boolean applicationLive = false;
 
   /**
    * The definition of the instance. Flexing updates the resources section
@@ -811,6 +811,10 @@ public class AppState {
     return activeContainers.remove(id);
   }
 
+  /**
+   * Clone the live container list. This is synchronized.
+   * @return a snapshot of the live node list
+   */
   public synchronized List<RoleInstance> cloneLiveContainerInfoList() {
     List<RoleInstance> allRoleInstances;
     Collection<RoleInstance> values = getLiveNodes().values();
@@ -818,8 +822,12 @@ public class AppState {
     return allRoleInstances;
   }
 
-
-
+  /**
+   * Lookup live instance by string value of container ID
+   * @param containerId container ID
+   * @return the role instance for that container
+   * @throws NoSuchNodeException if it does not exist
+   */
   public synchronized RoleInstance getLiveInstanceByContainerID(String 
containerId)
     throws NoSuchNodeException {
     Collection<RoleInstance> nodes = getLiveNodes().values();

http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/b111268a/slider-core/src/test/groovy/org/apache/slider/agent/standalone/TestStandaloneAgentAM.groovy
----------------------------------------------------------------------
diff --git 
a/slider-core/src/test/groovy/org/apache/slider/agent/standalone/TestStandaloneAgentAM.groovy
 
b/slider-core/src/test/groovy/org/apache/slider/agent/standalone/TestStandaloneAgentAM.groovy
index 8498ee2..73e9b07 100644
--- 
a/slider-core/src/test/groovy/org/apache/slider/agent/standalone/TestStandaloneAgentAM.groovy
+++ 
b/slider-core/src/test/groovy/org/apache/slider/agent/standalone/TestStandaloneAgentAM.groovy
@@ -37,10 +37,10 @@ import org.junit.Test
 @CompileStatic
 @Slf4j
 class TestStandaloneAgentAM  extends AgentMiniClusterTestBase {
+  
   @Test
   public void testStandaloneAgentAM() throws Throwable {
 
-
     describe "create a masterless AM then get the service and look it up via 
the AM"
 
     //launch fake master

Reply via email to