Repository: jclouds Updated Branches: refs/heads/master 2e1aa3c05 -> a38ee2120
Split availability Zone API to return Basic Info and Detailed info Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/a38ee212 Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/a38ee212 Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/a38ee212 Branch: refs/heads/master Commit: a38ee212074a2a0402c130f64c9fb24aa678fa5c Parents: 2e1aa3c Author: Arvind Nadendla <[email protected]> Authored: Wed Jul 15 11:02:01 2015 -0700 Committer: Zack Shoylev <[email protected]> Committed: Thu Jul 16 13:11:52 2015 -0500 ---------------------------------------------------------------------- .../domain/regionscoped/AvailabilityZone.java | 60 ++------- .../regionscoped/AvailabilityZoneDetails.java | 121 +++++++++++++++++++ .../v2_0/extensions/AvailabilityZoneApi.java | 11 +- .../AvailabilityZoneApiExpectTest.java | 88 +++++++++++++- .../AvailabilityZonesApiLiveTest.java | 18 ++- 5 files changed, 238 insertions(+), 60 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds/blob/a38ee212/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZone.java ---------------------------------------------------------------------- diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZone.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZone.java index 9010e3c..f1957c3 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZone.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZone.java @@ -17,58 +17,23 @@ package org.jclouds.openstack.nova.v2_0.domain.regionscoped; import com.google.common.base.Objects; -import com.google.common.collect.ImmutableMap; import com.google.gson.annotations.SerializedName; import java.beans.ConstructorProperties; -import java.util.Date; -import java.util.Map; +/** + * Availability Zone which shows name and state + */ public class AvailabilityZone { - public static final class HostService { - - private final boolean available; - private final boolean active; - @SerializedName("updated_at") - private final Date updated; - - @ConstructorProperties({"available", "active", "updated_at"}) - protected HostService(boolean available, boolean active, Date updated) { - this.available = available; - this.active = active; - this.updated = updated; - } - - public boolean isAvailable() { return available; } - - public boolean isActive() { return active; } - - public Date getUpdated() { return updated; } - - protected Objects.ToStringHelper string() { - return Objects.toStringHelper(this) - .add("available", available) - .add("active", active) - .add("updated", updated); - } - - @Override - public String toString() { - return string().toString(); - } - } - @SerializedName("zoneName") private final String name; private final ZoneState state; - private final Map<String, Map<String, HostService>> hosts; - @ConstructorProperties({"zoneName" , "zoneState", "hosts"}) - protected AvailabilityZone(String name, ZoneState state, Map<String, Map<String, HostService>> hosts) { + @ConstructorProperties({"zoneName" , "zoneState"}) + protected AvailabilityZone(String name, ZoneState state) { this.name = name; this.state = state; - this.hosts = hosts == null ? ImmutableMap.<String, Map<String, HostService>>of() : ImmutableMap.copyOf(hosts); } public String getName() { @@ -79,16 +44,9 @@ public class AvailabilityZone { return state; } - /** - * @return returns a map of host name and Host service objects - */ - public Map<String, Map<String, HostService>> getHosts() { - return this.hosts; - } - @Override public int hashCode() { - return Objects.hashCode(name, state, hosts); + return Objects.hashCode(name, state); } @Override @@ -97,15 +55,13 @@ public class AvailabilityZone { return false; if (obj == null || getClass() != obj.getClass()) return false; AvailabilityZone that = AvailabilityZone.class.cast(obj); - return Objects.equal(this.name, that.name) && Objects.equal(this.state, that.state) && Objects.equal(this.hosts, - that.hosts); + return Objects.equal(this.name, that.name) && Objects.equal(this.state, that.state); } protected Objects.ToStringHelper string() { return Objects.toStringHelper(this) .add("name", name) - .add("state", state) - .add("Hosts", hosts); + .add("state", state); } @Override http://git-wip-us.apache.org/repos/asf/jclouds/blob/a38ee212/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZoneDetails.java ---------------------------------------------------------------------- diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZoneDetails.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZoneDetails.java new file mode 100644 index 0000000..e226b40 --- /dev/null +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/regionscoped/AvailabilityZoneDetails.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.openstack.nova.v2_0.domain.regionscoped; + +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableMap; +import com.google.gson.annotations.SerializedName; + +import java.beans.ConstructorProperties; +import java.util.Date; +import java.util.Map; + +/** + * Availability Zone which show name, state and host information. + * + * Host information includes the host name and the services running on the hosts. + */ +public class AvailabilityZoneDetails { + + public static final class HostService { + + private final boolean available; + private final boolean active; + @SerializedName("updated_at") + private final Date updated; + + @ConstructorProperties({"available", "active", "updated_at"}) + protected HostService(boolean available, boolean active, Date updated) { + this.available = available; + this.active = active; + this.updated = updated; + } + + public boolean isAvailable() { return available; } + + public boolean isActive() { return active; } + + public Date getUpdated() { return updated; } + + protected Objects.ToStringHelper string() { + return Objects.toStringHelper(this) + .add("available", available) + .add("active", active) + .add("updated", updated); + } + + @Override + public String toString() { + return string().toString(); + } + } + + @SerializedName("zoneName") + private final String name; + private final ZoneState state; + private final Map<String, Map<String, HostService>> hosts; + + @ConstructorProperties({"zoneName" , "zoneState", "hosts"}) + protected AvailabilityZoneDetails(String name, ZoneState state, Map<String, Map<String, HostService>> hosts) { + this.name = name; + this.state = state; + this.hosts = hosts == null ? ImmutableMap.<String, Map<String, HostService>>of() : ImmutableMap.copyOf(hosts); + } + + public String getName() { + return name; + } + + public ZoneState getState() { + return state; + } + + /** + * @return returns a map of host name and Host service objects + */ + public Map<String, Map<String, HostService>> getHosts() { + return this.hosts; + } + + @Override + public int hashCode() { + return Objects.hashCode(name, state, hosts); + } + + @Override + public boolean equals(Object obj) { + if (this != obj) + return false; + if (obj == null || getClass() != obj.getClass()) return false; + AvailabilityZoneDetails that = AvailabilityZoneDetails.class.cast(obj); + return Objects.equal(this.name, that.name) && Objects.equal(this.state, that.state) && Objects.equal(this.hosts, + that.hosts); + } + + protected Objects.ToStringHelper string() { + return Objects.toStringHelper(this) + .add("name", name) + .add("state", state) + .add("Hosts", hosts); + } + + @Override + public String toString() { + return string().toString(); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/a38ee212/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneApi.java ---------------------------------------------------------------------- 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 index 4f8aa99..adae0a4 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 @@ -21,6 +21,7 @@ import com.google.common.collect.FluentIterable; import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404; import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; import org.jclouds.openstack.nova.v2_0.domain.regionscoped.AvailabilityZone; +import org.jclouds.openstack.nova.v2_0.domain.regionscoped.AvailabilityZoneDetails; import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.openstack.v2_0.services.Extension; import org.jclouds.rest.annotations.Fallback; @@ -54,12 +55,16 @@ public interface AvailabilityZoneApi { @Fallback(EmptyFluentIterableOnNotFoundOr404.class) FluentIterable<org.jclouds.openstack.nova.v2_0.domain.zonescoped.AvailabilityZone> list(); - /** - * @return all availability zones - */ @Named("availabilityZone:list") @GET @SelectJson("availabilityZoneInfo") @Fallback(EmptyFluentIterableOnNotFoundOr404.class) FluentIterable<AvailabilityZone> listAvailabilityZones(); + + @Named("availabilityZone:list") + @GET + @Path("/detail") + @SelectJson("availabilityZoneInfo") + @Fallback(EmptyFluentIterableOnNotFoundOr404.class) + FluentIterable<AvailabilityZoneDetails> listInDetail(); } http://git-wip-us.apache.org/repos/asf/jclouds/blob/a38ee212/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZoneApiExpectTest.java ---------------------------------------------------------------------- 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 348133d..f6960cb 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 @@ -23,6 +23,8 @@ import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.openstack.nova.v2_0.NovaApi; import org.jclouds.openstack.nova.v2_0.domain.regionscoped.AvailabilityZone; +import org.jclouds.openstack.nova.v2_0.domain.regionscoped.AvailabilityZoneDetails; +import org.jclouds.openstack.nova.v2_0.domain.regionscoped.AvailabilityZoneDetails.HostService; import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiExpectTest; import org.testng.annotations.Test; @@ -30,11 +32,34 @@ import java.util.Date; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertFalse; @Test(groups = "unit", testName = "AvailabilityZoneApiExpectTest") public class AvailabilityZoneApiExpectTest extends BaseNovaApiExpectTest { - public void testAvailabilityZonesList() throws Exception { + public void testWhenNamespaceInExtensionsListAvailabilityZonesPresent() throws Exception { + + NovaApi apiWhenExtensionInList = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse); + + assertEquals(apiWhenExtensionInList.getConfiguredRegions(), ImmutableSet.of("az-1.region-a.geo-1", "az-2.region-a.geo-1", "az-3.region-a.geo-1")); + + assertTrue(apiWhenExtensionInList.getFloatingIPApi("az-1.region-a.geo-1").isPresent()); + + } + + public void testWhenNamespaceNotInExtensionsListAvailabilityZonesPresent() throws Exception { + + NovaApi apiWhenExtensionNotInList = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, extensionsOfNovaRequest, unmatchedExtensionsOfNovaResponse); + + assertEquals(apiWhenExtensionNotInList.getConfiguredRegions(), ImmutableSet.of("az-1.region-a.geo-1", "az-2.region-a.geo-1", "az-3.region-a.geo-1")); + + assertFalse(apiWhenExtensionNotInList.getFloatingIPApi("az-1.region-a.geo-1").isPresent()); + + } + + public void testListAvailabilityZones() throws Exception { HttpRequest list = HttpRequest .builder() .method("GET") @@ -45,8 +70,8 @@ public class AvailabilityZoneApiExpectTest extends BaseNovaApiExpectTest { HttpResponse listResponse = HttpResponse.builder().statusCode(200) .payload(payloadFromResource("/listAvailabilityZones.json")).build(); - NovaApi availabilityZonesApi = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, - responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, list, listResponse); + NovaApi availabilityZonesApi = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess, + extensionsOfNovaRequest, extensionsOfNovaResponse, list, listResponse); assertEquals(availabilityZonesApi.getConfiguredRegions(), ImmutableSet.of("az-1.region-a.geo-1", "az-2.region-a.geo-1", "az-3.region-a.geo-1")); @@ -55,6 +80,46 @@ public class AvailabilityZoneApiExpectTest extends BaseNovaApiExpectTest { Optional<? extends AvailabilityZone> zone = zones.first(); assertTrue(zone.isPresent(), "Couldn't find zone"); + assertEquals(zone.get().getName(), "internal", "Expected zone name to be internal but it was: " + zone.get().getName()); + assertTrue(zone.get().getState().isAvailable(), "Zone: " + zone.get().getName() + " is not available."); + } + + public void testListAvailabilityZonesWhenResponseIs404() throws Exception { + HttpRequest list = HttpRequest.builder() + .method("GET") + .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v2/3456/os-availability-zone") + .addHeader("Accept", "application/json") + .addHeader("X-Auth-Token", authToken).build(); + + HttpResponse listResponse = HttpResponse.builder().statusCode(404).build(); + + NovaApi apiWhenNoServersExist = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess, + extensionsOfNovaRequest, extensionsOfNovaResponse, list, listResponse); + + assertTrue(apiWhenNoServersExist.getAvailabilityZoneApi("az-1.region-a.geo-1").get().listAvailabilityZones().isEmpty()); + } + + public void testListInDetail() throws Exception { + HttpRequest list = HttpRequest + .builder() + .method("GET") + .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v2/3456/os-availability-zone/detail") + .addHeader("Accept", "application/json") + .addHeader("X-Auth-Token", authToken).build(); + + HttpResponse listResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/listAvailabilityZones.json")).build(); + + NovaApi availabilityZonesApi = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, + responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, list, listResponse); + + assertEquals(availabilityZonesApi.getConfiguredRegions(), ImmutableSet.of("az-1.region-a.geo-1", "az-2.region-a.geo-1", "az-3.region-a.geo-1")); + + FluentIterable<? extends AvailabilityZoneDetails> zones = availabilityZonesApi.getAvailabilityZoneApi("az-1.region-a.geo-1").get().listInDetail(); + + Optional<? extends AvailabilityZoneDetails> zone = zones.first(); + + assertTrue(zone.isPresent(), "Couldn't find zone"); assertEquals(zone.get() .getName(), "internal", "Expected zone name to be internal but it was: " + zone.get() .getName()); @@ -67,10 +132,25 @@ public class AvailabilityZoneApiExpectTest extends BaseNovaApiExpectTest { String hostServiceName = zone.get().getHosts().get(hostName).keySet().iterator().next(); assertEquals(hostServiceName, "nova-conductor", "Expected host service name to be nova-conductor but it was: " + hostServiceName); - AvailabilityZone.HostService hostService = zone.get().getHosts().get(hostName).get(hostServiceName); + HostService hostService = zone.get().getHosts().get(hostName).get(hostServiceName); assertTrue(hostService.isAvailable(), "Couldn't find host service availability"); assertTrue(hostService.isActive(), "Couldn't find host service state"); assertEquals(hostService.getUpdated(), new Date(1436509815000L), "Expected Updated time: " + new Date(1436509815000L) + " does match Updated time : " + hostService.getUpdated()); } + + public void testListInDetailWhenResponseIs404() throws Exception { + HttpRequest list = HttpRequest.builder() + .method("GET") + .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v2/3456/os-availability-zone/detail") + .addHeader("Accept", "application/json") + .addHeader("X-Auth-Token", authToken).build(); + + HttpResponse listResponse = HttpResponse.builder().statusCode(404).build(); + + NovaApi apiWhenNoServersExist = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName, responseWithKeystoneAccess, + extensionsOfNovaRequest, extensionsOfNovaResponse, list, listResponse); + + assertTrue(apiWhenNoServersExist.getAvailabilityZoneApi("az-1.region-a.geo-1").get().listInDetail().isEmpty()); + } } http://git-wip-us.apache.org/repos/asf/jclouds/blob/a38ee212/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/extensions/AvailabilityZonesApiLiveTest.java ---------------------------------------------------------------------- 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 4c78bca..fd430a7 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 @@ -19,6 +19,8 @@ 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.regionscoped.AvailabilityZone; +import org.jclouds.openstack.nova.v2_0.domain.regionscoped.AvailabilityZoneDetails; +import org.jclouds.openstack.nova.v2_0.domain.regionscoped.AvailabilityZoneDetails.HostService; import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiLiveTest; import org.testng.annotations.Test; @@ -37,13 +39,27 @@ public class AvailabilityZonesApiLiveTest extends BaseNovaApiLiveTest { for (AvailabilityZone zone : zones) { assertNotNull(zone.getName()); + assertTrue(zone.getState().isAvailable(), "zone: " + zone.getName() + " is not available."); + } + } + } + + @Test + public void testListInDetail() throws Exception { + + Optional<? extends AvailabilityZoneApi> availabilityZoneApi = api.getAvailabilityZoneApi("RegionOne"); + if (availabilityZoneApi.isPresent()) { + FluentIterable<? extends AvailabilityZoneDetails> zones = availabilityZoneApi.get().listInDetail(); + + for (AvailabilityZoneDetails zone : zones) { + assertNotNull(zone.getName()); assertTrue(zone.getState() .isAvailable(), "zone: " + zone.getName() + " is not available."); String hostName = zone.getHosts().keySet().iterator().next(); assertNotNull(hostName, "Expected host name to be not null"); String hostServiceName = zone.getHosts().get(hostName).keySet().iterator().next(); assertNotNull(hostServiceName, "Expected host service name to be not null"); - AvailabilityZone.HostService hostService = zone.getHosts().get(hostName).get(hostServiceName); + HostService hostService = zone.getHosts().get(hostName).get(hostServiceName); assertTrue(hostService.isAvailable(), "Couldn't find host service availability"); assertTrue(hostService.isActive(), "Couldn't find host service state"); assertNotNull(hostService.getUpdated(), "Expected Updated time, but none received ");
