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 2015/08/19 13:09:55 UTC

[37/72] [abbrv] incubator-brooklyn git commit: BROOKLYN-162 - apply org.apache package prefix to software-base, tidying package names, and moving a few sensory things to core

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessSshDriver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessSshDriver.java b/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessSshDriver.java
deleted file mode 100644
index 74fe155..0000000
--- a/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessSshDriver.java
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * 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 brooklyn.entity.basic;
-
-import static org.apache.brooklyn.util.JavaGroovyEquivalents.elvis;
-import static org.apache.brooklyn.util.JavaGroovyEquivalents.groovyTruth;
-
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolver;
-import org.apache.brooklyn.api.internal.EntityLocal;
-import org.apache.brooklyn.core.BrooklynLogging;
-import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
-import org.apache.brooklyn.effector.core.EffectorTasks;
-import org.apache.brooklyn.entity.core.Attributes;
-import org.apache.brooklyn.entity.core.Entities;
-import org.apache.brooklyn.entity.core.EntityInternal;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
-import brooklyn.entity.basic.lifecycle.NaiveScriptRunner;
-import brooklyn.entity.basic.lifecycle.ScriptHelper;
-import brooklyn.entity.software.SshEffectorTasks;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-import org.apache.brooklyn.sensor.feed.ConfigToAttributes;
-import org.apache.brooklyn.util.core.internal.ssh.SshTool;
-import org.apache.brooklyn.util.core.internal.ssh.sshj.SshjTool;
-import org.apache.brooklyn.util.core.task.DynamicTasks;
-import org.apache.brooklyn.util.core.task.Tasks;
-import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
-import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.apache.brooklyn.util.guava.Maybe;
-import org.apache.brooklyn.util.os.Os;
-import org.apache.brooklyn.util.ssh.BashCommands;
-import org.apache.brooklyn.util.stream.KnownSizeInputStream;
-import org.apache.brooklyn.util.stream.Streams;
-import org.apache.brooklyn.util.text.StringPredicates;
-import org.apache.brooklyn.util.text.Strings;
-import org.apache.brooklyn.util.time.Duration;
-
-/**
- * An abstract SSH implementation of the {@link AbstractSoftwareProcessDriver}.
- *
- * This provides conveniences for clients implementing the install/customize/launch/isRunning/stop lifecycle
- * over SSH.  These conveniences include checking whether software is already installed,
- * creating/using a PID file for some operations, and reading ssh-specific config from the entity
- * to override/augment ssh flags on the session.
- */
-public abstract class AbstractSoftwareProcessSshDriver extends AbstractSoftwareProcessDriver implements NaiveScriptRunner {
-
-    public static final Logger log = LoggerFactory.getLogger(AbstractSoftwareProcessSshDriver.class);
-    public static final Logger logSsh = LoggerFactory.getLogger(BrooklynLogging.SSH_IO);
-
-    // we cache these for efficiency and in case the entity becomes unmanaged
-    private volatile String installDir;
-    private volatile String runDir;
-    private volatile String expandedInstallDir;
-    private final Object installDirSetupMutex = new Object();
-
-    protected volatile DownloadResolver resolver;
-
-    /** include this flag in newScript creation to prevent entity-level flags from being included;
-     * any SSH-specific flags passed to newScript override flags from the entity,
-     * and flags from the entity override flags on the location
-     * (where there aren't conflicts, flags from all three are used however) */
-    public static final String IGNORE_ENTITY_SSH_FLAGS = SshEffectorTasks.IGNORE_ENTITY_SSH_FLAGS.getName();
-
-    public AbstractSoftwareProcessSshDriver(EntityLocal entity, SshMachineLocation machine) {
-        super(entity, machine);
-
-        // FIXME this assumes we own the location, and causes warnings about configuring location after deployment;
-        // better would be to wrap the ssh-execution-provider to supply these flags
-        if (getSshFlags()!=null && !getSshFlags().isEmpty())
-            machine.configure(getSshFlags());
-
-        // ensure these are set using the routines below, not a global ConfigToAttributes.apply()
-        getInstallDir();
-        getRunDir();
-    }
-
-    /** returns location (tighten type, since we know it is an ssh machine location here) */
-    public SshMachineLocation getLocation() {
-        return (SshMachineLocation) super.getLocation();
-    }
-
-    protected void setInstallDir(String installDir) {
-        this.installDir = installDir;
-        entity.setAttribute(SoftwareProcess.INSTALL_DIR, installDir);
-    }
-
-    public String getInstallDir() {
-        if (installDir != null) return installDir;
-
-        String existingVal = getEntity().getAttribute(SoftwareProcess.INSTALL_DIR);
-        if (Strings.isNonBlank(existingVal)) { // e.g. on rebind
-            installDir = existingVal;
-            return installDir;
-        }
-
-        synchronized (installDirSetupMutex) {
-            // previously we looked at sensor value, but we shouldn't as it might have been converted from the config key value
-            // *before* we computed the install label, or that label may have changed since previous install; now force a recompute
-            setInstallLabel();
-
-            // deprecated in 0.7.0 - "brooklyn.dirs.install" is no longer supported
-            Maybe<Object> minstallDir = getEntity().getConfigRaw(SoftwareProcess.INSTALL_DIR, false);
-            if (!minstallDir.isPresent() || minstallDir.get()==null) {
-                String installBasedir = ((EntityInternal)entity).getManagementContext().getConfig().getFirst("brooklyn.dirs.install");
-                if (installBasedir != null) {
-                    log.warn("Using legacy 'brooklyn.dirs.install' setting for "+entity+"; may be removed in future versions.");
-                    setInstallDir(Os.tidyPath(Os.mergePathsUnix(installBasedir, getEntityVersionLabel()+"_"+entity.getId())));
-                    return installDir;
-                }
-            }
-
-            // set it null first so that we force a recompute
-            setInstallDir(null);
-            setInstallDir(Os.tidyPath(ConfigToAttributes.apply(getEntity(), SoftwareProcess.INSTALL_DIR)));
-            return installDir;
-        }
-    }
-
-    protected void setInstallLabel() {
-        if (getEntity().getConfigRaw(SoftwareProcess.INSTALL_UNIQUE_LABEL, false).isPresentAndNonNull()) return;
-        getEntity().setConfig(SoftwareProcess.INSTALL_UNIQUE_LABEL,
-            getEntity().getEntityType().getSimpleName()+
-            (Strings.isNonBlank(getVersion()) ? "_"+getVersion() : "")+
-            (Strings.isNonBlank(getInstallLabelExtraSalt()) ? "_"+getInstallLabelExtraSalt() : "") );
-    }
-
-    /** allows subclasses to return extra salt (ie unique hash)
-     * for cases where install dirs need to be distinct e.g. based on extra plugins being placed in the install dir;
-     * {@link #setInstallLabel()} uses entity-type simple name and version already
-     * <p>
-     * this salt should not be too long and must not contain invalid path chars.
-     * a hash code of other relevant info is not a bad choice.
-     **/
-    protected String getInstallLabelExtraSalt() {
-        return null;
-    }
-
-    protected void setRunDir(String runDir) {
-        this.runDir = runDir;
-        entity.setAttribute(SoftwareProcess.RUN_DIR, runDir);
-    }
-
-    public String getRunDir() {
-        if (runDir != null) return runDir;
-
-        String existingVal = getEntity().getAttribute(SoftwareProcess.RUN_DIR);
-        if (Strings.isNonBlank(existingVal)) { // e.g. on rebind
-            runDir = existingVal;
-            return runDir;
-        }
-
-        // deprecated in 0.7.0
-        Maybe<Object> mRunDir = getEntity().getConfigRaw(SoftwareProcess.RUN_DIR, true);
-        if (!mRunDir.isPresent() || mRunDir.get()==null) {
-            String runBasedir = ((EntityInternal)entity).getManagementContext().getConfig().getFirst("brooklyn.dirs.run");
-            if (runBasedir != null) {
-                log.warn("Using legacy 'brooklyn.dirs.run' setting for "+entity+"; may be removed in future versions.");
-                runDir = Os.mergePathsUnix(runBasedir, entity.getApplication().getId()+"/"+"entities"+"/"+getEntityVersionLabel()+"_"+entity.getId());
-                runDir = Os.tidyPath(runDir);
-                getEntity().setAttribute(SoftwareProcess.RUN_DIR, runDir);
-                return runDir;
-            }
-        }
-
-        setRunDir(Os.tidyPath(ConfigToAttributes.apply(getEntity(), SoftwareProcess.RUN_DIR)));
-        return runDir;
-    }
-
-    public void setExpandedInstallDir(String val) {
-        String oldVal = getEntity().getAttribute(SoftwareProcess.EXPANDED_INSTALL_DIR);
-        if (Strings.isNonBlank(oldVal) && !oldVal.equals(val)) {
-            log.info("Resetting expandedInstallDir (to "+val+" from "+oldVal+") for "+getEntity());
-        }
-
-        expandedInstallDir = val;
-        getEntity().setAttribute(SoftwareProcess.EXPANDED_INSTALL_DIR, val);
-    }
-
-    public String getExpandedInstallDir() {
-        if (expandedInstallDir != null) return expandedInstallDir;
-
-        String existingVal = getEntity().getAttribute(SoftwareProcess.EXPANDED_INSTALL_DIR);
-        if (Strings.isNonBlank(existingVal)) { // e.g. on rebind
-            expandedInstallDir = existingVal;
-            return expandedInstallDir;
-        }
-
-        String untidiedVal = ConfigToAttributes.apply(getEntity(), SoftwareProcess.EXPANDED_INSTALL_DIR);
-        if (Strings.isNonBlank(untidiedVal)) {
-            setExpandedInstallDir(Os.tidyPath(untidiedVal));
-            return expandedInstallDir;
-        } else {
-            throw new IllegalStateException("expandedInstallDir is null; most likely install was not called for "+getEntity());
-        }
-    }
-
-    public SshMachineLocation getMachine() { return getLocation(); }
-    public String getHostname() { return entity.getAttribute(Attributes.HOSTNAME); }
-    public String getAddress() { return entity.getAttribute(Attributes.ADDRESS); }
-    public String getSubnetHostname() { return entity.getAttribute(Attributes.SUBNET_HOSTNAME); }
-    public String getSubnetAddress() { return entity.getAttribute(Attributes.SUBNET_ADDRESS); }
-
-    protected Map<String, Object> getSshFlags() {
-        return SshEffectorTasks.getSshFlags(getEntity(), getMachine());
-    }
-
-    public int execute(String command, String summaryForLogging) {
-        return execute(ImmutableList.of(command), summaryForLogging);
-    }
-
-    public int execute(List<String> script, String summaryForLogging) {
-        return execute(Maps.newLinkedHashMap(), script, summaryForLogging);
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    @Override
-    public int execute(Map flags2, List<String> script, String summaryForLogging) {
-        // TODO replace with SshEffectorTasks.ssh ?; remove the use of flags
-
-        Map flags = Maps.newLinkedHashMap();
-        if (!flags2.containsKey(IGNORE_ENTITY_SSH_FLAGS)) {
-            flags.putAll(getSshFlags());
-        }
-        flags.putAll(flags2);
-        Map<String, String> environment = (Map<String, String>) flags.get("env");
-        if (environment == null) {
-            // Important only to call getShellEnvironment() if env was not supplied; otherwise it
-            // could cause us to resolve config (e.g. block for attributeWhenReady) too early.
-            environment = getShellEnvironment();
-        }
-        if (Tasks.current()!=null) {
-            // attach tags here, as well as in ScriptHelper, because they may have just been read from the driver
-            if (environment!=null) {
-                Tasks.addTagDynamically(BrooklynTaskTags.tagForEnvStream(BrooklynTaskTags.STREAM_ENV, environment));
-            }
-            if (BrooklynTaskTags.stream(Tasks.current(), BrooklynTaskTags.STREAM_STDIN)==null) {
-                Tasks.addTagDynamically(BrooklynTaskTags.tagForStreamSoft(BrooklynTaskTags.STREAM_STDIN,
-                    Streams.byteArrayOfString(Strings.join(script, "\n"))));
-            }
-            if (BrooklynTaskTags.stream(Tasks.current(), BrooklynTaskTags.STREAM_STDOUT)==null) {
-                ByteArrayOutputStream stdout = new ByteArrayOutputStream();
-                Tasks.addTagDynamically(BrooklynTaskTags.tagForStreamSoft(BrooklynTaskTags.STREAM_STDOUT, stdout));
-                ByteArrayOutputStream stderr = new ByteArrayOutputStream();
-                Tasks.addTagDynamically(BrooklynTaskTags.tagForStreamSoft(BrooklynTaskTags.STREAM_STDERR, stderr));
-                flags.put("out", stdout);
-                flags.put("err", stderr);
-            }
-        }
-        if (!flags.containsKey("logPrefix")) flags.put("logPrefix", ""+entity.getId()+"@"+getLocation().getDisplayName());
-        return getMachine().execScript(flags, summaryForLogging, script, environment);
-    }
-
-    @Override
-    public void copyInstallResources() {
-        getLocation().acquireMutex("installing " + elvis(entity, this), "installation lock at host for files and templates");
-        try {
-            super.copyInstallResources();
-        } catch (Exception e) {
-            log.warn("Error copying install resources", e);
-            throw Exceptions.propagate(e);
-        } finally {
-            getLocation().releaseMutex("installing " + elvis(entity, this));
-        }
-    }
-
-    @Override
-    public void runPreInstallCommand(String command) {
-        execute(ImmutableList.of(command), "running pre-install commands");
-    }
-
-    @Override
-    public void runPostInstallCommand(String command) {
-        execute(ImmutableList.of(command), "running post-install commands");
-    }
-
-    @Override
-    public void runPreLaunchCommand(String command) {
-        execute(ImmutableList.of(command), "running pre-launch commands");
-    }
-
-    @Override
-    public void runPostLaunchCommand(String command) {
-        execute(ImmutableList.of(command), "running post-launch commands");
-    }
-
-    /**
-     * The environment variables to be set when executing the commands (for install, run, check running, etc).
-     * @see SoftwareProcess#SHELL_ENVIRONMENT
-     */
-    public Map<String, String> getShellEnvironment() {
-        return Strings.toStringMap(entity.getConfig(SoftwareProcess.SHELL_ENVIRONMENT), "");
-    }
-
-
-    /**
-     * @param sshFlags Extra flags to be used when making an SSH connection to the entity's machine.
-     *                 If the map contains the key {@link #IGNORE_ENTITY_SSH_FLAGS} then only the
-     *                 given flags are used. Otherwise, the given flags are combined with (and take
-     *                 precendence over) the flags returned by {@link #getSshFlags()}.
-     * @param source URI of file to copy, e.g. file://.., http://.., classpath://..
-     * @param target Destination on server, relative to {@link #getRunDir()} if not absolute path
-     * @param createParentDir Whether to create the parent target directory, if it doesn't already exist
-     * @return The exit code of the SSH command run
-     */
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    public int copyResource(Map<Object,Object> sshFlags, String source, String target, boolean createParentDir) {
-        // TODO use SshTasks.put instead, better logging
-        Map flags = Maps.newLinkedHashMap();
-        if (!sshFlags.containsKey(IGNORE_ENTITY_SSH_FLAGS)) {
-            flags.putAll(getSshFlags());
-        }
-        flags.putAll(sshFlags);
-
-        String destination = Os.isAbsolutish(target) ? target : Os.mergePathsUnix(getRunDir(), target);
-
-        if (createParentDir) {
-            // don't use File.separator because it's remote machine's format, rather than local machine's
-            int lastSlashIndex = destination.lastIndexOf("/");
-            String parent = (lastSlashIndex > 0) ? destination.substring(0, lastSlashIndex) : null;
-            if (parent != null) {
-                getMachine().execCommands("createParentDir", ImmutableList.of("mkdir -p "+parent));
-            }
-        }
-
-        int result = getMachine().installTo(resource, flags, source, destination);
-        if (result == 0) {
-            if (log.isDebugEnabled()) {
-                log.debug("Copied file for {}: {} to {} - result {}", new Object[] { entity, source, destination, result });
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Input stream will be closed automatically.
-     * <p>
-     * If using {@link SshjTool} usage, consider using {@link KnownSizeInputStream} to avoid having
-     * to write out stream once to find its size!
-     *
-     * @see #copyResource(Map, String, String) for parameter descriptions.
-     */
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    public int copyResource(Map<Object,Object> sshFlags, InputStream source, String target, boolean createParentDir) {
-        Map flags = Maps.newLinkedHashMap();
-        if (!sshFlags.containsKey(IGNORE_ENTITY_SSH_FLAGS)) {
-            flags.putAll(getSshFlags());
-        }
-        flags.putAll(sshFlags);
-
-        String destination = Os.isAbsolutish(target) ? target : Os.mergePathsUnix(getRunDir(), target);
-
-        if (createParentDir) {
-            // don't use File.separator because it's remote machine's format, rather than local machine's
-            int lastSlashIndex = destination.lastIndexOf("/");
-            String parent = (lastSlashIndex > 0) ? destination.substring(0, lastSlashIndex) : null;
-            if (parent != null) {
-                getMachine().execCommands("createParentDir", ImmutableList.of("mkdir -p "+parent));
-            }
-        }
-
-        // TODO SshMachineLocation.copyTo currently doesn't log warn on non-zero or set blocking details
-        // (because delegated to by installTo, for multiple calls). So do it here for now.
-        int result;
-        String prevBlockingDetails = Tasks.setBlockingDetails("copying resource to server at "+destination);
-        try {
-            result = getMachine().copyTo(flags, source, destination);
-        } finally {
-            Tasks.setBlockingDetails(prevBlockingDetails);
-        }
-
-        if (result == 0) {
-            log.debug("copying stream complete; {} on {}", new Object[] { destination, getMachine() });
-        } else {
-            log.warn("copying stream failed; {} on {}: {}", new Object[] { destination, getMachine(), result });
-        }
-        return result;
-    }
-
-    public void checkNoHostnameBug() {
-        try {
-            ProcessTaskWrapper<Integer> hostnameTask = DynamicTasks.queue(SshEffectorTasks.ssh("echo FOREMARKER; hostname; echo AFTMARKER")).block();
-            String stdout = Strings.getFragmentBetween(hostnameTask.getStdout(), "FOREMARKER", "AFTMARKER");
-            if (hostnameTask.getExitCode() == 0 && Strings.isNonBlank(stdout)) {
-                String hostname = stdout.trim();
-                if (hostname.equals("(none)")) {
-                    String newHostname = "br-"+getEntity().getId().toLowerCase();
-                    log.info("Detected no-hostname bug with hostname "+hostname+" for "+getEntity()+"; renaming "+getMachine()+"  to hostname "+newHostname);
-                    DynamicTasks.queue(SshEffectorTasks.ssh(BashCommands.setHostname(newHostname, null))).block();
-                }
-            } else {
-                log.debug("Hostname could not be determined for location "+EffectorTasks.findSshMachine()+"; not doing no-hostname bug check");
-            }
-        } catch (Exception e) {
-            Exceptions.propagateIfFatal(e);
-            log.warn("Error checking/fixing no-hostname bug (continuing): "+e, e);
-        }
-    }
-
-    public static final String INSTALLING = "installing";
-    public static final String CUSTOMIZING = "customizing";
-    public static final String LAUNCHING = "launching";
-    public static final String CHECK_RUNNING = "check-running";
-    public static final String STOPPING = "stopping";
-    public static final String KILLING = "killing";
-    public static final String RESTARTING = "restarting";
-
-    public static final String PID_FILENAME = "pid.txt";
-
-    /* Flags */
-
-    /**
-     * Use a PID file, created by <em>launching</em>, and reading it for <em>check-running</em>,
-     * <em>stopping</em> and <em>killing</em>. The value can be <em>true</em> or a path to a file to
-     * use; either relative to <em>RUN_DIR</em> or an absolute path.
-     */
-    public static final String USE_PID_FILE = "usePidFile";
-
-    /**
-     * Define the process owner if not the same as the brooklyn user. Both <em>stopping</em> and
-     * <em>killing</em> will sudo to this user before issuing the <code>kill</code> command. Only valid
-     * if <em>USE_PID_FILE</em> is also set.
-     */
-    public static final String PROCESS_OWNER = "processOwner";
-
-    /**
-     * Marks the script as having a customised setup, to prevent the default headers and footers being
-     * added to the list of commands.
-     */
-    public static final String NON_STANDARD_LAYOUT = "nonStandardLayout";
-
-    /**
-     * Prevents creation of the <code>$INSTALL_DIR/BROOKLYN</code> marker file after <em>installing</em>
-     * phase finishes, to allow further installation phases to execute.
-     */
-    public static final String INSTALL_INCOMPLETE = "installIncomplete";
-
-    /**
-     * Enable shell debugging output via <code>set -x</code> prepended to the command header.
-     */
-    public static final String DEBUG = "debug";
-
-    /** Permitted flags for {@link #newScript(Map, String)}. */
-    public static final List<String> VALID_FLAGS =
-            ImmutableList.of(USE_PID_FILE, PROCESS_OWNER, NON_STANDARD_LAYOUT, INSTALL_INCOMPLETE, DEBUG);
-
-    /** @see #newScript(Map, String) */
-    protected ScriptHelper newScript(String phase) {
-        return newScript(Maps.<String, Object>newLinkedHashMap(), phase);
-    }
-
-    /**
-     * Sets up a {@link ScriptHelper} to generate a script that controls the given phase
-     * (<em>check-running</em>, <em>launching</em> etc.) including default header and
-     * footer commands.
-     * <p>
-     * Supported flags:
-     * <ul>
-     * <li><strong>usePidFile</strong> - <em>true</em> or <em>filename</em> to save and retrieve the PID
-     * <li><strong>processOwner</strong> - <em>username</em> that owns the running process
-     * <li><strong>nonStandardLayout</strong> - <em>true</em> to omit all default commands
-     * <li><strong>installIncomplete</strong> - <em>true</em> to prevent marking complete
-     * <li><strong>debug</strong> - <em>true</em> to enable shell debug output
-     * </li>
-     *
-     * @param flags a {@link Map} of flags to control script generation
-     * @param phase the phase to create the ScriptHelper for
-     *
-     * @see #newScript(String)
-     * @see #USE_PID_FILE
-     * @see #PROCESS_OWNER
-     * @see #NON_STANDARD_LAYOUT
-     * @see #INSTALL_INCOMPLETE
-     * @see #DEBUG
-     */
-    protected ScriptHelper newScript(Map<String, ?> flags, String phase) {
-        if (!Entities.isManaged(getEntity()))
-            throw new IllegalStateException(getEntity()+" is no longer managed; cannot create script to run here ("+phase+")");
-
-        if (!Iterables.all(flags.keySet(), StringPredicates.equalToAny(VALID_FLAGS))) {
-            throw new IllegalArgumentException("Invalid flags passed: " + flags);
-        }
-
-        ScriptHelper s = new ScriptHelper(this, phase+" "+elvis(entity,this));
-        if (!groovyTruth(flags.get(NON_STANDARD_LAYOUT))) {
-            if (groovyTruth(flags.get(DEBUG))) {
-                s.header.prepend("set -x");
-            }
-            if (INSTALLING.equals(phase)) {
-                // mutexId should be global because otherwise package managers will contend with each other
-                s.useMutex(getLocation(), "installation lock at host", "installing "+elvis(entity,this));
-                s.header.append(
-                        "export INSTALL_DIR=\""+getInstallDir()+"\"",
-                        "mkdir -p $INSTALL_DIR",
-                        "cd $INSTALL_DIR",
-                        "test -f BROOKLYN && exit 0"
-                        );
-
-                if (!groovyTruth(flags.get(INSTALL_INCOMPLETE))) {
-                    s.footer.append("date > $INSTALL_DIR/BROOKLYN");
-                }
-                // don't set vars during install phase, prevent dependency resolution
-                s.environmentVariablesReset();
-            }
-            if (ImmutableSet.of(CUSTOMIZING, LAUNCHING, CHECK_RUNNING, STOPPING, KILLING, RESTARTING).contains(phase)) {
-                s.header.append(
-                        "export RUN_DIR=\""+getRunDir()+"\"",
-                        "mkdir -p $RUN_DIR",
-                        "cd $RUN_DIR"
-                        );
-            }
-        }
-
-        if (ImmutableSet.of(LAUNCHING, RESTARTING).contains(phase)) {
-            s.failIfBodyEmpty();
-        }
-        if (ImmutableSet.of(STOPPING, KILLING).contains(phase)) {
-            // stopping and killing allowed to have empty body if pid file set
-            if (!groovyTruth(flags.get(USE_PID_FILE)))
-                s.failIfBodyEmpty();
-        }
-        if (ImmutableSet.of(INSTALLING, LAUNCHING).contains(phase)) {
-            s.updateTaskAndFailOnNonZeroResultCode();
-        }
-        if (phase.equalsIgnoreCase(CHECK_RUNNING)) {
-            s.setInessential();
-            s.setTransient();
-            s.setFlag(SshTool.PROP_CONNECT_TIMEOUT, Duration.TEN_SECONDS.toMilliseconds());
-            s.setFlag(SshTool.PROP_SESSION_TIMEOUT, Duration.THIRTY_SECONDS.toMilliseconds());
-            s.setFlag(SshTool.PROP_SSH_TRIES, 1);
-        }
-
-        if (groovyTruth(flags.get(USE_PID_FILE))) {
-            Object usePidFile = flags.get(USE_PID_FILE);
-            String pidFile = (usePidFile instanceof CharSequence ? usePidFile : Os.mergePathsUnix(getRunDir(), PID_FILENAME)).toString();
-            String processOwner = (String) flags.get(PROCESS_OWNER);
-            if (LAUNCHING.equals(phase)) {
-                entity.setAttribute(SoftwareProcess.PID_FILE, pidFile);
-                s.footer.prepend("echo $! > "+pidFile);
-            } else if (CHECK_RUNNING.equals(phase)) {
-                // old method, for supplied service, or entity.id
-                // "ps aux | grep ${service} | grep \$(cat ${pidFile}) > /dev/null"
-                // new way, preferred?
-                if (processOwner != null) {
-                    s.body.append(
-                            BashCommands.sudoAsUser(processOwner, "test -f "+pidFile) + " || exit 1",
-                            "ps -p $(" + BashCommands.sudoAsUser(processOwner, "cat "+pidFile) + ")"
-                    );
-                } else {
-                    s.body.append(
-                            "test -f "+pidFile+" || exit 1",
-                            "ps -p `cat "+pidFile+"`"
-                    );
-                }
-                // no pid, not running; 1 is not running
-                s.requireResultCode(Predicates.or(Predicates.equalTo(0), Predicates.equalTo(1)));
-            } else if (STOPPING.equals(phase)) {
-                if (processOwner != null) {
-                    s.body.append(
-                            "export PID=$(" + BashCommands.sudoAsUser(processOwner, "cat "+pidFile) + ")",
-                            "test -n \"$PID\" || exit 0",
-                            BashCommands.sudoAsUser(processOwner, "kill $PID"),
-                            BashCommands.sudoAsUser(processOwner, "kill -9 $PID"),
-                            BashCommands.sudoAsUser(processOwner, "rm -f "+pidFile)
-                    );
-                } else {
-                    s.body.append(
-                            "export PID=$(cat "+pidFile+")",
-                            "test -n \"$PID\" || exit 0",
-                            "kill $PID",
-                            "kill -9 $PID",
-                            "rm -f "+pidFile
-                    );
-                }
-            } else if (KILLING.equals(phase)) {
-                if (processOwner != null) {
-                    s.body.append(
-                            "export PID=$(" + BashCommands.sudoAsUser(processOwner, "cat "+pidFile) + ")",
-                            "test -n \"$PID\" || exit 0",
-                            BashCommands.sudoAsUser(processOwner, "kill -9 $PID"),
-                            BashCommands.sudoAsUser(processOwner, "rm -f "+pidFile)
-                    );
-                } else {
-                    s.body.append(
-                            "export PID=$(cat "+pidFile+")",
-                            "test -n \"$PID\" || exit 0",
-                            "kill -9 $PID",
-                            "rm -f "+pidFile
-                    );
-                }
-            } else if (RESTARTING.equals(phase)) {
-                if (processOwner != null) {
-                    s.footer.prepend(
-                            BashCommands.sudoAsUser(processOwner, "test -f "+pidFile) + " || exit 1",
-                            "ps -p $(" + BashCommands.sudoAsUser(processOwner, "cat "+pidFile) + ") || exit 1"
-                    );
-                } else {
-                    s.footer.prepend(
-                            "test -f "+pidFile+" || exit 1",
-                            "ps -p $(cat "+pidFile+") || exit 1"
-                    );
-                }
-                // no pid, not running; no process; can't restart, 1 is not running
-            } else {
-                log.warn(USE_PID_FILE + ": script option not valid for " + s.summary);
-            }
-        }
-
-        return s;
-    }
-
-    @Override
-    protected void createDirectory(String directoryName, String summaryForLogging) {
-        DynamicTasks.queue(SshEffectorTasks.ssh("mkdir -p " + directoryName).summary(summaryForLogging)
-                .requiringExitCodeZero()).get();
-    }
-
-    public Set<Integer> getPortsUsed() {
-        Set<Integer> result = Sets.newLinkedHashSet();
-        result.add(22);
-        return result;
-    }
-
-    @Override
-    public void setup() { }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessWinRmDriver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessWinRmDriver.java b/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessWinRmDriver.java
deleted file mode 100644
index 48402bc..0000000
--- a/software/base/src/main/java/brooklyn/entity/basic/AbstractSoftwareProcessWinRmDriver.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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 brooklyn.entity.basic;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.brooklyn.api.internal.EntityLocal;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.config.ConfigKey;
-import org.python.core.PyException;
-import org.apache.brooklyn.location.basic.WinRmMachineLocation;
-import org.apache.brooklyn.sensor.core.Sensors;
-import org.apache.brooklyn.util.exceptions.ReferenceWithError;
-import org.apache.brooklyn.util.repeat.Repeater;
-import org.apache.brooklyn.util.time.Duration;
-
-import io.cloudsoft.winrm4j.winrm.WinRmToolResponse;
-
-import com.google.api.client.util.Strings;
-import com.google.common.collect.ImmutableList;
-
-public abstract class AbstractSoftwareProcessWinRmDriver extends AbstractSoftwareProcessDriver {
-
-    AttributeSensor<String> WINDOWS_USERNAME = Sensors.newStringSensor("windows.username",
-            "Default Windows username to be used when connecting to the Entity's VM");
-    AttributeSensor<String> WINDOWS_PASSWORD = Sensors.newStringSensor("windows.password",
-            "Default Windows password to be used when connecting to the Entity's VM");
-
-    public AbstractSoftwareProcessWinRmDriver(EntityLocal entity, WinRmMachineLocation location) {
-        super(entity, location);
-        entity.setAttribute(WINDOWS_USERNAME, location.config().get(WinRmMachineLocation.USER));
-        entity.setAttribute(WINDOWS_PASSWORD, location.config().get(WinRmMachineLocation.PASSWORD));
-    }
-
-    @Override
-    public void runPreInstallCommand(String command) {
-        execute(ImmutableList.of(command));
-    }
-
-    @Override
-    public void setup() {
-        // Default to no-op
-    }
-
-    @Override
-    public void runPostInstallCommand(String command) {
-        execute(ImmutableList.of(command));
-    }
-
-    @Override
-    public void runPreLaunchCommand(String command) {
-        execute(ImmutableList.of(command));
-    }
-
-    @Override
-    public void runPostLaunchCommand(String command) {
-        execute(ImmutableList.of(command));
-    }
-
-    @Override
-    public WinRmMachineLocation getLocation() {
-        return (WinRmMachineLocation)super.getLocation();
-    }
-
-    @Override
-    public String getRunDir() {
-        // TODO: This needs to be tidied, and read from the appropriate flags (if set)
-        return "$HOME\\brooklyn-managed-processes\\apps\\" + entity.getApplicationId() + "\\entities\\" + getEntityVersionLabel()+"_"+entity.getId();
-    }
-
-    @Override
-    public String getInstallDir() {
-        // TODO: This needs to be tidied, and read from the appropriate flags (if set)
-        return "$HOME\\brooklyn-managed-processes\\installs\\" + entity.getApplicationId() + "\\" + getEntityVersionLabel()+"_"+entity.getId();
-    }
-
-    @Override
-    public int copyResource(Map<Object, Object> sshFlags, String source, String target, boolean createParentDir) {
-        if (createParentDir) {
-            createDirectory(getDirectory(target), "Creating resource directory");
-        }
-        return copyTo(new File(source), target);
-    }
-
-    @Override
-    public int copyResource(Map<Object, Object> sshFlags, InputStream source, String target, boolean createParentDir) {
-        if (createParentDir) {
-            createDirectory(getDirectory(target), "Creating resource directory");
-        }
-        return copyTo(source, target);
-    }
-
-    @Override
-    protected void createDirectory(String directoryName, String summaryForLogging) {
-        getLocation().executePsScript("New-Item -path \"" + directoryName + "\" -type directory -ErrorAction SilentlyContinue");
-    }
-
-    protected WinRmToolResponse executeCommand(ConfigKey<String> regularCommandKey, ConfigKey<String> powershellCommandKey, boolean allowNoOp) {
-        String regularCommand = getEntity().getConfig(regularCommandKey);
-        String powershellCommand = getEntity().getConfig(powershellCommandKey);
-        if (Strings.isNullOrEmpty(regularCommand) && Strings.isNullOrEmpty(powershellCommand)) {
-            if (allowNoOp) {
-                return new WinRmToolResponse("", "", 0);
-            } else {
-                throw new IllegalStateException(String.format("Exactly one of %s or %s must be set", regularCommandKey.getName(), powershellCommandKey.getName()));
-            }
-        } else if (!Strings.isNullOrEmpty(regularCommand) && !Strings.isNullOrEmpty(powershellCommand)) {
-            throw new IllegalStateException(String.format("%s and %s cannot both be set", regularCommandKey.getName(), powershellCommandKey.getName()));
-        }
-
-        if (Strings.isNullOrEmpty(regularCommand)) {
-            return getLocation().executePsScript(ImmutableList.of(powershellCommand));
-        } else {
-            return getLocation().executeScript(ImmutableList.of(regularCommand));
-        }
-    }
-
-    public int execute(List<String> script) {
-        return getLocation().executeScript(script).getStatusCode();
-    }
-
-    public int executePsScriptNoRetry(List<String> psScript) {
-        return getLocation().executePsScriptNoRetry(psScript).getStatusCode();
-    }
-
-    public int executePsScript(List<String> psScript) {
-        return getLocation().executePsScript(psScript).getStatusCode();
-    }
-
-    public int copyTo(File source, String destination) {
-        return getLocation().copyTo(source, destination);
-    }
-
-    public int copyTo(InputStream source, String destination) {
-        return getLocation().copyTo(source, destination);
-    }
-
-    public void rebootAndWait() {
-        try {
-            executePsScriptNoRetry(ImmutableList.of("Restart-Computer -Force"));
-        } catch (PyException e) {
-            // Restarting the computer will cause the command to fail; ignore the exception and continue
-        }
-        waitForWinRmStatus(false, entity.getConfig(VanillaWindowsProcess.REBOOT_BEGUN_TIMEOUT));
-        waitForWinRmStatus(true, entity.getConfig(VanillaWindowsProcess.REBOOT_COMPLETED_TIMEOUT)).getWithError();
-    }
-
-    private String getDirectory(String fileName) {
-        return fileName.substring(0, fileName.lastIndexOf("\\"));
-    }
-
-    private ReferenceWithError<Boolean> waitForWinRmStatus(final boolean requiredStatus, Duration timeout) {
-        // TODO: Reduce / remove duplication between this and JcloudsLocation.waitForWinRmAvailable
-        Callable<Boolean> checker = new Callable<Boolean>() {
-            @Override
-            public Boolean call() throws Exception {
-                try {
-                    return (execute(ImmutableList.of("hostname")) == 0) == requiredStatus;
-                } catch (Exception e) {
-                    return !requiredStatus;
-                }
-            }
-        };
-
-        return new Repeater()
-                .every(1, TimeUnit.SECONDS)
-                .until(checker)
-                .limitTimeTo(timeout)
-                .runKeepingError();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/AbstractVanillaProcess.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/AbstractVanillaProcess.java b/software/base/src/main/java/brooklyn/entity/basic/AbstractVanillaProcess.java
deleted file mode 100644
index 675ff88..0000000
--- a/software/base/src/main/java/brooklyn/entity/basic/AbstractVanillaProcess.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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 brooklyn.entity.basic;
-
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.sensor.core.AttributeSensorAndConfigKey;
-
-public interface AbstractVanillaProcess extends SoftwareProcess {
-    AttributeSensorAndConfigKey<String, String> DOWNLOAD_URL = SoftwareProcess.DOWNLOAD_URL;
-
-    ConfigKey<String> SUGGESTED_VERSION = ConfigKeys.newConfigKeyWithDefault(SoftwareProcess.SUGGESTED_VERSION, "0.0.0");
-    
-    ConfigKey<String> INSTALL_COMMAND = ConfigKeys.newStringConfigKey("install.command", "command to run during the install phase");
-    ConfigKey<String> CUSTOMIZE_COMMAND = ConfigKeys.newStringConfigKey("customize.command", "command to run during the customization phase");
-    ConfigKey<String> LAUNCH_COMMAND = ConfigKeys.newStringConfigKey("launch.command", "command to run to launch the process");
-    ConfigKey<String> CHECK_RUNNING_COMMAND = ConfigKeys.newStringConfigKey("checkRunning.command", "command to determine whether the process is running");
-    ConfigKey<String> STOP_COMMAND = ConfigKeys.newStringConfigKey("stop.command", "command to run to stop the process");
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcess.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcess.java b/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcess.java
deleted file mode 100644
index 2d2c771..0000000
--- a/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcess.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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 brooklyn.entity.basic;
-
-import org.apache.brooklyn.api.entity.ImplementedBy;
-
-@ImplementedBy(EmptySoftwareProcessImpl.class)
-public interface EmptySoftwareProcess extends SoftwareProcess {
-
-    public SoftwareProcessDriver getDriver();
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcessDriver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcessDriver.java b/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcessDriver.java
deleted file mode 100644
index 5a3fac7..0000000
--- a/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcessDriver.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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 brooklyn.entity.basic;
-
-public interface EmptySoftwareProcessDriver extends SoftwareProcessDriver {
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcessImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcessImpl.java b/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcessImpl.java
deleted file mode 100644
index ba86768..0000000
--- a/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcessImpl.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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 brooklyn.entity.basic;
-
-public class EmptySoftwareProcessImpl extends SoftwareProcessImpl implements EmptySoftwareProcess {
-
-    @Override
-    public Class<?> getDriverInterface() {
-        return EmptySoftwareProcessDriver.class;
-    }
-
-    @Override
-    protected void connectSensors() {
-        super.connectSensors();
-        connectServiceUpIsRunning();
-    }
-
-    @Override
-    protected void disconnectSensors() {
-        disconnectServiceUpIsRunning();
-        super.disconnectSensors();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcessSshDriver.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcessSshDriver.java b/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcessSshDriver.java
deleted file mode 100644
index ce1282b..0000000
--- a/software/base/src/main/java/brooklyn/entity/basic/EmptySoftwareProcessSshDriver.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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 brooklyn.entity.basic;
-
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.brooklyn.location.basic.SshMachineLocation;
-
-
-public class EmptySoftwareProcessSshDriver extends AbstractSoftwareProcessSshDriver implements EmptySoftwareProcessDriver {
-
-    private final AtomicBoolean running = new AtomicBoolean();
-
-    public EmptySoftwareProcessSshDriver(EmptySoftwareProcessImpl entity, SshMachineLocation machine) {
-        super(entity, machine);
-    }
-
-    @Override
-    public boolean isRunning() {
-        return running.get();
-    }
-
-    @Override
-    public void install() { }
-
-    @Override
-    public void customize() { }
-
-    @Override
-    public void copyInstallResources() { 
-        Map<String, String> installFiles = entity.getConfig(SoftwareProcess.INSTALL_FILES);
-        Map<String, String> installTemplates = entity.getConfig(SoftwareProcess.INSTALL_TEMPLATES);
-        if ((installFiles!=null && !installFiles.isEmpty()) || (installTemplates!=null && !installTemplates.isEmpty())) {
-            // only do this if there are files, to prevent unnecessary `mkdir`
-            super.copyInstallResources();
-        }
-    }
-
-    @Override
-    public void copyRuntimeResources() { 
-        Map<String, String> runtimeFiles = entity.getConfig(SoftwareProcess.RUNTIME_FILES);
-        Map<String, String> runtimeTemplates = entity.getConfig(SoftwareProcess.RUNTIME_TEMPLATES);
-        if ((runtimeFiles!=null && !runtimeFiles.isEmpty()) || (runtimeTemplates!=null && !runtimeTemplates.isEmpty())) {
-            // only do this if there are files, to prevent unnecessary `mkdir`
-            super.copyRuntimeResources();
-        }        
-    }
-
-    @Override
-    public void launch() {
-        running.set(true);
-    }
-
-    @Override
-    public void rebind() {
-        super.rebind();
-        /* TODO not necessarily, but there is not yet an easy way to persist state without 
-         * using config/sensors which we might not want do. */
-        running.set(true);
-    }
-
-    @Override
-    public void stop() {
-        running.set(false);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/SameServerDriverLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SameServerDriverLifecycleEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/basic/SameServerDriverLifecycleEffectorTasks.java
deleted file mode 100644
index f79c993..0000000
--- a/software/base/src/main/java/brooklyn/entity/basic/SameServerDriverLifecycleEffectorTasks.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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 brooklyn.entity.basic;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.location.MachineLocation;
-import org.apache.brooklyn.api.location.MachineProvisioningLocation;
-import org.apache.brooklyn.api.location.PortRange;
-import org.apache.brooklyn.api.mgmt.TaskAdaptable;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.entity.core.AbstractEntity;
-import org.apache.brooklyn.entity.trait.StartableMethods;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.common.reflect.TypeToken;
-
-import brooklyn.entity.software.MachineLifecycleEffectorTasks;
-
-import org.apache.brooklyn.location.basic.LocationConfigKeys;
-import org.apache.brooklyn.util.collections.MutableSet;
-import org.apache.brooklyn.util.core.flags.TypeCoercions;
-import org.apache.brooklyn.util.core.task.DynamicTasks;
-import org.apache.brooklyn.util.guava.Maybe;
-
-public class SameServerDriverLifecycleEffectorTasks extends MachineLifecycleEffectorTasks {
-
-    private static final Logger LOG = LoggerFactory.getLogger(SameServerDriverLifecycleEffectorTasks.class);
-
-    @Override
-    protected SameServerEntityImpl entity() {
-        return (SameServerEntityImpl) super.entity();
-    }
-
-    /**
-     * @return the ports that this entity wants to use, aggregated for all its child entities.
-     */
-    protected Collection<Integer> getRequiredOpenPorts() {
-        Set<Integer> result = Sets.newLinkedHashSet();
-        result.addAll(getRequiredOpenPorts(entity()));
-        LOG.debug("getRequiredOpenPorts detected aggregated default {} for {}", result, this);
-        return result;
-    }
-
-    /** @return the ports required for a specific child entity */
-    protected Collection<Integer> getRequiredOpenPorts(Entity entity) {
-        Set<Integer> ports = MutableSet.of(22);
-        /* TODO: This won't work if there's a port collision, which will cause the corresponding port attribute
-           to be incremented until a free port is found. In that case the entity will use the free port, but the
-           firewall will open the initial port instead. Mostly a problem for SameServerEntity, localhost location.
-        */
-        // TODO: Remove duplication between this and SoftwareProcessImpl.getRequiredOpenPorts
-        for (ConfigKey<?> k: entity.getEntityType().getConfigKeys()) {
-            Object value;
-            if (PortRange.class.isAssignableFrom(k.getType()) || k.getName().matches(".*\\.port")) {
-                value = entity.config().get(k);
-            } else {
-                // config().get() will cause this to block until all config has been resolved
-                // using config().getRaw(k) means that we won't be able to use e.g. 'http.port: $brooklyn:component("x").attributeWhenReady("foo")'
-                // but that's unlikely to be used
-                Maybe<Object> maybeValue = ((AbstractEntity.BasicConfigurationSupport)entity.config()).getRaw(k);
-                value = maybeValue.isPresent() ? maybeValue.get() : null;
-            }
-
-            Maybe<PortRange> maybePortRange = TypeCoercions.tryCoerce(value, TypeToken.of(PortRange.class));
-
-            if (maybePortRange.isPresentAndNonNull()) {
-                PortRange p = maybePortRange.get();
-                if (p != null && !p.isEmpty()) ports.add(p.iterator().next());
-            }
-        }
-        LOG.debug("getRequiredOpenPorts detected default {} for {}", ports, entity);
-
-        for (Entity child : entity.getChildren()) {
-            ports.addAll(getRequiredOpenPorts(child));
-        }
-        return ports;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    protected Map<String, Object> obtainProvisioningFlags(MachineProvisioningLocation<?> location) {
-        Map<String, Object> result = super.obtainProvisioningFlags(location);
-        result.putAll(obtainProvisioningFlags(entity(), location));
-        Collection<Integer> ports = getRequiredOpenPorts();
-
-        if (result.containsKey("inboundPorts")) {
-            ports.addAll((Collection<Integer>) result.get("inboundPorts"));
-        }
-        if (!ports.isEmpty()) {
-            result.put("inboundPorts", ports);
-        }
-
-        result.put(LocationConfigKeys.CALLER_CONTEXT.getName(), entity());
-        return result;
-    }
-
-    /** @return provisioning flags for the given entity */
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    protected Map<String,Object> obtainProvisioningFlags(Entity entity, MachineProvisioningLocation location) {
-        Map<String,Object> result = Maps.newLinkedHashMap();
-        result.putAll(Maps.newLinkedHashMap(location.getProvisioningFlags(ImmutableList.of(entity.getEntityType().getName()))));
-        result.putAll(entity.getConfig(SameServerEntity.PROVISIONING_PROPERTIES));
-
-        for (Entity child : entity.getChildren()) {
-            result.putAll(obtainProvisioningFlags(child, location));
-        }
-        return result;
-    }
-
-    @Override
-    protected String startProcessesAtMachine(Supplier<MachineLocation> machineS) {
-        DynamicTasks.queueIfPossible(StartableMethods.startingChildren(entity(), machineS.get()))
-                .orSubmitAsync(entity())
-                .getTask()
-                .getUnchecked();
-        DynamicTasks.waitForLast();
-        return "children started";
-    }
-
-    // Also see stopProcessesAtMachine in SoftwareProcessDriverLifecycleEffectorTasks.
-    // Any fixes made there should probably be applied here too.
-    @Override
-    protected String stopProcessesAtMachine() {
-        TaskAdaptable<?> children = StartableMethods.stoppingChildren(entity());
-        DynamicTasks.queue(children);
-        Exception childException = null;
-        try {
-            DynamicTasks.waitForLast();
-        } catch (Exception e) {
-            childException = e;
-        }
-
-        try {
-            children.asTask().get();
-        } catch (Exception e) {
-            childException = e;
-            LOG.debug("Error stopping children; continuing and will rethrow if no other errors", e);
-        }
-
-        if (childException != null)
-            throw new IllegalStateException("error stopping child", childException);
-
-        return "children stopped";
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java b/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java
deleted file mode 100644
index c2ac288..0000000
--- a/software/base/src/main/java/brooklyn/entity/basic/SameServerEntity.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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 brooklyn.entity.basic;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.ImplementedBy;
-import org.apache.brooklyn.api.location.MachineProvisioningLocation;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.entity.core.Attributes;
-import org.apache.brooklyn.entity.lifecycle.Lifecycle;
-import org.apache.brooklyn.entity.lifecycle.ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers;
-import org.apache.brooklyn.entity.trait.Startable;
-import org.apache.brooklyn.sensor.core.BasicAttributeSensor;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.collections.QuorumCheck;
-import org.apache.brooklyn.util.core.flags.SetFromFlag;
-
-import com.google.common.reflect.TypeToken;
-
-/**
- * An entity that, on start({@link MachineProvisioningLocation}), will obtain a machine
- * and pass that to each of its children by calling their {@link Startable#start(java.util.Collection)}
- * methods with that machine.
- * 
- * Thus multiple entities can be set up to run on the same machine.
- * 
- * @author aled
- */
-@ImplementedBy(SameServerEntityImpl.class)
-@SuppressWarnings("serial")
-public interface SameServerEntity extends Entity, Startable {
-
-    @SetFromFlag("provisioningProperties")
-    ConfigKey<Map<String,Object>> PROVISIONING_PROPERTIES = ConfigKeys.newConfigKey(
-            new TypeToken<Map<String, Object>>() {},
-            "provisioning.properties", "Custom properties to be passed in when provisioning a new machine",
-            MutableMap.<String, Object>of());
-    
-    ConfigKey<QuorumCheck> UP_QUORUM_CHECK = ComputeServiceIndicatorsFromChildrenAndMembers.UP_QUORUM_CHECK;
-    ConfigKey<QuorumCheck> RUNNING_QUORUM_CHECK = ComputeServiceIndicatorsFromChildrenAndMembers.RUNNING_QUORUM_CHECK;
-
-    AttributeSensor<Lifecycle> SERVICE_STATE_ACTUAL = Attributes.SERVICE_STATE_ACTUAL;
-
-    @SuppressWarnings("rawtypes")
-    AttributeSensor<MachineProvisioningLocation> PROVISIONING_LOCATION = new BasicAttributeSensor<MachineProvisioningLocation>(
-            MachineProvisioningLocation.class, "softwareservice.provisioningLocation", "Location used to provision a machine where this is running");
-    
-    AttributeSensor<String> HOSTNAME = Attributes.HOSTNAME;
-    
-    AttributeSensor<String> ADDRESS = Attributes.ADDRESS;
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java b/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java
deleted file mode 100644
index 057e6c2..0000000
--- a/software/base/src/main/java/brooklyn/entity/basic/SameServerEntityImpl.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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 brooklyn.entity.basic;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Collection;
-
-import org.apache.brooklyn.api.location.Location;
-import org.apache.brooklyn.api.mgmt.Task;
-import org.apache.brooklyn.entity.core.AbstractEntity;
-import org.apache.brooklyn.entity.core.Entities;
-import org.apache.brooklyn.entity.lifecycle.ServiceStateLogic;
-import org.apache.brooklyn.entity.lifecycle.ServiceStateLogic.ComputeServiceIndicatorsFromChildrenAndMembers;
-import org.apache.brooklyn.util.collections.QuorumCheck;
-import org.apache.brooklyn.util.core.config.ConfigBag;
-import org.apache.brooklyn.util.core.task.DynamicTasks;
-import org.apache.brooklyn.util.core.task.Tasks;
-
-import brooklyn.entity.software.MachineLifecycleEffectorTasks;
-
-public class SameServerEntityImpl extends AbstractEntity implements SameServerEntity {
-
-    private static final MachineLifecycleEffectorTasks LIFECYCLE_TASKS = new SameServerDriverLifecycleEffectorTasks();
-
-    @Override
-    protected void initEnrichers() {
-        super.initEnrichers();
-        
-        // Because can have multiple children (similar to groups/clusters/apps), need to
-        // monitor their health and indicate this has failed if any of them have failed.
-        addEnricher(ServiceStateLogic.newEnricherFromChildren()
-                .configure(ComputeServiceIndicatorsFromChildrenAndMembers.UP_QUORUM_CHECK, QuorumCheck.QuorumChecks.all()));
-    }
-    
-    /**
-     * Restarts the entity and its children.
-     * <p/>
-     * Subclasses should override {@link #doRestart(ConfigBag)} to customise behaviour. */
-    @Override
-    public final void restart() {
-        if (DynamicTasks.getTaskQueuingContext() != null) {
-            doRestart(ConfigBag.EMPTY);
-        } else {
-            Task<?> task = Tasks.builder().name("restart").body(new Runnable() { public void run() { doRestart(ConfigBag.EMPTY); } }).build();
-            Entities.submit(this, task).getUnchecked();
-        }
-    }
-
-    /**
-     * Starts the entity and its children in the given locations.
-     * <p/>
-     * Subclasses should override {@link #doStart} to customise behaviour.
-     */
-    @Override
-    public final void start(final Collection<? extends Location> locations) {
-        checkNotNull(locations, "locations");
-        if (DynamicTasks.getTaskQueuingContext() != null) {
-            doStart(locations);
-        } else {
-            Task<?> task = Tasks.builder().name("start").body(new Runnable() { public void run() { doStart(locations); } }).build();
-            Entities.submit(this, task).getUnchecked();
-        }
-    }
-
-    /**
-     * Stops the entity and its children.
-     * <p/>
-     * Subclasses should override {@link #doStop} to customise behaviour.
-     */
-    @Override
-    public final void stop() {
-        if (DynamicTasks.getTaskQueuingContext() != null) {
-            doStop();
-        } else {
-            Task<?> task = Tasks.builder().name("stop").body(new Runnable() { public void run() { doStop(); } }).build();
-            Entities.submit(this, task).getUnchecked();
-        }
-    }
-
-    /**
-     * To be overridden instead of {@link #start(Collection)}; sub-classes should call
-     * {@code super.doStart(locations)} and should add do additional work via tasks,
-     * executed using {@link DynamicTasks#queue(String, java.util.concurrent.Callable)}.
-     */
-    protected void doStart(Collection<? extends Location> locations) {
-        LIFECYCLE_TASKS.start(locations);
-    }
-
-    /**
-     * To be overridden instead of {@link #stop()}; sub-classes should call {@code
-     * super.doStop()} and should add do additional work via tasks, executed using
-     * {@link DynamicTasks#queue(String, java.util.concurrent.Callable)}.
-     */
-    protected void doStop() {
-        LIFECYCLE_TASKS.stop(ConfigBag.EMPTY);
-    }
-
-    /**
-     * To be overridden instead of {@link #restart()}; sub-classes should call {@code
-     * super.doRestart(ConfigBag)} and should add do additional work via tasks, executed using
-     * {@link DynamicTasks#queue(String, java.util.concurrent.Callable)}.
-     */
-    protected void doRestart(ConfigBag parameters) {
-        LIFECYCLE_TASKS.restart(parameters);
-    }
-
-    @Deprecated /** @deprecated since 0.7.0 subclasses should instead override {@link #doRestart(ConfigBag)} */
-    protected final void doRestart() {
-        doRestart(ConfigBag.EMPTY);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
deleted file mode 100644
index 9fa724b..0000000
--- a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * 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 brooklyn.entity.basic;
-
-import java.util.Collection;
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.location.MachineProvisioningLocation;
-import org.apache.brooklyn.api.sensor.AttributeSensor;
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.core.config.ConfigKeys;
-import org.apache.brooklyn.core.config.MapConfigKey;
-import org.apache.brooklyn.entity.annotation.Effector;
-import org.apache.brooklyn.entity.core.Attributes;
-import org.apache.brooklyn.entity.core.BrooklynConfigKeys;
-import org.apache.brooklyn.entity.lifecycle.Lifecycle;
-import org.apache.brooklyn.entity.lifecycle.Lifecycle.Transition;
-import org.apache.brooklyn.entity.trait.Startable;
-import org.apache.brooklyn.sensor.core.AttributeSensorAndConfigKey;
-import org.apache.brooklyn.sensor.core.Sensors;
-import org.apache.brooklyn.util.collections.MutableMap;
-import org.apache.brooklyn.util.core.flags.SetFromFlag;
-import org.apache.brooklyn.util.time.Duration;
-
-import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.reflect.TypeToken;
-
-public interface SoftwareProcess extends Entity, Startable {
-
-    AttributeSensor<String> HOSTNAME = Attributes.HOSTNAME;
-    AttributeSensor<String> ADDRESS = Attributes.ADDRESS;
-    AttributeSensor<String> SUBNET_HOSTNAME = Attributes.SUBNET_HOSTNAME;
-    AttributeSensor<String> SUBNET_ADDRESS = Attributes.SUBNET_ADDRESS;
-
-    @SuppressWarnings("serial")
-    ConfigKey<Collection<Integer>> REQUIRED_OPEN_LOGIN_PORTS = ConfigKeys.newConfigKey(
-            new TypeToken<Collection<Integer>>() {},
-            "requiredOpenLoginPorts",
-            "The port(s) to be opened, to allow login",
-            ImmutableSet.of(22));
-
-    @SetFromFlag("startTimeout")
-    ConfigKey<Duration> START_TIMEOUT = BrooklynConfigKeys.START_TIMEOUT;
-
-    @SetFromFlag("startLatch")
-    ConfigKey<Boolean> START_LATCH = BrooklynConfigKeys.START_LATCH;
-
-    @SetFromFlag("setupLatch")
-    ConfigKey<Boolean> SETUP_LATCH = BrooklynConfigKeys.SETUP_LATCH;
-
-    @SetFromFlag("installResourcesLatch")
-    ConfigKey<Boolean> INSTALL_RESOURCES_LATCH = BrooklynConfigKeys.INSTALL_RESOURCES_LATCH;
-
-    @SetFromFlag("installLatch")
-    ConfigKey<Boolean> INSTALL_LATCH = BrooklynConfigKeys.INSTALL_LATCH;
-
-    @SetFromFlag("runtimeResourcesLatch")
-    ConfigKey<Boolean> RUNTIME_RESOURCES_LATCH = BrooklynConfigKeys.RUNTIME_RESOURCES_LATCH;
-
-    @SetFromFlag("customizeLatch")
-    ConfigKey<Boolean> CUSTOMIZE_LATCH = BrooklynConfigKeys.CUSTOMIZE_LATCH;
-
-    @SetFromFlag("launchLatch")
-    ConfigKey<Boolean> LAUNCH_LATCH = BrooklynConfigKeys.LAUNCH_LATCH;
-
-    @SetFromFlag("skipStart")
-    ConfigKey<Boolean> ENTITY_STARTED = BrooklynConfigKeys.SKIP_ENTITY_START;
-
-    @SetFromFlag("skipStartIfRunning")
-    ConfigKey<Boolean> SKIP_ENTITY_START_IF_RUNNING = BrooklynConfigKeys.SKIP_ENTITY_START_IF_RUNNING;
-
-    @SetFromFlag("skipInstall")
-    ConfigKey<Boolean> SKIP_INSTALLATION = BrooklynConfigKeys.SKIP_ENTITY_INSTALLATION;
-
-    @SetFromFlag("preInstallCommand")
-    ConfigKey<String> PRE_INSTALL_COMMAND = BrooklynConfigKeys.PRE_INSTALL_COMMAND;
-
-    @SetFromFlag("postInstallCommand")
-    ConfigKey<String> POST_INSTALL_COMMAND = BrooklynConfigKeys.POST_INSTALL_COMMAND;
-
-    @SetFromFlag("preLaunchCommand")
-    ConfigKey<String> PRE_LAUNCH_COMMAND = BrooklynConfigKeys.PRE_LAUNCH_COMMAND;
-
-    @SetFromFlag("postLaunchCommand")
-    ConfigKey<String> POST_LAUNCH_COMMAND = BrooklynConfigKeys.POST_LAUNCH_COMMAND;
-
-    @SetFromFlag("version")
-    ConfigKey<String> SUGGESTED_VERSION = BrooklynConfigKeys.SUGGESTED_VERSION;
-
-    @SetFromFlag("downloadUrl")
-    AttributeSensorAndConfigKey<String,String> DOWNLOAD_URL = Attributes.DOWNLOAD_URL;
-
-    @SetFromFlag("downloadAddonUrls")
-    AttributeSensorAndConfigKey<Map<String,String>,Map<String,String>> DOWNLOAD_ADDON_URLS = Attributes.DOWNLOAD_ADDON_URLS;
-
-    @SetFromFlag("installLabel")
-    ConfigKey<String> INSTALL_UNIQUE_LABEL = BrooklynConfigKeys.INSTALL_UNIQUE_LABEL;
-
-    @SetFromFlag("expandedInstallDir")
-    AttributeSensorAndConfigKey<String,String> EXPANDED_INSTALL_DIR = BrooklynConfigKeys.EXPANDED_INSTALL_DIR;
-
-    @SetFromFlag("installDir")
-    AttributeSensorAndConfigKey<String,String> INSTALL_DIR = BrooklynConfigKeys.INSTALL_DIR;
-    @Deprecated
-    ConfigKey<String> SUGGESTED_INSTALL_DIR = BrooklynConfigKeys.SUGGESTED_INSTALL_DIR;
-
-    @SetFromFlag("runDir")
-    AttributeSensorAndConfigKey<String,String> RUN_DIR = BrooklynConfigKeys.RUN_DIR;
-    @Deprecated
-    ConfigKey<String> SUGGESTED_RUN_DIR = BrooklynConfigKeys.SUGGESTED_RUN_DIR;
-
-    public static final ConfigKey<Boolean> OPEN_IPTABLES = ConfigKeys.newBooleanConfigKey("openIptables", 
-            "Whether to open the INBOUND_PORTS via iptables rules; " +
-            "if true then ssh in to run iptables commands, as part of machine provisioning", false);
-
-    public static final ConfigKey<Boolean> STOP_IPTABLES = ConfigKeys.newBooleanConfigKey("stopIptables", 
-            "Whether to stop iptables entirely; " +
-            "if true then ssh in to stop the iptables service, as part of machine provisioning", false);
-
-    public static final ConfigKey<Boolean> DONT_REQUIRE_TTY_FOR_SUDO = ConfigKeys.newBooleanConfigKey("dontRequireTtyForSudo", 
-            "Whether to explicitly set /etc/sudoers, so don't need tty (will leave unchanged if 'false'); " +
-            "some machines require a tty for sudo; brooklyn by default does not use a tty " +
-            "(so that it can get separate error+stdout streams); you can enable a tty as an " +
-            "option to every ssh command, or you can do it once and " +
-            "modify the machine so that a tty is not subsequently required.",
-            false);
-    
-    /**
-     * Files to be copied to the server before pre-install.
-     * <p>
-     * Map of {@code classpath://foo/file.txt} (or other url) source to destination path,
-     * as {@code subdir/file} relative to installation directory or {@code /absolute/path/to/file}.
-     *
-     * @see #PRE_INSTALL_TEMPLATES
-     */
-    @Beta
-    @SuppressWarnings("serial")
-    @SetFromFlag("preInstallFiles")
-    ConfigKey<Map<String, String>> PRE_INSTALL_FILES = ConfigKeys.newConfigKey(new TypeToken<Map<String, String>>() { },
-            "files.preinstall", "Mapping of files, to be copied before install, to destination name relative to installDir");
-
-    /**
-     * Templates to be filled in and then copied to the server before install.
-     *
-     * @see #PRE_INSTALL_FILES
-     */
-    @Beta
-    @SuppressWarnings("serial")
-    @SetFromFlag("preInstallTemplates")
-    ConfigKey<Map<String, String>> PRE_INSTALL_TEMPLATES = ConfigKeys.newConfigKey(new TypeToken<Map<String, String>>() { },
-            "templates.preinstall", "Mapping of templates, to be filled in and copied before pre-install, to destination name relative to installDir");
-
-    /**
-     * Files to be copied to the server before install.
-     * <p>
-     * Map of {@code classpath://foo/file.txt} (or other url) source to destination path,
-     * as {@code subdir/file} relative to installation directory or {@code /absolute/path/to/file}.
-     *
-     * @see #INSTALL_TEMPLATES
-     */
-    @Beta
-    @SuppressWarnings("serial")
-    @SetFromFlag("installFiles")
-    ConfigKey<Map<String, String>> INSTALL_FILES = ConfigKeys.newConfigKey(new TypeToken<Map<String, String>>() { },
-            "files.install", "Mapping of files, to be copied before install, to destination name relative to installDir");
-
-    /**
-     * Templates to be filled in and then copied to the server before install.
-     *
-     * @see #INSTALL_FILES
-     */
-    @Beta
-    @SuppressWarnings("serial")
-    @SetFromFlag("installTemplates")
-    ConfigKey<Map<String, String>> INSTALL_TEMPLATES = ConfigKeys.newConfigKey(new TypeToken<Map<String, String>>() { },
-            "templates.install", "Mapping of templates, to be filled in and copied before install, to destination name relative to installDir");
-
-    /**
-     * Files to be copied to the server after customisation.
-     * <p>
-     * Map of {@code classpath://foo/file.txt} (or other url) source to destination path,
-     * as {@code subdir/file} relative to runtime directory or {@code /absolute/path/to/file}.
-     *
-     * @see #RUNTIME_TEMPLATES
-     */
-    @Beta
-    @SuppressWarnings("serial")
-    @SetFromFlag("runtimeFiles")
-    ConfigKey<Map<String, String>> RUNTIME_FILES = ConfigKeys.newConfigKey(new TypeToken<Map<String, String>>() { },
-            "files.runtime", "Mapping of files, to be copied before customisation, to destination name relative to runDir");
-
-    /**
-     * Templates to be filled in and then copied to the server after customisation.
-     *
-     * @see #RUNTIME_FILES
-     */
-    @Beta
-    @SuppressWarnings("serial")
-    @SetFromFlag("runtimeTemplates")
-    ConfigKey<Map<String, String>> RUNTIME_TEMPLATES = ConfigKeys.newConfigKey(new TypeToken<Map<String, String>>() { },
-            "templates.runtime", "Mapping of templates, to be filled in and copied before customisation, to destination name relative to runDir");
-
-    @SetFromFlag("env")
-    MapConfigKey<Object> SHELL_ENVIRONMENT = new MapConfigKey<Object>(Object.class,
-            "shell.env", "Map of environment variables to pass to the runtime shell", MutableMap.<String,Object>of());
-
-    @SetFromFlag("provisioningProperties")
-    MapConfigKey<Object> PROVISIONING_PROPERTIES = new MapConfigKey<Object>(Object.class,
-            "provisioning.properties", "Custom properties to be passed in when provisioning a new machine", MutableMap.<String,Object>of());
-
-    @SetFromFlag("maxRebindSensorsDelay")
-    ConfigKey<Duration> MAXIMUM_REBIND_SENSOR_CONNECT_DELAY = ConfigKeys.newConfigKey(Duration.class,
-            "softwareProcess.maxSensorRebindDelay",
-            "The maximum delay to apply when reconnecting sensors when rebinding to this entity. " +
-                    "Brooklyn will wait a random amount of time, up to the value of this config key, to " +
-                    "avoid a thundering herd problem when the entity shares its machine with " +
-                    "several others. Set to null or to 0 to disable any delay.",
-            Duration.TEN_SECONDS);
-
-    /**
-     * Sets the object that manages the sequence of calls of the entity's driver.
-     */
-    @Beta
-    @SetFromFlag("lifecycleEffectorTasks")
-    ConfigKey<SoftwareProcessDriverLifecycleEffectorTasks> LIFECYCLE_EFFECTOR_TASKS = ConfigKeys.newConfigKey(SoftwareProcessDriverLifecycleEffectorTasks.class,
-            "softwareProcess.lifecycleTasks", "An object that handles lifecycle of an entity's associated machine.",
-            new SoftwareProcessDriverLifecycleEffectorTasks());
-
-    ConfigKey<Boolean> RETRIEVE_USAGE_METRICS = ConfigKeys.newBooleanConfigKey(
-            "metrics.usage.retrieve",
-            "Whether to retrieve the usage (e.g. performance) metrics",
-            true);
-
-    /** Controls the behavior when starting (stop, restart) {@link Startable} children as part of the start (stop, restart) effector on this entity
-     * <p>
-     * (NB: restarts are currently not propagated to children in the default {@link SoftwareProcess}
-     * due to the various semantics which may be desired; this may change, but if entities have specific requirements for restart,
-     * developers should either subclass the {@link SoftwareProcessDriverLifecycleEffectorTasks} and/or lean on sensors from the parent */
-    enum ChildStartableMode {
-        /** do nothing with {@link Startable} children */
-        NONE(true, false, false),
-        /** start (stop) {@link Startable} children concurrent with *driver* start (stop),
-         * in foreground, so invoking entity will wait for children to complete.
-         * <p>
-         * if the child requires the parent to reach a particular state before acting,
-         * when running in foreground the parent should communicate its state using sensors
-         * which the child listens for.
-         * note that often sensors at the parent are not activated until it is started,
-         * so the usual sensors connected at an entity may not be available when running in this mode */
-        FOREGROUND(false, false, false),
-        /** as {@link #FOREGROUND} but {@link ChildStartableMode#isLate} */
-        FOREGROUND_LATE(false, false, true),
-        /** start {@link Startable} children concurrent with *driver* start (stop, restart),
-         * but in background, ie disassociated from the effector task at this entity
-         * (so that this entity can complete start/stop independent of children) */
-        BACKGROUND(false, true, false),
-        /** as {@link #BACKGROUND} but {@link ChildStartableMode#isLate} */
-        BACKGROUND_LATE(false, true, true);
-
-        /** whether starting (stopping, restarting) children is disabled */
-        public final boolean isDisabled;
-        /** whether starting (stopping, restarting) children is backgrounded, so parent should not wait on them */
-        public final boolean isBackground;
-        /** whether starting (stopping, restarting) children should be nested, so start occurs after the driver is started,
-         * and stop before the driver is stopped (if false the children operations are concurrent with the parent),
-         * (with restart always being done in parallel though this behaviour may change) */
-        public final boolean isLate;
-
-        private ChildStartableMode(boolean isDisabled, boolean isBackground, boolean isLate) {
-            this.isDisabled = isDisabled;
-            this.isBackground = isBackground;
-            this.isLate = isLate;
-        }
-
-    }
-
-    @SetFromFlag("childStartMode")
-    ConfigKey<ChildStartableMode> CHILDREN_STARTABLE_MODE = ConfigKeys.newConfigKey(ChildStartableMode.class,
-            "children.startable.mode", "Controls behaviour when starting Startable children as part of this entity's lifecycle.",
-            ChildStartableMode.NONE);
-
-    @SuppressWarnings("rawtypes")
-    AttributeSensor<MachineProvisioningLocation> PROVISIONING_LOCATION = Sensors.newSensor(
-            MachineProvisioningLocation.class, "softwareservice.provisioningLocation", "Location used to provision a machine where this is running");
-
-    AttributeSensor<Boolean> SERVICE_PROCESS_IS_RUNNING = Sensors.newBooleanSensor("service.process.isRunning", 
-            "Whether the process for the service is confirmed as running");
-    
-    AttributeSensor<Lifecycle> SERVICE_STATE_ACTUAL = Attributes.SERVICE_STATE_ACTUAL;
-    AttributeSensor<Transition> SERVICE_STATE_EXPECTED = Attributes.SERVICE_STATE_EXPECTED;
- 
-    AttributeSensor<String> PID_FILE = Sensors.newStringSensor("softwareprocess.pid.file", "PID file");
-
-    @Beta
-    public static class RestartSoftwareParameters {
-        @Beta /** @since 0.7.0 semantics of parameters to restart being explored */
-        public static final ConfigKey<Boolean> RESTART_CHILDREN = ConfigKeys.newConfigKey(Boolean.class, "restartChildren",
-            "Whether to restart children; default false", false);
-
-        @Beta /** @since 0.7.0 semantics of parameters to restart being explored */
-        public static final ConfigKey<Object> RESTART_MACHINE = ConfigKeys.newConfigKey(Object.class, "restartMachine",
-            "Whether to restart/replace the machine provisioned for this entity:  'true', 'false', or 'auto' are supported, "
-            + "with the default being 'auto' which means to restart or reprovision the machine if there is no simpler way known to restart the entity "
-            + "(for example, if the machine is unhealthy, it would not be possible to restart the process, not even via a stop-then-start sequence); "
-            + "if the machine was not provisioned for this entity, this parameter has no effect", 
-            RestartMachineMode.AUTO.toString().toLowerCase());
-        
-        // we supply a typed variant for retrieval; we want the untyped (above) to use lower case as the default in the GUI
-        // (very hard if using enum, since enum takes the name, and RendererHints do not apply to parameters) 
-        @Beta /** @since 0.7.0 semantics of parameters to restart being explored */
-        public static final ConfigKey<RestartMachineMode> RESTART_MACHINE_TYPED = ConfigKeys.newConfigKey(RestartMachineMode.class, "restartMachine");
-            
-        public enum RestartMachineMode { TRUE, FALSE, AUTO }
-    }
-
-    @Beta
-    public static class StopSoftwareParameters {
-        //IF_NOT_STOPPED includes STARTING, STOPPING, RUNNING
-        public enum StopMode { ALWAYS, IF_NOT_STOPPED, NEVER };
-
-        @Beta /** @since 0.7.0 semantics of parameters to restart being explored */
-        public static final ConfigKey<StopMode> STOP_PROCESS_MODE = ConfigKeys.newConfigKey(StopMode.class, "stopProcessMode",
-                "When to stop the process with regard to the entity state. " +
-                "ALWAYS will try to stop the process even if the entity is marked as stopped, " +
-                "IF_NOT_STOPPED stops the process only if the entity is not marked as stopped, " +
-                "NEVER doesn't stop the process.", StopMode.IF_NOT_STOPPED);
-
-        @Beta /** @since 0.7.0 semantics of parameters to restart being explored */
-        public static final ConfigKey<StopMode> STOP_MACHINE_MODE = ConfigKeys.newConfigKey(StopMode.class, "stopMachineMode",
-                "When to stop the machine with regard to the entity state. " +
-                "ALWAYS will try to stop the machine even if the entity is marked as stopped, " +
-                "IF_NOT_STOPPED stops the machine only if the entity is not marked as stopped, " +
-                "NEVER doesn't stop the machine.", StopMode.IF_NOT_STOPPED);
-    }
-    
-    // NB: the START, STOP, and RESTART effectors themselves are (re)defined by MachineLifecycleEffectorTasks
-
-    /**
-     * @since 0.8.0
-     */
-    @Effector(description="Populates the attribute service.notUp.diagnostics, with any available health indicators")
-    @Beta
-    void populateServiceNotUpDiagnostics();
-}