added exceptions to ssh commands and changed interface to not index on id, since ids are not guaranteed unique

This commit is contained in:
Adrian Cole 2010-05-04 15:01:01 -07:00
parent 0d61930192
commit 239519c8ca
70 changed files with 1292 additions and 694 deletions

View File

@ -22,7 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.compose; import static com.google.common.util.concurrent.Futures.compose;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -80,7 +80,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
@Inject @Inject
AtmosAsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, AtmosAsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Map<String, ? extends Location> locations, Location defaultLocation, Set<? extends Location> locations,
AtmosStorageAsyncClient async, AtmosStorageClient sync, ObjectToBlob object2Blob, AtmosStorageAsyncClient async, AtmosStorageClient sync, ObjectToBlob object2Blob,
ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,

View File

@ -20,7 +20,7 @@ package org.jclouds.atmosonline.saas.blobstore;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Provider; import javax.inject.Provider;
@ -65,8 +65,8 @@ public class AtmosBlobStore extends BaseBlobStore {
@Inject @Inject
AtmosBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, Location defaultLocation, AtmosBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, Location defaultLocation,
Map<String, ? extends Location> locations, AtmosStorageClient sync, Set<? extends Location> locations, AtmosStorageClient sync, ObjectToBlob object2Blob,
ObjectToBlob object2Blob, ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
BlobStoreListOptionsToListOptions container2ContainerListOptions, BlobStoreListOptionsToListOptions container2ContainerListOptions,
DirectoryEntryListToResourceMetadataList container2ResourceList, DirectoryEntryListToResourceMetadataList container2ResourceList,
EncryptionService encryptionService, BlobToHttpGetOptions blob2ObjectGetOptions, EncryptionService encryptionService, BlobToHttpGetOptions blob2ObjectGetOptions,

View File

@ -18,7 +18,7 @@
*/ */
package org.jclouds.atmosonline.saas.blobstore.config; package org.jclouds.atmosonline.saas.blobstore.config;
import java.util.Map; import java.util.Set;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -39,7 +39,7 @@ import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; import org.jclouds.domain.internal.LocationImpl;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.Scopes; import com.google.inject.Scopes;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -78,7 +78,7 @@ public class AtmosBlobStoreContextModule extends AtmosStorageContextModule {
@Provides @Provides
@Singleton @Singleton
Map<String, ? extends Location> provideLocations(Location location) { Set<? extends Location> provideLocations(Location location) {
return ImmutableMap.of(location.getId(), location); return ImmutableSet.of(location);
} }
} }

View File

@ -19,6 +19,7 @@
package org.jclouds.aws.ec2.compute; package org.jclouds.aws.ec2.compute;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.inject.Inject; import javax.inject.Inject;
@ -64,10 +65,9 @@ public class EC2ComputeService extends BaseComputeService {
@Inject @Inject
protected EC2ComputeService(ComputeServiceContext context, protected EC2ComputeService(ComputeServiceContext context,
Provider<Map<String, ? extends Image>> images, Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
Provider<Map<String, ? extends Size>> sizes, Provider<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
Provider<Map<String, ? extends Location>> locations, GetNodeMetadataStrategy getNodeMetadataStrategy,
ListNodesStrategy listNodesStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy, RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy, RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, ComputeUtils utils, Provider<TemplateBuilder> templateBuilderProvider, ComputeUtils utils,
@ -101,7 +101,7 @@ public class EC2ComputeService extends BaseComputeService {
logger.debug(">> deleting keyPair(%s)", tag); logger.debug(">> deleting keyPair(%s)", tag);
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName()); ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName());
credentialsMap.remove(new RegionTag(region, keyPair.getKeyName())); // TODO: test this credentialsMap.remove(new RegionTag(region, keyPair.getKeyName())); // TODO: test this
// clear happens // clear happens
logger.debug("<< deleted keyPair(%s)", keyPair.getKeyName()); logger.debug("<< deleted keyPair(%s)", keyPair.getKeyName());
} }
} }
@ -110,7 +110,7 @@ public class EC2ComputeService extends BaseComputeService {
@Override @Override
public void destroyNodesWithTag(String tag) { public void destroyNodesWithTag(String tag) {
super.destroyNodesWithTag(tag); super.destroyNodesWithTag(tag);
Iterable<? extends NodeMetadata> nodes = Iterables.filter(getNodesWithTag(tag).values(), Iterable<? extends NodeMetadata> nodes = Iterables.filter(listNodesWithTag(tag),
new Predicate<NodeMetadata>() { new Predicate<NodeMetadata>() {
@Override @Override
public boolean apply(NodeMetadata input) { public boolean apply(NodeMetadata input) {

View File

@ -254,32 +254,37 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides @Provides
@Singleton @Singleton
Map<String, ? extends Size> provideSizes(Function<ComputeMetadata, String> indexer) { Set<? extends Size> provideSizes() {
return Maps.uniqueIndex(ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, return ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
EC2Size.M1_LARGE, EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_XLARGE, EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE,
EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE), indexer); EC2Size.M2_4XLARGE);
} }
@Provides @Provides
@Singleton @Singleton
Map<String, ? extends Location> provideLocations(Map<String, String> availabilityZoneToRegionMap) { Set<? extends Location> provideLocations(Map<String, String> availabilityZoneToRegionMap) {
Location ec2 = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null); Location ec2 = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
Map<String, Location> locations = Maps.newLinkedHashMap(); Set<Location> locations = Sets.newLinkedHashSet();
for (String region : availabilityZoneToRegionMap.values()) {
locations.put(region, new LocationImpl(LocationScope.REGION, region, region, ec2));
}
for (String zone : availabilityZoneToRegionMap.keySet()) { for (String zone : availabilityZoneToRegionMap.keySet()) {
locations.put(zone, new LocationImpl(LocationScope.ZONE, zone, zone, locations Location region = new LocationImpl(LocationScope.REGION, availabilityZoneToRegionMap
.get(availabilityZoneToRegionMap.get(zone)))); .get(zone), availabilityZoneToRegionMap.get(zone), ec2);
locations.add(region);
locations.add(new LocationImpl(LocationScope.ZONE, zone, zone, region));
} }
return locations; return locations;
} }
@Provides @Provides
@Singleton @Singleton
Location getDefaultLocation(@EC2 String region, Map<String, ? extends Location> map) { Location getDefaultLocation(@EC2 final String region, Set<? extends Location> set) {
return map.get(region); return Iterables.find(set, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(region);
}
});
} }
private static class LogHolder { private static class LogHolder {
@ -297,7 +302,7 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides @Provides
@Singleton @Singleton
protected Map<String, ? extends Image> provideImages(final EC2Client sync, protected Set<? extends Image> provideImages(final EC2Client sync,
@EC2 Map<String, URI> regionMap, LogHolder holder, @EC2 Map<String, URI> regionMap, LogHolder holder,
Function<ComputeMetadata, String> indexer, Function<ComputeMetadata, String> indexer,
@Named(PROPERTY_EC2_AMI_OWNERS) String[] amiOwners, ImageParser parser) @Named(PROPERTY_EC2_AMI_OWNERS) String[] amiOwners, ImageParser parser)
@ -316,6 +321,6 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
} }
} }
holder.logger.debug("<< images(%d)", images.size()); holder.logger.debug("<< images(%d)", images.size());
return Maps.uniqueIndex(images, indexer); return images;
} }
} }

View File

@ -21,6 +21,8 @@ package org.jclouds.aws.ec2.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -38,10 +40,14 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy; import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -61,18 +67,21 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
.build(); .build();
private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider; private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider;
private final Map<String, ? extends Location> locations; private final Set<? extends Location> locations;
private final Location defaultLocation;
@Inject @Inject
ImageParser(PopulateDefaultLoginCredentialsForImageStrategy credentialProvider, ImageParser(PopulateDefaultLoginCredentialsForImageStrategy credentialProvider,
Map<String, ? extends Location> locations) { Set<? extends Location> locations, Location defaultLocation) {
this.credentialProvider = checkNotNull(credentialProvider, "credentialProvider"); this.credentialProvider = checkNotNull(credentialProvider, "credentialProvider");
this.locations = checkNotNull(locations, "locations"); this.locations = checkNotNull(locations, "locations");
this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation");
} }
@Override @Override
public Image apply(org.jclouds.aws.ec2.domain.Image from) { public Image apply(final org.jclouds.aws.ec2.domain.Image from) {
if (from.getImageLocation().indexOf("test") != -1) { if (from.getImageLocation().indexOf("test") != -1) {
logger.trace("skipping test image(%s)", from.getId()); logger.trace("skipping test image(%s)", from.getId());
return null; return null;
@ -102,10 +111,26 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
} }
Credentials defaultCredentials = credentialProvider.execute(from); Credentials defaultCredentials = credentialProvider.execute(from);
Location location = null;
try {
location = Iterables.find(locations, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(from.getRegion());
}
});
} catch (NoSuchElementException e) {
System.err.printf("unknown region %s for image %s; not in %s", from.getRegion(), from
.getId(), locations);
location = new LocationImpl(LocationScope.REGION, from.getRegion(), from.getRegion(),
defaultLocation.getParent());
}
return new ImageImpl( return new ImageImpl(
from.getId(), from.getId(),
name, name,
locations.get(from.getRegion()), location,
null, null,
ImmutableMap.<String, String> of("owner", from.getImageOwnerId()), ImmutableMap.<String, String> of("owner", from.getImageOwnerId()),
description, description,
@ -114,5 +139,6 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
osDescription, osDescription,
from.getArchitecture() == org.jclouds.aws.ec2.domain.Image.Architecture.I386 ? Architecture.X86_32 from.getArchitecture() == org.jclouds.aws.ec2.domain.Image.Architecture.I386 ? Architecture.X86_32
: Architecture.X86_64, defaultCredentials); : Architecture.X86_64, defaultCredentials);
} }
} }

View File

@ -24,8 +24,10 @@ import static org.jclouds.util.Utils.nullSafeSet;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -43,9 +45,11 @@ import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy; import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -55,6 +59,27 @@ import com.google.common.collect.Maps;
*/ */
@Singleton @Singleton
public class RunningInstanceToNodeMetadata implements Function<RunningInstance, NodeMetadata> { public class RunningInstanceToNodeMetadata implements Function<RunningInstance, NodeMetadata> {
@Resource
protected Logger logger = Logger.NULL;
private static class FindImageForInstance implements Predicate<Image> {
private final Location location;
private final RunningInstance instance;
private FindImageForInstance(Location location, RunningInstance instance) {
this.location = location;
this.instance = instance;
}
@Override
public boolean apply(Image input) {
return input.getId().equals(instance.getImageId())
&& (input.getLocation() == null || input.getLocation().equals(location) || input
.getLocation().equals(location.getParent()));
}
}
private static final Map<InstanceState, NodeState> instanceToNodeState = ImmutableMap private static final Map<InstanceState, NodeState> instanceToNodeState = ImmutableMap
.<InstanceState, NodeState> builder().put(InstanceState.PENDING, NodeState.PENDING) .<InstanceState, NodeState> builder().put(InstanceState.PENDING, NodeState.PENDING)
.put(InstanceState.RUNNING, NodeState.RUNNING).put(InstanceState.SHUTTING_DOWN, .put(InstanceState.RUNNING, NodeState.RUNNING).put(InstanceState.SHUTTING_DOWN,
@ -63,14 +88,17 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
private final AMIClient amiClient; private final AMIClient amiClient;
private final Map<RegionTag, KeyPair> credentialsMap; private final Map<RegionTag, KeyPair> credentialsMap;
private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider; private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider;
private final Map<String, ? extends Image> images; private final Set<? extends Image> images;
private final Map<String, ? extends Location> locations; private final Set<? extends Location> locations;
private final Function<RunningInstance, Map<String, String>> instanceToStorageMapping; private final Function<RunningInstance, Map<String, String>> instanceToStorageMapping;
@Inject @Inject
RunningInstanceToNodeMetadata(AMIClient amiClient, Map<RegionTag, KeyPair> credentialsMap, RunningInstanceToNodeMetadata(
AMIClient amiClient,
Map<RegionTag, KeyPair> credentialsMap,
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider, PopulateDefaultLoginCredentialsForImageStrategy credentialProvider,
Map<String, ? extends Image> images, Map<String, ? extends Location> locations, Set<? extends Image> images,
Set<? extends Location> locations,
@Named("volumeMapping") Function<RunningInstance, Map<String, String>> instanceToStorageMapping) { @Named("volumeMapping") Function<RunningInstance, Map<String, String>> instanceToStorageMapping) {
this.amiClient = checkNotNull(amiClient, "amiClient"); this.amiClient = checkNotNull(amiClient, "amiClient");
this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap"); this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap");
@ -81,7 +109,7 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
} }
@Override @Override
public NodeMetadata apply(RunningInstance instance) { public NodeMetadata apply(final RunningInstance instance) {
String id = checkNotNull(instance, "instance").getId(); String id = checkNotNull(instance, "instance").getId();
String name = null; // user doesn't determine a node name; String name = null; // user doesn't determine a node name;
URI uri = null; // no uri to get rest access to host info URI uri = null; // no uri to get rest access to host info
@ -102,13 +130,28 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
Set<InetAddress> publicAddresses = nullSafeSet(instance.getIpAddress()); Set<InetAddress> publicAddresses = nullSafeSet(instance.getIpAddress());
Set<InetAddress> privateAddresses = nullSafeSet(instance.getPrivateIpAddress()); Set<InetAddress> privateAddresses = nullSafeSet(instance.getPrivateIpAddress());
String locationId = instance.getAvailabilityZone(); final String locationId = instance.getAvailabilityZone();
Map<String, String> extra = getExtra(instance); Map<String, String> extra = getExtra(instance);
return new NodeMetadataImpl(id, name, locations.get(locationId), uri, userMetadata, tag, final Location location = Iterables.find(locations, new Predicate<Location>() {
images.get(instance.getImageId()), state, publicAddresses, privateAddresses, extra,
credentials); @Override
public boolean apply(Location input) {
return input.getId().equals(locationId);
}
});
Image image = null;
try {
image = Iterables.find(images, new FindImageForInstance(location, instance));
} catch (NoSuchElementException e) {
logger.warn("could not find a matching image for instance %s in location %s", instance,
location);
}
return new NodeMetadataImpl(id, name, location, uri, userMetadata, tag, image, state,
publicAddresses, privateAddresses, extra, credentials);
} }
/** /**

View File

@ -114,18 +114,19 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
@Override @Override
public Map<?, ListenableFuture<Void>> execute(final String tag, final int count, public Map<?, ListenableFuture<Void>> execute(final String tag, final int count,
final Template template, final Set<NodeMetadata> nodes) { final Template template, final Set<NodeMetadata> nodes,
final Map<NodeMetadata, Exception> badNodes) {
checkArgument(template.getSize() instanceof EC2Size, checkArgument(template.getSize() instanceof EC2Size,
"unexpected image type. should be EC2Size, was: " + template.getSize().getClass()); "unexpected image type. should be EC2Size, was: " + template.getSize().getClass());
EC2Size ec2Size = EC2Size.class.cast(template.getSize()); EC2Size ec2Size = EC2Size.class.cast(template.getSize());
// parse the availability zone of the request // parse the availability zone of the request
String zone = template.getLocation().getScope() == LocationScope.ZONE ? template.getLocation().getId() String zone = template.getLocation().getScope() == LocationScope.ZONE ? template
: null; .getLocation().getId() : null;
// if the location has a parent, it must be an availability zone. // if the location has a parent, it must be an availability zone.
String region = zone == null ? template.getLocation().getId() : String region = zone == null ? template.getLocation().getId() : template.getLocation()
template.getLocation().getParent().getId(); .getParent().getId();
// get or create incidental resources // get or create incidental resources
// TODO race condition. we were using MapMaker, but it doesn't seem to refresh properly when // TODO race condition. we were using MapMaker, but it doesn't seem to refresh properly when
@ -174,8 +175,7 @@ public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrate
} catch (Exception e) { } catch (Exception e) {
logger.error(e, "<< problem applying options to node(%s): ", node.getId(), logger.error(e, "<< problem applying options to node(%s): ", node.getId(),
Throwables.getRootCause(e).getMessage()); Throwables.getRootCause(e).getMessage());
if (!template.getOptions().shouldDestroyOnError()) badNodes.put(computeService.getNodeMetadata(node), e);
nodes.add(computeService.getNodeMetadata(node));
} }
return null; return null;
} }

View File

@ -49,13 +49,18 @@ import com.google.common.collect.Sets;
* /> * />
*/ */
public class DescribeImagesResponseHandler extends ParseSax.HandlerWithResult<Set<Image>> { public class DescribeImagesResponseHandler extends ParseSax.HandlerWithResult<Set<Image>> {
@Inject
public DescribeImagesResponseHandler(@EC2 String defaultRegion) {
this.defaultRegion = defaultRegion;
}
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@Inject
@EC2
String defaultRegion;
private Set<Image> contents = Sets.newLinkedHashSet(); private Set<Image> contents = Sets.newLinkedHashSet();
private StringBuilder currentText = new StringBuilder(); private StringBuilder currentText = new StringBuilder();
private final String defaultRegion;
private Architecture architecture; private Architecture architecture;
private String name; private String name;
@ -149,10 +154,10 @@ public class DescribeImagesResponseHandler extends ParseSax.HandlerWithResult<Se
String region = EC2Utils.findRegionInArgsOrNull(request); String region = EC2Utils.findRegionInArgsOrNull(request);
if (region == null) if (region == null)
region = defaultRegion; region = defaultRegion;
contents.add(new Image(region, architecture, contents.add(new Image(region, architecture, this.name, description, imageId,
this.name, description, imageId, imageLocation, imageOwnerId, imageState, imageLocation, imageOwnerId, imageState, imageType, isPublic, productCodes,
imageType, isPublic, productCodes, kernelId, platform, ramdiskId, kernelId, platform, ramdiskId, rootDeviceType, rootDeviceName,
rootDeviceType, rootDeviceName, ebsBlockDevices)); ebsBlockDevices));
} catch (NullPointerException e) { } catch (NullPointerException e) {
logger.warn(e, "malformed image: %s", imageId); logger.warn(e, "malformed image: %s", imageId);
} }

View File

@ -21,7 +21,7 @@ package org.jclouds.aws.s3.blobstore;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.compose; import static com.google.common.util.concurrent.Futures.compose;
import java.util.Map; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -84,8 +84,8 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
@Inject @Inject
S3AsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, S3AsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Map<String, ? extends Location> locations, Location defaultLocation, Set<? extends Location> locations, S3AsyncClient async,
S3AsyncClient async, S3Client sync, BucketToResourceMetadata bucket2ResourceMd, S3Client sync, BucketToResourceMetadata bucket2ResourceMd,
ContainerToBucketListOptions container2BucketListOptions, ContainerToBucketListOptions container2BucketListOptions,
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob, BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object,

View File

@ -20,7 +20,7 @@ package org.jclouds.aws.s3.blobstore;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import javax.inject.Inject; import javax.inject.Inject;
@ -75,7 +75,7 @@ public class S3BlobStore extends BaseBlobStore {
@Inject @Inject
S3BlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, Location defaultLocation, S3BlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, Location defaultLocation,
Map<String, ? extends Location> locations, S3Client sync, Set<? extends Location> locations, S3Client sync,
BucketToResourceMetadata bucket2ResourceMd, BucketToResourceMetadata bucket2ResourceMd,
ContainerToBucketListOptions container2BucketListOptions, ContainerToBucketListOptions container2BucketListOptions,
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob, BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,

View File

@ -18,7 +18,6 @@
*/ */
package org.jclouds.aws.s3.blobstore.config; package org.jclouds.aws.s3.blobstore.config;
import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -39,8 +38,8 @@ import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; import org.jclouds.domain.internal.LocationImpl;
import com.google.common.base.Function; import com.google.common.base.Predicate;
import com.google.common.collect.Maps; import com.google.common.collect.Iterables;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.Scopes; import com.google.inject.Scopes;
@ -72,24 +71,26 @@ public class S3BlobStoreContextModule extends S3ContextModule {
@Provides @Provides
@Singleton @Singleton
Location getDefaultLocation(@S3 String region, Map<String, ? extends Location> locations) { Location getDefaultLocation(@S3 final String region, Set<? extends Location> locations) {
return locations.get(region.toString()); return Iterables.find(locations, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(region);
}
});
} }
@Provides @Provides
@Singleton @Singleton
Map<String, ? extends Location> provideLocations(@S3 Set<String> regions) { Set<? extends Location> provideLocations(@S3 Set<String> regions) {
Set<Location> locations = Sets.newHashSet(); Set<Location> locations = Sets.newHashSet();
Location s3 = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null); Location s3 = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
for (String zone : regions) { for (String zone : regions) {
locations locations
.add(new LocationImpl(LocationScope.REGION, zone.toString(), zone.toString(), s3)); .add(new LocationImpl(LocationScope.REGION, zone.toString(), zone.toString(), s3));
} }
return Maps.uniqueIndex(locations, new Function<Location, String>() { return locations;
@Override
public String apply(Location from) {
return from.getId();
}
});
} }
} }

View File

