http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriver.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriver.java b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriver.java deleted file mode 100644 index bd3d8b3..0000000 --- a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriver.java +++ /dev/null @@ -1,75 +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.drivers.EntityDriver; -import org.apache.brooklyn.api.internal.EntityLocal; -import org.apache.brooklyn.entity.trait.Startable; - -/** - * The {@link EntityDriver} for a {@link SoftwareProcess}. - * - * <p/> - * In many cases it is cleaner to store entity lifecycle effectors (and sometimes other implementations) in a class to - * which the entity delegates. Classes implementing this interface provide this delegate, often inheriting utilities - * specific to a particular transport (e.g. ssh) shared among many different entities. - * <p/> - * In this way, it is also possible for entities to cleanly support multiple mechanisms for start/stop and other methods. - */ -public interface SoftwareProcessDriver extends EntityDriver { - - /** - * The entity whose components we are controlling. - */ - EntityLocal getEntity(); - - /** - * Whether the entity components have started. - */ - boolean isRunning(); - - /** - * Rebinds the driver to a pre-existing software process. - */ - void rebind(); - - /** - * Performs software start (or queues tasks to do this) - */ - void start(); - - /** - * Performs software restart (or queues tasks to do this). - * Unlike stop/start implementations here are expected to update SERVICE_STATE for STOPPING and STARTING - * as appropriate (but framework will set RUNNING afterwards, after detecting it is running). - * @see Startable#restart() - */ - void restart(); - - /** - * Performs software stop (or queues tasks to do this) - * @see Startable#stop() - */ - void stop(); - - /** - * Kills the process, ungracefully and immediately where possible (e.g. with `kill -9`). - */ - void kill(); -}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriverLifecycleEffectorTasks.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriverLifecycleEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriverLifecycleEffectorTasks.java deleted file mode 100644 index 5ce7667..0000000 --- a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessDriverLifecycleEffectorTasks.java +++ /dev/null @@ -1,262 +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.location.MachineLocation; -import org.apache.brooklyn.api.location.MachineProvisioningLocation; -import org.apache.brooklyn.api.mgmt.TaskAdaptable; -import org.apache.brooklyn.entity.core.Attributes; -import org.apache.brooklyn.entity.core.Entities; -import org.apache.brooklyn.entity.lifecycle.Lifecycle; -import org.apache.brooklyn.entity.lifecycle.ServiceStateLogic; -import org.apache.brooklyn.entity.trait.StartableMethods; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.core.task.DynamicTasks; -import org.apache.brooklyn.util.text.Strings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.entity.basic.SoftwareProcess.ChildStartableMode; -import brooklyn.entity.basic.SoftwareProcess.RestartSoftwareParameters; -import brooklyn.entity.basic.SoftwareProcess.RestartSoftwareParameters.RestartMachineMode; -import brooklyn.entity.software.MachineLifecycleEffectorTasks; - -import com.google.common.annotations.Beta; -import com.google.common.base.Supplier; - -/** Thin shim delegating to driver to do start/stop/restart, wrapping as tasks, - * with common code pulled up to {@link MachineLifecycleEffectorTasks} for non-driver usage - * @since 0.6.0 */ -@Beta -public class SoftwareProcessDriverLifecycleEffectorTasks extends MachineLifecycleEffectorTasks { - - private static final Logger log = LoggerFactory.getLogger(SoftwareProcessDriverLifecycleEffectorTasks.class); - - public void restart(ConfigBag parameters) { - RestartMachineMode isRestartMachine = parameters.get(RestartSoftwareParameters.RESTART_MACHINE_TYPED); - if (isRestartMachine==null) - isRestartMachine=RestartMachineMode.AUTO; - if (isRestartMachine==RestartMachineMode.AUTO) - isRestartMachine = getDefaultRestartStopsMachine() ? RestartMachineMode.TRUE : RestartMachineMode.FALSE; - - if (isRestartMachine==RestartMachineMode.TRUE) { - log.debug("restart of "+entity()+" requested be applied at machine level"); - super.restart(parameters); - return; - } - - DynamicTasks.queue("pre-restart", new PreRestartTask()); - - log.debug("restart of "+entity()+" appears to have driver and hostname - doing driver-level restart"); - entity().getDriver().restart(); - - restartChildren(parameters); - - DynamicTasks.queue("post-restart", new PostRestartTask()); - } - - private class PreRestartTask implements Runnable { - @Override - public void run() { - preRestartCustom(); - } - } - - private class PostRestartTask implements Runnable { - @Override - public void run() { - postStartCustom(); - postRestartCustom(); - ServiceStateLogic.setExpectedState(entity(), Lifecycle.RUNNING); - } - } - - @Override - protected boolean getDefaultRestartStopsMachine() { - if (entity().getDriver() == null) { - log.debug("restart of "+entity()+" has no driver - doing machine-level restart"); - return true; - } - - if (Strings.isEmpty(entity().getAttribute(Attributes.HOSTNAME))) { - log.debug("restart of "+entity()+" has no hostname - doing machine-level restart"); - return true; - } - - return false; - } - - @Override - protected SoftwareProcessImpl entity() { - return (SoftwareProcessImpl) super.entity(); - } - - @Override - protected Map<String, Object> obtainProvisioningFlags(final MachineProvisioningLocation<?> location) { - return entity().obtainProvisioningFlags(location); - } - - @Override - protected void preStartCustom(MachineLocation machine) { - entity().initDriver(machine); - - // Note: must only apply config-sensors after adding to locations and creating driver; - // otherwise can't do things like acquire free port from location, or allowing driver to set up ports - super.preStartCustom(machine); - - entity().preStart(); - } - - /** returns how children startables should be handled (reporting none for efficiency if there are no children) */ - protected ChildStartableMode getChildrenStartableModeEffective() { - if (entity().getChildren().isEmpty()) return ChildStartableMode.NONE; - ChildStartableMode result = entity().getConfig(SoftwareProcess.CHILDREN_STARTABLE_MODE); - if (result!=null) return result; - return ChildStartableMode.NONE; - } - - @Override - protected String startProcessesAtMachine(final Supplier<MachineLocation> machineS) { - ChildStartableMode mode = getChildrenStartableModeEffective(); - TaskAdaptable<?> children = null; - if (!mode.isDisabled) { - children = StartableMethods.startingChildren(entity(), machineS.get()); - // submit rather than queue so it runs in parallel - // (could also wrap as parallel task with driver.start() - - // but only benefit is that child starts show as child task, - // rather than bg task, so not worth the code complexity) - if (!mode.isLate) Entities.submit(entity(), children); - } - - entity().getDriver().start(); - String result = "Started with driver "+entity().getDriver(); - - if (!mode.isDisabled) { - if (mode.isLate) { - DynamicTasks.waitForLast(); - if (mode.isBackground) { - Entities.submit(entity(), children); - } else { - // when running foreground late, there is no harm here in queueing - DynamicTasks.queue(children); - } - } - if (!mode.isBackground) children.asTask().getUnchecked(); - result += "; children started "+mode; - } - return result; - } - - @Override - protected void postStartCustom() { - entity().postDriverStart(); - if (entity().connectedSensors) { - // many impls aren't idempotent - though they should be! - log.debug("skipping connecting sensors for "+entity()+" in driver-tasks postStartCustom because already connected (e.g. restarting)"); - } else { - log.debug("connecting sensors for "+entity()+" in driver-tasks postStartCustom because already connected (e.g. restarting)"); - entity().connectSensors(); - } - entity().waitForServiceUp(); - entity().postStart(); - } - - @Override - protected void preStopConfirmCustom() { - super.preStopConfirmCustom(); - - entity().preStopConfirmCustom(); - } - - @Override - protected void preStopCustom() { - super.preStopCustom(); - - entity().preStop(); - } - - @Override - protected void preRestartCustom() { - super.preRestartCustom(); - - entity().preRestart(); - } - - @Override - protected void postRestartCustom() { - super.postRestartCustom(); - - entity().postRestart(); - } - - @Override - protected String stopProcessesAtMachine() { - String result; - - ChildStartableMode mode = getChildrenStartableModeEffective(); - TaskAdaptable<?> children = null; - Exception childException = null; - - if (!mode.isDisabled) { - children = StartableMethods.stoppingChildren(entity()); - - if (mode.isBackground || !mode.isLate) Entities.submit(entity(), children); - else { - DynamicTasks.queue(children); - try { - DynamicTasks.waitForLast(); - } catch (Exception e) { - childException = e; - } - } - } - - if (entity().getDriver() != null) { - entity().getDriver().stop(); - result = "Driver stop completed"; - } else { - result = "No driver (nothing to do here)"; - } - - if (!mode.isDisabled && !mode.isBackground) { - 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(result+"; but error stopping child: "+childException, childException); - - return result; - } - - @Override - protected void postStopCustom() { - super.postStopCustom(); - - entity().postStop(); - } - -} - http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java deleted file mode 100644 index bb9717e..0000000 --- a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcessImpl.java +++ /dev/null @@ -1,651 +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 groovy.time.TimeDuration; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.drivers.DriverDependentEntity; -import org.apache.brooklyn.api.entity.drivers.EntityDriverManager; -import org.apache.brooklyn.api.internal.EntityLocal; -import org.apache.brooklyn.api.location.Location; -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.Task; -import org.apache.brooklyn.api.sensor.EnricherSpec; -import org.apache.brooklyn.api.sensor.SensorEvent; -import org.apache.brooklyn.api.sensor.SensorEventListener; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.entity.core.AbstractEntity; -import org.apache.brooklyn.entity.core.Attributes; -import org.apache.brooklyn.entity.core.BrooklynConfigKeys; -import org.apache.brooklyn.entity.core.Entities; -import org.apache.brooklyn.entity.lifecycle.Lifecycle; -import org.apache.brooklyn.entity.lifecycle.ServiceStateLogic; -import org.apache.brooklyn.entity.lifecycle.Lifecycle.Transition; -import org.apache.brooklyn.entity.lifecycle.ServiceStateLogic.ServiceNotUpLogic; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.brooklyn.location.basic.LocationConfigKeys; -import org.apache.brooklyn.location.basic.SshMachineLocation; -import org.apache.brooklyn.location.cloud.CloudLocationConfig; -import org.apache.brooklyn.sensor.enricher.AbstractEnricher; -import org.apache.brooklyn.sensor.feed.function.FunctionFeed; -import org.apache.brooklyn.sensor.feed.function.FunctionPollConfig; -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.collections.MutableSet; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.core.flags.TypeCoercions; -import org.apache.brooklyn.util.core.task.DynamicTasks; -import org.apache.brooklyn.util.core.task.Tasks; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.guava.Maybe; -import org.apache.brooklyn.util.time.CountdownTimer; -import org.apache.brooklyn.util.time.Duration; -import org.apache.brooklyn.util.time.Time; - -import com.google.common.base.Functions; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; -import com.google.common.reflect.TypeToken; - -/** - * An {@link Entity} representing a piece of software which can be installed, run, and controlled. - * A single such entity can only run on a single {@link MachineLocation} at a time (you can have multiple on the machine). - * It typically takes config keys for suggested versions, filesystem locations to use, and environment variables to set. - * <p> - * It exposes sensors for service state (Lifecycle) and status (String), and for host info, log file location. - */ -public abstract class SoftwareProcessImpl extends AbstractEntity implements SoftwareProcess, DriverDependentEntity { - private static final Logger log = LoggerFactory.getLogger(SoftwareProcessImpl.class); - - private transient SoftwareProcessDriver driver; - - /** @see #connectServiceUpIsRunning() */ - private volatile FunctionFeed serviceProcessIsRunning; - - protected boolean connectedSensors = false; - - public SoftwareProcessImpl() { - super(MutableMap.of(), null); - } - public SoftwareProcessImpl(Entity parent) { - this(MutableMap.of(), parent); - } - public SoftwareProcessImpl(Map properties) { - this(properties, null); - } - public SoftwareProcessImpl(Map properties, Entity parent) { - super(properties, parent); - } - - protected void setProvisioningLocation(MachineProvisioningLocation val) { - if (getAttribute(PROVISIONING_LOCATION) != null) throw new IllegalStateException("Cannot change provisioning location: existing="+getAttribute(PROVISIONING_LOCATION)+"; new="+val); - setAttribute(PROVISIONING_LOCATION, val); - } - - protected MachineProvisioningLocation getProvisioningLocation() { - return getAttribute(PROVISIONING_LOCATION); - } - - @Override - public SoftwareProcessDriver getDriver() { - return driver; - } - - protected SoftwareProcessDriver newDriver(MachineLocation loc){ - EntityDriverManager entityDriverManager = getManagementContext().getEntityDriverManager(); - return (SoftwareProcessDriver)entityDriverManager.build(this, loc); - } - - protected MachineLocation getMachineOrNull() { - return Iterables.get(Iterables.filter(getLocations(), MachineLocation.class), 0, null); - } - - @Override - public void init() { - super.init(); - getLifecycleEffectorTasks().attachLifecycleEffectors(this); - } - - @Override - protected void initEnrichers() { - super.initEnrichers(); - ServiceNotUpLogic.updateNotUpIndicator(this, SERVICE_PROCESS_IS_RUNNING, "No information yet on whether this service is running"); - // add an indicator above so that if is_running comes through, the map is cleared and an update is guaranteed - addEnricher(EnricherSpec.create(UpdatingNotUpFromServiceProcessIsRunning.class).uniqueTag("service-process-is-running-updating-not-up")); - addEnricher(EnricherSpec.create(ServiceNotUpDiagnosticsCollector.class).uniqueTag("service-not-up-diagnostics-collector")); - } - - /** - * @since 0.8.0 - */ - protected static class ServiceNotUpDiagnosticsCollector extends AbstractEnricher implements SensorEventListener<Object> { - public ServiceNotUpDiagnosticsCollector() { - } - - @Override - public void setEntity(EntityLocal entity) { - super.setEntity(entity); - if (!(entity instanceof SoftwareProcess)) { - throw new IllegalArgumentException("Expected SoftwareProcess, but got entity "+entity); - } - subscribe(entity, Attributes.SERVICE_UP, this); - onUpdated(); - } - - @Override - public void onEvent(SensorEvent<Object> event) { - onUpdated(); - } - - protected void onUpdated() { - Boolean up = entity.getAttribute(SERVICE_UP); - if (up == null || up) { - entity.setAttribute(ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, ImmutableMap.<String, Object>of()); - } else { - ((SoftwareProcess)entity).populateServiceNotUpDiagnostics(); - } - } - } - - @Override - public void populateServiceNotUpDiagnostics() { - if (getDriver() == null) { - ServiceStateLogic.updateMapSensorEntry(this, ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, "driver", "No driver"); - return; - } - - Location loc = getDriver().getLocation(); - if (loc instanceof SshMachineLocation) { - if (!((SshMachineLocation)loc).isSshable()) { - ServiceStateLogic.updateMapSensorEntry( - this, - ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, - "sshable", - "The machine for this entity does not appear to be sshable"); - } - return; - } - - boolean processIsRunning = getDriver().isRunning(); - if (!processIsRunning) { - ServiceStateLogic.updateMapSensorEntry( - this, - ServiceStateLogic.SERVICE_NOT_UP_DIAGNOSTICS, - SERVICE_PROCESS_IS_RUNNING.getName(), - "The software process for this entity does not appear to be running"); - } - } - - /** subscribes to SERVICE_PROCESS_IS_RUNNING and SERVICE_UP; the latter has no effect if the former is set, - * but to support entities which set SERVICE_UP directly we want to make sure that the absence of - * SERVICE_PROCESS_IS_RUNNING does not trigger any not-up indicators */ - protected static class UpdatingNotUpFromServiceProcessIsRunning extends AbstractEnricher implements SensorEventListener<Object> { - public UpdatingNotUpFromServiceProcessIsRunning() {} - - @Override - public void setEntity(EntityLocal entity) { - super.setEntity(entity); - subscribe(entity, SERVICE_PROCESS_IS_RUNNING, this); - subscribe(entity, Attributes.SERVICE_UP, this); - onUpdated(); - } - - @Override - public void onEvent(SensorEvent<Object> event) { - onUpdated(); - } - - protected void onUpdated() { - Boolean isRunning = entity.getAttribute(SERVICE_PROCESS_IS_RUNNING); - if (Boolean.FALSE.equals(isRunning)) { - ServiceNotUpLogic.updateNotUpIndicator(entity, SERVICE_PROCESS_IS_RUNNING, "The software process for this entity does not appear to be running"); - return; - } - if (Boolean.TRUE.equals(isRunning)) { - ServiceNotUpLogic.clearNotUpIndicator(entity, SERVICE_PROCESS_IS_RUNNING); - return; - } - // no info on "isRunning" - Boolean isUp = entity.getAttribute(Attributes.SERVICE_UP); - if (Boolean.TRUE.equals(isUp)) { - // if service explicitly set up, then don't apply our rule - ServiceNotUpLogic.clearNotUpIndicator(entity, SERVICE_PROCESS_IS_RUNNING); - return; - } - // service not up, or no info - ServiceNotUpLogic.updateNotUpIndicator(entity, SERVICE_PROCESS_IS_RUNNING, "No information on whether this service is running"); - } - } - - /** - * Called before driver.start; guarantees the driver will exist, and locations will have been set. - */ - protected void preStart() { - } - - /** - * Called after driver.start(). Default implementation is to wait to confirm the driver - * definitely started the process. - */ - protected void postDriverStart() { - waitForEntityStart(); - } - - /** - * For binding to the running app (e.g. connecting sensors to registry). Will be called - * on start() and on rebind(). - * <p> - * Implementations should be idempotent (ie tell whether sensors already connected), - * though the framework is pretty good about not calling when already connected. - * TODO improve the framework's feed system to detect duplicate additions - */ - protected void connectSensors() { - connectedSensors = true; - } - - /** - * For connecting the {@link #SERVICE_UP} sensor to the value of the {@code getDriver().isRunning()} expression. - * <p> - * Should be called inside {@link #connectSensors()}. - * - * @see #disconnectServiceUpIsRunning() - */ - protected void connectServiceUpIsRunning() { - serviceProcessIsRunning = FunctionFeed.builder() - .entity(this) - .period(Duration.FIVE_SECONDS) - .poll(new FunctionPollConfig<Boolean, Boolean>(SERVICE_PROCESS_IS_RUNNING) - .suppressDuplicates(true) - .onException(Functions.constant(Boolean.FALSE)) - .callable(new Callable<Boolean>() { - public Boolean call() { - return getDriver().isRunning(); - } - })) - .build(); - } - - /** - * For disconnecting the {@link #SERVICE_UP} feed. - * <p> - * Should be called from {@link #disconnectSensors()}. - * - * @see #connectServiceUpIsRunning() - */ - protected void disconnectServiceUpIsRunning() { - if (serviceProcessIsRunning != null) serviceProcessIsRunning.stop(); - // set null so the SERVICE_UP enricher runs (possibly removing it), then remove so everything is removed - // TODO race because the is-running check may be mid-task - setAttribute(SERVICE_PROCESS_IS_RUNNING, null); - removeAttribute(SERVICE_PROCESS_IS_RUNNING); - } - - /** - * Called after the rest of start has completed (after {@link #connectSensors()} and {@link #waitForServiceUp()}) - */ - protected void postStart() { - } - - protected void preStopConfirmCustom() { - } - - protected void preStop() { - // note asymmetry that disconnectSensors is done in the entity not the driver - // whereas on start the *driver* calls connectSensors, before calling postStart, - // ie waiting for the entity truly to be started before calling postStart; - // TODO feels like that confusion could be eliminated with a single place for pre/post logic!) - log.debug("disconnecting sensors for "+this+" in entity.preStop"); - disconnectSensors(); - - // Must set the serviceProcessIsRunning explicitly to false - we've disconnected the sensors - // so nothing else will. - // Otherwise, if restarted, there will be no change to serviceProcessIsRunning, so the - // serviceUpIndicators will not change, so serviceUp will not be reset. - // TODO Is there a race where disconnectSensors could leave a task of the feeds still running - // which could set serviceProcessIsRunning to true again before the task completes and the feed - // is fully terminated? - setAttribute(SoftwareProcess.SERVICE_PROCESS_IS_RUNNING, false); - } - - /** - * Called after the rest of stop has completed (after VM deprovisioned, but before state set to STOPPED) - */ - protected void postStop() { - } - - /** - * Called before driver.restart; guarantees the driver will exist, and locations will have been set. - */ - protected void preRestart() { - } - - protected void postRestart() { - } - - /** - * For disconnecting from the running app. Will be called on stop. - */ - protected void disconnectSensors() { - connectedSensors = false; - } - - /** - * Called after this entity is fully rebound (i.e. it is fully managed). - */ - protected void postRebind() { - } - - protected void callRebindHooks() { - Duration configuredMaxDelay = getConfig(MAXIMUM_REBIND_SENSOR_CONNECT_DELAY); - if (configuredMaxDelay == null || Duration.ZERO.equals(configuredMaxDelay)) { - connectSensors(); - } else { - long delay = (long) (Math.random() * configuredMaxDelay.toMilliseconds()); - log.debug("Scheduled reconnection of sensors on {} in {}ms", this, delay); - Timer timer = new Timer(); - timer.schedule(new TimerTask() { - @Override public void run() { - try { - if (getManagementSupport().isNoLongerManaged()) { - log.debug("Entity {} no longer managed; ignoring scheduled connect sensors on rebind", SoftwareProcessImpl.this); - return; - } - connectSensors(); - } catch (Throwable e) { - log.warn("Problem connecting sensors on rebind of "+SoftwareProcessImpl.this, e); - Exceptions.propagateIfFatal(e); - } - } - }, delay); - } - // don't wait here - it may be long-running, e.g. if remote entity has died, and we don't want to block rebind waiting or cause it to fail - // the service will subsequently show service not up and thus failure -// waitForServiceUp(); - } - - @Override - public void onManagementStarting() { - super.onManagementStarting(); - - Lifecycle state = getAttribute(SERVICE_STATE_ACTUAL); - if (state == null || state == Lifecycle.CREATED) { - // Expect this is a normal start() sequence (i.e. start() will subsequently be called) - setAttribute(SERVICE_UP, false); - ServiceStateLogic.setExpectedState(this, Lifecycle.CREATED); - // force actual to be created because this is expected subsequently - setAttribute(SERVICE_STATE_ACTUAL, Lifecycle.CREATED); - } - } - - @Override - public void onManagementStarted() { - super.onManagementStarted(); - - Lifecycle state = getAttribute(SERVICE_STATE_ACTUAL); - if (state != null && state != Lifecycle.CREATED) { - postRebind(); - } - } - - @Override - public void rebind() { - //SERVICE_STATE_ACTUAL might be ON_FIRE due to a temporary condition (problems map non-empty) - //Only if the expected state is ON_FIRE then the entity has permanently failed. - Transition expectedState = getAttribute(SERVICE_STATE_EXPECTED); - if (expectedState == null || expectedState.getState() != Lifecycle.RUNNING) { - log.warn("On rebind of {}, not calling software process rebind hooks because expected state is {}", this, expectedState); - return; - } - - Lifecycle actualState = getAttribute(SERVICE_STATE_ACTUAL); - if (actualState == null || actualState != Lifecycle.RUNNING) { - log.warn("Rebinding entity {}, even though actual state is {}. Expected state is {}", new Object[] {this, actualState, expectedState}); - } - - // e.g. rebinding to a running instance - // FIXME For rebind, what to do about things in STARTING or STOPPING state? - // FIXME What if location not set? - log.info("Rebind {} connecting to pre-running service", this); - - MachineLocation machine = getMachineOrNull(); - if (machine != null) { - initDriver(machine); - driver.rebind(); - if (log.isDebugEnabled()) log.debug("On rebind of {}, re-created driver {}", this, driver); - } else { - log.info("On rebind of {}, no MachineLocation found (with locations {}) so not generating driver", - this, getLocations()); - } - - callRebindHooks(); - } - - public void waitForServiceUp() { - Duration timeout = getConfig(BrooklynConfigKeys.START_TIMEOUT); - waitForServiceUp(timeout); - } - public void waitForServiceUp(Duration duration) { - Entities.waitForServiceUp(this, duration); - } - public void waitForServiceUp(TimeDuration duration) { - waitForServiceUp(duration.toMilliseconds(), TimeUnit.MILLISECONDS); - } - public void waitForServiceUp(long duration, TimeUnit units) { - Entities.waitForServiceUp(this, Duration.of(duration, units)); - } - - protected Map<String,Object> obtainProvisioningFlags(MachineProvisioningLocation location) { - ConfigBag result = ConfigBag.newInstance(location.getProvisioningFlags(ImmutableList.of(getClass().getName()))); - result.putAll(getConfig(PROVISIONING_PROPERTIES)); - if (result.get(CloudLocationConfig.INBOUND_PORTS) == null) { - Collection<Integer> ports = getRequiredOpenPorts(); - Object requiredPorts = result.get(CloudLocationConfig.ADDITIONAL_INBOUND_PORTS); - if (requiredPorts instanceof Integer) { - ports.add((Integer) requiredPorts); - } else if (requiredPorts instanceof Iterable) { - for (Object o : (Iterable<?>) requiredPorts) { - if (o instanceof Integer) ports.add((Integer) o); - } - } - if (ports != null && ports.size() > 0) result.put(CloudLocationConfig.INBOUND_PORTS, ports); - } - result.put(LocationConfigKeys.CALLER_CONTEXT, this); - return result.getAllConfigMutable(); - } - - /** returns the ports that this entity wants to use; - * default implementation returns {@link SoftwareProcess#REQUIRED_OPEN_LOGIN_PORTS} plus first value - * for each {@link org.apache.brooklyn.sensor.core.PortAttributeSensorAndConfigKey} config key {@link PortRange} - * plus any ports defined with a config keys ending in {@code .port}. - */ - protected Collection<Integer> getRequiredOpenPorts() { - Set<Integer> ports = MutableSet.copyOf(getConfig(REQUIRED_OPEN_LOGIN_PORTS)); - Map<ConfigKey<?>, ?> allConfig = config().getBag().getAllConfigAsConfigKeyMap(); - Set<ConfigKey<?>> configKeys = Sets.newHashSet(allConfig.keySet()); - configKeys.addAll(getEntityType().getConfigKeys()); - - /* 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. - */ - for (ConfigKey<?> k: configKeys) { - Object value; - if (PortRange.class.isAssignableFrom(k.getType()) || k.getName().matches(".*\\.port")) { - value = 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 = config().getRaw(k); - value = maybeValue.isPresent() ? maybeValue.get() : null; - } - - Maybe<PortRange> maybePortRange = TypeCoercions.tryCoerce(value, new TypeToken<PortRange>() {}); - - if (maybePortRange.isPresentAndNonNull()) { - PortRange p = maybePortRange.get(); - if (p != null && !p.isEmpty()) ports.add(p.iterator().next()); - } - } - - log.debug("getRequiredOpenPorts detected default {} for {}", ports, this); - return ports; - } - - protected void initDriver(MachineLocation machine) { - SoftwareProcessDriver newDriver = doInitDriver(machine); - if (newDriver == null) { - throw new UnsupportedOperationException("cannot start "+this+" on "+machine+": no driver available"); - } - driver = newDriver; - } - - /** - * Creates the driver (if does not already exist or needs replaced for some reason). Returns either the existing driver - * or a new driver. Must not return null. - */ - protected SoftwareProcessDriver doInitDriver(MachineLocation machine) { - if (driver!=null) { - if ((driver instanceof AbstractSoftwareProcessDriver) && machine.equals(((AbstractSoftwareProcessDriver)driver).getLocation())) { - return driver; //just reuse - } else { - log.warn("driver/location change is untested for {} at {}; changing driver and continuing", this, machine); - return newDriver(machine); - } - } else { - return newDriver(machine); - } - } - - // TODO Find a better way to detect early death of process. - public void waitForEntityStart() { - if (log.isDebugEnabled()) log.debug("waiting to ensure {} doesn't abort prematurely", this); - Duration startTimeout = getConfig(START_TIMEOUT); - CountdownTimer timer = startTimeout.countdownTimer(); - boolean isRunningResult = false; - long delay = 100; - Exception firstFailure = null; - while (!isRunningResult && !timer.isExpired()) { - Time.sleep(delay); - try { - isRunningResult = driver.isRunning(); - if (log.isDebugEnabled()) log.debug("checked {}, 'is running' returned: {}", this, isRunningResult); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - - isRunningResult = false; - if (driver != null) { - String msg = "checked " + this + ", 'is running' threw an exception; logging subsequent exceptions at debug level"; - if (firstFailure == null) { - log.error(msg, e); - } else { - log.debug(msg, e); - } - } else { - // provide extra context info, as we're seeing this happen in strange circumstances - log.error(this+" concurrent start and shutdown detected", e); - } - if (firstFailure == null) { - firstFailure = e; - } - } - // slow exponential delay -- 1.1^N means after 40 tries and 50s elapsed, it reaches the max of 5s intervals - // TODO use Repeater - delay = Math.min(delay*11/10, 5000); - } - if (!isRunningResult) { - String msg = "Software process entity "+this+" did not pass is-running check within "+ - "the required "+startTimeout+" limit ("+timer.getDurationElapsed().toStringRounded()+" elapsed)"; - if (firstFailure != null) { - msg += "; check failed at least once with exception: " + firstFailure.getMessage() + ", see logs for details"; - } - log.warn(msg+" (throwing)"); - ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); - throw new IllegalStateException(msg, firstFailure); - } - } - - /** - * If custom behaviour is required by sub-classes, consider overriding {@link #preStart()} or {@link #postStart()})}. - * Also consider adding additional work via tasks, executed using {@link DynamicTasks#queue(String, Callable)}. - */ - @Override - public final void start(final Collection<? extends Location> locations) { - if (DynamicTasks.getTaskQueuingContext() != null) { - getLifecycleEffectorTasks().start(locations); - } else { - Task<?> task = Tasks.builder().name("start (sequential)").body(new Runnable() { public void run() { getLifecycleEffectorTasks().start(locations); } }).build(); - Entities.submit(this, task).getUnchecked(); - } - } - - /** - * If custom behaviour is required by sub-classes, consider overriding {@link #preStop()} or {@link #postStop()}. - * Also consider adding additional work via tasks, executed using {@link DynamicTasks#queue(String, Callable)}. - */ - @Override - public final void stop() { - // TODO There is a race where we set SERVICE_UP=false while sensor-adapter threads may still be polling. - // The other thread might reset SERVICE_UP to true immediately after we set it to false here. - // Deactivating adapters before setting SERVICE_UP reduces the race, and it is reduced further by setting - // SERVICE_UP to false at the end of stop as well. - - // Perhaps we should wait until all feeds have completed here, - // or do a SERVICE_STATE check before setting SERVICE_UP to true in a feed (?). - - if (DynamicTasks.getTaskQueuingContext() != null) { - getLifecycleEffectorTasks().stop(ConfigBag.EMPTY); - } else { - Task<?> task = Tasks.builder().name("stop").body(new Runnable() { public void run() { getLifecycleEffectorTasks().stop(ConfigBag.EMPTY); } }).build(); - Entities.submit(this, task).getUnchecked(); - } - } - - /** - * If custom behaviour is required by sub-classes, consider overriding {@link #preRestart()} or {@link #postRestart()}. - * Also consider adding additional work via tasks, executed using {@link DynamicTasks#queue(String, Callable)}. - */ - @Override - public final void restart() { - if (DynamicTasks.getTaskQueuingContext() != null) { - getLifecycleEffectorTasks().restart(ConfigBag.EMPTY); - } else { - Task<?> task = Tasks.builder().name("restart").body(new Runnable() { public void run() { getLifecycleEffectorTasks().restart(ConfigBag.EMPTY); } }).build(); - Entities.submit(this, task).getUnchecked(); - } - } - - protected SoftwareProcessDriverLifecycleEffectorTasks getLifecycleEffectorTasks() { - return getConfig(LIFECYCLE_EFFECTOR_TASKS); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcess.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcess.java b/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcess.java deleted file mode 100644 index 4049e0f..0000000 --- a/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcess.java +++ /dev/null @@ -1,62 +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.catalog.Catalog; -import org.apache.brooklyn.api.entity.ImplementedBy; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; - -/** - * A {@link SoftwareProcess} entity that runs commands from an archive. - * <p> - * Downloads and unpacks the archive indicated (optionally) then runs the management commands (scripts) indicated - * (relative to the root of the archive if supplied, otherwise in a tmp working dir) to manage. Uses config keys - * to identify the files or commands to use. - * <p> - * In the simplest mode, simply provide either: - * <ul> - * <li> an archive in {@link #DOWNLOAD_URL} containing a <code>./start.sh</code> - * <li> a start command to invoke in {@link #LAUNCH_COMMAND} - * </ul> - * The only constraint is that the start command must write the PID into the file pointed to by the injected environment - * variable {@code PID_FILE} unless one of the options below is supported. - * <p> - * The start command can be a complex bash command, downloading and unpacking files, and handling the {@code PID_FILE} requirement. - * For example {@code export MY_PID_FILE=$PID_FILE ; ./my_start.sh} or {@code nohup ./start.sh & ; echo $! > $PID_FILE ; sleep 5}. - * </pre> - * You can supply both {@link #DOWNLOAD_URL} and {@link #LAUNCH_COMMAND} configuration as well.. - * <p> - * In addition, you can supply an {@link #INSTALL_COMMAND} and / or a {@link #CUSTOMIZE_COMMAND} to reduce the complexity - * of the {@link #LAUNCH_COMMAND}, and to avoid repeating actions that are unnecessary in subsequent launches. - * <p> - * By default the PID is used to stop the process using {@code kill} followed by {@code kill -9} if needed and restart - * is implemented by stopping the process and then running {@link VanillaSoftwareProcessSshDriver#launch()}, but it is - * possible to override this behavior through config keys: - * <ul> - * <li> A custom {@link #CHECK_RUNNING_COMMAND} - * <li> A custom {@link #STOP_COMMAND} - * <li> A different {@link SoftwareProcess#PID_FILE} to use - * <li> - */ -@Catalog(name="Vanilla Software Process", description="A software process configured with scripts, e.g. for launch, check-running and stop") -@ImplementedBy(VanillaSoftwareProcessImpl.class) -public interface VanillaSoftwareProcess extends AbstractVanillaProcess { - ConfigKey<String> LAUNCH_COMMAND = ConfigKeys.newConfigKeyWithDefault(AbstractVanillaProcess.LAUNCH_COMMAND, "./start.sh"); -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessDriver.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessDriver.java b/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessDriver.java deleted file mode 100644 index aa98086..0000000 --- a/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessDriver.java +++ /dev/null @@ -1,23 +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 VanillaSoftwareProcessDriver extends SoftwareProcessDriver { - -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessImpl.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessImpl.java b/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessImpl.java deleted file mode 100644 index e7a9f70..0000000 --- a/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessImpl.java +++ /dev/null @@ -1,37 +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 VanillaSoftwareProcessImpl extends SoftwareProcessImpl implements VanillaSoftwareProcess { - @Override - public Class<?> getDriverInterface() { - return VanillaSoftwareProcessDriver.class; - } - @Override - protected void connectSensors() { - super.connectSensors(); - connectServiceUpIsRunning(); - } - @Override - protected void disconnectSensors() { - disconnectServiceUpIsRunning(); - super.disconnectSensors(); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessSshDriver.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessSshDriver.java b/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessSshDriver.java deleted file mode 100644 index 4a85565..0000000 --- a/software/base/src/main/java/brooklyn/entity/basic/VanillaSoftwareProcessSshDriver.java +++ /dev/null @@ -1,164 +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.LinkedList; -import java.util.List; -import java.util.Map; - -import org.apache.brooklyn.api.entity.drivers.downloads.DownloadResolver; -import org.apache.brooklyn.api.internal.EntityLocal; -import org.apache.brooklyn.entity.core.Entities; - -import brooklyn.entity.basic.lifecycle.ScriptHelper; - -import org.apache.brooklyn.location.basic.SshMachineLocation; -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.core.file.ArchiveUtils; -import org.apache.brooklyn.util.guava.Maybe; -import org.apache.brooklyn.util.net.Urls; -import org.apache.brooklyn.util.os.Os; -import org.apache.brooklyn.util.ssh.BashCommands; -import org.apache.brooklyn.util.text.Identifiers; -import org.apache.brooklyn.util.text.Strings; - -public class VanillaSoftwareProcessSshDriver extends AbstractSoftwareProcessSshDriver implements VanillaSoftwareProcessDriver { - - public VanillaSoftwareProcessSshDriver(EntityLocal entity, SshMachineLocation machine) { - super(entity, machine); - } - - String downloadedFilename = null; - - /** needed because the download url might be different! */ - @Override - protected String getInstallLabelExtraSalt() { - Maybe<Object> url = getEntity().getConfigRaw(SoftwareProcess.DOWNLOAD_URL, true); - if (url.isAbsent()) return null; - // TODO a user-friendly hash would be nice, but tricky since we don't want it to be too long or contain path chars - return Identifiers.makeIdFromHash( url.get().hashCode() ); - } - - @Override - public void install() { - Maybe<Object> url = getEntity().getConfigRaw(SoftwareProcess.DOWNLOAD_URL, true); - if (url.isPresentAndNonNull()) { - DownloadResolver resolver = Entities.newDownloader(this); - List<String> urls = resolver.getTargets(); - downloadedFilename = resolver.getFilename(); - - List<String> commands = new LinkedList<String>(); - commands.addAll(BashCommands.commandsToDownloadUrlsAs(urls, downloadedFilename)); - commands.addAll(ArchiveUtils.installCommands(downloadedFilename)); - - int result = newScript(INSTALLING) - .failOnNonZeroResultCode(false) - .body.append(commands) - .execute(); - - if (result!=0) { - // could not install at remote machine; try resolving URL here and copying across - for (String urlI: urls) { - result = ArchiveUtils.install(getMachine(), urlI, Urls.mergePaths(getInstallDir(), downloadedFilename)); - if (result==0) - break; - } - if (result != 0) - throw new IllegalStateException("Error installing archive: " + downloadedFilename); - } - } - - String installCommand = getEntity().getConfig(VanillaSoftwareProcess.INSTALL_COMMAND); - - if (Strings.isNonBlank(installCommand)) { - newScript(INSTALLING) - .failOnNonZeroResultCode() - .environmentVariablesReset(getShellEnvironment()) - .body.append(installCommand) - .execute(); - } - } - - @Override - public void customize() { - if (downloadedFilename != null) { - newScript(CUSTOMIZING) - .failOnNonZeroResultCode() - // don't set vars yet -- it resolves dependencies (e.g. DB) which we don't want until we start - .environmentVariablesReset() - .body.append(ArchiveUtils.extractCommands(downloadedFilename, getInstallDir())) - .execute(); - } - - String customizeCommand = getEntity().getConfig(VanillaSoftwareProcess.CUSTOMIZE_COMMAND); - - if (Strings.isNonBlank(customizeCommand)) { - newScript(CUSTOMIZING) - .failOnNonZeroResultCode() - .body.append(customizeCommand) - .execute(); - } - } - - @Override - public Map<String, String> getShellEnvironment() { - return MutableMap.copyOf(super.getShellEnvironment()).add("PID_FILE", getPidFile()); - } - - public String getPidFile() { - // TODO see note in VanillaSoftwareProcess about PID_FILE as a config key - // if (getEntity().getConfigRaw(PID_FILE, includeInherited)) ... - return Os.mergePathsUnix(getRunDir(), PID_FILENAME); - } - - @Override - public void launch() { - newScript(LAUNCHING) - .failOnNonZeroResultCode() - .body.append(getEntity().getConfig(VanillaSoftwareProcess.LAUNCH_COMMAND)) - .execute(); - } - - @Override - public boolean isRunning() { - String customCommand = getEntity().getConfig(VanillaSoftwareProcess.CHECK_RUNNING_COMMAND); - ScriptHelper script = null; - if (customCommand == null) { - script = newScript(MutableMap.of(USE_PID_FILE, getPidFile()), CHECK_RUNNING); - } else { - // TODO: template substitutions? - script = newScript(CHECK_RUNNING).body.append(customCommand); - } - return script.execute() == 0; - } - - @Override - public void stop() { - String customCommand = getEntity().getConfig(VanillaSoftwareProcess.STOP_COMMAND); - ScriptHelper script = null; - if (customCommand == null) { - script = newScript(MutableMap.of(USE_PID_FILE, getPidFile()), STOPPING); - } else { - // TODO: template substitutions? - script = newScript(STOPPING).body.append(customCommand); - } - script.execute(); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcess.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcess.java b/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcess.java deleted file mode 100644 index 3fce37f..0000000 --- a/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcess.java +++ /dev/null @@ -1,64 +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 org.apache.brooklyn.api.entity.ImplementedBy; -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.sensor.core.Sensors; -import org.apache.brooklyn.util.time.Duration; - -import com.google.common.collect.ImmutableSet; - -@ImplementedBy(VanillaWindowsProcessImpl.class) -public interface VanillaWindowsProcess extends AbstractVanillaProcess { - // 3389 is RDP; 5985 is WinRM (3389 isn't used by Brooklyn, but useful for the end-user subsequently) - ConfigKey<Collection<Integer>> REQUIRED_OPEN_LOGIN_PORTS = ConfigKeys.newConfigKeyWithDefault( - SoftwareProcess.REQUIRED_OPEN_LOGIN_PORTS, - ImmutableSet.of(5985, 3389)); - ConfigKey<String> PRE_INSTALL_POWERSHELL_COMMAND = ConfigKeys.newStringConfigKey("pre.install.powershell.command", - "powershell command to run during the pre-install phase"); - ConfigKey<Boolean> PRE_INSTALL_REBOOT_REQUIRED = ConfigKeys.newBooleanConfigKey("pre.install.reboot.required", - "indicates that a reboot should be performed after the pre-install command is run", false); - ConfigKey<Boolean> INSTALL_REBOOT_REQUIRED = ConfigKeys.newBooleanConfigKey("install.reboot.required", - "indicates that a reboot should be performed after the install command is run", false); - ConfigKey<Boolean> CUSTOMIZE_REBOOT_REQUIRED = ConfigKeys.newBooleanConfigKey("customize.reboot.required", - "indicates that a reboot should be performed after the customize command is run", false); - ConfigKey<String> LAUNCH_POWERSHELL_COMMAND = ConfigKeys.newStringConfigKey("launch.powershell.command", - "command to run to launch the process"); - ConfigKey<String> CHECK_RUNNING_POWERSHELL_COMMAND = ConfigKeys.newStringConfigKey("checkRunning.powershell.command", - "command to determine whether the process is running"); - ConfigKey<String> STOP_POWERSHELL_COMMAND = ConfigKeys.newStringConfigKey("stop.powershell.command", - "command to run to stop the process"); - ConfigKey<String> CUSTOMIZE_POWERSHELL_COMMAND = ConfigKeys.newStringConfigKey("customize.powershell.command", - "powershell command to run during the customization phase"); - ConfigKey<String> INSTALL_POWERSHELL_COMMAND = ConfigKeys.newStringConfigKey("install.powershell.command", - "powershell command to run during the install phase"); - ConfigKey<Duration> REBOOT_BEGUN_TIMEOUT = ConfigKeys.newDurationConfigKey("reboot.begun.timeout", - "duration to wait whilst waiting for a machine to begin rebooting, and thus become unavailable", Duration.TWO_MINUTES); - // TODO If automatic updates are enabled and there are updates waiting to be installed, thirty minutes may not be sufficient... - ConfigKey<Duration> REBOOT_COMPLETED_TIMEOUT = ConfigKeys.newDurationConfigKey("reboot.completed.timeout", - "duration to wait whilst waiting for a machine to finish rebooting, and thus to become available again", Duration.minutes(30)); - - AttributeSensor<Integer> RDP_PORT = Sensors.newIntegerSensor("rdpPort"); - AttributeSensor<Integer> WINRM_PORT = Sensors.newIntegerSensor("winrmPort"); -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcessDriver.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcessDriver.java b/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcessDriver.java deleted file mode 100644 index 7e9fd8c..0000000 --- a/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcessDriver.java +++ /dev/null @@ -1,23 +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 VanillaWindowsProcessDriver extends SoftwareProcessDriver { - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcessImpl.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcessImpl.java b/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcessImpl.java deleted file mode 100644 index aaa6641..0000000 --- a/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcessImpl.java +++ /dev/null @@ -1,47 +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 VanillaWindowsProcessImpl extends SoftwareProcessImpl implements VanillaWindowsProcess { - @Override - public Class getDriverInterface() { - return VanillaWindowsProcessDriver.class; - } - - @Override - protected void preStart() { - super.preStart(); - setAttribute(RDP_PORT, 3389); - setAttribute(WINRM_PORT, 5985); - } - - @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/VanillaWindowsProcessWinRmDriver.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcessWinRmDriver.java b/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcessWinRmDriver.java deleted file mode 100644 index 2c952b0..0000000 --- a/software/base/src/main/java/brooklyn/entity/basic/VanillaWindowsProcessWinRmDriver.java +++ /dev/null @@ -1,84 +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.internal.EntityLocal; -import org.apache.brooklyn.entity.core.Attributes; -import org.apache.brooklyn.location.basic.WinRmMachineLocation; -import org.apache.brooklyn.util.net.UserAndHostAndPort; - -public class VanillaWindowsProcessWinRmDriver extends AbstractSoftwareProcessWinRmDriver implements VanillaWindowsProcessDriver { - - public VanillaWindowsProcessWinRmDriver(EntityLocal entity, WinRmMachineLocation location) { - super(entity, location); - } - - @Override - public void start() { - WinRmMachineLocation machine = (WinRmMachineLocation) location; - UserAndHostAndPort winrmAddress = UserAndHostAndPort.fromParts(machine.getUser(), machine.getAddress().getHostName(), machine.config().get(WinRmMachineLocation.WINRM_PORT)); - getEntity().setAttribute(Attributes.WINRM_ADDRESS, winrmAddress); - - super.start(); - } - - @Override - public void preInstall() { - super.preInstall(); - executeCommand(VanillaWindowsProcess.PRE_INSTALL_COMMAND, VanillaWindowsProcess.PRE_INSTALL_POWERSHELL_COMMAND, true); - if (entity.getConfig(VanillaWindowsProcess.PRE_INSTALL_REBOOT_REQUIRED)) { - rebootAndWait(); - } - } - - @Override - public void install() { - // TODO: Follow install path of VanillaSoftwareProcessSshDriver - executeCommand(VanillaWindowsProcess.INSTALL_COMMAND, VanillaWindowsProcess.INSTALL_POWERSHELL_COMMAND, true); - if (entity.getConfig(VanillaWindowsProcess.INSTALL_REBOOT_REQUIRED)) { - rebootAndWait(); - } - } - - @Override - public void customize() { - // TODO: Follow customize path of VanillaSoftwareProcessSshDriver - executeCommand(VanillaWindowsProcess.CUSTOMIZE_COMMAND, VanillaWindowsProcess.CUSTOMIZE_POWERSHELL_COMMAND, true); - if (entity.getConfig(VanillaWindowsProcess.CUSTOMIZE_REBOOT_REQUIRED)) { - rebootAndWait(); - } - } - - @Override - public void launch() { - executeCommand(VanillaWindowsProcess.LAUNCH_COMMAND, VanillaWindowsProcess.LAUNCH_POWERSHELL_COMMAND, true); - } - - @Override - public boolean isRunning() { - return executeCommand(VanillaWindowsProcess.CHECK_RUNNING_COMMAND, - VanillaWindowsProcess.CHECK_RUNNING_POWERSHELL_COMMAND, false).getStatusCode() == 0; - } - - @Override - public void stop() { - executeCommand(VanillaWindowsProcess.STOP_COMMAND, VanillaWindowsProcess.STOP_POWERSHELL_COMMAND, true); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunner.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunner.java b/software/base/src/main/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunner.java deleted file mode 100644 index 1e5e901..0000000 --- a/software/base/src/main/java/brooklyn/entity/basic/lifecycle/NaiveScriptRunner.java +++ /dev/null @@ -1,43 +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.lifecycle; - -import java.util.List; -import java.util.Map; - -import org.apache.brooklyn.util.core.task.ssh.SshTasks; - -/** Marks something which can run scripts. Called "Naive" because it hides too much of the complexity, - * about script execution and other ssh-related tasks (put, etc). The {@link SshTasks} approach seems better. - * <p> - * Not gone so far as deprecating (yet, in 0.6.0) although we might. Feedback welcome. - * @since 0.6.0 */ -public interface NaiveScriptRunner { - - /** Runs a script and returns the result code */ - int execute(List<String> script, String summaryForLogging); - - /** Runs a script and returns the result code, supporting flags including: - * out, err as output/error streams; - * logPrefix, prefix string to put in log output; - * env, map of environment vars to pass to shell environment */ - @SuppressWarnings("rawtypes") - int execute(Map flags, List<String> script, String summaryForLogging); - -}
