mirror of https://github.com/apache/jclouds.git
Issue 130: added options to runNode like openPorts and runScript; added ability to specify alternate endpoint in *ContextBuilderFactory; updated ant tasks to use new node features; Issue 112: normalized vcloud clients
git-svn-id: http://jclouds.googlecode.com/svn/trunk@2712 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
parent
1d2b1495a2
commit
cb906ded3c
|
@ -21,12 +21,12 @@ package org.jclouds.aws.ec2.compute;
|
||||||
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 org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withKeyName;
|
import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withKeyName;
|
||||||
import static org.jclouds.scriptbuilder.domain.Statements.exec;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -41,6 +41,7 @@ import org.jclouds.aws.ec2.domain.InstanceState;
|
||||||
import org.jclouds.aws.ec2.domain.IpProtocol;
|
import org.jclouds.aws.ec2.domain.IpProtocol;
|
||||||
import org.jclouds.aws.ec2.domain.KeyPair;
|
import org.jclouds.aws.ec2.domain.KeyPair;
|
||||||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
|
import org.jclouds.aws.ec2.options.RunInstancesOptions;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.domain.Architecture;
|
import org.jclouds.compute.domain.Architecture;
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
|
@ -54,11 +55,10 @@ import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
|
import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
|
||||||
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
||||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
||||||
|
import org.jclouds.compute.options.RunNodeOptions;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.scriptbuilder.ScriptBuilder;
|
|
||||||
import org.jclouds.scriptbuilder.domain.OsFamily;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
@ -76,14 +76,14 @@ public class EC2ComputeService implements ComputeService {
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
private final EC2Client ec2Client;
|
private final EC2Client ec2Client;
|
||||||
private final Set<EC2Size> sizes;
|
private final SortedSet<EC2Size> sizes;
|
||||||
private final Provider<Set<EC2Template>> templates;
|
private final Provider<Set<EC2Template>> templates;
|
||||||
private final Predicate<RunningInstance> instanceStateRunning;
|
private final Predicate<RunningInstance> instanceStateRunning;
|
||||||
private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
|
private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
|
||||||
private final Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap;
|
private final Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public EC2ComputeService(EC2Client client, Set<EC2Size> sizes,
|
public EC2ComputeService(EC2Client client, SortedSet<EC2Size> sizes,
|
||||||
Provider<Set<EC2Template>> templates,
|
Provider<Set<EC2Template>> templates,
|
||||||
Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap,
|
Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap,
|
||||||
Predicate<RunningInstance> instanceStateRunning,
|
Predicate<RunningInstance> instanceStateRunning,
|
||||||
|
@ -103,34 +103,34 @@ public class EC2ComputeService implements ComputeService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CreateNodeResponse runNode(String name, Template template) {
|
public CreateNodeResponse runNode(String name, Template template) {
|
||||||
|
return this.runNode(name, template, RunNodeOptions.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
|
||||||
checkArgument(template instanceof EC2Template,
|
checkArgument(template instanceof EC2Template,
|
||||||
"unexpected template type. should be EC2Template, was: " + template.getClass());
|
"unexpected template type. should be EC2Template, was: " + template.getClass());
|
||||||
EC2Template ec2Template = (EC2Template) template;
|
EC2Template ec2Template = (EC2Template) template;
|
||||||
|
|
||||||
KeyPair keyPair = createKeyPairInRegion(ec2Template.getRegion(), name);
|
KeyPair keyPair = createKeyPairInRegion(ec2Template.getRegion(), name);
|
||||||
String securityGroupName = name;
|
String securityGroupName = name;
|
||||||
createSecurityGroupInRegion(ec2Template.getRegion(), securityGroupName, 22, 80, 8080, 443);
|
createSecurityGroupInRegion(ec2Template.getRegion(), securityGroupName, options
|
||||||
|
.getOpenPorts());
|
||||||
String script = new ScriptBuilder() // update and install jdk
|
|
||||||
.addStatement(exec("apt-get update"))//
|
|
||||||
.addStatement(exec("apt-get upgrade -y"))//
|
|
||||||
.addStatement(exec("apt-get install -y openjdk-6-jdk"))//
|
|
||||||
.addStatement(exec("wget -qO/usr/bin/runurl run.alestic.com/runurl"))//
|
|
||||||
.addStatement(exec("chmod 755 /usr/bin/runurl"))//
|
|
||||||
.build(OsFamily.UNIX);
|
|
||||||
|
|
||||||
logger.debug(">> running instance region(%s) ami(%s) type(%s) keyPair(%s) securityGroup(%s)",
|
logger.debug(">> running instance region(%s) ami(%s) type(%s) keyPair(%s) securityGroup(%s)",
|
||||||
ec2Template.getRegion(), ec2Template.getImage().getId(), ec2Template.getSize()
|
ec2Template.getRegion(), ec2Template.getImage().getId(), ec2Template.getSize()
|
||||||
.getInstanceType(), keyPair.getKeyName(), securityGroupName);
|
.getInstanceType(), keyPair.getKeyName(), securityGroupName);
|
||||||
|
RunInstancesOptions instanceOptions = withKeyName(keyPair.getKeyName())// key
|
||||||
|
.asType(ec2Template.getSize().getInstanceType())// instance size
|
||||||
|
.withSecurityGroup(securityGroupName)// group I created above
|
||||||
|
.withAdditionalInfo(name);
|
||||||
|
|
||||||
|
if (options.getRunScript() != null)
|
||||||
|
instanceOptions.withUserData(options.getRunScript());
|
||||||
|
|
||||||
RunningInstance runningInstance = Iterables.getOnlyElement(ec2Client.getInstanceServices()
|
RunningInstance runningInstance = Iterables.getOnlyElement(ec2Client.getInstanceServices()
|
||||||
.runInstancesInRegion(ec2Template.getRegion(), null, ec2Template.getImage().getId(),
|
.runInstancesInRegion(ec2Template.getRegion(), null, ec2Template.getImage().getId(),
|
||||||
1, 1, withKeyName(keyPair.getKeyName())// key
|
1, 1, instanceOptions));
|
||||||
.asType(ec2Template.getSize().getInstanceType())// instance size
|
|
||||||
.withSecurityGroup(securityGroupName)// group I created above
|
|
||||||
.withAdditionalInfo(name)// description
|
|
||||||
.withUserData(script.getBytes()) // script to run as root
|
|
||||||
));
|
|
||||||
logger.debug("<< started instance(%s)", runningInstance.getId());
|
logger.debug("<< started instance(%s)", runningInstance.getId());
|
||||||
instanceStateRunning.apply(runningInstance);
|
instanceStateRunning.apply(runningInstance);
|
||||||
logger.debug("<< running instance(%s)", runningInstance.getId());
|
logger.debug("<< running instance(%s)", runningInstance.getId());
|
||||||
|
@ -316,7 +316,7 @@ public class EC2ComputeService implements ComputeService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<EC2Size> listSizes() {
|
public SortedSet<EC2Size> listSizes() {
|
||||||
return sizes;
|
return sizes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.jclouds.aws.ec2.compute.config;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -43,7 +44,7 @@ import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSortedSet;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
@ -69,8 +70,8 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
Set<EC2Size> provideSizes() {
|
SortedSet<EC2Size> provideSizes() {
|
||||||
return ImmutableSet.<EC2Size> of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
|
return ImmutableSortedSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE,
|
||||||
EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE);
|
EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +83,7 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
Set<EC2Template> provideTemplates(EC2Client client, Set<EC2Size> sizes,
|
Set<EC2Template> provideTemplates(EC2Client client, SortedSet<EC2Size> sizes,
|
||||||
Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap,
|
Map<Architecture, Map<OperatingSystem, Map<Region, String>>> imageAmiIdMap,
|
||||||
LogHolder holder) {
|
LogHolder holder) {
|
||||||
Set<EC2Template> templates = Sets.newHashSet();
|
Set<EC2Template> templates = Sets.newHashSet();
|
||||||
|
|
|
@ -18,43 +18,13 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.aws.ec2.compute;
|
package org.jclouds.aws.ec2.compute;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static org.jclouds.compute.domain.OperatingSystem.UBUNTU;
|
import static org.jclouds.compute.domain.OperatingSystem.UBUNTU;
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
import static org.testng.Assert.assertNotNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.jclouds.compute.BaseComputeServiceLiveTest;
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeService;
|
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
|
||||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
|
||||||
import org.jclouds.compute.domain.ComputeType;
|
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.LoginType;
|
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
|
||||||
import org.jclouds.compute.domain.Size;
|
|
||||||
import org.jclouds.compute.domain.Template;
|
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
|
||||||
import org.jclouds.predicates.SocketOpen;
|
|
||||||
import org.jclouds.ssh.ExecResponse;
|
|
||||||
import org.jclouds.ssh.SshClient;
|
|
||||||
import org.jclouds.ssh.SshException;
|
|
||||||
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
import org.testng.annotations.AfterTest;
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.BeforeGroups;
|
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Generally disabled, as it incurs higher fees.
|
* Generally disabled, as it incurs higher fees.
|
||||||
|
@ -62,115 +32,17 @@ import com.google.inject.Injector;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", enabled = true, sequential = true, testName = "ec2.EC2ComputeServiceLiveTest")
|
@Test(groups = "live", enabled = true, sequential = true, testName = "ec2.EC2ComputeServiceLiveTest")
|
||||||
public class EC2ComputeServiceLiveTest {
|
public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
||||||
private static final String service = "ec2";
|
@BeforeClass
|
||||||
|
@Override
|
||||||
protected SshClient.Factory sshFactory;
|
public void setServiceDefaults() {
|
||||||
private String nodeName = System.getProperty("user.name") + service;
|
service = "ec2";
|
||||||
|
testOS = UBUNTU;
|
||||||
private RetryablePredicate<InetSocketAddress> socketTester;
|
|
||||||
private CreateNodeResponse node;
|
|
||||||
private ComputeServiceContext context;
|
|
||||||
private ComputeService client;
|
|
||||||
|
|
||||||
@BeforeGroups(groups = { "live" })
|
|
||||||
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
|
|
||||||
IOException {
|
|
||||||
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
|
||||||
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
|
||||||
context = new ComputeServiceContextFactory().createContext(service, user, password,
|
|
||||||
ImmutableSet.of(new Log4JLoggingModule()), new Properties());
|
|
||||||
Injector injector = Guice.createInjector(new JschSshClientModule());
|
|
||||||
sshFactory = injector.getInstance(SshClient.Factory.class);
|
|
||||||
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
|
|
||||||
socketTester = new RetryablePredicate<InetSocketAddress>(socketOpen, 60, 1, TimeUnit.SECONDS);
|
|
||||||
injector.injectMembers(socketOpen); // add logger
|
|
||||||
client = context.getComputeService();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreate() throws Exception {
|
@Override
|
||||||
Template template = client.createTemplateInLocation("default").os(UBUNTU).smallest();
|
protected JschSshClientModule getSshModule() {
|
||||||
node = client.runNode(nodeName, template);
|
return new JschSshClientModule();
|
||||||
assertNotNull(node.getId());
|
|
||||||
assertEquals(node.getLoginPort(), 22);
|
|
||||||
assertEquals(node.getLoginType(), LoginType.SSH);
|
|
||||||
assertNotNull(node.getName());
|
|
||||||
assertEquals(node.getPrivateAddresses().size(), 1);
|
|
||||||
assertEquals(node.getPublicAddresses().size(), 1);
|
|
||||||
assertNotNull(node.getCredentials());
|
|
||||||
assertNotNull(node.getCredentials().account);
|
|
||||||
assertNotNull(node.getCredentials().key);
|
|
||||||
sshPing();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testCreate")
|
|
||||||
public void testGet() throws Exception {
|
|
||||||
NodeMetadata metadata = client.getNodeMetadata(node);
|
|
||||||
assertEquals(metadata.getId(), node.getId());
|
|
||||||
assertEquals(metadata.getLoginPort(), node.getLoginPort());
|
|
||||||
assertEquals(metadata.getLoginType(), node.getLoginType());
|
|
||||||
assertEquals(metadata.getName(), node.getName());
|
|
||||||
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
|
|
||||||
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testList() throws Exception {
|
|
||||||
for (ComputeMetadata node : client.listNodes()) {
|
|
||||||
assert node.getId() != null;
|
|
||||||
assert node.getLocation() != null;
|
|
||||||
assertEquals(node.getType(), ComputeType.NODE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testListTemplates() throws Exception {
|
|
||||||
for (Template template : client.listTemplates()) {
|
|
||||||
assert template.getImage() != null;
|
|
||||||
System.out.println(template);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testListSizes() throws Exception {
|
|
||||||
for (Size size : client.listSizes()) {
|
|
||||||
assert size.getCores() != null;
|
|
||||||
System.out.println(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sshPing() throws IOException {
|
|
||||||
try {
|
|
||||||
doCheckKey();
|
|
||||||
} catch (SshException e) {// try twice in case there is a network timeout
|
|
||||||
try {
|
|
||||||
Thread.sleep(10 * 1000);
|
|
||||||
} catch (InterruptedException e1) {
|
|
||||||
}
|
|
||||||
doCheckKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doCheckKey() throws IOException {
|
|
||||||
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), node
|
|
||||||
.getLoginPort());
|
|
||||||
socketTester.apply(socket);
|
|
||||||
SshClient ssh = node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----") ? sshFactory
|
|
||||||
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
|
|
||||||
: sshFactory
|
|
||||||
.create(socket, node.getCredentials().account, node.getCredentials().key);
|
|
||||||
try {
|
|
||||||
ssh.connect();
|
|
||||||
ExecResponse hello = ssh.exec("echo hello");
|
|
||||||
assertEquals(hello.getOutput().trim(), "hello");
|
|
||||||
} finally {
|
|
||||||
if (ssh != null)
|
|
||||||
ssh.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterTest
|
|
||||||
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
|
|
||||||
if (node != null)
|
|
||||||
client.destroyNode(node);
|
|
||||||
context.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
|
||||||
*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*/
|
|
||||||
package org.jclouds.blobstore;
|
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.jclouds.blobstore.reference.BlobStoreConstants;
|
|
||||||
import org.jclouds.http.HttpPropertiesBuilder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds properties used in Blob Stores
|
|
||||||
*
|
|
||||||
* @author Adrian Cole, Andrew Newdigate
|
|
||||||
*/
|
|
||||||
public class BlobStorePropertiesBuilder extends HttpPropertiesBuilder {
|
|
||||||
|
|
||||||
protected BlobStorePropertiesBuilder() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BlobStorePropertiesBuilder(Properties properties) {
|
|
||||||
super(properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* longest time a single synchronous operation can take before throwing an exception.
|
|
||||||
*/
|
|
||||||
public BlobStorePropertiesBuilder withRequestTimeout(long milliseconds) {
|
|
||||||
properties.setProperty(BlobStoreConstants.PROPERTY_BLOBSTORE_TIMEOUT, Long
|
|
||||||
.toString(milliseconds));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.blobstore.integration;
|
package org.jclouds.blobstore.integration;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.http.HttpPropertiesBuilder;
|
import org.jclouds.http.HttpPropertiesBuilder;
|
||||||
|
@ -37,4 +38,14 @@ public class StubPropertiesBuilder extends HttpPropertiesBuilder {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpPropertiesBuilder withCredentials(String account, String key) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpPropertiesBuilder withEndpoint(URI endpoint) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,11 @@
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-scriptbuilder</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>jclouds-core</artifactId>
|
<artifactId>jclouds-core</artifactId>
|
||||||
|
@ -52,5 +57,17 @@
|
||||||
<type>test-jar</type>
|
<type>test-jar</type>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-log4j</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>log4j</groupId>
|
||||||
|
<artifactId>log4j</artifactId>
|
||||||
|
<version>1.2.14</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -19,12 +19,14 @@
|
||||||
package org.jclouds.compute;
|
package org.jclouds.compute;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
import org.jclouds.compute.domain.CreateNodeResponse;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
|
import org.jclouds.compute.options.RunNodeOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides portable access to launching compute instances.
|
* Provides portable access to launching compute instances.
|
||||||
|
@ -44,7 +46,12 @@ public interface ComputeService {
|
||||||
/**
|
/**
|
||||||
* List all sizes available to the current user
|
* List all sizes available to the current user
|
||||||
*/
|
*/
|
||||||
Set<? extends Size> listSizes();
|
SortedSet<? extends Size> listSizes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List all images available to the current user
|
||||||
|
*/
|
||||||
|
// Set<? extends Image> listImages();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List all templates available to the current user
|
* List all templates available to the current user
|
||||||
|
@ -61,6 +68,7 @@ public interface ComputeService {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
CreateNodeResponse runNode(String name, Template template);
|
CreateNodeResponse runNode(String name, Template template);
|
||||||
|
CreateNodeResponse runNode(String name, Template template, RunNodeOptions options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* destroy the node.
|
* destroy the node.
|
||||||
|
|
|
@ -29,6 +29,5 @@ package org.jclouds.compute.domain;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public enum OperatingSystem {
|
public enum OperatingSystem {
|
||||||
|
CENTOS, RHEL, UBUNTU, JEOS, WINDOWS, UNKNOWN;
|
||||||
CENTOS, RHEL, UBUNTU, WINDOWS, UNKNOWN;
|
|
||||||
}
|
}
|
|
@ -33,17 +33,17 @@ public interface Size extends Comparable<Size> {
|
||||||
/**
|
/**
|
||||||
* Amount of virtual or physical cores provided
|
* Amount of virtual or physical cores provided
|
||||||
*/
|
*/
|
||||||
Integer getCores();
|
int getCores();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Amount of RAM provided in MB (256M, 1740)
|
* Amount of RAM provided in MB (256M, 1740)
|
||||||
*/
|
*/
|
||||||
Integer getRam();
|
int getRam();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Amount of boot disk provided in GB (200)
|
* Amount of boot disk provided in GB (200)
|
||||||
*/
|
*/
|
||||||
Integer getDisk();
|
int getDisk();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines platforms this can support
|
* Determines platforms this can support
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Set;
|
||||||
import org.jclouds.compute.domain.Architecture;
|
import org.jclouds.compute.domain.Architecture;
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
|
|
||||||
|
import com.google.common.collect.ComparisonChain;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
@ -31,13 +32,12 @@ import com.google.common.collect.Sets;
|
||||||
*/
|
*/
|
||||||
public class SizeImpl implements Size {
|
public class SizeImpl implements Size {
|
||||||
|
|
||||||
private final Integer cores;
|
private final int cores;
|
||||||
private final Integer ram;
|
private final int ram;
|
||||||
private final Integer disk;
|
private final int disk;
|
||||||
private final Set<Architecture> supportedArchitectures = Sets.newHashSet();
|
private final Set<Architecture> supportedArchitectures = Sets.newHashSet();
|
||||||
|
|
||||||
public SizeImpl(Integer cores, Integer ram, Integer disk,
|
public SizeImpl(int cores, int ram, int disk, Iterable<Architecture> supportedArchitectures) {
|
||||||
Iterable<Architecture> supportedArchitectures) {
|
|
||||||
this.cores = cores;
|
this.cores = cores;
|
||||||
this.ram = ram;
|
this.ram = ram;
|
||||||
this.disk = disk;
|
this.disk = disk;
|
||||||
|
@ -48,7 +48,7 @@ public class SizeImpl implements Size {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Integer getCores() {
|
public int getCores() {
|
||||||
return cores;
|
return cores;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ public class SizeImpl implements Size {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Integer getRam() {
|
public int getRam() {
|
||||||
return ram;
|
return ram;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ public class SizeImpl implements Size {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Integer getDisk() {
|
public int getDisk() {
|
||||||
return disk;
|
return disk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,9 +72,9 @@ public class SizeImpl implements Size {
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + ((cores == null) ? 0 : cores.hashCode());
|
result = prime * result + cores;
|
||||||
result = prime * result + ((disk == null) ? 0 : disk.hashCode());
|
result = prime * result + disk;
|
||||||
result = prime * result + ((ram == null) ? 0 : ram.hashCode());
|
result = prime * result + ram;
|
||||||
result = prime * result
|
result = prime * result
|
||||||
+ ((supportedArchitectures == null) ? 0 : supportedArchitectures.hashCode());
|
+ ((supportedArchitectures == null) ? 0 : supportedArchitectures.hashCode());
|
||||||
return result;
|
return result;
|
||||||
|
@ -89,20 +89,11 @@ public class SizeImpl implements Size {
|
||||||
if (getClass() != obj.getClass())
|
if (getClass() != obj.getClass())
|
||||||
return false;
|
return false;
|
||||||
SizeImpl other = (SizeImpl) obj;
|
SizeImpl other = (SizeImpl) obj;
|
||||||
if (cores == null) {
|
if (cores != other.cores)
|
||||||
if (other.cores != null)
|
|
||||||
return false;
|
return false;
|
||||||
} else if (!cores.equals(other.cores))
|
if (disk != other.disk)
|
||||||
return false;
|
return false;
|
||||||
if (disk == null) {
|
if (ram != other.ram)
|
||||||
if (other.disk != null)
|
|
||||||
return false;
|
|
||||||
} else if (!disk.equals(other.disk))
|
|
||||||
return false;
|
|
||||||
if (ram == null) {
|
|
||||||
if (other.ram != null)
|
|
||||||
return false;
|
|
||||||
} else if (!ram.equals(other.ram))
|
|
||||||
return false;
|
return false;
|
||||||
if (supportedArchitectures == null) {
|
if (supportedArchitectures == null) {
|
||||||
if (other.supportedArchitectures != null)
|
if (other.supportedArchitectures != null)
|
||||||
|
@ -112,20 +103,17 @@ public class SizeImpl implements Size {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public int compareTo(Size that) {
|
||||||
* {@inheritDoc}
|
return ComparisonChain.start().compare(this.getCores(), that.getCores()).compare(
|
||||||
*/
|
this.getRam(), that.getRam()).compare(this.getDisk(), that.getDisk()).result();
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "SizeImpl [cores=" + cores + ", disk=" + disk + ", ram=" + ram + "]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Size o) {
|
public String toString() {
|
||||||
return (this == o) ? 0 : getCores().compareTo(o.getCores());
|
return "Size [cores=" + cores + ", disk=" + disk + ", ram=" + ram + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
package org.jclouds.compute.options;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains options supported in the {@code ComputeService#runNode} operation. <h2>
|
||||||
|
* Usage</h2> The recommended way to instantiate a RunOptions object is to statically import
|
||||||
|
* RunOptions.* and invoke a static creation method followed by an instance mutator (if needed):
|
||||||
|
* <p/>
|
||||||
|
* <code>
|
||||||
|
* import static org.jclouds.compute.options.RunOptions.Builder.*
|
||||||
|
* <p/>
|
||||||
|
* ComputeService client = // get connection
|
||||||
|
* CreateNodeResponse client.runNode(name, template, openPorts(22, 80, 8080, 443));
|
||||||
|
* <code>
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class RunNodeOptions {
|
||||||
|
|
||||||
|
public static final RunNodeOptions NONE = new RunNodeOptions();
|
||||||
|
|
||||||
|
private int[] openPorts = new int[0];
|
||||||
|
|
||||||
|
private byte[] script;
|
||||||
|
|
||||||
|
public int[] getOpenPorts() {
|
||||||
|
return openPorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getRunScript() {
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This script will be executed as the root user upon system startup.
|
||||||
|
*/
|
||||||
|
public RunNodeOptions runScript(byte[] script) {
|
||||||
|
checkArgument(checkNotNull(script, "script").length <= 16 * 1024,
|
||||||
|
"script cannot be larger than 16kb");
|
||||||
|
this.script = script;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the set of ports to public access.
|
||||||
|
*/
|
||||||
|
public RunNodeOptions openPorts(int... ports) {
|
||||||
|
this.openPorts = ports;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see RunNodeOptions#openPorts
|
||||||
|
*/
|
||||||
|
public static RunNodeOptions openPorts(int... ports) {
|
||||||
|
RunNodeOptions options = new RunNodeOptions();
|
||||||
|
return options.openPorts(ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see RunNodeOptions#runScript
|
||||||
|
*/
|
||||||
|
public static RunNodeOptions runScript(byte[] script) {
|
||||||
|
RunNodeOptions options = new RunNodeOptions();
|
||||||
|
return options.runScript(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@
|
||||||
package org.jclouds.compute.util;
|
package org.jclouds.compute.util;
|
||||||
|
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
|
import org.jclouds.compute.domain.CreateNodeResponse;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
@ -28,8 +29,8 @@ import com.google.common.collect.Iterables;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class ComputeUtils {
|
public class ComputeUtils {
|
||||||
public static Iterable<? extends ComputeMetadata> filterByName(Iterable<? extends ComputeMetadata> nodes,
|
public static Iterable<? extends ComputeMetadata> filterByName(
|
||||||
final String name) {
|
Iterable<? extends ComputeMetadata> nodes, final String name) {
|
||||||
return Iterables.filter(nodes, new Predicate<ComputeMetadata>() {
|
return Iterables.filter(nodes, new Predicate<ComputeMetadata>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(ComputeMetadata input) {
|
public boolean apply(ComputeMetadata input) {
|
||||||
|
@ -38,4 +39,7 @@ public class ComputeUtils {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isKeyAuth(CreateNodeResponse createdNode) {
|
||||||
|
return createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* ====================================================================
|
||||||
|
*/
|
||||||
|
package org.jclouds.compute;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
import static org.testng.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
|
import org.jclouds.compute.domain.ComputeType;
|
||||||
|
import org.jclouds.compute.domain.CreateNodeResponse;
|
||||||
|
import org.jclouds.compute.domain.LoginType;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.OperatingSystem;
|
||||||
|
import org.jclouds.compute.domain.Size;
|
||||||
|
import org.jclouds.compute.domain.Template;
|
||||||
|
import org.jclouds.compute.options.RunNodeOptions;
|
||||||
|
import org.jclouds.http.HttpResponseException;
|
||||||
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
|
import org.jclouds.predicates.RetryablePredicate;
|
||||||
|
import org.jclouds.predicates.SocketOpen;
|
||||||
|
import org.jclouds.scriptbuilder.ScriptBuilder;
|
||||||
|
import org.jclouds.scriptbuilder.domain.OsFamily;
|
||||||
|
import org.jclouds.scriptbuilder.domain.Statements;
|
||||||
|
import org.jclouds.ssh.ExecResponse;
|
||||||
|
import org.jclouds.ssh.SshClient;
|
||||||
|
import org.jclouds.ssh.SshException;
|
||||||
|
import org.testng.annotations.AfterTest;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
|
import org.testng.annotations.BeforeGroups;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.inject.Guice;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "live", enabled = true, sequential = true, testName = "compute.ComputeServiceLiveTest")
|
||||||
|
public abstract class BaseComputeServiceLiveTest {
|
||||||
|
@BeforeClass
|
||||||
|
abstract public void setServiceDefaults();
|
||||||
|
|
||||||
|
protected String service;
|
||||||
|
protected OperatingSystem testOS;
|
||||||
|
protected SshClient.Factory sshFactory;
|
||||||
|
protected RunNodeOptions options = RunNodeOptions.Builder.openPorts(22);
|
||||||
|
private String nodeName;
|
||||||
|
|
||||||
|
private RetryablePredicate<InetSocketAddress> socketTester;
|
||||||
|
private CreateNodeResponse node;
|
||||||
|
protected ComputeServiceContext context;
|
||||||
|
protected ComputeService client;
|
||||||
|
protected String user;
|
||||||
|
protected String password;
|
||||||
|
|
||||||
|
@BeforeGroups(groups = { "live" })
|
||||||
|
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
|
||||||
|
IOException {
|
||||||
|
checkNotNull(testOS, "testOS");
|
||||||
|
nodeName = checkNotNull(service, "service");
|
||||||
|
if (canRunScript())
|
||||||
|
options.runScript(new ScriptBuilder()
|
||||||
|
// update add dns and install jdk
|
||||||
|
.addStatement(
|
||||||
|
Statements.exec("echo nameserver 208.67.222.222 >> /etc/resolv.conf"))
|
||||||
|
.addStatement(Statements.exec("apt-get update"))//
|
||||||
|
.addStatement(Statements.exec("apt-get upgrade -y"))//
|
||||||
|
.addStatement(Statements.exec("apt-get install -y openjdk-6-jdk"))//
|
||||||
|
.addStatement(Statements.exec("wget -qO/usr/bin/runurl run.alestic.com/runurl"))//
|
||||||
|
.addStatement(Statements.exec("chmod 755 /usr/bin/runurl"))//
|
||||||
|
.build(OsFamily.UNIX).getBytes());
|
||||||
|
user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
||||||
|
password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
||||||
|
context = new ComputeServiceContextFactory().createContext(service, user, password,
|
||||||
|
ImmutableSet.of(new Log4JLoggingModule(), getSshModule()), new Properties());
|
||||||
|
Injector injector = Guice.createInjector(getSshModule());
|
||||||
|
sshFactory = injector.getInstance(SshClient.Factory.class);
|
||||||
|
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
|
||||||
|
socketTester = new RetryablePredicate<InetSocketAddress>(socketOpen, 60, 1, TimeUnit.SECONDS);
|
||||||
|
injector.injectMembers(socketOpen); // add logger
|
||||||
|
client = context.getComputeService();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canRunScript() {
|
||||||
|
return testOS == OperatingSystem.UBUNTU || testOS == OperatingSystem.JEOS;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected Module getSshModule();
|
||||||
|
|
||||||
|
public void testCreate() throws Exception {
|
||||||
|
try {
|
||||||
|
client.destroyNode(Iterables.find(client.listNodes(), new Predicate<ComputeMetadata>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(ComputeMetadata input) {
|
||||||
|
return input.getName().equals(nodeName);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
} catch (HttpResponseException e) {
|
||||||
|
// TODO hosting.com throws 400 when we try to delete a vApp
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
Template template = client.createTemplateInLocation("default").os(testOS).smallest();
|
||||||
|
node = client.runNode(nodeName, template, options);
|
||||||
|
assertNotNull(node.getId());
|
||||||
|
assertEquals(node.getLoginPort(), 22);
|
||||||
|
assertEquals(node.getLoginType(), LoginType.SSH);
|
||||||
|
assertNotNull(node.getName());
|
||||||
|
assertEquals(node.getPublicAddresses().size(), 1);
|
||||||
|
assertNotNull(node.getCredentials());
|
||||||
|
assertNotNull(node.getCredentials().account);
|
||||||
|
assertNotNull(node.getCredentials().key);
|
||||||
|
sshPing();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dependsOnMethods = "testCreate")
|
||||||
|
public void testGet() throws Exception {
|
||||||
|
NodeMetadata metadata = client.getNodeMetadata(node);
|
||||||
|
assertEquals(metadata.getId(), node.getId());
|
||||||
|
assertEquals(metadata.getLoginPort(), node.getLoginPort());
|
||||||
|
assertEquals(metadata.getLoginType(), node.getLoginType());
|
||||||
|
assertEquals(metadata.getName(), node.getName());
|
||||||
|
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
|
||||||
|
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testList() throws Exception {
|
||||||
|
for (ComputeMetadata node : client.listNodes()) {
|
||||||
|
assert node.getId() != null;
|
||||||
|
assert node.getLocation() != null;
|
||||||
|
assertEquals(node.getType(), ComputeType.NODE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListTemplates() throws Exception {
|
||||||
|
for (Template template : client.listTemplates()) {
|
||||||
|
assert template.getImage() != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testListSizes() throws Exception {
|
||||||
|
for (Size size : client.listSizes()) {
|
||||||
|
assert size.getCores() > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sshPing() throws IOException {
|
||||||
|
try {
|
||||||
|
doCheckKey();
|
||||||
|
} catch (SshException e) {// try twice in case there is a network timeout
|
||||||
|
try {
|
||||||
|
Thread.sleep(10 * 1000);
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
}
|
||||||
|
doCheckKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doCheckKey() throws IOException {
|
||||||
|
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), node
|
||||||
|
.getLoginPort());
|
||||||
|
socketTester.apply(socket);
|
||||||
|
SshClient ssh = node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----") ? sshFactory
|
||||||
|
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
|
||||||
|
: sshFactory
|
||||||
|
.create(socket, node.getCredentials().account, node.getCredentials().key);
|
||||||
|
try {
|
||||||
|
ssh.connect();
|
||||||
|
ExecResponse hello = ssh.exec("echo hello");
|
||||||
|
assertEquals(hello.getOutput().trim(), "hello");
|
||||||
|
if (canRunScript())
|
||||||
|
System.out.println(ssh.exec("java -version"));
|
||||||
|
} finally {
|
||||||
|
if (ssh != null)
|
||||||
|
ssh.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterTest
|
||||||
|
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
|
if (node != null)
|
||||||
|
client.destroyNode(node);
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTIONS;
|
||||||
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE;
|
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_CONNECTION_REUSE;
|
||||||
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES;
|
import static org.jclouds.http.pool.PoolConstants.PROPERTY_POOL_MAX_SESSION_FAILURES;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
@ -36,7 +37,7 @@ import com.google.common.annotations.VisibleForTesting;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole, Andrew Newdigate
|
* @author Adrian Cole, Andrew Newdigate
|
||||||
*/
|
*/
|
||||||
public class HttpPropertiesBuilder {
|
public abstract class HttpPropertiesBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see org.jclouds.http.HttpConstants.PROPERTY_HTTP_RELAX_HOSTNAME
|
* @see org.jclouds.http.HttpConstants.PROPERTY_HTTP_RELAX_HOSTNAME
|
||||||
|
@ -122,9 +123,8 @@ public class HttpPropertiesBuilder {
|
||||||
this.properties.putAll(properties);
|
this.properties.putAll(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpPropertiesBuilder withCredentials(String account, String key) {
|
public abstract HttpPropertiesBuilder withEndpoint(URI endpoint);
|
||||||
return this;
|
public abstract HttpPropertiesBuilder withCredentials(String account, String key);
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public Properties build() {
|
public Properties build() {
|
||||||
|
|
|
@ -110,30 +110,18 @@ public class HttpRequest extends HttpMessage {
|
||||||
setLength();
|
setLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public void setPayload(InputStream data) {
|
public void setPayload(InputStream data) {
|
||||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public void setPayload(byte[] data) {
|
public void setPayload(byte[] data) {
|
||||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public void setPayload(String data) {
|
public void setPayload(String data) {
|
||||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
public void setPayload(File data) {
|
public void setPayload(File data) {
|
||||||
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
setPayload(Payloads.newPayload(checkNotNull(data, "data")));
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,10 +48,10 @@ public abstract class RestContextFactory<T, B extends RestContextBuilder<?, ?>>
|
||||||
* Initializes with the default properties built-in to jclouds. This is typically stored in the
|
* Initializes with the default properties built-in to jclouds. This is typically stored in the
|
||||||
* classpath resource {@code filename}
|
* classpath resource {@code filename}
|
||||||
*
|
*
|
||||||
* @parma filename name of the properties file to initialize from
|
* @param filename name of the properties file to initialize from
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* if the default properties file cannot be loaded
|
* if the default properties file cannot be loaded
|
||||||
* @see #init
|
* @see #getPropertiesFromResource
|
||||||
*/
|
*/
|
||||||
public RestContextFactory(String filename) throws IOException {
|
public RestContextFactory(String filename) throws IOException {
|
||||||
this(getPropertiesFromResource(filename));
|
this(getPropertiesFromResource(filename));
|
||||||
|
@ -82,6 +82,7 @@ public abstract class RestContextFactory<T, B extends RestContextBuilder<?, ?>>
|
||||||
static Properties getPropertiesFromResource(String filename) throws IOException {
|
static Properties getPropertiesFromResource(String filename) throws IOException {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
properties.load(Resources.newInputStreamSupplier(Resources.getResource(filename)).getInput());
|
properties.load(Resources.newInputStreamSupplier(Resources.getResource(filename)).getInput());
|
||||||
|
properties.putAll(System.getProperties());
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,8 +126,7 @@ public abstract class RestContextFactory<T, B extends RestContextBuilder<?, ?>>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Creates a new remote context.
|
||||||
* FIXME Comment this // ImmutableSet.<Module>of(new ExecutorServiceModule(myexecutor))
|
|
||||||
*
|
*
|
||||||
* @param hint
|
* @param hint
|
||||||
* @param account
|
* @param account
|
||||||
|
@ -134,8 +134,11 @@ public abstract class RestContextFactory<T, B extends RestContextBuilder<?, ?>>
|
||||||
* @param key
|
* @param key
|
||||||
* nullable, if credentials are present in the overrides
|
* nullable, if credentials are present in the overrides
|
||||||
* @param modules
|
* @param modules
|
||||||
|
* Configuration you'd like to pass to the context. Ex. ImmutableSet.<Module>of(new
|
||||||
|
* ExecutorServiceModule(myexecutor))
|
||||||
* @param overrides
|
* @param overrides
|
||||||
* @return
|
* properties to override defaults with.
|
||||||
|
* @return initialized context ready for use
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public T createContext(String hint, @Nullable String account, @Nullable String key,
|
public T createContext(String hint, @Nullable String account, @Nullable String key,
|
||||||
|
@ -151,6 +154,8 @@ public abstract class RestContextFactory<T, B extends RestContextBuilder<?, ?>>
|
||||||
String contextBuilderClassName = checkNotNull(properties.getProperty(contextBuilderKey),
|
String contextBuilderClassName = checkNotNull(properties.getProperty(contextBuilderKey),
|
||||||
contextBuilderKey);
|
contextBuilderKey);
|
||||||
|
|
||||||
|
String endpointKey = String.format("%s.endpoint", hint);
|
||||||
|
String endpoint = properties.getProperty(endpointKey);
|
||||||
try {
|
try {
|
||||||
Class<HttpPropertiesBuilder> propertiesBuilderClass = (Class<HttpPropertiesBuilder>) Class
|
Class<HttpPropertiesBuilder> propertiesBuilderClass = (Class<HttpPropertiesBuilder>) Class
|
||||||
.forName(propertiesBuilderClassName);
|
.forName(propertiesBuilderClassName);
|
||||||
|
@ -159,7 +164,8 @@ public abstract class RestContextFactory<T, B extends RestContextBuilder<?, ?>>
|
||||||
.newInstance(overrides);
|
.newInstance(overrides);
|
||||||
if (key != null)
|
if (key != null)
|
||||||
builder.withCredentials(account, key);
|
builder.withCredentials(account, key);
|
||||||
|
if (endpoint != null)
|
||||||
|
builder.withEndpoint(URI.create(endpoint));
|
||||||
B contextBuilder = (B) contextBuilderClass.getConstructor(Properties.class).newInstance(
|
B contextBuilder = (B) contextBuilderClass.getConstructor(Properties.class).newInstance(
|
||||||
builder.build()).withModules(Iterables.toArray(modules, Module.class));
|
builder.build()).withModules(Iterables.toArray(modules, Module.class));
|
||||||
return build(contextBuilder);
|
return build(contextBuilder);
|
||||||
|
|
|
@ -41,12 +41,6 @@ public class InputStreamChain extends InputStream {
|
||||||
*/
|
*/
|
||||||
private InputStream current;
|
private InputStream current;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor with an initial stream
|
|
||||||
*
|
|
||||||
* @param first
|
|
||||||
* Initial InputStream
|
|
||||||
*/
|
|
||||||
public InputStreamChain(InputStream... inputStreams) {
|
public InputStreamChain(InputStream... inputStreams) {
|
||||||
for (InputStream stream : inputStreams) {
|
for (InputStream stream : inputStreams) {
|
||||||
addInputStream(stream);
|
addInputStream(stream);
|
||||||
|
|
|
@ -32,6 +32,7 @@ import com.google.common.collect.MapMaker;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class Patterns {
|
public class Patterns {
|
||||||
|
public static final Pattern TOKEN_PATTERN = Pattern.compile("\\{(.+?)\\}");
|
||||||
public static final Pattern TWO_SPACE_PATTERN = Pattern.compile(" ");
|
public static final Pattern TWO_SPACE_PATTERN = Pattern.compile(" ");
|
||||||
public static final Pattern URL_ENCODED_PATTERN = Pattern.compile(".*%[a-fA-F0-9][a-fA-F0-9].*");
|
public static final Pattern URL_ENCODED_PATTERN = Pattern.compile(".*%[a-fA-F0-9][a-fA-F0-9].*");
|
||||||
public static final Pattern URI_PATTERN = Pattern.compile("([a-z0-9]+)://([^:]*):(.*)@(.*)");
|
public static final Pattern URI_PATTERN = Pattern.compile("([a-z0-9]+)://([^:]*):(.*)@(.*)");
|
||||||
|
|
|
@ -43,7 +43,7 @@ import com.google.common.io.Closeables;
|
||||||
import com.google.common.io.OutputSupplier;
|
import com.google.common.io.OutputSupplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* // TODO: Adrian: Document this!
|
* General utilities used in jclouds code.
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
|
@ -137,14 +137,16 @@ public class Utils {
|
||||||
* @see {@link String#getBytes()} - used as fall-back.
|
* @see {@link String#getBytes()} - used as fall-back.
|
||||||
*
|
*
|
||||||
* @param str
|
* @param str
|
||||||
* @param encoding
|
* what to encode
|
||||||
* @return
|
* @param charsetName
|
||||||
|
* the name of a supported {@link java.nio.charset.Charset </code>charset<code>}
|
||||||
|
* @return properly encoded String.
|
||||||
*/
|
*/
|
||||||
public static byte[] encodeString(String str, String encoding) {
|
public static byte[] encodeString(String str, String charsetName) {
|
||||||
try {
|
try {
|
||||||
return str.getBytes(encoding);
|
return str.getBytes(charsetName);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
logger.warn(e, "Failed to encode string to bytes with encoding " + encoding
|
logger.warn(e, "Failed to encode string to bytes with encoding " + charsetName
|
||||||
+ ". Falling back to system's default encoding");
|
+ ". Falling back to system's default encoding");
|
||||||
return str.getBytes();
|
return str.getBytes();
|
||||||
}
|
}
|
||||||
|
@ -156,45 +158,13 @@ public class Utils {
|
||||||
* the system's default encoding.
|
* the system's default encoding.
|
||||||
*
|
*
|
||||||
* @param str
|
* @param str
|
||||||
* @return
|
* what to encode
|
||||||
|
* @return properly encoded String.
|
||||||
*/
|
*/
|
||||||
public static byte[] encodeString(String str) {
|
public static byte[] encodeString(String str) {
|
||||||
return encodeString(str, UTF8_ENCODING);
|
return encodeString(str, UTF8_ENCODING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode the given string with the given encoding, if possible. If the decoding fails with
|
|
||||||
* {@link UnsupportedEncodingException}, log a warning and fall back to the system's default
|
|
||||||
* encoding.
|
|
||||||
*
|
|
||||||
* @param bytes
|
|
||||||
* @param encoding
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String decodeString(byte[] bytes, String encoding) {
|
|
||||||
try {
|
|
||||||
return new String(bytes, encoding);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
logger.warn(e, "Failed to decode bytes to string with encoding " + encoding
|
|
||||||
+ ". Falling back to system's default encoding");
|
|
||||||
return new String(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode the given string with the UTF-8 encoding, the sane default. In the very unlikely event
|
|
||||||
* the encoding fails with {@link UnsupportedEncodingException}, log a warning and fall back to
|
|
||||||
* the system's default encoding.
|
|
||||||
*
|
|
||||||
* @param str
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String decodeString(byte[] bytes) {
|
|
||||||
return decodeString(bytes, UTF8_ENCODING);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Pattern pattern = Pattern.compile("\\{(.+?)\\}");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* replaces tokens that are expressed as <code>{token}</code>
|
* replaces tokens that are expressed as <code>{token}</code>
|
||||||
*
|
*
|
||||||
|
@ -209,7 +179,7 @@ public class Utils {
|
||||||
* token/value pairs
|
* token/value pairs
|
||||||
*/
|
*/
|
||||||
public static String replaceTokens(String input, Map<String, String> replacements) {
|
public static String replaceTokens(String input, Map<String, String> replacements) {
|
||||||
Matcher matcher = pattern.matcher(input);
|
Matcher matcher = Patterns.TOKEN_PATTERN.matcher(input);
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.http;
|
package org.jclouds.http;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -37,7 +38,18 @@ public class HttpPropertiesBuilderTest {
|
||||||
int poolMaxClients = 3382;
|
int poolMaxClients = 3382;
|
||||||
int poolMaxSessionFailures = 857;
|
int poolMaxSessionFailures = 857;
|
||||||
|
|
||||||
HttpPropertiesBuilder builder = new HttpPropertiesBuilder(new Properties());
|
HttpPropertiesBuilder builder = new HttpPropertiesBuilder(new Properties()) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpPropertiesBuilder withCredentials(String account, String key) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpPropertiesBuilder withEndpoint(URI endpoint) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
builder.withHttpMaxRetries(httpMaxRetries);
|
builder.withHttpMaxRetries(httpMaxRetries);
|
||||||
|
|
||||||
builder.withPoolIoWorkerThreads(poolIoWorkerThreads);
|
builder.withPoolIoWorkerThreads(poolIoWorkerThreads);
|
||||||
|
|
|
@ -21,11 +21,15 @@ package org.jclouds.nirvanix.sdn;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.http.HttpPropertiesBuilder;
|
import org.jclouds.http.HttpPropertiesBuilder;
|
||||||
import org.jclouds.nirvanix.sdn.reference.SDNConstants;
|
import org.jclouds.nirvanix.sdn.reference.SDNConstants;
|
||||||
|
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds properties used in SDN Clients
|
* Builds properties used in SDN Clients
|
||||||
*
|
*
|
||||||
|
@ -65,4 +69,13 @@ public class SDNPropertiesBuilder extends HttpPropertiesBuilder {
|
||||||
.toString());
|
.toString());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SDNPropertiesBuilder withCredentials(String account, String key) {
|
||||||
|
List<String> parts = Lists.newArrayList(Splitter.on('/').split(account));
|
||||||
|
if (parts.size() != 3) {
|
||||||
|
throw new IllegalArgumentException("account syntax is appkey/appname/username");
|
||||||
|
}
|
||||||
|
return withCredentials(parts.get(0), parts.get(1), parts.get(2), key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,14 @@
|
||||||
package org.jclouds.rimuhosting.miro;
|
package org.jclouds.rimuhosting.miro;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import org.jclouds.http.HttpPropertiesBuilder;
|
import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.PROPERTY_RIMUHOSTING_APIKEY;
|
||||||
import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.*;
|
import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.PROPERTY_RIMUHOSTING_ENDPOINT;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.jclouds.http.HttpPropertiesBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds properties used in RimuHosting Clients
|
* Builds properties used in RimuHosting Clients
|
||||||
*
|
*
|
||||||
|
@ -52,9 +54,15 @@ public class RimuHostingPropertiesBuilder extends HttpPropertiesBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public RimuHostingPropertiesBuilder withEndpoint(URI endpoint) {
|
public RimuHostingPropertiesBuilder withEndpoint(URI endpoint) {
|
||||||
properties.setProperty(PROPERTY_RIMUHOSTING_ENDPOINT, checkNotNull(endpoint, "endpoint")
|
properties.setProperty(PROPERTY_RIMUHOSTING_ENDPOINT, checkNotNull(endpoint, "endpoint")
|
||||||
.toString());
|
.toString());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpPropertiesBuilder withCredentials(String account, String key) {
|
||||||
|
return withCredentials(account != null ? account : key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -43,6 +44,7 @@ import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
|
import org.jclouds.compute.domain.internal.ComputeMetadataImpl;
|
||||||
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
||||||
|
import org.jclouds.compute.options.RunNodeOptions;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
@ -82,6 +84,11 @@ public class RimuHostingComputeService implements ComputeService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CreateNodeResponse runNode(String name, Template template) {
|
public CreateNodeResponse runNode(String name, Template template) {
|
||||||
|
return this.runNode(name, template, RunNodeOptions.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CreateNodeResponse runNode(String name, Template template, RunNodeOptions options) {
|
||||||
NewServerResponse serverResponse = rhClient.createServer(name, checkNotNull(imageNameMap
|
NewServerResponse serverResponse = rhClient.createServer(name, checkNotNull(imageNameMap
|
||||||
.get(template.getImage().getOperatingSystem()), "os not supported: "
|
.get(template.getImage().getOperatingSystem()), "os not supported: "
|
||||||
+ template.getImage().getOperatingSystem()), "MIRO1B");
|
+ template.getImage().getOperatingSystem()), "MIRO1B");
|
||||||
|
@ -144,7 +151,7 @@ public class RimuHostingComputeService implements ComputeService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends Size> listSizes() {
|
public SortedSet<? extends Size> listSizes() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,156 +18,28 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rimuhosting.miro.compute;
|
package org.jclouds.rimuhosting.miro.compute;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static org.jclouds.compute.domain.OperatingSystem.UBUNTU;
|
import static org.jclouds.compute.domain.OperatingSystem.UBUNTU;
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
import static org.testng.Assert.assertNotNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.jclouds.compute.BaseComputeServiceLiveTest;
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeService;
|
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
|
||||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
|
||||||
import org.jclouds.compute.domain.ComputeType;
|
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.LoginType;
|
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
|
||||||
import org.jclouds.compute.domain.Size;
|
|
||||||
import org.jclouds.compute.domain.Template;
|
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
|
||||||
import org.jclouds.predicates.SocketOpen;
|
|
||||||
import org.jclouds.ssh.ExecResponse;
|
|
||||||
import org.jclouds.ssh.SshClient;
|
|
||||||
import org.jclouds.ssh.SshException;
|
|
||||||
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
import org.testng.annotations.AfterTest;
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.BeforeGroups;
|
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Ivan Meredith
|
* @author Ivan Meredith
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", sequential = true, testName = "rimuhosting.RimuHostingNodeServiceLiveTest")
|
@Test(groups = "live", sequential = true, testName = "rimuhosting.RimuHostingNodeServiceLiveTest")
|
||||||
public class RimuHostingComputeServiceLiveTest {
|
public class RimuHostingComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
||||||
private static final String service = "rimuhosting";
|
@BeforeClass
|
||||||
|
@Override
|
||||||
protected SshClient.Factory sshFactory;
|
public void setServiceDefaults() {
|
||||||
private String nodeName = System.getProperty("user.name") + service;
|
service = "rimuhosting";
|
||||||
|
testOS = UBUNTU;
|
||||||
private RetryablePredicate<InetSocketAddress> socketTester;
|
|
||||||
private CreateNodeResponse node;
|
|
||||||
private ComputeServiceContext context;
|
|
||||||
private ComputeService client;
|
|
||||||
|
|
||||||
@BeforeGroups(groups = { "live" })
|
|
||||||
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
|
|
||||||
IOException {
|
|
||||||
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
|
||||||
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
|
||||||
context = new ComputeServiceContextFactory().createContext(service, user, password,
|
|
||||||
ImmutableSet.of(new Log4JLoggingModule()), new Properties());
|
|
||||||
Injector injector = Guice.createInjector(new JschSshClientModule());
|
|
||||||
sshFactory = injector.getInstance(SshClient.Factory.class);
|
|
||||||
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
|
|
||||||
socketTester = new RetryablePredicate<InetSocketAddress>(socketOpen, 60, 1, TimeUnit.SECONDS);
|
|
||||||
injector.injectMembers(socketOpen); // add logger
|
|
||||||
client = context.getComputeService();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreate() throws Exception {
|
@Override
|
||||||
Template template = client.createTemplateInLocation("default").os(UBUNTU).smallest();
|
protected JschSshClientModule getSshModule() {
|
||||||
node = client.runNode(nodeName, template);
|
return new JschSshClientModule();
|
||||||
assertNotNull(node.getId());
|
|
||||||
assertEquals(node.getLoginPort(), 22);
|
|
||||||
assertEquals(node.getLoginType(), LoginType.SSH);
|
|
||||||
assertNotNull(node.getName());
|
|
||||||
assertEquals(node.getPrivateAddresses().size(), 1);
|
|
||||||
assertEquals(node.getPublicAddresses().size(), 1);
|
|
||||||
assertNotNull(node.getCredentials());
|
|
||||||
assertNotNull(node.getCredentials().account);
|
|
||||||
assertNotNull(node.getCredentials().key);
|
|
||||||
sshPing();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testCreate")
|
|
||||||
public void testGet() throws Exception {
|
|
||||||
NodeMetadata metadata = client.getNodeMetadata(node);
|
|
||||||
assertEquals(metadata.getId(), node.getId());
|
|
||||||
assertEquals(metadata.getLoginPort(), node.getLoginPort());
|
|
||||||
assertEquals(metadata.getLoginType(), node.getLoginType());
|
|
||||||
assertEquals(metadata.getName(), node.getName());
|
|
||||||
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
|
|
||||||
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testList() throws Exception {
|
|
||||||
for (ComputeMetadata node : client.listNodes()) {
|
|
||||||
assert node.getId() != null;
|
|
||||||
assert node.getLocation() != null;
|
|
||||||
assertEquals(node.getType(), ComputeType.NODE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testListTemplates() throws Exception {
|
|
||||||
for (Template template : client.listTemplates()) {
|
|
||||||
assert template.getImage() != null;
|
|
||||||
System.out.println(template);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testListSizes() throws Exception {
|
|
||||||
for (Size size : client.listSizes()) {
|
|
||||||
assert size.getCores() != null;
|
|
||||||
System.out.println(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sshPing() throws IOException {
|
|
||||||
try {
|
|
||||||
doCheckKey();
|
|
||||||
} catch (SshException e) {// try twice in case there is a network timeout
|
|
||||||
try {
|
|
||||||
Thread.sleep(10 * 1000);
|
|
||||||
} catch (InterruptedException e1) {
|
|
||||||
}
|
|
||||||
doCheckKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doCheckKey() throws IOException {
|
|
||||||
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), node
|
|
||||||
.getLoginPort());
|
|
||||||
socketTester.apply(socket);
|
|
||||||
SshClient ssh = node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----") ? sshFactory
|
|
||||||
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
|
|
||||||
: sshFactory
|
|
||||||
.create(socket, node.getCredentials().account, node.getCredentials().key);
|
|
||||||
try {
|
|
||||||
ssh.connect();
|
|
||||||
ExecResponse hello = ssh.exec("echo hello");
|
|
||||||
assertEquals(hello.getOutput().trim(), "hello");
|
|
||||||
} finally {
|
|
||||||
if (ssh != null)
|
|
||||||
ssh.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterTest
|
|
||||||
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
|
|
||||||
if (node != null)
|
|
||||||
client.destroyNode(node);
|
|
||||||
context.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
|
|
||||||
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
|
||||||
====================================================================
|
====================================================================
|
||||||
|
@ -23,6 +22,7 @@
|
||||||
<property file="build.properties" />
|
<property file="build.properties" />
|
||||||
<property name="password" value="" />
|
<property name="password" value="" />
|
||||||
<property name="keyfile" value="" />
|
<property name="keyfile" value="" />
|
||||||
|
<property name="listenport" value="8080" />
|
||||||
<property name="container.zip" value="http://www.ibiblio.org/pub/mirrors/apache/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.zip" />
|
<property name="container.zip" value="http://www.ibiblio.org/pub/mirrors/apache/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.zip" />
|
||||||
<property name="warfile" value="build/samples-blazeds.war" />
|
<property name="warfile" value="build/samples-blazeds.war" />
|
||||||
|
|
||||||
|
@ -60,55 +60,32 @@
|
||||||
<property name="service" value="terremark"/>
|
<property name="service" value="terremark"/>
|
||||||
<input message="What is your account on ${service}?" addproperty="account"/>
|
<input message="What is your account on ${service}?" addproperty="account"/>
|
||||||
<input message="What is the key for ${account}?" addproperty="key"/>
|
<input message="What is the key for ${account}?" addproperty="key"/>
|
||||||
<property name="jclouds.compute.nodename" value="terremark-blaze"/>
|
<property name="nodename" value="terremark-blaze"/>
|
||||||
<property name="jclouds.compute.url" value="compute://${account}:${key}@${service}"/>
|
<property name="url" value="compute://${account}:${key}@${service}"/>
|
||||||
|
|
||||||
<target name="destroy" description="destroy the node ${jclouds.compute.nodename}">
|
<target name="destroy" description="destroy the node ${nodename}">
|
||||||
<compute action="destroy" provider="${jclouds.compute.url}">
|
<compute action="destroy" provider="${url}">
|
||||||
<node name="${jclouds.compute.nodename}" />
|
<node name="${nodename}" />
|
||||||
</compute>
|
</compute>
|
||||||
<sleep seconds="2" />
|
<sleep seconds="2" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="create" description="create the node ${jclouds.compute.nodename}" depends="destroy" >
|
<target name="create" description="create the node ${nodename}" depends="destroy" >
|
||||||
<compute action="create" provider="${jclouds.compute.url}">
|
<compute action="create" provider="${url}">
|
||||||
<node name="${jclouds.compute.nodename}" os="UBUNTU" size="SMALLEST"
|
<node name="${nodename}" os="JEOS" size="SMALLEST"
|
||||||
|
runscript="runscript.sh" openports="22,${listenport}"
|
||||||
hostproperty="host" usernameproperty="username" passwordproperty="password" />
|
hostproperty="host" usernameproperty="username" passwordproperty="password" />
|
||||||
</compute>
|
</compute>
|
||||||
|
|
||||||
<echo message="provisioning java on: ${jclouds.compute.nodename}" />
|
|
||||||
<property name="sudo" value="echo ${password}|sudo -S" />
|
|
||||||
<!-- funny game to get around sudo problems with >>. first sudo is only to prime the password -->
|
|
||||||
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
|
|
||||||
command="${sudo} echo hello;echo nameserver 208.67.222.222 |sudo tee -a /etc/resolv.conf" />
|
|
||||||
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
|
|
||||||
command="${sudo} apt-get update -qq" />
|
|
||||||
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
|
|
||||||
command="${sudo} apt-get upgrade -y -qq" />
|
|
||||||
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
|
|
||||||
command="${sudo} apt-get install -y -qq wget" />
|
|
||||||
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
|
|
||||||
command="${sudo} apt-get install -y -qq openjdk-6-jdk" />
|
|
||||||
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
|
|
||||||
command="wget -q http://www.alliedquotes.com/mirrors/apache/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.tar.gz" />
|
|
||||||
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
|
|
||||||
command="tar xzf apache-tomcat-6.0.20.tar.gz" />
|
|
||||||
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
|
|
||||||
command="${sudo} mkdir -p /tmp/cargo/containers/" />
|
|
||||||
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
|
|
||||||
command="${sudo} chmod 1777 /tmp/cargo" />
|
|
||||||
<sshexec host="${host}" username="${username}" password="${password}" trust="true"
|
|
||||||
command="${sudo} mv apache-tomcat-6.0.20 /tmp/cargo/containers/tomcat6x" />
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="cargooverssh" depends="create" description="run cargo on remote node" >
|
<target name="cargooverssh" depends="create" description="run cargo on remote node" >
|
||||||
<echo message="deploying tomcat and blaze to: ${jclouds.compute.nodename}" />
|
<echo message="deploying tomcat and blaze to: ${nodename}" />
|
||||||
<cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000">
|
<cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000">
|
||||||
<zipurlinstaller installurl="${container.zip}" />
|
<zipurlinstaller installurl="${container.zip}" />
|
||||||
<configuration home="build/cargo" type="standalone">
|
<configuration home="build/cargo" type="standalone">
|
||||||
<property name="cargo.java.home" value="/usr/lib/jvm/java-6-openjdk"/>
|
<property name="cargo.java.home" value="/usr/lib/jvm/java-6-openjdk"/>
|
||||||
<property name="cargo.hostname" value="${host}"/>
|
<property name="cargo.hostname" value="${host}"/>
|
||||||
<property name="cargo.servlet.port" value="8080"/>
|
<property name="cargo.servlet.port" value="${listenport}"/>
|
||||||
<property name="cargo.ssh.host" value="${host}"/>
|
<property name="cargo.ssh.host" value="${host}"/>
|
||||||
<property name="cargo.ssh.username" value="${username}"/>
|
<property name="cargo.ssh.username" value="${username}"/>
|
||||||
<property name="cargo.ssh.password" value="${password}"/>
|
<property name="cargo.ssh.password" value="${password}"/>
|
||||||
|
@ -125,7 +102,7 @@
|
||||||
<cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000">
|
<cargo containerId="tomcat6x" output="build/output.log" log="build/cargo.log" action="start" timeout="600000">
|
||||||
<zipurlinstaller installurl="${container.zip}" />
|
<zipurlinstaller installurl="${container.zip}" />
|
||||||
<configuration home="build/cargo" type="standalone">
|
<configuration home="build/cargo" type="standalone">
|
||||||
<property name="cargo.servlet.port" value="8080"/>
|
<property name="cargo.servlet.port" value="${listenport}"/>
|
||||||
<property name="cargo.logging" value="high"/>
|
<property name="cargo.logging" value="high"/>
|
||||||
<deployable type="war" file="${warfile}"/>
|
<deployable type="war" file="${warfile}"/>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
echo nameserver 208.67.222.222 >> /etc/resolv.conf
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get upgrade -y -qq
|
||||||
|
apt-get install -y -qq wget
|
||||||
|
apt-get install -y -qq openjdk-6-jdk
|
||||||
|
wget -q http://www.alliedquotes.com/mirrors/apache/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.tar.gz
|
||||||
|
tar xzf apache-tomcat-6.0.20.tar.gz
|
||||||
|
mkdir -p /tmp/cargo/containers
|
||||||
|
chmod 1777 /tmp/cargo
|
||||||
|
mv apache-tomcat-6.0.20 /tmp/cargo/containers/tomcat6x
|
|
@ -18,37 +18,35 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.tools.ant.taskdefs.compute;
|
package org.jclouds.tools.ant.taskdefs.compute;
|
||||||
|
|
||||||
|
import static org.jclouds.compute.util.ComputeUtils.filterByName;
|
||||||
|
import static org.jclouds.compute.util.ComputeUtils.isKeyAuth;
|
||||||
|
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.buildComputeMap;
|
||||||
|
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.createTemplateFromElement;
|
||||||
|
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.getNodeOptionsFromElement;
|
||||||
|
import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.ipOrEmptyString;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.SortedSet;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.apache.tools.ant.BuildException;
|
import org.apache.tools.ant.BuildException;
|
||||||
import org.apache.tools.ant.Project;
|
import org.apache.tools.ant.Project;
|
||||||
import org.apache.tools.ant.Task;
|
import org.apache.tools.ant.Task;
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.compute.domain.ComputeMetadata;
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
import org.jclouds.compute.domain.CreateNodeResponse;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.domain.OperatingSystem;
|
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.options.RunNodeOptions;
|
||||||
import org.jclouds.compute.util.ComputeUtils;
|
|
||||||
import org.jclouds.http.HttpUtils;
|
import org.jclouds.http.HttpUtils;
|
||||||
import org.jclouds.tools.ant.logging.config.AntLoggingModule;
|
|
||||||
|
|
||||||
import com.google.common.base.CaseFormat;
|
import com.google.common.base.CaseFormat;
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.inject.Module;
|
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,92 +56,48 @@ import com.google.inject.Provider;
|
||||||
public class ComputeTask extends Task {
|
public class ComputeTask extends Task {
|
||||||
|
|
||||||
private final Map<URI, ComputeServiceContext> computeMap;
|
private final Map<URI, ComputeServiceContext> computeMap;
|
||||||
private static Project project;
|
private String provider;
|
||||||
/**
|
private String action;
|
||||||
* we don't have a reference to the project during the constructor, so we need to defer expansion
|
private NodeElement nodeElement;
|
||||||
* with a Provider.
|
|
||||||
*/
|
|
||||||
private static Provider<Iterable<? extends Module>> defaultModulesProvider = new Provider<Iterable<? extends Module>>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterable<Module> get() {
|
|
||||||
return ImmutableSet.of((Module) new AntLoggingModule(project,
|
|
||||||
ComputeServiceConstants.COMPUTE_LOGGER));
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* we don't have a reference to the project during the constructor, so we need to defer expansion
|
* we don't have a reference to the project during the constructor, so we need to defer expansion
|
||||||
* with a Provider.
|
* with a Provider.
|
||||||
*/
|
*/
|
||||||
private static Provider<Properties> defaultPropertiesProvider = new Provider<Properties>() {
|
private final Provider<Project> projectProvider = new Provider<Project>() {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
@Override
|
||||||
public Properties get() {
|
public Project get() {
|
||||||
Properties props = new Properties();
|
return getProject();
|
||||||
props.putAll(project.getProperties());
|
|
||||||
return props;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public ComputeTask(Map<URI, ComputeServiceContext> computeMap) {
|
public ComputeTask(@Nullable Map<URI, ComputeServiceContext> computeMap) {
|
||||||
this.computeMap = computeMap;
|
this.computeMap = computeMap != null ? computeMap : buildComputeMap(projectProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComputeTask() throws IOException {
|
public ComputeTask() throws IOException {
|
||||||
this(buildComputeMap());
|
this(null);
|
||||||
}
|
|
||||||
|
|
||||||
static Map<URI, ComputeServiceContext> buildComputeMap() {
|
|
||||||
return new MapMaker().makeComputingMap(new Function<URI, ComputeServiceContext>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ComputeServiceContext apply(URI from) {
|
|
||||||
try {
|
|
||||||
return new ComputeServiceContextFactory().createContext(from, defaultModulesProvider
|
|
||||||
.get(), defaultPropertiesProvider.get());
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum Action {
|
public static enum Action {
|
||||||
CREATE, GET, LIST, LIST_DETAILS, DESTROY
|
CREATE, GET, LIST, LIST_DETAILS, DESTROY
|
||||||
}
|
}
|
||||||
|
|
||||||
private String provider;
|
|
||||||
private String action;
|
|
||||||
private NodeElement nodeElement;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the configured {@link NodeElement} element
|
* makes a connection to the compute service and invokes
|
||||||
*/
|
*/
|
||||||
public final NodeElement createNode() {
|
|
||||||
if (getNode() == null) {
|
|
||||||
this.nodeElement = new NodeElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.nodeElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeElement getNode() {
|
|
||||||
return this.nodeElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void execute() throws BuildException {
|
public void execute() throws BuildException {
|
||||||
ComputeTask.project = getProject();
|
ComputeServiceContext context = computeMap.get(HttpUtils.createUri(provider));
|
||||||
Action action = Action.valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE,
|
Action action = Action.valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE,
|
||||||
this.action));
|
this.action));
|
||||||
ComputeServiceContext context = computeMap.get(HttpUtils.createUri(provider));
|
|
||||||
try {
|
try {
|
||||||
ComputeService computeService = context.getComputeService();
|
invokeActionOnService(action, context.getComputeService());
|
||||||
|
} finally {
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void invokeActionOnService(Action action, ComputeService computeService) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case CREATE:
|
case CREATE:
|
||||||
case GET:
|
case GET:
|
||||||
|
@ -165,62 +119,70 @@ public class ComputeTask extends Task {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LIST:
|
case LIST:
|
||||||
log("list");
|
list(computeService);
|
||||||
for (ComputeMetadata node : computeService.listNodes()) {
|
|
||||||
log(String.format(" location=%s, id=%s, name=%s", node.getLocation(), node
|
|
||||||
.getId(), node.getName()));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case LIST_DETAILS:
|
case LIST_DETAILS:
|
||||||
|
listDetails(computeService);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.log("bad action: " + action, Project.MSG_ERR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void listDetails(ComputeService computeService) {
|
||||||
log("list details");
|
log("list details");
|
||||||
for (ComputeMetadata node : computeService.listNodes()) {// TODO
|
for (ComputeMetadata node : computeService.listNodes()) {// TODO
|
||||||
// parallel
|
// parallel
|
||||||
logDetails(computeService, node);
|
logDetails(computeService, node);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.log("bad action: " + action, Project.MSG_ERR);
|
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
context.close();
|
private void list(ComputeService computeService) {
|
||||||
|
log("list");
|
||||||
|
for (ComputeMetadata node : computeService.listNodes()) {
|
||||||
|
log(String.format(" location=%s, id=%s, name=%s", node.getLocation(), node.getId(), node
|
||||||
|
.getName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void create(ComputeService computeService) {
|
private void create(ComputeService computeService) {
|
||||||
log(String.format("create name: %s, size: %s, os: %s", nodeElement.getName(), nodeElement
|
String name = nodeElement.getName();
|
||||||
.getSize(), nodeElement.getOs()));
|
|
||||||
Template template = computeService.createTemplateInLocation(nodeElement.getLocation());
|
log(String.format("create name: %s, size: %s, os: %s", name, nodeElement.getSize(),
|
||||||
template.os(OperatingSystem.valueOf(nodeElement.getOs()));
|
nodeElement.getOs()));
|
||||||
if (nodeElement.getSize().equalsIgnoreCase("smallest")) {
|
|
||||||
template.smallest();
|
Template template = createTemplateFromElement(nodeElement, computeService);
|
||||||
} else if (nodeElement.getSize().equalsIgnoreCase("fastest")) {
|
|
||||||
template.fastest();
|
RunNodeOptions options = getNodeOptionsFromElement(nodeElement);
|
||||||
} else if (nodeElement.getSize().equalsIgnoreCase("biggest")) {
|
|
||||||
template.biggest();
|
CreateNodeResponse createdNode = computeService.runNode(name, template, options);
|
||||||
} else {
|
|
||||||
throw new BuildException("size: " + nodeElement.getSize()
|
logNodeDetails(createdNode);
|
||||||
+ " not supported. valid sizes are smallest, fastest, biggest");
|
|
||||||
|
addNodeDetailsAsProjectProperties(createdNode);
|
||||||
}
|
}
|
||||||
CreateNodeResponse createdNode = computeService.runNode(nodeElement.getName(), template);
|
|
||||||
|
private void logNodeDetails(CreateNodeResponse createdNode) {
|
||||||
log(String.format(" id=%s, name=%s, connection=%s://%s:%s@%s:%d", createdNode.getId(),
|
log(String.format(" id=%s, name=%s, connection=%s://%s:%s@%s:%d", createdNode.getId(),
|
||||||
createdNode.getName(), createdNode.getLoginType().toString().toLowerCase(),
|
createdNode.getName(), createdNode.getLoginType().toString().toLowerCase(),
|
||||||
createdNode.getCredentials().account, createdNode.getCredentials().key, createdNode
|
createdNode.getCredentials().account, createdNode.getCredentials().key, createdNode
|
||||||
.getPublicAddresses().first().getHostAddress(), createdNode.getLoginPort()));
|
.getPublicAddresses().first().getHostAddress(), createdNode.getLoginPort()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addNodeDetailsAsProjectProperties(CreateNodeResponse createdNode) {
|
||||||
if (nodeElement.getIdproperty() != null)
|
if (nodeElement.getIdproperty() != null)
|
||||||
getProject().setProperty(nodeElement.getIdproperty(), createdNode.getId());
|
getProject().setProperty(nodeElement.getIdproperty(), createdNode.getId());
|
||||||
if (nodeElement.getHostproperty() != null)
|
if (nodeElement.getHostproperty() != null)
|
||||||
getProject().setProperty(nodeElement.getHostproperty(),
|
getProject().setProperty(nodeElement.getHostproperty(),
|
||||||
createdNode.getPublicAddresses().first().getHostAddress());
|
createdNode.getPublicAddresses().first().getHostAddress());
|
||||||
if (nodeElement.getKeyfile() != null
|
if (nodeElement.getKeyfile() != null && isKeyAuth(createdNode))
|
||||||
&& createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----"))
|
|
||||||
try {
|
try {
|
||||||
Files.write(createdNode.getCredentials().key, new File(nodeElement.getKeyfile()),
|
Files.write(createdNode.getCredentials().key, new File(nodeElement.getKeyfile()),
|
||||||
Charset.defaultCharset());
|
Charset.defaultCharset());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new BuildException(e);
|
throw new BuildException(e);
|
||||||
}
|
}
|
||||||
if (nodeElement.getPasswordproperty() != null
|
if (nodeElement.getPasswordproperty() != null && !isKeyAuth(createdNode))
|
||||||
&& !createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----"))
|
|
||||||
getProject().setProperty(nodeElement.getPasswordproperty(),
|
getProject().setProperty(nodeElement.getPasswordproperty(),
|
||||||
createdNode.getCredentials().key);
|
createdNode.getCredentials().key);
|
||||||
if (nodeElement.getUsernameproperty() != null)
|
if (nodeElement.getUsernameproperty() != null)
|
||||||
|
@ -230,8 +192,8 @@ public class ComputeTask extends Task {
|
||||||
|
|
||||||
private void destroy(ComputeService computeService) {
|
private void destroy(ComputeService computeService) {
|
||||||
log(String.format("destroy name: %s", nodeElement.getName()));
|
log(String.format("destroy name: %s", nodeElement.getName()));
|
||||||
Iterable<? extends ComputeMetadata> nodesThatMatch = ComputeUtils.filterByName(computeService
|
Iterable<? extends ComputeMetadata> nodesThatMatch = filterByName(computeService.listNodes(),
|
||||||
.listNodes(), nodeElement.getName());
|
nodeElement.getName());
|
||||||
for (ComputeMetadata node : nodesThatMatch) {
|
for (ComputeMetadata node : nodesThatMatch) {
|
||||||
log(String.format(" destroying id=%s, name=%s", node.getId(), node.getName()));
|
log(String.format(" destroying id=%s, name=%s", node.getId(), node.getName()));
|
||||||
computeService.destroyNode(node);
|
computeService.destroyNode(node);
|
||||||
|
@ -240,8 +202,8 @@ public class ComputeTask extends Task {
|
||||||
|
|
||||||
private void get(ComputeService computeService) {
|
private void get(ComputeService computeService) {
|
||||||
log(String.format("get name: %s", nodeElement.getName()));
|
log(String.format("get name: %s", nodeElement.getName()));
|
||||||
Iterable<? extends ComputeMetadata> nodesThatMatch = ComputeUtils.filterByName(computeService
|
Iterable<? extends ComputeMetadata> nodesThatMatch = filterByName(computeService.listNodes(),
|
||||||
.listNodes(), nodeElement.getName());
|
nodeElement.getName());
|
||||||
for (ComputeMetadata node : nodesThatMatch) {
|
for (ComputeMetadata node : nodesThatMatch) {
|
||||||
logDetails(computeService, node);
|
logDetails(computeService, node);
|
||||||
}
|
}
|
||||||
|
@ -257,12 +219,18 @@ public class ComputeTask extends Task {
|
||||||
.getPrivateAddresses()), metadata.getExtra()));
|
.getPrivateAddresses()), metadata.getExtra()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String ipOrEmptyString(SortedSet<InetAddress> set) {
|
/**
|
||||||
if (set.size() > 0) {
|
* @return the configured {@link NodeElement} element
|
||||||
return set.last().getHostAddress();
|
*/
|
||||||
} else {
|
public final NodeElement createNode() {
|
||||||
return "";
|
if (getNode() == null) {
|
||||||
|
this.nodeElement = new NodeElement();
|
||||||
}
|
}
|
||||||
|
return this.nodeElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeElement getNode() {
|
||||||
|
return this.nodeElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAction() {
|
public String getAction() {
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF 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.tools.ant.taskdefs.compute;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.BuildException;
|
||||||
|
import org.apache.tools.ant.Project;
|
||||||
|
import org.jclouds.compute.ComputeService;
|
||||||
|
import org.jclouds.compute.ComputeServiceContext;
|
||||||
|
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||||
|
import org.jclouds.compute.domain.OperatingSystem;
|
||||||
|
import org.jclouds.compute.domain.Template;
|
||||||
|
import org.jclouds.compute.options.RunNodeOptions;
|
||||||
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
|
import org.jclouds.tools.ant.logging.config.AntLoggingModule;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.MapMaker;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class ComputeTaskUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Creates a Map that associates a uri with a live connection to the compute provider. This is
|
||||||
|
* done on-demand.
|
||||||
|
*
|
||||||
|
* @param projectProvider
|
||||||
|
* allows access to the ant project to retrieve default properties needed for compute
|
||||||
|
* providers.
|
||||||
|
*/
|
||||||
|
static Map<URI, ComputeServiceContext> buildComputeMap(final Provider<Project> projectProvider) {
|
||||||
|
return new MapMaker().makeComputingMap(new Function<URI, ComputeServiceContext>() {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public ComputeServiceContext apply(URI from) {
|
||||||
|
try {
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.putAll(projectProvider.get().getProperties());
|
||||||
|
return new ComputeServiceContextFactory().createContext(from, ImmutableSet
|
||||||
|
.of((Module) new AntLoggingModule(projectProvider.get(),
|
||||||
|
ComputeServiceConstants.COMPUTE_LOGGER)), props);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static Template createTemplateFromElement(NodeElement nodeElement, ComputeService computeService) {
|
||||||
|
Template template = computeService.createTemplateInLocation(nodeElement.getLocation());
|
||||||
|
template.os(OperatingSystem.valueOf(nodeElement.getOs()));
|
||||||
|
addSizeFromElementToTemplate(nodeElement, template);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addSizeFromElementToTemplate(NodeElement nodeElement, Template template) {
|
||||||
|
if (nodeElement.getSize().equalsIgnoreCase("smallest")) {
|
||||||
|
template.smallest();
|
||||||
|
} else if (nodeElement.getSize().equalsIgnoreCase("fastest")) {
|
||||||
|
template.fastest();
|
||||||
|
} else if (nodeElement.getSize().equalsIgnoreCase("biggest")) {
|
||||||
|
template.biggest();
|
||||||
|
} else {
|
||||||
|
throw new BuildException("size: " + nodeElement.getSize()
|
||||||
|
+ " not supported. valid sizes are smallest, fastest, biggest");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static RunNodeOptions getNodeOptionsFromElement(NodeElement nodeElement) {
|
||||||
|
RunNodeOptions options = new RunNodeOptions()
|
||||||
|
.openPorts(getPortsToOpenFromElement(nodeElement));
|
||||||
|
addRunScriptToOptionsIfPresentInNodeElement(nodeElement, options);
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addRunScriptToOptionsIfPresentInNodeElement(NodeElement nodeElement,
|
||||||
|
RunNodeOptions options) {
|
||||||
|
if (nodeElement.getRunscript() != null)
|
||||||
|
try {
|
||||||
|
options.runScript(Files.toByteArray(nodeElement.getRunscript()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new BuildException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String ipOrEmptyString(SortedSet<InetAddress> set) {
|
||||||
|
if (set.size() > 0) {
|
||||||
|
return set.last().getHostAddress();
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int[] getPortsToOpenFromElement(NodeElement nodeElement) {
|
||||||
|
Iterable<String> portStrings = Splitter.on(',').split(nodeElement.getOpenports());
|
||||||
|
int[] ports = new int[Iterables.size(portStrings)];
|
||||||
|
int i = 0;
|
||||||
|
for (String port : portStrings) {
|
||||||
|
ports[i++] = Integer.parseInt(port);
|
||||||
|
}
|
||||||
|
return ports;
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.tools.ant.taskdefs.compute;
|
package org.jclouds.tools.ant.taskdefs.compute;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
* @author Ivan Meredith
|
* @author Ivan Meredith
|
||||||
|
@ -26,12 +28,14 @@ public class NodeElement {
|
||||||
private String name;
|
private String name;
|
||||||
private String size;
|
private String size;
|
||||||
private String os;
|
private String os;
|
||||||
|
private String openports = "22";
|
||||||
private String passwordproperty;
|
private String passwordproperty;
|
||||||
private String keyfi1le;
|
private String keyfile;
|
||||||
private String hostproperty;
|
private String hostproperty;
|
||||||
private String idproperty;
|
private String idproperty;
|
||||||
private String usernameproperty;
|
private String usernameproperty;
|
||||||
private String location = "default";
|
private String location = "default";
|
||||||
|
private File runscript;
|
||||||
|
|
||||||
public String getLocation() {
|
public String getLocation() {
|
||||||
return location;
|
return location;
|
||||||
|
@ -101,11 +105,11 @@ public class NodeElement {
|
||||||
* The name of a file under which to store the DSA key of the user (if supported)
|
* The name of a file under which to store the DSA key of the user (if supported)
|
||||||
*/
|
*/
|
||||||
public void setKeyfile(String keyfile) {
|
public void setKeyfile(String keyfile) {
|
||||||
this.keyfi1le = keyfile;
|
this.keyfile = keyfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getKeyfile() {
|
String getKeyfile() {
|
||||||
return keyfi1le;
|
return keyfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSize(String size) {
|
public void setSize(String size) {
|
||||||
|
@ -124,4 +128,20 @@ public class NodeElement {
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRunscript(File runscript) {
|
||||||
|
this.runscript = runscript;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getRunscript() {
|
||||||
|
return runscript;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpenports(String openports) {
|
||||||
|
this.openports = openports;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOpenports() {
|
||||||
|
return openports;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,171 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
|
||||||
*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*/
|
|
||||||
package org.jclouds.vcloud;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import org.jclouds.compute.domain.OperatingSystem;
|
|
||||||
import org.jclouds.logging.Logger;
|
|
||||||
import org.jclouds.vcloud.domain.Task;
|
|
||||||
import org.jclouds.vcloud.domain.VApp;
|
|
||||||
import org.jclouds.vcloud.domain.VAppStatus;
|
|
||||||
import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
public class VCloudComputeClient {
|
|
||||||
@Resource
|
|
||||||
protected Logger logger = Logger.NULL;
|
|
||||||
|
|
||||||
private final Predicate<String> taskTester;
|
|
||||||
private final VCloudClient tmClient;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public VCloudComputeClient(VCloudClient tmClient, Predicate<String> successTester) {
|
|
||||||
this.tmClient = tmClient;
|
|
||||||
this.taskTester = successTester;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<OperatingSystem, String> imageCatalogIdMap = ImmutableMap
|
|
||||||
.<OperatingSystem, String> builder().put(OperatingSystem.CENTOS, "1").put(
|
|
||||||
OperatingSystem.RHEL, "8").put(OperatingSystem.UBUNTU, "11").build();
|
|
||||||
|
|
||||||
public Map<String, String> start(String name, OperatingSystem image, int minCores, int minMegs,
|
|
||||||
long diskSize, Map<String, String> properties) {
|
|
||||||
checkArgument(imageCatalogIdMap.containsKey(image), "image not configured: " + image);
|
|
||||||
String templateId = imageCatalogIdMap.get(image);
|
|
||||||
String vDCId = tmClient.getDefaultVDC().getId();
|
|
||||||
logger
|
|
||||||
.debug(
|
|
||||||
">> instantiating vApp vDC(%s) name(%s) template(%s) minCores(%d) minMegs(%d) diskSize(%d) properties(%s) ",
|
|
||||||
vDCId, name, templateId, minCores, minMegs, diskSize, properties);
|
|
||||||
VApp vAppResponse = tmClient.instantiateVAppTemplateInVDC(vDCId, name, templateId,
|
|
||||||
InstantiateVAppTemplateOptions.Builder.processorCount(minCores).memory(minMegs)
|
|
||||||
.disk(diskSize).productProperties(properties));
|
|
||||||
logger.debug("<< instantiated VApp(%s)", vAppResponse.getId());
|
|
||||||
|
|
||||||
logger.debug(">> deploying vApp(%s)", vAppResponse.getId());
|
|
||||||
VApp vApp = blockUntilVAppStatusOrThrowException(vAppResponse, tmClient
|
|
||||||
.deployVApp(vAppResponse.getId()), "deploy", VAppStatus.ON);// TODO, I'm not sure
|
|
||||||
// this should be on
|
|
||||||
// already
|
|
||||||
// logger.debug("<< deployed vApp(%s)", vApp.getId());
|
|
||||||
//
|
|
||||||
// logger.debug(">> powering vApp(%s)", vApp.getId());
|
|
||||||
// vApp = blockUntilVAppStatusOrThrowException(vApp, tmClient.powerOnVApp(vApp.getId()),
|
|
||||||
// "powerOn", VAppStatus.ON);
|
|
||||||
logger.debug("<< on vApp(%s)", vApp.getId());
|
|
||||||
|
|
||||||
return ImmutableMap.<String, String> of("id", vApp.getId(), "username", null, "password",
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @throws ElementNotFoundException
|
|
||||||
* if no address is configured
|
|
||||||
*/
|
|
||||||
public InetAddress getAnyPrivateAddress(String id) {
|
|
||||||
VApp vApp = tmClient.getVApp(id);
|
|
||||||
return Iterables.getLast(vApp.getNetworkToAddresses().values());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reboot(String id) {
|
|
||||||
VApp vApp = tmClient.getVApp(id);
|
|
||||||
logger.debug(">> rebooting vApp(%s)", vApp.getId());
|
|
||||||
blockUntilVAppStatusOrThrowException(vApp, tmClient.resetVApp(vApp.getId()), "reset",
|
|
||||||
VAppStatus.ON);
|
|
||||||
logger.debug("<< on vApp(%s)", vApp.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop(String id) {
|
|
||||||
VApp vApp = tmClient.getVApp(id);
|
|
||||||
if (vApp.getStatus() != VAppStatus.OFF) {
|
|
||||||
logger.debug(">> powering off vApp(%s), current status: %s", vApp.getId(), vApp
|
|
||||||
.getStatus());
|
|
||||||
blockUntilVAppStatusOrThrowException(vApp, tmClient.powerOffVApp(vApp.getId()),
|
|
||||||
"powerOff", VAppStatus.OFF);
|
|
||||||
logger.debug("<< off vApp(%s)", vApp.getId());
|
|
||||||
}
|
|
||||||
logger.debug(">> deleting vApp(%s)", vApp.getId());
|
|
||||||
tmClient.deleteVApp(id);
|
|
||||||
logger.debug("<< deleted vApp(%s)", vApp.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private VApp blockUntilVAppStatusOrThrowException(VApp vApp, Task deployTask, String taskType,
|
|
||||||
VAppStatus expectedStatus) {
|
|
||||||
if (!taskTester.apply(deployTask.getId())) {
|
|
||||||
throw new TaskException(taskType, vApp, deployTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
vApp = tmClient.getVApp(vApp.getId());
|
|
||||||
if (vApp.getStatus() != expectedStatus) {
|
|
||||||
throw new VAppException(String.format("vApp %s status %s should be %s after %s", vApp
|
|
||||||
.getId(), vApp.getStatus(), expectedStatus, taskType), vApp);
|
|
||||||
}
|
|
||||||
return vApp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TaskException extends VAppException {
|
|
||||||
|
|
||||||
private final Task task;
|
|
||||||
/** The serialVersionUID */
|
|
||||||
private static final long serialVersionUID = 251801929573211256L;
|
|
||||||
|
|
||||||
public TaskException(String type, VApp vApp, Task task) {
|
|
||||||
super(String.format("failed to %s vApp %s status %s;task %s status %s", type,
|
|
||||||
vApp.getId(), vApp.getStatus(), task.getLocation(), task.getStatus()), vApp);
|
|
||||||
this.task = task;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task getTask() {
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class VAppException extends RuntimeException {
|
|
||||||
|
|
||||||
private final VApp vApp;
|
|
||||||
/** The serialVersionUID */
|
|
||||||
private static final long serialVersionUID = 251801929573211256L;
|
|
||||||
|
|
||||||
public VAppException(String message, VApp vApp) {
|
|
||||||
super(message);
|
|
||||||
this.vApp = vApp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public VApp getvApp() {
|
|
||||||
return vApp;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,158 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
|
||||||
*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*/
|
|
||||||
package org.jclouds.vcloud;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
import org.jclouds.compute.domain.OperatingSystem;
|
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
|
||||||
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
|
||||||
import org.jclouds.vcloud.domain.ResourceType;
|
|
||||||
import org.jclouds.vcloud.domain.VApp;
|
|
||||||
import org.jclouds.vcloud.domain.VAppStatus;
|
|
||||||
import org.testng.annotations.AfterTest;
|
|
||||||
import org.testng.annotations.BeforeGroups;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
import com.google.common.base.CaseFormat;
|
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
import com.google.inject.Key;
|
|
||||||
import com.google.inject.TypeLiteral;
|
|
||||||
import com.google.inject.internal.ImmutableMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests behavior of {@code VCloudComputeClientLiveTest}
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
@Test(groups = "live", sequential = true, testName = "vcloud.VCloudClientLiveTest")
|
|
||||||
public class VCloudComputeClientLiveTest {
|
|
||||||
VCloudComputeClient client;
|
|
||||||
VCloudClient tmClient;
|
|
||||||
|
|
||||||
private String id;
|
|
||||||
private InetAddress privateAddress;
|
|
||||||
|
|
||||||
public static final String PREFIX = (System.getProperty("user.name") + "-vcloud").replaceAll(
|
|
||||||
"\\.", "");
|
|
||||||
|
|
||||||
private static class Expectation {
|
|
||||||
final long hardDisk;
|
|
||||||
final String os;
|
|
||||||
|
|
||||||
public Expectation(long hardDisk, String os) {
|
|
||||||
this.hardDisk = hardDisk;
|
|
||||||
this.os = os;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<OperatingSystem, Expectation> expectationMap = ImmutableMap
|
|
||||||
.<OperatingSystem, Expectation> builder().put(OperatingSystem.CENTOS,
|
|
||||||
new Expectation(4194304 / 2 * 10, "Red Hat Enterprise Linux 5 (64-bit)")).put(
|
|
||||||
OperatingSystem.RHEL,
|
|
||||||
new Expectation(4194304 / 2 * 10, "Red Hat Enterprise Linux 5 (64-bit)")).put(
|
|
||||||
OperatingSystem.UBUNTU, new Expectation(4194304, "Ubuntu Linux (32-bit)"))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
private Predicate<InetAddress> addressTester;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPowerOn() throws InterruptedException, ExecutionException, TimeoutException,
|
|
||||||
IOException {
|
|
||||||
OperatingSystem toTest = OperatingSystem.CENTOS;
|
|
||||||
|
|
||||||
String serverName = getCompatibleServerName(toTest);
|
|
||||||
int processorCount = 1;
|
|
||||||
int memory = 512;
|
|
||||||
long disk = 10 * 1025 * 1024;
|
|
||||||
Map<String, String> properties = ImmutableMap.of("foo", "bar");
|
|
||||||
|
|
||||||
id = client.start(serverName, toTest, processorCount, memory, disk, properties).get("id");
|
|
||||||
Expectation expectation = expectationMap.get(toTest);
|
|
||||||
|
|
||||||
VApp vApp = tmClient.getVApp(id);
|
|
||||||
verifyConfigurationOfVApp(vApp, serverName, expectation.os, processorCount, memory,
|
|
||||||
expectation.hardDisk);
|
|
||||||
assertEquals(vApp.getStatus(), VAppStatus.ON);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCompatibleServerName(OperatingSystem toTest) {
|
|
||||||
String serverName = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, toTest.toString())
|
|
||||||
.substring(0,
|
|
||||||
toTest.toString().length() - 1 <= 15 ? toTest.toString().length() - 1 : 14);
|
|
||||||
return serverName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testPowerOn")
|
|
||||||
public void testGetAnyPrivateAddress() {
|
|
||||||
privateAddress = client.getAnyPrivateAddress(id);
|
|
||||||
assert !addressTester.apply(privateAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void verifyConfigurationOfVApp(VApp vApp, String serverName, String expectedOs,
|
|
||||||
int processorCount, int memory, long hardDisk) {
|
|
||||||
// assertEquals(vApp.getName(), serverName);
|
|
||||||
// assertEquals(vApp.getOperatingSystemDescription(), expectedOs);
|
|
||||||
assertEquals(
|
|
||||||
Iterables.getOnlyElement(
|
|
||||||
vApp.getResourceAllocationByType().get(ResourceType.PROCESSOR))
|
|
||||||
.getVirtualQuantity(), processorCount);
|
|
||||||
assertEquals(Iterables.getOnlyElement(
|
|
||||||
vApp.getResourceAllocationByType().get(ResourceType.SCSI_CONTROLLER))
|
|
||||||
.getVirtualQuantity(), 1);
|
|
||||||
assertEquals(Iterables.getOnlyElement(
|
|
||||||
vApp.getResourceAllocationByType().get(ResourceType.MEMORY)).getVirtualQuantity(),
|
|
||||||
memory);
|
|
||||||
assertEquals(Iterables.getOnlyElement(
|
|
||||||
vApp.getResourceAllocationByType().get(ResourceType.DISK_DRIVE))
|
|
||||||
.getVirtualQuantity(), hardDisk);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterTest
|
|
||||||
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
|
|
||||||
if (id != null)
|
|
||||||
client.stop(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeGroups(groups = { "live" })
|
|
||||||
public void setupClient() {
|
|
||||||
String endpoint = checkNotNull(System.getProperty("jclouds.test.endpoint"),
|
|
||||||
"jclouds.test.endpoint");
|
|
||||||
String account = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
|
||||||
String key = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
|
||||||
Injector injector = new VCloudContextBuilder(new VCloudPropertiesBuilder(
|
|
||||||
URI.create(endpoint), account, key).build()).withModules(new Log4JLoggingModule(),
|
|
||||||
new JschSshClientModule()).buildInjector();
|
|
||||||
client = injector.getInstance(VCloudComputeClient.class);
|
|
||||||
tmClient = injector.getInstance(VCloudClient.class);
|
|
||||||
addressTester = injector.getInstance(Key.get(new TypeLiteral<Predicate<InetAddress>>() {
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,164 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
|
||||||
*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*/
|
|
||||||
package org.jclouds.vcloud.hostingdotcom.compute;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import org.jclouds.logging.Logger;
|
|
||||||
import org.jclouds.vcloud.domain.Task;
|
|
||||||
import org.jclouds.vcloud.domain.VApp;
|
|
||||||
import org.jclouds.vcloud.domain.VAppStatus;
|
|
||||||
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
|
|
||||||
import org.jclouds.vcloud.hostingdotcom.domain.HostingDotComVApp;
|
|
||||||
import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
public class HostingDotComVCloudComputeClient {
|
|
||||||
@Resource
|
|
||||||
protected Logger logger = Logger.NULL;
|
|
||||||
|
|
||||||
private final Predicate<String> taskTester;
|
|
||||||
private final HostingDotComVCloudClient tmClient;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public HostingDotComVCloudComputeClient(HostingDotComVCloudClient tmClient,
|
|
||||||
Predicate<String> successTester) {
|
|
||||||
this.tmClient = tmClient;
|
|
||||||
this.taskTester = successTester;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, String> start(String vDCId, String name, String templateId, int minCores,
|
|
||||||
int minMegs, long diskSize, Map<String, String> properties) {
|
|
||||||
logger
|
|
||||||
.debug(
|
|
||||||
">> instantiating vApp vDC(%s) name(%s) template(%s) minCores(%d) minMegs(%d) diskSize(%d) properties(%s) ",
|
|
||||||
vDCId, name, templateId, minCores, minMegs, diskSize, properties);
|
|
||||||
HostingDotComVApp vAppResponse = tmClient.instantiateVAppTemplateInVDC(vDCId, name,
|
|
||||||
templateId, InstantiateVAppTemplateOptions.Builder.processorCount(minCores).memory(
|
|
||||||
minMegs).disk(diskSize).productProperties(properties));
|
|
||||||
logger.debug("<< instantiated VApp(%s)", vAppResponse.getId());
|
|
||||||
|
|
||||||
logger.debug(">> deploying vApp(%s)", vAppResponse.getId());
|
|
||||||
VApp vApp = blockUntilVAppStatusOrThrowException(vAppResponse, tmClient
|
|
||||||
.deployVApp(vAppResponse.getId()), "deploy", VAppStatus.ON);// TODO, I'm not sure
|
|
||||||
// this should be on
|
|
||||||
// already
|
|
||||||
// logger.debug("<< deployed vApp(%s)", vApp.getId());
|
|
||||||
//
|
|
||||||
// logger.debug(">> powering vApp(%s)", vApp.getId());
|
|
||||||
// vApp = blockUntilVAppStatusOrThrowException(vApp, tmClient.powerOnVApp(vApp.getId()),
|
|
||||||
// "powerOn", VAppStatus.ON);
|
|
||||||
logger.debug("<< on vApp(%s)", vApp.getId());
|
|
||||||
|
|
||||||
return ImmutableMap.<String, String> of("id", vApp.getId(), "username", vAppResponse
|
|
||||||
.getUsername(), "password", vAppResponse.getPassword());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @throws ElementNotFoundException
|
|
||||||
* if no address is configured
|
|
||||||
*/
|
|
||||||
public InetAddress getAnyPrivateAddress(String id) {
|
|
||||||
VApp vApp = tmClient.getVApp(id);
|
|
||||||
return Iterables.getLast(vApp.getNetworkToAddresses().values());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reboot(String id) {
|
|
||||||
VApp vApp = tmClient.getVApp(id);
|
|
||||||
logger.debug(">> rebooting vApp(%s)", vApp.getId());
|
|
||||||
blockUntilVAppStatusOrThrowException(vApp, tmClient.resetVApp(vApp.getId()), "reset",
|
|
||||||
VAppStatus.ON);
|
|
||||||
logger.debug("<< on vApp(%s)", vApp.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop(String id) {
|
|
||||||
VApp vApp = tmClient.getVApp(id);
|
|
||||||
if (vApp.getStatus() != VAppStatus.OFF) {
|
|
||||||
logger.debug(">> powering off vApp(%s), current status: %s", vApp.getId(), vApp
|
|
||||||
.getStatus());
|
|
||||||
blockUntilVAppStatusOrThrowException(vApp, tmClient.powerOffVApp(vApp.getId()),
|
|
||||||
"powerOff", VAppStatus.OFF);
|
|
||||||
logger.debug("<< off vApp(%s)", vApp.getId());
|
|
||||||
}
|
|
||||||
logger.debug(">> deleting vApp(%s)", vApp.getId());
|
|
||||||
tmClient.deleteVApp(id);
|
|
||||||
logger.debug("<< deleted vApp(%s)", vApp.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private VApp blockUntilVAppStatusOrThrowException(VApp vApp, Task deployTask, String taskType,
|
|
||||||
VAppStatus expectedStatus) {
|
|
||||||
if (!taskTester.apply(deployTask.getId())) {
|
|
||||||
throw new TaskException(taskType, vApp, deployTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
vApp = tmClient.getVApp(vApp.getId());
|
|
||||||
if (vApp.getStatus() != expectedStatus) {
|
|
||||||
throw new VAppException(String.format("vApp %s status %s should be %s after %s", vApp
|
|
||||||
.getId(), vApp.getStatus(), expectedStatus, taskType), vApp);
|
|
||||||
}
|
|
||||||
return vApp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TaskException extends VAppException {
|
|
||||||
|
|
||||||
private final Task task;
|
|
||||||
/** The serialVersionUID */
|
|
||||||
private static final long serialVersionUID = 251801929573211256L;
|
|
||||||
|
|
||||||
public TaskException(String type, VApp vApp, Task task) {
|
|
||||||
super(String.format("failed to %s vApp %s status %s;task %s status %s", type,
|
|
||||||
vApp.getId(), vApp.getStatus(), task.getLocation(), task.getStatus()), vApp);
|
|
||||||
this.task = task;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task getTask() {
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class VAppException extends RuntimeException {
|
|
||||||
|
|
||||||
private final VApp vApp;
|
|
||||||
/** The serialVersionUID */
|
|
||||||
private static final long serialVersionUID = 251801929573211256L;
|
|
||||||
|
|
||||||
public VAppException(String message, VApp vApp) {
|
|
||||||
super(message);
|
|
||||||
this.vApp = vApp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public VApp getvApp() {
|
|
||||||
return vApp;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,155 +1,48 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
|
||||||
*
|
|
||||||
* ====================================================================
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*/
|
|
||||||
package org.jclouds.vcloud.hostingdotcom.compute;
|
package org.jclouds.vcloud.hostingdotcom.compute;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeService;
|
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
|
||||||
import org.jclouds.compute.domain.ComputeType;
|
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.LoginType;
|
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
|
||||||
import org.jclouds.compute.domain.NodeState;
|
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.vcloud.VCloudClient;
|
||||||
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
import org.jclouds.vcloud.compute.VCloudComputeService;
|
||||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
import org.jclouds.vcloud.compute.VCloudTemplate;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
|
||||||
import org.jclouds.domain.Credentials;
|
|
||||||
import org.jclouds.logging.Logger;
|
|
||||||
import org.jclouds.vcloud.VCloudMediaType;
|
|
||||||
import org.jclouds.vcloud.domain.NamedResource;
|
|
||||||
import org.jclouds.vcloud.domain.VApp;
|
import org.jclouds.vcloud.domain.VApp;
|
||||||
import org.jclouds.vcloud.domain.VAppStatus;
|
import org.jclouds.vcloud.hostingdotcom.domain.HostingDotComVApp;
|
||||||
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
|
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.inject.internal.ImmutableSet;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class HostingDotComVCloudComputeService implements ComputeService {
|
public class HostingDotComVCloudComputeService extends VCloudComputeService {
|
||||||
@Resource
|
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
|
||||||
protected Logger logger = Logger.NULL;
|
|
||||||
private final HostingDotComVCloudComputeClient computeClient;
|
|
||||||
private final HostingDotComVCloudClient client;
|
|
||||||
private final Set<? extends Image> images;
|
|
||||||
private final Set<? extends Size> sizes;
|
|
||||||
private final Provider<Set<HostingDotComVCloudTemplate>> templates;
|
|
||||||
|
|
||||||
private static final Map<VAppStatus, NodeState> vAppStatusToNodeState = ImmutableMap
|
|
||||||
.<VAppStatus, NodeState> builder().put(VAppStatus.OFF, NodeState.TERMINATED).put(
|
|
||||||
VAppStatus.ON, NodeState.RUNNING).put(VAppStatus.RESOLVED, NodeState.PENDING)
|
|
||||||
.put(VAppStatus.SUSPENDED, NodeState.SUSPENDED).put(VAppStatus.UNRESOLVED,
|
|
||||||
NodeState.PENDING).build();
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public HostingDotComVCloudComputeService(HostingDotComVCloudClient client,
|
public HostingDotComVCloudComputeService(VCloudClient client,
|
||||||
HostingDotComVCloudComputeClient computeClient, Set<? extends Image> images,
|
Provider<Set<? extends Image>> images, Provider<SortedSet<? extends Size>> sizes,
|
||||||
Set<? extends Size> sizes, Provider<Set<HostingDotComVCloudTemplate>> templates) {
|
Provider<Set<? extends VCloudTemplate>> templates, Predicate<String> successTester,
|
||||||
this.client = client;
|
Predicate<InetSocketAddress> socketTester) {
|
||||||
this.computeClient = computeClient;
|
super(client, images, sizes, templates, successTester, socketTester);
|
||||||
this.images = images;
|
|
||||||
this.sizes = sizes;
|
|
||||||
this.templates = templates;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CreateNodeResponse runNode(String name, Template template) {
|
protected Map<String, String> parseResponse(VApp vAppResponse) {
|
||||||
checkNotNull(template.getImage().getLocation(), "location");
|
checkState(vAppResponse instanceof HostingDotComVApp,
|
||||||
Map<String, String> metaMap = computeClient.start(template.getImage().getLocation(), name,
|
"bad configuration, vApp should be an instance of "
|
||||||
template.getImage().getId(), template.getSize().getCores(), template.getSize()
|
+ HostingDotComVApp.class.getName());
|
||||||
.getRam(), template.getSize().getDisk(), ImmutableMap.<String, String> of());
|
HostingDotComVApp hVApp = HostingDotComVApp.class.cast(vAppResponse);
|
||||||
VApp vApp = client.getVApp(metaMap.get("id"));
|
return ImmutableMap.<String, String> of("id", vAppResponse.getId(), "username", hVApp
|
||||||
return new CreateNodeResponseImpl(vApp.getId(), vApp.getName(), template.getImage()
|
.getUsername(), "password", hVApp.getPassword());
|
||||||
.getLocation(), vApp.getLocation(), ImmutableMap.<String, String> of(),
|
|
||||||
vAppStatusToNodeState.get(vApp.getStatus()), vApp.getNetworkToAddresses().values(),
|
|
||||||
ImmutableSet.<InetAddress> of(), 22, LoginType.SSH, new Credentials(metaMap
|
|
||||||
.get("username"), metaMap.get("password")), ImmutableMap
|
|
||||||
.<String, String> of());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public NodeMetadata getNodeMetadata(ComputeMetadata node) {
|
|
||||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
|
||||||
+ node.getType());
|
|
||||||
return getNodeMetadataByIdInVDC(checkNotNull(node.getLocation(), "location"), checkNotNull(
|
|
||||||
node.getId(), "node.id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private NodeMetadata getNodeMetadataByIdInVDC(String vDCId, String id) {
|
|
||||||
VApp vApp = client.getVApp(id);
|
|
||||||
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vDCId, vApp.getLocation(),
|
|
||||||
ImmutableMap.<String, String> of(), vAppStatusToNodeState.get(vApp.getStatus()),
|
|
||||||
vApp.getNetworkToAddresses().values(), ImmutableSet.<InetAddress> of(), 22,
|
|
||||||
LoginType.SSH, ImmutableMap.<String, String> of());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<ComputeMetadata> listNodes() {
|
|
||||||
Set<ComputeMetadata> nodes = Sets.newHashSet();
|
|
||||||
for (NamedResource vdc : client.getDefaultOrganization().getVDCs().values()) {
|
|
||||||
for (NamedResource resource : client.getVDC(vdc.getId()).getResourceEntities().values()) {
|
|
||||||
if (resource.getType().equals(VCloudMediaType.VAPP_XML)) {
|
|
||||||
nodes.add(getNodeMetadataByIdInVDC(vdc.getId(), resource.getId()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroyNode(ComputeMetadata node) {
|
|
||||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
|
||||||
+ node.getType());
|
|
||||||
computeClient.stop(checkNotNull(node.getId(), "node.id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Template createTemplateInLocation(String location) {
|
|
||||||
return new HostingDotComVCloudTemplate(client, images, sizes, location);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<? extends Size> listSizes() {
|
|
||||||
return sizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<? extends Template> listTemplates() {
|
|
||||||
return templates.get();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,22 +20,15 @@ package org.jclouds.vcloud.hostingdotcom.compute;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
|
||||||
import org.jclouds.compute.ComputeServiceContextBuilder;
|
|
||||||
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
|
||||||
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
||||||
import org.jclouds.logging.jdk.config.JDKLoggingModule;
|
import org.jclouds.logging.jdk.config.JDKLoggingModule;
|
||||||
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudAsyncClient;
|
import org.jclouds.vcloud.compute.VCloudComputeServiceContextBuilder;
|
||||||
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
|
|
||||||
import org.jclouds.vcloud.hostingdotcom.compute.config.HostingDotComVCloudComputeServiceContextModule;
|
import org.jclouds.vcloud.hostingdotcom.compute.config.HostingDotComVCloudComputeServiceContextModule;
|
||||||
import org.jclouds.vcloud.hostingdotcom.config.HostingDotComVCloudRestClientModule;
|
import org.jclouds.vcloud.hostingdotcom.config.HostingDotComVCloudRestClientModule;
|
||||||
|
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Key;
|
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.TypeLiteral;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates {@link HostingDotComVCloudComputeServiceContext} or {@link Injector} instances based on
|
* Creates {@link HostingDotComVCloudComputeServiceContext} or {@link Injector} instances based on
|
||||||
|
@ -51,23 +44,10 @@ import com.google.inject.TypeLiteral;
|
||||||
* @see HostingDotComVCloudComputeServiceContext
|
* @see HostingDotComVCloudComputeServiceContext
|
||||||
*/
|
*/
|
||||||
public class HostingDotComVCloudComputeServiceContextBuilder extends
|
public class HostingDotComVCloudComputeServiceContextBuilder extends
|
||||||
ComputeServiceContextBuilder<HostingDotComVCloudAsyncClient, HostingDotComVCloudClient> {
|
VCloudComputeServiceContextBuilder {
|
||||||
|
|
||||||
public HostingDotComVCloudComputeServiceContextBuilder(Properties props) {
|
public HostingDotComVCloudComputeServiceContextBuilder(Properties props) {
|
||||||
super(new TypeLiteral<HostingDotComVCloudAsyncClient>() {
|
super(props);
|
||||||
}, new TypeLiteral<HostingDotComVCloudClient>() {
|
|
||||||
}, props);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HostingDotComVCloudComputeServiceContextBuilder withExecutorService(
|
|
||||||
ExecutorService service) {
|
|
||||||
return (HostingDotComVCloudComputeServiceContextBuilder) super.withExecutorService(service);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HostingDotComVCloudComputeServiceContextBuilder withModules(Module... modules) {
|
|
||||||
return (HostingDotComVCloudComputeServiceContextBuilder) super.withModules(modules);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -80,14 +60,4 @@ public class HostingDotComVCloudComputeServiceContextBuilder extends
|
||||||
modules.add(new HostingDotComVCloudRestClientModule());
|
modules.add(new HostingDotComVCloudRestClientModule());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ComputeServiceContext buildComputeServiceContext() {
|
|
||||||
// need the generic type information
|
|
||||||
return (ComputeServiceContext) this
|
|
||||||
.buildInjector()
|
|
||||||
.getInstance(
|
|
||||||
Key
|
|
||||||
.get(new TypeLiteral<ComputeServiceContextImpl<HostingDotComVCloudAsyncClient, HostingDotComVCloudClient>>() {
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,180 +0,0 @@
|
||||||
package org.jclouds.vcloud.hostingdotcom.compute;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.jclouds.compute.domain.Image;
|
|
||||||
import org.jclouds.compute.domain.OperatingSystem;
|
|
||||||
import org.jclouds.compute.domain.Size;
|
|
||||||
import org.jclouds.compute.domain.Template;
|
|
||||||
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
|
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
public class HostingDotComVCloudTemplate implements Template {
|
|
||||||
private final HostingDotComVCloudClient client;
|
|
||||||
private final Set<? extends Image> images;
|
|
||||||
private final Set<? extends Size> sizes;
|
|
||||||
private Size size;
|
|
||||||
private String vDC;
|
|
||||||
private OperatingSystem operatingSystem;
|
|
||||||
private transient Image image;
|
|
||||||
|
|
||||||
public HostingDotComVCloudTemplate(HostingDotComVCloudClient client,
|
|
||||||
Set<? extends Image> images, Set<? extends Size> sizes, String location,
|
|
||||||
@Nullable Size size, OperatingSystem operatingSystem, @Nullable Image image) {
|
|
||||||
this.client = client;
|
|
||||||
this.images = images;
|
|
||||||
this.sizes = sizes;
|
|
||||||
this.vDC = location;
|
|
||||||
this.image = image != null ? image : resolveTemplate(images, operatingSystem);
|
|
||||||
this.size = size != null ? size : Iterables.get(sizes, 0);
|
|
||||||
this.operatingSystem = operatingSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Image resolveTemplate(Set<? extends Image> images, OperatingSystem operatingSystem) {
|
|
||||||
for (Image image : images) {
|
|
||||||
if (image.getOperatingSystem() == operatingSystem)
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
throw new RuntimeException("no configured image matches os: " + operatingSystem);
|
|
||||||
}
|
|
||||||
|
|
||||||
HostingDotComVCloudTemplate(HostingDotComVCloudClient client, Set<? extends Image> images,
|
|
||||||
Set<? extends Size> sizes, String location) {
|
|
||||||
this(client, images, sizes, location, null, OperatingSystem.CENTOS, null);// note the default
|
|
||||||
// os
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Size getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Image getImage() {
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Template smallest() {
|
|
||||||
this.size = Iterables.get(sizes, 0);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Template biggest() {
|
|
||||||
this.size = Iterables.getLast(sizes);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Template fastest() {
|
|
||||||
this.size = Iterables.getLast(sizes);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Template inLocation(String location) {
|
|
||||||
if (location.equalsIgnoreCase("default"))
|
|
||||||
location = client.getDefaultVDC().getId();
|
|
||||||
this.vDC = location;// TODO match vdc on template as well arch
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Template os(OperatingSystem os) {
|
|
||||||
this.operatingSystem = os;
|
|
||||||
this.image = resolveTemplate(images, operatingSystem);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Object clone() throws CloneNotSupportedException {
|
|
||||||
return new HostingDotComVCloudTemplate(client, images, sizes, vDC, size, operatingSystem,
|
|
||||||
image);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getvDC() {
|
|
||||||
return vDC;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
final int prime = 31;
|
|
||||||
int result = 1;
|
|
||||||
result = prime * result + ((image == null) ? 0 : image.hashCode());
|
|
||||||
result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode());
|
|
||||||
result = prime * result + ((size == null) ? 0 : size.hashCode());
|
|
||||||
result = prime * result + ((vDC == null) ? 0 : vDC.hashCode());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null)
|
|
||||||
return false;
|
|
||||||
if (getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
HostingDotComVCloudTemplate other = (HostingDotComVCloudTemplate) obj;
|
|
||||||
if (image == null) {
|
|
||||||
if (other.image != null)
|
|
||||||
return false;
|
|
||||||
} else if (!image.equals(other.image))
|
|
||||||
return false;
|
|
||||||
if (operatingSystem == null) {
|
|
||||||
if (other.operatingSystem != null)
|
|
||||||
return false;
|
|
||||||
} else if (!operatingSystem.equals(other.operatingSystem))
|
|
||||||
return false;
|
|
||||||
if (size == null) {
|
|
||||||
if (other.size != null)
|
|
||||||
return false;
|
|
||||||
} else if (!size.equals(other.size))
|
|
||||||
return false;
|
|
||||||
if (vDC == null) {
|
|
||||||
if (other.vDC != null)
|
|
||||||
return false;
|
|
||||||
} else if (!vDC.equals(other.vDC))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "HostingDotComVCloudTemplate [image=" + image + ", operatingSystem=" + operatingSystem
|
|
||||||
+ ", size=" + size + ", vDC=" + vDC + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -18,39 +18,11 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.vcloud.hostingdotcom.compute.config;
|
package org.jclouds.vcloud.hostingdotcom.compute.config;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.inject.Named;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule;
|
||||||
import org.jclouds.compute.domain.Architecture;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
|
||||||
import org.jclouds.compute.domain.OperatingSystem;
|
|
||||||
import org.jclouds.compute.domain.Size;
|
|
||||||
import org.jclouds.compute.domain.internal.ImageImpl;
|
|
||||||
import org.jclouds.compute.domain.internal.SizeImpl;
|
|
||||||
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
|
||||||
import org.jclouds.logging.Logger;
|
|
||||||
import org.jclouds.rest.RestContext;
|
|
||||||
import org.jclouds.vcloud.VCloudClient;
|
|
||||||
import org.jclouds.vcloud.VCloudMediaType;
|
|
||||||
import org.jclouds.vcloud.domain.Catalog;
|
|
||||||
import org.jclouds.vcloud.domain.CatalogItem;
|
|
||||||
import org.jclouds.vcloud.domain.NamedResource;
|
|
||||||
import org.jclouds.vcloud.domain.VAppTemplate;
|
|
||||||
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudAsyncClient;
|
|
||||||
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
|
|
||||||
import org.jclouds.vcloud.hostingdotcom.compute.HostingDotComVCloudComputeService;
|
import org.jclouds.vcloud.hostingdotcom.compute.HostingDotComVCloudComputeService;
|
||||||
import org.jclouds.vcloud.hostingdotcom.compute.HostingDotComVCloudTemplate;
|
|
||||||
import org.jclouds.vcloud.hostingdotcom.config.HostingDotComVCloudContextModule;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.inject.Injector;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.inject.Provides;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the {@link HostingDotComVCloudComputeServiceContext}; requires
|
* Configures the {@link HostingDotComVCloudComputeServiceContext}; requires
|
||||||
|
@ -59,81 +31,16 @@ import com.google.inject.Provides;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class HostingDotComVCloudComputeServiceContextModule extends
|
public class HostingDotComVCloudComputeServiceContextModule extends
|
||||||
HostingDotComVCloudContextModule {
|
VCloudComputeServiceContextModule {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
super.configure();
|
super.configure();
|
||||||
bind(ComputeService.class).to(HostingDotComVCloudComputeService.class).asEagerSingleton();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Override
|
||||||
@Singleton
|
protected ComputeService provideComputeService(Injector injector) {
|
||||||
ComputeServiceContext provideContext(ComputeService computeService,
|
return injector.getInstance(HostingDotComVCloudComputeService.class);
|
||||||
RestContext<HostingDotComVCloudAsyncClient, HostingDotComVCloudClient> context) {
|
|
||||||
return new ComputeServiceContextImpl<HostingDotComVCloudAsyncClient, HostingDotComVCloudClient>(
|
|
||||||
computeService, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class LogHolder {
|
|
||||||
@Resource
|
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
|
||||||
protected Logger logger = Logger.NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
Set<? extends Image> provideImages(VCloudClient client, LogHolder holder) {
|
|
||||||
Set<Image> images = Sets.newLinkedHashSet();
|
|
||||||
holder.logger.debug(">> providing images");
|
|
||||||
Catalog response = client.getDefaultCatalog();
|
|
||||||
String vDC = client.getDefaultVDC().getId();
|
|
||||||
for (NamedResource resource : response.values()) {
|
|
||||||
if (resource.getType().equals(VCloudMediaType.CATALOGITEM_XML)) {
|
|
||||||
|
|
||||||
CatalogItem item = client.getCatalogItem(resource.getId());
|
|
||||||
OperatingSystem myOs = OperatingSystem.UNKNOWN;
|
|
||||||
for (OperatingSystem os : OperatingSystem.values()) {
|
|
||||||
if (resource.getName().toUpperCase().replaceAll("\\s", "").indexOf(os.toString()) != -1) {
|
|
||||||
myOs = os;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Architecture arch = resource.getName().matches("64[- ]bit") ? Architecture.X86_32
|
|
||||||
: Architecture.X86_64;
|
|
||||||
if (item.getEntity().getType().equals(VCloudMediaType.VAPPTEMPLATE_XML)) {
|
|
||||||
VAppTemplate template = client.getVAppTemplate(item.getEntity().getId());
|
|
||||||
images.add(new ImageImpl(resource.getId(), template.getDescription(), myOs, null,
|
|
||||||
vDC, arch));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
holder.logger.debug("<< images(%d)", images.size());
|
|
||||||
return images;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
Set<? extends Size> provideSizes(HostingDotComVCloudClient client, Set<? extends Image> images,
|
|
||||||
LogHolder holder) {
|
|
||||||
return ImmutableSet.<Size> of(new SizeImpl(1, 512, (int) (10l * 1025 * 1024), ImmutableSet
|
|
||||||
.<Architecture> of(Architecture.X86_32, Architecture.X86_64)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
Set<HostingDotComVCloudTemplate> provideTemplates(HostingDotComVCloudClient client,
|
|
||||||
Set<? extends Image> images, Set<? extends Size> sizes, LogHolder holder) {
|
|
||||||
Set<HostingDotComVCloudTemplate> templates = Sets.newHashSet();
|
|
||||||
holder.logger.debug(">> generating templates");
|
|
||||||
String vDC = client.getDefaultVDC().getId();
|
|
||||||
for (Size size : sizes) {
|
|
||||||
for (Image image : images) {
|
|
||||||
templates.add(new HostingDotComVCloudTemplate(client, images, sizes, vDC, size, image
|
|
||||||
.getOperatingSystem(), image));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
holder.logger.debug("<< templates(%d)", templates.size());
|
|
||||||
return templates;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,138 +19,49 @@
|
||||||
package org.jclouds.vcloud.hostingdotcom.compute;
|
package org.jclouds.vcloud.hostingdotcom.compute;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
import org.jclouds.compute.domain.OperatingSystem;
|
import org.jclouds.compute.domain.OperatingSystem;
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
import org.jclouds.vcloud.domain.ResourceType;
|
import org.jclouds.vcloud.compute.VCloudComputeClientLiveTest;
|
||||||
import org.jclouds.vcloud.domain.VApp;
|
|
||||||
import org.jclouds.vcloud.domain.VAppStatus;
|
|
||||||
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
|
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient;
|
||||||
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudContextBuilder;
|
|
||||||
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudPropertiesBuilder;
|
import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudPropertiesBuilder;
|
||||||
import org.testng.annotations.AfterTest;
|
|
||||||
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.CaseFormat;
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Key;
|
import com.google.inject.Key;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
import com.google.inject.internal.ImmutableMap;
|
import com.google.inject.internal.ImmutableMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests behavior of {@code HostingDotComVCloudClient}
|
* Tests behavior of {@code HostingDotComVCloudComputeClient}
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", enabled = true, sequential = true, testName = "vcloud.HostingDotComVCloudClientLiveTest")
|
@Test(groups = "live", enabled = true, sequential = true, testName = "vcloud.HostingDotComVCloudComputeClientLiveTest")
|
||||||
public class HostingDotComVCloudComputeClientLiveTest {
|
public class HostingDotComVCloudComputeClientLiveTest extends VCloudComputeClientLiveTest {
|
||||||
HostingDotComVCloudComputeClient client;
|
|
||||||
HostingDotComVCloudClient hostingClient;
|
|
||||||
|
|
||||||
private String id;
|
|
||||||
private InetAddress privateAddress;
|
|
||||||
|
|
||||||
public static final String PREFIX = System.getProperty("user.name") + "-terremark";
|
|
||||||
|
|
||||||
private static class Expectation {
|
|
||||||
final long hardDisk;
|
|
||||||
final String os;
|
|
||||||
|
|
||||||
public Expectation(long hardDisk, String os) {
|
|
||||||
this.hardDisk = hardDisk;
|
|
||||||
this.os = os;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<OperatingSystem, Expectation> expectationMap = ImmutableMap
|
|
||||||
.<OperatingSystem, Expectation> builder().put(OperatingSystem.CENTOS,
|
|
||||||
new Expectation(4194304 / 2 * 10, "Red Hat Enterprise Linux 5 (64-bit)"))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
private Predicate<InetAddress> addressTester;
|
|
||||||
|
|
||||||
@Test(enabled = true)
|
|
||||||
public void testPowerOn() throws InterruptedException, ExecutionException, TimeoutException,
|
|
||||||
IOException {
|
|
||||||
OperatingSystem toTest = OperatingSystem.CENTOS;
|
|
||||||
|
|
||||||
String serverName = getCompatibleServerName(toTest);
|
|
||||||
int processorCount = 1;
|
|
||||||
int memory = 512;
|
|
||||||
long disk = 10 * 1025 * 1024;
|
|
||||||
Map<String, String> properties = ImmutableMap.of("foo", "bar");
|
|
||||||
|
|
||||||
id = client.start(hostingClient.getDefaultVDC().getId(), serverName, "3", processorCount,
|
|
||||||
memory, disk, properties).get("id");
|
|
||||||
Expectation expectation = expectationMap.get(toTest);
|
|
||||||
|
|
||||||
VApp vApp = hostingClient.getVApp(id);
|
|
||||||
verifyConfigurationOfVApp(vApp, serverName, expectation.os, processorCount, memory,
|
|
||||||
expectation.hardDisk);
|
|
||||||
assertEquals(vApp.getStatus(), VAppStatus.ON);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getCompatibleServerName(OperatingSystem toTest) {
|
|
||||||
String serverName = CaseFormat.UPPER_UNDERSCORE
|
|
||||||
.to(CaseFormat.LOWER_HYPHEN, toTest.toString()).substring(0,
|
|
||||||
toTest.toString().length() <= 15 ? toTest.toString().length() : 14);
|
|
||||||
return serverName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testPowerOn", enabled = true)
|
|
||||||
public void testGetAnyPrivateAddress() {
|
|
||||||
privateAddress = client.getAnyPrivateAddress(id);
|
|
||||||
assert !addressTester.apply(privateAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void verifyConfigurationOfVApp(VApp vApp, String serverName, String expectedOs,
|
|
||||||
int processorCount, int memory, long hardDisk) {
|
|
||||||
// assertEquals(vApp.getName(), serverName);
|
|
||||||
// assertEquals(vApp.getOperatingSystemDescription(), expectedOs);
|
|
||||||
assertEquals(
|
|
||||||
Iterables.getOnlyElement(
|
|
||||||
vApp.getResourceAllocationByType().get(ResourceType.PROCESSOR))
|
|
||||||
.getVirtualQuantity(), processorCount);
|
|
||||||
assertEquals(Iterables.getOnlyElement(
|
|
||||||
vApp.getResourceAllocationByType().get(ResourceType.SCSI_CONTROLLER))
|
|
||||||
.getVirtualQuantity(), 1);
|
|
||||||
assertEquals(Iterables.getOnlyElement(
|
|
||||||
vApp.getResourceAllocationByType().get(ResourceType.MEMORY)).getVirtualQuantity(),
|
|
||||||
memory);
|
|
||||||
assertEquals(Iterables.getOnlyElement(
|
|
||||||
vApp.getResourceAllocationByType().get(ResourceType.DISK_DRIVE))
|
|
||||||
.getVirtualQuantity(), hardDisk);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterTest
|
|
||||||
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
|
|
||||||
if (id != null)
|
|
||||||
client.stop(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@BeforeGroups(groups = { "live" })
|
@BeforeGroups(groups = { "live" })
|
||||||
|
@Override
|
||||||
public void setupClient() {
|
public void setupClient() {
|
||||||
|
|
||||||
String account = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
String account = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
||||||
String key = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
String key = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
||||||
Injector injector = new HostingDotComVCloudContextBuilder(
|
Injector injector = new HostingDotComVCloudComputeServiceContextBuilder(
|
||||||
new HostingDotComVCloudPropertiesBuilder(account, key).build()).withModules(
|
new HostingDotComVCloudPropertiesBuilder(account, key).build()).withModules(
|
||||||
new Log4JLoggingModule(), new JschSshClientModule()).buildInjector();
|
new Log4JLoggingModule(), new JschSshClientModule()).buildInjector();
|
||||||
client = injector.getInstance(HostingDotComVCloudComputeClient.class);
|
computeClient = injector.getInstance(HostingDotComVCloudComputeService.class);
|
||||||
hostingClient = injector.getInstance(HostingDotComVCloudClient.class);
|
client = injector.getInstance(HostingDotComVCloudClient.class);
|
||||||
addressTester = injector.getInstance(Key.get(new TypeLiteral<Predicate<InetAddress>>() {
|
addressTester = injector.getInstance(Key.get(new TypeLiteral<Predicate<InetAddress>>() {
|
||||||
}));
|
}));
|
||||||
|
expectationMap = ImmutableMap.<OperatingSystem, Expectation> builder().put(
|
||||||
|
OperatingSystem.CENTOS,
|
||||||
|
new Expectation(4194304 / 2 * 10, "Red Hat Enterprise Linux 5 (64-bit)")).build();
|
||||||
|
service = "vcloudtest";
|
||||||
|
templateId = "3";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,160 +19,30 @@
|
||||||
|
|
||||||
package org.jclouds.vcloud.hostingdotcom.compute;
|
package org.jclouds.vcloud.hostingdotcom.compute;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static org.jclouds.compute.domain.OperatingSystem.CENTOS;
|
import static org.jclouds.compute.domain.OperatingSystem.CENTOS;
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
import static org.testng.Assert.assertNotNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.jclouds.compute.BaseComputeServiceLiveTest;
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeService;
|
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
|
||||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
|
||||||
import org.jclouds.compute.domain.ComputeType;
|
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.LoginType;
|
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
|
||||||
import org.jclouds.compute.domain.OperatingSystem;
|
|
||||||
import org.jclouds.compute.domain.Size;
|
|
||||||
import org.jclouds.compute.domain.Template;
|
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
|
||||||
import org.jclouds.predicates.SocketOpen;
|
|
||||||
import org.jclouds.ssh.ExecResponse;
|
|
||||||
import org.jclouds.ssh.SshClient;
|
|
||||||
import org.jclouds.ssh.SshException;
|
|
||||||
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
import org.testng.annotations.AfterTest;
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.BeforeGroups;
|
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Generally disabled, as it incurs higher fees.
|
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", enabled = true, sequential = true, testName = "compute.HostingDotComVCloudComputeServiceLiveTest")
|
@Test(groups = "live", enabled = true, sequential = true, testName = "compute.HostingDotComVCloudComputeServiceLiveTest")
|
||||||
public class HostingDotComVCloudComputeServiceLiveTest {
|
public class HostingDotComVCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
||||||
private static final String service = "hostingdotcom";
|
@BeforeClass
|
||||||
private static final OperatingSystem testOS = CENTOS;
|
@Override
|
||||||
|
public void setServiceDefaults() {
|
||||||
protected SshClient.Factory sshFactory;
|
service = "hostingdotcom";
|
||||||
private String nodeName = service;
|
testOS = CENTOS;
|
||||||
|
|
||||||
private RetryablePredicate<InetSocketAddress> socketTester;
|
|
||||||
private CreateNodeResponse node;
|
|
||||||
private ComputeServiceContext context;
|
|
||||||
private ComputeService client;
|
|
||||||
|
|
||||||
@BeforeGroups(groups = { "live" })
|
|
||||||
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
|
|
||||||
IOException {
|
|
||||||
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
|
||||||
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
|
||||||
context = new ComputeServiceContextFactory().createContext(service, user, password,
|
|
||||||
ImmutableSet.of(new Log4JLoggingModule()), new Properties());
|
|
||||||
Injector injector = Guice.createInjector(new JschSshClientModule());
|
|
||||||
sshFactory = injector.getInstance(SshClient.Factory.class);
|
|
||||||
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
|
|
||||||
socketTester = new RetryablePredicate<InetSocketAddress>(socketOpen, 60, 1, TimeUnit.SECONDS);
|
|
||||||
injector.injectMembers(socketOpen); // add logger
|
|
||||||
client = context.getComputeService();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreate() throws Exception {
|
@Override
|
||||||
Template template = client.createTemplateInLocation("default").os(testOS).smallest();
|
protected JschSshClientModule getSshModule() {
|
||||||
node = client.runNode(nodeName, template);
|
return new JschSshClientModule();
|
||||||
assertNotNull(node.getId());
|
|
||||||
assertEquals(node.getLoginPort(), 22);
|
|
||||||
assertEquals(node.getLoginType(), LoginType.SSH);
|
|
||||||
assertNotNull(node.getName());
|
|
||||||
assertEquals(node.getPrivateAddresses().size(), 1);
|
|
||||||
assertEquals(node.getPublicAddresses().size(), 1);
|
|
||||||
assertNotNull(node.getCredentials());
|
|
||||||
assertNotNull(node.getCredentials().account);
|
|
||||||
assertNotNull(node.getCredentials().key);
|
|
||||||
sshPing();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testCreate")
|
|
||||||
public void testGet() throws Exception {
|
|
||||||
NodeMetadata metadata = client.getNodeMetadata(node);
|
|
||||||
assertEquals(metadata.getId(), node.getId());
|
|
||||||
assertEquals(metadata.getLoginPort(), node.getLoginPort());
|
|
||||||
assertEquals(metadata.getLoginType(), node.getLoginType());
|
|
||||||
assertEquals(metadata.getName(), node.getName());
|
|
||||||
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
|
|
||||||
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testList() throws Exception {
|
|
||||||
for (ComputeMetadata node : client.listNodes()) {
|
|
||||||
assert node.getId() != null;
|
|
||||||
assert node.getLocation() != null;
|
|
||||||
assertEquals(node.getType(), ComputeType.NODE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testListTemplates() throws Exception {
|
|
||||||
for (Template template : client.listTemplates()) {
|
|
||||||
assert template.getImage() != null;
|
|
||||||
System.out.println(template);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testListSizes() throws Exception {
|
|
||||||
for (Size size : client.listSizes()) {
|
|
||||||
assert size.getCores() != null;
|
|
||||||
System.out.println(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sshPing() throws IOException {
|
|
||||||
try {
|
|
||||||
doCheckKey();
|
|
||||||
} catch (SshException e) {// try twice in case there is a network timeout
|
|
||||||
try {
|
|
||||||
Thread.sleep(10 * 1000);
|
|
||||||
} catch (InterruptedException e1) {
|
|
||||||
}
|
|
||||||
doCheckKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doCheckKey() throws IOException {
|
|
||||||
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), node
|
|
||||||
.getLoginPort());
|
|
||||||
socketTester.apply(socket);
|
|
||||||
SshClient ssh = node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----") ? sshFactory
|
|
||||||
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
|
|
||||||
: sshFactory
|
|
||||||
.create(socket, node.getCredentials().account, node.getCredentials().key);
|
|
||||||
try {
|
|
||||||
ssh.connect();
|
|
||||||
ExecResponse hello = ssh.exec("echo hello");
|
|
||||||
assertEquals(hello.getOutput().trim(), "hello");
|
|
||||||
} finally {
|
|
||||||
if (ssh != null)
|
|
||||||
ssh.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterTest
|
|
||||||
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
|
|
||||||
if (node != null)
|
|
||||||
client.destroyNode(node);
|
|
||||||
context.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -86,9 +86,8 @@ public class TerremarkVCloudComputeClient {
|
||||||
properties);
|
properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String start(String vdc, String name, String templateId, int minCores, int minMegs,
|
public String start(String vDCId, String name, String templateId, int minCores, int minMegs,
|
||||||
Map<String, String> properties) {
|
Map<String, String> properties) {
|
||||||
String vDCId = tmClient.getDefaultVDC().getId();
|
|
||||||
logger
|
logger
|
||||||
.debug(
|
.debug(
|
||||||
">> instantiating vApp vDC(%s) template(%s) name(%s) minCores(%d) minMegs(%d) properties(%s)",
|
">> instantiating vApp vDC(%s) template(%s) name(%s) minCores(%d) minMegs(%d) properties(%s)",
|
||||||
|
|
|
@ -18,12 +18,13 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.vcloud.terremark.compute;
|
package org.jclouds.vcloud.terremark.compute;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static org.jclouds.vcloud.terremark.options.AddInternetServiceOptions.Builder.withDescription;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -31,127 +32,176 @@ import javax.inject.Named;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeService;
|
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
|
||||||
import org.jclouds.compute.domain.ComputeType;
|
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.LoginType;
|
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
|
||||||
import org.jclouds.compute.domain.NodeState;
|
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.Template;
|
|
||||||
import org.jclouds.compute.domain.internal.CreateNodeResponseImpl;
|
|
||||||
import org.jclouds.compute.domain.internal.NodeMetadataImpl;
|
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.domain.Credentials;
|
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.vcloud.VCloudMediaType;
|
import org.jclouds.vcloud.compute.VCloudComputeService;
|
||||||
import org.jclouds.vcloud.domain.NamedResource;
|
import org.jclouds.vcloud.compute.VCloudTemplate;
|
||||||
import org.jclouds.vcloud.domain.VApp;
|
import org.jclouds.vcloud.domain.VApp;
|
||||||
import org.jclouds.vcloud.domain.VAppStatus;
|
|
||||||
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
|
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
|
||||||
|
import org.jclouds.vcloud.terremark.domain.InternetService;
|
||||||
|
import org.jclouds.vcloud.terremark.domain.Node;
|
||||||
|
import org.jclouds.vcloud.terremark.domain.Protocol;
|
||||||
|
import org.jclouds.vcloud.terremark.domain.PublicIpAddress;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.inject.internal.ImmutableSet;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class TerremarkVCloudComputeService implements ComputeService {
|
public class TerremarkVCloudComputeService extends VCloudComputeService {
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
private final TerremarkVCloudComputeClient computeClient;
|
|
||||||
private final TerremarkVCloudClient client;
|
private final TerremarkVCloudClient client;
|
||||||
private Set<? extends Image> images;
|
|
||||||
private Set<? extends Size> sizes;
|
|
||||||
private Provider<Set<TerremarkVCloudTemplate>> templates;
|
|
||||||
|
|
||||||
private static final Map<VAppStatus, NodeState> vAppStatusToNodeState = ImmutableMap
|
|
||||||
.<VAppStatus, NodeState> builder().put(VAppStatus.OFF, NodeState.TERMINATED).put(
|
|
||||||
VAppStatus.ON, NodeState.RUNNING).put(VAppStatus.RESOLVED, NodeState.PENDING)
|
|
||||||
.put(VAppStatus.SUSPENDED, NodeState.SUSPENDED).put(VAppStatus.UNRESOLVED,
|
|
||||||
NodeState.PENDING).build();
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public TerremarkVCloudComputeService(TerremarkVCloudClient tmClient,
|
public TerremarkVCloudComputeService(TerremarkVCloudClient client,
|
||||||
TerremarkVCloudComputeClient computeClient, Set<? extends Image> images,
|
Provider<Set<? extends Image>> images, Provider<SortedSet<? extends Size>> sizes,
|
||||||
Set<? extends Size> sizes, Provider<Set<TerremarkVCloudTemplate>> templates) {
|
Provider<Set<? extends VCloudTemplate>> templates, Predicate<String> successTester,
|
||||||
this.client = tmClient;
|
Predicate<InetSocketAddress> socketTester) {
|
||||||
this.computeClient = computeClient;
|
super(client, images, sizes, templates, successTester, socketTester);
|
||||||
this.images = images;
|
this.client = client;
|
||||||
this.sizes = sizes;
|
|
||||||
this.templates = templates;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CreateNodeResponse runNode(String name, Template template) {
|
protected Map<String, String> parseResponse(VApp vAppResponse) {
|
||||||
checkNotNull(template.getImage().getLocation(), "location");
|
return ImmutableMap.<String, String> of("id", vAppResponse.getId(), "username", "vcloud",
|
||||||
String id = computeClient.start(template.getImage().getLocation(), name, template.getImage()
|
"password", "p4ssw0rd");
|
||||||
.getId(), (int) template.getSize().getCores(), (int) template.getSize().getRam(),
|
}
|
||||||
ImmutableMap.<String, String> of());
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> start(String vDCId, String name, String templateId, int minCores,
|
||||||
|
int minMegs, Long diskSize, Map<String, String> properties, int... portsToOpen) {
|
||||||
|
Map<String, String> response = super.start(vDCId, name, templateId, minCores, minMegs, null,
|
||||||
|
properties, portsToOpen);// trmk does not support resizing the primary disk
|
||||||
|
if (portsToOpen.length > 0)
|
||||||
|
createPublicAddressMappedToPorts(response.get("id"), portsToOpen);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InetAddress createPublicAddressMappedToPorts(String vAppId, int... ports) {
|
||||||
|
VApp vApp = client.getVApp(vAppId);
|
||||||
|
PublicIpAddress ip = null;
|
||||||
|
InetAddress privateAddress = Iterables.getLast(vApp.getNetworkToAddresses().values());
|
||||||
|
for (int port : ports) {
|
||||||
|
InternetService is = null;
|
||||||
|
Protocol protocol;
|
||||||
|
switch (port) {
|
||||||
|
case 22:
|
||||||
|
protocol = Protocol.TCP;
|
||||||
|
break;
|
||||||
|
case 80:
|
||||||
|
case 8080:
|
||||||
|
protocol = Protocol.HTTP;
|
||||||
|
break;
|
||||||
|
case 443:
|
||||||
|
protocol = Protocol.HTTPS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
protocol = Protocol.HTTP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ip == null) {
|
||||||
|
logger.debug(">> creating InternetService in vDC %s:%s:%d", vApp.getVDC().getId(),
|
||||||
|
protocol, port);
|
||||||
|
is = client.addInternetServiceToVDC(vApp.getVDC().getId(), vApp.getName() + "-" + port,
|
||||||
|
protocol, port, withDescription(String.format(
|
||||||
|
"port %d access to serverId: %s name: %s", port, vApp.getId(), vApp
|
||||||
|
.getName())));
|
||||||
|
ip = is.getPublicIpAddress();
|
||||||
|
} else {
|
||||||
|
logger.debug(">> adding InternetService %s:%s:%d", ip.getAddress().getHostAddress(),
|
||||||
|
protocol, port);
|
||||||
|
is = client.addInternetServiceToExistingIp(ip.getId(), vApp.getName() + "-" + port,
|
||||||
|
protocol, port, withDescription(String.format(
|
||||||
|
"port %d access to serverId: %s name: %s", port, vApp.getId(), vApp
|
||||||
|
.getName())));
|
||||||
|
}
|
||||||
|
logger.debug("<< created InternetService(%s) %s:%s:%d", is.getId(), is
|
||||||
|
.getPublicIpAddress().getAddress().getHostAddress(), is.getProtocol(), is
|
||||||
|
.getPort());
|
||||||
|
logger.debug(">> adding Node %s:%d -> %s:%d", is.getPublicIpAddress().getAddress()
|
||||||
|
.getHostAddress(), is.getPort(), privateAddress.getHostAddress(), port);
|
||||||
|
Node node = client.addNode(is.getId(), privateAddress, vApp.getName() + "-" + port, port);
|
||||||
|
logger.debug("<< added Node(%s)", node.getId());
|
||||||
|
}
|
||||||
|
return ip != null ? ip.getAddress() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop(String id) {
|
||||||
VApp vApp = client.getVApp(id);
|
VApp vApp = client.getVApp(id);
|
||||||
InetAddress publicIp = computeClient
|
Set<PublicIpAddress> ipAddresses = deleteInternetServicesAndNodesAssociatedWithVApp(vApp);
|
||||||
.createPublicAddressMappedToPorts(vApp, 22, 80, 8080, 443);
|
deletePublicIpAddressesWithNoServicesAttached(ipAddresses);
|
||||||
return new CreateNodeResponseImpl(vApp.getId(), vApp.getName(), template.getImage().getLocation(), vApp.getLocation(),
|
super.stop(id);
|
||||||
ImmutableMap.<String, String> of(), vAppStatusToNodeState.get(vApp.getStatus()),
|
|
||||||
ImmutableSet.<InetAddress> of(publicIp), vApp.getNetworkToAddresses().values(), 22,
|
|
||||||
LoginType.SSH, new Credentials("vcloud", "p4ssw0rd"), ImmutableMap
|
|
||||||
.<String, String> of());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Set<PublicIpAddress> deleteInternetServicesAndNodesAssociatedWithVApp(VApp vApp) {
|
||||||
public NodeMetadata getNodeMetadata(ComputeMetadata node) {
|
Set<PublicIpAddress> ipAddresses = Sets.newHashSet();
|
||||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
SERVICE: for (InternetService service : client.getAllInternetServicesInVDC(vApp.getVDC()
|
||||||
+ node.getType());
|
.getId())) {
|
||||||
return getNodeMetadataByIdInVDC(checkNotNull(node.getLocation(), "location"), checkNotNull(
|
for (Node node : client.getNodes(service.getId())) {
|
||||||
node.getId(), "node.id"));
|
if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) {
|
||||||
|
ipAddresses.add(service.getPublicIpAddress());
|
||||||
|
logger.debug(">> deleting Node(%s) %s:%d -> %s:%d", node.getId(), service
|
||||||
|
.getPublicIpAddress().getAddress().getHostAddress(), service.getPort(),
|
||||||
|
node.getIpAddress().getHostAddress(), node.getPort());
|
||||||
|
client.deleteNode(node.getId());
|
||||||
|
logger.debug("<< deleted Node(%s)", node.getId());
|
||||||
|
SortedSet<Node> nodes = client.getNodes(service.getId());
|
||||||
|
if (nodes.size() == 0) {
|
||||||
|
logger.debug(">> deleting InternetService(%s) %s:%d", service.getId(), service
|
||||||
|
.getPublicIpAddress().getAddress().getHostAddress(), service.getPort());
|
||||||
|
client.deleteInternetService(service.getId());
|
||||||
|
logger.debug("<< deleted InternetService(%s)", service.getId());
|
||||||
|
continue SERVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ipAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
private NodeMetadata getNodeMetadataByIdInVDC(String vDCId, String id) {
|
private void deletePublicIpAddressesWithNoServicesAttached(Set<PublicIpAddress> ipAddresses) {
|
||||||
|
IPADDRESS: for (PublicIpAddress address : ipAddresses) {
|
||||||
|
SortedSet<InternetService> services = client
|
||||||
|
.getInternetServicesOnPublicIp(address.getId());
|
||||||
|
if (services.size() == 0) {
|
||||||
|
logger.debug(">> deleting PublicIpAddress(%s) %s", address.getId(), address
|
||||||
|
.getAddress().getHostAddress());
|
||||||
|
client.deletePublicIp(address.getId());
|
||||||
|
logger.debug("<< deleted PublicIpAddress(%s)", address.getId());
|
||||||
|
continue IPADDRESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @throws ElementNotFoundException
|
||||||
|
* if no address is configured
|
||||||
|
*/
|
||||||
|
public InetAddress getAnyPrivateAddress(String id) {
|
||||||
VApp vApp = client.getVApp(id);
|
VApp vApp = client.getVApp(id);
|
||||||
Set<InetAddress> publicAddresses = computeClient.getPublicAddresses(vApp.getId());
|
return Iterables.getLast(vApp.getNetworkToAddresses().values());
|
||||||
return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vDCId, vApp.getLocation(),
|
|
||||||
ImmutableMap.<String, String> of(), vAppStatusToNodeState.get(vApp.getStatus()),
|
|
||||||
publicAddresses, vApp.getNetworkToAddresses().values(), 22, LoginType.SSH,
|
|
||||||
ImmutableMap.<String, String> of());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Set<InetAddress> getPublicAddresses(String id) {
|
||||||
public Set<ComputeMetadata> listNodes() {
|
VApp vApp = client.getVApp(id);
|
||||||
Set<ComputeMetadata> nodes = Sets.newHashSet();
|
Set<InetAddress> ipAddresses = Sets.newHashSet();
|
||||||
for (NamedResource vdc : client.getDefaultOrganization().getVDCs().values()) {
|
for (InternetService service : client.getAllInternetServicesInVDC(vApp.getVDC().getId())) {
|
||||||
for (NamedResource resource : client.getVDC(vdc.getId()).getResourceEntities().values()) {
|
for (Node node : client.getNodes(service.getId())) {
|
||||||
if (resource.getType().equals(VCloudMediaType.VAPP_XML)) {
|
if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) {
|
||||||
nodes.add(getNodeMetadataByIdInVDC(vdc.getId(), resource.getId()));
|
ipAddresses.add(service.getPublicIpAddress().getAddress());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nodes;
|
return ipAddresses;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void destroyNode(ComputeMetadata node) {
|
|
||||||
checkArgument(node.getType() == ComputeType.NODE, "this is only valid for nodes, not "
|
|
||||||
+ node.getType());
|
|
||||||
computeClient.stop(checkNotNull(node.getId(), "node.id"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Template createTemplateInLocation(String location) {
|
|
||||||
return new TerremarkVCloudTemplate(client, images, sizes, location);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<? extends Size> listSizes() {
|
|
||||||
return sizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<? extends Template> listTemplates() {
|
|
||||||
return templates.get();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,22 +20,15 @@ package org.jclouds.vcloud.terremark.compute;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
|
||||||
import org.jclouds.compute.ComputeServiceContextBuilder;
|
|
||||||
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
|
||||||
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
||||||
import org.jclouds.logging.jdk.config.JDKLoggingModule;
|
import org.jclouds.logging.jdk.config.JDKLoggingModule;
|
||||||
import org.jclouds.vcloud.terremark.TerremarkVCloudAsyncClient;
|
import org.jclouds.vcloud.compute.VCloudComputeServiceContextBuilder;
|
||||||
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
|
|
||||||
import org.jclouds.vcloud.terremark.compute.config.TerremarkVCloudComputeServiceContextModule;
|
import org.jclouds.vcloud.terremark.compute.config.TerremarkVCloudComputeServiceContextModule;
|
||||||
import org.jclouds.vcloud.terremark.config.TerremarkVCloudRestClientModule;
|
import org.jclouds.vcloud.terremark.config.TerremarkVCloudRestClientModule;
|
||||||
|
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Key;
|
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.TypeLiteral;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates {@link TerremarkVCloudComputeServiceContext} or {@link Injector} instances based on the
|
* Creates {@link TerremarkVCloudComputeServiceContext} or {@link Injector} instances based on the
|
||||||
|
@ -50,23 +43,10 @@ import com.google.inject.TypeLiteral;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
* @see TerremarkVCloudComputeServiceContext
|
* @see TerremarkVCloudComputeServiceContext
|
||||||
*/
|
*/
|
||||||
public class TerremarkVCloudComputeServiceContextBuilder extends
|
public class TerremarkVCloudComputeServiceContextBuilder extends VCloudComputeServiceContextBuilder {
|
||||||
ComputeServiceContextBuilder<TerremarkVCloudAsyncClient, TerremarkVCloudClient> {
|
|
||||||
|
|
||||||
public TerremarkVCloudComputeServiceContextBuilder(Properties props) {
|
public TerremarkVCloudComputeServiceContextBuilder(Properties props) {
|
||||||
super(new TypeLiteral<TerremarkVCloudAsyncClient>() {
|
super(props);
|
||||||
}, new TypeLiteral<TerremarkVCloudClient>() {
|
|
||||||
}, props);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TerremarkVCloudComputeServiceContextBuilder withExecutorService(ExecutorService service) {
|
|
||||||
return (TerremarkVCloudComputeServiceContextBuilder) super.withExecutorService(service);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TerremarkVCloudComputeServiceContextBuilder withModules(Module... modules) {
|
|
||||||
return (TerremarkVCloudComputeServiceContextBuilder) super.withModules(modules);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -79,14 +59,4 @@ public class TerremarkVCloudComputeServiceContextBuilder extends
|
||||||
modules.add(new TerremarkVCloudRestClientModule());
|
modules.add(new TerremarkVCloudRestClientModule());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ComputeServiceContext buildComputeServiceContext() {
|
|
||||||
// need the generic type information
|
|
||||||
return (ComputeServiceContext) this
|
|
||||||
.buildInjector()
|
|
||||||
.getInstance(
|
|
||||||
Key
|
|
||||||
.get(new TypeLiteral<ComputeServiceContextImpl<TerremarkVCloudAsyncClient, TerremarkVCloudClient>>() {
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,178 +0,0 @@
|
||||||
package org.jclouds.vcloud.terremark.compute;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.jclouds.compute.domain.Image;
|
|
||||||
import org.jclouds.compute.domain.OperatingSystem;
|
|
||||||
import org.jclouds.compute.domain.Size;
|
|
||||||
import org.jclouds.compute.domain.Template;
|
|
||||||
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
|
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Adrian Cole
|
|
||||||
*/
|
|
||||||
public class TerremarkVCloudTemplate implements Template {
|
|
||||||
private final TerremarkVCloudClient client;
|
|
||||||
private final Set<? extends Image> images;
|
|
||||||
private final Set<? extends Size> sizes;
|
|
||||||
private Size size;
|
|
||||||
private String vDC;
|
|
||||||
private OperatingSystem operatingSystem;
|
|
||||||
private transient Image image;
|
|
||||||
|
|
||||||
public TerremarkVCloudTemplate(TerremarkVCloudClient client, Set<? extends Image> images,
|
|
||||||
Set<? extends Size> sizes, String location, @Nullable Size size,
|
|
||||||
OperatingSystem operatingSystem, @Nullable Image image) {
|
|
||||||
this.client = client;
|
|
||||||
this.images = images;
|
|
||||||
this.sizes = sizes;
|
|
||||||
this.vDC = location;
|
|
||||||
this.image = image != null ? image : resolveTemplate(images, operatingSystem);
|
|
||||||
this.size = size != null ? size : Iterables.get(sizes, 0);
|
|
||||||
this.operatingSystem = operatingSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Image resolveTemplate(Set<? extends Image> images, OperatingSystem operatingSystem) {
|
|
||||||
for (Image image : images) {
|
|
||||||
if (image.getOperatingSystem() == operatingSystem)
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
throw new RuntimeException("no configured image matches os: " + operatingSystem);
|
|
||||||
}
|
|
||||||
|
|
||||||
TerremarkVCloudTemplate(TerremarkVCloudClient client, Set<? extends Image> images,
|
|
||||||
Set<? extends Size> sizes, String location) {
|
|
||||||
this(client, images, sizes, location, null, OperatingSystem.UBUNTU, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Size getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Image getImage() {
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Template smallest() {
|
|
||||||
this.size = Iterables.get(sizes, 0);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Template biggest() {
|
|
||||||
this.size = Iterables.getLast(sizes);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Template fastest() {
|
|
||||||
this.size = Iterables.getLast(sizes);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Template inLocation(String location) {
|
|
||||||
if (location.equalsIgnoreCase("default"))
|
|
||||||
location = client.getDefaultVDC().getId();
|
|
||||||
this.vDC = location;// TODO match vdc on template as well arch
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Template os(OperatingSystem os) {
|
|
||||||
this.operatingSystem = os;
|
|
||||||
this.image = resolveTemplate(images, operatingSystem);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Object clone() throws CloneNotSupportedException {
|
|
||||||
return new TerremarkVCloudTemplate(client, images, sizes, vDC, size, operatingSystem, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getvDC() {
|
|
||||||
return vDC;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
final int prime = 31;
|
|
||||||
int result = 1;
|
|
||||||
result = prime * result + ((image == null) ? 0 : image.hashCode());
|
|
||||||
result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode());
|
|
||||||
result = prime * result + ((size == null) ? 0 : size.hashCode());
|
|
||||||
result = prime * result + ((vDC == null) ? 0 : vDC.hashCode());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null)
|
|
||||||
return false;
|
|
||||||
if (getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
TerremarkVCloudTemplate other = (TerremarkVCloudTemplate) obj;
|
|
||||||
if (image == null) {
|
|
||||||
if (other.image != null)
|
|
||||||
return false;
|
|
||||||
} else if (!image.equals(other.image))
|
|
||||||
return false;
|
|
||||||
if (operatingSystem == null) {
|
|
||||||
if (other.operatingSystem != null)
|
|
||||||
return false;
|
|
||||||
} else if (!operatingSystem.equals(other.operatingSystem))
|
|
||||||
return false;
|
|
||||||
if (size == null) {
|
|
||||||
if (other.size != null)
|
|
||||||
return false;
|
|
||||||
} else if (!size.equals(other.size))
|
|
||||||
return false;
|
|
||||||
if (vDC == null) {
|
|
||||||
if (other.vDC != null)
|
|
||||||
return false;
|
|
||||||
} else if (!vDC.equals(other.vDC))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "TerremarkVCloudTemplate [image=" + image + ", operatingSystem=" + operatingSystem
|
|
||||||
+ ", size=" + size + ", vDC=" + vDC + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -18,43 +18,26 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.vcloud.terremark.compute.config;
|
package org.jclouds.vcloud.terremark.compute.config;
|
||||||
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
import javax.annotation.Resource;
|
import java.util.concurrent.ExecutorService;
|
||||||
import javax.inject.Named;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeService;
|
import org.jclouds.compute.ComputeService;
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
|
||||||
import org.jclouds.compute.domain.Architecture;
|
import org.jclouds.compute.domain.Architecture;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.OperatingSystem;
|
|
||||||
import org.jclouds.compute.domain.Size;
|
import org.jclouds.compute.domain.Size;
|
||||||
import org.jclouds.compute.domain.internal.ImageImpl;
|
|
||||||
import org.jclouds.compute.domain.internal.SizeImpl;
|
import org.jclouds.compute.domain.internal.SizeImpl;
|
||||||
import org.jclouds.compute.internal.ComputeServiceContextImpl;
|
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
|
||||||
import org.jclouds.logging.Logger;
|
|
||||||
import org.jclouds.rest.RestContext;
|
|
||||||
import org.jclouds.vcloud.VCloudClient;
|
import org.jclouds.vcloud.VCloudClient;
|
||||||
import org.jclouds.vcloud.VCloudMediaType;
|
import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule;
|
||||||
import org.jclouds.vcloud.domain.Catalog;
|
|
||||||
import org.jclouds.vcloud.domain.CatalogItem;
|
|
||||||
import org.jclouds.vcloud.domain.NamedResource;
|
|
||||||
import org.jclouds.vcloud.domain.VAppTemplate;
|
|
||||||
import org.jclouds.vcloud.terremark.TerremarkVCloudAsyncClient;
|
|
||||||
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
|
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
|
||||||
import org.jclouds.vcloud.terremark.compute.TerremarkVCloudComputeService;
|
import org.jclouds.vcloud.terremark.compute.TerremarkVCloudComputeService;
|
||||||
import org.jclouds.vcloud.terremark.compute.TerremarkVCloudTemplate;
|
|
||||||
import org.jclouds.vcloud.terremark.config.TerremarkVCloudContextModule;
|
|
||||||
import org.jclouds.vcloud.terremark.domain.ComputeOptions;
|
import org.jclouds.vcloud.terremark.domain.ComputeOptions;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
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.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Injector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the {@link TerremarkVCloudComputeServiceContext}; requires
|
* Configures the {@link TerremarkVCloudComputeServiceContext}; requires
|
||||||
|
@ -62,98 +45,37 @@ import com.google.inject.Provides;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class TerremarkVCloudComputeServiceContextModule extends TerremarkVCloudContextModule {
|
public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeServiceContextModule {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
super.configure();
|
super.configure();
|
||||||
bind(ComputeService.class).to(TerremarkVCloudComputeService.class).asEagerSingleton();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Override
|
||||||
@Singleton
|
protected ComputeService provideComputeService(Injector injector) {
|
||||||
ComputeServiceContext provideContext(ComputeService computeService,
|
return injector.getInstance(TerremarkVCloudComputeService.class);
|
||||||
RestContext<TerremarkVCloudAsyncClient, TerremarkVCloudClient> context) {
|
|
||||||
return new ComputeServiceContextImpl<TerremarkVCloudAsyncClient, TerremarkVCloudClient>(
|
|
||||||
computeService, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final ComputeOptionsToSize sizeConverter = new ComputeOptionsToSize();
|
private static final ComputeOptionsToSize sizeConverter = new ComputeOptionsToSize();
|
||||||
|
|
||||||
private static class ComputeOptionsToSize implements Function<ComputeOptions, Size> {
|
private static class ComputeOptionsToSize implements Function<ComputeOptions, Size> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Size apply(ComputeOptions from) {
|
public Size apply(ComputeOptions from) {
|
||||||
return new SizeImpl(from.getProcessorCount(), (int) from.getMemory(), null, ImmutableSet
|
return new SizeImpl(from.getProcessorCount(), from.getMemory(), 10, ImmutableSet
|
||||||
.<Architecture> of(Architecture.X86_32, Architecture.X86_64));
|
.<Architecture> of(Architecture.X86_32, Architecture.X86_64));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LogHolder {
|
@Override
|
||||||
@Resource
|
protected SortedSet<? extends Size> provideSizes(VCloudClient client,
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
Set<? extends Image> images, LogHolder holder, ExecutorService executor) {
|
||||||
protected Logger logger = Logger.NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
Set<? extends Image> provideImages(VCloudClient client, LogHolder holder) {
|
|
||||||
Set<Image> images = Sets.newLinkedHashSet();
|
|
||||||
holder.logger.debug(">> providing images");
|
|
||||||
Catalog response = client.getDefaultCatalog();
|
|
||||||
String vDC = client.getDefaultVDC().getId();
|
|
||||||
for (NamedResource resource : response.values()) {
|
|
||||||
if (resource.getType().equals(VCloudMediaType.CATALOGITEM_XML)) {
|
|
||||||
|
|
||||||
CatalogItem item = client.getCatalogItem(resource.getId());
|
|
||||||
OperatingSystem myOs = OperatingSystem.UNKNOWN;
|
|
||||||
for (OperatingSystem os : OperatingSystem.values()) {
|
|
||||||
if (resource.getName().toUpperCase().replaceAll("\\s", "").indexOf(os.toString()) != -1) {
|
|
||||||
myOs = os;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Architecture arch = resource.getName().matches("64[- ]bit") ? Architecture.X86_32
|
|
||||||
: Architecture.X86_64;
|
|
||||||
if (item.getEntity().getType().equals(VCloudMediaType.VAPPTEMPLATE_XML)) {
|
|
||||||
VAppTemplate template = client.getVAppTemplate(item.getEntity().getId());
|
|
||||||
images.add(new ImageImpl(resource.getId(), template.getDescription(), myOs, null,
|
|
||||||
vDC, arch));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
holder.logger.debug("<< images(%d)", images.size());
|
|
||||||
return images;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
Set<? extends Size> provideSizes(TerremarkVCloudClient client, Set<? extends Image> images,
|
|
||||||
LogHolder holder) {
|
|
||||||
Image anyImage = Iterables.get(images, 0);
|
Image anyImage = Iterables.get(images, 0);
|
||||||
holder.logger.debug(">> providing sizes");
|
holder.logger.debug(">> providing sizes");
|
||||||
LinkedHashSet<Size> sizes = Sets.newLinkedHashSet(Iterables.transform(client
|
SortedSet<Size> sizes = Sets.newTreeSet(Iterables.transform(TerremarkVCloudClient.class.cast(
|
||||||
.getComputeOptionsOfCatalogItem(anyImage.getId()), sizeConverter));
|
client).getComputeOptionsOfCatalogItem(anyImage.getId()), sizeConverter));
|
||||||
holder.logger.debug("<< sizes(%d)", sizes.size());
|
holder.logger.debug("<< sizes(%d)", sizes.size());
|
||||||
return sizes;
|
return sizes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
Set<TerremarkVCloudTemplate> provideTemplates(TerremarkVCloudClient client,
|
|
||||||
Set<? extends Image> images, Set<? extends Size> sizes, LogHolder holder) {
|
|
||||||
Set<TerremarkVCloudTemplate> templates = Sets.newHashSet();
|
|
||||||
holder.logger.debug(">> generating templates");
|
|
||||||
String vDC = client.getDefaultVDC().getId();
|
|
||||||
for (Size size : sizes) {
|
|
||||||
for (Image image : images) {
|
|
||||||
templates.add(new TerremarkVCloudTemplate(client, images, sizes, vDC, size, image
|
|
||||||
.getOperatingSystem(), image));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
holder.logger.debug("<< templates(%d)", templates.size());
|
|
||||||
return templates;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,10 +29,10 @@ package org.jclouds.vcloud.terremark.domain;
|
||||||
*/
|
*/
|
||||||
public class ComputeOptions implements Comparable<ComputeOptions> {
|
public class ComputeOptions implements Comparable<ComputeOptions> {
|
||||||
private final int processorCount;
|
private final int processorCount;
|
||||||
private final long memory;
|
private final int memory;
|
||||||
private final float costPerHour;
|
private final float costPerHour;
|
||||||
|
|
||||||
public ComputeOptions(int processorCount, long memory, float costPerHour) {
|
public ComputeOptions(int processorCount, int memory, float costPerHour) {
|
||||||
this.processorCount = processorCount;
|
this.processorCount = processorCount;
|
||||||
this.memory = memory;
|
this.memory = memory;
|
||||||
this.costPerHour = costPerHour;
|
this.costPerHour = costPerHour;
|
||||||
|
@ -42,7 +42,7 @@ public class ComputeOptions implements Comparable<ComputeOptions> {
|
||||||
return processorCount;
|
return processorCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getMemory() {
|
public int getMemory() {
|
||||||
return memory;
|
return memory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,45 +19,18 @@
|
||||||
|
|
||||||
package org.jclouds.vcloud.terremark.compute;
|
package org.jclouds.vcloud.terremark.compute;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static org.jclouds.compute.domain.OperatingSystem.JEOS;
|
||||||
import static org.jclouds.compute.domain.OperatingSystem.CENTOS;
|
|
||||||
import static org.jclouds.compute.domain.OperatingSystem.UBUNTU;
|
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
import static org.testng.Assert.assertNotNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.jclouds.compute.BaseComputeServiceLiveTest;
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
import org.jclouds.compute.ComputeService;
|
|
||||||
import org.jclouds.compute.ComputeServiceContext;
|
|
||||||
import org.jclouds.compute.ComputeServiceContextFactory;
|
import org.jclouds.compute.ComputeServiceContextFactory;
|
||||||
import org.jclouds.compute.domain.ComputeMetadata;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.compute.domain.ComputeType;
|
|
||||||
import org.jclouds.compute.domain.CreateNodeResponse;
|
|
||||||
import org.jclouds.compute.domain.LoginType;
|
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
|
||||||
import org.jclouds.compute.domain.OperatingSystem;
|
|
||||||
import org.jclouds.compute.domain.Size;
|
|
||||||
import org.jclouds.compute.domain.Template;
|
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
|
||||||
import org.jclouds.predicates.RetryablePredicate;
|
|
||||||
import org.jclouds.predicates.SocketOpen;
|
|
||||||
import org.jclouds.ssh.ExecResponse;
|
|
||||||
import org.jclouds.ssh.SshClient;
|
|
||||||
import org.jclouds.ssh.SshException;
|
|
||||||
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
import org.testng.annotations.AfterTest;
|
import org.jclouds.vcloud.compute.VCloudComputeClient;
|
||||||
import org.testng.annotations.BeforeGroups;
|
import org.jclouds.vcloud.terremark.TerremarkVCloudAsyncClient;
|
||||||
|
import org.jclouds.vcloud.terremark.TerremarkVCloudClient;
|
||||||
|
import org.testng.annotations.BeforeClass;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Generally disabled, as it incurs higher fees.
|
* Generally disabled, as it incurs higher fees.
|
||||||
|
@ -65,115 +38,28 @@ import com.google.inject.Injector;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "live", enabled = true, sequential = true, testName = "terremark.TerremarkVCloudComputeServiceLiveTest")
|
@Test(groups = "live", enabled = true, sequential = true, testName = "terremark.TerremarkVCloudComputeServiceLiveTest")
|
||||||
public class TerremarkVCloudComputeServiceLiveTest {
|
public class TerremarkVCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
||||||
private static final String service = "terremark";
|
@BeforeClass
|
||||||
private static final OperatingSystem testOS = UBUNTU;
|
@Override
|
||||||
|
public void setServiceDefaults() {
|
||||||
protected SshClient.Factory sshFactory;
|
service = "terremark";
|
||||||
private String nodeName = service;
|
testOS = JEOS;
|
||||||
|
|
||||||
private RetryablePredicate<InetSocketAddress> socketTester;
|
|
||||||
private CreateNodeResponse node;
|
|
||||||
private ComputeServiceContext context;
|
|
||||||
private ComputeService client;
|
|
||||||
|
|
||||||
@BeforeGroups(groups = { "live" })
|
|
||||||
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException,
|
|
||||||
IOException {
|
|
||||||
String user = checkNotNull(System.getProperty("jclouds.test.user"), "jclouds.test.user");
|
|
||||||
String password = checkNotNull(System.getProperty("jclouds.test.key"), "jclouds.test.key");
|
|
||||||
context = new ComputeServiceContextFactory().createContext(service, user, password,
|
|
||||||
ImmutableSet.of(new Log4JLoggingModule()), new Properties());
|
|
||||||
Injector injector = Guice.createInjector(new JschSshClientModule());
|
|
||||||
sshFactory = injector.getInstance(SshClient.Factory.class);
|
|
||||||
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
|
|
||||||
socketTester = new RetryablePredicate<InetSocketAddress>(socketOpen, 60, 1, TimeUnit.SECONDS);
|
|
||||||
injector.injectMembers(socketOpen); // add logger
|
|
||||||
client = context.getComputeService();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreate() throws Exception {
|
@Override
|
||||||
Template template = client.createTemplateInLocation("default").os(testOS).smallest();
|
protected JschSshClientModule getSshModule() {
|
||||||
node = client.runNode(nodeName, template);
|
return new JschSshClientModule();
|
||||||
assertNotNull(node.getId());
|
|
||||||
assertEquals(node.getLoginPort(), 22);
|
|
||||||
assertEquals(node.getLoginType(), LoginType.SSH);
|
|
||||||
assertNotNull(node.getName());
|
|
||||||
assertEquals(node.getPrivateAddresses().size(), 1);
|
|
||||||
assertEquals(node.getPublicAddresses().size(), 1);
|
|
||||||
assertNotNull(node.getCredentials());
|
|
||||||
assertNotNull(node.getCredentials().account);
|
|
||||||
assertNotNull(node.getCredentials().key);
|
|
||||||
sshPing();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(dependsOnMethods = "testCreate")
|
public void testAssignability() throws Exception {
|
||||||
public void testGet() throws Exception {
|
@SuppressWarnings("unused")
|
||||||
NodeMetadata metadata = client.getNodeMetadata(node);
|
RestContext<TerremarkVCloudAsyncClient, TerremarkVCloudClient> tmContext = new ComputeServiceContextFactory()
|
||||||
assertEquals(metadata.getId(), node.getId());
|
.createContext(service, user, password).getProviderSpecificContext();
|
||||||
assertEquals(metadata.getLoginPort(), node.getLoginPort());
|
|
||||||
assertEquals(metadata.getLoginType(), node.getLoginType());
|
|
||||||
assertEquals(metadata.getName(), node.getName());
|
|
||||||
assertEquals(metadata.getPrivateAddresses(), node.getPrivateAddresses());
|
|
||||||
assertEquals(metadata.getPublicAddresses(), node.getPublicAddresses());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testList() throws Exception {
|
TerremarkVCloudComputeService computeService = TerremarkVCloudComputeService.class
|
||||||
for (ComputeMetadata node : client.listNodes()) {
|
.cast(client);
|
||||||
assert node.getId() != null;
|
|
||||||
assert node.getLocation() != null;
|
|
||||||
assertEquals(node.getType(), ComputeType.NODE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testListTemplates() throws Exception {
|
@SuppressWarnings("unused")
|
||||||
for (Template template : client.listTemplates()) {
|
VCloudComputeClient computeClient = VCloudComputeClient.class.cast(computeService);
|
||||||
assert template.getImage() != null;
|
|
||||||
System.out.println(template);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testListSizes() throws Exception {
|
|
||||||
for (Size size : client.listSizes()) {
|
|
||||||
assert size.getCores() != null;
|
|
||||||
System.out.println(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sshPing() throws IOException {
|
|
||||||
try {
|
|
||||||
doCheckKey();
|
|
||||||
} catch (SshException e) {// try twice in case there is a network timeout
|
|
||||||
try {
|
|
||||||
Thread.sleep(10 * 1000);
|
|
||||||
} catch (InterruptedException e1) {
|
|
||||||
}
|
|
||||||
doCheckKey();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void doCheckKey() throws IOException {
|
|
||||||
InetSocketAddress socket = new InetSocketAddress(node.getPublicAddresses().last(), node
|
|
||||||
.getLoginPort());
|
|
||||||
socketTester.apply(socket);
|
|
||||||
SshClient ssh = node.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----") ? sshFactory
|
|
||||||
.create(socket, node.getCredentials().account, node.getCredentials().key.getBytes())
|
|
||||||
: sshFactory
|
|
||||||
.create(socket, node.getCredentials().account, node.getCredentials().key);
|
|
||||||
try {
|
|
||||||
ssh.connect();
|
|
||||||
ExecResponse hello = ssh.exec("echo hello");
|
|
||||||
assertEquals(hello.getOutput().trim(), "hello");
|
|
||||||
} finally {
|
|
||||||
if (ssh != null)
|
|
||||||
ssh.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterTest
|
|
||||||
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
|
|
||||||
if (node != null)
|
|
||||||
client.destroyNode(node);
|
|
||||||
context.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue