http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/chef/ChefSoloDriver.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefSoloDriver.java b/software/base/src/main/java/brooklyn/entity/chef/ChefSoloDriver.java deleted file mode 100644 index aa97d72..0000000 --- a/software/base/src/main/java/brooklyn/entity/chef/ChefSoloDriver.java +++ /dev/null @@ -1,87 +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.chef; - -import org.apache.brooklyn.api.internal.EntityLocal; -import org.apache.brooklyn.api.mgmt.TaskAdaptable; -import org.apache.brooklyn.api.mgmt.TaskFactory; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.config.ConfigKeys; - -import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver; - -import org.apache.brooklyn.location.basic.SshMachineLocation; -import org.apache.brooklyn.util.core.task.DynamicTasks; - -import com.google.common.annotations.Beta; -import com.google.common.reflect.TypeToken; - -/** Driver class to facilitate use of Chef */ -@Beta -@Deprecated /** @deprecated since 0.7.0 use ChefEntity or ChefLifecycleEffectorTasks */ -public class ChefSoloDriver extends AbstractSoftwareProcessSshDriver implements ChefConfig { - - @SuppressWarnings("serial") - public static final ConfigKey<TaskFactory<? extends TaskAdaptable<Boolean>>> IS_RUNNING_TASK = ConfigKeys.newConfigKey( - new TypeToken<TaskFactory<? extends TaskAdaptable<Boolean>>>() {}, - "brooklyn.chef.task.driver.isRunningTask"); - - @SuppressWarnings("serial") - public static final ConfigKey<TaskFactory<?>> STOP_TASK = ConfigKeys.newConfigKey( - new TypeToken<TaskFactory<?>>() {}, - "brooklyn.chef.task.driver.stopTask"); - - public ChefSoloDriver(EntityLocal entity, SshMachineLocation location) { - super(entity, location); - } - - @Override - public void install() { - // TODO flag to force reinstallation - DynamicTasks.queue( - ChefSoloTasks.installChef(getInstallDir(), false), - ChefSoloTasks.installCookbooks(getInstallDir(), getRequiredConfig(CHEF_COOKBOOKS), false)); - } - - @Override - public void customize() { - DynamicTasks.queue(ChefSoloTasks.buildChefFile(getRunDir(), getInstallDir(), "launch", getRequiredConfig(CHEF_RUN_LIST), - getEntity().getConfig(CHEF_LAUNCH_ATTRIBUTES))); - } - - @Override - public void launch() { - DynamicTasks.queue(ChefSoloTasks.runChef(getRunDir(), "launch", getEntity().getConfig(CHEF_RUN_CONVERGE_TWICE))); - } - - @Override - public boolean isRunning() { - return DynamicTasks.queue(getRequiredConfig(IS_RUNNING_TASK)).asTask().getUnchecked(); - } - - @Override - public void stop() { - DynamicTasks.queue(getRequiredConfig(STOP_TASK)); - } - - protected <T> T getRequiredConfig(ConfigKey<T> key) { - return ChefConfigs.getRequiredConfig(getEntity(), key); - } - -}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/chef/ChefSoloTasks.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefSoloTasks.java b/software/base/src/main/java/brooklyn/entity/chef/ChefSoloTasks.java deleted file mode 100644 index 629d7a9..0000000 --- a/software/base/src/main/java/brooklyn/entity/chef/ChefSoloTasks.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.entity.chef; - -import java.util.Map; - -import org.apache.brooklyn.api.mgmt.TaskFactory; -import org.apache.brooklyn.util.ssh.BashCommands; - -import brooklyn.entity.software.SshEffectorTasks; - -import com.google.common.annotations.Beta; - -@Beta -public class ChefSoloTasks { - - public static TaskFactory<?> installChef(String chefDirectory, boolean force) { - // TODO check on entity whether it is chef _server_ - String installCmd = cdAndRun(chefDirectory, ChefBashCommands.INSTALL_FROM_OPSCODE); - if (!force) installCmd = BashCommands.alternatives("which chef-solo", installCmd); - return SshEffectorTasks.ssh(installCmd).summary("install chef"); - } - - public static TaskFactory<?> installCookbooks(final String chefDirectory, final Map<String,String> cookbooksAndUrls, final boolean force) { - return ChefTasks.installCookbooks(chefDirectory, cookbooksAndUrls, force); - } - - public static TaskFactory<?> installCookbook(String chefDirectory, String cookbookName, String cookbookArchiveUrl, boolean force) { - return ChefTasks.installCookbook(chefDirectory, cookbookName, cookbookArchiveUrl, force); - } - - protected static String cdAndRun(String targetDirectory, String command) { - return BashCommands.chain("mkdir -p "+targetDirectory, - "cd "+targetDirectory, - command); - } - - public static TaskFactory<?> buildChefFile(String runDirectory, String chefDirectory, String phase, Iterable<? extends String> runList, - Map<String, Object> optionalAttributes) { - return ChefTasks.buildChefFile(runDirectory, chefDirectory, phase, runList, optionalAttributes); - } - - public static TaskFactory<?> runChef(String runDir, String phase) { - return runChef(runDir, phase, false); - } - /** see {@link ChefConfig#CHEF_RUN_CONVERGE_TWICE} for background on why 'twice' is available */ - public static TaskFactory<?> runChef(String runDir, String phase, Boolean twice) { - String cmd = "sudo chef-solo -c "+phase+".rb -j "+phase+".json -ldebug"; - if (twice!=null && twice) cmd = BashCommands.alternatives(cmd, cmd); - - return SshEffectorTasks.ssh(cdAndRun(runDir, cmd)). - summary("run chef for "+phase).requiringExitCodeZero(); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/chef/ChefTasks.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/chef/ChefTasks.java b/software/base/src/main/java/brooklyn/entity/chef/ChefTasks.java deleted file mode 100644 index 7d5e46f..0000000 --- a/software/base/src/main/java/brooklyn/entity/chef/ChefTasks.java +++ /dev/null @@ -1,154 +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.chef; - -import java.util.Map; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.mgmt.TaskAdaptable; -import org.apache.brooklyn.api.mgmt.TaskFactory; -import org.apache.brooklyn.effector.core.EffectorTasks; -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.core.file.ArchiveTasks; -import org.apache.brooklyn.util.core.file.ArchiveUtils.ArchiveType; -import org.apache.brooklyn.util.core.task.DynamicTasks; -import org.apache.brooklyn.util.core.task.TaskBuilder; -import org.apache.brooklyn.util.core.task.Tasks; -import org.apache.brooklyn.util.net.Urls; -import org.apache.brooklyn.util.ssh.BashCommands; -import org.apache.brooklyn.util.text.Identifiers; -import org.apache.brooklyn.util.text.Strings; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.entity.software.SshEffectorTasks; - -import com.google.common.annotations.Beta; -import com.google.common.collect.ImmutableList; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -@Beta -public class ChefTasks { - - private static final Logger log = LoggerFactory.getLogger(ChefTasks.class); - - public static TaskFactory<?> installChef(String chefDirectory, boolean force) { - // TODO check on entity whether it is chef _server_ - String installCmd = cdAndRun(chefDirectory, ChefBashCommands.INSTALL_FROM_OPSCODE); - if (!force) installCmd = BashCommands.alternatives("which chef-solo", installCmd); - return SshEffectorTasks.ssh(installCmd).summary("install chef"); - } - - public static TaskFactory<?> installCookbooks(final String chefDirectory, final Map<String,String> cookbooksAndUrls, final boolean force) { - return Tasks.<Void>builder().name("install "+(cookbooksAndUrls==null ? "0" : cookbooksAndUrls.size())+" cookbook"+Strings.s(cookbooksAndUrls)).body( - new Runnable() { - public void run() { - Entity e = EffectorTasks.findEntity(); - if (cookbooksAndUrls==null) - throw new IllegalStateException("No cookbooks defined to install at "+e); - for (String cookbook: cookbooksAndUrls.keySet()) - DynamicTasks.queue(installCookbook(chefDirectory, cookbook, cookbooksAndUrls.get(cookbook), force)); - } - }).buildFactory(); - } - - public static TaskFactory<?> installCookbook(final String chefDirectory, final String cookbookName, final String cookbookArchiveUrl, final boolean force) { - return new TaskFactory<TaskAdaptable<?>>() { - @Override - public TaskAdaptable<?> newTask() { - TaskBuilder<Void> tb = Tasks.<Void>builder().name("install cookbook "+cookbookName); - - String cookbookDir = Urls.mergePaths(chefDirectory, cookbookName); - String privateTmpDirContainingUnpackedCookbook = - Urls.mergePaths(chefDirectory, "tmp-"+Strings.makeValidFilename(cookbookName)+"-"+Identifiers.makeRandomId(4)); - - // TODO - skip the install earlier if it exists and isn't forced -// if (!force) { -// // in builder.body, check -// // "ls "+cookbookDir -// // and stop if it's zero -// // remove reference to 'force' below -// } - - String destName = null; - if (ArchiveType.of(cookbookArchiveUrl)==ArchiveType.UNKNOWN) { - destName = cookbookName + ".tgz"; - log.debug("Assuming TGZ type for chef cookbook url "+cookbookArchiveUrl+"; it will be downloaded as "+destName); - } - tb.add(ArchiveTasks.deploy(null, null, cookbookArchiveUrl, EffectorTasks.findSshMachine(), privateTmpDirContainingUnpackedCookbook, - false, null, destName).newTask()); - - String installCmd = BashCommands.chain( - "cd "+privateTmpDirContainingUnpackedCookbook, - "COOKBOOK_EXPANDED_DIR=`ls`", - BashCommands.requireTest("`ls | wc -w` -eq 1", - "The deployed archive "+cookbookArchiveUrl+" must contain exactly one directory"), - "mv $COOKBOOK_EXPANDED_DIR '../"+cookbookName+"'", - "cd ..", - "rm -rf '"+privateTmpDirContainingUnpackedCookbook+"'"); - - installCmd = force ? BashCommands.alternatives("rm -rf "+cookbookDir, installCmd) : BashCommands.alternatives("ls "+cookbookDir+" > /dev/null 2> /dev/null", installCmd); - tb.add(SshEffectorTasks.ssh(installCmd).summary("renaming cookbook dir").requiringExitCodeZero().newTask()); - - return tb.build(); - } - }; - } - - protected static String cdAndRun(String targetDirectory, String command) { - return BashCommands.chain("mkdir -p '"+targetDirectory+"'", - "cd '"+targetDirectory+"'", - command); - } - - public static TaskFactory<?> buildChefFile(String runDirectory, String chefDirectory, String phase, Iterable<? extends String> runList, - Map<String, Object> optionalAttributes) { - // TODO if it's server, try knife first - // TODO configure add'l properties - String phaseRb = - "root = " - + "'"+runDirectory+"'" - // recommended alternate to runDir is the following, but it is not available in some rubies - //+ File.absolute_path(File.dirname(__FILE__))"+ - + "\n"+ - "file_cache_path root\n"+ -// "cookbook_path root + '/cookbooks'\n"; - "cookbook_path '"+chefDirectory+"'\n"; - - Map<String,Object> phaseJsonMap = MutableMap.of(); - if (optionalAttributes!=null) - phaseJsonMap.putAll(optionalAttributes); - if (runList!=null) - phaseJsonMap.put("run_list", ImmutableList.copyOf(runList)); - Gson json = new GsonBuilder().create(); - String phaseJson = json.toJson(phaseJsonMap); - - return Tasks.sequential("build chef files for "+phase, - SshEffectorTasks.put(Urls.mergePaths(runDirectory)+"/"+phase+".rb").contents(phaseRb).createDirectory(), - SshEffectorTasks.put(Urls.mergePaths(runDirectory)+"/"+phase+".json").contents(phaseJson)); - } - - public static TaskFactory<?> runChef(String runDir, String phase) { - // TODO chef server - return SshEffectorTasks.ssh(cdAndRun(runDir, "sudo chef-solo -c "+phase+".rb -j "+phase+".json -ldebug")). - summary("run chef for "+phase).requiringExitCodeZero(); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/chef/KnifeConvergeTaskFactory.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/chef/KnifeConvergeTaskFactory.java b/software/base/src/main/java/brooklyn/entity/chef/KnifeConvergeTaskFactory.java deleted file mode 100644 index f193598..0000000 --- a/software/base/src/main/java/brooklyn/entity/chef/KnifeConvergeTaskFactory.java +++ /dev/null @@ -1,246 +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.chef; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.apache.brooklyn.util.text.StringEscapes.BashStringEscapes.wrapBash; - -import java.io.File; -import java.util.List; -import java.util.Map; - -import com.google.common.base.Strings; -import com.google.common.net.HostAndPort; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.effector.core.EffectorTasks; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.brooklyn.location.basic.SshMachineLocation; -import org.apache.brooklyn.util.collections.Jsonya; -import org.apache.brooklyn.util.collections.MutableList; -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; -import org.apache.brooklyn.util.ssh.BashCommands; - -import com.google.common.base.Function; -import com.google.common.base.Functions; -import com.google.gson.GsonBuilder; - -public class KnifeConvergeTaskFactory<RET> extends KnifeTaskFactory<RET> { - - private static final Logger log = LoggerFactory.getLogger(KnifeConvergeTaskFactory.class); - - protected Function<? super Entity,String> runList; - protected Map<Object, Object> knifeAttributes = new MutableMap<Object, Object>(); - protected List<String> extraBootstrapParameters = MutableList.of(); - protected Boolean sudo; - protected Boolean runTwice; - protected String nodeName; - protected Integer port; - /** null means nothing specified, use user supplied or machine default; - * false means use machine default (disallow user supplied); - * true means use knife default (omit the argument and disallow user supplied) - */ - protected Boolean portOmittedToUseKnifeDefault; - - public KnifeConvergeTaskFactory(String taskName) { - super(taskName); - } - - @Override - protected KnifeConvergeTaskFactory<RET> self() { - return this; - } - - /** construct the knife command, based on the settings on other methods - * (called when instantiating the script, after all parameters sent) - */ - protected List<String> initialKnifeParameters() { - // runs inside the task so can detect entity/machine at runtime - MutableList<String> result = new MutableList<String>(); - SshMachineLocation machine = EffectorTasks.findSshMachine(); - - result.add("bootstrap"); - result.addAll(extraBootstrapParameters); - - HostAndPort hostAndPort = machine.getSshHostAndPort(); - result.add(wrapBash(hostAndPort.getHostText())); - Integer whichPort = knifeWhichPort(hostAndPort); - if (whichPort!=null) - result.add("-p "+whichPort); - - result.add("-x "+wrapBash(checkNotNull(machine.getUser(), "user"))); - - File keyfile = ChefServerTasks.extractKeyFile(machine); - if (keyfile!=null) result.add("-i "+keyfile.getPath()); - else result.add("-P "+checkNotNull(machine.findPassword(), "No password or private key data for "+machine)); - - result.add("--no-host-key-verify"); - - if (sudo != Boolean.FALSE) result.add("--sudo"); - - if (!Strings.isNullOrEmpty(nodeName)) { - result.add("--node-name"); - result.add(nodeName); - } - - result.add("-r "+wrapBash(runList.apply(entity()))); - - if (!knifeAttributes.isEmpty()) - result.add("-j "+wrapBash(new GsonBuilder().create() - .toJson(knifeAttributes))); - - return result; - } - - /** whether knife should attempt to run twice; - * see {@link ChefConfig#CHEF_RUN_CONVERGE_TWICE} */ - public KnifeConvergeTaskFactory<RET> knifeRunTwice(boolean runTwice) { - this.runTwice = runTwice; - return self(); - } - - /** whether to pass --sudo to knife; default true */ - public KnifeConvergeTaskFactory<RET> knifeSudo(boolean sudo) { - this.sudo = sudo; - return self(); - } - - /** what node name to pass to knife; default = null, meaning chef-client will pick the node name */ - public KnifeConvergeTaskFactory<RET> knifeNodeName(String nodeName) { - this.nodeName = nodeName; - return self(); - } - - /** tell knife to use an explicit port */ - public KnifeConvergeTaskFactory<RET> knifePort(int port) { - if (portOmittedToUseKnifeDefault!=null) { - log.warn("Port "+port+" specified to "+this+" for when already explicitly told to use a default (overriding previous); see subsequent warning for more details"); - } - this.port = port; - return self(); - } - - /** omit the port parameter altogether (let knife use its default) */ - public KnifeConvergeTaskFactory<RET> knifePortUseKnifeDefault() { - if (port!=null) { - log.warn("knifePortUseKnifeDefault specified to "+this+" when already told to use "+port+" explicitly (overriding previous); see subsequent warning for more details"); - port = -1; - } - portOmittedToUseKnifeDefault = true; - return self(); - } - - /** use the default port known to brooklyn for the target machine for ssh */ - public KnifeConvergeTaskFactory<RET> knifePortUseMachineSshPort() { - if (port!=null) { - log.warn("knifePortUseMachineSshPort specified to "+this+" when already told to use "+port+" explicitly (overriding previous); see subsequent warning for more details"); - port = -1; - } - portOmittedToUseKnifeDefault = false; - return self(); - } - - protected Integer knifeWhichPort(HostAndPort hostAndPort) { - if (port==null) { - if (Boolean.TRUE.equals(portOmittedToUseKnifeDefault)) - // user has explicitly said to use knife default, omitting port here - return null; - // default is to use the machine port - return hostAndPort.getPort(); - } - if (port==-1) { - // port was supplied by user, then portDefault (true or false) - port = null; - Integer whichPort = knifeWhichPort(hostAndPort); - log.warn("knife port conflicting instructions for "+this+" at entity "+entity()+" on "+hostAndPort+"; using default ("+whichPort+")"); - return whichPort; - } - if (portOmittedToUseKnifeDefault!=null) { - // portDefault was specified (true or false), then overridden with a port - log.warn("knife port conflicting instructions for "+this+" at entity "+entity()+" on "+hostAndPort+"; using supplied port "+port); - } - // port was supplied by user, use that - return port; - } - - /** parameters to pass to knife after the bootstrap command */ - public KnifeConvergeTaskFactory<RET> knifeAddExtraBootstrapParameters(String extraBootstrapParameter1, String ...extraBootstrapParameters) { - this.extraBootstrapParameters.add(extraBootstrapParameter1); - for (String p: extraBootstrapParameters) - this.extraBootstrapParameters.add(p); - return self(); - } - - /** function supplying the run list to be passed to knife, evaluated at the last moment */ - public KnifeConvergeTaskFactory<RET> knifeRunList(Function<? super Entity, String> runList) { - this.runList = runList; - return self(); - } - public KnifeConvergeTaskFactory<RET> knifeRunList(String runList) { - this.runList = Functions.constant(runList); - return self(); - } - - /** includes the given attributes in the attributes to be passed to chef; - * when combining with other attributes, this uses {@link Jsonya} semantics to add - * (a deep add, combining lists and maps) */ - public KnifeConvergeTaskFactory<RET> knifeAddAttributes(Map<? extends Object, ? extends Object> attributes) { - if (attributes!=null && !attributes.isEmpty()) { - Jsonya.of(knifeAttributes).add(attributes); - } - return self(); - } - - protected String buildKnifeCommand(int knifeCommandIndex) { - String result = super.buildKnifeCommand(knifeCommandIndex); - if (Boolean.TRUE.equals(runTwice)) - result = BashCommands.alternatives(result, result); - return result; - } - - @Override - public <T2> KnifeConvergeTaskFactory<T2> returning(ScriptReturnType type) { - return (KnifeConvergeTaskFactory<T2>) super.<T2>returning(type); - } - - @Override - public <RET2> KnifeConvergeTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation) { - return (KnifeConvergeTaskFactory<RET2>) super.returning(resultTransformation); - } - - @Override - public KnifeConvergeTaskFactory<Boolean> returningIsExitCodeZero() { - return (KnifeConvergeTaskFactory<Boolean>) super.returningIsExitCodeZero(); - } - - @Override - public KnifeConvergeTaskFactory<String> requiringZeroAndReturningStdout() { - return (KnifeConvergeTaskFactory<String>) super.requiringZeroAndReturningStdout(); - } - - public KnifeConvergeTaskFactory<RET> knifeAddParameters(String word1, String ...words) { - super.knifeAddParameters(word1, words); - return self(); - } - - // TODO other methods from KnifeTaskFactory will return KTF class not KCTF; - // should make it generic so it returns the right type... -} \ 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/chef/KnifeTaskFactory.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/chef/KnifeTaskFactory.java b/software/base/src/main/java/brooklyn/entity/chef/KnifeTaskFactory.java deleted file mode 100644 index 80fad0e..0000000 --- a/software/base/src/main/java/brooklyn/entity/chef/KnifeTaskFactory.java +++ /dev/null @@ -1,240 +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.chef; - -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nullable; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; -import org.apache.brooklyn.util.collections.MutableList; -import org.apache.brooklyn.util.core.internal.ssh.process.ProcessTool; -import org.apache.brooklyn.util.core.task.Tasks; -import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory; -import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; -import org.apache.brooklyn.util.core.task.system.internal.SystemProcessTaskFactory; -import org.apache.brooklyn.util.text.Strings; -import org.apache.brooklyn.util.text.StringEscapes.BashStringEscapes; - -import com.google.common.base.Function; - -/** A factory which acts like {@link ProcessTaskFactory} with special options for knife. - * Typical usage is to {@link #addKnifeParameters(String)}s for the knife command to be run. - * You can also {@link #add(String...)} commands as needed; these will run *before* knife, - * unless you addKnifeCommandHere(). - * <p> - * This impl will use sensible defaults, including {@link ConfigKey}s on the context entity, - * for general knife config but not specific commands etc. It supports: - * <li> {@link ChefConfig#KNIFE_EXECUTABLE} - * <li> {@link ChefConfig#KNIFE_CONFIG_FILE} - * <p> - * (Other fields will typically be used by methods calling to this factory.) - * */ -// see e.g. http://docs.opscode.com/knife_bootstrap.html -public class KnifeTaskFactory<RET> extends SystemProcessTaskFactory<KnifeTaskFactory<RET>, RET>{ - - private static String KNIFE_PLACEHOLDER = "<knife command goes here 1234>"; - public final String taskName; - protected String knifeExecutable; - protected List<String> knifeParameters = new ArrayList<String>(); - protected String knifeConfigFile; - protected String knifeSetupCommands; - protected Boolean throwOnCommonKnifeErrors; - - public KnifeTaskFactory(String taskName) { - this.taskName = taskName; - summary(taskName); - // knife setup usually requires a login shell - config.put(ProcessTool.PROP_LOGIN_SHELL, true); - } - - @Override - public List<Function<ProcessTaskWrapper<?>, Void>> getCompletionListeners() { - MutableList<Function<ProcessTaskWrapper<?>, Void>> result = MutableList.copyOf(super.getCompletionListeners()); - if (throwOnCommonKnifeErrors != Boolean.FALSE) - insertKnifeCompletionListenerIntoCompletionListenersList(result); - return result.asUnmodifiable(); - } - - public KnifeTaskFactory<RET> notThrowingOnCommonKnifeErrors() { - throwOnCommonKnifeErrors = false; - return self(); - } - - protected void insertKnifeCompletionListenerIntoCompletionListenersList(List<Function<ProcessTaskWrapper<?>, Void>> listeners) { - // give a nice warning if chef/knife not set up correctly - Function<ProcessTaskWrapper<?>, Void> propagateIfKnifeConfigFileMissing = new Function<ProcessTaskWrapper<?>, Void>() { - public Void apply(@Nullable ProcessTaskWrapper<?> input) { - if (input.getExitCode()!=0 && input.getStderr().indexOf("WARNING: No knife configuration file found")>=0) { - String myConfig = knifeConfigFileOption(); - if (Strings.isEmpty(myConfig)) - throw new IllegalStateException("Config file for Chef knife must be specified in "+ChefConfig.KNIFE_CONFIG_FILE+" (or valid knife default set up)"); - else - throw new IllegalStateException("Error reading config file for Chef knife ("+myConfig+") -- does it exist?"); - } - return null; - } - }; - listeners.add(propagateIfKnifeConfigFileMissing); - } - - - @Override - public ProcessTaskWrapper<RET> newTask() { - return new SystemProcessTaskWrapper("Knife"); - } - - /** Inserts the knife command at the current place in the list. - * Can be run multiple times. The knife command added at the end of the list - * if this is not invoked (and it is the only command if nothing is {@link #add(String...)}ed. - */ - public KnifeTaskFactory<RET> addKnifeCommandToScript() { - add(KNIFE_PLACEHOLDER); - return self(); - } - - @Override - public List<String> getCommands() { - MutableList<String> result = new MutableList<String>(); - String setupCommands = knifeSetupCommands(); - if (setupCommands != null && Strings.isNonBlank(setupCommands)) - result.add(setupCommands); - int numKnifes = 0; - for (String c: super.getCommands()) { - if (c==KNIFE_PLACEHOLDER) - result.add(buildKnifeCommand(numKnifes++)); - else - result.add(c); - } - if (numKnifes==0) - result.add(buildKnifeCommand(numKnifes++)); - return result.asUnmodifiable(); - } - - /** creates the command for running knife. - * in some cases knife may be added multiple times, - * and in that case the parameter here tells which time it is being added, - * on a single run. */ - protected String buildKnifeCommand(int knifeCommandIndex) { - MutableList<String> words = new MutableList<String>(); - words.add(knifeExecutable()); - words.addAll(initialKnifeParameters()); - words.addAll(knifeParameters()); - String x = knifeConfigFileOption(); - if (Strings.isNonBlank(x)) words.add(knifeConfigFileOption()); - return Strings.join(words, " "); - } - - /** allows a way for subclasses to build up parameters at the start */ - protected List<String> initialKnifeParameters() { - return new MutableList<String>(); - } - - @Nullable /** callers should allow this to be null so task can be used outside of an entity */ - protected Entity entity() { - return BrooklynTaskTags.getTargetOrContextEntity(Tasks.current()); - } - protected <T> T entityConfig(ConfigKey<T> key) { - Entity entity = entity(); - if (entity!=null) - return entity.getConfig(key); - return null; - } - - public KnifeTaskFactory<RET> knifeExecutable(String knifeExecutable) { - this.knifeExecutable = knifeExecutable; - return this; - } - - protected String knifeExecutable() { - if (knifeExecutable!=null) return knifeExecutable; - - String knifeExecFromConfig = entityConfig(ChefConfig.KNIFE_EXECUTABLE); - if (knifeExecFromConfig!=null) return BashStringEscapes.wrapBash(knifeExecFromConfig); - - // assume on the path, if executable not set - return "knife"; - } - - protected List<String> knifeParameters() { - return knifeParameters; - } - - public KnifeTaskFactory<RET> knifeAddParameters(String word1, String ...words) { - knifeParameters.add(word1); - for (String w: words) - knifeParameters.add(w); - return self(); - } - - public KnifeTaskFactory<RET> knifeConfigFile(String knifeConfigFile) { - this.knifeConfigFile = knifeConfigFile; - return self(); - } - - @Nullable - protected String knifeConfigFileOption() { - if (knifeConfigFile!=null) return "-c "+knifeConfigFile; - - String knifeConfigFileFromConfig = entityConfig(ChefConfig.KNIFE_CONFIG_FILE); - if (knifeConfigFileFromConfig!=null) return "-c "+BashStringEscapes.wrapBash(knifeConfigFileFromConfig); - - // if not supplied will use global config - return null; - } - - public KnifeTaskFactory<RET> knifeSetupCommands(String knifeSetupCommands) { - this.knifeSetupCommands = knifeSetupCommands; - return self(); - } - - @Nullable - protected String knifeSetupCommands() { - if (knifeSetupCommands!=null) return knifeSetupCommands; - - String knifeSetupCommandsFromConfig = entityConfig(ChefConfig.KNIFE_SETUP_COMMANDS); - if (knifeSetupCommandsFromConfig!=null) return knifeSetupCommandsFromConfig; - - // if not supplied will use global config - return null; - } - - @Override - public <T2> KnifeTaskFactory<T2> returning(ScriptReturnType type) { - return (KnifeTaskFactory<T2>) super.<T2>returning(type); - } - - @Override - public <RET2> KnifeTaskFactory<RET2> returning(Function<ProcessTaskWrapper<?>, RET2> resultTransformation) { - return (KnifeTaskFactory<RET2>) super.returning(resultTransformation); - } - - @Override - public KnifeTaskFactory<Boolean> returningIsExitCodeZero() { - return (KnifeTaskFactory<Boolean>) super.returningIsExitCodeZero(); - } - - @Override - public KnifeTaskFactory<String> requiringZeroAndReturningStdout() { - return (KnifeTaskFactory<String>) super.requiringZeroAndReturningStdout(); - } -} \ 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/java/JavaAppUtils.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/java/JavaAppUtils.java b/software/base/src/main/java/brooklyn/entity/java/JavaAppUtils.java deleted file mode 100644 index 42cffda..0000000 --- a/software/base/src/main/java/brooklyn/entity/java/JavaAppUtils.java +++ /dev/null @@ -1,264 +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.java; - -import static org.apache.brooklyn.util.JavaGroovyEquivalents.groovyTruth; - -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryUsage; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.management.openmbean.CompositeData; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.internal.EntityLocal; -import org.apache.brooklyn.core.config.render.RendererHints; -import org.apache.brooklyn.policy.enricher.RollingTimeWindowMeanEnricher; -import org.apache.brooklyn.policy.enricher.TimeFractionDeltaEnricher; -import org.apache.brooklyn.sensor.feed.http.HttpValueFunctions; -import org.apache.brooklyn.util.math.MathFunctions; -import org.apache.brooklyn.util.text.ByteSizeStrings; -import org.apache.brooklyn.util.time.Duration; -import org.apache.brooklyn.util.time.Time; - -import brooklyn.event.feed.jmx.JmxAttributePollConfig; -import brooklyn.event.feed.jmx.JmxFeed; - -import com.google.common.base.Function; - -public class JavaAppUtils { - - public static boolean isEntityMxBeanStatsEnabled(Entity entity) { - return groovyTruth(entity.getConfig(UsesJavaMXBeans.MXBEAN_STATS_ENABLED)); - } - - /** - * @see #connectJavaAppServerPolicies(EntityLocal, Duration) - * @see #getMxBeanSensorsBuilder(EntityLocal) - */ - @Nullable - public static JmxFeed connectMXBeanSensors(EntityLocal entity) { - if (isEntityMxBeanStatsEnabled(entity)) { - return getMxBeanSensorsBuilder(entity).build(); - } else { - return null; - } - } - - /** @see #connectJavaAppServerPolicies(EntityLocal, Duration) */ - @Nullable - public static JmxFeed connectMXBeanSensors(EntityLocal entity, long jmxPollPeriodMs) { - if (isEntityMxBeanStatsEnabled(entity)) { - return getMxBeanSensorsBuilder(entity, jmxPollPeriodMs).build(); - } else { - return null; - } - } - - /** - * @param entity The entity at which to poll - * @param jmxPollPeriod How often to poll - * @return A {@link JmxFeed} configured to poll the given entity at the given period, - * or null if the entity is not configured for MXBEAN_STATS - * @see brooklyn.entity.java.UsesJavaMXBeans#MXBEAN_STATS_ENABLED - */ - @Nullable - public static JmxFeed connectMXBeanSensors(EntityLocal entity, Duration jmxPollPeriod) { - if (isEntityMxBeanStatsEnabled(entity)) { - return getMxBeanSensorsBuilder(entity, jmxPollPeriod).build(); - } else { - return null; - } - } - - public static void connectJavaAppServerPolicies(EntityLocal entity) { - connectJavaAppServerPolicies(entity, Duration.TEN_SECONDS); - } - - public static void connectJavaAppServerPolicies(EntityLocal entity, Duration windowPeriod) { - entity.addEnricher(new TimeFractionDeltaEnricher<Double>(entity, UsesJavaMXBeans.PROCESS_CPU_TIME, - UsesJavaMXBeans.PROCESS_CPU_TIME_FRACTION_LAST, TimeUnit.MILLISECONDS)); - - entity.addEnricher(new RollingTimeWindowMeanEnricher<Double>(entity, - UsesJavaMXBeans.PROCESS_CPU_TIME_FRACTION_LAST, UsesJavaMXBeans.PROCESS_CPU_TIME_FRACTION_IN_WINDOW, - windowPeriod)); - } - - /** - * @param entity The entity at which to poll - * @return A {@link JmxFeed.Builder} configured to poll entity every ten seconds - * @see #getMxBeanSensorsBuilder(EntityLocal, Duration) - */ - @Nonnull - public static JmxFeed.Builder getMxBeanSensorsBuilder(EntityLocal entity) { - return getMxBeanSensorsBuilder(entity, Duration.TEN_SECONDS); - } - - /** @see #getMxBeanSensorsBuilder(EntityLocal, Duration) */ - @Nonnull - public static JmxFeed.Builder getMxBeanSensorsBuilder(EntityLocal entity, long jmxPollPeriod) { - return getMxBeanSensorsBuilder(entity, Duration.millis(jmxPollPeriod)); - } - - /** - * @param entity The entity at which to poll - * @param jmxPollPeriod How often to poll - * @return A {@link JmxFeed.Builder} configured to poll many interesting MXBeans - * at the given entity and to repeat according to the given poll period. - * <p/> - * If an entity does not have MXBean stats enabled (i.e. {@link UsesJavaMXBeans#MXBEAN_STATS_ENABLED} is - * configured to false) then returns a builder configured with entity and duration but no polls. - * <p/> - * Use {@link #connectMXBeanSensors(EntityLocal, Duration)} to create and build in one step. - */ - @Nonnull - @SuppressWarnings({"unchecked"}) - public static JmxFeed.Builder getMxBeanSensorsBuilder(EntityLocal entity, Duration jmxPollPeriod) { - JmxFeed.Builder builder = JmxFeed.builder() - .entity(entity) - .period(jmxPollPeriod); - if (isEntityMxBeanStatsEnabled(entity)) { - // TODO Could we reuse the result of compositeDataToMemoryUsage? - builder - .pollAttribute(new JmxAttributePollConfig<Long>(UsesJavaMXBeans.USED_HEAP_MEMORY) - .objectName(ManagementFactory.MEMORY_MXBEAN_NAME) - .attributeName("HeapMemoryUsage") - .onSuccess((Function) HttpValueFunctions.chain(compositeDataToMemoryUsage(), new Function<MemoryUsage, Long>() { - @Override public Long apply(MemoryUsage input) { - return (input == null) ? null : input.getUsed(); - }}))) - .pollAttribute(new JmxAttributePollConfig<Long>(UsesJavaMXBeans.INIT_HEAP_MEMORY) - .objectName(ManagementFactory.MEMORY_MXBEAN_NAME) - .attributeName("HeapMemoryUsage") - .onSuccess((Function) HttpValueFunctions.chain(compositeDataToMemoryUsage(), new Function<MemoryUsage, Long>() { - @Override public Long apply(MemoryUsage input) { - return (input == null) ? null : input.getInit(); - }}))) - .pollAttribute(new JmxAttributePollConfig<Long>(UsesJavaMXBeans.COMMITTED_HEAP_MEMORY) - .objectName(ManagementFactory.MEMORY_MXBEAN_NAME) - .attributeName("HeapMemoryUsage") - .onSuccess((Function) HttpValueFunctions.chain(compositeDataToMemoryUsage(), new Function<MemoryUsage, Long>() { - @Override public Long apply(MemoryUsage input) { - return (input == null) ? null : input.getCommitted(); - }}))) - .pollAttribute(new JmxAttributePollConfig<Long>(UsesJavaMXBeans.MAX_HEAP_MEMORY) - .objectName(ManagementFactory.MEMORY_MXBEAN_NAME) - .attributeName("HeapMemoryUsage") - .onSuccess((Function) HttpValueFunctions.chain(compositeDataToMemoryUsage(), new Function<MemoryUsage, Long>() { - @Override public Long apply(MemoryUsage input) { - return (input == null) ? null : input.getMax(); - }}))) - .pollAttribute(new JmxAttributePollConfig<Long>(UsesJavaMXBeans.NON_HEAP_MEMORY_USAGE) - .objectName(ManagementFactory.MEMORY_MXBEAN_NAME) - .attributeName("NonHeapMemoryUsage") - .onSuccess((Function) HttpValueFunctions.chain(compositeDataToMemoryUsage(), new Function<MemoryUsage, Long>() { - @Override public Long apply(MemoryUsage input) { - return (input == null) ? null : input.getUsed(); - }}))) - - .pollAttribute(new JmxAttributePollConfig<Integer>(UsesJavaMXBeans.CURRENT_THREAD_COUNT) - .objectName(ManagementFactory.THREAD_MXBEAN_NAME) - .attributeName("ThreadCount")) - .pollAttribute(new JmxAttributePollConfig<Integer>(UsesJavaMXBeans.PEAK_THREAD_COUNT) - .objectName(ManagementFactory.THREAD_MXBEAN_NAME) - .attributeName("PeakThreadCount")) - - .pollAttribute(new JmxAttributePollConfig<Long>(UsesJavaMXBeans.START_TIME) - .objectName(ManagementFactory.RUNTIME_MXBEAN_NAME) - .period(60, TimeUnit.SECONDS) - .attributeName("StartTime")) - .pollAttribute(new JmxAttributePollConfig<Long>(UsesJavaMXBeans.UP_TIME) - .objectName(ManagementFactory.RUNTIME_MXBEAN_NAME) - .period(60, TimeUnit.SECONDS) - .attributeName("Uptime")) - - .pollAttribute(new JmxAttributePollConfig<Double>(UsesJavaMXBeans.PROCESS_CPU_TIME) - .objectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME) - .attributeName("ProcessCpuTime") - .onSuccess((Function) MathFunctions.times(0.001*0.001))) // nanos to millis - .pollAttribute(new JmxAttributePollConfig<Double>(UsesJavaMXBeans.SYSTEM_LOAD_AVERAGE) - .objectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME) - .attributeName("SystemLoadAverage")) - .pollAttribute(new JmxAttributePollConfig<Integer>(UsesJavaMXBeans.AVAILABLE_PROCESSORS) - .objectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME) - .period(60, TimeUnit.SECONDS) - .attributeName("AvailableProcessors")) - .pollAttribute(new JmxAttributePollConfig<Long>(UsesJavaMXBeans.TOTAL_PHYSICAL_MEMORY_SIZE) - .objectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME) - .period(60, TimeUnit.SECONDS) - .attributeName("TotalPhysicalMemorySize")) - .pollAttribute(new JmxAttributePollConfig<Long>(UsesJavaMXBeans.FREE_PHYSICAL_MEMORY_SIZE) - .objectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME) - .period(60, TimeUnit.SECONDS) - .attributeName("FreePhysicalMemorySize")); - //FIXME: need a new type of adapter that maps multiple objectNames to a mapping - // jmxAdapter.objectName(ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",*").with { - // attribute("SystemLoadAverage").subscribe(UsesJavaMXBeans.GARBAGE_COLLECTION_TIME, { def m -> log.info("XXXXXXX $m") }); - // } - } - return builder; - } - - /** @deprecated Since 0.7.0. Use {@link org.apache.brooklyn.util.math.MathFunctions#times(double)} instead */ - @Deprecated - public static Function<Number, Double> times(final double x) { - return MathFunctions.times(x); - } - - public static Function<CompositeData, MemoryUsage> compositeDataToMemoryUsage() { - return new Function<CompositeData, MemoryUsage>() { - @Override public MemoryUsage apply(CompositeData input) { - return (input == null) ? null : MemoryUsage.from(input); - } - }; - } - - private static final AtomicBoolean initialized = new AtomicBoolean(false); - - /** Setup renderer hints for the MXBean attributes. */ - public static void init() { - if (initialized.get()) return; - synchronized (initialized) { - if (initialized.get()) return; - - RendererHints.register(UsesJavaMXBeans.USED_HEAP_MEMORY, RendererHints.displayValue(ByteSizeStrings.metric())); - RendererHints.register(UsesJavaMXBeans.INIT_HEAP_MEMORY, RendererHints.displayValue(ByteSizeStrings.metric())); - RendererHints.register(UsesJavaMXBeans.MAX_HEAP_MEMORY, RendererHints.displayValue(ByteSizeStrings.metric())); - RendererHints.register(UsesJavaMXBeans.COMMITTED_HEAP_MEMORY, RendererHints.displayValue(ByteSizeStrings.metric())); - RendererHints.register(UsesJavaMXBeans.NON_HEAP_MEMORY_USAGE, RendererHints.displayValue(ByteSizeStrings.metric())); - RendererHints.register(UsesJavaMXBeans.TOTAL_PHYSICAL_MEMORY_SIZE, RendererHints.displayValue(ByteSizeStrings.metric())); - RendererHints.register(UsesJavaMXBeans.FREE_PHYSICAL_MEMORY_SIZE, RendererHints.displayValue(ByteSizeStrings.metric())); - - RendererHints.register(UsesJavaMXBeans.START_TIME, RendererHints.displayValue(Time.toDateString())); - RendererHints.register(UsesJavaMXBeans.UP_TIME, RendererHints.displayValue(Duration.millisToStringRounded())); - RendererHints.register(UsesJavaMXBeans.PROCESS_CPU_TIME, RendererHints.displayValue(Duration.millisToStringRounded())); - RendererHints.register(UsesJavaMXBeans.PROCESS_CPU_TIME_FRACTION_LAST, RendererHints.displayValue(MathFunctions.percent(4))); - RendererHints.register(UsesJavaMXBeans.PROCESS_CPU_TIME_FRACTION_IN_WINDOW, RendererHints.displayValue(MathFunctions.percent(4))); - - initialized.set(true); - } - } - - static { - init(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/java/JavaEntityMethods.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/java/JavaEntityMethods.java b/software/base/src/main/java/brooklyn/entity/java/JavaEntityMethods.java deleted file mode 100644 index a9fad73..0000000 --- a/software/base/src/main/java/brooklyn/entity/java/JavaEntityMethods.java +++ /dev/null @@ -1,30 +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.java; - -import org.apache.brooklyn.config.ConfigKey; - -/** DSL conveniences for Java entities. Also see {@link JavaAppUtils} for methods useful within Java classes. */ -public class JavaEntityMethods { - - public static ConfigKey<String> javaSysProp(String propertyName) { return UsesJava.JAVA_SYSPROPS.subKey(propertyName); } - - // TODO javaMaxHeap javaInitialHeap javaMaxPermGen should all be supplied as ListConfigs on JAVA_OPTIONS - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessDriver.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessDriver.java b/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessDriver.java deleted file mode 100644 index 890403f..0000000 --- a/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessDriver.java +++ /dev/null @@ -1,30 +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.java; - -import brooklyn.entity.basic.SoftwareProcessDriver; - -/** - * A {@link SoftwareProcessDriver} for Java processes. - */ -public interface JavaSoftwareProcessDriver extends SoftwareProcessDriver { - - public boolean isJmxEnabled(); - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/64c2b2e5/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessSshDriver.java ---------------------------------------------------------------------- diff --git a/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessSshDriver.java b/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessSshDriver.java deleted file mode 100644 index 178d48f..0000000 --- a/software/base/src/main/java/brooklyn/entity/java/JavaSoftwareProcessSshDriver.java +++ /dev/null @@ -1,444 +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.java; - -import static org.apache.brooklyn.util.JavaGroovyEquivalents.groovyTruth; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.brooklyn.api.internal.EntityLocal; -import org.apache.brooklyn.effector.core.EffectorTasks; -import org.apache.brooklyn.entity.core.Attributes; -import org.apache.brooklyn.entity.core.Entities; -import org.apache.brooklyn.entity.core.EntityInternal; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.base.Function; -import com.google.common.base.Joiner; -import com.google.common.base.Optional; -import com.google.common.base.Splitter; -import com.google.common.base.Throwables; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.gson.internal.Primitives; - -import brooklyn.entity.basic.AbstractSoftwareProcessSshDriver; -import brooklyn.entity.software.SshEffectorTasks; - -import org.apache.brooklyn.location.basic.SshMachineLocation; -import org.apache.brooklyn.util.collections.MutableMap; -import org.apache.brooklyn.util.collections.MutableSet; -import org.apache.brooklyn.util.core.flags.TypeCoercions; -import org.apache.brooklyn.util.core.internal.ssh.ShellTool; -import org.apache.brooklyn.util.core.task.DynamicTasks; -import org.apache.brooklyn.util.core.task.Tasks; -import org.apache.brooklyn.util.core.task.ssh.SshTasks; -import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory; -import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; -import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.ssh.BashCommands; -import org.apache.brooklyn.util.text.Strings; -import org.apache.brooklyn.util.text.StringEscapes.BashStringEscapes; - -/** - * The SSH implementation of the {@link brooklyn.entity.java.JavaSoftwareProcessDriver}. - */ -public abstract class JavaSoftwareProcessSshDriver extends AbstractSoftwareProcessSshDriver implements JavaSoftwareProcessDriver { - - public static final Logger log = LoggerFactory.getLogger(JavaSoftwareProcessSshDriver.class); - - public static final List<List<String>> MUTUALLY_EXCLUSIVE_OPTS = ImmutableList.<List<String>> of(ImmutableList.of("-client", - "-server")); - - public static final List<String> KEY_VAL_OPT_PREFIXES = ImmutableList.of("-Xmx", "-Xms", "-Xss"); - - public JavaSoftwareProcessSshDriver(EntityLocal entity, SshMachineLocation machine) { - super(entity, machine); - - entity.setAttribute(Attributes.LOG_FILE_LOCATION, getLogFileLocation()); - } - - protected abstract String getLogFileLocation(); - - public boolean isJmxEnabled() { - return (entity instanceof UsesJmx) && (entity.getConfig(UsesJmx.USE_JMX)); - } - - public boolean isJmxSslEnabled() { - return isJmxEnabled() && groovyTruth(entity.getConfig(UsesJmx.JMX_SSL_ENABLED)); - } - - /** - * Sets all JVM options (-X.. -D..) in an environment var JAVA_OPTS. - * <p> - * That variable is constructed from {@link #getJavaOpts()}, then wrapped _unescaped_ in double quotes. An - * error is thrown if there is an unescaped double quote in the string. All other unescaped - * characters are permitted, but unless $var expansion or `command` execution is desired (although - * this is not confirmed as supported) the generally caller should escape any such characters, for - * example using {@link BashStringEscapes#escapeLiteralForDoubleQuotedBash(String)}. - */ - @Override - public Map<String, String> getShellEnvironment() { - List<String> javaOpts = getJavaOpts(); - - for (String it : javaOpts) { - BashStringEscapes.assertValidForDoubleQuotingInBash(it); - } - // do not double quote here; the env var is double quoted subsequently; - // spaces should be preceded by double-quote - // (if dbl quotes are needed we could pass on the command-line instead of in an env var) - String sJavaOpts = Joiner.on(' ').join(javaOpts); - return MutableMap.<String, String>builder().putAll(super.getShellEnvironment()).put("JAVA_OPTS", sJavaOpts).build(); - } - - /** - * arguments to pass to the JVM; this is the config options (e.g. -Xmx1024; only the contents of - * {@link #getCustomJavaConfigOptions()} by default) and java system properties (-Dk=v; add custom - * properties in {@link #getCustomJavaSystemProperties()}) - * <p> - * See {@link #getShellEnvironment()} for discussion of quoting/escaping strategy. - **/ - public List<String> getJavaOpts() { - Iterable<String> sysprops = Iterables.transform(getJavaSystemProperties().entrySet(), - new Function<Map.Entry<String, ?>, String>() { - public String apply(Map.Entry<String, ?> entry) { - String k = entry.getKey(); - Object v = entry.getValue(); - try { - if (v != null && Primitives.isWrapperType(v.getClass())) { - v = "" + v; - } else { - v = Tasks.resolveValue(v, Object.class, ((EntityInternal)entity).getExecutionContext()); - if (v == null) { - } else if (v instanceof CharSequence) { - } else if (TypeCoercions.isPrimitiveOrBoxer(v.getClass())) { - v = "" + v; - } else { - // could do toString, but that's likely not what is desired; - // probably a type mismatch, - // post-processing should be specified (common types are accepted - // above) - throw new IllegalArgumentException("cannot convert value " + v + " of type " + v.getClass() - + " to string to pass as JVM property; use a post-processor"); - } - } - return "-D" + k + (v != null ? "=" + v : ""); - } catch (Exception e) { - log.warn("Error resolving java option key {}, propagating: {}", k, e); - throw Throwables.propagate(e); - } - } - }); - - Set<String> result = MutableSet.<String> builder(). - addAll(getJmxJavaConfigOptions()). - addAll(getCustomJavaConfigOptions()). - addAll(sysprops). - build(); - - for (String customOpt : entity.getConfig(UsesJava.JAVA_OPTS)) { - for (List<String> mutuallyExclusiveOpt : MUTUALLY_EXCLUSIVE_OPTS) { - if (mutuallyExclusiveOpt.contains(customOpt)) { - result.removeAll(mutuallyExclusiveOpt); - } - } - for (String keyValOptPrefix : KEY_VAL_OPT_PREFIXES) { - if (customOpt.startsWith(keyValOptPrefix)) { - for (Iterator<String> iter = result.iterator(); iter.hasNext();) { - String existingOpt = iter.next(); - if (existingOpt.startsWith(keyValOptPrefix)) { - iter.remove(); - } - } - } - } - if (customOpt.contains("=")) { - String customOptPrefix = customOpt.substring(0, customOpt.indexOf("=")); - - for (Iterator<String> iter = result.iterator(); iter.hasNext();) { - String existingOpt = iter.next(); - if (existingOpt.startsWith(customOptPrefix)) { - iter.remove(); - } - } - } - result.add(customOpt); - } - - return ImmutableList.copyOf(result); - } - - /** - * Returns the complete set of Java system properties (-D defines) to set for the application. - * <p> - * This is exposed to the JVM as the contents of the {@code JAVA_OPTS} environment variable. Default - * set contains config key, custom system properties, and JMX defines. - * <p> - * Null value means to set -Dkey otherwise it is -Dkey=value. - * <p> - * See {@link #getShellEnvironment()} for discussion of quoting/escaping strategy. - */ - protected Map<String,?> getJavaSystemProperties() { - return MutableMap.<String,Object>builder() - .putAll(getCustomJavaSystemProperties()) - .putAll(isJmxEnabled() ? getJmxJavaSystemProperties() : Collections.<String,Object>emptyMap()) - .putAll(entity.getConfig(UsesJava.JAVA_SYSPROPS)) - .build(); - } - - /** - * Return extra Java system properties (-D defines) used by the application. - * - * Override as needed; default is an empty map. - */ - protected Map getCustomJavaSystemProperties() { - return Maps.newLinkedHashMap(); - } - - /** - * Return extra Java config options, ie arguments starting with - which are passed to the JVM prior - * to the class name. - * <p> - * Note defines are handled separately, in {@link #getCustomJavaSystemProperties()}. - * <p> - * Override as needed; default is an empty list. - */ - protected List<String> getCustomJavaConfigOptions() { - return Lists.newArrayList(); - } - - /** @deprecated since 0.6.0, the config key is always used instead of this */ @Deprecated - public Integer getJmxPort() { - return !isJmxEnabled() ? Integer.valueOf(-1) : entity.getAttribute(UsesJmx.JMX_PORT); - } - - /** @deprecated since 0.6.0, the config key is always used instead of this */ @Deprecated - public Integer getRmiRegistryPort() { - return !isJmxEnabled() ? -1 : entity.getAttribute(UsesJmx.RMI_REGISTRY_PORT); - } - - /** @deprecated since 0.6.0, the config key is always used instead of this */ @Deprecated - public String getJmxContext() { - return !isJmxEnabled() ? null : entity.getAttribute(UsesJmx.JMX_CONTEXT); - } - - /** - * Return the configuration properties required to enable JMX for a Java application. - * - * These should be set as properties in the {@code JAVA_OPTS} environment variable when calling the - * run script for the application. - */ - protected Map<String, ?> getJmxJavaSystemProperties() { - MutableMap.Builder<String, Object> result = MutableMap.<String, Object> builder(); - - if (isJmxEnabled()) { - new JmxSupport(getEntity(), getRunDir()).applyJmxJavaSystemProperties(result); - } - - return result.build(); - } - - /** - * Return any JVM arguments required, other than the -D defines returned by {@link #getJmxJavaSystemProperties()} - */ - protected List<String> getJmxJavaConfigOptions() { - List<String> result = new ArrayList<String>(); - if (isJmxEnabled()) { - result.addAll(new JmxSupport(getEntity(), getRunDir()).getJmxJavaConfigOptions()); - } - return result; - } - - /** - * Checks for the presence of Java on the entity's location, installing if necessary. - * @return true if the required version of Java was found on the machine or if it was installed correctly, - * otherwise false. - */ - protected boolean checkForAndInstallJava(String requiredVersion) { - int requiredJavaMinor; - if (requiredVersion.contains(".")) { - List<String> requiredVersionParts = Splitter.on(".").splitToList(requiredVersion); - requiredJavaMinor = Integer.valueOf(requiredVersionParts.get(1)); - } else if (requiredVersion.length() == 1) { - requiredJavaMinor = Integer.valueOf(requiredVersion); - } else { - log.error("java version required {} is not supported", requiredVersion); - throw new IllegalArgumentException("Required java version " + requiredVersion + " not supported"); - } - Optional<String> installedJavaVersion = getInstalledJavaVersion(); - if (installedJavaVersion.isPresent()) { - List<String> installedVersionParts = Splitter.on(".").splitToList(installedJavaVersion.get()); - int javaMajor = Integer.valueOf(installedVersionParts.get(0)); - int javaMinor = Integer.valueOf(installedVersionParts.get(1)); - if (javaMajor == 1 && javaMinor >= requiredJavaMinor) { - log.debug("Java {} already installed at {}@{}", new Object[]{installedJavaVersion.get(), getEntity(), getLocation()}); - return true; - } - } - return tryJavaInstall(requiredVersion, BashCommands.installJava(requiredJavaMinor)) == 0; - } - - protected int tryJavaInstall(String version, String command) { - getLocation().acquireMutex("installing", "installing Java at " + getLocation()); - try { - log.debug("Installing Java {} at {}@{}", new Object[]{version, getEntity(), getLocation()}); - ProcessTaskFactory<Integer> taskFactory = SshTasks.newSshExecTaskFactory(getLocation(), command) - .summary("install java ("+version+")") - .configure(ShellTool.PROP_EXEC_ASYNC, true); - ProcessTaskWrapper<Integer> installCommand = Entities.submit(getEntity(), taskFactory); - int result = installCommand.get(); - if (result != 0) { - log.warn("Installation of Java {} failed at {}@{}: {}", - new Object[]{version, getEntity(), getLocation(), installCommand.getStderr()}); - } - return result; - } finally { - getLocation().releaseMutex("installing"); - } - } - - /** - * @deprecated since 0.7.0; instead use {@link #getInstalledJavaVersion()} - */ - @Deprecated - protected Optional<String> getCurrentJavaVersion() { - return getInstalledJavaVersion(); - } - - /** - * Checks for the version of Java installed on the entity's location over SSH. - * @return An Optional containing the version portion of `java -version`, or absent if no Java found. - */ - protected Optional<String> getInstalledJavaVersion() { - log.debug("Checking Java version at {}@{}", getEntity(), getLocation()); - // sed gets stdin like 'java version "1.7.0_45"' - ProcessTaskWrapper<Integer> versionCommand = Entities.submit(getEntity(), SshTasks.newSshExecTaskFactory( - getLocation(), "java -version 2>&1 | grep \" version\" | sed 's/.*\"\\(.*\\).*\"/\\1/'")); - versionCommand.get(); - String stdOut = versionCommand.getStdout().trim(); - if (!Strings.isBlank(stdOut)) { - log.debug("Found Java version at {}@{}: {}", new Object[] {getEntity(), getLocation(), stdOut}); - return Optional.of(stdOut); - } else { - log.debug("Found no Java installed at {}@{}", getEntity(), getLocation()); - return Optional.absent(); - } - } - - /** - * Answers one of "OpenJDK", "Oracle", or other vendor info. - */ - protected Optional<String> getCurrentJavaVendor() { - // TODO Also handle IBM jvm - log.debug("Checking Java vendor at {}@{}", getEntity(), getLocation()); - ProcessTaskWrapper<Integer> versionCommand = Entities.submit(getEntity(), SshTasks.newSshExecTaskFactory( - getLocation(), "java -version 2>&1 | awk 'NR==2 {print $1}'")); - versionCommand.get(); - String stdOut = versionCommand.getStdout().trim(); - if (Strings.isBlank(stdOut)) { - log.debug("Found no Java installed at {}@{}", getEntity(), getLocation()); - return Optional.absent(); - } else if ("Java(TM)".equals(stdOut)) { - log.debug("Found Java version at {}@{}: {}", new Object[] {getEntity(), getLocation(), stdOut}); - return Optional.of("Oracle"); - } else { - return Optional.of(stdOut); - } - } - - /** - * Checks for Java 6 or 7, installing Java 7 if neither are found. Override this method to - * check for and install specific versions of Java. - * - * @see #checkForAndInstallJava(String) - */ - public boolean installJava() { - if (entity instanceof UsesJava) { - String version = entity.getConfig(UsesJava.JAVA_VERSION_REQUIRED); - return checkForAndInstallJava(version); - } - // by default it installs jdk7 - return checkForAndInstallJava("1.7"); - } - - public void installJmxSupport() { - if (isJmxEnabled()) { - newScript("JMX_SETUP_PREINSTALL").body.append("mkdir -p "+getRunDir()).execute(); - new JmxSupport(getEntity(), getRunDir()).install(); - } - } - - public void checkJavaHostnameBug() { - checkNoHostnameBug(); - - try { - ProcessTaskWrapper<Integer> hostnameTask = DynamicTasks.queue(SshEffectorTasks.ssh("echo FOREMARKER; hostname -f; echo AFTMARKER")).block(); - String stdout = Strings.getFragmentBetween(hostnameTask.getStdout(), "FOREMARKER", "AFTMARKER"); - if (hostnameTask.getExitCode() == 0 && Strings.isNonBlank(stdout)) { - String hostname = stdout.trim(); - Integer len = hostname.length(); - if (len > 63) { - // likely to cause a java crash due to java bug 7089443 -- set a new short hostname - // http://mail.openjdk.java.net/pipermail/net-dev/2012-July/004603.html - String newHostname = "br-"+getEntity().getId().toLowerCase(); - log.info("Detected likelihood of Java hostname bug with hostname length "+len+" for "+getEntity()+"; renaming "+getMachine()+" to hostname "+newHostname); - DynamicTasks.queue(SshEffectorTasks.ssh(BashCommands.setHostname(newHostname, null))).block(); - } - } else { - log.debug("Hostname length could not be determined for location "+EffectorTasks.findSshMachine()+"; not doing Java hostname bug check"); - } - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - log.warn("Error checking/fixing Java hostname bug (continuing): "+e, e); - } - } - - @Override - public void setup() { - DynamicTasks.queue("install java", new Runnable() { public void run() { - installJava(); - }}); - - // TODO check java version - - if (getEntity().getConfig(UsesJava.CHECK_JAVA_HOSTNAME_BUG)) { - DynamicTasks.queue("check java hostname bug", new Runnable() { public void run() { - checkJavaHostnameBug(); }}); - } - } - - @Override - public void copyRuntimeResources() { - super.copyRuntimeResources(); - - if (isJmxEnabled()) { - DynamicTasks.queue("install jmx", new Runnable() { public void run() { - installJmxSupport(); }}); - } - } - -}
