diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/NovaApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/NovaApi.java index b03727eede..65764b80e6 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/NovaApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/NovaApi.java @@ -21,7 +21,7 @@ import java.util.Set; import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.Zone; import org.jclouds.location.functions.ZoneToEndpoint; -import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneAPI; +import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneApi; import org.jclouds.openstack.nova.v2_0.extensions.FlavorExtraSpecsApi; import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi; import org.jclouds.openstack.nova.v2_0.extensions.HostAdministrationApi; @@ -69,7 +69,7 @@ public interface NovaApi extends Closeable { * Provides synchronous access to availability zone features */ @Delegate - AvailabilityZoneAPI getAvailabilityZoneApi( + Optional getAvailabilityZoneApi( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); /** diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/NovaAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/NovaAsyncApi.java index 9abea53124..e1d624efe2 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/NovaAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/NovaAsyncApi.java @@ -22,7 +22,7 @@ import java.util.Set; import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.Zone; import org.jclouds.location.functions.ZoneToEndpoint; -import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneAPI; +import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneAsyncApi; import org.jclouds.openstack.nova.v2_0.extensions.FlavorExtraSpecsAsyncApi; import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPAsyncApi; import org.jclouds.openstack.nova.v2_0.extensions.HostAdministrationAsyncApi; @@ -74,7 +74,7 @@ public interface NovaAsyncApi extends Closeable { * Provides asynchronous access to availability zone features */ @Delegate - AvailabilityZoneAPI getAvailabilityZoneApi( + Optional getAvailabilityZoneApi( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); /** diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaRestClientModule.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaRestClientModule.java index 556ec60b3a..cd6e8d3ef6 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaRestClientModule.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/config/NovaRestClientModule.java @@ -31,7 +31,7 @@ import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; import org.jclouds.openstack.nova.v2_0.NovaApi; import org.jclouds.openstack.nova.v2_0.NovaAsyncApi; -import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneAPI; +import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneApi; import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneAsyncApi; import org.jclouds.openstack.nova.v2_0.extensions.ExtensionNamespaces; import org.jclouds.openstack.nova.v2_0.extensions.FlavorExtraSpecsApi; @@ -102,7 +102,7 @@ public class NovaRestClientModule ext .put(ImageApi.class, ImageAsyncApi.class) .put(ExtensionApi.class, ExtensionAsyncApi.class) .put(FloatingIPApi.class, FloatingIPAsyncApi.class) - .put(AvailabilityZoneAPI.class, AvailabilityZoneAsyncApi.class) + .put(AvailabilityZoneApi.class, AvailabilityZoneAsyncApi.class) .put(SecurityGroupApi.class, SecurityGroupAsyncApi.class) .put(KeyPairApi.class, KeyPairAsyncApi.class) .put(HostAdministrationApi.class, HostAdministrationAsyncApi.class) @@ -167,6 +167,8 @@ public class NovaRestClientModule ext URI.create("http://docs.openstack.org/compute/ext/quota-classes-sets/api/v1.1")) .put(URI.create(ExtensionNamespaces.VOLUME_TYPES), URI.create("http://docs.openstack.org/compute/ext/volume_types/api/v1.1")) + .put(URI.create(ExtensionNamespaces.AVAILABILITY_ZONE), + URI.create("http://docs.openstack.org/compute/ext/availabilityzone/api/v1.1")) .build(); } diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneAPI.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneApi.java similarity index 95% rename from apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneAPI.java rename to apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneApi.java index d248681f18..59c3c178c8 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneAPI.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneApi.java @@ -29,8 +29,8 @@ import org.jclouds.openstack.v2_0.services.Extension; * @author Inbar Stolberg */ @Beta -@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.ADMIN_ACTIONS) -public interface AvailabilityZoneAPI { +@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.AVAILABILITY_ZONE) +public interface AvailabilityZoneApi { /** * @return all availability zones diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneAsyncApi.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneAsyncApi.java index d85f305976..5ac77960a6 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneAsyncApi.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneAsyncApi.java @@ -41,7 +41,7 @@ import javax.ws.rs.core.MediaType; */ @Beta -@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.ADMIN_ACTIONS) +@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.AVAILABILITY_ZONE) @RequestFilters(AuthenticateRequest.class) public interface AvailabilityZoneAsyncApi { diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ExtensionNamespaces.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ExtensionNamespaces.java index a249190882..37dde535f4 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ExtensionNamespaces.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/ExtensionNamespaces.java @@ -67,6 +67,10 @@ public interface ExtensionNamespaces { * Virtual interface support */ public static final String VIRTUAL_INTERFACES = "http://docs.openstack.org/ext/virtual_interfaces/api/v1.1"; + /** + * Availability zone extensions + */ + public static final String AVAILABILITY_ZONE = "http://docs.openstack.org/compute/ext/availabilityzone/api/v1.1"; /** * Extended support to the Create Server v1.1 API */ diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneApiExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneApiExpectTest.java index f033a1b266..7ca5b84ee0 100644 --- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneApiExpectTest.java +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneApiExpectTest.java @@ -37,7 +37,7 @@ import static org.testng.Assert.assertTrue; @Test(groups = "unit", testName = "AvailabilityZoneApiExpectTest") public class AvailabilityZoneApiExpectTest extends BaseNovaApiExpectTest { - public void testLAvailabilityZonesList() throws Exception { + public void testAvailabilityZonesList() throws Exception { HttpRequest list = HttpRequest .builder() .method("GET") @@ -53,7 +53,7 @@ public class AvailabilityZoneApiExpectTest extends BaseNovaApiExpectTest { assertEquals(availabilityZonesApi.getConfiguredZones(), ImmutableSet.of("az-1.region-a.geo-1", "az-2.region-a.geo-1", "az-3.region-a.geo-1")); - FluentIterable zones = availabilityZonesApi.getAvailabilityZoneApi("az-1.region-a.geo-1").list(); + FluentIterable zones = availabilityZonesApi.getAvailabilityZoneApi("az-1.region-a.geo-1").get().list(); Optional zone = zones.first(); diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZonesApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZonesApiLiveTest.java index a7ad44f3f3..4c930dc7d3 100644 --- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZonesApiLiveTest.java +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZonesApiLiveTest.java @@ -18,6 +18,7 @@ */ package org.jclouds.openstack.nova.v2_0.extensions; +import com.google.common.base.Optional; import com.google.common.collect.FluentIterable; import org.jclouds.openstack.nova.v2_0.domain.zonescoped.AvailabilityZone; import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiLiveTest; @@ -34,12 +35,14 @@ public class AvailabilityZonesApiLiveTest extends BaseNovaApiLiveTest { @Test public void testListAvailabilityZones() throws Exception { - AvailabilityZoneAPI availabilityZoneApi = api.getAvailabilityZoneApi("RegionOne"); - FluentIterable zones = availabilityZoneApi.list(); + Optional availabilityZoneApi = api.getAvailabilityZoneApi("RegionOne"); + if (availabilityZoneApi.isPresent()) { + FluentIterable zones = availabilityZoneApi.get().list(); - for (AvailabilityZone zone : zones) { - assertNotNull(zone.getName()); - assertTrue(zone.getState().available(), "zone: " + zone.getName() + " is not available."); + for (AvailabilityZone zone : zones) { + assertNotNull(zone.getName()); + assertTrue(zone.getState().available(), "zone: " + zone.getName() + " is not available."); + } } } } diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApiLiveTest.java index a7f14ad216..3ef4a29c88 100644 --- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApiLiveTest.java +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/VolumeApiLiveTest.java @@ -27,6 +27,7 @@ import org.jclouds.openstack.nova.v2_0.domain.Volume; import org.jclouds.openstack.nova.v2_0.domain.VolumeAttachment; import org.jclouds.openstack.nova.v2_0.domain.VolumeSnapshot; import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiLiveTest; +import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions; import org.jclouds.openstack.nova.v2_0.options.CreateVolumeOptions; import org.jclouds.openstack.nova.v2_0.options.CreateVolumeSnapshotOptions; import org.testng.annotations.AfterClass; @@ -48,6 +49,7 @@ public class VolumeApiLiveTest extends BaseNovaApiLiveTest { private Optional volumeOption; private String zone; + private String availabilityZone; private Volume testVolume; private VolumeSnapshot testSnapshot; @@ -58,6 +60,9 @@ public class VolumeApiLiveTest extends BaseNovaApiLiveTest { super.setup(); zone = Iterables.getLast(api.getConfiguredZones(), "nova"); volumeOption = api.getVolumeExtensionForZone(zone); + + Optional availabilityZoneApi = api.getAvailabilityZoneApi(zone); + availabilityZone = availabilityZoneApi.isPresent() ? Iterables.getLast(availabilityZoneApi.get().list()).getName() : zone; } @AfterClass(groups = { "integration", "live" }) @@ -91,7 +96,7 @@ public class VolumeApiLiveTest extends BaseNovaApiLiveTest { testVolume = volumeOption.get().create( 1, CreateVolumeOptions.Builder.name("jclouds-test-volume").description("description of test volume") - .availabilityZone(zone)); + .availabilityZone(availabilityZone)); assertTrue(retry(new Predicate() { public boolean apply(VolumeApi volumeApi) { return volumeOption.get().get(testVolume.getId()).getStatus() == Volume.Status.AVAILABLE; @@ -217,7 +222,8 @@ public class VolumeApiLiveTest extends BaseNovaApiLiveTest { if (volumeOption.isPresent()) { String server_id = null; try { - final String serverId = server_id = createServerInZone(zone).getId(); + CreateServerOptions createServerOptions = CreateServerOptions.Builder.availabilityZone(availabilityZone); + final String serverId = server_id = createServerInZone(zone, createServerOptions).getId(); Set attachments = volumeOption.get().listAttachmentsOnServer(serverId).toSet(); assertNotNull(attachments); @@ -238,7 +244,11 @@ public class VolumeApiLiveTest extends BaseNovaApiLiveTest { assertNotNull(attachments); assertEquals(attachments.size(), before + 1); - assertEquals(volumeOption.get().get(testVolume.getId()).getStatus(), Volume.Status.IN_USE); + assertTrue(retry(new Predicate() { + public boolean apply(VolumeApi volumeApi) { + return volumeApi.get(testVolume.getId()).getStatus() == Volume.Status.IN_USE; + } + }, 30 * 1000L).apply(volumeOption.get()), "Volume status did not show in-use after 30 seconds"); boolean foundIt = false; for (VolumeAttachment att : attachments) { diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ServerApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ServerApiLiveTest.java index 7e406d11a9..059e240a7d 100644 --- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ServerApiLiveTest.java +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/features/ServerApiLiveTest.java @@ -23,10 +23,12 @@ import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; +import com.google.common.base.Optional; import org.jclouds.http.HttpResponseException; import org.jclouds.openstack.nova.v2_0.domain.Network; import org.jclouds.openstack.nova.v2_0.domain.Server; import org.jclouds.openstack.nova.v2_0.domain.ServerCreated; +import org.jclouds.openstack.nova.v2_0.extensions.AvailabilityZoneApi; import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiLiveTest; import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions; import org.jclouds.openstack.nova.v2_0.options.RebuildServerOptions; @@ -84,10 +86,14 @@ public class ServerApiLiveTest extends BaseNovaApiLiveTest { @Test public void testCreateInAvailabilityZone() { String serverId = null; + String availabilityZone; + for (String zoneId : zones) { ServerApi serverApi = api.getServerApiForZone(zoneId); + Optional availabilityZoneApi = api.getAvailabilityZoneApi(zoneId); + availabilityZone = availabilityZoneApi.isPresent() ? Iterables.getLast(availabilityZoneApi.get().list()).getName() : "nova"; try { - serverId = createServer(zoneId, "nova").getId(); + serverId = createServer(zoneId, availabilityZone).getId(); Server server = serverApi.get(serverId); assertEquals(server.getStatus(), ACTIVE); } finally { diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/internal/BaseNovaApiLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/internal/BaseNovaApiLiveTest.java index fd8ad6fd9d..78f5ff3ccd 100644 --- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/internal/BaseNovaApiLiveTest.java +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/internal/BaseNovaApiLiveTest.java @@ -31,6 +31,7 @@ import org.jclouds.openstack.nova.v2_0.domain.ServerCreated; import org.jclouds.openstack.nova.v2_0.features.FlavorApi; import org.jclouds.openstack.nova.v2_0.features.ImageApi; import org.jclouds.openstack.nova.v2_0.features.ServerApi; +import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions; import org.jclouds.openstack.v2_0.domain.Resource; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -81,10 +82,14 @@ public class BaseNovaApiLiveTest extends BaseApiLiveTest { setIfTestSystemPropertyPresent(props, NovaProperties.AUTO_ALLOCATE_FLOATING_IPS); return props; } - + protected Server createServerInZone(String zoneId) { + return createServerInZone(zoneId, new CreateServerOptions()); + } + + protected Server createServerInZone(String zoneId, CreateServerOptions options) { ServerApi serverApi = api.getServerApiForZone(zoneId); - ServerCreated server = serverApi.create(hostName, imageIdForZone(zoneId), flavorRefForZone(zoneId)); + ServerCreated server = serverApi.create(hostName, imageIdForZone(zoneId), flavorRefForZone(zoneId), options); blockUntilServerInState(server.getId(), serverApi, Status.ACTIVE); return serverApi.get(server.getId()); } diff --git a/apis/openstack-nova/src/test/resources/extension_list_full.json b/apis/openstack-nova/src/test/resources/extension_list_full.json index 490bebc0fe..ec99615010 100644 --- a/apis/openstack-nova/src/test/resources/extension_list_full.json +++ b/apis/openstack-nova/src/test/resources/extension_list_full.json @@ -277,5 +277,13 @@ "links": [], "namespace": "http://docs.openstack.org/compute/ext/floating_ips/api/v1.1", "alias": "os-floating-ips", - "description": "Floating IPs support"} -]} \ No newline at end of file + "description": "Floating IPs support" +}, +{ + "updated": "2012-12-21T00:00:00+00:00", + "name": "AvailabilityZone", + "links": [], + "namespace": "http://docs.openstack.org/compute/ext/availabilityzone/api/v1.1", + "alias": "os-availability-zone", + "description": "1. Add availability_zone to the Create Server v1.1 API.\n 2. Add availability zones describing.\n "} +]}