Configure RiakNode internal networking using optional security group customizer
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-library/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-library/commit/112080aa Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-library/tree/112080aa Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-library/diff/112080aa Branch: refs/heads/master Commit: 112080aac919776e8e353a1db538a46c2392fbf2 Parents: 54ad071 Author: Andrew Donald Kennedy <andrew.kenn...@cloudsoftcorp.com> Authored: Thu Jun 16 08:22:28 2016 +0100 Committer: Andrew Donald Kennedy <andrew.kenn...@cloudsoftcorp.com> Committed: Tue Jul 19 10:32:41 2016 +0100 ---------------------------------------------------------------------- software/nosql/pom.xml | 12 ++- .../brooklyn/entity/nosql/riak/RiakNode.java | 41 +++++++-- .../entity/nosql/riak/RiakNodeImpl.java | 94 +++++++++++++++----- 3 files changed, 112 insertions(+), 35 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/112080aa/software/nosql/pom.xml ---------------------------------------------------------------------- diff --git a/software/nosql/pom.xml b/software/nosql/pom.xml index 067629f..bc9dbc2 100644 --- a/software/nosql/pom.xml +++ b/software/nosql/pom.xml @@ -82,6 +82,11 @@ <version>${project.version}</version> </dependency> <dependency> + <groupId>org.apache.brooklyn</groupId> + <artifactId>brooklyn-locations-jclouds</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> @@ -221,13 +226,6 @@ <classifier>tests</classifier> <scope>test</scope> </dependency> - <!-- bring in jclouds for testing --> - <dependency> - <groupId>org.apache.brooklyn</groupId> - <artifactId>brooklyn-locations-jclouds</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> <dependency> <!-- We exclude jsr311-api transitive dependency from jclouds (for javax.ws.rs) due to version conflict. Therefore explicitly bring this one in. http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/112080aa/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNode.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNode.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNode.java index 13de43d..117c31d 100644 --- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNode.java +++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNode.java @@ -23,6 +23,7 @@ import java.util.List; import org.apache.brooklyn.api.catalog.Catalog; import org.apache.brooklyn.api.entity.ImplementedBy; +import org.apache.brooklyn.api.location.PortRange; import org.apache.brooklyn.api.sensor.AttributeSensor; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.annotation.Effector; @@ -30,6 +31,7 @@ import org.apache.brooklyn.core.annotation.EffectorParam; import org.apache.brooklyn.core.config.ConfigKeys; import org.apache.brooklyn.core.effector.MethodEffector; import org.apache.brooklyn.core.entity.Attributes; +import org.apache.brooklyn.core.location.PortRanges; import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey; import org.apache.brooklyn.core.sensor.PortAttributeSensorAndConfigKey; import org.apache.brooklyn.core.sensor.Sensors; @@ -107,10 +109,10 @@ public interface RiakNode extends SoftwareProcess, UsesJava { // NB these two needed for clients to access @SetFromFlag("riakWebPort") - PortAttributeSensorAndConfigKey RIAK_WEB_PORT = new PortAttributeSensorAndConfigKey("riak.webPort", "Riak Web Port", "8098+"); + PortAttributeSensorAndConfigKey RIAK_WEB_PORT = ConfigKeys.newPortSensorAndConfigKey("riak.web.port", "Riak Web Port", "8098+"); @SetFromFlag("riakPbPort") - PortAttributeSensorAndConfigKey RIAK_PB_PORT = new PortAttributeSensorAndConfigKey("riak.pbPort", "Riak Protocol Buffers Port", "8087+"); + PortAttributeSensorAndConfigKey RIAK_PB_PORT = ConfigKeys.newPortSensorAndConfigKey("riak.pb.port", "Riak Protocol Buffers Port", "8087+"); @SetFromFlag("useHttpMonitoring") ConfigKey<Boolean> USE_HTTP_MONITORING = ConfigKeys.newConfigKey("httpMonitoring.enabled", "HTTP(S) monitoring enabled", Boolean.TRUE); @@ -125,14 +127,37 @@ public interface RiakNode extends SoftwareProcess, UsesJava { AttributeSensor<String> RIAK_NODE_NAME = Sensors.newStringSensor("riak.node", "Returns the riak node name as defined in vm.args"); - // these needed for nodes to talk to each other, but not clients (so ideally set up in the security group for internal access) - PortAttributeSensorAndConfigKey HANDOFF_LISTENER_PORT = new PortAttributeSensorAndConfigKey("handoffListenerPort", "Handoff Listener Port", "8099+"); - PortAttributeSensorAndConfigKey EPMD_LISTENER_PORT = new PortAttributeSensorAndConfigKey("epmdListenerPort", "Erlang Port Mapper Daemon Listener Port", "4369"); - PortAttributeSensorAndConfigKey ERLANG_PORT_RANGE_START = new PortAttributeSensorAndConfigKey("erlangPortRangeStart", "Erlang Port Range Start", "6000+"); - PortAttributeSensorAndConfigKey ERLANG_PORT_RANGE_END = new PortAttributeSensorAndConfigKey("erlangPortRangeEnd", "Erlang Port Range End", "7999+"); + /* + * Needed for nodes to talk to each other, but not clients, so ideally set up in the security group for internal access and configured here. + * If {@link #CONFIGURE_INTERNAL_NETWORKING} is set, then a location customizer will be added to confiure the security group dynamically. + */ + + @SetFromFlag("handoffListenerPort") + ConfigKey<Integer> HANDOFF_LISTENER_PORT = ConfigKeys.newIntegerConfigKey("riak.handoff.port.internal", "Handoff Listener Port", 8099); + + @SetFromFlag("epmdListenerPort") + ConfigKey<Integer> EPMD_LISTENER_PORT = ConfigKeys.newIntegerConfigKey("riak.epmd.port.internal", "Erlang Port Mapper Daemon Listener Port", 4369); + + @SetFromFlag("erlangPortRange") + ConfigKey<PortRange> ERLANG_PORT_RANGE = ConfigKeys.newConfigKey(PortRange.class, "riak.erlang.portrange.internal", "Erlang Port Range", new PortRanges.LinearPortRange(6000, 7999)); + + // TODO Change {@link #ERLANG_PORT_RANGE_START} and {@link #ERLANG_PORT_RANGE_END} to sensors + + /** @deprecated since 0.10.0; use {@link #ERLANG_PORT_RANGE} instead */ + @Deprecated + @SetFromFlag("erlangPortRangeStart") + AttributeSensorAndConfigKey<Integer, Integer> ERLANG_PORT_RANGE_START = ConfigKeys.newIntegerSensorAndConfigKey("riak.erlang.portrange.start.internal", "Erlang Port Range Start"); + + /** @deprecated since 0.10.0; use {@link #ERLANG_PORT_RANGE} instead */ + @Deprecated + @SetFromFlag("erlangPortRangeEnd") + AttributeSensorAndConfigKey<Integer, Integer> ERLANG_PORT_RANGE_END = ConfigKeys.newIntegerSensorAndConfigKey("riak.erlang.portrange.end.internal", "Erlang Port Range End"); + + @SetFromFlag("configInternalNetworking") + ConfigKey<Boolean> CONFIGURE_INTERNAL_NETWORKING = ConfigKeys.newBooleanConfigKey("riak.networking.internal", "Set up internal networking for intra-node communication", Boolean.TRUE); @SetFromFlag("searchEnabled") - ConfigKey<Boolean> SEARCH_ENABLED = ConfigKeys.newBooleanConfigKey("riak.search", "Deploy Solr and configure Riak to use it", false); + ConfigKey<Boolean> SEARCH_ENABLED = ConfigKeys.newBooleanConfigKey("riak.search", "Deploy Solr and configure Riak to use it", Boolean.FALSE); /** * http://docs.basho.com/riak/latest/dev/using/search/ http://git-wip-us.apache.org/repos/asf/brooklyn-library/blob/112080aa/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeImpl.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeImpl.java b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeImpl.java index 60358a4..b5c6d85 100644 --- a/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeImpl.java +++ b/software/nosql/src/main/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeImpl.java @@ -22,12 +22,25 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; + +import org.jclouds.net.domain.IpPermission; +import org.jclouds.net.domain.IpProtocol; + +import org.apache.brooklyn.api.location.Location; import org.apache.brooklyn.api.location.MachineProvisioningLocation; +import org.apache.brooklyn.api.location.PortRange; import org.apache.brooklyn.api.sensor.AttributeSensor; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.location.access.BrooklynAccessUtils; @@ -39,22 +52,20 @@ import org.apache.brooklyn.entity.webapp.WebAppServiceMethods; import org.apache.brooklyn.feed.http.HttpFeed; import org.apache.brooklyn.feed.http.HttpPollConfig; import org.apache.brooklyn.feed.http.HttpValueFunctions; -import org.apache.brooklyn.util.collections.MutableSet; +import org.apache.brooklyn.location.jclouds.JcloudsMachineLocation; +import org.apache.brooklyn.location.jclouds.JcloudsSshMachineLocation; +import org.apache.brooklyn.location.jclouds.networking.JcloudsLocationSecurityGroupCustomizer; +import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.guava.Functionals; +import org.apache.brooklyn.util.net.Cidr; import org.apache.brooklyn.util.time.Duration; -import com.google.common.base.Function; -import com.google.common.base.Functions; -import com.google.common.base.Preconditions; -import com.google.common.collect.ContiguousSet; -import com.google.common.collect.DiscreteDomain; -import com.google.common.collect.Range; -import com.google.common.net.HostAndPort; - public class RiakNodeImpl extends SoftwareProcessImpl implements RiakNode { - private volatile HttpFeed httpFeed; + private static final Logger LOG = LoggerFactory.getLogger(RiakNodeImpl.class); + + private transient HttpFeed httpFeed; @Override public RiakNodeDriver getDriver() { @@ -99,17 +110,59 @@ public class RiakNodeImpl extends SoftwareProcessImpl implements RiakNode { @Override protected Collection<Integer> getRequiredOpenPorts() { - // TODO this creates a huge list of inbound ports; much better to define on a security group using range syntax! - int erlangRangeStart = getConfig(ERLANG_PORT_RANGE_START).iterator().next(); - int erlangRangeEnd = getConfig(ERLANG_PORT_RANGE_END).iterator().next(); + PortRange erlangPorts = config().get(ERLANG_PORT_RANGE); + Integer erlangRangeStart = config().get(ERLANG_PORT_RANGE_START); + Integer erlangRangeEnd = config().get(ERLANG_PORT_RANGE_END); + if (erlangRangeStart == null) erlangRangeStart = Iterables.get(erlangPorts, 0); + if (erlangRangeEnd == null) erlangRangeEnd = Iterables.getLast(erlangPorts); + sensors().set(ERLANG_PORT_RANGE_START, erlangRangeStart); + sensors().set(ERLANG_PORT_RANGE_END, erlangRangeEnd); + + boolean configureInternalNetworking = config().get(CONFIGURE_INTERNAL_NETWORKING); + if (configureInternalNetworking) { + configureInternalNetworking(); + } - Set<Integer> ports = MutableSet.copyOf(super.getRequiredOpenPorts()); - Set<Integer> erlangPorts = ContiguousSet.create(Range.open(erlangRangeStart, erlangRangeEnd), DiscreteDomain.integers()); - ports.addAll(erlangPorts); + return super.getRequiredOpenPorts(); + } - return ports; + private void configureInternalNetworking() { + Location location = getDriver().getLocation(); + if (!(location instanceof JcloudsSshMachineLocation)) { + LOG.info("Not running in a JcloudsSshMachineLocation, not adding IP permissions to {}", this); + return; + } + JcloudsMachineLocation machine = (JcloudsMachineLocation) location; + JcloudsLocationSecurityGroupCustomizer customizer = JcloudsLocationSecurityGroupCustomizer.getInstance(getApplicationId()); + + synchronized (getParent()) { + String cidr = Cidr.UNIVERSAL.toString(); // TODO configure with a more restrictive CIDR + Collection<IpPermission> permissions = MutableList.<IpPermission>builder() + .add(IpPermission.builder() + .ipProtocol(IpProtocol.TCP) + .fromPort(sensors().get(ERLANG_PORT_RANGE_START)) + .toPort(sensors().get(ERLANG_PORT_RANGE_END)) + .cidrBlock(cidr) + .build()) + .add(IpPermission.builder() + .ipProtocol(IpProtocol.TCP) + .fromPort(config().get(HANDOFF_LISTENER_PORT)) + .toPort(config().get(HANDOFF_LISTENER_PORT)) + .cidrBlock(cidr) + .build()) + .add(IpPermission.builder() + .ipProtocol(IpProtocol.TCP) + .fromPort(config().get(EPMD_LISTENER_PORT)) + .toPort(config().get(EPMD_LISTENER_PORT)) + .cidrBlock(cidr) + .build()) + .build(); + LOG.debug("Applying custom security groups to {}: {}", machine, permissions); + customizer.addPermissionsToLocation(machine, permissions); + } } + @Override public void connectSensors() { super.connectSensors(); @@ -248,6 +301,7 @@ public class RiakNodeImpl extends SoftwareProcessImpl implements RiakNode { protected boolean isHttpMonitoringEnabled() { return Boolean.TRUE.equals(getConfig(USE_HTTP_MONITORING)); } + @Override public Integer getRiakWebPort() { return getAttribute(RiakNode.RIAK_WEB_PORT); @@ -260,12 +314,12 @@ public class RiakNodeImpl extends SoftwareProcessImpl implements RiakNode { @Override public Integer getHandoffListenerPort() { - return getAttribute(RiakNode.HANDOFF_LISTENER_PORT); + return getConfig(RiakNode.HANDOFF_LISTENER_PORT); } @Override public Integer getEpmdListenerPort() { - return getAttribute(RiakNode.EPMD_LISTENER_PORT); + return getConfig(RiakNode.EPMD_LISTENER_PORT); } @Override