@ -18,7 +18,8 @@
*/ */
package org.jclouds.aws.s3.blobstore.functions; package org.jclouds.aws.s3.blobstore.functions;
import java.util.Map; import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -35,6 +36,8 @@ import org.jclouds.domain.Location;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -42,13 +45,13 @@ import com.google.common.base.Function;
@Singleton @Singleton
public class BucketToResourceMetadata implements Function<BucketMetadata, StorageMetadata> { public class BucketToResourceMetadata implements Function<BucketMetadata, StorageMetadata> {
private final S3Client client; private final S3Client client;
private final Map<String, ? extends Location> locations; private final Set<? extends Location> locations;
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@Inject @Inject
BucketToResourceMetadata(S3Client client, Map<String, ? extends Location> locations) { BucketToResourceMetadata(S3Client client, Set<? extends Location> locations) {
this.client = client; this.client = client;
this.locations = locations; this.locations = locations;
} }
@ -58,12 +61,20 @@ public class BucketToResourceMetadata implements Function<BucketMetadata, Storag
to.setName(from.getName()); to.setName(from.getName());
to.setType(StorageType.CONTAINER); to.setType(StorageType.CONTAINER);
try { try {
String region = client.getBucketLocation(from.getName()); final String region = client.getBucketLocation(from.getName());
if (region != null) { if (region != null) {
Location location = locations.get(region.toString()); try {
if (location == null) to.setLocation(Iterables.find(locations, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(region.toString());
}
}));
} catch (NoSuchElementException e) {
logger.error("could not get location for region %s in %s", region, locations); logger.error("could not get location for region %s in %s", region, locations);
to.setLocation(location); }
} else { } else {
logger.error("could not get region for %s", from.getName()); logger.error("could not get region for %s", from.getName());
} }

View File

@ -44,7 +44,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Test @Test
public void testTemplateBuilderCanUseImageId() { public void testTemplateBuilderCanUseImageId() {
client.templateBuilder().imageId(Iterables.get(client.getImages().keySet(), 0)).build(); client.templateBuilder().imageId(Iterables.get(client.listImages(), 0).getId()).build();
} }
@Test @Test

View File

@ -41,7 +41,6 @@ import org.jclouds.domain.internal.LocationImpl;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -116,10 +115,10 @@ public class EC2ComputeServiceTest {
.<String, String> newHashMap(), "description", "1.0", null, "ubuntu", .<String, String> newHashMap(), "description", "1.0", null, "ubuntu",
Architecture.X86_64, new Credentials("root", null)); Architecture.X86_64, new Credentials("root", null));
return new TemplateBuilderImpl(ImmutableMap.of("us-east-1", location), ImmutableMap.of( return new TemplateBuilderImpl(ImmutableSet.of(location), ImmutableSet.of(image),
"ami-image", image), Maps.uniqueIndex(ImmutableSet.of(EC2Size.C1_MEDIUM, ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
EC2Size.C1_XLARGE, EC2Size.M1_LARGE, EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE,
EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE), indexer()), location) { EC2Size.M2_4XLARGE), location) {
}; };
} }

View File

@ -32,11 +32,14 @@ import org.jclouds.aws.ec2.xml.BaseEC2HandlerTest;
import org.jclouds.aws.ec2.xml.DescribeImagesResponseHandler; import org.jclouds.aws.ec2.xml.DescribeImagesResponseHandler;
import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.OsFamily;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
/** /**
@ -52,15 +55,15 @@ public class ImageParserTest extends BaseEC2HandlerTest {
assertEquals(result.size(), 6); assertEquals(result.size(), 6);
ImageParser parser = new ImageParser( ImageParser parser = new ImageParser(
new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableMap new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableSet
.<String, Location> of()); .<Location> of(defaultLocation), defaultLocation);
org.jclouds.compute.domain.Image ubuntuHardy = parser.apply(Iterables.get(result, 0)); org.jclouds.compute.domain.Image ubuntuHardy = parser.apply(Iterables.get(result, 0));
assertEquals(ubuntuHardy.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32); assertEquals(ubuntuHardy.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(ubuntuHardy.getDescription(), assertEquals(ubuntuHardy.getDescription(),
"ubuntu-images-us/ubuntu-hardy-8.04-i386-server-20091130.manifest.xml"); "ubuntu-images-us/ubuntu-hardy-8.04-i386-server-20091130.manifest.xml");
assertEquals(ubuntuHardy.getId(), "ami-7e28ca17"); assertEquals(ubuntuHardy.getId(), "ami-7e28ca17");
assertEquals(ubuntuHardy.getLocation(), null); assertEquals(ubuntuHardy.getLocation(), defaultLocation);
assertEquals(ubuntuHardy.getName(), "8.04"); assertEquals(ubuntuHardy.getName(), "8.04");
assertEquals(ubuntuHardy.getOsDescription(), assertEquals(ubuntuHardy.getOsDescription(),
"ubuntu-images-us/ubuntu-hardy-8.04-i386-server-20091130.manifest.xml"); "ubuntu-images-us/ubuntu-hardy-8.04-i386-server-20091130.manifest.xml");
@ -75,7 +78,7 @@ public class ImageParserTest extends BaseEC2HandlerTest {
assertEquals(alesticKarmic.getDescription(), assertEquals(alesticKarmic.getDescription(),
"alestic/ubuntu-9.10-karmic-base-20090623.manifest.xml"); "alestic/ubuntu-9.10-karmic-base-20090623.manifest.xml");
assertEquals(alesticKarmic.getId(), "ami-19a34270"); assertEquals(alesticKarmic.getId(), "ami-19a34270");
assertEquals(alesticKarmic.getLocation(), null); assertEquals(alesticKarmic.getLocation(), defaultLocation);
assertEquals(alesticKarmic.getName(), "9.10"); assertEquals(alesticKarmic.getName(), "9.10");
assertEquals(alesticKarmic.getOsDescription(), assertEquals(alesticKarmic.getOsDescription(),
"alestic/ubuntu-9.10-karmic-base-20090623.manifest.xml"); "alestic/ubuntu-9.10-karmic-base-20090623.manifest.xml");
@ -90,7 +93,7 @@ public class ImageParserTest extends BaseEC2HandlerTest {
assertEquals(ubuntuKarmic.getDescription(), assertEquals(ubuntuKarmic.getDescription(),
"ubuntu-images-us/ubuntu-karmic-9.10-i386-server-20100121.manifest.xml"); "ubuntu-images-us/ubuntu-karmic-9.10-i386-server-20100121.manifest.xml");
assertEquals(ubuntuKarmic.getId(), "ami-bb709dd2"); assertEquals(ubuntuKarmic.getId(), "ami-bb709dd2");
assertEquals(ubuntuKarmic.getLocation(), null); assertEquals(ubuntuKarmic.getLocation(), defaultLocation);
assertEquals(ubuntuKarmic.getName(), "9.10"); assertEquals(ubuntuKarmic.getName(), "9.10");
assertEquals(ubuntuKarmic.getOsDescription(), assertEquals(ubuntuKarmic.getOsDescription(),
"ubuntu-images-us/ubuntu-karmic-9.10-i386-server-20100121.manifest.xml"); "ubuntu-images-us/ubuntu-karmic-9.10-i386-server-20100121.manifest.xml");
@ -108,7 +111,7 @@ public class ImageParserTest extends BaseEC2HandlerTest {
assertEquals(alesticHardy.getDescription(), assertEquals(alesticHardy.getDescription(),
"alestic/ubuntu-8.04-hardy-base-20080905.manifest.xml"); "alestic/ubuntu-8.04-hardy-base-20080905.manifest.xml");
assertEquals(alesticHardy.getId(), "ami-c0fa1ea9"); assertEquals(alesticHardy.getId(), "ami-c0fa1ea9");
assertEquals(alesticHardy.getLocation(), null); assertEquals(alesticHardy.getLocation(), defaultLocation);
assertEquals(alesticHardy.getName(), "8.04"); assertEquals(alesticHardy.getName(), "8.04");
assertEquals(alesticHardy.getOsDescription(), assertEquals(alesticHardy.getOsDescription(),
"alestic/ubuntu-8.04-hardy-base-20080905.manifest.xml"); "alestic/ubuntu-8.04-hardy-base-20080905.manifest.xml");
@ -121,14 +124,17 @@ public class ImageParserTest extends BaseEC2HandlerTest {
assert parser.apply(Iterables.get(result, 5)) == null; assert parser.apply(Iterables.get(result, 5)) == null;
} }
private Location defaultLocation = new LocationImpl(LocationScope.REGION, "us-east-1",
"us-east-1", null);
public void testParseVostokImage() { public void testParseVostokImage() {
InputStream is = getClass().getResourceAsStream("/ec2/vostok.xml"); InputStream is = getClass().getResourceAsStream("/ec2/vostok.xml");
Set<Image> result = parseImages(is); Set<Image> result = parseImages(is);
ImageParser parser = new ImageParser( ImageParser parser = new ImageParser(
new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableMap new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableSet
.<String, Location> of()); .<Location> of(defaultLocation), defaultLocation);
org.jclouds.compute.domain.Image image = parser.apply(Iterables.get(result, 0)); org.jclouds.compute.domain.Image image = parser.apply(Iterables.get(result, 0));
@ -136,7 +142,7 @@ public class ImageParserTest extends BaseEC2HandlerTest {
assertEquals(image.getDescription(), assertEquals(image.getDescription(),
"vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml"); "vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml");
assertEquals(image.getId(), "ami-870de2ee"); assertEquals(image.getId(), "ami-870de2ee");
assertEquals(image.getLocation(), null); assertEquals(image.getLocation(), defaultLocation);
assertEquals(image.getName(), ""); assertEquals(image.getName(), "");
assertEquals(image.getOsDescription(), assertEquals(image.getOsDescription(),
"vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml"); "vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml");

View File

@ -20,7 +20,6 @@ package org.jclouds.aws.ec2.compute.functions;
import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock; import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay; import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify; import static org.easymock.classextension.EasyMock.verify;
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds; import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds;
@ -29,6 +28,7 @@ import static org.testng.Assert.assertEquals;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.jclouds.aws.domain.Region; import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.compute.domain.RegionTag; import org.jclouds.aws.ec2.compute.domain.RegionTag;
@ -62,19 +62,19 @@ public class RunningInstanceToNodeMetadataTest {
throws UnknownHostException { throws UnknownHostException {
AMIClient amiClient = createMock(AMIClient.class); AMIClient amiClient = createMock(AMIClient.class);
Map<RegionTag, KeyPair> credentialsMap = createMock(Map.class); Map<RegionTag, KeyPair> credentialsMap = createMock(Map.class);
Map<String, org.jclouds.compute.domain.Image> images = createMock(Map.class); org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
Map<String, Location> locations = createMock(Map.class);
Set<org.jclouds.compute.domain.Image> images = ImmutableSet
.<org.jclouds.compute.domain.Image> of(jcImage);
Location location = new LocationImpl(LocationScope.ZONE, "us-east-1a", "description", null);
Set<Location> locations = ImmutableSet.<Location> of(location);
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class); PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class); RunningInstance instance = createMock(RunningInstance.class);
expect(instance.getId()).andReturn("id").atLeastOnce(); expect(instance.getId()).andReturn("id").atLeastOnce();
expect(instance.getKeyName()).andReturn(null).atLeastOnce(); expect(instance.getKeyName()).andReturn(null).atLeastOnce();
expect(instance.getInstanceState()).andReturn(InstanceState.RUNNING); expect(instance.getInstanceState()).andReturn(InstanceState.RUNNING);
Location location = new LocationImpl(LocationScope.ZONE, "us-east-1a", "description", null);
expect(locations.get("us-east-1a")).andReturn(location);
org.jclouds.compute.domain.Image jcImage = createNiceMock(org.jclouds.compute.domain.Image.class);
expect(images.get("imageId")).andReturn(jcImage);
expect(instance.getIpAddress()).andReturn( expect(instance.getIpAddress()).andReturn(
InetAddress.getByAddress(new byte[] { 12, 10, 10, 1 })); InetAddress.getByAddress(new byte[] { 12, 10, 10, 1 }));
@ -84,32 +84,32 @@ public class RunningInstanceToNodeMetadataTest {
expect(instance.getAvailabilityZone()).andReturn(AvailabilityZone.US_EAST_1A).atLeastOnce(); expect(instance.getAvailabilityZone()).andReturn(AvailabilityZone.US_EAST_1A).atLeastOnce();
expect(instance.getImageId()).andReturn("imageId").atLeastOnce(); expect(instance.getImageId()).andReturn("imageId").atLeastOnce();
expect(jcImage.getId()).andReturn("imageId").atLeastOnce();
expect(jcImage.getLocation()).andReturn(location).atLeastOnce();
expect(instance.getInstanceType()).andReturn(InstanceType.C1_XLARGE).atLeastOnce(); expect(instance.getInstanceType()).andReturn(InstanceType.C1_XLARGE).atLeastOnce();
replay(jcImage);
replay(amiClient); replay(amiClient);
replay(credentialsMap); replay(credentialsMap);
replay(credentialProvider); replay(credentialProvider);
replay(instance); replay(instance);
replay(images);
replay(locations);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(amiClient, RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(amiClient,
credentialsMap, credentialProvider, images, locations, credentialsMap, credentialProvider, images, locations,
new RunningInstanceToStorageMappingUnix()); new RunningInstanceToStorageMappingUnix());
NodeMetadata metadata = parser.apply(instance); NodeMetadata metadata = parser.apply(instance);
assertEquals(metadata.getLocation(), location); assertEquals(metadata.getLocation(), locations.iterator().next());
assertEquals(metadata.getImage(), jcImage); assertEquals(metadata.getImage(), jcImage);
assertEquals(metadata.getTag(), "NOTAG-id"); assertEquals(metadata.getTag(), "NOTAG-id");
assertEquals(metadata.getCredentials(), null); assertEquals(metadata.getCredentials(), null);
verify(jcImage);
verify(amiClient); verify(amiClient);
verify(credentialsMap); verify(credentialsMap);
verify(credentialProvider); verify(credentialProvider);
verify(instance); verify(instance);
verify(images);
verify(locations);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -118,8 +118,6 @@ public class RunningInstanceToNodeMetadataTest {
throws UnknownHostException { throws UnknownHostException {
AMIClient amiClient = createMock(AMIClient.class); AMIClient amiClient = createMock(AMIClient.class);
Map<RegionTag, KeyPair> credentialsMap = createMock(Map.class); Map<RegionTag, KeyPair> credentialsMap = createMock(Map.class);
Map<String, org.jclouds.compute.domain.Image> images = createMock(Map.class);
Map<String, Location> locations = createMock(Map.class);
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class); PopulateDefaultLoginCredentialsForImageStrategy credentialProvider = createMock(PopulateDefaultLoginCredentialsForImageStrategy.class);
RunningInstance instance = createMock(RunningInstance.class); RunningInstance instance = createMock(RunningInstance.class);
@ -130,10 +128,10 @@ public class RunningInstanceToNodeMetadataTest {
expect(instance.getInstanceState()).andReturn(InstanceState.RUNNING); expect(instance.getInstanceState()).andReturn(InstanceState.RUNNING);
Location location = new LocationImpl(LocationScope.ZONE, "us-east-1a", "description", null); Location location = new LocationImpl(LocationScope.ZONE, "us-east-1a", "description", null);
expect(locations.get("us-east-1a")).andReturn(location); Set<Location> locations = ImmutableSet.<Location> of(location);
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
org.jclouds.compute.domain.Image jcImage = createNiceMock(org.jclouds.compute.domain.Image.class); Set<org.jclouds.compute.domain.Image> images = ImmutableSet
expect(images.get("imageId")).andReturn(jcImage); .<org.jclouds.compute.domain.Image> of(jcImage);
expect(instance.getIpAddress()).andReturn( expect(instance.getIpAddress()).andReturn(
InetAddress.getByAddress(new byte[] { 12, 10, 10, 1 })); InetAddress.getByAddress(new byte[] { 12, 10, 10, 1 }));
@ -143,6 +141,8 @@ public class RunningInstanceToNodeMetadataTest {
expect(instance.getRegion()).andReturn(Region.US_EAST_1).atLeastOnce(); expect(instance.getRegion()).andReturn(Region.US_EAST_1).atLeastOnce();
expect(instance.getImageId()).andReturn("imageId").atLeastOnce(); expect(instance.getImageId()).andReturn("imageId").atLeastOnce();
expect(jcImage.getId()).andReturn("imageId").atLeastOnce();
expect(jcImage.getLocation()).andReturn(location).atLeastOnce();
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("imageId"))).andReturn( expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("imageId"))).andReturn(
ImmutableSet.<Image> of(image)); ImmutableSet.<Image> of(image));
@ -160,8 +160,7 @@ public class RunningInstanceToNodeMetadataTest {
replay(credentialsMap); replay(credentialsMap);
replay(credentialProvider); replay(credentialProvider);
replay(instance); replay(instance);
replay(images); replay(jcImage);
replay(locations);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(amiClient, RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(amiClient,
credentialsMap, credentialProvider, images, locations, credentialsMap, credentialProvider, images, locations,
@ -175,12 +174,12 @@ public class RunningInstanceToNodeMetadataTest {
assertEquals(metadata.getCredentials(), new Credentials("user", "pass")); assertEquals(metadata.getCredentials(), new Credentials("user", "pass"));
verify(jcImage);
verify(amiClient); verify(amiClient);
verify(credentialsMap); verify(credentialsMap);
verify(credentialProvider); verify(credentialProvider);
verify(instance); verify(instance);
verify(images);
verify(locations);
} }
} }

View File

@ -27,7 +27,6 @@ import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2AsyncClient; import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client; import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.EC2ContextFactory; import org.jclouds.aws.ec2.EC2ContextFactory;

View File

@ -22,7 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.compose; import static com.google.common.util.concurrent.Futures.compose;
import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata; import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata;
import java.util.Map; import java.util.Set;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.inject.Inject; import javax.inject.Inject;
@ -77,7 +77,7 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
@Inject @Inject
AzureAsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, AzureAsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Map<String, ? extends Location> locations, Location defaultLocation, Set<? extends Location> locations,
AzureBlobAsyncClient async, ContainerToResourceMetadata container2ResourceMd, AzureBlobAsyncClient async, ContainerToResourceMetadata container2ResourceMd,
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions, ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,

View File

@ -21,7 +21,7 @@ package org.jclouds.azure.storage.blob.blobstore;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata; import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata;
import java.util.Map; import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -68,7 +68,7 @@ public class AzureBlobStore extends BaseBlobStore {
@Inject @Inject
AzureBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, Location defaultLocation, AzureBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, Location defaultLocation,
Map<String, ? extends Location> locations, AzureBlobClient sync, Set<? extends Location> locations, AzureBlobClient sync,
ContainerToResourceMetadata container2ResourceMd, ContainerToResourceMetadata container2ResourceMd,
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions, ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
ListBlobsResponseToResourceList azure2BlobStoreResourceList, ListBlobsResponseToResourceList azure2BlobStoreResourceList,

View File

@ -18,7 +18,7 @@
*/ */
package org.jclouds.azure.storage.blob.blobstore.config; package org.jclouds.azure.storage.blob.blobstore.config;
import java.util.Map; import java.util.Set;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -39,7 +39,7 @@ import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; import org.jclouds.domain.internal.LocationImpl;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.Scopes; import com.google.inject.Scopes;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -72,7 +72,7 @@ public class AzureBlobStoreContextModule extends AzureBlobContextModule {
@Provides @Provides
@Singleton @Singleton
Map<String, ? extends Location> provideLocations(Location location) { Set<? extends Location> provideLocations(Location location) {
return ImmutableMap.of(location.getId(), location); return ImmutableSet.of(location);
} }
} }

View File

@ -135,7 +135,7 @@ Options can also be specified for extension modules
"Retrieve the available container locations for the blobstore context." "Retrieve the available container locations for the blobstore context."
([] (locations *blobstore*)) ([] (locations *blobstore*))
([#^BlobStore blobstore] ([#^BlobStore blobstore]
(seq-from-immutable-set (.getAssignableLocations blobstore)))) (seq (.listAssignableLocations blobstore))))
(defn create-container (defn create-container
"Create a container." "Create a container."

View File

@ -18,7 +18,7 @@
*/ */
package org.jclouds.blobstore; package org.jclouds.blobstore;
import java.util.Map; import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -49,9 +49,9 @@ public interface AsyncBlobStore {
Blob newBlob(String name); Blob newBlob(String name);
/** /**
* @see BlobStore#getAssignableLocations * @see BlobStore#listAssignableLocations
*/ */
ListenableFuture<? extends Map<String, ? extends Location>> getAssignableLocations(); ListenableFuture<? extends Set<? extends Location>> listAssignableLocations();
/** /**
* @see BlobStore#list * @see BlobStore#list

View File

@ -18,7 +18,7 @@
*/ */
package org.jclouds.blobstore; package org.jclouds.blobstore;
import java.util.Map; import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -50,12 +50,12 @@ public interface BlobStore {
Blob newBlob(String name); Blob newBlob(String name);
/** /**
* The get locations command returns all the valid locations for containers. A location has a scope, * The get locations command returns all the valid locations for containers. A location has a
* which is typically region or zone. A region is a general area, like eu-west, where a zone is * scope, which is typically region or zone. A region is a general area, like eu-west, where a
* similar to a datacenter. If a location has a parent, that implies it is within that location. * zone is similar to a datacenter. If a location has a parent, that implies it is within that
* For example a location can be a rack, whose parent is likely to be a zone. * location. For example a location can be a rack, whose parent is likely to be a zone.
*/ */
Map<String, ? extends Location> getAssignableLocations(); Set<? extends Location> listAssignableLocations();
/** /**
* Lists all root-level resources available to the account. * Lists all root-level resources available to the account.

View File

@ -38,6 +38,7 @@ import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -112,7 +113,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory, IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory,
BlobStoreUtils blobUtils, BlobStoreUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Map<String, Location> locations) { Location defaultLocation, Set<Location> locations) {
super(context, blobUtils, service, defaultLocation, locations); super(context, blobUtils, service, defaultLocation, locations);
this.blobFactory = blobFactory; this.blobFactory = blobFactory;
this.dateService = dateService; this.dateService = dateService;

View File

@ -18,7 +18,7 @@
*/ */
package org.jclouds.blobstore.config; package org.jclouds.blobstore.config;
import java.util.Map; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
@ -30,7 +30,7 @@ import org.jclouds.blobstore.domain.Blob;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.util.Jsr330; import org.jclouds.util.Jsr330;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.Scopes; import com.google.inject.Scopes;
@ -55,7 +55,7 @@ public class TransientBlobStoreModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
Map<String, Location> provideLocations(Location defaultLocation) { Set<Location> provideLocations(Location defaultLocation) {
return ImmutableMap.<String, Location> of(defaultLocation.getId(), defaultLocation); return ImmutableSet.of( defaultLocation);
} }
} }

View File

@ -24,7 +24,7 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable; import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import java.util.Map; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -58,12 +58,12 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
protected final BlobStoreUtils blobUtils; protected final BlobStoreUtils blobUtils;
protected final ExecutorService service; protected final ExecutorService service;
protected final Location defaultLocation; protected final Location defaultLocation;
protected final Map<String, ? extends Location> locations; protected final Set<? extends Location> locations;
@Inject @Inject
protected BaseAsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, protected BaseAsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Map<String, ? extends Location> locations) { Location defaultLocation, Set<? extends Location> locations) {
this.context = checkNotNull(context, "context"); this.context = checkNotNull(context, "context");
this.blobUtils = checkNotNull(blobUtils, "blobUtils"); this.blobUtils = checkNotNull(blobUtils, "blobUtils");
this.service = checkNotNull(service, "service"); this.service = checkNotNull(service, "service");
@ -271,7 +271,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
} }
@Override @Override
public ListenableFuture<? extends Map<String, ? extends Location>> getAssignableLocations() { public ListenableFuture<? extends Set<? extends Location>> listAssignableLocations() {
return immediateFuture(locations); return immediateFuture(locations);
} }

