mirror of https://github.com/apache/jclouds.git
Issue 227: blockOnPort option when starting up a node
This commit is contained in:
parent
f3a9fabf44
commit
670c143cff
|
@ -28,11 +28,10 @@ import org.jclouds.compute.domain.Template;
|
|||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.internal.BaseComputeService;
|
||||
import org.jclouds.compute.options.RunScriptOptions;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
|
||||
import com.google.inject.ImplementedBy;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
|
||||
/**
|
||||
* Provides portable access to launching compute instances.
|
||||
|
|
|
@ -61,9 +61,9 @@ import org.jclouds.compute.strategy.ListNodesStrategy;
|
|||
import org.jclouds.compute.strategy.RebootNodeStrategy;
|
||||
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
|
||||
import org.jclouds.compute.util.ComputeUtils;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
|
@ -72,306 +72,309 @@ import com.google.common.collect.Iterables;
|
|||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class BaseComputeService implements ComputeService {
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
protected final ComputeServiceContext context;
|
||||
protected final Provider<Map<String, ? extends Image>> images;
|
||||
protected final Provider<Map<String, ? extends Size>> sizes;
|
||||
protected final Provider<Map<String, ? extends Location>> locations;
|
||||
protected final ListNodesStrategy listNodesStrategy;
|
||||
protected final GetNodeMetadataStrategy getNodeMetadataStrategy;
|
||||
protected final RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy;
|
||||
protected final RebootNodeStrategy rebootNodeStrategy;
|
||||
protected final DestroyNodeStrategy destroyNodeStrategy;
|
||||
protected final Provider<TemplateBuilder> templateBuilderProvider;
|
||||
protected final ComputeUtils utils;
|
||||
protected final ExecutorService executor;
|
||||
protected final ComputeServiceContext context;
|
||||
protected final Provider<Map<String, ? extends Image>> images;
|
||||
protected final Provider<Map<String, ? extends Size>> sizes;
|
||||
protected final Provider<Map<String, ? extends Location>> locations;
|
||||
protected final ListNodesStrategy listNodesStrategy;
|
||||
protected final GetNodeMetadataStrategy getNodeMetadataStrategy;
|
||||
protected final RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy;
|
||||
protected final RebootNodeStrategy rebootNodeStrategy;
|
||||
protected final DestroyNodeStrategy destroyNodeStrategy;
|
||||
protected final Provider<TemplateBuilder> templateBuilderProvider;
|
||||
protected final ComputeUtils utils;
|
||||
protected final ExecutorService executor;
|
||||
|
||||
private static class NodeMatchesTag implements Predicate<NodeMetadata> {
|
||||
private final String tag;
|
||||
private static class NodeMatchesTag implements Predicate<NodeMetadata> {
|
||||
private final String tag;
|
||||
|
||||
public NodeMatchesTag(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
public NodeMatchesTag(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(NodeMetadata from) {
|
||||
return from.getTag().equals(tag);
|
||||
}
|
||||
@Override
|
||||
public boolean apply(NodeMetadata from) {
|
||||
return from.getTag().equals(tag);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
public static Function<ComputeMetadata, String> METADATA_TO_ID = new Function<ComputeMetadata, String>() {
|
||||
@Override
|
||||
public String apply(ComputeMetadata from) {
|
||||
return from.getId();
|
||||
}
|
||||
};
|
||||
public static Function<ComputeMetadata, String> METADATA_TO_ID = new Function<ComputeMetadata, String>() {
|
||||
@Override
|
||||
public String apply(ComputeMetadata from) {
|
||||
return from.getId();
|
||||
}
|
||||
};
|
||||
|
||||
public static Function<ComputeMetadata, String> METADATA_TO_NAME = new Function<ComputeMetadata, String>() {
|
||||
@Override
|
||||
public String apply(ComputeMetadata from) {
|
||||
return from.getName();
|
||||
}
|
||||
};
|
||||
public static Function<ComputeMetadata, String> METADATA_TO_NAME = new Function<ComputeMetadata, String>() {
|
||||
@Override
|
||||
public String apply(ComputeMetadata from) {
|
||||
return from.getName();
|
||||
}
|
||||
};
|
||||
|
||||
@Inject
|
||||
protected BaseComputeService(ComputeServiceContext context,
|
||||
Provider<Map<String, ? extends Image>> images,
|
||||
Provider<Map<String, ? extends Size>> sizes,
|
||||
Provider<Map<String, ? extends Location>> locations,
|
||||
ListNodesStrategy listNodesStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
|
||||
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
|
||||
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
|
||||
Provider<TemplateBuilder> templateBuilderProvider, ComputeUtils utils,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||
this.context = checkNotNull(context, "context");
|
||||
this.images = checkNotNull(images, "images");
|
||||
this.sizes = checkNotNull(sizes, "sizes");
|
||||
this.locations = checkNotNull(locations, "locations");
|
||||
this.listNodesStrategy = checkNotNull(listNodesStrategy, "listNodesStrategy");
|
||||
this.getNodeMetadataStrategy = checkNotNull(getNodeMetadataStrategy,
|
||||
"getNodeMetadataStrategy");
|
||||
this.runNodesAndAddToSetStrategy = checkNotNull(runNodesAndAddToSetStrategy,
|
||||
"runNodesAndAddToSetStrategy");
|
||||
this.rebootNodeStrategy = checkNotNull(rebootNodeStrategy, "rebootNodeStrategy");
|
||||
this.destroyNodeStrategy = checkNotNull(destroyNodeStrategy, "destroyNodeStrategy");
|
||||
this.templateBuilderProvider = checkNotNull(templateBuilderProvider,
|
||||
"templateBuilderProvider");
|
||||
this.utils = checkNotNull(utils, "utils");
|
||||
this.executor = checkNotNull(executor, "executor");
|
||||
}
|
||||
@Inject
|
||||
protected BaseComputeService(ComputeServiceContext context,
|
||||
Provider<Map<String, ? extends Image>> images,
|
||||
Provider<Map<String, ? extends Size>> sizes,
|
||||
Provider<Map<String, ? extends Location>> locations,
|
||||
ListNodesStrategy listNodesStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
|
||||
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
|
||||
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
|
||||
Provider<TemplateBuilder> templateBuilderProvider, ComputeUtils utils,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||
this.context = checkNotNull(context, "context");
|
||||
this.images = checkNotNull(images, "images");
|
||||
this.sizes = checkNotNull(sizes, "sizes");
|
||||
this.locations = checkNotNull(locations, "locations");
|
||||
this.listNodesStrategy = checkNotNull(listNodesStrategy, "listNodesStrategy");
|
||||
this.getNodeMetadataStrategy = checkNotNull(getNodeMetadataStrategy,
|
||||
"getNodeMetadataStrategy");
|
||||
this.runNodesAndAddToSetStrategy = checkNotNull(runNodesAndAddToSetStrategy,
|
||||
"runNodesAndAddToSetStrategy");
|
||||
this.rebootNodeStrategy = checkNotNull(rebootNodeStrategy, "rebootNodeStrategy");
|
||||
this.destroyNodeStrategy = checkNotNull(destroyNodeStrategy, "destroyNodeStrategy");
|
||||
this.templateBuilderProvider = checkNotNull(templateBuilderProvider,
|
||||
"templateBuilderProvider");
|
||||
this.utils = checkNotNull(utils, "utils");
|
||||
this.executor = checkNotNull(executor, "executor");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComputeServiceContext getContext() {
|
||||
return context;
|
||||
}
|
||||
@Override
|
||||
public ComputeServiceContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends NodeMetadata> runNodesWithTag(final String tag, int count,
|
||||
final Template template) {
|
||||
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
|
||||
checkNotNull(template.getLocation(), "location");
|
||||
logger.debug(">> running %d node%s tag(%s) location(%s) image(%s) size(%s) options(%s)",
|
||||
count, count > 1 ? "s" : "", tag, template.getLocation().getId(), template
|
||||
@Override
|
||||
public Map<String, ? extends NodeMetadata> runNodesWithTag(final String tag, int count,
|
||||
final Template template) {
|
||||
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
|
||||
checkNotNull(template.getLocation(), "location");
|
||||
logger.debug(">> running %d node%s tag(%s) location(%s) image(%s) size(%s) options(%s)",
|
||||
count, count > 1 ? "s" : "", tag, template.getLocation().getId(), template
|
||||
.getImage().getId(), template.getSize().getId(), template.getOptions());
|
||||
final Set<NodeMetadata> nodes = Sets.newHashSet();
|
||||
Map<?, ListenableFuture<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count,
|
||||
template, nodes);
|
||||
Map<?, Exception> exceptions = awaitCompletion(responses, executor, null, logger,
|
||||
"starting nodes");
|
||||
if (exceptions.size() > 0 && template.getOptions().shouldDestroyOnError()) {
|
||||
ImmutableMap<?, ? extends ComputeMetadata> currentNodes = Maps.uniqueIndex(
|
||||
listNodesStrategy.execute(), METADATA_TO_ID);
|
||||
for (Entry<?, Exception> entry : exceptions.entrySet()) {
|
||||
logger.error(entry.getValue(), "<< error applying nodes(%s) [%s] destroying ", entry
|
||||
.getKey(), entry.getValue().getMessage());
|
||||
destroyNode(currentNodes.get(entry.getKey()));
|
||||
}
|
||||
}
|
||||
return Maps.uniqueIndex(nodes, METADATA_TO_ID);
|
||||
}
|
||||
final Set<NodeMetadata> nodes = Sets.newHashSet();
|
||||
Map<?, ListenableFuture<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count,
|
||||
template, nodes);
|
||||
Map<?, Exception> exceptions = awaitCompletion(responses, executor, null, logger,
|
||||
"starting nodes");
|
||||
if (exceptions.size() > 0 && template.getOptions().shouldDestroyOnError()) {
|
||||
ImmutableMap<?, ? extends ComputeMetadata> currentNodes = Maps.uniqueIndex(
|
||||
listNodesStrategy.execute(), METADATA_TO_ID);
|
||||
for (Entry<?, Exception> entry : exceptions.entrySet()) {
|
||||
logger.error(entry.getValue(), "<< error applying nodes(%s) [%s] destroying ", entry
|
||||
.getKey(), entry.getValue().getMessage());
|
||||
destroyNode(currentNodes.get(entry.getKey()));
|
||||
}
|
||||
}
|
||||
return Maps.uniqueIndex(nodes, METADATA_TO_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyNode(ComputeMetadata node) {
|
||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||
+ node.getType());
|
||||
checkNotNull(node.getId(), "node.id");
|
||||
logger.debug(">> destroying node(%s)", node.getId());
|
||||
boolean successful = destroyNodeStrategy.execute(node);
|
||||
logger.debug("<< destroyed node(%s) success(%s)", node.getId(), successful);
|
||||
}
|
||||
@Override
|
||||
public void destroyNode(ComputeMetadata node) {
|
||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||
+ node.getType());
|
||||
checkNotNull(node.getId(), "node.id");
|
||||
logger.debug(">> destroying node(%s)", node.getId());
|
||||
boolean successful = destroyNodeStrategy.execute(node);
|
||||
logger.debug("<< destroyed node(%s) success(%s)", node.getId(), successful);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyNodesWithTag(String tag) { // TODO parallel
|
||||
logger.debug(">> destroying nodes by tag(%s)", tag);
|
||||
Iterable<? extends NodeMetadata> nodesToDestroy = Iterables.filter(doGetNodesWithTag(tag)
|
||||
.values(), new Predicate<NodeMetadata>() {
|
||||
@Override
|
||||
public void destroyNodesWithTag(String tag) { // TODO parallel
|
||||
logger.debug(">> destroying nodes by tag(%s)", tag);
|
||||
Iterable<? extends NodeMetadata> nodesToDestroy = Iterables.filter(doGetNodesWithTag(tag)
|
||||
.values(), new Predicate<NodeMetadata>() {
|
||||
@Override
|
||||
public boolean apply(NodeMetadata input) {
|
||||
return input.getState() != NodeState.TERMINATED;
|
||||
|
||||
}
|
||||
});
|
||||
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
|
||||
for (final NodeMetadata node : nodesToDestroy) {
|
||||
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
|
||||
@Override
|
||||
public boolean apply(NodeMetadata input) {
|
||||
return input.getState() != NodeState.TERMINATED;
|
||||
|
||||
public Void call() throws Exception {
|
||||
destroyNode(node);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
|
||||
for (final NodeMetadata node : nodesToDestroy) {
|
||||
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
destroyNode(node);
|
||||
return null;
|
||||
}
|
||||
}), executor));
|
||||
}
|
||||
awaitCompletion(responses, executor, null, logger, "destroying nodes");
|
||||
logger.debug("<< destroyed");
|
||||
}
|
||||
}), executor));
|
||||
}
|
||||
awaitCompletion(responses, executor, null, logger, "destroying nodes");
|
||||
logger.debug("<< destroyed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends ComputeMetadata> getNodes() {
|
||||
logger.debug(">> listing servers");
|
||||
ImmutableMap<String, ? extends ComputeMetadata> map = Maps.uniqueIndex(listNodesStrategy
|
||||
.execute(), METADATA_TO_ID);
|
||||
logger.debug("<< list(%d)", map.size());
|
||||
return map;
|
||||
}
|
||||
@Override
|
||||
public Map<String, ? extends ComputeMetadata> getNodes() {
|
||||
logger.debug(">> listing servers");
|
||||
ImmutableMap<String, ? extends ComputeMetadata> map = Maps.uniqueIndex(listNodesStrategy
|
||||
.execute(), METADATA_TO_ID);
|
||||
logger.debug("<< list(%d)", map.size());
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the result of {@link ListNodesStrategy#execute} is a set of nodes, then return them.
|
||||
* Otherwise iteratively call {@link #getNodeMetadata}
|
||||
*/
|
||||
protected Map<String, ? extends NodeMetadata> doGetNodesWithTag(final String tag) {
|
||||
Iterable<? extends NodeMetadata> nodes = Iterables.filter(Iterables.transform(
|
||||
listNodesStrategy.execute(), new Function<ComputeMetadata, NodeMetadata>() {
|
||||
/**
|
||||
* If the result of {@link ListNodesStrategy#execute} is a set of nodes, then return them.
|
||||
* Otherwise iteratively call {@link #getNodeMetadata}
|
||||
*/
|
||||
protected Map<String, ? extends NodeMetadata> doGetNodesWithTag(final String tag) {
|
||||
Iterable<? extends NodeMetadata> nodes = Iterables.filter(Iterables.transform(
|
||||
listNodesStrategy.execute(), new Function<ComputeMetadata, NodeMetadata>() {
|
||||
|
||||
@Override
|
||||
public NodeMetadata apply(ComputeMetadata from) {
|
||||
return from instanceof NodeMetadata ? NodeMetadata.class.cast(from)
|
||||
: getNodeMetadata(from);
|
||||
}
|
||||
@Override
|
||||
public NodeMetadata apply(ComputeMetadata from) {
|
||||
return from instanceof NodeMetadata ? NodeMetadata.class.cast(from)
|
||||
: getNodeMetadata(from);
|
||||
}
|
||||
|
||||
}), new Predicate<NodeMetadata>() {
|
||||
}), new Predicate<NodeMetadata>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(NodeMetadata input) {
|
||||
return tag.equals(input.getTag());
|
||||
}
|
||||
|
||||
});
|
||||
return Maps.uniqueIndex(Iterables.filter(nodes, new NodeMatchesTag(tag)), METADATA_TO_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends NodeMetadata> getNodesWithTag(String tag) {
|
||||
logger.debug(">> listing nodes by tag(%s)", tag);
|
||||
Map<String, ? extends NodeMetadata> nodes = doGetNodesWithTag(tag);
|
||||
logger.debug("<< list(%d)", nodes.size());
|
||||
return nodes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends Size> getSizes() {
|
||||
return sizes.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends Image> getImages() {
|
||||
return images.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends Location> getLocations() {
|
||||
return locations.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemplateBuilder templateBuilder() {
|
||||
return templateBuilderProvider.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeMetadata getNodeMetadata(ComputeMetadata node) {
|
||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||
+ node.getType());
|
||||
return getNodeMetadataStrategy.execute(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rebootNode(ComputeMetadata node) {
|
||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||
+ node.getType());
|
||||
checkNotNull(node.getId(), "node.id");
|
||||
logger.debug(">> rebooting node(%s)", node.getId());
|
||||
boolean successful = rebootNodeStrategy.execute(node);
|
||||
logger.debug("<< rebooted node(%s) success(%s)", node.getId(), successful);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rebootNodesWithTag(String tag) { // TODO parallel
|
||||
logger.debug(">> rebooting nodes by tag(%s)", tag);
|
||||
Iterable<? extends NodeMetadata> nodesToReboot = Iterables.filter(doGetNodesWithTag(tag)
|
||||
.values(), new Predicate<NodeMetadata>() {
|
||||
@Override
|
||||
public boolean apply(NodeMetadata input) {
|
||||
return input.getState() != NodeState.TERMINATED;
|
||||
|
||||
}
|
||||
});
|
||||
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
|
||||
for (final NodeMetadata node : nodesToReboot) {
|
||||
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
|
||||
@Override
|
||||
public boolean apply(NodeMetadata input) {
|
||||
return tag.equals(input.getTag());
|
||||
public Void call() throws Exception {
|
||||
rebootNode(node);
|
||||
return null;
|
||||
}
|
||||
}), executor));
|
||||
}
|
||||
awaitCompletion(responses, executor, null, logger, "rebooting nodes");
|
||||
logger.debug("<< rebooted");
|
||||
}
|
||||
|
||||
});
|
||||
return Maps.uniqueIndex(Iterables.filter(nodes, new NodeMatchesTag(tag)), METADATA_TO_ID);
|
||||
}
|
||||
/**
|
||||
* @see #runScriptOnNodesWithTag(String, byte[], org.jclouds.compute.options.RunScriptOptions)
|
||||
*/
|
||||
public Map<String, ExecResponse> runScriptOnNodesWithTag(String tag, byte[] runScript) {
|
||||
return runScriptOnNodesWithTag(tag, runScript, RunScriptOptions.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends NodeMetadata> getNodesWithTag(String tag) {
|
||||
logger.debug(">> listing nodes by tag(%s)", tag);
|
||||
Map<String, ? extends NodeMetadata> nodes = doGetNodesWithTag(tag);
|
||||
logger.debug("<< list(%d)", nodes.size());
|
||||
return nodes;
|
||||
}
|
||||
/**
|
||||
* Run the script on all nodes with the specific tag.
|
||||
*
|
||||
* @param tag
|
||||
* tag to look up the nodes
|
||||
* @param runScript
|
||||
* script to run in byte format. If the script is a string, use
|
||||
* {@link String#getBytes()} to retrieve the bytes
|
||||
* @param options
|
||||
* nullable options to how to run the script, whether to override credentials
|
||||
* @return map with node identifiers and corresponding responses
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, ExecResponse> runScriptOnNodesWithTag(String tag, byte[] runScript,
|
||||
@Nullable RunScriptOptions options) {
|
||||
checkNotEmpty(tag, "Tag must be provided");
|
||||
checkNotNull(runScript,
|
||||
"The script (represented by bytes array - use \"script\".getBytes() must be provided");
|
||||
if (options == null)
|
||||
options = RunScriptOptions.NONE;
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends Size> getSizes() {
|
||||
return sizes.get();
|
||||
}
|
||||
Map<String, ? extends NodeMetadata> nodes = getNodesWithTag(tag);
|
||||
Map<String, ExecResponse> responses = Maps.newHashMap();
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends Image> getImages() {
|
||||
return images.get();
|
||||
}
|
||||
for (NodeMetadata node : nodes.values()) {
|
||||
if (NodeState.RUNNING != node.getState())
|
||||
continue; // make sure the node is active
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends Location> getLocations() {
|
||||
return locations.get();
|
||||
}
|
||||
if (options.getOverrideCredentials() != null) {
|
||||
// override the credentials with provided to this method
|
||||
node = ComputeUtils.installNewCredentials(node, options.getOverrideCredentials());
|
||||
} else {
|
||||
// don't override
|
||||
checkNotNull(node.getCredentials(),
|
||||
"If the default credentials need to be used, they can't be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TemplateBuilder templateBuilder() {
|
||||
return templateBuilderProvider.get();
|
||||
}
|
||||
ComputeUtils.SshCallable<?> callable;
|
||||
if (options.isRunAsRoot())
|
||||
callable = utils.runScriptOnNode(node, "computeserv.sh", runScript);
|
||||
else
|
||||
callable = utils.runScriptOnNodeAsDefaultUser(node, "computeserv.sh", runScript);
|
||||
|
||||
@Override
|
||||
public NodeMetadata getNodeMetadata(ComputeMetadata node) {
|
||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||
+ node.getType());
|
||||
return getNodeMetadataStrategy.execute(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rebootNode(ComputeMetadata node) {
|
||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
||||
+ node.getType());
|
||||
checkNotNull(node.getId(), "node.id");
|
||||
logger.debug(">> rebooting node(%s)", node.getId());
|
||||
boolean successful = rebootNodeStrategy.execute(node);
|
||||
logger.debug("<< rebooted node(%s) success(%s)", node.getId(), successful);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rebootNodesWithTag(String tag) { // TODO parallel
|
||||
logger.debug(">> rebooting nodes by tag(%s)", tag);
|
||||
Iterable<? extends NodeMetadata> nodesToReboot = Iterables.filter(doGetNodesWithTag(tag)
|
||||
.values(), new Predicate<NodeMetadata>() {
|
||||
@Override
|
||||
public boolean apply(NodeMetadata input) {
|
||||
return input.getState() != NodeState.TERMINATED;
|
||||
|
||||
}
|
||||
});
|
||||
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
|
||||
for (final NodeMetadata node : nodesToReboot) {
|
||||
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
rebootNode(node);
|
||||
return null;
|
||||
}
|
||||
}), executor));
|
||||
}
|
||||
awaitCompletion(responses, executor, null, logger, "rebooting nodes");
|
||||
logger.debug("<< rebooted");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #runScriptOnNodesWithTag(String, byte[],
|
||||
* org.jclouds.compute.options.RunScriptOptions)
|
||||
*/
|
||||
public Map<String, ExecResponse> runScriptOnNodesWithTag(String tag,
|
||||
byte[] runScript) {
|
||||
return runScriptOnNodesWithTag(tag, runScript, RunScriptOptions.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the script on all nodes with the specific tag.
|
||||
*
|
||||
* @param tag tag to look up the nodes
|
||||
* @param runScript script to run in byte format. If the script is a string, use
|
||||
* {@link String#getBytes()} to retrieve the bytes
|
||||
* @param options nullable options to how to run the script, whether to override credentials
|
||||
* @return map with node identifiers and corresponding responses
|
||||
*/
|
||||
public Map<String, ExecResponse> runScriptOnNodesWithTag(String tag, byte[] runScript, @Nullable RunScriptOptions options) {
|
||||
checkNotEmpty(tag, "Tag must be provided");
|
||||
checkNotNull(runScript,
|
||||
"The script (represented by bytes array - use \"script\".getBytes() must be provided");
|
||||
if(options == null) options = RunScriptOptions.NONE;
|
||||
|
||||
Map<String, ? extends NodeMetadata> nodes = getNodesWithTag(tag);
|
||||
Map<String, ExecResponse> responses = Maps.newHashMap();
|
||||
|
||||
for(NodeMetadata node : nodes.values()) {
|
||||
if(NodeState.RUNNING != node.getState()) continue; //make sure the node is active
|
||||
|
||||
if(options.getOverrideCredentials() != null) {
|
||||
//override the credentials with provided to this method
|
||||
node = ComputeUtils.installNewCredentials(node, options.getOverrideCredentials());
|
||||
} else {
|
||||
//don't override
|
||||
checkNotNull(node.getCredentials(), "If the default credentials need to be used, they can't be null");
|
||||
}
|
||||
|
||||
ComputeUtils.SshCallable<?> callable;
|
||||
if(options.isRunAsRoot())
|
||||
callable = utils.runScriptOnNode(node, "computeserv.sh", runScript);
|
||||
else
|
||||
callable = utils.runScriptOnNodeAsDefaultUser(node, "computeserv.sh", runScript);
|
||||
|
||||
Map<ComputeUtils.SshCallable<?>, ?> scriptRunResults = utils.runCallablesOnNode(node,
|
||||
Sets.newHashSet(callable),
|
||||
null);
|
||||
responses.put(node.getId(),
|
||||
(ExecResponse) scriptRunResults.get(callable));
|
||||
}
|
||||
return responses;
|
||||
}
|
||||
Map<ComputeUtils.SshCallable<?>, ?> scriptRunResults = utils.runCallablesOnNode(node, Sets
|
||||
.newHashSet(callable), null);
|
||||
responses.put(node.getId(), (ExecResponse) scriptRunResults.get(callable));
|
||||
}
|
||||
return responses;
|
||||
}
|
||||
}
|
|
@ -22,69 +22,65 @@ import org.jclouds.domain.Credentials;
|
|||
|
||||
/**
|
||||
* Enables additional options for running a script.
|
||||
*
|
||||
*
|
||||
* @author Oleksiy Yarmula
|
||||
*/
|
||||
public class RunScriptOptions {
|
||||
|
||||
/**
|
||||
* Default options. The default settings are:
|
||||
* <ul>
|
||||
* <li>override the credentials with ones supplied in
|
||||
* call to {@link org.jclouds.compute.ComputeService#runScriptOnNodesWithTag}</li>
|
||||
* <li>run the script as root (versus running with current privileges)</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static final RunScriptOptions NONE = new RunScriptOptions();
|
||||
/**
|
||||
* Default options. The default settings are:
|
||||
* <ul>
|
||||
* <li>override the credentials with ones supplied in call to
|
||||
* {@link org.jclouds.compute.ComputeService#runScriptOnNodesWithTag}</li>
|
||||
* <li>run the script as root (versus running with current privileges)</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static final RunScriptOptions NONE = new RunScriptOptions();
|
||||
|
||||
private Credentials overridingCredentials;
|
||||
private boolean runAsRoot = true;
|
||||
private Credentials overridingCredentials;
|
||||
private boolean runAsRoot = true;
|
||||
|
||||
private void withOverridingCredentials(Credentials overridingCredentials) {
|
||||
this.overridingCredentials = overridingCredentials;
|
||||
}
|
||||
public RunScriptOptions withOverridingCredentials(Credentials overridingCredentials) {
|
||||
this.overridingCredentials = overridingCredentials;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void runAsRoot(boolean runAsRoot) {
|
||||
this.runAsRoot = runAsRoot;
|
||||
}
|
||||
public RunScriptOptions runAsRoot(boolean runAsRoot) {
|
||||
this.runAsRoot = runAsRoot;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to override the credentials with ones supplied in
|
||||
* call to {@link org.jclouds.compute.ComputeService#runScriptOnNodesWithTag}.
|
||||
* By default, true.
|
||||
* @return value
|
||||
*/
|
||||
public Credentials getOverrideCredentials() {
|
||||
return overridingCredentials;
|
||||
}
|
||||
/**
|
||||
* Whether to override the credentials with ones supplied in call to
|
||||
* {@link org.jclouds.compute.ComputeService#runScriptOnNodesWithTag}. By default, true.
|
||||
*
|
||||
* @return value
|
||||
*/
|
||||
public Credentials getOverrideCredentials() {
|
||||
return overridingCredentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to run the script as root (or run with current privileges).
|
||||
* By default, true.
|
||||
* @return value
|
||||
*/
|
||||
public boolean isRunAsRoot() {
|
||||
return runAsRoot;
|
||||
}
|
||||
/**
|
||||
* Whether to run the script as root (or run with current privileges). By default, true.
|
||||
*
|
||||
* @return value
|
||||
*/
|
||||
public boolean isRunAsRoot() {
|
||||
return runAsRoot;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private RunScriptOptions options;
|
||||
public static class Builder {
|
||||
|
||||
public Builder overrideCredentials(Credentials credentials) {
|
||||
if(options == null) options = new RunScriptOptions();
|
||||
options.withOverridingCredentials(credentials);
|
||||
return this;
|
||||
}
|
||||
public static RunScriptOptions overrideCredentialsWith(Credentials credentials) {
|
||||
RunScriptOptions options = new RunScriptOptions();
|
||||
return options.withOverridingCredentials(credentials);
|
||||
}
|
||||
|
||||
public Builder runAsRoot(boolean value) {
|
||||
if(options == null) options = new RunScriptOptions();
|
||||
options.runAsRoot(value);
|
||||
return this;
|
||||
}
|
||||
public static RunScriptOptions runAsRoot(boolean value) {
|
||||
RunScriptOptions options = new RunScriptOptions();
|
||||
return options.runAsRoot(value);
|
||||
}
|
||||
|
||||
public RunScriptOptions build() {
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -34,6 +34,18 @@ public class TemplateOptions {
|
|||
|
||||
private boolean destroyOnError;
|
||||
|
||||
private int port = -1;
|
||||
|
||||
private int seconds = -1;
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public int getSeconds() {
|
||||
return seconds;
|
||||
}
|
||||
|
||||
public int[] getInboundPorts() {
|
||||
return inboundPorts;
|
||||
}
|
||||
|
@ -54,6 +66,17 @@ public class TemplateOptions {
|
|||
return destroyOnError;
|
||||
}
|
||||
|
||||
/**
|
||||
* When the node is started, wait until the following port is active
|
||||
*/
|
||||
public TemplateOptions blockOnPort(int port, int seconds) {
|
||||
checkArgument(port > 0 && port < 65536, "port must be a positive integer < 65535");
|
||||
checkArgument(seconds > 0, "seconds must be a positive integer");
|
||||
this.port = port;
|
||||
this.seconds = seconds;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is an error applying options after creating the node, destroy it.
|
||||
*/
|
||||
|
@ -98,6 +121,8 @@ public class TemplateOptions {
|
|||
* Opens the set of ports to public access.
|
||||
*/
|
||||
public TemplateOptions inboundPorts(int... ports) {
|
||||
for (int port : ports)
|
||||
checkArgument(port > 0 && port < 65536, "port must be a positive integer < 65535");
|
||||
this.inboundPorts = ports;
|
||||
return this;
|
||||
}
|
||||
|
@ -119,6 +144,14 @@ public class TemplateOptions {
|
|||
return options.inboundPorts(ports);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#port
|
||||
*/
|
||||
public static TemplateOptions blockOnPort(int port, int seconds) {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
return options.blockOnPort(port, seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see TemplateOptions#runScript
|
||||
*/
|
||||
|
@ -149,6 +182,7 @@ public class TemplateOptions {
|
|||
public String toString() {
|
||||
return "TemplateOptions [inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey="
|
||||
+ (privateKey != null) + ", publicKey=" + (publicKey != null) + ", runScript="
|
||||
+ (script != null) + ", destroyOnError=" + destroyOnError + "]";
|
||||
+ (script != null) + ", destroyOnError=" + destroyOnError + ", port:seconds=" + port
|
||||
+ ":" + seconds + "]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.Map;
|
|||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.Resource;
|
||||
|
@ -46,6 +47,8 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
|
|||
import org.jclouds.concurrent.ConcurrentUtils;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.predicates.RetryablePredicate;
|
||||
import org.jclouds.predicates.SocketOpen;
|
||||
import org.jclouds.scriptbuilder.InitBuilder;
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
|
@ -62,304 +65,330 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ComputeUtils {
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
@Inject(optional = true)
|
||||
private SshClient.Factory sshFactory;
|
||||
protected final Predicate<SshClient> runScriptNotRunning;
|
||||
private final Predicate<InetSocketAddress> socketTester;
|
||||
private final ExecutorService executor;
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
@Inject(optional = true)
|
||||
private SshClient.Factory sshFactory;
|
||||
protected final Predicate<SshClient> runScriptNotRunning;
|
||||
private final Predicate<InetSocketAddress> socketTester;
|
||||
private final ExecutorService executor;
|
||||
|
||||
@Inject
|
||||
public ComputeUtils(Predicate<InetSocketAddress> socketTester,
|
||||
@Named("NOT_RUNNING") Predicate<SshClient> runScriptNotRunning,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||
this.socketTester = socketTester;
|
||||
this.runScriptNotRunning = runScriptNotRunning;
|
||||
this.executor = executor;
|
||||
}
|
||||
private int sshRetries = 3;
|
||||
|
||||
public static Iterable<? extends ComputeMetadata> filterByName(
|
||||
@Inject
|
||||
public ComputeUtils(Predicate<InetSocketAddress> socketTester,
|
||||
@Named("NOT_RUNNING") Predicate<SshClient> runScriptNotRunning,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||
this.socketTester = socketTester;
|
||||
this.runScriptNotRunning = runScriptNotRunning;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
public static Iterable<? extends ComputeMetadata> filterByName(
|
||||
Iterable<? extends ComputeMetadata> nodes, final String name) {
|
||||
return Iterables.filter(nodes, new Predicate<ComputeMetadata>() {
|
||||
@Override
|
||||
public boolean apply(ComputeMetadata input) {
|
||||
return input.getName().equalsIgnoreCase(name);
|
||||
return Iterables.filter(nodes, new Predicate<ComputeMetadata>() {
|
||||
@Override
|
||||
public boolean apply(ComputeMetadata input) {
|
||||
return input.getName().equalsIgnoreCase(name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static final Comparator<InetAddress> ADDRESS_COMPARATOR = new Comparator<InetAddress>() {
|
||||
|
||||
@Override
|
||||
public int compare(InetAddress o1, InetAddress o2) {
|
||||
return (o1 == o2) ? 0 : o1.getHostAddress().compareTo(o2.getHostAddress());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public void runOptionsOnNode(NodeMetadata node, TemplateOptions options) {
|
||||
List<SshCallable<?>> callables = Lists.newArrayList();
|
||||
if (options.getRunScript() != null) {
|
||||
callables.add(runScriptOnNode(node, "runscript.sh", options.getRunScript()));
|
||||
}
|
||||
if (options.getPublicKey() != null) {
|
||||
callables.add(authorizeKeyOnNode(node, options.getPublicKey()));
|
||||
}
|
||||
|
||||
// changing the key "MUST" come last or else the other commands may fail.
|
||||
if (callables.size() > 0 || options.getPrivateKey() != null) {
|
||||
runCallablesOnNode(node, callables, options.getPrivateKey() != null ? installKeyOnNode(
|
||||
node, options.getPrivateKey()) : null);
|
||||
}
|
||||
|
||||
if (options.getPort() > 0) {
|
||||
blockUntilPortIsListeningOnPublicIp(options.getPort(), options.getSeconds(), Iterables
|
||||
.get(node.getPublicAddresses(), 0));
|
||||
}
|
||||
}
|
||||
|
||||
private void blockUntilPortIsListeningOnPublicIp(int port, int seconds, InetAddress inetAddress) {
|
||||
logger.debug(">> blocking on port %s:%d for %d seconds", inetAddress, port, seconds);
|
||||
RetryablePredicate<InetSocketAddress> tester = new RetryablePredicate<InetSocketAddress>(
|
||||
new SocketOpen(), seconds, 1, TimeUnit.SECONDS);
|
||||
InetSocketAddress socket = new InetSocketAddress(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", seconds, inetAddress, port);
|
||||
}
|
||||
|
||||
public InstallRSAPrivateKey installKeyOnNode(NodeMetadata node, String privateKey) {
|
||||
return new InstallRSAPrivateKey(node, privateKey);
|
||||
}
|
||||
|
||||
public AuthorizeRSAPublicKey authorizeKeyOnNode(NodeMetadata node, String publicKey) {
|
||||
return new AuthorizeRSAPublicKey(node, publicKey);
|
||||
}
|
||||
|
||||
public RunScriptOnNode runScriptOnNode(NodeMetadata node, String scriptName, byte[] script) {
|
||||
return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script);
|
||||
}
|
||||
|
||||
public RunScriptOnNode runScriptOnNodeAsDefaultUser(NodeMetadata node, String scriptName,
|
||||
byte[] script) {
|
||||
return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script, false);
|
||||
}
|
||||
|
||||
public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node,
|
||||
Iterable<? extends SshCallable<?>> parallel, @Nullable SshCallable<?> last) {
|
||||
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured");
|
||||
checkNotNull(node.getCredentials().key, "credentials.key for node " + node.getId());
|
||||
|
||||
InetSocketAddress socket = new InetSocketAddress(Iterables.get(node.getPublicAddresses(), 0),
|
||||
22);
|
||||
socketTester.apply(socket);
|
||||
SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().account,
|
||||
node.getCredentials().key.getBytes()) : sshFactory.create(socket, node
|
||||
.getCredentials().account, node.getCredentials().key);
|
||||
for (int i = 0; i < sshRetries; i++) {
|
||||
try {
|
||||
ssh.connect();
|
||||
Map<SshCallable<?>, ListenableFuture<?>> responses = Maps.newHashMap();
|
||||
|
||||
for (SshCallable<?> callable : parallel) {
|
||||
callable.setConnection(ssh, logger);
|
||||
responses.put(callable, ConcurrentUtils.makeListenable(executor.submit(callable),
|
||||
executor));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static final Comparator<InetAddress> ADDRESS_COMPARATOR = new Comparator<InetAddress>() {
|
||||
|
||||
@Override
|
||||
public int compare(InetAddress o1, InetAddress o2) {
|
||||
return (o1 == o2) ? 0 : o1.getHostAddress().compareTo(o2.getHostAddress());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public void runOptionsOnNode(NodeMetadata node, TemplateOptions options) {
|
||||
List<SshCallable<?>> callables = Lists.newArrayList();
|
||||
if (options.getRunScript() != null) {
|
||||
callables.add(runScriptOnNode(node, "runscript.sh", options.getRunScript()));
|
||||
}
|
||||
if (options.getPublicKey() != null) {
|
||||
callables.add(authorizeKeyOnNode(node, options.getPublicKey()));
|
||||
}
|
||||
// changing the key "MUST" come last or else the other commands may fail.
|
||||
if (callables.size() > 0 || options.getPrivateKey() != null) {
|
||||
runCallablesOnNode(node, callables, options.getPrivateKey() != null ? installKeyOnNode(
|
||||
node, options.getPrivateKey()) : null);
|
||||
}
|
||||
}
|
||||
|
||||
public InstallRSAPrivateKey installKeyOnNode(NodeMetadata node, String privateKey) {
|
||||
return new InstallRSAPrivateKey(node, privateKey);
|
||||
}
|
||||
|
||||
public AuthorizeRSAPublicKey authorizeKeyOnNode(NodeMetadata node, String publicKey) {
|
||||
return new AuthorizeRSAPublicKey(node, publicKey);
|
||||
}
|
||||
|
||||
public RunScriptOnNode runScriptOnNode(NodeMetadata node, String scriptName, byte[] script) {
|
||||
return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script);
|
||||
}
|
||||
|
||||
public RunScriptOnNode runScriptOnNodeAsDefaultUser(NodeMetadata node, String scriptName, byte[] script) {
|
||||
return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script, false);
|
||||
}
|
||||
|
||||
public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node, Iterable<? extends SshCallable<?>> parallel,
|
||||
@Nullable SshCallable<?> last) {
|
||||
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured");
|
||||
|
||||
InetSocketAddress socket = new InetSocketAddress(Iterables.get(node.getPublicAddresses(), 0),
|
||||
22);
|
||||
socketTester.apply(socket);
|
||||
SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().account,
|
||||
node.getCredentials().key.getBytes()) : sshFactory.create(socket, node
|
||||
.getCredentials().account, node.getCredentials().key);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
try {
|
||||
ssh.connect();
|
||||
Map<SshCallable<?>, ListenableFuture<?>> responses = Maps.newHashMap();
|
||||
|
||||
for (SshCallable<?> callable : parallel) {
|
||||
callable.setConnection(ssh, logger);
|
||||
responses.put(callable, ConcurrentUtils.makeListenable(executor.submit(callable),
|
||||
executor));
|
||||
}
|
||||
|
||||
Map<SshCallable<?>, Exception> exceptions = awaitCompletion(responses, executor, null,
|
||||
logger, "ssh");
|
||||
if (exceptions.size() > 0)
|
||||
throw new RuntimeException(String.format("error invoking callables on host %s: %s",
|
||||
socket, exceptions));
|
||||
if (last != null) {
|
||||
last.setConnection(ssh, logger);
|
||||
try {
|
||||
last.call();
|
||||
} catch (Exception e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
return transform(responses);
|
||||
} catch (RuntimeException from) {
|
||||
if (Iterables.size(Iterables.filter(Throwables.getCausalChain(from),
|
||||
ConnectException.class)) >= 1// auth fail sometimes happens in EC2
|
||||
|| Throwables.getRootCause(from).getMessage().indexOf("Auth fail") != -1
|
||||
|| Throwables.getRootCause(from).getMessage().indexOf("invalid privatekey") != -1) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
throw Throwables.propagate(from);
|
||||
} finally {
|
||||
if (ssh != null)
|
||||
ssh.disconnect();
|
||||
Map<SshCallable<?>, Exception> exceptions = awaitCompletion(responses, executor, null,
|
||||
logger, "ssh");
|
||||
if (exceptions.size() > 0)
|
||||
throw new RuntimeException(String.format("error invoking callables on host %s: %s",
|
||||
socket, exceptions));
|
||||
if (last != null) {
|
||||
last.setConnection(ssh, logger);
|
||||
try {
|
||||
last.call();
|
||||
} catch (Exception e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new RuntimeException(String.format("Couldn't connect to node %s and run the script", node.getId()));
|
||||
}
|
||||
return transform(responses);
|
||||
} catch (RuntimeException from) {
|
||||
if (i + 1 == sshRetries)
|
||||
throw Throwables.propagate(from);
|
||||
if (Iterables.size(Iterables.filter(Throwables.getCausalChain(from),
|
||||
ConnectException.class)) >= 1// auth fail sometimes happens in EC2
|
||||
|| Throwables.getRootCause(from).getMessage().indexOf("Auth fail") != -1
|
||||
|| Throwables.getRootCause(from).getMessage().indexOf("invalid privatekey") != -1) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
throw Throwables.propagate(from);
|
||||
} finally {
|
||||
if (ssh != null)
|
||||
ssh.disconnect();
|
||||
}
|
||||
}
|
||||
throw new RuntimeException(String.format("Couldn't connect to node %s and run the script",
|
||||
node.getId()));
|
||||
}
|
||||
|
||||
public <T> Map<SshCallable<?>, T> transform(Map<SshCallable<?>, ListenableFuture<?>> responses) {
|
||||
Map<SshCallable<?>, T> actualResponses = Maps.newHashMap();
|
||||
for(Map.Entry<SshCallable<?>, ListenableFuture<?>> entry : responses.entrySet()) {
|
||||
try {
|
||||
public <T> Map<SshCallable<?>, T> transform(Map<SshCallable<?>, ListenableFuture<?>> responses) {
|
||||
Map<SshCallable<?>, T> actualResponses = Maps.newHashMap();
|
||||
for (Map.Entry<SshCallable<?>, ListenableFuture<?>> entry : responses.entrySet()) {
|
||||
try {
|
||||
actualResponses.put(entry.getKey(), (T) entry.getValue().get());
|
||||
} catch(InterruptedException e) {
|
||||
throw Throwables.propagate(e);
|
||||
} catch(ExecutionException e) {
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
return actualResponses;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw Throwables.propagate(e);
|
||||
} catch (ExecutionException e) {
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
return actualResponses;
|
||||
}
|
||||
|
||||
public static interface SshCallable<T> extends Callable<T> {
|
||||
void setConnection(SshClient ssh, Logger logger);
|
||||
}
|
||||
public static interface SshCallable<T> extends Callable<T> {
|
||||
void setConnection(SshClient ssh, Logger logger);
|
||||
}
|
||||
|
||||
public static class RunScriptOnNode implements SshCallable<ExecResponse> {
|
||||
private SshClient ssh;
|
||||
protected final Predicate<SshClient> runScriptNotRunning;
|
||||
private final NodeMetadata node;
|
||||
private final String scriptName;
|
||||
private final byte[] script;
|
||||
private final boolean runAsRoot;
|
||||
private Logger logger = Logger.NULL;
|
||||
public static class RunScriptOnNode implements SshCallable<ExecResponse> {
|
||||
private SshClient ssh;
|
||||
protected final Predicate<SshClient> runScriptNotRunning;
|
||||
private final NodeMetadata node;
|
||||
private final String scriptName;
|
||||
private final byte[] script;
|
||||
private final boolean runAsRoot;
|
||||
private Logger logger = Logger.NULL;
|
||||
|
||||
RunScriptOnNode(@Named("NOT_RUNNING") Predicate<SshClient> runScriptNotRunning,
|
||||
NodeMetadata node, String scriptName, byte[] script) {
|
||||
this.runScriptNotRunning = runScriptNotRunning;
|
||||
this.node = checkNotNull(node, "node");
|
||||
this.scriptName = checkNotNull(scriptName, "scriptName");
|
||||
this.script = new InitBuilder("runscript", "/tmp", "/tmp", ImmutableMap
|
||||
.<String, String> of(), Iterables.toArray(Splitter.on("\n").split(
|
||||
new String(checkNotNull(script, "script"))), String.class)).build(OsFamily.UNIX)
|
||||
.getBytes();
|
||||
this.runAsRoot = true;
|
||||
}
|
||||
RunScriptOnNode(@Named("NOT_RUNNING") Predicate<SshClient> runScriptNotRunning,
|
||||
NodeMetadata node, String scriptName, byte[] script) {
|
||||
this.runScriptNotRunning = runScriptNotRunning;
|
||||
this.node = checkNotNull(node, "node");
|
||||
this.scriptName = checkNotNull(scriptName, "scriptName");
|
||||
this.script = new InitBuilder("runscript", "/tmp", "/tmp", ImmutableMap
|
||||
.<String, String> of(), Iterables.toArray(Splitter.on("\n").split(
|
||||
new String(checkNotNull(script, "script"))), String.class)).build(OsFamily.UNIX)
|
||||
.getBytes();
|
||||
this.runAsRoot = true;
|
||||
}
|
||||
|
||||
RunScriptOnNode(@Named("NOT_RUNNING") Predicate<SshClient> runScriptNotRunning,
|
||||
NodeMetadata node, String scriptName, byte[] script, boolean runAsRoot) {
|
||||
this.runScriptNotRunning = runScriptNotRunning;
|
||||
this.node = checkNotNull(node, "node");
|
||||
this.scriptName = checkNotNull(scriptName, "scriptName");
|
||||
this.script = new InitBuilder("runscript", "/tmp", "/tmp", ImmutableMap
|
||||
.<String, String> of(), Iterables.toArray(Splitter.on("\n").split(
|
||||
new String(checkNotNull(script, "script"))), String.class)).build(OsFamily.UNIX)
|
||||
.getBytes();
|
||||
this.runAsRoot = runAsRoot;
|
||||
}
|
||||
RunScriptOnNode(@Named("NOT_RUNNING") Predicate<SshClient> runScriptNotRunning,
|
||||
NodeMetadata node, String scriptName, byte[] script, boolean runAsRoot) {
|
||||
this.runScriptNotRunning = runScriptNotRunning;
|
||||
this.node = checkNotNull(node, "node");
|
||||
this.scriptName = checkNotNull(scriptName, "scriptName");
|
||||
this.script = new InitBuilder("runscript", "/tmp", "/tmp", ImmutableMap
|
||||
.<String, String> of(), Iterables.toArray(Splitter.on("\n").split(
|
||||
new String(checkNotNull(script, "script"))), String.class)).build(OsFamily.UNIX)
|
||||
.getBytes();
|
||||
this.runAsRoot = runAsRoot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecResponse call() throws Exception {
|
||||
ssh.put(scriptName, new ByteArrayInputStream(script));
|
||||
ExecResponse returnVal = ssh.exec("chmod 755 " + scriptName);
|
||||
returnVal = ssh.exec("./" + scriptName + " init");
|
||||
@Override
|
||||
public ExecResponse call() throws Exception {
|
||||
ssh.put(scriptName, new ByteArrayInputStream(script));
|
||||
ExecResponse returnVal = ssh.exec("chmod 755 " + scriptName);
|
||||
returnVal = ssh.exec("./" + scriptName + " init");
|
||||
|
||||
if(runAsRoot) returnVal = runScriptAsRoot();
|
||||
else returnVal = runScriptAsDefaultUser();
|
||||
runScriptNotRunning.apply(ssh);
|
||||
logger.debug("<< complete(%d)", returnVal.getExitCode());
|
||||
return returnVal;
|
||||
}
|
||||
if (runAsRoot)
|
||||
returnVal = runScriptAsRoot();
|
||||
else
|
||||
returnVal = runScriptAsDefaultUser();
|
||||
runScriptNotRunning.apply(ssh);
|
||||
logger.debug("<< complete(%d)", returnVal.getExitCode());
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConnection(SshClient ssh, Logger logger) {
|
||||
this.logger = checkNotNull(logger, "logger");
|
||||
this.ssh = checkNotNull(ssh, "ssh");
|
||||
}
|
||||
@Override
|
||||
public void setConnection(SshClient ssh, Logger logger) {
|
||||
this.logger = checkNotNull(logger, "logger");
|
||||
this.ssh = checkNotNull(ssh, "ssh");
|
||||
}
|
||||
|
||||
private ExecResponse runScriptAsRoot() {
|
||||
if (node.getCredentials().account.equals("root")) {
|
||||
logger.debug(">> running %s as %s@%s", scriptName, node.getCredentials().account,
|
||||
Iterables.get(node.getPublicAddresses(), 0).getHostAddress());
|
||||
return ssh.exec("./" + scriptName + " start");
|
||||
} else if (isKeyAuth(node)) {
|
||||
logger.debug(">> running sudo %s as %s@%s", scriptName, node.getCredentials().account,
|
||||
Iterables.get(node.getPublicAddresses(), 0).getHostAddress());
|
||||
return ssh.exec("sudo ./" + scriptName + " start");
|
||||
} else {
|
||||
logger.debug(">> running sudo -S %s as %s@%s", scriptName,
|
||||
node.getCredentials().account, Iterables.get(node.getPublicAddresses(), 0)
|
||||
.getHostAddress());
|
||||
return ssh.exec(String.format("echo %s|sudo -S ./%s", node.getCredentials().key,
|
||||
scriptName + " start"));
|
||||
}
|
||||
}
|
||||
private ExecResponse runScriptAsRoot() {
|
||||
if (node.getCredentials().account.equals("root")) {
|
||||
logger.debug(">> running %s as %s@%s", scriptName, node.getCredentials().account,
|
||||
Iterables.get(node.getPublicAddresses(), 0).getHostAddress());
|
||||
return ssh.exec("./" + scriptName + " start");
|
||||
} else if (isKeyAuth(node)) {
|
||||
logger.debug(">> running sudo %s as %s@%s", scriptName, node.getCredentials().account,
|
||||
Iterables.get(node.getPublicAddresses(), 0).getHostAddress());
|
||||
return ssh.exec("sudo ./" + scriptName + " start");
|
||||
} else {
|
||||
logger.debug(">> running sudo -S %s as %s@%s", scriptName,
|
||||
node.getCredentials().account, Iterables.get(node.getPublicAddresses(), 0)
|
||||
.getHostAddress());
|
||||
return ssh.exec(String.format("echo %s|sudo -S ./%s", node.getCredentials().key,
|
||||
scriptName + " start"));
|
||||
}
|
||||
}
|
||||
|
||||
private ExecResponse runScriptAsDefaultUser() {
|
||||
logger.debug(">> running script %s as %s@%s", scriptName,
|
||||
node.getCredentials().account, Iterables.get(node.getPublicAddresses(), 0)
|
||||
.getHostAddress());
|
||||
return ssh.exec(String.format("./%s", scriptName + " start"));
|
||||
}
|
||||
}
|
||||
private ExecResponse runScriptAsDefaultUser() {
|
||||
logger.debug(">> running script %s as %s@%s", scriptName, node.getCredentials().account,
|
||||
Iterables.get(node.getPublicAddresses(), 0).getHostAddress());
|
||||
return ssh.exec(String.format("./%s", scriptName + " start"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class InstallRSAPrivateKey implements SshCallable<ExecResponse> {
|
||||
private SshClient ssh;
|
||||
private final NodeMetadata node;
|
||||
private final String privateKey;
|
||||
public static class InstallRSAPrivateKey implements SshCallable<ExecResponse> {
|
||||
private SshClient ssh;
|
||||
private final NodeMetadata node;
|
||||
private final String privateKey;
|
||||
|
||||
private Logger logger = Logger.NULL;
|
||||
private Logger logger = Logger.NULL;
|
||||
|
||||
InstallRSAPrivateKey(NodeMetadata node, String privateKey) {
|
||||
this.node = checkNotNull(node, "node");
|
||||
this.privateKey = checkNotNull(privateKey, "privateKey");
|
||||
}
|
||||
InstallRSAPrivateKey(NodeMetadata node, String privateKey) {
|
||||
this.node = checkNotNull(node, "node");
|
||||
this.privateKey = checkNotNull(privateKey, "privateKey");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecResponse call() throws Exception {
|
||||
ssh.exec("mkdir .ssh");
|
||||
ssh.put(".ssh/id_rsa", new ByteArrayInputStream(privateKey.getBytes()));
|
||||
logger.debug(">> installing rsa key for %s@%s", node.getCredentials().account, Iterables
|
||||
.get(node.getPublicAddresses(), 0).getHostAddress());
|
||||
return ssh.exec("chmod 600 .ssh/id_rsa");
|
||||
}
|
||||
@Override
|
||||
public ExecResponse call() throws Exception {
|
||||
ssh.exec("mkdir .ssh");
|
||||
ssh.put(".ssh/id_rsa", new ByteArrayInputStream(privateKey.getBytes()));
|
||||
logger.debug(">> installing rsa key for %s@%s", node.getCredentials().account, Iterables
|
||||
.get(node.getPublicAddresses(), 0).getHostAddress());
|
||||
return ssh.exec("chmod 600 .ssh/id_rsa");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConnection(SshClient ssh, Logger logger) {
|
||||
this.logger = checkNotNull(logger, "logger");
|
||||
this.ssh = checkNotNull(ssh, "ssh");
|
||||
}
|
||||
@Override
|
||||
public void setConnection(SshClient ssh, Logger logger) {
|
||||
this.logger = checkNotNull(logger, "logger");
|
||||
this.ssh = checkNotNull(ssh, "ssh");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class AuthorizeRSAPublicKey implements SshCallable<ExecResponse> {
|
||||
private SshClient ssh;
|
||||
private final NodeMetadata node;
|
||||
private final String publicKey;
|
||||
public static class AuthorizeRSAPublicKey implements SshCallable<ExecResponse> {
|
||||
private SshClient ssh;
|
||||
private final NodeMetadata node;
|
||||
private final String publicKey;
|
||||
|
||||
private Logger logger = Logger.NULL;
|
||||
private Logger logger = Logger.NULL;
|
||||
|
||||
AuthorizeRSAPublicKey(NodeMetadata node, String publicKey) {
|
||||
this.node = checkNotNull(node, "node");
|
||||
this.publicKey = checkNotNull(publicKey, "publicKey");
|
||||
}
|
||||
AuthorizeRSAPublicKey(NodeMetadata node, String publicKey) {
|
||||
this.node = checkNotNull(node, "node");
|
||||
this.publicKey = checkNotNull(publicKey, "publicKey");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecResponse call() throws Exception {
|
||||
ssh.exec("mkdir .ssh");
|
||||
ssh.put(".ssh/id_rsa.pub", new ByteArrayInputStream(publicKey.getBytes()));
|
||||
logger.debug(">> authorizing rsa public key for %s@%s", node.getCredentials().account,
|
||||
Iterables.get(node.getPublicAddresses(), 0).getHostAddress());
|
||||
ExecResponse returnVal = ssh.exec("cat .ssh/id_rsa.pub >> .ssh/authorized_keys");
|
||||
returnVal = ssh.exec("chmod 600 .ssh/authorized_keys");
|
||||
logger.debug("<< complete(%d)", returnVal.getExitCode());
|
||||
return returnVal;
|
||||
}
|
||||
@Override
|
||||
public ExecResponse call() throws Exception {
|
||||
ssh.exec("mkdir .ssh");
|
||||
ssh.put(".ssh/id_rsa.pub", new ByteArrayInputStream(publicKey.getBytes()));
|
||||
logger.debug(">> authorizing rsa public key for %s@%s", node.getCredentials().account,
|
||||
Iterables.get(node.getPublicAddresses(), 0).getHostAddress());
|
||||
ExecResponse returnVal = ssh.exec("cat .ssh/id_rsa.pub >> .ssh/authorized_keys");
|
||||
returnVal = ssh.exec("chmod 600 .ssh/authorized_keys");
|
||||
logger.debug("<< complete(%d)", returnVal.getExitCode());
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConnection(SshClient ssh, Logger logger) {
|
||||
this.logger = checkNotNull(logger, "logger");
|
||||
this.ssh = checkNotNull(ssh, "ssh");
|
||||
}
|
||||
@Override
|
||||
public void setConnection(SshClient ssh, Logger logger) {
|
||||
this.logger = checkNotNull(logger, "logger");
|
||||
this.ssh = checkNotNull(ssh, "ssh");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isKeyAuth(NodeMetadata createdNode) {
|
||||
return createdNode.getCredentials().key != null
|
||||
&& createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----");
|
||||
}
|
||||
public static boolean isKeyAuth(NodeMetadata createdNode) {
|
||||
return createdNode.getCredentials().key != null
|
||||
&& createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----");
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the instances of {@link NodeMetadata} (immutable)
|
||||
* and {@link Credentials} (immutable), returns a new instance of {@link NodeMetadata}
|
||||
* that has new credentials
|
||||
*/
|
||||
public static NodeMetadata installNewCredentials(NodeMetadata node, Credentials newCredentials) {
|
||||
return new NodeMetadataImpl(node.getId(), node.getName(), node.getLocationId(), node.getUri(),
|
||||
node.getUserMetadata(), node.getTag(), node.getState(), node. getPublicAddresses(),
|
||||
node.getPrivateAddresses(), node.getExtra(), newCredentials);
|
||||
}
|
||||
/**
|
||||
* Given the instances of {@link NodeMetadata} (immutable) and {@link Credentials} (immutable),
|
||||
* returns a new instance of {@link NodeMetadata} that has new credentials
|
||||
*/
|
||||
public static NodeMetadata installNewCredentials(NodeMetadata node, Credentials newCredentials) {
|
||||
return new NodeMetadataImpl(node.getId(), node.getName(), node.getLocationId(),
|
||||
node.getUri(), node.getUserMetadata(), node.getTag(), node.getState(), node
|
||||
.getPublicAddresses(), node.getPrivateAddresses(), node.getExtra(),
|
||||
newCredentials);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 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.options;
|
||||
|
||||
import static org.jclouds.compute.options.TemplateOptions.Builder.authorizePublicKey;
|
||||
import static org.jclouds.compute.options.TemplateOptions.Builder.blockOnPort;
|
||||
import static org.jclouds.compute.options.TemplateOptions.Builder.inboundPorts;
|
||||
import static org.jclouds.compute.options.TemplateOptions.Builder.installPrivateKey;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests possible uses of TemplateOptions and TemplateOptions.Builder.*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class TemplateOptionsTest {
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testinstallPrivateKeyBadFormat() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
options.installPrivateKey("whompy");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testinstallPrivateKey() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
options.installPrivateKey("-----BEGIN RSA PRIVATE KEY-----");
|
||||
assertEquals(options.getPrivateKey(), "-----BEGIN RSA PRIVATE KEY-----");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullinstallPrivateKey() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
assertEquals(options.getPrivateKey(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testinstallPrivateKeyStatic() {
|
||||
TemplateOptions options = installPrivateKey("-----BEGIN RSA PRIVATE KEY-----");
|
||||
assertEquals(options.getPrivateKey(), "-----BEGIN RSA PRIVATE KEY-----");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testinstallPrivateKeyNPE() {
|
||||
installPrivateKey(null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testauthorizePublicKeyBadFormat() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
options.authorizePublicKey("whompy");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testauthorizePublicKey() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
options.authorizePublicKey("ssh-rsa");
|
||||
assertEquals(options.getPublicKey(), "ssh-rsa");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullauthorizePublicKey() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
assertEquals(options.getPublicKey(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testauthorizePublicKeyStatic() {
|
||||
TemplateOptions options = authorizePublicKey("ssh-rsa");
|
||||
assertEquals(options.getPublicKey(), "ssh-rsa");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testauthorizePublicKeyNPE() {
|
||||
authorizePublicKey(null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testblockOnPortBadFormat() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
options.blockOnPort(-1, -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testblockOnPort() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
options.blockOnPort(22, 30);
|
||||
assertEquals(options.getPort(), 22);
|
||||
assertEquals(options.getSeconds(), 30);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullblockOnPort() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
assertEquals(options.getPort(), -1);
|
||||
assertEquals(options.getSeconds(), -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testblockOnPortStatic() {
|
||||
TemplateOptions options = blockOnPort(22, 30);
|
||||
assertEquals(options.getPort(), 22);
|
||||
assertEquals(options.getSeconds(), 30);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testinboundPortsBadFormat() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
options.inboundPorts(-1, -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testinboundPorts() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
options.inboundPorts(22, 30);
|
||||
assertEquals(options.getInboundPorts()[0], 22);
|
||||
assertEquals(options.getInboundPorts()[1], 30);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultOpen22() {
|
||||
TemplateOptions options = new TemplateOptions();
|
||||
assertEquals(options.getInboundPorts()[0], 22);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testinboundPortsStatic() {
|
||||
TemplateOptions options = inboundPorts(22, 30);
|
||||
assertEquals(options.getInboundPorts()[0], 22);
|
||||
assertEquals(options.getInboundPorts()[1], 30);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue