You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/07/29 01:13:05 UTC
[1/6] incubator-brooklyn git commit: Support softwareProcess config
open/stop iptables
Repository: incubator-brooklyn
Updated Branches:
refs/heads/master 946b5dcf7 -> 05b95f377
Support softwareProcess config open/stop iptables
And also dontRequireTtyForSudo
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/90f18811
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/90f18811
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/90f18811
Branch: refs/heads/master
Commit: 90f18811328752fa99dad4af9f71a53135942f32
Parents: 42d6091
Author: Aled Sage <al...@gmail.com>
Authored: Sat Jul 25 15:00:57 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Mon Jul 27 13:50:00 2015 +0100
----------------------------------------------------------------------
.../brooklyn/entity/basic/SoftwareProcess.java | 16 ++
.../entity/software/MachineInitTasks.java | 172 +++++++++++++++++++
.../software/MachineLifecycleEffectorTasks.java | 41 ++++-
.../webapp/tomcat/TomcatServerEc2LiveTest.java | 1 +
4 files changed, 222 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90f18811/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
index 1de84de..1570355 100644
--- a/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
+++ b/software/base/src/main/java/brooklyn/entity/basic/SoftwareProcess.java
@@ -122,6 +122,22 @@ public interface SoftwareProcess extends Entity, Startable {
@Deprecated
ConfigKey<String> SUGGESTED_RUN_DIR = BrooklynConfigKeys.SUGGESTED_RUN_DIR;
+ public static final ConfigKey<Boolean> OPEN_IPTABLES = ConfigKeys.newBooleanConfigKey("openIptables",
+ "Whether to open the INBOUND_PORTS via iptables rules; " +
+ "if true then ssh in to run iptables commands, as part of machine provisioning", false);
+
+ public static final ConfigKey<Boolean> STOP_IPTABLES = ConfigKeys.newBooleanConfigKey("stopIptables",
+ "Whether to stop iptables entirely; " +
+ "if true then ssh in to stop the iptables service, as part of machine provisioning", false);
+
+ public static final ConfigKey<Boolean> DONT_REQUIRE_TTY_FOR_SUDO = ConfigKeys.newBooleanConfigKey("dontRequireTtyForSudo",
+ "Whether to explicitly set /etc/sudoers, so don't need tty (will leave unchanged if 'false'); " +
+ "some machines require a tty for sudo; brooklyn by default does not use a tty " +
+ "(so that it can get separate error+stdout streams); you can enable a tty as an " +
+ "option to every ssh command, or you can do it once and " +
+ "modify the machine so that a tty is not subsequently required.",
+ false);
+
/**
* Files to be copied to the server before pre-install.
* <p>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90f18811/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java b/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java
new file mode 100644
index 0000000..dfcb61d
--- /dev/null
+++ b/software/base/src/main/java/brooklyn/entity/software/MachineInitTasks.java
@@ -0,0 +1,172 @@
+/*
+ * 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.software;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.management.Task;
+import brooklyn.util.net.Protocol;
+import brooklyn.util.ssh.BashCommands;
+import brooklyn.util.ssh.IptablesCommands;
+import brooklyn.util.ssh.IptablesCommands.Chain;
+import brooklyn.util.ssh.IptablesCommands.Policy;
+import brooklyn.util.task.DynamicTasks;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.task.ssh.SshTasks;
+import brooklyn.util.text.Strings;
+
+/**
+ *
+ */
+@Beta
+public class MachineInitTasks {
+
+ // TODO Move somewhere so code can also be called by JcloudsLocation!
+
+ private static final Logger log = LoggerFactory.getLogger(MachineInitTasks.class);
+
+ protected EntityInternal entity() {
+ return (EntityInternal) BrooklynTaskTags.getTargetOrContextEntity(Tasks.current());
+ }
+
+ /**
+ * Returns a queued {@link Task} which opens the given ports in iptables on the given machine.
+ */
+ public Task<Void> openIptablesAsync(final Iterable<Integer> inboundPorts, final SshMachineLocation machine) {
+ return DynamicTasks.queue("open iptables "+toTruncatedString(inboundPorts, 6), new Callable<Void>() {
+ public Void call() {
+ openIptablesImpl(inboundPorts, machine);
+ return null;
+ }
+ });
+ }
+
+ /**
+ * Returns a queued {@link Task} which stops iptables on the given machine.
+ */
+ public Task<Void> stopIptablesAsync(final SshMachineLocation machine) {
+ return DynamicTasks.queue("stop iptables", new Callable<Void>() {
+ public Void call() {
+ stopIptablesImpl(machine);
+ return null;
+ }
+ });
+ }
+
+ /**
+ * See docs in {@link BashCommands#dontRequireTtyForSudo()}
+ */
+ public Task<Boolean> dontRequireTtyForSudoAsync(final SshMachineLocation machine) {
+ return SshTasks.dontRequireTtyForSudo(machine, true).newTask().asTask();
+ }
+
+ protected void openIptablesImpl(Iterable<Integer> inboundPorts, SshMachineLocation machine) {
+ if (inboundPorts == null || Iterables.isEmpty(inboundPorts)) {
+ log.info("No ports to open in iptables (no inbound ports) for {} at {}", machine, this);
+ } else {
+ log.info("Opening ports in iptables for {} at {}", entity(), machine);
+
+ List<String> iptablesRules = Lists.newArrayList();
+
+ if (isLocationFirewalldEnabled(machine)) {
+ for (Integer port : inboundPorts) {
+ iptablesRules.add(IptablesCommands.addFirewalldRule(Chain.INPUT, Protocol.TCP, port, Policy.ACCEPT));
+ }
+ } else {
+ iptablesRules = createIptablesRulesForNetworkInterface(inboundPorts);
+ iptablesRules.add(IptablesCommands.saveIptablesRules());
+ }
+ List<String> batch = Lists.newArrayList();
+ // Some entities, such as Riak (erlang based) have a huge range of ports, which leads to a script that
+ // is too large to run (fails with a broken pipe). Batch the rules into batches of 50
+ for (String rule : iptablesRules) {
+ batch.add(rule);
+ if (batch.size() == 50) {
+ machine.execCommands("Inserting iptables rules, 50 command batch", batch);
+ batch.clear();
+ }
+ }
+ if (batch.size() > 0) {
+ machine.execCommands("Inserting iptables rules", batch);
+ }
+ machine.execCommands("List iptables rules", ImmutableList.of(IptablesCommands.listIptablesRule()));
+ }
+ }
+
+ protected void stopIptablesImpl(SshMachineLocation machine) {
+ log.info("Stopping iptables for {} at {}", entity(), machine);
+
+ List<String> cmds = ImmutableList.<String>of();
+ if (isLocationFirewalldEnabled(machine)) {
+ cmds = ImmutableList.of(IptablesCommands.firewalldServiceStop(), IptablesCommands.firewalldServiceStatus());
+ } else {
+ cmds = ImmutableList.of(IptablesCommands.iptablesServiceStop(), IptablesCommands.iptablesServiceStatus());
+ }
+ machine.execCommands("Stopping iptables", cmds);
+ }
+
+ private List<String> createIptablesRulesForNetworkInterface(Iterable<Integer> ports) {
+ List<String> iptablesRules = Lists.newArrayList();
+ for (Integer port : ports) {
+ iptablesRules.add(IptablesCommands.insertIptablesRule(Chain.INPUT, Protocol.TCP, port, Policy.ACCEPT));
+ }
+ return iptablesRules;
+ }
+
+ public boolean isLocationFirewalldEnabled(SshMachineLocation location) {
+ int result = location.execCommands("checking if firewalld is active",
+ ImmutableList.of(IptablesCommands.firewalldServiceIsActive()));
+ if (result == 0) {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected String toTruncatedString(Iterable<?> vals, int maxShown) {
+ StringBuilder result = new StringBuilder("[");
+ int shown = 0;
+ for (Object val : (vals == null ? ImmutableList.of() : vals)) {
+ if (shown != 0) {
+ result.append(", ");
+ }
+ if (shown < maxShown) {
+ result.append(Strings.toString(val));
+ shown++;
+ } else {
+ result.append("...");
+ break;
+ }
+ }
+ result.append("]");
+ return result.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90f18811/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
----------------------------------------------------------------------
diff --git a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
index 2ba42f7..ec3ae1c 100644
--- a/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
+++ b/software/base/src/main/java/brooklyn/entity/software/MachineLifecycleEffectorTasks.java
@@ -25,11 +25,19 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
+
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
import brooklyn.config.ConfigKey;
import brooklyn.entity.Effector;
import brooklyn.entity.Entity;
@@ -62,6 +70,7 @@ import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import brooklyn.location.basic.Locations;
import brooklyn.location.basic.Machines;
import brooklyn.location.basic.SshMachineLocation;
+import brooklyn.location.cloud.CloudLocationConfig;
import brooklyn.management.Task;
import brooklyn.management.TaskFactory;
import brooklyn.util.collections.MutableMap;
@@ -77,13 +86,6 @@ import brooklyn.util.task.system.ProcessTaskWrapper;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
-import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
/**
* Default skeleton for start/stop/restart tasks on machines.
* <p>
@@ -116,6 +118,8 @@ public abstract class MachineLifecycleEffectorTasks {
public static final ConfigKey<Duration> STOP_PROCESS_TIMEOUT = ConfigKeys.newConfigKey(Duration.class,
"process.stop.timeout", "How long to wait for the processes to be stopped; use null to mean forever", Duration.TWO_MINUTES);
+ protected final MachineInitTasks machineInitTasks = new MachineInitTasks();
+
/** Attaches lifecycle effectors (start, restart, stop) to the given entity post-creation. */
public void attachLifecycleEffectors(Entity entity) {
((EntityInternal) entity).getMutableEntityType().addEffector(newStartEffector());
@@ -344,6 +348,28 @@ public abstract class MachineLifecycleEffectorTasks {
entity().setAttribute(Attributes.SSH_ADDRESS, sshAddress);
}
+ if (Boolean.TRUE.equals(entity().getConfig(SoftwareProcess.OPEN_IPTABLES))) {
+ if (machine instanceof SshMachineLocation) {
+ Iterable<Integer> inboundPorts = (Iterable<Integer>) machine.config().get(CloudLocationConfig.INBOUND_PORTS);
+ machineInitTasks.openIptablesAsync(inboundPorts, (SshMachineLocation)machine);
+ } else {
+ log.warn("Ignoring flag OPEN_IPTABLES on non-ssh location {}", machine);
+ }
+ }
+ if (Boolean.TRUE.equals(entity().getConfig(SoftwareProcess.STOP_IPTABLES))) {
+ if (machine instanceof SshMachineLocation) {
+ machineInitTasks.stopIptablesAsync((SshMachineLocation)machine);
+ } else {
+ log.warn("Ignoring flag STOP_IPTABLES on non-ssh location {}", machine);
+ }
+ }
+ if (Boolean.TRUE.equals(entity().getConfig(SoftwareProcess.DONT_REQUIRE_TTY_FOR_SUDO))) {
+ if (machine instanceof SshMachineLocation) {
+ machineInitTasks.dontRequireTtyForSudoAsync((SshMachineLocation)machine);
+ } else {
+ log.warn("Ignoring flag DONT_REQUIRE_TTY_FOR_SUDO on non-ssh location {}", machine);
+ }
+ }
resolveOnBoxDir(entity(), machine);
preStartCustom(machine);
}});
@@ -761,5 +787,4 @@ public abstract class MachineLifecycleEffectorTasks {
}
return new StopMachineDetails<Integer>("Decommissioned "+machine, 1);
}
-
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/90f18811/software/webapp/src/test/java/brooklyn/entity/webapp/tomcat/TomcatServerEc2LiveTest.java
----------------------------------------------------------------------
diff --git a/software/webapp/src/test/java/brooklyn/entity/webapp/tomcat/TomcatServerEc2LiveTest.java b/software/webapp/src/test/java/brooklyn/entity/webapp/tomcat/TomcatServerEc2LiveTest.java
index ec7f0a1..e0775b7 100644
--- a/software/webapp/src/test/java/brooklyn/entity/webapp/tomcat/TomcatServerEc2LiveTest.java
+++ b/software/webapp/src/test/java/brooklyn/entity/webapp/tomcat/TomcatServerEc2LiveTest.java
@@ -47,6 +47,7 @@ public class TomcatServerEc2LiveTest extends AbstractEc2LiveTest {
@Override
protected void doTest(Location loc) throws Exception {
final TomcatServer server = app.createAndManageChild(EntitySpec.create(TomcatServer.class)
+ .configure(TomcatServer.OPEN_IPTABLES, true)
.configure("war", getTestWar()));
app.start(ImmutableList.of(loc));
[2/6] incubator-brooklyn git commit: Adds BYON tcpPortMappings
Posted by al...@apache.org.
Adds BYON tcpPortMappings
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/9633236d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/9633236d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/9633236d
Branch: refs/heads/master
Commit: 9633236d9ee2adf6e63fab2682465944df78f667
Parents: c2e55c0
Author: Aled Sage <al...@gmail.com>
Authored: Mon Jul 20 23:31:53 2015 -0700
Committer: Aled Sage <al...@gmail.com>
Committed: Mon Jul 27 13:50:00 2015 +0100
----------------------------------------------------------------------
.../location/basic/ByonLocationResolver.java | 47 ++++++++++---
.../location/basic/SshMachineLocation.java | 72 +++++++++++++-------
.../location/basic/WinRmMachineLocation.java | 42 +++++++++---
.../camp/brooklyn/ByonLocationsYamlTest.java | 66 ++++++++++++++++--
4 files changed, 175 insertions(+), 52 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9633236d/core/src/main/java/brooklyn/location/basic/ByonLocationResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/location/basic/ByonLocationResolver.java b/core/src/main/java/brooklyn/location/basic/ByonLocationResolver.java
index 3695e3e..7838e24 100644
--- a/core/src/main/java/brooklyn/location/basic/ByonLocationResolver.java
+++ b/core/src/main/java/brooklyn/location/basic/ByonLocationResolver.java
@@ -27,6 +27,12 @@ import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.net.HostAndPort;
+
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Sanitizer;
@@ -41,12 +47,6 @@ import brooklyn.util.net.UserAndHostAndPort;
import brooklyn.util.text.WildcardGlobs;
import brooklyn.util.text.WildcardGlobs.PhraseTreatment;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.net.HostAndPort;
-
/**
* Examples of valid specs:
* <ul>
@@ -146,16 +146,33 @@ public class ByonLocationResolver extends AbstractLocationResolver {
String osfamily = (String) machineConfig.remove(OS_FAMILY.getName());
String ssh = (String) machineConfig.remove("ssh");
String winrm = (String) machineConfig.remove("winrm");
+ Map<Integer, String> tcpPortMappings = (Map<Integer, String>) machineConfig.get("tcpPortMappings");
+
checkArgument(ssh != null ^ winrm != null, "Must specify exactly one of 'ssh' or 'winrm' for machine: %s", valSanitized);
UserAndHostAndPort userAndHostAndPort;
+ String host;
+ int port;
if (ssh != null) {
- userAndHostAndPort = parseUserAndHostAndPort((String)ssh);
+ userAndHostAndPort = parseUserAndHostAndPort((String)ssh, 22);
} else {
- userAndHostAndPort = parseUserAndHostAndPort((String)winrm);
+ userAndHostAndPort = parseUserAndHostAndPort((String)winrm, 5985);
+ }
+
+ // If there is a tcpPortMapping defined for the connection-port, then use that for ssh/winrm machine
+ port = userAndHostAndPort.getHostAndPort().getPort();
+ if (tcpPortMappings != null && tcpPortMappings.containsKey(port)) {
+ String override = tcpPortMappings.get(port);
+ HostAndPort hostAndPortOverride = HostAndPort.fromString(override);
+ if (!hostAndPortOverride.hasPort()) {
+ throw new IllegalArgumentException("Invalid portMapping ('"+override+"') for port "+port+" in "+specForErrMsg);
+ }
+ port = hostAndPortOverride.getPort();
+ host = hostAndPortOverride.getHostText().trim();
+ } else {
+ host = userAndHostAndPort.getHostAndPort().getHostText().trim();
}
- String host = userAndHostAndPort.getHostAndPort().getHostText().trim();
machineConfig.put("address", host);
try {
InetAddress.getByName(host);
@@ -169,7 +186,7 @@ public class ByonLocationResolver extends AbstractLocationResolver {
}
if (userAndHostAndPort.getHostAndPort().hasPort()) {
checkArgument(!vals.containsKey("port"), "Must not specify port twice for machine: %s", valSanitized);
- machineConfig.put("port", userAndHostAndPort.getHostAndPort().getPort());
+ machineConfig.put("port", port);
}
for (Map.Entry<String, ?> entry : defaults.entrySet()) {
if (!machineConfig.containsKey(entry.getKey())) {
@@ -187,7 +204,7 @@ public class ByonLocationResolver extends AbstractLocationResolver {
protected LocationSpec<? extends MachineLocation> parseMachine(String val, Class<? extends MachineLocation> locationClass, Map<String, ?> defaults, String specForErrMsg) {
Map<String, Object> machineConfig = Maps.newLinkedHashMap();
-
+
UserAndHostAndPort userAndHostAndPort = parseUserAndHostAndPort(val);
String host = userAndHostAndPort.getHostAndPort().getHostText().trim();
@@ -222,4 +239,12 @@ public class ByonLocationResolver extends AbstractLocationResolver {
}
return UserAndHostAndPort.fromParts(userPart, HostAndPort.fromString(hostPart));
}
+
+ private UserAndHostAndPort parseUserAndHostAndPort(String val, int defaultPort) {
+ UserAndHostAndPort result = parseUserAndHostAndPort(val);
+ if (!result.getHostAndPort().hasPort()) {
+ result = UserAndHostAndPort.fromParts(result.getUser(), result.getHostAndPort().getHostText(), defaultPort);
+ }
+ return result;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9633236d/core/src/main/java/brooklyn/location/basic/SshMachineLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/location/basic/SshMachineLocation.java b/core/src/main/java/brooklyn/location/basic/SshMachineLocation.java
index 68f224d..8c06274 100644
--- a/core/src/main/java/brooklyn/location/basic/SshMachineLocation.java
+++ b/core/src/main/java/brooklyn/location/basic/SshMachineLocation.java
@@ -20,10 +20,6 @@ package brooklyn.location.basic;
import static brooklyn.util.GroovyJavaMethods.truth;
-import com.google.common.annotations.Beta;
-
-import groovy.lang.Closure;
-
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
@@ -52,6 +48,27 @@ import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.base.Throwables;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.cache.RemovalListener;
+import com.google.common.cache.RemovalNotification;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.net.HostAndPort;
+import com.google.common.reflect.TypeToken;
+
import brooklyn.config.BrooklynLogging;
import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
@@ -66,6 +83,7 @@ import brooklyn.location.MachineLocation;
import brooklyn.location.OsDetails;
import brooklyn.location.PortRange;
import brooklyn.location.PortSupplier;
+import brooklyn.location.access.PortForwardManager;
import brooklyn.management.Task;
import brooklyn.util.ResourceUtils;
import brooklyn.util.collections.MutableMap;
@@ -96,26 +114,7 @@ import brooklyn.util.task.system.internal.ExecWithLoggingHelpers;
import brooklyn.util.task.system.internal.ExecWithLoggingHelpers.ExecRunner;
import brooklyn.util.text.Strings;
import brooklyn.util.time.Duration;
-
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.common.base.Throwables;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.cache.RemovalListener;
-import com.google.common.cache.RemovalNotification;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.common.net.HostAndPort;
-import com.google.common.reflect.TypeToken;
+import groovy.lang.Closure;
/**
* Operations on a machine that is accessible via ssh.
@@ -153,6 +152,12 @@ public class SshMachineLocation extends AbstractLocation implements MachineLocat
"Private addresses of this machine, e.g. those within the private network",
null);
+ public static final ConfigKey<Map<Integer, String>> TCP_PORT_MAPPINGS = ConfigKeys.newConfigKey(
+ new TypeToken<Map<Integer, String>>() {},
+ "tcpPortMappings",
+ "NAT'ed ports, giving the mapping from private TCP port to a public host:port",
+ null);
+
@SetFromFlag
protected String user;
@@ -251,6 +256,25 @@ public class SshMachineLocation extends AbstractLocation implements MachineLocat
usedPorts = (usedPorts != null) ? Sets.newLinkedHashSet(usedPorts) : Sets.<Integer>newLinkedHashSet();
}
+ @Override
+ public void init() {
+ super.init();
+
+ // Register any pre-existing port-mappings with the PortForwardManager
+ Map<Integer, String> tcpPortMappings = getConfig(TCP_PORT_MAPPINGS);
+ if (tcpPortMappings != null) {
+ PortForwardManager pfm = (PortForwardManager) getManagementContext().getLocationRegistry().resolve("portForwardManager(scope=global)");
+ for (Map.Entry<Integer, String> entry : tcpPortMappings.entrySet()) {
+ int targetPort = entry.getKey();
+ HostAndPort publicEndpoint = HostAndPort.fromString(entry.getValue());
+ if (!publicEndpoint.hasPort()) {
+ throw new IllegalArgumentException("Invalid portMapping ('"+entry.getValue()+"') for port "+targetPort+" in machine "+this);
+ }
+ pfm.associate(publicEndpoint.getHostText(), publicEndpoint, this, targetPort);
+ }
+ }
+ }
+
private final transient Object poolCacheMutex = new Object();
@Nonnull
private LoadingCache<Map<String, ?>, Pool<SshTool>> getSshPoolCache() {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9633236d/core/src/main/java/brooklyn/location/basic/WinRmMachineLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/location/basic/WinRmMachineLocation.java b/core/src/main/java/brooklyn/location/basic/WinRmMachineLocation.java
index 54ee63a..3504ec0 100644
--- a/core/src/main/java/brooklyn/location/basic/WinRmMachineLocation.java
+++ b/core/src/main/java/brooklyn/location/basic/WinRmMachineLocation.java
@@ -19,8 +19,6 @@
package brooklyn.location.basic;
import static com.google.common.base.Preconditions.checkNotNull;
-import io.cloudsoft.winrm4j.winrm.WinRmTool;
-import io.cloudsoft.winrm4j.winrm.WinRmToolResponse;
import java.io.File;
import java.io.FileInputStream;
@@ -30,6 +28,7 @@ import java.net.InetAddress;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
@@ -38,22 +37,26 @@ import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Charsets;
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.net.HostAndPort;
+import com.google.common.reflect.TypeToken;
+
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.location.MachineDetails;
import brooklyn.location.MachineLocation;
import brooklyn.location.OsDetails;
+import brooklyn.location.access.PortForwardManager;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.stream.Streams;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
-
-import com.google.common.base.Charsets;
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.reflect.TypeToken;
+import io.cloudsoft.winrm4j.winrm.WinRmTool;
+import io.cloudsoft.winrm4j.winrm.WinRmToolResponse;
public class WinRmMachineLocation extends AbstractLocation implements MachineLocation {
@@ -98,6 +101,12 @@ public class WinRmMachineLocation extends AbstractLocation implements MachineLoc
"Private addresses of this machine, e.g. those within the private network",
null);
+ public static final ConfigKey<Map<Integer, String>> TCP_PORT_MAPPINGS = ConfigKeys.newConfigKey(
+ new TypeToken<Map<Integer, String>>() {},
+ "tcpPortMappings",
+ "NAT'ed ports, giving the mapping from private TCP port to a public host:port",
+ null);
+
@Override
public InetAddress getAddress() {
return getConfig(ADDRESS);
@@ -245,8 +254,21 @@ public class WinRmMachineLocation extends AbstractLocation implements MachineLoc
@Override
public void init() {
super.init();
- }
+ // Register any pre-existing port-mappings with the PortForwardManager
+ Map<Integer, String> tcpPortMappings = getConfig(TCP_PORT_MAPPINGS);
+ if (tcpPortMappings != null) {
+ PortForwardManager pfm = (PortForwardManager) getManagementContext().getLocationRegistry().resolve("portForwardManager(scope=global)");
+ for (Map.Entry<Integer, String> entry : tcpPortMappings.entrySet()) {
+ int targetPort = entry.getKey();
+ HostAndPort publicEndpoint = HostAndPort.fromString(entry.getValue());
+ if (!publicEndpoint.hasPort()) {
+ throw new IllegalArgumentException("Invalid portMapping ('"+entry.getValue()+"') for port "+targetPort+" in machine "+this);
+ }
+ pfm.associate(publicEndpoint.getHostText(), publicEndpoint, this, targetPort);
+ }
+ }
+ }
public String getUser() {
return config().get(USER);
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/9633236d/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java
index 5ce0dac..3ddc5ad 100644
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/ByonLocationsYamlTest.java
@@ -19,6 +19,7 @@
package io.brooklyn.camp.brooklyn;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
import java.io.StringReader;
import java.util.Map;
@@ -28,21 +29,23 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;
+import com.google.api.client.repackaged.com.google.common.base.Joiner;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.net.HostAndPort;
+
import brooklyn.entity.Entity;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.location.MachineLocation;
+import brooklyn.location.access.PortForwardManager;
import brooklyn.location.basic.FixedListMachineProvisioningLocation;
import brooklyn.location.basic.LocationPredicates;
import brooklyn.location.basic.SshMachineLocation;
import brooklyn.location.basic.WinRmMachineLocation;
import brooklyn.util.net.UserAndHostAndPort;
-import com.google.api.client.repackaged.com.google.common.base.Joiner;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-
public class ByonLocationsYamlTest extends AbstractYamlTest {
private static final Logger log = LoggerFactory.getLogger(ByonLocationsYamlTest.class);
@@ -165,7 +168,56 @@ public class ByonLocationsYamlTest extends AbstractYamlTest {
"mykey", "myval3"));
assertEquals(machine3.getPrivateAddresses(), ImmutableSet.of("10.0.0.3"));
}
-
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testByonPortMapping() throws Exception {
+ String yaml = Joiner.on("\n").join(
+ "location:",
+ " byon:",
+ " hosts:",
+ " - ssh: 1.1.1.1:22",
+ " privateAddresses: [10.0.0.1]",
+ " tcpPortMappings: {22: \"83.222.229.1:12001\", 8080: \"83.222.229.1:12002\"}",
+ " password: mypassword",
+ " user: myuser",
+ " mykey: myval1",
+ " - winrm: 1.1.1.2:8985",
+ " privateAddresses: [10.0.0.2]",
+ " tcpPortMappings: {8985: \"83.222.229.2:12003\", 8080: \"83.222.229.2:12004\"}",
+ " password: mypassword",
+ " user: myuser",
+ " mykey: myval2",
+ " osfamily: windows",
+ "services:",
+ "- serviceType: brooklyn.entity.basic.BasicApplication");
+
+ Entity app = createStartWaitAndLogApplication(new StringReader(yaml));
+ FixedListMachineProvisioningLocation<MachineLocation> loc = (FixedListMachineProvisioningLocation<MachineLocation>) Iterables.get(app.getLocations(), 0);
+ PortForwardManager pfm = (PortForwardManager) mgmt().getLocationRegistry().resolve("portForwardManager(scope=global)");
+
+ Set<MachineLocation> machines = loc.getAvailable();
+ assertEquals(machines.size(), 2, "machines="+machines);
+ SshMachineLocation machine1 = (SshMachineLocation) Iterables.find(machines, LocationPredicates.configEqualTo(ConfigKeys.newStringConfigKey("mykey"), "myval1"));
+ WinRmMachineLocation machine2 = (WinRmMachineLocation) Iterables.find(machines, Predicates.instanceOf(WinRmMachineLocation.class));
+
+ assertMachine(machine1, UserAndHostAndPort.fromParts("myuser", "83.222.229.1", 12001), ImmutableMap.of(
+ SshMachineLocation.PASSWORD.getName(), "mypassword",
+ "mykey", "myval1"));
+ assertEquals(machine1.getPrivateAddresses(), ImmutableSet.of("10.0.0.1"));
+ assertEquals(pfm.lookup(machine1, 22), HostAndPort.fromParts("83.222.229.1", 12001));
+ assertEquals(pfm.lookup(machine1, 8080), HostAndPort.fromParts("83.222.229.1", 12002));
+ assertNull(pfm.lookup(machine1, 12345));
+
+ assertMachine(machine2, UserAndHostAndPort.fromParts("myuser", "83.222.229.2", 12003), ImmutableMap.of(
+ SshMachineLocation.PASSWORD.getName(), "mypassword",
+ "mykey", "myval2"));
+ assertEquals(machine2.getPrivateAddresses(), ImmutableSet.of("10.0.0.2"));
+ assertEquals(pfm.lookup(machine2, 8985), HostAndPort.fromParts("83.222.229.2", 12003));
+ assertEquals(pfm.lookup(machine2, 8080), HostAndPort.fromParts("83.222.229.2", 12004));
+ assertNull(pfm.lookup(machine2, 12345));
+ }
+
private void assertMachine(SshMachineLocation machine, UserAndHostAndPort conn, Map<String, ?> config) {
assertEquals(machine.getAddress().getHostAddress(), conn.getHostAndPort().getHostText());
assertEquals(machine.getPort(), conn.getHostAndPort().getPort());
[6/6] incubator-brooklyn git commit: This closes #776
Posted by al...@apache.org.
This closes #776
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/05b95f37
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/05b95f37
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/05b95f37
Branch: refs/heads/master
Commit: 05b95f377197cc4033131de26c846db1c91575b5
Parents: 946b5dc bac43b0
Author: Aled Sage <al...@gmail.com>
Authored: Wed Jul 29 00:13:16 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Jul 29 00:13:16 2015 +0100
----------------------------------------------------------------------
.../BasicMachineLocationCustomizer.java | 41 +++++
.../location/MachineLocationCustomizer.java | 42 +++++
.../location/basic/ByonLocationResolver.java | 47 +++--
.../FixedListMachineProvisioningLocation.java | 44 +++--
.../java/brooklyn/location/basic/Machines.java | 11 ++
.../location/basic/SshMachineLocation.java | 72 +++++---
.../location/basic/WinRmMachineLocation.java | 42 +++--
.../location/cloud/CloudLocationConfig.java | 8 +
...ixedListMachineProvisioningLocationTest.java | 44 ++++-
.../RecordingMachineLocationCustomizer.java | 71 ++++++++
.../location/jclouds/JcloudsLocation.java | 79 +++++----
.../location/jclouds/JcloudsLocationConfig.java | 12 +-
.../location/jclouds/JcloudsLocationTest.java | 10 ++
.../brooklyn/entity/basic/SoftwareProcess.java | 16 ++
.../entity/software/MachineInitTasks.java | 172 +++++++++++++++++++
.../software/MachineLifecycleEffectorTasks.java | 41 ++++-
.../webapp/tomcat/TomcatServerEc2LiveTest.java | 1 +
.../camp/brooklyn/ByonLocationsYamlTest.java | 66 ++++++-
18 files changed, 707 insertions(+), 112 deletions(-)
----------------------------------------------------------------------
[4/6] incubator-brooklyn git commit: Set subnet_address if has
HasNetworkAddresses.privateAddresses
Posted by al...@apache.org.
Set subnet_address if has HasNetworkAddresses.privateAddresses
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/4980904f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/4980904f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/4980904f
Branch: refs/heads/master
Commit: 4980904fe1a93f5b5580484ccc5124d2a68152c4
Parents: 9633236
Author: Aled Sage <al...@gmail.com>
Authored: Fri Jul 24 19:15:43 2015 -0700
Committer: Aled Sage <al...@gmail.com>
Committed: Mon Jul 27 13:50:00 2015 +0100
----------------------------------------------------------------------
core/src/main/java/brooklyn/location/basic/Machines.java | 11 +++++++++++
1 file changed, 11 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4980904f/core/src/main/java/brooklyn/location/basic/Machines.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/location/basic/Machines.java b/core/src/main/java/brooklyn/location/basic/Machines.java
index 103870f..7c143a8 100644
--- a/core/src/main/java/brooklyn/location/basic/Machines.java
+++ b/core/src/main/java/brooklyn/location/basic/Machines.java
@@ -21,16 +21,20 @@ package brooklyn.location.basic;
import java.net.InetAddress;
import java.util.Collection;
import java.util.Iterator;
+import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.Iterables;
+
import brooklyn.entity.Entity;
import brooklyn.entity.basic.Attributes;
import brooklyn.location.Location;
import brooklyn.location.MachineLocation;
import brooklyn.location.basic.LocalhostMachineProvisioningLocation.LocalhostMachine;
import brooklyn.util.guava.Maybe;
+import brooklyn.util.net.HasNetworkAddresses;
/** utilities for working with MachineLocations */
public class Machines {
@@ -38,6 +42,7 @@ public class Machines {
private static final Logger log = LoggerFactory.getLogger(Machines.class);
public static Maybe<String> getSubnetHostname(Location where) {
+ // TODO Should we look at HasNetworkAddresses? But that's not a hostname.
String hostname = null;
if (where instanceof HasSubnetHostname) {
hostname = ((HasSubnetHostname) where).getSubnetHostname();
@@ -58,6 +63,12 @@ public class Machines {
if (where instanceof HasSubnetHostname) {
result = ((HasSubnetHostname) where).getSubnetIp();
}
+ if (where instanceof HasNetworkAddresses) {
+ Set<String> privateAddrs = ((HasNetworkAddresses) where).getPrivateAddresses();
+ if (privateAddrs.size() > 0) {
+ result = Iterables.get(privateAddrs, 0);
+ }
+ }
if (result == null && where instanceof MachineLocation) {
InetAddress addr = ((MachineLocation) where).getAddress();
if (addr != null) result = addr.getHostAddress();
[3/6] incubator-brooklyn git commit: Deprecates
JcloudsLocation.open/stopIptables config
Posted by al...@apache.org.
Deprecates JcloudsLocation.open/stopIptables config
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/42d60916
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/42d60916
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/42d60916
Branch: refs/heads/master
Commit: 42d6091663495665dc68c0d45d2e640984b3ad89
Parents: 4980904
Author: Aled Sage <al...@gmail.com>
Authored: Sat Jul 25 14:58:03 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Mon Jul 27 13:50:00 2015 +0100
----------------------------------------------------------------------
.../java/brooklyn/location/jclouds/JcloudsLocation.java | 8 ++++++--
.../location/jclouds/JcloudsLocationConfig.java | 12 ++++++++++--
2 files changed, 16 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/42d60916/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
index c4996df..60119ea 100644
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
+++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
@@ -877,8 +877,10 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
if (setup.get(OPEN_IPTABLES)) {
if (windows) {
- LOG.warn("Ignoring flag OPEN_IPTABLES on Windows location {}", machineLocation);
+ LOG.warn("Ignoring DEPRECATED flag OPEN_IPTABLES on Windows location {}", machineLocation);
} else {
+ LOG.warn("Using DEPRECATED flag OPEN_IPTABLES (will not be supported in future versions) for {} at {}", machineLocation, this);
+
@SuppressWarnings("unchecked")
Iterable<Integer> inboundPorts = (Iterable<Integer>) setup.get(INBOUND_PORTS);
@@ -917,8 +919,10 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
if (setup.get(STOP_IPTABLES)) {
if (windows) {
- LOG.warn("Ignoring flag OPEN_IPTABLES on Windows location {}", machineLocation);
+ LOG.warn("Ignoring DEPRECATED flag OPEN_IPTABLES on Windows location {}", machineLocation);
} else {
+ LOG.warn("Using DEPRECATED flag STOP_IPTABLES (will not be supported in future versions) for {} at {}", machineLocation, this);
+
customisationForLogging.add("stop iptables");
List<String> cmds = ImmutableList.<String>of();
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/42d60916/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java
index c37d915..2d570ae 100644
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java
+++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocationConfig.java
@@ -106,12 +106,20 @@ public interface JcloudsLocationConfig extends CloudLocationConfig {
Constants.PROPERTY_ENDPOINT, "Equivalent to 'endpoint'; provided for jclouds compatibility", null);
// note causing problems on centos due to use of `sudo -n`; but required for default RHEL VM
+ /**
+ * @deprecated since 0.8.0; instead configure this on the entity. See SoftwareProcess.OPEN_IPTABLES.
+ */
+ @Deprecated
public static final ConfigKey<Boolean> OPEN_IPTABLES = ConfigKeys.newBooleanConfigKey("openIptables",
- "Whether to open the INBOUND_PORTS via iptables rules; " +
+ "[DEPRECATED - use openIptables on SoftwareProcess entity] Whether to open the INBOUND_PORTS via iptables rules; " +
"if true then ssh in to run iptables commands, as part of machine provisioning", false);
+ /**
+ * @deprecated since 0.8.0; instead configure this on the entity. See SoftwareProcess.STOP_IPTABLES.
+ */
+ @Deprecated
public static final ConfigKey<Boolean> STOP_IPTABLES = ConfigKeys.newBooleanConfigKey("stopIptables",
- "Whether to stop iptables entirely; " +
+ "[DEPRECATED - use stopIptables on SoftwareProcess entity] Whether to stop iptables entirely; " +
"if true then ssh in to stop the iptables service, as part of machine provisioning", false);
public static final ConfigKey<String> HARDWARE_ID = ConfigKeys.newStringConfigKey("hardwareId",
[5/6] incubator-brooklyn git commit: Adds MACHINE_LOCATION_CUSTOMIZERS
Posted by al...@apache.org.
Adds MACHINE_LOCATION_CUSTOMIZERS
A similar idea to the JcloudsMachineLocationCustomizer, but more
generic - it deals just with the MachineLocation. It can be wired
in to JcloudsLocation and to BYON (i.e. FixedListMachineProvisioningLocation).
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/bac43b07
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/bac43b07
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/bac43b07
Branch: refs/heads/master
Commit: bac43b0705f6d2fd51e89402b6631f8f07619dbb
Parents: 90f1881
Author: Aled Sage <al...@gmail.com>
Authored: Mon Jul 27 17:48:02 2015 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Mon Jul 27 17:48:02 2015 +0100
----------------------------------------------------------------------
.../BasicMachineLocationCustomizer.java | 41 +++++++++++
.../location/MachineLocationCustomizer.java | 42 ++++++++++++
.../FixedListMachineProvisioningLocation.java | 44 +++++++++---
.../location/cloud/CloudLocationConfig.java | 8 +++
...ixedListMachineProvisioningLocationTest.java | 44 ++++++++++--
.../RecordingMachineLocationCustomizer.java | 71 ++++++++++++++++++++
.../location/jclouds/JcloudsLocation.java | 71 +++++++++++---------
.../location/jclouds/JcloudsLocationTest.java | 10 +++
8 files changed, 283 insertions(+), 48 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bac43b07/api/src/main/java/brooklyn/location/BasicMachineLocationCustomizer.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/location/BasicMachineLocationCustomizer.java b/api/src/main/java/brooklyn/location/BasicMachineLocationCustomizer.java
new file mode 100644
index 0000000..a05dd44
--- /dev/null
+++ b/api/src/main/java/brooklyn/location/BasicMachineLocationCustomizer.java
@@ -0,0 +1,41 @@
+/*
+ * 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.location;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A default no-op implementation, which can be extended to override the appropriate methods.
+ *
+ * Sub-classing will give the user some protection against future API changes - note that
+ * {@link MachineLocationCustomizer} is marked {@link Beta}.
+ */
+@Beta
+public class BasicMachineLocationCustomizer implements MachineLocationCustomizer {
+
+ @Override
+ public void customize(MachineLocation machine) {
+ // no-op
+ }
+
+ @Override
+ public void preRelease(MachineLocation machine) {
+ // no-op
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bac43b07/api/src/main/java/brooklyn/location/MachineLocationCustomizer.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/location/MachineLocationCustomizer.java b/api/src/main/java/brooklyn/location/MachineLocationCustomizer.java
new file mode 100644
index 0000000..83e1009
--- /dev/null
+++ b/api/src/main/java/brooklyn/location/MachineLocationCustomizer.java
@@ -0,0 +1,42 @@
+/*
+ * 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.location;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Customization hooks to allow apps to perform specific customisation of obtained machines.
+ * <p>
+ * Users are strongly encouraged to sub-class {@link BasicMachineLocationCustomizer}, to give
+ * some protection against this {@link Beta} API changing in future releases.
+ */
+@Beta
+public interface MachineLocationCustomizer {
+
+ /**
+ * Override to configure the given machine once it has been created (prior to any use).
+ */
+ void customize(MachineLocation machine);
+
+ /**
+ * Override to handle machine-related cleanup prior to {@link MachineProvisioningLocation}
+ * releasing the machine.
+ */
+ void preRelease(MachineLocation machine);
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bac43b07/core/src/main/java/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/location/basic/FixedListMachineProvisioningLocation.java b/core/src/main/java/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
index d8aad46..50a2a17 100644
--- a/core/src/main/java/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
+++ b/core/src/main/java/brooklyn/location/basic/FixedListMachineProvisioningLocation.java
@@ -31,31 +31,35 @@ import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.reflect.TypeToken;
+
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.location.Location;
import brooklyn.location.LocationSpec;
import brooklyn.location.MachineLocation;
+import brooklyn.location.MachineLocationCustomizer;
import brooklyn.location.MachineProvisioningLocation;
import brooklyn.location.NoMachinesAvailableException;
+import brooklyn.location.cloud.CloudLocationConfig;
import brooklyn.management.LocationManager;
import brooklyn.util.collections.CollectionFunctionals;
import brooklyn.util.collections.MutableMap;
import brooklyn.util.collections.MutableSet;
+import brooklyn.util.config.ConfigBag;
import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.stream.Streams;
import brooklyn.util.text.WildcardGlobs;
import brooklyn.util.text.WildcardGlobs.PhraseTreatment;
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.common.reflect.TypeToken;
-
/**
* A provisioner of {@link MachineLocation}s which takes a list of machines it can connect to.
* The collection of initial machines should be supplied in the 'machines' flag in the constructor,
@@ -80,6 +84,8 @@ implements MachineProvisioningLocation<T>, Closeable {
"byon.machineChooser",
"For choosing which of the possible machines is chosen and returned by obtain()",
CollectionFunctionals.<MachineLocation>firstElement());
+
+ public static final ConfigKey<Collection<MachineLocationCustomizer>> MACHINE_LOCATION_CUSTOMIZERS = CloudLocationConfig.MACHINE_LOCATION_CUSTOMIZERS;
private final Object lock = new Object();
@@ -238,13 +244,14 @@ implements MachineProvisioningLocation<T>, Closeable {
public T obtain(Map<?,?> flags) throws NoMachinesAvailableException {
T machine;
T desiredMachine = (T) flags.get("desiredMachine");
- Function<Iterable<? extends MachineLocation>, MachineLocation> chooser = getConfigPreferringOverridden(MACHINE_CHOOSER, flags);
+ ConfigBag allflags = ConfigBag.newInstanceExtending(config().getBag()).putAll(flags);
+ Function<Iterable<? extends MachineLocation>, MachineLocation> chooser = allflags.get(MACHINE_CHOOSER);
synchronized (lock) {
Set<T> a = getAvailable();
if (a.isEmpty()) {
if (canProvisionMore()) {
- provisionMore(1, flags);
+ provisionMore(1, allflags.getAllConfig());
a = getAvailable();
}
if (a.isEmpty())
@@ -265,11 +272,21 @@ implements MachineProvisioningLocation<T>, Closeable {
}
inUse.add(machine);
}
+
+ for (MachineLocationCustomizer customizer : getMachineCustomizers(allflags)) {
+ customizer.customize(machine);
+ }
+
return machine;
}
@Override
public void release(T machine) {
+ ConfigBag machineConfig = ((ConfigurationSupportInternal)machine.config()).getBag();
+ for (MachineLocationCustomizer customizer : getMachineCustomizers(machineConfig)) {
+ customizer.preRelease(machine);
+ }
+
synchronized (lock) {
if (inUse.contains(machine) == false)
throw new IllegalStateException("Request to release machine "+machine+", but this machine is not currently allocated");
@@ -294,6 +311,11 @@ implements MachineProvisioningLocation<T>, Closeable {
return result;
}
+ protected Collection<MachineLocationCustomizer> getMachineCustomizers(ConfigBag setup) {
+ Collection<MachineLocationCustomizer> customizers = setup.get(MACHINE_LOCATION_CUSTOMIZERS);
+ return (customizers == null ? ImmutableList.<MachineLocationCustomizer>of() : customizers);
+ }
+
/**
* Facilitates fluent/programmatic style for constructing a fixed pool of machines.
* <pre>
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bac43b07/core/src/main/java/brooklyn/location/cloud/CloudLocationConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/location/cloud/CloudLocationConfig.java b/core/src/main/java/brooklyn/location/cloud/CloudLocationConfig.java
index 9134af7..66c6065 100644
--- a/core/src/main/java/brooklyn/location/cloud/CloudLocationConfig.java
+++ b/core/src/main/java/brooklyn/location/cloud/CloudLocationConfig.java
@@ -18,11 +18,15 @@
*/
package brooklyn.location.cloud;
+import java.util.Collection;
+
import com.google.common.annotations.Beta;
+import com.google.common.reflect.TypeToken;
import brooklyn.config.ConfigKey;
import brooklyn.entity.basic.ConfigKeys;
import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.location.MachineLocationCustomizer;
import brooklyn.location.basic.LocationConfigKeys;
import brooklyn.util.flags.SetFromFlag;
@@ -105,4 +109,8 @@ public interface CloudLocationConfig {
public static final ConfigKey<String> DOMAIN_NAME = new BasicConfigKey<String>(String.class, "domainName",
"DNS domain where the host should be created, e.g. yourdomain.com (selected clouds only)", null);
+ @SuppressWarnings("serial")
+ public static final ConfigKey<Collection<MachineLocationCustomizer>> MACHINE_LOCATION_CUSTOMIZERS = ConfigKeys.newConfigKey(
+ new TypeToken<Collection<MachineLocationCustomizer>>() {},
+ "machineCustomizers", "Optional machine customizers");
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bac43b07/core/src/test/java/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java b/core/src/test/java/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
index b0edf8c..78a61a9 100644
--- a/core/src/test/java/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
+++ b/core/src/test/java/brooklyn/location/basic/FixedListMachineProvisioningLocationTest.java
@@ -34,10 +34,18 @@ import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
import brooklyn.entity.basic.Entities;
import brooklyn.location.LocationSpec;
import brooklyn.location.MachineLocation;
import brooklyn.location.NoMachinesAvailableException;
+import brooklyn.location.basic.RecordingMachineLocationCustomizer.Call;
import brooklyn.management.internal.LocalManagementContext;
import brooklyn.test.entity.LocalManagementContextForTests;
import brooklyn.util.collections.MutableList;
@@ -45,13 +53,6 @@ import brooklyn.util.collections.MutableMap;
import brooklyn.util.net.Networking;
import brooklyn.util.stream.Streams;
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
/**
* Provisions {@link SshMachineLocation}s in a specific location from a list of known machines
*/
@@ -472,6 +473,35 @@ public class FixedListMachineProvisioningLocationTest {
}
}
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testMachineCustomizerSetOnByon() throws Exception {
+ machine = mgmt.getLocationManager().createLocation(MutableMap.of("address", Inet4Address.getByName("192.168.144.200")), SshMachineLocation.class);
+ RecordingMachineLocationCustomizer customizer = new RecordingMachineLocationCustomizer();
+
+ provisioner2 = mgmt.getLocationManager().createLocation(LocationSpec.create(FixedListMachineProvisioningLocation.class)
+ .configure("machines", ImmutableList.of(machine))
+ .configure(FixedListMachineProvisioningLocation.MACHINE_LOCATION_CUSTOMIZERS.getName(), ImmutableList.of(customizer)));
+
+ SshMachineLocation obtained = provisioner2.obtain();
+ assertEquals(Iterables.getOnlyElement(customizer.calls), new Call("customize", ImmutableList.of(obtained)));
+
+ provisioner2.release(obtained);
+ assertEquals(customizer.calls.size(), 2);
+ assertEquals(Iterables.get(customizer.calls, 1), new Call("preRelease", ImmutableList.of(obtained)));
+ }
+
+ @Test
+ public void testMachineCustomizerSetOnObtainCall() throws Exception {
+ RecordingMachineLocationCustomizer customizer = new RecordingMachineLocationCustomizer();
+
+ SshMachineLocation obtained = provisioner.obtain(ImmutableMap.of(FixedListMachineProvisioningLocation.MACHINE_LOCATION_CUSTOMIZERS, ImmutableList.of(customizer)));
+ assertEquals(Iterables.getOnlyElement(customizer.calls), new Call("customize", ImmutableList.of(obtained)));
+
+ // TODO Does not call preRelease, because customizer is not config on provisioner, and is not config on machine
+ provisioner.release(obtained);
+ }
+
private static <T> List<T> randomized(Iterable<T> list) {
// TODO inefficient implementation, but don't care for small tests
Random random = new Random();
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bac43b07/core/src/test/java/brooklyn/location/basic/RecordingMachineLocationCustomizer.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/location/basic/RecordingMachineLocationCustomizer.java b/core/src/test/java/brooklyn/location/basic/RecordingMachineLocationCustomizer.java
new file mode 100644
index 0000000..0422b36
--- /dev/null
+++ b/core/src/test/java/brooklyn/location/basic/RecordingMachineLocationCustomizer.java
@@ -0,0 +1,71 @@
+/*
+ * 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.location.basic;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import brooklyn.location.MachineLocation;
+import brooklyn.location.MachineLocationCustomizer;
+
+public class RecordingMachineLocationCustomizer implements MachineLocationCustomizer {
+ public static class Call {
+ public final String methodName;
+ public final List<?> args;
+
+ Call(String methodName, List<?> args) {
+ this.methodName = checkNotNull(methodName);
+ this.args = checkNotNull(args);
+ }
+
+ @Override
+ public String toString() {
+ return methodName+args;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(methodName, args);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return (other instanceof RecordingMachineLocationCustomizer.Call) &&
+ methodName.equals(((RecordingMachineLocationCustomizer.Call)other).methodName) &&
+ args.equals(((RecordingMachineLocationCustomizer.Call)other).args);
+ }
+ }
+
+ public final List<RecordingMachineLocationCustomizer.Call> calls = Lists.newCopyOnWriteArrayList();
+
+ @Override
+ public void customize(MachineLocation machine) {
+ calls.add(new Call("customize", ImmutableList.of(machine)));
+ }
+
+ @Override
+ public void preRelease(MachineLocation machine) {
+ calls.add(new Call("preRelease", ImmutableList.of(machine)));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bac43b07/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
index 60119ea..c7d9f95 100644
--- a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
+++ b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
@@ -26,11 +26,6 @@ import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.compute.options.RunScriptOptions.Builder.overrideLoginCredentials;
import static org.jclouds.scriptbuilder.domain.Statements.exec;
-import brooklyn.util.flags.MethodCoercions;
-import brooklyn.location.basic.AbstractLocation;
-import io.cloudsoft.winrm4j.pywinrm.Session;
-import io.cloudsoft.winrm4j.pywinrm.WinRMFactory;
-
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
@@ -93,6 +88,31 @@ import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Charsets;
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Splitter;
+import com.google.common.base.Stopwatch;
+import com.google.common.base.Supplier;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Sets.SetView;
+import com.google.common.io.Files;
+import com.google.common.net.HostAndPort;
+import com.google.common.primitives.Ints;
+
import brooklyn.config.ConfigKey;
import brooklyn.config.ConfigKey.HasConfigKey;
import brooklyn.config.ConfigUtils;
@@ -103,11 +123,13 @@ import brooklyn.entity.rebind.persister.PersistenceObjectStore;
import brooklyn.entity.rebind.persister.jclouds.JcloudsBlobStoreBasedObjectStore;
import brooklyn.location.LocationSpec;
import brooklyn.location.MachineLocation;
+import brooklyn.location.MachineLocationCustomizer;
import brooklyn.location.MachineManagementMixins.MachineMetadata;
import brooklyn.location.MachineManagementMixins.RichMachineProvisioningLocation;
import brooklyn.location.NoMachinesAvailableException;
import brooklyn.location.access.PortForwardManager;
import brooklyn.location.access.PortMapping;
+import brooklyn.location.basic.AbstractLocation;
import brooklyn.location.basic.BasicMachineMetadata;
import brooklyn.location.basic.LocationConfigKeys;
import brooklyn.location.basic.LocationConfigUtils;
@@ -132,6 +154,7 @@ import brooklyn.util.crypto.SecureKeys;
import brooklyn.util.exceptions.CompoundRuntimeException;
import brooklyn.util.exceptions.Exceptions;
import brooklyn.util.exceptions.ReferenceWithError;
+import brooklyn.util.flags.MethodCoercions;
import brooklyn.util.flags.SetFromFlag;
import brooklyn.util.flags.TypeCoercions;
import brooklyn.util.guava.Maybe;
@@ -156,31 +179,8 @@ import brooklyn.util.text.Strings;
import brooklyn.util.text.TemplateProcessor;
import brooklyn.util.time.Duration;
import brooklyn.util.time.Time;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.base.Splitter;
-import com.google.common.base.Stopwatch;
-import com.google.common.base.Supplier;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Iterators;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Sets.SetView;
-import com.google.common.io.Files;
-import com.google.common.net.HostAndPort;
-import com.google.common.primitives.Ints;
+import io.cloudsoft.winrm4j.pywinrm.Session;
+import io.cloudsoft.winrm4j.pywinrm.WinRMFactory;
/**
* For provisioning and managing VMs in a particular provider/region, using jclouds.
@@ -440,6 +440,11 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
return result;
}
+ protected Collection<MachineLocationCustomizer> getMachineCustomizers(ConfigBag setup) {
+ Collection<MachineLocationCustomizer> customizers = setup.get(MACHINE_LOCATION_CUSTOMIZERS);
+ return (customizers == null ? ImmutableList.<MachineLocationCustomizer>of() : customizers);
+ }
+
public void setDefaultImageId(String val) {
config().set(DEFAULT_IMAGE_ID, val);
}
@@ -958,6 +963,9 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
for (JcloudsLocationCustomizer customizer : getCustomizers(setup)) {
customizer.customize(this, computeService, machineLocation);
}
+ for (MachineLocationCustomizer customizer : getMachineCustomizers(setup)) {
+ customizer.customize(machineLocation);
+ }
customizedTimestamp = Duration.of(provisioningStopwatch);
@@ -2167,6 +2175,9 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
if (tothrow==null) tothrow = e;
}
}
+ for (MachineLocationCustomizer customizer : getMachineCustomizers(setup)) {
+ customizer.preRelease(machine);
+ }
try {
// FIXME: Needs to release port forwarding for WinRmMachineLocations
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/bac43b07/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationTest.java b/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationTest.java
index c175e29..5676787 100644
--- a/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationTest.java
+++ b/locations/jclouds/src/test/java/brooklyn/location/jclouds/JcloudsLocationTest.java
@@ -24,6 +24,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+
import javax.annotation.Nullable;
import org.jclouds.scriptbuilder.domain.OsFamily;
@@ -48,6 +49,7 @@ import brooklyn.entity.basic.ConfigKeys;
import brooklyn.entity.basic.Entities;
import brooklyn.location.LocationSpec;
import brooklyn.location.MachineLocation;
+import brooklyn.location.MachineLocationCustomizer;
import brooklyn.location.NoMachinesAvailableException;
import brooklyn.location.basic.LocationConfigKeys;
import brooklyn.location.cloud.names.CustomMachineNamer;
@@ -383,6 +385,9 @@ public class JcloudsLocationTest implements JcloudsLocationConfig {
for (JcloudsLocationCustomizer customizer : getCustomizers(config().getBag())) {
customizer.customize(this, null, (JcloudsMachineLocation)result);
}
+ for (MachineLocationCustomizer customizer : getMachineCustomizers(config().getBag())) {
+ customizer.customize((JcloudsMachineLocation)result);
+ }
return result;
}
@@ -440,22 +445,27 @@ public class JcloudsLocationTest implements JcloudsLocationConfig {
@Test
public void testInvokesCustomizerCallbacks() throws Exception {
JcloudsLocationCustomizer customizer = Mockito.mock(JcloudsLocationCustomizer.class);
+ MachineLocationCustomizer machineCustomizer = Mockito.mock(MachineLocationCustomizer.class);
// Mockito.when(customizer.customize(Mockito.any(JcloudsLocation.class), Mockito.any(ComputeService.class), Mockito.any(JcloudsSshMachineLocation.class)));
ConfigBag allConfig = ConfigBag.newInstance()
.configure(CLOUD_PROVIDER, "aws-ec2")
.configure(ACCESS_IDENTITY, "bogus")
.configure(ACCESS_CREDENTIAL, "bogus")
.configure(JcloudsLocationConfig.JCLOUDS_LOCATION_CUSTOMIZERS, ImmutableList.of(customizer))
+ .configure(JcloudsLocation.MACHINE_LOCATION_CUSTOMIZERS, ImmutableList.of(machineCustomizer))
.configure(JcloudsLocation.MACHINE_CREATE_ATTEMPTS, 1);
FakeLocalhostWithParentJcloudsLocation ll = managementContext.getLocationManager().createLocation(LocationSpec.create(FakeLocalhostWithParentJcloudsLocation.class).configure(allConfig.getAllConfig()));
JcloudsMachineLocation l = (JcloudsMachineLocation)ll.obtain();
Mockito.verify(customizer, Mockito.times(1)).customize(ll, null, l);
Mockito.verify(customizer, Mockito.never()).preRelease(l);
Mockito.verify(customizer, Mockito.never()).postRelease(l);
+ Mockito.verify(machineCustomizer, Mockito.times(1)).customize(l);
+ Mockito.verify(machineCustomizer, Mockito.never()).preRelease(l);
ll.release(l);
Mockito.verify(customizer, Mockito.times(1)).preRelease(l);
Mockito.verify(customizer, Mockito.times(1)).postRelease(l);
+ Mockito.verify(machineCustomizer, Mockito.times(1)).preRelease(l);
}
// now test creating users