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 java.net.URI;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@ -80,7 +80,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
@Inject
AtmosAsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
@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,
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 java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Provider;
@ -65,8 +65,8 @@ public class AtmosBlobStore extends BaseBlobStore {
@Inject
AtmosBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, Location defaultLocation,
Map<String, ? extends Location> locations, AtmosStorageClient sync,
ObjectToBlob object2Blob, ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
Set<? extends Location> locations, AtmosStorageClient sync, ObjectToBlob object2Blob,
ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
BlobStoreListOptionsToListOptions container2ContainerListOptions,
DirectoryEntryListToResourceMetadataList container2ResourceList,
EncryptionService encryptionService, BlobToHttpGetOptions blob2ObjectGetOptions,

View File

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

View File

@ -19,6 +19,7 @@
package org.jclouds.aws.ec2.compute;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
@ -64,10 +65,9 @@ public class EC2ComputeService extends BaseComputeService {
@Inject
protected EC2ComputeService(ComputeServiceContext context,
Provider<Map<String, ? extends Image>> images,
Provider<Map<String, ? extends Size>> sizes,
Provider<Map<String, ? extends Location>> locations,
ListNodesStrategy listNodesStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
Provider<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy,
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, ComputeUtils utils,
@ -110,7 +110,7 @@ public class EC2ComputeService extends BaseComputeService {
@Override
public void destroyNodesWithTag(String tag) {
super.destroyNodesWithTag(tag);
Iterable<? extends NodeMetadata> nodes = Iterables.filter(getNodesWithTag(tag).values(),
Iterable<? extends NodeMetadata> nodes = Iterables.filter(listNodesWithTag(tag),
new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata input) {

View File

@ -254,32 +254,37 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides
@Singleton
Map<String, ? extends Size> provideSizes(Function<ComputeMetadata, String> indexer) {
return Maps.uniqueIndex(ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE,
EC2Size.M1_LARGE, EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_XLARGE,
EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE), indexer);
Set<? extends Size> provideSizes() {
return ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE,
EC2Size.M2_4XLARGE);
}
@Provides
@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);
Map<String, Location> locations = Maps.newLinkedHashMap();
for (String region : availabilityZoneToRegionMap.values()) {
locations.put(region, new LocationImpl(LocationScope.REGION, region, region, ec2));
}
Set<Location> locations = Sets.newLinkedHashSet();
for (String zone : availabilityZoneToRegionMap.keySet()) {
locations.put(zone, new LocationImpl(LocationScope.ZONE, zone, zone, locations
.get(availabilityZoneToRegionMap.get(zone))));
Location region = new LocationImpl(LocationScope.REGION, availabilityZoneToRegionMap
.get(zone), availabilityZoneToRegionMap.get(zone), ec2);
locations.add(region);
locations.add(new LocationImpl(LocationScope.ZONE, zone, zone, region));
}
return locations;
}
@Provides
@Singleton
Location getDefaultLocation(@EC2 String region, Map<String, ? extends Location> map) {
return map.get(region);
Location getDefaultLocation(@EC2 final String region, Set<? extends Location> set) {
return Iterables.find(set, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(region);
}
});
}
private static class LogHolder {
@ -297,7 +302,7 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
@Provides
@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,
Function<ComputeMetadata, String> indexer,
@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());
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 java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -38,10 +40,14 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
@ -61,18 +67,21 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
.build();
private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider;
private final Map<String, ? extends Location> locations;
private final Set<? extends Location> locations;
private final Location defaultLocation;
@Inject
ImageParser(PopulateDefaultLoginCredentialsForImageStrategy credentialProvider,
Map<String, ? extends Location> locations) {
Set<? extends Location> locations, Location defaultLocation) {
this.credentialProvider = checkNotNull(credentialProvider, "credentialProvider");
this.locations = checkNotNull(locations, "locations");
this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation");
}
@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) {
logger.trace("skipping test image(%s)", from.getId());
return null;
@ -102,10 +111,26 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
}
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(
from.getId(),
name,
locations.get(from.getRegion()),
location,
null,
ImmutableMap.<String, String> of("owner", from.getImageOwnerId()),
description,
@ -114,5 +139,6 @@ public class ImageParser implements Function<org.jclouds.aws.ec2.domain.Image, I
osDescription,
from.getArchitecture() == org.jclouds.aws.ec2.domain.Image.Architecture.I386 ? Architecture.X86_32
: Architecture.X86_64, defaultCredentials);
}
}

View File

