From 0821b027263e701c5cb3ea51fe6bcbe8a8cba3d3 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Wed, 18 Jan 2012 15:50:30 +0000 Subject: [PATCH] Add createPod and deletePod --- .../features/GlobalPodAsyncClient.java | 49 +++++++++++++++++ .../cloudstack/features/GlobalPodClient.java | 33 ++++++++++++ .../cloudstack/options/CreatePodOptions.java | 47 ++++++++++++++++ .../features/GlobalPodClientExpectTest.java | 53 +++++++++++++++++++ .../features/GlobalPodClientLiveTest.java | 39 ++++++++++++++ .../options/CreatePodOptionsTest.java | 46 ++++++++++++++++ .../src/test/resources/createpodresponse.json | 1 + 7 files changed, 268 insertions(+) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreatePodOptions.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/CreatePodOptionsTest.java create mode 100644 apis/cloudstack/src/test/resources/createpodresponse.json diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalPodAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalPodAsyncClient.java index 6fe4d09b25..46d7807aeb 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalPodAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalPodAsyncClient.java @@ -21,6 +21,7 @@ package org.jclouds.cloudstack.features; import com.google.common.util.concurrent.ListenableFuture; import org.jclouds.cloudstack.domain.Pod; import org.jclouds.cloudstack.filters.QuerySigner; +import org.jclouds.cloudstack.options.CreatePodOptions; import org.jclouds.cloudstack.options.ListPodsOptions; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.OnlyElement; @@ -29,6 +30,7 @@ import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -70,4 +72,51 @@ public interface GlobalPodAsyncClient { @ExceptionParser(ReturnNullOnNotFoundOr404.class) ListenableFuture getPod(@QueryParam("id") long id); + /** + * Creates a new Pod. + * + * @param name the name of the Pod + * @param zoneId the Zone ID in which the Pod will be created + * @param startIp the starting IP address for the Pod + * @param endIp the ending IP address for the Pod + * @param gateway the gateway for the Pod + * @param netmask the netmask for the Pod + * @param createPodOptions optional arguments + * @return the new Pod + */ + @GET + @QueryParams(keys = "command", values = "createPod") + @SelectJson("pod") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture createPod(@QueryParam("name") String name, @QueryParam("zoneid") long zoneId, @QueryParam("startip") String startIp, @QueryParam("endip") String endIp, @QueryParam("gateway") String gateway, @QueryParam("netmask") String netmask, CreatePodOptions... createPodOptions); + + /** + * Creates a new Pod. + * + * @param name the name of the Pod + * @param zoneId the Zone ID in which the Pod will be created + * @param startIp the starting IP address for the Pod + * @param gateway the gateway for the Pod + * @param netmask the netmask for the Pod + * @param createPodOptions optional arguments + * @return the new Pod + */ + @GET + @QueryParams(keys = "command", values = "createPod") + @SelectJson("pod") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture createPod(@QueryParam("name") String name, @QueryParam("zoneid") long zoneId, @QueryParam("startip") String startIp, @QueryParam("gateway") String gateway, @QueryParam("netmask") String netmask, CreatePodOptions... createPodOptions); + + /** + * Deletes a Pod. + * @param id the ID of the Pod + */ + @GET + @QueryParams(keys = "command", values = "deletePod") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture deletePod(@QueryParam("id") long id); + } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalPodClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalPodClient.java index eed13f0da7..e4541c250b 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalPodClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalPodClient.java @@ -19,6 +19,7 @@ package org.jclouds.cloudstack.features; import org.jclouds.cloudstack.domain.Pod; +import org.jclouds.cloudstack.options.CreatePodOptions; import org.jclouds.cloudstack.options.ListPodsOptions; import org.jclouds.concurrent.Timeout; @@ -55,4 +56,36 @@ public interface GlobalPodClient { */ Pod getPod(long id); + /** + * Creates a new Pod. + * + * @param name the name of the Pod + * @param zoneId the Zone ID in which the Pod will be created + * @param startIp the starting IP address for the Pod + * @param endIp the ending IP address for the Pod + * @param gateway the gateway for the Pod + * @param netmask the netmask for the Pod + * @param createPodOptions optional arguments + * @return the new Pod + */ + Pod createPod(String name, long zoneId, String startIp, String endIp, String gateway, String netmask, CreatePodOptions... createPodOptions); + + /** + * Creates a new Pod. + * + * @param name the name of the Pod + * @param zoneId the Zone ID in which the Pod will be created + * @param startIp the starting IP address for the Pod + * @param gateway the gateway for the Pod + * @param netmask the netmask for the Pod + * @param createPodOptions optional arguments + * @return the new Pod + */ + Pod createPod(String name, long zoneId, String startIp, String gateway, String netmask, CreatePodOptions... createPodOptions); + + /** + * Deletes a Pod. + * @param id the ID of the Pod + */ + void deletePod(long id); } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreatePodOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreatePodOptions.java new file mode 100644 index 0000000000..08db00fb2c --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreatePodOptions.java @@ -0,0 +1,47 @@ +/** + * 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.cloudstack.options; + +import com.google.common.collect.ImmutableSet; +import org.jclouds.cloudstack.domain.AllocationState; +import org.jclouds.http.options.BaseHttpRequestOptions; + +/** + * Options to the GlobalPodClient.createPod API call. + * + * @author Richard Downer + */ +public class CreatePodOptions extends BaseHttpRequestOptions { + + public static final CreatePodOptions NONE = new CreatePodOptions(); + + public static class Builder { + + public static CreatePodOptions allocationState(AllocationState allocationState) { + return new CreatePodOptions().allocationState(allocationState); + } + + } + + public CreatePodOptions allocationState(AllocationState allocationState) { + this.queryParameters.replaceValues("allocationstate", ImmutableSet.of(allocationState.toString())); + return this; + } + +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalPodClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalPodClientExpectTest.java index 230d41bc4e..e4274fc3bd 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalPodClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalPodClientExpectTest.java @@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableSet; import org.jclouds.cloudstack.CloudStackContext; import org.jclouds.cloudstack.domain.AllocationState; import org.jclouds.cloudstack.domain.Pod; +import org.jclouds.cloudstack.options.CreatePodOptions; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.testng.annotations.Test; @@ -101,6 +102,58 @@ public class GlobalPodClientExpectTest extends BaseCloudStackRestClientExpectTes assertEquals(client.listPods(), ImmutableSet.of()); } + public void testCreatePodWhenResponseIs2xx() { + GlobalPodClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&command=createPod&netmask=255.255.255.0&name=richard-pod&startip=172.20.0.1&zoneid=10&endip=172.20.0.250&gateway=172.20.0.254&allocationstate=Enabled&apiKey=identity&signature=fwsoQ77BmNQWfuqv4nVlPcKvKbU%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/createpodresponse.json")) + .build()); + + Pod expected = Pod.builder() + .id(6) + .name("richard-pod") + .zoneId(10) + .zoneName("richard-zone") + .gateway("172.20.0.254") + .netmask("255.255.255.0") + .startIp("172.20.0.1") + .endIp("172.20.0.250") + .allocationState(AllocationState.ENABLED) + .build(); + + Pod actual = client.createPod("richard-pod", 10, "172.20.0.1", "172.20.0.250", "172.20.0.254", "255.255.255.0", + CreatePodOptions.Builder.allocationState(AllocationState.ENABLED)); + + assertEquals(actual, expected); + } + + public void testDeletePodWhenResponseIs2xx() { + GlobalPodClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&command=deletePod&id=3&apiKey=identity&signature=rm4ItuAL1Ztnj%2BHFFvBFzvHAIog%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(200) + .build()); + + client.deletePod(3); + } + @Override protected GlobalPodClient clientFrom(CloudStackContext context) { return context.getGlobalContext().getApi().getPodClient(); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalPodClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalPodClientLiveTest.java index a4200fe899..64830c070f 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalPodClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalPodClientLiveTest.java @@ -19,14 +19,20 @@ package org.jclouds.cloudstack.features; import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import org.jclouds.cloudstack.domain.AllocationState; +import org.jclouds.cloudstack.domain.NetworkType; import org.jclouds.cloudstack.domain.Pod; +import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.cloudstack.options.CreatePodOptions; import org.jclouds.cloudstack.options.ListPodsOptions; +import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import java.util.Set; +import static org.jclouds.cloudstack.options.UpdateZoneOptions.Builder.name; import static org.testng.Assert.*; /** @@ -37,6 +43,9 @@ import static org.testng.Assert.*; @Test(groups = "live", singleThreaded = true, testName = "GlobalPodClientLiveTest") public class GlobalPodClientLiveTest extends BaseCloudStackClientLiveTest { + private Zone zone; + private Pod pod; + public void testListPods() throws Exception { Set response = globalAdminClient.getPodClient().listPods(); assert null != response; @@ -59,4 +68,34 @@ public class GlobalPodClientLiveTest extends BaseCloudStackClientLiveTest { } } + @Test + public void testCreatePod() { + assertTrue(globalAdminEnabled, "Global admin credentials must be given"); + + zone = globalAdminClient.getZoneClient().createZone(prefix + "-zone", NetworkType.BASIC, "8.8.8.8", "10.10.10.10"); + pod = globalAdminClient.getPodClient().createPod(prefix + "-pod", zone.getId(), "172.20.0.1", "172.20.0.250", "172.20.0.254", "255.255.255.0", + CreatePodOptions.Builder.allocationState(AllocationState.ENABLED)); + + assertNotNull(pod); + assertEquals(pod.getName(), prefix + "-pod"); + assertEquals(pod.getZoneId(), zone.getId()); + assertEquals(pod.getZoneName(), prefix + "-zone"); + assertEquals(pod.getStartIp(), "172.20.0.1"); + assertEquals(pod.getEndIp(), "172.20.0.250"); + assertEquals(pod.getGateway(), "172.20.0.254"); + assertEquals(pod.getNetmask(), "255.255.255.0"); + assertEquals(pod.getAllocationState(), AllocationState.ENABLED); + } + + @AfterClass + public void testFixtureTearDown() { + if (pod != null) { + globalAdminClient.getPodClient().deletePod(pod.getId()); + pod = null; + } + if (zone != null) { + globalAdminClient.getZoneClient().deleteZone(zone.getId()); + zone = null; + } + } } diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/CreatePodOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/CreatePodOptionsTest.java new file mode 100644 index 0000000000..5576d97520 --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/CreatePodOptionsTest.java @@ -0,0 +1,46 @@ +/** + * 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.cloudstack.options; + +import com.google.common.collect.ImmutableList; +import org.jclouds.cloudstack.domain.AllocationState; +import org.testng.annotations.Test; + +import static org.jclouds.cloudstack.options.CreatePodOptions.Builder.*; +import static org.testng.Assert.assertEquals; + +/** + * Tests behavior of {@code CreatePodOptions} + * + * @author Richard Downer + */ +@Test(groups = "unit") +public class CreatePodOptionsTest { + + public void testAllocationState() { + CreatePodOptions options = new CreatePodOptions().allocationState(AllocationState.ENABLED); + assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate")); + } + + public void testAllocationStateStatic() { + CreatePodOptions options = allocationState(AllocationState.ENABLED); + assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate")); + } + +} diff --git a/apis/cloudstack/src/test/resources/createpodresponse.json b/apis/cloudstack/src/test/resources/createpodresponse.json new file mode 100644 index 0000000000..925b0d412c --- /dev/null +++ b/apis/cloudstack/src/test/resources/createpodresponse.json @@ -0,0 +1 @@ +{ "createpodresponse" : { "pod" : {"id":6,"name":"richard-pod","zoneid":10,"zonename":"richard-zone","gateway":"172.20.0.254","netmask":"255.255.255.0","startip":"172.20.0.1","endip":"172.20.0.250","allocationstate":"Enabled"} } } \ No newline at end of file