Source:
<code>public ListenableFuture<Image> createImage(ImageTemplate template) { checkState(template instanceof CloneImageTemplate, " cloudstack only currently supports creating images through cloning."); CloneImageTemplate cloneTemplate = (CloneImageTemplate) template; DataCenterAndId datacenterAndId = DataCenterAndId.fromSlashEncoded(cloneTemplate.getSourceNodeId()); Server server = client.serverApi().getServer(datacenterAndId.getDataCenter(), datacenterAndId.getId()); List<Volume> volumes = client.volumeApi().getList(server.dataCenterId()); Volume volume = Iterables.getOnlyElement(volumes); <START> Snapshot snapshot = client.volumeApi().createSnapshot(Volume.Request.createSnapshotBuilder() <END> .dataCenterId(datacenterAndId.getDataCenter()) .volumeId(volume.id()) .name(cloneTemplate.getName()) .description(cloneTemplate.getName()) .build()); trackables.waitUntilRequestCompleted(snapshot); logger.info(">> Registered new template %s, waiting for it to become available.", snapshot.id()); final Image image = new ImageBuilder() .location(find(locations.get(), idEquals(snapshot.properties().location().getId()))) .id(snapshot.id()) .providerId(snapshot.id()) .name(cloneTemplate.getName()) .description(cloneTemplate.getName()) .operatingSystem(OperatingSystem.builder().description(cloneTemplate.getName()).build()) .status(Image.Status.PENDING).build(); return userExecutor.submit(new Callable<Image>() { @Override public Image call() throws Exception { if (snapshotAvailablePredicate.apply(image.getId())) { return image; } throw new UncheckedTimeoutException("Image was not created within the time limit: " + image); } }); }</code><technical_language>wrap volume snapshot creation future, this method return early. If returns a future, then, do job create snapshot asynchronously. operations get server volume ok future, validation if fail synchronously if preconditions met</technical_language>

Target:
public ListenableFuture<Image> createImage(ImageTemplate template) { final CloneImageTemplate cloneTemplate = (CloneImageTemplate) template; final DataCenterAndId datacenterAndId = DataCenterAndId.fromSlashEncoded(cloneTemplate.getSourceNodeId()); final Server server = client.serverApi().getServer(datacenterAndId.getDataCenter(), datacenterAndId.getId()); List<Volume> volumes = client.volumeApi().getList(server.dataCenterId()); final Volume volume = Iterables.getOnlyElement(volumes); return userExecutor.submit(new Callable<Image>() { @Override public Image call() throws Exception { Snapshot snapshot = client.volumeApi().createSnapshot(Volume.Request.createSnapshotBuilder() .dataCenterId(datacenterAndId.getDataCenter()) .volumeId(volume.id()) .name(cloneTemplate.getName()) .description(cloneTemplate.getName()) .build()); trackables.waitUntilRequestCompleted(snapshot); logger.info(">> Registered new snapshot %s, waiting for it to become available.", snapshot.id()); final Image image = new ImageBuilder() .location(find(locations.get(), idEquals(snapshot.properties().location().getId()))) .id(snapshot.id()) .providerId(snapshot.id()) .name(cloneTemplate.getName()) .description(cloneTemplate.getName()) .operatingSystem(OperatingSystem.builder().description(cloneTemplate.getName()).build()) .status(Image.Status.PENDING).build(); if (snapshotAvailablePredicate.apply(image.getId())) { return image; } throw new UncheckedTimeoutException("Image was not created within the time limit: " + image); } }); }