updated cloudstack to work with both security group and advanced networking

This commit is contained in:
Adrian Cole 2011-03-14 01:41:08 -07:00
parent f5fa2d983b
commit 94ac74d711
59 changed files with 2300 additions and 425 deletions

View File

@ -21,8 +21,10 @@ package org.jclouds.cloudstack;
import org.jclouds.cloudstack.features.AddressAsyncClient;
import org.jclouds.cloudstack.features.AsyncJobAsyncClient;
import org.jclouds.cloudstack.features.ConfigurationAsyncClient;
import org.jclouds.cloudstack.features.FirewallAsyncClient;
import org.jclouds.cloudstack.features.GuestOSAsyncClient;
import org.jclouds.cloudstack.features.HypervisorAsyncClient;
import org.jclouds.cloudstack.features.LoadBalancerAsyncClient;
import org.jclouds.cloudstack.features.NATAsyncClient;
import org.jclouds.cloudstack.features.NetworkAsyncClient;
@ -114,4 +116,16 @@ public interface CloudStackAsyncClient {
*/
@Delegate
GuestOSAsyncClient getGuestOSClient();
/**
* Provides asynchronous access to Hypervisor features.
*/
@Delegate
HypervisorAsyncClient getHypervisorClient();
/**
* Provides asynchronous access to Configuration features.
*/
@Delegate
ConfigurationAsyncClient getConfigurationClient();
}

View File

@ -23,8 +23,10 @@ import java.util.concurrent.TimeUnit;
import org.jclouds.cloudstack.features.AddressClient;
import org.jclouds.cloudstack.features.AsyncJobClient;
import org.jclouds.cloudstack.features.ConfigurationClient;
import org.jclouds.cloudstack.features.FirewallClient;
import org.jclouds.cloudstack.features.GuestOSClient;
import org.jclouds.cloudstack.features.HypervisorClient;
import org.jclouds.cloudstack.features.LoadBalancerClient;
import org.jclouds.cloudstack.features.NATClient;
import org.jclouds.cloudstack.features.NetworkClient;
@ -117,4 +119,16 @@ public interface CloudStackClient {
*/
@Delegate
GuestOSClient getGuestOSClient();
/**
* Provides synchronous access to Hypervisor features.
*/
@Delegate
HypervisorClient getHypervisorClient();
/**
* Provides synchronous access to Configuration features.
*/
@Delegate
ConfigurationClient getConfigurationClient();
}

View File

@ -0,0 +1,70 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map.Entry;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.ws.rs.core.UriBuilder;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.Binder;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.ImmutableMultimap.Builder;
/**
*
* @author Adrian Cole
*/
@Singleton
public class BindAccountSecurityGroupPairsToIndexedQueryParams implements Binder {
private final Provider<UriBuilder> uriBuilderProvider;
@Inject
public BindAccountSecurityGroupPairsToIndexedQueryParams(Provider<UriBuilder> uriBuilderProvider) {
this.uriBuilderProvider = checkNotNull(uriBuilderProvider, "uriBuilderProvider");
}
@SuppressWarnings("unchecked")
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(input instanceof Multimap<?, ?>, "this binder is only valid for Multimaps!");
Multimap<String, String> pairs = (Multimap<String, String>) checkNotNull(input, "account group pairs");
checkArgument(pairs.size() > 0, "you must specify at least one account, group pair");
UriBuilder builder = uriBuilderProvider.get();
builder.uri(request.getEndpoint());
Builder<String, String> map = ImmutableMultimap.<String, String> builder().putAll(
ModifyRequest.parseQueryToMap(request.getEndpoint().getQuery()));
int i = 0;
for (Entry<String, String> entry : pairs.entries())
map.put(String.format("usersecuritygrouplist[%d].account", i), entry.getKey()).put(
String.format("usersecuritygrouplist[%d].group", i++), entry.getValue());
builder.replaceQuery(ModifyRequest.makeQueryLine(map.build(), null));
return (R) request.toBuilder().endpoint(builder.build()).build();
}
}

View File

@ -0,0 +1,58 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.ws.rs.core.UriBuilder;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.rest.Binder;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*/
@Singleton
public class BindCIDRsToCommaDelimitedQueryParam implements Binder {
private final Provider<UriBuilder> uriBuilderProvider;
@Inject
public BindCIDRsToCommaDelimitedQueryParam(Provider<UriBuilder> uriBuilderProvider) {
this.uriBuilderProvider = checkNotNull(uriBuilderProvider, "uriBuilderProvider");
}
@SuppressWarnings("unchecked")
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(input instanceof Iterable<?>, "this binder is only valid for Iterables!");
Iterable<String> cidrs = (Iterable<String>) checkNotNull(input, "cidr list");
checkArgument(Iterables.size(cidrs) > 0, "you must specify at least one cidr range");
return ModifyRequest.addQueryParam(request, "cidrlist", Joiner.on(',').join(cidrs), uriBuilderProvider.get());
}
}

View File

@ -27,10 +27,14 @@ import org.jclouds.cloudstack.features.AddressAsyncClient;
import org.jclouds.cloudstack.features.AddressClient;
import org.jclouds.cloudstack.features.AsyncJobAsyncClient;
import org.jclouds.cloudstack.features.AsyncJobClient;
import org.jclouds.cloudstack.features.ConfigurationAsyncClient;
import org.jclouds.cloudstack.features.ConfigurationClient;
import org.jclouds.cloudstack.features.FirewallAsyncClient;
import org.jclouds.cloudstack.features.FirewallClient;
import org.jclouds.cloudstack.features.GuestOSAsyncClient;
import org.jclouds.cloudstack.features.GuestOSClient;
import org.jclouds.cloudstack.features.HypervisorAsyncClient;
import org.jclouds.cloudstack.features.HypervisorClient;
import org.jclouds.cloudstack.features.LoadBalancerAsyncClient;
import org.jclouds.cloudstack.features.LoadBalancerClient;
import org.jclouds.cloudstack.features.NATAsyncClient;
@ -72,19 +76,21 @@ import com.google.common.collect.ImmutableMap;
public class CloudStackRestClientModule extends RestClientModule<CloudStackClient, CloudStackAsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
.put(ZoneClient.class, ZoneAsyncClient.class)//
.put(TemplateClient.class, TemplateAsyncClient.class)//
.put(OfferingClient.class, OfferingAsyncClient.class)//
.put(NetworkClient.class, NetworkAsyncClient.class)//
.put(VirtualMachineClient.class, VirtualMachineAsyncClient.class)//
.put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)//
.put(AsyncJobClient.class, AsyncJobAsyncClient.class)//
.put(AddressClient.class, AddressAsyncClient.class)//
.put(NATClient.class, NATAsyncClient.class)//
.put(FirewallClient.class, FirewallAsyncClient.class)//
.put(LoadBalancerClient.class, LoadBalancerAsyncClient.class)//
.put(GuestOSClient.class, GuestOSAsyncClient.class)//
.build();
.put(ZoneClient.class, ZoneAsyncClient.class)//
.put(TemplateClient.class, TemplateAsyncClient.class)//
.put(OfferingClient.class, OfferingAsyncClient.class)//
.put(NetworkClient.class, NetworkAsyncClient.class)//
.put(VirtualMachineClient.class, VirtualMachineAsyncClient.class)//
.put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)//
.put(AsyncJobClient.class, AsyncJobAsyncClient.class)//
.put(AddressClient.class, AddressAsyncClient.class)//
.put(NATClient.class, NATAsyncClient.class)//
.put(FirewallClient.class, FirewallAsyncClient.class)//
.put(LoadBalancerClient.class, LoadBalancerAsyncClient.class)//
.put(GuestOSClient.class, GuestOSAsyncClient.class)//
.put(HypervisorClient.class, HypervisorAsyncClient.class)//
.put(ConfigurationClient.class, ConfigurationAsyncClient.class)//
.build();
public CloudStackRestClientModule() {
super(CloudStackClient.class, CloudStackAsyncClient.class, DELEGATE_MAP);

View File

@ -0,0 +1,140 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.domain;
import com.google.gson.annotations.SerializedName;
/**
*
* @author Adrian Cole
*/
public class Capabilities {
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String cloudStackVersion;
private boolean securityGroupsEnabled;
private boolean canShareTemplates;
public Builder cloudStackVersion(String cloudStackVersion) {
this.cloudStackVersion = cloudStackVersion;
return this;
}
public Builder securityGroupsEnabled(boolean securityGroupsEnabled) {
this.securityGroupsEnabled = securityGroupsEnabled;
return this;
}
public Builder sharedTemplatesEnabled(boolean canShareTemplates) {
this.canShareTemplates = canShareTemplates;
return this;
}
public Capabilities build() {
return new Capabilities(cloudStackVersion, securityGroupsEnabled, canShareTemplates);
}
}
@SerializedName("cloudstackversion")
private String cloudStackVersion;
@SerializedName("securitygroupsenabled")
private boolean securityGroupsEnabled;
@SerializedName("userpublictemplateenabled")
private boolean canShareTemplates;
/**
* present only for serializer
*
*/
Capabilities() {
}
public Capabilities(String cloudStackVersion, boolean securityGroupsEnabled, boolean canShareTemplates) {
this.cloudStackVersion = cloudStackVersion;
this.securityGroupsEnabled = securityGroupsEnabled;
this.canShareTemplates = canShareTemplates;
}
/**
*
* @return version of the cloud stack
*/
public String getCloudStackVersion() {
return cloudStackVersion;
}
/**
*
* @return true if security groups support is enabled, false otherwise
*/
public boolean isSecurityGroupsEnabled() {
return securityGroupsEnabled;
}
/**
*
* @return true if user and domain admins can set templates to be shared, false otherwise
*/
public boolean isSharedTemplatesEnabled() {
return canShareTemplates;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (canShareTemplates ? 1231 : 1237);
result = prime * result + ((cloudStackVersion == null) ? 0 : cloudStackVersion.hashCode());
result = prime * result + (securityGroupsEnabled ? 1231 : 1237);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Capabilities other = (Capabilities) obj;
if (canShareTemplates != other.canShareTemplates)
return false;
if (cloudStackVersion == null) {
if (other.cloudStackVersion != null)
return false;
} else if (!cloudStackVersion.equals(other.cloudStackVersion))
return false;
if (securityGroupsEnabled != other.securityGroupsEnabled)
return false;
return true;
}
@Override
public String toString() {
return "[cloudStackVersion=" + cloudStackVersion + ", canShareTemplates=" + canShareTemplates
+ ", securityGroupsEnabled=" + securityGroupsEnabled + "]";
}
}

View File

