mirror of https://github.com/apache/jclouds.git
refactored runScript logic
This commit is contained in:
parent
c34b973af3
commit
0455e0f509
|
@ -28,6 +28,7 @@ import java.util.Set;
|
|||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.collect.Memoized;
|
||||
|
@ -37,6 +38,7 @@ import org.jclouds.compute.domain.NodeMetadata;
|
|||
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||
import org.jclouds.compute.domain.NodeState;
|
||||
import org.jclouds.compute.domain.OperatingSystem;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.domain.LocationScope;
|
||||
|
@ -55,15 +57,16 @@ import com.google.common.collect.Iterables;
|
|||
*/
|
||||
@Singleton
|
||||
public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
protected final Supplier<Location> location;
|
||||
protected final Map<String, Credentials> credentialStore;
|
||||
protected final Map<ServerStatus, NodeState> serverToNodeState;
|
||||
protected final Supplier<Set<? extends Image>> images;
|
||||
protected final Supplier<Set<? extends Hardware>> hardwares;
|
||||
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private static class FindImageForServer implements Predicate<Image> {
|
||||
private final Server instance;
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ package org.jclouds.ec2.compute;
|
|||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -49,8 +49,8 @@ import org.jclouds.compute.strategy.ListNodesStrategy;
|
|||
import org.jclouds.compute.strategy.RebootNodeStrategy;
|
||||
import org.jclouds.compute.strategy.ResumeNodeStrategy;
|
||||
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
|
||||
import org.jclouds.compute.strategy.RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
|
||||
import org.jclouds.compute.strategy.SuspendNodeStrategy;
|
||||
import org.jclouds.compute.util.ComputeUtils;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.ec2.EC2Client;
|
||||
|
@ -81,23 +81,24 @@ public class EC2ComputeService extends BaseComputeService {
|
|||
|
||||
@Inject
|
||||
protected EC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
|
||||
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
|
||||
GetNodeMetadataStrategy getNodeMetadataStrategy, RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
|
||||
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
|
||||
ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
|
||||
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
|
||||
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
|
||||
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
|
||||
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended, ComputeUtils utils, Timeouts timeouts,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
|
||||
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
|
||||
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap,
|
||||
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted) {
|
||||
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
|
||||
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
|
||||
GetNodeMetadataStrategy getNodeMetadataStrategy, RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
|
||||
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
|
||||
ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
|
||||
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
|
||||
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
|
||||
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
|
||||
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
|
||||
RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory statementRunner, Timeouts timeouts,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
|
||||
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
|
||||
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap,
|
||||
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted) {
|
||||
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
|
||||
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
|
||||
templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended, utils,
|
||||
timeouts, executor);
|
||||
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy,
|
||||
stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated,
|
||||
nodeSuspended, statementRunner, timeouts, executor);
|
||||
this.ec2Client = ec2Client;
|
||||
this.credentialsMap = credentialsMap;
|
||||
this.securityGroupMap = securityGroupMap;
|
||||
|
@ -115,7 +116,7 @@ public class EC2ComputeService extends BaseComputeService {
|
|||
try {
|
||||
ec2Client.getPlacementGroupServices().deletePlacementGroupInRegion(region, group);
|
||||
checkState(placementGroupDeleted.apply(new PlacementGroup(region, group, "cluster", State.PENDING)),
|
||||
String.format("placementGroup region(%s) name(%s) failed to delete", region, group));
|
||||
String.format("placementGroup region(%s) name(%s) failed to delete", region, group));
|
||||
placementGroupMap.remove(new RegionAndName(region, group));
|
||||
logger.debug("<< deleted placementGroup(%s)", group);
|
||||
} catch (AWSResponseException e) {
|
||||
|
@ -129,8 +130,8 @@ public class EC2ComputeService extends BaseComputeService {
|
|||
} catch (UnsupportedOperationException e) {
|
||||
} catch (HttpResponseException e) {
|
||||
// Eucalyptus does not support placement groups yet.
|
||||
if (!(e.getResponse().getStatusCode() == 400 && context.getProviderSpecificContext().getProvider()
|
||||
.equals("eucalyptus")))
|
||||
if (!(e.getResponse().getStatusCode() == 400 && context.getProviderSpecificContext().getProvider().equals(
|
||||
"eucalyptus")))
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import javax.inject.Named;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.util.AWSUtils;
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
|
@ -52,6 +53,7 @@ import com.google.common.base.Function;
|
|||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* creates futures that correlate to
|
||||
|
@ -68,7 +70,7 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
|
|||
@VisibleForTesting
|
||||
final EC2Client client;
|
||||
@VisibleForTesting
|
||||
final CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
|
||||
final CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize;
|
||||
@VisibleForTesting
|
||||
final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
|
||||
@VisibleForTesting
|
||||
|
@ -80,14 +82,14 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
|
|||
@Inject
|
||||
EC2RunNodesAndAddToSetStrategy(
|
||||
EC2Client client,
|
||||
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
|
||||
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||
@Named("PRESENT") Predicate<RunningInstance> instancePresent,
|
||||
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
||||
Function<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
|
||||
ComputeUtils utils) {
|
||||
this.client = client;
|
||||
this.instancePresent = instancePresent;
|
||||
this.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
|
||||
this.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize;
|
||||
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
|
||||
this.instanceToCredentials = instanceToCredentials;
|
||||
this.credentialStore = credentialStore;
|
||||
|
@ -96,7 +98,7 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
|
|||
|
||||
@Override
|
||||
public Map<?, Future<Void>> execute(String tag, int count, Template template, Set<NodeMetadata> goodNodes,
|
||||
Map<NodeMetadata, Exception> badNodes) {
|
||||
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
|
||||
|
||||
Reservation<? extends RunningInstance> reservation = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(tag,
|
||||
count, template);
|
||||
|
@ -111,8 +113,8 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
|
|||
populateCredentials(reservation);
|
||||
}
|
||||
|
||||
return utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(template.getOptions(), transform(
|
||||
reservation, runningInstanceToNodeMetadata), goodNodes, badNodes);
|
||||
return utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(template.getOptions(), transform(reservation,
|
||||
runningInstanceToNodeMetadata), goodNodes, badNodes, customizationResponses);
|
||||
}
|
||||
|
||||
protected void populateCredentials(Reservation<? extends RunningInstance> reservation) {
|
||||
|
@ -129,7 +131,7 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
|
|||
String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation());
|
||||
String zone = getZoneFromLocationOrNull(template.getLocation());
|
||||
|
||||
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.execute(region,
|
||||
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize.execute(region,
|
||||
tag, template);
|
||||
|
||||
if (EC2TemplateOptions.class.cast(template.getOptions()).isMonitoringEnabled())
|
||||
|
|
|
@ -29,8 +29,6 @@ import java.util.concurrent.ExecutorService;
|
|||
|
||||
import javax.inject.Provider;
|
||||
|
||||
import org.jclouds.ec2.EC2Client;
|
||||
import org.jclouds.ec2.services.PlacementGroupClient;
|
||||
import org.jclouds.compute.ComputeServiceContext;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
|
||||
import org.jclouds.compute.strategy.DestroyNodeStrategy;
|
||||
|
@ -39,8 +37,10 @@ import org.jclouds.compute.strategy.ListNodesStrategy;
|
|||
import org.jclouds.compute.strategy.RebootNodeStrategy;
|
||||
import org.jclouds.compute.strategy.ResumeNodeStrategy;
|
||||
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
|
||||
import org.jclouds.compute.strategy.RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
|
||||
import org.jclouds.compute.strategy.SuspendNodeStrategy;
|
||||
import org.jclouds.compute.util.ComputeUtils;
|
||||
import org.jclouds.ec2.EC2Client;
|
||||
import org.jclouds.ec2.services.PlacementGroupClient;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
@ -52,25 +52,26 @@ import com.google.common.base.Supplier;
|
|||
@Test(groups = "unit")
|
||||
public class EC2ComputeServiceTest {
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
@SuppressWarnings( { "unchecked" })
|
||||
public void testUnsupportedOperationOkForPlacementGroups() {
|
||||
EC2Client client = createMock(EC2Client.class);
|
||||
EC2ComputeService service = new EC2ComputeService(createMock(ComputeServiceContext.class), createMock(Map.class),
|
||||
createMock(Supplier.class), createMock(Supplier.class), createMock(Supplier.class),
|
||||
createMock(ListNodesStrategy.class), createMock(GetNodeMetadataStrategy.class),
|
||||
createMock(RunNodesAndAddToSetStrategy.class), createMock(RebootNodeStrategy.class),
|
||||
createMock(DestroyNodeStrategy.class), createMock(ResumeNodeStrategy.class),
|
||||
createMock(SuspendNodeStrategy.class), createMock(Provider.class), createMock(Provider.class),
|
||||
createMock(Predicate.class), createMock(Predicate.class), createMock(Predicate.class),
|
||||
createMock(ComputeUtils.class), createMock(Timeouts.class), createMock(ExecutorService.class), client,
|
||||
createMock(Map.class), createMock(Map.class), createMock(Map.class), createMock(Predicate.class));
|
||||
createMock(Supplier.class), createMock(Supplier.class), createMock(Supplier.class),
|
||||
createMock(ListNodesStrategy.class), createMock(GetNodeMetadataStrategy.class),
|
||||
createMock(RunNodesAndAddToSetStrategy.class), createMock(RebootNodeStrategy.class),
|
||||
createMock(DestroyNodeStrategy.class), createMock(ResumeNodeStrategy.class),
|
||||
createMock(SuspendNodeStrategy.class), createMock(Provider.class), createMock(Provider.class),
|
||||
createMock(Predicate.class), createMock(Predicate.class), createMock(Predicate.class),
|
||||
createMock(RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory.class),
|
||||
createMock(Timeouts.class), createMock(ExecutorService.class), client, createMock(Map.class),
|
||||
createMock(Map.class), createMock(Map.class), createMock(Predicate.class));
|
||||
|
||||
PlacementGroupClient placementClient = createMock(PlacementGroupClient.class);
|
||||
|
||||
// setup expectations
|
||||
expect(client.getPlacementGroupServices()).andReturn(placementClient).atLeastOnce();
|
||||
expect(placementClient.describePlacementGroupsInRegion("us-west-1", "jclouds#tag#us-west-1")).andThrow(
|
||||
new UnsupportedOperationException());
|
||||
new UnsupportedOperationException());
|
||||
|
||||
// replay mocks
|
||||
replay(client);
|
||||
|
|
|
@ -100,15 +100,15 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
|||
replay(strategy);
|
||||
|
||||
// run
|
||||
RunInstancesOptions runOptions = strategy.execute(region, tag, template);
|
||||
assertEquals(runOptions.buildQueryParameters(), ImmutableMultimap.<String, String> of());
|
||||
RunInstancesOptions customize = strategy.execute(region, tag, template);
|
||||
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(
|
||||
runOptions.buildFormParameters().entries(),
|
||||
customize.buildFormParameters().entries(),
|
||||
ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SecurityGroup.1",
|
||||
generatedGroup, "KeyName", systemGeneratedKeyPairName).entries());
|
||||
assertEquals(runOptions.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(runOptions.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(runOptions.buildStringPayload(), null);
|
||||
assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(customize.buildStringPayload(), null);
|
||||
|
||||
// verify mocks
|
||||
verify(options);
|
||||
|
@ -159,16 +159,16 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
|||
replay(strategy);
|
||||
|
||||
// run
|
||||
RunInstancesOptions runOptions = strategy.execute(region, tag, template);
|
||||
assertEquals(runOptions.buildQueryParameters(), ImmutableMultimap.<String, String> of());
|
||||
RunInstancesOptions customize = strategy.execute(region, tag, template);
|
||||
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(
|
||||
runOptions.buildFormParameters().entries(),
|
||||
customize.buildFormParameters().entries(),
|
||||
ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SecurityGroup.1",
|
||||
generatedGroup, "KeyName", systemGeneratedKeyPairName, "Placement.GroupName", generatedGroup)
|
||||
.entries());
|
||||
assertEquals(runOptions.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(runOptions.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(runOptions.buildStringPayload(), null);
|
||||
assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(customize.buildStringPayload(), null);
|
||||
|
||||
// verify mocks
|
||||
verify(options);
|
||||
|
@ -219,16 +219,16 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
|||
replay(strategy);
|
||||
|
||||
// run
|
||||
RunInstancesOptions runOptions = strategy.execute(region, tag, template);
|
||||
assertEquals(runOptions.buildQueryParameters(), ImmutableMultimap.<String, String> of());
|
||||
RunInstancesOptions customize = strategy.execute(region, tag, template);
|
||||
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(
|
||||
runOptions.buildFormParameters().entries(),
|
||||
customize.buildFormParameters().entries(),
|
||||
ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SecurityGroup.1",
|
||||
generatedGroup, "KeyName", systemGeneratedKeyPairName, "Placement.GroupName", generatedGroup)
|
||||
.entries());
|
||||
assertEquals(runOptions.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(runOptions.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(runOptions.buildStringPayload(), null);
|
||||
assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(customize.buildStringPayload(), null);
|
||||
|
||||
// verify mocks
|
||||
verify(options);
|
||||
|
@ -274,15 +274,15 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
|||
replay(strategy);
|
||||
|
||||
// run
|
||||
RunInstancesOptions runOptions = strategy.execute(region, tag, template);
|
||||
assertEquals(runOptions.buildQueryParameters(), ImmutableMultimap.<String, String> of());
|
||||
RunInstancesOptions customize = strategy.execute(region, tag, template);
|
||||
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(
|
||||
runOptions.buildFormParameters().entries(),
|
||||
customize.buildFormParameters().entries(),
|
||||
ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SubnetId", "1", "KeyName",
|
||||
systemGeneratedKeyPairName).entries());
|
||||
assertEquals(runOptions.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(runOptions.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(runOptions.buildStringPayload(), null);
|
||||
assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(customize.buildStringPayload(), null);
|
||||
|
||||
// verify mocks
|
||||
verify(options);
|
||||
|
@ -331,15 +331,15 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
|||
replay(strategy);
|
||||
|
||||
// run
|
||||
RunInstancesOptions runOptions = strategy.execute(region, tag, template);
|
||||
assertEquals(runOptions.buildQueryParameters(), ImmutableMultimap.<String, String> of());
|
||||
RunInstancesOptions customize = strategy.execute(region, tag, template);
|
||||
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(
|
||||
runOptions.buildFormParameters().entries(),
|
||||
customize.buildFormParameters().entries(),
|
||||
ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SecurityGroup.1", "group",
|
||||
"KeyName", systemGeneratedKeyPairName, "UserData", Base64.encodeBytes("hello".getBytes())).entries());
|
||||
assertEquals(runOptions.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(runOptions.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(runOptions.buildStringPayload(), null);
|
||||
assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(customize.buildStringPayload(), null);
|
||||
|
||||
// verify mocks
|
||||
verify(options);
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.Set;
|
|||
|
||||
import org.easymock.IArgumentMatcher;
|
||||
import org.jclouds.aws.domain.Region;
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
|
@ -54,6 +55,7 @@ import com.google.common.base.Function;
|
|||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
|
@ -102,21 +104,20 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
|||
InstanceClient instanceClient = createMock(InstanceClient.class);
|
||||
RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class);
|
||||
RunningInstance instance = createMock(RunningInstance.class);
|
||||
Reservation<? extends RunningInstance> reservation = new Reservation<RunningInstance>(region,
|
||||
ImmutableSet.<String> of(), ImmutableSet.<RunningInstance> of(instance), "ownerId", "requesterId",
|
||||
"reservationId");
|
||||
Reservation<? extends RunningInstance> reservation = new Reservation<RunningInstance>(region, ImmutableSet
|
||||
.<String> of(), ImmutableSet.<RunningInstance> of(instance), "ownerId", "requesterId", "reservationId");
|
||||
NodeMetadata nodeMetadata = createMock(NodeMetadata.class);
|
||||
|
||||
// setup expectations
|
||||
expect(strategy.client.getInstanceServices()).andReturn(instanceClient).atLeastOnce();
|
||||
expect(
|
||||
strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.execute(region, input.tag,
|
||||
input.template)).andReturn(ec2Options);
|
||||
strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize.execute(region, input.tag,
|
||||
input.template)).andReturn(ec2Options);
|
||||
expect(input.template.getLocation()).andReturn(input.location).atLeastOnce();
|
||||
expect(input.template.getImage()).andReturn(input.image).atLeastOnce();
|
||||
expect(input.image.getProviderId()).andReturn(imageId).atLeastOnce();
|
||||
expect(instanceClient.runInstancesInRegion(region, zone, imageId, 1, input.count, ec2Options)).andReturn(
|
||||
(Reservation) reservation);
|
||||
(Reservation) reservation);
|
||||
expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce();
|
||||
// simulate a lazy credentials fetch
|
||||
Credentials creds = new Credentials("foo", "bar");
|
||||
|
@ -130,8 +131,9 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
|||
|
||||
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(nodeMetadata);
|
||||
expect(
|
||||
strategy.utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(eq(input.options),
|
||||
containsNodeMetadata(nodeMetadata), eq(input.nodes), eq(input.badNodes))).andReturn(null);
|
||||
strategy.utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(eq(input.options),
|
||||
containsNodeMetadata(nodeMetadata), eq(input.nodes), eq(input.badNodes),
|
||||
eq(input.customization))).andReturn(null);
|
||||
|
||||
// replay mocks
|
||||
replay(instanceClient);
|
||||
|
@ -142,7 +144,7 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
|||
replayStrategy(strategy);
|
||||
|
||||
// run
|
||||
strategy.execute(input.tag, input.count, input.template, input.nodes, input.badNodes);
|
||||
strategy.execute(input.tag, input.count, input.template, input.nodes, input.badNodes, input.customization);
|
||||
|
||||
// verify mocks
|
||||
verify(instanceClient);
|
||||
|
@ -154,9 +156,9 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
|||
}
|
||||
|
||||
private static final Location REGION_AP_SOUTHEAST_1 = new LocationImpl(LocationScope.REGION, Region.AP_SOUTHEAST_1,
|
||||
Region.AP_SOUTHEAST_1, new LocationImpl(LocationScope.PROVIDER, "ec2", "ec2", null));
|
||||
Region.AP_SOUTHEAST_1, new LocationImpl(LocationScope.PROVIDER, "ec2", "ec2", null));
|
||||
private static final Location ZONE_AP_SOUTHEAST_1A = new LocationImpl(LocationScope.ZONE,
|
||||
AvailabilityZone.AP_SOUTHEAST_1A, AvailabilityZone.AP_SOUTHEAST_1A, REGION_AP_SOUTHEAST_1);
|
||||
AvailabilityZone.AP_SOUTHEAST_1A, AvailabilityZone.AP_SOUTHEAST_1A, REGION_AP_SOUTHEAST_1);
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -166,6 +168,7 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
|||
Template template = createMock(Template.class);
|
||||
Set<NodeMetadata> nodes = createMock(Set.class);
|
||||
Map<NodeMetadata, Exception> badNodes = createMock(Map.class);
|
||||
Multimap<NodeMetadata, CustomizationResponse> customization = createMock(Multimap.class);
|
||||
Hardware hardware = createMock(Hardware.class);
|
||||
Image image = createMock(Image.class);
|
||||
final Location location;
|
||||
|
@ -181,6 +184,7 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
|||
replay(image);
|
||||
replay(nodes);
|
||||
replay(badNodes);
|
||||
replay(customization);
|
||||
replay(options);
|
||||
}
|
||||
|
||||
|
@ -190,12 +194,13 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
|||
verify(image);
|
||||
verify(nodes);
|
||||
verify(badNodes);
|
||||
verify(customization);
|
||||
verify(options);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyStrategy(EC2RunNodesAndAddToSetStrategy strategy) {
|
||||
verify(strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions);
|
||||
verify(strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize);
|
||||
verify(strategy.client);
|
||||
verify(strategy.instancePresent);
|
||||
verify(strategy.runningInstanceToNodeMetadata);
|
||||
|
@ -207,18 +212,18 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
private EC2RunNodesAndAddToSetStrategy setupStrategy() {
|
||||
EC2Client client = createMock(EC2Client.class);
|
||||
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions = createMock(CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class);
|
||||
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createMock(CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class);
|
||||
Predicate<RunningInstance> instanceStateRunning = createMock(Predicate.class);
|
||||
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class);
|
||||
Function<RunningInstance, Credentials> instanceToCredentials = createMock(Function.class);
|
||||
Map<String, Credentials> credentialStore = createMock(Map.class);
|
||||
ComputeUtils utils = createMock(ComputeUtils.class);
|
||||
return new EC2RunNodesAndAddToSetStrategy(client, createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
|
||||
instanceStateRunning, runningInstanceToNodeMetadata, instanceToCredentials, credentialStore, utils);
|
||||
return new EC2RunNodesAndAddToSetStrategy(client, createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||
instanceStateRunning, runningInstanceToNodeMetadata, instanceToCredentials, credentialStore, utils);
|
||||
}
|
||||
|
||||
private void replayStrategy(EC2RunNodesAndAddToSetStrategy strategy) {
|
||||
replay(strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions);
|
||||
replay(strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize);
|
||||
replay(strategy.client);
|
||||
replay(strategy.instancePresent);
|
||||
replay(strategy.runningInstanceToNodeMetadata);
|
||||
|
|
|
@ -45,8 +45,8 @@ import org.jclouds.compute.strategy.ListNodesStrategy;
|
|||
import org.jclouds.compute.strategy.RebootNodeStrategy;
|
||||
import org.jclouds.compute.strategy.ResumeNodeStrategy;
|
||||
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
|
||||
import org.jclouds.compute.strategy.RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
|
||||
import org.jclouds.compute.strategy.SuspendNodeStrategy;
|
||||
import org.jclouds.compute.util.ComputeUtils;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.vcloud.terremark.compute.domain.KeyPairCredentials;
|
||||
|
@ -75,13 +75,14 @@ public class TerremarkVCloudComputeService extends BaseComputeService {
|
|||
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
|
||||
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
|
||||
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
|
||||
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended, ComputeUtils utils, Timeouts timeouts,
|
||||
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
|
||||
RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory statementRunner, Timeouts timeouts,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, CleanupOrphanKeys cleanupOrphanKeys,
|
||||
ConcurrentMap<OrgAndName, KeyPairCredentials> credentialsMap, NodeMetadataToOrgAndName nodeToOrgAndName) {
|
||||
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
|
||||
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, resumeNodeStrategy,
|
||||
suspendNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated,
|
||||
nodeSuspended, utils, timeouts, executor);
|
||||
nodeSuspended, statementRunner, timeouts, executor);
|
||||
this.cleanupOrphanKeys = cleanupOrphanKeys;
|
||||
}
|
||||
|
||||
|
|
|
@ -115,14 +115,6 @@ public class TerremarkVCloudComputeServiceContextModule extends VCloudExpressCom
|
|||
return new ConcurrentHashMap<OrgAndName, KeyPairCredentials>();
|
||||
}
|
||||
|
||||
// TODO
|
||||
// @Override
|
||||
// protected void bindLoadBalancer() {
|
||||
// bind(LoadBalanceNodesStrategy.class).to(TerremarkLoadBalanceNodesStrategy.class);
|
||||
// bind(DestroyLoadBalancerStrategy.class).to(TerremarkDestroyLoadBalancerStrategy.class);
|
||||
// }
|
||||
//
|
||||
|
||||
@Named("PASSWORD")
|
||||
@Provides
|
||||
String providePassword(SecureRandom random) {
|
||||
|
|
|
@ -30,15 +30,18 @@ import javax.inject.Named;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
|
||||
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
|
||||
import org.jclouds.compute.strategy.ListNodesStrategy;
|
||||
import org.jclouds.compute.strategy.impl.EncodeTagIntoNameRunNodesAndAddToSetStrategy;
|
||||
import org.jclouds.compute.util.ComputeUtils;
|
||||
import org.jclouds.domain.LocationScope;
|
||||
import org.jclouds.vcloud.terremark.compute.options.TerremarkVCloudTemplateOptions;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* creates futures that correlate to
|
||||
*
|
||||
|
@ -50,23 +53,27 @@ public class TerremarkEncodeTagIntoNameRunNodesAndAddToSetStrategy extends Encod
|
|||
private final CreateNewKeyPairUnlessUserSpecifiedOtherwise createNewKeyPairUnlessUserSpecifiedOtherwise;
|
||||
|
||||
@Inject
|
||||
protected TerremarkEncodeTagIntoNameRunNodesAndAddToSetStrategy(AddNodeWithTagStrategy addNodeWithTagStrategy,
|
||||
ListNodesStrategy listNodesStrategy, @Named("NAMING_CONVENTION") String nodeNamingConvention,
|
||||
ComputeUtils utils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
|
||||
protected TerremarkEncodeTagIntoNameRunNodesAndAddToSetStrategy(
|
||||
AddNodeWithTagStrategy addNodeWithTagStrategy,
|
||||
ListNodesStrategy listNodesStrategy,
|
||||
@Named("NAMING_CONVENTION") String nodeNamingConvention,
|
||||
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
|
||||
CreateNewKeyPairUnlessUserSpecifiedOtherwise createNewKeyPairUnlessUserSpecifiedOtherwise) {
|
||||
super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention, utils, executor);
|
||||
super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention, executor,
|
||||
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
|
||||
this.createNewKeyPairUnlessUserSpecifiedOtherwise = createNewKeyPairUnlessUserSpecifiedOtherwise;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<?, Future<Void>> execute(String tag, int count, Template template, Set<NodeMetadata> nodes,
|
||||
Map<NodeMetadata, Exception> badNodes) {
|
||||
public Map<?, Future<Void>> execute(String tag, int count, Template template, Set<NodeMetadata> goodNodes,
|
||||
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
|
||||
assert template.getLocation().getParent().getScope() == LocationScope.REGION : "template location should have a parent of org, which should be mapped to region: "
|
||||
+ template.getLocation();
|
||||
String orgId = template.getLocation().getParent().getId();
|
||||
assert orgId.startsWith("http") : "parent id should be a rest url: " + template.getLocation().getParent();
|
||||
createNewKeyPairUnlessUserSpecifiedOtherwise.execute(URI.create(orgId), tag, template.getImage()
|
||||
.getDefaultCredentials().identity, template.getOptions().as(TerremarkVCloudTemplateOptions.class));
|
||||
return super.execute(tag, count, template, nodes, badNodes);
|
||||
return super.execute(tag, count, template, goodNodes, badNodes, customizationResponses);
|
||||
}
|
||||
}
|
|
@ -23,9 +23,9 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.internal.BaseComputeService;
|
||||
|
@ -33,6 +33,7 @@ import org.jclouds.compute.options.RunScriptOptions;
|
|||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
@ -137,7 +138,7 @@ public interface ComputeService {
|
|||
* default, equivalent to {@code templateBuilder().any().options(templateOptions)}.
|
||||
*/
|
||||
Set<? extends NodeMetadata> runNodesWithTag(String tag, int count, TemplateOptions templateOptions)
|
||||
throws RunNodesException;
|
||||
throws RunNodesException;
|
||||
|
||||
/**
|
||||
* Like {@link ComputeService#runNodesWithTag(String,int,TemplateOptions)}, except that the
|
||||
|
@ -238,11 +239,12 @@ public interface ComputeService {
|
|||
* org.jclouds.compute.options.RunScriptOptions)
|
||||
* @see org.jclouds.compute.predicates.NodePredicates#runningWithTag(String)
|
||||
*/
|
||||
@Deprecated
|
||||
Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript)
|
||||
throws RunScriptOnNodesException;
|
||||
throws RunScriptOnNodesException;
|
||||
|
||||
/**
|
||||
* Run the script on all nodes with the specific tag.
|
||||
* Run the script on all nodes with the specific predicate.
|
||||
*
|
||||
* @param filter
|
||||
* Predicate-based filter to define on which nodes the script is to be executed
|
||||
|
@ -257,7 +259,46 @@ public interface ComputeService {
|
|||
* @see org.jclouds.compute.predicates.NodePredicates#runningWithTag(String)
|
||||
* @see org.jclouds.io.Payloads
|
||||
*/
|
||||
@Deprecated
|
||||
Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
|
||||
Payload runScript, RunScriptOptions options) throws RunScriptOnNodesException;
|
||||
Payload runScript, RunScriptOptions options) throws RunScriptOnNodesException;
|
||||
|
||||
/**
|
||||
* Run the script on all nodes with the specific predicate.
|
||||
*
|
||||
* @param filter
|
||||
* Predicate-based filter to define on which nodes the script is to be executed
|
||||
* @param runScript
|
||||
* string containing the script to run
|
||||
* @param options
|
||||
* nullable options to how to run the script, whether to override credentials
|
||||
* @return map with node identifiers and corresponding responses
|
||||
* @throws RunScriptOnNodesException
|
||||
* if anything goes wrong during script execution
|
||||
*
|
||||
* @see org.jclouds.compute.predicates.NodePredicates#runningWithTag(String)
|
||||
* @see org.jclouds.scriptbuilder.domain.Statements
|
||||
*/
|
||||
Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, String runScript,
|
||||
RunScriptOptions options) throws RunScriptOnNodesException;
|
||||
|
||||
/**
|
||||
* Run the script on all nodes with the specific predicate.
|
||||
*
|
||||
* @param filter
|
||||
* Predicate-based filter to define on which nodes the script is to be executed
|
||||
* @param runScript
|
||||
* statement containing the script to run
|
||||
* @param options
|
||||
* nullable options to how to run the script, whether to override credentials
|
||||
* @return map with node identifiers and corresponding responses
|
||||
* @throws RunScriptOnNodesException
|
||||
* if anything goes wrong during script execution
|
||||
*
|
||||
* @see org.jclouds.compute.predicates.NodePredicates#runningWithTag(String)
|
||||
* @see org.jclouds.scriptbuilder.domain.Statements
|
||||
*/
|
||||
Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
|
||||
Statement runScript, RunScriptOptions options) throws RunScriptOnNodesException;
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import javax.annotation.Nullable;
|
|||
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.options.RunScriptOptions;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
|
||||
/**
|
||||
|
@ -39,17 +39,17 @@ public class RunScriptOnNodesException extends Exception {
|
|||
|
||||
/** The serialVersionUID */
|
||||
private static final long serialVersionUID = -2272965726680821281L;
|
||||
private final Payload runScript;
|
||||
private final Statement runScript;
|
||||
private final RunScriptOptions options;
|
||||
private final Map<NodeMetadata, ExecResponse> successfulNodes;
|
||||
private final Map<? extends NodeMetadata, ? extends Throwable> failedNodes;
|
||||
private final Map<?, Exception> executionExceptions;
|
||||
|
||||
public RunScriptOnNodesException(final Payload runScript, @Nullable final RunScriptOptions options,
|
||||
Map<NodeMetadata, ExecResponse> successfulNodes, Map<?, Exception> executionExceptions,
|
||||
Map<? extends NodeMetadata, ? extends Throwable> failedNodes) {
|
||||
public RunScriptOnNodesException(Statement runScript, @Nullable RunScriptOptions options,
|
||||
Map<NodeMetadata, ExecResponse> successfulNodes, Map<?, Exception> executionExceptions,
|
||||
Map<? extends NodeMetadata, ? extends Throwable> failedNodes) {
|
||||
super(String.format("error runScript on filtered nodes options(%s)%n%s%n%s", options,
|
||||
createExecutionErrorMessage(executionExceptions), createNodeErrorMessage(failedNodes)));
|
||||
createExecutionErrorMessage(executionExceptions), createNodeErrorMessage(failedNodes)));
|
||||
this.runScript = runScript;
|
||||
this.options = options;
|
||||
this.successfulNodes = successfulNodes;
|
||||
|
@ -66,8 +66,7 @@ public class RunScriptOnNodesException extends Exception {
|
|||
|
||||
/**
|
||||
*
|
||||
* @return Nodes that performed startup without error, but incurred problems
|
||||
* applying options
|
||||
* @return Nodes that performed startup without error, but incurred problems applying options
|
||||
*/
|
||||
public Map<?, ? extends Throwable> getExecutionErrors() {
|
||||
return executionExceptions;
|
||||
|
@ -75,14 +74,13 @@ public class RunScriptOnNodesException extends Exception {
|
|||
|
||||
/**
|
||||
*
|
||||
* @return Nodes that performed startup without error, but incurred problems
|
||||
* applying options
|
||||
* @return Nodes that performed startup without error, but incurred problems applying options
|
||||
*/
|
||||
public Map<? extends NodeMetadata, ? extends Throwable> getNodeErrors() {
|
||||
return failedNodes;
|
||||
}
|
||||
|
||||
public Payload getRunScript() {
|
||||
public Statement getRunScript() {
|
||||
return runScript;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,15 @@ package org.jclouds.compute.callables;
|
|||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.scriptbuilder.InitBuilder;
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
|
@ -33,23 +39,51 @@ import org.jclouds.ssh.ExecResponse;
|
|||
import org.jclouds.ssh.SshClient;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class InitAndStartScriptOnNode implements SshCallable<ExecResponse> {
|
||||
protected SshClient ssh;
|
||||
protected final NodeMetadata node;
|
||||
protected final InitBuilder init;
|
||||
protected final boolean runAsRoot;
|
||||
public class StartInitScriptOnNode implements Callable<ExecResponse> {
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
public InitAndStartScriptOnNode(NodeMetadata node, String name, Statement script, boolean runAsRoot) {
|
||||
public interface Factory {
|
||||
@Named("blocking")
|
||||
StartInitScriptOnNode blockOnComplete(NodeMetadata node, @Nullable String name, Statement script,
|
||||
boolean runAsRoot);
|
||||
|
||||
@Named("nonblocking")
|
||||
StartInitScriptOnNode dontBlockOnComplete(NodeMetadata node, @Nullable String name, Statement script,
|
||||
boolean runAsRoot);
|
||||
}
|
||||
|
||||
protected final Function<NodeMetadata, SshClient> sshFactory;
|
||||
protected final NodeMetadata node;
|
||||
protected final Statement init;
|
||||
protected final String name;
|
||||
protected final boolean runAsRoot;
|
||||
|
||||
protected SshClient ssh;
|
||||
|
||||
@Inject
|
||||
public StartInitScriptOnNode(Function<NodeMetadata, SshClient> sshFactory, @Assisted NodeMetadata node,
|
||||
@Assisted @Nullable String name, @Assisted Statement script, @Assisted boolean runAsRoot) {
|
||||
this.sshFactory = checkNotNull(sshFactory, "sshFactory");
|
||||
this.node = checkNotNull(node, "node");
|
||||
if (name == null) {
|
||||
if (checkNotNull(script, "script") instanceof InitBuilder)
|
||||
name = InitBuilder.class.cast(script).getInstanceName();
|
||||
else
|
||||
name = "jclouds-script-" + System.currentTimeMillis();
|
||||
}
|
||||
this.init = checkNotNull(script, "script") instanceof InitBuilder ? InitBuilder.class.cast(script)
|
||||
: createInitScript(checkNotNull(name, "name"), script);
|
||||
this.name = checkNotNull(name, "name");
|
||||
this.runAsRoot = runAsRoot;
|
||||
}
|
||||
|
||||
|
@ -60,13 +94,28 @@ public class InitAndStartScriptOnNode implements SshCallable<ExecResponse> {
|
|||
|
||||
@Override
|
||||
public ExecResponse call() {
|
||||
ssh.put(init.getInstanceName(), init.render(OsFamily.UNIX));
|
||||
ssh.exec("chmod 755 " + init.getInstanceName());
|
||||
ssh = sshFactory.apply(node);
|
||||
try {
|
||||
ssh.connect();
|
||||
return doCall();
|
||||
} finally {
|
||||
if (ssh != null)
|
||||
ssh.disconnect();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* ssh client is initialized through this call.
|
||||
*/
|
||||
protected ExecResponse doCall() {
|
||||
ssh.put(name, init.render(OsFamily.UNIX));
|
||||
ssh.exec("chmod 755 " + name);
|
||||
runAction("init");
|
||||
return runAction("start");
|
||||
}
|
||||
|
||||
private ExecResponse runAction(String action) {
|
||||
protected ExecResponse runAction(String action) {
|
||||
ExecResponse returnVal;
|
||||
String command = (runAsRoot) ? execScriptAsRoot(action) : execScriptAsDefaultUser(action);
|
||||
returnVal = runCommand(command);
|
||||
|
@ -84,30 +133,23 @@ public class InitAndStartScriptOnNode implements SshCallable<ExecResponse> {
|
|||
return returnVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConnection(SshClient ssh, Logger logger) {
|
||||
this.logger = checkNotNull(logger, "logger");
|
||||
this.ssh = checkNotNull(ssh, "ssh");
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public String execScriptAsRoot(String action) {
|
||||
String command;
|
||||
if (node.getCredentials().identity.equals("root")) {
|
||||
command = "./" + init.getInstanceName() + " " + action;
|
||||
command = "./" + name + " " + action;
|
||||
} else if (node.getAdminPassword() != null) {
|
||||
command = String.format("echo '%s'|sudo -S ./%s %s", node.getAdminPassword(), init.getInstanceName(), action);
|
||||
command = String.format("echo '%s'|sudo -S ./%s %s", node.getAdminPassword(), name, action);
|
||||
} else {
|
||||
command = "sudo ./" + init.getInstanceName() + " " + action;
|
||||
command = "sudo ./" + name + " " + action;
|
||||
}
|
||||
return command;
|
||||
}
|
||||
|
||||
protected String execScriptAsDefaultUser(String action) {
|
||||
return "./" + init.getInstanceName() + " " + action;
|
||||
return "./" + name + " " + action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeMetadata getNode() {
|
||||
return node;
|
||||
}
|
|
@ -19,40 +19,48 @@
|
|||
|
||||
package org.jclouds.compute.callables;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
import org.jclouds.ssh.SshClient;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class RunScriptOnNode extends InitAndStartScriptOnNode {
|
||||
public class StartInitScriptOnNodeAndBlockUntilComplete extends StartInitScriptOnNode {
|
||||
protected final Predicate<CommandUsingClient> runScriptNotRunning;
|
||||
|
||||
public RunScriptOnNode(@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning,
|
||||
NodeMetadata node, String scriptName, Statement script, boolean runAsRoot) {
|
||||
super(node, scriptName, script, runAsRoot);
|
||||
this.runScriptNotRunning = runScriptNotRunning;
|
||||
@Inject
|
||||
public StartInitScriptOnNodeAndBlockUntilComplete(
|
||||
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning,
|
||||
Function<NodeMetadata, SshClient> sshFactory, @Assisted NodeMetadata node, @Assisted String scriptName,
|
||||
@Assisted Statement script, @Assisted boolean runAsRoot) {
|
||||
super(sshFactory, node, scriptName, script, runAsRoot);
|
||||
this.runScriptNotRunning = checkNotNull(runScriptNotRunning, "runScriptNotRunning");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ExecResponse call() {
|
||||
ExecResponse returnVal = super.call();
|
||||
boolean complete = runScriptNotRunning.apply(new CommandUsingClient("./" + init.getInstanceName() + " status", ssh));
|
||||
public ExecResponse doCall() {
|
||||
ExecResponse returnVal = super.doCall();
|
||||
boolean complete = runScriptNotRunning.apply(new CommandUsingClient("./" + name + " status", ssh));
|
||||
logger.debug("<< complete(%s)", complete);
|
||||
if (logger.isDebugEnabled() || returnVal.getExitCode() != 0) {
|
||||
logger.debug("<< stdout from %s as %s@%s\n%s", init.getInstanceName(), node.getCredentials().identity, Iterables.get(node
|
||||
.getPublicAddresses(), 0), ssh.exec("./" + init.getInstanceName() + " tail").getOutput());
|
||||
logger.debug("<< stderr from %s as %s@%s\n%s", init.getInstanceName(), node.getCredentials().identity, Iterables.get(node
|
||||
.getPublicAddresses(), 0), ssh.exec("./" + init.getInstanceName() + " tailerr").getOutput());
|
||||
logger.debug("<< stdout from %s as %s@%s\n%s", name, node.getCredentials().identity, Iterables.get(node
|
||||
.getPublicAddresses(), 0), ssh.exec("./" + name + " tail").getOutput());
|
||||
logger.debug("<< stderr from %s as %s@%s\n%s", name, node.getCredentials().identity, Iterables.get(node
|
||||
.getPublicAddresses(), 0), ssh.exec("./" + name + " tailerr").getOutput());
|
||||
}
|
||||
return returnVal;
|
||||
}
|
|
@ -24,12 +24,15 @@ import static org.jclouds.compute.domain.OsFamily.UBUNTU;
|
|||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.collect.Memoized;
|
||||
import org.jclouds.compute.callables.StartInitScriptOnNode;
|
||||
import org.jclouds.compute.callables.StartInitScriptOnNodeAndBlockUntilComplete;
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
|
@ -37,11 +40,17 @@ import org.jclouds.compute.domain.NodeMetadata;
|
|||
import org.jclouds.compute.domain.OsFamily;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.functions.CreateSshClientOncePortIsListeningOnNode;
|
||||
import org.jclouds.compute.functions.TemplateOptionsToStatement;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
|
||||
import org.jclouds.compute.strategy.RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
|
||||
import org.jclouds.compute.util.ComputeServiceUtils;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.json.Json;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.rest.suppliers.RetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.ssh.SshClient;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
@ -52,6 +61,8 @@ import com.google.inject.AbstractModule;
|
|||
import com.google.inject.Injector;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
import com.google.inject.name.Names;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -63,6 +74,23 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
|
|||
install(new ComputeServiceTimeoutsModule());
|
||||
bind(new TypeLiteral<Function<NodeMetadata, SshClient>>() {
|
||||
}).to(CreateSshClientOncePortIsListeningOnNode.class);
|
||||
bind(new TypeLiteral<Function<TemplateOptions, Statement>>() {
|
||||
}).to(TemplateOptionsToStatement.class);
|
||||
|
||||
install(new FactoryModuleBuilder().implement(StartInitScriptOnNode.class, Names.named("blocking"),
|
||||
StartInitScriptOnNodeAndBlockUntilComplete.class).implement(StartInitScriptOnNode.class,
|
||||
Names.named("nonblocking"), StartInitScriptOnNode.class).build(StartInitScriptOnNode.Factory.class));
|
||||
|
||||
install(new FactoryModuleBuilder().implement(new TypeLiteral<Callable<Void>>() {
|
||||
}, CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.class).implement(
|
||||
new TypeLiteral<Function<NodeMetadata, Void>>() {
|
||||
}, CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.class).build(
|
||||
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory.class));
|
||||
|
||||
install(new FactoryModuleBuilder().implement(new TypeLiteral<Callable<Void>>() {
|
||||
}, RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap.class).build(
|
||||
RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory.class));
|
||||
requestStaticInjection(ComputeServiceUtils.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
@ -118,20 +146,20 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
|
|||
@Singleton
|
||||
@Memoized
|
||||
protected Supplier<Set<? extends Image>> supplyImageCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
|
||||
final Supplier<Set<? extends Image>> imageSupplier) {
|
||||
final Supplier<Set<? extends Image>> imageSupplier) {
|
||||
return new RetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Set<? extends Image>>(authException, seconds,
|
||||
new Supplier<Set<? extends Image>>() {
|
||||
@Override
|
||||
public Set<? extends Image> get() {
|
||||
return imageSupplier.get();
|
||||
}
|
||||
});
|
||||
new Supplier<Set<? extends Image>>() {
|
||||
@Override
|
||||
public Set<? extends Image> get() {
|
||||
return imageSupplier.get();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
protected Supplier<Map<String, ? extends Location>> provideLocationMap(
|
||||
@Memoized Supplier<Set<? extends Location>> locations) {
|
||||
@Memoized Supplier<Set<? extends Location>> locations) {
|
||||
return Suppliers.compose(new Function<Set<? extends Location>, Map<String, ? extends Location>>() {
|
||||
|
||||
@Override
|
||||
|
@ -153,14 +181,14 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
|
|||
@Singleton
|
||||
@Memoized
|
||||
protected Supplier<Set<? extends Location>> supplyLocationCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
|
||||
final Supplier<Set<? extends Location>> locationSupplier) {
|
||||
final Supplier<Set<? extends Location>> locationSupplier) {
|
||||
return new RetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Set<? extends Location>>(authException, seconds,
|
||||
new Supplier<Set<? extends Location>>() {
|
||||
@Override
|
||||
public Set<? extends Location> get() {
|
||||
return locationSupplier.get();
|
||||
}
|
||||
});
|
||||
new Supplier<Set<? extends Location>>() {
|
||||
@Override
|
||||
public Set<? extends Location> get() {
|
||||
return locationSupplier.get();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
@ -187,14 +215,14 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
|
|||
@Singleton
|
||||
@Memoized
|
||||
protected Supplier<Set<? extends Hardware>> supplySizeCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
|
||||
final Supplier<Set<? extends Hardware>> hardwareSupplier) {
|
||||
final Supplier<Set<? extends Hardware>> hardwareSupplier) {
|
||||
return new RetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Set<? extends Hardware>>(authException, seconds,
|
||||
new Supplier<Set<? extends Hardware>>() {
|
||||
@Override
|
||||
public Set<? extends Hardware> get() {
|
||||
return hardwareSupplier.get();
|
||||
}
|
||||
});
|
||||
new Supplier<Set<? extends Hardware>>() {
|
||||
@Override
|
||||
public Set<? extends Hardware> get() {
|
||||
return hardwareSupplier.get();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
*
|
||||
* 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.config;
|
||||
|
||||
/**
|
||||
*
|
||||
* Designates information related to customization of a resource.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public interface CustomizationResponse {
|
||||
|
||||
}
|
|
@ -53,7 +53,6 @@ public class JCloudsNativeComputeServiceAdapterContextModule<S, A> extends
|
|||
protected void configure() {
|
||||
bind(new TypeLiteral<ComputeServiceAdapter<NodeMetadata, Hardware, Image, Location>>() {
|
||||
}).to(adapter);
|
||||
bind(IdentityFunction.class).toInstance(IdentityFunction.INSTANCE);
|
||||
bind(new TypeLiteral<Function<NodeMetadata, NodeMetadata>>() {
|
||||
}).to((Class) IdentityFunction.class);
|
||||
bind(new TypeLiteral<Function<Image, Image>>() {
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
*
|
||||
* 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.collect.Lists.newArrayList;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.jclouds.scriptbuilder.InitBuilder;
|
||||
import org.jclouds.scriptbuilder.domain.AuthorizeRSAPublicKey;
|
||||
import org.jclouds.scriptbuilder.domain.InstallRSAPrivateKey;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.scriptbuilder.domain.StatementList;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class TemplateOptionsToStatement implements Function<TemplateOptions, Statement> {
|
||||
|
||||
@Override
|
||||
public Statement apply(TemplateOptions options) {
|
||||
List<Statement> bootstrap = newArrayList();
|
||||
if (options.getPublicKey() != null)
|
||||
bootstrap.add(new AuthorizeRSAPublicKey(options.getPublicKey()));
|
||||
if (options.getRunScript() != null)
|
||||
bootstrap.add(options.getRunScript());
|
||||
if (options.getPrivateKey() != null)
|
||||
bootstrap.add(new InstallRSAPrivateKey(options.getPrivateKey()));
|
||||
if (bootstrap.size() >= 1) {
|
||||
if (options.getTaskName() == null && !(options.getRunScript() instanceof InitBuilder))
|
||||
options.nameTask("bootstrap");
|
||||
return bootstrap.size() == 1 ? bootstrap.get(0) : new StatementList(bootstrap);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -27,10 +27,8 @@ import static com.google.common.base.Predicates.notNull;
|
|||
import static com.google.common.collect.Iterables.concat;
|
||||
import static com.google.common.collect.Iterables.filter;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
import static com.google.common.collect.Maps.newHashMap;
|
||||
import static com.google.common.collect.Maps.newLinkedHashMap;
|
||||
import static com.google.common.collect.Sets.filter;
|
||||
import static com.google.common.collect.Sets.newHashSet;
|
||||
import static com.google.common.collect.Sets.newLinkedHashSet;
|
||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||
import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
|
||||
|
@ -38,6 +36,7 @@ import static org.jclouds.compute.predicates.NodePredicates.all;
|
|||
import static org.jclouds.concurrent.FutureIterables.awaitCompletion;
|
||||
import static org.jclouds.concurrent.FutureIterables.transformParallel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
@ -59,6 +58,7 @@ import org.jclouds.compute.ComputeService;
|
|||
import org.jclouds.compute.ComputeServiceContext;
|
||||
import org.jclouds.compute.RunNodesException;
|
||||
import org.jclouds.compute.RunScriptOnNodesException;
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.Image;
|
||||
|
@ -76,13 +76,14 @@ import org.jclouds.compute.strategy.ListNodesStrategy;
|
|||
import org.jclouds.compute.strategy.RebootNodeStrategy;
|
||||
import org.jclouds.compute.strategy.ResumeNodeStrategy;
|
||||
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
|
||||
import org.jclouds.compute.strategy.RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
|
||||
import org.jclouds.compute.strategy.SuspendNodeStrategy;
|
||||
import org.jclouds.compute.util.ComputeUtils;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.predicates.RetryablePredicate;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.scriptbuilder.domain.Statements;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
import org.jclouds.util.Strings2;
|
||||
|
@ -90,6 +91,9 @@ import org.jclouds.util.Strings2;
|
|||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.LinkedHashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -104,24 +108,25 @@ public class BaseComputeService implements ComputeService {
|
|||
|
||||
protected final ComputeServiceContext context;
|
||||
protected final Map<String, Credentials> credentialStore;
|
||||
protected final Supplier<Set<? extends Image>> images;
|
||||
protected final Supplier<Set<? extends Hardware>> hardwareProfiles;
|
||||
protected final Supplier<Set<? 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 ResumeNodeStrategy resumeNodeStrategy;
|
||||
protected final SuspendNodeStrategy suspendNodeStrategy;
|
||||
protected final Provider<TemplateBuilder> templateBuilderProvider;
|
||||
protected final Provider<TemplateOptions> templateOptionsProvider;
|
||||
protected final Predicate<NodeMetadata> nodeRunning;
|
||||
protected final Predicate<NodeMetadata> nodeTerminated;
|
||||
protected final Predicate<NodeMetadata> nodeSuspended;
|
||||
protected final ComputeUtils utils;
|
||||
protected final Timeouts timeouts;
|
||||
protected final ExecutorService executor;
|
||||
|
||||
private final Supplier<Set<? extends Image>> images;
|
||||
private final Supplier<Set<? extends Hardware>> hardwareProfiles;
|
||||
private final Supplier<Set<? extends Location>> locations;
|
||||
private final ListNodesStrategy listNodesStrategy;
|
||||
private final GetNodeMetadataStrategy getNodeMetadataStrategy;
|
||||
private final RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy;
|
||||
private final RebootNodeStrategy rebootNodeStrategy;
|
||||
private final DestroyNodeStrategy destroyNodeStrategy;
|
||||
private final ResumeNodeStrategy resumeNodeStrategy;
|
||||
private final SuspendNodeStrategy suspendNodeStrategy;
|
||||
private final Provider<TemplateBuilder> templateBuilderProvider;
|
||||
private final Provider<TemplateOptions> templateOptionsProvider;
|
||||
private final Predicate<NodeMetadata> nodeRunning;
|
||||
private final Predicate<NodeMetadata> nodeTerminated;
|
||||
private final Predicate<NodeMetadata> nodeSuspended;
|
||||
private final RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory statementRunner;
|
||||
private final Timeouts timeouts;
|
||||
private final ExecutorService executor;
|
||||
|
||||
@Inject
|
||||
protected BaseComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
|
||||
|
@ -134,7 +139,8 @@ public class BaseComputeService implements ComputeService {
|
|||
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
|
||||
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
|
||||
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
|
||||
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended, ComputeUtils utils, Timeouts timeouts,
|
||||
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
|
||||
RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory statementRunner, Timeouts timeouts,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||
this.context = checkNotNull(context, "context");
|
||||
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
|
||||
|
@ -153,7 +159,7 @@ public class BaseComputeService implements ComputeService {
|
|||
this.nodeRunning = checkNotNull(nodeRunning, "nodeRunning");
|
||||
this.nodeTerminated = checkNotNull(nodeTerminated, "nodeTerminated");
|
||||
this.nodeSuspended = checkNotNull(nodeSuspended, "nodeSuspended");
|
||||
this.utils = checkNotNull(utils, "utils");
|
||||
this.statementRunner = checkNotNull(statementRunner, "statementRunner");
|
||||
this.timeouts = checkNotNull(timeouts, "timeouts");
|
||||
this.executor = checkNotNull(executor, "executor");
|
||||
}
|
||||
|
@ -177,17 +183,20 @@ public class BaseComputeService implements ComputeService {
|
|||
logger.debug(">> running %d node%s tag(%s) location(%s) image(%s) hardwareProfile(%s) options(%s)", count,
|
||||
count > 1 ? "s" : "", tag, template.getLocation().getId(), template.getImage().getId(), template
|
||||
.getHardware().getId(), template.getOptions());
|
||||
Set<NodeMetadata> nodes = newHashSet();
|
||||
Set<NodeMetadata> goodNodes = newLinkedHashSet();
|
||||
Map<NodeMetadata, Exception> badNodes = newLinkedHashMap();
|
||||
Map<?, Future<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count, template, nodes, badNodes);
|
||||
Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "resumeing nodes");
|
||||
for (NodeMetadata node : concat(nodes, badNodes.keySet()))
|
||||
Multimap<NodeMetadata, CustomizationResponse> customizationResponses = LinkedHashMultimap.create();
|
||||
|
||||
Map<?, Future<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count, template, goodNodes, badNodes,
|
||||
customizationResponses);
|
||||
Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "resuming nodes");
|
||||
for (NodeMetadata node : concat(goodNodes, badNodes.keySet()))
|
||||
if (node.getCredentials() != null)
|
||||
credentialStore.put("node#" + node.getId(), node.getCredentials());
|
||||
if (executionExceptions.size() > 0 || badNodes.size() > 0) {
|
||||
throw new RunNodesException(tag, count, template, nodes, executionExceptions, badNodes);
|
||||
throw new RunNodesException(tag, count, template, goodNodes, executionExceptions, badNodes);
|
||||
}
|
||||
return nodes;
|
||||
return goodNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -436,47 +445,54 @@ public class BaseComputeService implements ComputeService {
|
|||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
|
||||
final Payload runScript, @Nullable final RunScriptOptions options) throws RunScriptOnNodesException {
|
||||
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript,
|
||||
@Nullable RunScriptOptions options) throws RunScriptOnNodesException {
|
||||
try {
|
||||
return runScriptOnNodesMatching(filter, Statements.exec(Strings2.toStringAndClose(checkNotNull(runScript,
|
||||
"runScript").getInput())), options);
|
||||
} catch (IOException e) {
|
||||
Throwables.propagate(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, String runScript,
|
||||
@Nullable RunScriptOptions options) throws RunScriptOnNodesException {
|
||||
return runScriptOnNodesMatching(filter, Statements.exec(checkNotNull(runScript, "runScript")), options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript,
|
||||
@Nullable RunScriptOptions options) throws RunScriptOnNodesException {
|
||||
|
||||
checkNotNull(filter, "Filter must be provided");
|
||||
checkNotNull(runScript, "runScript");
|
||||
checkNotNull(options, "options");
|
||||
if (options.getTaskName() == null)
|
||||
options.nameTask("jclouds-script-" + System.currentTimeMillis());
|
||||
|
||||
Iterable<? extends NodeMetadata> nodes = filter(detailsOnAllNodes(), filter);
|
||||
|
||||
final Map<NodeMetadata, ExecResponse> execs = newHashMap();
|
||||
final Map<NodeMetadata, Future<Void>> responses = newHashMap();
|
||||
final Map<NodeMetadata, Exception> badNodes = newLinkedHashMap();
|
||||
Map<NodeMetadata, ExecResponse> goodNodes = newLinkedHashMap();
|
||||
Map<NodeMetadata, Exception> badNodes = newLinkedHashMap();
|
||||
|
||||
Map<NodeMetadata, Future<Void>> responses = newLinkedHashMap();
|
||||
nodes = filterNodesWhoCanRunScripts(nodes, badNodes, options.getOverrideCredentials());
|
||||
|
||||
for (final NodeMetadata node : nodes) {
|
||||
|
||||
responses.put(node, executor.submit(new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
try {
|
||||
ExecResponse response = utils.runScriptOnNode(node, Statements.exec(Strings2.toStringAndClose(runScript
|
||||
.getInput())), options);
|
||||
if (response != null)
|
||||
execs.put(node, response);
|
||||
} catch (Exception e) {
|
||||
badNodes.put(node, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
for (NodeMetadata node : nodes) {
|
||||
responses.put(node, executor.submit(statementRunner.create(node, runScript, options, goodNodes, badNodes)));
|
||||
}
|
||||
|
||||
Map<?, Exception> exceptions = awaitCompletion(responses, executor, null, logger, "running script on nodes");
|
||||
if (exceptions.size() > 0 || badNodes.size() > 0) {
|
||||
throw new RunScriptOnNodesException(runScript, options, execs, exceptions, badNodes);
|
||||
throw new RunScriptOnNodesException(runScript, options, goodNodes, exceptions, badNodes);
|
||||
}
|
||||
|
||||
return execs;
|
||||
return goodNodes;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
*
|
||||
* 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.strategy;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Throwables.getRootCause;
|
||||
import static org.jclouds.compute.util.ComputeServiceUtils.findReachableSocketOnNode;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.compute.callables.StartInitScriptOnNode;
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.assistedinject.AssistedInject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap implements Callable<Void>,
|
||||
Function<NodeMetadata, Void> {
|
||||
public static interface Factory {
|
||||
Callable<Void> create(TemplateOptions options, NodeMetadata node, Set<NodeMetadata> goodNodes,
|
||||
Map<NodeMetadata, Exception> badNodes,
|
||||
Multimap<NodeMetadata, CustomizationResponse> customizationResponses);
|
||||
|
||||
Function<NodeMetadata, Void> create(TemplateOptions options, Set<NodeMetadata> goodNodes,
|
||||
Map<NodeMetadata, Exception> badNodes,
|
||||
Multimap<NodeMetadata, CustomizationResponse> customizationResponses);
|
||||
}
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final Predicate<NodeMetadata> nodeRunning;
|
||||
private final ScriptInvokerForNodeAndStatement scriptInvokerForNodeAndStatement;
|
||||
private final GetNodeMetadataStrategy getNode;
|
||||
private final RetryIfSocketNotYetOpen socketTester;
|
||||
private final Timeouts timeouts;
|
||||
|
||||
@Nullable
|
||||
private final Statement statement;
|
||||
private final TemplateOptions options;
|
||||
private NodeMetadata node;
|
||||
private final Set<NodeMetadata> goodNodes;
|
||||
private final Map<NodeMetadata, Exception> badNodes;
|
||||
private final Multimap<NodeMetadata, CustomizationResponse> customizationResponses;
|
||||
|
||||
private transient boolean tainted;
|
||||
|
||||
@AssistedInject
|
||||
public CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap(
|
||||
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning, GetNodeMetadataStrategy getNode,
|
||||
RetryIfSocketNotYetOpen socketTester, Timeouts timeouts,
|
||||
Function<TemplateOptions, Statement> templateOptionsToStatement,
|
||||
ScriptInvokerForNodeAndStatement scriptInvokerForNodeAndStatement, @Assisted TemplateOptions options,
|
||||
@Assisted @Nullable NodeMetadata node, @Assisted Set<NodeMetadata> goodNodes,
|
||||
@Assisted Map<NodeMetadata, Exception> badNodes,
|
||||
@Assisted Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
|
||||
this.statement = checkNotNull(templateOptionsToStatement, "templateOptionsToStatement").apply(
|
||||
checkNotNull(options, "options"));
|
||||
this.nodeRunning = checkNotNull(nodeRunning, "nodeRunning");
|
||||
this.scriptInvokerForNodeAndStatement = checkNotNull(scriptInvokerForNodeAndStatement,
|
||||
"scriptInvokerForNodeAndStatement");
|
||||
this.getNode = checkNotNull(getNode, "getNode");
|
||||
this.socketTester = checkNotNull(socketTester, "socketTester");
|
||||
this.timeouts = checkNotNull(timeouts, "timeouts");
|
||||
this.node = node;
|
||||
this.options = checkNotNull(options, "options");
|
||||
this.goodNodes = checkNotNull(goodNodes, "goodNodes");
|
||||
this.badNodes = checkNotNull(badNodes, "badNodes");
|
||||
this.customizationResponses = checkNotNull(customizationResponses, "customizationResponses");
|
||||
}
|
||||
|
||||
@AssistedInject
|
||||
public CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap(
|
||||
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning, GetNodeMetadataStrategy getNode,
|
||||
RetryIfSocketNotYetOpen socketTester, Timeouts timeouts,
|
||||
Function<TemplateOptions, Statement> templateOptionsToStatement,
|
||||
ScriptInvokerForNodeAndStatement scriptInvokerForNodeAndStatement, @Assisted TemplateOptions options,
|
||||
@Assisted Set<NodeMetadata> goodNodes, @Assisted Map<NodeMetadata, Exception> badNodes,
|
||||
@Assisted Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
|
||||
this(nodeRunning, getNode, socketTester, timeouts, templateOptionsToStatement, scriptInvokerForNodeAndStatement,
|
||||
options, null, goodNodes, badNodes, customizationResponses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void call() {
|
||||
checkState(!tainted, "this object is not designed to be reused: %s", toString());
|
||||
tainted = true;
|
||||
try {
|
||||
if (options.shouldBlockUntilRunning()) {
|
||||
if (nodeRunning.apply(node)) {
|
||||
node = getNode.getNode(node.getId());
|
||||
} else {
|
||||
throw new IllegalStateException(String.format(
|
||||
"node didn't achieve the state running on node %s within %d seconds, final state: %s", node
|
||||
.getId(), timeouts.nodeRunning / 1000, node.getState()));
|
||||
}
|
||||
if (statement != null) {
|
||||
StartInitScriptOnNode scriptInstructions = scriptInvokerForNodeAndStatement.create(node, statement,
|
||||
options);
|
||||
ExecResponse exec = scriptInstructions.call();
|
||||
customizationResponses.put(node, exec);
|
||||
}
|
||||
if (options.getPort() > 0) {
|
||||
findReachableSocketOnNode(socketTester.seconds(options.getSeconds()), node, options.getPort());
|
||||
}
|
||||
}
|
||||
logger.debug("<< options applied node(%s)", node.getId());
|
||||
goodNodes.add(node);
|
||||
} catch (Exception e) {
|
||||
logger.error(e, "<< problem applying options to node(%s): ", node.getId(), getRootCause(e).getMessage());
|
||||
badNodes.put(node, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void apply(NodeMetadata input) {
|
||||
this.node = input;
|
||||
call();
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -21,12 +21,14 @@ package org.jclouds.compute.strategy;
|
|||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.strategy.impl.EncodeTagIntoNameRunNodesAndAddToSetStrategy;
|
||||
|
||||
import java.util.concurrent.Future;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
|
@ -37,6 +39,6 @@ import com.google.inject.ImplementedBy;
|
|||
@ImplementedBy(EncodeTagIntoNameRunNodesAndAddToSetStrategy.class)
|
||||
public interface RunNodesAndAddToSetStrategy {
|
||||
|
||||
Map<?, Future<Void>> execute(String tag, int count, Template template,
|
||||
Set<NodeMetadata> nodes, Map<NodeMetadata, Exception> badNodes);
|
||||
Map<?, Future<Void>> execute(String tag, int count, Template template, Set<NodeMetadata> goodNodes,
|
||||
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses);
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
*
|
||||
* 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.strategy;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Throwables.getRootCause;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.compute.callables.StartInitScriptOnNode;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.options.RunScriptOptions;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.inject.assistedinject.AssistedInject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap implements Callable<Void> {
|
||||
public static interface Factory {
|
||||
Callable<Void> create(NodeMetadata node, Statement statement, RunScriptOptions options,
|
||||
Map<NodeMetadata, ExecResponse> goodNodes, Map<NodeMetadata, Exception> badNodes);
|
||||
|
||||
}
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
// NOTE this is mutable
|
||||
protected NodeMetadata node;
|
||||
private final Map<NodeMetadata, Exception> badNodes;
|
||||
private final Map<NodeMetadata, ExecResponse> goodNodes;
|
||||
private final RunScriptOptions options;
|
||||
|
||||
protected final Statement statement;
|
||||
private final ScriptInvokerForNodeAndStatement scriptInvokerForNodeAndStatement;
|
||||
private transient boolean tainted;
|
||||
|
||||
@AssistedInject
|
||||
public RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap(
|
||||
ScriptInvokerForNodeAndStatement scriptInvokerForNodeAndStatement, @Assisted NodeMetadata node,
|
||||
@Assisted @Nullable Statement statement, @Assisted RunScriptOptions options,
|
||||
@Assisted Map<NodeMetadata, ExecResponse> goodNodes, @Assisted Map<NodeMetadata, Exception> badNodes) {
|
||||
this.statement = checkNotNull(statement, "statement");
|
||||
this.scriptInvokerForNodeAndStatement = checkNotNull(scriptInvokerForNodeAndStatement,
|
||||
"scriptInvokerForNodeAndStatement");
|
||||
this.node = node;
|
||||
this.badNodes = checkNotNull(badNodes, "badNodes");
|
||||
this.goodNodes = checkNotNull(goodNodes, "goodNodes");
|
||||
this.options = checkNotNull(options, "options");
|
||||
}
|
||||
|
||||
@AssistedInject
|
||||
public RunStatementOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap(
|
||||
ScriptInvokerForNodeAndStatement scriptInvokerForNodeAndStatement, @Assisted @Nullable Statement statement,
|
||||
@Assisted RunScriptOptions options, @Assisted Map<NodeMetadata, ExecResponse> goodNodes,
|
||||
@Assisted Map<NodeMetadata, Exception> badNodes) {
|
||||
this(scriptInvokerForNodeAndStatement, null, statement, options, goodNodes, badNodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void call() {
|
||||
checkState(node != null, "node must be set");
|
||||
checkState(!tainted, "this object is not designed to be reused: %s", toString());
|
||||
tainted = true;
|
||||
try {
|
||||
StartInitScriptOnNode scriptInstructions = scriptInvokerForNodeAndStatement.create(node, statement, options);
|
||||
ExecResponse exec = scriptInstructions.call();
|
||||
logger.trace("<< script output for node(%s): %s", node.getId(), exec);
|
||||
logger.debug("<< options applied node(%s)", node.getId());
|
||||
goodNodes.put(node, exec);
|
||||
} catch (Exception e) {
|
||||
logger.error(e, "<< problem applying options to node(%s): ", node.getId(), getRootCause(e).getMessage());
|
||||
badNodes.put(node, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
*
|
||||
* 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.strategy;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.compute.callables.StartInitScriptOnNode;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.options.RunScriptOptions;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Singleton
|
||||
public class ScriptInvokerForNodeAndStatement {
|
||||
|
||||
private final StartInitScriptOnNode.Factory initAndStartScriptOnNodeFactory;
|
||||
|
||||
@Inject
|
||||
public ScriptInvokerForNodeAndStatement(StartInitScriptOnNode.Factory initAndStartScriptOnNodeFactory) {
|
||||
this.initAndStartScriptOnNodeFactory = checkNotNull(initAndStartScriptOnNodeFactory,
|
||||
"initAndStartScriptOnNodeFactory");
|
||||
}
|
||||
|
||||
public StartInitScriptOnNode create(NodeMetadata node, Statement runScript, RunScriptOptions options) {
|
||||
checkNotNull(node, "node");
|
||||
checkNotNull(runScript, "runScript");
|
||||
checkNotNull(options, "options");
|
||||
return options.shouldBlockOnComplete() ? initAndStartScriptOnNodeFactory.blockOnComplete(node, options
|
||||
.getTaskName(), runScript, options.shouldRunAsRoot()) : initAndStartScriptOnNodeFactory
|
||||
.dontBlockOnComplete(node, options.getTaskName(), runScript, options.shouldRunAsRoot());
|
||||
}
|
||||
}
|
|
@ -19,6 +19,13 @@
|
|||
|
||||
package org.jclouds.compute.strategy.impl;
|
||||
|
||||
import static com.google.common.base.Objects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.collect.Iterables.any;
|
||||
import static com.google.common.collect.Maps.newLinkedHashMap;
|
||||
import static com.google.common.collect.Sets.newLinkedHashSet;
|
||||
import static org.jclouds.concurrent.Futures.compose;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -32,20 +39,19 @@ import javax.inject.Named;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
|
||||
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
|
||||
import org.jclouds.compute.strategy.ListNodesStrategy;
|
||||
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
|
||||
import org.jclouds.compute.util.ComputeUtils;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* creates futures that correlate to
|
||||
|
@ -54,24 +60,54 @@ import com.google.common.collect.Sets;
|
|||
*/
|
||||
@Singleton
|
||||
public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrategy {
|
||||
|
||||
private class AddNode implements Callable<NodeMetadata> {
|
||||
private final String name;
|
||||
private final String tag;
|
||||
private final Template template;
|
||||
|
||||
private AddNode(String name, String tag, Template template) {
|
||||
this.name = checkNotNull(name, "name");
|
||||
this.tag = checkNotNull(tag, "tag");
|
||||
this.template = checkNotNull(template, "template");
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeMetadata call() throws Exception {
|
||||
NodeMetadata node = null;
|
||||
logger.debug(">> starting node(%s) tag(%s)", name, tag);
|
||||
node = addNodeWithTagStrategy.addNodeWithTag(tag, name, template);
|
||||
logger.debug("<< %s node(%s)", node.getState(), node.getId());
|
||||
return node;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return toStringHelper(this).add("name", name).add("tag", tag).add("template", template).toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
protected final AddNodeWithTagStrategy addNodeWithTagStrategy;
|
||||
protected final ListNodesStrategy listNodesStrategy;
|
||||
protected final String nodeNamingConvention;
|
||||
protected final ComputeUtils utils;
|
||||
protected final ExecutorService executor;
|
||||
protected final CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
|
||||
|
||||
@Inject
|
||||
protected EncodeTagIntoNameRunNodesAndAddToSetStrategy(AddNodeWithTagStrategy addNodeWithTagStrategy,
|
||||
ListNodesStrategy listNodesStrategy, @Named("NAMING_CONVENTION") String nodeNamingConvention,
|
||||
ComputeUtils utils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||
protected EncodeTagIntoNameRunNodesAndAddToSetStrategy(
|
||||
AddNodeWithTagStrategy addNodeWithTagStrategy,
|
||||
ListNodesStrategy listNodesStrategy,
|
||||
@Named("NAMING_CONVENTION") String nodeNamingConvention,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
|
||||
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory) {
|
||||
this.addNodeWithTagStrategy = addNodeWithTagStrategy;
|
||||
this.listNodesStrategy = listNodesStrategy;
|
||||
this.nodeNamingConvention = nodeNamingConvention;
|
||||
this.utils = utils;
|
||||
this.executor = executor;
|
||||
this.customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory = customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,22 +115,13 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAnd
|
|||
* simultaneously runs the nodes and applies options to them.
|
||||
*/
|
||||
@Override
|
||||
public Map<?, Future<Void>> execute(final String tag, final int count, final Template template,
|
||||
final Set<NodeMetadata> nodes, final Map<NodeMetadata, Exception> badNodes) {
|
||||
Map<String, Future<Void>> responses = Maps.newHashMap();
|
||||
for (final String name : getNextNames(tag, template, count)) {
|
||||
responses.put(name, executor.submit(new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
NodeMetadata node = null;
|
||||
logger.debug(">> starting node(%s) tag(%s)", name, tag);
|
||||
node = addNodeWithTagStrategy.addNodeWithTag(tag, name, template);
|
||||
logger.debug("<< %s node(%s)", node.getState(), node.getId());
|
||||
utils.runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes, nodes,
|
||||
template.getOptions()).call();
|
||||
return null;
|
||||
}
|
||||
}));
|
||||
public Map<?, Future<Void>> execute(String tag, int count, Template template, Set<NodeMetadata> goodNodes,
|
||||
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
|
||||
Map<String, Future<Void>> responses = newLinkedHashMap();
|
||||
for (String name : getNextNames(tag, template, count)) {
|
||||
responses.put(name, compose(executor.submit(new AddNode(name, tag, template)),
|
||||
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory.create(template.getOptions(),
|
||||
goodNodes, badNodes, customizationResponses), executor));
|
||||
}
|
||||
return responses;
|
||||
}
|
||||
|
@ -110,13 +137,13 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAnd
|
|||
* @return
|
||||
*/
|
||||
protected Set<String> getNextNames(final String tag, final Template template, int count) {
|
||||
Set<String> names = Sets.newHashSet();
|
||||
Set<String> names = newLinkedHashSet();
|
||||
Iterable<? extends ComputeMetadata> currentNodes = listNodesStrategy.listNodes();
|
||||
int maxTries = 100;
|
||||
int currentTries = 0;
|
||||
while (names.size() < count && currentTries++ < maxTries) {
|
||||
final String name = getNextName(tag, template);
|
||||
if (!Iterables.any(currentNodes, new Predicate<ComputeMetadata>() {
|
||||
if (!any(currentNodes, new Predicate<ComputeMetadata>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(ComputeMetadata input) {
|
||||
|
|
|
@ -31,12 +31,14 @@ import static org.jclouds.scriptbuilder.domain.Statements.pipeHttpResponseToBash
|
|||
import java.net.URI;
|
||||
import java.util.Formatter;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Named;
|
||||
|
||||
import org.jclouds.compute.ComputeServiceContextBuilder;
|
||||
import org.jclouds.compute.domain.ComputeMetadata;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
|
@ -45,13 +47,13 @@ import org.jclouds.compute.domain.OsFamily;
|
|||
import org.jclouds.compute.domain.Processor;
|
||||
import org.jclouds.compute.domain.Volume;
|
||||
import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.net.IPSocket;
|
||||
import org.jclouds.rest.Providers;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.scriptbuilder.domain.Statements;
|
||||
import org.jclouds.ssh.SshClient;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
|
@ -84,7 +86,7 @@ public class ComputeServiceUtils {
|
|||
*/
|
||||
public static Statement extractTargzIntoDirectory(HttpRequest targz, String directory) {
|
||||
return Statements
|
||||
.extractTargzIntoDirectory(targz.getMethod(), targz.getEndpoint(), targz.getHeaders(), directory);
|
||||
.extractTargzIntoDirectory(targz.getMethod(), targz.getEndpoint(), targz.getHeaders(), directory);
|
||||
}
|
||||
|
||||
public static Statement extractTargzIntoDirectory(URI targz, String directory) {
|
||||
|
@ -104,9 +106,23 @@ public class ComputeServiceUtils {
|
|||
return extractZipIntoDirectory(new HttpRequest("GET", zip), directory);
|
||||
}
|
||||
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected static Logger logger = Logger.NULL;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return NOTAG#+from if tag cannot be parsed
|
||||
*/
|
||||
public static String parseTagFromName(String from) {
|
||||
Matcher matcher = DELIMETED_BY_HYPHEN_ENDING_IN_HYPHEN_HEX.matcher(from);
|
||||
return matcher.find() ? matcher.group(1) : "NOTAG#" + from;
|
||||
String returnVal = matcher.find() ? matcher.group(1) : "NOTAG#" + from;
|
||||
if (logger.isTraceEnabled()) {
|
||||
if (returnVal.startsWith("NOTAG#"))
|
||||
logger.trace("failed to parse tag from name %s", from);
|
||||
}
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
public static double getCores(Hardware input) {
|
||||
|
@ -147,8 +163,8 @@ public class ComputeServiceUtils {
|
|||
Formatter fmt = new Formatter().format("Execution failures:%n%n");
|
||||
int index = 1;
|
||||
for (Entry<?, Exception> errorMessage : executionExceptions.entrySet()) {
|
||||
fmt.format("%s) %s on %s:%n%s%n%n", index++, errorMessage.getValue().getClass().getSimpleName(),
|
||||
errorMessage.getKey(), getStackTraceAsString(errorMessage.getValue()));
|
||||
fmt.format("%s) %s on %s:%n%s%n%n", index++, errorMessage.getValue().getClass().getSimpleName(), errorMessage
|
||||
.getKey(), getStackTraceAsString(errorMessage.getValue()));
|
||||
}
|
||||
return fmt.format("%s error[s]", executionExceptions.size()).toString();
|
||||
}
|
||||
|
@ -158,13 +174,13 @@ public class ComputeServiceUtils {
|
|||
int index = 1;
|
||||
for (Entry<? extends NodeMetadata, ? extends Throwable> errorMessage : failedNodes.entrySet()) {
|
||||
fmt.format("%s) %s on node %s:%n%s%n%n", index++, errorMessage.getValue().getClass().getSimpleName(),
|
||||
errorMessage.getKey().getId(), getStackTraceAsString(errorMessage.getValue()));
|
||||
errorMessage.getKey().getId(), getStackTraceAsString(errorMessage.getValue()));
|
||||
}
|
||||
return fmt.format("%s error[s]", failedNodes.size()).toString();
|
||||
}
|
||||
|
||||
public static Iterable<? extends ComputeMetadata> filterByName(Iterable<? extends ComputeMetadata> nodes,
|
||||
final String name) {
|
||||
final String name) {
|
||||
return filter(nodes, new Predicate<ComputeMetadata>() {
|
||||
@Override
|
||||
public boolean apply(ComputeMetadata input) {
|
||||
|
@ -173,30 +189,23 @@ public class ComputeServiceUtils {
|
|||
});
|
||||
}
|
||||
|
||||
public static interface SshCallable<T> extends Callable<T> {
|
||||
NodeMetadata getNode();
|
||||
|
||||
void setConnection(SshClient ssh, Logger logger);
|
||||
}
|
||||
|
||||
public static Iterable<String> getSupportedProviders() {
|
||||
return Providers.getSupportedProvidersOfType(ComputeServiceContextBuilder.class);
|
||||
}
|
||||
|
||||
public static IPSocket findReachableSocketOnNode(RetryIfSocketNotYetOpen socketTester, final NodeMetadata node,
|
||||
final int port) {
|
||||
final int port) {
|
||||
checkNodeHasIps(node);
|
||||
IPSocket socket = null;
|
||||
try {
|
||||
socket = find(
|
||||
transform(concat(node.getPublicAddresses(), node.getPrivateAddresses()),
|
||||
new Function<String, IPSocket>() {
|
||||
socket = find(transform(concat(node.getPublicAddresses(), node.getPrivateAddresses()),
|
||||
new Function<String, IPSocket>() {
|
||||
|
||||
@Override
|
||||
public IPSocket apply(String from) {
|
||||
return new IPSocket(from, port);
|
||||
}
|
||||
}), socketTester);
|
||||
@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));
|
||||
}
|
||||
|
@ -205,11 +214,11 @@ public class ComputeServiceUtils {
|
|||
|
||||
public static void checkNodeHasIps(NodeMetadata node) {
|
||||
checkState(size(concat(node.getPublicAddresses(), node.getPrivateAddresses())) > 0,
|
||||
"node does not have IP addresses configured: " + node);
|
||||
"node does not have IP addresses configured: " + node);
|
||||
}
|
||||
|
||||
public static String parseVersionOrReturnEmptyString(org.jclouds.compute.domain.OsFamily family, final String in,
|
||||
Map<OsFamily, Map<String, String>> osVersionMap) {
|
||||
Map<OsFamily, Map<String, String>> osVersionMap) {
|
||||
if (osVersionMap.containsKey(family)) {
|
||||
if (osVersionMap.get(family).containsKey(in))
|
||||
return osVersionMap.get(family).get(in);
|
||||
|
|
|
@ -19,53 +19,24 @@
|
|||
|
||||
package org.jclouds.compute.util;
|
||||
|
||||
import static com.google.common.base.Throwables.getRootCause;
|
||||
import static com.google.common.base.Throwables.propagate;
|
||||
import static com.google.common.collect.Iterables.size;
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static com.google.common.collect.Maps.newHashMap;
|
||||
import static org.jclouds.compute.util.ComputeServiceUtils.findReachableSocketOnNode;
|
||||
import static org.jclouds.concurrent.FutureIterables.awaitCompletion;
|
||||
import static com.google.common.collect.Maps.newLinkedHashMap;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.compute.callables.InitAndStartScriptOnNode;
|
||||
import org.jclouds.compute.callables.RunScriptOnNode;
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||
import org.jclouds.compute.options.RunScriptOptions;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen;
|
||||
import org.jclouds.compute.predicates.ScriptStatusReturnsZero.CommandUsingClient;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
|
||||
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
|
||||
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.scriptbuilder.InitBuilder;
|
||||
import org.jclouds.scriptbuilder.domain.AuthorizeRSAPublicKey;
|
||||
import org.jclouds.scriptbuilder.domain.InstallRSAPrivateKey;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
import org.jclouds.scriptbuilder.domain.StatementList;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
import org.jclouds.ssh.SshClient;
|
||||
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -73,168 +44,26 @@ import com.google.inject.Inject;
|
|||
*/
|
||||
@Singleton
|
||||
public class ComputeUtils {
|
||||
@Resource
|
||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||
protected Logger logger = Logger.NULL;
|
||||
protected final Function<NodeMetadata, SshClient> sshFactory;
|
||||
protected final Predicate<CommandUsingClient> runScriptNotRunning;
|
||||
protected final Provider<RetryIfSocketNotYetOpen> socketTester;
|
||||
protected final ExecutorService executor;
|
||||
protected final Predicate<NodeMetadata> nodeRunning;
|
||||
protected final GetNodeMetadataStrategy getNode;
|
||||
protected final Timeouts timeouts;
|
||||
private final CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
|
||||
private final ExecutorService executor;
|
||||
|
||||
@Inject
|
||||
public ComputeUtils(Provider<RetryIfSocketNotYetOpen> socketTester, Function<NodeMetadata, SshClient> sshFactory,
|
||||
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning, GetNodeMetadataStrategy getNode,
|
||||
Timeouts timeouts, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||
this.sshFactory = sshFactory;
|
||||
this.nodeRunning = nodeRunning;
|
||||
this.timeouts = timeouts;
|
||||
this.getNode = getNode;
|
||||
this.socketTester = socketTester;
|
||||
this.runScriptNotRunning = runScriptNotRunning;
|
||||
public ComputeUtils(
|
||||
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
|
||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||
this.customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory = customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
public Map<?, Future<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(final TemplateOptions options,
|
||||
Iterable<NodeMetadata> runningNodes, final Set<NodeMetadata> goodNodes,
|
||||
final Map<NodeMetadata, Exception> badNodes) {
|
||||
Map<NodeMetadata, Future<Void>> responses = newHashMap();
|
||||
for (final NodeMetadata node : runningNodes) {
|
||||
responses.put(node, executor.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes,
|
||||
goodNodes, options)));
|
||||
public Map<?, Future<Void>> customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(TemplateOptions options,
|
||||
Iterable<NodeMetadata> runningNodes, Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
|
||||
Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
|
||||
Map<NodeMetadata, Future<Void>> responses = newLinkedHashMap();
|
||||
for (NodeMetadata node : runningNodes) {
|
||||
responses.put(node, executor.submit(customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory.create(
|
||||
options, node, goodNodes, badNodes, customizationResponses)));
|
||||
}
|
||||
return responses;
|
||||
}
|
||||
|
||||
public Callable<Void> runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(final NodeMetadata node,
|
||||
final Map<NodeMetadata, Exception> badNodes, final Set<NodeMetadata> goodNodes, final TemplateOptions options) {
|
||||
return new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
try {
|
||||
NodeMetadata node1 = runOptionsOnNode(node, options);
|
||||
logger.debug("<< options applied node(%s)", node1.getId());
|
||||
goodNodes.add(node1);
|
||||
} catch (Exception e) {
|
||||
logger.error(e, "<< problem applying options to node(%s): ", node.getId(), getRootCause(e).getMessage());
|
||||
badNodes.put(node, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public NodeMetadata runOptionsOnNode(NodeMetadata node, TemplateOptions options) {
|
||||
if (!options.shouldBlockUntilRunning())
|
||||
return node;
|
||||
|
||||
if (nodeRunning.apply(node))
|
||||
node = NodeMetadataBuilder.fromNodeMetadata(getNode.getNode(node.getId())).credentials(node.getCredentials())
|
||||
.build();
|
||||
else
|
||||
throw new IllegalStateException(String.format(
|
||||
"node didn't achieve the state running on node %s within %d seconds, final state: %s", node.getId(),
|
||||
timeouts.nodeRunning / 1000, node.getState()));
|
||||
List<Statement> bootstrap = newArrayList();
|
||||
if (options.getPublicKey() != null)
|
||||
bootstrap.add(new AuthorizeRSAPublicKey(options.getPublicKey()));
|
||||
if (options.getRunScript() != null)
|
||||
bootstrap.add(options.getRunScript());
|
||||
if (options.getPrivateKey() != null)
|
||||
bootstrap.add(new InstallRSAPrivateKey(options.getPrivateKey()));
|
||||
if (bootstrap.size() >= 1) {
|
||||
if (options.getTaskName() == null && !(options.getRunScript() instanceof InitBuilder))
|
||||
options.nameTask("bootstrap");
|
||||
runScriptOnNode(node, bootstrap.size() == 1 ? bootstrap.get(0) : new StatementList(bootstrap), options);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
public ExecResponse runScriptOnNode(NodeMetadata node, Statement runScript, RunScriptOptions options) {
|
||||
InitAndStartScriptOnNode callable = generateScript(node, runScript, options);
|
||||
ExecResponse response;
|
||||
SshClient ssh = sshFactory.apply(node);
|
||||
try {
|
||||
ssh.connect();
|
||||
callable.setConnection(ssh, logger);
|
||||
response = callable.call();
|
||||
} finally {
|
||||
if (ssh != null)
|
||||
ssh.disconnect();
|
||||
}
|
||||
if (options.getPort() > 0) {
|
||||
findReachableSocketOnNode(socketTester.get().seconds(options.getSeconds()), node, options.getPort());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
public InitAndStartScriptOnNode generateScript(NodeMetadata node, Statement script, RunScriptOptions options) {
|
||||
return options.shouldBlockOnComplete() ? new RunScriptOnNode(runScriptNotRunning, node, options.getTaskName(),
|
||||
script, options.shouldRunAsRoot()) : new InitAndStartScriptOnNode(node, options.getTaskName(), script,
|
||||
options.shouldRunAsRoot());
|
||||
}
|
||||
|
||||
public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node, Iterable<SshCallable<?>> parallel,
|
||||
@Nullable SshCallable<?> last) {
|
||||
SshClient ssh = sshFactory.apply(node);
|
||||
try {
|
||||
ssh.connect();
|
||||
return runTasksUsingSshClient(parallel, last, ssh);
|
||||
} finally {
|
||||
if (ssh != null)
|
||||
ssh.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<SshCallable<?>, ?> runTasksUsingSshClient(Iterable<SshCallable<?>> parallel, SshCallable<?> last,
|
||||
SshClient ssh) {
|
||||
Map<SshCallable<?>, Object> responses = newHashMap();
|
||||
if (size(parallel) > 0) {
|
||||
responses.putAll(runCallablesUsingSshClient(parallel, ssh));
|
||||
}
|
||||
if (last != null) {
|
||||
last.setConnection(ssh, logger);
|
||||
try {
|
||||
responses.put(last, last.call());
|
||||
} catch (Exception e) {
|
||||
propagate(e);
|
||||
}
|
||||
}
|
||||
return responses;
|
||||
}
|
||||
|
||||
// TODO refactor
|
||||
private Map<SshCallable<?>, Object> runCallablesUsingSshClient(Iterable<SshCallable<?>> parallel, SshClient ssh) {
|
||||
Map<SshCallable<?>, Future<?>> parallelResponses = newHashMap();
|
||||
|
||||
for (SshCallable<?> callable : parallel) {
|
||||
callable.setConnection(ssh, logger);
|
||||
parallelResponses.put(callable, executor.submit(callable));
|
||||
}
|
||||
|
||||
Map<SshCallable<?>, Exception> exceptions = awaitCompletion(parallelResponses, executor, null, logger, "ssh");
|
||||
if (exceptions.size() > 0)
|
||||
throw new RuntimeException(String.format("error invoking callables on nodes: %s", exceptions));
|
||||
Map<SshCallable<?>, Object> newresponses = transform(parallelResponses);
|
||||
return newresponses;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Map<SshCallable<?>, T> transform(Map<SshCallable<?>, Future<?>> responses) {
|
||||
Map<SshCallable<?>, T> actualResponses = newHashMap();
|
||||
for (Map.Entry<SshCallable<?>, Future<?>> entry : responses.entrySet()) {
|
||||
try {
|
||||
actualResponses.put(entry.getKey(), (T) entry.getValue().get());
|
||||
} catch (InterruptedException e) {
|
||||
throw propagate(e);
|
||||
} catch (ExecutionException e) {
|
||||
throw propagate(e);
|
||||
}
|
||||
}
|
||||
return actualResponses;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,10 +19,12 @@
|
|||
|
||||
package org.jclouds.ssh;
|
||||
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ExecResponse {
|
||||
public class ExecResponse implements CustomizationResponse {
|
||||
|
||||
private final String error;
|
||||
private final String output;
|
||||
|
|
|
@ -38,7 +38,6 @@ import static org.jclouds.compute.predicates.NodePredicates.all;
|
|||
import static org.jclouds.compute.predicates.NodePredicates.runningWithTag;
|
||||
import static org.jclouds.compute.predicates.NodePredicates.withTag;
|
||||
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
|
||||
import static org.jclouds.io.Payloads.newStringPayload;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
|
@ -75,7 +74,6 @@ import org.jclouds.predicates.RetryablePredicate;
|
|||
import org.jclouds.predicates.SocketOpen;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.jclouds.rest.RestContextFactory;
|
||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||
import org.jclouds.ssh.ExecResponse;
|
||||
import org.jclouds.ssh.SshClient;
|
||||
import org.jclouds.ssh.SshException;
|
||||
|
@ -159,8 +157,8 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
if (context != null)
|
||||
context.close();
|
||||
Properties props = setupProperties();
|
||||
context = new ComputeServiceContextFactory(getRestProperties()).createContext(provider,
|
||||
ImmutableSet.of(new Log4JLoggingModule(), getSshModule()), props);
|
||||
context = new ComputeServiceContextFactory(getRestProperties()).createContext(provider, ImmutableSet.of(
|
||||
new Log4JLoggingModule(), getSshModule()), props);
|
||||
client = context.getComputeService();
|
||||
}
|
||||
|
||||
|
@ -180,8 +178,8 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
public void testCorrectAuthException() throws Exception {
|
||||
ComputeServiceContext context = null;
|
||||
try {
|
||||
context = new ComputeServiceContextFactory().createContext(provider, "MOMMA", "MIA",
|
||||
ImmutableSet.<Module> of(new Log4JLoggingModule()));
|
||||
context = new ComputeServiceContextFactory().createContext(provider, "MOMMA", "MIA", ImmutableSet
|
||||
.<Module> of(new Log4JLoggingModule()));
|
||||
context.getComputeService().listNodes();
|
||||
} catch (AuthorizationException e) {
|
||||
throw e;
|
||||
|
@ -224,7 +222,7 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
OperatingSystem os = get(nodes, 0).getOperatingSystem();
|
||||
try {
|
||||
Map<? extends NodeMetadata, ExecResponse> responses = runScriptWithCreds(tag, os, new Credentials(
|
||||
good.identity, "romeo"));
|
||||
good.identity, "romeo"));
|
||||
assert false : "shouldn't pass with a bad password\n" + responses;
|
||||
} catch (RunScriptOnNodesException e) {
|
||||
assert getRootCause(e).getMessage().contains("Auth fail") : e;
|
||||
|
@ -283,7 +281,7 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
template = buildTemplate(client.templateBuilder());
|
||||
|
||||
template.getOptions().installPrivateKey(keyPair.get("private")).authorizePublicKey(keyPair.get("public"))
|
||||
.runScript(buildScript(template.getImage().getOperatingSystem()));
|
||||
.runScript(buildScript(template.getImage().getOperatingSystem()));
|
||||
}
|
||||
|
||||
protected void checkImageIdMatchesTemplate(NodeMetadata node) {
|
||||
|
@ -294,8 +292,8 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
protected void checkOsMatchesTemplate(NodeMetadata node) {
|
||||
if (node.getOperatingSystem() != null)
|
||||
assert node.getOperatingSystem().getFamily().equals(template.getImage().getOperatingSystem().getFamily()) : String
|
||||
.format("expecting family %s but got %s", template.getImage().getOperatingSystem().getFamily(),
|
||||
node.getOperatingSystem());
|
||||
.format("expecting family %s but got %s", template.getImage().getOperatingSystem().getFamily(), node
|
||||
.getOperatingSystem());
|
||||
}
|
||||
|
||||
void assertLocationSameOrChild(Location test, Location expected) {
|
||||
|
@ -327,11 +325,10 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
}
|
||||
|
||||
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(final String tag, OperatingSystem os,
|
||||
Credentials creds) throws RunScriptOnNodesException {
|
||||
Credentials creds) throws RunScriptOnNodesException {
|
||||
try {
|
||||
return client.runScriptOnNodesMatching(runningWithTag(tag),
|
||||
newStringPayload(buildScript(os).render(OsFamily.UNIX)),
|
||||
overrideCredentialsWith(creds).nameTask("runScriptWithCreds"));
|
||||
return client.runScriptOnNodesMatching(runningWithTag(tag), buildScript(os), overrideCredentialsWith(creds)
|
||||
.nameTask("runScriptWithCreds"));
|
||||
} catch (SshException e) {
|
||||
throw e;
|
||||
}
|
||||
|
@ -361,16 +358,16 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
|
||||
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
|
||||
public void testGet() throws Exception {
|
||||
Map<String, ? extends NodeMetadata> metadataMap = newLinkedHashMap(uniqueIndex(
|
||||
filter(client.listNodesDetailsMatching(all()), and(withTag(tag), not(TERMINATED))),
|
||||
new Function<NodeMetadata, String>() {
|
||||
Map<String, ? extends NodeMetadata> metadataMap = newLinkedHashMap(uniqueIndex(filter(client
|
||||
.listNodesDetailsMatching(all()), and(withTag(tag), not(TERMINATED))),
|
||||
new Function<NodeMetadata, String>() {
|
||||
|
||||
@Override
|
||||
public String apply(NodeMetadata from) {
|
||||
return from.getId();
|
||||
}
|
||||
@Override
|
||||
public String apply(NodeMetadata from) {
|
||||
return from.getId();
|
||||
}
|
||||
|
||||
}));
|
||||
}));
|
||||
for (NodeMetadata node : nodes) {
|
||||
metadataMap.remove(node.getId());
|
||||
NodeMetadata metadata = client.getNodeMetadata(node.getId());
|
||||
|
@ -389,7 +386,7 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
|
||||
protected void assertNodeZero(Collection<? extends NodeMetadata> metadataSet) {
|
||||
assert metadataSet.size() == 0 : String.format("nodes left in set: [%s] which didn't match set: [%s]",
|
||||
metadataSet, nodes);
|
||||
metadataSet, nodes);
|
||||
}
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "testGet")
|
||||
|
@ -453,7 +450,9 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
|
||||
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" })
|
||||
public void testDestroyNodes() {
|
||||
client.destroyNodesMatching(withTag(tag));
|
||||
int toDestroy = refreshNodes().size();
|
||||
Set<? extends NodeMetadata> destroyed = client.destroyNodesMatching(withTag(tag));
|
||||
assertEquals(toDestroy, destroyed.size());
|
||||
for (NodeMetadata node : filter(client.listNodesDetailsMatching(all()), withTag(tag))) {
|
||||
assert node.getState() == NodeState.TERMINATED : node;
|
||||
assertEquals(context.getCredentialStore().get("node#" + node.getId()), null);
|
||||
|
@ -475,12 +474,12 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
}
|
||||
|
||||
template = client.templateBuilder().options(blockOnComplete(false).blockOnPort(8080, 600).inboundPorts(22, 8080))
|
||||
.build();
|
||||
.build();
|
||||
|
||||
// note this is a dependency on the template resolution
|
||||
template.getOptions().runScript(
|
||||
RunScriptData.createScriptInstallAndStartJBoss(keyPair.get("public"), template.getImage()
|
||||
.getOperatingSystem()));
|
||||
RunScriptData.createScriptInstallAndStartJBoss(keyPair.get("public"), template.getImage()
|
||||
.getOperatingSystem()));
|
||||
try {
|
||||
NodeMetadata node = getOnlyElement(client.runNodesWithTag(tag, 1, template));
|
||||
|
||||
|
@ -514,26 +513,26 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
assert location != location.getParent() : location;
|
||||
assert location.getScope() != null : location;
|
||||
switch (location.getScope()) {
|
||||
case PROVIDER:
|
||||
assertProvider(location);
|
||||
break;
|
||||
case REGION:
|
||||
assertProvider(location.getParent());
|
||||
break;
|
||||
case ZONE:
|
||||
Location provider = location.getParent().getParent();
|
||||
// zone can be a direct descendant of provider
|
||||
if (provider == null)
|
||||
provider = location.getParent();
|
||||
assertProvider(provider);
|
||||
break;
|
||||
case HOST:
|
||||
Location provider2 = location.getParent().getParent().getParent();
|
||||
// zone can be a direct descendant of provider
|
||||
if (provider2 == null)
|
||||
provider2 = location.getParent().getParent();
|
||||
assertProvider(provider2);
|
||||
break;
|
||||
case PROVIDER:
|
||||
assertProvider(location);
|
||||
break;
|
||||
case REGION:
|
||||
assertProvider(location.getParent());
|
||||
break;
|
||||
case ZONE:
|
||||
Location provider = location.getParent().getParent();
|
||||
// zone can be a direct descendant of provider
|
||||
if (provider == null)
|
||||
provider = location.getParent();
|
||||
assertProvider(provider);
|
||||
break;
|
||||
case HOST:
|
||||
Location provider2 = location.getParent().getParent().getParent();
|
||||
// zone can be a direct descendant of provider
|
||||
if (provider2 == null)
|
||||
provider2 = location.getParent().getParent();
|
||||
assertProvider(provider2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -621,7 +620,7 @@ public abstract class BaseComputeServiceLiveTest {
|
|||
assertEquals(hello.getOutput().trim(), "hello");
|
||||
ExecResponse exec = ssh.exec("java -version");
|
||||
assert exec.getError().indexOf("1.6") != -1 || exec.getOutput().indexOf("1.6") != -1 : exec + "\n"
|
||||
+ ssh.exec("cat /tmp/bootstrap/stdout.log /tmp/bootstrap/stderr.log");
|
||||
+ ssh.exec("cat /tmp/bootstrap/stdout.log /tmp/bootstrap/stderr.log");
|
||||
} finally {
|
||||
if (ssh != null)
|
||||
ssh.disconnect();
|
||||
|
|
|
@ -361,17 +361,17 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
|||
super.testTemplateMatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
|
||||
public void testGetNodesWithDetails() throws Exception {
|
||||
super.testGetNodesWithDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test(enabled = true, dependsOnMethods = "testSuspendResume")
|
||||
public void testListNodes() throws Exception {
|
||||
super.testListNodes();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" })
|
||||
public void testDestroyNodes() {
|
||||
super.testDestroyNodes();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.jclouds.compute.util;
|
||||
|
||||
import static org.jclouds.compute.util.ComputeServiceUtils.parseTagFromName;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
|
@ -38,6 +39,11 @@ import com.google.common.collect.ImmutableMultimap;
|
|||
@Test(groups = "unit")
|
||||
public class ComputeServiceUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testParseTagFromName() {
|
||||
assertEquals(parseTagFromName("gogrid--849"), "gogrid-");
|
||||
|
||||
}
|
||||
@Test
|
||||
public void testExecHttpResponse() {
|
||||
HttpRequest request = new HttpRequest("GET", URI.create("https://adriancolehappy.s3.amazonaws.com/java/install"),
|
||||
|
|
|
@ -83,7 +83,6 @@ echo nameserver 208.67.222.222 >> /etc/resolv.conf
|
|||
rm -rf /var/cache/apt /usr/lib/vmware-tools
|
||||
echo "export PATH=\"\$JAVA_HOME/bin/:\$PATH\"" >> /root/.bashrc
|
||||
|
||||
|
||||
END_OF_SCRIPT
|
||||
|
||||
# add runscript footer
|
||||
|
|
|
@ -78,6 +78,11 @@
|
|||
<artifactId>jersey-core</artifactId>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-assistedinject</artifactId>
|
||||
<version>3.0-rc2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
|
|
|
@ -75,7 +75,7 @@ public class AWSEC2TemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
|
|||
assertEquals(template.getImage().getOperatingSystem().getVersion(), "10.10");
|
||||
assertEquals(template.getImage().getOperatingSystem().is64Bit(), false);
|
||||
assertEquals(template.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
||||
assertEquals(template.getImage().getVersion(), "20110115");
|
||||
assertEquals(template.getImage().getVersion(), "20110122");
|
||||
assertEquals(template.getImage().getUserMetadata().get("rootDeviceType"), "instance-store");
|
||||
assertEquals(template.getLocation().getId(), "us-east-1");
|
||||
assertEquals(getCores(template.getHardware()), 1.0d);
|
||||
|
|
|
@ -50,9 +50,9 @@ public class GoGridTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
|
|||
@Override
|
||||
public boolean apply(OsFamilyVersion64Bit input) {
|
||||
return ((input.family == OsFamily.RHEL && !input.version.equals("5.4")) || //
|
||||
(input.family == OsFamily.CENTOS && input.version.matches("5.[542]")) || //
|
||||
(input.family == OsFamily.CENTOS && input.is64Bit && input.version.equals("5.[42]")) || //
|
||||
(input.family == OsFamily.UBUNTU) || //
|
||||
(input.family == OsFamily.CENTOS && input.version.matches("5.[542]")) || //
|
||||
(input.family == OsFamily.CENTOS && input.is64Bit && input.version.equals("5.[42]")) || //
|
||||
(input.family == OsFamily.UBUNTU) || //
|
||||
(input.family == OsFamily.WINDOWS && input.version.equals("2008 SP2") || //
|
||||
(input.family == OsFamily.WINDOWS && input.version.equals("2008 R2"))));
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ public class SkaliCloudMalaysiaComputeServiceLiveTest extends ElasticStackComput
|
|||
|
||||
public SkaliCloudMalaysiaComputeServiceLiveTest() {
|
||||
provider = "skalicloud-sdg-my";
|
||||
tag = "skalicloud";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,11 +19,14 @@
|
|||
|
||||
package org.jclouds.slicehost.compute.config;
|
||||
|
||||
import static org.jclouds.compute.domain.OsFamily.UBUNTU;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.compute.config.BaseComputeServiceContextModule;
|
||||
import org.jclouds.compute.domain.TemplateBuilder;
|
||||
import org.jclouds.compute.internal.BaseComputeService;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.domain.LocationScope;
|
||||
|
@ -31,6 +34,7 @@ import org.jclouds.domain.internal.LocationImpl;
|
|||
import org.jclouds.location.Provider;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
|
@ -39,6 +43,10 @@ import com.google.inject.Provides;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
public class SlicehostComputeServiceContextModule extends BaseComputeServiceContextModule {
|
||||
@Override
|
||||
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
|
||||
return template.osFamily(UBUNTU).osVersionMatches("10.04").osDescriptionMatches("^((?!MGC).)*$").os64Bit(true);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
|
|
|
@ -50,7 +50,7 @@ public class TerremarkVCloudExpressTemplateBuilderLiveTest extends BaseTemplateB
|
|||
@Override
|
||||
public boolean apply(OsFamilyVersion64Bit input) {
|
||||
return ((input.family == OsFamily.RHEL || input.family == OsFamily.CENTOS) || //
|
||||
(input.family == OsFamily.UBUNTU && !input.version.equals("9.10")) || //
|
||||
(input.family == OsFamily.UBUNTU && !input.version.equals("9.10")) || //
|
||||
(input.family == OsFamily.WINDOWS && (input.version.equals("2008 SP2") || input.version.equals("2008 R2"))));
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,6 @@ public class TerremarkVCloudExpressTemplateBuilderLiveTest extends BaseTemplateB
|
|||
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
|
||||
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
||||
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
|
||||
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.
|
||||
====================================================================
|
||||
-->
|
||||
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
|
||||
|
||||
<!--
|
||||
For more configuration infromation and examples see the Apache
|
||||
Log4j website: http://logging.apache.org/log4j/
|
||||
-->
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
|
||||
debug="false">
|
||||
|
||||
<!-- A time/date based rolling appender -->
|
||||
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
|
||||
<param name="File" value="target/test-data/jclouds-wire.log" />
|
||||
<param name="Append" value="true" />
|
||||
|
||||
<!-- Rollover at midnight each day -->
|
||||
<param name="DatePattern" value="'.'yyyy-MM-dd" />
|
||||
|
||||
<param name="Threshold" value="TRACE" />
|
||||
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<!-- The default pattern: Date Priority [Category] Message\n -->
|
||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message\n <param name="ConversionPattern"
|
||||
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
|
||||
-->
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<!-- A time/date based rolling appender -->
|
||||
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
|
||||
<param name="File" value="target/test-data/jclouds.log" />
|
||||
<param name="Append" value="true" />
|
||||
|
||||
<!-- Rollover at midnight each day -->
|
||||
<param name="DatePattern" value="'.'yyyy-MM-dd" />
|
||||
|
||||
<param name="Threshold" value="TRACE" />
|
||||
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<!-- The default pattern: Date Priority [Category] Message\n -->
|
||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message\n <param name="ConversionPattern"
|
||||
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
|
||||
-->
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<!-- A time/date based rolling appender -->
|
||||
<appender name="COMPUTEFILE" class="org.apache.log4j.DailyRollingFileAppender">
|
||||
<param name="File" value="target/test-data/jclouds-compute.log" />
|
||||
<param name="Append" value="true" />
|
||||
|
||||
<!-- Rollover at midnight each day -->
|
||||
<param name="DatePattern" value="'.'yyyy-MM-dd" />
|
||||
|
||||
<param name="Threshold" value="TRACE" />
|
||||
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<!-- The default pattern: Date Priority [Category] Message\n -->
|
||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message\n <param name="ConversionPattern"
|
||||
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
|
||||
-->
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<!-- A time/date based rolling appender -->
|
||||
<appender name="SSHFILE" class="org.apache.log4j.DailyRollingFileAppender">
|
||||
<param name="File" value="target/test-data/jclouds-ssh.log" />
|
||||
<param name="Append" value="true" />
|
||||
|
||||
<!-- Rollover at midnight each day -->
|
||||
<param name="DatePattern" value="'.'yyyy-MM-dd" />
|
||||
|
||||
<param name="Threshold" value="TRACE" />
|
||||
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<!-- The default pattern: Date Priority [Category] Message\n -->
|
||||
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
|
||||
|
||||
<!--
|
||||
The full pattern: Date MS Priority [Category]
|
||||
(Thread:NDC) Message\n <param name="ConversionPattern"
|
||||
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
|
||||
-->
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNCCOMPUTE" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="COMPUTEFILE" />
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNCSSH" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="SSHFILE" />
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="FILE" />
|
||||
</appender>
|
||||
|
||||
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
|
||||
<appender-ref ref="WIREFILE" />
|
||||
</appender>
|
||||
|
||||
<!-- ================ -->
|
||||
<!-- Limit categories -->
|
||||
<!-- ================ -->
|
||||
|
||||
<category name="org.jclouds">
|
||||
<priority value="DEBUG" />
|
||||
<appender-ref ref="ASYNC" />
|
||||
</category>
|
||||
|
||||
<category name="jclouds.headers">
|
||||
<priority value="DEBUG" />
|
||||
<appender-ref ref="ASYNCWIRE" />
|
||||
</category>
|
||||
|
||||
<category name="jclouds.ssh">
|
||||
<priority value="DEBUG" />
|
||||
<appender-ref ref="ASYNCSSH" />
|
||||
</category>
|
||||
|
||||
<category name="jclouds.wire">
|
||||
<priority value="DEBUG" />
|
||||
<appender-ref ref="ASYNCWIRE" />
|
||||
</category>
|
||||
|
||||
<category name="jclouds.compute">
|
||||
<priority value="TRACE" />
|
||||
<appender-ref ref="ASYNCCOMPUTE" />
|
||||
</category>
|
||||
<!-- ======================= -->
|
||||
<!-- Setup the Root category -->
|
||||
<!-- ======================= -->
|
||||
|
||||
<root>
|
||||
<priority value="WARN" />
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
Loading…
Reference in New Issue