From e978e01a1d3c20a1517ac79f2ba0ceae82fadeb4 Mon Sep 17 00:00:00 2001 From: andreisavu Date: Fri, 13 Jan 2012 23:07:35 +0200 Subject: [PATCH] Implemented Zone API for Global Admin --- .../CloudStackGlobalAsyncClient.java | 8 + .../cloudstack/CloudStackGlobalClient.java | 8 + .../config/CloudStackRestClientModule.java | 3 + .../org/jclouds/cloudstack/domain/Zone.java | 35 ++- .../features/GlobalZoneAsyncClient.java | 81 ++++++ .../cloudstack/features/GlobalZoneClient.java | 79 ++++++ .../cloudstack/options/CreateZoneOptions.java | 176 ++++++++++++ .../cloudstack/options/UpdateZoneOptions.java | 260 ++++++++++++++++++ .../features/GlobalZoneClientExpectTest.java | 137 +++++++++ .../features/GlobalZoneClientLiveTest.java | 67 +++++ .../features/ZoneClientExpectTest.java | 97 +++++++ .../features/ZoneClientLiveTest.java | 4 +- .../test/resources/createzoneresponse.json | 4 + .../test/resources/deletezoneresponse.json | 1 + .../test/resources/updatezoneresponse.json | 4 + 15 files changed, 955 insertions(+), 9 deletions(-) create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalZoneAsyncClient.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalZoneClient.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateZoneOptions.java create mode 100644 apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateZoneOptions.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneClientExpectTest.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneClientLiveTest.java create mode 100644 apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneClientExpectTest.java create mode 100644 apis/cloudstack/src/test/resources/createzoneresponse.json create mode 100644 apis/cloudstack/src/test/resources/deletezoneresponse.json create mode 100644 apis/cloudstack/src/test/resources/updatezoneresponse.json diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalAsyncClient.java index 28f23cb064..7ef070929f 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalAsyncClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalAsyncClient.java @@ -29,6 +29,7 @@ import org.jclouds.cloudstack.features.GlobalOfferingAsyncClient; import org.jclouds.cloudstack.features.GlobalStoragePoolAsyncClient; import org.jclouds.cloudstack.features.GlobalUsageAsyncClient; import org.jclouds.cloudstack.features.GlobalUserAsyncClient; +import org.jclouds.cloudstack.features.GlobalZoneAsyncClient; import org.jclouds.rest.annotations.Delegate; /** @@ -107,4 +108,11 @@ public interface CloudStackGlobalAsyncClient extends CloudStackDomainAsyncClient @Delegate @Override GlobalDomainAsyncClient getDomainClient(); + + /** + * Provides asynchronous access to Zone + */ + @Delegate + @Override + GlobalZoneAsyncClient getZoneClient(); } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalClient.java index 135a2cb755..c4565f4a77 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalClient.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalClient.java @@ -30,6 +30,7 @@ import org.jclouds.cloudstack.features.GlobalOfferingClient; import org.jclouds.cloudstack.features.GlobalStoragePoolClient; import org.jclouds.cloudstack.features.GlobalUsageClient; import org.jclouds.cloudstack.features.GlobalUserClient; +import org.jclouds.cloudstack.features.GlobalZoneClient; import org.jclouds.concurrent.Timeout; import org.jclouds.rest.annotations.Delegate; @@ -110,4 +111,11 @@ public interface CloudStackGlobalClient extends CloudStackDomainClient { @Delegate @Override GlobalDomainClient getDomainClient(); + + /** + * Provides synchronous access to Zone + */ + @Delegate + @Override + GlobalZoneClient getZoneClient(); } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java index 62d4b1b284..b72fa3396a 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/config/CloudStackRestClientModule.java @@ -70,6 +70,8 @@ import org.jclouds.cloudstack.features.GlobalUsageAsyncClient; import org.jclouds.cloudstack.features.GlobalUsageClient; import org.jclouds.cloudstack.features.GlobalUserAsyncClient; import org.jclouds.cloudstack.features.GlobalUserClient; +import org.jclouds.cloudstack.features.GlobalZoneAsyncClient; +import org.jclouds.cloudstack.features.GlobalZoneClient; import org.jclouds.cloudstack.features.GuestOSAsyncClient; import org.jclouds.cloudstack.features.GuestOSClient; import org.jclouds.cloudstack.features.HypervisorAsyncClient; @@ -131,6 +133,7 @@ public class CloudStackRestClientModule extends RestClientModule, Class> DELEGATE_MAP = ImmutableMap., Class> builder()// .put(ZoneClient.class, ZoneAsyncClient.class)// + .put(GlobalZoneClient.class, GlobalZoneAsyncClient.class)// .put(TemplateClient.class, TemplateAsyncClient.class)// .put(OfferingClient.class, OfferingAsyncClient.class)// .put(NetworkClient.class, NetworkAsyncClient.class)// diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Zone.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Zone.java index 0da59de3b0..d5f2e69e0d 100644 --- a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Zone.java +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/domain/Zone.java @@ -18,6 +18,8 @@ */ package org.jclouds.cloudstack.domain; +import static com.google.common.base.CaseFormat.UPPER_CAMEL; +import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE; import static com.google.common.base.Preconditions.checkNotNull; import javax.annotation.Nullable; @@ -27,9 +29,29 @@ import com.google.common.collect.ImmutableList; import com.google.gson.annotations.SerializedName; /** - * @author Adrian Cole + * @author Adrian Cole, Andrei Savu */ public class Zone implements Comparable { + + public static enum AllocationState { + DISABLED, + ENABLED, + UNKNOWN; + + public static AllocationState fromValue(String value) { + try{ + return valueOf(value.toUpperCase()); + } catch (IllegalArgumentException e) { + return UNKNOWN; + } + } + + @Override + public String toString() { + return UPPER_UNDERSCORE.to(UPPER_CAMEL, name()); + } + } + public static Builder builder() { return new Builder(); } @@ -47,7 +69,7 @@ public class Zone implements Comparable { private NetworkType networkType; private String VLAN; private boolean securityGroupsEnabled; - private String allocationState; + private AllocationState allocationState; private String dhcpProvider; private String zoneToken; @@ -112,7 +134,7 @@ public class Zone implements Comparable { } - public Builder allocationState(String allocationState) { + public Builder allocationState(AllocationState allocationState) { this.allocationState = allocationState; return this; } @@ -159,8 +181,7 @@ public class Zone implements Comparable { @SerializedName("securitygroupsenabled") private boolean securityGroupsEnabled; @SerializedName("allocationstate") - //TODO Change to enum? - private String allocationState; + private AllocationState allocationState; @SerializedName("dhcpprovider") private String dhcpProvider; @SerializedName("zonetoken") @@ -175,7 +196,7 @@ public class Zone implements Comparable { public Zone(long id, String description, String displayText, List DNS, String domain, long domainId, String guestCIDRAddress, List internalDNS, String name, NetworkType networkType, - String vLAN, boolean securityGroupsEnabled, String allocationState, String dhcpProvider, String zoneToken) { + String vLAN, boolean securityGroupsEnabled, AllocationState allocationState, String dhcpProvider, String zoneToken) { this.id = id; this.description = description; this.displayText = displayText; @@ -293,7 +314,7 @@ public class Zone implements Comparable { /** * @return the allocation state of the cluster */ - public String getAllocationState() { + public AllocationState getAllocationState() { return allocationState; } diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalZoneAsyncClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalZoneAsyncClient.java new file mode 100644 index 0000000000..d6c068b7bb --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalZoneAsyncClient.java @@ -0,0 +1,81 @@ +/** + * 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.util.concurrent.ListenableFuture; +import org.jclouds.cloudstack.domain.NetworkType; +import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.cloudstack.filters.QuerySigner; +import org.jclouds.cloudstack.options.CreateZoneOptions; +import org.jclouds.cloudstack.options.UpdateZoneOptions; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.QueryParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +/** + * Provides asynchronous access to CloudStack Account features available to Global + * Admin users. + * + * @author Adrian Cole, Andrei Savu + * @see + */ +@RequestFilters(QuerySigner.class) +@QueryParams(keys = "response", values = "json") +public interface GlobalZoneAsyncClient extends ZoneAsyncClient { + + /** + * @see GlobalZoneClient#createZone + */ + @GET + @QueryParams(keys = "command", values = "createZone") + @SelectJson("zone") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture createZone(@QueryParam("name") String name, @QueryParam("networktype") NetworkType networkType, + @QueryParam("dns1") String externalDns1, @QueryParam("internaldns1") String internalDns1, CreateZoneOptions... options); + + /** + * @see GlobalZoneClient#updateZone + */ + @GET + @QueryParams(keys = "command", values = "updateZone") + @SelectJson("zone") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture updateZone(@QueryParam("id") long id, UpdateZoneOptions... options); + + /** + * @see GlobalZoneClient#deleteZone + */ + @GET + @QueryParams(keys = "command", values = "deleteZone") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture deleteZone(@QueryParam("id") long id); +} diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalZoneClient.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalZoneClient.java new file mode 100644 index 0000000000..b3b2bf9de6 --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/features/GlobalZoneClient.java @@ -0,0 +1,79 @@ +/** + * 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 org.jclouds.cloudstack.domain.NetworkType; +import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.cloudstack.options.CreateZoneOptions; +import org.jclouds.cloudstack.options.UpdateZoneOptions; +import org.jclouds.concurrent.Timeout; + +import java.util.concurrent.TimeUnit; + +/** + * Provides synchronous access to CloudStack Zone features available to Global + * Admin users. + * + * @author Andrei Savu + * @see + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface GlobalZoneClient extends ZoneClient { + + /** + * Create a new Zone + * + * @param name + * the name of the Zone + * @param networkType + * network type of the zone, can be Basic or Advanced + * @param dns1 + * the first DNS for the Zone + * @param internalDns1 + * the first internal DNS for the Zone + * @param options + * optional arguments + * @return + * zone instance or null + */ + Zone createZone(String name, NetworkType networkType, String dns1, + String internalDns1, CreateZoneOptions... options); + + /** + * Update a zone + * + * @param id + * the ID of the Zone + * @param options + * optional arguments + * @return + */ + Zone updateZone(long id, UpdateZoneOptions... options); + + /** + * Delete a zone with a specific ID + * + * @param zoneId + * the ID of the Zone + */ + Void deleteZone(long zoneId); + +} diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateZoneOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateZoneOptions.java new file mode 100644 index 0000000000..7a4123b84d --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/CreateZoneOptions.java @@ -0,0 +1,176 @@ +/** + * 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.Zone; +import org.jclouds.http.options.BaseHttpRequestOptions; +import org.jclouds.javax.annotation.Nullable; + +/** + * Options used to control how a zone is created + * + * @see + * @author Andrei Savu + */ +public class CreateZoneOptions extends BaseHttpRequestOptions { + + public static final CreateZoneOptions NONE = new CreateZoneOptions(); + + /** + * @param allocationState + * allocation state of this Zone for allocation of new resources + */ + public CreateZoneOptions allocationState(Zone.AllocationState allocationState) { + this.queryParameters.replaceValues("allocationstate", ImmutableSet.of(allocationState.toString())); + return this; + } + + /** + * @param dns2 + * the second DNS for the Zone + */ + public CreateZoneOptions dns2(String dns2) { + this.queryParameters.replaceValues("dns2", ImmutableSet.of(dns2)); + return this; + } + + /** + * @param internalDns2 + * the second internal DNS for the Zone + */ + public CreateZoneOptions internalDns2(String internalDns2) { + this.queryParameters.replaceValues("internaldns2", ImmutableSet.of(internalDns2)); + return this; + } + + /** + * @param domainName + * network domain name for the networks in zone + */ + public CreateZoneOptions domainName(String domainName) { + this.queryParameters.replaceValues("domain", ImmutableSet.of(domainName)); + return this; + } + + /** + * @param domainId + * the ID of the containing domain; null for public zones + */ + public CreateZoneOptions domainId(@Nullable long domainId) { + this.queryParameters.replaceValues("domainid", ImmutableSet.of(domainId + "")); + return this; + } + + /** + * @param guestCIDRAddress + * the guest CIDR address for the Zone + */ + public CreateZoneOptions guestCIDRAddress(String guestCIDRAddress) { + this.queryParameters.replaceValues("guestcidraddress", ImmutableSet.of(guestCIDRAddress)); + return this; + } + + /** + * @param securityGroupEnabled + * true if network is security group enabled, false otherwise + */ + public CreateZoneOptions securityGroupEnabled(boolean securityGroupEnabled) { + this.queryParameters.replaceValues("securitygroupenabled", ImmutableSet.of(securityGroupEnabled + "")); + return this; + } + + /** + * @param vlan + * the VLAN for the Zone + */ + public CreateZoneOptions vlan(String vlan) { + this.queryParameters.replaceValues("vlan", ImmutableSet.of(vlan)); + return this; + } + + public static class Builder { + + /** + * @see CreateZoneOptions#allocationState + */ + public static CreateZoneOptions allocationState(Zone.AllocationState allocationState) { + CreateZoneOptions options = new CreateZoneOptions(); + return options.allocationState(allocationState); + } + + /** + * @see CreateZoneOptions#dns2 + */ + public static CreateZoneOptions dns2(String dns2) { + CreateZoneOptions options = new CreateZoneOptions(); + return options.dns2(dns2); + } + + /** + * @see CreateZoneOptions#internalDns2 + */ + public static CreateZoneOptions internalDns2(String internalDns2) { + CreateZoneOptions options = new CreateZoneOptions(); + return options.internalDns2(internalDns2); + } + + /** + * @see CreateZoneOptions#domainName + */ + public static CreateZoneOptions domainName(String domainName) { + CreateZoneOptions options = new CreateZoneOptions(); + return options.domainName(domainName); + } + + /** + * @see CreateZoneOptions#domainId + */ + public static CreateZoneOptions domainId(@Nullable long domainId) { + CreateZoneOptions options = new CreateZoneOptions(); + return options.domainId(domainId); + } + + /** + * @see CreateZoneOptions#guestCIDRAddress + */ + public static CreateZoneOptions guestCIDRAddress(String guestCIDRAddress) { + CreateZoneOptions options = new CreateZoneOptions(); + return options.guestCIDRAddress(guestCIDRAddress); + } + + /** + * @see CreateZoneOptions#securityGroupEnabled + */ + public static CreateZoneOptions securityGroupEnabled(boolean securityGroupEnabled) { + CreateZoneOptions options = new CreateZoneOptions(); + return options.securityGroupEnabled(securityGroupEnabled); + } + + /** + * @see CreateZoneOptions#vlan + */ + public static CreateZoneOptions vlan(String vlan) { + CreateZoneOptions options = new CreateZoneOptions(); + return options.vlan(vlan); + } + } +} diff --git a/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateZoneOptions.java b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateZoneOptions.java new file mode 100644 index 0000000000..5ea966a17b --- /dev/null +++ b/apis/cloudstack/src/main/java/org/jclouds/cloudstack/options/UpdateZoneOptions.java @@ -0,0 +1,260 @@ +/** + * 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.Zone; +import org.jclouds.http.options.BaseHttpRequestOptions; + +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * Options used to control how a zone is updated + * + * @see + * @author Andrei Savu + */ +public class UpdateZoneOptions extends BaseHttpRequestOptions { + + public static final UpdateZoneOptions NONE = new UpdateZoneOptions(); + + /** + * @param allocationState + * allocation state of this Zone for allocation of new resources + */ + public UpdateZoneOptions allocationState(Zone.AllocationState allocationState) { + this.queryParameters.replaceValues("allocationstate", ImmutableSet.of(allocationState.toString())); + return this; + } + + /** + * @param details + * the details for the Zone + */ + public UpdateZoneOptions details(String details) { + this.queryParameters.replaceValues("details", ImmutableSet.of(details)); + return this; + } + + /** + * @param dhcpProvider + * the dhcp Provider for the Zone + */ + public UpdateZoneOptions dhcpProvider(String dhcpProvider) { + this.queryParameters.replaceValues("dhcpprovider", ImmutableSet.of(dhcpProvider)); + return this; + } + + /** + * @param externalDnsServers + * the list of external DNS servers + */ + public UpdateZoneOptions externalDns(List externalDnsServers) { + checkArgument(externalDnsServers.size() == 1 || externalDnsServers.size() == 2, + "The list of DNS servers should have 1 or 2 elements"); + this.queryParameters.replaceValues("dns1", + ImmutableSet.of(externalDnsServers.get(0))); + if (externalDnsServers.size() == 2) { + this.queryParameters.replaceValues("dns2", + ImmutableSet.of(externalDnsServers.get(1))); + } + return this; + } + + /** + * @param internalDnsServers + * the list of internal DNS for the Zone + */ + public UpdateZoneOptions internalDns(List internalDnsServers) { + checkArgument(internalDnsServers.size() == 1 || internalDnsServers.size() == 2, + "The list of internal DNS servers should have 1 or 2 elements"); + this.queryParameters.replaceValues("internaldns1", + ImmutableSet.of(internalDnsServers.get(0))); + if (internalDnsServers.size() == 2) { + this.queryParameters.replaceValues("internaldns2", + ImmutableSet.of(internalDnsServers.get(1))); + } + return this; + } + + /** + * @param dnsSearchOrder + * the dns search order list + */ + public UpdateZoneOptions dnsSearchOrder(String dnsSearchOrder) { + this.queryParameters.replaceValues("dnssearchorder", ImmutableSet.of(dnsSearchOrder)); + return this; + } + + /** + * @param domainName + * network domain name for the networks in zone + */ + public UpdateZoneOptions domainName(String domainName) { + this.queryParameters.replaceValues("domain", ImmutableSet.of(domainName)); + return this; + } + + /** + * @param guestCIDRAddress + * the guest CIDR address for the Zone + */ + public UpdateZoneOptions guestCIDRAddress(String guestCIDRAddress) { + this.queryParameters.replaceValues("guestcidraddress", ImmutableSet.of(guestCIDRAddress)); + return this; + } + + /** + * @param securityGroupEnabled + * true if network is security group enabled, false otherwise + */ + public UpdateZoneOptions securityGroupEnabled(boolean securityGroupEnabled) { + this.queryParameters.replaceValues("securitygroupenabled", ImmutableSet.of(securityGroupEnabled + "")); + return this; + } + + /** + * You can only make a private Zone public, not the other way around + */ + public UpdateZoneOptions makePublic() { + this.queryParameters.replaceValues("ispublic", ImmutableSet.of("true")); + return this; + } + + /** + * @param name + * the name of the Zone + */ + public UpdateZoneOptions name(String name) { + this.queryParameters.replaceValues("name", ImmutableSet.of(name)); + return this; + } + + /** + * @param vlan + * the VLAN for the Zone + */ + public UpdateZoneOptions vlan(String vlan) { + this.queryParameters.replaceValues("vlan", ImmutableSet.of(vlan)); + return this; + } + + public static class Builder { + + /** + * @see UpdateZoneOptions#allocationState + */ + public static UpdateZoneOptions allocationState(Zone.AllocationState allocationState) { + UpdateZoneOptions options = new UpdateZoneOptions(); + return options.allocationState(allocationState); + } + + /** + * @see UpdateZoneOptions#details + */ + public static UpdateZoneOptions details(String details) { + UpdateZoneOptions options = new UpdateZoneOptions(); + return options.details(details); + } + + /** + * @see UpdateZoneOptions#dhcpProvider + */ + public static UpdateZoneOptions dhcpProvider(String dhcpProvider) { + UpdateZoneOptions options = new UpdateZoneOptions(); + return options.dhcpProvider(dhcpProvider); + } + + /** + * @see UpdateZoneOptions#externalDns + */ + public static UpdateZoneOptions externalDns(List externalDnsServers) { + UpdateZoneOptions options = new UpdateZoneOptions(); + return options.externalDns(externalDnsServers); + } + + /** + * @see UpdateZoneOptions#internalDns + */ + public static UpdateZoneOptions internalDns(List internalDnsServers) { + UpdateZoneOptions options = new UpdateZoneOptions(); + return options.internalDns(internalDnsServers); + } + + /** + * @see UpdateZoneOptions#dnsSearchOrder + */ + public static UpdateZoneOptions dnsSearchOrder(String dnsSearchOrder) { + UpdateZoneOptions options = new UpdateZoneOptions(); + return options.dnsSearchOrder(dnsSearchOrder); + } + + /** + * @see UpdateZoneOptions#domainName + */ + public static UpdateZoneOptions domainName(String domainName) { + UpdateZoneOptions options = new UpdateZoneOptions(); + return options.domainName(domainName); + } + + /** + * @see UpdateZoneOptions#guestCIDRAddress + */ + public static UpdateZoneOptions guestCIDRAddress(String guestCIDRAddress) { + UpdateZoneOptions options = new UpdateZoneOptions(); + return options.guestCIDRAddress(guestCIDRAddress); + } + + /** + * @see UpdateZoneOptions#securityGroupEnabled + */ + public static UpdateZoneOptions securityGroupEnabled(boolean securityGroupEnabled) { + UpdateZoneOptions options = new UpdateZoneOptions(); + return options.securityGroupEnabled(securityGroupEnabled); + } + + /** + * @see UpdateZoneOptions#makePublic + */ + public static UpdateZoneOptions makePublic() { + UpdateZoneOptions options = new UpdateZoneOptions(); + return options.makePublic(); + } + + /** + * @see UpdateZoneOptions#name + */ + public static UpdateZoneOptions name(String name) { + UpdateZoneOptions options = new UpdateZoneOptions(); + return options.name(name); + } + + /** + * @see UpdateZoneOptions#vlan + */ + public static UpdateZoneOptions vlan(String vlan) { + UpdateZoneOptions options = new UpdateZoneOptions(); + return options.vlan(vlan); + } + } +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneClientExpectTest.java new file mode 100644 index 0000000000..c7228b342a --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneClientExpectTest.java @@ -0,0 +1,137 @@ +/** + * 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.collect.ImmutableList; +import com.google.common.collect.ImmutableMultimap; +import org.jclouds.cloudstack.CloudStackContext; +import org.jclouds.cloudstack.domain.NetworkType; +import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import java.net.URI; + +import static org.jclouds.cloudstack.options.UpdateZoneOptions.Builder.name; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +/** + * Test the CloudStack GlobalZoneClient + * + * @author Andrei Savu + */ +@Test(groups = "unit", testName = "GlobalZoneClientExpectTest") +public class GlobalZoneClientExpectTest extends BaseCloudStackRestClientExpectTest { + + public void testCreateZoneWhenResponseIs2xxAnd404() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&command=createZone&" + + "name=test-zone&dns1=8.8.8.8&networktype=Basic&internaldns1=10.10.10.10&" + + "apiKey=identity&signature=hWNmM2%2BTsfb5DelQa%2FGJLN5DVWE%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(); + + GlobalZoneClient client = requestSendsResponse(request, + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/createzoneresponse.json")) + .build()); + + assertEquals(client.createZone("test-zone", NetworkType.BASIC, "8.8.8.8", "10.10.10.10"), + Zone.builder() + .id(6) + .name("test-zone") + .DNS(ImmutableList.of("8.8.8.8")) + .internalDNS(ImmutableList.of("10.10.10.10")) + .networkType(NetworkType.BASIC) + .securityGroupsEnabled(true) + .allocationState(Zone.AllocationState.ENABLED) + .zoneToken("7b6e27df-30a6-3024-9d8b-7971a3127f64") + .dhcpProvider("DhcpServer").build()); + + client = requestSendsResponse(request, HttpResponse.builder().statusCode(404).build()); + assertNull(client.createZone("test-zone", NetworkType.BASIC, "8.8.8.8", "10.10.10.10")); + } + + public void testUpdateZoneWhenResponseIs2xxAnd404() { + HttpRequest request = HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&command=updateZone&" + + "id=6&name=test-zone&dns1=8.8.8.8&apiKey=identity&signature=v19FdHKHztdT0IRloYFFn0eNbWM%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(); + + GlobalZoneClient client = requestSendsResponse(request, + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/updatezoneresponse.json")) + .build()); + + assertEquals(client.updateZone(6, name("test-zone").externalDns(ImmutableList.of("8.8.8.8"))), + Zone.builder() + .id(6) + .name("test-zone") + .DNS(ImmutableList.of("8.8.8.8")) + .internalDNS(ImmutableList.of("10.10.10.10")) + .networkType(NetworkType.BASIC) + .securityGroupsEnabled(true) + .allocationState(Zone.AllocationState.ENABLED) + .zoneToken("7b6e27df-30a6-3024-9d8b-7971a3127f64") + .dhcpProvider("DhcpServer").build()); + + client = requestSendsResponse(request, HttpResponse.builder().statusCode(404).build()); + assertNull(client.updateZone(6, name("test-zone").externalDns(ImmutableList.of("8.8.8.8")))); + } + + public void testDeleteZone() { + GlobalZoneClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=deleteZone&id=6&apiKey=identity&signature=TfkzSIK8kzGJnIYo3DofECyuOII%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/deletezoneresponse.json")) + .build()); + + client.deleteZone(6); + } + + @Override + protected GlobalZoneClient clientFrom(CloudStackContext context) { + return context.getGlobalContext().getApi().getZoneClient(); + } +} \ No newline at end of file diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneClientLiveTest.java new file mode 100644 index 0000000000..e873376895 --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/GlobalZoneClientLiveTest.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.features; + +import com.google.common.collect.ImmutableList; +import org.jclouds.cloudstack.domain.NetworkType; +import org.jclouds.cloudstack.domain.Zone; +import org.testng.annotations.Test; + +import static org.jclouds.cloudstack.options.UpdateZoneOptions.Builder.name; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +/** + * Tests behavior of {@code GlobalZoneClient} + * + * @author Andrei Savu + */ +@Test(groups = "live", singleThreaded = true, testName = "GlobalZoneClientLiveTest") +public class GlobalZoneClientLiveTest extends BaseCloudStackClientLiveTest { + + @Test + public void testCreateUpdateDeleteZone() { + assert globalAdminEnabled; + + Zone zone = null; + String zoneName = prefix + "-zone"; + try { + zone = globalAdminClient.getZoneClient().createZone(zoneName, + NetworkType.BASIC, "8.8.8.8", "10.10.10.10"); + + assertNotNull(zone); + assertEquals(zone, globalAdminClient.getZoneClient().getZone(zone.getId())); + assertEquals(zone.getNetworkType(), NetworkType.BASIC); + assertEquals(zone.getDNS(), ImmutableList.of("8.8.8.8")); + assertEquals(zone.getInternalDNS(), ImmutableList.of("10.10.10.10")); + + Zone updated = globalAdminClient.getZoneClient().updateZone(zone.getId(), + name(zoneName + "-2").externalDns(ImmutableList.of("8.8.4.4"))); + assertEquals(updated.getId(), zone.getId()); + assertEquals(updated.getDNS(), ImmutableList.of("8.8.4.4")); + + } finally { + if (zone != null) { + globalAdminClient.getZoneClient().deleteZone(zone.getId()); + } + } + + } + +} diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneClientExpectTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneClientExpectTest.java new file mode 100644 index 0000000000..d71874016b --- /dev/null +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneClientExpectTest.java @@ -0,0 +1,97 @@ +/** + * 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.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import org.jclouds.cloudstack.CloudStackContext; +import org.jclouds.cloudstack.domain.NetworkType; +import org.jclouds.cloudstack.domain.Zone; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.testng.annotations.Test; + +import java.net.URI; + +import static org.testng.Assert.assertEquals; + +/** + * Test the CloudStack ZoneClient + * + * @author Andrei Savu + */ +@Test(groups = "unit", testName = "ZoneClientExpectTest") +public class ZoneClientExpectTest extends BaseCloudStackRestClientExpectTest { + + + public void testListZonesWhenResponseIs2xx() { + ZoneClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=listZones&apiKey=identity&signature=wLSqVlxuiLXZcHi9IoSAwXNRGFs%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/listzonesresponse.json")) + .build()); + + assertEquals(client.listZones(), + ImmutableSet.of( + Zone.builder() + .id(1) + .name("San Jose 1") + .networkType(NetworkType.ADVANCED) + .securityGroupsEnabled(false).build(), + Zone.builder() + .id(2) + .name("Chicago") + .networkType(NetworkType.ADVANCED) + .securityGroupsEnabled(true).build())); + } + + public void testListZonesWhenResponseIs404() { + ZoneClient client = requestSendsResponse( + HttpRequest.builder() + .method("GET") + .endpoint( + URI.create("http://localhost:8080/client/api?response=json&" + + "command=listZones&apiKey=identity&signature=wLSqVlxuiLXZcHi9IoSAwXNRGFs%3D")) + .headers( + ImmutableMultimap.builder() + .put("Accept", "application/json") + .build()) + .build(), + HttpResponse.builder() + .statusCode(404) + .build()); + + assertEquals(client.listZones(), ImmutableSet.of()); + } + + @Override + protected ZoneClient clientFrom(CloudStackContext context) { + return context.getProviderSpecificContext().getApi().getZoneClient(); + } +} \ No newline at end of file diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneClientLiveTest.java index c4d5846ff1..c829d52518 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/ZoneClientLiveTest.java @@ -61,8 +61,8 @@ public class ZoneClientLiveTest extends BaseCloudStackClientLiveTest { break; case BASIC: assert zone.getVLAN() == null : zone; - assert zone.getDNS().size() == 0 : zone; - assert zone.getInternalDNS().size() == 0 : zone; + assert zone.getDNS().size() >= 0 : zone; + assert zone.getInternalDNS().size() >= 0 : zone; assert zone.getDomain() == null : zone; assert zone.getDomainId() <= 0 : zone; assert zone.getGuestCIDRAddress() == null : zone; diff --git a/apis/cloudstack/src/test/resources/createzoneresponse.json b/apis/cloudstack/src/test/resources/createzoneresponse.json new file mode 100644 index 0000000000..a4b9604bda --- /dev/null +++ b/apis/cloudstack/src/test/resources/createzoneresponse.json @@ -0,0 +1,4 @@ +{ "createzoneresponse" : { "zone" : + {"id":6,"name":"test-zone","dns1":"8.8.8.8","internaldns1":"10.10.10.10","networktype":"Basic", + "securitygroupsenabled":true,"allocationstate":"Enabled","zonetoken":"7b6e27df-30a6-3024-9d8b-7971a3127f64", + "dhcpprovider":"DhcpServer"} } } \ No newline at end of file diff --git a/apis/cloudstack/src/test/resources/deletezoneresponse.json b/apis/cloudstack/src/test/resources/deletezoneresponse.json new file mode 100644 index 0000000000..93d68e2b6d --- /dev/null +++ b/apis/cloudstack/src/test/resources/deletezoneresponse.json @@ -0,0 +1 @@ +{ "deletezoneresponse" : { "success" : "true"} } \ No newline at end of file diff --git a/apis/cloudstack/src/test/resources/updatezoneresponse.json b/apis/cloudstack/src/test/resources/updatezoneresponse.json new file mode 100644 index 0000000000..240c49d913 --- /dev/null +++ b/apis/cloudstack/src/test/resources/updatezoneresponse.json @@ -0,0 +1,4 @@ +{ "updatezoneresponse" : { "zone" : + {"id":6,"name":"test-zone","dns1":"8.8.8.8","internaldns1":"10.10.10.10","networktype":"Basic", + "securitygroupsenabled":true,"allocationstate":"Enabled","zonetoken":"7b6e27df-30a6-3024-9d8b-7971a3127f64", + "dhcpprovider":"DhcpServer"} } } \ No newline at end of file