http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/effector/MethodEffector.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/effector/MethodEffector.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/effector/MethodEffector.java deleted file mode 100644 index ad53adb..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/effector/MethodEffector.java +++ /dev/null @@ -1,180 +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 org.apache.brooklyn.core.effector; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import org.apache.brooklyn.api.effector.Effector; -import org.apache.brooklyn.api.effector.ParameterType; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.core.annotation.EffectorParam; -import org.apache.brooklyn.core.entity.AbstractEntity; -import org.apache.brooklyn.core.mgmt.internal.EffectorUtils; -import org.apache.brooklyn.util.core.flags.TypeCoercions; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.groovy.GroovyJavaMethods; -import org.codehaus.groovy.runtime.MethodClosure; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.Lists; - -/** concrete class for providing an Effector implementation that gets its information from annotations on a method; - * see Effector*Test for usage example. - * <p> - * note that the method must be on an interface in order for it to be remoted, with the current implementation. - * see comments in {@link #call(Entity, Map)} for more details. - */ -public class MethodEffector<T> extends AbstractEffector<T> { - - private static final long serialVersionUID = 6989688364011965968L; - private static final Logger log = LoggerFactory.getLogger(MethodEffector.class); - - @SuppressWarnings("rawtypes") - public static Effector<?> create(Method m) { - return new MethodEffector(m); - } - - protected static class AnnotationsOnMethod { - final Class<?> clazz; - final String name; - final String description; - final Class<?> returnType; - final List<ParameterType<?>> parameters; - - public AnnotationsOnMethod(Class<?> clazz, String methodName) { - this(clazz, inferBestMethod(clazz, methodName)); - } - - public AnnotationsOnMethod(Class<?> clazz, Method method) { - this.clazz = clazz; - this.name = method.getName(); - this.returnType = method.getReturnType(); - - // Get the description - org.apache.brooklyn.core.annotation.Effector effectorAnnotation = method.getAnnotation(org.apache.brooklyn.core.annotation.Effector.class); - description = (effectorAnnotation != null) ? effectorAnnotation.description() : null; - - // Get the parameters - parameters = Lists.newArrayList(); - int numParameters = method.getParameterTypes().length; - for (int i = 0; i < numParameters; i++) { - parameters.add(toParameterType(method, i)); - } - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - protected static ParameterType<?> toParameterType(Method method, int paramIndex) { - Annotation[] anns = method.getParameterAnnotations()[paramIndex]; - Class<?> type = method.getParameterTypes()[paramIndex]; - EffectorParam paramAnnotation = findAnnotation(anns, EffectorParam.class); - - // TODO if blank, could do "param"+(i+1); would that be better? - // TODO this will now give "" if name is blank, rather than previously null. Is that ok?! - String name = (paramAnnotation != null) ? paramAnnotation.name() : null; - - String paramDescription = (paramAnnotation == null || EffectorParam.MAGIC_STRING_MEANING_NULL.equals(paramAnnotation.description())) ? null : paramAnnotation.description(); - String description = (paramDescription != null) ? paramDescription : null; - - String paramDefaultValue = (paramAnnotation == null || EffectorParam.MAGIC_STRING_MEANING_NULL.equals(paramAnnotation.defaultValue())) ? null : paramAnnotation.defaultValue(); - Object defaultValue = (paramDefaultValue != null) ? TypeCoercions.coerce(paramDefaultValue, type) : null; - - return new BasicParameterType(name, type, description, defaultValue); - } - - @SuppressWarnings("unchecked") - protected static <T extends Annotation> T findAnnotation(Annotation[] anns, Class<T> type) { - for (Annotation ann : anns) { - if (type.isInstance(ann)) return (T) ann; - } - return null; - } - - protected static Method inferBestMethod(Class<?> clazz, String methodName) { - Method best = null; - for (Method it : clazz.getMethods()) { - if (it.getName().equals(methodName)) { - if (best==null || best.getParameterTypes().length < it.getParameterTypes().length) best=it; - } - } - if (best==null) { - throw new IllegalStateException("Cannot find method "+methodName+" on "+clazz.getCanonicalName()); - } - return best; - } - } - - /** Defines a new effector whose details are supplied as annotations on the given type and method name */ - public MethodEffector(Class<?> whereEffectorDefined, String methodName) { - this(new AnnotationsOnMethod(whereEffectorDefined, methodName), null); - } - - public MethodEffector(Method method) { - this(new AnnotationsOnMethod(method.getDeclaringClass(), method), null); - } - - public MethodEffector(MethodClosure mc) { - this(new AnnotationsOnMethod((Class<?>)mc.getDelegate(), mc.getMethod()), null); - } - - @SuppressWarnings("unchecked") - protected MethodEffector(AnnotationsOnMethod anns, String description) { - super(anns.name, (Class<T>)anns.returnType, anns.parameters, GroovyJavaMethods.<String>elvis(description, anns.description)); - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public T call(Entity entity, Map parameters) { - Object[] parametersArray = EffectorUtils.prepareArgsForEffector(this, parameters); - if (entity instanceof AbstractEntity) { - return EffectorUtils.invokeMethodEffector(entity, this, parametersArray); - } else { - // we are dealing with a proxy here - // this implementation invokes the method on the proxy - // (requiring it to be on the interface) - // and letting the proxy deal with the remoting / runAtEntity; - // alternatively we could create the task here and pass it to runAtEntity; - // the latter may allow us to simplify/remove a lot of the stuff from - // EffectorUtils and possibly Effectors and Entities - - // TODO Should really find method with right signature, rather than just the right args. - // TODO prepareArgs can miss things out that have "default values"! Code below will probably fail if that happens. - Method[] methods = entity.getClass().getMethods(); - for (Method method : methods) { - if (method.getName().equals(getName())) { - if (parametersArray.length == method.getParameterTypes().length) { - try { - return (T) method.invoke(entity, parametersArray); - } catch (Exception e) { - // exception handled by the proxy invocation (which leads to EffectorUtils.invokeEffectorMethod...) - throw Exceptions.propagate(e); - } - } - } - } - String msg = "Could not find method for effector "+getName()+" with "+parametersArray.length+" parameters on "+entity; - log.warn(msg+" (throwing); available methods are: "+Arrays.toString(methods)); - throw new IllegalStateException(msg); - } - } - -}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshCommandEffector.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshCommandEffector.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshCommandEffector.java deleted file mode 100644 index b22f717..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshCommandEffector.java +++ /dev/null @@ -1,102 +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 org.apache.brooklyn.core.effector.ssh; - -import java.util.Map; - -import org.apache.brooklyn.api.effector.Effector; -import org.apache.brooklyn.api.effector.ParameterType; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.effector.AddEffector; -import org.apache.brooklyn.core.effector.EffectorBody; -import org.apache.brooklyn.core.effector.Effectors; -import org.apache.brooklyn.core.effector.Effectors.EffectorBuilder; -import org.apache.brooklyn.core.entity.BrooklynConfigKeys; -import org.apache.brooklyn.core.sensor.ssh.SshCommandSensor; -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.text.Strings; - -import com.google.common.base.Preconditions; - -public final class SshCommandEffector extends AddEffector { - - public static final ConfigKey<String> EFFECTOR_COMMAND = ConfigKeys.newStringConfigKey("command"); - public static final ConfigKey<String> EFFECTOR_EXECUTION_DIR = SshCommandSensor.SENSOR_EXECUTION_DIR; - - public SshCommandEffector(ConfigBag params) { - super(newEffectorBuilder(params).build()); - } - - public SshCommandEffector(Map<String,String> params) { - this(ConfigBag.newInstance(params)); - } - - public static EffectorBuilder<String> newEffectorBuilder(ConfigBag params) { - EffectorBuilder<String> eff = AddEffector.newEffectorBuilder(String.class, params); - eff.impl(new Body(eff.buildAbstract(), params)); - return eff; - } - - - protected static class Body extends EffectorBody<String> { - private final Effector<?> effector; - private final String command; - private final String executionDir; - - public Body(Effector<?> eff, ConfigBag params) { - this.effector = eff; - this.command = Preconditions.checkNotNull(params.get(EFFECTOR_COMMAND), "command must be supplied when defining this effector"); - this.executionDir = params.get(EFFECTOR_EXECUTION_DIR); - // TODO could take a custom "env" aka effectorShellEnv - } - - @Override - public String call(ConfigBag params) { - String command = this.command; - - command = SshCommandSensor.makeCommandExecutingInDirectory(command, executionDir, entity()); - - MutableMap<String, String> env = MutableMap.of(); - // first set all declared parameters, including default values - for (ParameterType<?> param: effector.getParameters()) { - env.addIfNotNull(param.getName(), Strings.toString( params.get(Effectors.asConfigKey(param)) )); - } - - // then set things from the entities defined shell environment, if applicable - env.putAll(Strings.toStringMap(entity().getConfig(BrooklynConfigKeys.SHELL_ENVIRONMENT), "")); - - // if we wanted to resolve the surrounding environment in real time -- see above -// Map<String,Object> paramsResolved = (Map<String, Object>) Tasks.resolveDeepValue(effectorShellEnv, Map.class, entity().getExecutionContext()); - - // finally set the parameters we've been passed; this will repeat declared parameters but to no harm, - // it may pick up additional values (could be a flag defining whether this is permitted or not) - env.putAll(Strings.toStringMap(params.getAllConfig())); - - SshEffectorTasks.SshEffectorTaskFactory<String> t = SshEffectorTasks.ssh(command) - .requiringZeroAndReturningStdout() - .summary("effector "+effector.getName()) - .environmentVariables(env); - return queue(t).get(); - } - - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java deleted file mode 100644 index a8e427c..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java +++ /dev/null @@ -1,342 +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 org.apache.brooklyn.core.effector.ssh; - -import java.util.List; -import java.util.Map; - -import javax.annotation.Nullable; - -import org.apache.brooklyn.api.effector.Effector; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.api.mgmt.Task; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.config.StringConfigMap; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.config.ConfigUtils; -import org.apache.brooklyn.core.effector.EffectorBody; -import org.apache.brooklyn.core.effector.EffectorTasks; -import org.apache.brooklyn.core.effector.EffectorTasks.EffectorTaskFactory; -import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks; -import org.apache.brooklyn.core.entity.EntityInternal; -import org.apache.brooklyn.core.location.internal.LocationInternal; -import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.brooklyn.location.ssh.SshMachineLocation; -import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.core.internal.ssh.SshTool; -import org.apache.brooklyn.util.core.task.Tasks; -import org.apache.brooklyn.util.core.task.ssh.SshFetchTaskFactory; -import org.apache.brooklyn.util.core.task.ssh.SshFetchTaskWrapper; -import org.apache.brooklyn.util.core.task.ssh.SshPutTaskFactory; -import org.apache.brooklyn.util.core.task.ssh.SshPutTaskWrapper; -import org.apache.brooklyn.util.core.task.ssh.SshTasks; -import org.apache.brooklyn.util.core.task.ssh.internal.AbstractSshExecTaskFactory; -import org.apache.brooklyn.util.core.task.ssh.internal.PlainSshExecTaskFactory; -import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory; -import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; -import org.apache.brooklyn.util.ssh.BashCommands; - -import com.google.common.annotations.Beta; -import com.google.common.base.Function; -import com.google.common.collect.Maps; - -/** - * Conveniences for generating {@link Task} instances to perform SSH activities. - * <p> - * If the {@link SshMachineLocation machine} is not specified directly it - * will be inferred from the {@link Entity} context of either the {@link Effector} - * or the current {@link Task}. - * - * @see SshTasks - * @since 0.6.0 - */ -@Beta -public class SshEffectorTasks { - - private static final Logger log = LoggerFactory.getLogger(SshEffectorTasks.class); - - public static final ConfigKey<Boolean> IGNORE_ENTITY_SSH_FLAGS = ConfigKeys.newBooleanConfigKey("ignoreEntitySshFlags", - "Whether to ignore any ssh flags (behaviour constraints) set on the entity or location " + - "where this is running, using only flags explicitly specified", false); - - /** - * Like {@link EffectorBody} but providing conveniences when in an entity with a single machine location. - */ - public abstract static class SshEffectorBody<T> extends EffectorBody<T> { - - /** convenience for accessing the machine */ - public SshMachineLocation machine() { - return EffectorTasks.getSshMachine(entity()); - } - - /** convenience for generating an {@link PlainSshExecTaskFactory} which can be further customised if desired, and then (it must be explicitly) queued */ - public ProcessTaskFactory<Integer> ssh(String ...commands) { - return new SshEffectorTaskFactory<Integer>(commands).machine(machine()); - } - } - - /** variant of {@link PlainSshExecTaskFactory} which fulfills the {@link EffectorTaskFactory} signature so can be used directly as an impl for an effector, - * also injects the machine automatically; can also be used outwith effector contexts, and machine is still injected if it is - * run from inside a task at an entity with a single SshMachineLocation */ - public static class SshEffectorTaskFactory<RET> extends AbstractSshExecTaskFactory<SshEffectorTaskFactory<RET>,RET> implements EffectorTaskFactory<RET> { - - public SshEffectorTaskFactory(String ...commands) { - super(commands); - } - public SshEffectorTaskFactory(SshMachineLocation machine, String ...commands) { - super(machine, commands); - } - @Override - public ProcessTaskWrapper<RET> newTask(Entity entity, Effector<RET> effector, ConfigBag parameters) { - markDirty(); - if (summary==null) summary(effector.getName()+" (ssh)"); - machine(EffectorTasks.getSshMachine(entity)); - return newTask(); - } - @Override - public synchronized ProcessTaskWrapper<RET> newTask() { - Entity entity = BrooklynTaskTags.getTargetOrContextEntity(Tasks.current()); - if (machine==null) { - if (log.isDebugEnabled()) - log.debug("Using an ssh task not in an effector without any machine; will attempt to infer the machine: "+this); - if (entity!=null) - machine(EffectorTasks.getSshMachine(entity)); - } - applySshFlags(getConfig(), entity, getMachine()); - return super.newTask(); - } - - @Override - public <T2> SshEffectorTaskFactory<T2> returning(ScriptReturnType type) { - return (SshEffectorTaskFactory<T2>) super.<T2>returning(type); - } - - @Override - public SshEffectorTaskFactory<Boolean> returningIsExitCodeZero() { - return (SshEffectorTaskFactory<Boolean>) super.returningIsExitCodeZero(); - } - - public SshEffectorTaskFactory<String> requiringZeroAndReturningStdout() { - return (SshEffectorTaskFactory<String>) super.requiringZeroAndReturningStdout(); - } - - public <RET2> SshEffectorTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation) { - return (SshEffectorTaskFactory<RET2>) super.returning(resultTransformation); - } - } - - public static class SshPutEffectorTaskFactory extends SshPutTaskFactory implements EffectorTaskFactory<Void> { - public SshPutEffectorTaskFactory(String remoteFile) { - super(remoteFile); - } - public SshPutEffectorTaskFactory(SshMachineLocation machine, String remoteFile) { - super(machine, remoteFile); - } - @Override - public SshPutTaskWrapper newTask(Entity entity, Effector<Void> effector, ConfigBag parameters) { - machine(EffectorTasks.getSshMachine(entity)); - applySshFlags(getConfig(), entity, getMachine()); - return super.newTask(); - } - @Override - public SshPutTaskWrapper newTask() { - Entity entity = BrooklynTaskTags.getTargetOrContextEntity(Tasks.current()); - if (machine==null) { - if (log.isDebugEnabled()) - log.debug("Using an ssh put task not in an effector without any machine; will attempt to infer the machine: "+this); - if (entity!=null) { - machine(EffectorTasks.getSshMachine(entity)); - } - - } - applySshFlags(getConfig(), entity, getMachine()); - return super.newTask(); - } - } - - public static class SshFetchEffectorTaskFactory extends SshFetchTaskFactory implements EffectorTaskFactory<String> { - public SshFetchEffectorTaskFactory(String remoteFile) { - super(remoteFile); - } - public SshFetchEffectorTaskFactory(SshMachineLocation machine, String remoteFile) { - super(machine, remoteFile); - } - @Override - public SshFetchTaskWrapper newTask(Entity entity, Effector<String> effector, ConfigBag parameters) { - machine(EffectorTasks.getSshMachine(entity)); - applySshFlags(getConfig(), entity, getMachine()); - return super.newTask(); - } - @Override - public SshFetchTaskWrapper newTask() { - Entity entity = BrooklynTaskTags.getTargetOrContextEntity(Tasks.current()); - if (machine==null) { - if (log.isDebugEnabled()) - log.debug("Using an ssh fetch task not in an effector without any machine; will attempt to infer the machine: "+this); - if (entity!=null) - machine(EffectorTasks.getSshMachine(entity)); - } - applySshFlags(getConfig(), entity, getMachine()); - return super.newTask(); - } - } - - /** - * @since 0.9.0 - */ - public static SshEffectorTaskFactory<Integer> ssh(SshMachineLocation machine, String ...commands) { - return new SshEffectorTaskFactory<Integer>(machine, commands); - } - - public static SshEffectorTaskFactory<Integer> ssh(String ...commands) { - return new SshEffectorTaskFactory<Integer>(commands); - } - - public static SshEffectorTaskFactory<Integer> ssh(List<String> commands) { - return ssh(commands.toArray(new String[commands.size()])); - } - - public static SshPutTaskFactory put(String remoteFile) { - return new SshPutEffectorTaskFactory(remoteFile); - } - - public static SshFetchEffectorTaskFactory fetch(String remoteFile) { - return new SshFetchEffectorTaskFactory(remoteFile); - } - - /** task which returns 0 if pid is running */ - public static SshEffectorTaskFactory<Integer> codePidRunning(Integer pid) { - return ssh("ps -p "+pid).summary("PID "+pid+" is-running check (exit code)").allowingNonZeroExitCode(); - } - - /** task which fails if the given PID is not running */ - public static SshEffectorTaskFactory<?> requirePidRunning(Integer pid) { - return codePidRunning(pid).summary("PID "+pid+" is-running check (required)").requiringExitCodeZero("Process with PID "+pid+" is required to be running"); - } - - /** as {@link #codePidRunning(Integer)} but returning boolean */ - public static SshEffectorTaskFactory<Boolean> isPidRunning(Integer pid) { - return codePidRunning(pid).summary("PID "+pid+" is-running check (boolean)").returning(new Function<ProcessTaskWrapper<?>, Boolean>() { - public Boolean apply(@Nullable ProcessTaskWrapper<?> input) { return Integer.valueOf(0).equals(input.getExitCode()); } - }); - } - - - /** task which returns 0 if pid in the given file is running; - * method accepts wildcards so long as they match a single file on the remote end - * <p> - * returns 1 if no matching file, - * 1 if matching file but no matching process, - * and 2 if 2+ matching files */ - public static SshEffectorTaskFactory<Integer> codePidFromFileRunning(final String pidFile) { - return ssh(BashCommands.chain( - // this fails, but isn't an error - BashCommands.requireTest("-f "+pidFile, "The PID file "+pidFile+" does not exist."), - // this fails and logs an error picked up later - BashCommands.requireTest("`ls "+pidFile+" | wc -w` -eq 1", "ERROR: there are multiple matching PID files"), - // this fails and logs an error picked up later - BashCommands.require("cat "+pidFile, "ERROR: the PID file "+pidFile+" cannot be read (permissions?)."), - // finally check the process - "ps -p `cat "+pidFile+"`")).summary("PID file "+pidFile+" is-running check (exit code)") - .allowingNonZeroExitCode() - .addCompletionListener(new Function<ProcessTaskWrapper<?>,Void>() { - public Void apply(ProcessTaskWrapper<?> input) { - if (input.getStderr().contains("ERROR:")) - throw new IllegalStateException("Invalid or inaccessible PID filespec: "+pidFile); - return null; - } - }); - } - - /** task which fails if the pid in the given file is not running (or if there is no such PID file); - * method accepts wildcards so long as they match a single file on the remote end (fails if 0 or 2+ matching files) */ - public static SshEffectorTaskFactory<?> requirePidFromFileRunning(String pidFile) { - return codePidFromFileRunning(pidFile) - .summary("PID file "+pidFile+" is-running check (required)") - .requiringExitCodeZero("Process with PID from file "+pidFile+" is required to be running"); - } - - /** as {@link #codePidFromFileRunning(String)} but returning boolean */ - public static SshEffectorTaskFactory<Boolean> isPidFromFileRunning(String pidFile) { - return codePidFromFileRunning(pidFile).summary("PID file "+pidFile+" is-running check (boolean)"). - returning(new Function<ProcessTaskWrapper<?>, Boolean>() { - public Boolean apply(@Nullable ProcessTaskWrapper<?> input) { return ((Integer)0).equals(input.getExitCode()); } - }); - } - - /** extracts the values for the main brooklyn.ssh.config.* config keys (i.e. those declared in ConfigKeys) - * as declared on the entity, and inserts them in a map using the unprefixed state, for ssh. - * <p> - * currently this is computed for each call, which may be wasteful, but it is reliable in the face of config changes. - * we could cache the Map. note that we do _not_ cache (or even own) the SshTool; - * the SshTool is created or re-used by the SshMachineLocation making use of these properties */ - @Beta - public static Map<String, Object> getSshFlags(Entity entity, Location optionalLocation) { - ConfigBag allConfig = ConfigBag.newInstance(); - - StringConfigMap globalConfig = ((EntityInternal)entity).getManagementContext().getConfig(); - allConfig.putAll(globalConfig.getAllConfig()); - - if (optionalLocation!=null) - allConfig.putAll(((LocationInternal)optionalLocation).config().getBag()); - - allConfig.putAll(((EntityInternal)entity).getAllConfig()); - - Map<String, Object> result = Maps.newLinkedHashMap(); - for (String keyS : allConfig.getAllConfig().keySet()) { - if (keyS.startsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX)) { - ConfigKey<?> key = ConfigKeys.newConfigKey(Object.class, keyS); - - Object val = allConfig.getStringKey(keyS); - - /* - * NOV 2013 changing this to rely on config above being inserted in the right order, - * so entity config will be preferred over location, and location over global. - * If that is consistent then remove the lines below. - * (We can also accept null entity and so combine with SshTasks.getSshFlags.) - */ - -// // have to use raw config to test whether the config is set -// Object val = ((EntityInternal)entity).getConfigMap().getRawConfig(key); -// if (val!=null) { -// val = entity.getConfig(key); -// } else { -// val = globalConfig.getRawConfig(key); -// if (val!=null) val = globalConfig.getConfig(key); -// } -// if (val!=null) { - result.put(ConfigUtils.unprefixedKey(SshTool.BROOKLYN_CONFIG_KEY_PREFIX, key).getName(), val); -// } - } - } - return result; - } - - private static void applySshFlags(ConfigBag config, Entity entity, Location machine) { - if (entity!=null) { - if (!config.get(IGNORE_ENTITY_SSH_FLAGS)) { - config.putIfAbsent(getSshFlags(entity, machine)); - } - } - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java deleted file mode 100644 index 5471c78..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/enricher/AbstractEnricher.java +++ /dev/null @@ -1,121 +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 org.apache.brooklyn.core.enricher; - -import static com.google.common.base.Preconditions.checkState; - -import java.util.Map; - -import org.apache.brooklyn.api.entity.EntityLocal; -import org.apache.brooklyn.api.mgmt.rebind.RebindSupport; -import org.apache.brooklyn.api.mgmt.rebind.mementos.EnricherMemento; -import org.apache.brooklyn.api.sensor.AttributeSensor; -import org.apache.brooklyn.api.sensor.Enricher; -import org.apache.brooklyn.api.sensor.EnricherType; -import org.apache.brooklyn.api.sensor.Sensor; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.entity.Entities; -import org.apache.brooklyn.core.entity.EntityInternal; -import org.apache.brooklyn.core.mgmt.rebind.BasicEnricherRebindSupport; -import org.apache.brooklyn.core.objs.AbstractEntityAdjunct; -import org.apache.brooklyn.util.core.flags.TypeCoercions; - -import com.google.common.base.Objects; -import com.google.common.collect.Maps; - -/** -* Base {@link Enricher} implementation; all enrichers should extend this or its children -*/ -public abstract class AbstractEnricher extends AbstractEntityAdjunct implements Enricher { - - public static final ConfigKey<Boolean> SUPPRESS_DUPLICATES = ConfigKeys.newBooleanConfigKey("enricher.suppressDuplicates", - "Whether duplicate values published by this enricher should be suppressed"); - - private final EnricherDynamicType enricherType; - protected Boolean suppressDuplicates; - - public AbstractEnricher() { - this(Maps.newLinkedHashMap()); - } - - public AbstractEnricher(Map<?,?> flags) { - super(flags); - - enricherType = new EnricherDynamicType(this); - - if (isLegacyConstruction() && !isLegacyNoConstructionInit()) { - init(); - } - } - - @Override - public RebindSupport<EnricherMemento> getRebindSupport() { - return new BasicEnricherRebindSupport(this); - } - - @SuppressWarnings("unchecked") - @Override - public RelationSupportInternal<Enricher> relations() { - return (RelationSupportInternal<Enricher>) super.relations(); - } - - @Override - public EnricherType getEnricherType() { - return enricherType.getSnapshot(); - } - - @Override - public void setEntity(EntityLocal entity) { - super.setEntity(entity); - Boolean suppressDuplicates = getConfig(SUPPRESS_DUPLICATES); - if (suppressDuplicates!=null) - this.suppressDuplicates = suppressDuplicates; - } - - @Override - protected void onChanged() { - requestPersist(); - } - - @Override - protected <T> void emit(Sensor<T> sensor, Object val) { - checkState(entity != null, "entity must first be set"); - if (val == Entities.UNCHANGED) { - return; - } - if (val == Entities.REMOVE) { - ((EntityInternal)entity).removeAttribute((AttributeSensor<T>) sensor); - return; - } - - T newVal = TypeCoercions.coerce(val, sensor.getTypeToken()); - if (sensor instanceof AttributeSensor) { - if (Boolean.TRUE.equals(suppressDuplicates)) { - T oldValue = entity.getAttribute((AttributeSensor<T>)sensor); - if (Objects.equal(oldValue, newVal)) - return; - } - entity.sensors().set((AttributeSensor<T>)sensor, newVal); - } else { - entity.sensors().emit(sensor, newVal); - } - } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/enricher/EnricherDynamicType.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/enricher/EnricherDynamicType.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/enricher/EnricherDynamicType.java deleted file mode 100644 index b6a0b23..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/enricher/EnricherDynamicType.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 org.apache.brooklyn.core.enricher; - -import org.apache.brooklyn.api.sensor.Enricher; -import org.apache.brooklyn.api.sensor.EnricherType; -import org.apache.brooklyn.core.objs.BrooklynDynamicType; - -public class EnricherDynamicType extends BrooklynDynamicType<Enricher, AbstractEnricher> { - - public EnricherDynamicType(Class<? extends Enricher> type) { - super(type); - } - - public EnricherDynamicType(AbstractEnricher enricher) { - super(enricher); - } - - public EnricherType getSnapshot() { - return (EnricherType) super.getSnapshot(); - } - - @Override - protected EnricherTypeSnapshot newSnapshot() { - return new EnricherTypeSnapshot(name, value(configKeys)); - } -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/enricher/EnricherTypeSnapshot.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/enricher/EnricherTypeSnapshot.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/enricher/EnricherTypeSnapshot.java deleted file mode 100644 index 240d884..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/enricher/EnricherTypeSnapshot.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.core.enricher; - -import java.util.Map; - -import org.apache.brooklyn.api.sensor.EnricherType; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.objs.BrooklynTypeSnapshot; - -public class EnricherTypeSnapshot extends BrooklynTypeSnapshot implements EnricherType { - private static final long serialVersionUID = 4670930188951106009L; - - EnricherTypeSnapshot(String name, Map<String, ConfigKey<?>> configKeys) { - super(name, configKeys); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - return (obj instanceof EnricherTypeSnapshot) && super.equals(obj); - } -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d03f254b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/AbstractApplication.java ---------------------------------------------------------------------- diff --git a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/AbstractApplication.java b/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/AbstractApplication.java deleted file mode 100644 index 3fd4b05..0000000 --- a/brooklyn-server/core/src/main/java/org/apache/brooklyn/core/entity/AbstractApplication.java +++ /dev/null @@ -1,267 +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 org.apache.brooklyn.core.entity; - -import java.util.Collection; -import java.util.Map; - -import org.apache.brooklyn.api.entity.Application; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; -import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; -import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic; -import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic.ServiceProblemsLogic; -import org.apache.brooklyn.core.entity.trait.StartableMethods; -import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.exceptions.RuntimeInterruptedException; -import org.apache.brooklyn.util.text.Strings; -import org.apache.brooklyn.util.time.Time; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.ImmutableSet; - -/** - * Users can extend this to define the entities in their application, and the relationships between - * those entities. Users should override the {@link #init()} method, and in there should create - * their entities. - */ -public abstract class AbstractApplication extends AbstractEntity implements StartableApplication { - - private static final Logger log = LoggerFactory.getLogger(AbstractApplication.class); - - /** - * The default name to use for this app, if not explicitly overridden by the top-level app. - * Necessary to avoid the app being wrapped in another layer of "BasicApplication" on deployment. - * Previously, the catalog item gave an explicit name (rathe rthan this defaultDisplayName), which - * meant that if the user chose a different name then AMP would automatically wrap this app so - * that both names would be presented. - */ - public static final ConfigKey<String> DEFAULT_DISPLAY_NAME = ConfigKeys.newStringConfigKey("defaultDisplayName"); - - private volatile Application application; - - public AbstractApplication() { - } - - public void init() { - super.init(); - if (Strings.isNonBlank(getConfig(DEFAULT_DISPLAY_NAME))) { - setDefaultDisplayName(getConfig(DEFAULT_DISPLAY_NAME)); - } - initApp(); - } - - protected void initApp() {} - - /** - * - * @deprecated since 0.6; use EntitySpec so no-arg constructor - */ - @Deprecated - public AbstractApplication(Map properties) { - super(properties); - } - - /** - * Constructor for when application is nested inside another application - * - * @deprecated Nesting applications is not currently supported - */ - @Deprecated - public AbstractApplication(Map properties, Entity parent) { - super(properties, parent); - } - - @Override - public Application getApplication() { - if (application!=null) { - if (application.getId().equals(getId())) - return (Application) getProxyIfAvailable(); - return application; - } - if (getParent()==null) return (Application)getProxyIfAvailable(); - return getParent().getApplication(); - } - - @Override - protected synchronized void setApplication(Application app) { - if (app.getId().equals(getId())) { - application = getProxy()!=null ? (Application)getProxy() : app; - } else { - application = app; - - // Alex, Mar 2013: added some checks; - // i *think* these conditions should not happen, - // and so should throw but don't want to break things (yet) - if (getParent()==null) { - log.warn("Setting application of "+this+" to "+app+", but "+this+" is not parented"); - } else if (getParent().getApplicationId().equals(app.getParent())) { - log.warn("Setting application of "+this+" to "+app+", but parent "+getParent()+" has different app "+getParent().getApplication()); - } - } - super.setApplication(app); - } - - @Override - public AbstractApplication setParent(Entity parent) { - super.setParent(parent); - return this; - } - - /** as {@link AbstractEntity#initEnrichers()} but also adding default service not-up and problem indicators from children */ - @Override - protected void initEnrichers() { - super.initEnrichers(); - - // default app logic; easily overridable by adding a different enricher with the same tag - ServiceStateLogic.newEnricherFromChildren().checkChildrenAndMembers().addTo(this); - ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL, "Application created but not yet started, at "+Time.makeDateString()); - } - - /** - * Default start will start all Startable children (child.start(Collection<? extends Location>)), - * calling preStart(locations) first and postStart(locations) afterwards. - */ - @Override - public void start(Collection<? extends Location> locations) { - this.addLocations(locations); - // 2016-01: only pass locations passed to us, as per ML discussion - Collection<? extends Location> locationsToUse = locations==null ? ImmutableSet.<Location>of() : locations; - ServiceProblemsLogic.clearProblemsIndicator(this, START); - ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL, "Application starting"); - setExpectedStateAndRecordLifecycleEvent(Lifecycle.STARTING); - try { - preStart(locationsToUse); - // if there are other items which should block service_up, they should be done in preStart - ServiceStateLogic.ServiceNotUpLogic.clearNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL); - - doStart(locationsToUse); - postStart(locationsToUse); - } catch (Exception e) { - // TODO should probably remember these problems then clear? if so, do it here ... or on all effectors? -// ServiceProblemsLogic.updateProblemsIndicator(this, START, e); - - recordApplicationEvent(Lifecycle.ON_FIRE); - // no need to log here; the effector invocation should do that - throw Exceptions.propagate(e); - } finally { - ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); - } - - setExpectedStateAndRecordLifecycleEvent(Lifecycle.RUNNING); - - logApplicationLifecycle("Started"); - } - - protected void logApplicationLifecycle(String message) { - log.info(message+" application " + this); - } - - protected void doStart(Collection<? extends Location> locations) { - StartableMethods.start(this, locations); - } - - /** - * Default is no-op. Subclasses can override. - * */ - public void preStart(Collection<? extends Location> locations) { - //no-op - } - - /** - * Default is no-op. Subclasses can override. - * */ - public void postStart(Collection<? extends Location> locations) { - //no-op - } - - /** - * Default stop will stop all Startable children - */ - @Override - public void stop() { - logApplicationLifecycle("Stopping"); - - ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL, "Application stopping"); - sensors().set(SERVICE_UP, false); - setExpectedStateAndRecordLifecycleEvent(Lifecycle.STOPPING); - try { - doStop(); - } catch (Exception e) { - setExpectedStateAndRecordLifecycleEvent(Lifecycle.ON_FIRE); - log.warn("Error stopping application " + this + " (rethrowing): "+e); - throw Exceptions.propagate(e); - } - ServiceStateLogic.ServiceNotUpLogic.updateNotUpIndicator(this, Attributes.SERVICE_STATE_ACTUAL, "Application stopped"); - setExpectedStateAndRecordLifecycleEvent(Lifecycle.STOPPED); - - if (getParent()==null) { - synchronized (this) { - //TODO review mgmt destroy lifecycle - // we don't necessarily want to forget all about the app on stop, - //since operator may be interested in things recently stopped; - //but that could be handled by the impl at management - //(keeping recently unmanaged things) - // however unmanaging must be done last, _after_ we stop children and set attributes - getEntityManager().unmanage(this); - } - } - - logApplicationLifecycle("Stopped"); - } - - protected void doStop() { - StartableMethods.stop(this); - } - - /** default impl invokes restart on all children simultaneously */ - @Override - public void restart() { - StartableMethods.restart(this); - } - - @Override - public void onManagementStopped() { - super.onManagementStopped(); - if (getManagementContext().isRunning()) { - recordApplicationEvent(Lifecycle.DESTROYED); - } - } - - protected void setExpectedStateAndRecordLifecycleEvent(Lifecycle state) { - ServiceStateLogic.setExpectedState(this, state); - recordApplicationEvent(state); - } - - protected void recordApplicationEvent(Lifecycle state) { - try { - ((ManagementContextInternal)getManagementContext()).getUsageManager().recordApplicationEvent(this, state); - } catch (RuntimeInterruptedException e) { - throw e; - } catch (RuntimeException e) { - if (getManagementContext().isRunning()) { - log.warn("Problem recording application event '"+state+"' for "+this, e); - } - } - } -}