View File

@ -21,7 +21,7 @@ package org.jclouds.blobstore.internal;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive; import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
import java.util.Map; import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
@ -48,11 +48,11 @@ public abstract class BaseBlobStore implements BlobStore {
protected final BlobStoreContext context; protected final BlobStoreContext context;
protected final BlobStoreUtils blobUtils; protected final BlobStoreUtils blobUtils;
protected final Location defaultLocation; protected final Location defaultLocation;
protected final Map<String, ? extends Location> locations; protected final Set<? extends Location> locations;
@Inject @Inject
protected BaseBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, protected BaseBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
Location defaultLocation, Map<String, ? extends Location> locations) { Location defaultLocation, Set<? extends Location> locations) {
this.context = checkNotNull(context, "context"); this.context = checkNotNull(context, "context");
this.blobUtils = checkNotNull(blobUtils, "blobUtils"); this.blobUtils = checkNotNull(blobUtils, "blobUtils");
this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation"); this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation");
@ -213,7 +213,7 @@ public abstract class BaseBlobStore implements BlobStore {
} }
@Override @Override
public Map<String, ? extends Location> getAssignableLocations() { public Set<? extends Location> listAssignableLocations() {
return locations; return locations;
} }

View File

@ -21,7 +21,6 @@ package org.jclouds.blobstore.integration.internal;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry;
import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageMetadata;
@ -47,7 +46,7 @@ public class BaseServiceIntegrationTest extends BaseBlobStoreIntegrationTest {
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
public void testAllLocations() throws InterruptedException { public void testAllLocations() throws InterruptedException {
for (final Location location : context.getBlobStore().getAssignableLocations().values()) { for (final Location location : context.getBlobStore().listAssignableLocations()) {
final String containerName = getScratchContainerName(); final String containerName = getScratchContainerName();
try { try {
System.err.printf(" >> creating container in location %s%n", location); System.err.printf(" >> creating container in location %s%n", location);
@ -77,32 +76,31 @@ public class BaseServiceIntegrationTest extends BaseBlobStoreIntegrationTest {
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
public void testGetAssignableLocations() throws Exception { public void testGetAssignableLocations() throws Exception {
for (Entry<String, ? extends Location> location : context.getBlobStore() for (Location location : context.getBlobStore()
.getAssignableLocations().entrySet()) { .listAssignableLocations()) {
System.err.printf("location %s%n", location.getValue()); System.err.printf("location %s%n", location);
assertEquals(location.getKey(), location.getValue().getId()); assert location.getId() != null : location;
assert location.getValue().getId() != null : location; assert location != location.getParent() : location;
assert location.getValue() != location.getValue().getParent() : location; assert location.getScope() != null : location;
assert location.getValue().getScope() != null : location; switch (location.getScope()) {
switch (location.getValue().getScope()) {
case PROVIDER: case PROVIDER:
assertProvider(location.getValue()); assertProvider(location);
break; break;
case REGION: case REGION:
assertProvider(location.getValue().getParent()); assertProvider(location.getParent());
break; break;
case ZONE: case ZONE:
Location provider = location.getValue().getParent().getParent(); Location provider = location.getParent().getParent();
// zone can be a direct descendant of provider // zone can be a direct descendant of provider
if (provider == null) if (provider == null)
provider = location.getValue().getParent(); provider = location.getParent();
assertProvider(provider); assertProvider(provider);
break; break;
case HOST: case HOST:
Location provider2 = location.getValue().getParent().getParent().getParent(); Location provider2 = location.getParent().getParent().getParent();
// zone can be a direct descendant of provider // zone can be a direct descendant of provider
if (provider2 == null) if (provider2 == null)
provider2 = location.getValue().getParent().getParent(); provider2 = location.getParent().getParent();
assertProvider(provider2); assertProvider(provider2);
break; break;
} }

View File

@ -117,11 +117,11 @@ See http://code.google.com/p/jclouds for details."
"Retrieve the available compute locations for the compute context." "Retrieve the available compute locations for the compute context."
([] (locations *compute*)) ([] (locations *compute*))
([#^ComputeService compute] ([#^ComputeService compute]
(seq-from-immutable-set (.getAssignableLocations compute)))) (seq (.listAssignableLocations compute))))
(defn nodes-with-tag (defn nodes-with-tag
[#^String tag #^ComputeService compute] [#^String tag #^ComputeService compute]
(seq-from-immutable-set (.getNodesWithTag compute tag))) (seq (.listNodesWithTag compute tag)))
(def #^{:private true} list-nodes-map (def #^{:private true} list-nodes-map
{ :with-details #(when %2 (.withDetails %1)) }) { :with-details #(when %2 (.withDetails %1)) })
@ -139,20 +139,20 @@ See http://code.google.com/p/jclouds for details."
((list-nodes-map k) lno v) ((list-nodes-map k) lno v)
lno) lno)
(GetNodesOptions.) options)] (GetNodesOptions.) options)]
(seq-from-immutable-set (.getNodes compute-or-tag list-nodes-options))) (seq (.listNodes compute-or-tag list-nodes-options)))
(nodes-with-tag compute-or-tag *compute*)))) (nodes-with-tag compute-or-tag *compute*))))
(defn images (defn images
"Retrieve the available images for the compute context." "Retrieve the available images for the compute context."
([] (images *compute*)) ([] (images *compute*))
([#^ComputeService compute] ([#^ComputeService compute]
(seq-from-immutable-set (.getImages compute)))) (seq (.listImages compute))))
(defn sizes (defn sizes
"Retrieve the available node sizes for the compute context." "Retrieve the available node sizes for the compute context."
([] (sizes *compute*)) ([] (sizes *compute*))
([#^ComputeService compute] ([#^ComputeService compute]
(seq-from-immutable-set (.getSizes compute)))) (seq (.listSizes compute))))
(defn default-template (defn default-template
([] (default-template *compute*)) ([] (default-template *compute*))
@ -193,7 +193,7 @@ See http://code.google.com/p/jclouds for details."
tag count (default-template compute-or-template) compute-or-template) tag count (default-template compute-or-template) compute-or-template)
(run-nodes tag count compute-or-template *compute*))) (run-nodes tag count compute-or-template *compute*)))
([tag count template #^ComputeService compute] ([tag count template #^ComputeService compute]
(seq-from-immutable-set (seq
(.runNodesWithTag compute tag count template)))) (.runNodesWithTag compute tag count template))))
(defn run-node (defn run-node

View File

@ -19,6 +19,7 @@
package org.jclouds.compute; package org.jclouds.compute;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
@ -54,14 +55,14 @@ public interface ComputeService {
TemplateBuilder templateBuilder(); TemplateBuilder templateBuilder();
/** /**
* The get sizes command shows you the options including virtual cpu count, memory, and disks. * The list sizes command shows you the options including virtual cpu count, memory, and disks.
* cpu count is not a portable quantity across clouds, as they are measured differently. However, * cpu count is not a portable quantity across clouds, as they are measured differently. However,
* it is a good indicator of relative speed within a cloud. memory is measured in megabytes and * it is a good indicator of relative speed within a cloud. memory is measured in megabytes and
* disks in gigabytes. * disks in gigabytes.
* *
* @return a map of sizes by ID, conceding that in some clouds the "id" is not used. * @return a map of sizes by ID, conceding that in some clouds the "id" is not used.
*/ */
Map<String, ? extends Size> getSizes(); Set<? extends Size> listSizes();
/** /**
* Images define the operating system and metadata related to a node. In some clouds, Images are * Images define the operating system and metadata related to a node. In some clouds, Images are
@ -70,27 +71,27 @@ public interface ComputeService {
* TemplateBuilder as opposed to choosing an image explicitly. The getImages() command returns a * TemplateBuilder as opposed to choosing an image explicitly. The getImages() command returns a
* map of images by id. * map of images by id.
*/ */
Map<String, ? extends Image> getImages(); Set<? extends Image> listImages();
/** /**
* all nodes available to the current user by id. If possible, the returned set will include * all nodes available to the current user by id. If possible, the returned set will include
* {@link NodeMetadata} objects. * {@link NodeMetadata} objects.
*/ */
Map<String, ? extends ComputeMetadata> getNodes(); Set<? extends ComputeMetadata> listNodes();
/** /**
* all nodes available to the current user by id. If possible, the returned set will include * all nodes available to the current user by id. If possible, the returned set will include
* {@link NodeMetadata} objects. * {@link NodeMetadata} objects.
*/ */
Map<String, ? extends ComputeMetadata> getNodes(GetNodesOptions options); Set<? extends ComputeMetadata> listNodes(GetNodesOptions options);
/** /**
* The get locations command returns all the valid locations for nodes. A location has a scope, * The list locations command returns all the valid locations for nodes. A location has a scope,
* which is typically region or zone. A region is a general area, like eu-west, where a zone is * which is typically region or zone. A region is a general area, like eu-west, where a zone is
* similar to a datacenter. If a location has a parent, that implies it is within that location. * similar to a datacenter. If a location has a parent, that implies it is within that location.
* For example a location can be a rack, whose parent is likely to be a zone. * For example a location can be a rack, whose parent is likely to be a zone.
*/ */
Map<String, ? extends Location> getAssignableLocations(); Set<? extends Location> listAssignableLocations();
/** /**
* *
@ -122,8 +123,13 @@ public interface ComputeService {
* @param template * @param template
* - how to configure the nodes * - how to configure the nodes
* @return all of the nodes the api was able to launch in a running state. * @return all of the nodes the api was able to launch in a running state.
*
* @throws RunNodesException
* when there's a problem applying options to nodes. Note that successful and failed
* nodes are a part of this exception, so be sure to inspect this carefully.
*/ */
Map<String, ? extends NodeMetadata> runNodesWithTag(String tag, int count, Template template); Set<? extends NodeMetadata> runNodesWithTag(String tag, int count, Template template)
throws RunNodesException;
/** /**
* destroy the node. If it is the only node in a tag set, the dependent resources will also be * destroy the node. If it is the only node in a tag set, the dependent resources will also be
@ -159,27 +165,32 @@ public interface ComputeService {
* *
* @param tag * @param tag
*/ */
Map<String, ? extends NodeMetadata> getNodesWithTag(String tag); Set<? extends NodeMetadata> listNodesWithTag(String tag);
/**
* Runs the script without any additional options
*
* @see #runScriptOnNodesWithTag(String,
* byte[], org.jclouds.compute.options.RunScriptOptions)
*/
Map<String, ExecResponse> runScriptOnNodesWithTag(String tag,
byte[] runScript);
/** /**
* Run the script on all nodes with the specific tag. * Runs the script without any additional options
* *
* @param tag tag to look up the nodes * @see #runScriptOnNodesWithTag(String, byte[], org.jclouds.compute.options.RunScriptOptions)
* @param runScript script to run in byte format. If the script is a string, use */
* {@link String#getBytes()} to retrieve the bytes Map<NodeMetadata, ExecResponse> runScriptOnNodesWithTag(String tag, byte[] runScript)
* @param options nullable options to how to run the script throws RunScriptOnNodesException;
* @return map with node identifiers and corresponding responses
*/ /**
Map<String, ExecResponse> runScriptOnNodesWithTag(String tag, * Run the script on all nodes with the specific tag.
byte[] runScript, RunScriptOptions options); *
* @param tag
* tag to look up the nodes
* @param runScript
* script to run in byte format. If the script is a string, use
* {@link String#getBytes()} to retrieve the bytes
* @param options
* nullable options to how to run the script
* @return map with node identifiers and corresponding responses
* @throws RunScriptOnNodesException
* when there's a problem running the script on the nodes. Note that successful and
* failed nodes are a part of this exception, so be sure to inspect this carefully.
*/
Map<NodeMetadata, ExecResponse> runScriptOnNodesWithTag(String tag, byte[] runScript,
RunScriptOptions options) throws RunScriptOnNodesException;
} }

View File

@ -0,0 +1,99 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.compute;
import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.util.ComputeUtils;
/**
*
* @author Adrian Cole
*/
public class RunNodesException extends Exception {
/** The serialVersionUID */
private static final long serialVersionUID = -2272965726680821281L;
private final String tag;
private final int count;
private final Template template;
private final Set<? extends NodeMetadata> successfulNodes;
private final Map<? extends NodeMetadata, ? extends Throwable> failedNodes;
private final Map<?, Exception> executionExceptions;
public RunNodesException(String tag, int count, Template template,
Set<? extends NodeMetadata> successfulNodes, Map<?, Exception> executionExceptions,
Map<? extends NodeMetadata, ? extends Throwable> failedNodes) {
super(
String
.format(
"error running %d node%s tag(%s) location(%s) image(%s) size(%s) options(%s)%n%s%n%s",
count, count > 1 ? "s" : "", tag, template.getLocation().getId(),
template.getImage().getId(), template.getSize().getId(), template
.getOptions(), ComputeUtils
.createExecutionErrorMessage(executionExceptions),
ComputeUtils.createNodeErrorMessage(failedNodes)));
this.tag = tag;
this.count = count;
this.template = template;
this.successfulNodes = successfulNodes;
this.failedNodes = failedNodes;
this.executionExceptions = executionExceptions;
}
/**
*
* @return Nodes that performed startup without error
*/
public Set<? extends NodeMetadata> getSuccessfulNodes() {
return successfulNodes;
}
/**
*
* @return Nodes that performed startup without error, but incurred problems applying options
*/
public Map<?, ? extends Throwable> getExecutionErrors() {
return executionExceptions;
}
/**
*
* @return Nodes that performed startup without error, but incurred problems applying options
*/
public Map<? extends NodeMetadata, ? extends Throwable> getNodeErrors() {
return failedNodes;
}
public String getTag() {
return tag;
}
public int getCount() {
return count;
}
public Template getTemplate() {
return template;
}
}

View File

@ -0,0 +1,96 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.compute;
import java.util.Map;
import javax.annotation.Nullable;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.ssh.ExecResponse;
/**
*
* @author Adrian Cole
*/
public class RunScriptOnNodesException extends Exception {
/** The serialVersionUID */
private static final long serialVersionUID = -2272965726680821281L;
private final String tag;
private final byte[] 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(String tag, final byte[] runScript,
@Nullable final RunScriptOptions options,
Map<NodeMetadata, ExecResponse> successfulNodes, Map<?, Exception> executionExceptions,
Map<? extends NodeMetadata, ? extends Throwable> failedNodes) {
super(String.format("error runScript on node tag(%s) options(%s) exceptions: %s", tag,
options, ComputeUtils.createExecutionErrorMessage(executionExceptions), ComputeUtils
.createNodeErrorMessage(failedNodes)));
this.tag = tag;
this.runScript = runScript;
this.options = options;
this.successfulNodes = successfulNodes;
this.failedNodes = failedNodes;
this.executionExceptions = executionExceptions;
}
/**
*
* @return Nodes that performed ssh without error
*/
public Map<NodeMetadata, ExecResponse> getSuccessfulNodes() {
return successfulNodes;
}
/**
*
* @return Nodes that performed startup without error, but incurred problems applying options
*/
public Map<?, ? extends Throwable> getExecutionErrors() {
return executionExceptions;
}
/**
*
* @return Nodes that performed startup without error, but incurred problems applying options
*/
public Map<? extends NodeMetadata, ? extends Throwable> getNodeErrors() {
return failedNodes;
}
public String getTag() {
return tag;
}
public byte[] getRunScript() {
return runScript;
}
public RunScriptOptions getOptions() {
return options;
}
}

View File

@ -31,7 +31,6 @@ import static org.jclouds.util.Utils.checkNotEmpty;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -45,6 +44,8 @@ import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.RunScriptOnNodesException;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.ComputeType; import org.jclouds.compute.domain.ComputeType;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
@ -62,13 +63,14 @@ import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy; import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy; import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.compute.util.ComputeUtils; import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.compute.util.ComputeUtils.RunScriptOnNode;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.ssh.ExecResponse; import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -86,9 +88,9 @@ public class BaseComputeService implements ComputeService {
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
protected final ComputeServiceContext context; protected final ComputeServiceContext context;
protected final Provider<Map<String, ? extends Image>> images; protected final Provider<Set<? extends Image>> images;
protected final Provider<Map<String, ? extends Size>> sizes; protected final Provider<Set<? extends Size>> sizes;
protected final Provider<Map<String, ? extends Location>> locations; protected final Provider<Set<? extends Location>> locations;
protected final ListNodesStrategy listNodesStrategy; protected final ListNodesStrategy listNodesStrategy;
protected final GetNodeMetadataStrategy getNodeMetadataStrategy; protected final GetNodeMetadataStrategy getNodeMetadataStrategy;
protected final RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy; protected final RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy;
@ -112,26 +114,11 @@ public class BaseComputeService implements ComputeService {
}; };
public static Function<ComputeMetadata, String> METADATA_TO_ID = new Function<ComputeMetadata, String>() {
@Override
public String apply(ComputeMetadata from) {
return from.getId();
}
};
public static Function<ComputeMetadata, String> METADATA_TO_NAME = new Function<ComputeMetadata, String>() {
@Override
public String apply(ComputeMetadata from) {
return from.getName();
}
};
@Inject @Inject
protected BaseComputeService(ComputeServiceContext context, protected BaseComputeService(ComputeServiceContext context,
Provider<Map<String, ? extends Image>> images, Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
Provider<Map<String, ? extends Size>> sizes, Provider<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
Provider<Map<String, ? extends Location>> locations, GetNodeMetadataStrategy getNodeMetadataStrategy,
ListNodesStrategy listNodesStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy, RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy, RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, ComputeUtils utils, Provider<TemplateBuilder> templateBuilderProvider, ComputeUtils utils,
@ -159,28 +146,23 @@ public class BaseComputeService implements ComputeService {
} }
@Override @Override
public Map<String, ? extends NodeMetadata> runNodesWithTag(final String tag, int count, public Set<? extends NodeMetadata> runNodesWithTag(final String tag, int count,
final Template template) { final Template template) throws RunNodesException {
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens"); checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
checkNotNull(template.getLocation(), "location"); checkNotNull(template.getLocation(), "location");
logger.debug(">> running %d node%s tag(%s) location(%s) image(%s) size(%s) options(%s)", logger.debug(">> running %d node%s tag(%s) location(%s) image(%s) size(%s) options(%s)",
count, count > 1 ? "s" : "", tag, template.getLocation().getId(), template count, count > 1 ? "s" : "", tag, template.getLocation().getId(), template
.getImage().getId(), template.getSize().getId(), template.getOptions()); .getImage().getId(), template.getSize().getId(), template.getOptions());
final Set<NodeMetadata> nodes = Sets.newHashSet(); final Set<NodeMetadata> nodes = Sets.newHashSet();
final Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
Map<?, ListenableFuture<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count, Map<?, ListenableFuture<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count,
template, nodes); template, nodes, badNodes);
Map<?, Exception> exceptions = awaitCompletion(responses, executor, null, logger, Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger,
"starting nodes"); "starting nodes");
if (exceptions.size() > 0 && template.getOptions().shouldDestroyOnError()) { if (executionExceptions.size() > 0 || badNodes.size() > 0) {
ImmutableMap<?, ? extends ComputeMetadata> currentNodes = Maps.uniqueIndex( throw new RunNodesException(tag, count, template, nodes, executionExceptions, badNodes);
listNodesStrategy.execute(GetNodesOptions.NONE), METADATA_TO_ID);
for (Entry<?, Exception> entry : exceptions.entrySet()) {
logger.error(entry.getValue(), "<< error applying nodes(%s) [%s] destroying ", entry
.getKey(), entry.getValue().getMessage());
destroyNode(currentNodes.get(entry.getKey()));
}
} }
return Maps.uniqueIndex(nodes, METADATA_TO_ID); return nodes;
} }
@Override @Override
@ -196,14 +178,14 @@ public class BaseComputeService implements ComputeService {
@Override @Override
public void destroyNodesWithTag(String tag) { // TODO parallel public void destroyNodesWithTag(String tag) { // TODO parallel
logger.debug(">> destroying nodes by tag(%s)", tag); logger.debug(">> destroying nodes by tag(%s)", tag);
Iterable<? extends NodeMetadata> nodesToDestroy = Iterables.filter(doGetNodesWithTag(tag) Iterable<? extends NodeMetadata> nodesToDestroy = Iterables.filter(doListNodesWithTag(tag),
.values(), new Predicate<NodeMetadata>() { new Predicate<NodeMetadata>() {
@Override @Override
public boolean apply(NodeMetadata input) { public boolean apply(NodeMetadata input) {
return input.getState() != NodeState.TERMINATED; return input.getState() != NodeState.TERMINATED;
} }
}); });
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap(); Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : nodesToDestroy) { for (final NodeMetadata node : nodesToDestroy) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() { responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
@ -219,69 +201,59 @@ public class BaseComputeService implements ComputeService {
} }
@Override @Override
public Map<String, ? extends ComputeMetadata> getNodes() { public Set<? extends ComputeMetadata> listNodes() {
logger.debug(">> listing servers"); return listNodes(null);
ImmutableMap<String, ? extends ComputeMetadata> map = Maps.uniqueIndex(listNodesStrategy
.execute(GetNodesOptions.NONE), METADATA_TO_ID);
logger.debug("<< list(%d)", map.size());
return map;
} }
@Override @Override
public Map<String, ? extends ComputeMetadata> getNodes(GetNodesOptions options) { public Set<? extends ComputeMetadata> listNodes(GetNodesOptions options) {
logger.debug(">> listing servers"); logger.debug(">> listing servers");
if(options == null){ if (options == null) {
options = GetNodesOptions.NONE; options = GetNodesOptions.NONE;
} }
ImmutableMap<String, ? extends ComputeMetadata> map = Maps.uniqueIndex(listNodesStrategy Set<? extends ComputeMetadata> set = Sets
.execute(options), METADATA_TO_ID); .newLinkedHashSet(listNodesStrategy.execute(options));
logger.debug("<< list(%d)", map.size()); logger.debug("<< list(%d)", set.size());
return map; return set;
} }
/** /**
* If the result of {@link ListNodesStrategy#execute} is a set of nodes, then return them. * If the result of {@link ListNodesStrategy#execute} is a set of nodes, then return them.
* Otherwise iteratively call {@link #getNodeMetadata} * Otherwise iteratively call {@link #getNodeMetadata}
*/ */
protected Map<String, ? extends NodeMetadata> doGetNodesWithTag(final String tag) { protected Set<? extends NodeMetadata> doListNodesWithTag(final String tag) {
Iterable<? extends NodeMetadata> nodes = Iterables.filter(Iterables.transform( return Sets.newHashSet(Iterables.filter(Iterables.transform(listNodesStrategy
listNodesStrategy.execute(GetNodesOptions.NONE), new Function<ComputeMetadata, NodeMetadata>() { .execute(GetNodesOptions.NONE), new Function<ComputeMetadata, NodeMetadata>() {
@Override
public NodeMetadata apply(ComputeMetadata from) {
return from instanceof NodeMetadata ? NodeMetadata.class.cast(from)
: getNodeMetadata(from);
}
}), new Predicate<NodeMetadata>() {
@Override @Override
public boolean apply(NodeMetadata input) { public NodeMetadata apply(ComputeMetadata from) {
return tag.equals(input.getTag()); return from instanceof NodeMetadata ? NodeMetadata.class.cast(from)
: getNodeMetadata(from);
} }
}); }), new NodeMatchesTag(tag)));
return Maps.uniqueIndex(Iterables.filter(nodes, new NodeMatchesTag(tag)), METADATA_TO_ID);
} }
@Override @Override
public Map<String, ? extends NodeMetadata> getNodesWithTag(String tag) { public Set<? extends NodeMetadata> listNodesWithTag(String tag) {
logger.debug(">> listing nodes by tag(%s)", tag); logger.debug(">> listing nodes by tag(%s)", tag);
Map<String, ? extends NodeMetadata> nodes = doGetNodesWithTag(tag); Set<? extends NodeMetadata> nodes = doListNodesWithTag(tag);
logger.debug("<< list(%d)", nodes.size()); logger.debug("<< list(%d)", nodes.size());
return nodes; return nodes;
} }
@Override @Override
public Map<String, ? extends Size> getSizes() { public Set<? extends Size> listSizes() {
return sizes.get(); return sizes.get();
} }
@Override @Override
public Map<String, ? extends Image> getImages() { public Set<? extends Image> listImages() {
return images.get(); return images.get();
} }
@Override @Override
public Map<String, ? extends Location> getAssignableLocations() { public Set<? extends Location> listAssignableLocations() {
return locations.get(); return locations.get();
} }
@ -310,14 +282,14 @@ public class BaseComputeService implements ComputeService {
@Override @Override
public void rebootNodesWithTag(String tag) { // TODO parallel public void rebootNodesWithTag(String tag) { // TODO parallel
logger.debug(">> rebooting nodes by tag(%s)", tag); logger.debug(">> rebooting nodes by tag(%s)", tag);
Iterable<? extends NodeMetadata> nodesToReboot = Iterables.filter(doGetNodesWithTag(tag) Iterable<? extends NodeMetadata> nodesToReboot = Iterables.filter(doListNodesWithTag(tag),
.values(), new Predicate<NodeMetadata>() { new Predicate<NodeMetadata>() {
@Override @Override
public boolean apply(NodeMetadata input) { public boolean apply(NodeMetadata input) {
return input.getState() != NodeState.TERMINATED; return input.getState() != NodeState.TERMINATED;
} }
}); });
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap(); Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : nodesToReboot) { for (final NodeMetadata node : nodesToReboot) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() { responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
@ -333,9 +305,11 @@ public class BaseComputeService implements ComputeService {
} }
/** /**
* @throws RunScriptOnNodesException
* @see #runScriptOnNodesWithTag(String, byte[], org.jclouds.compute.options.RunScriptOptions) * @see #runScriptOnNodesWithTag(String, byte[], org.jclouds.compute.options.RunScriptOptions)
*/ */
public Map<String, ExecResponse> runScriptOnNodesWithTag(String tag, byte[] runScript) { public Map<NodeMetadata, ExecResponse> runScriptOnNodesWithTag(String tag, byte[] runScript)
throws RunScriptOnNodesException {
return runScriptOnNodesWithTag(tag, runScript, RunScriptOptions.NONE); return runScriptOnNodesWithTag(tag, runScript, RunScriptOptions.NONE);
} }
@ -350,46 +324,94 @@ public class BaseComputeService implements ComputeService {
* @param options * @param options
* nullable options to how to run the script, whether to override credentials * nullable options to how to run the script, whether to override credentials
* @return map with node identifiers and corresponding responses * @return map with node identifiers and corresponding responses
* @throws RunScriptOnNodesException
*/ */
@SuppressWarnings("unchecked") public Map<NodeMetadata, ExecResponse> runScriptOnNodesWithTag(String tag,
public Map<String, ExecResponse> runScriptOnNodesWithTag(String tag, byte[] runScript, final byte[] runScript, @Nullable final RunScriptOptions options)
@Nullable RunScriptOptions options) { throws RunScriptOnNodesException {
Iterable<? extends NodeMetadata> nodes = verifyParametersAndGetNodes(tag, runScript,
(options != null) ? options : RunScriptOptions.NONE);
final Map<NodeMetadata, ExecResponse> execs = Maps.newHashMap();
final Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : nodes) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
try {
RunScriptOnNode callable;
if (options.isRunAsRoot())
callable = utils.runScriptOnNode(node, "computeserv", runScript);
else
callable = utils.runScriptOnNodeAsDefaultUser(node, "computeserv", runScript);
SshClient ssh = utils.createSshClientOncePortIsListeningOnNode(node);
try {
ssh.connect();
callable.setConnection(ssh, logger);
execs.put(node, callable.call());
} finally {
if (ssh != null)
ssh.disconnect();
}
} catch (Exception e) {
badNodes.put(node, e);
}
return null;
}
}), executor));
}
Map<?, Exception> exceptions = awaitCompletion(responses, executor, null, logger,
"starting nodes");
if (exceptions.size() > 0 || badNodes.size() > 0) {
throw new RunScriptOnNodesException(tag, runScript, options, execs, exceptions, badNodes);
}
return execs;
}
private Iterable<? extends NodeMetadata> verifyParametersAndGetNodes(String tag,
byte[] runScript, final RunScriptOptions options) {
checkNotEmpty(tag, "Tag must be provided"); checkNotEmpty(tag, "Tag must be provided");
checkNotNull(runScript, checkNotNull(runScript,
"The script (represented by bytes array - use \"script\".getBytes() must be provided"); "The script (represented by bytes array - use \"script\".getBytes() must be provided");
if (options == null) checkNotNull(options, "options");
options = RunScriptOptions.NONE; Iterable<? extends NodeMetadata> nodes = Iterables.filter(listNodesWithTag(tag),
new Predicate<NodeMetadata>() {
Map<String, ? extends NodeMetadata> nodes = getNodesWithTag(tag); @Override
Map<String, ExecResponse> responses = Maps.newHashMap(); public boolean apply(NodeMetadata input) {
return input.getState() == NodeState.RUNNING;
}
for (NodeMetadata node : nodes.values()) { });
if (NodeState.RUNNING != node.getState()) return Iterables.transform(nodes, new Function<NodeMetadata, NodeMetadata>() {
continue; // make sure the node is active
if (options.getOverrideCredentials() != null) { @Override
// override the credentials with provided to this method public NodeMetadata apply(NodeMetadata node) {
node = ComputeUtils.installNewCredentials(node, options.getOverrideCredentials());
} else { checkArgument(node.getPublicAddresses().size() > 0, "no public ip addresses on node: "
// don't override + node);
checkNotNull(node.getCredentials(), if (options.getOverrideCredentials() != null) {
"If the default credentials need to be used, they can't be null"); // override the credentials with provided to this method
checkNotNull(node.getCredentials().account, "Account name for ssh authentication must be " + node = ComputeUtils.installNewCredentials(node, options.getOverrideCredentials());
"specified. Try passing RunScriptOptions with new credentials"); } else {
checkNotNull(node.getCredentials().key, "Key or password for ssh authentication must be " + // don't override
"specified. Try passing RunScriptOptions with new credentials"); checkNotNull(node.getCredentials(),
"If the default credentials need to be used, they can't be null");
checkNotNull(node.getCredentials().account,
"Account name for ssh authentication must be "
+ "specified. Try passing RunScriptOptions with new credentials");
checkNotNull(node.getCredentials().key,
"Key or password for ssh authentication must be "
+ "specified. Try passing RunScriptOptions with new credentials");
}
return node;
} }
});
ComputeUtils.SshCallable<?> callable;
if (options.isRunAsRoot())
callable = utils.runScriptOnNode(node, "computeserv.sh", runScript);
else
callable = utils.runScriptOnNodeAsDefaultUser(node, "computeserv.sh", runScript);
Map<ComputeUtils.SshCallable<?>, ?> scriptRunResults = utils.runCallablesOnNode(node, Sets
.newHashSet(callable), null);
responses.put(node.getId(), (ExecResponse) scriptRunResults.get(callable));
}
return responses;
} }
} }

