mirror of https://github.com/apache/jclouds.git
Merge pull request #1065 from i11/master
Add flavor create and delete API calls for openstack-nova
This commit is contained in:
commit
6a6214d1c5
|
@ -18,6 +18,9 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.openstack.nova.v2_0.domain;
|
package org.jclouds.openstack.nova.v2_0.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.beans.ConstructorProperties;
|
import java.beans.ConstructorProperties;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -34,7 +37,7 @@ import com.google.common.base.Optional;
|
||||||
* A flavor is an available hardware configuration for a server. Each flavor has
|
* A flavor is an available hardware configuration for a server. Each flavor has
|
||||||
* a unique combination of disk space and memory capacity.
|
* a unique combination of disk space and memory capacity.
|
||||||
*
|
*
|
||||||
* @author Jeremy Daggett
|
* @author Jeremy Daggett, Ilja Bobkevic
|
||||||
* @see <a href=
|
* @see <a href=
|
||||||
"http://docs.openstack.org/api/openstack-compute/2/content/List_Flavors-d1e4188.html"
|
"http://docs.openstack.org/api/openstack-compute/2/content/List_Flavors-d1e4188.html"
|
||||||
/>
|
/>
|
||||||
|
@ -139,9 +142,11 @@ public class Flavor extends Resource {
|
||||||
@ConstructorProperties({
|
@ConstructorProperties({
|
||||||
"id", "name", "links", "ram", "disk", "vcpus", "swap", "rxtx_factor", "OS-FLV-EXT-DATA:ephemeral"
|
"id", "name", "links", "ram", "disk", "vcpus", "swap", "rxtx_factor", "OS-FLV-EXT-DATA:ephemeral"
|
||||||
})
|
})
|
||||||
protected Flavor(String id, @Nullable String name, java.util.Set<Link> links, int ram, int disk, int vcpus,
|
protected Flavor(String id, String name, java.util.Set<Link> links, int ram, int disk, int vcpus,
|
||||||
@Nullable String swap, @Nullable Double rxtxFactor, @Nullable Integer ephemeral) {
|
@Nullable String swap, @Nullable Double rxtxFactor, @Nullable Integer ephemeral) {
|
||||||
super(id, name, links);
|
super(id, checkNotNull(name, "name"), links);
|
||||||
|
checkArgument(ram > 0, "Value of ram has to greater than 0");
|
||||||
|
checkArgument(vcpus > 0, "Value of vcpus has to greater than 0");
|
||||||
this.ram = ram;
|
this.ram = ram;
|
||||||
this.disk = disk;
|
this.disk = disk;
|
||||||
this.vcpus = vcpus;
|
this.vcpus = vcpus;
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.jclouds.openstack.v2_0.options.PaginationOptions;
|
||||||
* @see <a href=
|
* @see <a href=
|
||||||
* "http://docs.openstack.org/api/openstack-compute/2/content/List_Flavors-d1e4188.html"
|
* "http://docs.openstack.org/api/openstack-compute/2/content/List_Flavors-d1e4188.html"
|
||||||
* />
|
* />
|
||||||
* @author Jeremy Daggett
|
* @author Jeremy Daggett, Ilja Bobkevic
|
||||||
*/
|
*/
|
||||||
public interface FlavorApi {
|
public interface FlavorApi {
|
||||||
|
|
||||||
|
@ -63,4 +63,18 @@ public interface FlavorApi {
|
||||||
*/
|
*/
|
||||||
Flavor get(String id);
|
Flavor get(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create flavor according to the provided object
|
||||||
|
*
|
||||||
|
* @param flavor - flavor object
|
||||||
|
* @return newly created flavor
|
||||||
|
*/
|
||||||
|
Flavor create(Flavor flavor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete flavor with a given id
|
||||||
|
*
|
||||||
|
* @param id - flavor id
|
||||||
|
*/
|
||||||
|
void delete(String id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,17 @@ package org.jclouds.openstack.nova.v2_0.features;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
|
import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
|
||||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
||||||
|
import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
|
||||||
import org.jclouds.collect.PagedIterable;
|
import org.jclouds.collect.PagedIterable;
|
||||||
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
|
import org.jclouds.openstack.keystone.v2_0.KeystoneFallbacks.EmptyPaginatedCollectionOnNotFoundOr404;
|
||||||
import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
|
import org.jclouds.openstack.keystone.v2_0.domain.PaginatedCollection;
|
||||||
|
@ -41,6 +45,8 @@ import org.jclouds.rest.annotations.RequestFilters;
|
||||||
import org.jclouds.rest.annotations.ResponseParser;
|
import org.jclouds.rest.annotations.ResponseParser;
|
||||||
import org.jclouds.rest.annotations.SelectJson;
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
import org.jclouds.rest.annotations.Transform;
|
import org.jclouds.rest.annotations.Transform;
|
||||||
|
import org.jclouds.rest.annotations.Unwrap;
|
||||||
|
import org.jclouds.rest.annotations.WrapWith;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
@ -54,6 +60,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||||
* >docs</a>
|
* >docs</a>
|
||||||
* @author Jeremy Daggett TODO: Need a ListFlavorOptions class minDisk=minDiskInGB&
|
* @author Jeremy Daggett TODO: Need a ListFlavorOptions class minDisk=minDiskInGB&
|
||||||
* minRam=minRamInMB& marker=markerID&limit=int
|
* minRam=minRamInMB& marker=markerID&limit=int
|
||||||
|
* @author Ilja Bobkevic
|
||||||
*/
|
*/
|
||||||
@RequestFilters(AuthenticateRequest.class)
|
@RequestFilters(AuthenticateRequest.class)
|
||||||
public interface FlavorAsyncApi {
|
public interface FlavorAsyncApi {
|
||||||
|
@ -115,4 +122,25 @@ public interface FlavorAsyncApi {
|
||||||
@Fallback(NullOnNotFoundOr404.class)
|
@Fallback(NullOnNotFoundOr404.class)
|
||||||
ListenableFuture<? extends Flavor> get(@PathParam("id") String id);
|
ListenableFuture<? extends Flavor> get(@PathParam("id") String id);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see FlavorApi#create
|
||||||
|
*/
|
||||||
|
@Named("flavor:create")
|
||||||
|
@POST
|
||||||
|
@Unwrap
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("/flavors")
|
||||||
|
ListenableFuture<? extends Flavor> create(@WrapWith("flavor") Flavor flavor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see FlavorApi#delete
|
||||||
|
*/
|
||||||
|
@Named("flavor:delete")
|
||||||
|
@DELETE
|
||||||
|
@Consumes
|
||||||
|
@Path("/flavors/{id}")
|
||||||
|
@Fallback(VoidOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<Void> delete(@PathParam("id") String id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,16 @@ import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertNull;
|
import static org.testng.Assert.assertNull;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import javax.ws.rs.HttpMethod;
|
||||||
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.openstack.nova.v2_0.NovaApi;
|
import org.jclouds.openstack.nova.v2_0.NovaApi;
|
||||||
|
import org.jclouds.openstack.nova.v2_0.domain.Flavor;
|
||||||
import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiExpectTest;
|
import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiExpectTest;
|
||||||
|
import org.jclouds.openstack.nova.v2_0.parse.ParseCreateFlavorTest;
|
||||||
import org.jclouds.openstack.nova.v2_0.parse.ParseFlavorListTest;
|
import org.jclouds.openstack.nova.v2_0.parse.ParseFlavorListTest;
|
||||||
import org.jclouds.openstack.nova.v2_0.parse.ParseFlavorTest;
|
import org.jclouds.openstack.nova.v2_0.parse.ParseFlavorTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -35,7 +41,7 @@ import com.google.common.collect.ImmutableSet;
|
||||||
/**
|
/**
|
||||||
* Tests annotation parsing of {@code FlavorAsyncApi}
|
* Tests annotation parsing of {@code FlavorAsyncApi}
|
||||||
*
|
*
|
||||||
* @author Jeremy Daggett
|
* @author Jeremy Daggett, Ilja Bobkevic
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "FlavorApiExpectTest")
|
@Test(groups = "unit", testName = "FlavorApiExpectTest")
|
||||||
public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
|
public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
|
||||||
|
@ -115,4 +121,46 @@ public class FlavorApiExpectTest extends BaseNovaApiExpectTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCreateFlavor200() throws Exception {
|
||||||
|
ParseCreateFlavorTest parser = new ParseCreateFlavorTest();
|
||||||
|
HttpRequest listFlavors = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method(HttpMethod.POST)
|
||||||
|
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors")
|
||||||
|
.addHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON)
|
||||||
|
.addHeader("X-Auth-Token", authToken)
|
||||||
|
.payload(payloadFromResource(parser.resource())).build();
|
||||||
|
|
||||||
|
HttpResponse listFlavorsResponse = HttpResponse.builder().statusCode(200)
|
||||||
|
.payload(payloadFromResource(parser.resource())).build();
|
||||||
|
|
||||||
|
NovaApi api = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
|
||||||
|
responseWithKeystoneAccess, listFlavors, listFlavorsResponse);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
api.getFlavorApiForZone("az-1.region-a.geo-1").create(Flavor.builder()
|
||||||
|
.id("1cb47a44-9b84-4da4-bf81-c1976e8414ab")
|
||||||
|
.name("128 MB Server").ram(128).vcpus(1)
|
||||||
|
.disk(10).build())
|
||||||
|
.toString(), parser.expected().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeleteFlavor202() throws Exception {
|
||||||
|
String flavorId = "1cb47a44-9b84-4da4-bf81-c1976e8414ab";
|
||||||
|
|
||||||
|
HttpRequest updateMetadata = HttpRequest
|
||||||
|
.builder()
|
||||||
|
.method(HttpMethod.DELETE)
|
||||||
|
.endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/flavors/" + flavorId)
|
||||||
|
.addHeader(HttpHeaders.ACCEPT, MediaType.WILDCARD)
|
||||||
|
.addHeader("X-Auth-Token", authToken)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HttpResponse updateMetadataResponse = HttpResponse.builder().statusCode(204).build();
|
||||||
|
|
||||||
|
NovaApi api = requestsSendResponses(keystoneAuthWithUsernameAndPasswordAndTenantName,
|
||||||
|
responseWithKeystoneAccess, updateMetadata, updateMetadataResponse);
|
||||||
|
|
||||||
|
api.getFlavorApiForZone("az-1.region-a.geo-1").delete(flavorId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/**
|
||||||
|
* 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.v2_0.parse;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.jclouds.json.BaseItemParserTest;
|
||||||
|
import org.jclouds.json.config.GsonModule;
|
||||||
|
import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
|
||||||
|
import org.jclouds.openstack.nova.v2_0.domain.Flavor;
|
||||||
|
import org.jclouds.openstack.nova.v2_0.features.FlavorApiExpectTest;
|
||||||
|
import org.jclouds.rest.annotations.SelectJson;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see FlavorApiExpectTest
|
||||||
|
* @author Ilja Bobkevic
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", testName = "ParseCreateFlavorTest")
|
||||||
|
public class ParseCreateFlavorTest extends BaseItemParserTest<Flavor> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String resource() {
|
||||||
|
return "/flavor_new.json";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SelectJson("flavor")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Flavor expected() {
|
||||||
|
return Flavor.builder()
|
||||||
|
.id("1cb47a44-9b84-4da4-bf81-c1976e8414ab")
|
||||||
|
.name("128 MB Server").ram(128).vcpus(1)
|
||||||
|
.disk(10).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Injector injector() {
|
||||||
|
return Guice.createInjector(new NovaParserModule(), new GsonModule());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"flavor" : {
|
||||||
|
"id" : "1cb47a44-9b84-4da4-bf81-c1976e8414ab",
|
||||||
|
"name" : "128 MB Server",
|
||||||
|
"ram" : 128,
|
||||||
|
"disk" : 10,
|
||||||
|
"vcpus" : 1,
|
||||||
|
"links" : []
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue