From a2afd265b89b61c7cef66e0c600e702c48c0b12d Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Wed, 11 Jan 2012 18:10:52 +0200 Subject: [PATCH 01/15] Regenerate Host.equals()/hashCode()/toString() as they were out of date --- .../org/jclouds/cloudstack/domain/Host.java | 137 ++++++++---------- 1 file changed, 60 insertions(+), 77 deletions(-) diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Host.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Host.java index 8b59238963..3a01ca8437 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Host.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Host.java @@ -707,6 +707,59 @@ public class Host implements Comparable { return zoneName; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Host host = (Host) o; + + if (averageLoad != host.averageLoad) return false; + if (clusterId != host.clusterId) return false; + if (cpuNumber != host.cpuNumber) return false; + if (cpuSpeed != host.cpuSpeed) return false; + if (Float.compare(host.cpuWithOverProvisioning, cpuWithOverProvisioning) != 0) return false; + if (diskSizeAllocated != host.diskSizeAllocated) return false; + if (diskSizeTotal != host.diskSizeTotal) return false; + if (hasEnoughCapacity != host.hasEnoughCapacity) return false; + if (id != host.id) return false; + if (jobId != host.jobId) return false; + if (localStorageActive != host.localStorageActive) return false; + if (managementServerId != host.managementServerId) return false; + if (memoryAllocated != host.memoryAllocated) return false; + if (memoryTotal != host.memoryTotal) return false; + if (memoryUsed != host.memoryUsed) return false; + if (networkKbsRead != host.networkKbsRead) return false; + if (networkKbsWrite != host.networkKbsWrite) return false; + if (osCategoryId != host.osCategoryId) return false; + if (osCategoryName != host.osCategoryName) return false; + if (podId != host.podId) return false; + if (zoneId != host.zoneId) return false; + if (allocationState != host.allocationState) return false; + if (capabilities != null ? !capabilities.equals(host.capabilities) : host.capabilities != null) return false; + if (clusterName != null ? !clusterName.equals(host.clusterName) : host.clusterName != null) return false; + if (clusterType != host.clusterType) return false; + if (cpuAllocated != null ? !cpuAllocated.equals(host.cpuAllocated) : host.cpuAllocated != null) return false; + if (cpuUsed != null ? !cpuUsed.equals(host.cpuUsed) : host.cpuUsed != null) return false; + if (created != null ? !created.equals(host.created) : host.created != null) return false; + if (disconnected != null ? !disconnected.equals(host.disconnected) : host.disconnected != null) return false; + if (events != null ? !events.equals(host.events) : host.events != null) return false; + if (hostTags != null ? !hostTags.equals(host.hostTags) : host.hostTags != null) return false; + if (hypervisor != null ? !hypervisor.equals(host.hypervisor) : host.hypervisor != null) return false; + if (ipAddress != null ? !ipAddress.equals(host.ipAddress) : host.ipAddress != null) return false; + if (jobStatus != host.jobStatus) return false; + if (lastPinged != null ? !lastPinged.equals(host.lastPinged) : host.lastPinged != null) return false; + if (name != null ? !name.equals(host.name) : host.name != null) return false; + if (podName != null ? !podName.equals(host.podName) : host.podName != null) return false; + if (removed != null ? !removed.equals(host.removed) : host.removed != null) return false; + if (state != host.state) return false; + if (type != host.type) return false; + if (version != null ? !version.equals(host.version) : host.version != null) return false; + if (zoneName != null ? !zoneName.equals(host.zoneName) : host.zoneName != null) return false; + + return true; + } + @Override public int hashCode() { int result = (int) (id ^ (id >>> 32)); @@ -720,7 +773,7 @@ public class Host implements Comparable { result = 31 * result + cpuNumber; result = 31 * result + cpuSpeed; result = 31 * result + (cpuUsed != null ? cpuUsed.hashCode() : 0); - result = 31 * result + (int) cpuWithOverProvisioning; + result = 31 * result + (cpuWithOverProvisioning != +0.0f ? Float.floatToIntBits(cpuWithOverProvisioning) : 0); result = 31 * result + (created != null ? created.hashCode() : 0); result = 31 * result + (disconnected != null ? disconnected.hashCode() : 0); result = 31 * result + (int) (diskSizeAllocated ^ (diskSizeAllocated >>> 32)); @@ -754,90 +807,20 @@ public class Host implements Comparable { return result; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Host host = (Host) o; - - if (averageLoad != host.averageLoad) return false; - if (clusterId != host.clusterId) return false; - if (cpuAllocated != host.cpuAllocated) return false; - if (cpuNumber != host.cpuNumber) return false; - if (cpuSpeed != host.cpuSpeed) return false; - if (cpuUsed != host.cpuUsed) return false; - if (cpuWithOverProvisioning != host.cpuWithOverProvisioning) return false; - if (disconnected != host.disconnected) return false; - if (diskSizeAllocated != host.diskSizeAllocated) return false; - if (diskSizeTotal != host.diskSizeTotal) return false; - if (hasEnoughCapacity != host.hasEnoughCapacity) return false; - if (id != host.id) return false; - if (localStorageActive != host.localStorageActive) return false; - if (jobId != host.jobId) return false; - if (managementServerId != host.managementServerId) return false; - if (memoryAllocated != host.memoryAllocated) return false; - if (memoryTotal != host.memoryTotal) return false; - if (memoryUsed != host.memoryUsed) return false; - if (networkKbsRead != host.networkKbsRead) return false; - if (networkKbsWrite != host.networkKbsWrite) return false; - if (osCategoryId != host.osCategoryId) return false; - if (osCategoryName != host.osCategoryName) return false; - if (podId != host.podId) return false; - if (zoneId != host.zoneId) return false; - if (allocationState != null ? !allocationState.equals(host.allocationState) : host.allocationState != null) - return false; - if (capabilities != null ? !capabilities.equals(host.capabilities) : host.capabilities != null) - return false; - if (clusterName != null ? !clusterName.equals(host.clusterName) : host.clusterName != null) - return false; - if (clusterType != null ? !clusterType.equals(host.clusterType) : host.clusterType != null) - return false; - if (created != null ? !created.equals(host.created) : host.created != null) - return false; - if (events != null ? !events.equals(host.events) : host.events != null) - return false; - if (hostTags != null ? !hostTags.equals(host.hostTags) : host.hostTags != null) - return false; - if (hypervisor != null ? !hypervisor.equals(host.hypervisor) : host.hypervisor != null) - return false; - if (ipAddress != null ? !ipAddress.equals(host.ipAddress) : host.ipAddress != null) - return false; - if (jobStatus != host.jobStatus) return false; - if (lastPinged != null ? !lastPinged.equals(host.lastPinged) : host.lastPinged != null) - return false; - if (name != null ? !name.equals(host.name) : host.name != null) - return false; - if (podName != null ? !podName.equals(host.podName) : host.podName != null) - return false; - if (removed != null ? !removed.equals(host.removed) : host.removed != null) - return false; - if (state != null ? !state.equals(host.state) : host.state != null) - return false; - if (type != null ? !type.equals(host.type) : host.type != null) - return false; - if (version != null ? !version.equals(host.version) : host.version != null) - return false; - if (zoneName != null ? !zoneName.equals(host.zoneName) : host.zoneName != null) - return false; - - return true; - } - @Override public String toString() { return "Host{" + "id=" + id + - ", allocationState='" + allocationState + '\'' + + ", allocationState=" + allocationState + ", averageLoad=" + averageLoad + ", capabilities='" + capabilities + '\'' + ", clusterId=" + clusterId + ", clusterName='" + clusterName + '\'' + - ", clusterType='" + clusterType + '\'' + - ", cpuAllocated=" + cpuAllocated + + ", clusterType=" + clusterType + + ", cpuAllocated='" + cpuAllocated + '\'' + ", cpuNumber=" + cpuNumber + ", cpuSpeed=" + cpuSpeed + - ", cpuUsed=" + cpuUsed + + ", cpuUsed='" + cpuUsed + '\'' + ", cpuWithOverProvisioning=" + cpuWithOverProvisioning + ", created=" + created + ", disconnected=" + disconnected + @@ -864,8 +847,8 @@ public class Host implements Comparable { ", podId=" + podId + ", podName='" + podName + '\'' + ", removed=" + removed + - ", state='" + state + '\'' + - ", type='" + type + '\'' + + ", state=" + state + + ", type=" + type + ", version='" + version + '\'' + ", zoneId=" + zoneId + ", zoneName='" + zoneName + '\'' + From 7833ca557b90d43176301341bc64dbb803250843 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Wed, 11 Jan 2012 18:11:35 +0200 Subject: [PATCH 02/15] Add expect-style test for GlobalHostClient.listHosts() --- .../features/GlobalHostClientExpectTest.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java new file mode 100644 index 0000000000..55b2a7108b --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -0,0 +1,112 @@ +/** + * 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.features; + +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import org.jclouds.cloudstack.CloudStackContext; +import org.jclouds.cloudstack.domain.ConfigurationEntry; +import org.jclouds.cloudstack.domain.Host; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import java.net.URI; +import java.util.Calendar; +import java.util.Date; +import java.util.Set; +import java.util.TimeZone; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +/** + * Test the CloudStack GlobalHostClient + * + * @author Richard Downer + */ +@Test(groups = "unit", testName = "GlobalConfigurationClientExpectTest") +public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTest { + + @Test + public void testListHostsWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=listHosts&apiKey=identity&signature=wsv4UBgXxURW0pNlso4MT9E052s%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .payload(payloadFromResource("/listhostsresponse.json")) + .statusCode(200).build(); + + Set actual = requestSendsResponse(request, response).listHosts(); + + Date lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 54, 43, "UTC"); + Date created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 28, 36, "UTC"); + Host host1 = Host.builder().id(1).name("cs2-xevsrv.alucloud.local").state(Host.State.UP).type(Host.Type.ROUTING).ipAddress("10.26.26.107").zoneId(1).zoneName("Dev Zone 1").podId(1).podName("Dev Pod 1").version("2.2.12.20110928142833").hypervisor("XenServer").cpuNumber(24).cpuSpeed(2266).cpuAllocated("2.76%").cpuUsed("0.1%").cpuWithOverProvisioning(54384.0F).networkKbsRead(4443).networkKbsWrite(15048).memoryTotal(100549733760L).memoryAllocated(3623878656L).memoryUsed(3623878656L).capabilities("xen-3.0-x86_64 , xen-3.0-x86_32p , hvm-3.0-x86_32 , hvm-3.0-x86_32p , hvm-3.0-x86_64").lastPinged(lastPinged).managementServerId(223098941760041L).clusterId(1).clusterName("Xen Clust 1").clusterType(Host.ClusterType.CLOUD_MANAGED).localStorageActive(false).created(created).events("PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping").hostTags("").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build(); + + Date disconnected = makeDate(2011, Calendar.NOVEMBER, 26, 23, 33, 38, "UTC"); + lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 42, 30, "UTC"); + created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 33, 38, "UTC"); + Host host2 = Host.builder().id(2).name("nfs://10.26.26.165/mnt/nfs/cs_sec").state(Host.State.ALERT).disconnected(disconnected).type(Host.Type.SECONDARY_STORAGE).ipAddress("nfs").zoneId(1).zoneName("Dev Zone 1").version("2.2.12.20110928142833").hypervisor("None").lastPinged(lastPinged).localStorageActive(false).created(created).events("ManagementServerDown; AgentDisconnected; Remove; MaintenanceRequested; AgentConnected; Ping").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build(); + + lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 54, 43, "UTC"); + created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 35, 51, "UTC"); + Host host3 = Host.builder().id(3).name("s-1-VM").state(Host.State.UP).type(Host.Type.SECONDARY_STORAGE_VM).ipAddress("10.26.26.81").zoneId(1).zoneName("Dev Zone 1").podId(1).podName("Dev Pod 1").version("2.2.12.20110928142833").lastPinged(lastPinged).managementServerId(223098941760041L).localStorageActive(false).created(created).events("PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build(); + + lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 54, 43, "UTC"); + created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 36, 46, "UTC"); + Host host4 = Host.builder().id(4).name("v-2-VM").state(Host.State.UP).type(Host.Type.CONSOLE_PROXY).ipAddress("10.26.26.96").zoneId(1).zoneName("Dev Zone 1").podId(1).podName("Dev Pod 1").version("2.2.12.20110928142833").lastPinged(lastPinged).managementServerId(223098941760041L).localStorageActive(false).created(created).events("PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build(); + + Set expected = ImmutableSet.of(host1, host2, host3, host4); + + assertEquals(actual, expected); + } + + private Date makeDate(int year, int month, int date, int hour, int minute, int second, String timeZoneName) { + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timeZoneName)); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month); + cal.set(Calendar.DATE, date); + cal.set(Calendar.HOUR_OF_DAY, hour); + cal.set(Calendar.MINUTE, minute); + cal.set(Calendar.SECOND, second); + cal.set(Calendar.MILLISECOND, 0); + return cal.getTime(); + } + + @Test + public void testListHostsEmptyOn404() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=listHosts&apiKey=identity&signature=wsv4UBgXxURW0pNlso4MT9E052s%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder().statusCode(404).build(); + GlobalHostClient client = requestSendsResponse(request, response); + + assertEquals(client.listHosts(), ImmutableSet.of()); + } + + @Override + protected GlobalHostClient clientFrom(CloudStackContext context) { + return context.getGlobalContext().getApi().getHostClient(); + } +} \ No newline at end of file From d4293bdb7a3bf81f927b524f604bdb7341ea0a38 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 11:24:04 +0200 Subject: [PATCH 03/15] Add expect-style test for GlobalHostClient.listClusters() --- .../features/GlobalHostClientExpectTest.java | 58 +++++++++++++++---- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index 55b2a7108b..89ac050f04 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -22,6 +22,7 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; import org.jclouds.cloudstack.CloudStackContext; +import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.ConfigurationEntry; import org.jclouds.cloudstack.domain.Host; import org.jclouds.http.HttpRequest; @@ -80,18 +81,6 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe assertEquals(actual, expected); } - private Date makeDate(int year, int month, int date, int hour, int minute, int second, String timeZoneName) { - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timeZoneName)); - cal.set(Calendar.YEAR, year); - cal.set(Calendar.MONTH, month); - cal.set(Calendar.DATE, date); - cal.set(Calendar.HOUR_OF_DAY, hour); - cal.set(Calendar.MINUTE, minute); - cal.set(Calendar.SECOND, second); - cal.set(Calendar.MILLISECOND, 0); - return cal.getTime(); - } - @Test public void testListHostsEmptyOn404() { HttpRequest request = HttpRequest.builder() @@ -105,6 +94,51 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe assertEquals(client.listHosts(), ImmutableSet.of()); } + @Test + public void testListClustersWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=listClusters&apiKey=identity&signature=MWOOe7bm1J14DIfLjAGqsSVb8oo%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .payload(payloadFromResource("/listclustersresponse.json")) + .statusCode(200).build(); + + Set actual = requestSendsResponse(request, response).listClusters(); + + Cluster cluster1 = Cluster.builder().id(1).name("Xen Clust 1").podId(1).podName("Dev Pod 1").zoneId(1).zoneName("Dev Zone 1").hypervisor("XenServer").clusterType(Host.ClusterType.CLOUD_MANAGED).allocationState(Host.AllocationState.ENABLED).managedState(Cluster.ManagedState.MANAGED).build(); + Cluster cluster2 = Cluster.builder().id(2).name("Xen Clust 1").podId(2).podName("Dev Pod 2").zoneId(2).zoneName("Dev Zone 2").hypervisor("XenServer").clusterType(Host.ClusterType.CLOUD_MANAGED).allocationState(Host.AllocationState.ENABLED).managedState(Cluster.ManagedState.MANAGED).build(); + ImmutableSet expected = ImmutableSet.of(cluster1, cluster2); + + assertEquals(actual, expected); + } + + @Test + public void testListClustersEmptyOn404() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=listClusters&apiKey=identity&signature=MWOOe7bm1J14DIfLjAGqsSVb8oo%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder().statusCode(404).build(); + GlobalHostClient client = requestSendsResponse(request, response); + + assertEquals(client.listClusters(), ImmutableSet.of()); + } + + private Date makeDate(int year, int month, int date, int hour, int minute, int second, String timeZoneName) { + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timeZoneName)); + cal.set(Calendar.YEAR, year); + cal.set(Calendar.MONTH, month); + cal.set(Calendar.DATE, date); + cal.set(Calendar.HOUR_OF_DAY, hour); + cal.set(Calendar.MINUTE, minute); + cal.set(Calendar.SECOND, second); + cal.set(Calendar.MILLISECOND, 0); + return cal.getTime(); + } + @Override protected GlobalHostClient clientFrom(CloudStackContext context) { return context.getGlobalContext().getApi().getHostClient(); From 4bc4008b82cb2f4ad37f5b76f44d79ba1f3f68a3 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 13:33:56 +0200 Subject: [PATCH 04/15] Add GlobalHost[Async]Client.addHost() --- .../features/GlobalHostAsyncClient.java | 19 +++ .../cloudstack/features/GlobalHostClient.java | 14 +++ .../cloudstack/options/AddHostOptions.java | 115 ++++++++++++++++++ .../features/GlobalHostClientExpectTest.java | 23 ++++ .../options/AddHostOptionsTest.java | 87 +++++++++++++ .../src/test/resources/addhostresponse.json | 2 + 6 files changed, 260 insertions(+) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/AddHostOptions.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/AddHostOptionsTest.java create mode 100644 apis/cloudstack/src/test/resources/addhostresponse.json diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java index a6fc4d05f0..871818ae21 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java @@ -22,6 +22,7 @@ import com.google.common.util.concurrent.ListenableFuture; import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.Host; import org.jclouds.cloudstack.filters.QuerySigner; +import org.jclouds.cloudstack.options.AddHostOptions; import org.jclouds.cloudstack.options.ListClustersOptions; import org.jclouds.cloudstack.options.ListHostsOptions; import org.jclouds.rest.annotations.ExceptionParser; @@ -32,6 +33,7 @@ import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import java.util.Set; @@ -57,6 +59,23 @@ public interface GlobalHostAsyncClient { @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) ListenableFuture> listHosts(ListHostsOptions... options); + /** + * Adds a new host. + * + * @param zoneId the Zone ID for the host + * @param url the host URL + * @param hypervisor hypervisor type of the host + * @param username the username for the host + * @param password the password for the host + * @param options optional arguments + * @return the new host. + */ + @GET + @QueryParams(keys = "command", values = "addHost") + @SelectJson("host") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture addHost(@QueryParam("zoneid") long zoneId, @QueryParam("url") String url, @QueryParam("hypervisor") String hypervisor, @QueryParam("username") String username, @QueryParam("password") String password, AddHostOptions... options); + /** * @see GlobalHostClient#listClusters */ diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java index 414ce8b6fa..6006c91458 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java @@ -20,6 +20,7 @@ package org.jclouds.cloudstack.features; import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.Host; +import org.jclouds.cloudstack.options.AddHostOptions; import org.jclouds.cloudstack.options.ListClustersOptions; import org.jclouds.cloudstack.options.ListHostsOptions; import org.jclouds.concurrent.Timeout; @@ -48,6 +49,19 @@ public interface GlobalHostClient { */ Set listHosts(ListHostsOptions... options); + /** + * Adds a new host. + * + * @param zoneId the Zone ID for the host + * @param url the host URL + * @param hypervisor hypervisor type of the host + * @param username the username for the host + * @param password the password for the host + * @param options optional arguments + * @return the new host. + */ + Host addHost(long zoneId, String url, String hypervisor, String username, String password, AddHostOptions... options); + /** * Lists clusters * diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/AddHostOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/AddHostOptions.java new file mode 100644 index 0000000000..5cdf4bb70b --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/AddHostOptions.java @@ -0,0 +1,115 @@ +/** + * 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.base.Joiner; +import com.google.common.collect.ImmutableSet; +import org.jclouds.cloudstack.domain.Host; +import org.jclouds.http.options.BaseHttpRequestOptions; + +import java.util.Set; + +/** + * Options to the GlobalHostClient.addHost() API call + * + * @author Richard Downer + */ +public class AddHostOptions extends BaseHttpRequestOptions { + + public static final AddHostOptions NONE = new AddHostOptions(); + + /** + * @param allocationState Allocation state of this Host for allocation of new resources + */ + public AddHostOptions allocationState(Host.AllocationState allocationState) { + this.queryParameters.replaceValues("allocationstate", ImmutableSet.of(allocationState.toString())); + return this; + } + + /** + * @param clusterId the cluster ID for the host + */ + public AddHostOptions clusterId(long clusterId) { + this.queryParameters.replaceValues("clusterid", ImmutableSet.of(clusterId + "")); + return this; + } + + /** + * @param clusterName the cluster name for the host + */ + public AddHostOptions clusterName(String clusterName) { + this.queryParameters.replaceValues("clustername", ImmutableSet.of(clusterName)); + return this; + } + + /** + * @param hostTags list of tags to be added to the host + */ + public AddHostOptions hostTags(Set hostTags) { + this.queryParameters.replaceValues("hosttags", ImmutableSet.of(Joiner.on(',').join(hostTags))); + return this; + } + + /** + * @param podId the Pod ID for the host + */ + public AddHostOptions podId(long podId) { + this.queryParameters.replaceValues("podid", ImmutableSet.of(podId + "")); + return this; + } + + public static class Builder { + + /** + * @param allocationState Allocation state of this Host for allocation of new resources + */ + public static AddHostOptions allocationState(Host.AllocationState allocationState) { + return new AddHostOptions().allocationState(allocationState); + } + + /** + * @param clusterId the cluster ID for the host + */ + public static AddHostOptions clusterId(long clusterId) { + return new AddHostOptions().clusterId(clusterId); + } + + /** + * @param clusterName the cluster name for the host + */ + public static AddHostOptions clusterName(String clusterName) { + return new AddHostOptions().clusterName(clusterName); + } + + /** + * @param hostTags list of tags to be added to the host + */ + public static AddHostOptions hostTags(Set hostTags) { + return new AddHostOptions().hostTags(hostTags); + } + + /** + * @param podId the Pod ID for the host + */ + public static AddHostOptions podId(long podId) { + return new AddHostOptions().podId(podId); + } + + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index 89ac050f04..a2c5c82490 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -25,12 +25,14 @@ import org.jclouds.cloudstack.CloudStackContext; import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.ConfigurationEntry; import org.jclouds.cloudstack.domain.Host; +import org.jclouds.cloudstack.options.AddHostOptions; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.testng.annotations.Test; import java.net.URI; import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.Set; import java.util.TimeZone; @@ -94,6 +96,27 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe assertEquals(client.listHosts(), ImmutableSet.of()); } + @Test + public void testAddHostWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=addHost&zoneid=1&hypervisor=XenServer&url=http%3A%2F%2Fexample.com&username=fred&password=sekrit&hosttags=&allocationstate=Enabled&clusterid=1&clustername=Xen%20Clust%201&podid=1&apiKey=identity&signature=ExGaljKKQIlVbWk5hd0BnnjmBzs%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .payload(payloadFromResource("/addhostresponse.json")) + .statusCode(200).build(); + + Date lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 54, 43, "UTC"); + Date created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 28, 36, "UTC"); + Host expected = Host.builder().id(1).name("cs2-xevsrv.alucloud.local").state(Host.State.UP).type(Host.Type.ROUTING).ipAddress("10.26.26.107").zoneId(1).zoneName("Dev Zone 1").podId(1).podName("Dev Pod 1").version("2.2.12.20110928142833").hypervisor("XenServer").cpuNumber(24).cpuSpeed(2266).cpuAllocated("2.76%").cpuUsed("0.1%").cpuWithOverProvisioning(54384.0F).networkKbsRead(4443).networkKbsWrite(15048).memoryTotal(100549733760L).memoryAllocated(3623878656L).memoryUsed(3623878656L).capabilities("xen-3.0-x86_64 , xen-3.0-x86_32p , hvm-3.0-x86_32 , hvm-3.0-x86_32p , hvm-3.0-x86_64").lastPinged(lastPinged).managementServerId(223098941760041L).clusterId(1).clusterName("Xen Clust 1").clusterType(Host.ClusterType.CLOUD_MANAGED).localStorageActive(false).created(created).events("PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping").hostTags("").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build(); + + Host actual = requestSendsResponse(request, response).addHost(1, "http://example.com", "XenServer", "fred", "sekrit", + AddHostOptions.Builder.hostTags(Collections.emptySet()).allocationState(Host.AllocationState.ENABLED).clusterId(1).clusterName("Xen Clust 1").podId(1)); + + assertEquals(actual, expected); + } + @Test public void testListClustersWhenResponseIs2xx() { HttpRequest request = HttpRequest.builder() diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/AddHostOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/AddHostOptionsTest.java new file mode 100644 index 0000000000..7dfd22fb7e --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/AddHostOptionsTest.java @@ -0,0 +1,87 @@ +/** + * 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 com.google.common.collect.ImmutableSet; +import org.jclouds.cloudstack.domain.Host; +import org.testng.annotations.Test; + +import static org.jclouds.cloudstack.options.AddHostOptions.Builder.*; +import static org.testng.Assert.assertEquals; + +/** + * Tests behavior of {@code AddHostOptions} + * + * @author Richard Downer + */ +@Test(groups = "unit") +public class AddHostOptionsTest { + + public void testAllocationState() { + AddHostOptions options = new AddHostOptions().allocationState(Host.AllocationState.ENABLED); + assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate")); + } + + public void testAllocationStateStatic() { + AddHostOptions options = allocationState(Host.AllocationState.ENABLED); + assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate")); + } + + public void testClusterId() { + AddHostOptions options = new AddHostOptions().clusterId(42L); + assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("clusterid")); + } + + public void testClusterIdStatic() { + AddHostOptions options = clusterId(42L); + assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("clusterid")); + } + + public void testClusterName() { + AddHostOptions options = new AddHostOptions().clusterName("Cluster Name"); + assertEquals(ImmutableList.of("Cluster Name"), options.buildQueryParameters().get("clustername")); + } + + public void testClusterNameStatic() { + AddHostOptions options = clusterName("Cluster Name"); + assertEquals(ImmutableList.of("Cluster Name"), options.buildQueryParameters().get("clustername")); + } + + public void testHostTags() { + AddHostOptions options = new AddHostOptions().hostTags(ImmutableSet.of("foo", "bar", "baz")); + assertEquals(ImmutableList.of("foo,bar,baz"), options.buildQueryParameters().get("hosttags")); + } + + public void testHostTagsStatic() { + AddHostOptions options = hostTags(ImmutableSet.of("foo", "bar", "baz")); + assertEquals(ImmutableList.of("foo,bar,baz"), options.buildQueryParameters().get("hosttags")); + } + + public void testPodId() { + AddHostOptions options = new AddHostOptions().podId(42L); + assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("podid")); + } + + public void testPodIdStatic() { + AddHostOptions options = podId(42L); + assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("podid")); + } + +} diff --git a/apis/cloudstack/src/test/resources/addhostresponse.json b/apis/cloudstack/src/test/resources/addhostresponse.json new file mode 100644 index 0000000000..7508410682 --- /dev/null +++ b/apis/cloudstack/src/test/resources/addhostresponse.json @@ -0,0 +1,2 @@ +{ "addhostresponse" : { "host" : + {"warning":"This test data is fabricated","id":1,"name":"cs2-xevsrv.alucloud.local","state":"Up","type":"Routing","ipaddress":"10.26.26.107","zoneid":1,"zonename":"Dev Zone 1","podid":1,"podname":"Dev Pod 1","version":"2.2.12.20110928142833","hypervisor":"XenServer","cpunumber":24,"cpuspeed":2266,"cpuallocated":"2.76%","cpuused":"0.1%","cpuwithoverprovisioning":"54384.0","networkkbsread":4443,"networkkbswrite":15048,"memorytotal":100549733760,"memoryallocated":3623878656,"memoryused":3623878656,"capabilities":"xen-3.0-x86_64 , xen-3.0-x86_32p , hvm-3.0-x86_32 , hvm-3.0-x86_32p , hvm-3.0-x86_64","lastpinged":"1970-01-16T00:54:43+0200","managementserverid":223098941760041,"clusterid":1,"clustername":"Xen Clust 1","clustertype":"CloudManaged","islocalstorageactive":false,"created":"2011-11-26T23:28:36+0200","events":"PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping","hosttags":"","hasEnoughCapacity":false,"allocationstate":"Enabled"} } } \ No newline at end of file From 9bb9312d4a23f99c057d50ce51fbc1d12c675095 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 13:55:32 +0200 Subject: [PATCH 05/15] Add GlobalHost[Async]Client.updateHost() --- .../features/GlobalHostAsyncClient.java | 14 +++ .../cloudstack/features/GlobalHostClient.java | 10 +++ .../cloudstack/options/UpdateHostOptions.java | 87 +++++++++++++++++++ .../features/GlobalHostClientExpectTest.java | 21 +++++ .../options/UpdateHostOptionsTest.java | 67 ++++++++++++++ .../test/resources/updatehostresponse.json | 2 + 6 files changed, 201 insertions(+) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateHostOptions.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/UpdateHostOptionsTest.java create mode 100644 apis/cloudstack/src/test/resources/updatehostresponse.json diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java index 871818ae21..46328fc9a3 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java @@ -25,6 +25,7 @@ import org.jclouds.cloudstack.filters.QuerySigner; import org.jclouds.cloudstack.options.AddHostOptions; import org.jclouds.cloudstack.options.ListClustersOptions; import org.jclouds.cloudstack.options.ListHostsOptions; +import org.jclouds.cloudstack.options.UpdateHostOptions; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; @@ -76,6 +77,19 @@ public interface GlobalHostAsyncClient { @Consumes(MediaType.APPLICATION_JSON) ListenableFuture addHost(@QueryParam("zoneid") long zoneId, @QueryParam("url") String url, @QueryParam("hypervisor") String hypervisor, @QueryParam("username") String username, @QueryParam("password") String password, AddHostOptions... options); + /** + * Updates a host. + * + * @param hostId the ID of the host to update + * @param options optional arguments + * @return the modified host. + */ + @GET + @QueryParams(keys = "command", values = "updateHost") + @SelectJson("host") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture updateHost(@QueryParam("id") long hostId, UpdateHostOptions... options); + /** * @see GlobalHostClient#listClusters */ diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java index 6006c91458..0dceadd261 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java @@ -23,6 +23,7 @@ import org.jclouds.cloudstack.domain.Host; import org.jclouds.cloudstack.options.AddHostOptions; import org.jclouds.cloudstack.options.ListClustersOptions; import org.jclouds.cloudstack.options.ListHostsOptions; +import org.jclouds.cloudstack.options.UpdateHostOptions; import org.jclouds.concurrent.Timeout; import java.util.Set; @@ -62,6 +63,15 @@ public interface GlobalHostClient { */ Host addHost(long zoneId, String url, String hypervisor, String username, String password, AddHostOptions... options); + /** + * Updates a host. + * + * @param hostId the ID of the host to update + * @param options optional arguments + * @return the modified host. + */ + Host updateHost(long hostId, UpdateHostOptions... options); + /** * Lists clusters * diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateHostOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateHostOptions.java new file mode 100644 index 0000000000..e89013ae92 --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateHostOptions.java @@ -0,0 +1,87 @@ +/** + * 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.base.Joiner; +import com.google.common.collect.ImmutableSet; +import org.jclouds.cloudstack.domain.Host; +import org.jclouds.functions.JoinOnComma; +import org.jclouds.http.options.BaseHttpRequestOptions; + +import java.util.Set; + +/** + * Options to the GlobalHostClient.addHost() API call + * + * @author Richard Downer + */ +public class UpdateHostOptions extends BaseHttpRequestOptions { + + + public static final UpdateHostOptions NONE = new UpdateHostOptions(); + + /** + * @param allocationState Allocation state of this Host for allocation of new resources + */ + public UpdateHostOptions allocationState(Host.AllocationState allocationState) { + this.queryParameters.replaceValues("allocationstate", ImmutableSet.of(allocationState.toString())); + return this; + } + + /** + * @param hostTags list of tags to be added to the host + */ + public UpdateHostOptions hostTags(Set hostTags) { + this.queryParameters.replaceValues("hosttags", ImmutableSet.of(Joiner.on(',').join(hostTags))); + return this; + } + + /** + * @param osCategoryId the id of Os category to update the host with + */ + public UpdateHostOptions osCategoryId(long osCategoryId) { + this.queryParameters.replaceValues("oscategoryid", ImmutableSet.of(osCategoryId + "")); + return this; + } + + public static class Builder { + + /** + * @param allocationState Allocation state of this Host for allocation of new resources + */ + public static UpdateHostOptions allocationState(Host.AllocationState allocationState) { + return new UpdateHostOptions().allocationState(allocationState); + } + + /** + * @param hostTags list of tags to be added to the host + */ + public static UpdateHostOptions hostTags(Set hostTags) { + return new UpdateHostOptions().hostTags(hostTags); + } + + /** + * @param podId the Pod ID for the host + */ + public static UpdateHostOptions osCategoryId(long osCategoryId) { + return new UpdateHostOptions().osCategoryId(osCategoryId); + } + + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index a2c5c82490..808b225382 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -26,6 +26,7 @@ import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.ConfigurationEntry; import org.jclouds.cloudstack.domain.Host; import org.jclouds.cloudstack.options.AddHostOptions; +import org.jclouds.cloudstack.options.UpdateHostOptions; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.testng.annotations.Test; @@ -117,6 +118,26 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe assertEquals(actual, expected); } + @Test + public void testUpdateHostWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=updateHost&id=1&allocationstate=Enabled&hosttags=&oscategoryid=5&apiKey=identity&signature=qTxNq9yQG8S108giqS%2FROFzgev8%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .payload(payloadFromResource("/updatehostresponse.json")) + .statusCode(200).build(); + + Date lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 54, 43, "UTC"); + Date created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 28, 36, "UTC"); + Host expected = Host.builder().id(1).name("cs2-xevsrv.alucloud.local").state(Host.State.UP).type(Host.Type.ROUTING).ipAddress("10.26.26.107").zoneId(1).zoneName("Dev Zone 1").podId(1).podName("Dev Pod 1").version("2.2.12.20110928142833").hypervisor("XenServer").cpuNumber(24).cpuSpeed(2266).cpuAllocated("2.76%").cpuUsed("0.1%").cpuWithOverProvisioning(54384.0F).networkKbsRead(4443).networkKbsWrite(15048).memoryTotal(100549733760L).memoryAllocated(3623878656L).memoryUsed(3623878656L).capabilities("xen-3.0-x86_64 , xen-3.0-x86_32p , hvm-3.0-x86_32 , hvm-3.0-x86_32p , hvm-3.0-x86_64").lastPinged(lastPinged).managementServerId(223098941760041L).clusterId(1).clusterName("Xen Clust 1").clusterType(Host.ClusterType.CLOUD_MANAGED).localStorageActive(false).created(created).events("PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping").hostTags("").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build(); + + Host actual = requestSendsResponse(request, response).updateHost(1, UpdateHostOptions.Builder.allocationState(Host.AllocationState.ENABLED).hostTags(Collections.emptySet()).osCategoryId(5)); + + assertEquals(actual, expected); + } + @Test public void testListClustersWhenResponseIs2xx() { HttpRequest request = HttpRequest.builder() diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/UpdateHostOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/UpdateHostOptionsTest.java new file mode 100644 index 0000000000..69ffc18592 --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/UpdateHostOptionsTest.java @@ -0,0 +1,67 @@ +/** + * 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 com.google.common.collect.ImmutableSet; +import org.jclouds.cloudstack.domain.Host; +import org.testng.annotations.Test; + +import static org.jclouds.cloudstack.options.UpdateHostOptions.Builder.*; +import static org.testng.Assert.assertEquals; + +/** + * Tests behavior of {@code UpdateHostOptions} + * + * @author Richard Downer + */ +@Test(groups = "unit") +public class UpdateHostOptionsTest { + + public void testAllocationState() { + UpdateHostOptions options = new UpdateHostOptions().allocationState(Host.AllocationState.ENABLED); + assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate")); + } + + public void testAllocationStateStatic() { + UpdateHostOptions options = allocationState(Host.AllocationState.ENABLED); + assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate")); + } + + public void testHostTags() { + UpdateHostOptions options = new UpdateHostOptions().hostTags(ImmutableSet.of("foo", "bar", "baz")); + assertEquals(ImmutableList.of("foo,bar,baz"), options.buildQueryParameters().get("hosttags")); + } + + public void testHostTagsStatic() { + UpdateHostOptions options = hostTags(ImmutableSet.of("foo", "bar", "baz")); + assertEquals(ImmutableList.of("foo,bar,baz"), options.buildQueryParameters().get("hosttags")); + } + + public void testOsCategoryId() { + UpdateHostOptions options = new UpdateHostOptions().osCategoryId(42L); + assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("oscategoryid")); + } + + public void testOsCategoryIdStatic() { + UpdateHostOptions options = osCategoryId(42L); + assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("oscategoryid")); + } + +} diff --git a/apis/cloudstack/src/test/resources/updatehostresponse.json b/apis/cloudstack/src/test/resources/updatehostresponse.json new file mode 100644 index 0000000000..cb70ddd6bf --- /dev/null +++ b/apis/cloudstack/src/test/resources/updatehostresponse.json @@ -0,0 +1,2 @@ +{ "updatehostresponse" : { "host" : + {"warning":"This test data is fabricated","id":1,"name":"cs2-xevsrv.alucloud.local","state":"Up","type":"Routing","ipaddress":"10.26.26.107","zoneid":1,"zonename":"Dev Zone 1","podid":1,"podname":"Dev Pod 1","version":"2.2.12.20110928142833","hypervisor":"XenServer","cpunumber":24,"cpuspeed":2266,"cpuallocated":"2.76%","cpuused":"0.1%","cpuwithoverprovisioning":"54384.0","networkkbsread":4443,"networkkbswrite":15048,"memorytotal":100549733760,"memoryallocated":3623878656,"memoryused":3623878656,"capabilities":"xen-3.0-x86_64 , xen-3.0-x86_32p , hvm-3.0-x86_32 , hvm-3.0-x86_32p , hvm-3.0-x86_64","lastpinged":"1970-01-16T00:54:43+0200","managementserverid":223098941760041,"clusterid":1,"clustername":"Xen Clust 1","clustertype":"CloudManaged","islocalstorageactive":false,"created":"2011-11-26T23:28:36+0200","events":"PrepareUnmanaged; HypervisorVersionChanged; ManagementServerDown; PingTimeout; AgentDisconnected; MaintenanceRequested; HostDown; AgentConnected; StartAgentRebalance; ShutdownRequested; Ping","hosttags":"","hasEnoughCapacity":false,"allocationstate":"Enabled"} } } \ No newline at end of file From 2b1c5f78f3bbe80b654380eb81d6d80a55258378 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 14:06:57 +0200 Subject: [PATCH 06/15] Add GlobalHost[Async]Client.updateHostPassword() --- .../cloudstack/features/GlobalHostAsyncClient.java | 12 ++++++++++++ .../cloudstack/features/GlobalHostClient.java | 9 +++++++++ .../features/GlobalHostClientExpectTest.java | 13 +++++++++++++ 3 files changed, 34 insertions(+) diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java index 46328fc9a3..975f6cd442 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java @@ -90,6 +90,18 @@ public interface GlobalHostAsyncClient { @Consumes(MediaType.APPLICATION_JSON) ListenableFuture updateHost(@QueryParam("id") long hostId, UpdateHostOptions... options); + /** + * Update password of a host on management server. + * + * @param hostId the host ID + * @param username the username for the host + * @param password the password for the host + */ + @GET + @QueryParams(keys = "command", values = "updateHostPassword") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture updateHostPassword(@QueryParam("hostid") long hostId, @QueryParam("username") String username, @QueryParam("password") String password); + /** * @see GlobalHostClient#listClusters */ diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java index 0dceadd261..098bca3ad2 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java @@ -72,6 +72,15 @@ public interface GlobalHostClient { */ Host updateHost(long hostId, UpdateHostOptions... options); + /** + * Update password of a host on management server. + * + * @param hostId the host ID + * @param username the username for the host + * @param password the password for the host + */ + void updateHostPassword(long hostId, String username, String password); + /** * Lists clusters * diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index 808b225382..cb2e01de7b 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -138,6 +138,19 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe assertEquals(actual, expected); } + @Test + public void testUpdateHostPasswordWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=updateHostPassword&hostid=1&password=sekrit&username=fred&apiKey=identity&signature=g9nMKDWoiU72y0HhaRFekZCgfJc%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .statusCode(200).build(); + + requestSendsResponse(request, response).updateHostPassword(1, "fred", "sekrit"); + } + @Test public void testListClustersWhenResponseIs2xx() { HttpRequest request = HttpRequest.builder() From 350e01c2308164a68584d6c943fd78122180228c Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 14:13:23 +0200 Subject: [PATCH 07/15] Add GlobalHost[Async]Client.deleteHost() --- .../features/GlobalHostAsyncClient.java | 12 ++++ .../cloudstack/features/GlobalHostClient.java | 9 +++ .../cloudstack/options/DeleteHostOptions.java | 66 +++++++++++++++++++ .../features/GlobalHostClientExpectTest.java | 14 ++++ .../options/DeleteHostOptionsTest.java | 57 ++++++++++++++++ 5 files changed, 158 insertions(+) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/DeleteHostOptions.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/DeleteHostOptionsTest.java diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java index 975f6cd442..5726aacca4 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java @@ -23,6 +23,7 @@ import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.Host; import org.jclouds.cloudstack.filters.QuerySigner; import org.jclouds.cloudstack.options.AddHostOptions; +import org.jclouds.cloudstack.options.DeleteHostOptions; import org.jclouds.cloudstack.options.ListClustersOptions; import org.jclouds.cloudstack.options.ListHostsOptions; import org.jclouds.cloudstack.options.UpdateHostOptions; @@ -102,6 +103,17 @@ public interface GlobalHostAsyncClient { @Consumes(MediaType.APPLICATION_JSON) ListenableFuture updateHostPassword(@QueryParam("hostid") long hostId, @QueryParam("username") String username, @QueryParam("password") String password); + /** + * Deletes a host. + * + * @param hostId the host ID + * @param options optional arguments + */ + @GET + @QueryParams(keys = "command", values = "deleteHost") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture deleteHost(@QueryParam("id") long hostId, DeleteHostOptions... options); + /** * @see GlobalHostClient#listClusters */ diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java index 098bca3ad2..22a83f1352 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java @@ -21,6 +21,7 @@ package org.jclouds.cloudstack.features; import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.Host; import org.jclouds.cloudstack.options.AddHostOptions; +import org.jclouds.cloudstack.options.DeleteHostOptions; import org.jclouds.cloudstack.options.ListClustersOptions; import org.jclouds.cloudstack.options.ListHostsOptions; import org.jclouds.cloudstack.options.UpdateHostOptions; @@ -81,6 +82,14 @@ public interface GlobalHostClient { */ void updateHostPassword(long hostId, String username, String password); + /** + * Deletes a host. + * + * @param hostId the host ID + * @param options optional arguments + */ + void deleteHost(long hostId, DeleteHostOptions... options); + /** * Lists clusters * diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/DeleteHostOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/DeleteHostOptions.java new file mode 100644 index 0000000000..f8d3a12edf --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/DeleteHostOptions.java @@ -0,0 +1,66 @@ +/** + * 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.http.options.BaseHttpRequestOptions; + +/** + * Options to the GlobalHostClient.deleteHost() API call + * + * @author Richard Downer + */ +public class DeleteHostOptions extends BaseHttpRequestOptions { + + public static final DeleteHostOptions NONE = new DeleteHostOptions(); + + /** + * @param forced Force delete the host. All HA enabled vms running on the host will be put to HA; HA disabled ones will be stopped + */ + public DeleteHostOptions forced(boolean forced) { + this.queryParameters.replaceValues("forced", ImmutableSet.of(forced + "")); + return this; + } + + /** + * @param forceDestroyLocalStorage Force destroy local storage on this host. All VMs created on this local storage will be destroyed + */ + public DeleteHostOptions forceDestroyLocalStorage(boolean forceDestroyLocalStorage) { + this.queryParameters.replaceValues("forcedestroylocalstorage", ImmutableSet.of(forceDestroyLocalStorage + "")); + return this; + } + + public static class Builder { + + /** + * @param forced Force delete the host. All HA enabled vms running on the host will be put to HA; HA disabled ones will be stopped + */ + public static DeleteHostOptions forced(boolean forced) { + return new DeleteHostOptions().forced(forced); + } + + /** + * @param forceDestroyLocalStorage Force destroy local storage on this host. All VMs created on this local storage will be destroyed + */ + public static DeleteHostOptions forceDestroyLocalStorage(boolean forceDestroyLocalStorage) { + return new DeleteHostOptions().forceDestroyLocalStorage(forceDestroyLocalStorage); + } + + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index cb2e01de7b..034e29df51 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -26,6 +26,7 @@ import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.ConfigurationEntry; import org.jclouds.cloudstack.domain.Host; import org.jclouds.cloudstack.options.AddHostOptions; +import org.jclouds.cloudstack.options.DeleteHostOptions; import org.jclouds.cloudstack.options.UpdateHostOptions; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; @@ -151,6 +152,19 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe requestSendsResponse(request, response).updateHostPassword(1, "fred", "sekrit"); } + @Test + public void testDeleteHostWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=deleteHost&id=1&forced=true&forcedestroylocalstorage=true&apiKey=identity&signature=ZdvO1BWBkdPiDAjsVlKtqDe6N7k%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .statusCode(200).build(); + + requestSendsResponse(request, response).deleteHost(1, DeleteHostOptions.Builder.forced(true).forceDestroyLocalStorage(true)); + } + @Test public void testListClustersWhenResponseIs2xx() { HttpRequest request = HttpRequest.builder() diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/DeleteHostOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/DeleteHostOptionsTest.java new file mode 100644 index 0000000000..0445a2e926 --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/DeleteHostOptionsTest.java @@ -0,0 +1,57 @@ +/** + * 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 com.google.common.collect.ImmutableSet; +import org.jclouds.cloudstack.domain.Host; +import org.testng.annotations.Test; + +import static org.jclouds.cloudstack.options.DeleteHostOptions.Builder.*; +import static org.testng.Assert.assertEquals; + +/** + * Tests behavior of {@code DeleteHostOptions} + * + * @author Richard Downer + */ +@Test(groups = "unit") +public class DeleteHostOptionsTest { + + public void testForced() { + DeleteHostOptions options = new DeleteHostOptions().forced(true); + assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("forced")); + } + + public void testForcedStatic() { + DeleteHostOptions options = forced(true); + assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("forced")); + } + + public void testForceDestroyLocalStorage() { + DeleteHostOptions options = new DeleteHostOptions().forceDestroyLocalStorage(true); + assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("forcedestroylocalstorage")); + } + + public void testForceDestroyLocalStorageStatic() { + DeleteHostOptions options = forceDestroyLocalStorage(true); + assertEquals(ImmutableList.of("true"), options.buildQueryParameters().get("forcedestroylocalstorage")); + } + +} From b3bb99da8857d7362e170775adac822a56ffa669 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 14:25:24 +0200 Subject: [PATCH 08/15] Add GlobalHost[Async]Client.prepareHostForMaintenance() --- .../features/GlobalHostAsyncClient.java | 12 ++++++++++++ .../cloudstack/features/GlobalHostClient.java | 8 ++++++++ .../features/GlobalHostClientExpectTest.java | 15 +++++++++++++++ .../preparehostformaintenanceresponse.json | 1 + 4 files changed, 36 insertions(+) create mode 100644 apis/cloudstack/src/test/resources/preparehostformaintenanceresponse.json diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java index 5726aacca4..0041d934ae 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java @@ -114,6 +114,18 @@ public interface GlobalHostAsyncClient { @Consumes(MediaType.APPLICATION_JSON) ListenableFuture deleteHost(@QueryParam("id") long hostId, DeleteHostOptions... options); + /** + * Prepares a host for maintenance. + * + * @param hostId the host ID + * @return a job reference number for tracking this asynchronous job. + */ + @GET + @QueryParams(keys = "command", values = "prepareHostForMaintenance") + @SelectJson("jobid") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture prepareHostForMaintenance(@QueryParam("id") long hostId); + /** * @see GlobalHostClient#listClusters */ diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java index 22a83f1352..54417f3256 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java @@ -90,6 +90,14 @@ public interface GlobalHostClient { */ void deleteHost(long hostId, DeleteHostOptions... options); + /** + * Prepares a host for maintenance. + * + * @param hostId the host ID + * @return a job reference number for tracking this asynchronous job. + */ + Long prepareHostForMaintenance(long hostId); + /** * Lists clusters * diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index 034e29df51..a2e66866be 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -165,6 +165,21 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe requestSendsResponse(request, response).deleteHost(1, DeleteHostOptions.Builder.forced(true).forceDestroyLocalStorage(true)); } + @Test + public void testPrepareHostForMaintenanceWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=prepareHostForMaintenance&id=1&apiKey=identity&signature=9tDwdox%2FxAKmZr9kVrR6Ttnxf3U%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .payload(payloadFromResource("/preparehostformaintenanceresponse.json")) + .statusCode(200).build(); + + Long actual = requestSendsResponse(request, response).prepareHostForMaintenance(1); + assertEquals(actual, Long.valueOf(2036L)); + } + @Test public void testListClustersWhenResponseIs2xx() { HttpRequest request = HttpRequest.builder() diff --git a/apis/cloudstack/src/test/resources/preparehostformaintenanceresponse.json b/apis/cloudstack/src/test/resources/preparehostformaintenanceresponse.json new file mode 100644 index 0000000000..294f6464f2 --- /dev/null +++ b/apis/cloudstack/src/test/resources/preparehostformaintenanceresponse.json @@ -0,0 +1 @@ +{ "preparehostformaintenanceresponse" : {"warning":"this test data is fabricated","jobid":2036,"id":2017} } \ No newline at end of file From 528fa0ae5aa18456fcd2c5c96dd9dccd9372d3b6 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 14:31:03 +0200 Subject: [PATCH 09/15] Add GlobalHost[Async]Client.cancelHostMaintenance() --- .../features/GlobalHostAsyncClient.java | 12 ++++++++++++ .../cloudstack/features/GlobalHostClient.java | 8 ++++++++ .../features/GlobalHostClientExpectTest.java | 15 +++++++++++++++ .../resources/cancelhostmaintenanceresponse.json | 1 + 4 files changed, 36 insertions(+) create mode 100644 apis/cloudstack/src/test/resources/cancelhostmaintenanceresponse.json diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java index 0041d934ae..70bfefcc8a 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java @@ -126,6 +126,18 @@ public interface GlobalHostAsyncClient { @Consumes(MediaType.APPLICATION_JSON) ListenableFuture prepareHostForMaintenance(@QueryParam("id") long hostId); + /** + * Cancels host maintenance. + * + * @param hostId the host ID + * @return a job reference number for tracking this asynchronous job. + */ + @GET + @QueryParams(keys = "command", values = "cancelHostMaintenance") + @SelectJson("jobid") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture cancelHostMaintenance(@QueryParam("id") long hostId); + /** * @see GlobalHostClient#listClusters */ diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java index 54417f3256..434470c8fc 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java @@ -98,6 +98,14 @@ public interface GlobalHostClient { */ Long prepareHostForMaintenance(long hostId); + /** + * Cancels host maintenance. + * + * @param hostId the host ID + * @return a job reference number for tracking this asynchronous job. + */ + Long cancelHostMaintenance(long hostId); + /** * Lists clusters * diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index a2e66866be..24dd923d82 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -180,6 +180,21 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe assertEquals(actual, Long.valueOf(2036L)); } + @Test + public void testCancelHostMaintenanceWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=cancelHostMaintenance&id=1&apiKey=identity&signature=9RduzuBoyRZKNTzAoVqUo9gRTfk%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .payload(payloadFromResource("/cancelhostmaintenanceresponse.json")) + .statusCode(200).build(); + + Long actual = requestSendsResponse(request, response).cancelHostMaintenance(1); + assertEquals(actual, Long.valueOf(2036L)); + } + @Test public void testListClustersWhenResponseIs2xx() { HttpRequest request = HttpRequest.builder() diff --git a/apis/cloudstack/src/test/resources/cancelhostmaintenanceresponse.json b/apis/cloudstack/src/test/resources/cancelhostmaintenanceresponse.json new file mode 100644 index 0000000000..5c3b0d0357 --- /dev/null +++ b/apis/cloudstack/src/test/resources/cancelhostmaintenanceresponse.json @@ -0,0 +1 @@ +{ "cancelhostmaintenanceresponse" : {"warning":"this test data is fabricated","jobid":2036,"id":2017} } \ No newline at end of file From 20f58c4a12654dc1259fcb0934e1efe20a884007 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 14:39:52 +0200 Subject: [PATCH 10/15] Add GlobalHost[Async]Client.reconnectHost() --- .../features/GlobalHostAsyncClient.java | 12 ++++++++++++ .../cloudstack/features/GlobalHostClient.java | 8 ++++++++ .../features/GlobalHostClientExpectTest.java | 15 +++++++++++++++ .../src/test/resources/reconnecthostresponse.json | 1 + 4 files changed, 36 insertions(+) create mode 100644 apis/cloudstack/src/test/resources/reconnecthostresponse.json diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java index 70bfefcc8a..fe53dca3dc 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java @@ -138,6 +138,18 @@ public interface GlobalHostAsyncClient { @Consumes(MediaType.APPLICATION_JSON) ListenableFuture cancelHostMaintenance(@QueryParam("id") long hostId); + /** + * Reconnects a host. + * + * @param hostId + * @return a job reference number for tracking this asynchronous job. + */ + @GET + @QueryParams(keys = "command", values = "reconnectHost") + @SelectJson("jobid") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture reconnectHost(@QueryParam("id") long hostId); + /** * @see GlobalHostClient#listClusters */ diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java index 434470c8fc..f422af69dd 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java @@ -106,6 +106,14 @@ public interface GlobalHostClient { */ Long cancelHostMaintenance(long hostId); + /** + * Reconnects a host. + * + * @param hostId + * @return a job reference number for tracking this asynchronous job. + */ + Long reconnectHost(long hostId); + /** * Lists clusters * diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index 24dd923d82..acbba0beb9 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -195,6 +195,21 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe assertEquals(actual, Long.valueOf(2036L)); } + @Test + public void testReconnectHostWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=reconnectHost&id=1&apiKey=identity&signature=wJEF02vwdyOnJOTa%2BWMMK906aRU%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .payload(payloadFromResource("/reconnecthostresponse.json")) + .statusCode(200).build(); + + Long actual = requestSendsResponse(request, response).reconnectHost(1); + assertEquals(actual, Long.valueOf(2036L)); + } + @Test public void testListClustersWhenResponseIs2xx() { HttpRequest request = HttpRequest.builder() diff --git a/apis/cloudstack/src/test/resources/reconnecthostresponse.json b/apis/cloudstack/src/test/resources/reconnecthostresponse.json new file mode 100644 index 0000000000..2b86f49790 --- /dev/null +++ b/apis/cloudstack/src/test/resources/reconnecthostresponse.json @@ -0,0 +1 @@ +{ "reconnecthostresponse" : {"warning":"this test data is fabricated","jobid":2036,"id":2017} } \ No newline at end of file From 533e13fc44e3398df93618787b035ef8dfcb707a Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 14:57:25 +0200 Subject: [PATCH 11/15] Add GlobalHost[Async]Client.addSecondaryStorage() --- .../features/GlobalHostAsyncClient.java | 14 +++++ .../cloudstack/features/GlobalHostClient.java | 10 ++++ .../options/AddSecondaryStorageOptions.java | 53 +++++++++++++++++++ .../features/GlobalHostClientExpectTest.java | 22 ++++++++ .../AddSecondaryStorageOptionsTest.java | 45 ++++++++++++++++ .../addsecondarystorageresponse.json | 3 ++ 6 files changed, 147 insertions(+) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/AddSecondaryStorageOptions.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/AddSecondaryStorageOptionsTest.java create mode 100644 apis/cloudstack/src/test/resources/addsecondarystorageresponse.json diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java index fe53dca3dc..9c46cd1367 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java @@ -23,6 +23,7 @@ import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.Host; import org.jclouds.cloudstack.filters.QuerySigner; import org.jclouds.cloudstack.options.AddHostOptions; +import org.jclouds.cloudstack.options.AddSecondaryStorageOptions; import org.jclouds.cloudstack.options.DeleteHostOptions; import org.jclouds.cloudstack.options.ListClustersOptions; import org.jclouds.cloudstack.options.ListHostsOptions; @@ -150,6 +151,19 @@ public interface GlobalHostAsyncClient { @Consumes(MediaType.APPLICATION_JSON) ListenableFuture reconnectHost(@QueryParam("id") long hostId); + /** + * Adds secondary storage. + * + * @param url the URL for the secondary storage + * @param options optional arguments + * @return the host of the storage. + */ + @GET + @QueryParams(keys = "command", values = "addSecondaryStorage") + @SelectJson("host") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture addSecondaryStorage(@QueryParam("url") String url, AddSecondaryStorageOptions... options); + /** * @see GlobalHostClient#listClusters */ diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java index f422af69dd..77ae55e023 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java @@ -21,6 +21,7 @@ package org.jclouds.cloudstack.features; import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.Host; import org.jclouds.cloudstack.options.AddHostOptions; +import org.jclouds.cloudstack.options.AddSecondaryStorageOptions; import org.jclouds.cloudstack.options.DeleteHostOptions; import org.jclouds.cloudstack.options.ListClustersOptions; import org.jclouds.cloudstack.options.ListHostsOptions; @@ -114,6 +115,15 @@ public interface GlobalHostClient { */ Long reconnectHost(long hostId); + /** + * Adds secondary storage. + * + * @param url the URL for the secondary storage + * @param options optional arguments + * @return the host of the storage. + */ + Host addSecondaryStorage(String url, AddSecondaryStorageOptions... options); + /** * Lists clusters * diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/AddSecondaryStorageOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/AddSecondaryStorageOptions.java new file mode 100644 index 0000000000..cfe8d5b146 --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/AddSecondaryStorageOptions.java @@ -0,0 +1,53 @@ +/** + * 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.http.options.BaseHttpRequestOptions; + +/** + * Options for the GlobalHostClient.addSecondaryStorage() API call + * + * @author Richard Downer + */ +public class AddSecondaryStorageOptions extends BaseHttpRequestOptions { + + public static final AddSecondaryStorageOptions NONE = new AddSecondaryStorageOptions(); + + /** + * @param zoneId + * the ID of the zone + */ + public AddSecondaryStorageOptions zoneId(long zoneId) { + this.queryParameters.replaceValues("zoneid", ImmutableSet.of(zoneId + "")); + return this; + } + + public static class Builder { + + /** + * @param zoneId + * the ID of the zone + */ + public static AddSecondaryStorageOptions zoneId(long zoneId) { + return new AddSecondaryStorageOptions().zoneId(zoneId); + } + + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index acbba0beb9..8a29f37a75 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -26,6 +26,7 @@ import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.ConfigurationEntry; import org.jclouds.cloudstack.domain.Host; import org.jclouds.cloudstack.options.AddHostOptions; +import org.jclouds.cloudstack.options.AddSecondaryStorageOptions; import org.jclouds.cloudstack.options.DeleteHostOptions; import org.jclouds.cloudstack.options.UpdateHostOptions; import org.jclouds.http.HttpRequest; @@ -210,6 +211,27 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe assertEquals(actual, Long.valueOf(2036L)); } + @Test + public void testAddSecondaryStorageWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=addSecondaryStorage&url=nfs%3A%2F%2F10.26.26.165%2Fmnt%2Fnfs%2Fcs_sec&zoneid=1&apiKey=identity&signature=MccRKx1yPP43ImiO70WlhVDlAIA%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .payload(payloadFromResource("/addsecondarystorageresponse.json")) + .statusCode(200).build(); + + Date disconnected = makeDate(2011, Calendar.NOVEMBER, 26, 23, 33, 38, "UTC"); + Date lastPinged = makeDate(1970, Calendar.JANUARY, 16, 0, 42, 30, "UTC"); + Date created = makeDate(2011, Calendar.NOVEMBER, 26, 23, 33, 38, "UTC"); + Host expected = Host.builder().id(2).name("nfs://10.26.26.165/mnt/nfs/cs_sec").state(Host.State.ALERT).disconnected(disconnected).type(Host.Type.SECONDARY_STORAGE).ipAddress("nfs").zoneId(1).zoneName("Dev Zone 1").version("2.2.12.20110928142833").hypervisor("None").lastPinged(lastPinged).localStorageActive(false).created(created).events("ManagementServerDown; AgentDisconnected; Remove; MaintenanceRequested; AgentConnected; Ping").hasEnoughCapacity(false).allocationState(Host.AllocationState.ENABLED).build(); + + Host actual = requestSendsResponse(request, response).addSecondaryStorage("nfs://10.26.26.165/mnt/nfs/cs_sec", AddSecondaryStorageOptions.Builder.zoneId(1)); + + assertEquals(actual, expected); + } + @Test public void testListClustersWhenResponseIs2xx() { HttpRequest request = HttpRequest.builder() diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/AddSecondaryStorageOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/AddSecondaryStorageOptionsTest.java new file mode 100644 index 0000000000..3d9ca51ec7 --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/AddSecondaryStorageOptionsTest.java @@ -0,0 +1,45 @@ +/** + * 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.testng.annotations.Test; + +import static org.jclouds.cloudstack.options.AddSecondaryStorageOptions.Builder.*; +import static org.testng.Assert.assertEquals; + +/** + * Tests behavior of {@code AddSecondaryStorageOptions} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class AddSecondaryStorageOptionsTest { + + public void testZoneId() { + AddSecondaryStorageOptions options = new AddSecondaryStorageOptions().zoneId(6); + assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("zoneid")); + } + + public void testZoneIdStatic() { + AddSecondaryStorageOptions options = zoneId(6); + assertEquals(ImmutableList.of("6"), options.buildQueryParameters().get("zoneid")); + } + +} diff --git a/apis/cloudstack/src/test/resources/addsecondarystorageresponse.json b/apis/cloudstack/src/test/resources/addsecondarystorageresponse.json new file mode 100644 index 0000000000..d164d9a54c --- /dev/null +++ b/apis/cloudstack/src/test/resources/addsecondarystorageresponse.json @@ -0,0 +1,3 @@ +{ "addsecondarystorageresponse" : { "host" : + {"warning":"this test data is fabricated","id":2,"name":"nfs://10.26.26.165/mnt/nfs/cs_sec","state":"Alert","disconnected":"2011-11-26T23:33:38+0200","type":"SecondaryStorage","ipaddress":"nfs","zoneid":1,"zonename":"Dev Zone 1","version":"2.2.12.20110928142833","hypervisor":"None","lastpinged":"1970-01-16T00:42:30+0200","islocalstorageactive":false,"created":"2011-11-26T23:33:38+0200","events":"ManagementServerDown; AgentDisconnected; Remove; MaintenanceRequested; AgentConnected; Ping","hasEnoughCapacity":false,"allocationstate":"Enabled"}, +} } \ No newline at end of file From 47345053103b2082feef51a3c99930b781f9674f Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 15:25:41 +0200 Subject: [PATCH 12/15] Add GlobalHost[Async]Client.addCluster() --- .../features/GlobalHostAsyncClient.java | 17 +++ .../cloudstack/features/GlobalHostClient.java | 13 ++ .../cloudstack/options/AddClusterOptions.java | 115 ++++++++++++++++++ .../features/GlobalHostClientExpectTest.java | 19 +++ .../options/AddClusterOptionsTest.java | 86 +++++++++++++ .../test/resources/addclusterresponse.json | 1 + 6 files changed, 251 insertions(+) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/AddClusterOptions.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/AddClusterOptionsTest.java create mode 100644 apis/cloudstack/src/test/resources/addclusterresponse.json diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java index 9c46cd1367..9fde927dcb 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java @@ -22,6 +22,7 @@ import com.google.common.util.concurrent.ListenableFuture; import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.Host; import org.jclouds.cloudstack.filters.QuerySigner; +import org.jclouds.cloudstack.options.AddClusterOptions; import org.jclouds.cloudstack.options.AddHostOptions; import org.jclouds.cloudstack.options.AddSecondaryStorageOptions; import org.jclouds.cloudstack.options.DeleteHostOptions; @@ -173,4 +174,20 @@ public interface GlobalHostAsyncClient { @Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) ListenableFuture> listClusters(ListClustersOptions... options); + + /** + * Adds a new cluster. + * + * @param zoneId the Zone ID for the cluster + * @param clusterName the cluster name + * @param clusterType type of the cluster + * @param hypervisor hypervisor type of the cluster + * @param options optional arguments + * @return the new cluster. + */ + @GET + @QueryParams(keys = "command", values = "addCluster") + @SelectJson("cluster") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture addCluster(@QueryParam("zoneid") long zoneId, @QueryParam("clustername") String clusterName, @QueryParam("clustertype") Host.ClusterType clusterType, @QueryParam("hypervisor") String hypervisor, AddClusterOptions... options); } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java index 77ae55e023..295b2d968e 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java @@ -20,6 +20,7 @@ package org.jclouds.cloudstack.features; import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.Host; +import org.jclouds.cloudstack.options.AddClusterOptions; import org.jclouds.cloudstack.options.AddHostOptions; import org.jclouds.cloudstack.options.AddSecondaryStorageOptions; import org.jclouds.cloudstack.options.DeleteHostOptions; @@ -131,4 +132,16 @@ public interface GlobalHostClient { * @return clusters matching query, or empty set if no clusters match */ Set listClusters(ListClustersOptions... options); + + /** + * Adds a new cluster. + * + * @param zoneId the Zone ID for the cluster + * @param clusterName the cluster name + * @param clusterType type of the cluster + * @param hypervisor hypervisor type of the cluster + * @param options optional arguments + * @return the new cluster. + */ + Cluster addCluster(long zoneId, String clusterName, Host.ClusterType clusterType, String hypervisor, AddClusterOptions... options); } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/AddClusterOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/AddClusterOptions.java new file mode 100644 index 0000000000..107a6a8dcd --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/AddClusterOptions.java @@ -0,0 +1,115 @@ +/** + * 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.Host; +import org.jclouds.functions.JoinOnComma; +import org.jclouds.http.options.BaseHttpRequestOptions; + +import java.util.Set; + +/** + * Options to the GlobalHostClient.addHost() API call + * + * @author Richard Downer + */ +public class AddClusterOptions extends BaseHttpRequestOptions { + + public static final AddClusterOptions NONE = new AddClusterOptions(); + + /** + * @param allocationState Allocation state of this Host for allocation of new resources + */ + public AddClusterOptions allocationState(Host.AllocationState allocationState) { + this.queryParameters.replaceValues("allocationstate", ImmutableSet.of(allocationState.toString())); + return this; + } + + /** + * @param password the password for the host + */ + public AddClusterOptions password(String password) { + this.queryParameters.replaceValues("password", ImmutableSet.of(password)); + return this; + } + + /** + * @param podId the Pod ID for the host + */ + public AddClusterOptions podId(long podId) { + this.queryParameters.replaceValues("podid", ImmutableSet.of(podId + "")); + return this; + } + + /** + * @param url the URL + */ + public AddClusterOptions url(String url) { + this.queryParameters.replaceValues("url", ImmutableSet.of(url)); + return this; + } + + /** + * @param username the username for the cluster + */ + public AddClusterOptions username(String username) { + this.queryParameters.replaceValues("username", ImmutableSet.of(username)); + return this; + } + + public static class Builder { + + /** + * @param allocationState Allocation state of this Host for allocation of new resources + */ + public static AddClusterOptions allocationState(Host.AllocationState allocationState) { + return new AddClusterOptions().allocationState(allocationState); + } + + /** + * @param password the password for the host + */ + public static AddClusterOptions password(String password) { + return new AddClusterOptions().password(password); + } + + /** + * @param podId the Pod ID for the host + */ + public static AddClusterOptions podId(long podId) { + return new AddClusterOptions().podId(podId); + } + + /** + * @param url the URL + */ + public static AddClusterOptions url(String url) { + return new AddClusterOptions().url(url); + } + + /** + * @param username the username for the cluster + */ + public static AddClusterOptions username(String username) { + return new AddClusterOptions().username(username); + } + + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index 8a29f37a75..0a00ec6f65 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -25,6 +25,7 @@ import org.jclouds.cloudstack.CloudStackContext; import org.jclouds.cloudstack.domain.Cluster; import org.jclouds.cloudstack.domain.ConfigurationEntry; import org.jclouds.cloudstack.domain.Host; +import org.jclouds.cloudstack.options.AddClusterOptions; import org.jclouds.cloudstack.options.AddHostOptions; import org.jclouds.cloudstack.options.AddSecondaryStorageOptions; import org.jclouds.cloudstack.options.DeleteHostOptions; @@ -265,6 +266,24 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe assertEquals(client.listClusters(), ImmutableSet.of()); } + @Test + public void testAddClusterWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=addCluster&zoneid=1&clustertype=CloudManaged&clustername=Xen%20Clust%201&hypervisor=XenServer&allocationstate=Enabled&podid=1&url=http%3A%2F%2Fexample.com%2Fcluster&username=fred&password=sekrit&apiKey=identity&signature=2uIQ5qF0bVycXK111wxvogWp1Yw%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .payload(payloadFromResource("/addclusterresponse.json")) + .statusCode(200).build(); + + Cluster expected = Cluster.builder().id(1).name("Xen Clust 1").podId(1).podName("Dev Pod 1").zoneId(1).zoneName("Dev Zone 1").hypervisor("XenServer").clusterType(Host.ClusterType.CLOUD_MANAGED).allocationState(Host.AllocationState.ENABLED).managedState(Cluster.ManagedState.MANAGED).build(); + + Cluster actual = requestSendsResponse(request, response).addCluster(1, "Xen Clust 1", Host.ClusterType.CLOUD_MANAGED, "XenServer", AddClusterOptions.Builder.allocationState(Host.AllocationState.ENABLED).podId(1).url("http://example.com/cluster").username("fred").password("sekrit")); + + assertEquals(actual, expected); + } + private Date makeDate(int year, int month, int date, int hour, int minute, int second, String timeZoneName) { Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timeZoneName)); cal.set(Calendar.YEAR, year); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/AddClusterOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/AddClusterOptionsTest.java new file mode 100644 index 0000000000..333343eceb --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/AddClusterOptionsTest.java @@ -0,0 +1,86 @@ +/** + * 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.Host; +import org.testng.annotations.Test; + +import static org.jclouds.cloudstack.options.AddClusterOptions.Builder.*; +import static org.testng.Assert.assertEquals; + +/** + * Tests behavior of {@code AddClusterOptions} + * + * @author Richard Downer + */ +@Test(groups = "unit") +public class AddClusterOptionsTest { + + public void testAllocationState() { + AddClusterOptions options = new AddClusterOptions().allocationState(Host.AllocationState.ENABLED); + assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate")); + } + + public void testAllocationStateStatic() { + AddClusterOptions options = allocationState(Host.AllocationState.ENABLED); + assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate")); + } + + public void testPassword() { + AddClusterOptions options = new AddClusterOptions().password("sekrit"); + assertEquals(ImmutableList.of("sekrit"), options.buildQueryParameters().get("password")); + } + + public void testPasswordStatic() { + AddClusterOptions options = password("sekrit"); + assertEquals(ImmutableList.of("sekrit"), options.buildQueryParameters().get("password")); + } + + public void testPodId() { + AddClusterOptions options = new AddClusterOptions().podId(42L); + assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("podid")); + } + + public void testPodIdStatic() { + AddClusterOptions options = podId(42L); + assertEquals(ImmutableList.of("42"), options.buildQueryParameters().get("podid")); + } + + public void testUrl() { + AddClusterOptions options = new AddClusterOptions().url("http://example.com"); + assertEquals(ImmutableList.of("http://example.com"), options.buildQueryParameters().get("url")); + } + + public void testUrlStatic() { + AddClusterOptions options = url("http://example.com"); + assertEquals(ImmutableList.of("http://example.com"), options.buildQueryParameters().get("url")); + } + + public void testUsername() { + AddClusterOptions options = new AddClusterOptions().username("fred"); + assertEquals(ImmutableList.of("fred"), options.buildQueryParameters().get("username")); + } + + public void testUsernameStatic() { + AddClusterOptions options = username("fred"); + assertEquals(ImmutableList.of("fred"), options.buildQueryParameters().get("username")); + } + +} diff --git a/apis/cloudstack/src/test/resources/addclusterresponse.json b/apis/cloudstack/src/test/resources/addclusterresponse.json new file mode 100644 index 0000000000..635a651f68 --- /dev/null +++ b/apis/cloudstack/src/test/resources/addclusterresponse.json @@ -0,0 +1 @@ +{ "addclusterresponse" : { "cluster" : {"warning":"this test data is fabricated","id":1,"name":"Xen Clust 1","podid":1,"podname":"Dev Pod 1","zoneid":1,"zonename":"Dev Zone 1","hypervisortype":"XenServer","clustertype":"CloudManaged","allocationstate":"Enabled","managedstate":"Managed"} } } \ No newline at end of file From fc50e80eb70f7f4323dc7c18140da60c701a28ff Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 15:33:39 +0200 Subject: [PATCH 13/15] Add GlobalHost[Async]Client.updateCluster() --- .../features/GlobalHostAsyncClient.java | 14 +++ .../cloudstack/features/GlobalHostClient.java | 10 ++ .../options/UpdateClusterOptions.java | 113 ++++++++++++++++++ .../features/GlobalHostClientExpectTest.java | 19 +++ .../options/UpdateClusterOptionsTest.java | 67 +++++++++++ .../test/resources/updateclusterresponse.json | 1 + 6 files changed, 224 insertions(+) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateClusterOptions.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/UpdateClusterOptionsTest.java create mode 100644 apis/cloudstack/src/test/resources/updateclusterresponse.json diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java index 9fde927dcb..2f7da209bf 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java @@ -28,6 +28,7 @@ import org.jclouds.cloudstack.options.AddSecondaryStorageOptions; import org.jclouds.cloudstack.options.DeleteHostOptions; import org.jclouds.cloudstack.options.ListClustersOptions; import org.jclouds.cloudstack.options.ListHostsOptions; +import org.jclouds.cloudstack.options.UpdateClusterOptions; import org.jclouds.cloudstack.options.UpdateHostOptions; import org.jclouds.rest.annotations.ExceptionParser; import org.jclouds.rest.annotations.QueryParams; @@ -190,4 +191,17 @@ public interface GlobalHostAsyncClient { @SelectJson("cluster") @Consumes(MediaType.APPLICATION_JSON) ListenableFuture addCluster(@QueryParam("zoneid") long zoneId, @QueryParam("clustername") String clusterName, @QueryParam("clustertype") Host.ClusterType clusterType, @QueryParam("hypervisor") String hypervisor, AddClusterOptions... options); + + /** + * Updates an existing cluster. + * + * @param clusterId the ID of the cluster + * @param options optional arguments + * @return the modified cluster + */ + @GET + @QueryParams(keys = "command", values = "updateCluster") + @SelectJson("cluster") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture updateCluster(@QueryParam("id") long clusterId, UpdateClusterOptions... options); } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java index 295b2d968e..24cb3e9000 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java @@ -26,6 +26,7 @@ import org.jclouds.cloudstack.options.AddSecondaryStorageOptions; import org.jclouds.cloudstack.options.DeleteHostOptions; import org.jclouds.cloudstack.options.ListClustersOptions; import org.jclouds.cloudstack.options.ListHostsOptions; +import org.jclouds.cloudstack.options.UpdateClusterOptions; import org.jclouds.cloudstack.options.UpdateHostOptions; import org.jclouds.concurrent.Timeout; @@ -144,4 +145,13 @@ public interface GlobalHostClient { * @return the new cluster. */ Cluster addCluster(long zoneId, String clusterName, Host.ClusterType clusterType, String hypervisor, AddClusterOptions... options); + + /** + * Updates an existing cluster. + * + * @param clusterId the ID of the cluster + * @param options optional arguments + * @return the modified cluster + */ + Cluster updateCluster(long clusterId, UpdateClusterOptions... options); } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateClusterOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateClusterOptions.java new file mode 100644 index 0000000000..e02fcbdb51 --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateClusterOptions.java @@ -0,0 +1,113 @@ +/** + * 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.Cluster; +import org.jclouds.cloudstack.domain.Host; +import org.jclouds.http.options.BaseHttpRequestOptions; + +/** + * Options for the GlobalHostClient.updateCluster() API call. + * + * @author Richard Downer + */ +public class UpdateClusterOptions extends BaseHttpRequestOptions { + + public static final UpdateClusterOptions NONE = new UpdateClusterOptions(); + + /** + * @param allocationState Allocation state of this cluster for allocation of new resources + */ + public UpdateClusterOptions allocationState(Host.AllocationState allocationState) { + this.queryParameters.replaceValues("allocationstate", ImmutableSet.of(allocationState.toString())); + return this; + } + + /** + * @param clusterName the cluster name + */ + public UpdateClusterOptions clusterName(String clusterName) { + this.queryParameters.replaceValues("clustername", ImmutableSet.of(clusterName)); + return this; + } + + /** + * @param clusterType type of the cluster + */ + public UpdateClusterOptions clusterType(Host.ClusterType clusterType) { + this.queryParameters.replaceValues("clustertype", ImmutableSet.of(clusterType.toString())); + return this; + } + + /** + * @param hypervisor hypervisor type of the cluster + */ + public UpdateClusterOptions hypervisor(String hypervisor) { + this.queryParameters.replaceValues("hypervisor", ImmutableSet.of(hypervisor)); + return this; + } + + /** + * @param managedState whether this cluster is managed by cloudstack + */ + public UpdateClusterOptions managedState(Cluster.ManagedState managedState) { + this.queryParameters.replaceValues("managedstate", ImmutableSet.of(managedState.toString())); + return this; + } + + public static class Builder { + + /** + * @param allocationState Allocation state of this cluster for allocation of new resources + */ + public static UpdateClusterOptions allocationState(Host.AllocationState allocationState) { + return new UpdateClusterOptions().allocationState(allocationState); + } + + /** + * @param clusterName the cluster name + */ + public static UpdateClusterOptions clusterName(String clusterName) { + return new UpdateClusterOptions().clusterName(clusterName); + } + + /** + * @param clusterType type of the cluster + */ + public static UpdateClusterOptions clusterType(Host.ClusterType clusterType) { + return new UpdateClusterOptions().clusterType(clusterType); + } + + /** + * @param hypervisor hypervisor type of the cluster + */ + public static UpdateClusterOptions hypervisor(String hypervisor) { + return new UpdateClusterOptions().hypervisor(hypervisor); + } + + /** + * @param managedState whether this cluster is managed by cloudstack + */ + public static UpdateClusterOptions managedState(Cluster.ManagedState managedState) { + return new UpdateClusterOptions().managedState(managedState); + } + + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index 0a00ec6f65..b4df927fb0 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -29,6 +29,7 @@ import org.jclouds.cloudstack.options.AddClusterOptions; import org.jclouds.cloudstack.options.AddHostOptions; import org.jclouds.cloudstack.options.AddSecondaryStorageOptions; import org.jclouds.cloudstack.options.DeleteHostOptions; +import org.jclouds.cloudstack.options.UpdateClusterOptions; import org.jclouds.cloudstack.options.UpdateHostOptions; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; @@ -284,6 +285,24 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe assertEquals(actual, expected); } + @Test + public void testUpdateClusterWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=updateCluster&id=1&allocationstate=Enabled&clustername=Xen%20Clust%201&clustertype=CloudManaged&hypervisor=XenServer&managedstate=Managed&apiKey=identity&signature=%2FwbuYKwInciSXWkUf05lEfJZShQ%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .payload(payloadFromResource("/updateclusterresponse.json")) + .statusCode(200).build(); + + Cluster expected = Cluster.builder().id(1).name("Xen Clust 1").podId(1).podName("Dev Pod 1").zoneId(1).zoneName("Dev Zone 1").hypervisor("XenServer").clusterType(Host.ClusterType.CLOUD_MANAGED).allocationState(Host.AllocationState.ENABLED).managedState(Cluster.ManagedState.MANAGED).build(); + + Cluster actual = requestSendsResponse(request, response).updateCluster(1, UpdateClusterOptions.Builder.allocationState(Host.AllocationState.ENABLED).clusterName("Xen Clust 1").clusterType(Host.ClusterType.CLOUD_MANAGED).hypervisor("XenServer").managedState(Cluster.ManagedState.MANAGED)); + + assertEquals(actual, expected); + } + private Date makeDate(int year, int month, int date, int hour, int minute, int second, String timeZoneName) { Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timeZoneName)); cal.set(Calendar.YEAR, year); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/UpdateClusterOptionsTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/UpdateClusterOptionsTest.java new file mode 100644 index 0000000000..0cb7db39e1 --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/options/UpdateClusterOptionsTest.java @@ -0,0 +1,67 @@ +/** + * 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.Cluster; +import org.jclouds.cloudstack.domain.Host; +import org.testng.annotations.Test; + +import static org.jclouds.cloudstack.options.UpdateClusterOptions.Builder.allocationState; +import static org.testng.Assert.assertEquals; + +/** + * Tests behavior of {@code UpdateClusterOptions} + * + * @author Richard Downer + */ +@Test(groups = "unit") +public class UpdateClusterOptionsTest { + + public void testAllocationState() { + UpdateClusterOptions options = new UpdateClusterOptions().allocationState(Host.AllocationState.ENABLED); + assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate")); + } + + public void testAllocationStateStatic() { + UpdateClusterOptions options = allocationState(Host.AllocationState.ENABLED); + assertEquals(ImmutableList.of("Enabled"), options.buildQueryParameters().get("allocationstate")); + } + + public void testClusterName() { + UpdateClusterOptions options = new UpdateClusterOptions().clusterName("My Cluster"); + assertEquals(ImmutableList.of("My Cluster"), options.buildQueryParameters().get("clustername")); + } + + public void testClusterType() { + UpdateClusterOptions options = new UpdateClusterOptions().clusterType(Host.ClusterType.CLOUD_MANAGED); + assertEquals(ImmutableList.of("CloudManaged"), options.buildQueryParameters().get("clustertype")); + } + + public void testHypervisor() { + UpdateClusterOptions options = new UpdateClusterOptions().hypervisor("XenServer"); + assertEquals(ImmutableList.of("XenServer"), options.buildQueryParameters().get("hypervisor")); + } + + public void testManagedState() { + UpdateClusterOptions options = new UpdateClusterOptions().managedState(Cluster.ManagedState.PREPARE_UNMANAGED); + assertEquals(ImmutableList.of("PrepareUnmanaged"), options.buildQueryParameters().get("managedstate")); + } + +} diff --git a/apis/cloudstack/src/test/resources/updateclusterresponse.json b/apis/cloudstack/src/test/resources/updateclusterresponse.json new file mode 100644 index 0000000000..4a03ca3a25 --- /dev/null +++ b/apis/cloudstack/src/test/resources/updateclusterresponse.json @@ -0,0 +1 @@ +{ "updateclusterresponse" : { "cluster" : {"warning":"this test data is fabricated","id":1,"name":"Xen Clust 1","podid":1,"podname":"Dev Pod 1","zoneid":1,"zonename":"Dev Zone 1","hypervisortype":"XenServer","clustertype":"CloudManaged","allocationstate":"Enabled","managedstate":"Managed"} } } \ No newline at end of file From 7284d7db2f80c61930bfd2910274125b37d5868d Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 15:36:14 +0200 Subject: [PATCH 14/15] Add GlobalHost[Async]Client.updateClusterPassword() --- .../cloudstack/features/GlobalHostAsyncClient.java | 13 +++++++++++++ .../cloudstack/features/GlobalHostClient.java | 9 +++++++++ .../features/GlobalHostClientExpectTest.java | 13 +++++++++++++ 3 files changed, 35 insertions(+) diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java index 2f7da209bf..be0c3a9a79 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java @@ -204,4 +204,17 @@ public interface GlobalHostAsyncClient { @SelectJson("cluster") @Consumes(MediaType.APPLICATION_JSON) ListenableFuture updateCluster(@QueryParam("id") long clusterId, UpdateClusterOptions... options); + + /** + * Update password of a cluster on management server. + * + * @param clusterId the cluster ID + * @param username the username for the cluster + * @param password the password for the cluster + */ + @GET + @QueryParams(keys = "command", values = "updateHostPassword") + @SelectJson("cluster") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture updateClusterPassword(@QueryParam("clusterid") long clusterId, @QueryParam("username") String username, @QueryParam("password") String password); } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java index 24cb3e9000..f1b042ef53 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java @@ -154,4 +154,13 @@ public interface GlobalHostClient { * @return the modified cluster */ Cluster updateCluster(long clusterId, UpdateClusterOptions... options); + + /** + * Update password of a cluster on management server. + * + * @param hostId the cluster ID + * @param username the username for the cluster + * @param password the password for the cluster + */ + void updateClusterPassword(long clusterId, String username, String password); } diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index b4df927fb0..57b0a7414f 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -303,6 +303,19 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe assertEquals(actual, expected); } + @Test + public void testUpdateClusterPasswordWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=updateHostPassword&clusterid=1&password=sekrit&username=fred&apiKey=identity&signature=xwc83%2BoYK0cuAiFQAlg%2F7%2F1IVHE%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .statusCode(200).build(); + + requestSendsResponse(request, response).updateClusterPassword(1, "fred", "sekrit"); + } + private Date makeDate(int year, int month, int date, int hour, int minute, int second, String timeZoneName) { Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timeZoneName)); cal.set(Calendar.YEAR, year); From 17fb7b55d036772932206d641e5464e03a31e109 Mon Sep 17 00:00:00 2001 From: Richard Downer Date: Thu, 12 Jan 2012 15:38:45 +0200 Subject: [PATCH 15/15] Add GlobalHost[Async]Client.deleteCluster() --- .../cloudstack/features/GlobalHostAsyncClient.java | 11 +++++++++++ .../cloudstack/features/GlobalHostClient.java | 8 ++++++++ .../features/GlobalHostClientExpectTest.java | 13 +++++++++++++ 3 files changed, 32 insertions(+) diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java index be0c3a9a79..7085302d30 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostAsyncClient.java @@ -217,4 +217,15 @@ public interface GlobalHostAsyncClient { @SelectJson("cluster") @Consumes(MediaType.APPLICATION_JSON) ListenableFuture updateClusterPassword(@QueryParam("clusterid") long clusterId, @QueryParam("username") String username, @QueryParam("password") String password); + + /** + * Deletes a cluster. + * + * @param clusterId the cluster ID + */ + @GET + @QueryParams(keys = "command", values = "deleteCluster") + @Consumes(MediaType.APPLICATION_JSON) + ListenableFuture deleteCluster(@QueryParam("id") long clusterId); + } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java index f1b042ef53..7345263990 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalHostClient.java @@ -163,4 +163,12 @@ public interface GlobalHostClient { * @param password the password for the cluster */ void updateClusterPassword(long clusterId, String username, String password); + + /** + * Deletes a cluster. + * + * @param clusterId the cluster ID + */ + void deleteCluster(long clusterId); + } diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java index 57b0a7414f..616b135a5e 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalHostClientExpectTest.java @@ -316,6 +316,19 @@ public class GlobalHostClientExpectTest extends BaseCloudStackRestClientExpectTe requestSendsResponse(request, response).updateClusterPassword(1, "fred", "sekrit"); } + @Test + public void testDeleteClusterWhenResponseIs2xx() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/client/api?response=json&command=deleteCluster&id=1&apiKey=identity&signature=CKH26MFgKGY7Sosd17LjBMNa3AI%3D")) + .headers(ImmutableMultimap.builder().put("Accept", "application/json").build()) + .build(); + HttpResponse response = HttpResponse.builder() + .statusCode(200).build(); + + requestSendsResponse(request, response).deleteCluster(1); + } + private Date makeDate(int year, int month, int date, int hour, int minute, int second, String timeZoneName) { Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(timeZoneName)); cal.set(Calendar.YEAR, year);