| /* |
| * 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(); |
| } |