@ -24,8 +24,10 @@ import static org.jclouds.util.Utils.nullSafeSet;
import java.net.InetAddress;
import java.net.URI;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
@ -43,9 +45,11 @@ import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
@ -55,6 +59,27 @@ import com.google.common.collect.Maps;
*/
@Singleton
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
.<InstanceState, NodeState> builder().put(InstanceState.PENDING, NodeState.PENDING)
.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 Map<RegionTag, KeyPair> credentialsMap;
private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider;
private final Map<String, ? extends Image> images;
private final Map<String, ? extends Location> locations;
private final Set<? extends Image> images;
private final Set<? extends Location> locations;
private final Function<RunningInstance, Map<String, String>> instanceToStorageMapping;
@Inject
RunningInstanceToNodeMetadata(AMIClient amiClient, Map<RegionTag, KeyPair> credentialsMap,
RunningInstanceToNodeMetadata(
AMIClient amiClient,
Map<RegionTag, KeyPair> credentialsMap,
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) {
this.amiClient = checkNotNull(amiClient, "amiClient");
this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap");
@ -81,7 +109,7 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
}
@Override
public NodeMetadata apply(RunningInstance instance) {
public NodeMetadata apply(final RunningInstance instance) {
String id = checkNotNull(instance, "instance").getId();
String name = null; // user doesn't determine a node name;
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> privateAddresses = nullSafeSet(instance.getPrivateIpAddress());
String locationId = instance.getAvailabilityZone();
final String locationId = instance.getAvailabilityZone();
Map<String, String> extra = getExtra(instance);
return new NodeMetadataImpl(id, name, locations.get(locationId), uri, userMetadata, tag,
images.get(instance.getImageId()), state, publicAddresses, privateAddresses, extra,
credentials);
final Location location = Iterables.find(locations, new Predicate<Location>() {
@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
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,
"unexpected image type. should be EC2Size, was: " + template.getSize().getClass());
EC2Size ec2Size = EC2Size.class.cast(template.getSize());
// parse the availability zone of the request
String zone = template.getLocation().getScope() == LocationScope.ZONE ? template.getLocation().getId()
: null;
String zone = template.getLocation().getScope() == LocationScope.ZONE ? template
.getLocation().getId() : null;
// if the location has a parent, it must be an availability zone.
String region = zone == null ? template.getLocation().getId() :
template.getLocation().getParent().getId();
String region = zone == null ? template.getLocation().getId() : template.getLocation()
.getParent().getId();
// get or create incidental resources
// 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) {
logger.error(e, "<< problem applying options to node(%s): ", node.getId(),
Throwables.getRootCause(e).getMessage());
if (!template.getOptions().shouldDestroyOnError())
nodes.add(computeService.getNodeMetadata(node));
badNodes.put(computeService.getNodeMetadata(node), e);
}
return null;
}

View File

@ -49,13 +49,18 @@ import com.google.common.collect.Sets;
* />
*/
public class DescribeImagesResponseHandler extends ParseSax.HandlerWithResult<Set<Image>> {
@Inject
public DescribeImagesResponseHandler(@EC2 String defaultRegion) {
this.defaultRegion = defaultRegion;
}
@Resource
protected Logger logger = Logger.NULL;
@Inject
@EC2
String defaultRegion;
private Set<Image> contents = Sets.newLinkedHashSet();
private StringBuilder currentText = new StringBuilder();
private final String defaultRegion;
private Architecture architecture;
private String name;
@ -149,10 +154,10 @@ public class DescribeImagesResponseHandler extends ParseSax.HandlerWithResult<Se
String region = EC2Utils.findRegionInArgsOrNull(request);
if (region == null)
region = defaultRegion;
contents.add(new Image(region, architecture,
this.name, description, imageId, imageLocation, imageOwnerId, imageState,
imageType, isPublic, productCodes, kernelId, platform, ramdiskId,
rootDeviceType, rootDeviceName, ebsBlockDevices));
contents.add(new Image(region, architecture, this.name, description, imageId,
imageLocation, imageOwnerId, imageState, imageType, isPublic, productCodes,
kernelId, platform, ramdiskId, rootDeviceType, rootDeviceName,
ebsBlockDevices));
} catch (NullPointerException e) {
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.util.concurrent.Futures.compose;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.ExecutorService;
@ -84,8 +84,8 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
@Inject
S3AsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Map<String, ? extends Location> locations,
S3AsyncClient async, S3Client sync, BucketToResourceMetadata bucket2ResourceMd,
Location defaultLocation, Set<? extends Location> locations, S3AsyncClient async,
S3Client sync, BucketToResourceMetadata bucket2ResourceMd,
ContainerToBucketListOptions container2BucketListOptions,
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
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 java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import javax.inject.Inject;
@ -75,7 +75,7 @@ public class S3BlobStore extends BaseBlobStore {
@Inject
S3BlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, Location defaultLocation,
Map<String, ? extends Location> locations, S3Client sync,
Set<? extends Location> locations, S3Client sync,
BucketToResourceMetadata bucket2ResourceMd,
ContainerToBucketListOptions container2BucketListOptions,
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,

View File

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

View File

@ -18,7 +18,8 @@
*/
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.inject.Inject;
@ -35,6 +36,8 @@ import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
@ -42,13 +45,13 @@ import com.google.common.base.Function;
@Singleton
public class BucketToResourceMetadata implements Function<BucketMetadata, StorageMetadata> {
private final S3Client client;
private final Map<String, ? extends Location> locations;
private final Set<? extends Location> locations;
@Resource
protected Logger logger = Logger.NULL;
@Inject
BucketToResourceMetadata(S3Client client, Map<String, ? extends Location> locations) {
BucketToResourceMetadata(S3Client client, Set<? extends Location> locations) {
this.client = client;
this.locations = locations;
}
@ -58,12 +61,20 @@ public class BucketToResourceMetadata implements Function<BucketMetadata, Storag
to.setName(from.getName());
to.setType(StorageType.CONTAINER);
try {
String region = client.getBucketLocation(from.getName());
final String region = client.getBucketLocation(from.getName());
if (region != null) {
Location location = locations.get(region.toString());
if (location == null)
try {
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);
to.setLocation(location);
}
} else {
logger.error("could not get region for %s", from.getName());
}

View File

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

View File

@ -41,7 +41,6 @@ import org.jclouds.domain.internal.LocationImpl;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
@ -116,10 +115,10 @@ public class EC2ComputeServiceTest {
.<String, String> newHashMap(), "description", "1.0", null, "ubuntu",
Architecture.X86_64, new Credentials("root", null));
return new TemplateBuilderImpl(ImmutableMap.of("us-east-1", location), ImmutableMap.of(
"ami-image", image), Maps.uniqueIndex(ImmutableSet.of(EC2Size.C1_MEDIUM,
EC2Size.C1_XLARGE, EC2Size.M1_LARGE, EC2Size.M1_SMALL, EC2Size.M1_XLARGE,
EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE), indexer()), location) {
return new TemplateBuilderImpl(ImmutableSet.of(location), ImmutableSet.of(image),
ImmutableSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_XLARGE, EC2Size.M2_2XLARGE,
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.compute.domain.OsFamily;
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.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
@ -52,15 +55,15 @@ public class ImageParserTest extends BaseEC2HandlerTest {
assertEquals(result.size(), 6);
ImageParser parser = new ImageParser(
new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableMap
.<String, Location> of());
new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableSet
.<Location> of(defaultLocation), defaultLocation);
org.jclouds.compute.domain.Image ubuntuHardy = parser.apply(Iterables.get(result, 0));
assertEquals(ubuntuHardy.getArchitecture(), org.jclouds.compute.domain.Architecture.X86_32);
assertEquals(ubuntuHardy.getDescription(),
"ubuntu-images-us/ubuntu-hardy-8.04-i386-server-20091130.manifest.xml");
assertEquals(ubuntuHardy.getId(), "ami-7e28ca17");
assertEquals(ubuntuHardy.getLocation(), null);
assertEquals(ubuntuHardy.getLocation(), defaultLocation);
assertEquals(ubuntuHardy.getName(), "8.04");
assertEquals(ubuntuHardy.getOsDescription(),
"ubuntu-images-us/ubuntu-hardy-8.04-i386-server-20091130.manifest.xml");
@ -75,7 +78,7 @@ public class ImageParserTest extends BaseEC2HandlerTest {
assertEquals(alesticKarmic.getDescription(),
"alestic/ubuntu-9.10-karmic-base-20090623.manifest.xml");
assertEquals(alesticKarmic.getId(), "ami-19a34270");
assertEquals(alesticKarmic.getLocation(), null);
assertEquals(alesticKarmic.getLocation(), defaultLocation);
assertEquals(alesticKarmic.getName(), "9.10");
assertEquals(alesticKarmic.getOsDescription(),
"alestic/ubuntu-9.10-karmic-base-20090623.manifest.xml");
@ -90,7 +93,7 @@ public class ImageParserTest extends BaseEC2HandlerTest {
assertEquals(ubuntuKarmic.getDescription(),
"ubuntu-images-us/ubuntu-karmic-9.10-i386-server-20100121.manifest.xml");
assertEquals(ubuntuKarmic.getId(), "ami-bb709dd2");
assertEquals(ubuntuKarmic.getLocation(), null);
assertEquals(ubuntuKarmic.getLocation(), defaultLocation);
assertEquals(ubuntuKarmic.getName(), "9.10");
assertEquals(ubuntuKarmic.getOsDescription(),
"ubuntu-images-us/ubuntu-karmic-9.10-i386-server-20100121.manifest.xml");
@ -108,7 +111,7 @@ public class ImageParserTest extends BaseEC2HandlerTest {
assertEquals(alesticHardy.getDescription(),
"alestic/ubuntu-8.04-hardy-base-20080905.manifest.xml");
assertEquals(alesticHardy.getId(), "ami-c0fa1ea9");
assertEquals(alesticHardy.getLocation(), null);
assertEquals(alesticHardy.getLocation(), defaultLocation);
assertEquals(alesticHardy.getName(), "8.04");
assertEquals(alesticHardy.getOsDescription(),
"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;
}
private Location defaultLocation = new LocationImpl(LocationScope.REGION, "us-east-1",
"us-east-1", null);
public void testParseVostokImage() {
InputStream is = getClass().getResourceAsStream("/ec2/vostok.xml");
Set<Image> result = parseImages(is);
ImageParser parser = new ImageParser(
new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableMap
.<String, Location> of());
new EC2PopulateDefaultLoginCredentialsForImageStrategy(), ImmutableSet
.<Location> of(defaultLocation), defaultLocation);
org.jclouds.compute.domain.Image image = parser.apply(Iterables.get(result, 0));
@ -136,7 +142,7 @@ public class ImageParserTest extends BaseEC2HandlerTest {
assertEquals(image.getDescription(),
"vostok-builds/vostok-0.95-5622/vostok-0.95-5622.manifest.xml");
assertEquals(image.getId(), "ami-870de2ee");
assertEquals(image.getLocation(), null);
assertEquals(image.getLocation(), defaultLocation);
assertEquals(image.getName(), "");
assertEquals(image.getOsDescription(),
"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.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
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.UnknownHostException;
import java.util.Map;
import java.util.Set;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.compute.domain.RegionTag;
@ -62,19 +62,19 @@ public class RunningInstanceToNodeMetadataTest {
throws UnknownHostException {
AMIClient amiClient = createMock(AMIClient.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);
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.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);
RunningInstance instance = createMock(RunningInstance.class);
expect(instance.getId()).andReturn("id").atLeastOnce();
expect(instance.getKeyName()).andReturn(null).atLeastOnce();
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(
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.getImageId()).andReturn("imageId").atLeastOnce();
expect(jcImage.getId()).andReturn("imageId").atLeastOnce();
expect(jcImage.getLocation()).andReturn(location).atLeastOnce();
expect(instance.getInstanceType()).andReturn(InstanceType.C1_XLARGE).atLeastOnce();
replay(jcImage);
replay(amiClient);
replay(credentialsMap);
replay(credentialProvider);
replay(instance);
replay(images);
replay(locations);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(amiClient,
credentialsMap, credentialProvider, images, locations,
new RunningInstanceToStorageMappingUnix());
NodeMetadata metadata = parser.apply(instance);
assertEquals(metadata.getLocation(), location);
assertEquals(metadata.getLocation(), locations.iterator().next());
assertEquals(metadata.getImage(), jcImage);
assertEquals(metadata.getTag(), "NOTAG-id");
assertEquals(metadata.getCredentials(), null);
verify(jcImage);
verify(amiClient);
verify(credentialsMap);
verify(credentialProvider);
verify(instance);
verify(images);
verify(locations);
}
@SuppressWarnings("unchecked")
@ -118,8 +118,6 @@ public class RunningInstanceToNodeMetadataTest {
throws UnknownHostException {
AMIClient amiClient = createMock(AMIClient.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);
RunningInstance instance = createMock(RunningInstance.class);
@ -130,10 +128,10 @@ public class RunningInstanceToNodeMetadataTest {
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);
Set<Location> locations = ImmutableSet.<Location> of(location);
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
Set<org.jclouds.compute.domain.Image> images = ImmutableSet
.<org.jclouds.compute.domain.Image> of(jcImage);
expect(instance.getIpAddress()).andReturn(
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.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(
ImmutableSet.<Image> of(image));
@ -160,8 +160,7 @@ public class RunningInstanceToNodeMetadataTest {
replay(credentialsMap);
replay(credentialProvider);
replay(instance);
replay(images);
replay(locations);
replay(jcImage);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(amiClient,
credentialsMap, credentialProvider, images, locations,
@ -175,12 +174,12 @@ public class RunningInstanceToNodeMetadataTest {
assertEquals(metadata.getCredentials(), new Credentials("user", "pass"));
verify(jcImage);
verify(amiClient);
verify(credentialsMap);
verify(credentialProvider);
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.TimeoutException;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client;
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 org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
@ -77,7 +77,7 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
@Inject
AzureAsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Map<String, ? extends Location> locations,
Location defaultLocation, Set<? extends Location> locations,
AzureBlobAsyncClient async, ContainerToResourceMetadata container2ResourceMd,
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 org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -68,7 +68,7 @@ public class AzureBlobStore extends BaseBlobStore {
@Inject
AzureBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils, Location defaultLocation,
Map<String, ? extends Location> locations, AzureBlobClient sync,
Set<? extends Location> locations, AzureBlobClient sync,
ContainerToResourceMetadata container2ResourceMd,
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
ListBlobsResponseToResourceList azure2BlobStoreResourceList,

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.azure.storage.blob.blobstore.config;
import java.util.Map;
import java.util.Set;
import javax.inject.Singleton;
@ -39,7 +39,7 @@ import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
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.Scopes;
import com.google.inject.TypeLiteral;
@ -72,7 +72,7 @@ public class AzureBlobStoreContextModule extends AzureBlobContextModule {
@Provides
@Singleton
Map<String, ? extends Location> provideLocations(Location location) {
return ImmutableMap.of(location.getId(), location);
Set<? extends Location> provideLocations(Location 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."
([] (locations *blobstore*))
([#^BlobStore blobstore]
(seq-from-immutable-set (.getAssignableLocations blobstore))))
(seq (.listAssignableLocations blobstore))))
(defn create-container
"Create a container."

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.blobstore;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
@ -49,9 +49,9 @@ public interface AsyncBlobStore {
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

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.blobstore;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
@ -50,12 +50,12 @@ public interface BlobStore {
Blob newBlob(String name);
/**
* The get locations command returns all the valid locations for containers. A location has a scope,
* 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.
* For example a location can be a rack, whose parent is likely to be a zone.
* The get locations command returns all the valid locations for containers. A location has a
* scope, 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. 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.

View File

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

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.blobstore.config;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@ -30,7 +30,7 @@ import org.jclouds.blobstore.domain.Blob;
import org.jclouds.domain.Location;
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.Provides;
import com.google.inject.Scopes;
@ -55,7 +55,7 @@ public class TransientBlobStoreModule extends AbstractModule {
@Provides
@Singleton
Map<String, Location> provideLocations(Location defaultLocation) {
return ImmutableMap.<String, Location> of(defaultLocation.getId(), defaultLocation);
Set<Location> provideLocations(Location 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.concurrent.ConcurrentUtils.makeListenable;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@ -58,12 +58,12 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
protected final BlobStoreUtils blobUtils;
protected final ExecutorService service;
protected final Location defaultLocation;
protected final Map<String, ? extends Location> locations;
protected final Set<? extends Location> locations;
@Inject
protected BaseAsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
@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.blobUtils = checkNotNull(blobUtils, "blobUtils");
this.service = checkNotNull(service, "service");
@ -271,7 +271,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
}
@Override
public ListenableFuture<? extends Map<String, ? extends Location>> getAssignableLocations() {
public ListenableFuture<? extends Set<? extends Location>> listAssignableLocations() {
return immediateFuture(locations);
}

View File

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

View File

@ -21,7 +21,6 @@ package org.jclouds.blobstore.integration.internal;
import static org.testng.Assert.assertEquals;
import java.util.Set;
import java.util.Map.Entry;
import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata;
@ -47,7 +46,7 @@ public class BaseServiceIntegrationTest extends BaseBlobStoreIntegrationTest {
@Test(groups = { "integration", "live" })
public void testAllLocations() throws InterruptedException {
for (final Location location : context.getBlobStore().getAssignableLocations().values()) {
for (final Location location : context.getBlobStore().listAssignableLocations()) {
final String containerName = getScratchContainerName();
try {
System.err.printf(" >> creating container in location %s%n", location);
@ -77,32 +76,31 @@ public class BaseServiceIntegrationTest extends BaseBlobStoreIntegrationTest {
@Test(groups = { "integration", "live" })
public void testGetAssignableLocations() throws Exception {
for (Entry<String, ? extends Location> location : context.getBlobStore()
.getAssignableLocations().entrySet()) {
System.err.printf("location %s%n", location.getValue());
assertEquals(location.getKey(), location.getValue().getId());
assert location.getValue().getId() != null : location;
assert location.getValue() != location.getValue().getParent() : location;
assert location.getValue().getScope() != null : location;
switch (location.getValue().getScope()) {
for (Location location : context.getBlobStore()
.listAssignableLocations()) {
System.err.printf("location %s%n", location);
assert location.getId() != null : location;
assert location != location.getParent() : location;
assert location.getScope() != null : location;
switch (location.getScope()) {
case PROVIDER:
assertProvider(location.getValue());
assertProvider(location);
break;
case REGION:
assertProvider(location.getValue().getParent());
assertProvider(location.getParent());
break;
case ZONE:
Location provider = location.getValue().getParent().getParent();
Location provider = location.getParent().getParent();
// zone can be a direct descendant of provider
if (provider == null)
provider = location.getValue().getParent();
provider = location.getParent();
assertProvider(provider);
break;
case HOST:
Location provider2 = location.getValue().getParent().getParent().getParent();
Location provider2 = location.getParent().getParent().getParent();
// zone can be a direct descendant of provider
if (provider2 == null)
provider2 = location.getValue().getParent().getParent();
provider2 = location.getParent().getParent();
assertProvider(provider2);
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."
([] (locations *compute*))
([#^ComputeService compute]
(seq-from-immutable-set (.getAssignableLocations compute))))
(seq (.listAssignableLocations compute))))
(defn nodes-with-tag
[#^String tag #^ComputeService compute]
(seq-from-immutable-set (.getNodesWithTag compute tag)))
(seq (.listNodesWithTag compute tag)))
(def #^{:private true} list-nodes-map
{ :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)
lno)
(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*))))
(defn images
"Retrieve the available images for the compute context."
([] (images *compute*))
([#^ComputeService compute]
(seq-from-immutable-set (.getImages compute))))
(seq (.listImages compute))))
(defn sizes
"Retrieve the available node sizes for the compute context."
([] (sizes *compute*))
([#^ComputeService compute]
(seq-from-immutable-set (.getSizes compute))))
(seq (.listSizes compute))))
(defn default-template
([] (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)
(run-nodes tag count compute-or-template *compute*)))
([tag count template #^ComputeService compute]
(seq-from-immutable-set
(seq
(.runNodesWithTag compute tag count template))))
(defn run-node

View File

@ -19,6 +19,7 @@
package org.jclouds.compute;
import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image;
@ -54,14 +55,14 @@ public interface ComputeService {
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,
* it is a good indicator of relative speed within a cloud. memory is measured in megabytes and
* disks in gigabytes.
*
* @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
@ -70,27 +71,27 @@ public interface ComputeService {
* TemplateBuilder as opposed to choosing an image explicitly. The getImages() command returns a
* 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
* {@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
* {@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
* 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.
*/
Map<String, ? extends Location> getAssignableLocations();
Set<? extends Location> listAssignableLocations();
/**
*
@ -122,8 +123,13 @@ public interface ComputeService {
* @param template
* - how to configure the nodes
* @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
@ -159,27 +165,32 @@ public interface ComputeService {
*
* @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)
* @see #runScriptOnNodesWithTag(String, byte[], org.jclouds.compute.options.RunScriptOptions)
*/
Map<String, ExecResponse> runScriptOnNodesWithTag(String tag,
byte[] runScript);
Map<NodeMetadata, ExecResponse> runScriptOnNodesWithTag(String tag, byte[] runScript)
throws RunScriptOnNodesException;
/**
* Run the script on all nodes with the specific tag.
*
* @param tag tag to look up the nodes
* @param runScript script to run in byte format. If the script is a string, use
* @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
* @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<String, ExecResponse> runScriptOnNodesWithTag(String tag,
byte[] runScript, RunScriptOptions options);
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.Set;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@ -45,6 +44,8 @@ import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.compute.ComputeService;
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.ComputeType;
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.RunNodesAndAddToSetStrategy;
import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.compute.util.ComputeUtils.RunScriptOnNode;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.ssh.ExecResponse;
import org.jclouds.ssh.SshClient;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@ -86,9 +88,9 @@ public class BaseComputeService implements ComputeService {
protected Logger logger = Logger.NULL;
protected final ComputeServiceContext context;
protected final Provider<Map<String, ? extends Image>> images;
protected final Provider<Map<String, ? extends Size>> sizes;
protected final Provider<Map<String, ? extends Location>> locations;
protected final Provider<Set<? extends Image>> images;
protected final Provider<Set<? extends Size>> sizes;
protected final Provider<Set<? extends Location>> locations;
protected final ListNodesStrategy listNodesStrategy;
protected final GetNodeMetadataStrategy getNodeMetadataStrategy;
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
protected BaseComputeService(ComputeServiceContext context,
Provider<Map<String, ? extends Image>> images,
Provider<Map<String, ? extends Size>> sizes,
Provider<Map<String, ? extends Location>> locations,
ListNodesStrategy listNodesStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes,
Provider<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy,
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, ComputeUtils utils,
@ -159,28 +146,23 @@ public class BaseComputeService implements ComputeService {
}
@Override
public Map<String, ? extends NodeMetadata> runNodesWithTag(final String tag, int count,
final Template template) {
public Set<? extends NodeMetadata> runNodesWithTag(final String tag, int count,
final Template template) throws RunNodesException {
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
checkNotNull(template.getLocation(), "location");
logger.debug(">> running %d node%s tag(%s) location(%s) image(%s) size(%s) options(%s)",
count, count > 1 ? "s" : "", tag, template.getLocation().getId(), template
.getImage().getId(), template.getSize().getId(), template.getOptions());
final Set<NodeMetadata> nodes = Sets.newHashSet();
final Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
Map<?, ListenableFuture<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count,
template, nodes);
Map<?, Exception> exceptions = awaitCompletion(responses, executor, null, logger,
template, nodes, badNodes);
Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger,
"starting nodes");
if (exceptions.size() > 0 && template.getOptions().shouldDestroyOnError()) {
ImmutableMap<?, ? extends ComputeMetadata> currentNodes = Maps.uniqueIndex(
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()));
if (executionExceptions.size() > 0 || badNodes.size() > 0) {
throw new RunNodesException(tag, count, template, nodes, executionExceptions, badNodes);
}
}
return Maps.uniqueIndex(nodes, METADATA_TO_ID);
return nodes;
}
@Override
@ -196,8 +178,8 @@ public class BaseComputeService implements ComputeService {
@Override
public void destroyNodesWithTag(String tag) { // TODO parallel
logger.debug(">> destroying nodes by tag(%s)", tag);
Iterable<? extends NodeMetadata> nodesToDestroy = Iterables.filter(doGetNodesWithTag(tag)
.values(), new Predicate<NodeMetadata>() {
Iterable<? extends NodeMetadata> nodesToDestroy = Iterables.filter(doListNodesWithTag(tag),
new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata input) {
return input.getState() != NodeState.TERMINATED;
@ -219,31 +201,29 @@ public class BaseComputeService implements ComputeService {
}
@Override
public Map<String, ? extends ComputeMetadata> getNodes() {
logger.debug(">> listing servers");
ImmutableMap<String, ? extends ComputeMetadata> map = Maps.uniqueIndex(listNodesStrategy
.execute(GetNodesOptions.NONE), METADATA_TO_ID);
logger.debug("<< list(%d)", map.size());
return map;
public Set<? extends ComputeMetadata> listNodes() {
return listNodes(null);
}
@Override
public Map<String, ? extends ComputeMetadata> getNodes(GetNodesOptions options) {
public Set<? extends ComputeMetadata> listNodes(GetNodesOptions options) {
logger.debug(">> listing servers");
if (options == null) {
options = GetNodesOptions.NONE;
}
ImmutableMap<String, ? extends ComputeMetadata> map = Maps.uniqueIndex(listNodesStrategy
.execute(options), METADATA_TO_ID);
logger.debug("<< list(%d)", map.size());
return map;
Set<? extends ComputeMetadata> set = Sets
.newLinkedHashSet(listNodesStrategy.execute(options));
logger.debug("<< list(%d)", set.size());
return set;
}
/**
* If the result of {@link ListNodesStrategy#execute} is a set of nodes, then return them.
* Otherwise iteratively call {@link #getNodeMetadata}
*/
protected Map<String, ? extends NodeMetadata> doGetNodesWithTag(final String tag) {
Iterable<? extends NodeMetadata> nodes = Iterables.filter(Iterables.transform(
listNodesStrategy.execute(GetNodesOptions.NONE), new Function<ComputeMetadata, NodeMetadata>() {
protected Set<? extends NodeMetadata> doListNodesWithTag(final String tag) {
return Sets.newHashSet(Iterables.filter(Iterables.transform(listNodesStrategy
.execute(GetNodesOptions.NONE), new Function<ComputeMetadata, NodeMetadata>() {
@Override
public NodeMetadata apply(ComputeMetadata from) {
@ -251,37 +231,29 @@ public class BaseComputeService implements ComputeService {
: getNodeMetadata(from);
}
}), new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata input) {
return tag.equals(input.getTag());
}
});
return Maps.uniqueIndex(Iterables.filter(nodes, new NodeMatchesTag(tag)), METADATA_TO_ID);
}), new NodeMatchesTag(tag)));
}
@Override
public Map<String, ? extends NodeMetadata> getNodesWithTag(String tag) {
public Set<? extends NodeMetadata> listNodesWithTag(String 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());
return nodes;
}
@Override
public Map<String, ? extends Size> getSizes() {
public Set<? extends Size> listSizes() {
return sizes.get();
}
@Override
public Map<String, ? extends Image> getImages() {
public Set<? extends Image> listImages() {
return images.get();
}
@Override
public Map<String, ? extends Location> getAssignableLocations() {
public Set<? extends Location> listAssignableLocations() {
return locations.get();
}
@ -310,8 +282,8 @@ public class BaseComputeService implements ComputeService {
@Override
public void rebootNodesWithTag(String tag) { // TODO parallel
logger.debug(">> rebooting nodes by tag(%s)", tag);
Iterable<? extends NodeMetadata> nodesToReboot = Iterables.filter(doGetNodesWithTag(tag)
.values(), new Predicate<NodeMetadata>() {
Iterable<? extends NodeMetadata> nodesToReboot = Iterables.filter(doListNodesWithTag(tag),
new Predicate<NodeMetadata>() {
@Override
public boolean apply(NodeMetadata input) {
return input.getState() != NodeState.TERMINATED;
@ -333,9 +305,11 @@ public class BaseComputeService implements ComputeService {
}
/**
* @throws RunScriptOnNodesException
* @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);
}
@ -350,23 +324,78 @@ public class BaseComputeService implements ComputeService {
* @param options
* nullable options to how to run the script, whether to override credentials
* @return map with node identifiers and corresponding responses
* @throws RunScriptOnNodesException
*/
@SuppressWarnings("unchecked")
public Map<String, ExecResponse> runScriptOnNodesWithTag(String tag, byte[] runScript,
@Nullable RunScriptOptions options) {
public Map<NodeMetadata, ExecResponse> runScriptOnNodesWithTag(String tag,
final byte[] runScript, @Nullable final 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");
checkNotNull(runScript,
"The script (represented by bytes array - use \"script\".getBytes() must be provided");
if (options == null)
options = RunScriptOptions.NONE;
checkNotNull(options, "options");
Iterable<? extends NodeMetadata> nodes = Iterables.filter(listNodesWithTag(tag),
new Predicate<NodeMetadata>() {
Map<String, ? extends NodeMetadata> nodes = getNodesWithTag(tag);
Map<String, ExecResponse> responses = Maps.newHashMap();
@Override
public boolean apply(NodeMetadata input) {
return input.getState() == NodeState.RUNNING;
}
for (NodeMetadata node : nodes.values()) {
if (NodeState.RUNNING != node.getState())
continue; // make sure the node is active
});
return Iterables.transform(nodes, new Function<NodeMetadata, NodeMetadata>() {
@Override
public NodeMetadata apply(NodeMetadata node) {
checkArgument(node.getPublicAddresses().size() > 0, "no public ip addresses on node: "
+ node);
if (options.getOverrideCredentials() != null) {
// override the credentials with provided to this method
node = ComputeUtils.installNewCredentials(node, options.getOverrideCredentials());
@ -374,22 +403,15 @@ public class BaseComputeService implements ComputeService {
// don't override
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");
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");
}
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 node;
}
return responses;
});
}
}

View File

@ -18,11 +18,10 @@
*/
package org.jclouds.compute.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -61,9 +60,9 @@ public class TemplateBuilderImpl implements TemplateBuilder {
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Map<String, ? extends Image> images;
private final Map<String, ? extends Size> sizes;
private final Map<String, ? extends Location> locations;
private final Set<? extends Image> images;
private final Set<? extends Size> sizes;
private final Set<? extends Location> locations;
@VisibleForTesting
OsFamily os;
@VisibleForTesting
@ -97,9 +96,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
private TemplateOptions options = TemplateOptions.NONE;
@Inject
protected TemplateBuilderImpl(Map<String, ? extends Location> locations,
Map<String, ? extends Image> images, Map<String, ? extends Size> sizes,
Location defaultLocation) {
protected TemplateBuilderImpl(Set<? extends Location> locations, Set<? extends Image> images,
Set<? extends Size> sizes, Location defaultLocation) {
this.locations = locations;
this.images = images;
this.sizes = sizes;
@ -363,8 +361,6 @@ public class TemplateBuilderImpl implements TemplateBuilder {
*/
@Override
public TemplateBuilder locationId(final String locationId) {
checkArgument(locations.get(checkNotNull(locationId, "locationId")) != null, "locationId "
+ locationId + " not configured in: " + locations.keySet());
this.locationId = locationId;
return this;
}
@ -395,7 +391,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
logger.debug(">> searching params(%s)", this);
Image image;
try {
image = DEFAULT_IMAGE_ORDERING.max(Iterables.filter(images.values(), imagePredicate));
image = DEFAULT_IMAGE_ORDERING.max(Iterables.filter(images, imagePredicate));
} catch (NoSuchElementException exception) {
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));
Size size;
try {
size = sizeOrdering.max(Iterables.filter(sizes.values(), sizePredicate));
size = sizeOrdering.max(Iterables.filter(sizes, sizePredicate));
} catch (NoSuchElementException exception) {
throw new NoSuchElementException("size didn't match: " + toString() + "\n" + sizes);
}
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);
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 boolean destroyOnError;
private int port = -1;
private int seconds = -1;
@ -64,10 +62,6 @@ public class TemplateOptions {
return publicKey;
}
public boolean shouldDestroyOnError() {
return destroyOnError;
}
public boolean isIncludeMetadata() {
return includeMetadata;
}
@ -83,14 +77,6 @@ public class TemplateOptions {
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
* prologue, so no #!/bin/bash required, path set up, etc
@ -139,13 +125,6 @@ public class TemplateOptions {
}
public static class Builder {
/**
* @see TemplateOptions#destroyOnError
*/
public static TemplateOptions destroyOnError() {
TemplateOptions options = new TemplateOptions();
return options.destroyOnError();
}
/**
* @see TemplateOptions#inboundPorts
@ -198,7 +177,7 @@ public class TemplateOptions {
public String toString() {
return "TemplateOptions [inboundPorts=" + Arrays.toString(inboundPorts) + ", privateKey="
+ (privateKey != null) + ", publicKey=" + (publicKey != null) + ", runScript="
+ (script != null) + ", destroyOnError=" + destroyOnError + ", port:seconds=" + port
+ ":" + seconds + ", metadata/details: " + includeMetadata + "]";
+ (script != null) + ", port:seconds=" + port + ":" + seconds
+ ", metadata/details: " + includeMetadata + "]";
}
}

View File

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

View File

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

View File

@ -31,7 +31,6 @@ import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@ -155,9 +154,9 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
public void testImagesCache() throws Exception {
client.getImages();
client.listImages();
long time = System.currentTimeMillis();
client.getImages();
client.listImages();
long duration = System.currentTimeMillis() - time;
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(
keyPair.get("public")).runScript(
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);
checkNodes(nodes, tag);
NodeMetadata node1 = nodes.first();
@ -210,8 +209,7 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCreateTwoNodesWithRunScript")
public void testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired() throws Exception {
initializeContextAndClient();
TreeSet<NodeMetadata> nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 1, template)
.values());
TreeSet<NodeMetadata> nodes = Sets.newTreeSet(client.runNodesWithTag(tag, 1, template));
checkNodes(nodes, tag);
NodeMetadata node = nodes.first();
this.nodes.add(node);
@ -226,13 +224,13 @@ public abstract class BaseComputeServiceLiveTest {
Template simpleTemplate = buildTemplate(client.templateBuilder());
simpleTemplate.getOptions().blockOnPort(22, 120);
try {
Map<String, ? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, simpleTemplate);
Credentials good = nodes.values().iterator().next().getCredentials();
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, simpleTemplate);
Credentials good = nodes.iterator().next().getCredentials();
assert good.account != null;
try {
Map<String, ExecResponse> responses = runScriptWithCreds(tag, simpleTemplate.getImage()
.getOsFamily(), new Credentials(good.account, "romeo"));
Map<NodeMetadata, ExecResponse> responses = runScriptWithCreds(tag, simpleTemplate
.getImage().getOsFamily(), new Credentials(good.account, "romeo"));
assert false : "shouldn't pass with a bad password\n" + responses;
} catch (SshException e) {
assert Throwables.getRootCause(e).getMessage().contains("Auth fail") : e;
@ -240,22 +238,22 @@ public abstract class BaseComputeServiceLiveTest {
runScriptWithCreds(tag, simpleTemplate.getImage().getOsFamily(), good);
checkNodes(nodes.values(), tag);
checkNodes(nodes, tag);
} finally {
client.destroyNodesWithTag(tag);
}
}
private Map<String, ExecResponse> runScriptWithCreds(String tag, OsFamily osFamily,
Credentials creds) {
private Map<NodeMetadata, ExecResponse> runScriptWithCreds(String tag, OsFamily osFamily,
Credentials creds) throws RunScriptOnNodesException {
try {
return client.runScriptOnNodesWithTag(tag, buildScript(osFamily).getBytes(),
RunScriptOptions.Builder.overrideCredentialsWith(creds));
} catch (SshException e) {
if (Throwables.getRootCause(e).getMessage().contains("Auth fail")) {
System.err.printf("bad credentials: %s:%s for %s%n", creds.account, creds.key, client
.getNodesWithTag(tag));
.listNodesWithTag(tag));
}
throw e;
}
@ -316,7 +314,7 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
public void testGet() throws Exception {
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
public boolean apply(NodeMetadata input) {
return input.getState() == NodeState.TERMINATED;
@ -352,23 +350,20 @@ public abstract class BaseComputeServiceLiveTest {
}
public void testListNodes() throws Exception {
for (Entry<String, ? extends ComputeMetadata> node : client.getNodes().entrySet()) {
assertEquals(node.getKey(), node.getValue().getId());
assert node.getValue().getId() != null;
assert node.getValue().getLocation() != null;
assertEquals(node.getValue().getType(), ComputeType.NODE);
for (ComputeMetadata node : client.listNodes()) {
assert node.getId() != null;
assert node.getLocation() != null;
assertEquals(node.getType(), ComputeType.NODE);
}
}
public void testGetNodesWithDetails() throws Exception {
for (Entry<String, ? extends ComputeMetadata> node : client.getNodes(
new GetNodesOptions().withDetails()).entrySet()) {
assertEquals(node.getKey(), node.getValue().getId());
assert node.getValue().getId() != null : node;
assert node.getValue().getLocation() != null : node;
assertEquals(node.getValue().getType(), ComputeType.NODE);
assert node.getValue() instanceof NodeMetadata;
NodeMetadata nodeMetadata = (NodeMetadata) node.getValue();
for (ComputeMetadata node : client.listNodes(new GetNodesOptions().withDetails())) {
assert node.getId() != null : node;
assert node.getLocation() != null : node;
assertEquals(node.getType(), ComputeType.NODE);
assert node instanceof NodeMetadata;
NodeMetadata nodeMetadata = (NodeMetadata) node;
assert nodeMetadata.getId() != null : nodeMetadata;
// nullable
// assert nodeMetadata.getImage() != null : node;
@ -384,41 +379,39 @@ public abstract class BaseComputeServiceLiveTest {
}
public void testListImages() throws Exception {
for (Entry<String, ? extends Image> image : client.getImages().entrySet()) {
assertEquals(image.getKey(), image.getValue().getId());
assert image.getValue().getId() != null : image;
// image.getValue().getLocationId() can be null, if it is a location-free image
assertEquals(image.getValue().getType(), ComputeType.IMAGE);
for (Image image : client.listImages()) {
assert image.getId() != null : image;
// image.getLocationId() can be null, if it is a location-free image
assertEquals(image.getType(), ComputeType.IMAGE);
}
}
@Test(groups = { "integration", "live" })
public void testGetAssignableLocations() throws Exception {
for (Entry<String, ? extends Location> location : client.getAssignableLocations().entrySet()) {
System.err.printf("location %s%n", location.getValue());
assertEquals(location.getKey(), location.getValue().getId());
assert location.getValue().getId() != null : location;
assert location.getValue() != location.getValue().getParent() : location;
assert location.getValue().getScope() != null : location;
switch (location.getValue().getScope()) {
for (Location location : client.listAssignableLocations()) {
System.err.printf("location %s%n", location);
assert location.getId() != null : location;
assert location != location.getParent() : location;
assert location.getScope() != null : location;
switch (location.getScope()) {
case PROVIDER:
assertProvider(location.getValue());
assertProvider(location);
break;
case REGION:
assertProvider(location.getValue().getParent());
assertProvider(location.getParent());
break;
case ZONE:
Location provider = location.getValue().getParent().getParent();
Location provider = location.getParent().getParent();
// zone can be a direct descendant of provider
if (provider == null)
provider = location.getValue().getParent();
provider = location.getParent();
assertProvider(provider);
break;
case HOST:
Location provider2 = location.getValue().getParent().getParent().getParent();
Location provider2 = location.getParent().getParent().getParent();
// zone can be a direct descendant of provider
if (provider2 == null)
provider2 = location.getValue().getParent().getParent();
provider2 = location.getParent().getParent();
assertProvider(provider2);
break;
}
@ -431,14 +424,13 @@ public abstract class BaseComputeServiceLiveTest {
}
public void testListSizes() throws Exception {
for (Entry<String, ? extends Size> size : client.getSizes().entrySet()) {
assertEquals(size.getKey(), size.getValue().getId());
assert size.getValue().getId() != null;
assert size.getValue().getCores() > 0;
assert size.getValue().getDisk() > 0;
assert size.getValue().getRam() > 0;
assert size.getValue().getSupportedArchitectures() != null;
assertEquals(size.getValue().getType(), ComputeType.SIZE);
for (Size size : client.listSizes()) {
assert size.getId() != null;
assert size.getCores() > 0;
assert size.getDisk() > 0;
assert size.getRam() > 0;
assert size.getSupportedArchitectures() != null;
assertEquals(size.getType(), ComputeType.SIZE);
}
}
@ -480,7 +472,7 @@ public abstract class BaseComputeServiceLiveTest {
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (nodes != null) {
client.destroyNodesWithTag(tag);
for (NodeMetadata node : client.getNodesWithTag(tag).values()) {
for (NodeMetadata node : client.listNodesWithTag(tag)) {
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.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
/**
*
@ -40,8 +40,8 @@ public class TemplateBuilderImplTest {
@Test
public void testImageIdNullsEverythingElse() {
TemplateBuilderImpl template = new TemplateBuilderImpl(ImmutableMap.<String, Location> of(),
ImmutableMap.<String, Image> of(), ImmutableMap.<String, Size> of(),
TemplateBuilderImpl template = new TemplateBuilderImpl(ImmutableSet.<Location> of(),
ImmutableSet.<Image> of(), ImmutableSet.<Size> of(),
new LocationImpl(LocationScope.REGION, " id", "description", null));
template.architecture(Architecture.X86_32);
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?)
(map (comp instantiate module-lookup) modules)))))
(defn seq-from-immutable-set [#^ImmutableSet set]
(map #(.getValue %) set))
(defn dashed [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.regex.Pattern;
import javax.annotation.Resource;
import org.jclouds.date.DateService;
import org.jclouds.logging.Logger;
/**
*
@ -35,6 +38,9 @@ import org.jclouds.date.DateService;
* @author James Murty
*/
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
* guard against the lack of thread safety.
@ -134,6 +140,8 @@ public class SimpleDateFormatDateService implements DateService {
public static final Pattern NANOS_TO_MILLIS_PATTERN = Pattern
.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) {
if (NANOS_TO_MILLIS_PATTERN.matcher(toParse).matches())
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");
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())
toParse = toParse.substring(0, toParse.length() - 6) + 'Z';
return toParse;

View File

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

View File

@ -58,15 +58,18 @@ public class DateServiceTest extends PerformanceTest {
protected class TestData {
public final String iso8601DateString;
public final String iso8601DateStringTz;
public final String iso8601SecondsDateString;
public final String rfc822DateString;
public final String cDateString;
public final Date date;
TestData(String iso8601, String iso8601Seconds, String rfc822, String cDateString,
Date dateTime) {
TestData(String iso8601, String iso8601DateStringTz, String iso8601Seconds, String rfc822,
String cDateString, Date dateTime) {
this.iso8601DateString = iso8601;
this.iso8601DateStringTz = iso8601DateStringTz;
this.iso8601SecondsDateString = iso8601Seconds;
this.rfc822DateString = rfc822;
this.cDateString = cDateString;
@ -77,21 +80,21 @@ public class DateServiceTest extends PerformanceTest {
public DateServiceTest() {
// Constant time test values, each TestData item must contain matching times!
testData = new TestData[] {
new TestData("2009-03-12T02:00:07.000Z", "2009-03-12T02:00:07Z",
"Thu, 12 Mar 2009 02:00:07 GMT", "Thu Mar 12 02:00:07 +0000 2009",
new Date(1236823207000l)),
new TestData("2009-03-14T04:00:07.000Z", "2009-03-14T04:00:07Z",
"Sat, 14 Mar 2009 04:00:07 GMT", "Thu Mar 14 04:00:07 +0000 2009",
new Date(1237003207000l)),
new TestData("2009-03-16T06:00:07.000Z", "2009-03-16T06:00:07Z",
"Mon, 16 Mar 2009 06:00:07 GMT", "Thu Mar 16 06:00:07 +0000 2009",
new Date(1237183207000l)),
new TestData("2009-03-18T08:00:07.000Z", "2009-03-18T08:00:07Z",
"Wed, 18 Mar 2009 08:00:07 GMT", "Thu Mar 18 08:00:07 +0000 2009",
new Date(1237363207000l)),
new TestData("2009-03-20T10:00:07.000Z", "2009-03-20T10:00:07Z",
"Fri, 20 Mar 2009 10:00:07 GMT", "Thu Mar 20 10:00:07 +0000 2009",
new Date(1237543207000l)) };
new TestData("2009-03-12T02:00:07.000Z", "2009-03-12T02:00:07+04:00",
"2009-03-12T02:00:07Z", "Thu, 12 Mar 2009 02:00:07 GMT",
"Thu Mar 12 02:00:07 +0000 2009", new Date(1236823207000l)),
new TestData("2009-03-14T04:00:07.000Z", "2009-03-14T04:00:07Z+04:00",
"2009-03-14T04:00:07Z", "Sat, 14 Mar 2009 04:00:07 GMT",
"Thu Mar 14 04:00:07 +0000 2009", new Date(1237003207000l)),
new TestData("2009-03-16T06:00:07.000Z", "2009-03-16T06:00:07Z+04:00",
"2009-03-16T06:00:07Z", "Mon, 16 Mar 2009 06:00:07 GMT",
"Thu Mar 16 06:00:07 +0000 2009", new Date(1237183207000l)),
new TestData("2009-03-18T08:00:07.000Z", "2009-03-18T08:00:07Z+04:00",
"2009-03-18T08:00:07Z", "Wed, 18 Mar 2009 08:00:07 GMT",
"Thu Mar 18 08:00:07 +0000 2009", new Date(1237363207000l)),
new TestData("2009-03-20T10:00:07.000Z", "2009-03-20T10:00:07Z+04:00",
"2009-03-20T10:00:07Z", "Fri, 20 Mar 2009 10:00:07 GMT",
"Thu Mar 20 10:00:07 +0000 2009", new Date(1237543207000l)) };
}
@Test
@ -99,6 +102,11 @@ public class DateServiceTest extends PerformanceTest {
Date dsDate = dateService.iso8601DateParse(testData[0].iso8601DateString);
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
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.InputStream;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@ -40,6 +41,8 @@ import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshException;
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.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
@ -75,6 +78,7 @@ public class JschSshClient implements SshClient {
private final int port;
private final String username;
private final String password;
private int sshRetries = 3;
@Resource
protected Logger logger = Logger.NULL;
@ -177,15 +181,37 @@ public class JschSshClient implements SshClient {
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
RETRY_LOOP: for (int i = 0; i < sshRetries; i++) {
try {
session.connect();
} catch (JSchException e) {
throw new SshException(String.format("%s@%s:%d: Error connecting to session.", username,
host.getHostAddress(), port), e);
break RETRY_LOOP;
} 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);
}
private SshException propagate(Exception e) {
throw new SshException(String.format("%s@%s:%d: Error connecting to session.", username, host
.getHostAddress(), port), e);
}
@PreDestroy
public void disconnect() {
if (session != null && session.isConnected())

View File

@ -23,14 +23,18 @@
*/
package org.jclouds.gogrid;
import org.jclouds.PropertiesBuilder;
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.util.Properties;
import org.jclouds.PropertiesBuilder;
/**
* Builds properties used in GoGrid Clients
*
@ -44,7 +48,7 @@ public class GoGridPropertiesBuilder extends PropertiesBuilder {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_GOGRID_ENDPOINT, "https://api.gogrid.com/api");
properties.setProperty(PROPERTY_GOGRID_SESSIONINTERVAL, 60 + "");
properties.setProperty(PROPERTY_GOGRID_DEFAULT_DC, "SANFRANCISCO");
return properties;
}

View File

@ -19,6 +19,7 @@
package org.jclouds.gogrid.compute.config;
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.UnknownHostException;
@ -82,7 +83,6 @@ import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
@ -279,13 +279,21 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Provides
@Singleton
Location getDefaultLocation(Map<String, ? extends Location> locations) {
return locations.get("SANFRANCISCO");
Location getDefaultLocation(@Named(PROPERTY_GOGRID_DEFAULT_DC) final String defaultDC,
Set<? extends Location> locations) {
return Iterables.find(locations, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(defaultDC);
}
});
}
@Provides
@Singleton
Map<String, ? extends Location> getDefaultLocations(GoGridClient sync, LogHolder holder,
Set<? extends Location> getDefaultLocations(GoGridClient sync, LogHolder holder,
Function<ComputeMetadata, String> indexer) {
final Set<Location> locations = Sets.newHashSet();
holder.logger.debug(">> providing locations");
@ -293,13 +301,7 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
locations.add(new LocationImpl(LocationScope.ZONE, "SANFRANCISCO", "San Francisco, CA",
parent));
holder.logger.debug("<< locations(%d)", locations.size());
return Maps.uniqueIndex(locations, new Function<Location, String>() {
@Override
public String apply(Location from) {
return from.getId();
}
});
return locations;
}
@Provides
@ -315,10 +317,9 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Provides
@Singleton
protected Map<String, ? extends Size> provideSizes(GoGridClient sync,
Map<String, ? extends Image> images, LogHolder holder,
Function<ComputeMetadata, String> indexer) throws InterruptedException,
TimeoutException, ExecutionException {
protected Set<? extends Size> provideSizes(GoGridClient sync, Set<? extends Image> images,
LogHolder holder, Function<ComputeMetadata, String> indexer)
throws InterruptedException, TimeoutException, ExecutionException {
final Set<Size> sizes = Sets.newHashSet();
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,
462, ImmutableSet.<Architecture> of(Architecture.X86_32, Architecture.X86_64)));
holder.logger.debug("<< sizes(%d)", sizes.size());
return Maps.uniqueIndex(sizes, indexer);
return sizes;
}
private static class LogHolder {
@ -346,7 +347,7 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
@Provides
@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,
PopulateDefaultLoginCredentialsForImageStrategy authenticator)
throws InterruptedException, ExecutionException, TimeoutException {
@ -375,6 +376,6 @@ public class GoGridComputeServiceContextModule extends GoGridContextModule {
osDescription, arch, defaultCredentials));
}
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.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -37,11 +39,14 @@ import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.gogrid.domain.Server;
import org.jclouds.gogrid.services.GridServerClient;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* @author Oleksiy Yarmula
@ -50,14 +55,33 @@ import com.google.common.collect.ImmutableSet;
public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
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 GridServerClient client;
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
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.client = checkNotNull(client, "client");
this.images = checkNotNull(images, "images");
@ -71,8 +95,16 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
Set<InetAddress> ipSet = ImmutableSet.of(from.getIp().getIp());
NodeState state = serverStateToNodeState.get(from.getState().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
.<String, String> of(), tag, images.get(from.getImage().getId() + ""), state, ipSet,
ImmutableList.<InetAddress> of(), ImmutableMap.<String, String> of(), creds);
.<String, String> of(), tag, image, state, ipSet, ImmutableList.<InetAddress> of(),
ImmutableMap.<String, String> of(), creds);
}
}

View File

@ -36,5 +36,6 @@ public interface GoGridConstants {
* 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_DEFAULT_DC = "jclouds.gogrid.defaultdc";
}

View File

@ -9,6 +9,7 @@ import static org.testng.Assert.assertEquals;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
@ -23,6 +24,8 @@ import org.jclouds.gogrid.domain.ServerImage;
import org.jclouds.gogrid.services.GridServerClient;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
*/
@ -34,7 +37,9 @@ public class ServerToNodeMetadataTest {
public void testApplySetsTagFromNameAndCredentialsFromName() throws UnknownHostException {
GridServerClient client = createMock(GridServerClient.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);
expect(server.getId()).andReturn(1000l).atLeastOnce();
@ -54,16 +59,15 @@ public class ServerToNodeMetadataTest {
ServerImage image = createMock(ServerImage.class);
expect(server.getImage()).andReturn(image).atLeastOnce();
expect(image.getId()).andReturn(2000l).atLeastOnce();
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
expect(images.get("2000")).andReturn(jcImage);
expect(jcImage.getId()).andReturn("2000").atLeastOnce();
expect(jcImage.getLocation()).andReturn(location).atLeastOnce();
replay(client);
replay(serverStateToNodeState);
replay(server);
replay(image);
replay(jcImage);
replay(credentialsMap);
replay(images);
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, client,
images, location);
@ -79,7 +83,8 @@ public class ServerToNodeMetadataTest {
verify(image);
verify(credentialsMap);
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.util.concurrent.Futures.compose;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
@ -81,7 +80,7 @@ public class CloudFilesAsyncBlobStore extends BaseAsyncBlobStore {
@Inject
CloudFilesAsyncBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Map<String, ? extends Location> locations,
Location defaultLocation, Set<? extends Location> locations,
CloudFilesClient sync, CloudFilesAsyncClient async,
ContainerToResourceMetadata container2ResourceMd,
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,

View File

@ -20,7 +20,6 @@ package org.jclouds.rackspace.cloudfiles.blobstore;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
@ -70,7 +69,7 @@ public class CloudFilesBlobStore extends BaseBlobStore {
@Inject
CloudFilesBlobStore(BlobStoreContext context, BlobStoreUtils blobUtils,
Location defaultLocation, Map<String, ? extends Location> locations,
Location defaultLocation, Set<? extends Location> locations,
CloudFilesClient sync, ContainerToResourceMetadata container2ResourceMd,
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
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.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
@ -303,8 +302,8 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Provides
@Singleton
protected Map<String, ? extends Size> provideSizes(CloudServersClient sync,
Map<String, ? extends Image> images, Location location, LogHolder holder,
protected Set<? extends Size> provideSizes(CloudServersClient sync, Set<? extends Image> images,
Location location, LogHolder holder,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
Function<ComputeMetadata, String> indexer) throws InterruptedException,
TimeoutException, ExecutionException {
@ -316,7 +315,7 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
ImmutableSet.<Architecture> of(Architecture.X86_32, Architecture.X86_64)));
}
holder.logger.debug("<< sizes(%d)", sizes.size());
return Maps.uniqueIndex(sizes, indexer);
return sizes;
}
private static class LogHolder {
@ -329,8 +328,8 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
@Provides
@Singleton
protected Map<String, ? extends Image> provideImages(final CloudServersClient sync,
Location location, LogHolder holder, Function<ComputeMetadata, String> indexer)
protected Set<? extends Image> provideImages(final CloudServersClient sync, Location location,
LogHolder holder, Function<ComputeMetadata, String> indexer)
throws InterruptedException, ExecutionException, TimeoutException {
final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images");
@ -358,6 +357,6 @@ public class CloudServersComputeServiceContextModule extends CloudServersContext
new Credentials("root", null)));
}
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 java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject;
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.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
import org.jclouds.logging.Logger;
import org.jclouds.rackspace.cloudservers.domain.Server;
import org.jclouds.rackspace.cloudservers.domain.ServerStatus;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
/**
* @author Adrian Cole
@ -47,11 +53,31 @@ public class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
.compile("[^-]+-([^-]+)-[0-9a-f]+");
private final Location location;
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
ServerToNodeMetadata(Map<ServerStatus, NodeState> serverStateToNodeState,
Map<String, ? extends Image> images, Location location) {
Set<? extends Image> images, Location location) {
this.serverToNodeState = checkNotNull(serverStateToNodeState, "serverStateToNodeState");
this.images = checkNotNull(images, "images");
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
.getName());
final String tag = matcher.find() ? matcher.group(1) : null;
return new NodeMetadataImpl(from.getId() + "", from.getName(), new LocationImpl(
LocationScope.HOST, from.getHostId(), from.getHostId(), location), null, from
.getMetadata(), tag, images.get(from.getImageId().toString()), serverToNodeState
.get(from.getStatus()), from.getAddresses().getPublicAddresses(), from
.getAddresses().getPrivateAddresses(), ImmutableMap.<String, String> of(), null);
Location host = new LocationImpl(LocationScope.HOST, from.getHostId(), from.getHostId(),
location);
Image image = null;
try {
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;
import java.util.Map;
import java.util.Set;
import javax.inject.Singleton;
@ -27,7 +27,7 @@ import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
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.Provides;
@ -57,7 +57,7 @@ public class RackspaceLocationsModule extends AbstractModule {
@Provides
@Singleton
Map<String, ? extends Location> provideLocations(Location location) {
return ImmutableMap.of(location.getId(), location);
Set<? extends Location> provideLocations(Location location) {
return ImmutableSet.of(location);
}
}

View File

@ -34,7 +34,9 @@ public class ServerToNodeMetadataTest {
@Test
public void testApplySetsTagFromNameAndSetsMetadata() throws UnknownHostException {
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);
expect(server.getId()).andReturn(10000).atLeastOnce();
@ -60,14 +62,13 @@ public class ServerToNodeMetadataTest {
expect(addresses.getPrivateAddresses()).andReturn(privateAddresses);
expect(server.getImageId()).andReturn(2000).atLeastOnce();
org.jclouds.compute.domain.Image jcImage = createMock(org.jclouds.compute.domain.Image.class);
expect(images.get("2000")).andReturn(jcImage);
expect(jcImage.getId()).andReturn("2000").atLeastOnce();
expect(jcImage.getLocation()).andReturn(provider).atLeastOnce();
replay(addresses);
replay(jcImage);
replay(serverStateToNodeState);
replay(server);
replay(images);
ServerToNodeMetadata parser = new ServerToNodeMetadata(serverStateToNodeState, images,
provider);
@ -85,7 +86,7 @@ public class ServerToNodeMetadataTest {
verify(addresses);
verify(serverStateToNodeState);
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 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 java.net.URI;
@ -37,6 +38,7 @@ public class RimuHostingPropertiesBuilder extends PropertiesBuilder {
protected Properties defaultProperties() {
Properties properties = super.defaultProperties();
properties.setProperty(PROPERTY_RIMUHOSTING_ENDPOINT, "https://rimuhosting.com/r");
properties.setProperty(PROPERTY_RIMUHOSTING_DEFAULT_DC, "DCDALLAS");
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 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.UnknownHostException;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ExecutionException;
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.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
@ -259,17 +260,37 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Singleton
private static class ServerToNodeMetadata implements Function<Server, NodeMetadata> {
@Resource
protected Logger logger = Logger.NULL;
private final Function<Server, Iterable<InetAddress>> getPublicAddresses;
private final Map<RunningState, NodeState> runningStateToNodeState;
private final Map<String, ? extends Image> images;
private final Set<? extends Image> images;
@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")
@Inject
ServerToNodeMetadata(Function<Server, Iterable<InetAddress>> getPublicAddresses,
Map<RunningState, NodeState> runningStateToNodeState,
Map<String, ? extends Image> images, Map<String, ? extends Location> locations) {
Map<RunningState, NodeState> runningStateToNodeState, Set<? extends Image> images,
Set<? extends Location> locations) {
this.getPublicAddresses = checkNotNull(getPublicAddresses, "serverStateToNodeState");
this.runningStateToNodeState = checkNotNull(runningStateToNodeState,
"serverStateToNodeState");
@ -284,10 +305,18 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
.getLocation().getName(), null);
String tag = from.getName().replaceAll("-[0-9]+", "");
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());
return new NodeMetadataImpl(from.getId() + "", from.getName(), location, null,
ImmutableMap.<String, String> of(), tag, images.get(from.getImageId()), state,
getPublicAddresses.apply(from), ImmutableList.<InetAddress> of(), ImmutableMap
ImmutableMap.<String, String> of(), tag, image, state, getPublicAddresses
.apply(from), ImmutableList.<InetAddress> of(), ImmutableMap
.<String, String> of(), creds);
}
@ -333,13 +362,21 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Provides
@Singleton
Location getDefaultLocation(Map<String, ? extends Location> locations) {
return locations.get("DCDALLAS");
Location getDefaultLocation(@Named(PROPERTY_RIMUHOSTING_DEFAULT_DC) final String defaultDC,
Set<? extends Location> locations) {
return Iterables.find(locations, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(defaultDC);
}
});
}
@Provides
@Singleton
Map<String, ? extends Location> getDefaultLocations(RimuHostingClient sync, LogHolder holder,
Set<? extends Location> getDefaultLocations(RimuHostingClient sync, LogHolder holder,
Function<ComputeMetadata, String> indexer) {
final Set<Location> locations = Sets.newHashSet();
holder.logger.debug(">> providing locations");
@ -353,13 +390,7 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
}
}
holder.logger.debug("<< locations(%d)", locations.size());
return Maps.uniqueIndex(locations, new Function<Location, String>() {
@Override
public String apply(Location from) {
return from.getId();
}
});
return locations;
}
@Provides
@ -375,25 +406,33 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Provides
@Singleton
protected Map<String, ? extends Size> provideSizes(RimuHostingClient sync,
Map<String, ? extends Image> images, Map<String, ? extends Location> locations,
LogHolder holder, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
protected Set<? extends Size> provideSizes(RimuHostingClient sync, Set<? extends Image> images,
Set<? extends Location> locations, LogHolder holder,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
Function<ComputeMetadata, String> indexer) throws InterruptedException,
TimeoutException, ExecutionException {
final Set<Size> sizes = Sets.newHashSet();
holder.logger.debug(">> providing sizes");
for (final PricingPlan from : sync.getPricingPlanList()) {
try {
sizes.add(new SizeImpl(from.getId(), from.getId(), locations.get(from.getDataCenter()
.getId()), null, ImmutableMap.<String, String> of(), 1, from.getRam(), from
.getDiskSize(), ImmutableSet.<Architecture> of(Architecture.X86_32,
Architecture.X86_64)));
final Location location = Iterables.find(locations, new Predicate<Location>() {
@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) {
holder.logger.warn("datacenter not present in " + from.getId());
}
}
holder.logger.debug("<< sizes(%d)", sizes.size());
return Maps.uniqueIndex(sizes, indexer);
return sizes;
}
private static class LogHolder {
@ -406,9 +445,9 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
@Provides
@Singleton
protected Map<String, ? extends Image> provideImages(final RimuHostingClient sync,
LogHolder holder, Function<ComputeMetadata, String> indexer)
throws InterruptedException, ExecutionException, TimeoutException {
protected Set<? extends Image> provideImages(final RimuHostingClient sync, LogHolder holder,
Function<ComputeMetadata, String> indexer) throws InterruptedException,
ExecutionException, TimeoutException {
final Set<Image> images = Sets.newHashSet();
holder.logger.debug(">> providing images");
for (final org.jclouds.rimuhosting.miro.domain.Image from : sync.getImageList()) {
@ -434,7 +473,7 @@ public class RimuHostingComputeServiceContextModule extends RimuHostingContextMo
new Credentials("root", null)));
}
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 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_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.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.RunNodesException;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
@ -90,14 +91,19 @@ public class ComputeTask extends Task {
for (String action : Splitter.on(',').split(actions)) {
Action act = Action.valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE,
action));
try {
invokeActionOnService(act, context.getComputeService());
} catch (RunNodesException e) {
throw new BuildException(e);
}
}
} finally {
context.close();
}
}
private void invokeActionOnService(Action action, ComputeService computeService) {
private void invokeActionOnService(Action action, ComputeService computeService)
throws RunNodesException {
switch (action) {
case CREATE:
case GET:
@ -140,7 +146,7 @@ public class ComputeTask extends Task {
private void listDetails(ComputeService computeService) {
log("list details");
for (ComputeMetadata node : computeService.getNodes().values()) {// TODO
for (ComputeMetadata node : computeService.listNodes()) {// TODO
// parallel
logDetails(computeService, node);
}
@ -148,7 +154,7 @@ public class ComputeTask extends Task {
private void listImages(ComputeService computeService) {
log("list images");
for (Image image : computeService.getImages().values()) {// TODO
for (Image image : computeService.listImages()) {// TODO
log(String
.format(
" 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) {
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
.getCores(), size.getRam(), size.getDisk()));
}
@ -168,7 +174,7 @@ public class ComputeTask extends Task {
private void listLocations(ComputeService computeService) {
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
.getId(), location.getScope(), location.getDescription(), location.getParent()));
}
@ -176,13 +182,13 @@ public class ComputeTask extends Task {
private void list(ComputeService computeService) {
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
.getName()));
}
}
private void create(ComputeService computeService) {
private void create(ComputeService computeService) throws RunNodesException {
String tag = nodeElement.getTag();
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);
for (NodeMetadata createdNode : computeService.runNodesWithTag(tag, nodeElement.getCount(),
template).values()) {
template)) {
logDetails(computeService, createdNode);
addNodeDetailsAsProjectProperties(createdNode);
}
@ -218,7 +224,7 @@ public class ComputeTask extends Task {
private void get(ComputeService computeService) {
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);
}
}

View File

@ -22,6 +22,7 @@ package org.jclouds.vcloud.bluelock.compute;
import static org.testng.Assert.assertEquals;
import java.util.Map;
import java.util.Set;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.Image;
@ -54,7 +55,7 @@ public class BlueLockVCloudComputeServiceLiveTest extends VCloudComputeServiceLi
@Override
public void testListImages() throws Exception {
super.testListImages();
Map<String, ? extends Image> images = client.getImages();
Set<? extends Image> images = client.listImages();
assertEquals(images.size(), 5);
// 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 java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.Callable;
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.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
@ -145,7 +147,7 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Provides
@Named("NAMING_CONVENTION")
@Singleton
String provideNamingConvention() {
protected String provideNamingConvention() {
return "%s-%s%s";
}
@ -232,8 +234,10 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Inject
protected VCloudListNodesStrategy(VCloudClient client, VCloudComputeClient computeClient,
Map<VAppStatus, NodeState> vAppStatusToNodeState, GetExtra getExtra,
Map<String, ? extends Location> locations, Map<String, ? extends Image> images) {
super(client, computeClient, vAppStatusToNodeState, getExtra, locations, images);
FindLocationForResourceInVDC findLocationForResourceInVDC,
Set<? extends Image> images) {
super(client, computeClient, vAppStatusToNodeState, getExtra,
findLocationForResourceInVDC, images);
}
@Override
@ -273,9 +277,10 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Inject
protected VCloudGetNodeMetadataStrategy(VCloudClient client,
VCloudComputeClient computeClient, Map<VAppStatus, NodeState> vAppStatusToNodeState,
GetExtra getExtra, Map<String, ? extends Location> locations,
Map<String, ? extends Image> images) {
super(client, computeClient, vAppStatusToNodeState, getExtra, locations, images);
GetExtra getExtra, FindLocationForResourceInVDC findLocationForResourceInVDC,
Set<? extends Image> images) {
super(client, computeClient, vAppStatusToNodeState, getExtra,
findLocationForResourceInVDC, images);
}
@Override
@ -311,9 +316,9 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Provides
@Singleton
protected Map<String, ? extends Image> provideImages(final VCloudClient client,
protected Set<? extends Image> provideImages(final VCloudClient client,
final PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider,
final Map<String, ? extends Location> locations, LogHolder holder,
LogHolder holder, final FindLocationForResourceInVDC findLocationForResourceInVDC,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
Function<ComputeMetadata, String> indexer) throws InterruptedException,
ExecutionException, TimeoutException {
@ -339,11 +344,15 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
Architecture arch = resource.getName().indexOf("64") == -1 ? Architecture.X86_32
: Architecture.X86_64;
VAppTemplate template = client.getVAppTemplate(resource.getId());
Location location = findLocationForResourceInVDC.apply(resource, vDC
.getId());
images.add(new ImageImpl(resource.getId(), template.getName(),
locations.get(vDC.getId()), template.getLocation(),
ImmutableMap.<String, String> of(), template
.getDescription(), "", myOs, template.getName(),
arch, new Credentials("root", null)));
location, template.getLocation(), ImmutableMap
.<String, String> of(), template.getDescription(),
"", myOs, template.getName(), arch, new Credentials("root",
null)));
return null;
}
}), executor));
@ -353,7 +362,7 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
ConcurrentUtils.awaitCompletion(responses, executor, null, holder.logger,
"vAppTemplates in " + vDC);
}
return Maps.uniqueIndex(images, indexer);
return images;
}
@Provides
@ -369,17 +378,15 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Provides
@Singleton
Map<String, ? extends Location> provideLocations(Supplier<VCloudSession> cache,
VCloudClient client) {
Set<? extends Location> provideLocations(Supplier<VCloudSession> cache, VCloudClient client) {
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()) {
Location orgL = new LocationImpl(LocationScope.REGION, org.getId(), org.getName(),
provider);
for (NamedResource vdc : client.getOrganization(org.getId()).getVDCs().values()) {
locations.put(vdc.getId(), new LocationImpl(LocationScope.ZONE, vdc.getId(), vdc
.getName(), orgL));
locations.add(new LocationImpl(LocationScope.ZONE, vdc.getId(), vdc.getName(), orgL));
}
}
return locations;
@ -387,14 +394,22 @@ public class VCloudComputeServiceContextModule extends VCloudContextModule {
@Provides
@Singleton
Location getVDC(VCloudClient client, Map<String, ? extends Location> locations) {
return locations.get(client.getDefaultVDC().getId());
Location getVDC(VCloudClient client, Set<? extends Location> locations) {
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
@Singleton
protected Map<String, ? extends Size> provideSizes(Function<ComputeMetadata, String> indexer,
VCloudClient client, Map<String, ? extends Image> images, LogHolder holder,
protected Set<? extends Size> provideSizes(Function<ComputeMetadata, String> indexer,
VCloudClient client, Set<? extends Image> images, LogHolder holder,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
throws InterruptedException, TimeoutException, ExecutionException {
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,
null, null, ImmutableMap.<String, String> of(), cpus, ram, 10, ImmutableSet
.<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 java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.domain.Location;
import org.jclouds.logging.Logger;
import org.jclouds.vcloud.VCloudClient;
import org.jclouds.vcloud.compute.BaseVCloudComputeClient;
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.VAppStatus;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
/**
* Configures the {@link VCloudComputeServiceContext}; requires {@link BaseVCloudComputeClient}
@ -48,28 +57,31 @@ import com.google.common.collect.ImmutableMap;
*/
@Singleton
public class VCloudGetNodeMetadata {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
public Logger logger = Logger.NULL;
protected final VCloudClient client;
protected final VCloudComputeClient computeClient;
protected final Map<String, ? extends Image> images;
protected final Map<String, ? extends Location> locations;
protected final Set<? extends Image> images;
protected final FindLocationForResourceInVDC findLocationForResourceInVDC;
protected final GetExtra getExtra;
protected final Map<VAppStatus, NodeState> vAppStatusToNodeState;
// hex [][][] are templateId, last two are instanceId
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
protected VCloudGetNodeMetadata(VCloudClient client, VCloudComputeClient computeClient,
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.images = checkNotNull(images, "images");
this.getExtra = checkNotNull(getExtra, "getExtra");
this.locations = checkNotNull(locations, "locations");
this.findLocationForResourceInVDC = checkNotNull(findLocationForResourceInVDC,
"findLocationForResourceInVDC");
this.computeClient = checkNotNull(computeClient, "computeClient");
this.vAppStatusToNodeState = checkNotNull(vAppStatusToNodeState, "vAppStatusToNodeState");
}
@ -80,11 +92,26 @@ public class VCloudGetNodeMetadata {
String tag = null;
Image image = null;
Matcher matcher = TAG_PATTERN_WITH_TEMPLATE.matcher(vApp.getName());
final Location location = findLocationForResourceInVDC.apply(vApp, vDCId);
if (matcher.find()) {
tag = matcher.group(1);
String templateIdInHexWithoutLeadingZeros = matcher.group(2).replaceAll("^[0]+", "");
String templateId = Integer.parseInt(templateIdInHexWithoutLeadingZeros, 16) + "";
image = images.get(templateId);
final String templateId = Integer.parseInt(templateIdInHexWithoutLeadingZeros, 16) + "";
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 {
matcher = TAG_PATTERN_WITHOUT_TEMPLATE.matcher(vApp.getName());
if (matcher.find()) {
@ -93,9 +120,9 @@ public class VCloudGetNodeMetadata {
tag = "NOTAG-" + vApp.getName();
}
}
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), locations.get(vDCId), vApp
.getLocation(), ImmutableMap.<String, String> of(), tag, image,
vAppStatusToNodeState.get(vApp.getStatus()), computeClient.getPublicAddresses(id),
computeClient.getPrivateAddresses(id), getExtra.apply(vApp), null);
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), location, vApp.getLocation(),
ImmutableMap.<String, String> of(), tag, image, vAppStatusToNodeState.get(vApp
.getStatus()), computeClient.getPublicAddresses(id), computeClient
.getPrivateAddresses(id), getExtra.apply(vApp), null);
}
}

View File

@ -42,12 +42,15 @@ import com.google.common.base.Strings;
public class EncodeTemplateIdIntoNameRunNodesAndAddToSetStrategy extends
EncodeTagIntoNameRunNodesAndAddToSetStrategy {
private final SecureRandom random;
@Inject
protected EncodeTemplateIdIntoNameRunNodesAndAddToSetStrategy(
AddNodeWithTagStrategy addNodeWithTagStrategy, ListNodesStrategy listNodesStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention, ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService 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) {
return String.format(nodeNamingConvention, tag, Strings.padStart(Integer.toHexString(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 org.testng.Assert.assertEquals;
import java.util.Map.Entry;
import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.ComputeMetadata;
@ -46,12 +44,11 @@ public class VCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
@Override
public void testListNodes() throws Exception {
for (Entry<String, ? extends ComputeMetadata> node : client.getNodes().entrySet()) {
assertEquals(node.getKey(), node.getValue().getId());
assert node.getValue().getId() != null;
assert node.getValue().getLocation() != null;
assertEquals(node.getValue().getType(), ComputeType.NODE);
NodeMetadata allData = client.getNodeMetadata(node.getValue());
for (ComputeMetadata node : client.listNodes()) {
assert node.getId() != null;
assert node.getLocation() != null;
assertEquals(node.getType(), ComputeType.NODE);
NodeMetadata allData = client.getNodeMetadata(node);
assert allData.getExtra().get("processor/count") != null;
assert allData.getExtra().get("disk_drive/1/kb") != 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.NodeState;
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.compute.VCloudComputeClient;
import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule.FindLocationForResourceInVDC;
import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule.VCloudListNodesStrategy;
import org.jclouds.vcloud.compute.functions.GetExtra;
import org.jclouds.vcloud.domain.NamedResource;
@ -52,7 +55,7 @@ import org.jclouds.vcloud.domain.internal.VAppImpl;
import org.testng.annotations.Test;
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.ListMultimap;
import com.google.common.collect.Maps;
@ -112,10 +115,14 @@ public class VCloudComputeServiceContextModuleTest {
replay(client);
replay(computeClient);
Map<String, ? extends Location> locations = ImmutableMap.of();
Map<String, ? extends Image> images= ImmutableMap.of();
Location vdcL = new LocationImpl(LocationScope.ZONE, "1", "1", null);
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,
vAppStatusToNodeState, getExtra, locations, images);
vAppStatusToNodeState, getExtra, findLocationForResourceInVDC, images);
Set<ComputeMetadata> nodes = Sets.newHashSet();
NamedResource vdc = new NamedResourceImpl("1", null, null, null);

View File

@ -113,9 +113,9 @@ public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeSer
* query the catalog.
*/
@Override
protected Map<String, ? extends Image> provideImages(final VCloudClient client,
protected Set<? extends Image> provideImages(final VCloudClient client,
final PopulateDefaultLoginCredentialsForImageStrategy credentialsProvider,
final Map<String, ? extends Location> locations, LogHolder holder,
LogHolder holder, final FindLocationForResourceInVDC findLocationForResourceInVDC,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
Function<ComputeMetadata, String> indexer) throws InterruptedException,
ExecutionException, TimeoutException {
@ -145,11 +145,15 @@ public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeSer
: Architecture.X86_64;
VAppTemplate template = client.getVAppTemplate(item.getEntity()
.getId());
Location location = findLocationForResourceInVDC.apply(resource, vDC
.getId());
images.add(new ImageImpl(resource.getId(), template.getName(),
locations.get(vDC.getId()), template.getLocation(),
ImmutableMap.<String, String> of(), template
.getDescription(), "", myOs, template.getName(),
arch, credentialsProvider.execute(template)));
location, template.getLocation(), ImmutableMap
.<String, String> of(), template.getDescription(),
"", myOs, template.getName(), arch, credentialsProvider
.execute(template)));
return null;
}
}), executor));
@ -158,20 +162,19 @@ public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeSer
}
ConcurrentUtils.awaitCompletion(responses, executor, null, holder.logger, "vAppTemplates in "
+ vDC);
return Maps.uniqueIndex(images, indexer);
return images;
}
@Override
protected Map<String, ? extends Size> provideSizes(Function<ComputeMetadata, String> indexer,
VCloudClient client, Map<String, ? extends Image> images, LogHolder holder,
protected Set<? extends Size> provideSizes(Function<ComputeMetadata, String> indexer,
VCloudClient client, Set<? extends Image> images, LogHolder holder,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor)
throws InterruptedException, TimeoutException, ExecutionException {
Image anyImage = Iterables.get(images.values(), 0);
Image anyImage = Iterables.get(images, 0);
holder.logger.debug(">> providing sizes");
SortedSet<Size> sizes = Sets.newTreeSet(Iterables.transform(TerremarkVCloudClient.class.cast(
client).getComputeOptionsOfCatalogItem(anyImage.getId()), sizeConverter));
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 java.util.Map.Entry;
import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.domain.Architecture;
import org.jclouds.compute.domain.ComputeType;
@ -78,14 +76,13 @@ public class TerremarkVCloudComputeServiceLiveTest extends VCloudComputeServiceL
@Override
public void testListImages() throws Exception {
for (Entry<String, ? extends Image> image : client.getImages().entrySet()) {
assertEquals(image.getKey(), image.getValue().getId());
assert image.getValue().getId() != null : image;
// image.getValue().getLocationId() can be null, if it is a location-free image
assertEquals(image.getValue().getType(), ComputeType.IMAGE);
assert image.getValue().getDefaultCredentials().account != null : image;
if (image.getValue().getOsFamily() != OsFamily.WINDOWS)
assert image.getValue().getDefaultCredentials().key != null : image;
for (Image image : client.listImages()) {
assert image.getId() != null : image;
// image.getLocationId() can be null, if it is a location-free image
assertEquals(image.getType(), ComputeType.IMAGE);
assert image.getDefaultCredentials().account != null : image;
if (image.getOsFamily() != OsFamily.WINDOWS)
assert image.getDefaultCredentials().key != null : image;
}
}