From cb906ded3ccad2ca0dbc01470460da57a958b96a Mon Sep 17 00:00:00 2001 From: "adrian.f.cole" Date: Thu, 21 Jan 2010 06:22:42 +0000 Subject: [PATCH] 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 --- .../aws/ec2/compute/EC2ComputeService.java | 42 +-- .../EC2ComputeServiceContextModule.java | 9 +- .../compute/EC2ComputeServiceLiveTest.java | 150 +---------- .../blobstore/BlobStorePropertiesBuilder.java | 50 ---- .../integration/StubPropertiesBuilder.java | 11 + compute/pom.xml | 17 ++ .../org/jclouds/compute/ComputeService.java | 10 +- .../compute/domain/OperatingSystem.java | 3 +- .../java/org/jclouds/compute/domain/Size.java | 6 +- .../compute/domain/internal/SizeImpl.java | 50 ++-- .../compute/options/RunNodeOptions.java | 74 ++++++ .../jclouds/compute/util/ComputeUtils.java | 8 +- .../compute/BaseComputeServiceLiveTest.java | 216 +++++++++++++++ .../jclouds/http/HttpPropertiesBuilder.java | 8 +- .../java/org/jclouds/http/HttpRequest.java | 12 - .../org/jclouds/rest/RestContextFactory.java | 18 +- .../org/jclouds/util/InputStreamChain.java | 6 - .../main/java/org/jclouds/util/Patterns.java | 1 + .../src/main/java/org/jclouds/util/Utils.java | 52 +--- .../http/HttpPropertiesBuilderTest.java | 14 +- .../nirvanix/sdn/SDNPropertiesBuilder.java | 13 + .../miro/RimuHostingPropertiesBuilder.java | 16 +- .../compute/RimuHostingComputeService.java | 9 +- .../RimuHostingComputeServiceLiveTest.java | 152 +---------- .../antcontrib/samples/cargooverssh/build.xml | 51 +--- .../samples/cargooverssh/runscript.sh | 10 + .../ant/taskdefs/compute/ComputeTask.java | 246 ++++++++---------- .../taskdefs/compute/ComputeTaskUtils.java | 143 ++++++++++ .../ant/taskdefs/compute/NodeElement.java | 28 +- .../jclouds/vcloud/VCloudComputeClient.java | 171 ------------ .../vcloud/VCloudComputeClientLiveTest.java | 158 ----------- .../HostingDotComVCloudComputeClient.java | 164 ------------ .../HostingDotComVCloudComputeService.java | 149 ++--------- ...ComVCloudComputeServiceContextBuilder.java | 36 +-- .../compute/HostingDotComVCloudTemplate.java | 180 ------------- ...tComVCloudComputeServiceContextModule.java | 105 +------- ...tingDotComVCloudComputeClientLiveTest.java | 115 +------- ...ingDotComVCloudComputeServiceLiveTest.java | 154 +---------- .../compute/TerremarkVCloudComputeClient.java | 3 +- .../TerremarkVCloudComputeService.java | 228 +++++++++------- ...arkVCloudComputeServiceContextBuilder.java | 36 +-- .../compute/TerremarkVCloudTemplate.java | 178 ------------- ...markVCloudComputeServiceContextModule.java | 106 +------- .../terremark/domain/ComputeOptions.java | 6 +- ...TerremarkVCloudComputeServiceLiveTest.java | 166 ++---------- 45 files changed, 1018 insertions(+), 2362 deletions(-) delete mode 100644 blobstore/src/main/java/org/jclouds/blobstore/BlobStorePropertiesBuilder.java create mode 100644 compute/src/main/java/org/jclouds/compute/options/RunNodeOptions.java create mode 100644 compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java create mode 100644 tools/antcontrib/samples/cargooverssh/runscript.sh create mode 100644 tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTaskUtils.java delete mode 100644 vcloud/core/src/test/java/org/jclouds/vcloud/VCloudComputeClient.java delete mode 100644 vcloud/core/src/test/java/org/jclouds/vcloud/VCloudComputeClientLiveTest.java delete mode 100644 vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeClient.java delete mode 100644 vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudTemplate.java delete mode 100644 vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudTemplate.java diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/EC2ComputeService.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/EC2ComputeService.java index 4b9861e299..ea007eb4c2 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/EC2ComputeService.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/EC2ComputeService.java @@ -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.checkNotNull; import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withKeyName; -import static org.jclouds.scriptbuilder.domain.Statements.exec; import java.net.InetAddress; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; +import java.util.SortedSet; import javax.annotation.Resource; 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.KeyPair; import org.jclouds.aws.ec2.domain.RunningInstance; +import org.jclouds.aws.ec2.options.RunInstancesOptions; import org.jclouds.compute.ComputeService; import org.jclouds.compute.domain.Architecture; 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.CreateNodeResponseImpl; import org.jclouds.compute.domain.internal.NodeMetadataImpl; +import org.jclouds.compute.options.RunNodeOptions; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.domain.Credentials; 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.Predicate; @@ -76,14 +76,14 @@ public class EC2ComputeService implements ComputeService { @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; private final EC2Client ec2Client; - private final Set sizes; + private final SortedSet sizes; private final Provider> templates; private final Predicate instanceStateRunning; private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata; private final Map>> imageAmiIdMap; @Inject - public EC2ComputeService(EC2Client client, Set sizes, + public EC2ComputeService(EC2Client client, SortedSet sizes, Provider> templates, Map>> imageAmiIdMap, Predicate instanceStateRunning, @@ -103,34 +103,34 @@ public class EC2ComputeService implements ComputeService { @Override 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, "unexpected template type. should be EC2Template, was: " + template.getClass()); EC2Template ec2Template = (EC2Template) template; KeyPair keyPair = createKeyPairInRegion(ec2Template.getRegion(), name); String securityGroupName = name; - createSecurityGroupInRegion(ec2Template.getRegion(), securityGroupName, 22, 80, 8080, 443); - - 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); + createSecurityGroupInRegion(ec2Template.getRegion(), securityGroupName, options + .getOpenPorts()); logger.debug(">> running instance region(%s) ami(%s) type(%s) keyPair(%s) securityGroup(%s)", ec2Template.getRegion(), ec2Template.getImage().getId(), ec2Template.getSize() .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() .runInstancesInRegion(ec2Template.getRegion(), null, ec2Template.getImage().getId(), - 1, 1, withKeyName(keyPair.getKeyName())// key - .asType(ec2Template.getSize().getInstanceType())// instance size - .withSecurityGroup(securityGroupName)// group I created above - .withAdditionalInfo(name)// description - .withUserData(script.getBytes()) // script to run as root - )); + 1, 1, instanceOptions)); logger.debug("<< started instance(%s)", runningInstance.getId()); instanceStateRunning.apply(runningInstance); logger.debug("<< running instance(%s)", runningInstance.getId()); @@ -316,7 +316,7 @@ public class EC2ComputeService implements ComputeService { } @Override - public Set listSizes() { + public SortedSet listSizes() { return sizes; } diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java index 46deb92f5a..6fc9647dc5 100755 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java @@ -20,6 +20,7 @@ package org.jclouds.aws.ec2.compute.config; import java.util.Map; import java.util.Set; +import java.util.SortedSet; import javax.annotation.Resource; import javax.inject.Named; @@ -43,7 +44,7 @@ import org.jclouds.logging.Logger; import org.jclouds.rest.RestContext; 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.inject.Provides; @@ -69,8 +70,8 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule { @Provides @Singleton - Set provideSizes() { - return ImmutableSet. of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE, + SortedSet provideSizes() { + return ImmutableSortedSet.of(EC2Size.C1_MEDIUM, EC2Size.C1_XLARGE, EC2Size.M1_LARGE, EC2Size.M1_SMALL, EC2Size.M1_XLARGE, EC2Size.M2_2XLARGE, EC2Size.M2_4XLARGE); } @@ -82,7 +83,7 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule { @Provides @Singleton - Set provideTemplates(EC2Client client, Set sizes, + Set provideTemplates(EC2Client client, SortedSet sizes, Map>> imageAmiIdMap, LogHolder holder) { Set templates = Sets.newHashSet(); diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EC2ComputeServiceLiveTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EC2ComputeServiceLiveTest.java index 8fa8f52c89..1e06914dab 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EC2ComputeServiceLiveTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/EC2ComputeServiceLiveTest.java @@ -18,43 +18,13 @@ */ 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.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import java.io.IOException; -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.compute.BaseComputeServiceLiveTest; import org.jclouds.ssh.jsch.config.JschSshClientModule; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeGroups; +import org.testng.annotations.BeforeClass; 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. @@ -62,115 +32,17 @@ import com.google.inject.Injector; * @author Adrian Cole */ @Test(groups = "live", enabled = true, sequential = true, testName = "ec2.EC2ComputeServiceLiveTest") -public class EC2ComputeServiceLiveTest { - private static final String service = "ec2"; - - protected SshClient.Factory sshFactory; - private String nodeName = System.getProperty("user.name") + service; - - private RetryablePredicate 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(socketOpen, 60, 1, TimeUnit.SECONDS); - injector.injectMembers(socketOpen); // add logger - client = context.getComputeService(); +public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest { + @BeforeClass + @Override + public void setServiceDefaults() { + service = "ec2"; + testOS = UBUNTU; } - public void testCreate() throws Exception { - Template template = client.createTemplateInLocation("default").os(UBUNTU).smallest(); - node = client.runNode(nodeName, template); - 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(); + @Override + protected JschSshClientModule getSshModule() { + return new JschSshClientModule(); } } diff --git a/blobstore/src/main/java/org/jclouds/blobstore/BlobStorePropertiesBuilder.java b/blobstore/src/main/java/org/jclouds/blobstore/BlobStorePropertiesBuilder.java deleted file mode 100644 index b7bc5ce8af..0000000000 --- a/blobstore/src/main/java/org/jclouds/blobstore/BlobStorePropertiesBuilder.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * - * Copyright (C) 2009 Cloud Conscious, LLC. - * - * ==================================================================== - * 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; - } - -} diff --git a/blobstore/src/test/java/org/jclouds/blobstore/integration/StubPropertiesBuilder.java b/blobstore/src/test/java/org/jclouds/blobstore/integration/StubPropertiesBuilder.java index 80e8647de3..acd97d8d44 100644 --- a/blobstore/src/test/java/org/jclouds/blobstore/integration/StubPropertiesBuilder.java +++ b/blobstore/src/test/java/org/jclouds/blobstore/integration/StubPropertiesBuilder.java @@ -18,6 +18,7 @@ */ package org.jclouds.blobstore.integration; +import java.net.URI; import java.util.Properties; import org.jclouds.http.HttpPropertiesBuilder; @@ -37,4 +38,14 @@ public class StubPropertiesBuilder extends HttpPropertiesBuilder { super(); } + @Override + public HttpPropertiesBuilder withCredentials(String account, String key) { + return this; + } + + @Override + public HttpPropertiesBuilder withEndpoint(URI endpoint) { + return this; + } + } diff --git a/compute/pom.xml b/compute/pom.xml index 9a5a1b1849..ca82f9784a 100644 --- a/compute/pom.xml +++ b/compute/pom.xml @@ -40,6 +40,11 @@ + + ${project.groupId} + jclouds-scriptbuilder + ${project.version} + ${project.groupId} jclouds-core @@ -52,5 +57,17 @@ test-jar test + + ${project.groupId} + jclouds-log4j + ${project.version} + test + + + log4j + log4j + 1.2.14 + test + diff --git a/compute/src/main/java/org/jclouds/compute/ComputeService.java b/compute/src/main/java/org/jclouds/compute/ComputeService.java index 33e547ac6a..28ef3e8850 100644 --- a/compute/src/main/java/org/jclouds/compute/ComputeService.java +++ b/compute/src/main/java/org/jclouds/compute/ComputeService.java @@ -19,12 +19,14 @@ package org.jclouds.compute; import java.util.Set; +import java.util.SortedSet; import org.jclouds.compute.domain.ComputeMetadata; import org.jclouds.compute.domain.CreateNodeResponse; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.Size; import org.jclouds.compute.domain.Template; +import org.jclouds.compute.options.RunNodeOptions; /** * Provides portable access to launching compute instances. @@ -44,7 +46,12 @@ public interface ComputeService { /** * List all sizes available to the current user */ - Set listSizes(); + SortedSet listSizes(); + + /** + * List all images available to the current user + */ +// Set listImages(); /** * 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, RunNodeOptions options); /** * destroy the node. diff --git a/compute/src/main/java/org/jclouds/compute/domain/OperatingSystem.java b/compute/src/main/java/org/jclouds/compute/domain/OperatingSystem.java index c6eee06b60..76854b732e 100644 --- a/compute/src/main/java/org/jclouds/compute/domain/OperatingSystem.java +++ b/compute/src/main/java/org/jclouds/compute/domain/OperatingSystem.java @@ -29,6 +29,5 @@ package org.jclouds.compute.domain; * @author Adrian Cole */ public enum OperatingSystem { - - CENTOS, RHEL, UBUNTU, WINDOWS, UNKNOWN; + CENTOS, RHEL, UBUNTU, JEOS, WINDOWS, UNKNOWN; } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/compute/domain/Size.java b/compute/src/main/java/org/jclouds/compute/domain/Size.java index 29eab0597c..a5ad9c9dce 100644 --- a/compute/src/main/java/org/jclouds/compute/domain/Size.java +++ b/compute/src/main/java/org/jclouds/compute/domain/Size.java @@ -33,17 +33,17 @@ public interface Size extends Comparable { /** * Amount of virtual or physical cores provided */ - Integer getCores(); + int getCores(); /** * Amount of RAM provided in MB (256M, 1740) */ - Integer getRam(); + int getRam(); /** * Amount of boot disk provided in GB (200) */ - Integer getDisk(); + int getDisk(); /** * Determines platforms this can support diff --git a/compute/src/main/java/org/jclouds/compute/domain/internal/SizeImpl.java b/compute/src/main/java/org/jclouds/compute/domain/internal/SizeImpl.java index 9f70849150..534879d0b5 100644 --- a/compute/src/main/java/org/jclouds/compute/domain/internal/SizeImpl.java +++ b/compute/src/main/java/org/jclouds/compute/domain/internal/SizeImpl.java @@ -23,6 +23,7 @@ import java.util.Set; import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Size; +import com.google.common.collect.ComparisonChain; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; @@ -31,13 +32,12 @@ import com.google.common.collect.Sets; */ public class SizeImpl implements Size { - private final Integer cores; - private final Integer ram; - private final Integer disk; + private final int cores; + private final int ram; + private final int disk; private final Set supportedArchitectures = Sets.newHashSet(); - public SizeImpl(Integer cores, Integer ram, Integer disk, - Iterable supportedArchitectures) { + public SizeImpl(int cores, int ram, int disk, Iterable supportedArchitectures) { this.cores = cores; this.ram = ram; this.disk = disk; @@ -48,7 +48,7 @@ public class SizeImpl implements Size { * {@inheritDoc} */ @Override - public Integer getCores() { + public int getCores() { return cores; } @@ -56,7 +56,7 @@ public class SizeImpl implements Size { * {@inheritDoc} */ @Override - public Integer getRam() { + public int getRam() { return ram; } @@ -64,7 +64,7 @@ public class SizeImpl implements Size { * {@inheritDoc} */ @Override - public Integer getDisk() { + public int getDisk() { return disk; } @@ -72,9 +72,9 @@ public class SizeImpl implements Size { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((cores == null) ? 0 : cores.hashCode()); - result = prime * result + ((disk == null) ? 0 : disk.hashCode()); - result = prime * result + ((ram == null) ? 0 : ram.hashCode()); + result = prime * result + cores; + result = prime * result + disk; + result = prime * result + ram; result = prime * result + ((supportedArchitectures == null) ? 0 : supportedArchitectures.hashCode()); return result; @@ -89,20 +89,11 @@ public class SizeImpl implements Size { if (getClass() != obj.getClass()) return false; SizeImpl other = (SizeImpl) obj; - if (cores == null) { - if (other.cores != null) - return false; - } else if (!cores.equals(other.cores)) + if (cores != other.cores) return false; - if (disk == null) { - if (other.disk != null) - return false; - } else if (!disk.equals(other.disk)) + if (disk != other.disk) return false; - if (ram == null) { - if (other.ram != null) - return false; - } else if (!ram.equals(other.ram)) + if (ram != other.ram) return false; if (supportedArchitectures == null) { if (other.supportedArchitectures != null) @@ -112,20 +103,17 @@ public class SizeImpl implements Size { return true; } - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return "SizeImpl [cores=" + cores + ", disk=" + disk + ", ram=" + ram + "]"; + public int compareTo(Size that) { + return ComparisonChain.start().compare(this.getCores(), that.getCores()).compare( + this.getRam(), that.getRam()).compare(this.getDisk(), that.getDisk()).result(); } /** * {@inheritDoc} */ @Override - public int compareTo(Size o) { - return (this == o) ? 0 : getCores().compareTo(o.getCores()); + public String toString() { + return "Size [cores=" + cores + ", disk=" + disk + ", ram=" + ram + "]"; } /** diff --git a/compute/src/main/java/org/jclouds/compute/options/RunNodeOptions.java b/compute/src/main/java/org/jclouds/compute/options/RunNodeOptions.java new file mode 100644 index 0000000000..19d9034d84 --- /dev/null +++ b/compute/src/main/java/org/jclouds/compute/options/RunNodeOptions.java @@ -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.

+ * Usage

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): + *

+ * + * import static org.jclouds.compute.options.RunOptions.Builder.* + *

+ * ComputeService client = // get connection + * CreateNodeResponse client.runNode(name, template, openPorts(22, 80, 8080, 443)); + * + * + * @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); + } + + } +} diff --git a/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java b/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java index a1e3b3cd2e..cf030a982c 100644 --- a/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java +++ b/compute/src/main/java/org/jclouds/compute/util/ComputeUtils.java @@ -19,6 +19,7 @@ package org.jclouds.compute.util; import org.jclouds.compute.domain.ComputeMetadata; +import org.jclouds.compute.domain.CreateNodeResponse; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; @@ -28,8 +29,8 @@ import com.google.common.collect.Iterables; * @author Adrian Cole */ public class ComputeUtils { - public static Iterable filterByName(Iterable nodes, - final String name) { + public static Iterable filterByName( + Iterable nodes, final String name) { return Iterables.filter(nodes, new Predicate() { @Override 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-----"); + } } diff --git a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java new file mode 100644 index 0000000000..8188bdf42d --- /dev/null +++ b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java @@ -0,0 +1,216 @@ +/** + * + * Copyright (C) 2009 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 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(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() { + @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(); + } + +} diff --git a/core/src/main/java/org/jclouds/http/HttpPropertiesBuilder.java b/core/src/main/java/org/jclouds/http/HttpPropertiesBuilder.java index aec9404a99..76f30db81a 100755 --- a/core/src/main/java/org/jclouds/http/HttpPropertiesBuilder.java +++ b/core/src/main/java/org/jclouds/http/HttpPropertiesBuilder.java @@ -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_SESSION_FAILURES; +import java.net.URI; import java.util.Properties; import com.google.common.annotations.VisibleForTesting; @@ -36,7 +37,7 @@ import com.google.common.annotations.VisibleForTesting; * * @author Adrian Cole, Andrew Newdigate */ -public class HttpPropertiesBuilder { +public abstract class HttpPropertiesBuilder { /** * @see org.jclouds.http.HttpConstants.PROPERTY_HTTP_RELAX_HOSTNAME @@ -122,9 +123,8 @@ public class HttpPropertiesBuilder { this.properties.putAll(properties); } - public HttpPropertiesBuilder withCredentials(String account, String key) { - return this; - } + public abstract HttpPropertiesBuilder withEndpoint(URI endpoint); + public abstract HttpPropertiesBuilder withCredentials(String account, String key); @VisibleForTesting public Properties build() { diff --git a/core/src/main/java/org/jclouds/http/HttpRequest.java b/core/src/main/java/org/jclouds/http/HttpRequest.java index e35a90397a..cd569ecd68 100644 --- a/core/src/main/java/org/jclouds/http/HttpRequest.java +++ b/core/src/main/java/org/jclouds/http/HttpRequest.java @@ -110,30 +110,18 @@ public class HttpRequest extends HttpMessage { setLength(); } - /** - * {@inheritDoc} - */ public void setPayload(InputStream data) { setPayload(Payloads.newPayload(checkNotNull(data, "data"))); } - /** - * {@inheritDoc} - */ public void setPayload(byte[] data) { setPayload(Payloads.newPayload(checkNotNull(data, "data"))); } - /** - * {@inheritDoc} - */ public void setPayload(String data) { setPayload(Payloads.newPayload(checkNotNull(data, "data"))); } - /** - * {@inheritDoc} - */ public void setPayload(File data) { setPayload(Payloads.newPayload(checkNotNull(data, "data"))); } diff --git a/core/src/main/java/org/jclouds/rest/RestContextFactory.java b/core/src/main/java/org/jclouds/rest/RestContextFactory.java index e73a1b6d53..1077d8ca1c 100644 --- a/core/src/main/java/org/jclouds/rest/RestContextFactory.java +++ b/core/src/main/java/org/jclouds/rest/RestContextFactory.java @@ -48,10 +48,10 @@ public abstract class RestContextFactory> * Initializes with the default properties built-in to jclouds. This is typically stored in the * 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 * if the default properties file cannot be loaded - * @see #init + * @see #getPropertiesFromResource */ public RestContextFactory(String filename) throws IOException { this(getPropertiesFromResource(filename)); @@ -82,6 +82,7 @@ public abstract class RestContextFactory> static Properties getPropertiesFromResource(String filename) throws IOException { Properties properties = new Properties(); properties.load(Resources.newInputStreamSupplier(Resources.getResource(filename)).getInput()); + properties.putAll(System.getProperties()); return properties; } @@ -125,8 +126,7 @@ public abstract class RestContextFactory> } /** - * - * FIXME Comment this // ImmutableSet.of(new ExecutorServiceModule(myexecutor)) + * Creates a new remote context. * * @param hint * @param account @@ -134,8 +134,11 @@ public abstract class RestContextFactory> * @param key * nullable, if credentials are present in the overrides * @param modules + * Configuration you'd like to pass to the context. Ex. ImmutableSet.of(new + * ExecutorServiceModule(myexecutor)) * @param overrides - * @return + * properties to override defaults with. + * @return initialized context ready for use */ @SuppressWarnings("unchecked") public T createContext(String hint, @Nullable String account, @Nullable String key, @@ -151,6 +154,8 @@ public abstract class RestContextFactory> String contextBuilderClassName = checkNotNull(properties.getProperty(contextBuilderKey), contextBuilderKey); + String endpointKey = String.format("%s.endpoint", hint); + String endpoint = properties.getProperty(endpointKey); try { Class propertiesBuilderClass = (Class) Class .forName(propertiesBuilderClassName); @@ -159,7 +164,8 @@ public abstract class RestContextFactory> .newInstance(overrides); if (key != null) builder.withCredentials(account, key); - + if (endpoint != null) + builder.withEndpoint(URI.create(endpoint)); B contextBuilder = (B) contextBuilderClass.getConstructor(Properties.class).newInstance( builder.build()).withModules(Iterables.toArray(modules, Module.class)); return build(contextBuilder); diff --git a/core/src/main/java/org/jclouds/util/InputStreamChain.java b/core/src/main/java/org/jclouds/util/InputStreamChain.java index 08c3ef34a2..d6d552a38a 100644 --- a/core/src/main/java/org/jclouds/util/InputStreamChain.java +++ b/core/src/main/java/org/jclouds/util/InputStreamChain.java @@ -41,12 +41,6 @@ public class InputStreamChain extends InputStream { */ private InputStream current; - /** - * Constructor with an initial stream - * - * @param first - * Initial InputStream - */ public InputStreamChain(InputStream... inputStreams) { for (InputStream stream : inputStreams) { addInputStream(stream); diff --git a/core/src/main/java/org/jclouds/util/Patterns.java b/core/src/main/java/org/jclouds/util/Patterns.java index 42bdc192ff..0cdf684246 100644 --- a/core/src/main/java/org/jclouds/util/Patterns.java +++ b/core/src/main/java/org/jclouds/util/Patterns.java @@ -32,6 +32,7 @@ import com.google.common.collect.MapMaker; * @author Adrian Cole */ public class Patterns { + public static final Pattern TOKEN_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 URI_PATTERN = Pattern.compile("([a-z0-9]+)://([^:]*):(.*)@(.*)"); diff --git a/core/src/main/java/org/jclouds/util/Utils.java b/core/src/main/java/org/jclouds/util/Utils.java index ddfefd0a36..720db26209 100644 --- a/core/src/main/java/org/jclouds/util/Utils.java +++ b/core/src/main/java/org/jclouds/util/Utils.java @@ -43,7 +43,7 @@ import com.google.common.io.Closeables; import com.google.common.io.OutputSupplier; /** - * // TODO: Adrian: Document this! + * General utilities used in jclouds code. * * @author Adrian Cole */ @@ -137,14 +137,16 @@ public class Utils { * @see {@link String#getBytes()} - used as fall-back. * * @param str - * @param encoding - * @return + * what to encode + * @param charsetName + * the name of a supported {@link java.nio.charset.Charset charset} + * @return properly encoded String. */ - public static byte[] encodeString(String str, String encoding) { + public static byte[] encodeString(String str, String charsetName) { try { - return str.getBytes(encoding); + return str.getBytes(charsetName); } 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"); return str.getBytes(); } @@ -156,45 +158,13 @@ public class Utils { * the system's default encoding. * * @param str - * @return + * what to encode + * @return properly encoded String. */ public static byte[] encodeString(String str) { 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 {token} * @@ -209,7 +179,7 @@ public class Utils { * token/value pairs */ public static String replaceTokens(String input, Map replacements) { - Matcher matcher = pattern.matcher(input); + Matcher matcher = Patterns.TOKEN_PATTERN.matcher(input); StringBuilder builder = new StringBuilder(); int i = 0; while (matcher.find()) { diff --git a/core/src/test/java/org/jclouds/http/HttpPropertiesBuilderTest.java b/core/src/test/java/org/jclouds/http/HttpPropertiesBuilderTest.java index 6b1cf8a2cc..9d8d9e4bcf 100755 --- a/core/src/test/java/org/jclouds/http/HttpPropertiesBuilderTest.java +++ b/core/src/test/java/org/jclouds/http/HttpPropertiesBuilderTest.java @@ -18,6 +18,7 @@ */ package org.jclouds.http; +import java.net.URI; import java.util.Properties; import org.testng.annotations.Test; @@ -37,7 +38,18 @@ public class HttpPropertiesBuilderTest { int poolMaxClients = 3382; 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.withPoolIoWorkerThreads(poolIoWorkerThreads); diff --git a/nirvanix/sdn/core/src/main/java/org/jclouds/nirvanix/sdn/SDNPropertiesBuilder.java b/nirvanix/sdn/core/src/main/java/org/jclouds/nirvanix/sdn/SDNPropertiesBuilder.java index d119a61699..1d114e88b6 100644 --- a/nirvanix/sdn/core/src/main/java/org/jclouds/nirvanix/sdn/SDNPropertiesBuilder.java +++ b/nirvanix/sdn/core/src/main/java/org/jclouds/nirvanix/sdn/SDNPropertiesBuilder.java @@ -21,11 +21,15 @@ package org.jclouds.nirvanix.sdn; import static com.google.common.base.Preconditions.checkNotNull; import java.net.URI; +import java.util.List; import java.util.Properties; import org.jclouds.http.HttpPropertiesBuilder; 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 * @@ -65,4 +69,13 @@ public class SDNPropertiesBuilder extends HttpPropertiesBuilder { .toString()); return this; } + + @Override + public SDNPropertiesBuilder withCredentials(String account, String key) { + List 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); + } } diff --git a/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/RimuHostingPropertiesBuilder.java b/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/RimuHostingPropertiesBuilder.java index 4db3b975f2..d5f9de107c 100644 --- a/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/RimuHostingPropertiesBuilder.java +++ b/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/RimuHostingPropertiesBuilder.java @@ -19,15 +19,17 @@ package org.jclouds.rimuhosting.miro; import static com.google.common.base.Preconditions.checkNotNull; -import org.jclouds.http.HttpPropertiesBuilder; -import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.*; +import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.PROPERTY_RIMUHOSTING_APIKEY; +import static org.jclouds.rimuhosting.miro.reference.RimuHostingConstants.PROPERTY_RIMUHOSTING_ENDPOINT; import java.net.URI; import java.util.Properties; +import org.jclouds.http.HttpPropertiesBuilder; + /** * Builds properties used in RimuHosting Clients - * + * * @author Adrian Cole */ public class RimuHostingPropertiesBuilder extends HttpPropertiesBuilder { @@ -52,9 +54,15 @@ public class RimuHostingPropertiesBuilder extends HttpPropertiesBuilder { return this; } + @Override public RimuHostingPropertiesBuilder withEndpoint(URI endpoint) { properties.setProperty(PROPERTY_RIMUHOSTING_ENDPOINT, checkNotNull(endpoint, "endpoint") - .toString()); + .toString()); return this; } + + @Override + public HttpPropertiesBuilder withCredentials(String account, String key) { + return withCredentials(account != null ? account : key); + } } diff --git a/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/compute/RimuHostingComputeService.java b/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/compute/RimuHostingComputeService.java index b12d786e64..ecd63f9ea8 100644 --- a/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/compute/RimuHostingComputeService.java +++ b/rimuhosting/src/main/java/org/jclouds/rimuhosting/miro/compute/RimuHostingComputeService.java @@ -25,6 +25,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Map; import java.util.Set; +import java.util.SortedSet; import javax.annotation.Resource; 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.internal.ComputeMetadataImpl; import org.jclouds.compute.domain.internal.CreateNodeResponseImpl; +import org.jclouds.compute.options.RunNodeOptions; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.domain.Credentials; import org.jclouds.logging.Logger; @@ -82,6 +84,11 @@ public class RimuHostingComputeService implements ComputeService { @Override 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 .get(template.getImage().getOperatingSystem()), "os not supported: " + template.getImage().getOperatingSystem()), "MIRO1B"); @@ -144,7 +151,7 @@ public class RimuHostingComputeService implements ComputeService { } @Override - public Set listSizes() { + public SortedSet listSizes() { return null; } diff --git a/rimuhosting/src/test/java/org/jclouds/rimuhosting/miro/compute/RimuHostingComputeServiceLiveTest.java b/rimuhosting/src/test/java/org/jclouds/rimuhosting/miro/compute/RimuHostingComputeServiceLiveTest.java index b73a07ca20..639feaa6a4 100755 --- a/rimuhosting/src/test/java/org/jclouds/rimuhosting/miro/compute/RimuHostingComputeServiceLiveTest.java +++ b/rimuhosting/src/test/java/org/jclouds/rimuhosting/miro/compute/RimuHostingComputeServiceLiveTest.java @@ -18,156 +18,28 @@ */ 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.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import java.io.IOException; -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.compute.BaseComputeServiceLiveTest; import org.jclouds.ssh.jsch.config.JschSshClientModule; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeGroups; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import com.google.common.collect.ImmutableSet; -import com.google.inject.Guice; -import com.google.inject.Injector; - /** * @author Ivan Meredith */ @Test(groups = "live", sequential = true, testName = "rimuhosting.RimuHostingNodeServiceLiveTest") -public class RimuHostingComputeServiceLiveTest { - private static final String service = "rimuhosting"; - - protected SshClient.Factory sshFactory; - private String nodeName = System.getProperty("user.name") + service; - - private RetryablePredicate 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(socketOpen, 60, 1, TimeUnit.SECONDS); - injector.injectMembers(socketOpen); // add logger - client = context.getComputeService(); +public class RimuHostingComputeServiceLiveTest extends BaseComputeServiceLiveTest { + @BeforeClass + @Override + public void setServiceDefaults() { + service = "rimuhosting"; + testOS = UBUNTU; } - public void testCreate() throws Exception { - Template template = client.createTemplateInLocation("default").os(UBUNTU).smallest(); - node = client.runNode(nodeName, template); - 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(); + @Override + protected JschSshClientModule getSshModule() { + return new JschSshClientModule(); } - @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(); - } - -} +} \ No newline at end of file diff --git a/tools/antcontrib/samples/cargooverssh/build.xml b/tools/antcontrib/samples/cargooverssh/build.xml index 5769fa6a35..f54f87a21a 100644 --- a/tools/antcontrib/samples/cargooverssh/build.xml +++ b/tools/antcontrib/samples/cargooverssh/build.xml @@ -1,7 +1,6 @@ - - - - - - - - - - - + - + @@ -125,7 +102,7 @@ - + diff --git a/tools/antcontrib/samples/cargooverssh/runscript.sh b/tools/antcontrib/samples/cargooverssh/runscript.sh new file mode 100644 index 0000000000..b33b06cd68 --- /dev/null +++ b/tools/antcontrib/samples/cargooverssh/runscript.sh @@ -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 diff --git a/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTask.java b/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTask.java index 67b7c2179a..c23e316e7e 100644 --- a/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTask.java +++ b/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTask.java @@ -18,37 +18,35 @@ */ 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.IOException; -import java.net.InetAddress; import java.net.URI; import java.nio.charset.Charset; 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.Project; import org.apache.tools.ant.Task; 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.CreateNodeResponse; import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.Template; -import org.jclouds.compute.reference.ComputeServiceConstants; -import org.jclouds.compute.util.ComputeUtils; +import org.jclouds.compute.options.RunNodeOptions; import org.jclouds.http.HttpUtils; -import org.jclouds.tools.ant.logging.config.AntLoggingModule; 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.inject.Module; import com.google.inject.Provider; /** @@ -58,169 +56,133 @@ import com.google.inject.Provider; public class ComputeTask extends Task { private final Map computeMap; - private static Project project; - /** - * we don't have a reference to the project during the constructor, so we need to defer expansion - * with a Provider. - */ - private static Provider> defaultModulesProvider = new Provider>() { - - @Override - public Iterable get() { - return ImmutableSet.of((Module) new AntLoggingModule(project, - ComputeServiceConstants.COMPUTE_LOGGER)); - } - - }; + private String provider; + private String action; + private NodeElement nodeElement; /** * we don't have a reference to the project during the constructor, so we need to defer expansion * with a Provider. */ - private static Provider defaultPropertiesProvider = new Provider() { - - @SuppressWarnings("unchecked") + private final Provider projectProvider = new Provider() { @Override - public Properties get() { - Properties props = new Properties(); - props.putAll(project.getProperties()); - return props; + public Project get() { + return getProject(); } - }; - public ComputeTask(Map computeMap) { - this.computeMap = computeMap; + public ComputeTask(@Nullable Map computeMap) { + this.computeMap = computeMap != null ? computeMap : buildComputeMap(projectProvider); } public ComputeTask() throws IOException { - this(buildComputeMap()); - } - - static Map buildComputeMap() { - return new MapMaker().makeComputingMap(new Function() { - - @Override - public ComputeServiceContext apply(URI from) { - try { - return new ComputeServiceContextFactory().createContext(from, defaultModulesProvider - .get(), defaultPropertiesProvider.get()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - }); - + this(null); } public static enum Action { 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 { - ComputeTask.project = getProject(); + ComputeServiceContext context = computeMap.get(HttpUtils.createUri(provider)); Action action = Action.valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, this.action)); - ComputeServiceContext context = computeMap.get(HttpUtils.createUri(provider)); try { - ComputeService computeService = context.getComputeService(); - switch (action) { - case CREATE: - case GET: - case DESTROY: - if (nodeElement != null) { - switch (action) { - case CREATE: - create(computeService); - break; - case GET: - get(computeService); - break; - case DESTROY: - destroy(computeService); - break; - } - } else { - this.log("missing node element for action: " + action, Project.MSG_ERR); - } - break; - case LIST: - log("list"); - for (ComputeMetadata node : computeService.listNodes()) { - log(String.format(" location=%s, id=%s, name=%s", node.getLocation(), node - .getId(), node.getName())); - } - break; - case LIST_DETAILS: - log("list details"); - for (ComputeMetadata node : computeService.listNodes()) {// TODO - // parallel - logDetails(computeService, node); - } - break; - default: - this.log("bad action: " + action, Project.MSG_ERR); - } + invokeActionOnService(action, context.getComputeService()); } finally { context.close(); } } - private void create(ComputeService computeService) { - log(String.format("create name: %s, size: %s, os: %s", nodeElement.getName(), nodeElement - .getSize(), nodeElement.getOs())); - Template template = computeService.createTemplateInLocation(nodeElement.getLocation()); - template.os(OperatingSystem.valueOf(nodeElement.getOs())); - 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"); + private void invokeActionOnService(Action action, ComputeService computeService) { + switch (action) { + case CREATE: + case GET: + case DESTROY: + if (nodeElement != null) { + switch (action) { + case CREATE: + create(computeService); + break; + case GET: + get(computeService); + break; + case DESTROY: + destroy(computeService); + break; + } + } else { + this.log("missing node element for action: " + action, Project.MSG_ERR); + } + break; + case LIST: + list(computeService); + break; + case LIST_DETAILS: + listDetails(computeService); + break; + default: + this.log("bad action: " + action, Project.MSG_ERR); } - CreateNodeResponse createdNode = computeService.runNode(nodeElement.getName(), template); + } + + private void listDetails(ComputeService computeService) { + log("list details"); + for (ComputeMetadata node : computeService.listNodes()) {// TODO + // parallel + logDetails(computeService, node); + } + } + + 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) { + String name = nodeElement.getName(); + + log(String.format("create name: %s, size: %s, os: %s", name, nodeElement.getSize(), + nodeElement.getOs())); + + Template template = createTemplateFromElement(nodeElement, computeService); + + RunNodeOptions options = getNodeOptionsFromElement(nodeElement); + + CreateNodeResponse createdNode = computeService.runNode(name, template, options); + + logNodeDetails(createdNode); + + addNodeDetailsAsProjectProperties(createdNode); + } + + private void logNodeDetails(CreateNodeResponse createdNode) { log(String.format(" id=%s, name=%s, connection=%s://%s:%s@%s:%d", createdNode.getId(), createdNode.getName(), createdNode.getLoginType().toString().toLowerCase(), createdNode.getCredentials().account, createdNode.getCredentials().key, createdNode .getPublicAddresses().first().getHostAddress(), createdNode.getLoginPort())); + } + + private void addNodeDetailsAsProjectProperties(CreateNodeResponse createdNode) { if (nodeElement.getIdproperty() != null) getProject().setProperty(nodeElement.getIdproperty(), createdNode.getId()); if (nodeElement.getHostproperty() != null) getProject().setProperty(nodeElement.getHostproperty(), createdNode.getPublicAddresses().first().getHostAddress()); - if (nodeElement.getKeyfile() != null - && createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----")) + if (nodeElement.getKeyfile() != null && isKeyAuth(createdNode)) try { Files.write(createdNode.getCredentials().key, new File(nodeElement.getKeyfile()), Charset.defaultCharset()); } catch (IOException e) { throw new BuildException(e); } - if (nodeElement.getPasswordproperty() != null - && !createdNode.getCredentials().key.startsWith("-----BEGIN RSA PRIVATE KEY-----")) + if (nodeElement.getPasswordproperty() != null && !isKeyAuth(createdNode)) getProject().setProperty(nodeElement.getPasswordproperty(), createdNode.getCredentials().key); if (nodeElement.getUsernameproperty() != null) @@ -230,8 +192,8 @@ public class ComputeTask extends Task { private void destroy(ComputeService computeService) { log(String.format("destroy name: %s", nodeElement.getName())); - Iterable nodesThatMatch = ComputeUtils.filterByName(computeService - .listNodes(), nodeElement.getName()); + Iterable nodesThatMatch = filterByName(computeService.listNodes(), + nodeElement.getName()); for (ComputeMetadata node : nodesThatMatch) { log(String.format(" destroying id=%s, name=%s", node.getId(), node.getName())); computeService.destroyNode(node); @@ -240,8 +202,8 @@ public class ComputeTask extends Task { private void get(ComputeService computeService) { log(String.format("get name: %s", nodeElement.getName())); - Iterable nodesThatMatch = ComputeUtils.filterByName(computeService - .listNodes(), nodeElement.getName()); + Iterable nodesThatMatch = filterByName(computeService.listNodes(), + nodeElement.getName()); for (ComputeMetadata node : nodesThatMatch) { logDetails(computeService, node); } @@ -257,12 +219,18 @@ public class ComputeTask extends Task { .getPrivateAddresses()), metadata.getExtra())); } - public static String ipOrEmptyString(SortedSet set) { - if (set.size() > 0) { - return set.last().getHostAddress(); - } else { - return ""; + /** + * @return the configured {@link NodeElement} element + */ + public final NodeElement createNode() { + if (getNode() == null) { + this.nodeElement = new NodeElement(); } + return this.nodeElement; + } + + public NodeElement getNode() { + return this.nodeElement; } public String getAction() { diff --git a/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTaskUtils.java b/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTaskUtils.java new file mode 100644 index 0000000000..1052cb819c --- /dev/null +++ b/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/ComputeTaskUtils.java @@ -0,0 +1,143 @@ +/** + * + * Copyright (C) 2009 Global Cloud Specialists, Inc. + * + * ==================================================================== + * 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 buildComputeMap(final Provider projectProvider) { + return new MapMaker().makeComputingMap(new Function() { + + @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 set) { + if (set.size() > 0) { + return set.last().getHostAddress(); + } else { + return ""; + } + } + + static int[] getPortsToOpenFromElement(NodeElement nodeElement) { + Iterable 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; + } +} diff --git a/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/NodeElement.java b/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/NodeElement.java index 3716812c93..38c5cec677 100644 --- a/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/NodeElement.java +++ b/tools/antcontrib/src/main/java/org/jclouds/tools/ant/taskdefs/compute/NodeElement.java @@ -18,6 +18,8 @@ */ package org.jclouds.tools.ant.taskdefs.compute; +import java.io.File; + /** * @author Adrian Cole * @author Ivan Meredith @@ -26,12 +28,14 @@ public class NodeElement { private String name; private String size; private String os; + private String openports = "22"; private String passwordproperty; - private String keyfi1le; + private String keyfile; private String hostproperty; private String idproperty; private String usernameproperty; private String location = "default"; + private File runscript; public String getLocation() { return location; @@ -40,7 +44,7 @@ public class NodeElement { public void setLocation(String location) { this.location = location; } - + String getName() { return name; } @@ -101,11 +105,11 @@ public class NodeElement { * The name of a file under which to store the DSA key of the user (if supported) */ public void setKeyfile(String keyfile) { - this.keyfi1le = keyfile; + this.keyfile = keyfile; } String getKeyfile() { - return keyfi1le; + return keyfile; } public void setSize(String size) { @@ -124,4 +128,20 @@ public class NodeElement { 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; + } + } diff --git a/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudComputeClient.java b/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudComputeClient.java deleted file mode 100644 index fbcf1c18f6..0000000000 --- a/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudComputeClient.java +++ /dev/null @@ -1,171 +0,0 @@ -/** - * - * Copyright (C) 2009 Cloud Conscious, LLC. - * - * ==================================================================== - * 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 taskTester; - private final VCloudClient tmClient; - - @Inject - public VCloudComputeClient(VCloudClient tmClient, Predicate successTester) { - this.tmClient = tmClient; - this.taskTester = successTester; - } - - private Map imageCatalogIdMap = ImmutableMap - . builder().put(OperatingSystem.CENTOS, "1").put( - OperatingSystem.RHEL, "8").put(OperatingSystem.UBUNTU, "11").build(); - - public Map start(String name, OperatingSystem image, int minCores, int minMegs, - long diskSize, Map 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. 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; - } - - } -} diff --git a/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudComputeClientLiveTest.java b/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudComputeClientLiveTest.java deleted file mode 100644 index 8909237e2f..0000000000 --- a/vcloud/core/src/test/java/org/jclouds/vcloud/VCloudComputeClientLiveTest.java +++ /dev/null @@ -1,158 +0,0 @@ -/** - * - * Copyright (C) 2009 Cloud Conscious, LLC. - * - * ==================================================================== - * 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 expectationMap = ImmutableMap - . 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 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 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>() { - })); - } - -} diff --git a/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeClient.java b/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeClient.java deleted file mode 100644 index 2eb0202f13..0000000000 --- a/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeClient.java +++ /dev/null @@ -1,164 +0,0 @@ -/** - * - * Copyright (C) 2009 Cloud Conscious, LLC. - * - * ==================================================================== - * 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 taskTester; - private final HostingDotComVCloudClient tmClient; - - @Inject - public HostingDotComVCloudComputeClient(HostingDotComVCloudClient tmClient, - Predicate successTester) { - this.tmClient = tmClient; - this.taskTester = successTester; - } - - public Map start(String vDCId, String name, String templateId, int minCores, - int minMegs, long diskSize, Map 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. 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; - } - - } -} diff --git a/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeService.java b/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeService.java index 27ff08cb21..bfada2ca3b 100644 --- a/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeService.java +++ b/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeService.java @@ -1,155 +1,48 @@ -/** - * - * Copyright (C) 2009 Cloud Conscious, LLC. - * - * ==================================================================== - * 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 static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; -import java.net.InetAddress; +import java.net.InetSocketAddress; import java.util.Map; import java.util.Set; +import java.util.SortedSet; -import javax.annotation.Resource; import javax.inject.Inject; -import javax.inject.Named; import javax.inject.Provider; 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.LoginType; -import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.domain.NodeState; 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.domain.Credentials; -import org.jclouds.logging.Logger; -import org.jclouds.vcloud.VCloudMediaType; -import org.jclouds.vcloud.domain.NamedResource; +import org.jclouds.vcloud.VCloudClient; +import org.jclouds.vcloud.compute.VCloudComputeService; +import org.jclouds.vcloud.compute.VCloudTemplate; 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 com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Sets; -import com.google.inject.internal.ImmutableSet; /** * @author Adrian Cole */ @Singleton -public class HostingDotComVCloudComputeService implements ComputeService { - @Resource - @Named(ComputeServiceConstants.COMPUTE_LOGGER) - protected Logger logger = Logger.NULL; - private final HostingDotComVCloudComputeClient computeClient; - private final HostingDotComVCloudClient client; - private final Set images; - private final Set sizes; - private final Provider> templates; - - private static final Map vAppStatusToNodeState = ImmutableMap - . 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(); +public class HostingDotComVCloudComputeService extends VCloudComputeService { @Inject - public HostingDotComVCloudComputeService(HostingDotComVCloudClient client, - HostingDotComVCloudComputeClient computeClient, Set images, - Set sizes, Provider> templates) { - this.client = client; - this.computeClient = computeClient; - this.images = images; - this.sizes = sizes; - this.templates = templates; + public HostingDotComVCloudComputeService(VCloudClient client, + Provider> images, Provider> sizes, + Provider> templates, Predicate successTester, + Predicate socketTester) { + super(client, images, sizes, templates, successTester, socketTester); } @Override - public CreateNodeResponse runNode(String name, Template template) { - checkNotNull(template.getImage().getLocation(), "location"); - Map metaMap = computeClient.start(template.getImage().getLocation(), name, - template.getImage().getId(), template.getSize().getCores(), template.getSize() - .getRam(), template.getSize().getDisk(), ImmutableMap. of()); - VApp vApp = client.getVApp(metaMap.get("id")); - return new CreateNodeResponseImpl(vApp.getId(), vApp.getName(), template.getImage() - .getLocation(), vApp.getLocation(), ImmutableMap. of(), - vAppStatusToNodeState.get(vApp.getStatus()), vApp.getNetworkToAddresses().values(), - ImmutableSet. of(), 22, LoginType.SSH, new Credentials(metaMap - .get("username"), metaMap.get("password")), ImmutableMap - . 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. of(), vAppStatusToNodeState.get(vApp.getStatus()), - vApp.getNetworkToAddresses().values(), ImmutableSet. of(), 22, - LoginType.SSH, ImmutableMap. of()); - } - - @Override - public Set listNodes() { - Set 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 listSizes() { - return sizes; - } - - @Override - public Set listTemplates() { - return templates.get(); + protected Map parseResponse(VApp vAppResponse) { + checkState(vAppResponse instanceof HostingDotComVApp, + "bad configuration, vApp should be an instance of " + + HostingDotComVApp.class.getName()); + HostingDotComVApp hVApp = HostingDotComVApp.class.cast(vAppResponse); + return ImmutableMap. of("id", vAppResponse.getId(), "username", hVApp + .getUsername(), "password", hVApp.getPassword()); } } \ No newline at end of file diff --git a/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeServiceContextBuilder.java b/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeServiceContextBuilder.java index 49abfa6fdb..17f8d53672 100755 --- a/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeServiceContextBuilder.java +++ b/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeServiceContextBuilder.java @@ -20,22 +20,15 @@ package org.jclouds.vcloud.hostingdotcom.compute; import java.util.List; 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.logging.jdk.config.JDKLoggingModule; -import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudAsyncClient; -import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient; +import org.jclouds.vcloud.compute.VCloudComputeServiceContextBuilder; import org.jclouds.vcloud.hostingdotcom.compute.config.HostingDotComVCloudComputeServiceContextModule; import org.jclouds.vcloud.hostingdotcom.config.HostingDotComVCloudRestClientModule; import com.google.inject.Injector; -import com.google.inject.Key; import com.google.inject.Module; -import com.google.inject.TypeLiteral; /** * Creates {@link HostingDotComVCloudComputeServiceContext} or {@link Injector} instances based on @@ -51,23 +44,10 @@ import com.google.inject.TypeLiteral; * @see HostingDotComVCloudComputeServiceContext */ public class HostingDotComVCloudComputeServiceContextBuilder extends - ComputeServiceContextBuilder { + VCloudComputeServiceContextBuilder { public HostingDotComVCloudComputeServiceContextBuilder(Properties props) { - super(new TypeLiteral() { - }, new TypeLiteral() { - }, props); - } - - @Override - public HostingDotComVCloudComputeServiceContextBuilder withExecutorService( - ExecutorService service) { - return (HostingDotComVCloudComputeServiceContextBuilder) super.withExecutorService(service); - } - - @Override - public HostingDotComVCloudComputeServiceContextBuilder withModules(Module... modules) { - return (HostingDotComVCloudComputeServiceContextBuilder) super.withModules(modules); + super(props); } @Override @@ -80,14 +60,4 @@ public class HostingDotComVCloudComputeServiceContextBuilder extends modules.add(new HostingDotComVCloudRestClientModule()); } - @Override - public ComputeServiceContext buildComputeServiceContext() { - // need the generic type information - return (ComputeServiceContext) this - .buildInjector() - .getInstance( - Key - .get(new TypeLiteral>() { - })); - } } diff --git a/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudTemplate.java b/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudTemplate.java deleted file mode 100644 index f45383564e..0000000000 --- a/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudTemplate.java +++ /dev/null @@ -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 images; - private final Set sizes; - private Size size; - private String vDC; - private OperatingSystem operatingSystem; - private transient Image image; - - public HostingDotComVCloudTemplate(HostingDotComVCloudClient client, - Set images, Set 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 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 images, - Set 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 + "]"; - } - -} diff --git a/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/config/HostingDotComVCloudComputeServiceContextModule.java b/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/config/HostingDotComVCloudComputeServiceContextModule.java index c04ef14ef1..97d3f4a5c2 100755 --- a/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/config/HostingDotComVCloudComputeServiceContextModule.java +++ b/vcloud/hostingdotcom/src/main/java/org/jclouds/vcloud/hostingdotcom/compute/config/HostingDotComVCloudComputeServiceContextModule.java @@ -18,39 +18,11 @@ */ 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.ComputeServiceContext; -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.compute.config.VCloudComputeServiceContextModule; 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.common.collect.Sets; -import com.google.inject.Provides; +import com.google.inject.Injector; /** * Configures the {@link HostingDotComVCloudComputeServiceContext}; requires @@ -59,81 +31,16 @@ import com.google.inject.Provides; * @author Adrian Cole */ public class HostingDotComVCloudComputeServiceContextModule extends - HostingDotComVCloudContextModule { + VCloudComputeServiceContextModule { @Override protected void configure() { super.configure(); - bind(ComputeService.class).to(HostingDotComVCloudComputeService.class).asEagerSingleton(); } - @Provides - @Singleton - ComputeServiceContext provideContext(ComputeService computeService, - RestContext context) { - return new ComputeServiceContextImpl( - computeService, context); - } - - private static class LogHolder { - @Resource - @Named(ComputeServiceConstants.COMPUTE_LOGGER) - protected Logger logger = Logger.NULL; - } - - @Provides - @Singleton - Set provideImages(VCloudClient client, LogHolder holder) { - Set 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 provideSizes(HostingDotComVCloudClient client, Set images, - LogHolder holder) { - return ImmutableSet. of(new SizeImpl(1, 512, (int) (10l * 1025 * 1024), ImmutableSet - . of(Architecture.X86_32, Architecture.X86_64))); - } - - @Provides - @Singleton - Set provideTemplates(HostingDotComVCloudClient client, - Set images, Set sizes, LogHolder holder) { - Set 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; + @Override + protected ComputeService provideComputeService(Injector injector) { + return injector.getInstance(HostingDotComVCloudComputeService.class); } } diff --git a/vcloud/hostingdotcom/src/test/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeClientLiveTest.java b/vcloud/hostingdotcom/src/test/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeClientLiveTest.java index 4b33b0b728..3d766ec4f0 100644 --- a/vcloud/hostingdotcom/src/test/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeClientLiveTest.java +++ b/vcloud/hostingdotcom/src/test/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeClientLiveTest.java @@ -19,138 +19,49 @@ package org.jclouds.vcloud.hostingdotcom.compute; import static com.google.common.base.Preconditions.checkNotNull; -import static org.testng.Assert.assertEquals; -import java.io.IOException; 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.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.jclouds.vcloud.compute.VCloudComputeClientLiveTest; import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudClient; -import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudContextBuilder; import org.jclouds.vcloud.hostingdotcom.HostingDotComVCloudPropertiesBuilder; -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 HostingDotComVCloudClient} + * Tests behavior of {@code HostingDotComVCloudComputeClient} * * @author Adrian Cole */ -@Test(groups = "live", enabled = true, sequential = true, testName = "vcloud.HostingDotComVCloudClientLiveTest") -public class HostingDotComVCloudComputeClientLiveTest { - 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 expectationMap = ImmutableMap - . builder().put(OperatingSystem.CENTOS, - new Expectation(4194304 / 2 * 10, "Red Hat Enterprise Linux 5 (64-bit)")) - .build(); - - private Predicate 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 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); - } +@Test(groups = "live", enabled = true, sequential = true, testName = "vcloud.HostingDotComVCloudComputeClientLiveTest") +public class HostingDotComVCloudComputeClientLiveTest extends VCloudComputeClientLiveTest { @BeforeGroups(groups = { "live" }) + @Override public void setupClient() { - 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 HostingDotComVCloudContextBuilder( + Injector injector = new HostingDotComVCloudComputeServiceContextBuilder( new HostingDotComVCloudPropertiesBuilder(account, key).build()).withModules( new Log4JLoggingModule(), new JschSshClientModule()).buildInjector(); - client = injector.getInstance(HostingDotComVCloudComputeClient.class); - hostingClient = injector.getInstance(HostingDotComVCloudClient.class); + computeClient = injector.getInstance(HostingDotComVCloudComputeService.class); + client = injector.getInstance(HostingDotComVCloudClient.class); addressTester = injector.getInstance(Key.get(new TypeLiteral>() { })); + expectationMap = ImmutableMap. builder().put( + OperatingSystem.CENTOS, + new Expectation(4194304 / 2 * 10, "Red Hat Enterprise Linux 5 (64-bit)")).build(); + service = "vcloudtest"; + templateId = "3"; } } diff --git a/vcloud/hostingdotcom/src/test/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeServiceLiveTest.java b/vcloud/hostingdotcom/src/test/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeServiceLiveTest.java index 0b30391f35..03b2d78b78 100644 --- a/vcloud/hostingdotcom/src/test/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeServiceLiveTest.java +++ b/vcloud/hostingdotcom/src/test/java/org/jclouds/vcloud/hostingdotcom/compute/HostingDotComVCloudComputeServiceLiveTest.java @@ -19,160 +19,30 @@ 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.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import java.io.IOException; -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.compute.BaseComputeServiceLiveTest; import org.jclouds.ssh.jsch.config.JschSshClientModule; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeGroups; +import org.testng.annotations.BeforeClass; 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 */ @Test(groups = "live", enabled = true, sequential = true, testName = "compute.HostingDotComVCloudComputeServiceLiveTest") -public class HostingDotComVCloudComputeServiceLiveTest { - private static final String service = "hostingdotcom"; - private static final OperatingSystem testOS = CENTOS; - - protected SshClient.Factory sshFactory; - private String nodeName = service; - - private RetryablePredicate 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(socketOpen, 60, 1, TimeUnit.SECONDS); - injector.injectMembers(socketOpen); // add logger - client = context.getComputeService(); +public class HostingDotComVCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest { + @BeforeClass + @Override + public void setServiceDefaults() { + service = "hostingdotcom"; + testOS = CENTOS; } - public void testCreate() throws Exception { - Template template = client.createTemplateInLocation("default").os(testOS).smallest(); - node = client.runNode(nodeName, template); - 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(); + @Override + protected JschSshClientModule getSshModule() { + return new JschSshClientModule(); } - @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(); - } -} +} \ No newline at end of file diff --git a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeClient.java b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeClient.java index 1fb0128cb8..bbaa4af91c 100644 --- a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeClient.java +++ b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeClient.java @@ -86,9 +86,8 @@ public class TerremarkVCloudComputeClient { 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 properties) { - String vDCId = tmClient.getDefaultVDC().getId(); logger .debug( ">> instantiating vApp vDC(%s) template(%s) name(%s) minCores(%d) minMegs(%d) properties(%s)", diff --git a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeService.java b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeService.java index 95cfafca3c..59681f104b 100644 --- a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeService.java +++ b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeService.java @@ -18,12 +18,13 @@ */ package org.jclouds.vcloud.terremark.compute; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.vcloud.terremark.options.AddInternetServiceOptions.Builder.withDescription; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.util.Map; import java.util.Set; +import java.util.SortedSet; import javax.annotation.Resource; import javax.inject.Inject; @@ -31,127 +32,176 @@ import javax.inject.Named; import javax.inject.Provider; 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.LoginType; -import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.domain.NodeState; 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.domain.Credentials; import org.jclouds.logging.Logger; -import org.jclouds.vcloud.VCloudMediaType; -import org.jclouds.vcloud.domain.NamedResource; +import org.jclouds.vcloud.compute.VCloudComputeService; +import org.jclouds.vcloud.compute.VCloudTemplate; import org.jclouds.vcloud.domain.VApp; -import org.jclouds.vcloud.domain.VAppStatus; 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.Iterables; import com.google.common.collect.Sets; -import com.google.inject.internal.ImmutableSet; /** * @author Adrian Cole */ @Singleton -public class TerremarkVCloudComputeService implements ComputeService { +public class TerremarkVCloudComputeService extends VCloudComputeService { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; - private final TerremarkVCloudComputeClient computeClient; private final TerremarkVCloudClient client; - private Set images; - private Set sizes; - private Provider> templates; - - private static final Map vAppStatusToNodeState = ImmutableMap - . 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 - public TerremarkVCloudComputeService(TerremarkVCloudClient tmClient, - TerremarkVCloudComputeClient computeClient, Set images, - Set sizes, Provider> templates) { - this.client = tmClient; - this.computeClient = computeClient; - this.images = images; - this.sizes = sizes; - this.templates = templates; + public TerremarkVCloudComputeService(TerremarkVCloudClient client, + Provider> images, Provider> sizes, + Provider> templates, Predicate successTester, + Predicate socketTester) { + super(client, images, sizes, templates, successTester, socketTester); + this.client = client; } @Override - public CreateNodeResponse runNode(String name, Template template) { - checkNotNull(template.getImage().getLocation(), "location"); - String id = computeClient.start(template.getImage().getLocation(), name, template.getImage() - .getId(), (int) template.getSize().getCores(), (int) template.getSize().getRam(), - ImmutableMap. of()); + protected Map parseResponse(VApp vAppResponse) { + return ImmutableMap. of("id", vAppResponse.getId(), "username", "vcloud", + "password", "p4ssw0rd"); + } + + @Override + public Map start(String vDCId, String name, String templateId, int minCores, + int minMegs, Long diskSize, Map properties, int... portsToOpen) { + Map 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); - InetAddress publicIp = computeClient - .createPublicAddressMappedToPorts(vApp, 22, 80, 8080, 443); - return new CreateNodeResponseImpl(vApp.getId(), vApp.getName(), template.getImage().getLocation(), vApp.getLocation(), - ImmutableMap. of(), vAppStatusToNodeState.get(vApp.getStatus()), - ImmutableSet. of(publicIp), vApp.getNetworkToAddresses().values(), 22, - LoginType.SSH, new Credentials("vcloud", "p4ssw0rd"), ImmutableMap - . of()); + Set ipAddresses = deleteInternetServicesAndNodesAssociatedWithVApp(vApp); + deletePublicIpAddressesWithNoServicesAttached(ipAddresses); + super.stop(id); } - @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); - Set publicAddresses = computeClient.getPublicAddresses(vApp.getId()); - return new NodeMetadataImpl(vApp.getId(), vApp.getName(), vDCId, vApp.getLocation(), - ImmutableMap. of(), vAppStatusToNodeState.get(vApp.getStatus()), - publicAddresses, vApp.getNetworkToAddresses().values(), 22, LoginType.SSH, - ImmutableMap. of()); - } - - @Override - public Set listNodes() { - Set 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())); + private Set deleteInternetServicesAndNodesAssociatedWithVApp(VApp vApp) { + Set ipAddresses = Sets.newHashSet(); + SERVICE: for (InternetService service : client.getAllInternetServicesInVDC(vApp.getVDC() + .getId())) { + for (Node node : client.getNodes(service.getId())) { + 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 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 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")); + private void deletePublicIpAddressesWithNoServicesAttached(Set ipAddresses) { + IPADDRESS: for (PublicIpAddress address : ipAddresses) { + SortedSet 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; + } + } } - @Override - public Template createTemplateInLocation(String location) { - return new TerremarkVCloudTemplate(client, images, sizes, location); + /** + * + * @throws ElementNotFoundException + * if no address is configured + */ + public InetAddress getAnyPrivateAddress(String id) { + VApp vApp = client.getVApp(id); + return Iterables.getLast(vApp.getNetworkToAddresses().values()); } - @Override - public Set listSizes() { - return sizes; - } - - @Override - public Set listTemplates() { - return templates.get(); + public Set getPublicAddresses(String id) { + VApp vApp = client.getVApp(id); + Set ipAddresses = Sets.newHashSet(); + for (InternetService service : client.getAllInternetServicesInVDC(vApp.getVDC().getId())) { + for (Node node : client.getNodes(service.getId())) { + if (vApp.getNetworkToAddresses().containsValue(node.getIpAddress())) { + ipAddresses.add(service.getPublicIpAddress().getAddress()); + } + } + } + return ipAddresses; } } \ No newline at end of file diff --git a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeServiceContextBuilder.java b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeServiceContextBuilder.java index 287b18f117..ce7a83b7c4 100755 --- a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeServiceContextBuilder.java +++ b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeServiceContextBuilder.java @@ -20,22 +20,15 @@ package org.jclouds.vcloud.terremark.compute; import java.util.List; 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.logging.jdk.config.JDKLoggingModule; -import org.jclouds.vcloud.terremark.TerremarkVCloudAsyncClient; -import org.jclouds.vcloud.terremark.TerremarkVCloudClient; +import org.jclouds.vcloud.compute.VCloudComputeServiceContextBuilder; import org.jclouds.vcloud.terremark.compute.config.TerremarkVCloudComputeServiceContextModule; import org.jclouds.vcloud.terremark.config.TerremarkVCloudRestClientModule; import com.google.inject.Injector; -import com.google.inject.Key; import com.google.inject.Module; -import com.google.inject.TypeLiteral; /** * Creates {@link TerremarkVCloudComputeServiceContext} or {@link Injector} instances based on the @@ -50,23 +43,10 @@ import com.google.inject.TypeLiteral; * @author Adrian Cole * @see TerremarkVCloudComputeServiceContext */ -public class TerremarkVCloudComputeServiceContextBuilder extends - ComputeServiceContextBuilder { +public class TerremarkVCloudComputeServiceContextBuilder extends VCloudComputeServiceContextBuilder { public TerremarkVCloudComputeServiceContextBuilder(Properties props) { - super(new TypeLiteral() { - }, new TypeLiteral() { - }, props); - } - - @Override - public TerremarkVCloudComputeServiceContextBuilder withExecutorService(ExecutorService service) { - return (TerremarkVCloudComputeServiceContextBuilder) super.withExecutorService(service); - } - - @Override - public TerremarkVCloudComputeServiceContextBuilder withModules(Module... modules) { - return (TerremarkVCloudComputeServiceContextBuilder) super.withModules(modules); + super(props); } @Override @@ -79,14 +59,4 @@ public class TerremarkVCloudComputeServiceContextBuilder extends modules.add(new TerremarkVCloudRestClientModule()); } - @Override - public ComputeServiceContext buildComputeServiceContext() { - // need the generic type information - return (ComputeServiceContext) this - .buildInjector() - .getInstance( - Key - .get(new TypeLiteral>() { - })); - } } diff --git a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudTemplate.java b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudTemplate.java deleted file mode 100644 index b3e7283574..0000000000 --- a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudTemplate.java +++ /dev/null @@ -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 images; - private final Set sizes; - private Size size; - private String vDC; - private OperatingSystem operatingSystem; - private transient Image image; - - public TerremarkVCloudTemplate(TerremarkVCloudClient client, Set images, - Set 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 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 images, - Set 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 + "]"; - } - -} diff --git a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/config/TerremarkVCloudComputeServiceContextModule.java b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/config/TerremarkVCloudComputeServiceContextModule.java index e2adf14c4b..2ce1b48aed 100755 --- a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/config/TerremarkVCloudComputeServiceContextModule.java +++ b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/compute/config/TerremarkVCloudComputeServiceContextModule.java @@ -18,43 +18,26 @@ */ package org.jclouds.vcloud.terremark.compute.config; -import java.util.LinkedHashSet; import java.util.Set; - -import javax.annotation.Resource; -import javax.inject.Named; -import javax.inject.Singleton; +import java.util.SortedSet; +import java.util.concurrent.ExecutorService; import org.jclouds.compute.ComputeService; -import org.jclouds.compute.ComputeServiceContext; 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.terremark.TerremarkVCloudAsyncClient; +import org.jclouds.vcloud.compute.config.VCloudComputeServiceContextModule; import org.jclouds.vcloud.terremark.TerremarkVCloudClient; 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 com.google.common.base.Function; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; -import com.google.inject.Provides; +import com.google.inject.Injector; /** * Configures the {@link TerremarkVCloudComputeServiceContext}; requires @@ -62,98 +45,37 @@ import com.google.inject.Provides; * * @author Adrian Cole */ -public class TerremarkVCloudComputeServiceContextModule extends TerremarkVCloudContextModule { +public class TerremarkVCloudComputeServiceContextModule extends VCloudComputeServiceContextModule { @Override protected void configure() { super.configure(); - bind(ComputeService.class).to(TerremarkVCloudComputeService.class).asEagerSingleton(); } - @Provides - @Singleton - ComputeServiceContext provideContext(ComputeService computeService, - RestContext context) { - return new ComputeServiceContextImpl( - computeService, context); + @Override + protected ComputeService provideComputeService(Injector injector) { + return injector.getInstance(TerremarkVCloudComputeService.class); } private static final ComputeOptionsToSize sizeConverter = new ComputeOptionsToSize(); private static class ComputeOptionsToSize implements Function { - @Override public Size apply(ComputeOptions from) { - return new SizeImpl(from.getProcessorCount(), (int) from.getMemory(), null, ImmutableSet + return new SizeImpl(from.getProcessorCount(), from.getMemory(), 10, ImmutableSet . of(Architecture.X86_32, Architecture.X86_64)); } - } - private static class LogHolder { - @Resource - @Named(ComputeServiceConstants.COMPUTE_LOGGER) - protected Logger logger = Logger.NULL; - } - - @Provides - @Singleton - Set provideImages(VCloudClient client, LogHolder holder) { - Set 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 provideSizes(TerremarkVCloudClient client, Set images, - LogHolder holder) { + @Override + protected SortedSet provideSizes(VCloudClient client, + Set images, LogHolder holder, ExecutorService executor) { Image anyImage = Iterables.get(images, 0); holder.logger.debug(">> providing sizes"); - LinkedHashSet sizes = Sets.newLinkedHashSet(Iterables.transform(client - .getComputeOptionsOfCatalogItem(anyImage.getId()), sizeConverter)); + SortedSet sizes = Sets.newTreeSet(Iterables.transform(TerremarkVCloudClient.class.cast( + client).getComputeOptionsOfCatalogItem(anyImage.getId()), sizeConverter)); holder.logger.debug("<< sizes(%d)", sizes.size()); return sizes; } - @Provides - @Singleton - Set provideTemplates(TerremarkVCloudClient client, - Set images, Set sizes, LogHolder holder) { - Set 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; - } - } diff --git a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/domain/ComputeOptions.java b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/domain/ComputeOptions.java index 7c0dd31122..a1599db684 100644 --- a/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/domain/ComputeOptions.java +++ b/vcloud/terremark/src/main/java/org/jclouds/vcloud/terremark/domain/ComputeOptions.java @@ -29,10 +29,10 @@ package org.jclouds.vcloud.terremark.domain; */ public class ComputeOptions implements Comparable { private final int processorCount; - private final long memory; + private final int memory; private final float costPerHour; - public ComputeOptions(int processorCount, long memory, float costPerHour) { + public ComputeOptions(int processorCount, int memory, float costPerHour) { this.processorCount = processorCount; this.memory = memory; this.costPerHour = costPerHour; @@ -42,7 +42,7 @@ public class ComputeOptions implements Comparable { return processorCount; } - public long getMemory() { + public int getMemory() { return memory; } diff --git a/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeServiceLiveTest.java b/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeServiceLiveTest.java index a7b12c4924..42d2a20506 100644 --- a/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeServiceLiveTest.java +++ b/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudComputeServiceLiveTest.java @@ -19,45 +19,18 @@ package org.jclouds.vcloud.terremark.compute; -import static com.google.common.base.Preconditions.checkNotNull; -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 static org.jclouds.compute.domain.OperatingSystem.JEOS; -import java.io.IOException; -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.BaseComputeServiceLiveTest; 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.rest.RestContext; import org.jclouds.ssh.jsch.config.JschSshClientModule; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeGroups; +import org.jclouds.vcloud.compute.VCloudComputeClient; +import org.jclouds.vcloud.terremark.TerremarkVCloudAsyncClient; +import org.jclouds.vcloud.terremark.TerremarkVCloudClient; +import org.testng.annotations.BeforeClass; 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. @@ -65,115 +38,28 @@ import com.google.inject.Injector; * @author Adrian Cole */ @Test(groups = "live", enabled = true, sequential = true, testName = "terremark.TerremarkVCloudComputeServiceLiveTest") -public class TerremarkVCloudComputeServiceLiveTest { - private static final String service = "terremark"; - private static final OperatingSystem testOS = UBUNTU; - - protected SshClient.Factory sshFactory; - private String nodeName = service; - - private RetryablePredicate 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(socketOpen, 60, 1, TimeUnit.SECONDS); - injector.injectMembers(socketOpen); // add logger - client = context.getComputeService(); +public class TerremarkVCloudComputeServiceLiveTest extends BaseComputeServiceLiveTest { + @BeforeClass + @Override + public void setServiceDefaults() { + service = "terremark"; + testOS = JEOS; } - public void testCreate() throws Exception { - Template template = client.createTemplateInLocation("default").os(testOS).smallest(); - node = client.runNode(nodeName, template); - 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(); + @Override + protected JschSshClientModule getSshModule() { + return new JschSshClientModule(); } - @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(); + public void testAssignability() throws Exception { + @SuppressWarnings("unused") + RestContext tmContext = new ComputeServiceContextFactory() + .createContext(service, user, password).getProviderSpecificContext(); + + TerremarkVCloudComputeService computeService = TerremarkVCloudComputeService.class + .cast(client); + + @SuppressWarnings("unused") + VCloudComputeClient computeClient = VCloudComputeClient.class.cast(computeService); } } \ No newline at end of file