do the node and client deletion as part of stopping a chef node
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/7ab18f67 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/7ab18f67 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/7ab18f67 Branch: refs/heads/master Commit: 7ab18f6758b28adb46cd51ba593d80c455715443 Parents: d78c172 Author: Alex Heneveld <[email protected]> Authored: Thu May 14 12:40:01 2015 -0700 Committer: Alex Heneveld <[email protected]> Committed: Thu May 14 12:44:57 2015 -0700 ---------------------------------------------------------------------- .../java/brooklyn/entity/chef/ChefConfig.java | 5 +++ .../entity/chef/ChefLifecycleEffectorTasks.java | 33 +++++++++++++++++++- .../software/MachineLifecycleEffectorTasks.java | 23 +++++++------- 3 files changed, 48 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7ab18f67/software/base/src/main/java/brooklyn/entity/chef/ChefConfig.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefConfig.java b/software/base/src/main/java/brooklyn/entity/chef/ChefConfig.java index 4d01b2c..769d8d0 100644 --- a/software/base/src/main/java/brooklyn/entity/chef/ChefConfig.java +++ b/software/base/src/main/java/brooklyn/entity/chef/ChefConfig.java @@ -79,6 +79,11 @@ public interface ChefConfig { public static final ConfigKey<String> KNIFE_CONFIG_FILE = ConfigKeys.newStringConfigKey("brooklyn.chef.knife.configFile", "Knife config file (typically knife.rb) to use, including full path; defaults to knife default/global config"); + @SetFromFlag("chef_node_name") + public static final ConfigKey<String> CHEF_NODE_NAME = ConfigKeys.newStringConfigKey("brooklyn.chef.node.nodeName", + "Node name to register with the chef server for this entity, if using Chef server and a specific node name is desired; " + + "if supplied ,this must be unique across the nodes Chef Server manages; if not supplied, one will be created if needed"); + // for providing some simple (ssh-based) lifecycle operations and checks @SetFromFlag("pid_file") public static final ConfigKey<String> PID_FILE = ConfigKeys.newStringConfigKey("brooklyn.chef.lifecycle.pidFile", http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7ab18f67/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java index 8f7ee31..e82aaec 100644 --- a/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java +++ b/software/base/src/main/java/brooklyn/entity/chef/ChefLifecycleEffectorTasks.java @@ -40,6 +40,7 @@ import brooklyn.util.exceptions.Exceptions; import brooklyn.util.net.Urls; import brooklyn.util.ssh.BashCommands; import brooklyn.util.task.DynamicTasks; +import brooklyn.util.task.TaskTags; import brooklyn.util.task.Tasks; import brooklyn.util.task.system.ProcessTaskWrapper; import brooklyn.util.text.Strings; @@ -93,6 +94,18 @@ public class ChefLifecycleEffectorTasks extends MachineLifecycleEffectorTasks im return _serviceName = entity().getConfig(ChefConfig.SERVICE_NAME); } + protected String getNodeName() { + // (node name is needed so we can node delete it) + + // TODO would be better if CHEF_NODE_NAME were a freemarker template, could access entity.id, or hostname, etc, + // in addition to supporting hard-coded node names (which is all we support so far). + + String nodeName = entity().getConfig(ChefConfig.CHEF_NODE_NAME); + if (Strings.isNonBlank(nodeName)) return nodeName; + // node name is taken from ID of this entity, if not specified + return entity().getId(); + } + public String getWindowsServiceName() { if (_windowsServiceName!=null) return _windowsServiceName; return _windowsServiceName = entity().getConfig(ChefConfig.WINDOWS_SERVICE_NAME); @@ -217,6 +230,7 @@ public class ChefLifecycleEffectorTasks extends MachineLifecycleEffectorTasks im DynamicTasks.queue( ChefServerTasks.knifeConvergeTask() + .knifeNodeName(getNodeName()) .knifeRunList(Strings.join(runList, ",")) .knifeAddAttributes((Map<? extends Object, ? extends Object>)(Map) attrs.root().get()) .knifeRunTwice(entity().getConfig(CHEF_RUN_CONVERGE_TWICE)) ); @@ -279,11 +293,28 @@ public class ChefLifecycleEffectorTasks extends MachineLifecycleEffectorTasks im result |= tryStopWindowsService(); result |= tryStopPid(); if (!result) { - throw new IllegalStateException("The process for "+entity()+" appears could not be stopped (no impl!)"); + throw new IllegalStateException("The process for "+entity()+" could not be stopped (no impl!)"); } return "stopped"; } + @Override + protected StopMachineDetails<Integer> stopAnyProvisionedMachines() { + if (detectChefMode(entity())==ChefModes.KNIFE) { + DynamicTasks.queue( + // if this task fails show it as failed but don't block subsequent routines + // (ie allow us to actually decommission the machine) + TaskTags.markInessential( + new KnifeTaskFactory<String>("delete node and client registration at chef server") + .add("knife node delete "+getNodeName()) + .add("knife client delete "+getNodeName()) + .requiringZeroAndReturningStdout() + .newTask() )); + } + + return super.stopAnyProvisionedMachines(); + } + protected boolean tryStopService() { if (getServiceName()==null) return false; int result = DynamicTasks.queue(SshEffectorTasks.ssh("/etc/init.d/"+getServiceName()+" stop").runAsRoot()).get(); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/7ab18f67/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 4fd6b09..6ccfc38 100644 --- a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java +++ b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java @@ -42,6 +42,7 @@ import brooklyn.entity.basic.EffectorStartableImpl.StartParameters; import brooklyn.entity.basic.Entities; import brooklyn.entity.basic.EntityInternal; import brooklyn.entity.basic.Lifecycle; +import brooklyn.entity.basic.Sanitizer; import brooklyn.entity.basic.ServiceStateLogic; import brooklyn.entity.basic.SoftwareProcess; import brooklyn.entity.basic.SoftwareProcess.RestartSoftwareParameters; @@ -292,7 +293,7 @@ public abstract class MachineLifecycleEffectorTasks { if (log.isDebugEnabled()) log.debug("While starting {}, obtained new location instance {}", entity(), (machine instanceof SshMachineLocation ? - machine+", details "+((SshMachineLocation)machine).getUser()+":"+Entities.sanitize(((SshMachineLocation)machine).config().getLocalBag()) + machine+", details "+((SshMachineLocation)machine).getUser()+":"+Sanitizer.sanitize(((SshMachineLocation)machine).config().getLocalBag()) : machine)); return machine; } @@ -664,6 +665,7 @@ public abstract class MachineLifecycleEffectorTasks { stopMode == StopMode.IF_NOT_STOPPED && !isStopped; } + @SuppressWarnings("deprecation") private static void checkCompatibleMachineModes(Boolean isStopMachine, boolean hasStopMachineMode, StopMode stopMachineMode) { if (hasStopMachineMode && (isStopMachine && stopMachineMode != StopMode.IF_NOT_STOPPED || @@ -714,6 +716,13 @@ public abstract class MachineLifecycleEffectorTasks { } /** + * Return string message of result. + * <p> + * Can run synchronously or not, caller will submit/queue as needed, and will block on any submitted tasks. + */ + protected abstract String stopProcessesAtMachine(); + + /** * Stop 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. @@ -722,9 +731,6 @@ public abstract class MachineLifecycleEffectorTasks { @SuppressWarnings("unchecked") MachineProvisioningLocation<MachineLocation> provisioner = entity().getAttribute(SoftwareProcess.PROVISIONING_LOCATION); - // NB: previously has logic about "removeFirstMachine" but elsewhere had assumptions that there was only one, - // so i think that was an aborted bit of work (which has been removed here). Alex, Aug 2013 - if (Iterables.isEmpty(entity().getLocations())) { log.debug("No machine decommissioning necessary for "+entity()+" - no locations"); return new StopMachineDetails<Integer>("No machine decommissioning necessary - no locations", 0); @@ -741,7 +747,7 @@ public abstract class MachineLifecycleEffectorTasks { log.debug("No decommissioning necessary for "+entity()+" - not a machine location ("+machine+")"); return new StopMachineDetails<Integer>("No machine decommissioning necessary - not a machine ("+machine+")", 0); } - + try { entity().removeLocations(ImmutableList.of(machine)); entity().setAttribute(Attributes.HOSTNAME, null); @@ -755,11 +761,4 @@ public abstract class MachineLifecycleEffectorTasks { return new StopMachineDetails<Integer>("Decommissioned "+machine, 1); } - /** - * Return string message of result. - * <p> - * Can run synchronously or not, caller will submit/queue as needed, and will block on any submitted tasks. - */ - protected abstract String stopProcessesAtMachine(); - }
