mirror of https://github.com/apache/jclouds.git
Improved DigitalOcean image extension
Do not block when waiting for the images to become available.
This commit is contained in:
parent
62f1c0bc9a
commit
c188570444
|
@ -17,17 +17,18 @@
|
||||||
package org.jclouds.digitalocean2.compute.extensions;
|
package org.jclouds.digitalocean2.compute.extensions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
|
||||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
|
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE;
|
||||||
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
|
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
|
||||||
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.compute.domain.CloneImageTemplate;
|
import org.jclouds.compute.domain.CloneImageTemplate;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.ImageTemplate;
|
import org.jclouds.compute.domain.ImageTemplate;
|
||||||
|
@ -45,6 +46,8 @@ import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.common.util.concurrent.UncheckedTimeoutException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link org.jclouds.compute.extensions.ImageExtension} implementation for the DigitalOcean provider.
|
* The {@link org.jclouds.compute.extensions.ImageExtension} implementation for the DigitalOcean provider.
|
||||||
|
@ -60,15 +63,18 @@ public class DigitalOcean2ImageExtension implements ImageExtension {
|
||||||
private final Predicate<Integer> imageAvailablePredicate;
|
private final Predicate<Integer> imageAvailablePredicate;
|
||||||
private final Predicate<Integer> nodeStoppedPredicate;
|
private final Predicate<Integer> nodeStoppedPredicate;
|
||||||
private final Function<ImageInRegion, Image> imageTransformer;
|
private final Function<ImageInRegion, Image> imageTransformer;
|
||||||
|
private final ListeningExecutorService userExecutor;
|
||||||
|
|
||||||
@Inject DigitalOcean2ImageExtension(DigitalOcean2Api api,
|
@Inject DigitalOcean2ImageExtension(DigitalOcean2Api api,
|
||||||
@Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<Integer> imageAvailablePredicate,
|
@Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<Integer> imageAvailablePredicate,
|
||||||
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<Integer> nodeStoppedPredicate,
|
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<Integer> nodeStoppedPredicate,
|
||||||
Function<ImageInRegion, Image> imageTransformer) {
|
Function<ImageInRegion, Image> imageTransformer,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
|
||||||
this.api = api;
|
this.api = api;
|
||||||
this.imageAvailablePredicate = imageAvailablePredicate;
|
this.imageAvailablePredicate = imageAvailablePredicate;
|
||||||
this.nodeStoppedPredicate = nodeStoppedPredicate;
|
this.nodeStoppedPredicate = nodeStoppedPredicate;
|
||||||
this.imageTransformer = imageTransformer;
|
this.imageTransformer = imageTransformer;
|
||||||
|
this.userExecutor = userExecutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -89,31 +95,36 @@ public class DigitalOcean2ImageExtension implements ImageExtension {
|
||||||
int dropletId = Integer.parseInt(cloneTemplate.getSourceNodeId());
|
int dropletId = Integer.parseInt(cloneTemplate.getSourceNodeId());
|
||||||
|
|
||||||
// Droplet needs to be stopped
|
// Droplet needs to be stopped
|
||||||
Droplet droplet = api.dropletApi().get(dropletId);
|
final Droplet droplet = api.dropletApi().get(dropletId);
|
||||||
if (droplet.status() != Status.OFF) {
|
if (droplet.status() != Status.OFF) {
|
||||||
api.dropletApi().powerOff(dropletId);
|
api.dropletApi().powerOff(dropletId);
|
||||||
checkState(nodeStoppedPredicate.apply(dropletId), "node was not powered off in the configured timeout");
|
checkState(nodeStoppedPredicate.apply(dropletId), "node was not powered off in the configured timeout");
|
||||||
}
|
}
|
||||||
|
|
||||||
Action snapshotEvent = api.dropletApi().snapshot(Integer.parseInt(cloneTemplate.getSourceNodeId()),
|
final Action snapshotEvent = api.dropletApi().snapshot(Integer.parseInt(cloneTemplate.getSourceNodeId()),
|
||||||
cloneTemplate.getName());
|
cloneTemplate.getName());
|
||||||
|
|
||||||
logger.info(">> registered new Image, waiting for it to become available");
|
logger.info(">> registered new Image, waiting for it to become available");
|
||||||
|
|
||||||
// Until the process completes we don't have enough information to build an image to return
|
return userExecutor.submit(new Callable<Image>() {
|
||||||
checkState(imageAvailablePredicate.apply(snapshotEvent.id()),
|
@Override
|
||||||
"snapshot failed to complete in the configured timeout");
|
public Image call() throws Exception {
|
||||||
|
if (imageAvailablePredicate.apply(snapshotEvent.id())) {
|
||||||
org.jclouds.digitalocean2.domain.Image snapshot = api.imageApi().list().concat().firstMatch(
|
org.jclouds.digitalocean2.domain.Image snapshot = api.imageApi().list().concat()
|
||||||
new Predicate<org.jclouds.digitalocean2.domain.Image>() {
|
.firstMatch(new Predicate<org.jclouds.digitalocean2.domain.Image>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(org.jclouds.digitalocean2.domain.Image input) {
|
public boolean apply(org.jclouds.digitalocean2.domain.Image input) {
|
||||||
return input.name().equals(cloneTemplate.getName());
|
return input.name().equals(cloneTemplate.getName());
|
||||||
}
|
}
|
||||||
}).get();
|
}).get();
|
||||||
|
|
||||||
// By default snapshots are only available in the Droplet's region
|
return imageTransformer.apply(ImageInRegion.create(snapshot, droplet.region().slug()));
|
||||||
return immediateFuture(imageTransformer.apply(ImageInRegion.create(snapshot, droplet.region().slug())));
|
}
|
||||||
|
|
||||||
|
throw new UncheckedTimeoutException("Image was not created within the time limit: "
|
||||||
|
+ cloneTemplate.getName());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue