diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VolumeAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VolumeAsyncClient.java index 28271b08f6..3f7a6d0a72 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VolumeAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VolumeAsyncClient.java @@ -29,12 +29,9 @@ import org.jclouds.cloudstack.domain.AsyncCreateResponse; import org.jclouds.cloudstack.domain.Volume; import org.jclouds.cloudstack.filters.QuerySigner; import org.jclouds.cloudstack.options.ListVolumesOptions; -import org.jclouds.rest.annotations.ExceptionParser; -import org.jclouds.rest.annotations.QueryParams; -import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.Unwrap; +import org.jclouds.rest.annotations.*; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; /** @@ -58,6 +55,17 @@ public interface VolumeAsyncClient { @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) ListenableFuture> listVolumes(ListVolumesOptions... options); + /** + * @see VolumeClient#getVolume(long) + */ + @GET + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "command", values = "listVolumes") + @SelectJson("volume") + @OnlyElement + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getVolume(@QueryParam("id") long id); + /** * @see VolumeClient#createVolumeFromDiskOfferingInZone(String, long, long) diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VolumeClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VolumeClient.java index 2a71a3b605..f0d57f3bac 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VolumeClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/VolumeClient.java @@ -59,10 +59,18 @@ public interface VolumeClient { /** * List volumes * - * @return volume list or null if not found + * @return volume list, empty if not found */ Set listVolumes(ListVolumesOptions... options); + /** + * Get volume by id + * + * @param id the volume id to retrieve + * @return volume or null if not found + */ + Volume getVolume(long id); + /** * Deletes a attached disk volume * diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeClientLiveTest.java index a9e5c4ebc9..50e4d0ad9e 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VolumeClientLiveTest.java @@ -23,16 +23,20 @@ import static org.testng.AssertJUnit.*; import java.util.Set; +import com.google.common.base.Function; import org.jclouds.cloudstack.domain.AsyncCreateResponse; import org.jclouds.cloudstack.domain.Snapshot; import org.jclouds.cloudstack.domain.Volume; import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.cloudstack.options.ListVolumesOptions; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; +import javax.annotation.Nullable; + /** * Tests behavior of {@code VolumeClient} * @@ -53,12 +57,57 @@ public class VolumeClientLiveTest extends BaseCloudStackClientLiveTest { } public void testListVolumes() { - final Set volumes = client.getVolumeClient().listVolumes(); + Set volumes = client.getVolumeClient().listVolumes(); + assertNotNull(volumes); + assertFalse(volumes.isEmpty()); + for (Volume volume : volumes) { checkVolume(volume); } } + public void testListVolumesById() { + Iterable volumeIds = Iterables.transform(client.getVolumeClient().listVolumes(), new Function() { + public Long apply(Volume input) { + return input.getId(); + } + }); + assertNotNull(volumeIds); + assertFalse(Iterables.isEmpty(volumeIds)); + + for (Long id : volumeIds) { + Set found = client.getVolumeClient().listVolumes(ListVolumesOptions.Builder.id(id)); + assertNotNull(found); + assertEquals(1, found.size()); + Volume volume = Iterables.getOnlyElement(found); + assertEquals(id.longValue(), volume.getId()); + checkVolume(volume); + } + } + + public void testListVolumesNonexistantId() { + Set found = client.getVolumeClient().listVolumes(ListVolumesOptions.Builder.id(-1)); + assertNotNull(found); + assertTrue(found.isEmpty()); + } + + public void testGetVolumeById() { + Iterable volumeIds = Iterables.transform(client.getVolumeClient().listVolumes(), new Function() { + public Long apply(Volume input) { + return input.getId(); + } + }); + assertNotNull(volumeIds); + assertFalse(Iterables.isEmpty(volumeIds)); + + for (Long id : volumeIds) { + Volume found = client.getVolumeClient().getVolume(id); + assertNotNull(found); + assertEquals(id.longValue(), found.getId()); + checkVolume(found); + } + } + public void testCreateVolumeFromDiskofferingInZoneAndDeleteVolume() { // Pick some disk offering long diskOfferingId = Iterables.get(client.getOfferingClient().listDiskOfferings(), 0).getId();