View File

@ -18,11 +18,10 @@
*/ */
package org.jclouds.compute.internal; package org.jclouds.compute.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -61,9 +60,9 @@ public class TemplateBuilderImpl implements TemplateBuilder {
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final Map<String, ? extends Image> images; private final Set<? extends Image> images;
private final Map<String, ? extends Size> sizes; private final Set<? extends Size> sizes;
private final Map<String, ? extends Location> locations; private final Set<? extends Location> locations;
@VisibleForTesting @VisibleForTesting
OsFamily os; OsFamily os;
@VisibleForTesting @VisibleForTesting
@ -97,9 +96,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
private TemplateOptions options = TemplateOptions.NONE; private TemplateOptions options = TemplateOptions.NONE;
@Inject @Inject
protected TemplateBuilderImpl(Map<String, ? extends Location> locations, protected TemplateBuilderImpl(Set<? extends Location> locations, Set<? extends Image> images,
Map<String, ? extends Image> images, Map<String, ? extends Size> sizes, Set<? extends Size> sizes, Location defaultLocation) {
Location defaultLocation) {
this.locations = locations; this.locations = locations;
this.images = images; this.images = images;
this.sizes = sizes; this.sizes = sizes;
@ -363,8 +361,6 @@ public class TemplateBuilderImpl implements TemplateBuilder {
*/ */
@Override @Override
public TemplateBuilder locationId(final String locationId) { public TemplateBuilder locationId(final String locationId) {
checkArgument(locations.get(checkNotNull(locationId, "locationId")) != null, "locationId "
+ locationId + " not configured in: " + locations.keySet());
this.locationId = locationId; this.locationId = locationId;
return this; return this;
} }
@ -395,7 +391,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
logger.debug(">> searching params(%s)", this); logger.debug(">> searching params(%s)", this);
Image image; Image image;
try { try {
image = DEFAULT_IMAGE_ORDERING.max(Iterables.filter(images.values(), imagePredicate)); image = DEFAULT_IMAGE_ORDERING.max(Iterables.filter(images, imagePredicate));
} catch (NoSuchElementException exception) { } catch (NoSuchElementException exception) {
throw new NoSuchElementException("image didn't match: " + toString() + "\n" + images); throw new NoSuchElementException("image didn't match: " + toString() + "\n" + images);
} }
@ -410,12 +406,19 @@ public class TemplateBuilderImpl implements TemplateBuilder {
sizeOrdering = Ordering.compound(ImmutableList.of(BY_CORES_ORDERING, sizeOrdering)); sizeOrdering = Ordering.compound(ImmutableList.of(BY_CORES_ORDERING, sizeOrdering));
Size size; Size size;
try { try {
size = sizeOrdering.max(Iterables.filter(sizes.values(), sizePredicate)); size = sizeOrdering.max(Iterables.filter(sizes, sizePredicate));
} catch (NoSuchElementException exception) { } catch (NoSuchElementException exception) {
throw new NoSuchElementException("size didn't match: " + toString() + "\n" + sizes); throw new NoSuchElementException("size didn't match: " + toString() + "\n" + sizes);
} }
logger.debug("<< matched size(%s)", size); logger.debug("<< matched size(%s)", size);
Location location = locations.get(locationId); Location location = Iterables.find(locations, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(locationId);
}
});
logger.debug("<< matched location(%s)", location); logger.debug("<< matched location(%s)", location);
return new TemplateImpl(image, size, location, options); return new TemplateImpl(image, size, location, options);
} }

View File

@ -83,4 +83,10 @@ public class RunScriptOptions {
} }
@Override
public String toString() {
return "RunScriptOptions [overridingCredentials=" + (overridingCredentials != null)
+ ", runAsRoot=" + runAsRoot + "]";
}
} }

View File

