mirror of https://github.com/apache/jclouds.git
added function to obtain a new ip or reuse
This commit is contained in:
parent
0e794c4788
commit
e8038f5d48
|
@ -51,7 +51,7 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<test.cloudstack.endpoint>http://localhost:8080/client/api</test.cloudstack.endpoint>
|
<test.cloudstack.endpoint>http://localhost:8080/client/api</test.cloudstack.endpoint>
|
||||||
<test.cloudstack.apiversion>2.2</test.cloudstack.apiversion>
|
<test.cloudstack.apiversion>2.2.0</test.cloudstack.apiversion>
|
||||||
<test.cloudstack.identity>FIXME_apiKey</test.cloudstack.identity>
|
<test.cloudstack.identity>FIXME_apiKey</test.cloudstack.identity>
|
||||||
<test.cloudstack.credential>FIXME_secretKey</test.cloudstack.credential>
|
<test.cloudstack.credential>FIXME_secretKey</test.cloudstack.credential>
|
||||||
</properties>
|
</properties>
|
||||||
|
@ -68,6 +68,18 @@
|
||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-compute</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jclouds</groupId>
|
||||||
|
<artifactId>jclouds-compute</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>test-jar</type>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jclouds.driver</groupId>
|
<groupId>org.jclouds.driver</groupId>
|
||||||
<artifactId>jclouds-jsch</artifactId>
|
<artifactId>jclouds-jsch</artifactId>
|
||||||
|
@ -108,6 +120,8 @@
|
||||||
<goal>test</goal>
|
<goal>test</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
<!-- too many tasks seem to overload the server and make the test take longer -->
|
||||||
|
<threadCount>2</threadCount>
|
||||||
<systemProperties>
|
<systemProperties>
|
||||||
<property>
|
<property>
|
||||||
<name>test.cloudstack.endpoint</name>
|
<name>test.cloudstack.endpoint</name>
|
||||||
|
|
|
@ -38,6 +38,11 @@ public class AsyncCreateResponse {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AsyncCreateResponse(long id, long jobId) {
|
||||||
|
this.id = id;
|
||||||
|
this.jobId = jobId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return id of the resource being created
|
* @return id of the resource being created
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -29,6 +29,7 @@ import javax.ws.rs.core.MediaType;
|
||||||
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
||||||
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
||||||
import org.jclouds.cloudstack.filters.QuerySigner;
|
import org.jclouds.cloudstack.filters.QuerySigner;
|
||||||
|
import org.jclouds.cloudstack.functions.ReturnVoidOnNotFoundOr404OrUnableToFindAccountOwner;
|
||||||
import org.jclouds.cloudstack.options.AssociateIPAddressOptions;
|
import org.jclouds.cloudstack.options.AssociateIPAddressOptions;
|
||||||
import org.jclouds.cloudstack.options.ListPublicIPAddressesOptions;
|
import org.jclouds.cloudstack.options.ListPublicIPAddressesOptions;
|
||||||
import org.jclouds.rest.annotations.ExceptionParser;
|
import org.jclouds.rest.annotations.ExceptionParser;
|
||||||
|
@ -37,7 +38,6 @@ import org.jclouds.rest.annotations.RequestFilters;
|
||||||
import org.jclouds.rest.annotations.Unwrap;
|
import org.jclouds.rest.annotations.Unwrap;
|
||||||
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||||
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||||
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ public interface AddressAsyncClient {
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@QueryParams(keys = "command", values = "disassociateIpAddress")
|
@QueryParams(keys = "command", values = "disassociateIpAddress")
|
||||||
@ExceptionParser(ReturnVoidOnNotFoundOr404.class)
|
@ExceptionParser(ReturnVoidOnNotFoundOr404OrUnableToFindAccountOwner.class)
|
||||||
ListenableFuture<Void> disassociateIPAddress(@QueryParam("id") long id);
|
ListenableFuture<Void> disassociateIPAddress(@QueryParam("id") long id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
||||||
|
import org.jclouds.util.Throwables2;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CloudStack is currently sending 431 errors with the text "Unable to find account owner for ip ".
|
||||||
|
* In this case, we have to ignore as there's no means for us to avoid the problem, or action to
|
||||||
|
* take.
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ReturnVoidOnNotFoundOr404OrUnableToFindAccountOwner implements Function<Exception, Void> {
|
||||||
|
|
||||||
|
private final ReturnVoidOnNotFoundOr404 rto404;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ReturnVoidOnNotFoundOr404OrUnableToFindAccountOwner(ReturnVoidOnNotFoundOr404 rto404) {
|
||||||
|
this.rto404 = checkNotNull(rto404, "rto404");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Void apply(Exception from) {
|
||||||
|
IllegalStateException e = Throwables2.getFirstThrowableOfType(from, IllegalStateException.class);
|
||||||
|
if (e != null && e.getMessage().indexOf("Unable to find account owner for") != -1) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return rto404.apply(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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 static com.google.common.base.Preconditions.checkState;
|
||||||
|
import static com.google.common.base.Predicates.and;
|
||||||
|
import static com.google.common.collect.Iterables.find;
|
||||||
|
import static org.jclouds.cloudstack.options.AssociateIPAddressOptions.Builder.networkId;
|
||||||
|
import static org.jclouds.cloudstack.options.ListPublicIPAddressesOptions.Builder.allocatedOnly;
|
||||||
|
import static org.jclouds.cloudstack.predicates.PublicIPAddressPredicates.associatedWithNetwork;
|
||||||
|
import static org.jclouds.cloudstack.predicates.PublicIPAddressPredicates.available;
|
||||||
|
import static org.jclouds.compute.reference.ComputeServiceConstants.COMPUTE_LOGGER;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.cloudstack.CloudStackClient;
|
||||||
|
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
||||||
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
|
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
||||||
|
import org.jclouds.cloudstack.features.AddressClient;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class ReuseOrAssociateNewPublicIPAddress implements Function<Network, PublicIPAddress> {
|
||||||
|
private final CloudStackClient client;
|
||||||
|
private final Predicate<Long> jobComplete;
|
||||||
|
@Resource
|
||||||
|
@Named(COMPUTE_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public
|
||||||
|
ReuseOrAssociateNewPublicIPAddress(CloudStackClient client, Predicate<Long> jobComplete) {
|
||||||
|
this.client = checkNotNull(client, "client");
|
||||||
|
this.jobComplete = checkNotNull(jobComplete, "jobComplete");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds existing addresses who are ready for use and not assigned to a machine.
|
||||||
|
*
|
||||||
|
* @param networkId
|
||||||
|
* network id to search
|
||||||
|
* @param client
|
||||||
|
* address client
|
||||||
|
* @return address to use
|
||||||
|
* @throws NoSuchElementException
|
||||||
|
* if there's no existing ip address that is free for use
|
||||||
|
*/
|
||||||
|
public static PublicIPAddress findAvailableAndAssociatedWithNetwork(long networkId, AddressClient client) {
|
||||||
|
return find(client.listPublicIPAddresses(allocatedOnly(true).networkId(networkId)), and(
|
||||||
|
associatedWithNetwork(networkId), available()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PublicIPAddress associateIPAddressInNetwork(Network network, CloudStackClient client,
|
||||||
|
Predicate<Long> jobComplete) {
|
||||||
|
AsyncCreateResponse job = client.getAddressClient().associateIPAddress(network.getZoneId(),
|
||||||
|
networkId(network.getId()));
|
||||||
|
checkState(jobComplete.apply(job.getJobId()), "job %d failed to complete", job.getJobId());
|
||||||
|
PublicIPAddress ip = client.getAsyncJobClient().<PublicIPAddress> getAsyncJob(job.getJobId()).getResult();
|
||||||
|
assert ip.getZoneId() == network.getZoneId();
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PublicIPAddress apply(Network input) {
|
||||||
|
try {
|
||||||
|
logger.debug(">> looking for existing address in network %d", input.getId());
|
||||||
|
PublicIPAddress returnVal = findAvailableAndAssociatedWithNetwork(input.getId(), client.getAddressClient());
|
||||||
|
logger.debug("<< address(%d)", returnVal.getId());
|
||||||
|
return returnVal;
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
logger.debug(">> associating new address in network %d", input.getId());
|
||||||
|
PublicIPAddress returnVal = associateIPAddressInNetwork(input, client, jobComplete);
|
||||||
|
logger.debug("<< address(%d)", returnVal.getId());
|
||||||
|
return returnVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,8 @@ package org.jclouds.cloudstack.predicates;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@ -29,6 +31,7 @@ import org.jclouds.cloudstack.domain.AsyncJob;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,14 +55,19 @@ public class JobComplete implements Predicate<Long> {
|
||||||
|
|
||||||
public boolean apply(Long jobId) {
|
public boolean apply(Long jobId) {
|
||||||
logger.trace("looking for status on job %s", checkNotNull(jobId, "jobId"));
|
logger.trace("looking for status on job %s", checkNotNull(jobId, "jobId"));
|
||||||
AsyncJob job = refresh(jobId);
|
AsyncJob<?> job = refresh(jobId);
|
||||||
if (job == null)
|
if (job == null)
|
||||||
return false;
|
return false;
|
||||||
logger.trace("%s: looking for job status %s: currently: %s", job.getId(), 1, job.getStatus());
|
logger.trace("%s: looking for job status %s: currently: %s", job.getId(), 1, job.getStatus());
|
||||||
|
if (job.getError() != null)
|
||||||
|
Throwables.propagate(new ExecutionException(String.format("job %s failed with exception %s", job.getId(), job
|
||||||
|
.getError().toString())) {
|
||||||
|
private static final long serialVersionUID = 4371112085613620239L;
|
||||||
|
});
|
||||||
return job.getStatus() > 0;
|
return job.getStatus() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AsyncJob refresh(Long jobId) {
|
private AsyncJob<?> refresh(Long jobId) {
|
||||||
return client.getAsyncJobClient().getAsyncJob(jobId);
|
return client.getAsyncJobClient().getAsyncJob(jobId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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 org.jclouds.cloudstack.domain.Network;
|
||||||
|
import org.jclouds.cloudstack.domain.NetworkService;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class NetworkPredicates {
|
||||||
|
|
||||||
|
public static enum HasFirewallServiceWhichSupportsStaticNAT implements Predicate<Network> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Network arg0) {
|
||||||
|
return Iterables.any(checkNotNull(arg0, "network").getServices(), supportsStaticNAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return supportsStaticNAT.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum HasFirewallServiceWhichSupportsPortForwarding implements Predicate<Network> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Network arg0) {
|
||||||
|
return Iterables.any(checkNotNull(arg0, "network").getServices(), supportsPortForwarding);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return supportsPortForwarding.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum HasLoadBalancerService implements Predicate<Network> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Network arg0) {
|
||||||
|
return Iterables.any(checkNotNull(arg0, "network").getServices(), isLoadBalancerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return isLoadBalancerService.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class NetworkServiceNamed implements Predicate<NetworkService> {
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public NetworkServiceNamed(String name) {
|
||||||
|
this.name = checkNotNull(name, "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(NetworkService input) {
|
||||||
|
return name.equals(checkNotNull(input, "networkService").getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "networkServiceNamed(" + name + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CapabilitiesInclude implements Predicate<NetworkService> {
|
||||||
|
private final String capability;
|
||||||
|
|
||||||
|
public CapabilitiesInclude(String capability) {
|
||||||
|
this.capability = checkNotNull(capability, "capability");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(NetworkService input) {
|
||||||
|
return "true".equals(input.getCapabilities().get(capability));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "capabilitiesInclude(" + capability + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Predicate<NetworkService> supportsStaticNAT = Predicates.and(new NetworkServiceNamed("Firewall"),
|
||||||
|
new CapabilitiesInclude("StaticNat"));
|
||||||
|
|
||||||
|
public static Predicate<NetworkService> supportsPortForwarding = Predicates.and(new NetworkServiceNamed("Firewall"),
|
||||||
|
new CapabilitiesInclude("PortForwarding"));
|
||||||
|
|
||||||
|
public static Predicate<NetworkService> isLoadBalancerService = new NetworkServiceNamed("Lb");
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return true, if the network supports static NAT.
|
||||||
|
*/
|
||||||
|
public static Predicate<Network> supportsStaticNAT() {
|
||||||
|
return HasFirewallServiceWhichSupportsStaticNAT.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return true, if the network supports port forwarding.
|
||||||
|
*/
|
||||||
|
public static Predicate<Network> supportsPortForwarding() {
|
||||||
|
return HasFirewallServiceWhichSupportsPortForwarding.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return true, if the network supports load balancing.
|
||||||
|
*/
|
||||||
|
public static Predicate<Network> hasLoadBalancerService() {
|
||||||
|
return HasLoadBalancerService.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return always returns true.
|
||||||
|
*/
|
||||||
|
public static Predicate<Network> any() {
|
||||||
|
return Predicates.alwaysTrue();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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 org.jclouds.cloudstack.domain.PublicIPAddress;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class PublicIPAddressPredicates {
|
||||||
|
|
||||||
|
public static final class AssociatedWithNetwork implements Predicate<PublicIPAddress> {
|
||||||
|
private final long networkId;
|
||||||
|
|
||||||
|
public AssociatedWithNetwork(long networkId) {
|
||||||
|
this.networkId = networkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(PublicIPAddress input) {
|
||||||
|
return checkNotNull(input, "ipaddress").getAssociatedNetworkId() == networkId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "associatedWithNetwork(" + networkId + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum Available implements Predicate<PublicIPAddress> {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(PublicIPAddress arg0) {
|
||||||
|
return !checkNotNull(arg0, "ipaddress").isSourceNAT() && !arg0.isStaticNAT()
|
||||||
|
&& arg0.getVirtualMachineId() <= 0 && arg0.getState() == PublicIPAddress.State.ALLOCATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "available()";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return true, if the public ip address is not assigned to a VM or NAT rule
|
||||||
|
*/
|
||||||
|
public static Predicate<PublicIPAddress> available() {
|
||||||
|
return Available.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return true, if the public ip address is associated with the specified network
|
||||||
|
*/
|
||||||
|
public static Predicate<PublicIPAddress> associatedWithNetwork(final long networkId) {
|
||||||
|
return new AssociatedWithNetwork(networkId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return always returns true.
|
||||||
|
*/
|
||||||
|
public static Predicate<PublicIPAddress> any() {
|
||||||
|
return Predicates.alwaysTrue();
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ package org.jclouds.cloudstack.features;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import org.jclouds.cloudstack.functions.ReturnVoidOnNotFoundOr404OrUnableToFindAccountOwner;
|
||||||
import org.jclouds.cloudstack.options.AssociateIPAddressOptions;
|
import org.jclouds.cloudstack.options.AssociateIPAddressOptions;
|
||||||
import org.jclouds.cloudstack.options.ListPublicIPAddressesOptions;
|
import org.jclouds.cloudstack.options.ListPublicIPAddressesOptions;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
|
@ -32,7 +33,6 @@ import org.jclouds.http.functions.UnwrapOnlyNestedJsonValueInSet;
|
||||||
import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
|
import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
|
||||||
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||||
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
|
||||||
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ public class AddressAsyncClientTest extends BaseCloudStackAsyncClientTest<Addres
|
||||||
|
|
||||||
assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class);
|
assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class);
|
||||||
assertSaxResponseParserClassEquals(method, null);
|
assertSaxResponseParserClassEquals(method, null);
|
||||||
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class);
|
assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404OrUnableToFindAccountOwner.class);
|
||||||
|
|
||||||
checkFilters(httpRequest);
|
checkFilters(httpRequest);
|
||||||
|
|
||||||
|
|
|
@ -19,28 +19,19 @@
|
||||||
|
|
||||||
package org.jclouds.cloudstack.features;
|
package org.jclouds.cloudstack.features;
|
||||||
|
|
||||||
import static com.google.common.collect.Iterables.find;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.jclouds.cloudstack.CloudStackClient;
|
|
||||||
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
||||||
import org.jclouds.cloudstack.domain.Network;
|
|
||||||
import org.jclouds.cloudstack.domain.NetworkService;
|
|
||||||
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
||||||
import org.jclouds.cloudstack.options.AssociateIPAddressOptions;
|
|
||||||
import org.jclouds.cloudstack.options.ListPublicIPAddressesOptions;
|
import org.jclouds.cloudstack.options.ListPublicIPAddressesOptions;
|
||||||
import org.jclouds.cloudstack.predicates.JobComplete;
|
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
|
||||||
import org.testng.annotations.AfterGroups;
|
import org.testng.annotations.AfterGroups;
|
||||||
import org.testng.annotations.BeforeGroups;
|
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,53 +42,15 @@ import com.google.common.collect.Iterables;
|
||||||
@Test(groups = "live", sequential = true, testName = "PublicIPAddressClientLiveTest")
|
@Test(groups = "live", sequential = true, testName = "PublicIPAddressClientLiveTest")
|
||||||
public class AddressClientLiveTest extends BaseCloudStackClientLiveTest {
|
public class AddressClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
private PublicIPAddress ip = null;
|
private PublicIPAddress ip = null;
|
||||||
private RetryablePredicate<Long> jobComplete;
|
|
||||||
|
|
||||||
@BeforeGroups(groups = "live")
|
|
||||||
public void setupClient() {
|
|
||||||
super.setupClient();
|
|
||||||
jobComplete = new RetryablePredicate<Long>(new JobComplete(client), 600, 5, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAssociateDisassociatePublicIPAddress() throws Exception {
|
public void testAssociateDisassociatePublicIPAddress() throws Exception {
|
||||||
ip = createPublicIPAddress(client, jobComplete);
|
AsyncCreateResponse job = client.getAddressClient().associateIPAddress(
|
||||||
|
Iterables.get(client.getNetworkClient().listNetworks(), 0).getZoneId());
|
||||||
|
checkState(jobComplete.apply(job.getJobId()), "job %d failed to complete", job.getJobId());
|
||||||
|
ip = client.getAsyncJobClient().<PublicIPAddress> getAsyncJob(job.getJobId()).getResult();
|
||||||
checkIP(ip);
|
checkIP(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PublicIPAddress createPublicIPAddress(final CloudStackClient client,
|
|
||||||
RetryablePredicate<Long> jobComplete) {
|
|
||||||
Network network = find(client.getNetworkClient().listNetworks(), new Predicate<Network>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Network arg0) {
|
|
||||||
return Iterables.any(arg0.getServices(), new Predicate<NetworkService>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(NetworkService input) {
|
|
||||||
return input.getName().equals("Firewall") && "true".equals(input.getCapabilities().get("StaticNat"));
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "networkType(ADVANCED)";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return createPublicIPAddressInNetwork(network, client, jobComplete);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PublicIPAddress createPublicIPAddressInNetwork(Network network, CloudStackClient client,
|
|
||||||
RetryablePredicate<Long> jobComplete) {
|
|
||||||
AsyncCreateResponse job = client.getAddressClient().associateIPAddress(network.getZoneId(),
|
|
||||||
AssociateIPAddressOptions.Builder.networkId(network.getId()));
|
|
||||||
assert jobComplete.apply(job.getJobId());
|
|
||||||
PublicIPAddress ip = client.getAsyncJobClient().<PublicIPAddress> getAsyncJob(job.getJobId()).getResult();
|
|
||||||
assertEquals(ip.getZoneId(), network.getZoneId());
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterGroups(groups = "live")
|
@AfterGroups(groups = "live")
|
||||||
protected void tearDown() {
|
protected void tearDown() {
|
||||||
if (ip != null) {
|
if (ip != null) {
|
||||||
|
|
|
@ -34,7 +34,8 @@ import org.testng.annotations.Test;
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", sequential = true, testName = "AsyncJobClientLiveTest")
|
@Test(groups = "live", sequential = true, testName = "AsyncJobClientLiveTest")
|
||||||
public class AsyncJobClientLiveTest extends BaseCloudStackClientLiveTest {
|
public class AsyncJobClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
|
// disabled as it takes too long
|
||||||
|
@Test(enabled = false)
|
||||||
public void testListAsyncJobs() throws Exception {
|
public void testListAsyncJobs() throws Exception {
|
||||||
Set<AsyncJob<?>> response = client.getAsyncJobClient().listAsyncJobs();
|
Set<AsyncJob<?>> response = client.getAsyncJobClient().listAsyncJobs();
|
||||||
assert null != response;
|
assert null != response;
|
||||||
|
@ -48,7 +49,7 @@ public class AsyncJobClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
AsyncJob<?> query = client.getAsyncJobClient().getAsyncJob(asyncJob.getId());
|
AsyncJob<?> query = client.getAsyncJobClient().getAsyncJob(asyncJob.getId());
|
||||||
assertEquals(query.getId(), asyncJob.getId());
|
assertEquals(query.getId(), asyncJob.getId());
|
||||||
|
|
||||||
assert query.getResultType() != null :query;
|
assert query.getResultType() != null : query;
|
||||||
checkJob(query);
|
checkJob(query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.jclouds.Constants;
|
||||||
import org.jclouds.cloudstack.CloudStackAsyncClient;
|
import org.jclouds.cloudstack.CloudStackAsyncClient;
|
||||||
import org.jclouds.cloudstack.CloudStackClient;
|
import org.jclouds.cloudstack.CloudStackClient;
|
||||||
import org.jclouds.cloudstack.domain.VirtualMachine;
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
|
import org.jclouds.cloudstack.functions.ReuseOrAssociateNewPublicIPAddress;
|
||||||
import org.jclouds.cloudstack.predicates.JobComplete;
|
import org.jclouds.cloudstack.predicates.JobComplete;
|
||||||
import org.jclouds.cloudstack.predicates.VirtualMachineDestroyed;
|
import org.jclouds.cloudstack.predicates.VirtualMachineDestroyed;
|
||||||
import org.jclouds.cloudstack.predicates.VirtualMachineRunning;
|
import org.jclouds.cloudstack.predicates.VirtualMachineRunning;
|
||||||
|
@ -48,6 +49,7 @@ import org.testng.annotations.BeforeGroups;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,6 +73,10 @@ public class BaseCloudStackClientLiveTest {
|
||||||
protected SshClient.Factory sshFactory;
|
protected SshClient.Factory sshFactory;
|
||||||
protected String password = "password";
|
protected String password = "password";
|
||||||
|
|
||||||
|
protected Injector injector;
|
||||||
|
|
||||||
|
protected ReuseOrAssociateNewPublicIPAddress reuseOrAssociate;
|
||||||
|
|
||||||
protected void setupCredentials() {
|
protected void setupCredentials() {
|
||||||
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider
|
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider
|
||||||
+ ".identity must be set. ex. apiKey");
|
+ ".identity must be set. ex. apiKey");
|
||||||
|
@ -115,13 +121,20 @@ public class BaseCloudStackClientLiveTest {
|
||||||
overrides);
|
overrides);
|
||||||
|
|
||||||
client = context.getApi();
|
client = context.getApi();
|
||||||
sshFactory = Guice.createInjector(new JschSshClientModule()).getInstance(SshClient.Factory.class);
|
injector = Guice.createInjector(new JschSshClientModule(),new Log4JLoggingModule());
|
||||||
socketTester = new RetryablePredicate<IPSocket>(new InetSocketAddressConnect(), 180, 1, TimeUnit.SECONDS);
|
sshFactory = injector.getInstance(SshClient.Factory.class);
|
||||||
jobComplete = new RetryablePredicate<Long>(new JobComplete(client), 600, 5, TimeUnit.SECONDS);
|
socketTester = new RetryablePredicate<IPSocket>(new InetSocketAddressConnect(), 180, 1, 1, TimeUnit.SECONDS);
|
||||||
virtualMachineRunning = new RetryablePredicate<VirtualMachine>(new VirtualMachineRunning(client), 600, 5,
|
injector.injectMembers(socketTester);
|
||||||
|
jobComplete = new RetryablePredicate<Long>(new JobComplete(client), 600, 5, 5, TimeUnit.SECONDS);
|
||||||
|
injector.injectMembers(jobComplete);
|
||||||
|
virtualMachineRunning = new RetryablePredicate<VirtualMachine>(new VirtualMachineRunning(client), 600, 5, 5,
|
||||||
TimeUnit.SECONDS);
|
TimeUnit.SECONDS);
|
||||||
virtualMachineDestroyed = new RetryablePredicate<VirtualMachine>(new VirtualMachineDestroyed(client), 600, 5,
|
injector.injectMembers(virtualMachineRunning);
|
||||||
|
virtualMachineDestroyed = new RetryablePredicate<VirtualMachine>(new VirtualMachineDestroyed(client), 600, 5, 5,
|
||||||
TimeUnit.SECONDS);
|
TimeUnit.SECONDS);
|
||||||
|
injector.injectMembers(virtualMachineDestroyed);
|
||||||
|
reuseOrAssociate = new ReuseOrAssociateNewPublicIPAddress(client, jobComplete);
|
||||||
|
injector.injectMembers(reuseOrAssociate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterGroups(groups = "live")
|
@AfterGroups(groups = "live")
|
||||||
|
|
|
@ -26,13 +26,12 @@ import static org.testng.Assert.assertTrue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
||||||
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
import org.jclouds.cloudstack.domain.PortForwardingRule;
|
import org.jclouds.cloudstack.domain.PortForwardingRule;
|
||||||
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
||||||
import org.jclouds.cloudstack.domain.VirtualMachine;
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
import org.jclouds.compute.domain.ExecResponse;
|
import org.jclouds.cloudstack.predicates.NetworkPredicates;
|
||||||
import org.jclouds.domain.Credentials;
|
|
||||||
import org.jclouds.net.IPSocket;
|
import org.jclouds.net.IPSocket;
|
||||||
import org.jclouds.ssh.SshClient;
|
|
||||||
import org.testng.annotations.AfterGroups;
|
import org.testng.annotations.AfterGroups;
|
||||||
import org.testng.annotations.BeforeGroups;
|
import org.testng.annotations.BeforeGroups;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -49,38 +48,39 @@ public class FirewallClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
private PublicIPAddress ip = null;
|
private PublicIPAddress ip = null;
|
||||||
private VirtualMachine vm;
|
private VirtualMachine vm;
|
||||||
private PortForwardingRule rule;
|
private PortForwardingRule rule;
|
||||||
|
private Network network;
|
||||||
|
|
||||||
@BeforeGroups(groups = "live")
|
@BeforeGroups(groups = "live")
|
||||||
public void setupClient() {
|
public void setupClient() {
|
||||||
super.setupClient();
|
super.setupClient();
|
||||||
prefix += "rule";
|
prefix += "rule";
|
||||||
ip = AddressClientLiveTest.createPublicIPAddress(client, jobComplete);
|
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.supportsPortForwarding());
|
||||||
vm = VirtualMachineClientLiveTest.createVirtualMachine(client, jobComplete, virtualMachineRunning);
|
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, client, jobComplete,
|
||||||
|
virtualMachineRunning);
|
||||||
if (vm.getPassword() != null)
|
if (vm.getPassword() != null)
|
||||||
password = vm.getPassword();
|
password = vm.getPassword();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreatePortForwardingRule() throws Exception {
|
public void testCreatePortForwardingRule() throws Exception {
|
||||||
AsyncCreateResponse job = client.getFirewallClient().createPortForwardingRuleForVirtualMachine(vm.getId(),
|
|
||||||
ip.getId(), "tcp", 22, 22);
|
while (rule == null) {
|
||||||
assert jobComplete.apply(job.getJobId());
|
ip = reuseOrAssociate.apply(network);
|
||||||
rule = findRuleWithId(job.getId());
|
try {
|
||||||
|
AsyncCreateResponse job = client.getFirewallClient().createPortForwardingRuleForVirtualMachine(vm.getId(),
|
||||||
|
ip.getId(), "tcp", 22, 22);
|
||||||
|
assert jobComplete.apply(job.getJobId());
|
||||||
|
rule = findRuleWithId(job.getId());
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
// very likely an ip conflict, so retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assertEquals(rule.getIPAddressId(), ip.getId());
|
assertEquals(rule.getIPAddressId(), ip.getId());
|
||||||
assertEquals(rule.getVirtualMachineId(), vm.getId());
|
assertEquals(rule.getVirtualMachineId(), vm.getId());
|
||||||
assertEquals(rule.getPublicPort(), 22);
|
assertEquals(rule.getPublicPort(), 22);
|
||||||
assertEquals(rule.getProtocol(), "tcp");
|
assertEquals(rule.getProtocol(), "tcp");
|
||||||
checkRule(rule);
|
checkRule(rule);
|
||||||
IPSocket socket = new IPSocket(ip.getIPAddress(), 22);
|
checkSSH(new IPSocket(ip.getIPAddress(), 22));
|
||||||
socketTester.apply(socket);
|
|
||||||
SshClient client = sshFactory.create(socket, new Credentials("root", password));
|
|
||||||
try {
|
|
||||||
client.connect();
|
|
||||||
ExecResponse exec = client.exec("echo hello");
|
|
||||||
assertEquals(exec.getOutput().trim(), "hello");
|
|
||||||
} finally {
|
|
||||||
if (client != null)
|
|
||||||
client.disconnect();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterGroups(groups = "live")
|
@AfterGroups(groups = "live")
|
||||||
|
@ -88,12 +88,12 @@ public class FirewallClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
if (rule != null) {
|
if (rule != null) {
|
||||||
client.getFirewallClient().deletePortForwardingRule(rule.getId());
|
client.getFirewallClient().deletePortForwardingRule(rule.getId());
|
||||||
}
|
}
|
||||||
|
if (vm != null) {
|
||||||
|
jobComplete.apply(client.getVirtualMachineClient().destroyVirtualMachine(vm.getId()));
|
||||||
|
}
|
||||||
if (ip != null) {
|
if (ip != null) {
|
||||||
client.getAddressClient().disassociateIPAddress(ip.getId());
|
client.getAddressClient().disassociateIPAddress(ip.getId());
|
||||||
}
|
}
|
||||||
if (vm != null) {
|
|
||||||
assert jobComplete.apply(client.getVirtualMachineClient().destroyVirtualMachine(vm.getId()));
|
|
||||||
}
|
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,17 +23,21 @@ import static com.google.common.collect.Iterables.find;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.jclouds.cloudstack.domain.LoadBalancerRule;
|
import org.jclouds.cloudstack.domain.LoadBalancerRule;
|
||||||
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
||||||
import org.jclouds.cloudstack.domain.VirtualMachine;
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
import org.jclouds.cloudstack.domain.LoadBalancerRule.Algorithm;
|
import org.jclouds.cloudstack.domain.LoadBalancerRule.Algorithm;
|
||||||
import org.jclouds.cloudstack.domain.LoadBalancerRule.State;
|
import org.jclouds.cloudstack.domain.LoadBalancerRule.State;
|
||||||
import org.jclouds.cloudstack.predicates.LoadBalancerRuleActive;
|
import org.jclouds.cloudstack.predicates.LoadBalancerRuleActive;
|
||||||
|
import org.jclouds.cloudstack.predicates.NetworkPredicates;
|
||||||
import org.jclouds.net.IPSocket;
|
import org.jclouds.net.IPSocket;
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
import org.jclouds.ssh.SshException;
|
||||||
import org.testng.annotations.AfterGroups;
|
import org.testng.annotations.AfterGroups;
|
||||||
import org.testng.annotations.BeforeGroups;
|
import org.testng.annotations.BeforeGroups;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -51,22 +55,32 @@ public class LoadBalancerClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
private VirtualMachine vm;
|
private VirtualMachine vm;
|
||||||
private LoadBalancerRule rule;
|
private LoadBalancerRule rule;
|
||||||
private RetryablePredicate<LoadBalancerRule> loadBalancerRuleActive;
|
private RetryablePredicate<LoadBalancerRule> loadBalancerRuleActive;
|
||||||
|
private Network network;
|
||||||
|
|
||||||
@BeforeGroups(groups = "live")
|
@BeforeGroups(groups = "live")
|
||||||
public void setupClient() {
|
public void setupClient() {
|
||||||
super.setupClient();
|
super.setupClient();
|
||||||
loadBalancerRuleActive = new RetryablePredicate<LoadBalancerRule>(new LoadBalancerRuleActive(client), 600, 5,
|
|
||||||
|
loadBalancerRuleActive = new RetryablePredicate<LoadBalancerRule>(new LoadBalancerRuleActive(client), 60, 1, 1,
|
||||||
TimeUnit.SECONDS);
|
TimeUnit.SECONDS);
|
||||||
prefix += "rule";
|
prefix += "rule";
|
||||||
ip = AddressClientLiveTest.createPublicIPAddress(client, jobComplete);
|
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.hasLoadBalancerService());
|
||||||
vm = VirtualMachineClientLiveTest.createVirtualMachine(client, jobComplete, virtualMachineRunning);
|
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, client, jobComplete,
|
||||||
|
virtualMachineRunning);
|
||||||
if (vm.getPassword() != null)
|
if (vm.getPassword() != null)
|
||||||
password = vm.getPassword();
|
password = vm.getPassword();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreateLoadBalancerRule() throws Exception {
|
public void testCreateLoadBalancerRule() throws Exception {
|
||||||
rule = client.getLoadBalancerClient().createLoadBalancerRuleForPublicIP(ip.getId(), Algorithm.LEASTCONN, prefix,
|
while (rule == null) {
|
||||||
22, 22);
|
ip = reuseOrAssociate.apply(network);
|
||||||
|
try {
|
||||||
|
rule = client.getLoadBalancerClient().createLoadBalancerRuleForPublicIP(ip.getId(), Algorithm.LEASTCONN,
|
||||||
|
prefix, 22, 22);
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
// very likely an ip conflict, so retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
assert (rule.getPublicIPId() == ip.getId()) : rule;
|
assert (rule.getPublicIPId() == ip.getId()) : rule;
|
||||||
assertEquals(rule.getPublicPort(), 22);
|
assertEquals(rule.getPublicPort(), 22);
|
||||||
assertEquals(rule.getPrivatePort(), 22);
|
assertEquals(rule.getPrivatePort(), 22);
|
||||||
|
@ -84,18 +98,33 @@ public class LoadBalancerClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
vm.getId()));
|
vm.getId()));
|
||||||
assertEquals(client.getLoadBalancerClient().listVirtualMachinesAssignedToLoadBalancerRule(rule.getId()).size(), 1);
|
assertEquals(client.getLoadBalancerClient().listVirtualMachinesAssignedToLoadBalancerRule(rule.getId()).size(), 1);
|
||||||
assert loadBalancerRuleActive.apply(rule) : rule;
|
assert loadBalancerRuleActive.apply(rule) : rule;
|
||||||
IPSocket socket = new IPSocket(ip.getIPAddress(), 22);
|
loopAndCheckSSH();
|
||||||
assert socketTester.apply(socket) : vm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testAssignToLoadBalancerRule")
|
// note that when in LB mode, there's a chance you'll have a connection failure
|
||||||
|
private void loopAndCheckSSH() throws IOException {
|
||||||
|
for (int i = 0; i < 5; i++) {// retry loop TODO replace with predicate.
|
||||||
|
try {
|
||||||
|
checkSSH(new IPSocket(ip.getIPAddress(), 22));
|
||||||
|
return;
|
||||||
|
} catch (SshException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
try {
|
||||||
|
Thread.sleep(10 * 1000);
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "testAssignToLoadBalancerRule", expectedExceptions = SshException.class)
|
||||||
public void testRemoveFromLoadBalancerRule() throws Exception {
|
public void testRemoveFromLoadBalancerRule() throws Exception {
|
||||||
assert jobComplete.apply(client.getLoadBalancerClient().removeVirtualMachinesFromLoadBalancerRule(rule.getId(),
|
assert jobComplete.apply(client.getLoadBalancerClient().removeVirtualMachinesFromLoadBalancerRule(rule.getId(),
|
||||||
vm.getId()));
|
vm.getId()));
|
||||||
assertEquals(client.getLoadBalancerClient().listVirtualMachinesAssignedToLoadBalancerRule(rule.getId()).size(), 0);
|
assertEquals(client.getLoadBalancerClient().listVirtualMachinesAssignedToLoadBalancerRule(rule.getId()).size(), 0);
|
||||||
assertEquals(rule.getState(), State.ADD);
|
assertEquals(rule.getState(), State.ADD);
|
||||||
IPSocket socket = new IPSocket(ip.getIPAddress(), 22);
|
checkSSH(new IPSocket(ip.getIPAddress(), 22));
|
||||||
assert !socketTester.apply(socket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterGroups(groups = "live")
|
@AfterGroups(groups = "live")
|
||||||
|
@ -116,7 +145,7 @@ public class LoadBalancerClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
Set<LoadBalancerRule> response = client.getLoadBalancerClient().listLoadBalancerRules();
|
Set<LoadBalancerRule> response = client.getLoadBalancerClient().listLoadBalancerRules();
|
||||||
assert null != response;
|
assert null != response;
|
||||||
assertTrue(response.size() >= 0);
|
assertTrue(response.size() >= 0);
|
||||||
for (final LoadBalancerRule rule : response) {
|
for (LoadBalancerRule rule : response) {
|
||||||
LoadBalancerRule newDetails = findRuleWithId(rule.getId());
|
LoadBalancerRule newDetails = findRuleWithId(rule.getId());
|
||||||
assertEquals(rule.getId(), newDetails.getId());
|
assertEquals(rule.getId(), newDetails.getId());
|
||||||
checkRule(rule);
|
checkRule(rule);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.jclouds.cloudstack.features;
|
package org.jclouds.cloudstack.features;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.find;
|
||||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
@ -27,9 +28,11 @@ import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
||||||
import org.jclouds.cloudstack.domain.IPForwardingRule;
|
import org.jclouds.cloudstack.domain.IPForwardingRule;
|
||||||
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
||||||
import org.jclouds.cloudstack.domain.VirtualMachine;
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
import org.jclouds.cloudstack.options.ListIPForwardingRulesOptions;
|
import org.jclouds.cloudstack.options.ListIPForwardingRulesOptions;
|
||||||
|
import org.jclouds.cloudstack.predicates.NetworkPredicates;
|
||||||
import org.jclouds.compute.domain.ExecResponse;
|
import org.jclouds.compute.domain.ExecResponse;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.net.IPSocket;
|
import org.jclouds.net.IPSocket;
|
||||||
|
@ -48,23 +51,34 @@ public class NATClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
private PublicIPAddress ip = null;
|
private PublicIPAddress ip = null;
|
||||||
private VirtualMachine vm;
|
private VirtualMachine vm;
|
||||||
private IPForwardingRule rule;
|
private IPForwardingRule rule;
|
||||||
|
private Network network;
|
||||||
|
|
||||||
@BeforeGroups(groups = "live")
|
@BeforeGroups(groups = "live")
|
||||||
public void setupClient() {
|
public void setupClient() {
|
||||||
super.setupClient();
|
super.setupClient();
|
||||||
prefix += "nat";
|
prefix += "nat";
|
||||||
ip = AddressClientLiveTest.createPublicIPAddress(client, jobComplete);
|
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.supportsStaticNAT());
|
||||||
vm = VirtualMachineClientLiveTest.createVirtualMachine(client, jobComplete, virtualMachineRunning);
|
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, client, jobComplete,
|
||||||
|
virtualMachineRunning);
|
||||||
if (vm.getPassword() != null)
|
if (vm.getPassword() != null)
|
||||||
password = vm.getPassword();
|
password = vm.getPassword();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreateIPForwardingRule() throws Exception {
|
public void testCreateIPForwardingRule() throws Exception {
|
||||||
|
for (ip = reuseOrAssociate.apply(network); (!ip.isStaticNAT() || ip.getVirtualMachineId() != vm.getId()); ip = reuseOrAssociate
|
||||||
assert !ip.isStaticNAT();
|
.apply(network)) {
|
||||||
client.getNATClient().enableStaticNATForVirtualMachine(vm.getId(), ip.getId());
|
// check to see if someone already grabbed this ip
|
||||||
ip = client.getAddressClient().getPublicIPAddress(ip.getId());
|
if (ip.getVirtualMachineId() > 0 && ip.getVirtualMachineId() != vm.getId())
|
||||||
assert ip.isStaticNAT();
|
continue;
|
||||||
|
try {
|
||||||
|
client.getNATClient().enableStaticNATForVirtualMachine(vm.getId(), ip.getId());
|
||||||
|
ip = client.getAddressClient().getPublicIPAddress(ip.getId());
|
||||||
|
if (ip.isStaticNAT() && ip.getVirtualMachineId() == vm.getId())
|
||||||
|
break;
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
// very likely an ip conflict, so retry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AsyncCreateResponse job = client.getNATClient().createIPForwardingRule(ip.getId(), "tcp", 22);
|
AsyncCreateResponse job = client.getNATClient().createIPForwardingRule(ip.getId(), "tcp", 22);
|
||||||
assert jobComplete.apply(job.getJobId());
|
assert jobComplete.apply(job.getJobId());
|
||||||
|
@ -76,7 +90,7 @@ public class NATClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
checkRule(rule);
|
checkRule(rule);
|
||||||
IPSocket socket = new IPSocket(ip.getIPAddress(), 22);
|
IPSocket socket = new IPSocket(ip.getIPAddress(), 22);
|
||||||
socketTester.apply(socket);
|
socketTester.apply(socket);
|
||||||
SshClient client = sshFactory.create(socket, new Credentials("root",password));
|
SshClient client = sshFactory.create(socket, new Credentials("root", password));
|
||||||
try {
|
try {
|
||||||
client.connect();
|
client.connect();
|
||||||
ExecResponse exec = client.exec("echo hello");
|
ExecResponse exec = client.exec("echo hello");
|
||||||
|
@ -92,22 +106,24 @@ public class NATClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
if (rule != null) {
|
if (rule != null) {
|
||||||
client.getNATClient().deleteIPForwardingRule(rule.getId());
|
client.getNATClient().deleteIPForwardingRule(rule.getId());
|
||||||
}
|
}
|
||||||
|
if (vm != null) {
|
||||||
|
jobComplete.apply(client.getVirtualMachineClient().destroyVirtualMachine(vm.getId()));
|
||||||
|
}
|
||||||
if (ip != null) {
|
if (ip != null) {
|
||||||
client.getAddressClient().disassociateIPAddress(ip.getId());
|
client.getAddressClient().disassociateIPAddress(ip.getId());
|
||||||
}
|
}
|
||||||
if (vm != null) {
|
|
||||||
assert jobComplete.apply(client.getVirtualMachineClient().destroyVirtualMachine(vm.getId()));
|
|
||||||
}
|
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(enabled = false)
|
||||||
|
// takes too long
|
||||||
public void testListIPForwardingRules() throws Exception {
|
public void testListIPForwardingRules() throws Exception {
|
||||||
Set<IPForwardingRule> response = client.getNATClient().listIPForwardingRules();
|
Set<IPForwardingRule> response = client.getNATClient().listIPForwardingRules();
|
||||||
assert null != response;
|
assert null != response;
|
||||||
assertTrue(response.size() >= 0);
|
assertTrue(response.size() >= 0);
|
||||||
for (IPForwardingRule rule : response) {
|
for (IPForwardingRule rule : response) {
|
||||||
IPForwardingRule newDetails = getOnlyElement(client.getNATClient().listIPForwardingRules(
|
IPForwardingRule newDetails = getOnlyElement(client.getNATClient().listIPForwardingRules(
|
||||||
ListIPForwardingRulesOptions.Builder.id(rule.getId())));
|
ListIPForwardingRulesOptions.Builder.id(rule.getId())));
|
||||||
assertEquals(rule.getId(), newDetails.getId());
|
assertEquals(rule.getId(), newDetails.getId());
|
||||||
checkRule(rule);
|
checkRule(rule);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,11 @@ import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import org.jclouds.cloudstack.CloudStackClient;
|
import org.jclouds.cloudstack.CloudStackClient;
|
||||||
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
||||||
|
import org.jclouds.cloudstack.domain.AsyncJob;
|
||||||
import org.jclouds.cloudstack.domain.GuestIPType;
|
import org.jclouds.cloudstack.domain.GuestIPType;
|
||||||
import org.jclouds.cloudstack.domain.NIC;
|
import org.jclouds.cloudstack.domain.NIC;
|
||||||
import org.jclouds.cloudstack.domain.Network;
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
|
@ -49,6 +51,7 @@ import org.testng.annotations.AfterGroups;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.ComparisonChain;
|
import com.google.common.collect.ComparisonChain;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Ordering;
|
import com.google.common.collect.Ordering;
|
||||||
|
@ -140,7 +143,13 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
AsyncCreateResponse job = client.getVirtualMachineClient().deployVirtualMachine(serviceOfferingId, templateId,
|
AsyncCreateResponse job = client.getVirtualMachineClient().deployVirtualMachine(serviceOfferingId, templateId,
|
||||||
zoneId, options);
|
zoneId, options);
|
||||||
assert jobComplete.apply(job.getJobId());
|
assert jobComplete.apply(job.getJobId());
|
||||||
VirtualMachine vm = client.getAsyncJobClient().<VirtualMachine> getAsyncJob(job.getJobId()).getResult();
|
AsyncJob<VirtualMachine> jobWithResult = client.getAsyncJobClient().<VirtualMachine> getAsyncJob(job.getJobId());
|
||||||
|
if (jobWithResult.getError() != null)
|
||||||
|
Throwables.propagate(new ExecutionException(String.format("job %s failed with exception %s", job.getId(),
|
||||||
|
jobWithResult.getError().toString())) {
|
||||||
|
private static final long serialVersionUID = 4371112085613620239L;
|
||||||
|
});
|
||||||
|
VirtualMachine vm = jobWithResult.getResult();
|
||||||
if (vm.isPasswordEnabled()) {
|
if (vm.isPasswordEnabled()) {
|
||||||
assert vm.getPassword() != null : vm;
|
assert vm.getPassword() != null : vm;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.easymock.EasyMock.expect;
|
||||||
|
import static org.easymock.classextension.EasyMock.createMock;
|
||||||
|
import static org.easymock.classextension.EasyMock.replay;
|
||||||
|
import static org.easymock.classextension.EasyMock.verify;
|
||||||
|
import static org.jclouds.cloudstack.options.AssociateIPAddressOptions.Builder.networkId;
|
||||||
|
import static org.jclouds.cloudstack.options.ListPublicIPAddressesOptions.Builder.allocatedOnly;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.jclouds.cloudstack.CloudStackClient;
|
||||||
|
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
||||||
|
import org.jclouds.cloudstack.domain.AsyncJob;
|
||||||
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
|
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
||||||
|
import org.jclouds.cloudstack.features.AddressClient;
|
||||||
|
import org.jclouds.cloudstack.features.AsyncJobClient;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit")
|
||||||
|
public class ReuseOrAssociateNewPublicIPAddressTest {
|
||||||
|
long networkId = 99l;
|
||||||
|
long zoneId = 100l;
|
||||||
|
// note that it is associated network, not networkId
|
||||||
|
PublicIPAddress address = PublicIPAddress.builder().id(200).state(PublicIPAddress.State.ALLOCATED)
|
||||||
|
.associatedNetworkId(networkId).zoneId(zoneId).build();
|
||||||
|
|
||||||
|
public void testReuseWorks() throws SecurityException, NoSuchMethodException {
|
||||||
|
|
||||||
|
// create mocks
|
||||||
|
CloudStackClient client = createMock(CloudStackClient.class);
|
||||||
|
Predicate<Long> jobComplete = Predicates.alwaysTrue();
|
||||||
|
AddressClient addressClient = createMock(AddressClient.class);
|
||||||
|
expect(client.getAddressClient()).andReturn(addressClient).atLeastOnce();
|
||||||
|
|
||||||
|
// an address is available
|
||||||
|
expect(addressClient.listPublicIPAddresses(allocatedOnly(true).networkId(networkId))).andReturn(
|
||||||
|
ImmutableSet.<PublicIPAddress> of(address));
|
||||||
|
|
||||||
|
// replay mocks
|
||||||
|
replay(client);
|
||||||
|
replay(addressClient);
|
||||||
|
|
||||||
|
// run
|
||||||
|
assertEquals(new ReuseOrAssociateNewPublicIPAddress(client, jobComplete).apply(Network.builder().id(networkId)
|
||||||
|
.zoneId(zoneId).build()), address);
|
||||||
|
|
||||||
|
// verify mocks
|
||||||
|
verify(client);
|
||||||
|
verify(addressClient);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAssociateWorks() throws SecurityException, NoSuchMethodException {
|
||||||
|
long networkId = 99l;
|
||||||
|
long zoneId = 100l;
|
||||||
|
|
||||||
|
// create mocks
|
||||||
|
CloudStackClient client = createMock(CloudStackClient.class);
|
||||||
|
Predicate<Long> jobComplete = Predicates.alwaysTrue();
|
||||||
|
AddressClient addressClient = createMock(AddressClient.class);
|
||||||
|
expect(client.getAddressClient()).andReturn(addressClient).atLeastOnce();
|
||||||
|
|
||||||
|
// no ip addresses available
|
||||||
|
expect(addressClient.listPublicIPAddresses(allocatedOnly(true).networkId(networkId))).andReturn(
|
||||||
|
ImmutableSet.<PublicIPAddress> of());
|
||||||
|
|
||||||
|
AsyncCreateResponse job = new AsyncCreateResponse(1, 2);
|
||||||
|
// make sure we created the job relating to a new ip
|
||||||
|
expect(addressClient.associateIPAddress(zoneId, networkId(networkId))).andReturn(job);
|
||||||
|
|
||||||
|
AsyncJobClient jobClient = createMock(AsyncJobClient.class);
|
||||||
|
expect(client.getAsyncJobClient()).andReturn(jobClient).atLeastOnce();
|
||||||
|
|
||||||
|
expect(jobClient.getAsyncJob(2)).andReturn(AsyncJob.builder().result(address).build());
|
||||||
|
|
||||||
|
// replay mocks
|
||||||
|
replay(client);
|
||||||
|
replay(addressClient);
|
||||||
|
replay(jobClient);
|
||||||
|
|
||||||
|
// run
|
||||||
|
assertEquals(new ReuseOrAssociateNewPublicIPAddress(client, jobComplete).apply(Network.builder().id(networkId)
|
||||||
|
.zoneId(zoneId).build()), address);
|
||||||
|
|
||||||
|
// verify mocks
|
||||||
|
verify(client);
|
||||||
|
verify(addressClient);
|
||||||
|
verify(jobClient);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expectedExceptions = IllegalStateException.class)
|
||||||
|
public void testJobDoesntCompleteThrowsIllegalStateException() throws SecurityException, NoSuchMethodException {
|
||||||
|
long networkId = 99l;
|
||||||
|
long zoneId = 100l;
|
||||||
|
|
||||||
|
// create mocks
|
||||||
|
CloudStackClient client = createMock(CloudStackClient.class);
|
||||||
|
Predicate<Long> jobComplete = Predicates.alwaysFalse();
|
||||||
|
AddressClient addressClient = createMock(AddressClient.class);
|
||||||
|
expect(client.getAddressClient()).andReturn(addressClient).atLeastOnce();
|
||||||
|
|
||||||
|
// no ip addresses available
|
||||||
|
expect(addressClient.listPublicIPAddresses(allocatedOnly(true).networkId(networkId))).andReturn(
|
||||||
|
ImmutableSet.<PublicIPAddress> of());
|
||||||
|
|
||||||
|
AsyncCreateResponse job = new AsyncCreateResponse(1, 2);
|
||||||
|
// make sure we created the job relating to a new ip
|
||||||
|
expect(addressClient.associateIPAddress(zoneId, networkId(networkId))).andReturn(job);
|
||||||
|
|
||||||
|
// the alwaysfalse predicate above should blow up with IllegalStateException
|
||||||
|
|
||||||
|
// replay mocks
|
||||||
|
replay(client);
|
||||||
|
replay(addressClient);
|
||||||
|
|
||||||
|
// run
|
||||||
|
new ReuseOrAssociateNewPublicIPAddress(client, jobComplete).apply(Network.builder().id(networkId).zoneId(zoneId)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
// verify mocks
|
||||||
|
verify(client);
|
||||||
|
verify(addressClient);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.predicates;
|
||||||
|
|
||||||
|
import static org.jclouds.cloudstack.predicates.NetworkPredicates.hasLoadBalancerService;
|
||||||
|
import static org.jclouds.cloudstack.predicates.NetworkPredicates.supportsPortForwarding;
|
||||||
|
import static org.jclouds.cloudstack.predicates.NetworkPredicates.supportsStaticNAT;
|
||||||
|
|
||||||
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
|
import org.jclouds.cloudstack.domain.NetworkService;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit")
|
||||||
|
public class NetworkPredicatesTest {
|
||||||
|
|
||||||
|
public void testHasLoadBalancerService() {
|
||||||
|
Network network = Network.builder().id(204).services(ImmutableSet.of(new NetworkService("Lb"))).build();
|
||||||
|
|
||||||
|
assert hasLoadBalancerService().apply(network);
|
||||||
|
assert !supportsStaticNAT().apply(network);
|
||||||
|
assert !supportsPortForwarding().apply(network);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSupportsStaticNATFindsWhenFirewallHasStaticNatFeature() {
|
||||||
|
Network network = Network.builder().id(204).services(
|
||||||
|
ImmutableSet.of(new NetworkService("Firewall", ImmutableMap.<String, String> of("StaticNat", "true"))))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert !hasLoadBalancerService().apply(network);
|
||||||
|
assert supportsStaticNAT().apply(network);
|
||||||
|
assert !supportsPortForwarding().apply(network);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNoSupport() {
|
||||||
|
Network network = Network.builder().id(204).services(
|
||||||
|
ImmutableSet.of(new NetworkService("Firewall", ImmutableMap.<String, String> of()))).build();
|
||||||
|
|
||||||
|
assert !hasLoadBalancerService().apply(network);
|
||||||
|
assert !supportsStaticNAT().apply(network);
|
||||||
|
assert !supportsPortForwarding().apply(network);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSupportsPortForwardingFindsWhenFirewallHasPortForwardingFeature() {
|
||||||
|
Network network = Network.builder().id(204).services(
|
||||||
|
ImmutableSet.of(new NetworkService("Firewall", ImmutableMap
|
||||||
|
.<String, String> of("PortForwarding", "true")))).build();
|
||||||
|
|
||||||
|
assert !hasLoadBalancerService().apply(network);
|
||||||
|
assert !supportsStaticNAT().apply(network);
|
||||||
|
assert supportsPortForwarding().apply(network);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSupportsPortForwardingAndStaticNATWhenFirewallHasFeatures() {
|
||||||
|
Network network = Network.builder().id(204).services(
|
||||||
|
ImmutableSet.of(new NetworkService("Firewall", ImmutableMap.<String, String> of("StaticNat", "true",
|
||||||
|
"PortForwarding", "true")))).build();
|
||||||
|
|
||||||
|
assert Predicates.and(supportsPortForwarding(), supportsStaticNAT()).apply(network);
|
||||||
|
assert !hasLoadBalancerService().apply(network);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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 org.jclouds.cloudstack.predicates.PublicIPAddressPredicates.available;
|
||||||
|
|
||||||
|
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit")
|
||||||
|
public class PublicIPAddressPredicatesTest {
|
||||||
|
|
||||||
|
public void testIsAvailableWhenAllocated() {
|
||||||
|
PublicIPAddress address = PublicIPAddress.builder().state(PublicIPAddress.State.ALLOCATED).id(204).build();
|
||||||
|
|
||||||
|
assert available().apply(address);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsNotAvailableWhenNotAllocated() {
|
||||||
|
PublicIPAddress address = PublicIPAddress.builder().state(PublicIPAddress.State.ALLOCATING).id(204).build();
|
||||||
|
|
||||||
|
assert !available().apply(address);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsNotAvailableWhenAssignedToVM() {
|
||||||
|
PublicIPAddress address = PublicIPAddress.builder().state(PublicIPAddress.State.ALLOCATED).virtualMachineId(1)
|
||||||
|
.id(204).build();
|
||||||
|
|
||||||
|
assert !available().apply(address);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsNotAvailableWhenSourceNAT() {
|
||||||
|
PublicIPAddress address = PublicIPAddress.builder().state(PublicIPAddress.State.ALLOCATED).isSourceNAT(true).id(
|
||||||
|
204).build();
|
||||||
|
|
||||||
|
assert !available().apply(address);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIsNotAvailableWhenStaticNAT() {
|
||||||
|
PublicIPAddress address = PublicIPAddress.builder().state(PublicIPAddress.State.ALLOCATED).isStaticNAT(true).id(
|
||||||
|
204).build();
|
||||||
|
|
||||||
|
assert !available().apply(address);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -146,7 +146,7 @@
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
<category name="jclouds.ssh">
|
<category name="jclouds.ssh">
|
||||||
<priority value="DEBUG" />
|
<priority value="TRACE" />
|
||||||
<appender-ref ref="ASYNCSSH" />
|
<appender-ref ref="ASYNCSSH" />
|
||||||
</category>
|
</category>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue