You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by sj...@apache.org on 2015/07/30 22:00:24 UTC

[07/11] incubator-brooklyn git commit: MachineLifecycleEffectorTasks can suspend as well as stop machines.

MachineLifecycleEffectorTasks can suspend as well as stop machines.

Leaves it to subclasses to attach the effector to entities.


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

Branch: refs/heads/master
Commit: f012c9c7e879248b08bee6912d2698ff97e2ed9d
Parents: 415d083
Author: Sam Corbett <sa...@cloudsoftcorp.com>
Authored: Tue Jul 21 16:56:13 2015 +0100
Committer: Sam Corbett <sa...@cloudsoftcorp.com>
Committed: Wed Jul 29 17:00:19 2015 +0100

----------------------------------------------------------------------
 .../software/MachineLifecycleEffectorTasks.java | 127 ++++++++++++++++---
 1 file changed, 108 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f012c9c7/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
index ec3ae1c..920e5b9 100644
--- a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
@@ -63,6 +63,7 @@ import brooklyn.entity.trait.StartableMethods;
 import brooklyn.event.feed.ConfigToAttributes;
 import brooklyn.location.Location;
 import brooklyn.location.MachineLocation;
+import brooklyn.location.MachineManagementMixins.SuspendsMachines;
 import brooklyn.location.MachineProvisioningLocation;
 import brooklyn.location.NoMachinesAvailableException;
 import brooklyn.location.basic.AbstractLocation;
@@ -72,7 +73,6 @@ import brooklyn.location.basic.Machines;
 import brooklyn.location.basic.SshMachineLocation;
 import brooklyn.location.cloud.CloudLocationConfig;
 import brooklyn.management.Task;
-import brooklyn.management.TaskFactory;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.config.ConfigBag;
 import brooklyn.util.exceptions.Exceptions;
@@ -155,8 +155,18 @@ public abstract class MachineLifecycleEffectorTasks {
                 .build();
     }
 
+    /** @see {@link #newStartEffector()} */
+    public Effector<Void> newSuspendEffector() {
+        return Effectors.effector(Void.class, "suspend")
+                .description("Suspend the process/service represented by an entity")
+                .parameter(StopSoftwareParameters.STOP_PROCESS_MODE)
+                .parameter(StopSoftwareParameters.STOP_MACHINE_MODE)
+                .impl(newSuspendEffectorTask())
+                .build();
+    }
+
     /**
-     * Returns the {@link TaskFactory} which supplies the implementation for the start effector.
+     * Returns the {@link EffectorBody} which supplies the implementation for the start effector.
      * <p>
      * Calls {@link #start(Collection)} in this class.
      */
@@ -196,7 +206,7 @@ public abstract class MachineLifecycleEffectorTasks {
     }
 
     /**
-     * Calls {@link #stop()}.
+     * Calls {@link #stop(ConfigBag)}.
      *
      * @see {@link #newStartEffectorTask()}
      */
@@ -210,6 +220,21 @@ public abstract class MachineLifecycleEffectorTasks {
         };
     }
 
+    /**
+     * Calls {@link #suspend(ConfigBag)}.
+     *
+     * @see {@link #newStartEffectorTask()}
+     */
+    public EffectorBody<Void> newSuspendEffectorTask() {
+        return new EffectorBody<Void>() {
+            @Override
+            public Void call(ConfigBag parameters) {
+                suspend(parameters);
+                return null;
+            }
+        };
+    }
+
     protected EntityInternal entity() {
         return (EntityInternal) BrooklynTaskTags.getTargetOrContextEntity(Tasks.current());
     }