@ -32,8 +32,6 @@ public class TemplateOptions {
private String publicKey; private String publicKey;
private boolean destroyOnError;
private int port = -1; private int port = -1;
private int seconds = -1; private int seconds = -1;
@ -64,10 +62,6 @@ public class TemplateOptions {
return publicKey; return publicKey;
} }
public boolean shouldDestroyOnError() {
return destroyOnError;
}
public boolean isIncludeMetadata() { public boolean isIncludeMetadata() {
return includeMetadata; return includeMetadata;
} }
@ -83,14 +77,6 @@ public class TemplateOptions {
return this; return this;
} }
/**
* If there is an error applying options after creating the node, destroy it.
*/
public TemplateOptions destroyOnError() {
this.destroyOnError = true;
return this;
}
/** /**
* This script will be executed as the root user upon system startup. This script gets a * This script will be executed as the root user upon system startup. This script gets a
* prologue, so no #!/bin/bash required, path set up, etc * prologue, so no #!/bin/bash required, path set up, etc
@ -139,13 +125,6 @@ public class TemplateOptions {
} }
public static class Builder { public static class Builder {
/**
* @see TemplateOptions#destroyOnError
*/
public static TemplateOptions destroyOnError() {
TemplateOptions options = new TemplateOptions();
return options.destroyOnError();
}
/** /**
* @see TemplateOptions#inboundPorts * @see TemplateOptions#inboundPorts
@ -198,7 +177,7 @@ public class TemplateOptions {
public String toString() { public String toString() {
return "TemplateOptions [inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey=" return "TemplateOptions [inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey="
+ (privateKey != null) + ", publicKey=" + (publicKey != null) + ", runScript=" + (privateKey != null) + ", publicKey=" + (publicKey != null) + ", runScript="
+ (script != null) + ", destroyOnError=" + destroyOnError + ", port:seconds=" + port + (script != null) + ", port:seconds=" + port + ":" + seconds
+ ":" + seconds + ", metadata/details: " + includeMetadata + "]"; + ", metadata/details: " + includeMetadata + "]";
} }
} }

View File

@ -38,5 +38,5 @@ import com.google.inject.ImplementedBy;
public interface RunNodesAndAddToSetStrategy { public interface RunNodesAndAddToSetStrategy {
Map<?, ListenableFuture<Void>> execute(String tag, int count, Template template, Map<?, ListenableFuture<Void>> execute(String tag, int count, Template template,
Set<NodeMetadata> nodes); Set<NodeMetadata> nodes, Map<NodeMetadata, Exception> badNodes);
} }

View File

@ -36,7 +36,6 @@ import org.jclouds.Constants;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.options.GetNodesOptions; import org.jclouds.compute.options.GetNodesOptions;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.AddNodeWithTagStrategy; import org.jclouds.compute.strategy.AddNodeWithTagStrategy;
@ -45,6 +44,8 @@ import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.compute.util.ComputeUtils; import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.logging.Logger; 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.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -83,7 +84,8 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAnd
*/ */
@Override @Override
public Map<?, ListenableFuture<Void>> execute(final String tag, final int count, public Map<?, ListenableFuture<Void>> execute(final String tag, final int count,
final Template template, final Set<NodeMetadata> nodes) { final Template template, final Set<NodeMetadata> nodes,
final Map<NodeMetadata, Exception> badNodes) {
Map<String, ListenableFuture<Void>> responses = Maps.newHashMap(); Map<String, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final String name : getNextNames(tag, template, count)) { for (final String name : getNextNames(tag, template, count)) {
responses.put(name, makeListenable(executor.submit(new Callable<Void>() { responses.put(name, makeListenable(executor.submit(new Callable<Void>() {
@ -100,8 +102,7 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAnd
} catch (Exception e) { } catch (Exception e) {
logger.error(e, "<< error applying options (%s) on node (%s)", template logger.error(e, "<< error applying options (%s) on node (%s)", template
.getOptions(), node.getId()); .getOptions(), node.getId());
if (!template.getOptions().shouldDestroyOnError()) badNodes.put(node, e);
nodes.add(node);
} }
return null; return null;
} }
@ -122,11 +123,20 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAnd
*/ */
protected Set<String> getNextNames(final String tag, final Template template, int count) { protected Set<String> getNextNames(final String tag, final Template template, int count) {
Set<String> names = Sets.newHashSet(); Set<String> names = Sets.newHashSet();
Map<String, ? extends ComputeMetadata> currentNodes = Maps.uniqueIndex(listNodesStrategy Iterable<? extends ComputeMetadata> currentNodes = listNodesStrategy
.execute(GetNodesOptions.NONE), BaseComputeService.METADATA_TO_NAME); .execute(GetNodesOptions.NONE);
while (names.size() < count) { int maxTries = 100;
String name = getNextName(tag, template); int currentTries = 0;
if (!currentNodes.containsKey(name)) { while (names.size() < count && currentTries++ < maxTries) {
final String name = getNextName(tag, template);
if (!Iterables.any(currentNodes, new Predicate<ComputeMetadata>() {
@Override
public boolean apply(ComputeMetadata input) {
return name.equals(input.getName());
}
})) {
names.add(name); names.add(name);
} }
} }

View File

@ -24,15 +24,16 @@ import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.Comparator; import java.util.Comparator;
import java.util.Formatter;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -84,7 +85,28 @@ public class ComputeUtils {
private final Predicate<InetSocketAddress> socketTester; private final Predicate<InetSocketAddress> socketTester;
private final ExecutorService executor; private final ExecutorService executor;
private int sshRetries = 3; public static String createExecutionErrorMessage(Map<?, Exception> executionExceptions) {
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(), Throwables
.getStackTraceAsString(errorMessage.getValue()));
}
return fmt.format("%s error[s]", executionExceptions.size()).toString();
}
public static String createNodeErrorMessage(
Map<? extends NodeMetadata, ? extends Throwable> failedNodes) {
Formatter fmt = new Formatter().format("Node failures:%n%n");
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(), Throwables
.getStackTraceAsString(errorMessage.getValue()));
}
return fmt.format("%s error[s]", failedNodes.size()).toString();
}
@Inject @Inject
public ComputeUtils(Predicate<InetSocketAddress> socketTester, public ComputeUtils(Predicate<InetSocketAddress> socketTester,
@ -117,7 +139,7 @@ public class ComputeUtils {
public void runOptionsOnNode(NodeMetadata node, TemplateOptions options) { public void runOptionsOnNode(NodeMetadata node, TemplateOptions options) {
List<SshCallable<?>> callables = Lists.newArrayList(); List<SshCallable<?>> callables = Lists.newArrayList();
if (options.getRunScript() != null) { if (options.getRunScript() != null) {
callables.add(runScriptOnNode(node, "runscript.sh", options.getRunScript())); callables.add(runScriptOnNode(node, "runscript", options.getRunScript()));
} }
if (options.getPublicKey() != null) { if (options.getPublicKey() != null) {
callables.add(authorizeKeyOnNode(node, options.getPublicKey())); callables.add(authorizeKeyOnNode(node, options.getPublicKey()));
@ -168,60 +190,60 @@ public class ComputeUtils {
Iterable<? extends SshCallable<?>> parallel, @Nullable SshCallable<?> last) { Iterable<? extends SshCallable<?>> parallel, @Nullable SshCallable<?> last) {
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured"); checkState(this.sshFactory != null, "runScript requested, but no SshModule configured");
checkNotNull(node.getCredentials().key, "credentials.key for node " + node.getId()); checkNotNull(node.getCredentials().key, "credentials.key for node " + node.getId());
SshClient ssh = createSshClientOncePortIsListeningOnNode(node);
try {
ssh.connect();
return runTasksUsingSshClient(parallel, last, ssh);
} finally {
if (ssh != null)
ssh.disconnect();
}
}
private Map<SshCallable<?>, ?> runTasksUsingSshClient(
Iterable<? extends SshCallable<?>> parallel, SshCallable<?> last, SshClient ssh) {
Map<SshCallable<?>, Object> responses = Maps.newHashMap();
if (Iterables.size(parallel) > 0) {
responses.putAll(runCallablesUsingSshClient(parallel, ssh));
}
if (last != null) {
last.setConnection(ssh, logger);
try {
responses.put(last, last.call());
} catch (Exception e) {
Throwables.propagate(e);
}
}
return responses;
}
public SshClient createSshClientOncePortIsListeningOnNode(NodeMetadata node) {
InetSocketAddress socket = new InetSocketAddress(Iterables.get(node.getPublicAddresses(), 0), InetSocketAddress socket = new InetSocketAddress(Iterables.get(node.getPublicAddresses(), 0),
22); 22);
socketTester.apply(socket); socketTester.apply(socket);
SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().account, SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().account,
node.getCredentials().key.getBytes()) : sshFactory.create(socket, node node.getCredentials().key.getBytes()) : sshFactory.create(socket, node
.getCredentials().account, node.getCredentials().key); .getCredentials().account, node.getCredentials().key);
for (int i = 0; i < sshRetries; i++) { return ssh;
try { }
ssh.connect();
Map<SshCallable<?>, ListenableFuture<?>> responses = Maps.newHashMap();
for (SshCallable<?> callable : parallel) { private Map<SshCallable<?>, Object> runCallablesUsingSshClient(
callable.setConnection(ssh, logger); Iterable<? extends SshCallable<?>> parallel, SshClient ssh) {
responses.put(callable, ConcurrentUtils.makeListenable(executor.submit(callable), Map<SshCallable<?>, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
executor));
}
Map<SshCallable<?>, Exception> exceptions = awaitCompletion(responses, executor, null, for (SshCallable<?> callable : parallel) {
logger, "ssh"); callable.setConnection(ssh, logger);
if (exceptions.size() > 0) parallelResponses.put(callable, ConcurrentUtils.makeListenable(executor.submit(callable),
throw new RuntimeException(String.format("error invoking callables on host %s: %s", executor));
socket, exceptions));
if (last != null) {
last.setConnection(ssh, logger);
try {
last.call();
} catch (Exception e) {
Throwables.propagate(e);
}
}
return transform(responses);
} catch (RuntimeException from) {
if (i + 1 == sshRetries)
throw Throwables.propagate(from);
if (Iterables.size(Iterables.filter(Throwables.getCausalChain(from),
ConnectException.class)) >= 1// auth fail sometimes happens in EC2
|| Throwables.getRootCause(from).getMessage().indexOf("Auth fail") != -1
|| Throwables.getRootCause(from).getMessage().indexOf("invalid privatekey") != -1) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw Throwables.propagate(e);
}
continue;
}
throw Throwables.propagate(from);
} finally {
if (ssh != null)
ssh.disconnect();
}
} }
throw new RuntimeException(String.format("Couldn't connect to node %s and run the script",
node.getId())); 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") @SuppressWarnings("unchecked")
@ -240,6 +262,8 @@ public class ComputeUtils {
} }
public static interface SshCallable<T> extends Callable<T> { public static interface SshCallable<T> extends Callable<T> {
NodeMetadata getNode();
void setConnection(SshClient ssh, Logger logger); void setConnection(SshClient ssh, Logger logger);
} }
@ -254,14 +278,7 @@ public class ComputeUtils {
RunScriptOnNode(@Named("NOT_RUNNING") Predicate<CommandUsingClient> runScriptNotRunning, RunScriptOnNode(@Named("NOT_RUNNING") Predicate<CommandUsingClient> runScriptNotRunning,
NodeMetadata node, String scriptName, byte[] script) { NodeMetadata node, String scriptName, byte[] script) {
this.runScriptNotRunning = runScriptNotRunning; this(runScriptNotRunning, node, scriptName, script, true);
this.node = checkNotNull(node, "node");
this.scriptName = checkNotNull(scriptName, "scriptName");
this.script = new InitBuilder("runscript", "/tmp", "/tmp", ImmutableMap
.<String, String> of(), Iterables.toArray(Splitter.on("\n").split(
new String(checkNotNull(script, "script"))), String.class)).build(OsFamily.UNIX)
.getBytes();
this.runAsRoot = true;
} }
RunScriptOnNode(@Named("NOT_RUNNING") Predicate<CommandUsingClient> runScriptNotRunning, RunScriptOnNode(@Named("NOT_RUNNING") Predicate<CommandUsingClient> runScriptNotRunning,
@ -269,10 +286,10 @@ public class ComputeUtils {
this.runScriptNotRunning = runScriptNotRunning; this.runScriptNotRunning = runScriptNotRunning;
this.node = checkNotNull(node, "node"); this.node = checkNotNull(node, "node");
this.scriptName = checkNotNull(scriptName, "scriptName"); this.scriptName = checkNotNull(scriptName, "scriptName");
this.script = new InitBuilder("runscript", "/tmp", "/tmp", ImmutableMap this.script = new InitBuilder(scriptName, "/tmp/" + scriptName, "/tmp/" + scriptName,
.<String, String> of(), Iterables.toArray(Splitter.on("\n").split( ImmutableMap.<String, String> of(), Iterables.toArray(Splitter.on("\n").split(
new String(checkNotNull(script, "script"))), String.class)).build(OsFamily.UNIX) new String(checkNotNull(script, "script"))), String.class)).build(
.getBytes(); OsFamily.UNIX).getBytes();
this.runAsRoot = runAsRoot; this.runAsRoot = runAsRoot;
} }
@ -329,6 +346,11 @@ public class ComputeUtils {
Iterables.get(node.getPublicAddresses(), 0).getHostAddress()); Iterables.get(node.getPublicAddresses(), 0).getHostAddress());
return ssh.exec(String.format("./%s", scriptName + " start")); return ssh.exec(String.format("./%s", scriptName + " start"));
} }
@Override
public NodeMetadata getNode() {
return node;
}
} }
public static class InstallRSAPrivateKey implements SshCallable<ExecResponse> { public static class InstallRSAPrivateKey implements SshCallable<ExecResponse> {
@ -358,6 +380,10 @@ public class ComputeUtils {
this.ssh = checkNotNull(ssh, "ssh"); this.ssh = checkNotNull(ssh, "ssh");
} }
@Override
public NodeMetadata getNode() {
return node;
}
} }
public static class AuthorizeRSAPublicKey implements SshCallable<ExecResponse> { public static class AuthorizeRSAPublicKey implements SshCallable<ExecResponse> {
@ -390,6 +416,10 @@ public class ComputeUtils {
this.ssh = checkNotNull(ssh, "ssh"); this.ssh = checkNotNull(ssh, "ssh");
} }
@Override
public NodeMetadata getNode() {
return node;
}
} }
public static boolean isKeyAuth(NodeMetadata createdNode) { public static boolean isKeyAuth(NodeMetadata createdNode) {
@ -434,4 +464,5 @@ public class ComputeUtils {
} }
return providers; return providers;
} }
} }

View File

@ -31,7 +31,6 @@ import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
@ -155,9 +154,9 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException") @Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
public void testImagesCache() throws Exception { public void testImagesCache() throws Exception {
client.getImages(); client.listImages();
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
client.getImages(); client.listImages();
long duration = System.currentTimeMillis() - time; long duration = System.currentTimeMillis() - time;
assert duration < 1000 : String.format("%dms to get images", duration); assert duration < 1000 : String.format("%dms to get images", duration);
} }
@ -183,7 +182,7 @@ public abstract class BaseComputeServiceLiveTest {
template.getOptions().installPrivateKey(keyPair.get("private")).authorizePublicKey( template.getOptions().installPrivateKey(keyPair.get("private")).authorizePublicKey(
keyPair.get("public")).runScript( keyPair.get("public")).runScript(
buildScript(template.getImage().getOsFamily()).getBytes()); buildScript(template.getImage().getOsFamily()).getBytes());
nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 2, template).values()); nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 2, template));
assertEquals(nodes.size(), 2); assertEquals(nodes.size(), 2);
checkNodes(nodes, tag); checkNodes(nodes, tag);
NodeMetadata node1 = nodes.first(); NodeMetadata node1 = nodes.first();
@ -210,8 +209,7 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCreateTwoNodesWithRunScript") @Test(enabled = true, dependsOnMethods = "testCreateTwoNodesWithRunScript")
public void testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired() throws Exception { public void testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired() throws Exception {
initializeContextAndClient(); initializeContextAndClient();
TreeSet<NodeMetadata> nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 1, template) TreeSet<NodeMetadata> nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 1, template));
.values());
checkNodes(nodes, tag); checkNodes(nodes, tag);
NodeMetadata node = nodes.first(); NodeMetadata node = nodes.first();
this.nodes.add(node); this.nodes.add(node);
@ -226,13 +224,13 @@ public abstract class BaseComputeServiceLiveTest {
Template simpleTemplate = buildTemplate(client.templateBuilder()); Template simpleTemplate = buildTemplate(client.templateBuilder());
simpleTemplate.getOptions().blockOnPort(22, 120); simpleTemplate.getOptions().blockOnPort(22, 120);
try { try {
Map<String, ? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, simpleTemplate); Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, simpleTemplate);
Credentials good = nodes.values().iterator().next().getCredentials(); Credentials good = nodes.iterator().next().getCredentials();
assert good.account != null; assert good.account != null;
try { try {
Map<String, ExecResponse> responses = runScriptWithCreds(tag, simpleTemplate.getImage() Map<NodeMetadata, ExecResponse> responses = runScriptWithCreds(tag, simpleTemplate
.getOsFamily(), new Credentials(good.account, "romeo")); .getImage().getOsFamily(), new Credentials(good.account, "romeo"));
assert false : "shouldn't pass with a bad password\n" + responses; assert false : "shouldn't pass with a bad password\n" + responses;
} catch (SshException e) { } catch (SshException e) {
assert Throwables.getRootCause(e).getMessage().contains("Auth fail") : e; assert Throwables.getRootCause(e).getMessage().contains("Auth fail") : e;
@ -240,22 +238,22 @@ public abstract class BaseComputeServiceLiveTest {
runScriptWithCreds(tag, simpleTemplate.getImage().getOsFamily(), good); runScriptWithCreds(tag, simpleTemplate.getImage().getOsFamily(), good);
checkNodes(nodes.values(), tag); checkNodes(nodes, tag);
} finally { } finally {
client.destroyNodesWithTag(tag); client.destroyNodesWithTag(tag);
} }
} }
private Map<String, ExecResponse> runScriptWithCreds(String tag, OsFamily osFamily, private Map<NodeMetadata, ExecResponse> runScriptWithCreds(String tag, OsFamily osFamily,
Credentials creds) { Credentials creds) throws RunScriptOnNodesException {
try { try {
return client.runScriptOnNodesWithTag(tag, buildScript(osFamily).getBytes(), return client.runScriptOnNodesWithTag(tag, buildScript(osFamily).getBytes(),
RunScriptOptions.Builder.overrideCredentialsWith(creds)); RunScriptOptions.Builder.overrideCredentialsWith(creds));
} catch (SshException e) { } catch (SshException e) {
if (Throwables.getRootCause(e).getMessage().contains("Auth fail")) { if (Throwables.getRootCause(e).getMessage().contains("Auth fail")) {
System.err.printf("bad credentials: %s:%s for %s%n", creds.account, creds.key, client System.err.printf("bad credentials: %s:%s for %s%n", creds.account, creds.key, client
.getNodesWithTag(tag)); .listNodesWithTag(tag));
} }
throw e; throw e;
} }
@ -316,7 +314,7 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired") @Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
public void testGet() throws Exception { public void testGet() throws Exception {
Set<? extends NodeMetadata> metadataSet = Sets.newHashSet(Iterables.filter(client Set<? extends NodeMetadata> metadataSet = Sets.newHashSet(Iterables.filter(client
.getNodesWithTag(tag).values(), Predicates.not(new Predicate<NodeMetadata>() { .listNodesWithTag(tag), Predicates.not(new Predicate<NodeMetadata>() {
@Override @Override
public boolean apply(NodeMetadata input) { public boolean apply(NodeMetadata input) {
return input.getState() == NodeState.TERMINATED; return input.getState() == NodeState.TERMINATED;
@ -352,23 +350,20 @@ public abstract class BaseComputeServiceLiveTest {
} }
public void testListNodes() throws Exception { public void testListNodes() throws Exception {
for (Entry<String, ? extends ComputeMetadata> node : client.getNodes().entrySet()) { for (ComputeMetadata node : client.listNodes()) {
assertEquals(node.getKey(), node.getValue().getId()); assert node.getId() != null;
assert node.getValue().getId() != null; assert node.getLocation() != null;
assert node.getValue().getLocation() != null; assertEquals(node.getType(), ComputeType.NODE);
assertEquals(node.getValue().getType(), ComputeType.NODE);
} }
} }
public void testGetNodesWithDetails() throws Exception { public void testGetNodesWithDetails() throws Exception {
for (Entry<String, ? extends ComputeMetadata> node : client.getNodes( for (ComputeMetadata node : client.listNodes(new GetNodesOptions().withDetails())) {
new GetNodesOptions().withDetails()).entrySet()) { assert node.getId() != null : node;
assertEquals(node.getKey(), node.getValue().getId()); assert node.getLocation() != null : node;
assert node.getValue().getId() != null : node; assertEquals(node.getType(), ComputeType.NODE);
assert node.getValue().getLocation() != null : node; assert node instanceof NodeMetadata;
assertEquals(node.getValue().getType(), ComputeType.NODE); NodeMetadata nodeMetadata = (NodeMetadata) node;
assert node.getValue() instanceof NodeMetadata;
NodeMetadata nodeMetadata = (NodeMetadata) node.getValue();
assert nodeMetadata.getId() != null : nodeMetadata; assert nodeMetadata.getId() != null : nodeMetadata;
// nullable // nullable
// assert nodeMetadata.getImage() != null : node; // assert nodeMetadata.getImage() != null : node;
@ -384,41 +379,39 @@ public abstract class BaseComputeServiceLiveTest {
} }
public void testListImages() throws Exception { public void testListImages() throws Exception {
for (Entry<String, ? extends Image> image : client.getImages().entrySet()) { for (Image image : client.listImages()) {
assertEquals(image.getKey(), image.getValue().getId()); assert image.getId() != null : image;
assert image.getValue().getId() != null : image; // image.getLocationId() can be null, if it is a location-free image
// image.getValue().getLocationId() can be null, if it is a location-free image assertEquals(image.getType(), ComputeType.IMAGE);
assertEquals(image.getValue().getType(), ComputeType.IMAGE);
} }
} }
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
public void testGetAssignableLocations() throws Exception { public void testGetAssignableLocations() throws Exception {
for (Entry<String, ? extends Location> location : client.getAssignableLocations().entrySet()) { for (Location location : client.listAssignableLocations()) {
System.err.printf("location %s%n", location.getValue()); System.err.printf("location %s%n", location);
assertEquals(location.getKey(), location.getValue().getId()); assert location.getId() != null : location;
assert location.getValue().getId() != null : location; assert location != location.getParent() : location;
assert location.getValue() != location.getValue().getParent() : location; assert location.getScope() != null : location;
assert location.getValue().getScope() != null : location; switch (location.getScope()) {
switch (location.getValue().getScope()) {
case PROVIDER: case PROVIDER:
assertProvider(location.getValue()); assertProvider(location);
break; break;
case REGION: case REGION:
assertProvider(location.getValue().getParent()); assertProvider(location.getParent());
break; break;
case ZONE: case ZONE:
Location provider = location.getValue().getParent().getParent(); Location provider = location.getParent().getParent();
// zone can be a direct descendant of provider // zone can be a direct descendant of provider
if (provider == null) if (provider == null)
provider = location.getValue().getParent(); provider = location.getParent();
assertProvider(provider); assertProvider(provider);
break; break;
case HOST: case HOST:
Location provider2 = location.getValue().getParent().getParent().getParent(); Location provider2 = location.getParent().getParent().getParent();
// zone can be a direct descendant of provider // zone can be a direct descendant of provider
if (provider2 == null) if (provider2 == null)
provider2 = location.getValue().getParent().getParent(); provider2 = location.getParent().getParent();
assertProvider(provider2); assertProvider(provider2);
break; break;
} }
@ -431,14 +424,13 @@ public abstract class BaseComputeServiceLiveTest {
} }
public void testListSizes() throws Exception { public void testListSizes() throws Exception {
for (Entry<String, ? extends Size> size : client.getSizes().entrySet()) { for (Size size : client.listSizes()) {
assertEquals(size.getKey(), size.getValue().getId()); assert size.getId() != null;
assert size.getValue().getId() != null; assert size.getCores() > 0;
assert size.getValue().getCores() > 0; assert size.getDisk() > 0;
assert size.getValue().getDisk() > 0; assert size.getRam() > 0;
assert size.getValue().getRam() > 0; assert size.getSupportedArchitectures() != null;
assert size.getValue().getSupportedArchitectures() != null; assertEquals(size.getType(), ComputeType.SIZE);
assertEquals(size.getValue().getType(), ComputeType.SIZE);
} }
} }
@ -480,7 +472,7 @@ public abstract class BaseComputeServiceLiveTest {
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException { protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (nodes != null) { if (nodes != null) {
client.destroyNodesWithTag(tag); client.destroyNodesWithTag(tag);
for (NodeMetadata node : client.getNodesWithTag(tag).values()) { for (NodeMetadata node : client.listNodesWithTag(tag)) {
assert node.getState() == NodeState.TERMINATED : node; assert node.getState() == NodeState.TERMINATED : node;
} }
} }

View File

@ -29,7 +29,7 @@ import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; import org.jclouds.domain.internal.LocationImpl;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet;
/** /**
* *
@ -40,8 +40,8 @@ public class TemplateBuilderImplTest {
@Test @Test
public void testImageIdNullsEverythingElse() { public void testImageIdNullsEverythingElse() {
TemplateBuilderImpl template = new TemplateBuilderImpl(ImmutableMap.<String, Location> of(), TemplateBuilderImpl template = new TemplateBuilderImpl(ImmutableSet.<Location> of(),
ImmutableMap.<String, Image> of(), ImmutableMap.<String, Size> of(), ImmutableSet.<Image> of(), ImmutableSet.<Size> of(),
new LocationImpl(LocationScope.REGION, " id", "description", null)); new LocationImpl(LocationScope.REGION, " id", "description", null));
template.architecture(Architecture.X86_32); template.architecture(Architecture.X86_32);
template.imageDescriptionMatches("imageDescriptionMatches"); template.imageDescriptionMatches("imageDescriptionMatches");

View File

@ -57,9 +57,6 @@ Ensure the module is on the classpath. You are maybe missing a dependency on
(filter (complement nil?) (filter (complement nil?)
(map (comp instantiate module-lookup) modules))))) (map (comp instantiate module-lookup) modules)))))
(defn seq-from-immutable-set [#^ImmutableSet set]
(map #(.getValue %) set))
(defn dashed [a] (defn dashed [a]
(apply str (interpose "-" (map string/lower-case (re-seq #"[A-Z][^A-Z]*" a))))) (apply str (interpose "-" (map string/lower-case (re-seq #"[A-Z][^A-Z]*" a)))))

View File

@ -25,7 +25,10 @@ import java.util.Locale;
import java.util.SimpleTimeZone; import java.util.SimpleTimeZone;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Resource;
import org.jclouds.date.DateService; import org.jclouds.date.DateService;
import org.jclouds.logging.Logger;
/** /**
* *
@ -35,23 +38,26 @@ import org.jclouds.date.DateService;
* @author James Murty * @author James Murty
*/ */
public class SimpleDateFormatDateService implements DateService { public class SimpleDateFormatDateService implements DateService {
@Resource
protected Logger logger = Logger.NULL;
/* /*
* Use default Java Date/SimpleDateFormat classes for date manipulation, but be *very* careful to * Use default Java Date/SimpleDateFormat classes for date manipulation, but be *very* careful to
* guard against the lack of thread safety. * guard against the lack of thread safety.
*/ */
//@GuardedBy("this") // @GuardedBy("this")
private static final SimpleDateFormat iso8601SecondsSimpleDateFormat = new SimpleDateFormat( private static final SimpleDateFormat iso8601SecondsSimpleDateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); "yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
//@GuardedBy("this") // @GuardedBy("this")
private static final SimpleDateFormat iso8601SimpleDateFormat = new SimpleDateFormat( private static final SimpleDateFormat iso8601SimpleDateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
//@GuardedBy("this") // @GuardedBy("this")
private static final SimpleDateFormat rfc822SimpleDateFormat = new SimpleDateFormat( private static final SimpleDateFormat rfc822SimpleDateFormat = new SimpleDateFormat(
"EEE, dd MMM yyyy HH:mm:ss z", Locale.US); "EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
//@GuardedBy("this") // @GuardedBy("this")
private static final SimpleDateFormat cSimpleDateFormat = new SimpleDateFormat( private static final SimpleDateFormat cSimpleDateFormat = new SimpleDateFormat(
"EEE MMM dd HH:mm:ss '+0000' yyyy", Locale.US); "EEE MMM dd HH:mm:ss '+0000' yyyy", Locale.US);
@ -134,6 +140,8 @@ public class SimpleDateFormatDateService implements DateService {
public static final Pattern NANOS_TO_MILLIS_PATTERN = Pattern public static final Pattern NANOS_TO_MILLIS_PATTERN = Pattern
.compile(".*[0-9][0-9][0-9][0-9][0-9][0-9]"); .compile(".*[0-9][0-9][0-9][0-9][0-9][0-9]");
public static final Pattern TZ_PATTERN = Pattern.compile(".*[+][0-9][0-9]:[0-9][0-9]");
private String trimNanosToMillis(String toParse) { private String trimNanosToMillis(String toParse) {
if (NANOS_TO_MILLIS_PATTERN.matcher(toParse).matches()) if (NANOS_TO_MILLIS_PATTERN.matcher(toParse).matches())
toParse = toParse.substring(0, toParse.length() - 3) + 'Z'; toParse = toParse.substring(0, toParse.length() - 3) + 'Z';
@ -143,6 +151,10 @@ public class SimpleDateFormatDateService implements DateService {
public static final Pattern SECOND_PATTERN = Pattern.compile(".*[0-2][0-9]:00"); public static final Pattern SECOND_PATTERN = Pattern.compile(".*[0-2][0-9]:00");
private String trimTZ(String toParse) { private String trimTZ(String toParse) {
if (TZ_PATTERN.matcher(toParse).matches()) {
logger.warn("trimming tz from %s", toParse);
toParse = toParse.substring(0, toParse.length() - 6) + 'Z';
}
if (toParse.length() == 25 && SECOND_PATTERN.matcher(toParse).matches()) if (toParse.length() == 25 && SECOND_PATTERN.matcher(toParse).matches())
toParse = toParse.substring(0, toParse.length() - 6) + 'Z'; toParse = toParse.substring(0, toParse.length() - 6) + 'Z';
return toParse; return toParse;

View File

@ -38,6 +38,8 @@ public class MapHttp4xxCodesToExceptions implements Function<Exception, Object>
switch (responseException.getResponse().getStatusCode()) { switch (responseException.getResponse().getStatusCode()) {
case 401: case 401:
throw new AuthorizationException(from); throw new AuthorizationException(from);
case 403:
throw new AuthorizationException(from);
case 404: case 404:
throw new ResourceNotFoundException(from); throw new ResourceNotFoundException(from);
} }

View File

@ -58,15 +58,18 @@ public class DateServiceTest extends PerformanceTest {
protected class TestData { protected class TestData {
public final String iso8601DateString; public final String iso8601DateString;
public final String iso8601DateStringTz;
public final String iso8601SecondsDateString; public final String iso8601SecondsDateString;
public final String rfc822DateString; public final String rfc822DateString;
public final String cDateString; public final String cDateString;
public final Date date; public final Date date;
TestData(String iso8601, String iso8601Seconds, String rfc822, String cDateString, TestData(String iso8601, String iso8601DateStringTz, String iso8601Seconds, String rfc822,
Date dateTime) { String cDateString, Date dateTime) {
this.iso8601DateString = iso8601; this.iso8601DateString = iso8601;
this.iso8601DateStringTz = iso8601DateStringTz;
this.iso8601SecondsDateString = iso8601Seconds; this.iso8601SecondsDateString = iso8601Seconds;
this.rfc822DateString = rfc822; this.rfc822DateString = rfc822;
this.cDateString = cDateString; this.cDateString = cDateString;
@ -77,21 +80,21 @@ public class DateServiceTest extends PerformanceTest {
public DateServiceTest() { public DateServiceTest() {
// Constant time test values, each TestData item must contain matching times! // Constant time test values, each TestData item must contain matching times!
testData = new TestData[] { testData = new TestData[] {
new TestData("2009-03-12T02:00:07.000Z", "2009-03-12T02:00:07Z", new TestData("2009-03-12T02:00:07.000Z", "2009-03-12T02:00:07+04:00",
"Thu, 12 Mar 2009 02:00:07 GMT", "Thu Mar 12 02:00:07 +0000 2009", "2009-03-12T02:00:07Z", "Thu, 12 Mar 2009 02:00:07 GMT",
new Date(1236823207000l)), "Thu Mar 12 02:00:07 +0000 2009", new Date(1236823207000l)),
new TestData("2009-03-14T04:00:07.000Z", "2009-03-14T04:00:07Z", new TestData("2009-03-14T04:00:07.000Z", "2009-03-14T04:00:07Z+04:00",
"Sat, 14 Mar 2009 04:00:07 GMT", "Thu Mar 14 04:00:07 +0000 2009", "2009-03-14T04:00:07Z", "Sat, 14 Mar 2009 04:00:07 GMT",
new Date(1237003207000l)), "Thu Mar 14 04:00:07 +0000 2009", new Date(1237003207000l)),
new TestData("2009-03-16T06:00:07.000Z", "2009-03-16T06:00:07Z", new TestData("2009-03-16T06:00:07.000Z", "2009-03-16T06:00:07Z+04:00",
"Mon, 16 Mar 2009 06:00:07 GMT", "Thu Mar 16 06:00:07 +0000 2009", "2009-03-16T06:00:07Z", "Mon, 16 Mar 2009 06:00:07 GMT",
new Date(1237183207000l)), "Thu Mar 16 06:00:07 +0000 2009", new Date(1237183207000l)),
new TestData("2009-03-18T08:00:07.000Z", "2009-03-18T08:00:07Z", new TestData("2009-03-18T08:00:07.000Z", "2009-03-18T08:00:07Z+04:00",
"Wed, 18 Mar 2009 08:00:07 GMT", "Thu Mar 18 08:00:07 +0000 2009", "2009-03-18T08:00:07Z", "Wed, 18 Mar 2009 08:00:07 GMT",
new Date(1237363207000l)), "Thu Mar 18 08:00:07 +0000 2009", new Date(1237363207000l)),
new TestData("2009-03-20T10:00:07.000Z", "2009-03-20T10:00:07Z", new TestData("2009-03-20T10:00:07.000Z", "2009-03-20T10:00:07Z+04:00",
"Fri, 20 Mar 2009 10:00:07 GMT", "Thu Mar 20 10:00:07 +0000 2009", "2009-03-20T10:00:07Z", "Fri, 20 Mar 2009 10:00:07 GMT",
new Date(1237543207000l)) }; "Thu Mar 20 10:00:07 +0000 2009", new Date(1237543207000l)) };
} }
@Test @Test
@ -99,6 +102,11 @@ public class DateServiceTest extends PerformanceTest {
Date dsDate = dateService.iso8601DateParse(testData[0].iso8601DateString); Date dsDate = dateService.iso8601DateParse(testData[0].iso8601DateString);
assertEquals(dsDate, testData[0].date); assertEquals(dsDate, testData[0].date);
} }
@Test
public void testIso8601DateParseTz() throws ExecutionException, InterruptedException {
Date dsDate = dateService.iso8601SecondsDateParse(testData[0].iso8601DateStringTz);
assertEquals(dsDate, testData[0].date);
}
@Test @Test
public void testIso8601SecondsDateParse() throws ExecutionException, InterruptedException { public void testIso8601SecondsDateParse() throws ExecutionException, InterruptedException {

View File

@ -24,6 +24,7 @@ import static com.google.common.base.Preconditions.checkState;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.ConnectException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@ -40,6 +41,8 @@ import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshException; import org.jclouds.ssh.SshException;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.io.Closeables; import com.google.common.io.Closeables;
import com.jcraft.jsch.ChannelExec; import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.ChannelSftp;
@ -75,6 +78,7 @@ public class JschSshClient implements SshClient {
private final int port; private final int port;
private final String username; private final String username;
private final String password; private final String password;
private int sshRetries = 3;
@Resource @Resource
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
@ -177,15 +181,37 @@ public class JschSshClient implements SshClient {
java.util.Properties config = new java.util.Properties(); java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no"); config.put("StrictHostKeyChecking", "no");
session.setConfig(config); session.setConfig(config);
try { RETRY_LOOP: for (int i = 0; i < sshRetries; i++) {
session.connect(); try {
} catch (JSchException e) { session.connect();
throw new SshException(String.format("%s@%s:%d: Error connecting to session.", username, break RETRY_LOOP;
host.getHostAddress(), port), e); } catch (Exception from) {
String rootMessage = Throwables.getRootCause(from).getMessage();
if (i + 1 == sshRetries)
throw propagate(from);
if (Iterables.size(Iterables.filter(Throwables.getCausalChain(from),
ConnectException.class)) >= 1
|| rootMessage.indexOf("Auth fail") != -1// auth fail sometimes happens in EC2
|| rootMessage.indexOf("invalid data") != -1
|| rootMessage.indexOf("invalid privatekey") != -1) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw propagate(e);
}
continue;
}
throw propagate(from);
}
} }
logger.debug("%s@%s:%d: Session connected.", username, host.getHostAddress(), port); logger.debug("%s@%s:%d: Session connected.", username, host.getHostAddress(), port);
} }
private SshException propagate(Exception e) {
throw new SshException(String.format("%s@%s:%d: Error connecting to session.", username, host
.getHostAddress(), port), e);
}
@PreDestroy @PreDestroy
public void disconnect() { public void disconnect() {
if (session != null && session.isConnected()) if (session != null && session.isConnected())

View File

@ -23,14 +23,18 @@
*/ */
package org.jclouds.gogrid; package org.jclouds.gogrid;
import org.jclouds.PropertiesBuilder;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.gogrid.reference.GoGridConstants.*; import static org.jclouds.gogrid.reference.GoGridConstants.PROPERTY_GOGRID_DEFAULT_DC;
import static org.jclouds.gogrid.reference.GoGridConstants.PROPERTY_GOGRID_ENDPOINT;
import static org.jclouds.gogrid.reference.GoGridConstants.PROPERTY_GOGRID_PASSWORD;
import static org.jclouds.gogrid.reference.GoGridConstants.PROPERTY_GOGRID_SESSIONINTERVAL;
import static org.jclouds.gogrid.reference.GoGridConstants.PROPERTY_GOGRID_USER;
import java.net.URI; import java.net.URI;
import java.util.Properties; import java.util.Properties;
import org.jclouds.PropertiesBuilder;
/** /**
* Builds properties used in GoGrid Clients * Builds properties used in GoGrid Clients
* *
@ -44,7 +48,7 @@ public class GoGridPropertiesBuilder extends PropertiesBuilder {
Properties properties = super.defaultProperties(); Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_GOGRID_ENDPOINT, "https://api.gogrid.com/api"); properties.setProperty(PROPERTY_GOGRID_ENDPOINT, "https://api.gogrid.com/api");
properties.setProperty(PROPERTY_GOGRID_SESSIONINTERVAL, 60 + ""); properties.setProperty(PROPERTY_GOGRID_SESSIONINTERVAL, 60 + "");
properties.setProperty(PROPERTY_GOGRID_DEFAULT_DC, "SANFRANCISCO");
return properties; return properties;
} }

View File

@ -19,6 +19,7 @@
package org.jclouds.gogrid.compute.config; package org.jclouds.gogrid.compute.config;
import static org.jclouds.compute.domain.OsFamily.CENTOS; import static org.jclouds.compute.domain.OsFamily.CENTOS;
import static org.jclouds.gogrid.reference.GoGridConstants.PROPERTY_GOGRID_DEFAULT_DC;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
@ -82,7 +83,6 @@ import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -279,13 +279,21 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Provides @Provides
@Singleton @Singleton
Location getDefaultLocation(Map<String, ? extends Location> locations) { Location getDefaultLocation(@Named(PROPERTY_GOGRID_DEFAULT_DC) final String defaultDC,
return locations.get("SANFRANCISCO"); Set<? extends Location> locations) {
return Iterables.find(locations, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(defaultDC);
}
});
} }
@Provides @Provides
@Singleton @Singleton
Map<String, ? extends Location> getDefaultLocations(GoGridClient sync, LogHolder holder, Set<? extends Location> getDefaultLocations(GoGridClient sync, LogHolder holder,
Function<ComputeMetadata, String> indexer) { Function<ComputeMetadata, String> indexer) {
final Set<Location> locations = Sets.newHashSet(); final Set<Location> locations = Sets.newHashSet();
holder.logger.debug(">> providing locations"); holder.logger.debug(">> providing locations");
@ -293,13 +301,7 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
locations.add(new LocationImpl(LocationScope.ZONE, "SANFRANCISCO", "San Francisco, CA", locations.add(new LocationImpl(LocationScope.ZONE, "SANFRANCISCO", "San Francisco, CA",
parent)); parent));
holder.logger.debug("<< locations(%d)", locations.size()); holder.logger.debug("<< locations(%d)", locations.size());
return Maps.uniqueIndex(locations, new Function<Location, String>() { return locations;
@Override
public String apply(Location from) {
return from.getId();
}
});
} }
@Provides @Provides
@ -315,10 +317,9 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Provides @Provides
@Singleton @Singleton
protected Map<String, ? extends Size> provideSizes(GoGridClient sync, protected Set<? extends Size> provideSizes(GoGridClient sync, Set<? extends Image> images,
Map<String, ? extends Image> images, LogHolder holder, LogHolder holder, Function<ComputeMetadata, String> indexer)
Function<ComputeMetadata, String> indexer) throws InterruptedException, throws InterruptedException, TimeoutException, ExecutionException {
TimeoutException, ExecutionException {
final Set<Size> sizes = Sets.newHashSet(); final Set<Size> sizes = Sets.newHashSet();
holder.logger.debug(">> providing sizes"); holder.logger.debug(">> providing sizes");
@ -333,7 +334,7 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
sizes.add(new SizeImpl("5", "5", null, null, ImmutableMap.<String, String> of(), 6, 8192, sizes.add(new SizeImpl("5", "5", null, null, ImmutableMap.<String, String> of(), 6, 8192,
462, ImmutableSet.<Architecture> of(Architecture.X86_32, Architecture.X86_64))); 462, ImmutableSet.<Architecture> of(Architecture.X86_32, Architecture.X86_64)));
holder.logger.debug("<< sizes(%d)", sizes.size()); holder.logger.debug("<< sizes(%d)", sizes.size());
return Maps.uniqueIndex(sizes, indexer); return sizes;
} }
private static class LogHolder { private static class LogHolder {
@ -346,7 +347,7 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Provides @Provides
@Singleton @Singleton
protected Map<String, ? extends Image> provideImages(final GoGridClient sync, LogHolder holder, protected Set<? extends Image> provideImages(final GoGridClient sync, LogHolder holder,
Function<ComputeMetadata, String> indexer, Location location, Function<ComputeMetadata, String> indexer, Location location,
PopulateDefaultLoginCredentialsForImageStrategy authenticator) PopulateDefaultLoginCredentialsForImageStrategy authenticator)
throws InterruptedException, ExecutionException, TimeoutException { throws InterruptedException, ExecutionException, TimeoutException {
@ -375,6 +376,6 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
osDescription, arch, defaultCredentials)); osDescription, arch, defaultCredentials));
} }
holder.logger.debug("<< images(%d)", images.size()); holder.logger.debug("<< images(%d)", images.size());
return Maps.uniqueIndex(images, indexer); return images;
} }
} }

View File

@ -22,10 +22,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -37,11 +39,14 @@ import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.gogrid.domain.Server; import org.jclouds.gogrid.domain.Server;
import org.jclouds.gogrid.services.GridServerClient; import org.jclouds.gogrid.services.GridServerClient;
import org.jclouds.logging.Logger;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/** /**
* @author Oleksiy Yarmula * @author Oleksiy Yarmula
@ -50,14 +55,33 @@ import com.google.common.collect.ImmutableSet;
public class ServerToNodeMetadata implements Function<Server, NodeMetadata> { public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
public static final Pattern ALL_BEFORE_HYPHEN_HEX = Pattern.compile("([^-]+)-[0-9a-f]+"); public static final Pattern ALL_BEFORE_HYPHEN_HEX = Pattern.compile("([^-]+)-[0-9a-f]+");
@Resource
protected Logger logger = Logger.NULL;
private final Map<String, NodeState> serverStateToNodeState; private final Map<String, NodeState> serverStateToNodeState;
private final GridServerClient client; private final GridServerClient client;
private final Location location; private final Location location;
private final Map<String, ? extends Image> images; private final Set<? extends Image> images;
private static class FindImageForServer implements Predicate<Image> {
private final Location location;
private final Server instance;
private FindImageForServer(Location location, Server instance) {
this.location = location;
this.instance = instance;
}
@Override
public boolean apply(Image input) {
return input.getId().equals(instance.getImage().getId() + "")
&& (input.getLocation() == null || input.getLocation().equals(location) || input
.getLocation().equals(location.getParent()));
}
}
@Inject @Inject
ServerToNodeMetadata(Map<String, NodeState> serverStateToNodeState, GridServerClient client, ServerToNodeMetadata(Map<String, NodeState> serverStateToNodeState, GridServerClient client,
Map<String, ? extends Image> images, Location location) { Set<? extends Image> images, Location location) {
this.serverStateToNodeState = checkNotNull(serverStateToNodeState, "serverStateToNodeState"); this.serverStateToNodeState = checkNotNull(serverStateToNodeState, "serverStateToNodeState");
this.client = checkNotNull(client, "client"); this.client = checkNotNull(client, "client");
this.images = checkNotNull(images, "images"); this.images = checkNotNull(images, "images");
@ -71,8 +95,16 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
Set<InetAddress> ipSet = ImmutableSet.of(from.getIp().getIp()); Set<InetAddress> ipSet = ImmutableSet.of(from.getIp().getIp());
NodeState state = serverStateToNodeState.get(from.getState().getName()); NodeState state = serverStateToNodeState.get(from.getState().getName());
Credentials creds = client.getServerCredentialsList().get(from.getName()); Credentials creds = client.getServerCredentialsList().get(from.getName());
Image image = null;
try {
image = Iterables.find(images, new FindImageForServer(location, from));
} catch (NoSuchElementException e) {
logger
.warn("could not find a matching image for server %s in location %s", from,
location);
}
return new NodeMetadataImpl(from.getId() + "", from.getName(), location, null, ImmutableMap return new NodeMetadataImpl(from.getId() + "", from.getName(), location, null, ImmutableMap
.<String, String> of(), tag, images.get(from.getImage().getId() + ""), state, ipSet, .<String, String> of(), tag, image, state, ipSet, ImmutableList.<InetAddress> of(),
ImmutableList.<InetAddress> of(), ImmutableMap.<String, String> of(), creds); ImmutableMap.<String, String> of(), creds);
} }
} }

View File

@ -29,12 +29,13 @@ package org.jclouds.gogrid.reference;
* @author Adrian Cole * @author Adrian Cole
*/ */
public interface GoGridConstants { public interface GoGridConstants {
public static final String PROPERTY_GOGRID_ENDPOINT = "jclouds.gogrid.endpoint"; public static final String PROPERTY_GOGRID_ENDPOINT = "jclouds.gogrid.endpoint";
public static final String PROPERTY_GOGRID_USER = "jclouds.gogrid.api.key"; public static final String PROPERTY_GOGRID_USER = "jclouds.gogrid.api.key";
public static final String PROPERTY_GOGRID_PASSWORD = "jclouds.gogrid.secret"; public static final String PROPERTY_GOGRID_PASSWORD = "jclouds.gogrid.secret";
/** /**
* how long do we wait before obtaining a new timestamp for requests. * how long do we wait before obtaining a new timestamp for requests.
*/ */
public static final String PROPERTY_GOGRID_SESSIONINTERVAL = "jclouds.gogrid.sessioninterval"; public static final String PROPERTY_GOGRID_SESSIONINTERVAL = "jclouds.gogrid.sessioninterval";
public static final String PROPERTY_GOGRID_DEFAULT_DC = "jclouds.gogrid.defaultdc";
} }

View File

@ -9,6 +9,7 @@ import static org.testng.Assert.assertEquals;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
@ -23,6 +24,8 @@ import org.jclouds.gogrid.domain.ServerImage;
import org.jclouds.gogrid.services.GridServerClient; import org.jclouds.gogrid.services.GridServerClient;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
@ -34,7 +37,9 @@ public class ServerToNodeMetadataTest {
public void testApplySetsTagFromNameAndCredentialsFromName() throws UnknownHostException { public void testApplySetsTagFromNameAndCredentialsFromName() throws UnknownHostException {
GridServerClient client = createMock(GridServerClient.class); GridServerClient client = createMock(GridServerClient.class);
Map<String, NodeState> serverStateToNodeState = createMock(Map.class); Map<String, NodeState> serverStateToNodeState = createMock(Map.class);
Map<String, org.jclouds.compute.domain.Image> images = createMock(Map.class); org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
Set<org.jclouds.compute.domain.Image> images = ImmutableSet.of(jcImage);
Server server = createMock(Server.class); Server server = createMock(Server.class);
expect(server.getId()).andReturn(1000l).atLeastOnce(); expect(server.getId()).andReturn(1000l).atLeastOnce();
@ -54,16 +59,15 @@ public class ServerToNodeMetadataTest {
ServerImage image = createMock(ServerImage.class); ServerImage image = createMock(ServerImage.class);
expect(server.getImage()).andReturn(image).atLeastOnce(); expect(server.getImage()).andReturn(image).atLeastOnce();
expect(image.getId()).andReturn(2000l).atLeastOnce(); expect(image.getId()).andReturn(2000l).atLeastOnce();
expect(jcImage.getId()).andReturn("2000").atLeastOnce();
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class); expect(jcImage.getLocation()).andReturn(location).atLeastOnce();
expect(images.get("2000")).andReturn(jcImage);
replay(client); replay(client);
replay(serverStateToNodeState); replay(serverStateToNodeState);
replay(server); replay(server);
replay(image); replay(image);
replay(jcImage);
replay(credentialsMap); replay(credentialsMap);
replay(images);
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, client, ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, client,
images, location); images, location);
@ -79,7 +83,8 @@ public class ServerToNodeMetadataTest {
verify(image); verify(image);
verify(credentialsMap); verify(credentialsMap);
verify(server); verify(server);
verify(images); verify(jcImage);
} }
} }

View File

@ -21,7 +21,6 @@ package org.jclouds.rackspace.cloudfiles.blobstore;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.compose; import static com.google.common.util.concurrent.Futures.compose;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -81,7 +80,7 @@ public class CloudFilesAsyncBlobStore extends BaseAsyncBlobStore {
@Inject @Inject
CloudFilesAsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, CloudFilesAsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Map<String, ? extends Location> locations, Location defaultLocation, Set<? extends Location> locations,
CloudFilesClient sync, CloudFilesAsyncClient async, CloudFilesClient sync, CloudFilesAsyncClient async,
ContainerToResourceMetadata container2ResourceMd, ContainerToResourceMetadata container2ResourceMd,
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions, BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,

View File

@ -20,7 +20,6 @@ package org.jclouds.rackspace.cloudfiles.blobstore;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
@ -70,7 +69,7 @@ public class CloudFilesBlobStore extends BaseBlobStore {
@Inject @Inject
CloudFilesBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, CloudFilesBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
Location defaultLocation, Map<String, ? extends Location> locations, Location defaultLocation, Set<? extends Location> locations,
CloudFilesClient sync, ContainerToResourceMetadata container2ResourceMd, CloudFilesClient sync, ContainerToResourceMetadata container2ResourceMd,
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions, BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob, ContainerToResourceList container2ResourceList, ObjectToBlob object2Blob,

View File

@ -87,7 +87,6 @@ import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -303,8 +302,8 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Provides @Provides
@Singleton @Singleton
protected Map<String, ? extends Size> provideSizes(CloudServersClient sync, protected Set<? extends Size> provideSizes(CloudServersClient sync, Set<? extends Image> images,
Map<String, ? extends Image> images, Location location, LogHolder holder, Location location, LogHolder holder,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
Function<ComputeMetadata, String> indexer) throws InterruptedException, Function<ComputeMetadata, String> indexer) throws InterruptedException,
TimeoutException, ExecutionException { TimeoutException, ExecutionException {
@ -316,7 +315,7 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
ImmutableSet.<Architecture> of(Architecture.X86_32, Architecture.X86_64))); ImmutableSet.<Architecture> of(Architecture.X86_32, Architecture.X86_64)));
} }
holder.logger.debug("<< sizes(%d)", sizes.size()); holder.logger.debug("<< sizes(%d)", sizes.size());
return Maps.uniqueIndex(sizes, indexer); return sizes;
} }
private static class LogHolder { private static class LogHolder {
@ -329,8 +328,8 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Provides @Provides
@Singleton @Singleton
protected Map<String, ? extends Image> provideImages(final CloudServersClient sync, protected Set<? extends Image> provideImages(final CloudServersClient sync, Location location,
Location location, LogHolder holder, Function<ComputeMetadata, String> indexer) LogHolder holder, Function<ComputeMetadata, String> indexer)
throws InterruptedException, ExecutionException, TimeoutException { throws InterruptedException, ExecutionException, TimeoutException {
final Set<Image> images = Sets.newHashSet(); final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images"); holder.logger.debug(">> providing images");
@ -358,6 +357,6 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
new Credentials("root", null))); new Credentials("root", null)));
} }
holder.logger.debug("<< images(%d)", images.size()); holder.logger.debug("<< images(%d)", images.size());
return Maps.uniqueIndex(images, indexer); return images;
} }
} }

View File

@ -21,9 +21,12 @@ package org.jclouds.rackspace.cloudservers.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
@ -33,11 +36,14 @@ import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.logging.Logger;
import org.jclouds.rackspace.cloudservers.domain.Server; import org.jclouds.rackspace.cloudservers.domain.Server;
import org.jclouds.rackspace.cloudservers.domain.ServerStatus; import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -47,11 +53,31 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
.compile("[^-]+-([^-]+)-[0-9a-f]+"); .compile("[^-]+-([^-]+)-[0-9a-f]+");
private final Location location; private final Location location;
private final Map<ServerStatus, NodeState> serverToNodeState; private final Map<ServerStatus, NodeState> serverToNodeState;
private final Map<String, ? extends Image> images; private final Set<? extends Image> images;
@Resource
protected Logger logger = Logger.NULL;
private static class FindImageForServer implements Predicate<Image> {
private final Location location;
private final Server instance;
private FindImageForServer(Location location, Server instance) {
this.location = location;
this.instance = instance;
}
@Override
public boolean apply(Image input) {
return input.getId().equals(instance.getImageId() + "")
&& (input.getLocation() == null || input.getLocation().equals(
location.getParent()));
}
}
@Inject @Inject
ServerToNodeMetadata(Map<ServerStatus, NodeState> serverStateToNodeState, ServerToNodeMetadata(Map<ServerStatus, NodeState> serverStateToNodeState,
Map<String, ? extends Image> images, Location location) { Set<? extends Image> images, Location location) {
this.serverToNodeState = checkNotNull(serverStateToNodeState, "serverStateToNodeState"); this.serverToNodeState = checkNotNull(serverStateToNodeState, "serverStateToNodeState");
this.images = checkNotNull(images, "images"); this.images = checkNotNull(images, "images");
this.location = checkNotNull(location, "location"); this.location = checkNotNull(location, "location");
@ -62,10 +88,19 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
Matcher matcher = SECOND_FIELD_DELIMETED_BY_HYPHEN_ENDING_IN_HYPHEN_HEX.matcher(from Matcher matcher = SECOND_FIELD_DELIMETED_BY_HYPHEN_ENDING_IN_HYPHEN_HEX.matcher(from
.getName()); .getName());
final String tag = matcher.find() ? matcher.group(1) : null; final String tag = matcher.find() ? matcher.group(1) : null;
return new NodeMetadataImpl(from.getId() + "", from.getName(), new LocationImpl( Location host = new LocationImpl(LocationScope.HOST, from.getHostId(), from.getHostId(),
LocationScope.HOST, from.getHostId(), from.getHostId(), location), null, from location);
.getMetadata(), tag, images.get(from.getImageId().toString()), serverToNodeState Image image = null;
.get(from.getStatus()), from.getAddresses().getPublicAddresses(), from try {
.getAddresses().getPrivateAddresses(), ImmutableMap.<String, String> of(), null); image = Iterables.find(images, new FindImageForServer(host, from));
} catch (NoSuchElementException e) {
logger
.warn("could not find a matching image for server %s in location %s", from,
location);
}
return new NodeMetadataImpl(from.getId() + "", from.getName(), host, null,
from.getMetadata(), tag, image, serverToNodeState.get(from.getStatus()), from
.getAddresses().getPublicAddresses(), from.getAddresses()
.getPrivateAddresses(), ImmutableMap.<String, String> of(), null);
} }
} }

View File

@ -18,7 +18,7 @@
*/ */
package org.jclouds.rackspace.config; package org.jclouds.rackspace.config;
import java.util.Map; import java.util.Set;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -27,7 +27,7 @@ import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.http.RequiresHttp; import org.jclouds.http.RequiresHttp;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -57,7 +57,7 @@ public class RackspaceLocationsModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
Map<String, ? extends Location> provideLocations(Location location) { Set<? extends Location> provideLocations(Location location) {
return ImmutableMap.of(location.getId(), location); return ImmutableSet.of(location);
} }
} }

View File

@ -34,7 +34,9 @@ public class ServerToNodeMetadataTest {
@Test @Test
public void testApplySetsTagFromNameAndSetsMetadata() throws UnknownHostException { public void testApplySetsTagFromNameAndSetsMetadata() throws UnknownHostException {
Map<ServerStatus, NodeState> serverStateToNodeState = createMock(Map.class); Map<ServerStatus, NodeState> serverStateToNodeState = createMock(Map.class);
Map<String, org.jclouds.compute.domain.Image> images = createMock(Map.class); org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
Set<org.jclouds.compute.domain.Image> images = ImmutableSet.of(jcImage);
Server server = createMock(Server.class); Server server = createMock(Server.class);
expect(server.getId()).andReturn(10000).atLeastOnce(); expect(server.getId()).andReturn(10000).atLeastOnce();
@ -60,14 +62,13 @@ public class ServerToNodeMetadataTest {
expect(addresses.getPrivateAddresses()).andReturn(privateAddresses); expect(addresses.getPrivateAddresses()).andReturn(privateAddresses);
expect(server.getImageId()).andReturn(2000).atLeastOnce(); expect(server.getImageId()).andReturn(2000).atLeastOnce();
expect(jcImage.getId()).andReturn("2000").atLeastOnce();
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class); expect(jcImage.getLocation()).andReturn(provider).atLeastOnce();
expect(images.get("2000")).andReturn(jcImage);
replay(addresses); replay(addresses);
replay(jcImage);
replay(serverStateToNodeState); replay(serverStateToNodeState);
replay(server); replay(server);
replay(images);
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, images, ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, images,
provider); provider);
@ -85,7 +86,7 @@ public class ServerToNodeMetadataTest {
verify(addresses); verify(addresses);
verify(serverStateToNodeState); verify(serverStateToNodeState);
verify(server); verify(server);
verify(images); verify(jcImage);
} }
} }

View File

@ -20,6 +20,7 @@ package org.jclouds.rimuhosting.miro;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.PROPERTY_RIMUHOSTING_APIKEY; import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.PROPERTY_RIMUHOSTING_APIKEY;
import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.PROPERTY_RIMUHOSTING_DEFAULT_DC;
import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.PROPERTY_RIMUHOSTING_ENDPOINT; import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.PROPERTY_RIMUHOSTING_ENDPOINT;
import java.net.URI; import java.net.URI;
@ -37,6 +38,7 @@ public class RimuHostingPropertiesBuilder extends PropertiesBuilder {
protected Properties defaultProperties() { protected Properties defaultProperties() {
Properties properties = super.defaultProperties(); Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_RIMUHOSTING_ENDPOINT, "https://rimuhosting.com/r"); properties.setProperty(PROPERTY_RIMUHOSTING_ENDPOINT, "https://rimuhosting.com/r");
properties.setProperty(PROPERTY_RIMUHOSTING_DEFAULT_DC, "DCDALLAS");
return properties; return properties;
} }

View File

@ -20,10 +20,12 @@ package org.jclouds.rimuhosting.miro.compute.config;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.domain.OsFamily.UBUNTU; import static org.jclouds.compute.domain.OsFamily.UBUNTU;
import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.PROPERTY_RIMUHOSTING_DEFAULT_DC;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -85,7 +87,6 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -259,17 +260,37 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Singleton @Singleton
private static class ServerToNodeMetadata implements Function<Server, NodeMetadata> { private static class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
@Resource
protected Logger logger = Logger.NULL;
private final Function<Server, Iterable<InetAddress>> getPublicAddresses; private final Function<Server, Iterable<InetAddress>> getPublicAddresses;
private final Map<RunningState, NodeState> runningStateToNodeState; private final Map<RunningState, NodeState> runningStateToNodeState;
private final Map<String, ? extends Image> images; private final Set<? extends Image> images;
@SuppressWarnings("unused") @SuppressWarnings("unused")
private final Map<String, ? extends Location> locations; private final Set<? extends Location> locations;
private static class FindImageForServer implements Predicate<Image> {
private final Location location;
private final Server instance;
private FindImageForServer(Location location, Server instance) {
this.location = location;
this.instance = instance;
}
@Override
public boolean apply(Image input) {
return input.getId().equals(instance.getImageId())
&& (input.getLocation() == null || input.getLocation().equals(location) || input
.getLocation().equals(location.getParent()));
}
}
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Inject @Inject
ServerToNodeMetadata(Function<Server, Iterable<InetAddress>> getPublicAddresses, ServerToNodeMetadata(Function<Server, Iterable<InetAddress>> getPublicAddresses,
Map<RunningState, NodeState> runningStateToNodeState, Map<RunningState, NodeState> runningStateToNodeState, Set<? extends Image> images,
Map<String, ? extends Image> images, Map<String, ? extends Location> locations) { Set<? extends Location> locations) {
this.getPublicAddresses = checkNotNull(getPublicAddresses, "serverStateToNodeState"); this.getPublicAddresses = checkNotNull(getPublicAddresses, "serverStateToNodeState");
this.runningStateToNodeState = checkNotNull(runningStateToNodeState, this.runningStateToNodeState = checkNotNull(runningStateToNodeState,
"serverStateToNodeState"); "serverStateToNodeState");
@ -284,10 +305,18 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
.getLocation().getName(), null); .getLocation().getName(), null);
String tag = from.getName().replaceAll("-[0-9]+", ""); String tag = from.getName().replaceAll("-[0-9]+", "");
Credentials creds = null; Credentials creds = null;
Image image = null;
try {
image = Iterables.find(images, new FindImageForServer(location, from));
} catch (NoSuchElementException e) {
logger.warn("could not find a matching image for server %s in location %s", from,
location);
}
NodeState state = runningStateToNodeState.get(from.getState()); NodeState state = runningStateToNodeState.get(from.getState());
return new NodeMetadataImpl(from.getId() + "", from.getName(), location, null, return new NodeMetadataImpl(from.getId() + "", from.getName(), location, null,
ImmutableMap.<String, String> of(), tag, images.get(from.getImageId()), state, ImmutableMap.<String, String> of(), tag, image, state, getPublicAddresses
getPublicAddresses.apply(from), ImmutableList.<InetAddress> of(), ImmutableMap .apply(from), ImmutableList.<InetAddress> of(), ImmutableMap
.<String, String> of(), creds); .<String, String> of(), creds);
} }
@ -333,13 +362,21 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Provides @Provides
@Singleton @Singleton
Location getDefaultLocation(Map<String, ? extends Location> locations) { Location getDefaultLocation(@Named(PROPERTY_RIMUHOSTING_DEFAULT_DC) final String defaultDC,
return locations.get("DCDALLAS"); Set<? extends Location> locations) {
return Iterables.find(locations, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(defaultDC);
}
});
} }
@Provides @Provides
@Singleton @Singleton
Map<String, ? extends Location> getDefaultLocations(RimuHostingClient sync, LogHolder holder, Set<? extends Location> getDefaultLocations(RimuHostingClient sync, LogHolder holder,
Function<ComputeMetadata, String> indexer) { Function<ComputeMetadata, String> indexer) {
final Set<Location> locations = Sets.newHashSet(); final Set<Location> locations = Sets.newHashSet();
holder.logger.debug(">> providing locations"); holder.logger.debug(">> providing locations");
@ -353,13 +390,7 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
} }
} }
holder.logger.debug("<< locations(%d)", locations.size()); holder.logger.debug("<< locations(%d)", locations.size());
return Maps.uniqueIndex(locations, new Function<Location, String>() { return locations;
@Override
public String apply(Location from) {
return from.getId();
}
});
} }
@Provides @Provides
@ -375,25 +406,33 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Provides @Provides
@Singleton @Singleton
protected Map<String, ? extends Size> provideSizes(RimuHostingClient sync, protected Set<? extends Size> provideSizes(RimuHostingClient sync, Set<? extends Image> images,
Map<String, ? extends Image> images, Map<String, ? extends Location> locations, Set<? extends Location> locations, LogHolder holder,
LogHolder holder, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
Function<ComputeMetadata, String> indexer) throws InterruptedException, Function<ComputeMetadata, String> indexer) throws InterruptedException,
TimeoutException, ExecutionException { TimeoutException, ExecutionException {
final Set<Size> sizes = Sets.newHashSet(); final Set<Size> sizes = Sets.newHashSet();
holder.logger.debug(">> providing sizes"); holder.logger.debug(">> providing sizes");
for (final PricingPlan from : sync.getPricingPlanList()) { for (final PricingPlan from : sync.getPricingPlanList()) {
try { try {
sizes.add(new SizeImpl(from.getId(), from.getId(), locations.get(from.getDataCenter()
.getId()), null, ImmutableMap.<String, String> of(), 1, from.getRam(), from final Location location = Iterables.find(locations, new Predicate<Location>() {
.getDiskSize(), ImmutableSet.<Architecture> of(Architecture.X86_32,
Architecture.X86_64))); @Override
public boolean apply(Location input) {
return input.getId().equals(from.getDataCenter().getId());
}
});
sizes.add(new SizeImpl(from.getId(), from.getId(), location, null, ImmutableMap
.<String, String> of(), 1, from.getRam(), from.getDiskSize(), ImmutableSet
.<Architecture> of(Architecture.X86_32, Architecture.X86_64)));
} catch (NullPointerException e) { } catch (NullPointerException e) {
holder.logger.warn("datacenter not present in " + from.getId()); holder.logger.warn("datacenter not present in " + from.getId());
} }
} }
holder.logger.debug("<< sizes(%d)", sizes.size()); holder.logger.debug("<< sizes(%d)", sizes.size());
return Maps.uniqueIndex(sizes, indexer); return sizes;
} }
private static class LogHolder { private static class LogHolder {
@ -406,9 +445,9 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Provides @Provides
@Singleton @Singleton
protected Map<String, ? extends Image> provideImages(final RimuHostingClient sync, protected Set<? extends Image> provideImages(final RimuHostingClient sync, LogHolder holder,
LogHolder holder, Function<ComputeMetadata, String> indexer) Function<ComputeMetadata, String> indexer) throws InterruptedException,
throws InterruptedException, ExecutionException, TimeoutException { ExecutionException, TimeoutException {
final Set<Image> images = Sets.newHashSet(); final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images"); holder.logger.debug(">> providing images");
for (final org.jclouds.rimuhosting.miro.domain.Image from : sync.getImageList()) { for (final org.jclouds.rimuhosting.miro.domain.Image from : sync.getImageList()) {
@ -434,7 +473,7 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
new Credentials("root", null))); new Credentials("root", null)));
} }
holder.logger.debug("<< images(%d)", images.size()); holder.logger.debug("<< images(%d)", images.size());
return Maps.uniqueIndex(images, indexer); return images;
} }
} }

View File

@ -26,4 +26,6 @@ package org.jclouds.rimuhosting.miro.reference;
public interface RimuHostingConstants { public interface RimuHostingConstants {
public static final String PROPERTY_RIMUHOSTING_ENDPOINT = "jclouds.rimuhosting.endpoint"; public static final String PROPERTY_RIMUHOSTING_ENDPOINT = "jclouds.rimuhosting.endpoint";
public static final String PROPERTY_RIMUHOSTING_APIKEY = "jclouds.rimuhosting.password"; public static final String PROPERTY_RIMUHOSTING_APIKEY = "jclouds.rimuhosting.password";
public static final String PROPERTY_RIMUHOSTING_DEFAULT_DC = "jclouds.rimuhosting.defaultdc";
} }

View File

@ -34,6 +34,7 @@ import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task; import org.apache.tools.ant.Task;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
@ -90,14 +91,19 @@ public class ComputeTask extends Task {
for (String action : Splitter.on(',').split(actions)) { for (String action : Splitter.on(',').split(actions)) {
Action act = Action.valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, Action act = Action.valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE,
action)); action));
invokeActionOnService(act, context.getComputeService()); try {
invokeActionOnService(act, context.getComputeService());
} catch (RunNodesException e) {
throw new BuildException(e);
}
} }
} finally { } finally {
context.close(); context.close();
} }
} }
private void invokeActionOnService(Action action, ComputeService computeService) { private void invokeActionOnService(Action action, ComputeService computeService)
throws RunNodesException {
switch (action) { switch (action) {
case CREATE: case CREATE:
case GET: case GET:
@ -140,7 +146,7 @@ public class ComputeTask extends Task {
private void listDetails(ComputeService computeService) { private void listDetails(ComputeService computeService) {
log("list details"); log("list details");
for (ComputeMetadata node : computeService.getNodes().values()) {// TODO for (ComputeMetadata node : computeService.listNodes()) {// TODO
// parallel // parallel
logDetails(computeService, node); logDetails(computeService, node);
} }
@ -148,7 +154,7 @@ public class ComputeTask extends Task {
private void listImages(ComputeService computeService) { private void listImages(ComputeService computeService) {
log("list images"); log("list images");
for (Image image : computeService.getImages().values()) {// TODO for (Image image : computeService.listImages()) {// TODO
log(String log(String
.format( .format(
" image location=%s, id=%s, name=%s, version=%s, arch=%s, osfam=%s, osdesc=%s, desc=%s", " image location=%s, id=%s, name=%s, version=%s, arch=%s, osfam=%s, osdesc=%s, desc=%s",
@ -160,7 +166,7 @@ public class ComputeTask extends Task {
private void listSizes(ComputeService computeService) { private void listSizes(ComputeService computeService) {
log("list sizes"); log("list sizes");
for (Size size : computeService.getSizes().values()) {// TODO for (Size size : computeService.listSizes()) {// TODO
log(String.format(" size id=%s, cores=%s, ram=%s, disk=%s", size.getId(), size log(String.format(" size id=%s, cores=%s, ram=%s, disk=%s", size.getId(), size
.getCores(), size.getRam(), size.getDisk())); .getCores(), size.getRam(), size.getDisk()));
} }
@ -168,7 +174,7 @@ public class ComputeTask extends Task {
private void listLocations(ComputeService computeService) { private void listLocations(ComputeService computeService) {
log("list locations"); log("list locations");
for (Location location : computeService.getAssignableLocations().values()) {// TODO for (Location location : computeService.listAssignableLocations()) {// TODO
log(String.format(" location id=%s, scope=%s, description=%s, parent=%s", location log(String.format(" location id=%s, scope=%s, description=%s, parent=%s", location
.getId(), location.getScope(), location.getDescription(), location.getParent())); .getId(), location.getScope(), location.getDescription(), location.getParent()));
} }
@ -176,13 +182,13 @@ public class ComputeTask extends Task {
private void list(ComputeService computeService) { private void list(ComputeService computeService) {
log("list"); log("list");
for (ComputeMetadata node : computeService.getNodes().values()) { for (ComputeMetadata node : computeService.listNodes()) {
log(String.format(" location=%s, id=%s, tag=%s", node.getLocation(), node.getId(), node log(String.format(" location=%s, id=%s, tag=%s", node.getLocation(), node.getId(), node
.getName())); .getName()));
} }
} }
private void create(ComputeService computeService) { private void create(ComputeService computeService) throws RunNodesException {
String tag = nodeElement.getTag(); String tag = nodeElement.getTag();
log(String.format("create tag: %s, count: %d, size: %s, os: %s", tag, nodeElement.getCount(), log(String.format("create tag: %s, count: %d, size: %s, os: %s", tag, nodeElement.getCount(),
@ -191,7 +197,7 @@ public class ComputeTask extends Task {
Template template = createTemplateFromElement(nodeElement, computeService); Template template = createTemplateFromElement(nodeElement, computeService);
for (NodeMetadata createdNode : computeService.runNodesWithTag(tag, nodeElement.getCount(), for (NodeMetadata createdNode : computeService.runNodesWithTag(tag, nodeElement.getCount(),
template).values()) { template)) {
logDetails(computeService, createdNode); logDetails(computeService, createdNode);
addNodeDetailsAsProjectProperties(createdNode); addNodeDetailsAsProjectProperties(createdNode);
} }
@ -218,7 +224,7 @@ public class ComputeTask extends Task {
private void get(ComputeService computeService) { private void get(ComputeService computeService) {
log(String.format("get tag: %s", nodeElement.getTag())); log(String.format("get tag: %s", nodeElement.getTag()));
for (ComputeMetadata node : computeService.getNodesWithTag(nodeElement.getTag()).values()) { for (ComputeMetadata node : computeService.listNodesWithTag(nodeElement.getTag())) {
logDetails(computeService, node); logDetails(computeService, node);
} }
} }

View File

@ -22,6 +22,7 @@ package org.jclouds.vcloud.bluelock.compute;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
@ -54,7 +55,7 @@ public class BlueLockVCloudComputeServiceLiveTest extends VCloudComputeServiceLi
@Override @Override
public void testListImages() throws Exception { public void testListImages() throws Exception {
super.testListImages(); super.testListImages();
Map<String, ? extends Image> images = client.getImages(); Set<? extends Image> images = client.listImages();
assertEquals(images.size(), 5); assertEquals(images.size(), 5);
// TODO verify parsing works // TODO verify parsing works
} }

View File

@ -24,6 +24,7 @@ import static org.jclouds.compute.domain.OsFamily.UBUNTU;
import static org.jclouds.vcloud.options.InstantiateVAppTemplateOptions.Builder.processorCount; import static org.jclouds.vcloud.options.InstantiateVAppTemplateOptions.Builder.processorCount;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -97,6 +98,7 @@ import com.google.common.base.Predicates;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -145,7 +147,7 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Provides @Provides
@Named("NAMING_CONVENTION") @Named("NAMING_CONVENTION")
@Singleton @Singleton
String provideNamingConvention() { protected String provideNamingConvention() {
return "%s-%s%s"; return "%s-%s%s";
} }
@ -232,8 +234,10 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Inject @Inject
protected VCloudListNodesStrategy(VCloudClient client, VCloudComputeClient computeClient, protected VCloudListNodesStrategy(VCloudClient client, VCloudComputeClient computeClient,
Map<VAppStatus, NodeState> vAppStatusToNodeState, GetExtra getExtra, Map<VAppStatus, NodeState> vAppStatusToNodeState, GetExtra getExtra,
Map<String, ? extends Location> locations, Map<String, ? extends Image> images) { FindLocationForResourceInVDC findLocationForResourceInVDC,
super(client, computeClient, vAppStatusToNodeState, getExtra, locations, images); Set<? extends Image> images) {
super(client, computeClient, vAppStatusToNodeState, getExtra,
findLocationForResourceInVDC, images);
} }
@Override @Override
@ -273,9 +277,10 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Inject @Inject
protected VCloudGetNodeMetadataStrategy(VCloudClient client, protected VCloudGetNodeMetadataStrategy(VCloudClient client,
VCloudComputeClient computeClient, Map<VAppStatus, NodeState> vAppStatusToNodeState, VCloudComputeClient computeClient, Map<VAppStatus, NodeState> vAppStatusToNodeState,
GetExtra getExtra, Map<String, ? extends Location> locations, GetExtra getExtra, FindLocationForResourceInVDC findLocationForResourceInVDC,
Map<String, ? extends Image> images) { Set<? extends Image> images) {
super(client, computeClient, vAppStatusToNodeState, getExtra, locations, images); super(client, computeClient, vAppStatusToNodeState, getExtra,
findLocationForResourceInVDC, images);
} }
@Override @Override
@ -311,9 +316,9 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Provides @Provides
@Singleton @Singleton
protected Map<String, ? extends Image> provideImages(final VCloudClient client, protected Set<? extends Image> provideImages(final VCloudClient client,
final PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider, final PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider,
final Map<String, ? extends Location> locations, LogHolder holder, LogHolder holder, final FindLocationForResourceInVDC findLocationForResourceInVDC,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
Function<ComputeMetadata, String> indexer) throws InterruptedException, Function<ComputeMetadata, String> indexer) throws InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
@ -339,11 +344,15 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
Architecture arch = resource.getName().indexOf("64") == -1 ? Architecture.X86_32 Architecture arch = resource.getName().indexOf("64") == -1 ? Architecture.X86_32
: Architecture.X86_64; : Architecture.X86_64;
VAppTemplate template = client.getVAppTemplate(resource.getId()); VAppTemplate template = client.getVAppTemplate(resource.getId());
Location location = findLocationForResourceInVDC.apply(resource, vDC
.getId());
images.add(new ImageImpl(resource.getId(), template.getName(), images.add(new ImageImpl(resource.getId(), template.getName(),
locations.get(vDC.getId()), template.getLocation(), location, template.getLocation(), ImmutableMap
ImmutableMap.<String, String> of(), template .<String, String> of(), template.getDescription(),
.getDescription(), "", myOs, template.getName(), "", myOs, template.getName(), arch, new Credentials("root",
arch, new Credentials("root", null))); null)));
return null; return null;
} }
}), executor)); }), executor));
@ -353,7 +362,7 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
ConcurrentUtils.awaitCompletion(responses, executor, null, holder.logger, ConcurrentUtils.awaitCompletion(responses, executor, null, holder.logger,
"vAppTemplates in " + vDC); "vAppTemplates in " + vDC);
} }
return Maps.uniqueIndex(images, indexer); return images;
} }
@Provides @Provides
@ -369,17 +378,15 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Provides @Provides
@Singleton @Singleton
Map<String, ? extends Location> provideLocations(Supplier<VCloudSession> cache, Set<? extends Location> provideLocations(Supplier<VCloudSession> cache, VCloudClient client) {
VCloudClient client) {
Location provider = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null); Location provider = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
Map<String, Location> locations = Maps.newLinkedHashMap(); Set<Location> locations = Sets.newLinkedHashSet();
for (NamedResource org : cache.get().getOrgs().values()) { for (NamedResource org : cache.get().getOrgs().values()) {
Location orgL = new LocationImpl(LocationScope.REGION, org.getId(), org.getName(), Location orgL = new LocationImpl(LocationScope.REGION, org.getId(), org.getName(),
provider); provider);
for (NamedResource vdc : client.getOrganization(org.getId()).getVDCs().values()) { for (NamedResource vdc : client.getOrganization(org.getId()).getVDCs().values()) {
locations.put(vdc.getId(), new LocationImpl(LocationScope.ZONE, vdc.getId(), vdc locations.add(new LocationImpl(LocationScope.ZONE, vdc.getId(), vdc.getName(), orgL));
.getName(), orgL));
} }
} }
return locations; return locations;
@ -387,14 +394,22 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Provides @Provides
@Singleton @Singleton
Location getVDC(VCloudClient client, Map<String, ? extends Location> locations) { Location getVDC(VCloudClient client, Set<? extends Location> locations) {
return locations.get(client.getDefaultVDC().getId()); final String vdc = client.getDefaultVDC().getId();
return Iterables.find(locations, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(vdc);
}
});
} }
@Provides @Provides
@Singleton @Singleton
protected Map<String, ? extends Size> provideSizes(Function<ComputeMetadata, String> indexer, protected Set<? extends Size> provideSizes(Function<ComputeMetadata, String> indexer,
VCloudClient client, Map<String, ? extends Image> images, LogHolder holder, VCloudClient client, Set<? extends Image> images, LogHolder holder,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
throws InterruptedException, TimeoutException, ExecutionException { throws InterruptedException, TimeoutException, ExecutionException {
Set<Size> sizes = Sets.newHashSet(); Set<Size> sizes = Sets.newHashSet();
@ -403,6 +418,42 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
sizes.add(new SizeImpl(String.format("cpu=%d,ram=%s,disk=%d", cpus, ram, 10), null, sizes.add(new SizeImpl(String.format("cpu=%d,ram=%s,disk=%d", cpus, ram, 10), null,
null, null, ImmutableMap.<String, String> of(), cpus, ram, 10, ImmutableSet null, null, ImmutableMap.<String, String> of(), cpus, ram, 10, ImmutableSet
.<Architecture> of(Architecture.X86_32, Architecture.X86_64))); .<Architecture> of(Architecture.X86_32, Architecture.X86_64)));
return Maps.uniqueIndex(sizes, indexer); return sizes;
}
public static class FindLocationForResourceInVDC {
@Resource
protected Logger logger = Logger.NULL;
final Set<? extends Location> locations;
final Location defaultLocation;
@Inject
public FindLocationForResourceInVDC(Set<? extends Location> locations,
Location defaultLocation) {
this.locations = locations;
this.defaultLocation = defaultLocation;
}
public Location apply(final NamedResource resource, final String vdcId) {
Location location = null;
try {
location = Iterables.find(locations, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(vdcId);
}
});
} catch (NoSuchElementException e) {
logger.error("unknown vdc %s for %s %s; not in %s", vdcId, resource.getType(), resource
.getId(), locations);
location = new LocationImpl(LocationScope.ZONE, vdcId, vdcId, defaultLocation
.getParent());
}
return location;
}
} }
} }

View File

@ -21,24 +21,33 @@ package org.jclouds.vcloud.compute.functions;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.internal.NodeMetadataImpl; import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.VCloudClient; import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.compute.BaseVCloudComputeClient; import org.jclouds.vcloud.compute.BaseVCloudComputeClient;
import org.jclouds.vcloud.compute.VCloudComputeClient; import org.jclouds.vcloud.compute.VCloudComputeClient;
import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule.FindLocationForResourceInVDC;
import org.jclouds.vcloud.domain.VApp; import org.jclouds.vcloud.domain.VApp;
import org.jclouds.vcloud.domain.VAppStatus; import org.jclouds.vcloud.domain.VAppStatus;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
/** /**
* Configures the {@link VCloudComputeServiceContext}; requires {@link BaseVCloudComputeClient} * Configures the {@link VCloudComputeServiceContext}; requires {@link BaseVCloudComputeClient}
@ -48,28 +57,31 @@ import com.google.common.collect.ImmutableMap;
*/ */
@Singleton @Singleton
public class VCloudGetNodeMetadata { public class VCloudGetNodeMetadata {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
public Logger logger = Logger.NULL;
protected final VCloudClient client; protected final VCloudClient client;
protected final VCloudComputeClient computeClient; protected final VCloudComputeClient computeClient;
protected final Map<String, ? extends Image> images; protected final Set<? extends Image> images;
protected final Map<String, ? extends Location> locations; protected final FindLocationForResourceInVDC findLocationForResourceInVDC;
protected final GetExtra getExtra; protected final GetExtra getExtra;
protected final Map<VAppStatus, NodeState> vAppStatusToNodeState; protected final Map<VAppStatus, NodeState> vAppStatusToNodeState;
// hex [][][] are templateId, last two are instanceId // hex [][][] are templateId, last two are instanceId
public static final Pattern TAG_PATTERN_WITH_TEMPLATE = Pattern public static final Pattern TAG_PATTERN_WITH_TEMPLATE = Pattern
.compile("([^-]+)-([0-9a-f][0-9a-f][0-9a-f])[0-9a-f]+"); .compile("([^-]+)-?([0-9a-f][0-9a-f][0-9a-f])[0-9a-f]+");
public static final Pattern TAG_PATTERN_WITHOUT_TEMPLATE = Pattern.compile("([^-]+)-[0-9]+"); public static final Pattern TAG_PATTERN_WITHOUT_TEMPLATE = Pattern.compile("([^-]+)-?[0-9]+");
@Inject @Inject
protected VCloudGetNodeMetadata(VCloudClient client, VCloudComputeClient computeClient, protected VCloudGetNodeMetadata(VCloudClient client, VCloudComputeClient computeClient,
Map<VAppStatus, NodeState> vAppStatusToNodeState, GetExtra getExtra, Map<VAppStatus, NodeState> vAppStatusToNodeState, GetExtra getExtra,
Map<String, ? extends Location> locations, Map<String, ? extends Image> images) { FindLocationForResourceInVDC findLocationForResourceInVDC, Set<? extends Image> images) {
this.client = checkNotNull(client, "client"); this.client = checkNotNull(client, "client");
this.images = checkNotNull(images, "images"); this.images = checkNotNull(images, "images");
this.getExtra = checkNotNull(getExtra, "getExtra"); this.getExtra = checkNotNull(getExtra, "getExtra");
this.locations = checkNotNull(locations, "locations"); this.findLocationForResourceInVDC = checkNotNull(findLocationForResourceInVDC,
"findLocationForResourceInVDC");
this.computeClient = checkNotNull(computeClient, "computeClient"); this.computeClient = checkNotNull(computeClient, "computeClient");
this.vAppStatusToNodeState = checkNotNull(vAppStatusToNodeState, "vAppStatusToNodeState"); this.vAppStatusToNodeState = checkNotNull(vAppStatusToNodeState, "vAppStatusToNodeState");
} }
@ -80,11 +92,26 @@ public class VCloudGetNodeMetadata {
String tag = null; String tag = null;
Image image = null; Image image = null;
Matcher matcher = TAG_PATTERN_WITH_TEMPLATE.matcher(vApp.getName()); Matcher matcher = TAG_PATTERN_WITH_TEMPLATE.matcher(vApp.getName());
final Location location = findLocationForResourceInVDC.apply(vApp, vDCId);
if (matcher.find()) { if (matcher.find()) {
tag = matcher.group(1); tag = matcher.group(1);
String templateIdInHexWithoutLeadingZeros = matcher.group(2).replaceAll("^[0]+", ""); String templateIdInHexWithoutLeadingZeros = matcher.group(2).replaceAll("^[0]+", "");
String templateId = Integer.parseInt(templateIdInHexWithoutLeadingZeros, 16) + ""; final String templateId = Integer.parseInt(templateIdInHexWithoutLeadingZeros, 16) + "";
image = images.get(templateId); try {
image = Iterables.find(images, new Predicate<Image>() {
@Override
public boolean apply(Image input) {
return input.getId().equals(templateId) && input.getLocation().equals(location);
}
});
} catch (NoSuchElementException e) {
logger.warn(
"could not find a matching image for vapp %s; vapptemplate %s in location %s",
vApp, templateId, location);
}
} else { } else {
matcher = TAG_PATTERN_WITHOUT_TEMPLATE.matcher(vApp.getName()); matcher = TAG_PATTERN_WITHOUT_TEMPLATE.matcher(vApp.getName());
if (matcher.find()) { if (matcher.find()) {
@ -93,9 +120,9 @@ public class VCloudGetNodeMetadata {
tag = "NOTAG-" + vApp.getName(); tag = "NOTAG-" + vApp.getName();
} }
} }
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), locations.get(vDCId), vApp return new NodeMetadataImpl(vApp.getId(), vApp.getName(), location, vApp.getLocation(),
.getLocation(), ImmutableMap.<String, String> of(), tag, image, ImmutableMap.<String, String> of(), tag, image, vAppStatusToNodeState.get(vApp
vAppStatusToNodeState.get(vApp.getStatus()), computeClient.getPublicAddresses(id), .getStatus()), computeClient.getPublicAddresses(id), computeClient
computeClient.getPrivateAddresses(id), getExtra.apply(vApp), null); .getPrivateAddresses(id), getExtra.apply(vApp), null);
} }
} }

View File

@ -42,12 +42,15 @@ import com.google.common.base.Strings;
public class EncodeTemplateIdIntoNameRunNodesAndAddToSetStrategy extends public class EncodeTemplateIdIntoNameRunNodesAndAddToSetStrategy extends
EncodeTagIntoNameRunNodesAndAddToSetStrategy { EncodeTagIntoNameRunNodesAndAddToSetStrategy {
private final SecureRandom random;
@Inject @Inject
protected EncodeTemplateIdIntoNameRunNodesAndAddToSetStrategy( protected EncodeTemplateIdIntoNameRunNodesAndAddToSetStrategy(
AddNodeWithTagStrategy addNodeWithTagStrategy, ListNodesStrategy listNodesStrategy, AddNodeWithTagStrategy addNodeWithTagStrategy, ListNodesStrategy listNodesStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention, ComputeUtils utils, @Named("NAMING_CONVENTION") String nodeNamingConvention, ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention, utils, executor); super(addNodeWithTagStrategy, listNodesStrategy, nodeNamingConvention, utils, executor);
this.random = new SecureRandom();
} }
/** /**
@ -59,6 +62,6 @@ public class EncodeTemplateIdIntoNameRunNodesAndAddToSetStrategy extends
protected String getNextName(final String tag, final Template template) { protected String getNextName(final String tag, final Template template) {
return String.format(nodeNamingConvention, tag, Strings.padStart(Integer.toHexString(Integer return String.format(nodeNamingConvention, tag, Strings.padStart(Integer.toHexString(Integer
.parseInt(template.getImage().getId())), 3, '0'), Strings.padStart(Integer .parseInt(template.getImage().getId())), 3, '0'), Strings.padStart(Integer
.toHexString(new SecureRandom().nextInt(255)), 2, '0')); .toHexString(random.nextInt(255)), 2, '0'));
} }
} }

View File

@ -3,8 +3,6 @@ package org.jclouds.vcloud.compute;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.util.Map.Entry;
import org.jclouds.compute.BaseComputeServiceLiveTest; import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.ComputeServiceContextFactory; import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.ComputeMetadata;
@ -46,12 +44,11 @@ public class VCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Override @Override
public void testListNodes() throws Exception { public void testListNodes() throws Exception {
for (Entry<String, ? extends ComputeMetadata> node : client.getNodes().entrySet()) { for (ComputeMetadata node : client.listNodes()) {
assertEquals(node.getKey(), node.getValue().getId()); assert node.getId() != null;
assert node.getValue().getId() != null; assert node.getLocation() != null;
assert node.getValue().getLocation() != null; assertEquals(node.getType(), ComputeType.NODE);
assertEquals(node.getValue().getType(), ComputeType.NODE); NodeMetadata allData = client.getNodeMetadata(node);
NodeMetadata allData = client.getNodeMetadata(node.getValue());
assert allData.getExtra().get("processor/count") != null; assert allData.getExtra().get("processor/count") != null;
assert allData.getExtra().get("disk_drive/1/kb") != null; assert allData.getExtra().get("disk_drive/1/kb") != null;
assert allData.getExtra().get("memory/mb") != null; assert allData.getExtra().get("memory/mb") != null;

View File

@ -37,8 +37,11 @@ import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.NodeState;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.vcloud.VCloudClient; import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.compute.VCloudComputeClient; import org.jclouds.vcloud.compute.VCloudComputeClient;
import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule.FindLocationForResourceInVDC;
import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule.VCloudListNodesStrategy; import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule.VCloudListNodesStrategy;
import org.jclouds.vcloud.compute.functions.GetExtra; import org.jclouds.vcloud.compute.functions.GetExtra;
import org.jclouds.vcloud.domain.NamedResource; import org.jclouds.vcloud.domain.NamedResource;
@ -52,7 +55,7 @@ import org.jclouds.vcloud.domain.internal.VAppImpl;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.ListMultimap; import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -112,10 +115,14 @@ public class VCloudComputeServiceContextModuleTest {
replay(client); replay(client);
replay(computeClient); replay(computeClient);
Map<String, ? extends Location> locations = ImmutableMap.of(); Location vdcL = new LocationImpl(LocationScope.ZONE, "1", "1", null);
Map<String, ? extends Image> images= ImmutableMap.of(); Set<? extends Location> locations = ImmutableSet.of(vdcL);
Set<? extends Image> images = ImmutableSet.of();
FindLocationForResourceInVDC findLocationForResourceInVDC = new FindLocationForResourceInVDC(
locations, null);
VCloudListNodesStrategy strategy = new VCloudListNodesStrategy(client, computeClient, VCloudListNodesStrategy strategy = new VCloudListNodesStrategy(client, computeClient,
vAppStatusToNodeState, getExtra, locations, images); vAppStatusToNodeState, getExtra, findLocationForResourceInVDC, images);
Set<ComputeMetadata> nodes = Sets.newHashSet(); Set<ComputeMetadata> nodes = Sets.newHashSet();
NamedResource vdc = new NamedResourceImpl("1", null, null, null); NamedResource vdc = new NamedResourceImpl("1", null, null, null);

View File

@ -113,9 +113,9 @@ public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeSer
* query the catalog. * query the catalog.
*/ */
@Override @Override
protected Map<String, ? extends Image> provideImages(final VCloudClient client, protected Set<? extends Image> provideImages(final VCloudClient client,
final PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider, final PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider,
final Map<String, ? extends Location> locations, LogHolder holder, LogHolder holder, final FindLocationForResourceInVDC findLocationForResourceInVDC,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
Function<ComputeMetadata, String> indexer) throws InterruptedException, Function<ComputeMetadata, String> indexer) throws InterruptedException,
ExecutionException, TimeoutException { ExecutionException, TimeoutException {
@ -145,11 +145,15 @@ public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeSer
: Architecture.X86_64; : Architecture.X86_64;
VAppTemplate template = client.getVAppTemplate(item.getEntity() VAppTemplate template = client.getVAppTemplate(item.getEntity()
.getId()); .getId());
Location location = findLocationForResourceInVDC.apply(resource, vDC
.getId());
images.add(new ImageImpl(resource.getId(), template.getName(), images.add(new ImageImpl(resource.getId(), template.getName(),
locations.get(vDC.getId()), template.getLocation(), location, template.getLocation(), ImmutableMap
ImmutableMap.<String, String> of(), template .<String, String> of(), template.getDescription(),
.getDescription(), "", myOs, template.getName(), "", myOs, template.getName(), arch, credentialsProvider
arch, credentialsProvider.execute(template))); .execute(template)));
return null; return null;
} }
}), executor)); }), executor));
@ -158,20 +162,19 @@ public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeSer
} }
ConcurrentUtils.awaitCompletion(responses, executor, null, holder.logger, "vAppTemplates in " ConcurrentUtils.awaitCompletion(responses, executor, null, holder.logger, "vAppTemplates in "
+ vDC); + vDC);
return Maps.uniqueIndex(images, indexer); return images;
} }
@Override @Override
protected Map<String, ? extends Size> provideSizes(Function<ComputeMetadata, String> indexer, protected Set<? extends Size> provideSizes(Function<ComputeMetadata, String> indexer,
VCloudClient client, Map<String, ? extends Image> images, LogHolder holder, VCloudClient client, Set<? extends Image> images, LogHolder holder,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
throws InterruptedException, TimeoutException, ExecutionException { throws InterruptedException, TimeoutException, ExecutionException {
Image anyImage = Iterables.get(images.values(), 0); Image anyImage = Iterables.get(images, 0);
holder.logger.debug(">> providing sizes"); holder.logger.debug(">> providing sizes");
SortedSet<Size> sizes = Sets.newTreeSet(Iterables.transform(TerremarkVCloudClient.class.cast( SortedSet<Size> sizes = Sets.newTreeSet(Iterables.transform(TerremarkVCloudClient.class.cast(
client).getComputeOptionsOfCatalogItem(anyImage.getId()), sizeConverter)); client).getComputeOptionsOfCatalogItem(anyImage.getId()), sizeConverter));
holder.logger.debug("<< sizes(%d)", sizes.size()); holder.logger.debug("<< sizes(%d)", sizes.size());
return Maps.uniqueIndex(sizes, indexer); return sizes;
} }
} }

