From 7dbba2a4e1aeafd4b075275f868eb236d6dfac38 Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Thu, 19 Apr 2012 07:20:56 +0100 Subject: [PATCH 1/9] Adjusting iso8601SecondsDateParse to replace ' ' with 'T" in the same manner as iso8601DateParse --- .../org/jclouds/date/internal/SimpleDateFormatDateService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/org/jclouds/date/internal/SimpleDateFormatDateService.java b/core/src/main/java/org/jclouds/date/internal/SimpleDateFormatDateService.java index 78b54a24d6..b6a0108dc8 100644 --- a/core/src/main/java/org/jclouds/date/internal/SimpleDateFormatDateService.java +++ b/core/src/main/java/org/jclouds/date/internal/SimpleDateFormatDateService.java @@ -157,6 +157,8 @@ public class SimpleDateFormatDateService implements DateService { toParse = trimToMillis(toParse); toParse = trimTZ(toParse); toParse += tz; + if (toParse.charAt(10) == ' ') + toParse = new StringBuilder(toParse).replace(10, 11, "T").toString(); synchronized (iso8601SecondsSimpleDateFormat) { try { return iso8601SecondsSimpleDateFormat.parse(toParse); From eef27bbe4ee0f60dbfc7d5e7be588fd3dad91f3a Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Thu, 19 Apr 2012 07:24:56 +0100 Subject: [PATCH 2/9] Adding full extension list --- .../v1_1/internal/BaseNovaExpectTest.java | 2 +- .../test/resources/extension_list_full.json | 123 ++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 apis/openstack-nova/src/test/resources/extension_list_full.json diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/internal/BaseNovaExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/internal/BaseNovaExpectTest.java index c311dbcbe0..336f507ba7 100644 --- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/internal/BaseNovaExpectTest.java +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/internal/BaseNovaExpectTest.java @@ -63,7 +63,7 @@ public class BaseNovaExpectTest extends BaseRestClientExpectTest { .put("X-Auth-Token", authToken).build()).build(); extensionsOfNovaResponse = HttpResponse.builder().statusCode(200) - .payload(payloadFromResource("/extension_list_normal.json")).build(); + .payload(payloadFromResource("/extension_list_full.json")).build(); unmatchedExtensionsOfNovaResponse = HttpResponse.builder().statusCode(200) .payload(payloadFromResource("/extension_list.json")).build(); diff --git a/apis/openstack-nova/src/test/resources/extension_list_full.json b/apis/openstack-nova/src/test/resources/extension_list_full.json new file mode 100644 index 0000000000..298a2f2f4a --- /dev/null +++ b/apis/openstack-nova/src/test/resources/extension_list_full.json @@ -0,0 +1,123 @@ +{ + "extensions": [{ + "updated": "2011-06-09T00:00:00+00:00", + "name": "Multinic", + "links": [], + "namespace": "https://docs.openstack.org/ext/multinic/api/v1.1", + "alias": "NMN", + "description": "Multiple network support" + }, { + "updated": "2011-06-29T00:00:00+00:00", + "name": "Hosts", + "links": [], + "namespace": "https://docs.openstack.org/ext/hosts/api/v1.1", + "alias": "os-hosts", + "description": "Host administration" + }, { + "updated": "2011-03-25T00:00:00+00:00", + "name": "Volumes", + "links": [], + "namespace": "https://docs.openstack.org/ext/volumes/api/v1.1", + "alias": "os-volumes", + "description": "Volumes support" + }, { + "updated": "2011-05-25 16:12:21.656723", + "name": "Admin Controller", + "links": [], + "namespace": "https:TODO/", + "alias": "ADMIN", + "description": "The Admin API Extension" + }, { + "updated": "2011-08-08T00:00:00+00:00", + "name": "Quotas", + "links": [], + "namespace": "https://docs.openstack.org/ext/quotas-sets/api/v1.1", + "alias": "os-quota-sets", + "description": "Quotas management support" + }, { + "updated": "2011-08-24T00:00:00+00:00", + "name": "VolumeTypes", + "links": [], + "namespace": "https://docs.openstack.org/ext/volume_types/api/v1.1", + "alias": "os-volume-types", + "description": "Volume types support" + }, { + "updated": "2011-06-23T00:00:00+00:00", + "name": "FlavorExtraSpecs", + "links": [], + "namespace": "https://docs.openstack.org/ext/flavor_extra_specs/api/v1.1", + "alias": "os-flavor-extra-specs", + "description": "Instance type (flavor) extra specs" + }, { + "updated": "2011-09-14T00:00:00+00:00", + "name": "FlavorExtraData", + "links": [], + "namespace": "https://docs.openstack.org/ext/flavor_extra_data/api/v1.1", + "alias": "os-flavor-extra-data", + "description": "Provide additional data for flavors" + }, { + "updated": "2011-08-17T00:00:00+00:00", + "name": "VirtualInterfaces", + "links": [], + "namespace": "https://docs.openstack.org/ext/virtual_interfaces/api/v1.1", + "alias": "virtual_interfaces", + "description": "Virtual interface support" + }, { + "updated": "2011-07-19T00:00:00+00:00", + "name": "Createserverext", + "links": [], + "namespace": "https://docs.openstack.org/ext/createserverext/api/v1.1", + "alias": "os-create-server-ext", + "description": "Extended support to the Create Server v1.1 API" + }, { + "updated": "2011-08-08T00:00:00+00:00", + "name": "Keypairs", + "links": [], + "namespace": "https://docs.openstack.org/ext/keypairs/api/v1.1", + "alias": "os-keypairs", + "description": "Keypair Support" + }, { + "updated": "2011-08-25T00:00:00+00:00", + "name": "VSAs", + "links": [], + "namespace": "https://docs.openstack.org/ext/vsa/api/v1.1", + "alias": "zadr-vsa", + "description": "Virtual Storage Arrays support" + }, { + "updated": "2011-08-19T00:00:00+00:00", + "name": "SimpleTenantUsage", + "links": [], + "namespace": "https://docs.openstack.org/ext/os-simple-tenant-usage/api/v1.1", + "alias": "os-simple-tenant-usage", + "description": "Simple tenant usage extension" + }, { + "updated": "2011-08-18T00:00:00+00:00", + "name": "Rescue", + "links": [], + "namespace": "https://docs.openstack.org/ext/rescue/api/v1.1", + "alias": "os-rescue", + "description": "Instance rescue mode" + }, { + "updated": "2011-07-21T00:00:00+00:00", + "name": "SecurityGroups", + "links": [], + "namespace": "https://docs.openstack.org/ext/securitygroups/api/v1.1", + "alias": "security_groups", + "description": "Security group support" + }, { + "updated": "2011-06-16T00:00:00+00:00", + "name": "Floating_ips", + "links": [], + "namespace": "https://docs.openstack.org/ext/floating_ips/api/v1.1", + "alias": "os-floating-ips", + "description": "Floating IPs support" + }, { + "updated": "2011-06-16T00:00:00+00:00", + "name": "Users", + "links": [], + "namespace": "http://docs.openstack.org/compute/ext/users/api/v1.1", + "alias": "os-users", + "description": "Users support" + } + ] +} \ No newline at end of file From 400221820a555012df60ff84bbc337705b09e4dc Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Thu, 19 Apr 2012 07:25:41 +0100 Subject: [PATCH 3/9] Adding Host Administration extension --- .../openstack/nova/v1_1/NovaAsyncClient.java | 10 ++ .../openstack/nova/v1_1/NovaClient.java | 9 + .../v1_1/config/NovaRestClientModule.java | 6 +- .../openstack/nova/v1_1/domain/Host.java | 126 ++++++++++++++ .../nova/v1_1/domain/HostResourceUsage.java | 163 ++++++++++++++++++ .../HostAdministrationAsyncClient.java | 78 +++++++++ .../extensions/HostAdministrationClient.java | 55 ++++++ ...paceEqualsAnyNamespaceInExtensionsSet.java | 6 +- .../src/test/resources/host.json | 1 + .../src/test/resources/hosts_list.json | 1 + 10 files changed, 453 insertions(+), 2 deletions(-) create mode 100644 apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/Host.java create mode 100644 apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/HostResourceUsage.java create mode 100644 apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationAsyncClient.java create mode 100644 apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClient.java create mode 100644 apis/openstack-nova/src/test/resources/host.json create mode 100644 apis/openstack-nova/src/test/resources/hosts_list.json diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java index cb8a4864df..263d9ec745 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java @@ -24,8 +24,10 @@ import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.Zone; import org.jclouds.location.functions.ZoneToEndpoint; import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPAsyncClient; +import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient; +import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageAsyncClient; import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient; import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient; import org.jclouds.openstack.nova.v1_1.features.ImageAsyncClient; @@ -103,4 +105,12 @@ public interface NovaAsyncClient { @Delegate Optional getKeyPairExtensionForZone( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + + /** + * Provides asynchronous access to Host Administration features. + */ + @Delegate + Optional getHostAdministrationExtensionForZone( + @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + } diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java index 65725174da..2ffdf21b02 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java @@ -26,8 +26,10 @@ import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.Zone; import org.jclouds.location.functions.ZoneToEndpoint; import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient; +import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationClient; import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient; import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient; +import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageClient; import org.jclouds.openstack.nova.v1_1.features.ExtensionClient; import org.jclouds.openstack.nova.v1_1.features.FlavorClient; import org.jclouds.openstack.nova.v1_1.features.ImageClient; @@ -106,4 +108,11 @@ public interface NovaClient { Optional getKeyPairExtensionForZone( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + /** + * Provides synchronous access to Host Administration features. + */ + @Delegate + Optional getHostAdministrationExtensionForZone( + @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + } diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java index c9f603d178..559cabaae7 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java @@ -37,6 +37,8 @@ import org.jclouds.openstack.nova.v1_1.NovaClient; import org.jclouds.openstack.nova.v1_1.domain.Extension; import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient; +import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationAsyncClient; +import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationClient; import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient; import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient; @@ -75,7 +77,9 @@ public class NovaRestClientModule extends RestClientModule builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromHost(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + private String name; + private String service; + + public T name(String name) { + this.name = name; + return self(); + } + + public T service(String service) { + this.service = service; + return self(); + } + + public Host build() { + return new Host(this); + } + + public T fromHost(Host in) { + return this + .name(in.getName()) + .service(in.getService()) + ; + } + + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + @SerializedName(value="host_name") + private final String name; + private final String service; + + protected Host(Builder builder) { + this.name = builder.name; + this.service = builder.service; + } + + /** + */ + @Nullable + public String getName() { + return this.name; + } + + /** + */ + @Nullable + public String getService() { + return this.service; + } + + @Override + public int hashCode() { + return Objects.hashCode(name, service); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Host that = Host.class.cast(obj); + return Objects.equal(this.name, that.name) + && Objects.equal(this.service, that.service) + ; + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("name", name) + .add("service", service) + ; + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/HostResourceUsage.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/HostResourceUsage.java new file mode 100644 index 0000000000..95e2b76571 --- /dev/null +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/HostResourceUsage.java @@ -0,0 +1,163 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.domain; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.gson.annotations.SerializedName; + +/** + * Class HostResourceUsage + */ +public class HostResourceUsage { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromHostResourceUsage(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + private String host; + private String memoryMb; + private int cpu; + private int diskGb; + + public T host(String host) { + this.host = host; + return self(); + } + + public T memoryMb(String memoryMb) { + this.memoryMb = memoryMb; + return self(); + } + + public T cpu(int cpu) { + this.cpu = cpu; + return self(); + } + + public T diskGb(int diskGb) { + this.diskGb = diskGb; + return self(); + } + + public HostResourceUsage build() { + return new HostResourceUsage(this); + } + + public T fromHostResourceUsage(HostResourceUsage in) { + return this + .host(in.getHost()) + .memoryMb(in.getMemoryMb()) + .cpu(in.getCpu()) + .diskGb(in.getDiskGb()) + ; + } + + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final String host; + @SerializedName(value = "memory_mb") + private final String memoryMb; + private final int cpu; + @SerializedName(value = "disk_gb") + private final int diskGb; + + protected HostResourceUsage(Builder builder) { + this.host = builder.host; + this.memoryMb = builder.memoryMb; + this.cpu = builder.cpu; + this.diskGb = builder.diskGb; + } + + /** + */ + @Nullable + public String getHost() { + return this.host; + } + + /** + */ + @Nullable + public String getMemoryMb() { + return this.memoryMb; + } + + /** + */ + @Nullable + public int getCpu() { + return this.cpu; + } + + /** + */ + @Nullable + public int getDiskGb() { + return this.diskGb; + } + + @Override + public int hashCode() { + return Objects.hashCode(host, memoryMb, cpu, diskGb); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + HostResourceUsage that = HostResourceUsage.class.cast(obj); + return Objects.equal(this.host, that.host) + && Objects.equal(this.memoryMb, that.memoryMb) + && Objects.equal(this.cpu, that.cpu) + && Objects.equal(this.diskGb, that.diskGb) + ; + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("host", host) + .add("memoryMb", memoryMb) + .add("cpu", cpu) + .add("diskGb", diskGb) + ; + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationAsyncClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationAsyncClient.java new file mode 100644 index 0000000000..9e1819f52d --- /dev/null +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationAsyncClient.java @@ -0,0 +1,78 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.extensions; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.openstack.filters.AuthenticateRequest; +import org.jclouds.openstack.nova.v1_1.domain.Host; +import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage; +import org.jclouds.openstack.services.Extension; +import org.jclouds.openstack.services.ServiceType; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Host Administration features via the REST API. + *