@ -19,6 +19,8 @@
package org.jclouds.cloudstack.domain;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.gson.annotations.SerializedName;
/**
@ -33,13 +35,13 @@ public class IngressRule implements Comparable<IngressRule> {
public static class Builder {
private String account;
private String CIDR;
private int endPort;
private int ICMPCode;
private int ICMPType;
private int endPort = -1;
private int ICMPCode = -1;
private int ICMPType = -1;
private String protocol;
private long id;
private long id = -1;
private String securityGroupName;
private int startPort;
private int startPort = -1;
public Builder account(String account) {
this.account = account;
@ -95,28 +97,34 @@ public class IngressRule implements Comparable<IngressRule> {
@SerializedName("cidr")
private String CIDR;
@SerializedName("endport")
private int endPort;
private int endPort = -1;
@SerializedName("icmpcode")
private int ICMPCode;
private int ICMPCode = -1;
@SerializedName("icmptype")
private int ICMPType;
private int ICMPType = -1;
private String protocol;
@SerializedName("ruleid")
private long id;
private long id = -1;
@SerializedName("securitygroupname")
private String securityGroupName;
@SerializedName("startport")
private int startPort;
private int startPort = -1;
// for serialization
IngressRule() {
}
public IngressRule(String account, String cIDR, int endPort, int iCMPCode, int iCMPType, String protocol, long id,
String securityGroupName, int startPort) {
public IngressRule(String account, String CIDR, int endPort, int iCMPCode, int iCMPType, String protocol, long id,
String securityGroupName, int startPort) {
if (account == null)
checkArgument(securityGroupName == null && CIDR != null,
"if you do not specify an account and security group, you must specify a CIDR range");
if (CIDR == null)
checkArgument(account != null && securityGroupName != null,
"if you do not specify an account and security group, you must specify a CIDR range");
this.account = account;
this.CIDR = cIDR;
this.CIDR = CIDR;
this.endPort = endPort;
this.ICMPCode = iCMPCode;
this.ICMPType = iCMPType;
@ -250,8 +258,8 @@ public class IngressRule implements Comparable<IngressRule> {
@Override
public String toString() {
return "[id=" + id + ", securityGroupName=" + securityGroupName + ", account=" + account + ", startPort="
+ startPort + ", endPort=" + endPort + ", protocol=" + protocol + ", CIDR=" + CIDR + ", ICMPCode="
+ ICMPCode + ", ICMPType=" + ICMPType + "]";
+ startPort + ", endPort=" + endPort + ", protocol=" + protocol + ", CIDR=" + CIDR + ", ICMPCode="
+ ICMPCode + ", ICMPType=" + ICMPType + "]";
}
@Override

View File

@ -287,7 +287,7 @@ public class Zone implements Comparable<Zone> {
/**
*
* @return true if this is an advanced network with security groups enabled, or a basic network.
* @return true if this zone has security groups enabled
*/
public boolean isSecurityGroupsEnabled() {
return securityGroupsEnabled;

View File

@ -0,0 +1,55 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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 javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.core.MediaType;
import org.jclouds.cloudstack.domain.Capabilities;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.Unwrap;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to cloudstack via their REST API.
* <p/>
*
* @see ConfigurationClient
* @see <a href="http://download.cloud.com/releases/2.2.0/api/TOC_User.html" />
* @author Adrian Cole
*/
@RequestFilters(QuerySigner.class)
@QueryParams(keys = "response", values = "json")
public interface ConfigurationAsyncClient {
/**
* @see ConfigurationClient#listCapabilities
*/
@GET
@QueryParams(keys = "command", values = "listCapabilities")
@Unwrap(depth = 2)
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Capabilities> listCapabilities();
}

View File

@ -0,0 +1,45 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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 java.util.concurrent.TimeUnit;
import org.jclouds.cloudstack.domain.Capabilities;
import org.jclouds.concurrent.Timeout;
/**
* Provides synchronous access to CloudStack Configuration features.
* <p/>
*
* @see ConfigurationAsyncClient
* @see <a href="http://download.cloud.com/releases/2.2.0/api/TOC_User.html" />
* @author Adrian Cole
*/
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface ConfigurationClient {
/**
* Lists capabilities
*
* @return current capabilities of this cloud
*
*/
Capabilities listCapabilities();
}

View File

@ -19,6 +19,7 @@
package org.jclouds.cloudstack.features;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.Consumes;
@ -28,10 +29,13 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.cloudstack.domain.OSType;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.functions.ParseIdToNameEntryFromHttpResponse;
import org.jclouds.cloudstack.functions.ParseIdToNameFromHttpResponse;
import org.jclouds.cloudstack.options.ListOSTypesOptions;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.Unwrap;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
@ -69,4 +73,23 @@ public interface GuestOSAsyncClient {
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<OSType> getOSType(@QueryParam("id") long id);
/**
* @see GuestOSClient#listOSCategories
*/
@GET
@QueryParams(keys = "command", values = "listOsCategories")
@ResponseParser(ParseIdToNameFromHttpResponse.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Map<Long, String>> listOSCategories();
/**
* @see GuestOSClient#getOSCategory
*/
@GET
@QueryParams(keys = "command", values = "listOsCategories")
@ResponseParser(ParseIdToNameEntryFromHttpResponse.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Map.Entry<Long, String>> getOSCategory(@QueryParam("id") long id);
}

View File

@ -19,6 +19,7 @@
package org.jclouds.cloudstack.features;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -53,4 +54,20 @@ public interface GuestOSClient {
* @return os type or null if not found
*/
OSType getOSType(long id);
/**
* Lists all supported OS categories for this cloud.
*
* @return os categories matching query, or empty set, if no categories are found
*/
Map<Long, String> listOSCategories();
/**
* get a specific os category by id
*
* @param id
* os category to get
* @return os category or null if not found
*/
Map.Entry<Long, String> getOSCategory(long id);
}

View File

@ -0,0 +1,66 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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 java.util.Set;
import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.functions.ParseNamesFromHttpResponse;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides asynchronous access to cloudstack via their REST API.
* <p/>
*
* @see AsyncJobClient
* @see <a href="http://download.cloud.com/releases/2.2.0/api/TOC_User.html" />
* @author Adrian Cole
*/
@RequestFilters(QuerySigner.class)
@QueryParams(keys = "response", values = "json")
public interface HypervisorAsyncClient {
/**
* @see HypervisorClient#listHypervisors
*/
@GET
@QueryParams(keys = "command", values = "listHypervisors")
@ResponseParser(ParseNamesFromHttpResponse.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<String>> listHypervisors();
/**
* @see HypervisorClient#listHypervisorsInZone
*/
@GET
@QueryParams(keys = "command", values = "listHypervisors")
@ResponseParser(ParseNamesFromHttpResponse.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<String>> listHypervisorsInZone(@QueryParam("zoneid") long zoneId);
}

View File

@ -0,0 +1,53 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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 java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
/**
* Provides synchronous access to CloudStack Operating System features.
* <p/>
*
* @see GuestOSAsyncClient
* @see <a href="http://download.cloud.com/releases/2.2.0/api/TOC_User.html" />
* @author Adrian Cole
*/
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface HypervisorClient {
/**
* Lists all supported hypervisors for this cloud.
*
* @return hypervisors, or empty set, if no hypervisors are found
*/
Set<String> listHypervisors();
/**
* Lists all supported hypervisors for this zone.
*
* @param zoneId
* the zone id for listing hypervisors.
* @return hypervisors in the zone, or empty set, if no hypervisors are found
*/
Set<String> listHypervisorsInZone(long zoneId);
}

View File

@ -26,9 +26,13 @@ import javax.ws.rs.GET;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.cloudstack.binders.BindAccountSecurityGroupPairsToIndexedQueryParams;
import org.jclouds.cloudstack.binders.BindCIDRsToCommaDelimitedQueryParam;
import org.jclouds.cloudstack.domain.SecurityGroup;
import org.jclouds.cloudstack.filters.QuerySigner;
import org.jclouds.cloudstack.options.AccountInDomainOptions;
import org.jclouds.cloudstack.options.ListSecurityGroupsOptions;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
@ -37,6 +41,7 @@ import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture;
/**
@ -80,6 +85,70 @@ public interface SecurityGroupAsyncClient {
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<SecurityGroup> createSecurityGroup(@QueryParam("name") String name);
/**
* @see SecurityGroupClient#authorizeIngressPortsToCIDRs
*/
@GET
@QueryParams(keys = "command", values = "authorizeSecurityGroupIngress")
@Unwrap(depth = 2)
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Long> authorizeIngressPortsToCIDRs(@QueryParam("securitygroupid") long securityGroupId,
@QueryParam("protocol") String protocol, @QueryParam("startport") int startPort,
@QueryParam("endport") int endPort,
@BinderParam(BindCIDRsToCommaDelimitedQueryParam.class) Iterable<String> cidrList,
AccountInDomainOptions... options);
/**
* @see SecurityGroupClient#authorizeIngressPortsToSecurityGroups
*/
@GET
@QueryParams(keys = "command", values = "authorizeSecurityGroupIngress")
@Unwrap(depth = 2)
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Long> authorizeIngressPortsToSecurityGroups(
@QueryParam("securitygroupid") long securityGroupId,
@QueryParam("protocol") String protocol,
@QueryParam("startport") int startPort,
@QueryParam("endport") int endPort,
@BinderParam(BindAccountSecurityGroupPairsToIndexedQueryParams.class) Multimap<String, String> accountToGroup,
AccountInDomainOptions... options);
/**
* @see SecurityGroupClient#authorizeIngressICMPToCIDRs
*/
@GET
@QueryParams(keys = { "command", "protocol" }, values = { "authorizeSecurityGroupIngress", "ICMP" })
@Unwrap(depth = 2)
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Long> authorizeIngressICMPToCIDRs(@QueryParam("securitygroupid") long securityGroupId,
@QueryParam("icmpcode") int ICMPCode, @QueryParam("icmptype") int ICMPType,
@BinderParam(BindCIDRsToCommaDelimitedQueryParam.class) Iterable<String> cidrList,
AccountInDomainOptions... options);
/**
* @see SecurityGroupClient#authorizeIngressICMPToSecurityGroups
*/
@GET
@QueryParams(keys = { "command", "protocol" }, values = { "authorizeSecurityGroupIngress", "ICMP" })
@Unwrap(depth = 2)
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Long> authorizeIngressICMPToSecurityGroups(
@QueryParam("securitygroupid") long securityGroupId,
@QueryParam("icmpcode") int ICMPCode,
@QueryParam("icmptype") int ICMPType,
@BinderParam(BindAccountSecurityGroupPairsToIndexedQueryParams.class) Multimap<String, String> accountToGroup,
AccountInDomainOptions... options);
/**
* @see SecurityGroupClient#revokeIngressRule
*/
@GET
@QueryParams(keys = "command", values = "revokeSecurityGroupIngress")
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
@Unwrap(depth = 2)
@Consumes(MediaType.APPLICATION_JSON)
ListenableFuture<Long> revokeIngressRule(@QueryParam("id") long id, AccountInDomainOptions... options);
/**
* @see SecurityGroupClient#deleteSecurityGroup
*/

View File

@ -23,9 +23,12 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.cloudstack.domain.SecurityGroup;
import org.jclouds.cloudstack.options.AccountInDomainOptions;
import org.jclouds.cloudstack.options.ListSecurityGroupsOptions;
import org.jclouds.concurrent.Timeout;
import com.google.common.collect.Multimap;
/**
* Provides synchronous access to CloudStack security group features.
* <p/>
@ -45,6 +48,82 @@ public interface SecurityGroupClient {
*/
Set<SecurityGroup> listSecurityGroups(ListSecurityGroupsOptions... options);
/**
* Authorizes a particular TCP or UDP ingress rule for this security group
*
* @param securityGroupId
* The ID of the security group
* @param protocol
* tcp or udp
* @param startPort
* start port for this ingress rule
* @param endPort
* end port for this ingress rule
* @param cidrList
* the cidr list associated
* @return response relating to the creation of this ingress rule
*/
long authorizeIngressPortsToCIDRs(long securityGroupId, String protocol, int startPort, int endPort,
Iterable<String> cidrList, AccountInDomainOptions... options);
/**
* Authorizes a particular TCP or UDP ingress rule for this security group
*
* @param securityGroupId
* The ID of the security group
* @param protocol
* tcp or udp
* @param startPort
* start port for this ingress rule
* @param endPort
* end port for this ingress rule
* @param accountToGroup
* mapping of account names to security groups you wish to authorize
* @return response relating to the creation of this ingress rule
*/
long authorizeIngressPortsToSecurityGroups(long securityGroupId, String protocol, int startPort,
int endPort, Multimap<String, String> accountToGroup, AccountInDomainOptions... options);
/**
* Authorizes a particular ICMP ingress rule for this security group
*
* @param securityGroupId
* The ID of the security group
* @param ICMPCode
* type of the icmp message being sent
* @param ICMPType
* error code for this icmp message
* @param cidrList
* the cidr list associated
* @return response relating to the creation of this ingress rule
*/
long authorizeIngressICMPToCIDRs(long securityGroupId, int ICMPCode, int ICMPType,
Iterable<String> cidrList, AccountInDomainOptions... options);
/**
* Authorizes a particular ICMP ingress rule for this security group
*
* @param securityGroupId
* The ID of the security group
* @param ICMPCode
* type of the icmp message being sent
* @param ICMPType
* error code for this icmp message
* @param accountToGroup
* mapping of account names to security groups you wish to authorize
* @return response relating to the creation of this ingress rule
*/
long authorizeIngressICMPToSecurityGroups(long securityGroupId, int ICMPCode, int ICMPType,
Multimap<String, String> accountToGroup, AccountInDomainOptions... options);
/**
* Deletes a particular ingress rule from this security group
*
* @param id The ID of the ingress rule
* @param options scope of the rule.
*/
long revokeIngressRule(long id, AccountInDomainOptions... options);;
/**
* get a specific security group by id
*

View File

@ -78,6 +78,6 @@ public interface TemplateAsyncClient {
@Unwrap(depth = 3, edgeCollection = Set.class)
@Consumes(MediaType.APPLICATION_JSON)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Template> getTemplate(@QueryParam("id") long id);
ListenableFuture<Template> getTemplateInZone(@QueryParam("zoneid") long zoneId, @QueryParam("id") long id);
}

View File

@ -57,9 +57,11 @@ public interface TemplateClient {
/**
* get a specific template by id
*
* @param zoneId
* zone template is defined in
* @param id
* template to get
* @return template or null if not found
*/
Template getTemplate(long id);
Template getTemplateInZone(long zoneId, long id);
}

View File

@ -21,6 +21,10 @@ package org.jclouds.cloudstack.filters;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Comparator;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -43,12 +47,10 @@ import org.jclouds.rest.RequestSigner;
import org.jclouds.util.Strings2;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.ImmutableMultimap.Builder;
/**
*
@ -118,14 +120,15 @@ public class QuerySigner implements HttpRequestFilter, RequestSigner {
@VisibleForTesting
public String createStringToSign(HttpRequest request, Multimap<String, String> decodedParams) {
utils.logRequest(signatureLog, request, ">>");
Builder<String, String> builder = ImmutableMultimap.<String, String> builder();
for (String key : ImmutableSortedSet.copyOf(decodedParams.keySet()))
builder.put(key.toLowerCase(), Iterables.getOnlyElement(decodedParams.get(key)).toLowerCase());
ImmutableSortedSet.Builder<String> builder = ImmutableSortedSet.<String> naturalOrder();
for (Entry<String, String> entry : decodedParams.entries())
builder.add(entry.getKey().toLowerCase() + "=" + Strings2.urlEncode(entry.getValue().toLowerCase()));
String stringToSign = ModifyRequest.makeQueryLine(builder.build(), null);
String stringToSign = Joiner.on('&').join(builder.build());
if (signatureWire.enabled())
signatureWire.output(stringToSign);
return stringToSign;
}

View File

@ -0,0 +1,53 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.inject.Singleton;
import org.jclouds.http.HttpResponse;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
/**
*
* @author Adrian Cole
*/
@Singleton
public class ParseIdToNameEntryFromHttpResponse implements Function<HttpResponse, Map.Entry<Long, String>> {
private final ParseIdToNameFromHttpResponse parser;
@Inject
public ParseIdToNameEntryFromHttpResponse(ParseIdToNameFromHttpResponse parser) {
this.parser = checkNotNull(parser, "parser");
}
public Map.Entry<Long, String> apply(HttpResponse response) {
checkNotNull(response, "response");
Map<Long, String> toParse = parser.apply(response);
checkNotNull(toParse, "parsed result from %s", response);
return Iterables.getFirst(toParse.entrySet(), null);
}
}

View File

@ -0,0 +1,93 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Set;
import javax.inject.Singleton;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.inject.Inject;
/**
*
* @author Adrian Cole
*/
@Singleton
public class ParseIdToNameFromHttpResponse implements Function<HttpResponse, Map<Long, String>> {
private final UnwrapOnlyNestedJsonValue<Set<IdName>> parser;
private static class IdName {
private long id;
private String name;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IdName other = (IdName) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
@Inject
public ParseIdToNameFromHttpResponse(UnwrapOnlyNestedJsonValue<Set<IdName>> parser) {
this.parser = checkNotNull(parser, "parser");
}
public Map<Long, String> apply(HttpResponse response) {
checkNotNull(response, "response");
Set<IdName> toParse = parser.apply(response);
checkNotNull(toParse, "parsed result from %s", response);
Builder<Long, String> builder = ImmutableMap.<Long, String> builder();
for (IdName entry : toParse)
builder.put(entry.id, entry.name);
return builder.build();
}
}

View File

@ -0,0 +1,88 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import javax.inject.Singleton;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.inject.Inject;
/**
*
* @author Adrian Cole
*/
@Singleton
public class ParseNamesFromHttpResponse implements Function<HttpResponse, Set<String>> {
private final UnwrapOnlyNestedJsonValue<Set<Name>> parser;
private static class Name {
private String name;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Name other = (Name) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
@Inject
public ParseNamesFromHttpResponse(UnwrapOnlyNestedJsonValue<Set<Name>> parser) {
this.parser = checkNotNull(parser, "parser");
}
public Set<String> apply(HttpResponse response) {
checkNotNull(response, "response");
Set<Name> toParse = parser.apply(response);
checkNotNull(toParse, "parsed result from %s", response);
Builder<String> builder = ImmutableSet.<String> builder();
for (Name entry : toParse)
builder.add(entry.name);
return builder.build();
}
}

View File

@ -0,0 +1,76 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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 org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.collect.ImmutableSet;
/**
* Options for services that apply to accounts in domains
*
* @see <a href="http://download.cloud.com/releases/2.2.0/api/TOC_User.html" />
* @author Adrian Cole
*/
public class AccountInDomainOptions extends BaseHttpRequestOptions {
public static final AccountInDomainOptions NONE = new AccountInDomainOptions();
/**
*
* @param account
* an optional account for the resource
* @param domain
* domain id
*/
public AccountInDomainOptions accountInDomain(String account, long domain) {
this.queryParameters.replaceValues("account", ImmutableSet.of(account));
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domain + ""));
return this;
}
/**
* @param domainId
* The domain for the resource
*/
public AccountInDomainOptions domainId(long domainId) {
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domainId + ""));
return this;
}
public static class Builder {
/**
* @see AccountInDomainOptions#accountInDomain
*/
public static AccountInDomainOptions accountInDomain(String account, long domain) {
AccountInDomainOptions options = new AccountInDomainOptions();
return options.accountInDomain(account, domain);
}
/**
* @see AccountInDomainOptions#domainId
*/
public static AccountInDomainOptions domainId(long domainId) {
AccountInDomainOptions options = new AccountInDomainOptions();
return options.domainId(domainId);
}
}
}

View File

@ -19,8 +19,6 @@
package org.jclouds.cloudstack.options;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.collect.ImmutableSet;
/**
@ -29,23 +27,10 @@ import com.google.common.collect.ImmutableSet;
* @see <a href="http://download.cloud.com/releases/2.2.0/api/user/associateIpAddress.html" />
* @author Adrian Cole
*/
public class AssociateIPAddressOptions extends BaseHttpRequestOptions {
public class AssociateIPAddressOptions extends AccountInDomainOptions {
public static final AssociateIPAddressOptions NONE = new AssociateIPAddressOptions();
/**
*
* @param account
* an optional account for the ip address
* @param domain
* domain id
*/
public AssociateIPAddressOptions accountInDomain(String account, long domain) {
this.queryParameters.replaceValues("account", ImmutableSet.of(account));
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domain + ""));
return this;
}
/**
* @param networkId
* The network this ip address should be associated to.
@ -57,6 +42,15 @@ public class AssociateIPAddressOptions extends BaseHttpRequestOptions {
}
public static class Builder {
/**
* @see AssociateIPAddressOptions#networkId
*/
public static AssociateIPAddressOptions networkId(long networkId) {
AssociateIPAddressOptions options = new AssociateIPAddressOptions();
return options.networkId(networkId);
}
/**
* @see AssociateIPAddressOptions#accountInDomain
*/
@ -66,11 +60,27 @@ public class AssociateIPAddressOptions extends BaseHttpRequestOptions {
}
/**
* @see AssociateIPAddressOptions#networkId
* @see AssociateIPAddressOptions#domainId
*/
public static AssociateIPAddressOptions networkId(long networkId) {
public static AssociateIPAddressOptions domainId(long domainId) {
AssociateIPAddressOptions options = new AssociateIPAddressOptions();
return options.networkId(networkId);
return options.domainId(domainId);
}
}
/**
* {@inheritDoc}
*/
@Override
public AssociateIPAddressOptions accountInDomain(String account, long domain) {
return AssociateIPAddressOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public AssociateIPAddressOptions domainId(long domainId) {
return AssociateIPAddressOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -23,7 +23,6 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.encryption.internal.Base64;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet;
@ -34,23 +33,10 @@ import com.google.common.collect.ImmutableSet;
* @see <a href="http://download.cloud.com/releases/2.2.0/api/user/deployVirtualMachine.html" />
* @author Adrian Cole
*/
public class DeployVirtualMachineOptions extends BaseHttpRequestOptions {
public class DeployVirtualMachineOptions extends AccountInDomainOptions {
public static final DeployVirtualMachineOptions NONE = new DeployVirtualMachineOptions();
/**
*
* @param account
* an optional account for the virtual machine
* @param domain
* domain id
*/
public DeployVirtualMachineOptions accountInDomain(String account, long domain) {
this.queryParameters.replaceValues("account", ImmutableSet.of(account));
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domain + ""));
return this;
}
/**
* the ID of the disk offering for the virtual machine. If the template is of ISO format, the
* diskOfferingId is for the root disk volume. Otherwise this parameter is used to dinidcate the
@ -176,13 +162,6 @@ public class DeployVirtualMachineOptions extends BaseHttpRequestOptions {
}
public static class Builder {
/**
* @see DeployVirtualMachineOptions#accountInDomain
*/
public static DeployVirtualMachineOptions accountInDomain(String account, long domain) {
DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
return options.accountInDomain(account, domain);
}
/**
* @see DeployVirtualMachineOptions#diskOfferingId
@ -279,5 +258,37 @@ public class DeployVirtualMachineOptions extends BaseHttpRequestOptions {
DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
return options.userData(unencodedData);
}
/**
* @see DeployVirtualMachineOptions#accountInDomain
*/
public static DeployVirtualMachineOptions accountInDomain(String account, long domain) {
DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
return options.accountInDomain(account, domain);
}
/**
* @see DeployVirtualMachineOptions#domainId
*/
public static DeployVirtualMachineOptions domainId(long domainId) {
DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
return options.domainId(domainId);
}
}
/**
* {@inheritDoc}
*/
@Override
public DeployVirtualMachineOptions accountInDomain(String account, long domain) {
return DeployVirtualMachineOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public DeployVirtualMachineOptions domainId(long domainId) {
return DeployVirtualMachineOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -25,7 +25,6 @@ import java.util.Date;
import org.jclouds.date.DateService;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.collect.ImmutableSet;
@ -35,40 +34,18 @@ import com.google.common.collect.ImmutableSet;
* @see <a href="http://download.cloud.com/releases/2.2.0/api/user/listAsyncJobs.html" />
* @author Adrian Cole
*/
public class ListAsyncJobsOptions extends BaseHttpRequestOptions {
public class ListAsyncJobsOptions extends AccountInDomainOptions {
private final static DateService dateService = new SimpleDateFormatDateService();
public static final ListAsyncJobsOptions NONE = new ListAsyncJobsOptions();
/**
*
* @param account
* an optional account for the virtual machine
* @param domain
* domain id
*/
public ListAsyncJobsOptions accountInDomain(String account, long domain) {
this.queryParameters.replaceValues("account", ImmutableSet.of(account + ""));
return domainId(domain);
}
/**
* @param domainId
* the ID of the domain associated with the asyncJob
*/
public ListAsyncJobsOptions domainId(long domainId) {
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domainId + ""));
return this;
}
/**
* @param startDate
* the start date of the async job
*/
public ListAsyncJobsOptions startDate(Date startDate) {
this.queryParameters.replaceValues("startdate",
ImmutableSet.of(dateService.iso8601SecondsDateFormat(checkNotNull(startDate, "startDate"))));
this.queryParameters.replaceValues("startdate", ImmutableSet.of(dateService
.iso8601SecondsDateFormat(checkNotNull(startDate, "startDate"))));
return this;
}
@ -99,4 +76,20 @@ public class ListAsyncJobsOptions extends BaseHttpRequestOptions {
}
}
/**
* {@inheritDoc}
*/
@Override
public ListAsyncJobsOptions accountInDomain(String account, long domain) {
return ListAsyncJobsOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public ListAsyncJobsOptions domainId(long domainId) {
return ListAsyncJobsOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -19,8 +19,6 @@
package org.jclouds.cloudstack.options;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.collect.ImmutableSet;
/**
@ -29,7 +27,7 @@ import com.google.common.collect.ImmutableSet;
* @see <a href="http://download.cloud.com/releases/2.2.0/api/user/listIpForwardingRules.html" />
* @author Adrian Cole
*/
public class ListIPForwardingRulesOptions extends BaseHttpRequestOptions {
public class ListIPForwardingRulesOptions extends AccountInDomainOptions {
public static final ListIPForwardingRulesOptions NONE = new ListIPForwardingRulesOptions();
@ -42,31 +40,6 @@ public class ListIPForwardingRulesOptions extends BaseHttpRequestOptions {
return this;
}
/**
* @param domainId
* Lists all rules for this id. If used with the account parameter, returns all rules
* for an account in the specified domain ID.
*/
public ListIPForwardingRulesOptions domainId(long domainId) {
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domainId + ""));
return this;
}
/**
* @param account
* the account associated with the ip forwarding rule. Must be used with the domainId
* parameter.
*
* @param domain
* domain id
*/
public ListIPForwardingRulesOptions accountInDomain(String account, long domain) {
this.queryParameters.replaceValues("account", ImmutableSet.of(account));
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domain + ""));
return this;
}
/**
* @param IPAddressId
* list the rule belonging to this public ip address
@ -129,4 +102,20 @@ public class ListIPForwardingRulesOptions extends BaseHttpRequestOptions {
return options.virtualMachineId(virtualMachineId);
}
}
/**
* {@inheritDoc}
*/
@Override
public ListIPForwardingRulesOptions accountInDomain(String account, long domain) {
return ListIPForwardingRulesOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public ListIPForwardingRulesOptions domainId(long domainId) {
return ListIPForwardingRulesOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -19,8 +19,6 @@
package org.jclouds.cloudstack.options;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.collect.ImmutableSet;
/**
@ -29,7 +27,7 @@ import com.google.common.collect.ImmutableSet;
* @see <a href="http://download.cloud.com/releases/2.2.0/api/user/listLoadBalancerRules.html" />
* @author Adrian Cole
*/
public class ListLoadBalancerRulesOptions extends BaseHttpRequestOptions {
public class ListLoadBalancerRulesOptions extends AccountInDomainOptions {
public static final ListLoadBalancerRulesOptions NONE = new ListLoadBalancerRulesOptions();
@ -42,31 +40,6 @@ public class ListLoadBalancerRulesOptions extends BaseHttpRequestOptions {
return this;
}
/**
* @param domainId
* Lists all rules for this id. If used with the account parameter, returns all rules
* for an account in the specified domain ID.
*/
public ListLoadBalancerRulesOptions domainId(long domainId) {
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domainId + ""));
return this;
}
/**
* @param account
* the account associated with the load balancing rule. Must be used with the domainId
* parameter.
*
* @param domain
* domain id
*/
public ListLoadBalancerRulesOptions accountInDomain(String account, long domain) {
this.queryParameters.replaceValues("account", ImmutableSet.of(account));
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domain + ""));
return this;
}
/**
* @param name
* the name of the load balancer rule
@ -145,4 +118,20 @@ public class ListLoadBalancerRulesOptions extends BaseHttpRequestOptions {
return options.virtualMachineId(virtualMachineId);
}
}
/**
* {@inheritDoc}
*/
@Override
public ListLoadBalancerRulesOptions accountInDomain(String account, long domain) {
return ListLoadBalancerRulesOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public ListLoadBalancerRulesOptions domainId(long domainId) {
return ListLoadBalancerRulesOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -19,8 +19,6 @@
package org.jclouds.cloudstack.options;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.collect.ImmutableSet;
/**
@ -29,35 +27,10 @@ import com.google.common.collect.ImmutableSet;
* @see <a href="http://download.cloud.com/releases/2.2.0/api/user/listIpForwardingRules.html" />
* @author Adrian Cole
*/
public class ListPortForwardingRulesOptions extends BaseHttpRequestOptions {
public class ListPortForwardingRulesOptions extends AccountInDomainOptions {
public static final ListPortForwardingRulesOptions NONE = new ListPortForwardingRulesOptions();
/**
* @param domainId
* Lists all rules for this id. If used with the account parameter, returns all rules
* for an account in the specified domain ID.
*/
public ListPortForwardingRulesOptions domainId(long domainId) {
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domainId + ""));
return this;
}
/**
* @param account
* the account associated with the port forwarding rule. Must be used with the domainId
* parameter.
*
* @param domain
* domain id
*/
public ListPortForwardingRulesOptions accountInDomain(String account, long domain) {
this.queryParameters.replaceValues("account", ImmutableSet.of(account));
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domain + ""));
return this;
}
/**
* @param IPAddressId
* list the rule belonging to this public ip address
@ -94,4 +67,20 @@ public class ListPortForwardingRulesOptions extends BaseHttpRequestOptions {
}
}
/**
* {@inheritDoc}
*/
@Override
public ListPortForwardingRulesOptions accountInDomain(String account, long domain) {
return ListPortForwardingRulesOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public ListPortForwardingRulesOptions domainId(long domainId) {
return ListPortForwardingRulesOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -19,8 +19,6 @@
package org.jclouds.cloudstack.options;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.collect.ImmutableSet;
/**
@ -29,7 +27,7 @@ import com.google.common.collect.ImmutableSet;
* @see <a href="http://download.cloud.com/releases/2.2.0/api/user/listIPAddresses.html" />
* @author Adrian Cole
*/
public class ListPublicIPAddressesOptions extends BaseHttpRequestOptions {
public class ListPublicIPAddressesOptions extends AccountInDomainOptions {
public static final ListPublicIPAddressesOptions NONE = new ListPublicIPAddressesOptions();
@ -42,29 +40,6 @@ public class ListPublicIPAddressesOptions extends BaseHttpRequestOptions {
return this;
}
/**
* @param domainId
* lists all public IP addresses by domain ID. If used with the account parameter,
* lists all public IP addresses by account for specified domain.
*/
public ListPublicIPAddressesOptions domainId(long domainId) {
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domainId + ""));
return this;
}
/**
*
* @param account
* account id
* @param domain
* domain id
*/
public ListPublicIPAddressesOptions accountInDomain(String account, long domain) {
this.queryParameters.replaceValues("account", ImmutableSet.of(account));
return domainId(domain);
}
/**
* @param allocatedOnly
* limits search results to allocated public IP addresses
@ -197,4 +172,20 @@ public class ListPublicIPAddressesOptions extends BaseHttpRequestOptions {
return options.usesVirtualNetwork(usesVirtualNetwork);
}
}
/**
* {@inheritDoc}
*/
@Override
public ListPublicIPAddressesOptions accountInDomain(String account, long domain) {
return ListPublicIPAddressesOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public ListPublicIPAddressesOptions domainId(long domainId) {
return ListPublicIPAddressesOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -19,8 +19,6 @@
package org.jclouds.cloudstack.options;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.collect.ImmutableSet;
/**
@ -29,7 +27,7 @@ import com.google.common.collect.ImmutableSet;
* @see <a href="http://download.cloud.com/releases/2.2.0/api/user/listSecurityGroups.html" />
* @author Adrian Cole
*/
public class ListSecurityGroupsOptions extends BaseHttpRequestOptions {
public class ListSecurityGroupsOptions extends AssociateIPAddressOptions {
public static final ListSecurityGroupsOptions NONE = new ListSecurityGroupsOptions();
@ -42,25 +40,6 @@ public class ListSecurityGroupsOptions extends BaseHttpRequestOptions {
return this;
}
/**
* @param domainId
* the ID of the domain associated with the security group
*/
public ListSecurityGroupsOptions domainId(long domainId) {
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domainId + ""));
return this;
}
/**
* @param account
* the security group account
*/
public ListSecurityGroupsOptions account(String account) {
this.queryParameters.replaceValues("account", ImmutableSet.of(account));
return this;
}
/**
* @param securityGroupName
* lists security groups by name
@ -83,14 +62,6 @@ public class ListSecurityGroupsOptions extends BaseHttpRequestOptions {
public static class Builder {
/**
* @see ListSecurityGroupsOptions#account
*/
public static ListSecurityGroupsOptions account(String account) {
ListSecurityGroupsOptions options = new ListSecurityGroupsOptions();
return options.account(account);
}
/**
* @see ListSecurityGroupsOptions#named
*/
@ -99,14 +70,6 @@ public class ListSecurityGroupsOptions extends BaseHttpRequestOptions {
return options.named(securityGroupName);
}
/**
* @see ListSecurityGroupsOptions#domainId
*/
public static ListSecurityGroupsOptions domainId(long id) {
ListSecurityGroupsOptions options = new ListSecurityGroupsOptions();
return options.domainId(id);
}
/**
* @see ListSecurityGroupsOptions#id
*/
@ -122,5 +85,37 @@ public class ListSecurityGroupsOptions extends BaseHttpRequestOptions {
ListSecurityGroupsOptions options = new ListSecurityGroupsOptions();
return options.virtualMachineId(virtualMachineId);
}
/**
* @see DeployVirtualMachineOptions#accountInDomain
*/
public static ListSecurityGroupsOptions accountInDomain(String account, long domain) {
ListSecurityGroupsOptions options = new ListSecurityGroupsOptions();
return options.accountInDomain(account, domain);
}
/**
* @see DeployVirtualMachineOptions#domainId
*/
public static ListSecurityGroupsOptions domainId(long domainId) {
ListSecurityGroupsOptions options = new ListSecurityGroupsOptions();
return options.domainId(domainId);
}
}
/**
* {@inheritDoc}
*/
@Override
public ListSecurityGroupsOptions accountInDomain(String account, long domain) {
return ListSecurityGroupsOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public ListSecurityGroupsOptions domainId(long domainId) {
return ListSecurityGroupsOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -20,7 +20,6 @@
package org.jclouds.cloudstack.options;
import org.jclouds.cloudstack.domain.TemplateFilter;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.collect.ImmutableSet;
@ -30,7 +29,7 @@ import com.google.common.collect.ImmutableSet;
* @see <a href="http://download.cloud.com/releases/2.2.0/api/user/listTemplates.html" />
* @author Adrian Cole
*/
public class ListTemplatesOptions extends BaseHttpRequestOptions {
public class ListTemplatesOptions extends AccountInDomainOptions {
public ListTemplatesOptions() {
filter(TemplateFilter.EXECUTABLE);
}
@ -55,18 +54,6 @@ public class ListTemplatesOptions extends BaseHttpRequestOptions {
return this;
}
/**
*
* @param account
* account id
* @param domain
* domain id
*/
public ListTemplatesOptions accountInDomain(String account, long domain) {
this.queryParameters.replaceValues("account", ImmutableSet.of(account + ""));
return domainId(domain);
}
/**
* @param name
* the template name
@ -76,17 +63,6 @@ public class ListTemplatesOptions extends BaseHttpRequestOptions {
return this;
}
/**
* @param domainId
* list all templates in specified domain. If used with the account parameter, lists
* all templates for an account in the specified domain.
*/
public ListTemplatesOptions domainId(long domainId) {
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domainId + ""));
return this;
}
/**
* @param zoneId
* list templates by zoneId.
@ -165,4 +141,19 @@ public class ListTemplatesOptions extends BaseHttpRequestOptions {
}
}
/**
* {@inheritDoc}
*/
@Override
public ListTemplatesOptions accountInDomain(String account, long domain) {
return ListTemplatesOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public ListTemplatesOptions domainId(long domainId) {
return ListTemplatesOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -19,8 +19,6 @@
package org.jclouds.cloudstack.options;
import org.jclouds.http.options.BaseHttpRequestOptions;
import com.google.common.collect.ImmutableSet;
/**
@ -29,7 +27,7 @@ import com.google.common.collect.ImmutableSet;
* @see <a href="http://download.cloud.com/releases/2.2.0/api/user/listVirtualMachines.html" />
* @author Adrian Cole
*/
public class ListVirtualMachinesOptions extends BaseHttpRequestOptions {
public class ListVirtualMachinesOptions extends AccountInDomainOptions {
public static final ListVirtualMachinesOptions NONE = new ListVirtualMachinesOptions();
@ -60,28 +58,6 @@ public class ListVirtualMachinesOptions extends BaseHttpRequestOptions {
return this;
}
/**
* @param domainId
* the ID of the domain associated with the virtual machine
*/
public ListVirtualMachinesOptions domainId(long domainId) {
this.queryParameters.replaceValues("domainid", ImmutableSet.of(domainId + ""));
return this;
}
/**
*
* @param account
* account id
* @param domain
* domain id
*/
public ListVirtualMachinesOptions accountInDomain(String account, long domain) {
this.queryParameters.replaceValues("account", ImmutableSet.of(account));
return domainId(domain);
}
/**
* @param groupId
* list virtual machines by groupId.
@ -232,4 +208,20 @@ public class ListVirtualMachinesOptions extends BaseHttpRequestOptions {
return options.usesVirtualNetwork(usesVirtualNetwork);
}
}
/**
* {@inheritDoc}
*/
@Override
public ListVirtualMachinesOptions accountInDomain(String account, long domain) {
return ListVirtualMachinesOptions.class.cast(super.accountInDomain(account, domain));
}
/**
* {@inheritDoc}
*/
@Override
public ListVirtualMachinesOptions domainId(long domainId) {
return ListVirtualMachinesOptions.class.cast(super.domainId(domainId));
}
}

View File

@ -0,0 +1,99 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.domain.Template;
import org.jclouds.cloudstack.domain.Zone;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
/**
* Templates can be present in a zone, and available, but not valid for launch as their hypervisor
* isn't installed.
*
* @author Adrian Cole
*/
@Singleton
public class CorrectHypervisorForZone implements Function<Long, Predicate<Template>> {
private final Supplier<Map<Long, Set<String>>> hypervisorsSupplier;
@Inject
public CorrectHypervisorForZone(CloudStackClient client) {
this(Suppliers.ofInstance(new CloudStackClientToZoneToHypervisors().apply(checkNotNull(client, "client"))));
}
public CorrectHypervisorForZone(Supplier<Map<Long, Set<String>>> hypervisorsSupplier) {
this.hypervisorsSupplier = checkNotNull(hypervisorsSupplier, "hypervisorsSupplier");
}
private static class CloudStackClientToZoneToHypervisors implements
Function<CloudStackClient, Map<Long, Set<String>>> {
@Override
public Map<Long, Set<String>> apply(CloudStackClient client) {
checkNotNull(client, "client");
Builder<Long, Set<String>> builder = ImmutableMap.<Long, Set<String>> builder();
for (Zone zone : client.getZoneClient().listZones()) {
builder.put(zone.getId(), client.getHypervisorClient().listHypervisorsInZone(zone.getId()));
}
return builder.build();
}
}
@Override
public Predicate<Template> apply(final Long zoneId) {
final Set<String> acceptableHypervisorsInZone;
try {
acceptableHypervisorsInZone = this.hypervisorsSupplier.get().get(zoneId);
} catch (NullPointerException e) {
throw new IllegalArgumentException("unknown zone: " + zoneId);
}
if (acceptableHypervisorsInZone.size() == 0)
return Predicates.alwaysFalse();
return new Predicate<Template>() {
@Override
public boolean apply(Template input) {
return Predicates.in(acceptableHypervisorsInZone).apply(input.getHypervisor());
}
@Override
public String toString() {
return "hypervisorsInZone(" + zoneId + ", " + acceptableHypervisorsInZone + ")";
}
};
}
}

View File

@ -0,0 +1,94 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.domain.OSType;
import org.jclouds.cloudstack.domain.Template;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Maps;
/**
*
*
* @author Adrian Cole
*/
@Singleton
public class OSCategoryIn implements Function<Set<String>, Predicate<Template>> {
private final Supplier<Map<Long, String>> categoriesSupplier;
private final Supplier<Set<OSType>> osTypesSupplier;
@Inject
public OSCategoryIn(CloudStackClient client) {
this(Suppliers.ofInstance(checkNotNull(client, "client").getGuestOSClient().listOSCategories()), Suppliers.ofInstance(client
.getGuestOSClient().listOSTypes()));
}
public OSCategoryIn(Supplier<Map<Long, String>> categoriesSupplier, Supplier<Set<OSType>> osTypesSupplier) {
this.categoriesSupplier = checkNotNull(categoriesSupplier, "categoriesSupplier");
this.osTypesSupplier = checkNotNull(osTypesSupplier, "osTypesSupplier");
}
@Override
public Predicate<Template> apply(final Set<String> acceptableCategories) {
final Map<Long, String> categories = categoriesSupplier.get();
final Set<Long> acceptableOSTypeIds = Maps.filterValues(
Maps.transformValues(Maps.uniqueIndex(osTypesSupplier.get(), new Function<OSType, Long>() {
@Override
public Long apply(OSType input) {
return input.getId();
}
}), new Function<OSType, String>() {
@Override
public String apply(OSType input) {
return categories.get(input.getOSCategoryId());
}
}), Predicates.in(acceptableCategories)).keySet();
return new Predicate<Template>() {
@Override
public boolean apply(Template input) {
return Predicates.in(acceptableOSTypeIds).apply(input.getOSTypeId());
}
@Override
public String toString() {
return "OSCategoryIn(" + acceptableCategories + ")";
}
};
}
}

View File

@ -0,0 +1,70 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.predicates;
import javax.inject.Singleton;
import org.jclouds.cloudstack.domain.Template;
import com.google.common.base.Predicate;
/**
*
*
* @author Adrian Cole
*/
@Singleton
public class TemplatePredicates {
public static Predicate<Template> isReady() {
return Ready.INSTANCE;
}
public enum Ready implements Predicate<Template> {
INSTANCE;
@Override
public boolean apply(Template arg0) {
return arg0.isReady();
}
@Override
public String toString() {
return "isReady()";
}
}
public static enum PasswordEnabled implements Predicate<Template> {
INSTANCE;
@Override
public boolean apply(Template arg0) {
return arg0.isPasswordEnabled();
}
@Override
public String toString() {
return "isPasswordEnabled()";
}
}
public static Predicate<Template> isPasswordEnabled() {
return PasswordEnabled.INSTANCE;
}
}

View File

@ -23,7 +23,13 @@ import java.io.IOException;
import java.util.concurrent.ExecutionException;
import org.jclouds.cloudstack.features.BaseCloudStackAsyncClientTest;
import org.jclouds.cloudstack.features.FirewallClient;
import org.jclouds.cloudstack.features.GuestOSClient;
import org.jclouds.cloudstack.features.HypervisorClient;
import org.jclouds.cloudstack.features.LoadBalancerClient;
import org.jclouds.cloudstack.features.NATClient;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -51,6 +57,11 @@ public class CloudStackAsyncClientTest extends BaseCloudStackAsyncClientTest<Clo
assert syncClient.getSecurityGroupClient() != null;
assert syncClient.getAsyncJobClient() != null;
assert syncClient.getAddressClient() != null;
assert syncClient.getNATClient() != null;
assert syncClient.getFirewallClient() != null;
assert syncClient.getLoadBalancerClient() != null;
assert syncClient.getGuestOSClient() != null;
assert syncClient.getHypervisorClient() != null;
}
public void testAsync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
@ -62,6 +73,11 @@ public class CloudStackAsyncClientTest extends BaseCloudStackAsyncClientTest<Clo
assert asyncClient.getSecurityGroupClient() != null;
assert asyncClient.getAsyncJobClient() != null;
assert asyncClient.getAddressClient() != null;
assert asyncClient.getNATClient() != null;
assert asyncClient.getFirewallClient() != null;
assert asyncClient.getLoadBalancerClient() != null;
assert asyncClient.getGuestOSClient() != null;
assert asyncClient.getHypervisorClient() != null;
}
@Override

View File

@ -30,6 +30,8 @@ import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.PublicIPAddress;
import org.jclouds.cloudstack.options.ListPublicIPAddressesOptions;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
@ -41,9 +43,18 @@ import com.google.common.collect.Iterables;
*/
@Test(groups = "live", sequential = true, testName = "PublicIPAddressClientLiveTest")
public class AddressClientLiveTest extends BaseCloudStackClientLiveTest {
private boolean networksEnabled;
@BeforeGroups(groups = "live")
void networksEnabled() {
networksEnabled = client.getNetworkClient().listNetworks().size() > 0;
}
private PublicIPAddress ip = null;
public void testAssociateDisassociatePublicIPAddress() throws Exception {
if (!networksEnabled)
return;
AsyncCreateResponse job = client.getAddressClient().associateIPAddress(
Iterables.get(client.getNetworkClient().listNetworks(), 0).getZoneId());
checkState(jobComplete.apply(job.getJobId()), "job %d failed to complete", job.getJobId());
@ -60,6 +71,8 @@ public class AddressClientLiveTest extends BaseCloudStackClientLiveTest {
}
public void testListPublicIPAddresss() throws Exception {
if (!networksEnabled)
return;
Set<PublicIPAddress> response = client.getAddressClient().listPublicIPAddresses();
assert null != response;
assertTrue(response.size() >= 0);

View File

@ -125,7 +125,7 @@ public class BaseCloudStackClientLiveTest {
sshFactory = injector.getInstance(SshClient.Factory.class);
socketTester = new RetryablePredicate<IPSocket>(new InetSocketAddressConnect(), 180, 1, 1, TimeUnit.SECONDS);
injector.injectMembers(socketTester);
jobComplete = new RetryablePredicate<Long>(new JobComplete(client), 600, 5, 5, TimeUnit.SECONDS);
jobComplete = new RetryablePredicate<Long>(new JobComplete(client), 1200, 1, 5, TimeUnit.SECONDS);
injector.injectMembers(jobComplete);
virtualMachineRunning = new RetryablePredicate<VirtualMachine>(new VirtualMachineRunning(client), 600, 5, 5,
TimeUnit.SECONDS);

View File

@ -0,0 +1,64 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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 java.io.IOException;
import java.lang.reflect.Method;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code ConfigurationAsyncClient}
*
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "ConfigurationAsyncClientTest")
public class ConfigurationAsyncClientTest extends BaseCloudStackAsyncClientTest<ConfigurationAsyncClient> {
public void testListCapabilities() throws SecurityException, NoSuchMethodException, IOException {
Method method = ConfigurationAsyncClient.class.getMethod("listCapabilities");
HttpRequest httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listCapabilities HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyNestedJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(httpRequest);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<ConfigurationAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<ConfigurationAsyncClient>>() {
};
}
}

View File

@ -0,0 +1,39 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.Capabilities;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code ConfigurationClientLiveTest}
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true, testName = "ConfigurationClientLiveTest")
public class ConfigurationClientLiveTest extends BaseCloudStackClientLiveTest {
public void testListCapabilities() throws Exception {
Capabilities response = client.getConfigurationClient().listCapabilities();
assert null != response;
assert null != response.getCloudStackVersion();
}
}

View File

@ -23,6 +23,7 @@ import static com.google.common.collect.Iterables.find;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.NoSuchElementException;
import java.util.Set;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
@ -49,20 +50,26 @@ public class FirewallClientLiveTest extends BaseCloudStackClientLiveTest {
private VirtualMachine vm;
private PortForwardingRule rule;
private Network network;
private boolean networksDisabled;
@BeforeGroups(groups = "live")
public void setupClient() {
super.setupClient();
prefix += "rule";
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.supportsPortForwarding());
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, client, jobComplete,
virtualMachineRunning);
if (vm.getPassword() != null)
password = vm.getPassword();
try {
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.supportsPortForwarding());
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, client, jobComplete,
virtualMachineRunning);
if (vm.getPassword() != null)
password = vm.getPassword();
} catch (NoSuchElementException e) {
networksDisabled = true;
}
}
public void testCreatePortForwardingRule() throws Exception {
if (networksDisabled)
return;
while (rule == null) {
ip = reuseOrAssociate.apply(network);
try {

View File

@ -22,6 +22,8 @@ package org.jclouds.cloudstack.features;
import java.io.IOException;
import java.lang.reflect.Method;
import org.jclouds.cloudstack.functions.ParseIdToNameEntryFromHttpResponse;
import org.jclouds.cloudstack.functions.ParseIdToNameFromHttpResponse;
import org.jclouds.cloudstack.options.ListOSTypesOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
@ -42,12 +44,46 @@ import com.google.inject.TypeLiteral;
@Test(groups = "unit", testName = "GuestOSAsyncClientTest")
public class GuestOSAsyncClientTest extends BaseCloudStackAsyncClientTest<GuestOSAsyncClient> {
public void testGetOSCategory() throws SecurityException, NoSuchMethodException, IOException {
Method method = GuestOSAsyncClient.class.getMethod("getOSCategory", long.class);
HttpRequest httpRequest = processor.createRequest(method, 11l);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listOsCategories&id=11 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseIdToNameEntryFromHttpResponse.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testListOSCategories() throws SecurityException, NoSuchMethodException, IOException {
Method method = GuestOSAsyncClient.class.getMethod("listOSCategories");
HttpRequest httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listOsCategories HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseIdToNameFromHttpResponse.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testGetOSType() throws SecurityException, NoSuchMethodException, IOException {
Method method = GuestOSAsyncClient.class.getMethod("getOSType", long.class);
HttpRequest httpRequest = processor.createRequest(method, 11l);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listOsTypes&id=11 HTTP/1.1");
"GET http://localhost:8080/client/api?response=json&command=listOsTypes&id=11 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -64,7 +100,7 @@ public class GuestOSAsyncClientTest extends BaseCloudStackAsyncClientTest<GuestO
HttpRequest httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listOsTypes HTTP/1.1");
"GET http://localhost:8080/client/api?response=json&command=listOsTypes HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -81,7 +117,7 @@ public class GuestOSAsyncClientTest extends BaseCloudStackAsyncClientTest<GuestO
HttpRequest httpRequest = processor.createRequest(method, ListOSTypesOptions.Builder.OSCategoryId(11));
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listOsTypes&oscategoryid=11 HTTP/1.1");
"GET http://localhost:8080/client/api?response=json&command=listOsTypes&oscategoryid=11 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);

View File

@ -23,7 +23,9 @@ import static com.google.common.collect.Iterables.getOnlyElement;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.jclouds.cloudstack.domain.OSType;
import org.jclouds.cloudstack.options.ListOSTypesOptions;
@ -43,13 +45,28 @@ public class GuestOSClientLiveTest extends BaseCloudStackClientLiveTest {
assertTrue(response.size() >= 0);
for (OSType type : response) {
OSType newDetails = getOnlyElement(client.getGuestOSClient().listOSTypes(
ListOSTypesOptions.Builder.id(type.getId())));
ListOSTypesOptions.Builder.id(type.getId())));
assertEquals(type.getId(), newDetails.getId());
checkIP(type);
checkOSType(type);
}
}
protected void checkIP(OSType type) {
public void testListOSCategories() throws Exception {
Map<Long, String> response = client.getGuestOSClient().listOSCategories();
assert null != response;
assertTrue(response.size() >= 0);
for (Entry<Long, String> category : response.entrySet()) {
checkOSCategory(category);
}
}
protected void checkOSCategory(Entry<Long, String> category) {
assertEquals(category, client.getGuestOSClient().getOSCategory(category.getKey()));
assert category.getKey() > 0 : category;
assert category.getValue() != null : category;
}
protected void checkOSType(OSType type) {
assertEquals(type.getId(), client.getGuestOSClient().getOSType(type.getId()).getId());
assert type.getId() > 0 : type;
assert type.getOSCategoryId() > 0 : type;

View File

@ -0,0 +1,81 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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 java.io.IOException;
import java.lang.reflect.Method;
import org.jclouds.cloudstack.functions.ParseNamesFromHttpResponse;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code HypervisorAsyncClient}
*
* @author Adrian Cole
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "HypervisorAsyncClientTest")
public class HypervisorAsyncClientTest extends BaseCloudStackAsyncClientTest<HypervisorAsyncClient> {
public void testListHypervisors() throws SecurityException, NoSuchMethodException, IOException {
Method method = HypervisorAsyncClient.class.getMethod("listHypervisors");
HttpRequest httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listHypervisors HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseNamesFromHttpResponse.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testListHypervisorsInZon() throws SecurityException, NoSuchMethodException, IOException {
Method method = HypervisorAsyncClient.class.getMethod("listHypervisorsInZone", long.class);
HttpRequest httpRequest = processor.createRequest(method, 11);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listHypervisors&zoneid=11 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, ParseNamesFromHttpResponse.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class);
checkFilters(httpRequest);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<HypervisorAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<HypervisorAsyncClient>>() {
};
}
}

View File

@ -0,0 +1,47 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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 static org.testng.Assert.assertTrue;
import java.util.Set;
import org.jclouds.cloudstack.domain.Zone;
import org.testng.annotations.Test;
/**
* Tests behavior of {@code HypervisorClientLiveTest}
*
* @author Adrian Cole
*/
@Test(groups = "live", sequential = true, testName = "HypervisorClientLiveTest")
public class HypervisorClientLiveTest extends BaseCloudStackClientLiveTest {
public void testListHypervisors() throws Exception {
Set<String> response = client.getHypervisorClient().listHypervisors();
assert null != response;
assertTrue(response.size() >= 0);
for (Zone zone : client.getZoneClient().listZones()) {
Set<String> zoneHype = client.getHypervisorClient().listHypervisorsInZone(zone.getId());
assert response.containsAll(zoneHype);
}
}
}

View File

@ -24,6 +24,7 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -56,6 +57,7 @@ public class LoadBalancerClientLiveTest extends BaseCloudStackClientLiveTest {
private LoadBalancerRule rule;
private RetryablePredicate<LoadBalancerRule> loadBalancerRuleActive;
private Network network;
private boolean networksDisabled;
@BeforeGroups(groups = "live")
public void setupClient() {
@ -64,14 +66,20 @@ public class LoadBalancerClientLiveTest extends BaseCloudStackClientLiveTest {
loadBalancerRuleActive = new RetryablePredicate<LoadBalancerRule>(new LoadBalancerRuleActive(client), 60, 1, 1,
TimeUnit.SECONDS);
prefix += "rule";
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.hasLoadBalancerService());
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, client, jobComplete,
virtualMachineRunning);
if (vm.getPassword() != null)
password = vm.getPassword();
try {
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.hasLoadBalancerService());
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, client, jobComplete,
virtualMachineRunning);
if (vm.getPassword() != null)
password = vm.getPassword();
} catch (NoSuchElementException e) {
networksDisabled = true;
}
}
public void testCreateLoadBalancerRule() throws Exception {
if (networksDisabled)
return;
while (rule == null) {
ip = reuseOrAssociate.apply(network);
try {
@ -94,6 +102,8 @@ public class LoadBalancerClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(dependsOnMethods = "testCreateLoadBalancerRule")
public void testAssignToLoadBalancerRule() throws Exception {
if (networksDisabled)
return;
assert jobComplete.apply(client.getLoadBalancerClient().assignVirtualMachinesToLoadBalancerRule(rule.getId(),
vm.getId()));
assertEquals(client.getLoadBalancerClient().listVirtualMachinesAssignedToLoadBalancerRule(rule.getId()).size(), 1);
@ -120,6 +130,8 @@ public class LoadBalancerClientLiveTest extends BaseCloudStackClientLiveTest {
@Test(dependsOnMethods = "testAssignToLoadBalancerRule", expectedExceptions = SshException.class)
public void testRemoveFromLoadBalancerRule() throws Exception {
if (networksDisabled)
throw new SshException();
assert jobComplete.apply(client.getLoadBalancerClient().removeVirtualMachinesFromLoadBalancerRule(rule.getId(),
vm.getId()));
assertEquals(client.getLoadBalancerClient().listVirtualMachinesAssignedToLoadBalancerRule(rule.getId()).size(), 0);

View File

@ -24,6 +24,7 @@ import static com.google.common.collect.Iterables.getOnlyElement;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.NoSuchElementException;
import java.util.Set;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
@ -52,19 +53,26 @@ public class NATClientLiveTest extends BaseCloudStackClientLiveTest {
private VirtualMachine vm;
private IPForwardingRule rule;
private Network network;
private boolean networksDisabled;
@BeforeGroups(groups = "live")
public void setupClient() {
super.setupClient();
prefix += "nat";
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.supportsStaticNAT());
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, client, jobComplete,
virtualMachineRunning);
if (vm.getPassword() != null)
password = vm.getPassword();
try {
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.supportsStaticNAT());
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, client, jobComplete,
virtualMachineRunning);
if (vm.getPassword() != null)
password = vm.getPassword();
} catch (NoSuchElementException e) {
networksDisabled = true;
}
}
public void testCreateIPForwardingRule() throws Exception {
if (networksDisabled)
return;
for (ip = reuseOrAssociate.apply(network); (!ip.isStaticNAT() || ip.getVirtualMachineId() != vm.getId()); ip = reuseOrAssociate
.apply(network)) {
// check to see if someone already grabbed this ip

View File

@ -22,7 +22,6 @@ package org.jclouds.cloudstack.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.NoSuchElementException;
import java.util.Set;
import org.jclouds.cloudstack.domain.DiskOffering;
@ -52,7 +51,7 @@ public class OfferingClientLiveTest extends BaseCloudStackClientLiveTest {
assertTrue(offeringCount >= 0);
for (DiskOffering offering : response) {
DiskOffering newDetails = Iterables.getOnlyElement(client.getOfferingClient().listDiskOfferings(
ListDiskOfferingsOptions.Builder.id(offering.getId())));
ListDiskOfferingsOptions.Builder.id(offering.getId())));
assertEquals(offering, newDetails);
assertEquals(offering, client.getOfferingClient().getDiskOffering(offering.getId()));
assert offering.getId() > 0 : offering;
@ -70,16 +69,9 @@ public class OfferingClientLiveTest extends BaseCloudStackClientLiveTest {
long offeringCount = response.size();
assertTrue(offeringCount >= 0);
for (ServiceOffering offering : response) {
try {
ServiceOffering newDetails = Iterables.getOnlyElement(client.getOfferingClient().listServiceOfferings(
ServiceOffering newDetails = Iterables.getOnlyElement(client.getOfferingClient().listServiceOfferings(
ListServiceOfferingsOptions.Builder.id(offering.getId())));
assertEquals(offering, newDetails);
assert false : "should be a bug as of 2.2.0";
} catch (NoSuchElementException e) {
}
// bug as of 2.2.0
assertEquals(client.getOfferingClient().getServiceOffering(offering.getId()), null);
assertEquals(offering, newDetails);
assert offering.getId() > 0 : offering;
assert offering.getName() != null : offering;
@ -100,7 +92,7 @@ public class OfferingClientLiveTest extends BaseCloudStackClientLiveTest {
assertTrue(offeringCount >= 0);
for (NetworkOffering offering : response) {
NetworkOffering newDetails = Iterables.getOnlyElement(client.getOfferingClient().listNetworkOfferings(
ListNetworkOfferingsOptions.Builder.id(offering.getId())));
ListNetworkOfferingsOptions.Builder.id(offering.getId())));
assertEquals(offering, newDetails);
assertEquals(offering, client.getOfferingClient().getNetworkOffering(offering.getId()));
assert offering.getId() > 0 : offering;

View File

@ -22,6 +22,7 @@ package org.jclouds.cloudstack.features;
import java.io.IOException;
import java.lang.reflect.Method;
import org.jclouds.cloudstack.options.AccountInDomainOptions;
import org.jclouds.cloudstack.options.ListSecurityGroupsOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
@ -34,6 +35,9 @@ import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.inject.TypeLiteral;
/**
@ -50,7 +54,7 @@ public class SecurityGroupAsyncClientTest extends BaseCloudStackAsyncClientTest<
HttpRequest httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listSecurityGroups HTTP/1.1");
"GET http://localhost:8080/client/api?response=json&command=listSecurityGroups HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -65,11 +69,11 @@ public class SecurityGroupAsyncClientTest extends BaseCloudStackAsyncClientTest<
public void testListSecurityGroupsOptions() throws SecurityException, NoSuchMethodException, IOException {
Method method = SecurityGroupAsyncClient.class.getMethod("listSecurityGroups", ListSecurityGroupsOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, ListSecurityGroupsOptions.Builder.virtualMachineId(4)
.domainId(5).id(6));
.domainId(5).id(6));
assertRequestLineEquals(
httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listSecurityGroups&virtualmachineid=4&domainid=5&id=6 HTTP/1.1");
httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listSecurityGroups&virtualmachineid=4&domainid=5&id=6 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -86,7 +90,7 @@ public class SecurityGroupAsyncClientTest extends BaseCloudStackAsyncClientTest<
HttpRequest httpRequest = processor.createRequest(method, 5);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listSecurityGroups&id=5 HTTP/1.1");
"GET http://localhost:8080/client/api?response=json&command=listSecurityGroups&id=5 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -103,7 +107,7 @@ public class SecurityGroupAsyncClientTest extends BaseCloudStackAsyncClientTest<
HttpRequest httpRequest = processor.createRequest(method, "goo");
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=createSecurityGroup&name=goo HTTP/1.1");
"GET http://localhost:8080/client/api?response=json&command=createSecurityGroup&name=goo HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -115,12 +119,110 @@ public class SecurityGroupAsyncClientTest extends BaseCloudStackAsyncClientTest<
}
public void testAuthorizeIngressPortsToCIDRs() throws SecurityException, NoSuchMethodException, IOException {
Method method = SecurityGroupAsyncClient.class.getMethod("authorizeIngressPortsToCIDRs", long.class,
String.class, int.class, int.class, Iterable.class, AccountInDomainOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, 2, "tcp", 22, 22, ImmutableSet.of("1.1.1.1/24",
"1.2.2.2/16"));
assertRequestLineEquals(
httpRequest,
"GET http://localhost:8080/client/api?response=json&command=authorizeSecurityGroupIngress&securitygroupid=2&startport=22&protocol=tcp&endport=22&cidrlist=1.1.1.1%2F24%2C1.2.2.2%2F16 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyNestedJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(httpRequest);
}
public void testAuthorizeIngressPortsToSecurityGroups() throws SecurityException, NoSuchMethodException, IOException {
Method method = SecurityGroupAsyncClient.class.getMethod("authorizeIngressPortsToSecurityGroups", long.class,
String.class, int.class, int.class, Multimap.class, AccountInDomainOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, 2, "tcp", 22, 22, ImmutableMultimap.of("adrian",
"group1", "adrian", "group2", "bob", "group1"));
assertRequestLineEquals(
httpRequest,
"GET http://localhost:8080/client/api?response=json&command=authorizeSecurityGroupIngress&securitygroupid=2&startport=22&protocol=tcp&endport=22&usersecuritygrouplist%5B0%5D.account=adrian&usersecuritygrouplist%5B0%5D.group=group1&usersecuritygrouplist%5B1%5D.account=adrian&usersecuritygrouplist%5B1%5D.group=group2&usersecuritygrouplist%5B2%5D.account=bob&usersecuritygrouplist%5B2%5D.group=group1 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyNestedJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(httpRequest);
}
public void testAuthorizeIngressICMPToCIDRs() throws SecurityException, NoSuchMethodException, IOException {
Method method = SecurityGroupAsyncClient.class.getMethod("authorizeIngressICMPToCIDRs", long.class, int.class,
int.class, Iterable.class, AccountInDomainOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, 2, 22, 22, ImmutableSet.of("1.1.1.1/24", "1.2.2.2/16"));
assertRequestLineEquals(
httpRequest,
"GET http://localhost:8080/client/api?response=json&command=authorizeSecurityGroupIngress&protocol=ICMP&securitygroupid=2&icmptype=22&icmpcode=22&cidrlist=1.1.1.1%2F24%2C1.2.2.2%2F16 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyNestedJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(httpRequest);
}
public void testAuthorizeIngressICMPToSecurityGroups() throws SecurityException, NoSuchMethodException, IOException {
Method method = SecurityGroupAsyncClient.class.getMethod("authorizeIngressICMPToSecurityGroups", long.class,
int.class, int.class, Multimap.class, AccountInDomainOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, 2, 22, 22, ImmutableMultimap.of("adrian", "group1",
"adrian", "group2", "bob", "group1"));
assertRequestLineEquals(
httpRequest,
"GET http://localhost:8080/client/api?response=json&command=authorizeSecurityGroupIngress&protocol=ICMP&securitygroupid=2&icmptype=22&icmpcode=22&usersecuritygrouplist%5B0%5D.account=adrian&usersecuritygrouplist%5B0%5D.group=group1&usersecuritygrouplist%5B1%5D.account=adrian&usersecuritygrouplist%5B1%5D.group=group2&usersecuritygrouplist%5B2%5D.account=bob&usersecuritygrouplist%5B2%5D.group=group1 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyNestedJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(httpRequest);
}
public void testRevokeIngressRule() throws SecurityException, NoSuchMethodException, IOException {
Method method = SecurityGroupAsyncClient.class.getMethod("revokeIngressRule", long.class,
AccountInDomainOptions[].class);
HttpRequest httpRequest = processor.createRequest(method, 5, AccountInDomainOptions.Builder.accountInDomain(
"adrian", 1));
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=revokeSecurityGroupIngress&id=5&account=adrian&domainid=1 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
assertResponseParserClassEquals(method, httpRequest, UnwrapOnlyNestedJsonValue.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
checkFilters(httpRequest);
}
public void testDeleteSecurityGroup() throws SecurityException, NoSuchMethodException, IOException {
Method method = SecurityGroupAsyncClient.class.getMethod("deleteSecurityGroup", long.class);
HttpRequest httpRequest = processor.createRequest(method, 5);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=deleteSecurityGroup&id=5 HTTP/1.1");
"GET http://localhost:8080/client/api?response=json&command=deleteSecurityGroup&id=5 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null, null, false);

View File

@ -21,15 +21,24 @@ package org.jclouds.cloudstack.features;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.NoSuchElementException;
import org.jclouds.cloudstack.domain.IngressRule;
import org.jclouds.cloudstack.domain.SecurityGroup;
import org.jclouds.cloudstack.domain.VirtualMachine;
import org.jclouds.cloudstack.domain.Zone;
import org.jclouds.cloudstack.options.AccountInDomainOptions;
import org.jclouds.cloudstack.options.ListSecurityGroupsOptions;
import org.jclouds.net.IPSocket;
import org.jclouds.util.Strings2;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
@ -39,12 +48,19 @@ import com.google.common.collect.Iterables;
*/
@Test(groups = "live", sequential = true, testName = "SecurityGroupClientLiveTest")
public class SecurityGroupClientLiveTest extends BaseCloudStackClientLiveTest {
public SecurityGroupClientLiveTest() {
prefix += "2";
}
private SecurityGroup group;
private boolean securityGroupsSupported;
private VirtualMachine vm;
private Zone zone;
public void testCreateDestroySecurityGroup() throws Exception {
@Test
public void testCreateDestroySecurityGroup() {
try {
Iterables.find(client.getZoneClient().listZones(), new Predicate<Zone>() {
zone = Iterables.find(client.getZoneClient().listZones(), new Predicate<Zone>() {
@Override
public boolean apply(Zone arg0) {
@ -52,10 +68,13 @@ public class SecurityGroupClientLiveTest extends BaseCloudStackClientLiveTest {
}
});
securityGroupsSupported = true;
for (SecurityGroup securityGroup : client.getSecurityGroupClient().listSecurityGroups(
ListSecurityGroupsOptions.Builder.named(prefix)))
ListSecurityGroupsOptions.Builder.named(prefix))) {
for (IngressRule rule : securityGroup.getIngressRules())
assert this.jobComplete.apply(client.getSecurityGroupClient().revokeIngressRule(rule.getId())) : rule;
client.getSecurityGroupClient().deleteSecurityGroup(securityGroup.getId());
}
group = client.getSecurityGroupClient().createSecurityGroup(prefix);
assertEquals(group.getName(), prefix);
checkGroup(group);
@ -66,13 +85,106 @@ public class SecurityGroupClientLiveTest extends BaseCloudStackClientLiveTest {
}
} catch (NoSuchElementException e) {
e.printStackTrace();
}
}
protected void checkGroup(SecurityGroup group) throws InterruptedException {
// sometimes this comes up different
// assertEquals(group, client.getSecurityGroupClient().getSecurityGroup(group.getId()));
public static String getCurrentCIDR() throws IOException {
URL url = new URL("http://checkip.amazonaws.com/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
// http://bugs.cloud.com/show_bug.cgi?id=8969
// return Strings2.toStringAndClose(connection.getInputStream()).trim()+"/32";
return Strings2.toStringAndClose(connection.getInputStream()).trim();
}
@Test(dependsOnMethods = "testCreateDestroySecurityGroup")
public void testCreateIngress() throws Exception {
if (!securityGroupsSupported)
return;
String cidr = getCurrentCIDR();
ImmutableSet<String> cidrs = ImmutableSet.of(cidr);
assert jobComplete.apply(client.getSecurityGroupClient().authorizeIngressICMPToCIDRs(group.getId(), 0, 8, cidrs)) : group;
assert jobComplete.apply(client.getSecurityGroupClient().authorizeIngressPortsToCIDRs(group.getId(), "TCP", 22,
22, cidrs)) : group;
AccountInDomainOptions.Builder.accountInDomain(group.getAccount(), group.getDomainId());
// replace with get once bug is fixed where getGroup returns only one ingress rule
group = Iterables.find(client.getSecurityGroupClient().listSecurityGroups(), new Predicate<SecurityGroup>() {
@Override
public boolean apply(SecurityGroup input) {
return input.getId() == group.getId();
}
});
IngressRule ICMPPingRule = Iterables.find(group.getIngressRules(), new Predicate<IngressRule>() {
@Override
public boolean apply(IngressRule input) {
return "icmp".equals(input.getProtocol());
}
});
assert ICMPPingRule.getId() > 0 : ICMPPingRule;
assert "icmp".equals(ICMPPingRule.getProtocol()) : ICMPPingRule;
assert ICMPPingRule.getStartPort() == -1 : ICMPPingRule;
assert ICMPPingRule.getEndPort() == -1 : ICMPPingRule;
assert ICMPPingRule.getICMPCode() == 0 : ICMPPingRule;
assert ICMPPingRule.getICMPType() == 8 : ICMPPingRule;
assert ICMPPingRule.getAccount() == null : ICMPPingRule;
assert ICMPPingRule.getSecurityGroupName() == null : ICMPPingRule;
assert cidr.equals(ICMPPingRule.getCIDR()) : ICMPPingRule;
IngressRule SSHRule = Iterables.find(group.getIngressRules(), new Predicate<IngressRule>() {
@Override
public boolean apply(IngressRule input) {
return "tcp".equals(input.getProtocol());
}
});
assert SSHRule.getId() > 0 : SSHRule;
assert "tcp".equals(SSHRule.getProtocol()) : SSHRule;
assert SSHRule.getStartPort() == 22 : SSHRule;
assert SSHRule.getEndPort() == 22 : SSHRule;
assert SSHRule.getICMPCode() == -1 : SSHRule;
assert SSHRule.getICMPType() == -1 : SSHRule;
assert SSHRule.getAccount() == null : SSHRule;
assert SSHRule.getSecurityGroupName() == null : SSHRule;
assert cidr.equals(SSHRule.getCIDR()) : SSHRule;
}
public void testListSecurityGroup() throws Exception {
if (!securityGroupsSupported)
return;
for (SecurityGroup securityGroup : client.getSecurityGroupClient().listSecurityGroups())
checkGroup(securityGroup);
}
@Test(dependsOnMethods = "testCreateIngress")
public void testCreateVMInSecurityGroup() throws Exception {
if (!securityGroupsSupported)
return;
vm = VirtualMachineClientLiveTest.createVirtualMachineWithSecurityGroupInZone(zone.getId(), group.getId(),
client, jobComplete, virtualMachineRunning);
if (vm.getPassword() != null)
password = vm.getPassword();
// ingress port 22
checkSSH(new IPSocket(vm.getIPAddress(), 22));
// ingress icmp disabled as this is platform dependent and may actually just try tcp port 7
// assert InetAddress.getByName(vm.getIPAddress()).isReachable(1000) : vm;
}
protected void checkGroup(SecurityGroup group) {
// http://bugs.cloud.com/show_bug.cgi?id=8968
if (group.getIngressRules().size() <= 1)
assertEquals(group, client.getSecurityGroupClient().getSecurityGroup(group.getId()));
assert group.getId() > 0 : group;
assert group.getName() != null : group;
assert group.getAccount() != null : group;
@ -83,7 +195,12 @@ public class SecurityGroupClientLiveTest extends BaseCloudStackClientLiveTest {
@AfterGroups(groups = "live")
protected void tearDown() {
if (vm != null) {
assert jobComplete.apply(client.getVirtualMachineClient().destroyVirtualMachine(vm.getId()));
}
if (group != null) {
for (IngressRule rule : group.getIngressRules())
assert this.jobComplete.apply(client.getSecurityGroupClient().revokeIngressRule(rule.getId())) : rule;
client.getSecurityGroupClient().deleteSecurityGroup(group.getId());
assertEquals(client.getSecurityGroupClient().getSecurityGroup(group.getId()), null);
}

View File

@ -47,7 +47,7 @@ public class TemplateAsyncClientTest extends BaseCloudStackAsyncClientTest<Templ
HttpRequest httpRequest = processor.createRequest(method);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listTemplates&templatefilter=executable HTTP/1.1");
"GET http://localhost:8080/client/api?response=json&command=listTemplates&templatefilter=executable HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -61,15 +61,12 @@ public class TemplateAsyncClientTest extends BaseCloudStackAsyncClientTest<Templ
public void testListTemplatesOptions() throws SecurityException, NoSuchMethodException, IOException {
Method method = TemplateAsyncClient.class.getMethod("listTemplates", ListTemplatesOptions.class);
HttpRequest httpRequest = processor
.createRequest(
method,
ListTemplatesOptions.Builder.accountInDomain("adrian", 6).hypervisor("xen")
.filter(TemplateFilter.FEATURED));
HttpRequest httpRequest = processor.createRequest(method, ListTemplatesOptions.Builder.accountInDomain("adrian",
6).hypervisor("xen").filter(TemplateFilter.FEATURED));
assertRequestLineEquals(
httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listTemplates&account=adrian&domainid=6&hypervisor=xen&templatefilter=featured HTTP/1.1");
httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listTemplates&account=adrian&domainid=6&hypervisor=xen&templatefilter=featured HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);
@ -82,11 +79,11 @@ public class TemplateAsyncClientTest extends BaseCloudStackAsyncClientTest<Templ
}
public void testGetTemplate() throws SecurityException, NoSuchMethodException, IOException {
Method method = TemplateAsyncClient.class.getMethod("getTemplate", long.class);
HttpRequest httpRequest = processor.createRequest(method, 5);
Method method = TemplateAsyncClient.class.getMethod("getTemplateInZone", long.class, long.class);
HttpRequest httpRequest = processor.createRequest(method, 1, 5);
assertRequestLineEquals(httpRequest,
"GET http://localhost:8080/client/api?response=json&command=listTemplates&templatefilter=executable&id=5 HTTP/1.1");
"GET http://localhost:8080/client/api?response=json&command=listTemplates&templatefilter=executable&zoneid=1&id=5 HTTP/1.1");
assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\n");
assertPayloadEquals(httpRequest, null, null, false);

View File

@ -25,7 +25,7 @@ import static org.testng.Assert.assertTrue;
import java.util.Set;
import org.jclouds.cloudstack.domain.Template;
import org.jclouds.cloudstack.options.ListTemplatesOptions;
import static org.jclouds.cloudstack.options.ListTemplatesOptions.Builder.zoneId;
import org.testng.annotations.Test;
import com.google.common.collect.Iterables;
@ -45,9 +45,9 @@ public class TemplateClientLiveTest extends BaseCloudStackClientLiveTest {
assertTrue(templateCount >= 0);
for (Template template : response) {
Template newDetails = Iterables.getOnlyElement(client.getTemplateClient().listTemplates(
ListTemplatesOptions.Builder.id(template.getId())));
zoneId(template.getZoneId()).id(template.getId())));
assertEquals(template, newDetails);
assertEquals(template, client.getTemplateClient().getTemplate(template.getId()));
assertEquals(template, client.getTemplateClient().getTemplateInZone(template.getZoneId(), template.getId()));
assert template.getId() > 0 : template;
assert template.getName() != null : template;
assert template.getDisplayText() != null : template;

View File

@ -38,12 +38,16 @@ import org.jclouds.cloudstack.domain.AsyncJob;
import org.jclouds.cloudstack.domain.GuestIPType;
import org.jclouds.cloudstack.domain.NIC;
import org.jclouds.cloudstack.domain.Network;
import org.jclouds.cloudstack.domain.SecurityGroup;
import org.jclouds.cloudstack.domain.ServiceOffering;
import org.jclouds.cloudstack.domain.Template;
import org.jclouds.cloudstack.domain.VirtualMachine;
import org.jclouds.cloudstack.domain.Zone;
import org.jclouds.cloudstack.options.DeployVirtualMachineOptions;
import org.jclouds.cloudstack.options.ListTemplatesOptions;
import org.jclouds.cloudstack.options.ListVirtualMachinesOptions;
import org.jclouds.cloudstack.predicates.CorrectHypervisorForZone;
import org.jclouds.cloudstack.predicates.OSCategoryIn;
import org.jclouds.cloudstack.predicates.TemplatePredicates;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.util.InetAddresses2;
@ -51,8 +55,10 @@ import org.testng.annotations.AfterGroups;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Throwables;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
import com.google.common.net.HostSpecifier;
@ -77,24 +83,26 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
RetryablePredicate<VirtualMachine> virtualMachineRunning) {
Set<Network> networks = client.getNetworkClient().listNetworks();
if (networks.size() > 0) {
return createVirtualMachineInNetwork(Iterables.get(networks, 0), client, jobComplete, virtualMachineRunning);
return createVirtualMachineInNetwork(get(networks, 0), client, jobComplete, virtualMachineRunning);
} else {
return createVirtualMachineWithSecurityGroup(find(client.getSecurityGroupClient().listSecurityGroups(),
new Predicate<SecurityGroup>() {
return createVirtualMachineWithSecurityGroupInZone(find(client.getZoneClient().listZones(),
new Predicate<Zone>() {
@Override
public boolean apply(SecurityGroup arg0) {
return arg0.getName().equals("default");
public boolean apply(Zone arg0) {
return arg0.isSecurityGroupsEnabled();
}
}), client, jobComplete, virtualMachineRunning);
}).getId(), get(client.getSecurityGroupClient().listSecurityGroups(), 0).getId(), client,
jobComplete, virtualMachineRunning);
}
}
public static VirtualMachine createVirtualMachineWithSecurityGroup(SecurityGroup group, CloudStackClient client,
RetryablePredicate<Long> jobComplete, RetryablePredicate<VirtualMachine> virtualMachineRunning) {
return createVirtualMachineWithOptionsInZone(new DeployVirtualMachineOptions().securityGroupId(group.getId()),
get(client.getZoneClient().listZones(), 0).getId(), client, jobComplete, virtualMachineRunning);
public static VirtualMachine createVirtualMachineWithSecurityGroupInZone(long zoneId, long groupId,
CloudStackClient client, RetryablePredicate<Long> jobComplete,
RetryablePredicate<VirtualMachine> virtualMachineRunning) {
return createVirtualMachineWithOptionsInZone(new DeployVirtualMachineOptions().securityGroupId(groupId), zoneId,
client, jobComplete, virtualMachineRunning);
}
public static VirtualMachine createVirtualMachineInNetwork(Network network, CloudStackClient client,
@ -108,36 +116,26 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
public static VirtualMachine createVirtualMachineWithOptionsInZone(DeployVirtualMachineOptions options,
final long zoneId, CloudStackClient client, RetryablePredicate<Long> jobComplete,
RetryablePredicate<VirtualMachine> virtualMachineRunning) {
// TODO enum, as this is way too easy to mess up.
Set<String> acceptableCategories = ImmutableSet.of("Ubuntu", "CentOS");
final Predicate<Template> hypervisorPredicate = new CorrectHypervisorForZone(client).apply(zoneId);
final Predicate<Template> osTypePredicate = new OSCategoryIn(client).apply(acceptableCategories);
Predicate<Template> templatePredicate = Predicates.<Template> and(TemplatePredicates.isReady(),
hypervisorPredicate, osTypePredicate);
Iterable<Template> templates = filter(client.getTemplateClient().listTemplates(
ListTemplatesOptions.Builder.zoneId(zoneId)), templatePredicate);
if (Iterables.any(templates, TemplatePredicates.isPasswordEnabled())) {
templates = filter(templates, TemplatePredicates.isPasswordEnabled());
}
if (Iterables.size(templates) == 0) {
throw new NoSuchElementException(templatePredicate.toString());
}
long templateId = get(templates, 0).getId();
long serviceOfferingId = DEFAULT_SIZE_ORDERING.min(client.getOfferingClient().listServiceOfferings()).getId();
Iterable<Template> templates = filter(client.getTemplateClient().listTemplates(), new Predicate<Template>() {
@Override
public boolean apply(Template arg0) {
return arg0.isReady() && (arg0.isCrossZones() || arg0.getZoneId() == zoneId)
&& or(equalTo("Ubuntu 10.04 (64-bit)"), equalTo("CentOS 5.3 (64-bit)")).apply(arg0.getOSType());
}
});
if (Iterables.size(templates) == 0) {
throw new NoSuchElementException();
}
long templateId;
try {
// prefer password enabled
templateId = find(templates, new Predicate<Template>() {
@Override
public boolean apply(Template arg0) {
return arg0.isPasswordEnabled();
}
}).getId();
} catch (NoSuchElementException e) {
templateId = get(templates, 0).getId();
}
System.out.printf("serviceOfferingId %d, templateId %d, zoneId %d, options %s%n", serviceOfferingId, templateId,
zoneId, options);
AsyncCreateResponse job = client.getVirtualMachineClient().deployVirtualMachine(serviceOfferingId, templateId,
@ -211,9 +209,8 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
@AfterGroups(groups = "live")
protected void tearDown() {
if (vm != null) {
Long job = client.getVirtualMachineClient().destroyVirtualMachine(vm.getId());
assert job != null;
assert jobComplete.apply(job);
assert jobComplete.apply(client.getVirtualMachineClient().stopVirtualMachine(vm.getId())) : vm;
assert jobComplete.apply(client.getVirtualMachineClient().destroyVirtualMachine(vm.getId())) : vm;
assert virtualMachineDestroyed.apply(vm);
}
super.tearDown();

View File

@ -0,0 +1,57 @@
/**
*
* Copyright (C) 2010 Cloud Conscious) LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.functions;
import static org.testng.Assert.assertEquals;
import org.jclouds.cloudstack.domain.Capabilities;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
import org.jclouds.io.Payloads;
import org.jclouds.json.config.GsonModule;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ListCapabilitiesResponseTest {
public void test() {
UnwrapOnlyNestedJsonValue<Capabilities> parser = Guice.createInjector(new GsonModule()).getInstance(
Key.get(new TypeLiteral<UnwrapOnlyNestedJsonValue<Capabilities>>() {
}));
Capabilities response = parser
.apply(new HttpResponse(
200,
"ok",
Payloads
.newStringPayload("{ \"listcapabilitiesresponse\" : { \"capability\" : {\"securitygroupsenabled\":true,\"cloudstackversion\":\"2.2\",\"userpublictemplateenabled\":true} } }")));
assertEquals(Capabilities.builder().securityGroupsEnabled(true).sharedTemplatesEnabled(true).cloudStackVersion(
"2.2").build(), response);
}
}

View File

@ -33,7 +33,7 @@ import org.jclouds.json.config.GsonModule;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.ImmutableSortedSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
@ -59,25 +59,49 @@ public class ListSecurityGroupsResponseTest {
public void test() {
InputStream is = getClass().getResourceAsStream("/listsecuritygroupsresponse.json");
Set<SecurityGroup> expects = ImmutableSet.<SecurityGroup> of(SecurityGroup.builder().id(3).name("default")
.description("Default Security Group").account("adrian").domainId(1).domain("ROOT").ingressRules(
ImmutableSet.of(IngressRule.builder().id(8).protocol("tcp").startPort(22).endPort(22).CIDR(
"0.0.0.0/32").build(),
Set<SecurityGroup> expects = ImmutableSortedSet.<SecurityGroup> naturalOrder().add(
IngressRule.builder().id(9).protocol("icmp").ICMPType(-1).ICMPCode(-1).securityGroupName(
"default").account("adrian").build(),
SecurityGroup.builder().id(12).name("adriancole").account("adrian").domainId(1).domain("ROOT").build()).add(
SecurityGroup.builder().id(13).name("default").description("description").account("adrian").domainId(1)
.domain("ROOT").ingressRules(
ImmutableSet.of(
IngressRule.builder().id(10).protocol("tcp").startPort(80).endPort(80).securityGroupName(
"default").account("adrian").build())).build(),
IngressRule.builder().id(5).protocol("tcp").startPort(22).endPort(22)
.securityGroupName("adriancole").account("adrian").build(),
SecurityGroup.builder().id(15).name("adriancole").account("adrian").domainId(1).domain("ROOT").build());
IngressRule.builder().id(6).protocol("udp").startPort(11).endPort(11).CIDR(
"1.1.1.1/24").build())).build()).add(
SecurityGroup.builder().id(14).name("1").description("description").account("adrian").domainId(1)
.domain("ROOT").ingressRules(
ImmutableSet.of(
IngressRule.builder().id(7).protocol("tcp").startPort(10).endPort(10).CIDR(
"1.1.1.1/24").build(),
IngressRule.builder().id(8).protocol("tcp").startPort(10).endPort(10).CIDR(
"2.2.2.2/16").build())).build()).add(
SecurityGroup.builder().id(15).name("2").description("description").account("adrian").domainId(1)
.domain("ROOT").build(),
SecurityGroup.builder().id(16).name("with1and2").description("description").account("adrian")
.domainId(1).domain("ROOT").ingressRules(
ImmutableSet.of(
IngressRule.builder().id(9).protocol("icmp").ICMPType(-1).ICMPCode(-1)
.securityGroupName("1").account("adrian").build(),
IngressRule.builder().id(10).protocol("tcp").startPort(22).endPort(22)
.securityGroupName("1").account("adrian").build(),
IngressRule.builder().id(11).protocol("tcp").startPort(22).endPort(22)
.securityGroupName("2").account("adrian").build())).build()).build();
UnwrapOnlyNestedJsonValue<Set<SecurityGroup>> parser = i.getInstance(Key
.get(new TypeLiteral<UnwrapOnlyNestedJsonValue<Set<SecurityGroup>>>() {
}));
Set<SecurityGroup> response = parser.apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is)));
Set<SecurityGroup> response = ImmutableSortedSet.copyOf(parser.apply(new HttpResponse(200, "ok", Payloads
.newInputStreamPayload(is))));
assertEquals(Sets.newHashSet(response), expects);
assertEquals(response, expects);
}
}

View File

@ -19,7 +19,7 @@
package org.jclouds.cloudstack.options;
import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.account;
import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.accountInDomain;
import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.domainId;
import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.id;
import static org.jclouds.cloudstack.options.ListSecurityGroupsOptions.Builder.named;
@ -49,12 +49,12 @@ public class ListSecurityGroupsOptionsTest {
}
public void testAccount() {
ListSecurityGroupsOptions options = new ListSecurityGroupsOptions().account("account");
ListSecurityGroupsOptions options = new ListSecurityGroupsOptions().accountInDomain("account", 1);
assertEquals(ImmutableList.of("account"), options.buildQueryParameters().get("account"));
}
public void testAccountStatic() {
ListSecurityGroupsOptions options = account("account");
ListSecurityGroupsOptions options = accountInDomain("account", 1);
assertEquals(ImmutableList.of("account"), options.buildQueryParameters().get("account"));
}

View File

@ -1 +1 @@
{ "listsecuritygroupsresponse" : { "securitygroup" : [ {"id":3,"name":"default","description":"Default Security Group","account":"adrian","domainid":1,"domain":"ROOT","ingressrule":[{"ruleid":8,"protocol":"tcp","startport":22,"endport":22,"cidr":"0.0.0.0/32"},{"ruleid":9,"protocol":"icmp","icmptype":-1,"icmpcode":-1,"securitygroupname":"default","account":"adrian"},{"ruleid":10,"protocol":"tcp","startport":80,"endport":80,"securitygroupname":"default","account":"adrian"}]}, {"id":15,"name":"adriancole","account":"adrian","domainid":1,"domain":"ROOT"} ] } }
{ "listsecuritygroupsresponse" : { "securitygroup" : [ {"id":12,"name":"adriancole","account":"adrian","domainid":1,"domain":"ROOT"}, {"id":13,"name":"default","description":"description","account":"adrian","domainid":1,"domain":"ROOT","ingressrule":[{"ruleid":5,"protocol":"tcp","startport":22,"endport":22,"securitygroupname":"adriancole","account":"adrian"},{"ruleid":6,"protocol":"udp","startport":11,"endport":11,"cidr":"1.1.1.1/24"}]}, {"id":14,"name":"1","description":"description","account":"adrian","domainid":1,"domain":"ROOT","ingressrule":[{"ruleid":7,"protocol":"tcp","startport":10,"endport":10,"cidr":"1.1.1.1/24"},{"ruleid":8,"protocol":"tcp","startport":10,"endport":10,"cidr":"2.2.2.2/16"}]}, {"id":15,"name":"2","description":"description","account":"adrian","domainid":1,"domain":"ROOT"}, {"id":16,"name":"with1and2","description":"description","account":"adrian","domainid":1,"domain":"ROOT","ingressrule":[{"ruleid":9,"protocol":"icmp","icmptype":-1,"icmpcode":-1,"securitygroupname":"1","account":"adrian"},{"ruleid":10,"protocol":"tcp","startport":22,"endport":22,"securitygroupname":"1","account":"adrian"},{"ruleid":11,"protocol":"tcp","startport":22,"endport":22,"securitygroupname":"2","account":"adrian"}]} ] } }

View File

@ -148,9 +148,13 @@
<category name="jclouds.ssh">
<priority value="TRACE" />
<appender-ref ref="ASYNCSSH" />
</category><!--
<category name="jclouds.signature">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="jclouds.wire">
--><category name="jclouds.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>