Updated Branches: refs/heads/branch-0.8 e025f8c85 -> c0ad6e869
WHIRR-713. Enable programmatic use of BYON via CacheNodeStoreModule. Project: http://git-wip-us.apache.org/repos/asf/whirr/repo Commit: http://git-wip-us.apache.org/repos/asf/whirr/commit/c0ad6e86 Tree: http://git-wip-us.apache.org/repos/asf/whirr/tree/c0ad6e86 Diff: http://git-wip-us.apache.org/repos/asf/whirr/diff/c0ad6e86 Branch: refs/heads/branch-0.8 Commit: c0ad6e86929f33475d8e6817e5dcdfea6b485556 Parents: e025f8c Author: Andrew Bayer <andrew.ba...@gmail.com> Authored: Sun Apr 7 19:13:49 2013 -0700 Committer: Andrew Bayer <andrew.ba...@gmail.com> Committed: Sun Apr 7 19:14:06 2013 -0700 ---------------------------------------------------------------------- CHANGES.txt | 3 + .../main/java/org/apache/whirr/ClusterSpec.java | 37 ++++++++- .../org/apache/whirr/service/ComputeCache.java | 44 +++++++++-- .../apache/whirr/ByonClusterControllerTest.java | 61 +++++++++++++++ 4 files changed, 136 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/whirr/blob/c0ad6e86/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 0a2921d..9023293 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,6 +4,9 @@ Release 0.8.2 (unreleased changes) IMPROVEMENTS + WHIRR-713. Enable programmatic use of BYON via + CacheNodeStoreModule. (abayer) + WHIRR-708. Upgrade to jclouds 1.5.8. (abayer) WHIRR-705. Provide better integration between parameterized http://git-wip-us.apache.org/repos/asf/whirr/blob/c0ad6e86/core/src/main/java/org/apache/whirr/ClusterSpec.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/whirr/ClusterSpec.java b/core/src/main/java/org/apache/whirr/ClusterSpec.java index fdddf14..e02c675 100644 --- a/core/src/main/java/org/apache/whirr/ClusterSpec.java +++ b/core/src/main/java/org/apache/whirr/ClusterSpec.java @@ -40,6 +40,7 @@ import org.apache.commons.configuration.ConfigurationUtils; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.io.IOUtils; import org.apache.whirr.internal.ConfigToTemplateBuilderSpec; +import org.jclouds.byon.Node; import org.jclouds.compute.domain.TemplateBuilderSpec; import org.jclouds.javax.annotation.Nullable; import org.jclouds.predicates.validators.DnsNameValidator; @@ -314,6 +315,8 @@ public class ClusterSpec { private String kerberosRealm; private Configuration config; + + private Map<String,Node> byonNodes; public ClusterSpec() throws ConfigurationException { this(new PropertiesConfiguration()); @@ -323,10 +326,14 @@ public class ClusterSpec { this(config, true); // load default configs } + public ClusterSpec(Configuration userConfig, boolean loadDefaults) { + this(userConfig, loadDefaults, new HashMap<String,Node>()); + } + /** * @throws ConfigurationException if something is wrong */ - public ClusterSpec(Configuration userConfig, boolean loadDefaults) + public ClusterSpec(Configuration userConfig, boolean loadDefaults, Map<String,Node> byonNodes) throws ConfigurationException { if (loadDefaults) { @@ -379,6 +386,8 @@ public class ClusterSpec { setAwsEc2PlacementGroup(getString(Property.AWS_EC2_PLACEMENT_GROUP)); + setByonNodes(byonNodes); + Map<String, List<String>> fr = new HashMap<String, List<String>>(); String firewallPrefix = Property.FIREWALL_RULES.getConfigName(); Pattern firewallRuleKeyPattern = Pattern.compile("^".concat(Pattern.quote(firewallPrefix).concat("(?:\\.(.+))?$"))); @@ -447,6 +456,8 @@ public class ClusterSpec { r.setJdkInstallUrl(getJdkInstallUrl()); r.setKerberosRealm(getKerberosRealm()); + + r.setByonNodes(getByonNodes()); return r; } @@ -677,6 +688,10 @@ public class ClusterSpec { return firewallRules; } + public Map<String, Node> getByonNodes() { + return byonNodes; + } + public String getVersion() { return version; } @@ -911,6 +926,18 @@ public class ClusterSpec { public void setFirewallRules(Map<String,List<String>> firewallRules) { this.firewallRules = firewallRules; } + + /** + * Sets the list of BYON nodes. Optional. Once the Cluster has been initialized from the ClusterSpec, + * further calls to setByonNodes will not result in changes in the Cluster. Generally, byonNodes + * should be initialized via the full constructor rather than this setter. + * + * @param byonNodes + */ + @VisibleForTesting + public void setByonNodes(Map<String,Node> byonNodes) { + this.byonNodes = byonNodes; + } public void setVersion(String version) { this.version = version; @@ -994,6 +1021,8 @@ public class ClusterSpec { && Objects.equal(getAutoHostnameSuffix(), that.getAutoHostnameSuffix()) && Objects.equal(getJdkInstallUrl(), that.getJdkInstallUrl()) && Objects.equal(getKerberosRealm(), that.getKerberosRealm()) + && Objects.equal(getFirewallRules(), that.getFirewallRules()) + && Objects.equal(getByonNodes(), that.getByonNodes()) ; } return false; @@ -1030,7 +1059,9 @@ public class ClusterSpec { getAutoHostnamePrefix(), getAutoHostnameSuffix(), getJdkInstallUrl(), - getKerberosRealm() + getKerberosRealm(), + getFirewallRules(), + getByonNodes() ); } @@ -1067,6 +1098,8 @@ public class ClusterSpec { .add("autoHostnameSuffix",getAutoHostnameSuffix()) .add("jdkInstallUrl", getJdkInstallUrl()) .add("kerberosRealm", getKerberosRealm()) + .add("firewallRules", getByonNodes()) + .add("byonNodes", getByonNodes()) .toString(); } } http://git-wip-us.apache.org/repos/asf/whirr/blob/c0ad6e86/core/src/main/java/org/apache/whirr/service/ComputeCache.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/whirr/service/ComputeCache.java b/core/src/main/java/org/apache/whirr/service/ComputeCache.java index 0455d6c..8f8d7d4 100644 --- a/core/src/main/java/org/apache/whirr/service/ComputeCache.java +++ b/core/src/main/java/org/apache/whirr/service/ComputeCache.java @@ -35,6 +35,10 @@ import org.jclouds.Context; import org.jclouds.ContextBuilder; import org.jclouds.apis.ApiMetadata; import org.jclouds.apis.Apis; +import org.jclouds.byon.BYONApiMetadata; +import org.jclouds.byon.Node; +import org.jclouds.byon.config.BYONComputeServiceContextModule; +import org.jclouds.byon.config.CacheNodeStoreModule; import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.Utils; @@ -60,6 +64,7 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ForwardingObject; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; @@ -84,7 +89,7 @@ public enum ComputeCache implements Function<ClusterSpec, ComputeServiceContext> } public void invalidate(ClusterSpec arg0) { - return cache.invalidate(new Key(arg0)); + cache.invalidate(new Key(arg0)); } // this should prevent recreating the same compute context twice @@ -95,10 +100,20 @@ public enum ComputeCache implements Function<ClusterSpec, ComputeServiceContext> @Override public ComputeServiceContext load(Key arg0) { LOG.debug("creating new ComputeServiceContext {}", arg0); - ContextBuilder builder = ContextBuilder.newBuilder(arg0.provider) - .credentials(arg0.identity, arg0.credential) - .overrides(arg0.overrides) - .modules(arg0.modules); + ContextBuilder builder; + + if (arg0.overrideApiMetadata != null) { + builder = ContextBuilder.newBuilder(arg0.overrideApiMetadata) + .credentials(arg0.identity, arg0.credential) + .overrides(arg0.overrides) + .modules(arg0.modules); + } else { + builder = ContextBuilder.newBuilder(arg0.provider) + .credentials(arg0.identity, arg0.credential) + .overrides(arg0.overrides) + .modules(arg0.modules); + } + if (arg0.endpoint != null) builder.endpoint(arg0.endpoint); ComputeServiceContext context = new IgnoreCloseComputeServiceContext( @@ -245,7 +260,9 @@ public enum ComputeCache implements Function<ClusterSpec, ComputeServiceContext> private String endpoint; private String identity; private String credential; - + private String clusterName; + private ApiMetadata overrideApiMetadata; + private final String key; private final Properties overrides; private final Set<Module> modules; @@ -256,11 +273,13 @@ public enum ComputeCache implements Function<ClusterSpec, ComputeServiceContext> endpoint = spec.getEndpoint(); identity = spec.getIdentity(); credential = spec.getCredential(); + clusterName = spec.getClusterName(); key = Objects.toStringHelper("").omitNullValues() .add("provider", provider) .add("endpoint", endpoint) - .add("identity", identity).toString(); + .add("identity", identity) + .add("clusterName", clusterName).toString(); Configuration jcloudsConfig = spec.getConfigurationForKeysWithPrefix("jclouds"); // jclouds configuration for providers are not prefixed with jclouds. @@ -282,6 +301,16 @@ public enum ComputeCache implements Function<ClusterSpec, ComputeServiceContext> if ("stub".equals(spec.getProvider())) { modules = ImmutableSet.<Module>of(new SLF4JLoggingModule(), new DryRunModule()); + } else if ("byon".equals(spec.getProvider()) && !spec.getByonNodes().isEmpty()) { + overrideApiMetadata = new BYONApiMetadata() + .toBuilder() + .defaultModule(BYONComputeServiceContextModule.class) + .build(); + + modules = ImmutableSet.<Module>of(new SLF4JLoggingModule(), + new EnterpriseConfigurationModule(), + new SshjSshClientModule(), + new CacheNodeStoreModule(ImmutableMap.<String,Node>copyOf(spec.getByonNodes()))); } else { modules = ImmutableSet.<Module>of(new SLF4JLoggingModule(), new EnterpriseConfigurationModule(), new SshjSshClientModule()); @@ -324,6 +353,7 @@ public enum ComputeCache implements Function<ClusterSpec, ComputeServiceContext> .add("provider", provider) .add("identity", identity) .add("overrides", overrides) + .add("clusterName", clusterName) .toString(); } } http://git-wip-us.apache.org/repos/asf/whirr/blob/c0ad6e86/core/src/test/java/org/apache/whirr/ByonClusterControllerTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/whirr/ByonClusterControllerTest.java b/core/src/test/java/org/apache/whirr/ByonClusterControllerTest.java new file mode 100644 index 0000000..3ebfa8b --- /dev/null +++ b/core/src/test/java/org/apache/whirr/ByonClusterControllerTest.java @@ -0,0 +1,61 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.whirr; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.HashMap; +import java.util.Map; + +import org.jclouds.byon.Node; + +import org.junit.Test; + +public class ByonClusterControllerTest { + @Test + public void testSpecifyByonCache() throws Exception { + Map<String,Node> byonNodes = new HashMap<String,Node>(); + + byonNodes.put("foo", Node.builder() + .id("foo-1234") + .name("foo-node") + .hostname("1.2.3.4") + .osFamily("ubuntu") + .osVersion("12.04") + .osDescription("foo OS") + .description("foo node").build()); + + ClusterSpec tempSpec = ClusterSpec.withTemporaryKeys(); + + tempSpec.setClusterName("test-cluster-for-byon-cache"); + tempSpec.setProvider("byon"); + tempSpec.setServiceName("byon"); + tempSpec.setIdentity("dummy"); + tempSpec.setStateStore("none"); + tempSpec.setByonNodes(byonNodes); + + ClusterControllerFactory factory = new ClusterControllerFactory(); + ClusterController controller = factory.create(tempSpec.getServiceName()); + + assertThat(controller.getInstances(tempSpec).size(), is(1)); + } + + +}