From ad96923db7f80da1fc2dca2288f0924c61eefffa Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Fri, 8 Apr 2011 12:51:53 -0700 Subject: [PATCH] Issue 518:add limits operation to CloudServersClient --- .../cloudservers/CloudServersAsyncClient.java | 12 +++ .../cloudservers/CloudServersClient.java | 27 ++++--- .../jclouds/cloudservers/domain/Limits.java | 54 ++++++++++--- .../cloudservers/domain/RateLimit.java | 81 ++++++++++++++++--- .../CloudServersAsyncClientTest.java | 15 ++++ .../CloudServersClientLiveTest.java | 38 +++++---- 6 files changed, 179 insertions(+), 48 deletions(-) diff --git a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/CloudServersAsyncClient.java b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/CloudServersAsyncClient.java index 76026dba58..ebb865ca66 100644 --- a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/CloudServersAsyncClient.java +++ b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/CloudServersAsyncClient.java @@ -37,6 +37,7 @@ import org.jclouds.cloudservers.domain.Addresses; import org.jclouds.cloudservers.domain.BackupSchedule; import org.jclouds.cloudservers.domain.Flavor; import org.jclouds.cloudservers.domain.Image; +import org.jclouds.cloudservers.domain.Limits; import org.jclouds.cloudservers.domain.RebootType; import org.jclouds.cloudservers.domain.Server; import org.jclouds.cloudservers.domain.SharedIpGroup; @@ -80,6 +81,17 @@ import com.google.common.util.concurrent.ListenableFuture; @Endpoint(ServerManagement.class) public interface CloudServersAsyncClient { + /** + * @see CloudServersClient#getLimits + */ + @GET + @Unwrap + @Consumes(MediaType.APPLICATION_JSON) + @QueryParams(keys = "format", values = "json") + @Path("/limits") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture getLimits(); + /** * @see CloudServersClient#listServers */ diff --git a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/CloudServersClient.java b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/CloudServersClient.java index 47239a3564..6603206629 100644 --- a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/CloudServersClient.java +++ b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/CloudServersClient.java @@ -21,15 +21,16 @@ package org.jclouds.cloudservers; import java.util.Set; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import javax.ws.rs.PathParam; -import org.jclouds.concurrent.Timeout; import org.jclouds.cloudservers.domain.Addresses; import org.jclouds.cloudservers.domain.BackupSchedule; import org.jclouds.cloudservers.domain.Flavor; import org.jclouds.cloudservers.domain.Image; +import org.jclouds.cloudservers.domain.Limits; import org.jclouds.cloudservers.domain.RebootType; import org.jclouds.cloudservers.domain.Server; import org.jclouds.cloudservers.domain.SharedIpGroup; @@ -37,16 +38,14 @@ import org.jclouds.cloudservers.options.CreateServerOptions; import org.jclouds.cloudservers.options.CreateSharedIpGroupOptions; import org.jclouds.cloudservers.options.ListOptions; import org.jclouds.cloudservers.options.RebuildServerOptions; +import org.jclouds.concurrent.Timeout; import org.jclouds.rest.ResourceNotFoundException; -import java.util.concurrent.Future; - /** * Provides access to Cloud Servers via their REST API. *

- * All commands return a Future of the result from Cloud Servers. Any exceptions incurred - * during processing will be wrapped in an {@link ExecutionException} as documented in - * {@link Future#get()}. + * All commands return a Future of the result from Cloud Servers. Any exceptions incurred during + * processing will be wrapped in an {@link ExecutionException} as documented in {@link Future#get()}. * * @see CloudServersAsyncClient * @see @@ -54,13 +53,22 @@ import java.util.concurrent.Future; */ @Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) public interface CloudServersClient { + /** + * All accounts, by default, have a preconfigured set of thresholds (or limits) to manage + * capacity and prevent abuse of the system. The system recognizes two kinds of limits: rate + * limits and absolute limits. Rate limits are thresholds that are reset after a certain amount + * of time passes. Absolute limits are fixed. + * + * @return limits on the account + */ + Limits getLimits(); /** * * List all servers (IDs and names only) * - * This operation provides a list of servers associated with your identity. Servers that have been - * deleted are not included in this list. + * This operation provides a list of servers associated with your identity. Servers that have + * been deleted are not included in this list. *

* in order to retrieve all details, pass the option {@link ListOptions#withDetails() * withDetails()} @@ -194,8 +202,7 @@ public interface CloudServersClient { * (e.g. keepalived) can then be used within the servers to perform health checks and * manage IP failover. */ - void shareIp(String addressToShare, int serverToTosignBindressTo, int sharedIpGroup, - boolean configureServer); + void shareIp(String addressToShare, int serverToTosignBindressTo, int sharedIpGroup, boolean configureServer); /** * This operation removes a shared IP address from the specified server. diff --git a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/domain/Limits.java b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/domain/Limits.java index ce28dd3d04..f18e23ddc4 100644 --- a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/domain/Limits.java +++ b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/domain/Limits.java @@ -19,28 +19,58 @@ package org.jclouds.cloudservers.domain; -import java.util.List; +import java.util.Map; +import java.util.Set; -import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; public class Limits { - private List rate = Lists.newArrayList(); - private List absolute = Lists.newArrayList(); + private Set rate = Sets.newLinkedHashSet(); + private Map absolute = Maps.newLinkedHashMap(); - public void setRate(List rate) { - this.rate = rate; - } - - public List getRate() { + public Set getRate() { return rate; } - public void setAbsolute(List absolute) { - this.absolute = absolute; + @Override + public String toString() { + return "Limits [rate=" + rate + ", absolute=" + absolute + "]"; } - public List getAbsolute() { + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((absolute == null) ? 0 : absolute.hashCode()); + result = prime * result + ((rate == null) ? 0 : rate.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Limits other = (Limits) obj; + if (absolute == null) { + if (other.absolute != null) + return false; + } else if (!absolute.equals(other.absolute)) + return false; + if (rate == null) { + if (other.rate != null) + return false; + } else if (!rate.equals(other.rate)) + return false; + return true; + } + + public Map getAbsolute() { return absolute; } diff --git a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/domain/RateLimit.java b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/domain/RateLimit.java index ad1bc5a142..e3c12cbe67 100644 --- a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/domain/RateLimit.java +++ b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/domain/RateLimit.java @@ -19,8 +19,6 @@ package org.jclouds.cloudservers.domain; -import javax.ws.rs.HttpMethod; - /** * * RateLimit. @@ -40,16 +38,69 @@ import javax.ws.rs.HttpMethod; */ public class RateLimit { - private final String uri; - private final String regex; - private final int remaining; - private final long resetTime; - private final RateLimitUnit unit; - private final int value; - private final HttpMethod verb; + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((regex == null) ? 0 : regex.hashCode()); + result = prime * result + remaining; + result = prime * result + (int) (resetTime ^ (resetTime >>> 32)); + result = prime * result + ((unit == null) ? 0 : unit.hashCode()); + result = prime * result + ((uri == null) ? 0 : uri.hashCode()); + result = prime * result + value; + result = prime * result + ((verb == null) ? 0 : verb.hashCode()); + return result; + } - public RateLimit(String uri, String regex, int remaining, long resetTime, RateLimitUnit unit, - int value, HttpMethod verb) { + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RateLimit other = (RateLimit) obj; + if (regex == null) { + if (other.regex != null) + return false; + } else if (!regex.equals(other.regex)) + return false; + if (remaining != other.remaining) + return false; + if (resetTime != other.resetTime) + return false; + if (unit != other.unit) + return false; + if (uri == null) { + if (other.uri != null) + return false; + } else if (!uri.equals(other.uri)) + return false; + if (value != other.value) + return false; + if (verb == null) { + if (other.verb != null) + return false; + } else if (!verb.equals(other.verb)) + return false; + return true; + } + + private String uri; + private String regex; + private int remaining; + private long resetTime; + private RateLimitUnit unit; + private int value; + private String verb; + + // for deserializer + public RateLimit() { + + } + + public RateLimit(String uri, String regex, int remaining, long resetTime, RateLimitUnit unit, int value, String verb) { this.uri = uri; this.regex = regex; this.remaining = remaining; @@ -83,8 +134,14 @@ public class RateLimit { return value; } - public HttpMethod getVerb() { + public String getVerb() { return verb; } + @Override + public String toString() { + return "[uri=" + uri + ", regex=" + regex + ", remaining=" + remaining + ", resetTime=" + resetTime + ", unit=" + + unit + ", value=" + value + ", verb=" + verb + "]"; + } + } diff --git a/apis/cloudservers/src/test/java/org/jclouds/cloudservers/CloudServersAsyncClientTest.java b/apis/cloudservers/src/test/java/org/jclouds/cloudservers/CloudServersAsyncClientTest.java index 09fb445b02..d7ef239229 100644 --- a/apis/cloudservers/src/test/java/org/jclouds/cloudservers/CloudServersAsyncClientTest.java +++ b/apis/cloudservers/src/test/java/org/jclouds/cloudservers/CloudServersAsyncClientTest.java @@ -199,6 +199,21 @@ public class CloudServersAsyncClientTest extends RestClientTest of(new Log4JLoggingModule(), new JschSshClientModule()), overrides) - .buildInjector(); + ImmutableSet. of(new Log4JLoggingModule(), new JschSshClientModule()), overrides).buildInjector(); client = injector.getInstance(CloudServersClient.class); sshFactory = injector.getInstance(SshClient.Factory.class); @@ -126,6 +126,13 @@ public class CloudServersClientLiveTest { injector.injectMembers(socketOpen); // add logger } + public void testLimits() throws Exception { + Limits response = client.getLimits(); + assert null != response; + assertTrue(response.getAbsolute().size() > 0); + assertTrue(response.getRate().size() > 0); + } + public void testListServers() throws Exception { Set response = client.listServers(); @@ -323,8 +330,8 @@ public class CloudServersClientLiveTest { while (server == null) { String serverName = serverPrefix + "createserver" + new SecureRandom().nextInt(); try { - server = client.createServer(serverName, imageId, flavorId, withFile("/etc/jclouds.txt", - "rackspace".getBytes()).withMetadata(metadata)); + server = client.createServer(serverName, imageId, flavorId, + withFile("/etc/jclouds.txt", "rackspace".getBytes()).withMetadata(metadata)); } catch (UndeclaredThrowableException e) { HttpResponseException htpe = (HttpResponseException) e.getCause().getCause(); if (htpe.getResponse().getStatusCode() == 400) @@ -343,7 +350,7 @@ public class CloudServersClientLiveTest { private void blockUntilServerActive(int serverId) throws InterruptedException { Server currentDetails = null; for (currentDetails = client.getServer(serverId); currentDetails.getStatus() != ServerStatus.ACTIVE; currentDetails = client - .getServer(serverId)) { + .getServer(serverId)) { System.out.printf("blocking on status active%n%s%n", currentDetails); Thread.sleep(5 * 1000); } @@ -352,7 +359,7 @@ public class CloudServersClientLiveTest { private void blockUntilServerVerifyResize(int serverId) throws InterruptedException { Server currentDetails = null; for (currentDetails = client.getServer(serverId); currentDetails.getStatus() != ServerStatus.VERIFY_RESIZE; currentDetails = client - .getServer(serverId)) { + .getServer(serverId)) { System.out.printf("blocking on status verify resize%n%s%n", currentDetails); Thread.sleep(5 * 1000); } @@ -361,7 +368,7 @@ public class CloudServersClientLiveTest { private void blockUntilImageActive(int imageId) throws InterruptedException { Image currentDetails = null; for (currentDetails = client.getImage(imageId); currentDetails.getStatus() != ImageStatus.ACTIVE; currentDetails = client - .getImage(imageId)) { + .getImage(imageId)) { System.out.printf("blocking on status active%n%s%n", currentDetails); Thread.sleep(5 * 1000); } @@ -459,9 +466,12 @@ public class CloudServersClientLiveTest { while (server == null) { String serverName = serverPrefix + "createserver" + new SecureRandom().nextInt(); try { - server = client - .createServer(serverName, imageId, flavorId, withFile("/etc/jclouds.txt", "rackspace".getBytes()) - .withMetadata(metadata).withSharedIpGroup(sharedIpGroupId).withSharedIp(ip)); + server = client.createServer( + serverName, + imageId, + flavorId, + withFile("/etc/jclouds.txt", "rackspace".getBytes()).withMetadata(metadata) + .withSharedIpGroup(sharedIpGroupId).withSharedIp(ip)); } catch (UndeclaredThrowableException e) { HttpResponseException htpe = (HttpResponseException) e.getCause().getCause(); if (htpe.getResponse().getStatusCode() == 400) @@ -482,7 +492,7 @@ public class CloudServersClientLiveTest { try { ExecResponse response = exec(server, password, "ifconfig -a"); assert response.getOutput().indexOf(ip) > 0 : String.format("server %s didn't get ip %s%n%s", server, ip, - response); + response); } catch (Exception e) { e.printStackTrace(); } catch (AssertionError e) { @@ -503,7 +513,7 @@ public class CloudServersClientLiveTest { try { ExecResponse response = exec(server, password, "ifconfig -a"); assert response.getOutput().indexOf(ip) == -1 : String.format("server %s still has get ip %s%n%s", server, ip, - response); + response); } catch (Exception e) { e.printStackTrace(); } catch (AssertionError e) { @@ -592,7 +602,7 @@ public class CloudServersClientLiveTest { } @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = { "testRebootSoft", "testRevertResize", - "testConfirmResize" }) + "testConfirmResize" }) void deleteServer2() { if (serverId2 > 0) { client.deleteServer(serverId2);