View File

@ -21,8 +21,6 @@ package org.jclouds.vcloud.terremark.compute;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.util.Map.Entry;
import org.jclouds.compute.ComputeServiceContextFactory; import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeType; import org.jclouds.compute.domain.ComputeType;
@ -78,14 +76,13 @@ public class TerremarkVCloudComputeServiceLiveTest extends VCloudComputeServiceL
@Override @Override
public void testListImages() throws Exception { public void testListImages() throws Exception {
for (Entry<String, ? extends Image> image : client.getImages().entrySet()) { for (Image image : client.listImages()) {
assertEquals(image.getKey(), image.getValue().getId()); assert image.getId() != null : image;
assert image.getValue().getId() != null : image; // image.getLocationId() can be null, if it is a location-free image
// image.getValue().getLocationId() can be null, if it is a location-free image assertEquals(image.getType(), ComputeType.IMAGE);
assertEquals(image.getValue().getType(), ComputeType.IMAGE); assert image.getDefaultCredentials().account != null : image;
assert image.getValue().getDefaultCredentials().account != null : image; if (image.getOsFamily() != OsFamily.WINDOWS)
if (image.getValue().getOsFamily() != OsFamily.WINDOWS) assert image.getDefaultCredentials().key != null : image;
assert image.getValue().getDefaultCredentials().key != null : image;
} }
} }