diff --git a/aws/demos/createlamp/src/main/java/org/jclouds/aws/ec2/demos/createlamp/MainApp.java b/aws/demos/createlamp/src/main/java/org/jclouds/aws/ec2/demos/createlamp/MainApp.java index be7089718c..65517ef4a9 100755 --- a/aws/demos/createlamp/src/main/java/org/jclouds/aws/ec2/demos/createlamp/MainApp.java +++ b/aws/demos/createlamp/src/main/java/org/jclouds/aws/ec2/demos/createlamp/MainApp.java @@ -37,12 +37,12 @@ import org.jclouds.aws.ec2.domain.Reservation; import org.jclouds.aws.ec2.domain.RunningInstance; import org.jclouds.aws.ec2.predicates.InstanceStateRunning; import org.jclouds.net.IPSocket; +import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContextFactory; import org.jclouds.scriptbuilder.ScriptBuilder; import org.jclouds.scriptbuilder.domain.OsFamily; -import org.jclouds.ssh.jsch.predicates.InetSocketAddressConnect; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; diff --git a/compute/src/main/java/org/jclouds/compute/Utils.java b/compute/src/main/java/org/jclouds/compute/Utils.java index 53e40340fe..3d25c26635 100644 --- a/compute/src/main/java/org/jclouds/compute/Utils.java +++ b/compute/src/main/java/org/jclouds/compute/Utils.java @@ -21,9 +21,11 @@ package org.jclouds.compute; import javax.annotation.Nullable; +import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.internal.UtilsImpl; import org.jclouds.ssh.SshClient; +import com.google.common.base.Function; import com.google.inject.ImplementedBy; /** @@ -37,4 +39,9 @@ public interface Utils extends org.jclouds.rest.Utils { @Nullable SshClient.Factory sshFactory(); + + /** + * @return function that gets an ssh client for a node that is available via ssh. + */ + Function sshForNode(); } diff --git a/compute/src/main/java/org/jclouds/compute/callables/InitAndStartScriptOnNode.java b/compute/src/main/java/org/jclouds/compute/callables/InitAndStartScriptOnNode.java index ab4d575da2..105d5a9378 100644 --- a/compute/src/main/java/org/jclouds/compute/callables/InitAndStartScriptOnNode.java +++ b/compute/src/main/java/org/jclouds/compute/callables/InitAndStartScriptOnNode.java @@ -24,7 +24,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.util.Collections; import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.util.ComputeServiceUtils; import org.jclouds.compute.util.ComputeServiceUtils.SshCallable; import org.jclouds.logging.Logger; import org.jclouds.scriptbuilder.InitBuilder; @@ -32,6 +31,7 @@ import org.jclouds.scriptbuilder.domain.OsFamily; import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.ssh.ExecResponse; import org.jclouds.ssh.SshClient; +import org.jclouds.util.Utils; import com.google.common.collect.Iterables; @@ -93,7 +93,7 @@ public class InitAndStartScriptOnNode implements SshCallable { String command; if (node.getCredentials().identity.equals("root")) { command = "./" + init.getInstanceName() + " " + action; - } else if (ComputeServiceUtils.isKeyAuth(node)) { + } else if (Utils.isPrivateKeyCredential(node.getCredentials())) { command = "sudo ./" + init.getInstanceName() + " " + action; } else { command = String.format("echo '%s'|sudo -S ./%s %s", node.getCredentials().credential, init.getInstanceName(), diff --git a/compute/src/main/java/org/jclouds/compute/config/BaseComputeServiceContextModule.java b/compute/src/main/java/org/jclouds/compute/config/BaseComputeServiceContextModule.java index d498dba1f4..5eb304e647 100644 --- a/compute/src/main/java/org/jclouds/compute/config/BaseComputeServiceContextModule.java +++ b/compute/src/main/java/org/jclouds/compute/config/BaseComputeServiceContextModule.java @@ -34,10 +34,13 @@ import org.jclouds.compute.LoadBalancerService; import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.functions.CreateSshClientOncePortIsListeningOnNode; import org.jclouds.domain.Location; import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.suppliers.RetryOnTimeOutButNotOnAuthorizationExceptionSupplier; +import org.jclouds.ssh.SshClient; import com.google.common.base.Function; import com.google.common.base.Supplier; @@ -47,6 +50,7 @@ import com.google.inject.AbstractModule; import com.google.inject.Injector; import com.google.inject.Provides; import com.google.inject.Scopes; +import com.google.inject.TypeLiteral; import com.google.inject.util.Providers; /** @@ -58,6 +62,8 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule { protected void configure() { install(new ComputeServiceTimeoutsModule()); bindLoadBalancerService(); + bind(new TypeLiteral>() { + }).to(CreateSshClientOncePortIsListeningOnNode.class); } protected void bindLoadBalancerService() { diff --git a/compute/src/main/java/org/jclouds/compute/config/ComputeServiceTimeoutsModule.java b/compute/src/main/java/org/jclouds/compute/config/ComputeServiceTimeoutsModule.java index 12f0b6c1fe..9b1bb1e3cc 100644 --- a/compute/src/main/java/org/jclouds/compute/config/ComputeServiceTimeoutsModule.java +++ b/compute/src/main/java/org/jclouds/compute/config/ComputeServiceTimeoutsModule.java @@ -30,9 +30,7 @@ import org.jclouds.compute.predicates.NodeTerminated; import org.jclouds.compute.predicates.ScriptStatusReturnsZero; import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient; import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; -import org.jclouds.predicates.SocketOpen; import com.google.common.base.Predicate; import com.google.inject.AbstractModule; @@ -50,7 +48,7 @@ public class ComputeServiceTimeoutsModule extends AbstractModule { @Named("NODE_RUNNING") protected Predicate nodeRunning(NodeRunning stateRunning, Timeouts timeouts) { return timeouts.nodeRunning == 0 ? stateRunning : new RetryablePredicate(stateRunning, - timeouts.nodeRunning); + timeouts.nodeRunning); } @Provides @@ -58,7 +56,7 @@ public class ComputeServiceTimeoutsModule extends AbstractModule { @Named("NODE_TERMINATED") protected Predicate serverTerminated(NodeTerminated stateTerminated, Timeouts timeouts) { return timeouts.nodeTerminated == 0 ? stateTerminated : new RetryablePredicate(stateTerminated, - timeouts.nodeTerminated); + timeouts.nodeTerminated); } @Provides @@ -66,13 +64,7 @@ public class ComputeServiceTimeoutsModule extends AbstractModule { @Named("SCRIPT_COMPLETE") protected Predicate runScriptRunning(ScriptStatusReturnsZero stateRunning, Timeouts timeouts) { return timeouts.scriptComplete == 0 ? not(stateRunning) : new RetryablePredicate( - not(stateRunning), timeouts.scriptComplete); - } - - @Provides - @Singleton - protected Predicate socketTester(SocketOpen open, Timeouts timeouts) { - return timeouts.portOpen == 0 ? open : new RetryablePredicate(open, timeouts.portOpen); + not(stateRunning), timeouts.scriptComplete); } @Override diff --git a/compute/src/main/java/org/jclouds/compute/domain/NodeMetadataBuilder.java b/compute/src/main/java/org/jclouds/compute/domain/NodeMetadataBuilder.java index ab5cf48f6f..c99d2a3451 100644 --- a/compute/src/main/java/org/jclouds/compute/domain/NodeMetadataBuilder.java +++ b/compute/src/main/java/org/jclouds/compute/domain/NodeMetadataBuilder.java @@ -45,7 +45,7 @@ public class NodeMetadataBuilder extends ComputeMetadataBuilder { private Credentials credentials; @Nullable private String tag; - private int loginPort; + private int loginPort = 22; @Nullable private String imageId; @Nullable diff --git a/compute/src/main/java/org/jclouds/compute/functions/CreateSshClientOncePortIsListeningOnNode.java b/compute/src/main/java/org/jclouds/compute/functions/CreateSshClientOncePortIsListeningOnNode.java new file mode 100644 index 0000000000..869bb22d1e --- /dev/null +++ b/compute/src/main/java/org/jclouds/compute/functions/CreateSshClientOncePortIsListeningOnNode.java @@ -0,0 +1,60 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed 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.jclouds.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +import javax.inject.Singleton; + +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen; +import org.jclouds.compute.util.ComputeServiceUtils; +import org.jclouds.net.IPSocket; +import org.jclouds.ssh.SshClient; + +import com.google.common.base.Function; +import com.google.inject.Inject; + +/** + * + * @author Adrian Cole + * + */ +@Singleton +public class CreateSshClientOncePortIsListeningOnNode implements Function { + @Inject(optional = true) + SshClient.Factory sshFactory; + private final RetryIfSocketNotYetOpen socketTester; + + @Inject + public CreateSshClientOncePortIsListeningOnNode(RetryIfSocketNotYetOpen socketTester) { + this.socketTester = socketTester; + } + + @Override + public SshClient apply(NodeMetadata node) { + checkState(sshFactory != null, "ssh requested, but no SshModule configured"); + checkNotNull(node.getCredentials(), "credentials for node " + node.getName()); + checkNotNull(node.getCredentials().credential, "credentials.credential for node " + node.getName()); + IPSocket socket = ComputeServiceUtils.findReachableSocketOnNode(socketTester, node, node.getLoginPort()); + return sshFactory.create(socket, node.getCredentials()); + } +} \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/compute/internal/UtilsImpl.java b/compute/src/main/java/org/jclouds/compute/internal/UtilsImpl.java index 56ede405d2..83a135439a 100644 --- a/compute/src/main/java/org/jclouds/compute/internal/UtilsImpl.java +++ b/compute/src/main/java/org/jclouds/compute/internal/UtilsImpl.java @@ -26,14 +26,17 @@ import javax.inject.Singleton; import org.jclouds.Constants; import org.jclouds.compute.Utils; +import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.crypto.Crypto; import org.jclouds.date.DateService; import org.jclouds.json.Json; import org.jclouds.logging.Logger.LoggerFactory; import org.jclouds.rest.HttpAsyncClient; import org.jclouds.rest.HttpClient; +import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient.Factory; +import com.google.common.base.Function; import com.google.inject.Inject; /** @@ -44,15 +47,15 @@ import com.google.inject.Inject; public class UtilsImpl extends org.jclouds.rest.internal.UtilsImpl implements Utils { @Inject(optional = true) private Factory sshFactory; + private final Function sshForNode; @Inject - UtilsImpl(Json json, HttpClient simpleClient, HttpAsyncClient simpleAsyncClient, - Crypto encryption, DateService date, - @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads, - @Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads, - LoggerFactory loggerFactory) { - super(json, simpleClient, simpleAsyncClient, encryption, date, userThreads, ioThreads, - loggerFactory); + UtilsImpl(Json json, HttpClient simpleClient, HttpAsyncClient simpleAsyncClient, Crypto encryption, + DateService date, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads, + @Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads, LoggerFactory loggerFactory, + Function sshForNode) { + super(json, simpleClient, simpleAsyncClient, encryption, date, userThreads, ioThreads, loggerFactory); + this.sshForNode = sshForNode; } @Override @@ -65,4 +68,9 @@ public class UtilsImpl extends org.jclouds.rest.internal.UtilsImpl implements Ut return sshFactory; } + @Override + public Function sshForNode() { + return sshForNode; + } + } diff --git a/compute/src/main/java/org/jclouds/compute/predicates/RetryIfSocketNotYetOpen.java b/compute/src/main/java/org/jclouds/compute/predicates/RetryIfSocketNotYetOpen.java new file mode 100644 index 0000000000..19f26c0e65 --- /dev/null +++ b/compute/src/main/java/org/jclouds/compute/predicates/RetryIfSocketNotYetOpen.java @@ -0,0 +1,86 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * Licensed 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.jclouds.compute.predicates; + +import java.util.concurrent.TimeUnit; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; + +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; +import org.jclouds.logging.Logger; +import org.jclouds.net.IPSocket; +import org.jclouds.predicates.RetryablePredicate; +import org.jclouds.predicates.SocketOpen; + +import com.google.common.base.Predicate; + +/** + * + * + * Not singleton as seconds are mutable + * + * @author Adrian Cole + * + */ +public class RetryIfSocketNotYetOpen implements Predicate { + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + private Logger logger = Logger.NULL; + + private final SocketOpen socketTester; + private long seconds; + + public RetryIfSocketNotYetOpen seconds(long seconds) { + this.seconds = seconds; + return this; + } + + @Inject + public RetryIfSocketNotYetOpen(SocketOpen socketTester, Timeouts timeouts) { + this.socketTester = socketTester; + this.seconds = timeouts.portOpen; + } + + public RetryIfSocketNotYetOpen(SocketOpen socketTester, Logger logger, long seconds) { + this.socketTester = socketTester; + this.logger = logger; + this.seconds = seconds; + } + + @Override + public String toString() { + return "retryIfSocketNotYetOpen(" + seconds + ")"; + } + + @Override + public boolean apply(IPSocket socket) { + logger.debug(">> blocking on socket %s for %d seconds", socket, seconds); + RetryablePredicate tester = new RetryablePredicate(socketTester, seconds, 1, TimeUnit.SECONDS); + boolean passed = tester.apply(socket); + if (passed) + logger.debug("<< socket %s opened", socket); + else + logger.warn("<< socket %s didn't open after %d seconds", socket, seconds); + return passed; + } +} \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/compute/util/ComputeServiceUtils.java b/compute/src/main/java/org/jclouds/compute/util/ComputeServiceUtils.java index 5175dcbb32..84b9c38254 100644 --- a/compute/src/main/java/org/jclouds/compute/util/ComputeServiceUtils.java +++ b/compute/src/main/java/org/jclouds/compute/util/ComputeServiceUtils.java @@ -19,10 +19,15 @@ package org.jclouds.compute.util; +import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Throwables.getStackTraceAsString; +import static com.google.common.collect.Iterables.concat; import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.find; +import static com.google.common.collect.Iterables.size; +import static com.google.common.collect.Iterables.transform; import static org.jclouds.scriptbuilder.domain.Statements.pipeHttpResponseToBash; +import static org.jclouds.util.Utils.getSupportedProvidersOfType; import java.net.URI; import java.util.Formatter; @@ -33,6 +38,7 @@ import java.util.concurrent.Callable; import java.util.regex.Matcher; import java.util.regex.Pattern; + import org.jclouds.compute.ComputeServiceContextBuilder; import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.Hardware; @@ -40,13 +46,15 @@ import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen; import org.jclouds.http.HttpRequest; import org.jclouds.logging.Logger; +import org.jclouds.net.IPSocket; import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statements; import org.jclouds.ssh.SshClient; -import org.jclouds.util.Utils; +import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap; @@ -212,13 +220,33 @@ public class ComputeServiceUtils { void setConnection(SshClient ssh, Logger logger); } - public static boolean isKeyAuth(NodeMetadata createdNode) { - return createdNode.getCredentials().credential != null - && createdNode.getCredentials().credential.startsWith("-----BEGIN RSA PRIVATE KEY-----"); + public static Iterable getSupportedProviders() { + return getSupportedProvidersOfType(ComputeServiceContextBuilder.class); } - public static Iterable getSupportedProviders() { - return Utils.getSupportedProvidersOfType(ComputeServiceContextBuilder.class); + public static IPSocket findReachableSocketOnNode(RetryIfSocketNotYetOpen socketTester, final NodeMetadata node, + final int port) { + checkNodeHasIps(node); + IPSocket socket = null; + try { + socket = find( + transform(concat(node.getPublicAddresses(), node.getPrivateAddresses()), + new Function() { + + @Override + public IPSocket apply(String from) { + return new IPSocket(from, port); + } + }), socketTester); + } catch (NoSuchElementException e) { + throw new RuntimeException(String.format("could not connect to any ip address port %d on node %s", port, node)); + } + return socket; + } + + public static void checkNodeHasIps(NodeMetadata node) { + checkState(size(concat(node.getPublicAddresses(), node.getPrivateAddresses())) > 0, + "node does not have IP addresses configured: " + node); } } diff --git a/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java b/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java index 5ea1889a77..7424444238 100644 --- a/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java +++ b/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java @@ -19,9 +19,12 @@ package org.jclouds.compute.util; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static org.jclouds.compute.util.ComputeServiceUtils.isKeyAuth; +import static com.google.common.base.Throwables.getRootCause; +import static com.google.common.base.Throwables.propagate; +import static com.google.common.collect.Iterables.size; +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Maps.newHashMap; +import static org.jclouds.compute.util.ComputeServiceUtils.findReachableSocketOnNode; import static org.jclouds.concurrent.FutureIterables.awaitCompletion; import java.util.List; @@ -31,11 +34,11 @@ import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; import javax.annotation.Resource; import javax.inject.Named; +import javax.inject.Provider; import javax.inject.Singleton; import org.jclouds.Constants; @@ -45,14 +48,13 @@ import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.options.RunScriptOptions; import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen; import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; import org.jclouds.compute.strategy.GetNodeMetadataStrategy; import org.jclouds.compute.util.ComputeServiceUtils.SshCallable; import org.jclouds.logging.Logger; -import org.jclouds.net.IPSocket; -import org.jclouds.predicates.RetryablePredicate; import org.jclouds.scriptbuilder.domain.AuthorizeRSAPublicKey; import org.jclouds.scriptbuilder.domain.InstallRSAPrivateKey; import org.jclouds.scriptbuilder.domain.Statement; @@ -60,11 +62,8 @@ import org.jclouds.scriptbuilder.domain.StatementList; import org.jclouds.ssh.ExecResponse; import org.jclouds.ssh.SshClient; +import com.google.common.base.Function; import com.google.common.base.Predicate; -import com.google.common.base.Throwables; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.google.inject.Inject; /** @@ -76,20 +75,20 @@ public class ComputeUtils { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; - @Inject(optional = true) - protected SshClient.Factory sshFactory; + protected final Function sshFactory; protected final Predicate runScriptNotRunning; - protected final Predicate socketTester; + protected final Provider socketTester; protected final ExecutorService executor; protected final Predicate nodeRunning; protected final GetNodeMetadataStrategy getNode; protected final Timeouts timeouts; @Inject - public ComputeUtils(Predicate socketTester, + public ComputeUtils(Provider socketTester, Function sshFactory, @Named("SCRIPT_COMPLETE") Predicate runScriptNotRunning, GetNodeMetadataStrategy getNode, Timeouts timeouts, @Named("NODE_RUNNING") Predicate nodeRunning, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { + this.sshFactory = sshFactory; this.nodeRunning = nodeRunning; this.timeouts = timeouts; this.getNode = getNode; @@ -101,7 +100,7 @@ public class ComputeUtils { public Map> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(final TemplateOptions options, Iterable runningNodes, final Set goodNodes, final Map badNodes) { - Map> responses = Maps.newHashMap(); + Map> responses = newHashMap(); for (final NodeMetadata node : runningNodes) { responses.put(node, executor.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes, goodNodes, options))); @@ -119,8 +118,7 @@ public class ComputeUtils { logger.debug("<< options applied node(%s)", node1.getId()); goodNodes.add(node1); } catch (Exception e) { - logger.error(e, "<< problem applying options to node(%s): ", node.getId(), Throwables.getRootCause(e) - .getMessage()); + logger.error(e, "<< problem applying options to node(%s): ", node.getId(), getRootCause(e).getMessage()); badNodes.put(node, e); } return null; @@ -133,13 +131,13 @@ public class ComputeUtils { return node; if (nodeRunning.apply(node)) - node = NodeMetadataBuilder.fromNodeMetadata(getNode.getNode(node.getId())) - .credentials(node.getCredentials()).build(); + node = NodeMetadataBuilder.fromNodeMetadata(getNode.getNode(node.getId())).credentials(node.getCredentials()) + .build(); else throw new IllegalStateException(String.format( "node didn't achieve the state running on node %s within %d seconds, final state: %s", node.getId(), timeouts.nodeRunning / 1000, node.getState())); - List bootstrap = Lists.newArrayList(); + List bootstrap = newArrayList(); if (options.getRunScript() != null) bootstrap.add(options.getRunScript()); if (options.getPublicKey() != null) @@ -151,14 +149,10 @@ public class ComputeUtils { return node; } - public void checkNodeHasPublicIps(NodeMetadata node) { - checkState(node.getPublicAddresses().size() > 0, "node does not have IP addresses configured: " + node); - } - public ExecResponse runScriptOnNode(NodeMetadata node, Statement runScript, RunScriptOptions options) { InitAndStartScriptOnNode callable = generateScript(node, runScript, options); ExecResponse response; - SshClient ssh = createSshClientOncePortIsListeningOnNode(node); + SshClient ssh = sshFactory.apply(node); try { ssh.connect(); callable.setConnection(ssh, logger); @@ -168,24 +162,11 @@ public class ComputeUtils { ssh.disconnect(); } if (options.getPort() > 0) { - checkNodeHasPublicIps(node); - blockUntilPortIsListeningOnPublicIp(options.getPort(), options.getSeconds(), - Iterables.get(node.getPublicAddresses(), 0)); + findReachableSocketOnNode(socketTester.get().seconds(options.getSeconds()), node, options.getPort()); } return response; } - public void blockUntilPortIsListeningOnPublicIp(int port, int seconds, String inetAddress) { - logger.debug(">> blocking on port %s:%d for %d seconds", inetAddress, port, seconds); - RetryablePredicate tester = new RetryablePredicate(socketTester, seconds, 1, TimeUnit.SECONDS); - IPSocket socket = new IPSocket(inetAddress, port); - boolean passed = tester.apply(socket); - if (passed) - logger.debug("<< port %s:%d opened", inetAddress, port); - else - logger.warn("<< port %s:%d didn't open after %d seconds", inetAddress, port, seconds); - } - public InitAndStartScriptOnNode generateScript(NodeMetadata node, Statement script, RunScriptOptions options) { return options.shouldBlockOnComplete() ? new RunScriptOnNode(runScriptNotRunning, node, options.getTaskName(), script, options.shouldRunAsRoot()) : new InitAndStartScriptOnNode(node, options.getTaskName(), script, @@ -194,11 +175,7 @@ public class ComputeUtils { public Map, ?> runCallablesOnNode(NodeMetadata node, Iterable> parallel, @Nullable SshCallable last) { - checkState(this.sshFactory != null, "runScript requested, but no SshModule configured"); - checkNodeHasPublicIps(node); - checkNotNull(node.getCredentials(), "credentials for node " + node.getName()); - checkNotNull(node.getCredentials().credential, "credentials.credential for node " + node.getName()); - SshClient ssh = createSshClientOncePortIsListeningOnNode(node); + SshClient ssh = sshFactory.apply(node); try { ssh.connect(); return runTasksUsingSshClient(parallel, last, ssh); @@ -210,8 +187,8 @@ public class ComputeUtils { private Map, ?> runTasksUsingSshClient(Iterable> parallel, SshCallable last, SshClient ssh) { - Map, Object> responses = Maps.newHashMap(); - if (Iterables.size(parallel) > 0) { + Map, Object> responses = newHashMap(); + if (size(parallel) > 0) { responses.putAll(runCallablesUsingSshClient(parallel, ssh)); } if (last != null) { @@ -219,24 +196,15 @@ public class ComputeUtils { try { responses.put(last, last.call()); } catch (Exception e) { - Throwables.propagate(e); + propagate(e); } } return responses; } - public SshClient createSshClientOncePortIsListeningOnNode(NodeMetadata node) { - IPSocket socket = new IPSocket(Iterables.get(node.getPublicAddresses(), 0), 22); - socketTester.apply(socket); - SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().identity, - node.getCredentials().credential.getBytes()) : sshFactory.create(socket, node.getCredentials().identity, - node.getCredentials().credential); - return ssh; - } - // TODO refactor private Map, Object> runCallablesUsingSshClient(Iterable> parallel, SshClient ssh) { - Map, Future> parallelResponses = Maps.newHashMap(); + Map, Future> parallelResponses = newHashMap(); for (SshCallable callable : parallel) { callable.setConnection(ssh, logger); @@ -252,14 +220,14 @@ public class ComputeUtils { @SuppressWarnings("unchecked") public Map, T> transform(Map, Future> responses) { - Map, T> actualResponses = Maps.newHashMap(); + Map, T> actualResponses = newHashMap(); for (Map.Entry, Future> entry : responses.entrySet()) { try { actualResponses.put(entry.getKey(), (T) entry.getValue().get()); } catch (InterruptedException e) { - throw Throwables.propagate(e); + throw propagate(e); } catch (ExecutionException e) { - throw Throwables.propagate(e); + throw propagate(e); } } return actualResponses; diff --git a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java index 692106d0ce..c0fca2fc2f 100755 --- a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java @@ -564,20 +564,7 @@ public abstract class BaseComputeServiceLiveTest { } protected void doCheckJavaIsInstalledViaSsh(NodeMetadata node) throws IOException { - IPSocket socket = new IPSocket(get(node.getPublicAddresses(), 0), 22); - socketTester.apply(socket); // TODO add transitionTo option that accepts - // a socket conection - // state. - SshClient ssh = (node.getCredentials().credential != null && !node.getCredentials().credential - .startsWith("-----BEGIN RSA PRIVATE KEY-----")) ? context.utils().sshFactory() - .create(socket, node.getCredentials().identity, node.getCredentials().credential) : context - .utils() - .sshFactory() - .create( - socket, - node.getCredentials().identity, - node.getCredentials().credential != null ? node.getCredentials().credential.getBytes() : keyPair.get( - "private").getBytes()); + SshClient ssh = context.utils().sshForNode().apply(node); try { ssh.connect(); ExecResponse hello = ssh.exec("echo hello"); diff --git a/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java b/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java index d36118244c..63cde85bde 100644 --- a/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java +++ b/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java @@ -19,7 +19,6 @@ package org.jclouds.compute; -import static org.easymock.EasyMock.aryEq; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.reportMatcher; @@ -41,6 +40,7 @@ import org.easymock.IArgumentMatcher; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Template; +import org.jclouds.domain.Credentials; import org.jclouds.io.Payload; import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; @@ -120,15 +120,14 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes SshClient client4 = createMock(SshClient.class); SshClient client5 = createMock(SshClient.class); - expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "password1")).andReturn(client1) - .atLeastOnce(); + expect(factory.create(new IPSocket("144.175.1.1", 22), new Credentials("root", "password1"))).andReturn( + client1); runScriptAndService(client1, 1); - expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "romeo")).andThrow( + expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "password2"))).andReturn( + client2).times(2); + expect(factory.create(new IPSocket("144.175.1.2", 22), new Credentials("root", "romeo"))).andThrow( new SshException("Auth fail")); - expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "password2")).andReturn(client2) - .atLeastOnce(); - client2.connect(); try { runScript(client2, "runScriptWithCreds", Utils.toStringAndClose(StubComputeServiceIntegrationTest.class @@ -138,32 +137,32 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes } client2.disconnect(); - expect(factory.create(new IPSocket("144.175.1.3", 22), "root", "password3")).andReturn(client3) - .atLeastOnce(); - expect(factory.create(new IPSocket("144.175.1.4", 22), "root", "password4")).andReturn(client4) - .atLeastOnce(); - expect(factory.create(new IPSocket("144.175.1.5", 22), "root", "password5")).andReturn(client5) - .atLeastOnce(); + expect(factory.create(new IPSocket("144.175.1.3", 22), new Credentials("root", "password3"))).andReturn( + client3).times(2); + expect(factory.create(new IPSocket("144.175.1.4", 22), new Credentials("root", "password4"))).andReturn( + client4).times(2); + expect(factory.create(new IPSocket("144.175.1.5", 22), new Credentials("root", "password5"))).andReturn( + client5).times(2); runScriptAndInstallSsh(client3, "bootstrap", 3); runScriptAndInstallSsh(client4, "bootstrap", 4); runScriptAndInstallSsh(client5, "bootstrap", 5); expect( - factory.create(eq(new IPSocket("144.175.1.1", 22)), eq("root"), aryEq(keyPair.get("private") - .getBytes()))).andReturn(client1).atLeastOnce(); + factory.create(eq(new IPSocket("144.175.1.1", 22)), + eq(new Credentials("root", keyPair.get("private"))))).andReturn(client1); expect( - factory.create(eq(new IPSocket("144.175.1.2", 22)), eq("root"), aryEq(keyPair.get("private") - .getBytes()))).andReturn(client2).atLeastOnce(); + factory.create(eq(new IPSocket("144.175.1.2", 22)), + eq(new Credentials("root", keyPair.get("private"))))).andReturn(client2); expect( - factory.create(eq(new IPSocket("144.175.1.3", 22)), eq("root"), aryEq(keyPair.get("private") - .getBytes()))).andReturn(client3).atLeastOnce(); + factory.create(eq(new IPSocket("144.175.1.3", 22)), + eq(new Credentials("root", keyPair.get("private"))))).andReturn(client3); expect( - factory.create(eq(new IPSocket("144.175.1.4", 22)), eq("root"), aryEq(keyPair.get("private") - .getBytes()))).andReturn(client4).atLeastOnce(); + factory.create(eq(new IPSocket("144.175.1.4", 22)), + eq(new Credentials("root", keyPair.get("private"))))).andReturn(client4); expect( - factory.create(eq(new IPSocket("155.175.1.5", 22)), eq("root"), aryEq(keyPair.get("private") - .getBytes()))).andReturn(client5).atLeastOnce(); + factory.create(eq(new IPSocket("144.175.1.5", 22)), + eq(new Credentials("root", keyPair.get("private"))))).andReturn(client5); helloAndJava(client2); helloAndJava(client3); diff --git a/extensions/ssh/jsch/src/main/java/org/jclouds/ssh/jsch/predicates/InetSocketAddressConnect.java b/core/src/main/java/org/jclouds/predicates/InetSocketAddressConnect.java similarity index 96% rename from extensions/ssh/jsch/src/main/java/org/jclouds/ssh/jsch/predicates/InetSocketAddressConnect.java rename to core/src/main/java/org/jclouds/predicates/InetSocketAddressConnect.java index 05f6492d9c..b8fafab38a 100644 --- a/extensions/ssh/jsch/src/main/java/org/jclouds/ssh/jsch/predicates/InetSocketAddressConnect.java +++ b/core/src/main/java/org/jclouds/predicates/InetSocketAddressConnect.java @@ -17,7 +17,7 @@ * ==================================================================== */ -package org.jclouds.ssh.jsch.predicates; +package org.jclouds.predicates; import java.io.IOException; import java.net.InetSocketAddress; @@ -29,7 +29,6 @@ import javax.inject.Singleton; import org.jclouds.logging.Logger; import org.jclouds.net.IPSocket; -import org.jclouds.predicates.SocketOpen; import com.google.inject.Inject; diff --git a/core/src/main/java/org/jclouds/util/Utils.java b/core/src/main/java/org/jclouds/util/Utils.java index b8720e2f7b..3032fce497 100644 --- a/core/src/main/java/org/jclouds/util/Utils.java +++ b/core/src/main/java/org/jclouds/util/Utils.java @@ -58,6 +58,8 @@ import javax.annotation.Nullable; import javax.annotation.Resource; import org.jclouds.PropertiesBuilder; +import org.jclouds.crypto.Pems; +import org.jclouds.domain.Credentials; import org.jclouds.logging.Logger; import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.RestContextBuilder; @@ -246,15 +248,14 @@ public class Utils { } /** - * Encode the given string with the given encoding, if possible. If the - * encoding fails with {@link UnsupportedEncodingException}, log a warning - * and fall back to the system's default encoding. + * Encode the given string with the given encoding, if possible. If the encoding fails with + * {@link UnsupportedEncodingException}, log a warning and fall back to the system's default + * encoding. * * @param str * what to encode * @param charsetName - * the name of a supported {@link java.nio.charset.Charset - * charset} + * the name of a supported {@link java.nio.charset.Charset charset} * @return properly encoded String. */ public static byte[] encodeString(String str, String charsetName) { @@ -268,10 +269,9 @@ public class Utils { } /** - * Encode the given string with the UTF-8 encoding, the sane default. In the - * very unlikely event the encoding fails with - * {@link UnsupportedEncodingException}, log a warning and fall back to the - * system's default encoding. + * Encode the given string with the UTF-8 encoding, the sane default. In the very unlikely event + * the encoding fails with {@link UnsupportedEncodingException}, log a warning and fall back to + * the system's default encoding. * * @param str * what to encode @@ -322,8 +322,7 @@ public class Utils { } /** - * Will throw an exception if the argument is null or empty. Accepts a custom - * error message. + * Will throw an exception if the argument is null or empty. Accepts a custom error message. * * @param nullableString * string to verify. Can be null or empty. @@ -335,8 +334,8 @@ public class Utils { } /** - * Gets a set of supported providers. Idea stolen from pallets - * (supported-clouds). Uses rest.properties to populate the set. + * Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses + * rest.properties to populate the set. * */ public static Iterable getSupportedProviders() { @@ -344,8 +343,8 @@ public class Utils { } /** - * Gets a set of supported providers. Idea stolen from pallets - * (supported-clouds). Uses rest.properties to populate the set. + * Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses + * rest.properties to populate the set. * */ @SuppressWarnings("unchecked") @@ -468,4 +467,24 @@ public class Utils { } return modules; } + + public static boolean isPrivateKeyCredential(Credentials credentials) { + return credentials != null + && credentials.credential != null + && (credentials.credential.startsWith(Pems.PRIVATE_PKCS1_MARKER) || credentials.credential + .startsWith(Pems.PRIVATE_PKCS8_MARKER)); + } + + public static Credentials overrideCredentialsIfSupplied(Credentials defaultCredentials, + @Nullable Credentials overridingCredentials) { + if (overridingCredentials == null) + return defaultCredentials; + String identity = overridingCredentials.identity != null ? overridingCredentials.identity : checkNotNull( + defaultCredentials, "defaultCredentials").identity; + String credential = overridingCredentials.credential != null ? overridingCredentials.credential : checkNotNull( + defaultCredentials, "defaultCredentials").credential; + + return new Credentials(identity, credential); + } + } diff --git a/core/src/test/java/org/jclouds/util/UtilsTest.java b/core/src/test/java/org/jclouds/util/UtilsTest.java index 96fa08d66c..d17880b0db 100644 --- a/core/src/test/java/org/jclouds/util/UtilsTest.java +++ b/core/src/test/java/org/jclouds/util/UtilsTest.java @@ -25,6 +25,7 @@ import static org.testng.Assert.assertEquals; import java.io.UnsupportedEncodingException; import java.util.concurrent.TimeoutException; +import org.jclouds.domain.Credentials; import org.jclouds.rest.AuthorizationException; import org.testng.annotations.Test; @@ -42,6 +43,33 @@ import com.google.inject.spi.Message; @Test(groups = "unit", testName = "jclouds.UtilsTest") public class UtilsTest { + public void testOverridingCredentialsWhenOverridingIsNull() { + Credentials defaultCredentials = new Credentials("foo", "bar"); + Credentials overridingCredentials = null; + assertEquals(Utils.overrideCredentialsIfSupplied(defaultCredentials, overridingCredentials), defaultCredentials); + } + + public void testOverridingCredentialsWhenOverridingLoginIsNull() { + Credentials defaultCredentials = new Credentials("foo", "bar"); + Credentials overridingCredentials = new Credentials(null, "baz"); + assertEquals(Utils.overrideCredentialsIfSupplied(defaultCredentials, overridingCredentials), new Credentials( + "foo", "baz")); + } + + public void testOverridingCredentialsWhenOverridingCredentialIsNull() { + Credentials defaultCredentials = new Credentials("foo", "bar"); + Credentials overridingCredentials = new Credentials("fooble", null); + assertEquals(Utils.overrideCredentialsIfSupplied(defaultCredentials, overridingCredentials), new Credentials( + "fooble", "bar")); + } + + public void testOverridingCredentialsWhenOverridingCredentialsAreNull() { + Credentials defaultCredentials = new Credentials("foo", "bar"); + Credentials overridingCredentials = new Credentials(null, null); + assertEquals(Utils.overrideCredentialsIfSupplied(defaultCredentials, overridingCredentials), new Credentials( + "foo", "bar")); + } + public void testGetCause() { AuthorizationException aex = createMock(AuthorizationException.class); Message message = new Message(ImmutableList.of(), "test", aex); diff --git a/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java b/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java index 811325390d..9e85005fe0 100644 --- a/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java +++ b/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java @@ -59,11 +59,11 @@ import org.jclouds.gogrid.predicates.ServerLatestJobCompleted; import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.net.IPSocket; +import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.rest.RestContext; import org.jclouds.ssh.SshClient; import org.jclouds.ssh.jsch.JschSshClient; -import org.jclouds.ssh.jsch.predicates.InetSocketAddressConnect; import org.testng.SkipException; import org.testng.TestException; import org.testng.annotations.AfterTest; diff --git a/rackspace/src/main/java/org/jclouds/rackspace/config/RackspaceAuthenticationRestModule.java b/rackspace/src/main/java/org/jclouds/rackspace/config/RackspaceAuthenticationRestModule.java index d3e5f99a7e..0fd6f69c8a 100755 --- a/rackspace/src/main/java/org/jclouds/rackspace/config/RackspaceAuthenticationRestModule.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/config/RackspaceAuthenticationRestModule.java @@ -117,7 +117,7 @@ public class RackspaceAuthenticationRestModule extends AbstractModule { @Provides @Singleton @CloudFiles - protected URI provideStorageUrl(AuthenticationResponse response) { + protected URI providestroageUrl(AuthenticationResponse response) { return response.getStorageUrl(); } diff --git a/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/RimuHostingAsyncClient.java b/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/RimuHostingAsyncClient.java index 18c34f6147..57bf048d9a 100644 --- a/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/RimuHostingAsyncClient.java +++ b/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/RimuHostingAsyncClient.java @@ -139,7 +139,7 @@ public interface RimuHostingAsyncClient { ListenableFuture restartServer(@PathParam("id") Long id); /** - * @see RimuHostingClient#destoryServer + * @see RimuHostingClient#destroyServer */ @DELETE @Path("/orders/order-{id}-blah/vps") diff --git a/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTask.java b/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTask.java index 357b1a8cb0..7e069b2076 100644 --- a/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTask.java +++ b/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTask.java @@ -20,7 +20,6 @@ package org.jclouds.tools.ant.taskdefs.compute; import static org.jclouds.compute.util.ComputeServiceUtils.getCores; -import static org.jclouds.compute.util.ComputeServiceUtils.isKeyAuth; import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.buildComputeMap; import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.createTemplateFromElement; import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.ipOrEmptyString; @@ -45,6 +44,7 @@ import org.jclouds.compute.domain.Template; import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.domain.Location; import org.jclouds.http.HttpUtils; +import org.jclouds.util.Utils; import com.google.common.base.CaseFormat; import com.google.common.base.Splitter; @@ -212,7 +212,7 @@ public class ComputeTask extends Task { getProject().setProperty(nodeElement.getIdproperty(), createdNode.getProviderId()); if (nodeElement.getHostproperty() != null) getProject().setProperty(nodeElement.getHostproperty(), ipOrEmptyString(createdNode.getPublicAddresses())); - if (nodeElement.getPasswordproperty() != null && !isKeyAuth(createdNode)) + if (nodeElement.getPasswordproperty() != null && !Utils.isPrivateKeyCredential(createdNode.getCredentials())) getProject().setProperty(nodeElement.getPasswordproperty(), createdNode.getCredentials().credential); if (nodeElement.getUsernameproperty() != null) getProject().setProperty(nodeElement.getUsernameproperty(), createdNode.getCredentials().identity); diff --git a/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudGuestCustomizationLiveTest.java b/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudGuestCustomizationLiveTest.java index 540ce3b341..443f6d7f08 100644 --- a/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudGuestCustomizationLiveTest.java +++ b/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudGuestCustomizationLiveTest.java @@ -35,11 +35,11 @@ import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.options.TemplateOptions; import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.net.IPSocket; +import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient.Factory; import org.jclouds.ssh.jsch.config.JschSshClientModule; -import org.jclouds.ssh.jsch.predicates.InetSocketAddressConnect; import org.jclouds.vcloud.compute.options.VCloudTemplateOptions; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test;