blob: c0e87bd7b77b172ccef13981ed267c99cf5529a8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.brooklyn.entity.software.base;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import com.google.common.collect.Sets;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.MachineProvisioningLocation;
import org.apache.brooklyn.api.location.PortRange;
import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.annotation.Effector;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.config.ConfigUtils;
import org.apache.brooklyn.core.config.MapConfigKey;
import org.apache.brooklyn.core.entity.AbstractEntity;
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
import org.apache.brooklyn.core.entity.lifecycle.Lifecycle.Transition;
import org.apache.brooklyn.core.entity.trait.Startable;
import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey;
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
import org.apache.brooklyn.util.core.flags.TypeCoercions;
import org.apache.brooklyn.util.guava.Maybe;
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;
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));
ConfigKey<String> INBOUND_PORTS_CONFIG_REGEX = ConfigKeys.newStringConfigKey("inboundPorts.configRegex",
"Regex governing the opening of ports based on config names",
".*\\.port");
ConfigKey<Boolean> INBOUND_PORTS_AUTO_INFER = ConfigKeys.newBooleanConfigKey("inboundPorts.autoInfer",
"If set to false turns off the opening of ports based on naming convention, and also those that are of type PortRange in Java entities",
true);
@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("env")
MapConfigKey<Object> SHELL_ENVIRONMENT = BrooklynConfigKeys.SHELL_ENVIRONMENT;
@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("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();
}