mirror of https://github.com/apache/jclouds.git
Issue 77: added support for flavors
git-svn-id: http://jclouds.googlecode.com/svn/trunk@1635 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
b25f3fbed7
commit
f5e52178f9
|
@ -30,7 +30,9 @@ import java.util.concurrent.Future;
|
|||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
|
||||
import org.jclouds.rackspace.cloudservers.domain.Flavor;
|
||||
import org.jclouds.rackspace.cloudservers.domain.Server;
|
||||
import org.jclouds.rackspace.cloudservers.functions.ParseFlavorListFromGsonResponse;
|
||||
import org.jclouds.rackspace.cloudservers.functions.ParseServerListFromGsonResponse;
|
||||
import org.jclouds.rackspace.filters.AuthenticateRequest;
|
||||
import org.jclouds.rest.Query;
|
||||
|
@ -61,24 +63,48 @@ public interface CloudServersConnection {
|
|||
@ResponseParser(ParseServerListFromGsonResponse.class)
|
||||
@Query(key = "format", value = "json")
|
||||
@Path("/servers")
|
||||
// TODO: Error Response Code(s): cloudServersFault (400, 500), serviceUnavailable (503),
|
||||
// unauthorized (401), badRequest (400), overLimit (413)
|
||||
List<Server> listServers();
|
||||
|
||||
/**
|
||||
* This operation provides a list of servers associated with your account. Servers that have been
|
||||
* deleted are not included in this list. Servers contain a status attribute that can be used as
|
||||
* an indication of the current server state. Servers with an ACTIVE status are available for
|
||||
* use. Other possible values for the status attribute include: BUILD, REBUILD, SUSPENDED,
|
||||
* QUEUE_RESIZE, PREP_RESIZE, VERIFY_RESIZE, PASSWORD, RESCUE, REBOOT, HARD_REBOOT, SHARE_IP,
|
||||
* SHARE_IP_NO_CONFIG, DELETE_IP, and UNKNOWN. The Cloud Servers provisioning algorithm has an
|
||||
* anti-affinity property that attempts to spread out customer VMs across hosts. Under certain
|
||||
* situations, VMs from the same customer may be placed on the same host. hostId represents the
|
||||
* host your cloud server runs on and can be used to determine this scenario if it's relevant to
|
||||
* your application. Note: hostId is unique PER ACCOUNT and is not globally unique.
|
||||
* deleted are not included in this list.
|
||||
*/
|
||||
@GET
|
||||
@ResponseParser(ParseServerListFromGsonResponse.class)
|
||||
@Query(key = "format", value = "json")
|
||||
@Path("/servers/detail")
|
||||
// TODO: Error Response Code(s): cloudServersFault (400, 500), serviceUnavailable (503),
|
||||
// unauthorized (401), badRequest (400), overLimit (413)
|
||||
List<Server> listServerDetails();
|
||||
|
||||
/**
|
||||
*
|
||||
* List available flavors (IDs and names only)
|
||||
*
|
||||
* @see #listFlavorDetails()
|
||||
*/
|
||||
@GET
|
||||
@ResponseParser(ParseFlavorListFromGsonResponse.class)
|
||||
@Query(key = "format", value = "json")
|
||||
@Path("/flavors")
|
||||
// TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
|
||||
// (400)
|
||||
List<Flavor> listFlavors();
|
||||
|
||||
/**
|
||||
*
|
||||
* List available flavors (all details)
|
||||
*
|
||||
* @see Flavor
|
||||
*/
|
||||
@GET
|
||||
@ResponseParser(ParseFlavorListFromGsonResponse.class)
|
||||
@Query(key = "format", value = "json")
|
||||
@Path("/flavors/detail")
|
||||
// TODO: cloudServersFault (400, 500), serviceUnavailable (503), unauthorized (401), badRequest
|
||||
// (400)
|
||||
List<Flavor> listFlavorDetails();
|
||||
|
||||
}
|
||||
|
|
|
@ -24,49 +24,103 @@
|
|||
|
||||
package org.jclouds.rackspace.cloudservers.domain;
|
||||
|
||||
/**
|
||||
*
|
||||
* A flavor is an available hardware configuration for a server. Each flavor has a unique
|
||||
* combination of disk space, memory capacity, and priority for CPU time.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class Flavor {
|
||||
|
||||
public Flavor(int id, String name) {
|
||||
super();
|
||||
public Flavor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Flavor [disk=" + disk + ", id=" + id + ", name=" + name + ", ram=" + ram + "]";
|
||||
}
|
||||
|
||||
public Flavor(int id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected Integer disk;
|
||||
protected int id;
|
||||
protected String name;
|
||||
protected Integer ram;
|
||||
private int id;
|
||||
private String name;
|
||||
private Integer disk;
|
||||
private Integer ram;
|
||||
|
||||
|
||||
public Integer getDisk() {
|
||||
return disk;
|
||||
}
|
||||
public Integer getDisk() {
|
||||
return disk;
|
||||
}
|
||||
|
||||
public void setDisk(Integer value) {
|
||||
this.disk = value;
|
||||
}
|
||||
public void setDisk(Integer value) {
|
||||
this.disk = value;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int value) {
|
||||
this.id = value;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setId(int value) {
|
||||
this.id = value;
|
||||
}
|
||||
|
||||
public void setName(String value) {
|
||||
this.name = value;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Integer getRam() {
|
||||
return ram;
|
||||
}
|
||||
public void setName(String value) {
|
||||
this.name = value;
|
||||
}
|
||||
|
||||
public void setRam(Integer value) {
|
||||
this.ram = value;
|
||||
}
|
||||
public Integer getRam() {
|
||||
return ram;
|
||||
}
|
||||
|
||||
public void setRam(Integer value) {
|
||||
this.ram = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((disk == null) ? 0 : disk.hashCode());
|
||||
result = prime * result + id;
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((ram == null) ? 0 : ram.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;
|
||||
Flavor other = (Flavor) obj;
|
||||
if (disk == null) {
|
||||
if (other.disk != null)
|
||||
return false;
|
||||
} else if (!disk.equals(other.disk))
|
||||
return false;
|
||||
if (id != other.id)
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
if (ram == null) {
|
||||
if (other.ram != null)
|
||||
return false;
|
||||
} else if (!ram.equals(other.ram))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,13 @@ import java.util.Map;
|
|||
import com.google.inject.internal.Lists;
|
||||
import com.google.inject.internal.Maps;
|
||||
|
||||
/**
|
||||
*
|
||||
* Server.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
* @since 4.0
|
||||
*/
|
||||
public class Server {
|
||||
private int id;
|
||||
private String name;
|
||||
|
@ -98,6 +105,14 @@ public class Server {
|
|||
this.hostId = hostId;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Cloud Servers provisioning algorithm has an anti-affinity property that attempts to spread
|
||||
* out customer VMs across hosts. Under certain situations, VMs from the same customer may be
|
||||
* placed on the same host. hostId represents the host your cloud server runs on and can be used
|
||||
* to determine this scenario if it's relevant to your application.
|
||||
* <p/>
|
||||
* Note: hostId is unique PER ACCOUNT and is not globally unique.
|
||||
*/
|
||||
public String getHostId() {
|
||||
return hostId;
|
||||
}
|
||||
|
@ -138,6 +153,10 @@ public class Server {
|
|||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Servers contain a status attribute that can be used as an indication of the current server
|
||||
* state. Servers with an ACTIVE status are available for use.
|
||||
*/
|
||||
public ServerStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,13 @@
|
|||
*/
|
||||
package org.jclouds.rackspace.cloudservers.domain;
|
||||
|
||||
/**
|
||||
*
|
||||
* Servers contain a status attribute that can be used as an indication of the current server state.
|
||||
* Servers with an ACTIVE status are available for use.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public enum ServerStatus {
|
||||
|
||||
ACTIVE, SUSPENDED, DELETED, QUEUE_RESIZE, PREP_RESIZE, RESIZE, VERIFY_RESIZE, QUEUE_MOVE, PREP_MOVE, MOVE, VERIFY_MOVE, RESCUE, ERROR, BUILD, RESTORING, PASSWORD, REBUILD, DELETE_IP, SHARE_IP_NO_CONFIG, SHARE_IP, REBOOT, HARD_REBOOT, UNKNOWN;
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudservers.functions;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.http.functions.ParseJson;
|
||||
import org.jclouds.rackspace.cloudservers.domain.Flavor;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.internal.Lists;
|
||||
|
||||
/**
|
||||
* This parses {@link Flavor} from a gson string.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class ParseFlavorListFromGsonResponse extends ParseJson<List<Flavor>> {
|
||||
|
||||
@Inject
|
||||
public ParseFlavorListFromGsonResponse(Gson gson) {
|
||||
super(gson);
|
||||
}
|
||||
|
||||
private static class FlavorListResponse {
|
||||
List<Flavor> flavors = Lists.newArrayList();
|
||||
}
|
||||
|
||||
public List<Flavor> apply(InputStream stream) {
|
||||
|
||||
try {
|
||||
return gson.fromJson(new InputStreamReader(stream, "UTF-8"), FlavorListResponse.class).flavors;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("jclouds requires UTF-8 encoding", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@ import static org.testng.Assert.assertTrue;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.rackspace.cloudservers.domain.Flavor;
|
||||
import org.jclouds.rackspace.cloudservers.domain.Server;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@ -65,4 +66,34 @@ public class CloudServersConnectionLiveTest {
|
|||
assertTrue(initialContainerCount >= 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListFlavors() throws Exception {
|
||||
CloudServersConnection connection = CloudServersContextBuilder.newBuilder(sysRackspaceUser,
|
||||
sysRackspaceKey).withJsonDebug().buildContext().getConnection();
|
||||
List<Flavor> response = connection.listFlavors();
|
||||
assertNotNull(response);
|
||||
long flavorCount = response.size();
|
||||
assertTrue(flavorCount >= 1);
|
||||
for (Flavor flavor : response) {
|
||||
assertTrue(flavor.getId() >= 0);
|
||||
assertNotNull(flavor.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListFlavorsDetail() throws Exception {
|
||||
CloudServersConnection connection = CloudServersContextBuilder.newBuilder(sysRackspaceUser,
|
||||
sysRackspaceKey).withJsonDebug().buildContext().getConnection();
|
||||
List<Flavor> response = connection.listFlavorDetails();
|
||||
assertNotNull(response);
|
||||
long flavorCount = response.size();
|
||||
assertTrue(flavorCount >= 0);
|
||||
for (Flavor flavor : response) {
|
||||
assertTrue(flavor.getId() >= 1);
|
||||
assertNotNull(flavor.getName());
|
||||
assertNotNull(flavor.getDisk());
|
||||
assertNotNull(flavor.getRam());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.jclouds.http.HttpMethod;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
||||
import org.jclouds.rackspace.Authentication;
|
||||
import org.jclouds.rackspace.cloudservers.functions.ParseFlavorListFromGsonResponse;
|
||||
import org.jclouds.rackspace.cloudservers.functions.ParseServerListFromGsonResponse;
|
||||
import org.jclouds.rest.JaxrsAnnotationProcessor;
|
||||
import org.jclouds.rest.config.JaxrsModule;
|
||||
|
@ -86,6 +87,38 @@ public class CloudServersConnectionTest {
|
|||
|
||||
}
|
||||
|
||||
public void testListFlavors() throws SecurityException, NoSuchMethodException {
|
||||
Method method = CloudServersConnection.class.getMethod("listFlavors");
|
||||
URI endpoint = URI.create("http://localhost");
|
||||
HttpRequest httpMethod = factory.create(CloudServersConnection.class).createRequest(endpoint,
|
||||
method, new Object[] {});
|
||||
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
|
||||
assertEquals(httpMethod.getEndpoint().getPath(), "/flavors");
|
||||
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
||||
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
||||
assertEquals(httpMethod.getHeaders().size(), 0);
|
||||
factory.create(CloudServersConnection.class);
|
||||
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
||||
ParseFlavorListFromGsonResponse.class);
|
||||
|
||||
}
|
||||
|
||||
public void testListFlavorsDetail() throws SecurityException, NoSuchMethodException {
|
||||
Method method = CloudServersConnection.class.getMethod("listFlavorDetails");
|
||||
URI endpoint = URI.create("http://localhost");
|
||||
HttpRequest httpMethod = factory.create(CloudServersConnection.class).createRequest(endpoint,
|
||||
method, new Object[] {});
|
||||
assertEquals(httpMethod.getEndpoint().getHost(), "localhost");
|
||||
assertEquals(httpMethod.getEndpoint().getPath(), "/flavors/detail");
|
||||
assertEquals(httpMethod.getEndpoint().getQuery(), "format=json");
|
||||
assertEquals(httpMethod.getMethod(), HttpMethod.GET);
|
||||
assertEquals(httpMethod.getHeaders().size(), 0);
|
||||
factory.create(CloudServersConnection.class);
|
||||
assertEquals(JaxrsAnnotationProcessor.getParserOrThrowException(method),
|
||||
ParseFlavorListFromGsonResponse.class);
|
||||
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
void setupFactory() {
|
||||
factory = Guice.createInjector(new AbstractModule() {
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.rackspace.cloudservers.functions;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.List;
|
||||
|
||||
import org.jclouds.http.functions.config.ParserModule;
|
||||
import org.jclouds.rackspace.cloudservers.domain.Flavor;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
|
||||
/**
|
||||
* Tests behavior of {@code ParseFlavorListFromGsonResponseTest}
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "cloudFlavors.ParseFlavorListFromGsonResponseTest")
|
||||
public class ParseFlavorListFromGsonResponseTest {
|
||||
|
||||
Injector i = Guice.createInjector(new ParserModule());
|
||||
|
||||
public void testApplyInputStream() {
|
||||
InputStream is = getClass().getResourceAsStream("/test_list_flavors.json");
|
||||
|
||||
List<Flavor> expects = ImmutableList.of(new Flavor(1, "256 MB Server"), new Flavor(2,
|
||||
"512 MB Server"));
|
||||
|
||||
ParseFlavorListFromGsonResponse parser = new ParseFlavorListFromGsonResponse(i
|
||||
.getInstance(Gson.class));
|
||||
assertEquals(parser.apply(is), expects);
|
||||
}
|
||||
|
||||
public void testApplyInputStreamDetails() throws UnknownHostException {
|
||||
InputStream is = getClass().getResourceAsStream("/test_list_flavors_detail.json");
|
||||
|
||||
ParseFlavorListFromGsonResponse parser = new ParseFlavorListFromGsonResponse(i
|
||||
.getInstance(Gson.class));
|
||||
List<Flavor> response = parser.apply(is);
|
||||
assertEquals(response.get(0).getId(), 1);
|
||||
assertEquals(response.get(0).getName(), "256 MB Server");
|
||||
assertEquals(response.get(0).getDisk(), new Integer(10));
|
||||
assertEquals(response.get(0).getRam(), new Integer(256));
|
||||
|
||||
assertEquals(response.get(1).getId(), 2);
|
||||
assertEquals(response.get(1).getName(), "512 MB Server");
|
||||
assertEquals(response.get(1).getDisk(), new Integer(20));
|
||||
assertEquals(response.get(1).getRam(), new Integer(512));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"flavors" : [
|
||||
{
|
||||
"id" : 1,
|
||||
"name" : "256 MB Server"
|
||||
},
|
||||
{
|
||||
"id" : 2,
|
||||
"name" : "512 MB Server"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"flavors" : [
|
||||
{
|
||||
"id" : 1,
|
||||
"name" : "256 MB Server",
|
||||
"ram" : 256,
|
||||
"disk" : 10
|
||||
},
|
||||
{
|
||||
"id" : 2,
|
||||
"name" : "512 MB Server",
|
||||
"ram" : 512,
|
||||
"disk" : 20
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue