mirror of https://github.com/apache/jclouds.git
added cloudstack support to launch servers in a network with ip forwarding
This commit is contained in:
parent
4329129c25
commit
be7cf42f04
|
@ -34,6 +34,8 @@ public class CloudStackPropertiesBuilder extends PropertiesBuilder {
|
||||||
protected Properties defaultProperties() {
|
protected Properties defaultProperties() {
|
||||||
Properties properties = super.defaultProperties();
|
Properties properties = super.defaultProperties();
|
||||||
properties.setProperty(PROPERTY_API_VERSION, "2.2");
|
properties.setProperty(PROPERTY_API_VERSION, "2.2");
|
||||||
|
properties.setProperty("jclouds.ssh.max-retries", "7");
|
||||||
|
properties.setProperty("jclouds.ssh.retry-auth", "true");
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,13 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.cloudstack.compute.config;
|
package org.jclouds.cloudstack.compute.config;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@ -35,13 +37,19 @@ import org.jclouds.cloudstack.compute.functions.VirtualMachineToNodeMetadata;
|
||||||
import org.jclouds.cloudstack.compute.functions.ZoneToLocation;
|
import org.jclouds.cloudstack.compute.functions.ZoneToLocation;
|
||||||
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
|
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
|
||||||
import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter;
|
import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter;
|
||||||
|
import org.jclouds.cloudstack.domain.IPForwardingRule;
|
||||||
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
import org.jclouds.cloudstack.domain.OSType;
|
import org.jclouds.cloudstack.domain.OSType;
|
||||||
import org.jclouds.cloudstack.domain.ServiceOffering;
|
import org.jclouds.cloudstack.domain.ServiceOffering;
|
||||||
import org.jclouds.cloudstack.domain.Template;
|
import org.jclouds.cloudstack.domain.Template;
|
||||||
|
import org.jclouds.cloudstack.domain.User;
|
||||||
import org.jclouds.cloudstack.domain.VirtualMachine;
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
import org.jclouds.cloudstack.domain.Zone;
|
import org.jclouds.cloudstack.domain.Zone;
|
||||||
import org.jclouds.cloudstack.features.GuestOSClient;
|
import org.jclouds.cloudstack.features.GuestOSClient;
|
||||||
|
import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork;
|
||||||
import org.jclouds.cloudstack.predicates.JobComplete;
|
import org.jclouds.cloudstack.predicates.JobComplete;
|
||||||
|
import org.jclouds.cloudstack.suppliers.GetCurrentUser;
|
||||||
|
import org.jclouds.cloudstack.suppliers.NetworksForCurrentUser;
|
||||||
import org.jclouds.collect.Memoized;
|
import org.jclouds.collect.Memoized;
|
||||||
import org.jclouds.compute.ComputeServiceAdapter;
|
import org.jclouds.compute.ComputeServiceAdapter;
|
||||||
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
|
import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
|
||||||
|
@ -51,14 +59,19 @@ import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
|
import org.jclouds.location.suppliers.OnlyLocationOrFirstZone;
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
|
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -90,6 +103,9 @@ public class CloudStackComputeServiceContextModule
|
||||||
bind(TemplateOptions.class).to(CloudStackTemplateOptions.class);
|
bind(TemplateOptions.class).to(CloudStackTemplateOptions.class);
|
||||||
bind(new TypeLiteral<Function<Template, OperatingSystem>>() {
|
bind(new TypeLiteral<Function<Template, OperatingSystem>>() {
|
||||||
}).to(TemplateToOperatingSystem.class);
|
}).to(TemplateToOperatingSystem.class);
|
||||||
|
install(new FactoryModuleBuilder().build(StaticNATVirtualMachineInNetwork.Factory.class));
|
||||||
|
bind(new TypeLiteral<CacheLoader<Long, IPForwardingRule>>() {
|
||||||
|
}).to(GetIPForwardingRuleByVirtualMachine.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -128,10 +144,58 @@ public class CloudStackComputeServiceContextModule
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@Memoized
|
||||||
|
public Supplier<Map<Long, Network>> listNetworks(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
|
||||||
|
final NetworksForCurrentUser networksForCurrentUser) {
|
||||||
|
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Map<Long, Network>>(authException,
|
||||||
|
seconds, networksForCurrentUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@Memoized
|
||||||
|
public Supplier<User> getCurrentUser(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
|
||||||
|
final GetCurrentUser getCurrentUser) {
|
||||||
|
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<User>(authException, seconds,
|
||||||
|
getCurrentUser);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Predicate<Long> jobComplete(JobComplete jobComplete) {
|
protected Predicate<Long> jobComplete(JobComplete jobComplete) {
|
||||||
// TODO: parameterize
|
// TODO: parameterize
|
||||||
return new RetryablePredicate<Long>(jobComplete, 1200, 1, 5, TimeUnit.SECONDS);
|
return new RetryablePredicate<Long>(jobComplete, 1200, 1, 5, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Cache<Long, IPForwardingRule> getIPForwardingRuleByVirtualMachine(
|
||||||
|
CacheLoader<Long, IPForwardingRule> getIPForwardingRule) {
|
||||||
|
return CacheBuilder.newBuilder().build(getIPForwardingRule);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static class GetIPForwardingRuleByVirtualMachine extends CacheLoader<Long, IPForwardingRule> {
|
||||||
|
private final CloudStackClient client;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public GetIPForwardingRuleByVirtualMachine(CloudStackClient client) {
|
||||||
|
this.client = checkNotNull(client, "client");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws ResourceNotFoundException
|
||||||
|
* when there is no ip forwarding rule available for the VM
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public IPForwardingRule load(Long input) {
|
||||||
|
IPForwardingRule rule = client.getNATClient().getIPForwardingRuleForVirtualMachine(input);
|
||||||
|
if (rule == null)
|
||||||
|
throw new ResourceNotFoundException("no ip forwarding rule for: " + input);
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -27,6 +27,7 @@ import java.util.Set;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.cloudstack.domain.IPForwardingRule;
|
||||||
import org.jclouds.cloudstack.domain.VirtualMachine;
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
import org.jclouds.collect.FindResourceInSet;
|
import org.jclouds.collect.FindResourceInSet;
|
||||||
import org.jclouds.collect.Memoized;
|
import org.jclouds.collect.Memoized;
|
||||||
|
@ -37,12 +38,17 @@ import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||||
import org.jclouds.compute.domain.NodeState;
|
import org.jclouds.compute.domain.NodeState;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
import org.jclouds.util.InetAddresses2;
|
import org.jclouds.util.InetAddresses2;
|
||||||
|
import org.jclouds.util.Throwables2;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -66,16 +72,20 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
|
||||||
private final FindLocationForVirtualMachine findLocationForVirtualMachine;
|
private final FindLocationForVirtualMachine findLocationForVirtualMachine;
|
||||||
private final FindHardwareForVirtualMachine findHardwareForVirtualMachine;
|
private final FindHardwareForVirtualMachine findHardwareForVirtualMachine;
|
||||||
private final FindImageForVirtualMachine findImageForVirtualMachine;
|
private final FindImageForVirtualMachine findImageForVirtualMachine;
|
||||||
|
private final Cache<Long, IPForwardingRule> getIPForwardingRuleByVirtualMachine;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
VirtualMachineToNodeMetadata(Map<String, Credentials> credentialStore,
|
VirtualMachineToNodeMetadata(Map<String, Credentials> credentialStore,
|
||||||
FindLocationForVirtualMachine findLocationForVirtualMachine,
|
FindLocationForVirtualMachine findLocationForVirtualMachine,
|
||||||
FindHardwareForVirtualMachine findHardwareForVirtualMachine,
|
FindHardwareForVirtualMachine findHardwareForVirtualMachine,
|
||||||
FindImageForVirtualMachine findImageForVirtualMachine) {
|
FindImageForVirtualMachine findImageForVirtualMachine,
|
||||||
|
Cache<Long, IPForwardingRule> getIPForwardingRuleByVirtualMachine) {
|
||||||
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
|
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
|
||||||
this.findLocationForVirtualMachine = checkNotNull(findLocationForVirtualMachine, "findLocationForVirtualMachine");
|
this.findLocationForVirtualMachine = checkNotNull(findLocationForVirtualMachine, "findLocationForVirtualMachine");
|
||||||
this.findHardwareForVirtualMachine = checkNotNull(findHardwareForVirtualMachine, "findHardwareForVirtualMachine");
|
this.findHardwareForVirtualMachine = checkNotNull(findHardwareForVirtualMachine, "findHardwareForVirtualMachine");
|
||||||
this.findImageForVirtualMachine = checkNotNull(findImageForVirtualMachine, "findImageForVirtualMachine");
|
this.findImageForVirtualMachine = checkNotNull(findImageForVirtualMachine, "findImageForVirtualMachine");
|
||||||
|
this.getIPForwardingRuleByVirtualMachine = checkNotNull(getIPForwardingRuleByVirtualMachine,
|
||||||
|
"getIPForwardingRuleByVirtualMachine");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -108,6 +118,15 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
|
||||||
else
|
else
|
||||||
builder.publicAddresses(addresses);
|
builder.publicAddresses(addresses);
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
IPForwardingRule rule = getIPForwardingRuleByVirtualMachine.getUnchecked(from.getId());
|
||||||
|
builder.publicAddresses(ImmutableSet.<String> of(rule.getIPAddress()));
|
||||||
|
} catch (UncheckedExecutionException e) {
|
||||||
|
if (Throwables2.getFirstThrowableOfType(e, ResourceNotFoundException.class) == null) {
|
||||||
|
Throwables.propagateIfPossible(e.getCause());
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
builder.credentials(credentialStore.get("node#" + from.getId()));
|
builder.credentials(credentialStore.get("node#" + from.getId()));
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ import com.google.common.collect.Sets;
|
||||||
public class CloudStackTemplateOptions extends TemplateOptions implements Cloneable {
|
public class CloudStackTemplateOptions extends TemplateOptions implements Cloneable {
|
||||||
|
|
||||||
protected Set<Long> securityGroupIds = Sets.<Long> newLinkedHashSet();
|
protected Set<Long> securityGroupIds = Sets.<Long> newLinkedHashSet();
|
||||||
|
protected Set<Long> networkIds = Sets.<Long> newLinkedHashSet();
|
||||||
protected String keyPair;
|
protected String keyPair;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -70,6 +71,7 @@ public class CloudStackTemplateOptions extends TemplateOptions implements Clonea
|
||||||
if (to instanceof CloudStackTemplateOptions) {
|
if (to instanceof CloudStackTemplateOptions) {
|
||||||
CloudStackTemplateOptions eTo = CloudStackTemplateOptions.class.cast(to);
|
CloudStackTemplateOptions eTo = CloudStackTemplateOptions.class.cast(to);
|
||||||
eTo.securityGroupIds(this.securityGroupIds);
|
eTo.securityGroupIds(this.securityGroupIds);
|
||||||
|
eTo.keyPair(this.keyPair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +95,26 @@ public class CloudStackTemplateOptions extends TemplateOptions implements Clonea
|
||||||
return securityGroupIds;
|
return securityGroupIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DeployVirtualMachineOptions#networkId
|
||||||
|
*/
|
||||||
|
public CloudStackTemplateOptions networkId(long networkId) {
|
||||||
|
this.networkIds.add(networkId);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DeployVirtualMachineOptions#networkIds
|
||||||
|
*/
|
||||||
|
public CloudStackTemplateOptions networkIds(Iterable<Long> networkIds) {
|
||||||
|
Iterables.addAll(this.networkIds, checkNotNull(networkIds, "networkIds was null"));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Long> getNetworkIds() {
|
||||||
|
return networkIds;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DeployVirtualMachineOptions#keyPair(String)
|
* @see DeployVirtualMachineOptions#keyPair(String)
|
||||||
*/
|
*/
|
||||||
|
@ -125,6 +147,22 @@ public class CloudStackTemplateOptions extends TemplateOptions implements Clonea
|
||||||
return options.securityGroupIds(securityGroupIds);
|
return options.securityGroupIds(securityGroupIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CloudStackTemplateOptions#networkId
|
||||||
|
*/
|
||||||
|
public static CloudStackTemplateOptions networkId(long id) {
|
||||||
|
CloudStackTemplateOptions options = new CloudStackTemplateOptions();
|
||||||
|
return options.networkId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see CloudStackTemplateOptions#networkIds
|
||||||
|
*/
|
||||||
|
public static CloudStackTemplateOptions networkIds(Iterable<Long> networkIds) {
|
||||||
|
CloudStackTemplateOptions options = new CloudStackTemplateOptions();
|
||||||
|
return options.networkIds(networkIds);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see CloudStackTemplateOptions#keyPair
|
* @see CloudStackTemplateOptions#keyPair
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -20,7 +20,9 @@ package org.jclouds.cloudstack.compute.strategy;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Throwables.propagate;
|
||||||
import static com.google.common.collect.Iterables.filter;
|
import static com.google.common.collect.Iterables.filter;
|
||||||
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
@ -30,17 +32,21 @@ import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import com.google.common.base.Predicates;
|
|
||||||
import org.jclouds.cloudstack.CloudStackClient;
|
import org.jclouds.cloudstack.CloudStackClient;
|
||||||
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
|
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
|
||||||
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
||||||
import org.jclouds.cloudstack.domain.AsyncJob;
|
import org.jclouds.cloudstack.domain.AsyncJob;
|
||||||
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
|
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
||||||
import org.jclouds.cloudstack.domain.ServiceOffering;
|
import org.jclouds.cloudstack.domain.ServiceOffering;
|
||||||
import org.jclouds.cloudstack.domain.Template;
|
import org.jclouds.cloudstack.domain.Template;
|
||||||
import org.jclouds.cloudstack.domain.VirtualMachine;
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
import org.jclouds.cloudstack.domain.Zone;
|
import org.jclouds.cloudstack.domain.Zone;
|
||||||
|
import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork;
|
||||||
|
import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork.Factory;
|
||||||
import org.jclouds.cloudstack.options.DeployVirtualMachineOptions;
|
import org.jclouds.cloudstack.options.DeployVirtualMachineOptions;
|
||||||
import org.jclouds.cloudstack.predicates.TemplatePredicates;
|
import org.jclouds.cloudstack.predicates.TemplatePredicates;
|
||||||
|
import org.jclouds.collect.Memoized;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.ComputeServiceAdapter;
|
import org.jclouds.compute.ComputeServiceAdapter;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
|
@ -48,7 +54,7 @@ import org.jclouds.domain.Credentials;
|
||||||
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.common.base.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* defines the connection between the {@link CloudStackClient} implementation
|
* defines the connection between the {@link CloudStackClient} implementation
|
||||||
|
@ -65,63 +71,96 @@ public class CloudStackComputeServiceAdapter implements
|
||||||
|
|
||||||
private final CloudStackClient client;
|
private final CloudStackClient client;
|
||||||
private final Predicate<Long> jobComplete;
|
private final Predicate<Long> jobComplete;
|
||||||
|
private final Supplier<Map<Long, Network>> networkSupplier;
|
||||||
|
private final Factory staticNATVMInNetwork;
|
||||||
|
private final Map<String, Credentials> credentialStore;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CloudStackComputeServiceAdapter(CloudStackClient client, Predicate<Long> jobComplete) {
|
public CloudStackComputeServiceAdapter(CloudStackClient client, Predicate<Long> jobComplete,
|
||||||
|
@Memoized Supplier<Map<Long, Network>> networkSupplier,
|
||||||
|
StaticNATVirtualMachineInNetwork.Factory staticNATVMInNetwork, Map<String, Credentials> credentialStore) {
|
||||||
this.client = checkNotNull(client, "client");
|
this.client = checkNotNull(client, "client");
|
||||||
this.jobComplete=checkNotNull(jobComplete, "jobComplete");
|
this.jobComplete = checkNotNull(jobComplete, "jobComplete");
|
||||||
|
this.networkSupplier = checkNotNull(networkSupplier, "networkSupplier");
|
||||||
|
this.staticNATVMInNetwork = checkNotNull(staticNATVMInNetwork, "staticNATVMInNetwork");
|
||||||
|
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VirtualMachine createNodeWithGroupEncodedIntoNameThenStoreCredentials(String group, String name,
|
public NodeAndInitialCredentials<VirtualMachine> createNodeWithGroupEncodedIntoName(String group, String name,
|
||||||
org.jclouds.compute.domain.Template template, Map<String, Credentials> credentialStore) {
|
org.jclouds.compute.domain.Template template) {
|
||||||
checkNotNull(template, "template was null");
|
checkNotNull(template, "template was null");
|
||||||
checkNotNull(template.getOptions(), "template options was null");
|
checkNotNull(template.getOptions(), "template options was null");
|
||||||
checkArgument(template.getOptions().getClass().isAssignableFrom(CloudStackTemplateOptions.class),
|
checkArgument(template.getOptions().getClass().isAssignableFrom(CloudStackTemplateOptions.class),
|
||||||
"options class %s should have been assignable from CloudStackTemplateOptions", template.getOptions()
|
"options class %s should have been assignable from CloudStackTemplateOptions", template.getOptions()
|
||||||
.getClass());
|
.getClass());
|
||||||
|
Map<Long, Network> networks = networkSupplier.get();
|
||||||
|
|
||||||
|
final long zoneId = Long.parseLong(template.getLocation().getId());
|
||||||
|
|
||||||
CloudStackTemplateOptions templateOptions = template.getOptions().as(CloudStackTemplateOptions.class);
|
CloudStackTemplateOptions templateOptions = template.getOptions().as(CloudStackTemplateOptions.class);
|
||||||
|
|
||||||
DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
|
DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
|
||||||
if (templateOptions.getSecurityGroupIds().size() > 0)
|
if (templateOptions.getSecurityGroupIds().size() > 0) {
|
||||||
options.securityGroupIds(templateOptions.getSecurityGroupIds());
|
options.securityGroupIds(templateOptions.getSecurityGroupIds());
|
||||||
|
} else if (templateOptions.getNetworkIds().size() > 0) {
|
||||||
|
options.networkIds(templateOptions.getNetworkIds());
|
||||||
|
} else if (networks.size() > 0) {
|
||||||
|
try {
|
||||||
|
options.networkId(getOnlyElement(filter(networks.values(), new Predicate<Network>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Network arg0) {
|
||||||
|
return arg0.getZoneId() == zoneId;
|
||||||
|
}
|
||||||
|
|
||||||
|
})).getId());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new IllegalArgumentException("please choose a specific network in zone " + zoneId + ": " + networks);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("please setup a network or security group for zone: " + zoneId);
|
||||||
|
}
|
||||||
|
|
||||||
if (templateOptions.getKeyPair() != null) {
|
if (templateOptions.getKeyPair() != null) {
|
||||||
options.keyPair(templateOptions.getKeyPair());
|
options.keyPair(templateOptions.getKeyPair());
|
||||||
if (templateOptions.getRunScript() != null) {
|
if (templateOptions.getRunScript() != null) {
|
||||||
checkArgument(
|
checkArgument(
|
||||||
credentialStore.containsKey("keypair#" + templateOptions.getKeyPair()),
|
credentialStore.containsKey("keypair#" + templateOptions.getKeyPair()),
|
||||||
"no private key configured for: %s; please use options.overrideLoginCredentialWith(rsa_private_text)",
|
"no private key configured for: %s; please use options.overrideLoginCredentialWith(rsa_private_text)",
|
||||||
templateOptions.getKeyPair());
|
templateOptions.getKeyPair());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long zoneId = Long.parseLong(template.getLocation().getId());
|
|
||||||
long templateId = Long.parseLong(template.getImage().getId());
|
long templateId = Long.parseLong(template.getImage().getId());
|
||||||
long serviceOfferingId = Long.parseLong(template.getHardware().getId());
|
long serviceOfferingId = Long.parseLong(template.getHardware().getId());
|
||||||
|
|
||||||
System.out.printf("serviceOfferingId %d, templateId %d, zoneId %d, options %s%n", serviceOfferingId, templateId,
|
logger.info("serviceOfferingId %d, templateId %d, zoneId %d, options %s%n", serviceOfferingId, templateId,
|
||||||
zoneId, options);
|
zoneId, options);
|
||||||
AsyncCreateResponse job = client.getVirtualMachineClient().deployVirtualMachineInZone(zoneId, serviceOfferingId,
|
AsyncCreateResponse job = client.getVirtualMachineClient().deployVirtualMachineInZone(zoneId, serviceOfferingId,
|
||||||
templateId, options);
|
templateId, options);
|
||||||
assert jobComplete.apply(job.getJobId());
|
boolean completed = jobComplete.apply(job.getJobId());
|
||||||
AsyncJob<VirtualMachine> jobWithResult = client.getAsyncJobClient().<VirtualMachine> getAsyncJob(job.getJobId());
|
AsyncJob<VirtualMachine> jobWithResult = client.getAsyncJobClient().<VirtualMachine> getAsyncJob(job.getJobId());
|
||||||
|
assert completed : jobWithResult;
|
||||||
if (jobWithResult.getError() != null)
|
if (jobWithResult.getError() != null)
|
||||||
Throwables.propagate(new ExecutionException(String.format("job %s failed with exception %s", job.getId(),
|
propagate(new ExecutionException(String.format("job %s failed with exception %s", job.getId(), jobWithResult
|
||||||
jobWithResult.getError().toString())) {
|
.getError().toString())) {
|
||||||
private static final long serialVersionUID = 4371112085613620239L;
|
private static final long serialVersionUID = 4371112085613620239L;
|
||||||
});
|
});
|
||||||
VirtualMachine vm = jobWithResult.getResult();
|
VirtualMachine vm = jobWithResult.getResult();
|
||||||
|
Credentials credentials = null;
|
||||||
if (vm.isPasswordEnabled()) {
|
if (vm.isPasswordEnabled()) {
|
||||||
assert vm.getPassword() != null : vm;
|
assert vm.getPassword() != null : vm;
|
||||||
Credentials credentials = new Credentials("root", vm.getPassword());
|
credentials = new Credentials(null, vm.getPassword());
|
||||||
credentialStore.put("node#" + vm.getId(), credentials);
|
|
||||||
} else {
|
} else {
|
||||||
// assert templateOptions.getKeyPair() != null : vm;
|
credentials = credentialStore.get("keypair#" + templateOptions.getKeyPair());
|
||||||
Credentials credentials = credentialStore.get("keypair#" + templateOptions.getKeyPair());
|
|
||||||
credentialStore.put("node#" + vm.getId(), credentials);
|
|
||||||
}
|
}
|
||||||
return vm;
|
// TODO: possibly not all network ids, do we want to do this
|
||||||
|
for (long networkId : options.getNetworkIds()) {
|
||||||
|
// TODO: log this
|
||||||
|
PublicIPAddress ip = staticNATVMInNetwork.create(networks.get(networkId)).apply(vm);
|
||||||
|
}
|
||||||
|
return new NodeAndInitialCredentials<VirtualMachine>(vm, vm.getId() + "", credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -56,4 +56,34 @@ public class AsyncCreateResponse {
|
||||||
return jobId;
|
return jobId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + (int) (id ^ (id >>> 32));
|
||||||
|
result = prime * result + (int) (jobId ^ (jobId >>> 32));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
AsyncCreateResponse other = (AsyncCreateResponse) obj;
|
||||||
|
if (id != other.id)
|
||||||
|
return false;
|
||||||
|
if (jobId != other.jobId)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[id=" + id + ", jobId=" + jobId + "]";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.jclouds.concurrent.Timeout;
|
||||||
* @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
|
* @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
|
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
|
||||||
public interface AccountClient {
|
public interface AccountClient {
|
||||||
/**
|
/**
|
||||||
* Lists Accounts
|
* Lists Accounts
|
||||||
|
|
|
@ -46,7 +46,9 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||||
* <p/>
|
* <p/>
|
||||||
*
|
*
|
||||||
* @see NATClient
|
* @see NATClient
|
||||||
* @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
|
* @see <a
|
||||||
|
* href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html"
|
||||||
|
* />
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@RequestFilters(QuerySigner.class)
|
@RequestFilters(QuerySigner.class)
|
||||||
|
@ -74,6 +76,28 @@ public interface NATAsyncClient {
|
||||||
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
ListenableFuture<IPForwardingRule> getIPForwardingRule(@QueryParam("id") long id);
|
ListenableFuture<IPForwardingRule> getIPForwardingRule(@QueryParam("id") long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see NATClient#getIPForwardingRuleForIPAddress
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@QueryParams(keys = "command", values = "listIpForwardingRules")
|
||||||
|
@SelectJson("ipforwardingrule")
|
||||||
|
@OnlyElement
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<IPForwardingRule> getIPForwardingRuleForIPAddress(@QueryParam("ipaddressid") long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see NATClient#getIPForwardingRuleForVirtualMachine
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@QueryParams(keys = "command", values = "listIpForwardingRules")
|
||||||
|
@SelectJson("ipforwardingrule")
|
||||||
|
@OnlyElement
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
|
||||||
|
ListenableFuture<IPForwardingRule> getIPForwardingRuleForVirtualMachine(@QueryParam("virtualmachineid") long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see NATClient#createIPForwardingRule
|
* @see NATClient#createIPForwardingRule
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -32,7 +32,9 @@ import org.jclouds.concurrent.Timeout;
|
||||||
* <p/>
|
* <p/>
|
||||||
*
|
*
|
||||||
* @see IPForwardingRuleAsyncClient
|
* @see IPForwardingRuleAsyncClient
|
||||||
* @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
|
* @see <a
|
||||||
|
* href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html"
|
||||||
|
* />
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
|
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
|
||||||
|
@ -56,6 +58,24 @@ public interface NATClient {
|
||||||
*/
|
*/
|
||||||
IPForwardingRule getIPForwardingRule(long id);
|
IPForwardingRule getIPForwardingRule(long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get a specific IPForwardingRule by ipaddress id
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* IPAddress of rule to get
|
||||||
|
* @return IPForwardingRule or null if not found
|
||||||
|
*/
|
||||||
|
IPForwardingRule getIPForwardingRuleForIPAddress(long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get a specific IPForwardingRule by virtual machine id
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* virtual machine of rule to get
|
||||||
|
* @return IPForwardingRule or null if not found
|
||||||
|
*/
|
||||||
|
IPForwardingRule getIPForwardingRuleForVirtualMachine(long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an ip forwarding rule
|
* Creates an ip forwarding rule
|
||||||
*
|
*
|
||||||
|
|
|
@ -50,16 +50,18 @@ import org.jclouds.rest.annotations.SkipEncoding;
|
||||||
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;
|
||||||
import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides asynchronous access to cloudstack via their REST API.
|
* Provides asynchronous access to cloudstack via their REST API.
|
||||||
* <p/>
|
* <p/>
|
||||||
*
|
*
|
||||||
* @see TemplateClient
|
* @see TemplateClient
|
||||||
* @see <a href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html" />
|
* @see <a
|
||||||
|
* href="http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html"
|
||||||
|
* />
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@RequestFilters(QuerySigner.class)
|
@RequestFilters(QuerySigner.class)
|
||||||
|
@ -74,7 +76,9 @@ public interface TemplateAsyncClient {
|
||||||
@QueryParams(keys = "command", values = "createTemplate")
|
@QueryParams(keys = "command", values = "createTemplate")
|
||||||
@Unwrap
|
@Unwrap
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
ListenableFuture<AsyncCreateResponse> createTemplate(@BinderParam(BindTemplateMetadataToQueryParams.class) TemplateMetadata templateMetadata, CreateTemplateOptions... options);
|
ListenableFuture<AsyncCreateResponse> createTemplate(
|
||||||
|
@BinderParam(BindTemplateMetadataToQueryParams.class) TemplateMetadata templateMetadata,
|
||||||
|
CreateTemplateOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see TemplateClient#registerTemplate
|
* @see TemplateClient#registerTemplate
|
||||||
|
@ -83,7 +87,10 @@ public interface TemplateAsyncClient {
|
||||||
@QueryParams(keys = "command", values = "registerTemplate")
|
@QueryParams(keys = "command", values = "registerTemplate")
|
||||||
@SelectJson("template")
|
@SelectJson("template")
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
ListenableFuture<Template> registerTemplate(@BinderParam(BindTemplateMetadataToQueryParams.class) TemplateMetadata templateMetadata, @QueryParam("format") String format, @QueryParam("hypervisor") String hypervisor, @QueryParam("url") String url, @QueryParam("zoneid") long zoneId, RegisterTemplateOptions... options);
|
ListenableFuture<Template> registerTemplate(
|
||||||
|
@BinderParam(BindTemplateMetadataToQueryParams.class) TemplateMetadata templateMetadata,
|
||||||
|
@QueryParam("format") String format, @QueryParam("hypervisor") String hypervisor,
|
||||||
|
@QueryParam("url") String url, @QueryParam("zoneid") long zoneId, RegisterTemplateOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see TemplateClient#updateTemplate
|
* @see TemplateClient#updateTemplate
|
||||||
|
@ -101,7 +108,8 @@ public interface TemplateAsyncClient {
|
||||||
@QueryParams(keys = "command", values = "copyTemplate")
|
@QueryParams(keys = "command", values = "copyTemplate")
|
||||||
@Unwrap
|
@Unwrap
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
ListenableFuture<AsyncCreateResponse> copyTemplateToZone(@QueryParam("id") long id, @QueryParam("sourcezoneid") long sourceZoneId, @QueryParam("destzoneid") long destZoneId);
|
ListenableFuture<AsyncCreateResponse> copyTemplateToZone(@QueryParam("id") long id,
|
||||||
|
@QueryParam("sourcezoneid") long sourceZoneId, @QueryParam("destzoneid") long destZoneId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see TemplateClient#deleteTemplate
|
* @see TemplateClient#deleteTemplate
|
||||||
|
@ -135,6 +143,7 @@ public interface TemplateAsyncClient {
|
||||||
* @see TemplateClient#getTemplate
|
* @see TemplateClient#getTemplate
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
|
// templatefilter required in at least 2.2.8 version
|
||||||
@QueryParams(keys = { "command", "templatefilter" }, values = { "listTemplates", "executable" })
|
@QueryParams(keys = { "command", "templatefilter" }, values = { "listTemplates", "executable" })
|
||||||
@SelectJson("template")
|
@SelectJson("template")
|
||||||
@OnlyElement
|
@OnlyElement
|
||||||
|
@ -147,7 +156,8 @@ public interface TemplateAsyncClient {
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@QueryParams(keys = "command", values = "updateTemplatePermissions")
|
@QueryParams(keys = "command", values = "updateTemplatePermissions")
|
||||||
ListenableFuture<Void> updateTemplatePermissions(@QueryParam("id") long id, UpdateTemplatePermissionsOptions... options);
|
ListenableFuture<Void> updateTemplatePermissions(@QueryParam("id") long id,
|
||||||
|
UpdateTemplatePermissionsOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see TemplateClient#listTemplatePermissions
|
* @see TemplateClient#listTemplatePermissions
|
||||||
|
@ -156,7 +166,8 @@ public interface TemplateAsyncClient {
|
||||||
@QueryParams(keys = "command", values = "listTemplatePermissions")
|
@QueryParams(keys = "command", values = "listTemplatePermissions")
|
||||||
@Unwrap
|
@Unwrap
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
ListenableFuture<Set<TemplatePermission>> listTemplatePermissions(@QueryParam("id") long id, AccountInDomainOptions... options);
|
ListenableFuture<Set<TemplatePermission>> listTemplatePermissions(@QueryParam("id") long id,
|
||||||
|
AccountInDomainOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see TemplateClient#extractTemplate
|
* @see TemplateClient#extractTemplate
|
||||||
|
@ -165,5 +176,6 @@ public interface TemplateAsyncClient {
|
||||||
@QueryParams(keys = "command", values = "extractTemplate")
|
@QueryParams(keys = "command", values = "extractTemplate")
|
||||||
@Unwrap
|
@Unwrap
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
ListenableFuture<AsyncCreateResponse> extractTemplate(@QueryParam("id") long id, @QueryParam("mode") ExtractMode mode, @QueryParam("zoneid") long zoneId, ExtractTemplateOptions... options);
|
ListenableFuture<AsyncCreateResponse> extractTemplate(@QueryParam("id") long id,
|
||||||
|
@QueryParam("mode") ExtractMode mode, @QueryParam("zoneid") long zoneId, ExtractTemplateOptions... options);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.cloudstack.functions;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.cloudstack.CloudStackClient;
|
||||||
|
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
|
||||||
|
import org.jclouds.cloudstack.domain.AsyncJob;
|
||||||
|
import org.jclouds.cloudstack.domain.IPForwardingRule;
|
||||||
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
|
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
||||||
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class StaticNATVirtualMachineInNetwork implements Function<VirtualMachine, PublicIPAddress> {
|
||||||
|
public static interface Factory {
|
||||||
|
StaticNATVirtualMachineInNetwork create(Network in);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final CloudStackClient client;
|
||||||
|
private final ReuseOrAssociateNewPublicIPAddress reuseOrAssociate;
|
||||||
|
private final Network network;
|
||||||
|
private final Predicate<Long> jobComplete;
|
||||||
|
private final Cache<Long, IPForwardingRule> getIPForwardingRuleByVirtualMachine;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public StaticNATVirtualMachineInNetwork(CloudStackClient client,
|
||||||
|
ReuseOrAssociateNewPublicIPAddress reuseOrAssociate, Predicate<Long> jobComplete,
|
||||||
|
Cache<Long, IPForwardingRule> getIPForwardingRuleByVirtualMachine, @Assisted Network network) {
|
||||||
|
this.client = checkNotNull(client, "client");
|
||||||
|
this.reuseOrAssociate = checkNotNull(reuseOrAssociate, "reuseOrAssociate");
|
||||||
|
this.jobComplete = checkNotNull(jobComplete, "jobComplete");
|
||||||
|
this.getIPForwardingRuleByVirtualMachine = checkNotNull(getIPForwardingRuleByVirtualMachine,
|
||||||
|
"getIPForwardingRuleByVirtualMachine");
|
||||||
|
this.network = checkNotNull(network, "network");
|
||||||
|
}
|
||||||
|
|
||||||
|
public PublicIPAddress apply(VirtualMachine vm) {
|
||||||
|
PublicIPAddress ip;
|
||||||
|
for (ip = reuseOrAssociate.apply(network); (!ip.isStaticNAT() || ip.getVirtualMachineId() != vm.getId()); ip = reuseOrAssociate
|
||||||
|
.apply(network)) {
|
||||||
|
// check to see if someone already grabbed this ip
|
||||||
|
if (ip.getVirtualMachineId() > 0 && ip.getVirtualMachineId() != vm.getId())
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
AsyncCreateResponse job = client.getNATClient().createIPForwardingRule(ip.getId(), "tcp", 22);
|
||||||
|
checkState(jobComplete.apply(job.getJobId()), "Timeout creating IP forwarding rule: ", job);
|
||||||
|
AsyncJob<IPForwardingRule> response = client.getAsyncJobClient().getAsyncJob(job.getJobId());
|
||||||
|
checkState(response.getResult() != null, "No result after creating IP forwarding rule: ", response);
|
||||||
|
getIPForwardingRuleByVirtualMachine.asMap().put(vm.getId(), response.getResult());
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
|
@ -70,7 +70,12 @@ public class CloudStackErrorHandler implements HttpErrorHandler {
|
||||||
break;
|
break;
|
||||||
case 409:
|
case 409:
|
||||||
case 431:
|
case 431:
|
||||||
exception = new IllegalStateException(message, exception);
|
if (command.getCurrentRequest().getRequestLine().indexOf("delete") != -1
|
||||||
|
&& message.indexOf("does not exist") != -1) {
|
||||||
|
exception = new ResourceNotFoundException(message, exception);
|
||||||
|
} else {
|
||||||
|
exception = new IllegalStateException(message, exception);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -23,8 +23,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import org.jclouds.encryption.internal.Base64;
|
import org.jclouds.encryption.internal.Base64;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options used to control what disk offerings are returned
|
* Options used to control what disk offerings are returned
|
||||||
|
@ -119,6 +122,23 @@ public class DeployVirtualMachineOptions extends AccountInDomainOptions {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterable<Long> getNetworkIds() {
|
||||||
|
if (queryParameters.get("networkids").size() == 1) {
|
||||||
|
return Iterables.transform(
|
||||||
|
Splitter.on(",").split(Iterables.getOnlyElement(queryParameters.get("networkids"))),
|
||||||
|
new Function<String, Long>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long apply(String arg0) {
|
||||||
|
return Long.parseLong(arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return ImmutableSet.<Long> of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param securityGroupId
|
* @param securityGroupId
|
||||||
* security group applied to the virtual machine. Should be passed
|
* security group applied to the virtual machine. Should be passed
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.cloudstack.suppliers;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.cloudstack.CloudStackClient;
|
||||||
|
import org.jclouds.cloudstack.domain.Account;
|
||||||
|
import org.jclouds.cloudstack.domain.User;
|
||||||
|
import org.jclouds.cloudstack.predicates.UserPredicates;
|
||||||
|
import org.jclouds.rest.annotations.Identity;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class GetCurrentUser implements Supplier<User> {
|
||||||
|
private final CloudStackClient client;
|
||||||
|
private final String identity;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public GetCurrentUser(CloudStackClient client, @Identity String identity) {
|
||||||
|
this.client = checkNotNull(client, "client");
|
||||||
|
this.identity = checkNotNull(identity, "identity");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User get() {
|
||||||
|
Iterable<User> users = Iterables.concat(client.getAccountClient().listAccounts());
|
||||||
|
Predicate<User> apiKeyMatches = UserPredicates.apiKeyEquals(identity);
|
||||||
|
User currentUser = null;
|
||||||
|
try {
|
||||||
|
currentUser = Iterables.find(users, apiKeyMatches);
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
throw new NoSuchElementException(String.format("none of the following users match %s: %s", apiKeyMatches,
|
||||||
|
users));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentUser.getAccountType() != Account.Type.USER)
|
||||||
|
throw new IllegalArgumentException(String.format(
|
||||||
|
"invalid account type: %s, please specify an apiKey of a USER, for example: %s",
|
||||||
|
currentUser.getAccountType(), Iterables.filter(users, UserPredicates.isUserAccount())));
|
||||||
|
return currentUser;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.cloudstack.suppliers;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.jclouds.cloudstack.options.ListNetworksOptions.Builder.accountInDomain;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.cloudstack.CloudStackClient;
|
||||||
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
|
import org.jclouds.cloudstack.domain.User;
|
||||||
|
import org.jclouds.cloudstack.features.NetworkClient;
|
||||||
|
import org.jclouds.collect.Memoized;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class NetworksForCurrentUser implements Supplier<Map<Long, Network>> {
|
||||||
|
private final CloudStackClient client;
|
||||||
|
private final Supplier<User> currentUserSupplier;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public NetworksForCurrentUser(CloudStackClient client, @Memoized Supplier<User> currentUserSupplier) {
|
||||||
|
this.client = checkNotNull(client, "client");
|
||||||
|
this.currentUserSupplier = checkNotNull(currentUserSupplier, "currentUserSupplier");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, Network> get() {
|
||||||
|
User currentUser = currentUserSupplier.get();
|
||||||
|
NetworkClient networkClient = client.getNetworkClient();
|
||||||
|
return Maps.uniqueIndex(
|
||||||
|
networkClient.listNetworks(accountInDomain(currentUser.getAccount(), currentUser.getDomainId())),
|
||||||
|
new Function<Network, Long>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long apply(Network arg0) {
|
||||||
|
return arg0.getId();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,35 +25,47 @@ import static org.testng.Assert.fail;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.cloudstack.CloudStackClient;
|
import org.jclouds.cloudstack.CloudStackClient;
|
||||||
import org.jclouds.cloudstack.CloudStackPropertiesBuilder;
|
import org.jclouds.cloudstack.compute.config.CloudStackComputeServiceContextModule.GetIPForwardingRuleByVirtualMachine;
|
||||||
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
|
import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions;
|
||||||
import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter;
|
import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter;
|
||||||
|
import org.jclouds.cloudstack.domain.IPForwardingRule;
|
||||||
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
import org.jclouds.cloudstack.domain.ServiceOffering;
|
import org.jclouds.cloudstack.domain.ServiceOffering;
|
||||||
import org.jclouds.cloudstack.domain.SshKeyPair;
|
import org.jclouds.cloudstack.domain.User;
|
||||||
import org.jclouds.cloudstack.domain.VirtualMachine;
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
import org.jclouds.cloudstack.features.BaseCloudStackClientLiveTest;
|
import org.jclouds.cloudstack.features.BaseCloudStackClientLiveTest;
|
||||||
|
import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork;
|
||||||
import org.jclouds.cloudstack.predicates.JobComplete;
|
import org.jclouds.cloudstack.predicates.JobComplete;
|
||||||
import org.jclouds.cloudstack.predicates.TemplatePredicates;
|
import org.jclouds.cloudstack.predicates.TemplatePredicates;
|
||||||
|
import org.jclouds.cloudstack.suppliers.GetCurrentUser;
|
||||||
|
import org.jclouds.cloudstack.suppliers.NetworksForCurrentUser;
|
||||||
|
import org.jclouds.collect.Memoized;
|
||||||
|
import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials;
|
||||||
import org.jclouds.compute.ComputeTestUtils;
|
import org.jclouds.compute.ComputeTestUtils;
|
||||||
import org.jclouds.compute.domain.ExecResponse;
|
import org.jclouds.compute.domain.ExecResponse;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
|
import org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials;
|
||||||
|
import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
import org.jclouds.net.IPSocket;
|
import org.jclouds.net.IPSocket;
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
import org.jclouds.rest.annotations.Identity;
|
||||||
import org.jclouds.ssh.SshClient;
|
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;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.net.InetAddresses;
|
import com.google.common.net.InetAddresses;
|
||||||
|
@ -61,15 +73,19 @@ import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
import com.google.inject.Scopes;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
|
|
||||||
@Test(groups = "live", singleThreaded = true, testName = "CloudStackComputeServiceAdapterLiveTest")
|
@Test(groups = "live", singleThreaded = true, testName = "CloudStackComputeServiceAdapterLiveTest")
|
||||||
public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClientLiveTest {
|
public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
|
|
||||||
private CloudStackComputeServiceAdapter adapter;
|
private CloudStackComputeServiceAdapter adapter;
|
||||||
private VirtualMachine vm;
|
private NodeAndInitialCredentials<VirtualMachine> vm;
|
||||||
|
|
||||||
private String keyPairName;
|
private String keyPairName;
|
||||||
private Map<String, String> keyPair;
|
private Map<String, String> keyPair;
|
||||||
|
Map<String, Credentials> credentialStore = Maps.newLinkedHashMap();
|
||||||
|
|
||||||
@BeforeGroups(groups = { "live" })
|
@BeforeGroups(groups = { "live" })
|
||||||
public void setupClient() {
|
public void setupClient() {
|
||||||
|
@ -78,8 +94,16 @@ public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClien
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bindProperties(binder(), CloudStackComputeServiceAdapterLiveTest.this.setupProperties());
|
bindProperties(binder(), setupProperties());
|
||||||
|
bind(String.class).annotatedWith(Identity.class).toInstance(identity);
|
||||||
|
bind(new TypeLiteral<Supplier<User>>() {
|
||||||
|
}).annotatedWith(Memoized.class).to(GetCurrentUser.class).in(Scopes.SINGLETON);
|
||||||
|
bind(new TypeLiteral<Supplier<Map<Long, Network>>>() {
|
||||||
|
}).annotatedWith(Memoized.class).to(NetworksForCurrentUser.class).in(Scopes.SINGLETON);
|
||||||
|
bind(new TypeLiteral<Map<String, Credentials>>() {
|
||||||
|
}).toInstance(credentialStore);
|
||||||
bind(CloudStackClient.class).toInstance(context.getApi());
|
bind(CloudStackClient.class).toInstance(context.getApi());
|
||||||
|
install(new FactoryModuleBuilder().build(StaticNATVirtualMachineInNetwork.Factory.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
@ -88,6 +112,14 @@ public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClien
|
||||||
protected Predicate<Long> jobComplete(JobComplete jobComplete) {
|
protected Predicate<Long> jobComplete(JobComplete jobComplete) {
|
||||||
return new RetryablePredicate<Long>(jobComplete, 1200, 1, 5, TimeUnit.SECONDS);
|
return new RetryablePredicate<Long>(jobComplete, 1200, 1, 5, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Cache<Long, IPForwardingRule> getIPForwardingRuleByVirtualMachine(
|
||||||
|
GetIPForwardingRuleByVirtualMachine getIPForwardingRule) {
|
||||||
|
return CacheBuilder.newBuilder().build(getIPForwardingRule);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
adapter = Guice.createInjector(module, new Log4JLoggingModule()).getInstance(
|
adapter = Guice.createInjector(module, new Log4JLoggingModule()).getInstance(
|
||||||
CloudStackComputeServiceAdapter.class);
|
CloudStackComputeServiceAdapter.class);
|
||||||
|
@ -105,35 +137,47 @@ public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClien
|
||||||
assertFalse(Iterables.isEmpty(adapter.listLocations()));
|
assertFalse(Iterables.isEmpty(adapter.listLocations()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final PrioritizeCredentialsFromTemplate prioritizeCredentialsFromTemplate = new PrioritizeCredentialsFromTemplate(
|
||||||
|
new DefaultCredentialsFromImageOrOverridingCredentials());
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentialsWithSecurityGroup() {
|
public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentialsWithSecurityGroup()
|
||||||
|
throws InterruptedException {
|
||||||
String group = "foo";
|
String group = "foo";
|
||||||
String name = "node" + new Random().nextInt();
|
String name = "node" + new Random().nextInt();
|
||||||
Template template = computeContext.getComputeService().templateBuilder().build();
|
Template template = computeContext.getComputeService().templateBuilder().build();
|
||||||
|
|
||||||
client.getSSHKeyPairClient().deleteSSHKeyPair(keyPairName);
|
if (!client
|
||||||
client.getSSHKeyPairClient().registerSSHKeyPair(keyPairName, keyPair.get("public"));
|
.getTemplateClient()
|
||||||
|
.getTemplateInZone(Long.parseLong(template.getImage().getId()),
|
||||||
|
Long.parseLong(template.getLocation().getId())).isPasswordEnabled()) {
|
||||||
|
client.getSSHKeyPairClient().deleteSSHKeyPair(keyPairName);
|
||||||
|
client.getSSHKeyPairClient().registerSSHKeyPair(keyPairName, keyPair.get("public"));
|
||||||
|
|
||||||
Map<String, Credentials> credentialStore = Maps.newLinkedHashMap();
|
credentialStore.put("keypair#" + keyPairName, new Credentials("root", keyPair.get("private")));
|
||||||
credentialStore.put("keypair#" + keyPairName, new Credentials("root", keyPair.get("private")));
|
|
||||||
|
|
||||||
// TODO: look at SecurityGroupClientLiveTest for how to do this
|
// TODO: look at SecurityGroupClientLiveTest for how to do this
|
||||||
template.getOptions().as(CloudStackTemplateOptions.class).keyPair(keyPairName);
|
template.getOptions().as(CloudStackTemplateOptions.class).keyPair(keyPairName);
|
||||||
|
}
|
||||||
vm = adapter.createNodeWithGroupEncodedIntoNameThenStoreCredentials(group, name, template, credentialStore);
|
vm = adapter.createNodeWithGroupEncodedIntoName(group, name, template);
|
||||||
|
|
||||||
// TODO: check security groups vm.getSecurityGroups(),
|
// TODO: check security groups vm.getSecurityGroups(),
|
||||||
// check other things, like cpu correct, mem correct, image/os is correct
|
// check other things, like cpu correct, mem correct, image/os is correct
|
||||||
// (as possible)
|
// (as possible)
|
||||||
|
|
||||||
assert credentialStore.containsKey("node#" + vm.getId()) : "credentials to log into vm not found " + vm;
|
// check to see if we setup a NAT rule (conceding we could check this from
|
||||||
assert InetAddresses.isInetAddress(vm.getIPAddress()) : vm;
|
// cache)
|
||||||
|
IPForwardingRule rule = client.getNATClient().getIPForwardingRuleForVirtualMachine(vm.getNode().getId());
|
||||||
|
|
||||||
doConnectViaSsh(vm, credentialStore.get("node#" + vm.getId()));
|
String address = rule != null ? rule.getIPAddress() : vm.getNode().getIPAddress();
|
||||||
|
|
||||||
|
assert InetAddresses.isInetAddress(address) : vm;
|
||||||
|
IPSocket socket = new IPSocket(address, 22);
|
||||||
|
doConnectViaSsh(socket, prioritizeCredentialsFromTemplate.apply(template, vm.getCredentials()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void doConnectViaSsh(VirtualMachine vm, Credentials creds) {
|
protected void doConnectViaSsh(IPSocket socket, Credentials creds) {
|
||||||
SshClient ssh = computeContext.utils().sshFactory().create(new IPSocket(vm.getIPAddress(), 22), creds);
|
SshClient ssh = computeContext.utils().sshFactory().create(socket, creds);
|
||||||
try {
|
try {
|
||||||
ssh.connect();
|
ssh.connect();
|
||||||
ExecResponse hello = ssh.exec("echo hello");
|
ExecResponse hello = ssh.exec("echo hello");
|
||||||
|
@ -170,7 +214,7 @@ public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClien
|
||||||
@AfterGroups(groups = "live")
|
@AfterGroups(groups = "live")
|
||||||
protected void tearDown() {
|
protected void tearDown() {
|
||||||
if (vm != null)
|
if (vm != null)
|
||||||
adapter.destroyNode(vm.getId() + "");
|
adapter.destroyNode(vm.getNodeId());
|
||||||
super.tearDown();
|
super.tearDown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.jclouds.sshj.config.SshjSshClientModule;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,8 +50,9 @@ public class CloudStackComputeServiceLiveTest extends BaseComputeServiceLiveTest
|
||||||
|
|
||||||
public void testAssignability() throws Exception {
|
public void testAssignability() throws Exception {
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
RestContext<CloudStackClient, CloudStackAsyncClient> tmContext = new ComputeServiceContextFactory()
|
RestContext<CloudStackClient, CloudStackAsyncClient> tmContext = new ComputeServiceContextFactory(
|
||||||
.createContext(provider, identity, credential).getProviderSpecificContext();
|
setupRestProperties()).createContext(provider, identity, credential, ImmutableSet.<Module> of(),
|
||||||
|
setupProperties()).getProviderSpecificContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
// cloudstack does not support metadata
|
// cloudstack does not support metadata
|
||||||
|
@ -60,4 +62,3 @@ public class CloudStackComputeServiceLiveTest extends BaseComputeServiceLiveTest
|
||||||
"node userMetadata did not match %s %s", userMetadata, node);
|
"node userMetadata did not match %s %s", userMetadata, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Set;
|
||||||
import org.jclouds.cloudstack.compute.functions.VirtualMachineToNodeMetadata.FindHardwareForVirtualMachine;
|
import org.jclouds.cloudstack.compute.functions.VirtualMachineToNodeMetadata.FindHardwareForVirtualMachine;
|
||||||
import org.jclouds.cloudstack.compute.functions.VirtualMachineToNodeMetadata.FindImageForVirtualMachine;
|
import org.jclouds.cloudstack.compute.functions.VirtualMachineToNodeMetadata.FindImageForVirtualMachine;
|
||||||
import org.jclouds.cloudstack.compute.functions.VirtualMachineToNodeMetadata.FindLocationForVirtualMachine;
|
import org.jclouds.cloudstack.compute.functions.VirtualMachineToNodeMetadata.FindLocationForVirtualMachine;
|
||||||
|
import org.jclouds.cloudstack.domain.IPForwardingRule;
|
||||||
import org.jclouds.cloudstack.domain.VirtualMachine;
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
import org.jclouds.cloudstack.parse.ListVirtualMachinesResponseTest;
|
import org.jclouds.cloudstack.parse.ListVirtualMachinesResponseTest;
|
||||||
import org.jclouds.compute.domain.Hardware;
|
import org.jclouds.compute.domain.Hardware;
|
||||||
|
@ -36,10 +37,13 @@ import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||||
import org.jclouds.compute.domain.NodeState;
|
import org.jclouds.compute.domain.NodeState;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.common.base.Suppliers;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
@ -50,6 +54,51 @@ import com.google.common.collect.Iterables;
|
||||||
@Test(groups = "unit", testName = "VirtualMachineToNodeMetadataTest")
|
@Test(groups = "unit", testName = "VirtualMachineToNodeMetadataTest")
|
||||||
public class VirtualMachineToNodeMetadataTest {
|
public class VirtualMachineToNodeMetadataTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testApplyWhereVirtualMachineWithIPForwardingRule() throws UnknownHostException {
|
||||||
|
|
||||||
|
// note we are testing when no credentials are here. otherwise would be
|
||||||
|
// ("node#416696", new
|
||||||
|
// Credentials("root", "password"))
|
||||||
|
Map<String, Credentials> credentialStore = ImmutableMap.<String, Credentials> of();
|
||||||
|
|
||||||
|
Supplier<Set<? extends Location>> locationSupplier = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
|
||||||
|
.<Location> of(ZoneToLocationTest.one, ZoneToLocationTest.two));
|
||||||
|
|
||||||
|
Supplier<Set<? extends Hardware>> hardwareSupplier = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
|
||||||
|
.<Hardware> of(ServiceOfferingToHardwareTest.one, ServiceOfferingToHardwareTest.two));
|
||||||
|
|
||||||
|
Supplier<Set<? extends Image>> imageSupplier = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet
|
||||||
|
.<Image> of(TemplateToImageTest.one, TemplateToImageTest.two));
|
||||||
|
VirtualMachineToNodeMetadata parser = new VirtualMachineToNodeMetadata(credentialStore,
|
||||||
|
new FindLocationForVirtualMachine(locationSupplier), new FindHardwareForVirtualMachine(hardwareSupplier),
|
||||||
|
new FindImageForVirtualMachine(imageSupplier), CacheBuilder.newBuilder().<Long, IPForwardingRule> build(
|
||||||
|
new CacheLoader<Long, IPForwardingRule>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPForwardingRule load(Long arg0) throws Exception {
|
||||||
|
return IPForwardingRule.builder().id(1234l).IPAddress("1.1.1.1").build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
// notice if we've already parsed this properly here, we can rely on it.
|
||||||
|
VirtualMachine guest = Iterables.get(new ListVirtualMachinesResponseTest().expected(), 0);
|
||||||
|
|
||||||
|
NodeMetadata node = parser.apply(guest);
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
node.toString(),
|
||||||
|
new NodeMetadataBuilder().id("54").providerId("54").name("i-3-54-VM").location(ZoneToLocationTest.one)
|
||||||
|
.state(NodeState.PENDING).privateAddresses(ImmutableSet.of("10.1.1.18"))
|
||||||
|
.publicAddresses(ImmutableSet.of("1.1.1.1")).hardware(ServiceOfferingToHardwareTest.one)
|
||||||
|
.imageId(TemplateToImageTest.one.getId())
|
||||||
|
.operatingSystem(TemplateToImageTest.one.getOperatingSystem()).build().toString());
|
||||||
|
|
||||||
|
// because it wasn't present in the credential store.
|
||||||
|
assertEquals(node.getCredentials(), null);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testApplyWhereVirtualMachineWithNoPassword() throws UnknownHostException {
|
public void testApplyWhereVirtualMachineWithNoPassword() throws UnknownHostException {
|
||||||
|
|
||||||
|
@ -66,10 +115,17 @@ public class VirtualMachineToNodeMetadataTest {
|
||||||
|
|
||||||
Supplier<Set<? extends Image>> imageSupplier = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet
|
Supplier<Set<? extends Image>> imageSupplier = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet
|
||||||
.<Image> of(TemplateToImageTest.one, TemplateToImageTest.two));
|
.<Image> of(TemplateToImageTest.one, TemplateToImageTest.two));
|
||||||
|
|
||||||
VirtualMachineToNodeMetadata parser = new VirtualMachineToNodeMetadata(credentialStore,
|
VirtualMachineToNodeMetadata parser = new VirtualMachineToNodeMetadata(credentialStore,
|
||||||
new FindLocationForVirtualMachine(locationSupplier), new FindHardwareForVirtualMachine(hardwareSupplier),
|
new FindLocationForVirtualMachine(locationSupplier), new FindHardwareForVirtualMachine(hardwareSupplier),
|
||||||
new FindImageForVirtualMachine(imageSupplier));
|
new FindImageForVirtualMachine(imageSupplier), CacheBuilder.newBuilder().<Long, IPForwardingRule> build(
|
||||||
|
new CacheLoader<Long, IPForwardingRule>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPForwardingRule load(Long arg0) throws Exception {
|
||||||
|
throw new ResourceNotFoundException("no ip forwarding rule for: " + arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
// notice if we've already parsed this properly here, we can rely on it.
|
// notice if we've already parsed this properly here, we can rely on it.
|
||||||
VirtualMachine guest = Iterables.get(new ListVirtualMachinesResponseTest().expected(), 0);
|
VirtualMachine guest = Iterables.get(new ListVirtualMachinesResponseTest().expected(), 0);
|
||||||
|
@ -104,7 +160,15 @@ public class VirtualMachineToNodeMetadataTest {
|
||||||
|
|
||||||
VirtualMachineToNodeMetadata parser = new VirtualMachineToNodeMetadata(credentialStore,
|
VirtualMachineToNodeMetadata parser = new VirtualMachineToNodeMetadata(credentialStore,
|
||||||
new FindLocationForVirtualMachine(locationSupplier), new FindHardwareForVirtualMachine(hardwareSupplier),
|
new FindLocationForVirtualMachine(locationSupplier), new FindHardwareForVirtualMachine(hardwareSupplier),
|
||||||
new FindImageForVirtualMachine(imageSupplier));
|
new FindImageForVirtualMachine(imageSupplier), CacheBuilder.newBuilder().<Long, IPForwardingRule> build(
|
||||||
|
new CacheLoader<Long, IPForwardingRule>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPForwardingRule load(Long arg0) throws Exception {
|
||||||
|
throw new ResourceNotFoundException("no ip forwarding rule for: " + arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
// notice if we've already parsed this properly here, we can rely on it.
|
// notice if we've already parsed this properly here, we can rely on it.
|
||||||
VirtualMachine guest = Iterables.get(new ListVirtualMachinesResponseTest().expected(), 0);
|
VirtualMachine guest = Iterables.get(new ListVirtualMachinesResponseTest().expected(), 0);
|
||||||
|
@ -121,5 +185,4 @@ public class VirtualMachineToNodeMetadataTest {
|
||||||
|
|
||||||
assertEquals(node.getCredentials(), new Credentials("root", "password"));
|
assertEquals(node.getCredentials(), new Credentials("root", "password"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
package org.jclouds.cloudstack.compute.options;
|
package org.jclouds.cloudstack.compute.options;
|
||||||
|
|
||||||
import static org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions.Builder.keyPair;
|
import static org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions.Builder.keyPair;
|
||||||
|
import static org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions.Builder.networkId;
|
||||||
|
import static org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions.Builder.networkIds;
|
||||||
import static org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions.Builder.securityGroupId;
|
import static org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions.Builder.securityGroupId;
|
||||||
import static org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions.Builder.securityGroupIds;
|
import static org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions.Builder.securityGroupIds;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
@ -74,6 +76,36 @@ public class CloudStackTemplateOptionsTest {
|
||||||
assertEquals(options.as(CloudStackTemplateOptions.class).getSecurityGroupIds(), ImmutableSet.of(3l));
|
assertEquals(options.as(CloudStackTemplateOptions.class).getSecurityGroupIds(), ImmutableSet.of(3l));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultNetworkIds() {
|
||||||
|
TemplateOptions options = new CloudStackTemplateOptions();
|
||||||
|
assertEquals(options.as(CloudStackTemplateOptions.class).getNetworkIds(), ImmutableSet.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNetworkId() {
|
||||||
|
TemplateOptions options = new CloudStackTemplateOptions().networkId(3l);
|
||||||
|
assertEquals(options.as(CloudStackTemplateOptions.class).getNetworkIds(), ImmutableSet.of(3l));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNetworkIdStatic() {
|
||||||
|
TemplateOptions options = networkId(3l);
|
||||||
|
assertEquals(options.as(CloudStackTemplateOptions.class).getNetworkIds(), ImmutableSet.of(3l));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNetworkIds() {
|
||||||
|
TemplateOptions options = new CloudStackTemplateOptions().networkIds(ImmutableSet.of(3l));
|
||||||
|
assertEquals(options.as(CloudStackTemplateOptions.class).getNetworkIds(), ImmutableSet.of(3l));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNetworkIdsStatic() {
|
||||||
|
TemplateOptions options = networkIds(ImmutableSet.of(3l));
|
||||||
|
assertEquals(options.as(CloudStackTemplateOptions.class).getNetworkIds(), ImmutableSet.of(3l));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testKeyPair() {
|
public void testKeyPair() {
|
||||||
TemplateOptions options = keyPair("test");
|
TemplateOptions options = keyPair("test");
|
||||||
|
|
|
@ -18,19 +18,27 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.cloudstack.features;
|
package org.jclouds.cloudstack.features;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.filter;
|
||||||
|
import static com.google.common.collect.Iterables.get;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
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.Account;
|
import org.jclouds.cloudstack.domain.Account;
|
||||||
|
import org.jclouds.cloudstack.domain.Template;
|
||||||
import org.jclouds.cloudstack.domain.User;
|
import org.jclouds.cloudstack.domain.User;
|
||||||
import org.jclouds.cloudstack.domain.VirtualMachine;
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
import org.jclouds.cloudstack.functions.ReuseOrAssociateNewPublicIPAddress;
|
import org.jclouds.cloudstack.functions.ReuseOrAssociateNewPublicIPAddress;
|
||||||
|
import org.jclouds.cloudstack.options.ListTemplatesOptions;
|
||||||
|
import org.jclouds.cloudstack.predicates.CorrectHypervisorForZone;
|
||||||
import org.jclouds.cloudstack.predicates.JobComplete;
|
import org.jclouds.cloudstack.predicates.JobComplete;
|
||||||
|
import org.jclouds.cloudstack.predicates.OSCategoryIn;
|
||||||
|
import org.jclouds.cloudstack.predicates.TemplatePredicates;
|
||||||
import org.jclouds.cloudstack.predicates.UserPredicates;
|
import org.jclouds.cloudstack.predicates.UserPredicates;
|
||||||
import org.jclouds.cloudstack.predicates.VirtualMachineDestroyed;
|
import org.jclouds.cloudstack.predicates.VirtualMachineDestroyed;
|
||||||
import org.jclouds.cloudstack.predicates.VirtualMachineRunning;
|
import org.jclouds.cloudstack.predicates.VirtualMachineRunning;
|
||||||
|
@ -50,6 +58,7 @@ import org.testng.annotations.AfterGroups;
|
||||||
import org.testng.annotations.BeforeGroups;
|
import org.testng.annotations.BeforeGroups;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
|
@ -65,6 +74,33 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
|
||||||
provider = "cloudstack";
|
provider = "cloudstack";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long defaultTemplateOrPreferredInZone(Long defaultTemplate, CloudStackClient client, long zoneId) {
|
||||||
|
long templateId = defaultTemplate != null ? defaultTemplate : getTemplateForZone(client, zoneId);
|
||||||
|
return templateId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getTemplateForZone(CloudStackClient client, long zoneId) {
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
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();
|
||||||
|
return templateId;
|
||||||
|
}
|
||||||
|
|
||||||
protected String prefix = System.getProperty("user.name");
|
protected String prefix = System.getProperty("user.name");
|
||||||
|
|
||||||
protected CloudStackClient client;
|
protected CloudStackClient client;
|
||||||
|
@ -83,7 +119,6 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
|
||||||
|
|
||||||
protected ComputeServiceContext computeContext;
|
protected ComputeServiceContext computeContext;
|
||||||
|
|
||||||
|
|
||||||
protected void checkSSH(IPSocket socket) {
|
protected void checkSSH(IPSocket socket) {
|
||||||
socketTester.apply(socket);
|
socketTester.apply(socket);
|
||||||
SshClient client = sshFactory.create(socket, new Credentials("root", password));
|
SshClient client = sshFactory.create(socket, new Credentials("root", password));
|
||||||
|
@ -97,7 +132,7 @@ public class BaseCloudStackClientLiveTest extends BaseVersionedServiceLiveTest {
|
||||||
client.disconnect();
|
client.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeGroups(groups = "live")
|
@BeforeGroups(groups = "live")
|
||||||
public void setupClient() {
|
public void setupClient() {
|
||||||
setupCredentials();
|
setupCredentials();
|
||||||
|
|
|
@ -57,7 +57,9 @@ public class FirewallClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
prefix += "rule";
|
prefix += "rule";
|
||||||
try {
|
try {
|
||||||
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.supportsPortForwarding());
|
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.supportsPortForwarding());
|
||||||
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, client, jobComplete,
|
Long defaultTemplate = (imageId != null && !"".equals(imageId)) ? new Long(imageId) : null;
|
||||||
|
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network,
|
||||||
|
defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()), client, jobComplete,
|
||||||
virtualMachineRunning);
|
virtualMachineRunning);
|
||||||
if (vm.getPassword() != null)
|
if (vm.getPassword() != null)
|
||||||
password = vm.getPassword();
|
password = vm.getPassword();
|
||||||
|
|
|
@ -67,7 +67,9 @@ public class LoadBalancerClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
prefix += "rule";
|
prefix += "rule";
|
||||||
try {
|
try {
|
||||||
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.hasLoadBalancerService());
|
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.hasLoadBalancerService());
|
||||||
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network, client, jobComplete,
|
Long defaultTemplate = (imageId != null && !"".equals(imageId)) ? new Long(imageId) : null;
|
||||||
|
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network,
|
||||||
|
defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()), client, jobComplete,
|
||||||
virtualMachineRunning);
|
virtualMachineRunning);
|
||||||
if (vm.getPassword() != null)
|
if (vm.getPassword() != null)
|
||||||
password = vm.getPassword();
|
password = vm.getPassword();
|
||||||
|
|
|
@ -27,7 +27,6 @@ import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
|
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
|
||||||
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
|
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
|
||||||
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
|
import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue;
|
||||||
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;
|
||||||
|
|
|
@ -18,27 +18,14 @@
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
|
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
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.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.domain.Credentials;
|
|
||||||
import org.jclouds.net.IPSocket;
|
|
||||||
import org.jclouds.ssh.SshClient;
|
|
||||||
import org.testng.annotations.AfterGroups;
|
|
||||||
import org.testng.annotations.BeforeGroups;
|
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,79 +35,6 @@ import org.testng.annotations.Test;
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", singleThreaded = true, testName = "NATClientLiveTest")
|
@Test(groups = "live", singleThreaded = true, testName = "NATClientLiveTest")
|
||||||
public class NATClientLiveTest extends BaseCloudStackClientLiveTest {
|
public class NATClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
private PublicIPAddress ip = null;
|
|
||||||
private VirtualMachine vm;
|
|
||||||
private IPForwardingRule rule;
|
|
||||||
private Network network;
|
|
||||||
private boolean networksDisabled;
|
|
||||||
|
|
||||||
@BeforeGroups(groups = "live")
|
|
||||||
public void setupClient() {
|
|
||||||
super.setupClient();
|
|
||||||
prefix += "nat";
|
|
||||||
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
|
|
||||||
if (ip.getVirtualMachineId() > 0 && ip.getVirtualMachineId() != vm.getId())
|
|
||||||
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);
|
|
||||||
assert jobComplete.apply(job.getJobId());
|
|
||||||
rule = client.getNATClient().getIPForwardingRule(job.getId());
|
|
||||||
assertEquals(rule.getIPAddressId(), ip.getId());
|
|
||||||
assertEquals(rule.getVirtualMachineId(), vm.getId());
|
|
||||||
assertEquals(rule.getStartPort(), 22);
|
|
||||||
assertEquals(rule.getProtocol(), "tcp");
|
|
||||||
checkRule(rule);
|
|
||||||
IPSocket socket = 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")
|
|
||||||
protected void tearDown() {
|
|
||||||
if (rule != null) {
|
|
||||||
client.getNATClient().deleteIPForwardingRule(rule.getId());
|
|
||||||
}
|
|
||||||
if (vm != null) {
|
|
||||||
jobComplete.apply(client.getVirtualMachineClient().destroyVirtualMachine(vm.getId()));
|
|
||||||
}
|
|
||||||
if (ip != null) {
|
|
||||||
client.getAddressClient().disassociateIPAddress(ip.getId());
|
|
||||||
}
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(enabled = false)
|
@Test(enabled = false)
|
||||||
// takes too long
|
// takes too long
|
||||||
|
|
|
@ -169,8 +169,10 @@ public class SecurityGroupClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
public void testCreateVMInSecurityGroup() throws Exception {
|
public void testCreateVMInSecurityGroup() throws Exception {
|
||||||
if (!securityGroupsSupported)
|
if (!securityGroupsSupported)
|
||||||
return;
|
return;
|
||||||
vm = VirtualMachineClientLiveTest.createVirtualMachineWithSecurityGroupInZone(zone.getId(), group.getId(),
|
Long defaultTemplate = (imageId != null && !"".equals(imageId)) ? new Long(imageId) : null;
|
||||||
client, jobComplete, virtualMachineRunning);
|
vm = VirtualMachineClientLiveTest.createVirtualMachineWithSecurityGroupInZone(zone.getId(),
|
||||||
|
defaultTemplateOrPreferredInZone(defaultTemplate, client, zone.getId()), group.getId(), client,
|
||||||
|
jobComplete, virtualMachineRunning);
|
||||||
if (vm.getPassword() != null)
|
if (vm.getPassword() != null)
|
||||||
password = vm.getPassword();
|
password = vm.getPassword();
|
||||||
// ingress port 22
|
// ingress port 22
|
||||||
|
|
|
@ -20,14 +20,12 @@ package org.jclouds.cloudstack.features;
|
||||||
|
|
||||||
import static com.google.common.base.Predicates.equalTo;
|
import static com.google.common.base.Predicates.equalTo;
|
||||||
import static com.google.common.base.Predicates.or;
|
import static com.google.common.base.Predicates.or;
|
||||||
import static com.google.common.collect.Iterables.filter;
|
|
||||||
import static com.google.common.collect.Iterables.find;
|
import static com.google.common.collect.Iterables.find;
|
||||||
import static com.google.common.collect.Iterables.get;
|
import static com.google.common.collect.Iterables.get;
|
||||||
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.NoSuchElementException;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
@ -37,15 +35,10 @@ import org.jclouds.cloudstack.domain.AsyncJob;
|
||||||
import org.jclouds.cloudstack.domain.NIC;
|
import org.jclouds.cloudstack.domain.NIC;
|
||||||
import org.jclouds.cloudstack.domain.Network;
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
import org.jclouds.cloudstack.domain.ServiceOffering;
|
import org.jclouds.cloudstack.domain.ServiceOffering;
|
||||||
import org.jclouds.cloudstack.domain.Template;
|
|
||||||
import org.jclouds.cloudstack.domain.VirtualMachine;
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
import org.jclouds.cloudstack.domain.Zone;
|
import org.jclouds.cloudstack.domain.Zone;
|
||||||
import org.jclouds.cloudstack.options.DeployVirtualMachineOptions;
|
import org.jclouds.cloudstack.options.DeployVirtualMachineOptions;
|
||||||
import org.jclouds.cloudstack.options.ListTemplatesOptions;
|
|
||||||
import org.jclouds.cloudstack.options.ListVirtualMachinesOptions;
|
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.net.IPSocket;
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
import org.jclouds.util.InetAddresses2;
|
import org.jclouds.util.InetAddresses2;
|
||||||
|
@ -53,11 +46,8 @@ 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.Predicates;
|
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.ComparisonChain;
|
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.collect.Ordering;
|
||||||
import com.google.common.net.HostSpecifier;
|
import com.google.common.net.HostSpecifier;
|
||||||
|
|
||||||
|
@ -77,61 +67,50 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static VirtualMachine createVirtualMachine(CloudStackClient client, RetryablePredicate<Long> jobComplete,
|
public static VirtualMachine createVirtualMachine(CloudStackClient client, Long defaultTemplate,
|
||||||
RetryablePredicate<VirtualMachine> virtualMachineRunning) {
|
RetryablePredicate<Long> jobComplete, RetryablePredicate<VirtualMachine> virtualMachineRunning) {
|
||||||
Set<Network> networks = client.getNetworkClient().listNetworks();
|
Set<Network> networks = client.getNetworkClient().listNetworks();
|
||||||
if (networks.size() > 0) {
|
if (networks.size() > 0) {
|
||||||
return createVirtualMachineInNetwork(get(networks, 0), client, jobComplete, virtualMachineRunning);
|
Network network = get(networks, 0);
|
||||||
|
return createVirtualMachineInNetwork(network,
|
||||||
|
defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()), client, jobComplete,
|
||||||
|
virtualMachineRunning);
|
||||||
} else {
|
} else {
|
||||||
return createVirtualMachineWithSecurityGroupInZone(
|
long zoneId = find(client.getZoneClient().listZones(), new Predicate<Zone>() {
|
||||||
find(client.getZoneClient().listZones(), new Predicate<Zone>() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Zone arg0) {
|
public boolean apply(Zone arg0) {
|
||||||
return arg0.isSecurityGroupsEnabled();
|
return arg0.isSecurityGroupsEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
}).getId(), get(client.getSecurityGroupClient().listSecurityGroups(), 0).getId(), client, jobComplete,
|
}).getId();
|
||||||
|
return createVirtualMachineWithSecurityGroupInZone(zoneId,
|
||||||
|
defaultTemplateOrPreferredInZone(defaultTemplate, client, zoneId),
|
||||||
|
get(client.getSecurityGroupClient().listSecurityGroups(), 0).getId(), client, jobComplete,
|
||||||
virtualMachineRunning);
|
virtualMachineRunning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VirtualMachine createVirtualMachineWithSecurityGroupInZone(long zoneId, long groupId,
|
public static VirtualMachine createVirtualMachineWithSecurityGroupInZone(long zoneId, long templateId, long groupId,
|
||||||
CloudStackClient client, RetryablePredicate<Long> jobComplete,
|
CloudStackClient client, RetryablePredicate<Long> jobComplete,
|
||||||
RetryablePredicate<VirtualMachine> virtualMachineRunning) {
|
RetryablePredicate<VirtualMachine> virtualMachineRunning) {
|
||||||
return createVirtualMachineWithOptionsInZone(new DeployVirtualMachineOptions().securityGroupId(groupId), zoneId,
|
return createVirtualMachineWithOptionsInZone(new DeployVirtualMachineOptions().securityGroupId(groupId), zoneId,
|
||||||
client, jobComplete, virtualMachineRunning);
|
templateId, client, jobComplete, virtualMachineRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VirtualMachine createVirtualMachineInNetwork(Network network, CloudStackClient client,
|
public static VirtualMachine createVirtualMachineInNetwork(Network network, long templateId,
|
||||||
RetryablePredicate<Long> jobComplete, RetryablePredicate<VirtualMachine> virtualMachineRunning) {
|
CloudStackClient client, RetryablePredicate<Long> jobComplete,
|
||||||
|
RetryablePredicate<VirtualMachine> virtualMachineRunning) {
|
||||||
DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
|
DeployVirtualMachineOptions options = new DeployVirtualMachineOptions();
|
||||||
long zoneId = network.getZoneId();
|
long zoneId = network.getZoneId();
|
||||||
options.networkId(network.getId());
|
options.networkId(network.getId());
|
||||||
return createVirtualMachineWithOptionsInZone(options, zoneId, client, jobComplete, virtualMachineRunning);
|
return createVirtualMachineWithOptionsInZone(options, zoneId, templateId, client, jobComplete,
|
||||||
|
virtualMachineRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static VirtualMachine createVirtualMachineWithOptionsInZone(DeployVirtualMachineOptions options,
|
public static VirtualMachine createVirtualMachineWithOptionsInZone(DeployVirtualMachineOptions options, long zoneId,
|
||||||
final long zoneId, CloudStackClient client, RetryablePredicate<Long> jobComplete,
|
long templateId, CloudStackClient client, RetryablePredicate<Long> jobComplete,
|
||||||
RetryablePredicate<VirtualMachine> virtualMachineRunning) {
|
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);
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
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();
|
long serviceOfferingId = DEFAULT_SIZE_ORDERING.min(client.getOfferingClient().listServiceOfferings()).getId();
|
||||||
|
|
||||||
System.out.printf("serviceOfferingId %d, templateId %d, zoneId %d, options %s%n", serviceOfferingId, templateId,
|
System.out.printf("serviceOfferingId %d, templateId %d, zoneId %d, options %s%n", serviceOfferingId, templateId,
|
||||||
|
@ -158,7 +137,8 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void testCreateVirtualMachine() throws Exception {
|
public void testCreateVirtualMachine() throws Exception {
|
||||||
vm = createVirtualMachine(client, jobComplete, virtualMachineRunning);
|
Long templateId = (imageId != null && !"".equals(imageId)) ? new Long(imageId) : null;
|
||||||
|
vm = createVirtualMachine(client, templateId, jobComplete, virtualMachineRunning);
|
||||||
if (vm.getPassword() != null) {
|
if (vm.getPassword() != null) {
|
||||||
conditionallyCheckSSH();
|
conditionallyCheckSSH();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.cloudstack.functions;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.find;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import org.jclouds.cloudstack.compute.config.CloudStackComputeServiceContextModule.GetIPForwardingRuleByVirtualMachine;
|
||||||
|
import org.jclouds.cloudstack.domain.IPForwardingRule;
|
||||||
|
import org.jclouds.cloudstack.domain.Network;
|
||||||
|
import org.jclouds.cloudstack.domain.PublicIPAddress;
|
||||||
|
import org.jclouds.cloudstack.domain.VirtualMachine;
|
||||||
|
import org.jclouds.cloudstack.features.NATClientLiveTest;
|
||||||
|
import org.jclouds.cloudstack.features.VirtualMachineClientLiveTest;
|
||||||
|
import org.jclouds.cloudstack.predicates.NetworkPredicates;
|
||||||
|
import org.jclouds.compute.domain.ExecResponse;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.net.IPSocket;
|
||||||
|
import org.jclouds.ssh.SshClient;
|
||||||
|
import org.testng.annotations.AfterGroups;
|
||||||
|
import org.testng.annotations.BeforeGroups;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests behavior of {@code StaticNATVirtualMachineInNetwork}
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", singleThreaded = true, testName = "StaticNATVirtualMachineInNetworkLiveTest")
|
||||||
|
public class StaticNATVirtualMachineInNetworkLiveTest extends NATClientLiveTest {
|
||||||
|
private PublicIPAddress ip = null;
|
||||||
|
private VirtualMachine vm;
|
||||||
|
private IPForwardingRule rule;
|
||||||
|
private Network network;
|
||||||
|
private boolean networksDisabled;
|
||||||
|
|
||||||
|
@BeforeGroups(groups = "live")
|
||||||
|
public void setupClient() {
|
||||||
|
super.setupClient();
|
||||||
|
prefix += "nat";
|
||||||
|
try {
|
||||||
|
network = find(client.getNetworkClient().listNetworks(), NetworkPredicates.supportsStaticNAT());
|
||||||
|
Long defaultTemplate = (imageId != null && !"".equals(imageId)) ? new Long(imageId) : null;
|
||||||
|
vm = VirtualMachineClientLiveTest.createVirtualMachineInNetwork(network,
|
||||||
|
defaultTemplateOrPreferredInZone(defaultTemplate, client, network.getZoneId()), client, jobComplete,
|
||||||
|
virtualMachineRunning);
|
||||||
|
if (vm.getPassword() != null)
|
||||||
|
password = vm.getPassword();
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
networksDisabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCreateIPForwardingRule() throws Exception {
|
||||||
|
if (networksDisabled)
|
||||||
|
return;
|
||||||
|
ip = new StaticNATVirtualMachineInNetwork(client, reuseOrAssociate, jobComplete, CacheBuilder.newBuilder()
|
||||||
|
.<Long, IPForwardingRule> build(new GetIPForwardingRuleByVirtualMachine(client)), network).apply(vm);
|
||||||
|
|
||||||
|
rule = client.getNATClient().getIPForwardingRuleForIPAddress(ip.getId());
|
||||||
|
assertEquals(rule.getIPAddressId(), ip.getId());
|
||||||
|
assertEquals(rule.getVirtualMachineId(), vm.getId());
|
||||||
|
assertEquals(rule.getStartPort(), 22);
|
||||||
|
assertEquals(rule.getProtocol(), "tcp");
|
||||||
|
checkRule(rule);
|
||||||
|
IPSocket socket = 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")
|
||||||
|
protected void tearDown() {
|
||||||
|
if (rule != null) {
|
||||||
|
client.getNATClient().deleteIPForwardingRule(rule.getId());
|
||||||
|
}
|
||||||
|
if (vm != null) {
|
||||||
|
jobComplete.apply(client.getVirtualMachineClient().destroyVirtualMachine(vm.getId()));
|
||||||
|
}
|
||||||
|
if (ip != null) {
|
||||||
|
client.getAddressClient().disassociateIPAddress(ip.getId());
|
||||||
|
}
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -75,6 +75,17 @@ public class CloudStackErrorHandlerTest {
|
||||||
IllegalStateException.class);
|
IllegalStateException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test431MakesResourceNotFoundExceptionOnDelete() {
|
||||||
|
assertCodeMakes(
|
||||||
|
"GET",
|
||||||
|
URI.create("https://api.ninefold.com/compute/v1.0/?response=json&command=deleteSSHKeyPair"),
|
||||||
|
431,
|
||||||
|
"",
|
||||||
|
"{ \"deletekeypairresponse\" : {\"errorcode\" : 431, \"errortext\" : \"A key pair with name 'adriancole-adapter-test-keypair' does not exist for account jclouds in domain id=457\"} }",
|
||||||
|
ResourceNotFoundException.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test409MakesIllegalStateException() {
|
public void test409MakesIllegalStateException() {
|
||||||
assertCodeMakes("GET", URI.create("https://cloudstack.com/foo"), 409, "", "Conflict", IllegalStateException.class);
|
assertCodeMakes("GET", URI.create("https://cloudstack.com/foo"), 409, "", "Conflict", IllegalStateException.class);
|
||||||
|
|
Loading…
Reference in New Issue