You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whirr.apache.org by as...@apache.org on 2011/12/07 18:15:00 UTC
svn commit: r1211543 - in /whirr/trunk: ./
cli/src/main/java/org/apache/whirr/cli/command/
cli/src/test/java/org/apache/whirr/cli/
cli/src/test/java/org/apache/whirr/cli/command/
core/src/main/java/org/apache/whirr/ core/src/main/java/org/apache/whirr/...
Author: asavu
Date: Wed Dec 7 17:14:59 2011
New Revision: 1211543
URL: http://svn.apache.org/viewvc?rev=1211543&view=rev
Log:
WHIRR-440. Unit tests improvements (less bound to external services) (asavu)
Added:
whirr/trunk/core/src/main/java/org/apache/whirr/net/
whirr/trunk/core/src/main/java/org/apache/whirr/net/DnsException.java
whirr/trunk/core/src/main/java/org/apache/whirr/net/DnsResolver.java
whirr/trunk/core/src/main/java/org/apache/whirr/net/FastDnsResolver.java
whirr/trunk/core/src/main/java/org/apache/whirr/state/
whirr/trunk/core/src/main/java/org/apache/whirr/state/BlobClusterStateStore.java
whirr/trunk/core/src/main/java/org/apache/whirr/state/ClusterStateStore.java
whirr/trunk/core/src/main/java/org/apache/whirr/state/ClusterStateStoreFactory.java
whirr/trunk/core/src/main/java/org/apache/whirr/state/FileClusterStateStore.java
whirr/trunk/core/src/main/java/org/apache/whirr/state/MemoryClusterStateStore.java
whirr/trunk/core/src/test/java/org/apache/whirr/net/
whirr/trunk/core/src/test/java/org/apache/whirr/net/integration/
whirr/trunk/core/src/test/java/org/apache/whirr/net/integration/FakeDnsResolver.java
whirr/trunk/core/src/test/java/org/apache/whirr/net/integration/FastDnsResolverTest.java
whirr/trunk/core/src/test/java/org/apache/whirr/state/
whirr/trunk/core/src/test/java/org/apache/whirr/state/integration/
whirr/trunk/core/src/test/java/org/apache/whirr/state/integration/BlobClusterStateStoreTest.java
Removed:
whirr/trunk/cli/src/test/java/org/apache/whirr/cli/MemoryClusterStateStore.java
whirr/trunk/core/src/main/java/org/apache/whirr/service/BlobClusterStateStore.java
whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterStateStore.java
whirr/trunk/core/src/main/java/org/apache/whirr/service/ClusterStateStoreFactory.java
whirr/trunk/core/src/main/java/org/apache/whirr/service/FileClusterStateStore.java
whirr/trunk/core/src/main/java/org/apache/whirr/util/DnsUtil.java
whirr/trunk/core/src/test/java/org/apache/whirr/service/integration/
whirr/trunk/core/src/test/java/org/apache/whirr/util/integration/DnsUtilTest.java
Modified:
whirr/trunk/CHANGES.txt
whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java
whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/RunScriptCommand.java
whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/ListClusterCommandTest.java
whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/RunScriptCommandTest.java
whirr/trunk/core/src/main/java/org/apache/whirr/Cluster.java
whirr/trunk/core/src/main/java/org/apache/whirr/ClusterController.java
whirr/trunk/core/src/main/java/org/apache/whirr/ClusterSpec.java
whirr/trunk/core/src/main/java/org/apache/whirr/command/AbstractClusterCommand.java
whirr/trunk/core/src/main/java/org/apache/whirr/service/jclouds/StatementBuilder.java
whirr/trunk/core/src/test/java/org/apache/whirr/service/DryRunModuleTest.java
whirr/trunk/services/chef/src/test/java/org/apache/whirr/service/chef/ChefServiceDryRunTest.java
whirr/trunk/services/hadoop/src/main/java/org/apache/whirr/service/hadoop/HadoopConfigurationBuilder.java
whirr/trunk/services/hadoop/src/test/java/org/apache/whirr/service/hadoop/HadoopConfigurationBuilderTest.java
Modified: whirr/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/whirr/trunk/CHANGES.txt?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/CHANGES.txt (original)
+++ whirr/trunk/CHANGES.txt Wed Dec 7 17:14:59 2011
@@ -87,6 +87,8 @@ Trunk (unreleased changes)
WHIRR-404. Add Project Metadata (Jean-Baptiste Onofré and asavu)
+ WHIRR-440. Unit tests improvements (less bound to external services) (asavu)
+
BUG FIXES
WHIRR-377. Fix broken CLI logging config. (asavu via tomwhite)
Modified: whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java
URL: http://svn.apache.org/viewvc/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java (original)
+++ whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/ListClusterCommand.java Wed Dec 7 17:14:59 2011
@@ -33,8 +33,8 @@ import org.apache.whirr.ClusterControlle
import org.apache.whirr.ClusterControllerFactory;
import org.apache.whirr.ClusterSpec;
import org.apache.whirr.command.AbstractClusterCommand;
-import org.apache.whirr.service.ClusterStateStore;
-import org.apache.whirr.service.ClusterStateStoreFactory;
+import org.apache.whirr.state.ClusterStateStore;
+import org.apache.whirr.state.ClusterStateStoreFactory;
/**
* A command to list the nodes in a cluster.
Modified: whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/RunScriptCommand.java
URL: http://svn.apache.org/viewvc/whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/RunScriptCommand.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/RunScriptCommand.java (original)
+++ whirr/trunk/cli/src/main/java/org/apache/whirr/cli/command/RunScriptCommand.java Wed Dec 7 17:14:59 2011
@@ -33,7 +33,7 @@ import org.apache.whirr.ClusterControlle
import org.apache.whirr.ClusterControllerFactory;
import org.apache.whirr.ClusterSpec;
import org.apache.whirr.command.AbstractClusterCommand;
-import org.apache.whirr.service.ClusterStateStoreFactory;
+import org.apache.whirr.state.ClusterStateStoreFactory;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.scriptbuilder.domain.Statement;
Modified: whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/ListClusterCommandTest.java
URL: http://svn.apache.org/viewvc/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/ListClusterCommandTest.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/ListClusterCommandTest.java (original)
+++ whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/ListClusterCommandTest.java Wed Dec 7 17:14:59 2011
@@ -40,9 +40,9 @@ import org.apache.whirr.Cluster;
import org.apache.whirr.ClusterController;
import org.apache.whirr.ClusterControllerFactory;
import org.apache.whirr.ClusterSpec;
-import org.apache.whirr.cli.MemoryClusterStateStore;
-import org.apache.whirr.service.ClusterStateStore;
-import org.apache.whirr.service.ClusterStateStoreFactory;
+import org.apache.whirr.state.ClusterStateStore;
+import org.apache.whirr.state.ClusterStateStoreFactory;
+import org.apache.whirr.state.MemoryClusterStateStore;
import org.apache.whirr.util.KeyPair;
import org.hamcrest.Matcher;
import org.jclouds.compute.domain.NodeMetadata;
Modified: whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/RunScriptCommandTest.java
URL: http://svn.apache.org/viewvc/whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/RunScriptCommandTest.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/RunScriptCommandTest.java (original)
+++ whirr/trunk/cli/src/test/java/org/apache/whirr/cli/command/RunScriptCommandTest.java Wed Dec 7 17:14:59 2011
@@ -26,9 +26,9 @@ import org.apache.whirr.Cluster;
import org.apache.whirr.ClusterController;
import org.apache.whirr.ClusterControllerFactory;
import org.apache.whirr.ClusterSpec;
-import org.apache.whirr.cli.MemoryClusterStateStore;
-import org.apache.whirr.service.ClusterStateStore;
-import org.apache.whirr.service.ClusterStateStoreFactory;
+import org.apache.whirr.state.ClusterStateStore;
+import org.apache.whirr.state.ClusterStateStoreFactory;
+import org.apache.whirr.state.MemoryClusterStateStore;
import org.apache.whirr.util.KeyPair;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.domain.Credentials;
Modified: whirr/trunk/core/src/main/java/org/apache/whirr/Cluster.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/Cluster.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/Cluster.java (original)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/Cluster.java Wed Dec 7 17:14:59 2011
@@ -24,7 +24,8 @@ import com.google.common.base.Predicates
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.net.InetAddresses;
-import org.apache.whirr.util.DnsUtil;
+import org.apache.whirr.net.DnsResolver;
+import org.apache.whirr.net.FastDnsResolver;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.domain.Credentials;
@@ -41,13 +42,14 @@ import static com.google.common.base.Pre
*
*/
public class Cluster {
-
+
/**
* This class represents a real node running in a cluster. An instance has
* one or more roles.
* @see InstanceTemplate
*/
public static class Instance {
+
private final Credentials loginCredentials;
private final Set<String> roles;
private final String publicIp;
@@ -56,9 +58,15 @@ public class Cluster {
private String privateHostName;
private final String id;
private final NodeMetadata nodeMetadata;
+ private final DnsResolver dnsResolver;
public Instance(Credentials loginCredentials, Set<String> roles, String publicIp,
String privateIp, String id, NodeMetadata nodeMetadata) {
+ this(loginCredentials, roles, publicIp, privateIp, id, nodeMetadata, new FastDnsResolver());
+ }
+
+ public Instance(Credentials loginCredentials, Set<String> roles, String publicIp,
+ String privateIp, String id, NodeMetadata nodeMetadata, DnsResolver dnsResolver) {
this.loginCredentials = checkNotNull(loginCredentials, "loginCredentials");
this.roles = checkNotNull(roles, "roles");
this.publicIp = checkNotNull(publicIp, "publicIp");
@@ -71,12 +79,13 @@ public class Cluster {
}
this.id = checkNotNull(id, "id");
this.nodeMetadata = nodeMetadata;
+ this.dnsResolver = dnsResolver;
}
public Credentials getLoginCredentials() {
return loginCredentials;
}
-
+
public Set<String> getRoles() {
return roles;
}
@@ -88,42 +97,42 @@ public class Cluster {
public InetAddress getPrivateAddress() throws IOException {
return resolveIpAddress(getPrivateIp(), getPrivateHostName());
}
-
+
private InetAddress resolveIpAddress(String ip, String host) throws IOException {
byte[] addr = InetAddresses.forString(ip).getAddress();
return InetAddress.getByAddress(host, addr);
}
-
+
public String getPublicIp() {
return publicIp;
}
-
+
public synchronized String getPublicHostName() throws IOException {
if (publicHostName == null) {
- publicHostName = DnsUtil.resolveAddress(publicIp);
+ publicHostName = dnsResolver.apply(publicIp);
}
return publicHostName;
}
-
+
public String getPrivateIp() {
return privateIp;
}
-
+
public synchronized String getPrivateHostName() throws IOException {
if (privateHostName == null) {
- privateHostName = DnsUtil.resolveAddress(privateIp);
+ privateHostName = dnsResolver.apply(privateIp);
}
return privateHostName;
}
-
+
public String getId() {
return id;
}
-
+
public NodeMetadata getNodeMetadata() {
return nodeMetadata;
}
-
+
public String toString() {
return Objects.toStringHelper(this)
.add("roles", roles)
@@ -150,10 +159,10 @@ public class Cluster {
this.instances = instances;
this.configuration = configuration;
}
-
+
public Set<Instance> getInstances() {
return instances;
- }
+ }
public Properties getConfiguration() {
return configuration;
}
@@ -176,5 +185,5 @@ public class Cluster {
.add("configuration", configuration)
.toString();
}
-
+
}
Modified: whirr/trunk/core/src/main/java/org/apache/whirr/ClusterController.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/ClusterController.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/ClusterController.java (original)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/ClusterController.java Wed Dec 7 17:14:59 2011
@@ -27,8 +27,8 @@ import org.apache.whirr.actions.Bootstra
import org.apache.whirr.actions.ConfigureClusterAction;
import org.apache.whirr.actions.DestroyClusterAction;
import org.apache.whirr.service.ClusterActionHandler;
-import org.apache.whirr.service.ClusterStateStore;
-import org.apache.whirr.service.ClusterStateStoreFactory;
+import org.apache.whirr.state.ClusterStateStore;
+import org.apache.whirr.state.ClusterStateStoreFactory;
import org.apache.whirr.service.ComputeCache;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
Modified: whirr/trunk/core/src/main/java/org/apache/whirr/ClusterSpec.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/ClusterSpec.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/ClusterSpec.java (original)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/ClusterSpec.java Wed Dec 7 17:14:59 2011
@@ -494,6 +494,10 @@ public class ClusterSpec {
return provider;
}
+ public boolean isStub() {
+ return "stub".equals(getProvider());
+ }
+
public String getIdentity() {
return identity;
}
@@ -682,7 +686,7 @@ public class ClusterSpec {
public void setStateStore(String type) {
if (type != null) {
- checkArgument(Sets.newHashSet("local", "blob", "none").contains(type),
+ checkArgument(Sets.newHashSet("local", "blob", "memory", "none").contains(type),
"Invalid state store. Valid values are local, blob or none.");
}
this.stateStore = type;
Modified: whirr/trunk/core/src/main/java/org/apache/whirr/command/AbstractClusterCommand.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/command/AbstractClusterCommand.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/command/AbstractClusterCommand.java (original)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/command/AbstractClusterCommand.java Wed Dec 7 17:14:59 2011
@@ -40,8 +40,8 @@ import org.apache.whirr.ClusterControlle
import org.apache.whirr.ClusterControllerFactory;
import org.apache.whirr.ClusterSpec;
import org.apache.whirr.ClusterSpec.Property;
-import org.apache.whirr.service.ClusterStateStore;
-import org.apache.whirr.service.ClusterStateStoreFactory;
+import org.apache.whirr.state.ClusterStateStore;
+import org.apache.whirr.state.ClusterStateStoreFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Added: whirr/trunk/core/src/main/java/org/apache/whirr/net/DnsException.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/net/DnsException.java?rev=1211543&view=auto
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/net/DnsException.java (added)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/net/DnsException.java Wed Dec 7 17:14:59 2011
@@ -0,0 +1,28 @@
+/**
+ * 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.net;
+
+/**
+ * Generic dns resolution exception
+ */
+public class DnsException extends RuntimeException {
+ public DnsException(Throwable e) {
+ super(e);
+ }
+}
Added: whirr/trunk/core/src/main/java/org/apache/whirr/net/DnsResolver.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/net/DnsResolver.java?rev=1211543&view=auto
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/net/DnsResolver.java (added)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/net/DnsResolver.java Wed Dec 7 17:14:59 2011
@@ -0,0 +1,27 @@
+/**
+ * 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.net;
+
+import com.google.common.base.Function;
+
+/**
+ * Marker interface for a reverse DNS resolver
+ */
+public interface DnsResolver extends Function<String, String> {
+}
Added: whirr/trunk/core/src/main/java/org/apache/whirr/net/FastDnsResolver.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/net/FastDnsResolver.java?rev=1211543&view=auto
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/net/FastDnsResolver.java (added)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/net/FastDnsResolver.java Wed Dec 7 17:14:59 2011
@@ -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 org.apache.whirr.net;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+
+import org.xbill.DNS.DClass;
+import org.xbill.DNS.ExtendedResolver;
+import org.xbill.DNS.Message;
+import org.xbill.DNS.Name;
+import org.xbill.DNS.Record;
+import org.xbill.DNS.Resolver;
+import org.xbill.DNS.ReverseMap;
+import org.xbill.DNS.Section;
+import org.xbill.DNS.Type;
+
+/**
+ * Utility functions for DNS.
+ */
+public class FastDnsResolver implements DnsResolver {
+
+ /**
+ * Resolve the reverse dns name for the given IP address
+ *
+ * @param hostIp
+ * @return The resolved DNS name.
+ * @throws IOException
+ */
+ @Override
+ public String apply(String hostIp) {
+ try {
+ Resolver res = new ExtendedResolver();
+ res.setTimeout(5); // seconds
+
+ Name name = ReverseMap.fromAddress(hostIp);
+ Record rec = Record.newRecord(name, Type.PTR, DClass.IN);
+ Message query = Message.newQuery(rec);
+ Message response = res.send(query);
+
+ Record[] answers = response.getSectionArray(Section.ANSWER);
+ if (answers.length == 0) {
+ // Fall back to standard Java: in contrast to dnsjava, this also reads /etc/hosts
+ return new InetSocketAddress(hostIp, 0).getAddress().getCanonicalHostName();
+ } else {
+ String revaddr = answers[0].rdataToString();
+ return revaddr.endsWith(".") ? revaddr.substring(0, revaddr.length() - 1) : revaddr;
+ }
+ } catch(IOException e) {
+ throw new DnsException(e);
+ }
+ }
+
+}
+
Modified: whirr/trunk/core/src/main/java/org/apache/whirr/service/jclouds/StatementBuilder.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/service/jclouds/StatementBuilder.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/service/jclouds/StatementBuilder.java (original)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/service/jclouds/StatementBuilder.java Wed Dec 7 17:14:59 2011
@@ -81,15 +81,17 @@ public class StatementBuilder {
"privateIp", instance.getPrivateIp()
)
);
- try {
- metadataMap.putAll(
- ImmutableMap.of(
- "publicHostName", instance.getPublicHostName(),
- "privateHostName", instance.getPrivateHostName()
- )
- );
- } catch (IOException e) {
- LOG.warn("Could not resolve hostname for " + instance, e);
+ if (!clusterSpec.isStub()) {
+ try {
+ metadataMap.putAll(
+ ImmutableMap.of(
+ "publicHostName", instance.getPublicHostName(),
+ "privateHostName", instance.getPrivateHostName()
+ )
+ );
+ } catch (IOException e) {
+ LOG.warn("Could not resolve hostname for " + instance, e);
+ }
}
}
for (Iterator<?> it = clusterSpec.getConfiguration().getKeys("whirr.env"); it.hasNext(); ) {
@@ -107,9 +109,6 @@ public class StatementBuilder {
scriptBuilder.addStatement(statement);
}
- // Quick fix: jclouds considers that a script that runs for <2 seconds failed
- scriptBuilder.addStatement(exec("sleep 4"));
-
return scriptBuilder.render(family);
}
}
Added: whirr/trunk/core/src/main/java/org/apache/whirr/state/BlobClusterStateStore.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/state/BlobClusterStateStore.java?rev=1211543&view=auto
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/state/BlobClusterStateStore.java (added)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/state/BlobClusterStateStore.java Wed Dec 7 17:14:59 2011
@@ -0,0 +1,85 @@
+/**
+ * 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.state;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.whirr.Cluster;
+import org.apache.whirr.ClusterSpec;
+import org.apache.whirr.service.BlobStoreContextBuilder;
+import org.jclouds.blobstore.BlobStore;
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.blobstore.domain.Blob;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class BlobClusterStateStore extends ClusterStateStore {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(FileClusterStateStore.class);
+
+ private ClusterSpec spec;
+ private BlobStoreContext context;
+
+ private String container;
+ private String blobName;
+
+ public BlobClusterStateStore(ClusterSpec spec) {
+ this.spec = spec;
+ this.context = BlobStoreContextBuilder.build(spec);
+
+ this.container = checkNotNull(spec.getStateStoreContainer());
+ this.blobName = checkNotNull(spec.getStateStoreBlob());
+
+ /* create container if it does not already exists */
+ if (!context.getBlobStore().containerExists(container)) {
+ context.getBlobStore().createContainerInLocation(null, container);
+ }
+ }
+
+ @Override
+ public Cluster load() throws IOException {
+ Blob blob = context.getBlobStore().getBlob(container, blobName);
+ if (blob != null) {
+ return unserialize(spec,
+ IOUtils.toString(blob.getPayload().getInput(), "utf-8"));
+ }
+ return null;
+ }
+
+ @Override
+ public void save(Cluster cluster) throws IOException {
+ BlobStore store = context.getBlobStore();
+
+ Blob blob = store.newBlob(blobName);
+ blob.setPayload(serialize(cluster));
+ store.putBlob(container, blob);
+
+ LOG.info("Saved cluster state to '{}' ", context.getSigner()
+ .signGetBlob(container, blobName).getEndpoint().toString());
+ }
+
+ @Override
+ public void destroy() throws IOException {
+ context.getBlobStore().removeBlob(container, blobName);
+ }
+}
Added: whirr/trunk/core/src/main/java/org/apache/whirr/state/ClusterStateStore.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/state/ClusterStateStore.java?rev=1211543&view=auto
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/state/ClusterStateStore.java (added)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/state/ClusterStateStore.java Wed Dec 7 17:14:59 2011
@@ -0,0 +1,133 @@
+/**
+ * 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.state;
+
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.util.Iterator;
+import java.util.Set;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Sets;
+import org.apache.whirr.Cluster;
+import org.apache.whirr.ClusterSpec;
+import org.jclouds.domain.Credentials;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Interface for cluster state storage facilities.
+ *
+ */
+public abstract class ClusterStateStore {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ClusterStateStore.class);
+
+ /**
+ * Deserializes cluster state from storage.
+ *
+ * @return
+ * @throws IOException
+ */
+ public abstract Cluster load() throws IOException;
+
+ /**
+ * Try to load the cluster state or return an empty instance
+ *
+ * @return
+ */
+ public Cluster tryLoadOrEmpty() {
+ try {
+ return load();
+
+ } catch (Exception e) {
+ LOG.info("Unable to load cluster state, assuming it has no running nodes.", e);
+ return Cluster.empty();
+ }
+ }
+
+ /**
+ * Saves cluster state to storage.
+ *
+ * @param cluster
+ * @throws IOException
+ */
+ public abstract void save(Cluster cluster) throws IOException;
+
+ /**
+ * Destroys the provided cluster's state in storage.
+ *
+ * @throws IOException
+ */
+ public abstract void destroy() throws IOException;
+
+
+ /**
+ * Create parser friendly string representation for a {@link Cluster}
+ *
+ * @param cluster
+ * @return String representation
+ * @throws IOException
+ */
+ protected String serialize(Cluster cluster) throws IOException {
+ StringBuilder sb = new StringBuilder();
+
+ for (Cluster.Instance instance : cluster.getInstances()) {
+ String id = instance.getId();
+ String roles = Joiner.on(',').join(instance.getRoles());
+
+ sb.append(id).append("\t");
+ sb.append(roles).append("\t");
+ sb.append(instance.getPublicIp()).append("\t");
+ sb.append(instance.getPrivateIp()).append("\n");
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * Rebuild the {@link Cluster} instance by using the string representation
+ *
+ * @param spec
+ * @param content
+ * @return
+ * @throws UnknownHostException
+ */
+ protected Cluster unserialize(ClusterSpec spec, String content) throws UnknownHostException {
+ Credentials credentials = new Credentials(spec.getClusterUser(), spec.getPrivateKey());
+ Set<Cluster.Instance> instances = Sets.newLinkedHashSet();
+
+ for(String line : Splitter.on("\n").split(content)) {
+ if (line.trim().equals("")) continue; /* ignore empty lines */
+ Iterator<String> fields = Splitter.on("\t").split(line).iterator();
+
+ String id = fields.next();
+ Set<String> roles = Sets.newLinkedHashSet(Splitter.on(",").split(fields.next()));
+ String publicIPAddress = fields.next();
+ String privateIPAddress = fields.next();
+
+ instances.add(new Cluster.Instance(credentials, roles,
+ publicIPAddress, privateIPAddress, id, null));
+ }
+
+ return new Cluster(instances);
+ }
+
+}
Added: whirr/trunk/core/src/main/java/org/apache/whirr/state/ClusterStateStoreFactory.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/state/ClusterStateStoreFactory.java?rev=1211543&view=auto
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/state/ClusterStateStoreFactory.java (added)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/state/ClusterStateStoreFactory.java Wed Dec 7 17:14:59 2011
@@ -0,0 +1,81 @@
+/**
+ * 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.state;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import org.apache.whirr.Cluster;
+import org.apache.whirr.ClusterSpec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+/**
+ * A factory for ClusterStateStores.
+ */
+public class ClusterStateStoreFactory {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(ClusterStateStoreFactory.class);
+
+ private static class NoopClusterStateStore extends ClusterStateStore {
+ public NoopClusterStateStore() {
+ LOG.warn("No cluster state is going to be persisted. There is no easy " +
+ "way to retrieve instance roles after launch.");
+ }
+
+ @Override
+ public Cluster load() throws IOException {
+ return null;
+ }
+
+ @Override
+ public void save(Cluster cluster) throws IOException {
+ }
+
+ @Override
+ public void destroy() throws IOException {
+ }
+ }
+
+ private Cache<ClusterSpec, ClusterStateStore> storeCache = CacheBuilder.newBuilder().build(
+ new CacheLoader<ClusterSpec, ClusterStateStore>() {
+ @Override
+ public ClusterStateStore load(ClusterSpec spec) throws Exception {
+ if ("local".equals(spec.getStateStore())) {
+ return new FileClusterStateStore(spec);
+
+ } else if ("blob".equals(spec.getStateStore())) {
+ return new BlobClusterStateStore(spec);
+
+ } else if ("memory".equals(spec.getStateStore())) {
+ return new MemoryClusterStateStore();
+
+ } else {
+ return new NoopClusterStateStore();
+ }
+ }
+ });
+
+ public ClusterStateStore create(ClusterSpec spec) {
+ return storeCache.getUnchecked(spec);
+ }
+}
Added: whirr/trunk/core/src/main/java/org/apache/whirr/state/FileClusterStateStore.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/state/FileClusterStateStore.java?rev=1211543&view=auto
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/state/FileClusterStateStore.java (added)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/state/FileClusterStateStore.java Wed Dec 7 17:14:59 2011
@@ -0,0 +1,76 @@
+/**
+ * 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.state;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.whirr.Cluster;
+import org.apache.whirr.ClusterSpec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Joiner;
+import com.google.common.io.Files;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Stores/Reads cluster state from a local file (located at:
+ * "~/.whirr/cluster-name/instances")
+ *
+ */
+public class FileClusterStateStore extends ClusterStateStore {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(FileClusterStateStore.class);
+
+ private ClusterSpec spec;
+
+ public FileClusterStateStore(ClusterSpec spec) {
+ checkNotNull(spec,"clusterSpec");
+ this.spec = spec;
+ }
+
+ @Override
+ public Cluster load() throws IOException {
+ File instancesFile = new File(spec.getClusterDirectory(), "instances");
+ return unserialize(spec,
+ Joiner.on("\n").join(Files.readLines(instancesFile, Charsets.UTF_8)));
+ }
+
+ @Override
+ public void destroy() throws IOException {
+ Files.deleteRecursively(spec.getClusterDirectory());
+ }
+
+ @Override
+ public void save(Cluster cluster) throws IOException {
+ File instancesFile = new File(spec.getClusterDirectory(), "instances");
+
+ try {
+ Files.write(serialize(cluster).toString(), instancesFile, Charsets.UTF_8);
+ LOG.info("Wrote instances file {}", instancesFile);
+
+ } catch (IOException e) {
+ LOG.error("Problem writing instances file {}", instancesFile, e);
+ }
+ }
+
+}
Added: whirr/trunk/core/src/main/java/org/apache/whirr/state/MemoryClusterStateStore.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/main/java/org/apache/whirr/state/MemoryClusterStateStore.java?rev=1211543&view=auto
==============================================================================
--- whirr/trunk/core/src/main/java/org/apache/whirr/state/MemoryClusterStateStore.java (added)
+++ whirr/trunk/core/src/main/java/org/apache/whirr/state/MemoryClusterStateStore.java Wed Dec 7 17:14:59 2011
@@ -0,0 +1,46 @@
+/**
+ * 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.state;
+
+import org.apache.whirr.Cluster;
+
+import java.io.IOException;
+
+/**
+ * Memory only cluster state storage useful for testing
+ */
+public class MemoryClusterStateStore extends ClusterStateStore {
+
+ private Cluster cluster;
+
+ @Override
+ public Cluster load() throws IOException {
+ return cluster;
+ }
+
+ @Override
+ public void save(Cluster cluster) throws IOException {
+ this.cluster = cluster;
+ }
+
+ @Override
+ public void destroy() throws IOException {
+ cluster = null;
+ }
+}
Added: whirr/trunk/core/src/test/java/org/apache/whirr/net/integration/FakeDnsResolver.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/test/java/org/apache/whirr/net/integration/FakeDnsResolver.java?rev=1211543&view=auto
==============================================================================
--- whirr/trunk/core/src/test/java/org/apache/whirr/net/integration/FakeDnsResolver.java (added)
+++ whirr/trunk/core/src/test/java/org/apache/whirr/net/integration/FakeDnsResolver.java Wed Dec 7 17:14:59 2011
@@ -0,0 +1,34 @@
+/**
+ * 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.net.integration;
+
+import org.apache.whirr.net.DnsResolver;
+
+import static org.apache.commons.lang.StringUtils.replace;
+
+/**
+ * Fake reverse DNS resolver
+ */
+public class FakeDnsResolver implements DnsResolver {
+
+ @Override
+ public String apply(String hostIp) {
+ return replace(hostIp, ".", "-") + ".example.com";
+ }
+}
Added: whirr/trunk/core/src/test/java/org/apache/whirr/net/integration/FastDnsResolverTest.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/test/java/org/apache/whirr/net/integration/FastDnsResolverTest.java?rev=1211543&view=auto
==============================================================================
--- whirr/trunk/core/src/test/java/org/apache/whirr/net/integration/FastDnsResolverTest.java (added)
+++ whirr/trunk/core/src/test/java/org/apache/whirr/net/integration/FastDnsResolverTest.java Wed Dec 7 17:14:59 2011
@@ -0,0 +1,89 @@
+/**
+ * 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.net.integration;
+
+import static java.lang.System.out;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.UnknownHostException;
+import java.util.Collections;
+import java.util.Enumeration;
+
+import org.apache.whirr.net.DnsResolver;
+import org.apache.whirr.net.FastDnsResolver;
+import org.junit.Test;
+import org.xbill.DNS.Address;
+
+public class FastDnsResolverTest {
+
+ private static final DnsResolver DNS_RESOLVER = new FastDnsResolver();
+
+ @Test
+ public void testResolveAddress() throws IOException {
+ // test it with all interfaces
+ Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
+ while (en.hasMoreElements()) {
+ NetworkInterface netint = (NetworkInterface) en.nextElement();
+ Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
+ for (InetAddress inetAddress : Collections.list(inetAddresses)) {
+ if (inetAddress instanceof Inet4Address) {
+ long start = System.currentTimeMillis();
+ String reverse = DNS_RESOLVER.apply(inetAddress.getHostAddress());
+ long end = System.currentTimeMillis();
+ // we know that java.net.InetAddress's getHostName takes > 4.5s if
+ // there is no reverse address assigned to it
+ // FastDnsResolver should resolve any address in less than 5 seconds or fail
+ assertTrue("FastDnsResolver.resolveAddress takes " + (end - start)
+ + " millis, it should be shorter than five seconds",
+ end - start < 5000);
+ if (inetAddress.toString().substring(1).equals(reverse)) {
+ out.printf(
+ "InetAddress %s on interface %s does not have reverse dns name, so their reverse remains: %s\n",
+ inetAddress, netint.getDisplayName(), reverse);
+ } else {
+ if (inetAddress.isLoopbackAddress()) {
+ out.printf(
+ "InetAddress %s on loopback interface %s obtained reverse name as %s\n",
+ inetAddress, netint.getDisplayName(), reverse);
+ } else {
+ out.printf(
+ "InetAddress %s on interface %s has reverse dns name: %s\n",
+ inetAddress, netint.getDisplayName(), reverse);
+ try {
+ InetAddress checkedAddr = Address.getByName(reverse);
+ assertEquals(inetAddress, checkedAddr);
+ } catch (UnknownHostException uhex) {
+ fail("InetAddress " + inetAddress + " on interface "
+ + netint.getDisplayName() + " got " + reverse
+ + " reverse dns name which in return is an unknown host!");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+}
Modified: whirr/trunk/core/src/test/java/org/apache/whirr/service/DryRunModuleTest.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/test/java/org/apache/whirr/service/DryRunModuleTest.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/core/src/test/java/org/apache/whirr/service/DryRunModuleTest.java (original)
+++ whirr/trunk/core/src/test/java/org/apache/whirr/service/DryRunModuleTest.java Wed Dec 7 17:14:59 2011
@@ -80,6 +80,7 @@ public class DryRunModuleTest {
config.setProperty("whirr.cluster-name", "stub-test");
config.setProperty("whirr.instance-templates",
"10 noop+noop3,10 noop2+noop,10 noop3+noop2");
+ config.setProperty("whirr.state-store", "memory");
ClusterSpec clusterSpec = ClusterSpec.withTemporaryKeys(config);
ClusterController controller = new ClusterController();
Added: whirr/trunk/core/src/test/java/org/apache/whirr/state/integration/BlobClusterStateStoreTest.java
URL: http://svn.apache.org/viewvc/whirr/trunk/core/src/test/java/org/apache/whirr/state/integration/BlobClusterStateStoreTest.java?rev=1211543&view=auto
==============================================================================
--- whirr/trunk/core/src/test/java/org/apache/whirr/state/integration/BlobClusterStateStoreTest.java (added)
+++ whirr/trunk/core/src/test/java/org/apache/whirr/state/integration/BlobClusterStateStoreTest.java Wed Dec 7 17:14:59 2011
@@ -0,0 +1,126 @@
+/**
+ * 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.state.integration;
+
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.whirr.Cluster;
+import org.apache.whirr.ClusterSpec;
+import org.apache.whirr.state.BlobClusterStateStore;
+import org.apache.whirr.service.BlobStoreContextBuilder;
+import org.jclouds.blobstore.BlobStoreContext;
+import org.jclouds.domain.Credentials;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+public class BlobClusterStateStoreTest {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(BlobClusterStateStoreTest.class);
+
+ private Configuration getTestConfiguration() throws ConfigurationException {
+ return new PropertiesConfiguration("whirr-core-test.properties");
+ }
+
+ private ClusterSpec getTestClusterSpec() throws Exception {
+ return ClusterSpec.withTemporaryKeys(getTestConfiguration());
+ }
+
+ @Test
+ public void testStoreAndLoadState() throws Exception {
+ ClusterSpec spec = getTestClusterSpec();
+
+ BlobStoreContext context = BlobStoreContextBuilder.build(spec);
+ String container = generateRandomContainerName(context);
+ try {
+ spec.setStateStore("blob");
+ spec.setStateStoreContainer(container);
+
+ Cluster expected = createTestCluster(new String[]{"region/id1", "region/id2"},
+ new String[]{"role1", "role2"});
+
+ BlobClusterStateStore store = new BlobClusterStateStore(spec);
+ store.save(expected);
+
+ /* load and check the stored state */
+ Cluster stored = store.load();
+ Cluster.Instance first = Iterables.getFirst(stored.getInstances(), null);
+ assertNotNull(first);
+
+ assertThat(first.getId(), is("region/id1"));
+ assertThat(first.getRoles().contains("role1"), is(true));
+ assertThat(stored.getInstances().size(), is(2));
+
+ /* destroy stored state and check it no longer exists */
+ store.destroy();
+ expected = store.load();
+ assertNull(expected);
+
+ } finally {
+ LOG.info("Removing temporary container '{}'", container);
+ context.getBlobStore().deleteContainer(container);
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidContainerName() throws Exception {
+ ClusterSpec spec = getTestClusterSpec();
+
+ /* underscores are not allowed and it should throw exception */
+ spec.setStateStoreContainer("whirr_test");
+ }
+
+ private String generateRandomContainerName(BlobStoreContext context) {
+ String candidate;
+ do {
+ candidate = RandomStringUtils.randomAlphanumeric(12).toLowerCase();
+ } while(!context.getBlobStore().createContainerInLocation(null, candidate));
+ LOG.info("Created temporary container '{}'", candidate);
+ return candidate;
+ }
+
+ private Cluster createTestCluster(String[] ids, String[] roles) {
+ checkArgument(ids.length == roles.length, "each ID should have a role");
+
+ Credentials credentials = new Credentials("dummy", "dummy");
+ Set<Cluster.Instance> instances = Sets.newLinkedHashSet();
+
+ for(int i = 0; i < ids.length; i++) {
+ String ip = "127.0.0." + (i + 1);
+ instances.add(new Cluster.Instance(credentials,
+ Sets.newHashSet(roles[i]), ip, ip, ids[i], null));
+ }
+
+ return new Cluster(instances);
+ }
+
+}
Modified: whirr/trunk/services/chef/src/test/java/org/apache/whirr/service/chef/ChefServiceDryRunTest.java
URL: http://svn.apache.org/viewvc/whirr/trunk/services/chef/src/test/java/org/apache/whirr/service/chef/ChefServiceDryRunTest.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/services/chef/src/test/java/org/apache/whirr/service/chef/ChefServiceDryRunTest.java (original)
+++ whirr/trunk/services/chef/src/test/java/org/apache/whirr/service/chef/ChefServiceDryRunTest.java Wed Dec 7 17:14:59 2011
@@ -80,10 +80,11 @@ public class ChefServiceDryRunTest {
Configuration config = new PropertiesConfiguration();
config.setProperty("whirr.provider", "stub");
config.setProperty("whirr.cluster-name", "stub-test");
+ config.setProperty("whirr.state-store", "memory");
return config;
}
- private ClusterController lauchWithConfig(Configuration config)
+ private ClusterController launchWithConfig(Configuration config)
throws IOException, InterruptedException, ConfigurationException,
JSchException {
ClusterSpec clusterSpec = ClusterSpec.withTemporaryKeys(config);
@@ -98,7 +99,7 @@ public class ChefServiceDryRunTest {
*/
@Test
public void testChefOnly() throws Exception {
- lauchWithConfig(chefOnly);
+ launchWithConfig(chefOnly);
assertInstallFunctionsWereExecuted(DryRun.INSTANCE);
// chef only install should not contain any chef-solo executions
assertScriptPredicateOnPhase(DryRun.INSTANCE, "configure",
@@ -117,7 +118,7 @@ public class ChefServiceDryRunTest {
*/
@Test
public void testChefWithDefaultRecipe() throws Exception {
- lauchWithConfig(cookbookWithDefaultRecipe);
+ launchWithConfig(cookbookWithDefaultRecipe);
assertInstallFunctionsWereExecuted(DryRun.INSTANCE);
// chef execution with a default cookbook recipe should contain a
// particular string
@@ -136,7 +137,7 @@ public class ChefServiceDryRunTest {
*/
@Test
public void testChefWithAttributes() throws Exception {
- lauchWithConfig(cookbookWithSpecificRecipe);
+ launchWithConfig(cookbookWithSpecificRecipe);
assertInstallFunctionsWereExecuted(DryRun.INSTANCE);
// chef execution with a default cookbook recipe should contain a
// particular string
@@ -155,7 +156,7 @@ public class ChefServiceDryRunTest {
*/
@Test
public void testChefWithParticularRecipe() throws Exception {
- lauchWithConfig(cookbookWithAttributes);
+ launchWithConfig(cookbookWithAttributes);
assertInstallFunctionsWereExecuted(DryRun.INSTANCE);
// chef execution with a default cookbook recipe should contain a
// particular string
Modified: whirr/trunk/services/hadoop/src/main/java/org/apache/whirr/service/hadoop/HadoopConfigurationBuilder.java
URL: http://svn.apache.org/viewvc/whirr/trunk/services/hadoop/src/main/java/org/apache/whirr/service/hadoop/HadoopConfigurationBuilder.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/services/hadoop/src/main/java/org/apache/whirr/service/hadoop/HadoopConfigurationBuilder.java (original)
+++ whirr/trunk/services/hadoop/src/main/java/org/apache/whirr/service/hadoop/HadoopConfigurationBuilder.java Wed Dec 7 17:14:59 2011
@@ -89,7 +89,7 @@ public class HadoopConfigurationBuilder
Instance namenode = cluster
.getInstanceMatching(role(HadoopNameNodeClusterActionHandler.ROLE));
config.setProperty("fs.default.name", String.format("hdfs://%s:8020/",
- namenode.getPublicAddress().getHostName()));
+ namenode.getPublicHostName()));
return config;
}
@@ -135,7 +135,7 @@ public class HadoopConfigurationBuilder
Instance jobtracker = cluster
.getInstanceMatching(role(HadoopJobTrackerClusterActionHandler.ROLE));
config.setProperty("mapred.job.tracker", String.format("%s:8021",
- jobtracker.getPublicAddress().getHostName()));
+ jobtracker.getPublicHostName()));
return config;
}
Modified: whirr/trunk/services/hadoop/src/test/java/org/apache/whirr/service/hadoop/HadoopConfigurationBuilderTest.java
URL: http://svn.apache.org/viewvc/whirr/trunk/services/hadoop/src/test/java/org/apache/whirr/service/hadoop/HadoopConfigurationBuilderTest.java?rev=1211543&r1=1211542&r2=1211543&view=diff
==============================================================================
--- whirr/trunk/services/hadoop/src/test/java/org/apache/whirr/service/hadoop/HadoopConfigurationBuilderTest.java (original)
+++ whirr/trunk/services/hadoop/src/test/java/org/apache/whirr/service/hadoop/HadoopConfigurationBuilderTest.java Wed Dec 7 17:14:59 2011
@@ -36,6 +36,8 @@ import org.apache.commons.configuration.
import org.apache.whirr.Cluster;
import org.apache.whirr.Cluster.Instance;
import org.apache.whirr.ClusterSpec;
+import org.apache.whirr.net.DnsResolver;
+import org.apache.whirr.net.integration.FakeDnsResolver;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.jclouds.compute.domain.Hardware;
@@ -48,7 +50,7 @@ import org.junit.Before;
import org.junit.Test;
public class HadoopConfigurationBuilderTest {
-
+
static class RegexMatcher extends BaseMatcher<String> {
private final String regex;
@@ -87,6 +89,8 @@ public class HadoopConfigurationBuilderT
}
private Cluster newCluster(int numberOfWorkers) {
+ DnsResolver fakeDnsResolver = new FakeDnsResolver();
+
NodeMetadata node = mock(NodeMetadata.class);
List<Processor> processors = ImmutableList.of(new Processor(4, 1.0));
Hardware hardware = new HardwareImpl(null, null, "id", null, null,
@@ -98,14 +102,14 @@ public class HadoopConfigurationBuilderT
Instance master = new Instance(new Credentials("", ""),
ImmutableSet.of(HadoopNameNodeClusterActionHandler.ROLE,
HadoopJobTrackerClusterActionHandler.ROLE),
- "10.0.0.1", "10.0.0.1", "1", node);
+ "10.0.0.1", "10.0.0.1", "1", node, fakeDnsResolver);
instances.add(master);
for (int i = 0; i < numberOfWorkers; i++) {
int id = i + 2;
instances.add(new Instance(new Credentials("", ""),
ImmutableSet.of(HadoopDataNodeClusterActionHandler.ROLE,
HadoopTaskTrackerClusterActionHandler.ROLE),
- "10.0.0." + id, "10.0.0." + id, id + "", node));
+ "10.0.0." + id, "10.0.0." + id, id + "", node, fakeDnsResolver));
}
return new Cluster(instances.build());
}