mirror of https://github.com/apache/jclouds.git
refactored ssh connections so that they can be shared across views
This commit is contained in:
parent
c7c6e9eae1
commit
b08abc6745
|
@ -37,12 +37,12 @@ import org.jclouds.aws.ec2.domain.Reservation;
|
||||||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.aws.ec2.predicates.InstanceStateRunning;
|
import org.jclouds.aws.ec2.predicates.InstanceStateRunning;
|
||||||
import org.jclouds.net.IPSocket;
|
import org.jclouds.net.IPSocket;
|
||||||
|
import org.jclouds.predicates.InetSocketAddressConnect;
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.rest.RestContextFactory;
|
import org.jclouds.rest.RestContextFactory;
|
||||||
import org.jclouds.scriptbuilder.ScriptBuilder;
|
import org.jclouds.scriptbuilder.ScriptBuilder;
|
||||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
import org.jclouds.ssh.jsch.predicates.InetSocketAddressConnect;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
|
@ -21,9 +21,11 @@ package org.jclouds.compute;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.internal.UtilsImpl;
|
import org.jclouds.compute.internal.UtilsImpl;
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.inject.ImplementedBy;
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,4 +39,9 @@ public interface Utils extends org.jclouds.rest.Utils {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
SshClient.Factory sshFactory();
|
SshClient.Factory sshFactory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return function that gets an ssh client for a node that is available via ssh.
|
||||||
|
*/
|
||||||
|
Function<NodeMetadata, SshClient> sshForNode();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.util.ComputeServiceUtils;
|
|
||||||
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
|
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.scriptbuilder.InitBuilder;
|
import org.jclouds.scriptbuilder.InitBuilder;
|
||||||
|
@ -32,6 +31,7 @@ import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
import org.jclouds.scriptbuilder.domain.Statement;
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
import org.jclouds.ssh.ExecResponse;
|
import org.jclouds.ssh.ExecResponse;
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
|
import org.jclouds.util.Utils;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ public class InitAndStartScriptOnNode implements SshCallable<ExecResponse> {
|
||||||
String command;
|
String command;
|
||||||
if (node.getCredentials().identity.equals("root")) {
|
if (node.getCredentials().identity.equals("root")) {
|
||||||
command = "./" + init.getInstanceName() + " " + action;
|
command = "./" + init.getInstanceName() + " " + action;
|
||||||
} else if (ComputeServiceUtils.isKeyAuth(node)) {
|
} else if (Utils.isPrivateKeyCredential(node.getCredentials())) {
|
||||||
command = "sudo ./" + init.getInstanceName() + " " + action;
|
command = "sudo ./" + init.getInstanceName() + " " + action;
|
||||||
} else {
|
} else {
|
||||||
command = String.format("echo '%s'|sudo -S ./%s %s", node.getCredentials().credential, init.getInstanceName(),
|
command = String.format("echo '%s'|sudo -S ./%s %s", node.getCredentials().credential, init.getInstanceName(),
|
||||||
|
|
|
@ -34,10 +34,13 @@ import org.jclouds.compute.LoadBalancerService;
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.Hardware;
|
import org.jclouds.compute.domain.Hardware;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.domain.TemplateBuilder;
|
import org.jclouds.compute.domain.TemplateBuilder;
|
||||||
|
import org.jclouds.compute.functions.CreateSshClientOncePortIsListeningOnNode;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.jclouds.rest.suppliers.RetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
|
import org.jclouds.rest.suppliers.RetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
|
||||||
|
import org.jclouds.ssh.SshClient;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
@ -47,6 +50,7 @@ import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.Scopes;
|
import com.google.inject.Scopes;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
import com.google.inject.util.Providers;
|
import com.google.inject.util.Providers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,6 +62,8 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
install(new ComputeServiceTimeoutsModule());
|
install(new ComputeServiceTimeoutsModule());
|
||||||
bindLoadBalancerService();
|
bindLoadBalancerService();
|
||||||
|
bind(new TypeLiteral<Function<NodeMetadata, SshClient>>() {
|
||||||
|
}).to(CreateSshClientOncePortIsListeningOnNode.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void bindLoadBalancerService() {
|
protected void bindLoadBalancerService() {
|
||||||
|
|
|
@ -30,9 +30,7 @@ import org.jclouds.compute.predicates.NodeTerminated;
|
||||||
import org.jclouds.compute.predicates.ScriptStatusReturnsZero;
|
import org.jclouds.compute.predicates.ScriptStatusReturnsZero;
|
||||||
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
|
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
|
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
|
||||||
import org.jclouds.net.IPSocket;
|
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
import org.jclouds.predicates.SocketOpen;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
|
@ -69,12 +67,6 @@ public class ComputeServiceTimeoutsModule extends AbstractModule {
|
||||||
not(stateRunning), timeouts.scriptComplete);
|
not(stateRunning), timeouts.scriptComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
protected Predicate<IPSocket> socketTester(SocketOpen open, Timeouts timeouts) {
|
|
||||||
return timeouts.portOpen == 0 ? open : new RetryablePredicate<IPSocket>(open, timeouts.portOpen);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class NodeMetadataBuilder extends ComputeMetadataBuilder {
|
||||||
private Credentials credentials;
|
private Credentials credentials;
|
||||||
@Nullable
|
@Nullable
|
||||||
private String tag;
|
private String tag;
|
||||||
private int loginPort;
|
private int loginPort = 22;
|
||||||
@Nullable
|
@Nullable
|
||||||
private String imageId;
|
private String imageId;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* 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<NodeMetadata, SshClient> {
|
||||||
|
@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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,14 +26,17 @@ import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.compute.Utils;
|
import org.jclouds.compute.Utils;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.crypto.Crypto;
|
import org.jclouds.crypto.Crypto;
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
import org.jclouds.json.Json;
|
import org.jclouds.json.Json;
|
||||||
import org.jclouds.logging.Logger.LoggerFactory;
|
import org.jclouds.logging.Logger.LoggerFactory;
|
||||||
import org.jclouds.rest.HttpAsyncClient;
|
import org.jclouds.rest.HttpAsyncClient;
|
||||||
import org.jclouds.rest.HttpClient;
|
import org.jclouds.rest.HttpClient;
|
||||||
|
import org.jclouds.ssh.SshClient;
|
||||||
import org.jclouds.ssh.SshClient.Factory;
|
import org.jclouds.ssh.SshClient.Factory;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.inject.Inject;
|
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 {
|
public class UtilsImpl extends org.jclouds.rest.internal.UtilsImpl implements Utils {
|
||||||
@Inject(optional = true)
|
@Inject(optional = true)
|
||||||
private Factory sshFactory;
|
private Factory sshFactory;
|
||||||
|
private final Function<NodeMetadata, SshClient> sshForNode;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
UtilsImpl(Json json, HttpClient simpleClient, HttpAsyncClient simpleAsyncClient,
|
UtilsImpl(Json json, HttpClient simpleClient, HttpAsyncClient simpleAsyncClient, Crypto encryption,
|
||||||
Crypto encryption, DateService date,
|
DateService date, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
|
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads, LoggerFactory loggerFactory,
|
||||||
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads,
|
Function<NodeMetadata, SshClient> sshForNode) {
|
||||||
LoggerFactory loggerFactory) {
|
super(json, simpleClient, simpleAsyncClient, encryption, date, userThreads, ioThreads, loggerFactory);
|
||||||
super(json, simpleClient, simpleAsyncClient, encryption, date, userThreads, ioThreads,
|
this.sshForNode = sshForNode;
|
||||||
loggerFactory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -65,4 +68,9 @@ public class UtilsImpl extends org.jclouds.rest.internal.UtilsImpl implements Ut
|
||||||
return sshFactory;
|
return sshFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Function<NodeMetadata, SshClient> sshForNode() {
|
||||||
|
return sshForNode;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* 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<IPSocket> {
|
||||||
|
@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<IPSocket> tester = new RetryablePredicate<IPSocket>(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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,10 +19,15 @@
|
||||||
|
|
||||||
package org.jclouds.compute.util;
|
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.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.filter;
|
||||||
import static com.google.common.collect.Iterables.find;
|
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.scriptbuilder.domain.Statements.pipeHttpResponseToBash;
|
||||||
|
import static org.jclouds.util.Utils.getSupportedProvidersOfType;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Formatter;
|
import java.util.Formatter;
|
||||||
|
@ -33,6 +38,7 @@ import java.util.concurrent.Callable;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeServiceContextBuilder;
|
import org.jclouds.compute.ComputeServiceContextBuilder;
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.Hardware;
|
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.OsFamily;
|
||||||
import org.jclouds.compute.domain.Processor;
|
import org.jclouds.compute.domain.Processor;
|
||||||
import org.jclouds.compute.domain.Volume;
|
import org.jclouds.compute.domain.Volume;
|
||||||
|
import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
import org.jclouds.net.IPSocket;
|
||||||
import org.jclouds.scriptbuilder.domain.Statement;
|
import org.jclouds.scriptbuilder.domain.Statement;
|
||||||
import org.jclouds.scriptbuilder.domain.Statements;
|
import org.jclouds.scriptbuilder.domain.Statements;
|
||||||
import org.jclouds.ssh.SshClient;
|
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.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
|
@ -212,13 +220,33 @@ public class ComputeServiceUtils {
|
||||||
void setConnection(SshClient ssh, Logger logger);
|
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<String> getSupportedProviders() {
|
public static Iterable<String> getSupportedProviders() {
|
||||||
return Utils.getSupportedProvidersOfType(ComputeServiceContextBuilder.class);
|
return 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<String, IPSocket>() {
|
||||||
|
|
||||||
|
@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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,12 @@
|
||||||
|
|
||||||
package org.jclouds.compute.util;
|
package org.jclouds.compute.util;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Throwables.getRootCause;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Throwables.propagate;
|
||||||
import static org.jclouds.compute.util.ComputeServiceUtils.isKeyAuth;
|
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 static org.jclouds.concurrent.FutureIterables.awaitCompletion;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -31,11 +34,11 @@ import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
|
@ -45,14 +48,13 @@ import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||||
import org.jclouds.compute.options.RunScriptOptions;
|
import org.jclouds.compute.options.RunScriptOptions;
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
|
import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen;
|
||||||
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
|
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
|
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
|
||||||
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
|
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
|
||||||
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
|
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
|
||||||
import org.jclouds.logging.Logger;
|
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.AuthorizeRSAPublicKey;
|
||||||
import org.jclouds.scriptbuilder.domain.InstallRSAPrivateKey;
|
import org.jclouds.scriptbuilder.domain.InstallRSAPrivateKey;
|
||||||
import org.jclouds.scriptbuilder.domain.Statement;
|
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.ExecResponse;
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
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;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,20 +75,20 @@ public class ComputeUtils {
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
@Inject(optional = true)
|
protected final Function<NodeMetadata, SshClient> sshFactory;
|
||||||
protected SshClient.Factory sshFactory;
|
|
||||||
protected final Predicate<CommandUsingClient> runScriptNotRunning;
|
protected final Predicate<CommandUsingClient> runScriptNotRunning;
|
||||||
protected final Predicate<IPSocket> socketTester;
|
protected final Provider<RetryIfSocketNotYetOpen> socketTester;
|
||||||
protected final ExecutorService executor;
|
protected final ExecutorService executor;
|
||||||
protected final Predicate<NodeMetadata> nodeRunning;
|
protected final Predicate<NodeMetadata> nodeRunning;
|
||||||
protected final GetNodeMetadataStrategy getNode;
|
protected final GetNodeMetadataStrategy getNode;
|
||||||
protected final Timeouts timeouts;
|
protected final Timeouts timeouts;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ComputeUtils(Predicate<IPSocket> socketTester,
|
public ComputeUtils(Provider<RetryIfSocketNotYetOpen> socketTester, Function<NodeMetadata, SshClient> sshFactory,
|
||||||
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning, GetNodeMetadataStrategy getNode,
|
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning, GetNodeMetadataStrategy getNode,
|
||||||
Timeouts timeouts, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
|
Timeouts timeouts, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
|
this.sshFactory = sshFactory;
|
||||||
this.nodeRunning = nodeRunning;
|
this.nodeRunning = nodeRunning;
|
||||||
this.timeouts = timeouts;
|
this.timeouts = timeouts;
|
||||||
this.getNode = getNode;
|
this.getNode = getNode;
|
||||||
|
@ -101,7 +100,7 @@ public class ComputeUtils {
|
||||||
public Map<?, Future<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(final TemplateOptions options,
|
public Map<?, Future<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(final TemplateOptions options,
|
||||||
Iterable<NodeMetadata> runningNodes, final Set<NodeMetadata> goodNodes,
|
Iterable<NodeMetadata> runningNodes, final Set<NodeMetadata> goodNodes,
|
||||||
final Map<NodeMetadata, Exception> badNodes) {
|
final Map<NodeMetadata, Exception> badNodes) {
|
||||||
Map<NodeMetadata, Future<Void>> responses = Maps.newHashMap();
|
Map<NodeMetadata, Future<Void>> responses = newHashMap();
|
||||||
for (final NodeMetadata node : runningNodes) {
|
for (final NodeMetadata node : runningNodes) {
|
||||||
responses.put(node, executor.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes,
|
responses.put(node, executor.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes,
|
||||||
goodNodes, options)));
|
goodNodes, options)));
|
||||||
|
@ -119,8 +118,7 @@ public class ComputeUtils {
|
||||||
logger.debug("<< options applied node(%s)", node1.getId());
|
logger.debug("<< options applied node(%s)", node1.getId());
|
||||||
goodNodes.add(node1);
|
goodNodes.add(node1);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error(e, "<< problem applying options to node(%s): ", node.getId(), Throwables.getRootCause(e)
|
logger.error(e, "<< problem applying options to node(%s): ", node.getId(), getRootCause(e).getMessage());
|
||||||
.getMessage());
|
|
||||||
badNodes.put(node, e);
|
badNodes.put(node, e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -133,13 +131,13 @@ public class ComputeUtils {
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
if (nodeRunning.apply(node))
|
if (nodeRunning.apply(node))
|
||||||
node = NodeMetadataBuilder.fromNodeMetadata(getNode.getNode(node.getId()))
|
node = NodeMetadataBuilder.fromNodeMetadata(getNode.getNode(node.getId())).credentials(node.getCredentials())
|
||||||
.credentials(node.getCredentials()).build();
|
.build();
|
||||||
else
|
else
|
||||||
throw new IllegalStateException(String.format(
|
throw new IllegalStateException(String.format(
|
||||||
"node didn't achieve the state running on node %s within %d seconds, final state: %s", node.getId(),
|
"node didn't achieve the state running on node %s within %d seconds, final state: %s", node.getId(),
|
||||||
timeouts.nodeRunning / 1000, node.getState()));
|
timeouts.nodeRunning / 1000, node.getState()));
|
||||||
List<Statement> bootstrap = Lists.newArrayList();
|
List<Statement> bootstrap = newArrayList();
|
||||||
if (options.getRunScript() != null)
|
if (options.getRunScript() != null)
|
||||||
bootstrap.add(options.getRunScript());
|
bootstrap.add(options.getRunScript());
|
||||||
if (options.getPublicKey() != null)
|
if (options.getPublicKey() != null)
|
||||||
|
@ -151,14 +149,10 @@ public class ComputeUtils {
|
||||||
return node;
|
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) {
|
public ExecResponse runScriptOnNode(NodeMetadata node, Statement runScript, RunScriptOptions options) {
|
||||||
InitAndStartScriptOnNode callable = generateScript(node, runScript, options);
|
InitAndStartScriptOnNode callable = generateScript(node, runScript, options);
|
||||||
ExecResponse response;
|
ExecResponse response;
|
||||||
SshClient ssh = createSshClientOncePortIsListeningOnNode(node);
|
SshClient ssh = sshFactory.apply(node);
|
||||||
try {
|
try {
|
||||||
ssh.connect();
|
ssh.connect();
|
||||||
callable.setConnection(ssh, logger);
|
callable.setConnection(ssh, logger);
|
||||||
|
@ -168,24 +162,11 @@ public class ComputeUtils {
|
||||||
ssh.disconnect();
|
ssh.disconnect();
|
||||||
}
|
}
|
||||||
if (options.getPort() > 0) {
|
if (options.getPort() > 0) {
|
||||||
checkNodeHasPublicIps(node);
|
findReachableSocketOnNode(socketTester.get().seconds(options.getSeconds()), node, options.getPort());
|
||||||
blockUntilPortIsListeningOnPublicIp(options.getPort(), options.getSeconds(),
|
|
||||||
Iterables.get(node.getPublicAddresses(), 0));
|
|
||||||
}
|
}
|
||||||
return response;
|
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<IPSocket> tester = new RetryablePredicate<IPSocket>(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) {
|
public InitAndStartScriptOnNode generateScript(NodeMetadata node, Statement script, RunScriptOptions options) {
|
||||||
return options.shouldBlockOnComplete() ? new RunScriptOnNode(runScriptNotRunning, node, options.getTaskName(),
|
return options.shouldBlockOnComplete() ? new RunScriptOnNode(runScriptNotRunning, node, options.getTaskName(),
|
||||||
script, options.shouldRunAsRoot()) : new InitAndStartScriptOnNode(node, options.getTaskName(), script,
|
script, options.shouldRunAsRoot()) : new InitAndStartScriptOnNode(node, options.getTaskName(), script,
|
||||||
|
@ -194,11 +175,7 @@ public class ComputeUtils {
|
||||||
|
|
||||||
public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node, Iterable<SshCallable<?>> parallel,
|
public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node, Iterable<SshCallable<?>> parallel,
|
||||||
@Nullable SshCallable<?> last) {
|
@Nullable SshCallable<?> last) {
|
||||||
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured");
|
SshClient ssh = sshFactory.apply(node);
|
||||||
checkNodeHasPublicIps(node);
|
|
||||||
checkNotNull(node.getCredentials(), "credentials for node " + node.getName());
|
|
||||||
checkNotNull(node.getCredentials().credential, "credentials.credential for node " + node.getName());
|
|
||||||
SshClient ssh = createSshClientOncePortIsListeningOnNode(node);
|
|
||||||
try {
|
try {
|
||||||
ssh.connect();
|
ssh.connect();
|
||||||
return runTasksUsingSshClient(parallel, last, ssh);
|
return runTasksUsingSshClient(parallel, last, ssh);
|
||||||
|
@ -210,8 +187,8 @@ public class ComputeUtils {
|
||||||
|
|
||||||
private Map<SshCallable<?>, ?> runTasksUsingSshClient(Iterable<SshCallable<?>> parallel, SshCallable<?> last,
|
private Map<SshCallable<?>, ?> runTasksUsingSshClient(Iterable<SshCallable<?>> parallel, SshCallable<?> last,
|
||||||
SshClient ssh) {
|
SshClient ssh) {
|
||||||
Map<SshCallable<?>, Object> responses = Maps.newHashMap();
|
Map<SshCallable<?>, Object> responses = newHashMap();
|
||||||
if (Iterables.size(parallel) > 0) {
|
if (size(parallel) > 0) {
|
||||||
responses.putAll(runCallablesUsingSshClient(parallel, ssh));
|
responses.putAll(runCallablesUsingSshClient(parallel, ssh));
|
||||||
}
|
}
|
||||||
if (last != null) {
|
if (last != null) {
|
||||||
|
@ -219,24 +196,15 @@ public class ComputeUtils {
|
||||||
try {
|
try {
|
||||||
responses.put(last, last.call());
|
responses.put(last, last.call());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Throwables.propagate(e);
|
propagate(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return responses;
|
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
|
// TODO refactor
|
||||||
private Map<SshCallable<?>, Object> runCallablesUsingSshClient(Iterable<SshCallable<?>> parallel, SshClient ssh) {
|
private Map<SshCallable<?>, Object> runCallablesUsingSshClient(Iterable<SshCallable<?>> parallel, SshClient ssh) {
|
||||||
Map<SshCallable<?>, Future<?>> parallelResponses = Maps.newHashMap();
|
Map<SshCallable<?>, Future<?>> parallelResponses = newHashMap();
|
||||||
|
|
||||||
for (SshCallable<?> callable : parallel) {
|
for (SshCallable<?> callable : parallel) {
|
||||||
callable.setConnection(ssh, logger);
|
callable.setConnection(ssh, logger);
|
||||||
|
@ -252,14 +220,14 @@ public class ComputeUtils {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> Map<SshCallable<?>, T> transform(Map<SshCallable<?>, Future<?>> responses) {
|
public <T> Map<SshCallable<?>, T> transform(Map<SshCallable<?>, Future<?>> responses) {
|
||||||
Map<SshCallable<?>, T> actualResponses = Maps.newHashMap();
|
Map<SshCallable<?>, T> actualResponses = newHashMap();
|
||||||
for (Map.Entry<SshCallable<?>, Future<?>> entry : responses.entrySet()) {
|
for (Map.Entry<SshCallable<?>, Future<?>> entry : responses.entrySet()) {
|
||||||
try {
|
try {
|
||||||
actualResponses.put(entry.getKey(), (T) entry.getValue().get());
|
actualResponses.put(entry.getKey(), (T) entry.getValue().get());
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
throw Throwables.propagate(e);
|
throw propagate(e);
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
throw Throwables.propagate(e);
|
throw propagate(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return actualResponses;
|
return actualResponses;
|
||||||
|
|
|
@ -564,20 +564,7 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void doCheckJavaIsInstalledViaSsh(NodeMetadata node) throws IOException {
|
protected void doCheckJavaIsInstalledViaSsh(NodeMetadata node) throws IOException {
|
||||||
IPSocket socket = new IPSocket(get(node.getPublicAddresses(), 0), 22);
|
SshClient ssh = context.utils().sshForNode().apply(node);
|
||||||
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());
|
|
||||||
try {
|
try {
|
||||||
ssh.connect();
|
ssh.connect();
|
||||||
ExecResponse hello = ssh.exec("echo hello");
|
ExecResponse hello = ssh.exec("echo hello");
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
package org.jclouds.compute;
|
package org.jclouds.compute;
|
||||||
|
|
||||||
import static org.easymock.EasyMock.aryEq;
|
|
||||||
import static org.easymock.EasyMock.eq;
|
import static org.easymock.EasyMock.eq;
|
||||||
import static org.easymock.EasyMock.expect;
|
import static org.easymock.EasyMock.expect;
|
||||||
import static org.easymock.EasyMock.reportMatcher;
|
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.NodeMetadata;
|
||||||
import org.jclouds.compute.domain.OsFamily;
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.io.Payload;
|
import org.jclouds.io.Payload;
|
||||||
import org.jclouds.net.IPSocket;
|
import org.jclouds.net.IPSocket;
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
@ -120,15 +120,14 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
SshClient client4 = createMock(SshClient.class);
|
SshClient client4 = createMock(SshClient.class);
|
||||||
SshClient client5 = createMock(SshClient.class);
|
SshClient client5 = createMock(SshClient.class);
|
||||||
|
|
||||||
expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "password1")).andReturn(client1)
|
expect(factory.create(new IPSocket("144.175.1.1", 22), new Credentials("root", "password1"))).andReturn(
|
||||||
.atLeastOnce();
|
client1);
|
||||||
runScriptAndService(client1, 1);
|
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"));
|
new SshException("Auth fail"));
|
||||||
expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "password2")).andReturn(client2)
|
|
||||||
.atLeastOnce();
|
|
||||||
|
|
||||||
client2.connect();
|
client2.connect();
|
||||||
try {
|
try {
|
||||||
runScript(client2, "runScriptWithCreds", Utils.toStringAndClose(StubComputeServiceIntegrationTest.class
|
runScript(client2, "runScriptWithCreds", Utils.toStringAndClose(StubComputeServiceIntegrationTest.class
|
||||||
|
@ -138,32 +137,32 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
}
|
}
|
||||||
client2.disconnect();
|
client2.disconnect();
|
||||||
|
|
||||||
expect(factory.create(new IPSocket("144.175.1.3", 22), "root", "password3")).andReturn(client3)
|
expect(factory.create(new IPSocket("144.175.1.3", 22), new Credentials("root", "password3"))).andReturn(
|
||||||
.atLeastOnce();
|
client3).times(2);
|
||||||
expect(factory.create(new IPSocket("144.175.1.4", 22), "root", "password4")).andReturn(client4)
|
expect(factory.create(new IPSocket("144.175.1.4", 22), new Credentials("root", "password4"))).andReturn(
|
||||||
.atLeastOnce();
|
client4).times(2);
|
||||||
expect(factory.create(new IPSocket("144.175.1.5", 22), "root", "password5")).andReturn(client5)
|
expect(factory.create(new IPSocket("144.175.1.5", 22), new Credentials("root", "password5"))).andReturn(
|
||||||
.atLeastOnce();
|
client5).times(2);
|
||||||
|
|
||||||
runScriptAndInstallSsh(client3, "bootstrap", 3);
|
runScriptAndInstallSsh(client3, "bootstrap", 3);
|
||||||
runScriptAndInstallSsh(client4, "bootstrap", 4);
|
runScriptAndInstallSsh(client4, "bootstrap", 4);
|
||||||
runScriptAndInstallSsh(client5, "bootstrap", 5);
|
runScriptAndInstallSsh(client5, "bootstrap", 5);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("144.175.1.1", 22)), eq("root"), aryEq(keyPair.get("private")
|
factory.create(eq(new IPSocket("144.175.1.1", 22)),
|
||||||
.getBytes()))).andReturn(client1).atLeastOnce();
|
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client1);
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("144.175.1.2", 22)), eq("root"), aryEq(keyPair.get("private")
|
factory.create(eq(new IPSocket("144.175.1.2", 22)),
|
||||||
.getBytes()))).andReturn(client2).atLeastOnce();
|
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client2);
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("144.175.1.3", 22)), eq("root"), aryEq(keyPair.get("private")
|
factory.create(eq(new IPSocket("144.175.1.3", 22)),
|
||||||
.getBytes()))).andReturn(client3).atLeastOnce();
|
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client3);
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("144.175.1.4", 22)), eq("root"), aryEq(keyPair.get("private")
|
factory.create(eq(new IPSocket("144.175.1.4", 22)),
|
||||||
.getBytes()))).andReturn(client4).atLeastOnce();
|
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client4);
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("155.175.1.5", 22)), eq("root"), aryEq(keyPair.get("private")
|
factory.create(eq(new IPSocket("144.175.1.5", 22)),
|
||||||
.getBytes()))).andReturn(client5).atLeastOnce();
|
eq(new Credentials("root", keyPair.get("private"))))).andReturn(client5);
|
||||||
|
|
||||||
helloAndJava(client2);
|
helloAndJava(client2);
|
||||||
helloAndJava(client3);
|
helloAndJava(client3);
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jclouds.ssh.jsch.predicates;
|
package org.jclouds.predicates;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
@ -29,7 +29,6 @@ import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.net.IPSocket;
|
import org.jclouds.net.IPSocket;
|
||||||
import org.jclouds.predicates.SocketOpen;
|
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
|
@ -58,6 +58,8 @@ import javax.annotation.Nullable;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
import org.jclouds.PropertiesBuilder;
|
import org.jclouds.PropertiesBuilder;
|
||||||
|
import org.jclouds.crypto.Pems;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.jclouds.rest.RestContextBuilder;
|
import org.jclouds.rest.RestContextBuilder;
|
||||||
|
@ -246,15 +248,14 @@ public class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode the given string with the given encoding, if possible. If the
|
* Encode the given string with the given encoding, if possible. If the encoding fails with
|
||||||
* encoding fails with {@link UnsupportedEncodingException}, log a warning
|
* {@link UnsupportedEncodingException}, log a warning and fall back to the system's default
|
||||||
* and fall back to the system's default encoding.
|
* encoding.
|
||||||
*
|
*
|
||||||
* @param str
|
* @param str
|
||||||
* what to encode
|
* what to encode
|
||||||
* @param charsetName
|
* @param charsetName
|
||||||
* the name of a supported {@link java.nio.charset.Charset
|
* the name of a supported {@link java.nio.charset.Charset </code>charset<code>}
|
||||||
* </code>charset<code>}
|
|
||||||
* @return properly encoded String.
|
* @return properly encoded String.
|
||||||
*/
|
*/
|
||||||
public static byte[] encodeString(String str, String charsetName) {
|
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
|
* Encode the given string with the UTF-8 encoding, the sane default. In the very unlikely event
|
||||||
* very unlikely event the encoding fails with
|
* the encoding fails with {@link UnsupportedEncodingException}, log a warning and fall back to
|
||||||
* {@link UnsupportedEncodingException}, log a warning and fall back to the
|
* the system's default encoding.
|
||||||
* system's default encoding.
|
|
||||||
*
|
*
|
||||||
* @param str
|
* @param str
|
||||||
* what to encode
|
* what to encode
|
||||||
|
@ -322,8 +322,7 @@ public class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will throw an exception if the argument is null or empty. Accepts a custom
|
* Will throw an exception if the argument is null or empty. Accepts a custom error message.
|
||||||
* error message.
|
|
||||||
*
|
*
|
||||||
* @param nullableString
|
* @param nullableString
|
||||||
* string to verify. Can be null or empty.
|
* 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
|
* Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses
|
||||||
* (supported-clouds). Uses rest.properties to populate the set.
|
* rest.properties to populate the set.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static Iterable<String> getSupportedProviders() {
|
public static Iterable<String> getSupportedProviders() {
|
||||||
|
@ -344,8 +343,8 @@ public class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a set of supported providers. Idea stolen from pallets
|
* Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses
|
||||||
* (supported-clouds). Uses rest.properties to populate the set.
|
* rest.properties to populate the set.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -468,4 +467,24 @@ public class Utils {
|
||||||
}
|
}
|
||||||
return modules;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import static org.testng.Assert.assertEquals;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@ -42,6 +43,33 @@ import com.google.inject.spi.Message;
|
||||||
@Test(groups = "unit", testName = "jclouds.UtilsTest")
|
@Test(groups = "unit", testName = "jclouds.UtilsTest")
|
||||||
public class 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() {
|
public void testGetCause() {
|
||||||
AuthorizationException aex = createMock(AuthorizationException.class);
|
AuthorizationException aex = createMock(AuthorizationException.class);
|
||||||
Message message = new Message(ImmutableList.of(), "test", aex);
|
Message message = new Message(ImmutableList.of(), "test", aex);
|
||||||
|
|
|
@ -59,11 +59,11 @@ import org.jclouds.gogrid.predicates.ServerLatestJobCompleted;
|
||||||
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
import org.jclouds.net.IPSocket;
|
import org.jclouds.net.IPSocket;
|
||||||
|
import org.jclouds.predicates.InetSocketAddressConnect;
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
import org.jclouds.ssh.jsch.JschSshClient;
|
import org.jclouds.ssh.jsch.JschSshClient;
|
||||||
import org.jclouds.ssh.jsch.predicates.InetSocketAddressConnect;
|
|
||||||
import org.testng.SkipException;
|
import org.testng.SkipException;
|
||||||
import org.testng.TestException;
|
import org.testng.TestException;
|
||||||
import org.testng.annotations.AfterTest;
|
import org.testng.annotations.AfterTest;
|
||||||
|
|
|
@ -117,7 +117,7 @@ public class RackspaceAuthenticationRestModule extends AbstractModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@CloudFiles
|
@CloudFiles
|
||||||
protected URI provideStorageUrl(AuthenticationResponse response) {
|
protected URI providestroageUrl(AuthenticationResponse response) {
|
||||||
return response.getStorageUrl();
|
return response.getStorageUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,7 +139,7 @@ public interface RimuHostingAsyncClient {
|
||||||
ListenableFuture<ServerInfo> restartServer(@PathParam("id") Long id);
|
ListenableFuture<ServerInfo> restartServer(@PathParam("id") Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see RimuHostingClient#destoryServer
|
* @see RimuHostingClient#destroyServer
|
||||||
*/
|
*/
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("/orders/order-{id}-blah/vps")
|
@Path("/orders/order-{id}-blah/vps")
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.jclouds.tools.ant.taskdefs.compute;
|
package org.jclouds.tools.ant.taskdefs.compute;
|
||||||
|
|
||||||
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
|
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.buildComputeMap;
|
||||||
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.createTemplateFromElement;
|
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.createTemplateFromElement;
|
||||||
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.ipOrEmptyString;
|
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.compute.predicates.NodePredicates;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.http.HttpUtils;
|
import org.jclouds.http.HttpUtils;
|
||||||
|
import org.jclouds.util.Utils;
|
||||||
|
|
||||||
import com.google.common.base.CaseFormat;
|
import com.google.common.base.CaseFormat;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
|
@ -212,7 +212,7 @@ public class ComputeTask extends Task {
|
||||||
getProject().setProperty(nodeElement.getIdproperty(), createdNode.getProviderId());
|
getProject().setProperty(nodeElement.getIdproperty(), createdNode.getProviderId());
|
||||||
if (nodeElement.getHostproperty() != null)
|
if (nodeElement.getHostproperty() != null)
|
||||||
getProject().setProperty(nodeElement.getHostproperty(), ipOrEmptyString(createdNode.getPublicAddresses()));
|
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);
|
getProject().setProperty(nodeElement.getPasswordproperty(), createdNode.getCredentials().credential);
|
||||||
if (nodeElement.getUsernameproperty() != null)
|
if (nodeElement.getUsernameproperty() != null)
|
||||||
getProject().setProperty(nodeElement.getUsernameproperty(), createdNode.getCredentials().identity);
|
getProject().setProperty(nodeElement.getUsernameproperty(), createdNode.getCredentials().identity);
|
||||||
|
|
|
@ -35,11 +35,11 @@ import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
import org.jclouds.net.IPSocket;
|
import org.jclouds.net.IPSocket;
|
||||||
|
import org.jclouds.predicates.InetSocketAddressConnect;
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
import org.jclouds.ssh.SshClient;
|
import org.jclouds.ssh.SshClient;
|
||||||
import org.jclouds.ssh.SshClient.Factory;
|
import org.jclouds.ssh.SshClient.Factory;
|
||||||
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
import org.jclouds.ssh.jsch.predicates.InetSocketAddressConnect;
|
|
||||||
import org.jclouds.vcloud.compute.options.VCloudTemplateOptions;
|
import org.jclouds.vcloud.compute.options.VCloudTemplateOptions;
|
||||||
import org.testng.annotations.BeforeGroups;
|
import org.testng.annotations.BeforeGroups;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
Loading…
Reference in New Issue