diff --git a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/CloudServersImageExtension.java b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/CloudServersImageExtension.java index 2914789c53..0cffdb1d71 100644 --- a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/CloudServersImageExtension.java +++ b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/CloudServersImageExtension.java @@ -35,7 +35,6 @@ import javax.inject.Singleton; import org.jclouds.Constants; import org.jclouds.cloudservers.CloudServersClient; import org.jclouds.cloudservers.domain.Server; -import org.jclouds.cloudservers.options.ListOptions; import org.jclouds.compute.ImageExtension; import org.jclouds.compute.domain.CloneImageTemplate; import org.jclouds.compute.domain.Image; @@ -47,9 +46,6 @@ import org.jclouds.logging.Logger; import org.jclouds.predicates.PredicateWithResult; import org.jclouds.predicates.Retryables; -import com.google.common.base.Function; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; import com.google.common.util.concurrent.ListenableFuture; /** @@ -65,28 +61,28 @@ public class CloudServersImageExtension implements ImageExtension { @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; - private final CloudServersClient syncClient; + private final CloudServersClient client; private final ExecutorService executor; - private final Function cloudserversImageToImage; + private final PredicateWithResult imageAvailablePredicate; @com.google.inject.Inject(optional = true) @Named("IMAGE_MAX_WAIT") - long maxWait = 3600; + private long maxWait = 3600; @com.google.inject.Inject(optional = true) @Named("IMAGE_WAIT_PERIOD") - long waitPeriod = 1; + private long waitPeriod = 1; @Inject - public CloudServersImageExtension(CloudServersClient novaClient, + public CloudServersImageExtension(CloudServersClient client, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads, - Function cloudserversImageToImage) { - this.syncClient = checkNotNull(novaClient); + PredicateWithResult imageAvailablePredicate) { + this.client = checkNotNull(client); this.executor = userThreads; - this.cloudserversImageToImage = cloudserversImageToImage; + this.imageAvailablePredicate = imageAvailablePredicate; } @Override public ImageTemplate buildImageTemplateFromNode(String name, final String id) { - Server server = syncClient.getServer(Integer.parseInt(id)); + Server server = client.getServer(Integer.parseInt(id)); if (server == null) throw new NoSuchElementException("Cannot find server with id: " + id); CloneImageTemplate template = new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(name).build(); @@ -98,44 +94,14 @@ public class CloudServersImageExtension implements ImageExtension { checkState(template instanceof CloneImageTemplate, " openstack-nova only supports creating images through cloning."); CloneImageTemplate cloneTemplate = (CloneImageTemplate) template; - final org.jclouds.cloudservers.domain.Image image = syncClient.createImageFromServer(cloneTemplate.getName(), + final org.jclouds.cloudservers.domain.Image image = client.createImageFromServer(cloneTemplate.getName(), Integer.parseInt(cloneTemplate.getSourceNodeId())); return Futures.makeListenable(executor.submit(new Callable() { @Override public Image call() throws Exception { - return Retryables.retryGettingResultOrFailing(new PredicateWithResult() { - - org.jclouds.cloudservers.domain.Image result; - RuntimeException lastFailure; - - @Override - public boolean apply(Integer input) { - result = checkNotNull(findImage(input)); - switch (result.getStatus()) { - case ACTIVE: - logger.info("<< Image %s is available for use.", input); - return true; - case UNKNOWN: - case SAVING: - logger.debug("<< Image %s is not available yet.", input); - return false; - default: - lastFailure = new IllegalStateException("Image was not created: " + input); - throw lastFailure; - } - } - - @Override - public Image getResult() { - return cloudserversImageToImage.apply(image); - } - - @Override - public Throwable getLastFailure() { - return lastFailure; - } - }, image.getId(), maxWait, waitPeriod, TimeUnit.SECONDS, - "Image was not created within the time limit, Giving up! [Limit: " + maxWait + " secs.]"); + return Retryables.retryGettingResultOrFailing(imageAvailablePredicate, image.getId(), maxWait, waitPeriod, + TimeUnit.SECONDS, "Image was not created within the time limit, Giving up! [Limit: " + maxWait + + " secs.]"); } }), executor); @@ -144,22 +110,11 @@ public class CloudServersImageExtension implements ImageExtension { @Override public boolean deleteImage(String id) { try { - this.syncClient.deleteImage(Integer.parseInt(id)); + this.client.deleteImage(Integer.parseInt(id)); } catch (Exception e) { return false; } return true; } - private org.jclouds.cloudservers.domain.Image findImage(final int id) { - return Iterables.tryFind(syncClient.listImages(ListOptions.NONE), - new Predicate() { - @Override - public boolean apply(org.jclouds.cloudservers.domain.Image input) { - return input.getId() == id; - } - }).orNull(); - - } - } diff --git a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/config/CloudServersComputeServiceContextModule.java b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/config/CloudServersComputeServiceContextModule.java index 6375c15277..d40bbbe5ac 100644 --- a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/config/CloudServersComputeServiceContextModule.java +++ b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/config/CloudServersComputeServiceContextModule.java @@ -27,6 +27,7 @@ import org.jclouds.cloudservers.compute.functions.CloudServersImageToImage; import org.jclouds.cloudservers.compute.functions.CloudServersImageToOperatingSystem; import org.jclouds.cloudservers.compute.functions.FlavorToHardware; import org.jclouds.cloudservers.compute.functions.ServerToNodeMetadata; +import org.jclouds.cloudservers.compute.predicates.GetImageWhenStatusActivePredicateWithResult; import org.jclouds.cloudservers.compute.strategy.CloudServersComputeServiceAdapter; import org.jclouds.cloudservers.domain.Flavor; import org.jclouds.cloudservers.domain.Server; @@ -42,6 +43,7 @@ import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.internal.BaseComputeService; import org.jclouds.domain.Location; import org.jclouds.functions.IdentityFunction; +import org.jclouds.predicates.PredicateWithResult; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; @@ -84,6 +86,9 @@ public class CloudServersComputeServiceContextModule extends bind(new TypeLiteral() { }).to(CloudServersImageExtension.class); + + bind(new TypeLiteral>() { + }).to(GetImageWhenStatusActivePredicateWithResult.class); } diff --git a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/predicates/GetImageWhenStatusActivePredicateWithResult.java b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/predicates/GetImageWhenStatusActivePredicateWithResult.java new file mode 100644 index 0000000000..e4d1122f77 --- /dev/null +++ b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/predicates/GetImageWhenStatusActivePredicateWithResult.java @@ -0,0 +1,75 @@ +package org.jclouds.cloudservers.compute.predicates; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; + +import org.jclouds.cloudservers.CloudServersClient; +import org.jclouds.cloudservers.options.ListOptions; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.logging.Logger; +import org.jclouds.predicates.PredicateWithResult; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; + +public final class GetImageWhenStatusActivePredicateWithResult implements PredicateWithResult { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final CloudServersClient client; + private final Function cloudserversImageToImage; + private org.jclouds.cloudservers.domain.Image result; + private RuntimeException lastFailure; + + @Inject + public GetImageWhenStatusActivePredicateWithResult(CloudServersClient client, + Function cloudserversImageToImage) { + this.client = client; + this.cloudserversImageToImage = cloudserversImageToImage; + } + + @Override + public boolean apply(Integer input) { + result = checkNotNull(findImage(input)); + switch (result.getStatus()) { + case ACTIVE: + logger.info("<< Image %s is available for use.", input); + return true; + case QUEUED: + case SAVING: + logger.debug("<< Image %s is not available yet.", input); + return false; + default: + lastFailure = new IllegalStateException("Image was not created: " + input); + throw lastFailure; + } + } + + @Override + public Image getResult() { + return cloudserversImageToImage.apply(result); + } + + @Override + public Throwable getLastFailure() { + return lastFailure; + } + + private org.jclouds.cloudservers.domain.Image findImage(final int id) { + return Iterables.tryFind(client.listImages(new ListOptions().withDetails()), + new Predicate() { + @Override + public boolean apply(org.jclouds.cloudservers.domain.Image input) { + return input.getId() == id; + } + }).orNull(); + + } +} \ No newline at end of file diff --git a/apis/cloudservers/src/test/java/org/jclouds/cloudservers/compute/predicates/GetImageWhenStatusActivePredicateWithResultExpectTest.java b/apis/cloudservers/src/test/java/org/jclouds/cloudservers/compute/predicates/GetImageWhenStatusActivePredicateWithResultExpectTest.java new file mode 100644 index 0000000000..7ae0c636c3 --- /dev/null +++ b/apis/cloudservers/src/test/java/org/jclouds/cloudservers/compute/predicates/GetImageWhenStatusActivePredicateWithResultExpectTest.java @@ -0,0 +1,82 @@ +package org.jclouds.cloudservers.compute.predicates; + +import static junit.framework.Assert.assertTrue; +import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS; + +import java.net.URI; +import java.util.Map; +import java.util.Properties; + +import org.jclouds.apis.ApiMetadata; +import org.jclouds.cloudservers.CloudServersApiMetadata; +import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.compute.domain.Image; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.keystone.v1_1.internal.BaseKeystoneRestClientExpectTest; +import org.jclouds.predicates.PredicateWithResult; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.net.HttpHeaders; +import com.google.inject.Injector; +import com.google.inject.Module; + +@Test(groups = "unit", testName = "GetImageWhenStatusActivePredicateWithResultExpectTest") +public class GetImageWhenStatusActivePredicateWithResultExpectTest extends BaseKeystoneRestClientExpectTest + implements Function { + + private final HttpRequest listImagesDetail = HttpRequest + .builder() + .method("GET") + .endpoint(URI.create("https://lon.servers.api.rackspacecloud.com/v1.0/10001786/images/detail?format=json")) + .headers(ImmutableMultimap. builder().put("X-Auth-Token", authToken) + .put(HttpHeaders.ACCEPT, "application/json").build()).build(); + + private final HttpResponse listImagesResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/test_list_images_detail_imageextension.json")).build(); + + Map requestResponseMap = ImmutableMap. builder() + .put(initialAuth, responseWithAuth).put(listImagesDetail, listImagesResponse).build(); + + public GetImageWhenStatusActivePredicateWithResultExpectTest() { + provider = "cloudservers"; + } + + @Override + protected ApiMetadata createApiMetadata() { + return new CloudServersApiMetadata(); + } + + @Override + protected Properties setupProperties() { + Properties overrides = new Properties(); + overrides.setProperty(PROPERTY_REGIONS, "US"); + overrides.setProperty(provider + ".endpoint", endpoint); + return overrides; + } + + @Override + public Injector createClient(Function fn, Module module, Properties props) { + return apply(createComputeServiceContext(fn, module, props)); + } + + private ComputeServiceContext createComputeServiceContext(Function fn, Module module, + Properties props) { + return createInjector(fn, module, props).getInstance(ComputeServiceContext.class); + } + + @Override + public Injector apply(ComputeServiceContext input) { + return input.utils().injector(); + } + + public void testReturnsFalseOnQueuedAndSavingAndTrueOnActive() { + Injector injector = requestsSendResponses(requestResponseMap); + PredicateWithResult predicate = injector + .getInstance(GetImageWhenStatusActivePredicateWithResult.class); + assertTrue(predicate.apply(2)); + } +} diff --git a/apis/cloudservers/src/test/resources/test_list_images_detail_imageextension.json b/apis/cloudservers/src/test/resources/test_list_images_detail_imageextension.json new file mode 100644 index 0000000000..af18ac6233 --- /dev/null +++ b/apis/cloudservers/src/test/resources/test_list_images_detail_imageextension.json @@ -0,0 +1,60 @@ +{ + "images" : [ + { + "id" : 2, + "name" : "CentOS 5.2", + "updated" : "2010-10-10T12:00:00Z", + "created" : "2010-08-10T12:00:00Z", + "status" : "ACTIVE" + }, + { + "id" : 743, + "name" : "My Server Backup1", + "serverId" : 12, + "updated" : "2010-10-10T12:00:00Z", + "created" : "2009-07-07T09:56:16-05:00", + "status" : "SAVING", + "progress" : 80 + } + { + "id" : 744, + "name" : "My Server Backup2", + "serverId" : 12, + "updated" : "2010-10-10T12:00:00Z", + "created" : "2009-07-07T09:56:16-05:00", + "status" : "UNRECOGNIZED", + } + { + "id" : 745, + "name" : "My Server Backup3", + "serverId" : 12, + "updated" : "2010-10-10T12:00:00Z", + "created" : "2009-07-07T09:56:16-05:00", + "status" : "UNKNOWN", + } + { + "id" : 746, + "name" : "My Server Backup4", + "serverId" : 12, + "updated" : "2010-10-10T12:00:00Z", + "created" : "2009-07-07T09:56:16-05:00", + "status" : "PREPARING", + } + { + "id" : 747, + "name" : "My Server Backup5", + "serverId" : 12, + "updated" : "2010-10-10T12:00:00Z", + "created" : "2009-07-07T09:56:16-05:00", + "status" : "QUEUED", + } + { + "id" : 748, + "name" : "My Server Backup6", + "serverId" : 12, + "updated" : "2010-10-10T12:00:00Z", + "created" : "2009-07-07T09:56:16-05:00", + "status" : "FAILED", + } + ] +} diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ImageExtension.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ImageExtension.java index 2dc958b934..276fb230a4 100644 --- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ImageExtension.java +++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ImageExtension.java @@ -41,16 +41,13 @@ import org.jclouds.compute.domain.ImageTemplateBuilder; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.concurrent.Futures; import org.jclouds.ec2.EC2Client; -import org.jclouds.ec2.compute.functions.EC2ImageParser; import org.jclouds.ec2.domain.Reservation; import org.jclouds.ec2.domain.RunningInstance; import org.jclouds.ec2.options.CreateImageOptions; -import org.jclouds.ec2.options.DescribeImagesOptions; import org.jclouds.logging.Logger; import org.jclouds.predicates.PredicateWithResult; import org.jclouds.predicates.Retryables; -import com.google.common.base.Function; import com.google.common.collect.Iterables; import com.google.common.util.concurrent.ListenableFuture; @@ -66,23 +63,22 @@ public class EC2ImageExtension implements ImageExtension { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; - - @com.google.inject.Inject(optional = true) - @Named("IMAGE_MAX_WAIT") - long maxWait = 3600; - @com.google.inject.Inject(optional = true) - @Named("IMAGE_WAIT_PERIOD") - long waitPeriod = 1; private final EC2Client ec2Client; private final ExecutorService executor; - private final Function ecImageToImage; + private final PredicateWithResult imageReadyPredicate; + @com.google.inject.Inject(optional = true) + @Named("IMAGE_MAX_WAIT") + private long maxWait = 3600; + @com.google.inject.Inject(optional = true) + @Named("IMAGE_WAIT_PERIOD") + private long waitPeriod = 1; @Inject public EC2ImageExtension(EC2Client ec2Client, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads, - EC2ImageParser ec2ImageToImage) { + PredicateWithResult imageReadyPredicate) { this.ec2Client = checkNotNull(ec2Client); this.executor = checkNotNull(userThreads); - this.ecImageToImage = checkNotNull(ec2ImageToImage); + this.imageReadyPredicate = imageReadyPredicate; } @Override @@ -112,38 +108,9 @@ public class EC2ImageExtension implements ImageExtension { return Futures.makeListenable(executor.submit(new Callable() { @Override public Image call() throws Exception { - return Retryables.retryGettingResultOrFailing(new PredicateWithResult() { - - org.jclouds.ec2.domain.Image result; - RuntimeException lastFailure; - - @Override - public boolean apply(String input) { - result = checkNotNull(findImage(region, input)); - switch (result.getImageState()) { - case AVAILABLE: - logger.info("<< Image %s is available for use.", input); - return true; - case UNRECOGNIZED: - logger.debug("<< Image %s is not available yet.", input); - return false; - default: - lastFailure = new IllegalStateException("Image was not created: " + input); - throw lastFailure; - } - } - - @Override - public Image getResult() { - return ecImageToImage.apply(result); - } - - @Override - public Throwable getLastFailure() { - return lastFailure; - } - }, imageId, maxWait, waitPeriod, TimeUnit.SECONDS, - "Image was not created within the time limit, Giving up! [Limit: " + maxWait + " secs.]"); + return Retryables.retryGettingResultOrFailing(imageReadyPredicate, imageId, maxWait, waitPeriod, + TimeUnit.SECONDS, "Image was not created within the time limit, Giving up! [Limit: " + maxWait + + " secs.]"); } }), executor); } @@ -161,9 +128,4 @@ public class EC2ImageExtension implements ImageExtension { } } - private org.jclouds.ec2.domain.Image findImage(String region, String id) { - return Iterables.getOnlyElement(ec2Client.getAMIServices().describeImagesInRegion(region, - new DescribeImagesOptions().imageIds(id))); - - } } diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/GetImageWhenStatusAvailablePredicateWithResult.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/GetImageWhenStatusAvailablePredicateWithResult.java new file mode 100644 index 0000000000..8db7a7067c --- /dev/null +++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/GetImageWhenStatusAvailablePredicateWithResult.java @@ -0,0 +1,68 @@ +package org.jclouds.ec2.compute.predicates; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Resource; +import javax.inject.Named; + +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.ec2.EC2Client; +import org.jclouds.ec2.compute.functions.EC2ImageParser; +import org.jclouds.ec2.options.DescribeImagesOptions; +import org.jclouds.logging.Logger; +import org.jclouds.predicates.PredicateWithResult; + +import com.google.common.collect.Iterables; + +public final class GetImageWhenStatusAvailablePredicateWithResult implements PredicateWithResult { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + private final String region; + private final EC2Client ec2Client; + private final EC2ImageParser ec2ImageToImage; + private org.jclouds.ec2.domain.Image result; + private RuntimeException lastFailure; + + public GetImageWhenStatusAvailablePredicateWithResult(EC2Client ec2Client, EC2ImageParser ec2ImageToImage, + String region) { + this.region = region; + this.ec2Client = ec2Client; + this.ec2ImageToImage = ec2ImageToImage; + } + + @Override + public boolean apply(String input) { + result = checkNotNull(findImage(input)); + switch (result.getImageState()) { + case AVAILABLE: + logger.info("<< Image %s is available for use.", input); + return true; + case UNRECOGNIZED: + logger.debug("<< Image %s is not available yet.", input); + return false; + default: + lastFailure = new IllegalStateException("Image was not created: " + input); + throw lastFailure; + } + } + + @Override + public Image getResult() { + return ec2ImageToImage.apply(result); + } + + @Override + public Throwable getLastFailure() { + return lastFailure; + } + + private org.jclouds.ec2.domain.Image findImage(String id) { + return Iterables.getOnlyElement(ec2Client.getAMIServices().describeImagesInRegion(region, + new DescribeImagesOptions().imageIds(id))); + + } +} \ No newline at end of file diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/compute/NovaImageExtension.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/compute/NovaImageExtension.java index d9c6dfe28f..900a2d4547 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/compute/NovaImageExtension.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/compute/NovaImageExtension.java @@ -47,8 +47,6 @@ import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndId; import org.jclouds.predicates.PredicateWithResult; import org.jclouds.predicates.Retryables; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; import com.google.common.util.concurrent.ListenableFuture; @Singleton @@ -122,15 +120,4 @@ public class NovaImageExtension implements ImageExtension { return true; } - public static org.jclouds.openstack.nova.v1_1.domain.Image findImage(NovaClient novaClient, final ZoneAndId zoneAndId) { - return Iterables.tryFind(novaClient.getImageClientForZone(zoneAndId.getZone()).listImagesInDetail(), - new Predicate() { - @Override - public boolean apply(org.jclouds.openstack.nova.v1_1.domain.Image input) { - return input.getId().equals(zoneAndId.getId()); - } - }).orNull(); - - } - } diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/compute/predicates/GetImageWhenImageInZoneHasActiveStatusPredicateWithResult.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/compute/predicates/GetImageWhenImageInZoneHasActiveStatusPredicateWithResult.java index 2ca35ad10d..fb8f73e83e 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/compute/predicates/GetImageWhenImageInZoneHasActiveStatusPredicateWithResult.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/compute/predicates/GetImageWhenImageInZoneHasActiveStatusPredicateWithResult.java @@ -29,12 +29,13 @@ import org.jclouds.compute.domain.Image; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.logging.Logger; import org.jclouds.openstack.nova.v1_1.NovaClient; -import org.jclouds.openstack.nova.v1_1.compute.NovaImageExtension; import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ImageInZone; import org.jclouds.openstack.nova.v1_1.domain.zonescoped.ZoneAndId; import org.jclouds.predicates.PredicateWithResult; import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; /** * @author David Alves @@ -61,8 +62,7 @@ public final class GetImageWhenImageInZoneHasActiveStatusPredicateWithResult imp @Override public boolean apply(ZoneAndId input) { - result = checkNotNull(NovaImageExtension.findImage(client, - ZoneAndId.fromZoneAndId(input.getZone(), input.getId()))); + result = checkNotNull(findImage(ZoneAndId.fromZoneAndId(input.getZone(), input.getId()))); resultZoneAndId = input; switch (result.getStatus()) { case ACTIVE: @@ -86,4 +86,15 @@ public final class GetImageWhenImageInZoneHasActiveStatusPredicateWithResult imp public Throwable getLastFailure() { return lastFailure; } + + public org.jclouds.openstack.nova.v1_1.domain.Image findImage(final ZoneAndId zoneAndId) { + return Iterables.tryFind(client.getImageClientForZone(zoneAndId.getZone()).listImagesInDetail(), + new Predicate() { + @Override + public boolean apply(org.jclouds.openstack.nova.v1_1.domain.Image input) { + return input.getId().equals(zoneAndId.getId()); + } + }).orNull(); + + } } \ No newline at end of file