@@ -576,6 +601,27 @@ public abstract class MachineLifecycleEffectorTasks {
      * If no errors were encountered call {@link #postStopCustom()} at the end.
      */
     public void stop(ConfigBag parameters) {
+        doStop(parameters, new Callable<StopMachineDetails<Integer>>() {
+            public StopMachineDetails<Integer> call() {
+                return stopAnyProvisionedMachines();
+            }
+        });
+    }
+
+    /**
+     * As {@link #stop} but calling {@link #suspendAnyProvisionedMachines} rather than
+     * {@link #stopAnyProvisionedMachines}.
+     */
+    public void suspend(ConfigBag parameters) {
+        doStop(parameters, new Callable<StopMachineDetails<Integer>>() {
+            @Override
+            public StopMachineDetails<Integer> call() throws Exception {
+                return suspendAnyProvisionedMachines();
+            }
+        });
+    }
+
+    protected void doStop(ConfigBag parameters, Callable<StopMachineDetails<Integer>> stopTask) {
         preStopConfirmCustom();
 
         log.info("Stopping {} in {}", entity(), entity().getLocations());
@@ -608,11 +654,7 @@ public abstract class MachineLifecycleEffectorTasks {
         Task<StopMachineDetails<Integer>> stoppingMachine = null;
         if (canStop(stopMachineMode, machine.isAbsent())) {
             // Release this machine (even if error trying to stop process - we rethrow that after)
-            stoppingMachine = DynamicTasks.queue("stopping (machine)", new Callable<StopMachineDetails<Integer>>() {
-                public StopMachineDetails<Integer> call() {
-                    return stopAnyProvisionedMachines();
-                }
-            });
+            stoppingMachine = DynamicTasks.queue("stopping (machine)", stopTask);
 
             DynamicTasks.drain(entity().getConfig(STOP_PROCESS_TIMEOUT), false);
 
@@ -750,7 +792,7 @@ public abstract class MachineLifecycleEffectorTasks {
     protected abstract String stopProcessesAtMachine();
 
     /**
-     * Stop the {@link MachineLocation} the entity is provisioned at.
+     * Stop and release the {@link MachineLocation} the entity is provisioned at.
      * <p>
      * Can run synchronously or not, caller will submit/queue as needed, and will block on any submitted tasks.
      */
@@ -775,16 +817,63 @@ public abstract class MachineLifecycleEffectorTasks {
             return new StopMachineDetails<Integer>("No machine decommissioning necessary - not a machine ("+machine+")", 0);
         }
         
-        try {
-            entity().removeLocations(ImmutableList.of(machine));
-            entity().setAttribute(Attributes.HOSTNAME, null);
-            entity().setAttribute(Attributes.ADDRESS, null);
-            entity().setAttribute(Attributes.SUBNET_HOSTNAME, null);
-            entity().setAttribute(Attributes.SUBNET_ADDRESS, null);
-            if (provisioner != null) provisioner.release((MachineLocation)machine);
-        } catch (Throwable t) {
-            throw Exceptions.propagate(t);
-        }
+        clearEntityLocationAttributes(machine);
+        provisioner.release((MachineLocation)machine);
+
         return new StopMachineDetails<Integer>("Decommissioned "+machine, 1);
     }
+
+    /**
+     * Suspend the {@link MachineLocation} the entity is provisioned at.
+     * <p>
+     * Expects the entity's {@link SoftwareProcess#PROVISIONING_LOCATION provisioner} to be capable of
+     * {@link SuspendsMachines suspending machines}.
+     *
+     * @throws java.lang.UnsupportedOperationException if the entity's provisioner cannot suspend machines.
+     * @see brooklyn.location.MachineManagementMixins.SuspendsMachines
+     */
+    protected StopMachineDetails<Integer> suspendAnyProvisionedMachines() {
+        @SuppressWarnings("unchecked")
+        MachineProvisioningLocation<MachineLocation> provisioner = entity().getAttribute(SoftwareProcess.PROVISIONING_LOCATION);
+
+        if (Iterables.isEmpty(entity().getLocations())) {
+            log.debug("No machine decommissioning necessary for " + entity() + " - no locations");
+            return new StopMachineDetails<>("No machine suspend necessary - no locations", 0);
+        }
+
+        // Only release this machine if we ourselves provisioned it (e.g. it might be running other services)
+        if (provisioner == null) {
+            log.debug("No machine decommissioning necessary for " + entity() + " - did not provision");
+            return new StopMachineDetails<>("No machine suspend necessary - did not provision", 0);
+        }
+
+        Location machine = getLocation(null);
+        if (!(machine instanceof MachineLocation)) {
+            log.debug("No decommissioning necessary for " + entity() + " - not a machine location (" + machine + ")");
+            return new StopMachineDetails<>("No machine suspend necessary - not a machine (" + machine + ")", 0);
+        }
+
+        if (!(provisioner instanceof SuspendsMachines)) {
+            log.debug("Location provisioner ({}) cannot suspend machines", provisioner);
+            throw new UnsupportedOperationException("Location provisioner cannot suspend machines: " + provisioner);
+        }
+
+        clearEntityLocationAttributes(machine);
+        SuspendsMachines.class.cast(provisioner).suspendMachine(MachineLocation.class.cast(machine));
+
+        return new StopMachineDetails<>("Suspended " + machine, 1);
+    }
+
+    /**
+     * Nulls the attached entity's hostname, address, subnet hostname and subnet address sensors
+     * and removes the given machine from its locations.
+     */
+    protected void clearEntityLocationAttributes(Location machine) {
+        entity().removeLocations(ImmutableList.of(machine));
+        entity().setAttribute(Attributes.HOSTNAME, null);
+        entity().setAttribute(Attributes.ADDRESS, null);
+        entity().setAttribute(Attributes.SUBNET_HOSTNAME, null);
+        entity().setAttribute(Attributes.SUBNET_ADDRESS, null);
+    }
+
 }