Issue 518:add limits operation to CloudServersClient

This commit is contained in:
Adrian Cole 2011-04-08 12:51:53 -07:00
parent a3fc778035
commit ad96923db7
6 changed files with 179 additions and 48 deletions

View File

@ -37,6 +37,7 @@ import org.jclouds.cloudservers.domain.Addresses;
import org.jclouds.cloudservers.domain.BackupSchedule; import org.jclouds.cloudservers.domain.BackupSchedule;
import org.jclouds.cloudservers.domain.Flavor; import org.jclouds.cloudservers.domain.Flavor;
import org.jclouds.cloudservers.domain.Image; import org.jclouds.cloudservers.domain.Image;
import org.jclouds.cloudservers.domain.Limits;
import org.jclouds.cloudservers.domain.RebootType; import org.jclouds.cloudservers.domain.RebootType;
import org.jclouds.cloudservers.domain.Server; import org.jclouds.cloudservers.domain.Server;
import org.jclouds.cloudservers.domain.SharedIpGroup; import org.jclouds.cloudservers.domain.SharedIpGroup;
@ -80,6 +81,17 @@ import com.google.common.util.concurrent.ListenableFuture;
@Endpoint(ServerManagement.class) @Endpoint(ServerManagement.class)
public interface CloudServersAsyncClient { public interface CloudServersAsyncClient {
/**
* @see CloudServersClient#getLimits
*/
@GET
@Unwrap
@Consumes(MediaType.APPLICATION_JSON)
@QueryParams(keys = "format", values = "json")
@Path("/limits")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Limits> getLimits();
/** /**
* @see CloudServersClient#listServers * @see CloudServersClient#listServers
*/ */

View File

@ -21,15 +21,16 @@ package org.jclouds.cloudservers;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.concurrent.Timeout;
import org.jclouds.cloudservers.domain.Addresses; import org.jclouds.cloudservers.domain.Addresses;
import org.jclouds.cloudservers.domain.BackupSchedule; import org.jclouds.cloudservers.domain.BackupSchedule;
import org.jclouds.cloudservers.domain.Flavor; import org.jclouds.cloudservers.domain.Flavor;
import org.jclouds.cloudservers.domain.Image; import org.jclouds.cloudservers.domain.Image;
import org.jclouds.cloudservers.domain.Limits;
import org.jclouds.cloudservers.domain.RebootType; import org.jclouds.cloudservers.domain.RebootType;
import org.jclouds.cloudservers.domain.Server; import org.jclouds.cloudservers.domain.Server;
import org.jclouds.cloudservers.domain.SharedIpGroup; 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.CreateSharedIpGroupOptions;
import org.jclouds.cloudservers.options.ListOptions; import org.jclouds.cloudservers.options.ListOptions;
import org.jclouds.cloudservers.options.RebuildServerOptions; import org.jclouds.cloudservers.options.RebuildServerOptions;
import org.jclouds.concurrent.Timeout;
import org.jclouds.rest.ResourceNotFoundException; import org.jclouds.rest.ResourceNotFoundException;
import java.util.concurrent.Future;
/** /**
* Provides access to Cloud Servers via their REST API. * Provides access to Cloud Servers via their REST API.
* <p/> * <p/>
* All commands return a Future of the result from Cloud Servers. Any exceptions incurred * All commands return a Future of the result from Cloud Servers. Any exceptions incurred during
* during processing will be wrapped in an {@link ExecutionException} as documented in * processing will be wrapped in an {@link ExecutionException} as documented in {@link Future#get()}.
* {@link Future#get()}.
* *
* @see CloudServersAsyncClient * @see CloudServersAsyncClient
* @see <a href="http://docs.rackspacecloud.com/servers/api/cs-devguide-latest.pdf" /> * @see <a href="http://docs.rackspacecloud.com/servers/api/cs-devguide-latest.pdf" />
@ -54,13 +53,22 @@ import java.util.concurrent.Future;
*/ */
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) @Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface CloudServersClient { 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) * List all servers (IDs and names only)
* *
* This operation provides a list of servers associated with your identity. Servers that have been * This operation provides a list of servers associated with your identity. Servers that have
* deleted are not included in this list. * been deleted are not included in this list.
* <p/> * <p/>
* in order to retrieve all details, pass the option {@link ListOptions#withDetails() * in order to retrieve all details, pass the option {@link ListOptions#withDetails()
* withDetails()} * withDetails()}
@ -194,8 +202,7 @@ public interface CloudServersClient {
* (e.g. keepalived) can then be used within the servers to perform health checks and * (e.g. keepalived) can then be used within the servers to perform health checks and
* manage IP failover. * manage IP failover.
*/ */
void shareIp(String addressToShare, int serverToTosignBindressTo, int sharedIpGroup, void shareIp(String addressToShare, int serverToTosignBindressTo, int sharedIpGroup, boolean configureServer);
boolean configureServer);
/** /**
* This operation removes a shared IP address from the specified server. * This operation removes a shared IP address from the specified server.

View File

@ -19,28 +19,58 @@
package org.jclouds.cloudservers.domain; 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 { public class Limits {
private List<RateLimit> rate = Lists.newArrayList(); private Set<RateLimit> rate = Sets.newLinkedHashSet();
private List<AbsoluteLimit> absolute = Lists.newArrayList(); private Map<String, Integer> absolute = Maps.newLinkedHashMap();
public void setRate(List<RateLimit> rate) { public Set<RateLimit> getRate() {
this.rate = rate;
}
public List<RateLimit> getRate() {
return rate; return rate;
} }
public void setAbsolute(List<AbsoluteLimit> absolute) { @Override
this.absolute = absolute; public String toString() {
return "Limits [rate=" + rate + ", absolute=" + absolute + "]";
} }
public List<AbsoluteLimit> 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<String, Integer> getAbsolute() {
return absolute; return absolute;
} }

View File

@ -19,8 +19,6 @@
package org.jclouds.cloudservers.domain; package org.jclouds.cloudservers.domain;
import javax.ws.rs.HttpMethod;
/** /**
* *
* RateLimit. * RateLimit.
@ -40,16 +38,69 @@ import javax.ws.rs.HttpMethod;
*/ */
public class RateLimit { public class RateLimit {
private final String uri; @Override
private final String regex; public int hashCode() {
private final int remaining; final int prime = 31;
private final long resetTime; int result = 1;
private final RateLimitUnit unit; result = prime * result + ((regex == null) ? 0 : regex.hashCode());
private final int value; result = prime * result + remaining;
private final HttpMethod verb; 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, @Override
int value, HttpMethod verb) { 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.uri = uri;
this.regex = regex; this.regex = regex;
this.remaining = remaining; this.remaining = remaining;
@ -83,8 +134,14 @@ public class RateLimit {
return value; return value;
} }
public HttpMethod getVerb() { public String getVerb() {
return verb; return verb;
} }
@Override
public String toString() {
return "[uri=" + uri + ", regex=" + regex + ", remaining=" + remaining + ", resetTime=" + resetTime + ", unit="
+ unit + ", value=" + value + ", verb=" + verb + "]";
}
} }

View File

@ -199,6 +199,21 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
checkFilters(request); checkFilters(request);
} }
public void testLimits() throws IOException, SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("getLimits");
HttpRequest request = processor.createRequest(method);
assertRequestLineEquals(request, "GET http://serverManagementUrl/limits?format=json HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Accept: application/json\n");
assertPayloadEquals(request, null, null, false);
assertResponseParserClassEquals(method, request, UnwrapOnlyJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(request);
}
public void testListServers() throws IOException, SecurityException, NoSuchMethodException { public void testListServers() throws IOException, SecurityException, NoSuchMethodException {
Method method = CloudServersAsyncClient.class.getMethod("listServers", listOptionsVarargsClass); Method method = CloudServersAsyncClient.class.getMethod("listServers", listOptionsVarargsClass);
HttpRequest request = processor.createRequest(method); HttpRequest request = processor.createRequest(method);

View File

@ -41,6 +41,7 @@ import org.jclouds.cloudservers.domain.DailyBackup;
import org.jclouds.cloudservers.domain.Flavor; import org.jclouds.cloudservers.domain.Flavor;
import org.jclouds.cloudservers.domain.Image; import org.jclouds.cloudservers.domain.Image;
import org.jclouds.cloudservers.domain.ImageStatus; import org.jclouds.cloudservers.domain.ImageStatus;
import org.jclouds.cloudservers.domain.Limits;
import org.jclouds.cloudservers.domain.RebootType; import org.jclouds.cloudservers.domain.RebootType;
import org.jclouds.cloudservers.domain.Server; import org.jclouds.cloudservers.domain.Server;
import org.jclouds.cloudservers.domain.ServerStatus; import org.jclouds.cloudservers.domain.ServerStatus;
@ -92,7 +93,7 @@ public class CloudServersClientLiveTest {
protected void setupCredentials() { protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"); identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential"); + ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint"); endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion"); apiversion = System.getProperty("test." + provider + ".apiversion");
} }
@ -116,8 +117,7 @@ public class CloudServersClientLiveTest {
Properties overrides = setupProperties(); Properties overrides = setupProperties();
Injector injector = new RestContextFactory().createContextBuilder(provider, Injector injector = new RestContextFactory().createContextBuilder(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new JschSshClientModule()), overrides) ImmutableSet.<Module> of(new Log4JLoggingModule(), new JschSshClientModule()), overrides).buildInjector();
.buildInjector();
client = injector.getInstance(CloudServersClient.class); client = injector.getInstance(CloudServersClient.class);
sshFactory = injector.getInstance(SshClient.Factory.class); sshFactory = injector.getInstance(SshClient.Factory.class);
@ -126,6 +126,13 @@ public class CloudServersClientLiveTest {
injector.injectMembers(socketOpen); // add logger 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 { public void testListServers() throws Exception {
Set<Server> response = client.listServers(); Set<Server> response = client.listServers();
@ -323,8 +330,8 @@ public class CloudServersClientLiveTest {
while (server == null) { while (server == null) {
String serverName = serverPrefix + "createserver" + new SecureRandom().nextInt(); String serverName = serverPrefix + "createserver" + new SecureRandom().nextInt();
try { try {
server = client.createServer(serverName, imageId, flavorId, withFile("/etc/jclouds.txt", server = client.createServer(serverName, imageId, flavorId,
"rackspace".getBytes()).withMetadata(metadata)); withFile("/etc/jclouds.txt", "rackspace".getBytes()).withMetadata(metadata));
} catch (UndeclaredThrowableException e) { } catch (UndeclaredThrowableException e) {
HttpResponseException htpe = (HttpResponseException) e.getCause().getCause(); HttpResponseException htpe = (HttpResponseException) e.getCause().getCause();
if (htpe.getResponse().getStatusCode() == 400) if (htpe.getResponse().getStatusCode() == 400)
@ -343,7 +350,7 @@ public class CloudServersClientLiveTest {
private void blockUntilServerActive(int serverId) throws InterruptedException { private void blockUntilServerActive(int serverId) throws InterruptedException {
Server currentDetails = null; Server currentDetails = null;
for (currentDetails = client.getServer(serverId); currentDetails.getStatus() != ServerStatus.ACTIVE; currentDetails = client 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); System.out.printf("blocking on status active%n%s%n", currentDetails);
Thread.sleep(5 * 1000); Thread.sleep(5 * 1000);
} }
@ -352,7 +359,7 @@ public class CloudServersClientLiveTest {
private void blockUntilServerVerifyResize(int serverId) throws InterruptedException { private void blockUntilServerVerifyResize(int serverId) throws InterruptedException {
Server currentDetails = null; Server currentDetails = null;
for (currentDetails = client.getServer(serverId); currentDetails.getStatus() != ServerStatus.VERIFY_RESIZE; currentDetails = client 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); System.out.printf("blocking on status verify resize%n%s%n", currentDetails);
Thread.sleep(5 * 1000); Thread.sleep(5 * 1000);
} }
@ -361,7 +368,7 @@ public class CloudServersClientLiveTest {
private void blockUntilImageActive(int imageId) throws InterruptedException { private void blockUntilImageActive(int imageId) throws InterruptedException {
Image currentDetails = null; Image currentDetails = null;
for (currentDetails = client.getImage(imageId); currentDetails.getStatus() != ImageStatus.ACTIVE; currentDetails = client 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); System.out.printf("blocking on status active%n%s%n", currentDetails);
Thread.sleep(5 * 1000); Thread.sleep(5 * 1000);
} }
@ -459,9 +466,12 @@ public class CloudServersClientLiveTest {
while (server == null) { while (server == null) {
String serverName = serverPrefix + "createserver" + new SecureRandom().nextInt(); String serverName = serverPrefix + "createserver" + new SecureRandom().nextInt();
try { try {
server = client server = client.createServer(
.createServer(serverName, imageId, flavorId, withFile("/etc/jclouds.txt", "rackspace".getBytes()) serverName,
.withMetadata(metadata).withSharedIpGroup(sharedIpGroupId).withSharedIp(ip)); imageId,
flavorId,
withFile("/etc/jclouds.txt", "rackspace".getBytes()).withMetadata(metadata)
.withSharedIpGroup(sharedIpGroupId).withSharedIp(ip));
} catch (UndeclaredThrowableException e) { } catch (UndeclaredThrowableException e) {
HttpResponseException htpe = (HttpResponseException) e.getCause().getCause(); HttpResponseException htpe = (HttpResponseException) e.getCause().getCause();
if (htpe.getResponse().getStatusCode() == 400) if (htpe.getResponse().getStatusCode() == 400)
@ -482,7 +492,7 @@ public class CloudServersClientLiveTest {
try { try {
ExecResponse response = exec(server, password, "ifconfig -a"); 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, assert response.getOutput().indexOf(ip) > 0 : String.format("server %s didn't get ip %s%n%s", server, ip,
response); response);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} catch (AssertionError e) { } catch (AssertionError e) {
@ -503,7 +513,7 @@ public class CloudServersClientLiveTest {
try { try {
ExecResponse response = exec(server, password, "ifconfig -a"); 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, assert response.getOutput().indexOf(ip) == -1 : String.format("server %s still has get ip %s%n%s", server, ip,
response); response);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} catch (AssertionError e) { } catch (AssertionError e) {
@ -592,7 +602,7 @@ public class CloudServersClientLiveTest {
} }
@Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = { "testRebootSoft", "testRevertResize", @Test(enabled = false, timeOut = 10 * 60 * 1000, dependsOnMethods = { "testRebootSoft", "testRevertResize",
"testConfirmResize" }) "testConfirmResize" })
void deleteServer2() { void deleteServer2() {
if (serverId2 > 0) { if (serverId2 > 0) {
client.deleteServer(serverId2); client.deleteServer(serverId2);