+ * + * @author Adam Lowe + * @see SimpleTenantUsageClient + * @see + * @see + * @see + */ +@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.HOSTS) +@SkipEncoding({'/', '='}) +@RequestFilters(AuthenticateRequest.class) +public interface HostAdministrationAsyncClient { + + /** + * @see HostAdministrationClient#listHosts() + */ + @GET + @Path("/os-hosts") + @SelectJson("hosts") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listHosts(); + + /** + * @see HostAdministrationClient#getHostResourceUsage(String) + */ + @GET + @Path("/os-hosts/{id}") + @SelectJson("host") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture> getHostResourceUsage(@PathParam("id") String hostId); + +} diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClient.java new file mode 100644 index 0000000000..01b3e9ba29 --- /dev/null +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClient.java @@ -0,0 +1,55 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.extensions; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.ws.rs.PathParam; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.openstack.nova.v1_1.domain.Host; +import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage; +import org.jclouds.openstack.services.Extension; +import org.jclouds.openstack.services.ServiceType; + +/** + * Provides asynchronous access to Host Administration features via the REST API. + *

+ * + * @author Adam Lowe + * @see HostAdministrationAsyncClient + */ +@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.HOSTS) +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface HostAdministrationClient { + + /** + * Returns the list of hosts + * @return the usage information + */ + Set listHosts(); + + /** + * Retrieves the physical/usage resource on a specific host + * @return the usage information + */ + Set getHostResourceUsage(@PathParam("id") String hostId); + +} diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.java index 30d365d278..5db7bb9d46 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.java @@ -43,7 +43,7 @@ import com.google.common.collect.Multimap; /** * We use the annotation {@link org.jclouds.openstack.services.Extension} to * bind a class that is an extension to an extension found in the - * {@link ExtensionsClient#listExtensions} call. + * {@link org.jclouds.openstack.nova.v1_1.features.ExtensionClient#listExtensions} call. * * @author Adrian Cole * @@ -62,6 +62,10 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio URI.create("http://docs.openstack.org/compute/ext/floating_ips/api/v1.1")) .put(URI.create(ExtensionNamespaces.KEYPAIRS), URI.create("http://docs.openstack.org/compute/ext/keypairs/api/v1.1")) + .put(URI.create(ExtensionNamespaces.SIMPLE_TENANT_USAGE), + URI.create("http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1")) + .put(URI.create(ExtensionNamespaces.HOSTS), + URI.create("http://docs.openstack.org/compute/ext/hosts/api/v1.1")) .build(); @Inject diff --git a/apis/openstack-nova/src/test/resources/host.json b/apis/openstack-nova/src/test/resources/host.json new file mode 100644 index 0000000000..ad2e217e24 --- /dev/null +++ b/apis/openstack-nova/src/test/resources/host.json @@ -0,0 +1 @@ +{"host": [{"resource": {"project": "(total)", "memory_mb": 16083, "host": "ubuntu", "cpu": 4, "disk_gb": 181}}, {"resource": {"project": "(used_now)", "memory_mb": 3396, "host": "ubuntu", "cpu": 3, "disk_gb": 5}}, {"resource": {"project": "(used_max)", "memory_mb": 6144, "host": "ubuntu", "cpu": 3, "disk_gb": 80}}, {"resource": {"project": "f8535069c3fb404cb61c873b1a0b4921", "memory_mb": 6144, "host": "ubuntu", "cpu": 3, "disk_gb": 80}}]} \ No newline at end of file diff --git a/apis/openstack-nova/src/test/resources/hosts_list.json b/apis/openstack-nova/src/test/resources/hosts_list.json new file mode 100644 index 0000000000..b8a2cbd2a8 --- /dev/null +++ b/apis/openstack-nova/src/test/resources/hosts_list.json @@ -0,0 +1 @@ +["hosts": [{"host_name": "ubuntu", "service": "compute"}] \ No newline at end of file From 80c48193ee2571fccbd0af1ec296d9a54988351a Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Thu, 19 Apr 2012 07:32:11 +0100 Subject: [PATCH 4/9] Adding tests of Host Administration extension --- .../extensions/HostAdministrationClient.java | 1 + .../HostAdministrationClientExpectTest.java | 63 +++++++++++++++++++ .../HostAdministrationClientLiveTest.java | 55 ++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientExpectTest.java create mode 100644 apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientLiveTest.java diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClient.java index 01b3e9ba29..fa23767b6b 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClient.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClient.java @@ -32,6 +32,7 @@ import org.jclouds.openstack.services.ServiceType; /** * Provides asynchronous access to Host Administration features via the REST API. *

+ * TODO reboot, shutdown, startup, update * * @author Adam Lowe * @see HostAdministrationAsyncClient diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientExpectTest.java new file mode 100644 index 0000000000..2c0c0f8b7c --- /dev/null +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientExpectTest.java @@ -0,0 +1,63 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.extensions; + +import java.net.URI; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; + +/** + * Tests HostAdministrationClient guice wiring and parsing + * + * @author Adam Lowe + */ +@Test(groups = "unit", testName = "HostAdministrationClientExpectTest") +public class HostAdministrationClientExpectTest extends BaseNovaClientExpectTest { + + + public void testList() throws Exception { + URI endpoint = URI.create("https://compute.north.host/v1.1/3456/os-hosts"); + HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, + HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken)) + .endpoint(endpoint).build(), + HttpResponse.builder().statusCode(200).build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get(); + + client.listHosts(); + } + + public void testGet() throws Exception { + URI endpoint = URI.create("https://compute.north.host/v1.1/3456/os-hosts/xyz"); + HostAdministrationClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, + HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken)) + .endpoint(endpoint).build(), + HttpResponse.builder().statusCode(200).build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get(); + + client.getHostResourceUsage("xyz"); + } + +} diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientLiveTest.java new file mode 100644 index 0000000000..019068a118 --- /dev/null +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientLiveTest.java @@ -0,0 +1,55 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.extensions; + +import static org.testng.Assert.assertNotNull; + +import java.util.Set; + +import org.jclouds.openstack.nova.v1_1.domain.Host; +import org.jclouds.openstack.nova.v1_1.domain.SimpleTenantUsage; +import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest; +import org.testng.annotations.Test; + +import com.google.common.base.Optional; + +/** + * Tests behavior of HostAdministrationClient + * + * @author Adam Lowe + */ +@Test(groups = "live", testName = "HostAdministrationClientLiveTest") +public class HostAdministrationClientLiveTest extends BaseNovaClientLiveTest { + + + public void testListAndGet() throws Exception { + for (String zoneId : novaContext.getApi().getConfiguredZones()) { + Optional optClient = novaContext.getApi().getHostAdministrationExtensionForZone(zoneId); + if (optClient.isPresent()) { + HostAdministrationClient client = optClient.get(); + Set hosts = client.listHosts(); + assertNotNull(hosts); + for(Host host : hosts) { + client.getHostResourceUsage(host.getName()); + } + } + } + } + +} From 522147a9ce04e2f713a9622a3edcdbfcd2ed6676 Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Thu, 19 Apr 2012 07:59:06 +0100 Subject: [PATCH 5/9] Fixing imports for Host Administration extension --- .../java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java | 1 - .../main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java | 1 - .../nova/v1_1/extensions/HostAdministrationClientLiveTest.java | 1 - 3 files changed, 3 deletions(-) diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java index 263d9ec745..f323161ebb 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java @@ -27,7 +27,6 @@ import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient; -import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageAsyncClient; import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient; import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient; import org.jclouds.openstack.nova.v1_1.features.ImageAsyncClient; diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java index 2ffdf21b02..52b8b5bdda 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java @@ -29,7 +29,6 @@ import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient; import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationClient; import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient; import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient; -import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageClient; import org.jclouds.openstack.nova.v1_1.features.ExtensionClient; import org.jclouds.openstack.nova.v1_1.features.FlavorClient; import org.jclouds.openstack.nova.v1_1.features.ImageClient; diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientLiveTest.java index 019068a118..1092a5b95d 100644 --- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientLiveTest.java +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientLiveTest.java @@ -23,7 +23,6 @@ import static org.testng.Assert.assertNotNull; import java.util.Set; import org.jclouds.openstack.nova.v1_1.domain.Host; -import org.jclouds.openstack.nova.v1_1.domain.SimpleTenantUsage; import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest; import org.testng.annotations.Test; From 1d09fc3400d549f1d7f2e0c3037d0ad761918cd4 Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Thu, 19 Apr 2012 10:30:24 +0100 Subject: [PATCH 6/9] Adding project field to HostResourceUsage --- .../nova/v1_1/domain/HostResourceUsage.java | 52 ++++++++++++------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/HostResourceUsage.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/HostResourceUsage.java index 95e2b76571..e8dbbd1301 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/HostResourceUsage.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/HostResourceUsage.java @@ -18,6 +18,8 @@ */ package org.jclouds.openstack.nova.v1_1.domain; +import static com.google.common.base.Preconditions.checkNotNull; + import org.jclouds.javax.annotation.Nullable; import com.google.common.base.Objects; @@ -37,11 +39,12 @@ public class HostResourceUsage { return new ConcreteBuilder().fromHostResourceUsage(this); } - public static abstract class Builder> { + public static abstract class Builder> { protected abstract T self(); private String host; - private String memoryMb; + private String project; + private int memoryMb; private int cpu; private int diskGb; @@ -50,7 +53,12 @@ public class HostResourceUsage { return self(); } - public T memoryMb(String memoryMb) { + public T project(String project) { + this.project = project; + return self(); + } + + public T memoryMb(int memoryMb) { this.memoryMb = memoryMb; return self(); } @@ -72,6 +80,7 @@ public class HostResourceUsage { public T fromHostResourceUsage(HostResourceUsage in) { return this .host(in.getHost()) + .project(in.getProject()) .memoryMb(in.getMemoryMb()) .cpu(in.getCpu()) .diskGb(in.getDiskGb()) @@ -88,22 +97,23 @@ public class HostResourceUsage { } private final String host; - @SerializedName(value = "memory_mb") - private final String memoryMb; + private final String project; + @SerializedName(value="memory_mb") + private final int memoryMb; private final int cpu; - @SerializedName(value = "disk_gb") + @SerializedName(value="disk_gb") private final int diskGb; protected HostResourceUsage(Builder builder) { - this.host = builder.host; - this.memoryMb = builder.memoryMb; - this.cpu = builder.cpu; - this.diskGb = builder.diskGb; + this.host = checkNotNull(builder.host, "host"); + this.project = builder.project; + this.memoryMb = checkNotNull(builder.memoryMb, "memoryMb"); + this.cpu = checkNotNull(builder.cpu, "cpu"); + this.diskGb = checkNotNull(builder.diskGb, "diskGb"); } /** */ - @Nullable public String getHost() { return this.host; } @@ -111,27 +121,31 @@ public class HostResourceUsage { /** */ @Nullable - public String getMemoryMb() { + public String getProject() { + return this.project; + } + + /** + */ + public int getMemoryMb() { return this.memoryMb; } /** */ - @Nullable public int getCpu() { return this.cpu; } /** */ - @Nullable public int getDiskGb() { return this.diskGb; } @Override public int hashCode() { - return Objects.hashCode(host, memoryMb, cpu, diskGb); + return Objects.hashCode(host, project, memoryMb, cpu, diskGb); } @Override @@ -140,19 +154,19 @@ public class HostResourceUsage { if (obj == null || getClass() != obj.getClass()) return false; HostResourceUsage that = HostResourceUsage.class.cast(obj); return Objects.equal(this.host, that.host) + && Objects.equal(this.project, that.project) && Objects.equal(this.memoryMb, that.memoryMb) && Objects.equal(this.cpu, that.cpu) - && Objects.equal(this.diskGb, that.diskGb) - ; + && Objects.equal(this.diskGb, that.diskGb); } protected ToStringHelper string() { return Objects.toStringHelper("") .add("host", host) + .add("project", project) .add("memoryMb", memoryMb) .add("cpu", cpu) - .add("diskGb", diskGb) - ; + .add("diskGb", diskGb); } @Override From 43d258837d998c1f20f35c936ee8c367a5ba0ee2 Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Thu, 19 Apr 2012 10:31:23 +0100 Subject: [PATCH 7/9] Adding gson adaptor for HostResourceUsage --- .../nova/v1_1/config/NovaParserModule.java | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaParserModule.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaParserModule.java index 63209fb4f0..e2a50efcc8 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaParserModule.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaParserModule.java @@ -25,8 +25,15 @@ import javax.inject.Singleton; import org.jclouds.json.config.GsonModule; import org.jclouds.json.config.GsonModule.DateAdapter; +import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage; import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; import com.google.inject.AbstractModule; import com.google.inject.Provides; @@ -38,7 +45,7 @@ public class NovaParserModule extends AbstractModule { @Provides @Singleton public Map provideCustomAdapterBindings() { - return ImmutableMap. of(); + return ImmutableMap. of(HostResourceUsage.class, new HostResourceUsageAdapter()); } @Override @@ -46,4 +53,30 @@ public class NovaParserModule extends AbstractModule { bind(DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class); } + @Singleton + public static class HostResourceUsageAdapter implements JsonSerializer, JsonDeserializer { + public HostResourceUsage apply(HostResourceUsageWrapper in) { + return in.resource.toBuilder().build(); + } + + @Override + public HostResourceUsage deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException { + return apply((HostResourceUsageWrapper) context.deserialize(jsonElement, HostResourceUsageWrapper.class)); + } + + @Override + public JsonElement serialize(HostResourceUsage hostResourceUsage, Type type, JsonSerializationContext context) { + return context.serialize(hostResourceUsage); + } + + private static class HostResourceUsageWrapper { + protected HostResourceUsageInternal resource; + } + private static class HostResourceUsageInternal extends HostResourceUsage { + protected HostResourceUsageInternal(Builder builder) { + super(builder); + } + } + } + } From f45b9ca849fbe85160c162f77b3e3c1b0b8a4c3c Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Thu, 19 Apr 2012 10:37:17 +0100 Subject: [PATCH 8/9] Improving Host Administration extension tests --- .../HostAdministrationClientExpectTest.java | 29 ++++++++++++++++--- .../HostAdministrationClientLiveTest.java | 10 +++++-- .../src/test/resources/hosts_list.json | 2 +- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientExpectTest.java index 2c0c0f8b7c..54d7036994 100644 --- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientExpectTest.java +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientExpectTest.java @@ -18,16 +18,23 @@ */ package org.jclouds.openstack.nova.v1_1.extensions; +import static org.testng.Assert.assertEquals; + import java.net.URI; +import java.util.Set; import javax.ws.rs.core.MediaType; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.nova.v1_1.domain.Host; +import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage; import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; /** * Tests HostAdministrationClient guice wiring and parsing @@ -44,9 +51,16 @@ public class HostAdministrationClientExpectTest extends BaseNovaClientExpectTest responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken)) .endpoint(endpoint).build(), - HttpResponse.builder().statusCode(200).build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get(); + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/hosts_list.json")).build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get(); - client.listHosts(); + Host expected = Host.builder().name("ubuntu").service("compute").build(); + + Set result = client.listHosts(); + Host host = Iterables.getOnlyElement(result); + assertEquals(host.getName(), "ubuntu"); + assertEquals(host.getService(), "compute"); + + assertEquals(host, expected); } public void testGet() throws Exception { @@ -55,9 +69,16 @@ public class HostAdministrationClientExpectTest extends BaseNovaClientExpectTest responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken)) .endpoint(endpoint).build(), - HttpResponse.builder().statusCode(200).build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get(); + HttpResponse.builder().statusCode(200).payload(payloadFromResource("/host.json")).build()).getHostAdministrationExtensionForZone("az-1.region-a.geo-1").get(); - client.getHostResourceUsage("xyz"); + Set expected = ImmutableSet.of( + HostResourceUsage.builder().memoryMb(16083).project("(total)").cpu(4).diskGb(181).host("ubuntu").build(), + HostResourceUsage.builder().memoryMb(3396).project("(used_now)").cpu(3).diskGb(5).host("ubuntu").build(), + HostResourceUsage.builder().memoryMb(6144).project("(used_max)").cpu(3).diskGb(80).host("ubuntu").build(), + HostResourceUsage.builder().memoryMb(6144).project("f8535069c3fb404cb61c873b1a0b4921").cpu(3).diskGb(80).host("ubuntu").build() + ); + + assertEquals(client.getHostResourceUsage("xyz"), expected); } } diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientLiveTest.java index 1092a5b95d..e79dd89891 100644 --- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientLiveTest.java +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/HostAdministrationClientLiveTest.java @@ -18,11 +18,13 @@ */ package org.jclouds.openstack.nova.v1_1.extensions; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import java.util.Set; import org.jclouds.openstack.nova.v1_1.domain.Host; +import org.jclouds.openstack.nova.v1_1.domain.HostResourceUsage; import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest; import org.testng.annotations.Test; @@ -36,16 +38,18 @@ import com.google.common.base.Optional; @Test(groups = "live", testName = "HostAdministrationClientLiveTest") public class HostAdministrationClientLiveTest extends BaseNovaClientLiveTest { - public void testListAndGet() throws Exception { for (String zoneId : novaContext.getApi().getConfiguredZones()) { Optional optClient = novaContext.getApi().getHostAdministrationExtensionForZone(zoneId); - if (optClient.isPresent()) { + if (optClient.isPresent() && identity.endsWith(":admin")) { HostAdministrationClient client = optClient.get(); Set hosts = client.listHosts(); assertNotNull(hosts); for(Host host : hosts) { - client.getHostResourceUsage(host.getName()); + for (HostResourceUsage usage : client.getHostResourceUsage(host.getName())) { + assertEquals(usage.getHost(), host.getName()); + assertNotNull(usage); + } } } } diff --git a/apis/openstack-nova/src/test/resources/hosts_list.json b/apis/openstack-nova/src/test/resources/hosts_list.json index b8a2cbd2a8..30d377016b 100644 --- a/apis/openstack-nova/src/test/resources/hosts_list.json +++ b/apis/openstack-nova/src/test/resources/hosts_list.json @@ -1 +1 @@ -["hosts": [{"host_name": "ubuntu", "service": "compute"}] \ No newline at end of file +{"hosts": [{"host_name": "ubuntu", "service": "compute"}]} \ No newline at end of file From adc6e2aa935e82e0171de1c602d721780e0386b0 Mon Sep 17 00:00:00 2001 From: Adam Lowe Date: Thu, 19 Apr 2012 10:42:30 +0100 Subject: [PATCH 9/9] Adding Simple Tenant Usage extension --- .../openstack/nova/v1_1/NovaAsyncClient.java | 8 + .../openstack/nova/v1_1/NovaClient.java | 8 + .../v1_1/config/NovaRestClientModule.java | 10 +- .../nova/v1_1/domain/SimpleServerUsage.java | 302 ++++++++++++++++++ .../nova/v1_1/domain/SimpleTenantUsage.java | 239 ++++++++++++++ .../SimpleTenantUsageAsyncClient.java | 77 +++++ .../extensions/SimpleTenantUsageClient.java | 53 +++ .../SimpleTenantUsageClientExpectTest.java | 110 +++++++ .../SimpleTenantUsageClientLiveTest.java | 55 ++++ .../test/resources/simple_tenant_usage.json | 1 + .../test/resources/simple_tenant_usages.json | 1 + 11 files changed, 856 insertions(+), 8 deletions(-) create mode 100644 apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SimpleServerUsage.java create mode 100644 apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SimpleTenantUsage.java create mode 100644 apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageAsyncClient.java create mode 100644 apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageClient.java create mode 100644 apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageClientExpectTest.java create mode 100644 apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageClientLiveTest.java create mode 100644 apis/openstack-nova/src/test/resources/simple_tenant_usage.json create mode 100644 apis/openstack-nova/src/test/resources/simple_tenant_usages.json diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java index f323161ebb..da9d6507b5 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java @@ -27,6 +27,7 @@ import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient; +import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageAsyncClient; import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient; import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient; import org.jclouds.openstack.nova.v1_1.features.ImageAsyncClient; @@ -112,4 +113,11 @@ public interface NovaAsyncClient { Optional getHostAdministrationExtensionForZone( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + /** + * Provides asynchronous access to Simple Tenant Usage features. + */ + @Delegate + Optional getSimpleTenantUsageExtensionForZone( + @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + } diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java index 52b8b5bdda..d33e0ab91b 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java @@ -29,6 +29,7 @@ import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient; import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationClient; import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient; import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient; +import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageClient; import org.jclouds.openstack.nova.v1_1.features.ExtensionClient; import org.jclouds.openstack.nova.v1_1.features.FlavorClient; import org.jclouds.openstack.nova.v1_1.features.ImageClient; @@ -114,4 +115,11 @@ public interface NovaClient { Optional getHostAdministrationExtensionForZone( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + /** + * Provides synchronous access to Simple Tenant Usage features. + */ + @Delegate + Optional getSimpleTenantUsageExtensionForZone( + @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + } diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java index 559cabaae7..fdb3b039a8 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java @@ -35,14 +35,7 @@ import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; import org.jclouds.openstack.nova.v1_1.NovaAsyncClient; import org.jclouds.openstack.nova.v1_1.NovaClient; import org.jclouds.openstack.nova.v1_1.domain.Extension; -import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPAsyncClient; -import org.jclouds.openstack.nova.v1_1.extensions.FloatingIPClient; -import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationAsyncClient; -import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationClient; -import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient; -import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient; -import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient; -import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient; +import org.jclouds.openstack.nova.v1_1.extensions.*; import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient; import org.jclouds.openstack.nova.v1_1.features.ExtensionClient; import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient; @@ -79,6 +72,7 @@ public class NovaRestClientModule extends RestClientModule builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromSimpleServerUsage(this); + } + + public static abstract class Builder> { + private String instanceName; + private double hours; + private double flavorMemoryMb; + private double flavorLocalGb; + private double flavorVcpus; + private String tenantId; + private String flavorName; + private Date instanceCreated; + private Date instanceTerminiated; + private Status instanceStatus; + private long uptime; + + protected abstract T self(); + + public T instanceName(String instanceName) { + this.instanceName = instanceName; + return self(); + } + + public T hours(double hours) { + this.hours = hours; + return self(); + } + + public T flavorMemoryMb(double flavorMemoryMb) { + this.flavorMemoryMb = flavorMemoryMb; + return self(); + } + + public T flavorLocalGb(double flavorLocalGb) { + this.flavorLocalGb = flavorLocalGb; + return self(); + } + + public T flavorVcpus(double flavorVcpus) { + this.flavorVcpus = flavorVcpus; + return self(); + } + + public T tenantId(String tenantId) { + this.tenantId = tenantId; + return self(); + } + + public T flavorName(String flavorName) { + this.flavorName = flavorName; + return self(); + } + + public T instanceCreated(Date instanceCreated) { + this.instanceCreated = instanceCreated; + return self(); + } + + public T instanceTerminiated(Date instanceTerminiated) { + this.instanceTerminiated = instanceTerminiated; + return self(); + } + + public T instanceStatus(Status instanceStatus) { + this.instanceStatus = instanceStatus; + return self(); + } + + public T uptime(long uptime) { + this.uptime = uptime; + return self(); + } + + public SimpleServerUsage build() { + return new SimpleServerUsage(this); + } + + + public T fromSimpleServerUsage(SimpleServerUsage in) { + return this + .instanceName(in.getInstanceName()) + .flavorMemoryMb(in.getFlavorMemoryMb()) + .flavorLocalGb(in.getFlavorLocalGb()) + .flavorVcpus(in.getFlavorVcpus()) + .tenantId(in.getTenantId()) + .flavorName(in.getFlavorName()) + .instanceCreated(in.getInstanceCreated()) + .instanceTerminiated(in.getInstanceTerminiated()) + .instanceStatus(in.getInstanceStatus()) + .uptime(in.getUptime()) + ; + } + + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + @SerializedName("name") + private final String instanceName; + private final double hours; + @SerializedName("memory_mb") + private final double flavorMemoryMb; + @SerializedName("local_gb") + private final double flavorLocalGb; + @SerializedName("vcpus") + private final double flavorVcpus; + @SerializedName("tenant_id") + private final String tenantId; + @SerializedName("flavor") + private final String flavorName; + @SerializedName("started_at") + private final Date instanceCreated; + @SerializedName("ended_at") + private final Date instanceTerminiated; + @SerializedName("state") + private final Status instanceStatus; + private final long uptime; + + private SimpleServerUsage(Builder builder) { + this.instanceName = checkNotNull(builder.instanceName, "instanceName"); + this.hours = builder.hours; + this.flavorMemoryMb = builder.flavorMemoryMb; + this.flavorLocalGb = builder.flavorLocalGb; + this.flavorVcpus = builder.flavorVcpus; + this.tenantId = checkNotNull(builder.tenantId, "tenantId"); + this.flavorName = checkNotNull(builder.flavorName, "flavorName"); + this.instanceCreated = builder.instanceCreated; //checkNotNull(builder.instanceCreated, "instanceCreated"); + this.instanceTerminiated = builder.instanceTerminiated; + this.instanceStatus = checkNotNull(builder.instanceStatus, "instanceStatus"); + this.uptime = checkNotNull(builder.uptime, "uptime"); + } + + /** + */ + public String getInstanceName() { + return this.instanceName; + } + + /** + */ + public double getFlavorMemoryMb() { + return this.flavorMemoryMb; + } + + /** + */ + public double getFlavorLocalGb() { + return this.flavorLocalGb; + } + + /** + */ + public double getFlavorVcpus() { + return this.flavorVcpus; + } + + /** + */ + public String getTenantId() { + return this.tenantId; + } + + /** + */ + public String getFlavorName() { + return this.flavorName; + } + + /** + */ + public Date getInstanceCreated() { + return this.instanceCreated; + } + + /** + */ + @Nullable + public Date getInstanceTerminiated() { + return this.instanceTerminiated; + } + + /** + */ + public Status getInstanceStatus() { + return this.instanceStatus; + } + + /** + */ + public long getUptime() { + return this.uptime; + } + + @Override + public int hashCode() { + return Objects.hashCode(instanceName, flavorMemoryMb, flavorLocalGb, flavorVcpus, tenantId, flavorName, instanceCreated, instanceTerminiated, instanceStatus, uptime); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + SimpleServerUsage that = SimpleServerUsage.class.cast(obj); + return Objects.equal(this.instanceName, that.instanceName) + && Objects.equal(this.flavorMemoryMb, that.flavorMemoryMb) + && Objects.equal(this.flavorLocalGb, that.flavorLocalGb) + && Objects.equal(this.flavorVcpus, that.flavorVcpus) + && Objects.equal(this.tenantId, that.tenantId) + && Objects.equal(this.flavorName, that.flavorName) + && Objects.equal(this.instanceCreated, that.instanceCreated) + && Objects.equal(this.instanceTerminiated, that.instanceTerminiated) + && Objects.equal(this.instanceStatus, that.instanceStatus) + && Objects.equal(this.uptime, that.uptime) + ; + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("instanceName", instanceName) + .add("flavorMemoryMb", flavorMemoryMb) + .add("flavorLocalGb", flavorLocalGb) + .add("flavorVcpus", flavorVcpus) + .add("tenantId", tenantId) + .add("flavorName", flavorName) + .add("instanceCreated", instanceCreated) + .add("instanceTerminiated", instanceTerminiated) + .add("instanceStatus", instanceStatus) + .add("uptime", uptime) + ; + } + + @Override + public String toString() { + return string().toString(); + } + +} diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SimpleTenantUsage.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SimpleTenantUsage.java new file mode 100644 index 0000000000..b4b20ddd2e --- /dev/null +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/domain/SimpleTenantUsage.java @@ -0,0 +1,239 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Collections; +import java.util.Date; +import java.util.Set; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.gson.annotations.SerializedName; + +/** + * Information the SimpleTenantUsage extension returns data about each tenant + * + * @author Adam Lowe + */ +public class SimpleTenantUsage { + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromSimpleTenantUsage(this); + } + + public static abstract class Builder> { + private String tenantId; + private double totalLocalGbUsage; + private double totalVcpusUsage; + private double totalMemoryMbUsage; + private double totalHours; + private Date start; + private Date stop; + private Set serverUsages = Sets.newLinkedHashSet(); + + protected abstract T self(); + + public T tenantId(String tenantId) { + this.tenantId = tenantId; + return self(); + } + + public T totalLocalGbUsage(double total_local_gb_usage) { + this.totalLocalGbUsage = total_local_gb_usage; + return self(); + } + + public T totalVcpusUsage(double total_vcpus_usage) { + this.totalVcpusUsage = total_vcpus_usage; + return self(); + } + + public T totalMemoryMbUsage(double total_memory_mb_usage) { + this.totalMemoryMbUsage = total_memory_mb_usage; + return self(); + } + + public T totalHours(double total_hours) { + this.totalHours = total_hours; + return self(); + } + + public T start(Date start) { + this.start = start; + return self(); + } + + public T stop(Date stop) { + this.stop = stop; + return self(); + } + + public T serverUsages(Set serverUsages) { + this.serverUsages = serverUsages; + return self(); + } + + public SimpleTenantUsage build() { + return new SimpleTenantUsage(this); + } + + + public T fromSimpleTenantUsage(SimpleTenantUsage in) { + return this + .totalLocalGbUsage(in.getTotalLocalGbUsage()) + .totalVcpusUsage(in.getTotalVcpusUsage()) + .totalMemoryMbUsage(in.getTotalMemoryMbUsage()) + .totalHours(in.getTotalHours()) + .start(in.getStart()) + .stop(in.getStop()) + .serverUsages(in.getServerUsages()) + ; + } + + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + @SerializedName("tenant_id") + private final String tenantId; + @SerializedName("total_local_gb_usage") + private final double totalLocalGbUsage; + @SerializedName("total_vcpus_usage") + private final double totalVcpusUsage; + @SerializedName("total_memory_mb_usage") + private final double totalMemoryMbUsage; + @SerializedName("total_hours") + private final double totalHours; + private final Date start; + private final Date stop; + @SerializedName("server_usages") + private final Set serverUsages; + + private SimpleTenantUsage(Builder builder) { + this.tenantId = builder.tenantId; + this.totalLocalGbUsage = builder.totalLocalGbUsage; + this.totalVcpusUsage = builder.totalVcpusUsage; + this.totalMemoryMbUsage = builder.totalMemoryMbUsage; + this.totalHours = builder.totalHours; + this.start = builder.start; + this.stop = builder.stop; + this.serverUsages = ImmutableSet.copyOf(checkNotNull(builder.serverUsages, "serverUsages")); + } + + public String getTenantId() { + return tenantId; + } + + /** + */ + public double getTotalLocalGbUsage() { + return this.totalLocalGbUsage; + } + + /** + */ + public double getTotalVcpusUsage() { + return this.totalVcpusUsage; + } + + /** + */ + public double getTotalMemoryMbUsage() { + return this.totalMemoryMbUsage; + } + + /** + */ + public double getTotalHours() { + return this.totalHours; + } + + /** + */ + @Nullable + public Date getStart() { + return this.start; + } + + /** + */ + @Nullable + public Date getStop() { + return this.stop; + } + + /** + */ + @Nullable + public Set getServerUsages() { + return serverUsages == null ? ImmutableSet.of() : Collections.unmodifiableSet(this.serverUsages); + } + + @Override + public int hashCode() { + return Objects.hashCode(totalLocalGbUsage, totalVcpusUsage, totalMemoryMbUsage, totalHours, start, stop, serverUsages); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + SimpleTenantUsage that = SimpleTenantUsage.class.cast(obj); + return Objects.equal(this.totalLocalGbUsage, that.totalLocalGbUsage) + && Objects.equal(this.totalVcpusUsage, that.totalVcpusUsage) + && Objects.equal(this.totalMemoryMbUsage, that.totalMemoryMbUsage) + && Objects.equal(this.totalHours, that.totalHours) + && Objects.equal(this.start, that.start) + && Objects.equal(this.stop, that.stop) + && Objects.equal(this.serverUsages, that.serverUsages) + ; + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("totalLocalGbUsage", totalLocalGbUsage) + .add("totalVcpusUsage", totalVcpusUsage) + .add("totalMemoryMbUsage", totalMemoryMbUsage) + .add("totalHours", totalHours) + .add("start", start) + .add("stop", stop) + .add("serverUsages", serverUsages) + ; + } + + @Override + public String toString() { + return string().toString(); + } + +} diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageAsyncClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageAsyncClient.java new file mode 100644 index 0000000000..4e2e2b80cf --- /dev/null +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageAsyncClient.java @@ -0,0 +1,77 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.extensions; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.openstack.filters.AuthenticateRequest; +import org.jclouds.openstack.nova.v1_1.domain.SimpleTenantUsage; +import org.jclouds.openstack.services.Extension; +import org.jclouds.openstack.services.ServiceType; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Simple Tenant Usage via the REST API. + *

+ * + * @author Adam Lowe + * @see SimpleTenantUsageClient + * @see + * @see + * @see + */ +@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SIMPLE_TENANT_USAGE) +@SkipEncoding({'/', '='}) +@RequestFilters(AuthenticateRequest.class) +public interface SimpleTenantUsageAsyncClient { + + /** + * @see SimpleTenantUsageClient#listTenantUsages() + */ + @GET + @Path("/os-simple-tenant-usage") + @SelectJson("tenant_usages") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listTenantUsages(); + + /** + * @see SimpleTenantUsageClient#getTenantUsage(String) + */ + @GET + @Path("/os-simple-tenant-usage/{id}") + @SelectJson("tenant_usage") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getTenantUsage(@PathParam("id") String tenantId); + +} diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageClient.java new file mode 100644 index 0000000000..dcef9aafde --- /dev/null +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageClient.java @@ -0,0 +1,53 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.extensions; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.openstack.nova.v1_1.domain.SimpleTenantUsage; +import org.jclouds.openstack.services.Extension; +import org.jclouds.openstack.services.ServiceType; + +/** + * Provides asynchronous access to Simple Tenant Usage via the REST API. + *

+ * + * @author Adam Lowe + * @see SimpleTenantUsageAsyncClient + */ +@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.SIMPLE_TENANT_USAGE) +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface SimpleTenantUsageClient { + + /** + * Retrive tenant_usage for all tenants + * + * @return the set of TenantUsage reports + */ + Set listTenantUsages(); + + /** + * Retrive tenant_usage for a specified tenant + * + * @return the requested tenant usage + */ + SimpleTenantUsage getTenantUsage(String tenantId); +} diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageClientExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageClientExpectTest.java new file mode 100644 index 0000000000..9f9a01e508 --- /dev/null +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageClientExpectTest.java @@ -0,0 +1,110 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.extensions; + +import static org.testng.Assert.*; +import static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.Set; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.ContextBuilder; +import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.nova.v1_1.NovaClient; +import org.jclouds.openstack.nova.v1_1.domain.Ingress; +import org.jclouds.openstack.nova.v1_1.domain.IpProtocol; +import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup; +import org.jclouds.openstack.nova.v1_1.domain.SecurityGroupRule; +import org.jclouds.openstack.nova.v1_1.domain.Server; +import org.jclouds.openstack.nova.v1_1.domain.SimpleServerUsage; +import org.jclouds.openstack.nova.v1_1.domain.SimpleTenantUsage; +import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest; +import org.jclouds.openstack.nova.v1_1.parse.ParseSecurityGroupListTest; +import org.jclouds.openstack.nova.v1_1.parse.ParseSecurityGroupTest; +import org.jclouds.rest.internal.RestContextImpl; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; + +/** + * Tests SimpleTenantUsageClient guice wiring and parsing + * + * @author Adam Lowe + */ +@Test(groups = "unit", testName = "SimpleTenantUsageClientExpectTest") +public class SimpleTenantUsageClientExpectTest extends BaseNovaClientExpectTest { + private DateService dateService = new SimpleDateFormatDateService(); + + public void testList() throws Exception { + URI endpoint = URI.create("https://compute.north.host/v1.1/3456/os-simple-tenant-usage"); + SimpleTenantUsageClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, + HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken)) + .endpoint(endpoint).build(), + HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/simple_tenant_usages.json")).build()) + .getSimpleTenantUsageExtensionForZone("az-1.region-a.geo-1").get(); + + Set results = client.listTenantUsages(); + + SimpleTenantUsage usage = Iterables.getOnlyElement(results); + assertEquals(usage.getTenantId(), "f8535069c3fb404cb61c873b1a0b4921"); + assertEquals(usage.getTotalHours(), 4.888888888888889e-07); + assertEquals(usage.getTotalLocalGbUsage(), 1.9555555555555557e-05); + assertEquals(usage.getTotalMemoryMbUsage(), 0.0015018666666666667); + assertEquals(usage.getTotalVcpusUsage(), 7.333333333333333e-07); + assertEquals(usage.getStart(), dateService.iso8601DateParse("2012-04-18 12:18:39.702411")); + assertEquals(usage.getStop(), dateService.iso8601DateParse("2012-04-18 12:18:39.702499")); + assertNotNull(usage.getServerUsages()); + assertTrue(usage.getServerUsages().isEmpty()); + } + + public void testGet() throws Exception { + URI endpoint = URI.create("https://compute.north.host/v1.1/3456/os-simple-tenant-usage/test-1234"); + SimpleTenantUsageClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, + HttpRequest.builder().method("GET").headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken)) + .endpoint(endpoint).build(), + HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/simple_tenant_usage.json")).build()) + .getSimpleTenantUsageExtensionForZone("az-1.region-a.geo-1").get(); + + SimpleTenantUsage usage = client.getTenantUsage("test-1234"); + assertEquals(usage.getTenantId(), "f8535069c3fb404cb61c873b1a0b4921"); + + SimpleTenantUsage expected = SimpleTenantUsage.builder().totalHours(4.833333333333333E-7).totalLocalGbUsage(1.933333333333333E-05) + .start(dateService.iso8601DateParse("2012-04-18 13:32:07.255743")).stop(dateService.iso8601DateParse("2012-04-18 13:32:07.255743")) + .totalMemoryMbUsage(0.0014847999999999999).totalVcpusUsage(7.249999999999999E-07).serverUsages( + ImmutableSet.of( + SimpleServerUsage.builder().hours(2.4166666666666665e-07).uptime(91149).flavorLocalGb(50).instanceName("test1").tenantId("f8535069c3fb404cb61c873b1a0b4921").flavorVcpus(2).flavorMemoryMb(4096).instanceStatus(SimpleServerUsage.Status.ACTIVE).flavorName("m1.medium").instanceCreated(this.dateService.iso8601SecondsDateParse("2012-04-17T12:12:58")).build(), + SimpleServerUsage.builder().hours(2.4166666666666665e-07).uptime(84710).flavorLocalGb(30).instanceName("mish_test").tenantId("f8535069c3fb404cb61c873b1a0b4921").flavorVcpus(1).flavorMemoryMb(2048).instanceStatus(SimpleServerUsage.Status.ACTIVE).flavorName("m1.small").instanceCreated(this.dateService.iso8601SecondsDateParse("2012-04-17T14:00:17")).build() + )).build(); + + assertEquals(usage, expected); + } + +} diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageClientLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageClientLiveTest.java new file mode 100644 index 0000000000..c3d7de7b14 --- /dev/null +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/SimpleTenantUsageClientLiveTest.java @@ -0,0 +1,55 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.extensions; + +import static org.testng.Assert.assertNotNull; + +import java.util.Set; + +import org.jclouds.openstack.nova.v1_1.domain.SecurityGroup; +import org.jclouds.openstack.nova.v1_1.domain.SimpleTenantUsage; +import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest; +import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest; +import org.testng.annotations.Test; + +import com.google.common.base.Optional; + +/** + * Tests behavior of SimpleTenantUsageClient + * + * @author Adam Lowe + */ +@Test(groups = "live", testName = "SimpleTenantUsageClientLiveTest") +public class SimpleTenantUsageClientLiveTest extends BaseNovaClientLiveTest { + + public void testList() throws Exception { + for (String zoneId : novaContext.getApi().getConfiguredZones()) { + Optional optClient = novaContext.getApi().getSimpleTenantUsageExtensionForZone(zoneId); + if (optClient.isPresent() && identity.endsWith(":admin")) { + SimpleTenantUsageClient client = optClient.get(); + Set usages = client.listTenantUsages(); + assertNotNull(usages); + for (SimpleTenantUsage usage : usages) { + SimpleTenantUsage details = client.getTenantUsage(usage.getTenantId()); + assertNotNull(details); + } + } + } + } +} diff --git a/apis/openstack-nova/src/test/resources/simple_tenant_usage.json b/apis/openstack-nova/src/test/resources/simple_tenant_usage.json new file mode 100644 index 0000000000..de07dc4f7c --- /dev/null +++ b/apis/openstack-nova/src/test/resources/simple_tenant_usage.json @@ -0,0 +1 @@ +{"tenant_usage": {"total_memory_mb_usage": 0.0014847999999999999, "total_vcpus_usage": 7.249999999999999e-07, "total_hours": 4.833333333333333e-07, "tenant_id": "f8535069c3fb404cb61c873b1a0b4921", "stop": "2012-04-18 13:32:07.255830", "server_usages": [{"hours": 2.4166666666666665e-07, "uptime": 91149, "local_gb": 50, "ended_at": null, "name": "test1", "tenant_id": "f8535069c3fb404cb61c873b1a0b4921", "vcpus": 2, "memory_mb": 4096, "state": "active", "flavor": "m1.medium", "started_at": "2012-04-17 12:12:58"}, {"hours": 2.4166666666666665e-07, "uptime": 84710, "local_gb": 30, "ended_at": null, "name": "mish_test", "tenant_id": "f8535069c3fb404cb61c873b1a0b4921", "vcpus": 1, "memory_mb": 2048, "state": "active", "flavor": "m1.small", "started_at": "2012-04-17 14:00:17"}], "start": "2012-04-18 13:32:07.255743", "total_local_gb_usage": 1.933333333333333e-05}} \ No newline at end of file diff --git a/apis/openstack-nova/src/test/resources/simple_tenant_usages.json b/apis/openstack-nova/src/test/resources/simple_tenant_usages.json new file mode 100644 index 0000000000..6f3c0d74f6 --- /dev/null +++ b/apis/openstack-nova/src/test/resources/simple_tenant_usages.json @@ -0,0 +1 @@ +{"tenant_usages": [{"total_memory_mb_usage": 0.0015018666666666667, "total_vcpus_usage": 7.333333333333333e-07, "start": "2012-04-18 12:18:39.702411", "tenant_id": "f8535069c3fb404cb61c873b1a0b4921", "stop": "2012-04-18 12:18:39.702499", "total_hours": 4.888888888888889e-07, "total_local_gb_usage": 1.9555555555555557e-05}] \ No newline at end of file