diff --git a/README.txt b/README.txt index 6fbeb8f7de..6ef98d2ad9 100644 --- a/README.txt +++ b/README.txt @@ -30,8 +30,10 @@ our current version is 1.0-beta-8 our dev version is 1.0-SNAPSHOT our compute api supports: ec2, gogrid, cloudservers (rackspace), rimuhosting, vcloud, - trmk-ecloud, trmk-vcloudexpress, eucalyptus, - bluelock-vclouddirector, slicehost, stub (in-memory) + trmk-ecloud, trmk-vcloudexpress, eucalyptus, cloudsigma, + elasticstack, bluelock-vclouddirector, slicehost, + elastichosts-lon-p (Peer 1), elastichosts-sat-p (Peer 1), + elastichosts-lon-b (BlueSquare), stub (in-memory) * note * the pom dependency org.jclouds/jclouds-allcompute gives you access to to all of these providers @@ -103,8 +105,8 @@ Compute Example (Clojure): Downloads: * distribution zip: http://jclouds.googlecode.com/files/jclouds-1.0-beta-8.zip - * maven repo: http://jclouds.googlecode.com/svn/repo - * snapshot repo: http://jclouds.rimuhosting.com/maven2/snapshots + * maven repo: https://oss.sonatype.org/content/repositories/releases + * snapshot repo: https://oss.sonatype.org/content/repositories/snapshots Links: * project page: http://code.google.com/p/jclouds/ diff --git a/allcompute/pom.xml b/allcompute/pom.xml index 000e927a1f..3d4e4dfb54 100644 --- a/allcompute/pom.xml +++ b/allcompute/pom.xml @@ -69,5 +69,15 @@ jclouds-slicehost ${project.version} + + ${project.groupId} + jclouds-elasticstack + ${project.version} + + + ${project.groupId} + jclouds-cloudsigma + ${project.version} + diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RegionAndIdToImage.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RegionAndIdToImage.java index 310b30f9ca..03333a0544 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RegionAndIdToImage.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RegionAndIdToImage.java @@ -21,6 +21,8 @@ package org.jclouds.aws.ec2.compute.functions; import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds; +import java.util.NoSuchElementException; + import javax.annotation.Resource; import javax.inject.Inject; import javax.inject.Singleton; @@ -29,6 +31,7 @@ import org.jclouds.aws.ec2.EC2Client; import org.jclouds.aws.ec2.compute.domain.RegionAndName; import org.jclouds.compute.domain.Image; import org.jclouds.logging.Logger; +import org.jclouds.rest.ResourceNotFoundException; import com.google.common.base.Function; import com.google.common.collect.Iterables; @@ -56,9 +59,19 @@ public final class RegionAndIdToImage implements Function org.jclouds.aws.ec2.domain.Image image = Iterables.getOnlyElement(sync.getAMIServices() .describeImagesInRegion(key.getRegion(), imageIds(key.getName()))); return parser.apply(image); + } catch (NoSuchElementException e) { + logger.debug(message(key, e)); + return null; + } catch (ResourceNotFoundException e) { + logger.debug(message(key, e)); + return null; } catch (Exception e) { - logger.warn(e, "could not find image %s/%s: %s", key.getRegion(), key.getName(), e.getMessage()); + logger.warn(e, message(key, e)); return null; } } + + public static String message(RegionAndName key, Exception e) { + return String.format("could not find image %s/%s: %s", key.getRegion(), key.getName(), e.getMessage()); + } } \ No newline at end of file diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java index 64c8eb219a..cc7839635d 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java @@ -39,6 +39,7 @@ import org.jclouds.aws.ec2.domain.KeyPair; import org.jclouds.aws.ec2.options.RunInstancesOptions; import org.jclouds.compute.domain.Template; import org.jclouds.compute.options.TemplateOptions; +import org.jclouds.rest.annotations.Provider; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Sets; @@ -49,6 +50,8 @@ import com.google.common.collect.Sets; */ @Singleton public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions { + @VisibleForTesting + final String provider; @VisibleForTesting final Map credentialsMap; @VisibleForTesting @@ -63,11 +66,12 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions final CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded; @Inject - CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions(Map credentialsMap, - @Named("SECURITY") Map securityGroupMap, + CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions(@Provider String provider, + Map credentialsMap, @Named("SECURITY") Map securityGroupMap, @Named("PLACEMENT") Map placementGroupMap, CreateUniqueKeyPair createUniqueKeyPair, CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded, CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded) { + this.provider = provider; this.credentialsMap = credentialsMap; this.securityGroupMap = securityGroupMap; this.placementGroupMap = placementGroupMap; @@ -76,9 +80,14 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions this.createPlacementGroupIfNeeded = createPlacementGroupIfNeeded; } + // this method only exists so that we can mock + String getProvider() { + return provider; + } + public RunInstancesOptions execute(String region, String tag, Template template) { - RunInstancesOptions instanceOptions = asType(template.getHardware().getId()).withAdditionalInfo(tag); + RunInstancesOptions instanceOptions = asType(template.getHardware().getId()); String keyPairName = createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, template.getOptions()); diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/options/RunInstancesOptions.java b/aws/core/src/main/java/org/jclouds/aws/ec2/options/RunInstancesOptions.java index b9bd70cb42..0701fe43ba 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/options/RunInstancesOptions.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/options/RunInstancesOptions.java @@ -41,7 +41,8 @@ import org.jclouds.encryption.internal.Base64; * * @author Adrian Cole * @see */ public class RunInstancesOptions extends BaseEC2RequestOptions { @@ -105,24 +106,13 @@ public class RunInstancesOptions extends BaseEC2RequestOptions { return getFirstFormOrNull("Placement.GroupName"); } - /** - * Specifies additional information to make available to the instance(s). - */ - public RunInstancesOptions withAdditionalInfo(String info) { - formParameters.put("AdditionalInfo", checkNotNull(info, "info")); - return this; - } - - String getAdditionalInfo() { - return getFirstFormOrNull("AdditionalInfo"); - } - /** * Unencoded data */ public RunInstancesOptions withUserData(byte[] unencodedData) { - checkArgument(checkNotNull(unencodedData, "unencodedData").length <= 16 * 1024, - "userData cannot be larger than 16kb"); + int length = checkNotNull(unencodedData, "unencodedData").length; + checkArgument(length > 0, "userData cannot be empty"); + checkArgument(length <= 16 * 1024, "userData cannot be larger than 16kb"); formParameters.put("UserData", Base64.encodeBytes(unencodedData)); return this; } @@ -244,14 +234,6 @@ public class RunInstancesOptions extends BaseEC2RequestOptions { return options.inPlacementGroup(placementGroup); } - /** - * @see RunInstancesOptions#withAdditionalInfo(String) - */ - public static RunInstancesOptions withAdditionalInfo(String additionalInfo) { - RunInstancesOptions options = new RunInstancesOptions(); - return options.withAdditionalInfo(additionalInfo); - } - /** * @see RunInstancesOptions#withUserData(byte []) */ diff --git a/aws/core/src/test/java/org/jclouds/aws/cloudwatch/CloudWatchAsyncClientTest.java b/aws/core/src/test/java/org/jclouds/aws/cloudwatch/CloudWatchAsyncClientTest.java index 9c3b11b049..545edf3847 100644 --- a/aws/core/src/test/java/org/jclouds/aws/cloudwatch/CloudWatchAsyncClientTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/cloudwatch/CloudWatchAsyncClientTest.java @@ -57,16 +57,23 @@ public class CloudWatchAsyncClientTest extends RestClientTest of()); assertEquals( runOptions.buildFormParameters().entries(), - ImmutableMultimap. of("InstanceType", size.getProviderId(), "AdditionalInfo", tag, - "SecurityGroup.1", generatedGroup, "KeyName", systemGeneratedKeyPairName).entries()); + ImmutableMultimap. of("InstanceType", size.getProviderId(), "SecurityGroup.1", + generatedGroup, "KeyName", systemGeneratedKeyPairName).entries()); assertEquals(runOptions.buildMatrixParameters(), ImmutableMultimap. of()); assertEquals(runOptions.buildRequestHeaders(), ImmutableMultimap. of()); assertEquals(runOptions.buildStringPayload(), null); @@ -158,9 +160,9 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT assertEquals(runOptions.buildQueryParameters(), ImmutableMultimap. of()); assertEquals( runOptions.buildFormParameters().entries(), - ImmutableMultimap. of("InstanceType", size.getProviderId(), "AdditionalInfo", tag, - "SecurityGroup.1", generatedGroup, "KeyName", systemGeneratedKeyPairName, "Placement.GroupName", - generatedGroup).entries()); + ImmutableMultimap. of("InstanceType", size.getProviderId(), "SecurityGroup.1", + generatedGroup, "KeyName", systemGeneratedKeyPairName, "Placement.GroupName", generatedGroup) + .entries()); assertEquals(runOptions.buildMatrixParameters(), ImmutableMultimap. of()); assertEquals(runOptions.buildRequestHeaders(), ImmutableMultimap. of()); assertEquals(runOptions.buildStringPayload(), null); @@ -217,9 +219,9 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT assertEquals(runOptions.buildQueryParameters(), ImmutableMultimap. of()); assertEquals( runOptions.buildFormParameters().entries(), - ImmutableMultimap. of("InstanceType", size.getProviderId(), "AdditionalInfo", tag, - "SecurityGroup.1", generatedGroup, "KeyName", systemGeneratedKeyPairName, "Placement.GroupName", - generatedGroup).entries()); + ImmutableMultimap. of("InstanceType", size.getProviderId(), "SecurityGroup.1", + generatedGroup, "KeyName", systemGeneratedKeyPairName, "Placement.GroupName", generatedGroup) + .entries()); assertEquals(runOptions.buildMatrixParameters(), ImmutableMultimap. of()); assertEquals(runOptions.buildRequestHeaders(), ImmutableMultimap. of()); assertEquals(runOptions.buildStringPayload(), null); @@ -271,8 +273,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT assertEquals(runOptions.buildQueryParameters(), ImmutableMultimap. of()); assertEquals( runOptions.buildFormParameters().entries(), - ImmutableMultimap. of("InstanceType", size.getProviderId(), "AdditionalInfo", tag, - "SubnetId", "1", "KeyName", systemGeneratedKeyPairName).entries()); + ImmutableMultimap. of("InstanceType", size.getProviderId(), "SubnetId", "1", "KeyName", + systemGeneratedKeyPairName).entries()); assertEquals(runOptions.buildMatrixParameters(), ImmutableMultimap. of()); assertEquals(runOptions.buildRequestHeaders(), ImmutableMultimap. of()); assertEquals(runOptions.buildStringPayload(), null); @@ -291,7 +293,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT String systemGeneratedKeyPairName = "systemGeneratedKeyPair"; String generatedGroup = "group"; Set generatedGroups = ImmutableSet.of(generatedGroup); - + // create mocks CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock( CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, @@ -327,8 +329,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT assertEquals(runOptions.buildQueryParameters(), ImmutableMultimap. of()); assertEquals( runOptions.buildFormParameters().entries(), - ImmutableMultimap. of("InstanceType", size.getProviderId(), "AdditionalInfo", tag, - "SecurityGroup.1", "group", "KeyName", systemGeneratedKeyPairName, "UserData", Base64.encodeBytes("hello".getBytes())).entries()); + ImmutableMultimap. of("InstanceType", size.getProviderId(), "SecurityGroup.1", "group", + "KeyName", systemGeneratedKeyPairName, "UserData", Base64.encodeBytes("hello".getBytes())).entries()); assertEquals(runOptions.buildMatrixParameters(), ImmutableMultimap. of()); assertEquals(runOptions.buildRequestHeaders(), ImmutableMultimap. of()); assertEquals(runOptions.buildStringPayload(), null); @@ -681,8 +683,12 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT verify(strategy.createPlacementGroupIfNeeded); } - @SuppressWarnings("unchecked") private CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions setupStrategy() { + return setupStrategy("ec2"); + } + + @SuppressWarnings("unchecked") + private CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions setupStrategy(String provider) { Map credentialsMap = createMock(Map.class); Map securityGroupMap = createMock(Map.class); Map placementGroupMap = createMock(Map.class); @@ -690,8 +696,9 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded = createMock(CreateSecurityGroupIfNeeded.class); CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded = createMock(CreatePlacementGroupIfNeeded.class); - return new CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions(credentialsMap, securityGroupMap, - placementGroupMap, createUniqueKeyPair, createSecurityGroupIfNeeded, createPlacementGroupIfNeeded); + return new CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions(provider, credentialsMap, + securityGroupMap, placementGroupMap, createUniqueKeyPair, createSecurityGroupIfNeeded, + createPlacementGroupIfNeeded); } private void replayStrategy(CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy) { diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/options/RunInstancesOptionsTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/options/RunInstancesOptionsTest.java index 945ab9f88b..f29be3c5b5 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/options/RunInstancesOptionsTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/options/RunInstancesOptionsTest.java @@ -21,7 +21,6 @@ package org.jclouds.aws.ec2.options; import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.asType; import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.enableMonitoring; -import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withAdditionalInfo; import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withDeviceName; import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withKernelId; import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.withKeyName; @@ -79,8 +78,7 @@ public class RunInstancesOptionsTest { public void testWithSecurityGroup() { RunInstancesOptions options = new RunInstancesOptions(); options.withSecurityGroup("test"); - assertEquals(options.buildFormParameters().get("SecurityGroup.1"), Collections - .singletonList("test")); + assertEquals(options.buildFormParameters().get("SecurityGroup.1"), Collections.singletonList("test")); } @Test @@ -92,8 +90,7 @@ public class RunInstancesOptionsTest { @Test public void testWithSecurityGroupStatic() { RunInstancesOptions options = withSecurityGroup("test"); - assertEquals(options.buildFormParameters().get("SecurityGroup.1"), Collections - .singletonList("test")); + assertEquals(options.buildFormParameters().get("SecurityGroup.1"), Collections.singletonList("test")); } @Test(expectedExceptions = NullPointerException.class) @@ -101,32 +98,12 @@ public class RunInstancesOptionsTest { withSecurityGroup(null); } - @Test - public void testWithAdditionalInfo() { - RunInstancesOptions options = new RunInstancesOptions(); - options.withAdditionalInfo("test"); - assertEquals(options.buildFormParameters().get("AdditionalInfo"), Collections - .singletonList("test")); - } - @Test public void testNullWithAdditionalInfo() { RunInstancesOptions options = new RunInstancesOptions(); assertEquals(options.buildFormParameters().get("AdditionalInfo"), Collections.EMPTY_LIST); } - @Test - public void testWithAdditionalInfoStatic() { - RunInstancesOptions options = withAdditionalInfo("test"); - assertEquals(options.buildFormParameters().get("AdditionalInfo"), Collections - .singletonList("test")); - } - - @Test(expectedExceptions = NullPointerException.class) - public void testWithAdditionalInfoNPE() { - withAdditionalInfo(null); - } - @Test public void testWithUserData() { RunInstancesOptions options = new RunInstancesOptions(); @@ -151,12 +128,16 @@ public class RunInstancesOptionsTest { withUserData(null); } + @Test(expectedExceptions = IllegalArgumentException.class) + public void testWithUserDataEmpty() { + withUserData("".getBytes()); + } + @Test public void testWithInstanceType() { RunInstancesOptions options = new RunInstancesOptions(); options.asType(InstanceType.C1_XLARGE); - assertEquals(options.buildFormParameters().get("InstanceType"), Collections - .singletonList("c1.xlarge")); + assertEquals(options.buildFormParameters().get("InstanceType"), Collections.singletonList("c1.xlarge")); } @Test @@ -168,8 +149,7 @@ public class RunInstancesOptionsTest { @Test public void testWithInstanceTypeStatic() { RunInstancesOptions options = asType(InstanceType.C1_XLARGE); - assertEquals(options.buildFormParameters().get("InstanceType"), Collections - .singletonList("c1.xlarge")); + assertEquals(options.buildFormParameters().get("InstanceType"), Collections.singletonList("c1.xlarge")); } @Test(expectedExceptions = NullPointerException.class) @@ -205,22 +185,21 @@ public class RunInstancesOptionsTest { public void testWithDeviceName() { RunInstancesOptions options = new RunInstancesOptions(); options.withDeviceName("test"); - assertEquals(options.buildFormParameters().get("BlockDeviceMapping.DeviceName"), Collections - .singletonList("test")); + assertEquals(options.buildFormParameters().get("BlockDeviceMapping.DeviceName"), + Collections.singletonList("test")); } @Test public void testNullWithDeviceName() { RunInstancesOptions options = new RunInstancesOptions(); - assertEquals(options.buildFormParameters().get("BlockDeviceMapping.DeviceName"), - Collections.EMPTY_LIST); + assertEquals(options.buildFormParameters().get("BlockDeviceMapping.DeviceName"), Collections.EMPTY_LIST); } @Test public void testWithDeviceNameStatic() { RunInstancesOptions options = withDeviceName("test"); - assertEquals(options.buildFormParameters().get("BlockDeviceMapping.DeviceName"), Collections - .singletonList("test")); + assertEquals(options.buildFormParameters().get("BlockDeviceMapping.DeviceName"), + Collections.singletonList("test")); } @Test(expectedExceptions = NullPointerException.class) @@ -232,8 +211,7 @@ public class RunInstancesOptionsTest { public void testWithMonitoringEnabled() { RunInstancesOptions options = new RunInstancesOptions(); options.enableMonitoring(); - assertEquals(options.buildFormParameters().get("Monitoring.Enabled"), Collections - .singletonList("true")); + assertEquals(options.buildFormParameters().get("Monitoring.Enabled"), Collections.singletonList("true")); } @Test @@ -245,8 +223,7 @@ public class RunInstancesOptionsTest { @Test public void testWithMonitoringEnabledStatic() { RunInstancesOptions options = enableMonitoring(); - assertEquals(options.buildFormParameters().get("Monitoring.Enabled"), Collections - .singletonList("true")); + assertEquals(options.buildFormParameters().get("Monitoring.Enabled"), Collections.singletonList("true")); } @Test @@ -277,8 +254,7 @@ public class RunInstancesOptionsTest { public void testWithRamdisk() { RunInstancesOptions options = new RunInstancesOptions(); options.withRamdisk("test"); - assertEquals(options.buildFormParameters().get("RamdiskId"), Collections - .singletonList("test")); + assertEquals(options.buildFormParameters().get("RamdiskId"), Collections.singletonList("test")); } @Test @@ -290,8 +266,7 @@ public class RunInstancesOptionsTest { @Test public void testWithRamdiskStatic() { RunInstancesOptions options = withRamdisk("test"); - assertEquals(options.buildFormParameters().get("RamdiskId"), Collections - .singletonList("test")); + assertEquals(options.buildFormParameters().get("RamdiskId"), Collections.singletonList("test")); } @Test(expectedExceptions = NullPointerException.class) @@ -303,22 +278,21 @@ public class RunInstancesOptionsTest { public void testWithVirtualName() { RunInstancesOptions options = new RunInstancesOptions(); options.withVirtualName("test"); - assertEquals(options.buildFormParameters().get("BlockDeviceMapping.VirtualName"), Collections - .singletonList("test")); + assertEquals(options.buildFormParameters().get("BlockDeviceMapping.VirtualName"), + Collections.singletonList("test")); } @Test public void testNullWithVirtualName() { RunInstancesOptions options = new RunInstancesOptions(); - assertEquals(options.buildFormParameters().get("BlockDeviceMapping.VirtualName"), - Collections.EMPTY_LIST); + assertEquals(options.buildFormParameters().get("BlockDeviceMapping.VirtualName"), Collections.EMPTY_LIST); } @Test public void testWithVirtualNameStatic() { RunInstancesOptions options = withVirtualName("test"); - assertEquals(options.buildFormParameters().get("BlockDeviceMapping.VirtualName"), Collections - .singletonList("test")); + assertEquals(options.buildFormParameters().get("BlockDeviceMapping.VirtualName"), + Collections.singletonList("test")); } @Test(expectedExceptions = NullPointerException.class) diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/services/InstanceAsyncClientTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/services/InstanceAsyncClientTest.java index daa9214b2d..98f5883c59 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/services/InstanceAsyncClientTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/services/InstanceAsyncClientTest.java @@ -111,9 +111,14 @@ public class InstanceAsyncClientTest extends BaseEC2AsyncClientTestorg.jclouds jclouds-project 1.0-SNAPSHOT - ../../project/pom.xml + ../project/pom.xml org.jclouds jclouds-cloudsigma @@ -61,9 +61,15 @@ ${project.groupId} - jclouds-elasticstack + jclouds-compute ${project.version} + + ${project.groupId} + jclouds-jsch + ${project.version} + test + ${project.groupId} jclouds-core @@ -73,7 +79,14 @@ ${project.groupId} - jclouds-elasticstack + jclouds-core + ${project.version} + test-jar + test + + + ${project.groupId} + jclouds-compute ${project.version} test-jar test diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaAsyncClient.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaAsyncClient.java new file mode 100644 index 0000000000..e199a1e378 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaAsyncClient.java @@ -0,0 +1,235 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.cloudsigma.binders.BindCloneDriveOptionsToPlainTextString; +import org.jclouds.cloudsigma.binders.BindDriveDataToPlainTextString; +import org.jclouds.cloudsigma.binders.BindDriveToPlainTextString; +import org.jclouds.cloudsigma.binders.BindServerToPlainTextString; +import org.jclouds.cloudsigma.domain.Drive; +import org.jclouds.cloudsigma.domain.DriveData; +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.cloudsigma.domain.Server; +import org.jclouds.cloudsigma.domain.ServerInfo; +import org.jclouds.cloudsigma.functions.KeyValuesDelimitedByBlankLinesToDriveInfo; +import org.jclouds.cloudsigma.functions.KeyValuesDelimitedByBlankLinesToServerInfo; +import org.jclouds.cloudsigma.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet; +import org.jclouds.cloudsigma.functions.ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet; +import org.jclouds.cloudsigma.functions.SplitNewlines; +import org.jclouds.cloudsigma.options.CloneDriveOptions; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.MapBinder; +import org.jclouds.rest.annotations.MapPayloadParam; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to CloudSigma via their REST API. + *

+ * + * @see CloudSigmaClient + * @see + * @author Adrian Cole + */ +@RequestFilters(BasicAuthentication.class) +@Consumes(MediaType.TEXT_PLAIN) +public interface CloudSigmaAsyncClient { + + /** + * @see CloudSigmaClient#listStandardDrives + */ + @GET + @Path("/drives/standard/list") + @ResponseParser(SplitNewlines.class) + ListenableFuture> listStandardDrives(); + + /** + * @see CloudSigmaClient#listStandardCds + */ + @GET + @Path("/drives/standard/cd/list") + @ResponseParser(SplitNewlines.class) + ListenableFuture> listStandardCds(); + + /** + * @see CloudSigmaClient#listStandardImages + */ + @GET + @Path("/drives/standard/img/list") + @ResponseParser(SplitNewlines.class) + ListenableFuture> listStandardImages(); + + /** + * @see CloudSigmaClient#cloneDrive + */ + @POST + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/{uuid}/clone") + @MapBinder(BindCloneDriveOptionsToPlainTextString.class) + ListenableFuture cloneDrive(@PathParam("uuid") String sourceUuid, + @MapPayloadParam("name") String newName, CloneDriveOptions... options); + + /** + * @see CloudSigmaClient#listDriveInfo + */ + @GET + @Path("/drives/info") + @ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class) + ListenableFuture> listDriveInfo(); + + /** + * @see CloudSigmaClient#getDriveInfo + */ + @GET + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/{uuid}/info") + ListenableFuture getDriveInfo(@PathParam("uuid") String uuid); + + /** + * @see CloudSigmaClient#createDrive + */ + @POST + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/create") + ListenableFuture createDrive(@BinderParam(BindDriveToPlainTextString.class) Drive createDrive); + + /** + * @see CloudSigmaClient#setDriveData + */ + @POST + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/{uuid}/set") + ListenableFuture setDriveData(@PathParam("uuid") String uuid, + @BinderParam(BindDriveDataToPlainTextString.class) DriveData createDrive); + + /** + * @see CloudSigmaClient#createServer + */ + @POST + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToServerInfo.class) + @Path("/servers/create") + ListenableFuture createServer( + @BinderParam(BindServerToPlainTextString.class) Server createServer); + + /** + * @see CloudSigmaClient#listServerInfo + */ + @GET + @Path("/servers/info") + @ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.class) + ListenableFuture> listServerInfo(); + + /** + * @see CloudSigmaClient#getServerInfo + */ + @GET + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToServerInfo.class) + @Path("/servers/{uuid}/info") + ListenableFuture getServerInfo(@PathParam("uuid") String uuid); + + /** + * @see CloudSigmaClient#setServerConfiguration + */ + @POST + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToServerInfo.class) + @Path("/servers/{uuid}/set") + ListenableFuture setServerConfiguration(@PathParam("uuid") String uuid, + @BinderParam(BindServerToPlainTextString.class) Server setServer); + + /** + * @see CloudSigmaClient#listServers + */ + @GET + @Path("/servers/list") + @ResponseParser(SplitNewlines.class) + ListenableFuture> listServers(); + + /** + * @see CloudSigmaClient#destroyServer + */ + @POST + @Path("/servers/{uuid}/destroy") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture destroyServer(@PathParam("uuid") String uuid); + + /** + * @see CloudSigmaClient#startServer + */ + @POST + @Path("/servers/{uuid}/start") + ListenableFuture startServer(@PathParam("uuid") String uuid); + + /** + * @see CloudSigmaClient#stopServer + */ + @POST + @Path("/servers/{uuid}/stop") + ListenableFuture stopServer(@PathParam("uuid") String uuid); + + /** + * @see CloudSigmaClient#shutdownServer + */ + @POST + @Path("/servers/{uuid}/shutdown") + ListenableFuture shutdownServer(@PathParam("uuid") String uuid); + + /** + * @see CloudSigmaClient#resetServer + */ + @POST + @Path("/servers/{uuid}/reset") + ListenableFuture resetServer(@PathParam("uuid") String uuid); + + /** + * @see CloudSigmaClient#listDrives + */ + @GET + @Path("/drives/list") + @ResponseParser(SplitNewlines.class) + ListenableFuture> listDrives(); + + /** + * @see CloudSigmaClient#destroyDrive + */ + @POST + @Path("/drives/{uuid}/destroy") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture destroyDrive(@PathParam("uuid") String uuid); +} diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaClient.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaClient.java new file mode 100644 index 0000000000..84a8bb8db7 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaClient.java @@ -0,0 +1,215 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.cloudsigma.domain.Drive; +import org.jclouds.cloudsigma.domain.DriveData; +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.cloudsigma.domain.Server; +import org.jclouds.cloudsigma.domain.ServerInfo; +import org.jclouds.cloudsigma.options.CloneDriveOptions; +import org.jclouds.concurrent.Timeout; + +/** + * Provides synchronous access to CloudSigma. + *

+ * + * @see CloudSigmaAsyncClient + * @see + * @author Adrian Cole + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface CloudSigmaClient { + /** + * list of server uuids in your account + * + * @return or empty set if no servers are found + */ + Set listServers(); + + /** + * Get all servers info + * + * @return or empty set if no servers are found + */ + Set listServerInfo(); + + /** + * @param uuid + * what to get + * @return null, if not found + */ + ServerInfo getServerInfo(String uuid); + + /** + * create a new server + * + * @param server + * @return newly created server + */ + ServerInfo createServer(Server server); + + /** + * set server configuration + * + * @param uuid + * what server to change + * @param serverData + * what values to change + * @return new data + */ + ServerInfo setServerConfiguration(String uuid, Server server); + + /** + * Destroy a server + * + * @param uuid + * what to destroy + */ + void destroyServer(String uuid); + + /** + * Start a server + * + * @param uuid + * what to start + */ + void startServer(String uuid); + + /** + * Stop a server + *

+ * Kills the server immediately, equivalent to a power failure. Server reverts to a stopped + * status if it is persistent and is automatically destroyed otherwise. + * + * @param uuid + * what to stop + */ + void stopServer(String uuid); + + /** + * Shutdown a server + *

+ * Sends the server an ACPI power-down event. Server reverts to a stopped status if it is + * persistent and is automatically destroyed otherwise. + *

note

behaviour on shutdown depends on how your server OS is set up to respond to an + * ACPI power button signal. + * + * @param uuid + * what to shutdown + */ + void shutdownServer(String uuid); + + /** + * Reset a server + * + * @param uuid + * what to reset + */ + void resetServer(String uuid); + + /** + * list of drive uuids in your account + * + * @return or empty set if no drives are found + */ + Set listDrives(); + + /** + * Get all drives info + * + * @return or empty set if no drives are found + */ + Set listDriveInfo(); + + /** + * @param uuid + * what to get + * @return null, if not found + */ + DriveInfo getDriveInfo(String uuid); + + /** + * create a new drive + * + * @param createDrive + * required parameters: name, size + * @return newly created drive + */ + DriveInfo createDrive(Drive createDrive); + + /** + * set extra drive data + * + * @param uuid + * what drive to change + * @param driveData + * what values to change + * @return new data + */ + DriveInfo setDriveData(String uuid, DriveData driveData); + + /** + * Destroy a drive + * + * @param uuid + * what to delete + */ + void destroyDrive(String uuid); + + /** + * list of drive uuids that are in the library + * + * @return or empty set if no drives are found + */ + Set listStandardDrives(); + + /** + * list of cd uuids that are in the library + * + * @return or empty set if no cds are found + */ + Set listStandardCds(); + + /** + * list of image uuids that are in the library + * + * @return or empty set if no images are found + */ + Set listStandardImages(); + + /** + * Clone an existing drive. By default, the size is the same as the source + * + * @param sourceUuid + * source to clone + * @param newName + * name of the resulting drive + * @param options + * options to control size + * @return new drive + */ + DriveInfo cloneDrive(String sourceUuid, String newName, CloneDriveOptions... options); + + +} diff --git a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaContextBuilder.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaContextBuilder.java similarity index 75% rename from sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaContextBuilder.java rename to cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaContextBuilder.java index d69dfc3874..71f5fc550e 100644 --- a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaContextBuilder.java +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaContextBuilder.java @@ -22,8 +22,9 @@ package org.jclouds.cloudsigma; import java.util.List; import java.util.Properties; +import org.jclouds.cloudsigma.compute.config.CloudSigmaComputeServiceContextModule; import org.jclouds.cloudsigma.config.CloudSigmaRestClientModule; -import org.jclouds.rest.RestContextBuilder; +import org.jclouds.compute.ComputeServiceContextBuilder; import com.google.inject.Module; @@ -31,13 +32,17 @@ import com.google.inject.Module; * * @author Adrian Cole */ -public class CloudSigmaContextBuilder extends - RestContextBuilder { +public class CloudSigmaContextBuilder extends ComputeServiceContextBuilder { public CloudSigmaContextBuilder(Properties props) { super(CloudSigmaClient.class, CloudSigmaAsyncClient.class, props); } + @Override + protected void addContextModule(List modules) { + modules.add(new CloudSigmaComputeServiceContextModule()); + } + protected void addClientModule(List modules) { modules.add(new CloudSigmaRestClientModule()); } diff --git a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaPropertiesBuilder.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaPropertiesBuilder.java similarity index 76% rename from sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaPropertiesBuilder.java rename to cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaPropertiesBuilder.java index d1daf9bde5..4a38f0f2dd 100644 --- a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaPropertiesBuilder.java +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaPropertiesBuilder.java @@ -19,8 +19,10 @@ package org.jclouds.cloudsigma; +import static com.google.common.base.Preconditions.checkArgument; import static org.jclouds.Constants.PROPERTY_API_VERSION; import static org.jclouds.Constants.PROPERTY_ENDPOINT; +import static org.jclouds.cloudsigma.reference.CloudSigmaConstants.PROPERTY_VNC_PASSWORD; import java.util.Properties; @@ -37,6 +39,7 @@ public class CloudSigmaPropertiesBuilder extends PropertiesBuilder { Properties properties = super.defaultProperties(); properties.setProperty(PROPERTY_ENDPOINT, "https://api.cloudsigma.com"); properties.setProperty(PROPERTY_API_VERSION, "1.0"); + properties.setProperty(PROPERTY_VNC_PASSWORD, "IL9vs34d"); return properties; } @@ -44,4 +47,11 @@ public class CloudSigmaPropertiesBuilder extends PropertiesBuilder { super(properties); } + @Override + public Properties build() { + Properties props = super.build(); + checkArgument(props.getProperty(PROPERTY_VNC_PASSWORD).length() <= 8, + "vnc passwords should be less that 8 characters!"); + return props; + } } diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/binders/BindCloneDriveOptionsToPlainTextString.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/binders/BindCloneDriveOptionsToPlainTextString.java new file mode 100644 index 0000000000..c0e26d0a88 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/binders/BindCloneDriveOptionsToPlainTextString.java @@ -0,0 +1,91 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.binders; + +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.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.ws.rs.core.MediaType; + +import org.jclouds.cloudsigma.CloudSigmaAsyncClient; +import org.jclouds.cloudsigma.functions.ListOfMapsToListOfKeyValuesDelimitedByBlankLines; +import org.jclouds.cloudsigma.options.CloneDriveOptions; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.MapBinder; +import org.jclouds.rest.internal.GeneratedHttpRequest; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class BindCloneDriveOptionsToPlainTextString implements MapBinder { + private final ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines; + + @Inject + public BindCloneDriveOptionsToPlainTextString( + ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines) { + this.listOfMapsToListOfKeyValuesDelimitedByBlankLines = listOfMapsToListOfKeyValuesDelimitedByBlankLines; + } + + @Override + public void bindToRequest(HttpRequest request, Map postParams) { + checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest, + "this binder is only valid for GeneratedHttpRequests!"); + @SuppressWarnings("unchecked") + GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request; + checkState(gRequest.getArgs() != null, "args should be initialized at this point"); + + CloneDriveOptions options = findOptionsInArgsOrNull(gRequest); + if (options != null) { + postParams = ImmutableMap. builder().putAll(postParams).putAll(options.getOptions()).build(); + } + + request.setPayload(listOfMapsToListOfKeyValuesDelimitedByBlankLines.apply(ImmutableSet.of(postParams))); + request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_PLAIN); + + } + + static CloneDriveOptions findOptionsInArgsOrNull(GeneratedHttpRequest gRequest) { + for (Object arg : gRequest.getArgs()) { + if (arg instanceof CloneDriveOptions) { + return (CloneDriveOptions) arg; + } else if (arg instanceof CloneDriveOptions[]) { + CloneDriveOptions[] options = (CloneDriveOptions[]) arg; + return (options.length > 0) ? options[0] : null; + } + } + return null; + } + + @Override + public void bindToRequest(HttpRequest request, Object input) { + throw new UnsupportedOperationException(); + } + +} diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/binders/BindDriveDataToPlainTextString.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/binders/BindDriveDataToPlainTextString.java new file mode 100644 index 0000000000..9f86bfcceb --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/binders/BindDriveDataToPlainTextString.java @@ -0,0 +1,61 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.binders; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.ws.rs.core.MediaType; + +import org.jclouds.cloudsigma.domain.DriveData; +import org.jclouds.cloudsigma.functions.ListOfMapsToListOfKeyValuesDelimitedByBlankLines; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class BindDriveDataToPlainTextString implements Binder { + private final Function> createDriveRequestToMap; + private final ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines; + + @Inject + public BindDriveDataToPlainTextString(Function> createDriveRequestToMap, + ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines) { + this.createDriveRequestToMap = createDriveRequestToMap; + this.listOfMapsToListOfKeyValuesDelimitedByBlankLines = listOfMapsToListOfKeyValuesDelimitedByBlankLines; + } + + public void bindToRequest(HttpRequest request, Object payload) { + checkArgument(payload instanceof DriveData, "this binder is only valid for DriveData!"); + DriveData create = DriveData.class.cast(payload); + Map map = createDriveRequestToMap.apply(create); + request.setPayload(listOfMapsToListOfKeyValuesDelimitedByBlankLines.apply(ImmutableSet.of(map))); + request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_PLAIN); + } +} diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/binders/BindDriveToPlainTextString.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/binders/BindDriveToPlainTextString.java new file mode 100644 index 0000000000..71d5627b1a --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/binders/BindDriveToPlainTextString.java @@ -0,0 +1,61 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.binders; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.ws.rs.core.MediaType; + +import org.jclouds.cloudsigma.domain.Drive; +import org.jclouds.cloudsigma.functions.ListOfMapsToListOfKeyValuesDelimitedByBlankLines; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class BindDriveToPlainTextString implements Binder { + private final Function> createDriveRequestToMap; + private final ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines; + + @Inject + public BindDriveToPlainTextString(Function> createDriveRequestToMap, + ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines) { + this.createDriveRequestToMap = createDriveRequestToMap; + this.listOfMapsToListOfKeyValuesDelimitedByBlankLines = listOfMapsToListOfKeyValuesDelimitedByBlankLines; + } + + public void bindToRequest(HttpRequest request, Object payload) { + checkArgument(payload instanceof Drive, "this binder is only valid for Drive!"); + Drive create = Drive.class.cast(payload); + Map map = createDriveRequestToMap.apply(create); + request.setPayload(listOfMapsToListOfKeyValuesDelimitedByBlankLines.apply(ImmutableSet.of(map))); + request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_PLAIN); + } +} diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/binders/BindServerToPlainTextString.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/binders/BindServerToPlainTextString.java new file mode 100644 index 0000000000..371b1858db --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/binders/BindServerToPlainTextString.java @@ -0,0 +1,61 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.binders; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.ws.rs.core.MediaType; + +import org.jclouds.cloudsigma.domain.Server; +import org.jclouds.cloudsigma.functions.ListOfMapsToListOfKeyValuesDelimitedByBlankLines; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class BindServerToPlainTextString implements Binder { + private final Function> createServerRequestToMap; + private final ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines; + + @Inject + public BindServerToPlainTextString(Function> createServerRequestToMap, + ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines) { + this.createServerRequestToMap = createServerRequestToMap; + this.listOfMapsToListOfKeyValuesDelimitedByBlankLines = listOfMapsToListOfKeyValuesDelimitedByBlankLines; + } + + public void bindToRequest(HttpRequest request, Object payload) { + checkArgument(payload instanceof Server, "this binder is only valid for Server!"); + Server create = Server.class.cast(payload); + Map map = createServerRequestToMap.apply(create); + request.setPayload(listOfMapsToListOfKeyValuesDelimitedByBlankLines.apply(ImmutableSet.of(map))); + request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_PLAIN); + } +} diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/CloudSigmaComputeServiceAdapter.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/CloudSigmaComputeServiceAdapter.java new file mode 100644 index 0000000000..c29111a60a --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/CloudSigmaComputeServiceAdapter.java @@ -0,0 +1,231 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.compute; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.filter; +import static org.jclouds.concurrent.FutureIterables.transformParallel; + +import java.net.URI; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.Constants; +import org.jclouds.cloudsigma.CloudSigmaAsyncClient; +import org.jclouds.cloudsigma.CloudSigmaClient; +import org.jclouds.cloudsigma.domain.Device; +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.cloudsigma.domain.DriveType; +import org.jclouds.cloudsigma.domain.Server; +import org.jclouds.cloudsigma.domain.ServerInfo; +import org.jclouds.cloudsigma.options.CloneDriveOptions; +import org.jclouds.cloudsigma.reference.CloudSigmaConstants; +import org.jclouds.cloudsigma.util.Servers; +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.ComputeServiceAdapter; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.internal.VolumeImpl; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.domain.Credentials; +import org.jclouds.domain.Location; +import org.jclouds.domain.LocationScope; +import org.jclouds.domain.internal.LocationImpl; +import org.jclouds.logging.Logger; +import org.jclouds.rest.annotations.Provider; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; + +/** + * defines the connection between the {@link CloudSigmaClient} implementation and the jclouds + * {@link ComputeService} + * + */ +@Singleton +public class CloudSigmaComputeServiceAdapter implements + ComputeServiceAdapter { + private static final Predicate PREINSTALLED_DISK = Predicates.and(Predicates.notNull(), + new Predicate() { + + @Override + public boolean apply(DriveInfo drive) { + return drive.getType().equals(DriveType.DISK) && drive.getDriveType().contains("preinstalled"); + } + + }); + private final CloudSigmaClient client; + private final CloudSigmaAsyncClient aclient; + private final Predicate driveNotClaimed; + private final String providerName; + private final URI providerURI; + private final String defaultVncPassword; + private final Map cache; + private final ExecutorService executor; + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + @Inject + public CloudSigmaComputeServiceAdapter(CloudSigmaClient client, CloudSigmaAsyncClient aclient, + Predicate driveNotClaimed, @Provider String providerName, @Provider URI providerURI, + @Named(CloudSigmaConstants.PROPERTY_VNC_PASSWORD) String defaultVncPassword, Map cache, + @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { + this.client = checkNotNull(client, "client"); + this.aclient = checkNotNull(aclient, "aclient"); + this.driveNotClaimed = checkNotNull(driveNotClaimed, "driveNotClaimed"); + this.providerName = checkNotNull(providerName, "providerName"); + this.providerURI = checkNotNull(providerURI, "providerURI"); + this.defaultVncPassword = checkNotNull(defaultVncPassword, "defaultVncPassword"); + this.cache = checkNotNull(cache, "cache"); + this.executor = checkNotNull(executor, "executor"); + } + + @Override + public ServerInfo runNodeWithTagAndNameAndStoreCredentials(String tag, String name, Template template, + Map credentialStore) { + long bootSize = (long) (template.getHardware().getVolumes().get(0).getSize() * 1024 * 1024 * 1024l); + logger.debug(">> imaging boot drive source(%s) bytes(%d)", template.getImage().getId(), bootSize); + DriveInfo drive = client.cloneDrive(template.getImage().getId(), template.getImage().getId(), + new CloneDriveOptions().size(bootSize)); + boolean success = driveNotClaimed.apply(drive); + logger.debug("<< image(%s) complete(%s)", drive.getUuid(), success); + if (!success) { + client.destroyDrive(drive.getUuid()); + throw new IllegalStateException("could not image drive in time!"); + } + Server toCreate = Servers.small(name, drive.getUuid(), defaultVncPassword).mem(template.getHardware().getRam()) + .cpu((int) (template.getHardware().getProcessors().get(0).getSpeed())).build(); + + logger.debug(">> creating server"); + ServerInfo from = client.createServer(toCreate); + logger.debug("<< created server(%s)", from.getUuid()); + logger.debug(">> starting server(%s)", from.getUuid()); + client.startServer(from.getUuid()); + // store the credentials so that later functions can use them + credentialStore.put(from.getUuid() + "", new Credentials("cloudsigma", "cloudsigma")); + return from; + } + + @Override + public Iterable listHardwareProfiles() { + Builder hardware = ImmutableSet. builder(); + for (double cpu : new double[] { 1000, 5000, 10000, 20000 }) + for (int ram : new int[] { 512, 1024, 4 * 1024, 16 * 1024, 32 * 1024 }) { + final float size = (float) cpu / 100; + String id = String.format("cpu=%f,ram=%s,disk=%f", cpu, ram, size); + hardware.add(new HardwareBuilder().supportsImage(new Predicate() { + + @Override + public boolean apply(Image input) { + String toParse = input.getUserMetadata().get("size"); + return (toParse != null && new Float(toParse) <= size); + } + + @Override + public String toString() { + return "sizeLessThanOrEqual(" + size + ")"; + } + + }).ids(id).ram(ram).processors(ImmutableList.of(new Processor(1, cpu))) + .volumes(ImmutableList. of(new VolumeImpl(size, true, true))).build()); + } + return hardware.build(); + } + + /** + * look up the current standard images and do not error out, if they are not found. + */ + @Override + public Iterable listImages() { + Iterable drives = transformParallel(client.listStandardDrives(), + new Function>() { + + @Override + public Future apply(String input) { + return aclient.getDriveInfo(input); + } + + }, executor, null, logger, "drives"); + Iterable returnVal = filter(drives, PREINSTALLED_DISK); + for (DriveInfo drive : returnVal) + cache.put(drive.getUuid(), drive); + return returnVal; + } + + @SuppressWarnings("unchecked") + @Override + public Iterable listNodes() { + return (Iterable) client.listServerInfo(); + } + + @Override + public Iterable listLocations() { + return ImmutableSet. of(new LocationImpl(LocationScope.PROVIDER, providerName, providerURI + .toASCIIString(), null)); + } + + @Override + public ServerInfo getNode(String id) { + return client.getServerInfo(id); + } + + @Override + public void destroyNode(String id) { + ServerInfo server = getNode(id); + if (server != null) { + client.stopServer(id); + client.destroyServer(id); + for (Device dev : server.getDevices().values()) + client.destroyDrive(dev.getDriveUuid()); + } + } + + @Override + public void rebootNode(String id) { + client.resetServer(id); + } + + @Override + public void resumeNode(String id) { + client.startServer(id); + + } + + @Override + public void suspendNode(String id) { + client.stopServer(id); + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/config/CloudSigmaComputeServiceContextModule.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/config/CloudSigmaComputeServiceContextModule.java new file mode 100644 index 0000000000..055c85fa6b --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/config/CloudSigmaComputeServiceContextModule.java @@ -0,0 +1,140 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.compute.config; + +import static org.jclouds.compute.domain.OsFamily.UBUNTU; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.CloudSigmaAsyncClient; +import org.jclouds.cloudsigma.CloudSigmaClient; +import org.jclouds.cloudsigma.compute.CloudSigmaComputeServiceAdapter; +import org.jclouds.cloudsigma.compute.functions.ParseOsFamilyVersion64BitFromImageName; +import org.jclouds.cloudsigma.compute.functions.PreinstalledDiskToImage; +import org.jclouds.cloudsigma.compute.functions.ServerInfoToNodeMetadata; +import org.jclouds.cloudsigma.compute.functions.ServerInfoToNodeMetadata.DeviceToVolume; +import org.jclouds.cloudsigma.compute.functions.ServerInfoToNodeMetadata.FindImageForId; +import org.jclouds.cloudsigma.compute.functions.ServerInfoToNodeMetadata.GetImageIdFromServer; +import org.jclouds.cloudsigma.domain.Device; +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.cloudsigma.domain.Server; +import org.jclouds.cloudsigma.domain.ServerInfo; +import org.jclouds.cloudsigma.predicates.DriveClaimed; +import org.jclouds.compute.ComputeServiceAdapter; +import org.jclouds.compute.config.ComputeServiceAdapterContextModule; +import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule.IdentityFunction; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.TemplateBuilder; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.compute.suppliers.DefaultLocationSupplier; +import org.jclouds.domain.Location; +import org.jclouds.predicates.RetryablePredicate; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.collect.MapMaker; +import com.google.inject.Injector; +import com.google.inject.Provides; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +public class CloudSigmaComputeServiceContextModule + extends + ComputeServiceAdapterContextModule { + + public CloudSigmaComputeServiceContextModule() { + super(CloudSigmaClient.class, CloudSigmaAsyncClient.class); + } + + @Override + protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) { + return template.osFamily(UBUNTU).osVersionMatches("10.04").os64Bit(true).minRam(1024); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + protected void configure() { + super.configure(); + bind(new TypeLiteral>() { + }).to(CloudSigmaComputeServiceAdapter.class); + bind(IdentityFunction.class).toInstance(IdentityFunction.INSTANCE); + bind(new TypeLiteral>() { + }).to(DefaultLocationSupplier.class); + bind(new TypeLiteral>() { + }).to(ServerInfoToNodeMetadata.class); + bind(new TypeLiteral>() { + }).to((Class) IdentityFunction.class); + bind(new TypeLiteral>() { + }).to(PreinstalledDiskToImage.class); + bind(new TypeLiteral>() { + }).to((Class) IdentityFunction.class); + bind(new TypeLiteral>() { + }).to(DeviceToVolume.class); + bind(new TypeLiteral>() { + }).to(GetImageIdFromServer.class); + bind(new TypeLiteral>() { + }).to(FindImageForId.class); + bind(new TypeLiteral>() { + }).to(ParseOsFamilyVersion64BitFromImageName.class); + + } + + @Provides + @Singleton + protected Map cache(GetDrive getDrive) { + return new MapMaker().makeComputingMap(getDrive); + } + + @Singleton + public static class GetDrive implements Function { + private final CloudSigmaClient client; + + @Inject + public GetDrive(CloudSigmaClient client) { + this.client = client; + } + + @Override + public DriveInfo apply(String input) { + return client.getDriveInfo(input); + } + } + + @Provides + @Singleton + protected Predicate supplyDriveUnclaimed(DriveClaimed driveClaimed, + ComputeServiceConstants.Timeouts timeouts) { + return new RetryablePredicate(Predicates.not(driveClaimed), timeouts.nodeRunning, 1000, + TimeUnit.MILLISECONDS); + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/functions/ParseOsFamilyVersion64BitFromImageName.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/functions/ParseOsFamilyVersion64BitFromImageName.java new file mode 100644 index 0000000000..a86f2a32e3 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/functions/ParseOsFamilyVersion64BitFromImageName.java @@ -0,0 +1,81 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.compute.functions; + +import static com.google.common.base.Predicates.and; +import static com.google.common.base.Predicates.containsPattern; +import static com.google.common.base.Predicates.not; +import static com.google.common.base.Predicates.or; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.inject.Singleton; + +import org.jclouds.compute.domain.OsFamily; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; + +import com.google.common.base.Function; + +/** + * Defaults to version null and 64bit, if the operating system is unrecognized and the pattern + * "32bit" isn't in the string. + * + * @author Adrian Cole + * + */ +@Singleton +public class ParseOsFamilyVersion64BitFromImageName implements Function { + + // ex CentOS 5.5 Linux 64bit Preinstalled System with AppFirst Monitoring + public static final Pattern PATTERN = Pattern.compile("([^ ]+)[^0-9]([0-9.]+) .*"); + + @Override + public OsFamilyVersion64Bit apply(String input) { + boolean is64Bit = and(not(containsPattern("32bit")), + or(containsPattern("64bit"), not(containsPattern("Windows")))).apply(input); + if (input.contains("Windows")) { + String version = null; + Matcher matcher = Pattern.compile(".*(20[01][0-9] R[1-9]).*").matcher(input); + if (matcher.find()) { + version = matcher.group(1); + } else { + matcher = Pattern.compile(".*(20[01][0-9]).*").matcher(input); + if (matcher.find()) + version = matcher.group(1); + } + return new OsFamilyVersion64Bit(OsFamily.WINDOWS, version, is64Bit); + } else { + Matcher matcher = PATTERN.matcher(input); + if (matcher.find()) { + OsFamily fam = OsFamily.fromValue(matcher.group(1).toLowerCase()); + String version = matcher.group(2); + switch (fam) { + case UNRECOGNIZED: + return new OsFamilyVersion64Bit(OsFamily.UNRECOGNIZED, null, is64Bit); + case WINDOWS: + } + return new OsFamilyVersion64Bit(fam, version, is64Bit); + } else { + return new OsFamilyVersion64Bit(OsFamily.UNRECOGNIZED, null, is64Bit); + } + } + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/functions/PreinstalledDiskToImage.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/functions/PreinstalledDiskToImage.java new file mode 100644 index 0000000000..1815bac10f --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/functions/PreinstalledDiskToImage.java @@ -0,0 +1,66 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.compute.functions; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.OperatingSystemBuilder; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; +import org.jclouds.domain.Credentials; +import org.jclouds.domain.Location; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; + +/** + * @author Adrian Cole + */ +@Singleton +public class PreinstalledDiskToImage implements Function { + private final Supplier locationSupplier; + private final Function imageParser; + + @Inject + public PreinstalledDiskToImage(Supplier locationSupplier, + Function imageParser) { + this.locationSupplier = locationSupplier; + this.imageParser = imageParser; + } + + @Override + public Image apply(DriveInfo drive) { + if (drive.getName() == null) + return null; + String description = drive.getDescription() != null ? drive.getDescription() : drive.getName(); + OperatingSystemBuilder builder = new OperatingSystemBuilder(); + OsFamilyVersion64Bit parsed = imageParser.apply(drive.getName()); + builder.name(drive.getName()).description(description).is64Bit(parsed.is64Bit).version(parsed.version) + .family(parsed.family); + return new ImageBuilder().ids(drive.getUuid()) + .userMetadata(ImmutableMap. of("size", drive.getSize() / 1024 / 1024 / 1024 + "")) + .defaultCredentials(new Credentials("cloudsigma", "cloudsigma")).location(locationSupplier.get()) + .name(drive.getName()).description(description).operatingSystem(builder.build()).version("").build(); + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/functions/ServerInfoToNodeMetadata.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/functions/ServerInfoToNodeMetadata.java new file mode 100644 index 0000000000..ef07925402 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/compute/functions/ServerInfoToNodeMetadata.java @@ -0,0 +1,183 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.compute.util.ComputeServiceUtils.parseTagFromName; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.Device; +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.cloudsigma.domain.Server; +import org.jclouds.cloudsigma.domain.ServerInfo; +import org.jclouds.cloudsigma.domain.ServerStatus; +import org.jclouds.collect.FindResourceInSet; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.domain.NodeState; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.VolumeBuilder; +import org.jclouds.domain.Credentials; +import org.jclouds.domain.Location; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +@Singleton +public class ServerInfoToNodeMetadata implements Function { + public static final Map serverStatusToNodeState = ImmutableMap + . builder().put(ServerStatus.ACTIVE, NodeState.RUNNING)// + .put(ServerStatus.STOPPED, NodeState.SUSPENDED)// + .put(ServerStatus.PAUSED, NodeState.SUSPENDED)// + .put(ServerStatus.DUMPED, NodeState.PENDING)// + .put(ServerStatus.DEAD, NodeState.TERMINATED)// + .put(ServerStatus.UNRECOGNIZED, NodeState.UNRECOGNIZED)// + .build(); + + private final Function getImageIdFromServer; + private final Function findImageForId; + private final Map credentialStore; + private final Supplier locationSupplier; + private final Function deviceToVolume; + + @Inject + ServerInfoToNodeMetadata(Map credentialStore, Function getImageIdFromServer, + Function findImageForId, Function deviceToVolume, + Supplier locationSupplier) { + this.credentialStore = checkNotNull(credentialStore, "credentialStore"); + this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier"); + this.deviceToVolume = checkNotNull(deviceToVolume, "deviceToVolume"); + this.findImageForId = checkNotNull(findImageForId, "findImageForId"); + this.getImageIdFromServer = checkNotNull(getImageIdFromServer, "getImageIdFromServer"); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public NodeMetadata apply(ServerInfo from) { + NodeMetadataBuilder builder = new NodeMetadataBuilder(); + builder.ids(from.getUuid()); + builder.name(from.getName()); + builder.location(locationSupplier.get()); + builder.tag(parseTagFromName(from.getName())); + + String imageId = getImageIdFromServer.apply(from); + if (imageId != null) { + Image image = findImageForId.apply(imageId); + if (image != null) { + builder.operatingSystem(image.getOperatingSystem()); + } + } + builder.hardware(new HardwareBuilder().ids(from.getUuid()) + .processors(ImmutableList.of(new Processor(1, from.getCpu()))).ram(from.getMem()) + .volumes((List) ImmutableList.of(Iterables.transform(from.getDevices().values(), deviceToVolume))).build()); + builder.state(serverStatusToNodeState.get(from.getStatus())); + builder.publicAddresses(ImmutableSet. of(from.getVnc().getIp())); + builder.privateAddresses(ImmutableSet. of()); + builder.credentials(credentialStore.get(from.getUuid())); + // note sudo password! + builder.adminPassword(from.getVnc().getPassword()); + return builder.build(); + } + + @Singleton + public static final class DeviceToVolume implements Function { + private final Map cache; + + @Inject + public DeviceToVolume(Map cache) { + this.cache = checkNotNull(cache, "cache"); + } + + @Override + public Volume apply(Device input) { + VolumeBuilder builder = new VolumeBuilder(); + builder.id(input.getId()); + DriveInfo drive = cache.get(input.getDriveUuid()); + if (drive != null) { + builder.size(drive.getSize() / 1024 / 1024f); + } + return new VolumeBuilder().durable(true).type(Volume.Type.NAS).build(); + } + } + + /** + * When we create the boot drive of the server, by convention we set the name to the image it + * came from. + * + * @author Adrian Cole + * + */ + @Singleton + public static class GetImageIdFromServer implements Function { + private final Map cache; + + @Inject + public GetImageIdFromServer(Map cache) { + this.cache = cache; + } + + @Override + public String apply(Server from) { + String imageId = null; + String bootDeviceId = Iterables.get(from.getBootDeviceIds(), 0); + Device bootDevice = from.getDevices().get(bootDeviceId); + if (bootDevice != null) { + try { + imageId = cache.get(bootDevice.getDriveUuid()).getName(); + } catch (NullPointerException e) { + + } + } + return imageId; + } + } + + @Singleton + public static class FindImageForId extends FindResourceInSet { + + @Inject + public FindImageForId(@Memoized Supplier> images) { + super(images); + } + + @Override + public boolean matches(String from, Image input) { + return input.getProviderId().equals(from); + } + } + +} diff --git a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/config/CloudSigmaRestClientModule.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/config/CloudSigmaRestClientModule.java similarity index 73% rename from sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/config/CloudSigmaRestClientModule.java rename to cloudsigma/src/main/java/org/jclouds/cloudsigma/config/CloudSigmaRestClientModule.java index e935551866..cdd01de601 100644 --- a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/config/CloudSigmaRestClientModule.java +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/config/CloudSigmaRestClientModule.java @@ -24,20 +24,22 @@ import java.util.Map; import org.jclouds.cloudsigma.CloudSigmaAsyncClient; import org.jclouds.cloudsigma.CloudSigmaClient; -import org.jclouds.cloudsigma.functions.CreateDriveRequestToMap; +import org.jclouds.cloudsigma.domain.Device; +import org.jclouds.cloudsigma.domain.Drive; +import org.jclouds.cloudsigma.domain.DriveData; +import org.jclouds.cloudsigma.domain.DriveMetrics; +import org.jclouds.cloudsigma.domain.NIC; +import org.jclouds.cloudsigma.domain.Server; +import org.jclouds.cloudsigma.domain.ServerMetrics; +import org.jclouds.cloudsigma.functions.BaseDriveToMap; import org.jclouds.cloudsigma.functions.DriveDataToMap; -import org.jclouds.elasticstack.domain.Device; -import org.jclouds.elasticstack.domain.Drive; -import org.jclouds.elasticstack.domain.DriveData; -import org.jclouds.elasticstack.domain.DriveMetrics; -import org.jclouds.elasticstack.domain.NIC; -import org.jclouds.elasticstack.domain.ServerMetrics; -import org.jclouds.elasticstack.functions.MapToDevices; -import org.jclouds.elasticstack.functions.MapToDevices.DeviceToId; -import org.jclouds.elasticstack.functions.MapToDriveMetrics; -import org.jclouds.elasticstack.functions.MapToNICs; -import org.jclouds.elasticstack.functions.MapToServerMetrics; -import org.jclouds.elasticstack.handlers.ElasticStackErrorHandler; +import org.jclouds.cloudsigma.functions.MapToDevices; +import org.jclouds.cloudsigma.functions.MapToDevices.DeviceToId; +import org.jclouds.cloudsigma.functions.MapToDriveMetrics; +import org.jclouds.cloudsigma.functions.MapToNICs; +import org.jclouds.cloudsigma.functions.MapToServerMetrics; +import org.jclouds.cloudsigma.functions.ServerToMap; +import org.jclouds.cloudsigma.handlers.CloudSigmaErrorHandler; import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.RequiresHttp; import org.jclouds.http.annotation.ClientError; @@ -64,16 +66,16 @@ public class CloudSigmaRestClientModule extends RestClientModule>>() { - }).to(CreateDriveRequestToMap.class); + }).to(BaseDriveToMap.class); bind(new TypeLiteral>>() { }).to(DriveDataToMap.class); bind(new TypeLiteral, List>>() { @@ -86,6 +88,8 @@ public class CloudSigmaRestClientModule extends RestClientModule>() { }).to(DeviceToId.class); + bind(new TypeLiteral>>() { + }).to(ServerToMap.class); } @Override diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/BlockDevice.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/BlockDevice.java new file mode 100644 index 0000000000..42ae17cb78 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/BlockDevice.java @@ -0,0 +1,86 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * + * @author Adrian Cole + */ +public class BlockDevice extends Device { + public static class Builder extends Device.Builder { + private final int index; + + public Builder(int index) { + this.index = index; + } + + @Override + public Device build() { + return new BlockDevice(uuid, mediaType, index); + } + + } + + private final int index; + + public BlockDevice(String driveUuid, MediaType mediaType, int index) { + super(driveUuid, mediaType); + checkArgument(index >= 0 && index < 8, "index must be between 0 and 7"); + this.index = index; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + index; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BlockDevice other = (BlockDevice) obj; + if (index != other.index) + return false; + return true; + } + + @Override + public String getId() { + return String.format("block:%d", index); + } + + public int getIndex() { + return index; + } + + @Override + public String toString() { + return "[id=" + getId() + ", driveUuid=" + driveUuid + ", mediaType=" + mediaType + "]"; + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/ClaimType.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/ClaimType.java new file mode 100644 index 0000000000..ccaa572ba1 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/ClaimType.java @@ -0,0 +1,57 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * either 'exclusive' (the default) or 'shared' to allow multiple servers to access a drive + * simultaneously + * + * @author Adrian Cole + */ +public enum ClaimType { + /** + * + */ + EXCLUSIVE, + /** + * allow multiple servers to access a drive simultaneously + */ + SHARED, UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static ClaimType fromValue(String claim) { + try { + return valueOf(checkNotNull(claim, "claim").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/CreateDriveRequest.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/CreateDriveRequest.java new file mode 100644 index 0000000000..4f3987de66 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/CreateDriveRequest.java @@ -0,0 +1,162 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class CreateDriveRequest extends Drive { + public static class Builder extends Drive.Builder { + + private Set avoid = ImmutableSet.of(); + + @Nullable + private String encryptionCipher; + + public Builder avoid(Iterable avoid) { + this.avoid = ImmutableSet.copyOf(checkNotNull(avoid, "avoid")); + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Builder claimType(ClaimType claimType) { + return Builder.class.cast(super.claimType(claimType)); + } + + public Builder encryptionCipher(String encryptionCipher) { + this.encryptionCipher = encryptionCipher; + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder readers(Iterable readers) { + return Builder.class.cast(super.readers(readers)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder size(long size) { + return Builder.class.cast(super.size(size)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder use(Iterable use) { + return Builder.class.cast(super.use(use)); + } + + public CreateDriveRequest build() { + return new CreateDriveRequest(name, size, claimType, readers, use, encryptionCipher, avoid); + } + } + + private final Set avoid; + @Nullable + private final String encryptionCipher; + + public CreateDriveRequest(String name, long size, @Nullable ClaimType claimType, Iterable readers, + Iterable use, @Nullable String encryptionCipher, Iterable avoid) { + super(null, name, size, claimType, readers, use); + this.encryptionCipher = encryptionCipher; + this.avoid = ImmutableSet.copyOf(checkNotNull(avoid, "avoid")); + } + + /** + * + * @return list of existing drives to ensure this new drive is created on physical different + * hardware than those existing drives + */ + public Set getAvoid() { + return avoid; + } + + /** + * + * @return either 'none' or 'aes-xts-plain' (the default) + */ + @Nullable + public String getEncryptionCipher() { + return encryptionCipher; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((avoid == null) ? 0 : avoid.hashCode()); + result = prime * result + ((encryptionCipher == null) ? 0 : encryptionCipher.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + CreateDriveRequest other = (CreateDriveRequest) obj; + if (avoid == null) { + if (other.avoid != null) + return false; + } else if (!avoid.equals(other.avoid)) + return false; + if (encryptionCipher == null) { + if (other.encryptionCipher != null) + return false; + } else if (!encryptionCipher.equals(other.encryptionCipher)) + return false; + return true; + } + + @Override + public String toString() { + return "[name=" + name + ", size=" + size + ", claimType=" + claimType + ", readers=" + readers + ", use=" + use + + ", avoid=" + avoid + ", encryptionCipher=" + encryptionCipher + "]"; + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Device.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Device.java new file mode 100644 index 0000000000..13a45b996b --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Device.java @@ -0,0 +1,108 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * + * @author Adrian Cole + */ +public abstract class Device { + public static abstract class Builder { + protected String uuid; + protected MediaType mediaType = MediaType.DISK; + + public Builder mediaType(MediaType mediaType) { + this.mediaType = mediaType; + return this; + } + + public Builder uuid(String uuid) { + this.uuid = uuid; + return this; + } + + public abstract Device build(); + } + + protected final String driveUuid; + protected final MediaType mediaType; + + public Device(String driveUuid, MediaType mediaType) { + this.driveUuid = checkNotNull(driveUuid, "driveUuid"); + this.mediaType = checkNotNull(mediaType, "mediaType"); + } + + /** + * id generated based on the device bus, unit, and/or index numbers; + */ + public abstract String getId(); + + /** + * + * @return Drive UUID to connect as specified device. + */ + public String getDriveUuid() { + return driveUuid; + } + + /** + * + * @return set to 'cdrom' to simulate a cdrom, set to 'disk' or leave unset to simulate a hard + * disk. + */ + public MediaType getMediaType() { + return mediaType; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((driveUuid == null) ? 0 : driveUuid.hashCode()); + result = prime * result + ((mediaType == null) ? 0 : mediaType.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; + Device other = (Device) obj; + if (driveUuid == null) { + if (other.driveUuid != null) + return false; + } else if (!driveUuid.equals(other.driveUuid)) + return false; + if (mediaType != other.mediaType) + return false; + return true; + } + + @Override + public String toString() { + return "[driveUuid=" + driveUuid + ", mediaType=" + mediaType + "]"; + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Drive.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Drive.java new file mode 100644 index 0000000000..2b19a03fa4 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Drive.java @@ -0,0 +1,203 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class Drive extends Item { + public static class Builder extends Item.Builder { + protected long size; + protected ClaimType claimType = ClaimType.EXCLUSIVE; + protected Set readers = ImmutableSet.of(); + + public Builder claimType(ClaimType claimType) { + this.claimType = claimType; + return this; + } + + public Builder readers(Iterable readers) { + this.readers = ImmutableSet.copyOf(checkNotNull(readers, "readers")); + return this; + } + + public Builder size(long size) { + this.size = size; + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Builder uuid(String uuid) { + return Builder.class.cast(super.uuid(uuid)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder use(Iterable use) { + return Builder.class.cast(super.use(use)); + } + + public Drive build() { + return new Drive(uuid, name, size, claimType, readers, use); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((claimType == null) ? 0 : claimType.hashCode()); + result = prime * result + ((readers == null) ? 0 : readers.hashCode()); + result = prime * result + (int) (size ^ (size >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + Builder other = (Builder) obj; + if (claimType != other.claimType) + return false; + if (readers == null) { + if (other.readers != null) + return false; + } else if (!readers.equals(other.readers)) + return false; + if (size != other.size) + return false; + return true; + } + } + + protected final long size; + protected final ClaimType claimType; + protected final Set readers; + + public Drive(@Nullable String uuid, String name, long size, @Nullable ClaimType claimType, Iterable readers, + Iterable use) { + super(uuid, name, use); + this.size = size; + this.claimType = checkNotNull(claimType, "set claimType to exclusive, not null"); + this.readers = ImmutableSet.copyOf(checkNotNull(readers, "readers")); + } + + /** + * + * @return either 'exclusive' (the default) or 'shared' to allow multiple servers to access a + * drive simultaneously + */ + @Nullable + public ClaimType getClaimType() { + return claimType; + } + + /** + * + * @return list of users allowed to read from a drive or 'ffffffff-ffff-ffff-ffff-ffffffffffff' + * for all users + */ + public Set getReaders() { + return readers; + } + + /** + * + * @return size of drive in bytes + */ + public long getSize() { + return size; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((claimType == null) ? 0 : claimType.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((readers == null) ? 0 : readers.hashCode()); + result = prime * result + (int) (size ^ (size >>> 32)); + result = prime * result + ((use == null) ? 0 : use.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; + Drive other = (Drive) obj; + if (claimType != other.claimType) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (readers == null) { + if (other.readers != null) + return false; + } else if (!readers.equals(other.readers)) + return false; + if (size != other.size) + return false; + if (use == null) { + if (other.use != null) + return false; + } else if (!use.equals(other.use)) + return false; + return true; + } + + @Override + public String toString() { + return "[uuid=" + uuid + ", name=" + name + ", use=" + use + ", size=" + size + ", claimType=" + claimType + + ", readers=" + readers + "]"; + } + +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveData.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveData.java new file mode 100644 index 0000000000..4504f5f4f7 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveData.java @@ -0,0 +1,80 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import javax.annotation.Nullable; + +/** + * + * @author Adrian Cole + */ +public class DriveData extends Drive { + public static class Builder extends Drive.Builder { + + /** + * {@inheritDoc} + */ + @Override + public Builder claimType(ClaimType claimType) { + return Builder.class.cast(super.claimType(claimType)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder readers(Iterable readers) { + return Builder.class.cast(super.readers(readers)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder size(long size) { + return Builder.class.cast(super.size(size)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder use(Iterable use) { + return Builder.class.cast(super.use(use)); + } + + public DriveData build() { + return new DriveData(uuid, name, size, claimType, readers, use); + } + } + + public DriveData(@Nullable String uuid, String name, long size, @Nullable ClaimType claimType, + Iterable readers, Iterable use) { + super(uuid, name, size, claimType, readers, use); + } +} \ No newline at end of file diff --git a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveInfo.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveInfo.java similarity index 61% rename from sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveInfo.java rename to cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveInfo.java index ddec88deac..9792cf65e8 100644 --- a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveInfo.java +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveInfo.java @@ -22,12 +22,9 @@ package org.jclouds.cloudsigma.domain; import static com.google.common.base.Preconditions.checkNotNull; import java.net.URI; -import java.util.Map; import java.util.Set; -import org.jclouds.elasticstack.domain.ClaimType; -import org.jclouds.elasticstack.domain.DriveMetrics; -import org.jclouds.elasticstack.domain.DriveStatus; +import javax.annotation.Nullable; import com.google.common.collect.ImmutableSet; @@ -35,8 +32,17 @@ import com.google.common.collect.ImmutableSet; * * @author Adrian Cole */ -public class DriveInfo extends org.jclouds.elasticstack.domain.DriveInfo { - public static class Builder extends org.jclouds.elasticstack.domain.DriveInfo.Builder { +public class DriveInfo extends Drive { + public static class Builder extends Drive.Builder { + + protected DriveStatus status; + protected String user; + protected Set claimed = ImmutableSet.of(); + @Nullable + protected String encryptionCipher; + @Nullable + protected String imaging; + protected DriveMetrics metrics; private Boolean autoexpanding; private Integer bits; private String description; @@ -48,6 +54,36 @@ public class DriveInfo extends org.jclouds.elasticstack.domain.DriveInfo { private DriveType type; private URI url; + public Builder status(DriveStatus status) { + this.status = status; + return this; + } + + public Builder user(String user) { + this.user = user; + return this; + } + + public Builder claimed(Iterable claimed) { + this.claimed = ImmutableSet.copyOf(checkNotNull(claimed, "claimed")); + return this; + } + + public Builder imaging(String imaging) { + this.imaging = imaging; + return this; + } + + public Builder metrics(DriveMetrics metrics) { + this.metrics = metrics; + return this; + } + + public Builder encryptionCipher(String encryptionCipher) { + this.encryptionCipher = encryptionCipher; + return this; + } + public Builder autoexpanding(Boolean autoexpanding) { this.autoexpanding = autoexpanding; return this; @@ -98,55 +134,6 @@ public class DriveInfo extends org.jclouds.elasticstack.domain.DriveInfo { return this; } - /** - * {@inheritDoc} - */ - @Override - public Builder status(DriveStatus status) { - return Builder.class.cast(super.status(status)); - } - - /** - * {@inheritDoc} - */ - @Override - public Builder user(String user) { - return Builder.class.cast(super.user(user)); - } - - /** - * {@inheritDoc} - */ - @Override - public Builder claimed(Iterable claimed) { - return Builder.class.cast(super.claimed(claimed)); - } - - /** - * {@inheritDoc} - */ - @Override - public Builder imaging(String imaging) { - return Builder.class.cast(super.imaging(imaging)); - } - - /** - * {@inheritDoc} - */ - @Override - public Builder metrics(DriveMetrics metrics) { - return Builder.class.cast(super.metrics(metrics)); - - } - - /** - * {@inheritDoc} - */ - @Override - public Builder encryptionCipher(String encryptionCipher) { - return Builder.class.cast(super.encryptionCipher(encryptionCipher)); - } - /** * {@inheritDoc} */ @@ -191,24 +178,17 @@ public class DriveInfo extends org.jclouds.elasticstack.domain.DriveInfo { * {@inheritDoc} */ @Override - public Builder tags(Iterable tags) { - return Builder.class.cast(super.tags(tags)); + public Builder use(Iterable use) { + return Builder.class.cast(super.use(use)); } - /** - * {@inheritDoc} - */ - @Override - public Builder userMetadata(Map userMetadata) { - return Builder.class.cast(super.userMetadata(userMetadata)); - } - - public static Builder fromDriveInfo(org.jclouds.elasticstack.domain.DriveInfo driveInfo) { - return new Builder().uuid(driveInfo.getUuid()).name(driveInfo.getName()).size(driveInfo.getSize()) - .claimType(driveInfo.getClaimType()).readers(driveInfo.getReaders()).tags(driveInfo.getTags()) - .userMetadata(driveInfo.getUserMetadata()).status(driveInfo.getStatus()).user(driveInfo.getUser()) - .claimed(driveInfo.getClaimed()).encryptionCipher(driveInfo.getEncryptionCipher()) - .imaging(driveInfo.getImaging()).metrics(driveInfo.getMetrics()); + public static Builder fromDriveInfo(DriveInfo in) { + return new Builder().uuid(in.getUuid()).name(in.getName()).size(in.getSize()).claimType(in.getClaimType()) + .readers(in.getReaders()).use(in.getUse()).status(in.getStatus()).user(in.getUser()) + .claimed(in.getClaimed()).encryptionCipher(in.getEncryptionCipher()).imaging(in.getImaging()) + .metrics(in.getMetrics()).autoexpanding(in.getAutoexpanding()).bits(in.getBits()) + .description(in.getDescription()).encryptionKey(in.getEncryptionKey()).free(in.getFree()) + .installNotes(in.getInstallNotes()).type(in.getType()).url(in.getUrl()); } /** @@ -216,12 +196,21 @@ public class DriveInfo extends org.jclouds.elasticstack.domain.DriveInfo { */ @Override public DriveInfo build() { - return new DriveInfo(uuid, name, size, claimType, readers, tags, userMetadata, status, user, claimed, - encryptionCipher, imaging, metrics, autoexpanding, bits, description, driveType, encryptionKey, free, - installNotes, os, type, url); + return new DriveInfo(uuid, name, size, claimType, readers, use, status, user, claimed, encryptionCipher, + imaging, metrics, autoexpanding, bits, description, driveType, encryptionKey, free, installNotes, os, + type, url); } + } + protected final DriveStatus status; + protected final String user; + protected final Set claimed; + @Nullable + protected final String encryptionCipher; + @Nullable + protected final String imaging; + protected final DriveMetrics metrics; private final Boolean autoexpanding; private final Integer bits; private final String description; @@ -234,12 +223,17 @@ public class DriveInfo extends org.jclouds.elasticstack.domain.DriveInfo { private final URI url; public DriveInfo(String uuid, String name, long size, ClaimType claimType, Iterable readers, - Iterable tags, Map userMetadata, DriveStatus status, String user, Set claimed, - String encryptionCipher, String imaging, DriveMetrics metrics, Boolean autoexpanding, Integer bits, - String description, Iterable driveType, String encryptionKey, Boolean free, String installNotes, - String os, DriveType type, URI url) { - super(uuid, name, size, claimType, readers, tags, userMetadata, status, user, claimed, encryptionCipher, imaging, - metrics); + Iterable use, DriveStatus status, String user, Set claimed, String encryptionCipher, + String imaging, DriveMetrics metrics, Boolean autoexpanding, Integer bits, String description, + Iterable driveType, String encryptionKey, Boolean free, String installNotes, String os, + DriveType type, URI url) { + super(uuid, name, size, claimType, readers, use); + this.status = status; + this.user = user; + this.claimed = ImmutableSet.copyOf(checkNotNull(claimed, "claimed")); + this.encryptionCipher = encryptionCipher; + this.imaging = imaging; + this.metrics = checkNotNull(metrics, "metrics"); this.autoexpanding = autoexpanding; this.bits = bits; this.description = description; @@ -252,80 +246,54 @@ public class DriveInfo extends org.jclouds.elasticstack.domain.DriveInfo { this.url = url; } - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((autoexpanding == null) ? 0 : autoexpanding.hashCode()); - result = prime * result + ((bits == null) ? 0 : bits.hashCode()); - result = prime * result + ((description == null) ? 0 : description.hashCode()); - result = prime * result + ((driveType == null) ? 0 : driveType.hashCode()); - result = prime * result + ((encryptionKey == null) ? 0 : encryptionKey.hashCode()); - result = prime * result + ((free == null) ? 0 : free.hashCode()); - result = prime * result + ((installNotes == null) ? 0 : installNotes.hashCode()); - result = prime * result + ((os == null) ? 0 : os.hashCode()); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + ((url == null) ? 0 : url.hashCode()); - return result; + /** + * + * @return current status of the drive + */ + public DriveStatus getStatus() { + return status; } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - DriveInfo other = (DriveInfo) obj; - if (autoexpanding == null) { - if (other.autoexpanding != null) - return false; - } else if (!autoexpanding.equals(other.autoexpanding)) - return false; - if (bits == null) { - if (other.bits != null) - return false; - } else if (!bits.equals(other.bits)) - return false; - if (description == null) { - if (other.description != null) - return false; - } else if (!description.equals(other.description)) - return false; - if (driveType == null) { - if (other.driveType != null) - return false; - } else if (!driveType.equals(other.driveType)) - return false; - if (encryptionKey == null) { - if (other.encryptionKey != null) - return false; - } else if (!encryptionKey.equals(other.encryptionKey)) - return false; - if (free == null) { - if (other.free != null) - return false; - } else if (!free.equals(other.free)) - return false; - if (installNotes == null) { - if (other.installNotes != null) - return false; - } else if (!installNotes.equals(other.installNotes)) - return false; - if (os == null) { - if (other.os != null) - return false; - } else if (!os.equals(other.os)) - return false; - if (type != other.type) - return false; - if (url == null) { - if (other.url != null) - return false; - } else if (!url.equals(other.url)) - return false; - return true; + /** + * + * @return owner of the drive + */ + public String getUser() { + return user; + } + + /** + * + * @return if drive is in use by a server, values are the server uuids + */ + public Set getClaimed() { + return claimed; + } + + /** + * + * @return either 'none' or 'aes-xts-plain' (the default) + */ + @Nullable + public String getEncryptionCipher() { + return encryptionCipher; + } + + /** + * + * @return percentage completed of drive imaging if this is underway, or 'queued' if waiting for + * another imaging operation to complete first + */ + public String getImaging() { + return imaging; + } + + /** + * + * @return i/o and request metrics for read and write ops + */ + public DriveMetrics getMetrics() { + return metrics; } // TODO @@ -373,19 +341,124 @@ public class DriveInfo extends org.jclouds.elasticstack.domain.DriveInfo { return type; } - // TODO - - @Override - public String toString() { - return "[size=" + size + ", claimType=" + claimType + ", readers=" + readers + ", uuid=" + uuid + ", name=" - + name + ", tags=" + tags + ", userMetadata=" + userMetadata + ", autoexpanding=" + autoexpanding - + ", bits=" + bits + ", description=" + description + ", driveType=" + driveType + ", encryptionKey=" - + encryptionKey + ", free=" + free + ", installNotes=" + installNotes + ", os=" + os + ", type=" + type - + ", url=" + url + "]"; - } - public URI getUrl() { return url; } + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((autoexpanding == null) ? 0 : autoexpanding.hashCode()); + result = prime * result + ((bits == null) ? 0 : bits.hashCode()); + result = prime * result + ((claimed == null) ? 0 : claimed.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((driveType == null) ? 0 : driveType.hashCode()); + result = prime * result + ((encryptionCipher == null) ? 0 : encryptionCipher.hashCode()); + result = prime * result + ((encryptionKey == null) ? 0 : encryptionKey.hashCode()); + result = prime * result + ((free == null) ? 0 : free.hashCode()); + result = prime * result + ((imaging == null) ? 0 : imaging.hashCode()); + result = prime * result + ((installNotes == null) ? 0 : installNotes.hashCode()); + result = prime * result + ((metrics == null) ? 0 : metrics.hashCode()); + result = prime * result + ((os == null) ? 0 : os.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + ((url == null) ? 0 : url.hashCode()); + result = prime * result + ((user == null) ? 0 : user.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + DriveInfo other = (DriveInfo) obj; + if (autoexpanding == null) { + if (other.autoexpanding != null) + return false; + } else if (!autoexpanding.equals(other.autoexpanding)) + return false; + if (bits == null) { + if (other.bits != null) + return false; + } else if (!bits.equals(other.bits)) + return false; + if (claimed == null) { + if (other.claimed != null) + return false; + } else if (!claimed.equals(other.claimed)) + return false; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (driveType == null) { + if (other.driveType != null) + return false; + } else if (!driveType.equals(other.driveType)) + return false; + if (encryptionCipher == null) { + if (other.encryptionCipher != null) + return false; + } else if (!encryptionCipher.equals(other.encryptionCipher)) + return false; + if (encryptionKey == null) { + if (other.encryptionKey != null) + return false; + } else if (!encryptionKey.equals(other.encryptionKey)) + return false; + if (free == null) { + if (other.free != null) + return false; + } else if (!free.equals(other.free)) + return false; + if (imaging == null) { + if (other.imaging != null) + return false; + } else if (!imaging.equals(other.imaging)) + return false; + if (installNotes == null) { + if (other.installNotes != null) + return false; + } else if (!installNotes.equals(other.installNotes)) + return false; + if (metrics == null) { + if (other.metrics != null) + return false; + } else if (!metrics.equals(other.metrics)) + return false; + if (os == null) { + if (other.os != null) + return false; + } else if (!os.equals(other.os)) + return false; + if (status != other.status) + return false; + if (type != other.type) + return false; + if (url == null) { + if (other.url != null) + return false; + } else if (!url.equals(other.url)) + return false; + if (user == null) { + if (other.user != null) + return false; + } else if (!user.equals(other.user)) + return false; + return true; + } + + @Override + public String toString() { + return "[size=" + size + ", claimType=" + claimType + ", readers=" + readers + ", uuid=" + uuid + ", name=" + + name + ", use=" + use + ", status=" + status + ", user=" + user + ", claimed=" + claimed + + ", encryptionCipher=" + encryptionCipher + ", imaging=" + imaging + ", metrics=" + metrics + "]"; + } + } \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveMetrics.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveMetrics.java new file mode 100644 index 0000000000..f3f69eda6f --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveMetrics.java @@ -0,0 +1,139 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + + +/** + * + * @author Adrian Cole + */ +public class DriveMetrics { + public static class Builder { + protected long readBytes; + protected long readRequests; + protected long writeBytes; + protected long writeRequests; + + public Builder readBytes(long readBytes) { + this.readBytes = readBytes; + return this; + } + + public Builder readRequests(long readRequests) { + this.readRequests = readRequests; + return this; + } + + public Builder writeBytes(long writeBytes) { + this.writeBytes = writeBytes; + return this; + } + + public Builder writeRequests(long writeRequests) { + this.writeRequests = writeRequests; + return this; + } + + public DriveMetrics build() { + return new DriveMetrics(readBytes, readRequests, writeBytes, writeRequests); + } + } + + protected final long readBytes; + protected final long readRequests; + protected final long writeBytes; + protected final long writeRequests; + + public DriveMetrics(long readBytes, long readRequests, long writeBytes, long writeRequests) { + this.readBytes = readBytes; + this.readRequests = readRequests; + this.writeBytes = writeBytes; + this.writeRequests = writeRequests; + } + + /** + * + * @return Cumulative i/o byte/request count for each drive + */ + public long getReadBytes() { + return readBytes; + } + + /** + * + * @return Cumulative i/o byte/request count for each drive + */ + public long getReadRequests() { + return readRequests; + } + + /** + * + * @return Cumulative i/o byte/request count for each drive + */ + public long getWriteBytes() { + return writeBytes; + } + + /** + * + * @return Cumulative i/o byte/request count for each drive + */ + public long getWriteRequests() { + return writeRequests; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (int) (readBytes ^ (readBytes >>> 32)); + result = prime * result + (int) (readRequests ^ (readRequests >>> 32)); + result = prime * result + (int) (writeBytes ^ (writeBytes >>> 32)); + result = prime * result + (int) (writeRequests ^ (writeRequests >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DriveMetrics other = (DriveMetrics) obj; + if (readBytes != other.readBytes) + return false; + if (readRequests != other.readRequests) + return false; + if (writeBytes != other.writeBytes) + return false; + if (writeRequests != other.writeRequests) + return false; + return true; + } + + @Override + public String toString() { + return "[readBytes=" + readBytes + ", readRequests=" + readRequests + ", writeBytes=" + writeBytes + + ", writeRequests=" + writeRequests + "]"; + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveStatus.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveStatus.java new file mode 100644 index 0000000000..20b47fe597 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveStatus.java @@ -0,0 +1,48 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * + * @author Adrian Cole + */ +public enum DriveStatus { + ACTIVE, INACTIVE, COPYING, IMAGING, UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static DriveStatus fromValue(String status) { + try { + return valueOf(checkNotNull(status, "status").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} \ No newline at end of file diff --git a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveType.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveType.java similarity index 100% rename from sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveType.java rename to cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/DriveType.java diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/IDEDevice.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/IDEDevice.java new file mode 100644 index 0000000000..8dc328a3ea --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/IDEDevice.java @@ -0,0 +1,98 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * + * @author Adrian Cole + */ +public class IDEDevice extends Device { + public static class Builder extends Device.Builder { + private final int bus; + private final int unit; + + public Builder(int bus, int unit) { + this.bus = bus; + this.unit = unit; + } + + @Override + public Device build() { + return new IDEDevice(uuid, mediaType, bus, unit); + } + + } + + private final int bus; + private final int unit; + + public IDEDevice(String driveUuid, MediaType mediaType, int bus, int unit) { + super(driveUuid, mediaType); + checkArgument(bus == 0 || bus == 1, "bus must be 0 or 1"); + checkArgument(unit == 0 || unit == 1, "unit must be 0 or 1"); + this.bus = bus; + this.unit = unit; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + bus; + result = prime * result + unit; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + IDEDevice other = (IDEDevice) obj; + if (bus != other.bus) + return false; + if (unit != other.unit) + return false; + return true; + } + + @Override + public String getId() { + return String.format("ide:%d:%d", bus, unit); + } + + public int getBus() { + return bus; + } + + public int getUnit() { + return unit; + } + + @Override + public String toString() { + return "[id=" + getId() + ", driveUuid=" + driveUuid + ", mediaType=" + mediaType + "]"; + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Item.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Item.java new file mode 100644 index 0000000000..ead2748e01 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Item.java @@ -0,0 +1,170 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class Item { + public static class Builder { + protected String uuid; + protected String name; + protected Set use = ImmutableSet.of(); + + public Builder uuid(String uuid) { + this.uuid = uuid; + return this; + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder use(Iterable use) { + this.use = ImmutableSet.copyOf(checkNotNull(use, "use")); + return this; + } + + public Item build() { + return new Item(uuid, name, use); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((use == null) ? 0 : use.hashCode()); + result = prime * result + ((uuid == null) ? 0 : uuid.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; + Builder other = (Builder) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (use == null) { + if (other.use != null) + return false; + } else if (!use.equals(other.use)) + return false; + if (uuid == null) { + if (other.uuid != null) + return false; + } else if (!uuid.equals(other.uuid)) + return false; + return true; + } + } + + @Nullable + protected final String uuid; + protected final String name; + protected final Set use; + + public Item(@Nullable String uuid, String name, Iterable use) { + this.uuid = uuid; + this.name = checkNotNull(name, "name"); + this.use = ImmutableSet.copyOf(checkNotNull(use, "use")); + } + + /** + * + * @return uuid of the item. + */ + @Nullable + public String getUuid() { + return uuid; + } + + /** + * + * @return name of the item + */ + public String getName() { + return name; + } + + /** + * + * @return list of use + */ + public Set getUse() { + return use; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((use == null) ? 0 : use.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; + Item other = (Item) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (use == null) { + if (other.use != null) + return false; + } else if (!use.equals(other.use)) + return false; + + return true; + } + + @Override + public String toString() { + return "[uuid=" + uuid + ", name=" + name + ", use=" + use + "]"; + } + +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/MediaType.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/MediaType.java new file mode 100644 index 0000000000..4fd67bb459 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/MediaType.java @@ -0,0 +1,50 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Media type - set to 'cdrom' to simulate a cdrom, set to 'disk' or leave unset to simulate a hard + * disk. + * + * @author Adrian Cole + */ +public enum MediaType { + DISK, CDROM, UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static MediaType fromValue(String type) { + try { + return valueOf(checkNotNull(type, "type").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Model.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Model.java new file mode 100644 index 0000000000..cbec34277b --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Model.java @@ -0,0 +1,47 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * + * @author Adrian Cole + */ +public enum Model { + E1000, RTl8139, VIRTIO, UNRECOGNIZED; + + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static Model fromValue(String model) { + try { + return valueOf(checkNotNull(model, "model").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/NIC.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/NIC.java new file mode 100644 index 0000000000..f19f3d3259 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/NIC.java @@ -0,0 +1,177 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class NIC { + public static class Builder { + private String dhcp; + private Model model; + private String vlan; + private String mac; + // TODO cloudsigma specific + private Set block = ImmutableSet.of(); + + public Builder dhcp(String dhcp) { + this.dhcp = dhcp; + return this; + } + + public Builder model(Model model) { + this.model = model; + return this; + } + + public Builder vlan(String vlan) { + this.vlan = vlan; + return this; + } + + public Builder mac(String mac) { + this.mac = mac; + return this; + } + + public Builder block(Iterable block) { + this.block = ImmutableSet.copyOf(checkNotNull(block, "block")); + return this; + } + + public NIC build() { + return new NIC(dhcp, model, vlan, mac, block); + } + } + + private final String dhcp; + private final Model model; + private final String vlan; + private final String mac; + private final Set block; + + public NIC(@Nullable String dhcp, Model model, @Nullable String vlan, @Nullable String mac, Iterable block) { + this.dhcp = dhcp; + this.model = checkNotNull(model, "model"); + this.vlan = vlan; + this.mac = mac; + this.block = ImmutableSet.copyOf(checkNotNull(block, "block")); + } + + /** + * + * @return The IP address offered by DHCP to network interface 0. If unset, no address is + * offered. Set to 'auto' to allocate a temporary IP at boot. + */ + public String getDhcp() { + return dhcp; + } + + /** + * + * @return Create network interface with given type (use 'e1000' as default value; 'rtl8139' or + * 'virtio' are also available). + */ + public Model getModel() { + return model; + } + + /** + * + * @return The VLAN to which the network interface is attached. + */ + public String getVlan() { + return vlan; + } + + /** + * + * @return The MAC address of the network interface. If unset, a randomly generated address is + * used. If set, should be unique on the VLAN. + */ + public String getMac() { + return mac; + } + + // TODO undocumented + public Set getBlock() { + return block; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((block == null) ? 0 : block.hashCode()); + result = prime * result + ((dhcp == null) ? 0 : dhcp.hashCode()); + result = prime * result + ((mac == null) ? 0 : mac.hashCode()); + result = prime * result + ((model == null) ? 0 : model.hashCode()); + result = prime * result + ((vlan == null) ? 0 : vlan.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; + NIC other = (NIC) obj; + if (block == null) { + if (other.block != null) + return false; + } else if (!block.equals(other.block)) + return false; + if (dhcp == null) { + if (other.dhcp != null) + return false; + } else if (!dhcp.equals(other.dhcp)) + return false; + if (mac == null) { + if (other.mac != null) + return false; + } else if (!mac.equals(other.mac)) + return false; + if (model != other.model) + return false; + if (vlan == null) { + if (other.vlan != null) + return false; + } else if (!vlan.equals(other.vlan)) + return false; + return true; + } + + @Override + public String toString() { + return "[dhcp=" + dhcp + ", model=" + model + ", vlan=" + vlan + ", mac=" + mac + ", block=" + block + "]"; + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/SCSIDevice.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/SCSIDevice.java new file mode 100644 index 0000000000..aad202cc56 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/SCSIDevice.java @@ -0,0 +1,94 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * + * @author Adrian Cole + */ +public class SCSIDevice extends Device { + public static class Builder extends Device.Builder { + private final int unit; + + public Builder(int unit) { + this.unit = unit; + } + + @Override + public Device build() { + return new SCSIDevice(uuid, mediaType, unit); + } + + } + + private final int bus = 0; + private final int unit; + + public SCSIDevice(String driveUuid, MediaType mediaType, int unit) { + super(driveUuid, mediaType); + checkArgument(unit >= 0 && unit < 8, "unit must be between 0 and 7"); + this.unit = unit; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + bus; + result = prime * result + unit; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SCSIDevice other = (SCSIDevice) obj; + if (bus != other.bus) + return false; + if (unit != other.unit) + return false; + return true; + } + + public int getBus() { + return bus; + } + + public int getUnit() { + return unit; + } + + @Override + public String getId() { + return String.format("scsi:%d:%d", bus, unit); + } + + @Override + public String toString() { + return "[id=" + getId() + ", driveUuid=" + driveUuid + ", mediaType=" + mediaType + "]"; + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Server.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Server.java new file mode 100644 index 0000000000..87e026f00c --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/Server.java @@ -0,0 +1,293 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class Server extends Item { + + public static class Builder extends Item.Builder { + protected int cpu; + protected Integer smp; + protected int mem; + protected boolean persistent; + protected Map devices = ImmutableMap.of(); + protected Set bootDeviceIds = ImmutableSet.of(); + protected List nics = ImmutableList.of(); + protected VNC vnc; + // TODO cloudsigma specific + protected String description; + + public Builder cpu(int cpu) { + this.cpu = cpu; + return this; + } + + public Builder smp(Integer smp) { + this.smp = smp; + return this; + } + + public Builder mem(int mem) { + this.mem = mem; + return this; + } + + public Builder persistent(boolean persistent) { + this.persistent = persistent; + return this; + } + + public Builder devices(Map devices) { + this.devices = ImmutableMap.copyOf(checkNotNull(devices, "devices")); + return this; + } + + public Builder bootDeviceIds(Iterable bootDeviceIds) { + this.bootDeviceIds = ImmutableSet.copyOf(checkNotNull(bootDeviceIds, "bootDeviceIds")); + return this; + } + + public Builder nics(Iterable nics) { + this.nics = ImmutableList.copyOf(checkNotNull(nics, "nics")); + return this; + } + + public Builder vnc(VNC vnc) { + this.vnc = vnc; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Builder uuid(String uuid) { + return Builder.class.cast(super.uuid(uuid)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder use(Iterable use) { + return Builder.class.cast(super.use(use)); + } + + public Server build() { + return new Server(uuid, name, cpu, smp, mem, persistent, devices, bootDeviceIds, use, nics, vnc, description); + } + + public static Builder fromServer(Server in) { + return new Builder().uuid(in.getUuid()).name(in.getName()).cpu(in.getCpu()).mem(in.getMem()) + .persistent(in.isPersistent()).description(in.getDescription()).devices(in.getDevices()) + .bootDeviceIds(in.getBootDeviceIds()).use(in.getUse()).nics(in.getNics()).vnc(in.getVnc()); + } + } + + protected final int cpu; + protected final Integer smp; + protected final int mem; + protected final boolean persistent; + @Nullable + protected final Map devices; + protected final Set bootDeviceIds; + protected final List nics; + protected final VNC vnc; + @Nullable + private final String description; + + public Server(@Nullable String uuid, String name, int cpu, @Nullable Integer smp, int mem, boolean persistent, + Map devices, Iterable bootDeviceIds, Iterable use, + Iterable nics, VNC vnc, String description) { + super(uuid, name, use); + this.cpu = cpu; + this.smp = smp; + this.mem = mem; + this.persistent = persistent; + this.devices = ImmutableMap.copyOf(checkNotNull(devices, "devices")); + this.bootDeviceIds = ImmutableSet.copyOf(checkNotNull(bootDeviceIds, "bootDeviceIds")); + this.nics = ImmutableList.copyOf(checkNotNull(nics, "nics")); + this.vnc = checkNotNull(vnc, "vnc"); + this.description = description; + } + + /** + * + * @return CPU quota in core MHz. + */ + public int getCpu() { + return cpu; + } + + /** + * + * @return number of virtual processors or null if calculated based on cpu. + */ + public Integer getSmp() { + return smp; + } + + /** + * + * @return virtual memory size in MB. + */ + public int getMem() { + return mem; + } + + /** + * + * @return 'true' means that server will revert to a 'stopped' status on server stop or shutdown, + * rather than being destroyed automatically. + */ + public boolean isPersistent() { + return persistent; + } + + /** + * + * @return devices present, mapped by id + */ + public Map getDevices() { + return devices; + } + + /** + * + * @return ids of the devices to boot, e.g. ide:0:0 or ide:1:0 + * @see Device#getId() + */ + public Set getBootDeviceIds() { + return bootDeviceIds; + } + + public List getNics() { + return nics; + } + + public VNC getVnc() { + return vnc; + } + + // TODO undocumented + public String getDescription() { + return description; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((bootDeviceIds == null) ? 0 : bootDeviceIds.hashCode()); + result = prime * result + cpu; + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((devices == null) ? 0 : devices.hashCode()); + result = prime * result + mem; + result = prime * result + ((nics == null) ? 0 : nics.hashCode()); + result = prime * result + (persistent ? 1231 : 1237); + result = prime * result + ((smp == null) ? 0 : smp.hashCode()); + result = prime * result + ((vnc == null) ? 0 : vnc.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + Server other = (Server) obj; + if (bootDeviceIds == null) { + if (other.bootDeviceIds != null) + return false; + } else if (!bootDeviceIds.equals(other.bootDeviceIds)) + return false; + if (cpu != other.cpu) + return false; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (devices == null) { + if (other.devices != null) + return false; + } else if (!devices.equals(other.devices)) + return false; + if (mem != other.mem) + return false; + if (nics == null) { + if (other.nics != null) + return false; + } else if (!nics.equals(other.nics)) + return false; + if (persistent != other.persistent) + return false; + if (smp == null) { + if (other.smp != null) + return false; + } else if (!smp.equals(other.smp)) + return false; + if (vnc == null) { + if (other.vnc != null) + return false; + } else if (!vnc.equals(other.vnc)) + return false; + return true; + } + + @Override + public String toString() { + return "[uuid=" + uuid + ", name=" + name + ", use=" + use + ", cpu=" + cpu + ", smp=" + smp + ", mem=" + mem + + ", persistent=" + persistent + ", devices=" + devices + ", bootDeviceIds=" + bootDeviceIds + ", nics=" + + nics + ", vnc=" + vnc + ", description=" + description + "]"; + } + +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/ServerInfo.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/ServerInfo.java new file mode 100644 index 0000000000..1fcc31f422 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/ServerInfo.java @@ -0,0 +1,258 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import java.util.Date; +import java.util.Map; + +import javax.annotation.Nullable; + +/** + * + * @author Adrian Cole + */ +public class ServerInfo extends Server { + + public static class Builder extends Server.Builder { + protected ServerStatus status; + protected Date started; + protected String user; + protected ServerMetrics metrics; + + public Builder status(ServerStatus status) { + this.status = status; + return this; + } + + public Builder started(Date started) { + this.started = started; + return this; + } + + public Builder user(String user) { + this.user = user; + return this; + } + + public Builder metrics(ServerMetrics metrics) { + this.metrics = metrics; + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Builder cpu(int cpu) { + return Builder.class.cast(super.cpu(cpu)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder smp(Integer smp) { + return Builder.class.cast(super.smp(smp)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder mem(int mem) { + return Builder.class.cast(super.mem(mem)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder persistent(boolean persistent) { + return Builder.class.cast(super.persistent(persistent)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder devices(Map devices) { + return Builder.class.cast(super.devices(devices)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder bootDeviceIds(Iterable bootDeviceIds) { + return Builder.class.cast(super.bootDeviceIds(bootDeviceIds)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder nics(Iterable nics) { + return Builder.class.cast(super.nics(nics)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder vnc(VNC vnc) { + return Builder.class.cast(super.vnc(vnc)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder description(String description) { + return Builder.class.cast(super.description(description)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder uuid(String uuid) { + return Builder.class.cast(super.uuid(uuid)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder use(Iterable use) { + return Builder.class.cast(super.use(use)); + } + + public ServerInfo build() { + return new ServerInfo(uuid, name, cpu, smp, mem, persistent, devices, bootDeviceIds, use, nics, vnc, + description, status, started, user, metrics); + } + } + + protected final ServerStatus status; + @Nullable + protected final Date started; + @Nullable + protected final String user; + protected final ServerMetrics metrics; + + public ServerInfo(String uuid, String name, int cpu, Integer smp, int mem, boolean persistent, + Map devices, Iterable bootDeviceIds, Iterable use, + Iterable nics, VNC vnc, String description, ServerStatus status, Date started, String user, + @Nullable ServerMetrics metrics) { + super(uuid, name, cpu, smp, mem, persistent, devices, bootDeviceIds, use, nics, vnc, description); + this.status = status; + this.started = started; + this.user = user; + this.metrics = metrics; + } + + /** + * + * @return active | stopped | paused | dumped | dead + */ + public ServerStatus getStatus() { + return status; + } + + // TODO undocumented + public Date getStarted() { + return started; + } + + /** + * + * @return metrics, if the server is running, or null + */ + @Nullable + public ServerMetrics getMetrics() { + return metrics; + } + + // TODO undocumented + /** + * + * @return owner of the server. + */ + public String getUser() { + return user; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((metrics == null) ? 0 : metrics.hashCode()); + result = prime * result + ((started == null) ? 0 : started.hashCode()); + result = prime * result + ((status == null) ? 0 : status.hashCode()); + result = prime * result + ((user == null) ? 0 : user.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + ServerInfo other = (ServerInfo) obj; + if (metrics == null) { + if (other.metrics != null) + return false; + } else if (!metrics.equals(other.metrics)) + return false; + if (started == null) { + if (other.started != null) + return false; + } else if (!started.equals(other.started)) + return false; + if (status != other.status) + return false; + if (user == null) { + if (other.user != null) + return false; + } else if (!user.equals(other.user)) + return false; + return true; + } + + @Override + public String toString() { + return "[cpu=" + cpu + ", smp=" + smp + ", mem=" + mem + ", persistent=" + persistent + ", devices=" + devices + + ", bootDeviceIds=" + bootDeviceIds + ", nics=" + nics + ", vnc=" + vnc + ", uuid=" + uuid + ", name=" + + name + ", use=" + use + ", status=" + status + ", started=" + started + ", user=" + user + ", metrics=" + + metrics + "]"; + } + +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/ServerMetrics.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/ServerMetrics.java new file mode 100644 index 0000000000..8826bfe0af --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/ServerMetrics.java @@ -0,0 +1,156 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; + +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + */ +public class ServerMetrics { + + public static class Builder { + protected long txPackets; + protected long tx; + protected long rxPackets; + protected long rx; + protected Map driveMetrics = ImmutableMap. of(); + + public Builder txPackets(long txPackets) { + this.txPackets = txPackets; + return this; + } + + public Builder tx(long tx) { + this.tx = tx; + return this; + } + + public Builder rxPackets(long rxPackets) { + this.rxPackets = rxPackets; + return this; + } + + public Builder rx(long rx) { + this.rx = rx; + return this; + } + + public Builder driveMetrics(Map driveMetrics) { + this.driveMetrics = ImmutableMap.copyOf(checkNotNull(driveMetrics, "driveMetrics")); + return this; + } + + public ServerMetrics build() { + return new ServerMetrics(tx, txPackets, rx, rxPackets, driveMetrics); + } + } + + protected final long txPackets; + protected final long tx; + protected final long rxPackets; + protected final long rx; + protected final Map driveMetrics; + + public ServerMetrics(long tx, long txPackets, long rx, long rxPackets, Map driveMetrics) { + this.txPackets = txPackets; + this.tx = tx; + this.rxPackets = rxPackets; + this.rx = rx; + this.driveMetrics = ImmutableMap.copyOf(checkNotNull(driveMetrics, "driveMetrics")); + } + + // TODO undocumented + public long getTxPackets() { + return txPackets; + } + + // TODO undocumented + public long getTx() { + return tx; + } + + // TODO undocumented + public long getRxPackets() { + return rxPackets; + } + + // TODO undocumented + public long getRx() { + return rx; + } + + /** + * + * @return metrics keyed on device id ex. {@code ide:0:0} + */ + public Map getDriveMetrics() { + return driveMetrics; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((driveMetrics == null) ? 0 : driveMetrics.hashCode()); + result = prime * result + (int) (rx ^ (rx >>> 32)); + result = prime * result + (int) (rxPackets ^ (rxPackets >>> 32)); + result = prime * result + (int) (tx ^ (tx >>> 32)); + result = prime * result + (int) (txPackets ^ (txPackets >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ServerMetrics other = (ServerMetrics) obj; + if (driveMetrics == null) { + if (other.driveMetrics != null) + return false; + } else if (!driveMetrics.equals(other.driveMetrics)) + return false; + if (rx != other.rx) + return false; + if (rxPackets != other.rxPackets) + return false; + if (tx != other.tx) + return false; + if (txPackets != other.txPackets) + return false; + return true; + } + + @Override + public String toString() { + return "[ txPackets=" + txPackets + ", tx=" + tx + ", rxPackets=" + rxPackets + ", rx=" + rx + ", driveMetrics=" + + driveMetrics + "]"; + } + +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/ServerStatus.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/ServerStatus.java new file mode 100644 index 0000000000..443b889d6c --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/ServerStatus.java @@ -0,0 +1,47 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * + * @author Adrian Cole + */ +public enum ServerStatus { + ACTIVE, STOPPED, PAUSED, DUMPED, DEAD, UNRECOGNIZED; + public String value() { + return name().toLowerCase(); + } + + @Override + public String toString() { + return value(); + } + + public static ServerStatus fromValue(String status) { + try { + return valueOf(checkNotNull(status, "status").toUpperCase()); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } + +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/VNC.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/VNC.java new file mode 100644 index 0000000000..8bfc818928 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/domain/VNC.java @@ -0,0 +1,105 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.domain; + +import javax.annotation.Nullable; + +/** + * + * @author Adrian Cole + */ +public class VNC { + @Nullable + private final String ip; + @Nullable + private final String password; + private final boolean tls; + + public VNC(String ip, String password, boolean tls) { + this.ip = ip; + this.password = password; + this.tls = tls; + } + + /** + * + * @return IP address for overlay VNC access on port 5900. Set to 'auto', to reuse nic:0:dhcp if + * available, or otherwise allocate a temporary IP at boot. + */ + public String getIp() { + return ip; + } + + /** + * + * @return Password for VNC access. If unset, VNC is disabled. + */ + public String getPassword() { + return password; + } + + /** + * + * @return Set to 'on' to require VeNCrypt-style TLS auth in addition to the password. If this is + * unset, only unencrypted VNC is available. + */ + public boolean isTls() { + return tls; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((ip == null) ? 0 : ip.hashCode()); + result = prime * result + ((password == null) ? 0 : password.hashCode()); + result = prime * result + (tls ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + VNC other = (VNC) obj; + if (ip == null) { + if (other.ip != null) + return false; + } else if (!ip.equals(other.ip)) + return false; + if (password == null) { + if (other.password != null) + return false; + } else if (!password.equals(other.password)) + return false; + if (tls != other.tls) + return false; + return true; + } + + @Override + public String toString() { + return "[ip=" + ip + ", password=" + password + ", tls=" + tls + "]"; + } +} \ No newline at end of file diff --git a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/CreateDriveRequestToMap.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/BaseDriveToMap.java similarity index 53% rename from sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/CreateDriveRequestToMap.java rename to cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/BaseDriveToMap.java index 91564eac6c..87557a5ba1 100644 --- a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/CreateDriveRequestToMap.java +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/BaseDriveToMap.java @@ -19,40 +19,37 @@ package org.jclouds.cloudsigma.functions; -import static org.jclouds.util.Utils.renameKey; +import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; -import javax.inject.Inject; import javax.inject.Singleton; -import org.jclouds.elasticstack.domain.Drive; +import org.jclouds.cloudsigma.domain.ClaimType; +import org.jclouds.cloudsigma.domain.Drive; import com.google.common.base.Function; -import com.google.common.collect.Maps; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableMap; /** * * @author Adrian Cole */ @Singleton -public class CreateDriveRequestToMap implements Function> { - private final org.jclouds.elasticstack.functions.CreateDriveRequestToMap baseDriveToMap; - - @Inject - public CreateDriveRequestToMap(org.jclouds.elasticstack.functions.CreateDriveRequestToMap baseDriveToMap) { - this.baseDriveToMap = baseDriveToMap; - } - +public class BaseDriveToMap implements Function> { @Override public Map apply(Drive from) { - return Maps.transformEntries(renameKey(baseDriveToMap.apply(from), "tags", "use"), - new Maps.EntryTransformer() { - - @Override - public String transformEntry(String arg0, String arg1) { - return "use".equals(arg0) ? arg1.replace(' ', ',') : arg1; - } - - }); } + checkNotNull(from, "drive"); + ImmutableMap.Builder builder = ImmutableMap.builder(); + builder.put("name", from.getName()); + builder.put("size", from.getSize() + ""); + if (from.getClaimType() != ClaimType.EXCLUSIVE) + builder.put("claim:type", from.getClaimType().toString()); + if (from.getReaders().size() != 0) + builder.put("readers", Joiner.on(' ').join(from.getReaders())); + if (from.getUse().size() != 0) + builder.put("use", Joiner.on(' ').join(from.getUse())); + return builder.build(); + } } \ No newline at end of file diff --git a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/DriveDataToMap.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/DriveDataToMap.java similarity index 66% rename from sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/DriveDataToMap.java rename to cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/DriveDataToMap.java index 715098e6b8..f3ae1ae6c5 100644 --- a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/DriveDataToMap.java +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/DriveDataToMap.java @@ -26,10 +26,9 @@ import java.util.Map; import javax.inject.Inject; import javax.inject.Singleton; -import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.cloudsigma.domain.DriveData; import com.google.common.base.Function; -import com.google.common.collect.Maps; /** * @@ -37,23 +36,15 @@ import com.google.common.collect.Maps; */ @Singleton public class DriveDataToMap implements Function> { - private final org.jclouds.elasticstack.functions.DriveDataToMap baseDriveToMap; + private final BaseDriveToMap baseDriveToMap; @Inject - public DriveDataToMap(org.jclouds.elasticstack.functions.DriveDataToMap baseDriveToMap) { + public DriveDataToMap(BaseDriveToMap baseDriveToMap) { this.baseDriveToMap = baseDriveToMap; } @Override public Map apply(DriveData from) { - return Maps.transformEntries(renameKey(baseDriveToMap.apply(from), "tags", "use"), - new Maps.EntryTransformer() { - - @Override - public String transformEntry(String arg0, String arg1) { - return "use".equals(arg0) ? arg1.replace(' ', ',') : arg1; - } - - }); + return renameKey(baseDriveToMap.apply(from), "use", "use"); } } \ No newline at end of file diff --git a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java similarity index 100% rename from sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java rename to cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToServerInfo.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToServerInfo.java new file mode 100644 index 0000000000..8e1beccc0d --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToServerInfo.java @@ -0,0 +1,53 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.ServerInfo; +import org.jclouds.http.HttpResponse; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class KeyValuesDelimitedByBlankLinesToServerInfo implements Function { + private final ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet setParser; + + @Inject + public KeyValuesDelimitedByBlankLinesToServerInfo(ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet setParser) { + this.setParser = setParser; + } + + @Override + public ServerInfo apply(HttpResponse response) { + Set drives = setParser.apply(response); + if (drives.size() == 0) + return null; + return Iterables.get(drives, 0); + } +} \ No newline at end of file diff --git a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java similarity index 95% rename from sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java rename to cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java index 3d7d1a3d53..54ef298a44 100644 --- a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java @@ -25,7 +25,6 @@ import javax.inject.Inject; import javax.inject.Singleton; import org.jclouds.cloudsigma.domain.DriveInfo; -import org.jclouds.elasticstack.functions.ListOfKeyValuesDelimitedByBlankLinesToListOfMaps; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ReturnStringIf2xx; diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMaps.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMaps.java new file mode 100644 index 0000000000..abc3956fe6 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMaps.java @@ -0,0 +1,59 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import java.util.List; +import java.util.Map; + +import javax.inject.Singleton; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class ListOfKeyValuesDelimitedByBlankLinesToListOfMaps implements Function>> { + + @Override + public List> apply(String from) { + List> maps = Lists.newArrayList(); + for (String listOfKeyValues : Splitter.on("\n\n").split(from)) { + if (!"".equals(listOfKeyValues)) { + Map map = Maps.newLinkedHashMap(); + for (String keyValueLine : Splitter.on('\n').split(listOfKeyValues)) { + if (!"".equals(keyValueLine)) { + int firstIndex = keyValueLine.indexOf(' '); + String key = keyValueLine.substring(0, firstIndex); + String value = keyValueLine.substring(firstIndex + 1).replace("\\n", "\n"); + map.put(key, value); + } + } + if (map.size() != 0) + maps.add(map); + } + } + return maps; + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.java new file mode 100644 index 0000000000..bf9e95fab9 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.java @@ -0,0 +1,61 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.ServerInfo; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ReturnStringIf2xx; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; + + +/** + * + * @author Adrian Cole + */ +@Singleton +public class ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet implements Function> { + private final ReturnStringIf2xx returnStringIf200; + private final ListOfKeyValuesDelimitedByBlankLinesToListOfMaps mapConverter; + private final MapToServerInfo mapToServer; + + @Inject + ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet(ReturnStringIf2xx returnStringIf200, + ListOfKeyValuesDelimitedByBlankLinesToListOfMaps mapConverter, MapToServerInfo mapToServer) { + this.returnStringIf200 = returnStringIf200; + this.mapConverter = mapConverter; + this.mapToServer = mapToServer; + } + + @Override + public Set apply(HttpResponse response) { + String text = returnStringIf200.apply(response); + if (text == null || text.trim().equals("")) + return ImmutableSet. of(); + return ImmutableSet.copyOf(Iterables.transform(mapConverter.apply(text), mapToServer)); + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLines.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLines.java new file mode 100644 index 0000000000..0e6befe520 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLines.java @@ -0,0 +1,58 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import java.util.Map; + +import javax.inject.Singleton; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class ListOfMapsToListOfKeyValuesDelimitedByBlankLines implements + Function>, String> { + + @Override + public String apply(Iterable> from) { + return Joiner.on("\n\n").join(Iterables.transform(from, new Function, String>() { + + @Override + public String apply(Map from) { + return Joiner.on('\n').withKeyValueSeparator(" ") + .join(Maps.transformValues(from, new Function() { + + @Override + public String apply(String from) { + return from.replace("\n", "\\n"); + } + + })); + } + + })); + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToDevices.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToDevices.java new file mode 100644 index 0000000000..00f237250f --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToDevices.java @@ -0,0 +1,102 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.BlockDevice; +import org.jclouds.cloudsigma.domain.Device; +import org.jclouds.cloudsigma.domain.IDEDevice; +import org.jclouds.cloudsigma.domain.MediaType; +import org.jclouds.cloudsigma.domain.SCSIDevice; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.collect.Maps; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class MapToDevices implements Function, Map> { + @Singleton + public static class DeviceToId implements Function { + @Override + public String apply(Device input) { + return input.getId(); + } + } + + private final Function deviceToId; + + @Inject + public MapToDevices(Function deviceToId) { + this.deviceToId = deviceToId; + } + + public Map apply(Map from) { + Builder devices = ImmutableSet.builder(); + addIDEDevices(from, devices); + addSCSIDevices(from, devices); + addBlockDevices(from, devices); + + return Maps.uniqueIndex(devices.build(), deviceToId); + } + + protected void addBlockDevices(Map from, Builder devices) { + BLOCK: for (int index : new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }) { + String key = String.format("block:0:%d", index); + if (!from.containsKey(key)) + break BLOCK; + devices.add(populateBuilder(new BlockDevice.Builder(index), key, from).build()); + } + } + + protected void addSCSIDevices(Map from, Builder devices) { + SCSI: for (int unit : new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }) { + String key = String.format("scsi:0:%d", unit); + if (!from.containsKey(key)) + break SCSI; + devices.add(populateBuilder(new SCSIDevice.Builder(unit), key, from).build()); + } + } + + protected void addIDEDevices(Map from, Builder devices) { + IDE: for (int bus : new int[] { 0, 1 }) + for (int unit : new int[] { 0, 1 }) { + String key = String.format("ide:%d:%d", bus, unit); + if (!from.containsKey(key)) + break IDE; + devices.add(populateBuilder(new IDEDevice.Builder(bus, unit), key, from).build()); + } + } + + protected Device.Builder populateBuilder(Device.Builder deviceBuilder, String key, Map from) { + deviceBuilder.uuid(from.get(key)); + if (from.containsKey(key + ":media")) + deviceBuilder.mediaType(MediaType.fromValue(from.get(key + ":media"))); + return deviceBuilder; + } +} \ No newline at end of file diff --git a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToDriveInfo.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToDriveInfo.java similarity index 50% rename from sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToDriveInfo.java rename to cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToDriveInfo.java index 2910718e2a..fd61960b1b 100644 --- a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToDriveInfo.java +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToDriveInfo.java @@ -21,15 +21,19 @@ package org.jclouds.cloudsigma.functions; import java.net.URI; import java.util.Map; +import java.util.Map.Entry; -import javax.inject.Inject; import javax.inject.Singleton; +import org.jclouds.cloudsigma.domain.ClaimType; import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.cloudsigma.domain.DriveMetrics; +import org.jclouds.cloudsigma.domain.DriveStatus; import org.jclouds.cloudsigma.domain.DriveType; import com.google.common.base.Function; import com.google.common.base.Splitter; +import com.google.common.collect.Maps; /** * @@ -37,20 +41,38 @@ import com.google.common.base.Splitter; */ @Singleton public class MapToDriveInfo implements Function, DriveInfo> { - private final org.jclouds.elasticstack.functions.MapToDriveInfo mapToDriveInfo; - - @Inject - public MapToDriveInfo(org.jclouds.elasticstack.functions.MapToDriveInfo mapToDriveInfo) { - this.mapToDriveInfo = mapToDriveInfo; - } @Override public DriveInfo apply(Map from) { if (from.size() == 0) return null; - DriveInfo.Builder builder = DriveInfo.Builder.fromDriveInfo(mapToDriveInfo.apply(from)); + if (from.size() == 0) + return null; + DriveInfo.Builder builder = new DriveInfo.Builder(); + builder.name(from.get("name")); if (from.containsKey("use")) - builder.tags(Splitter.on(',').split(from.get("use"))); + builder.use(Splitter.on(' ').split(from.get("use"))); + if (from.containsKey("status")) + builder.status(DriveStatus.fromValue(from.get("status"))); + builder.metrics(buildMetrics(from)); + builder.user(from.get("user")); + builder.encryptionCipher(from.get("encryption:cipher")); + builder.uuid(from.get("drive")); + if (from.containsKey("claim:type")) + builder.claimType(ClaimType.fromValue(from.get("claim:type"))); + if (from.containsKey("claimed")) + builder.claimed(Splitter.on(' ').split(from.get("claimed"))); + if (from.containsKey("readers")) + builder.readers(Splitter.on(' ').split(from.get("readers"))); + if (from.containsKey("size")) + builder.size(new Long(from.get("size"))); + Map metadata = Maps.newLinkedHashMap(); + for (Entry entry : from.entrySet()) { + if (entry.getKey().startsWith("user:")) + metadata.put(entry.getKey().substring(entry.getKey().indexOf(':') + 1), entry.getValue()); + } + if (from.containsKey("use")) + builder.use(Splitter.on(' ').split(from.get("use"))); if (from.containsKey("bits")) builder.bits(new Integer(from.get("bits"))); if (from.containsKey("url")) @@ -69,4 +91,17 @@ public class MapToDriveInfo implements Function, DriveInfo> builder.type(DriveType.fromValue(from.get("type"))); return builder.build(); } + + protected DriveMetrics buildMetrics(Map from) { + DriveMetrics.Builder metricsBuilder = new DriveMetrics.Builder(); + if (from.containsKey("read:bytes")) + metricsBuilder.readBytes(new Long(from.get("read:bytes"))); + if (from.containsKey("read:requests")) + metricsBuilder.readRequests(new Long(from.get("read:requests"))); + if (from.containsKey("write:bytes")) + metricsBuilder.writeBytes(new Long(from.get("write:bytes"))); + if (from.containsKey("write:requests")) + metricsBuilder.writeRequests(new Long(from.get("write:requests"))); + return metricsBuilder.build(); + } } \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToDriveMetrics.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToDriveMetrics.java new file mode 100644 index 0000000000..79e515901c --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToDriveMetrics.java @@ -0,0 +1,87 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import java.util.Map; + +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.DriveMetrics; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class MapToDriveMetrics implements Function, Map> { + + public Map apply(Map from) { + Builder builder = ImmutableMap. builder(); + addIDEDevices(from, builder); + addSCSIDevices(from, builder); + addBlockDevices(from, builder); + return builder.build(); + } + + protected void addBlockDevices(Map from, Builder devices) { + BLOCK: for (int index : new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }) { + String key = String.format("block:0:%d", index); + if (!from.containsKey(key)) + break BLOCK; + devices.put(key, buildMetrics(key, from)); + } + } + + protected void addSCSIDevices(Map from, Builder devices) { + SCSI: for (int unit : new int[] { 0, 1, 2, 3, 4, 5, 6, 7 }) { + String key = String.format("scsi:0:%d", unit); + if (!from.containsKey(key)) + break SCSI; + devices.put(key, buildMetrics(key, from)); + } + } + + protected void addIDEDevices(Map from, Builder devices) { + IDE: for (int bus : new int[] { 0, 1 }) + for (int unit : new int[] { 0, 1 }) { + String key = String.format("ide:%d:%d", bus, unit); + if (!from.containsKey(key)) + break IDE; + devices.put(key, buildMetrics(key, from)); + } + } + + protected DriveMetrics buildMetrics(String key, Map from) { + DriveMetrics.Builder builder = new DriveMetrics.Builder(); + if (from.containsKey(key + ":read:bytes")) + builder.readBytes(new Long(from.get(key + ":read:bytes"))); + if (from.containsKey(key + ":read:requests")) + builder.readRequests(new Long(from.get(key + ":read:requests"))); + if (from.containsKey(key + ":write:bytes")) + builder.writeBytes(new Long(from.get(key + ":write:bytes"))); + if (from.containsKey(key + ":write:requests")) + builder.writeRequests(new Long(from.get(key + ":write:requests"))); + return builder.build(); + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToNICs.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToNICs.java new file mode 100644 index 0000000000..9baa6e8606 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToNICs.java @@ -0,0 +1,59 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import java.util.List; +import java.util.Map; + +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.Model; +import org.jclouds.cloudsigma.domain.NIC; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class MapToNICs implements Function, List> { + + @Override + public List apply(Map from) { + ImmutableList.Builder nics = ImmutableList.builder(); + NIC: for (int id : new int[] { 0, 1 }) { + String key = String.format("nic:%d", id); + if (!from.containsKey(key + ":model")) + break NIC; + NIC.Builder nicBuilder = new NIC.Builder(); + nicBuilder.dhcp(from.get(key + ":dhcp")); + nicBuilder.model(Model.fromValue(from.get(key + ":model"))); + nicBuilder.vlan(from.get(key + ":vlan")); + nicBuilder.mac(from.get(key + ":mac")); + if (from.containsKey(key + ":block")) + nicBuilder.block(Splitter.on(' ').split(from.get(key + ":block"))); + nics.add(nicBuilder.build()); + } + return nics.build(); + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToServerInfo.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToServerInfo.java new file mode 100644 index 0000000000..bb9fea7572 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToServerInfo.java @@ -0,0 +1,94 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.Device; +import org.jclouds.cloudsigma.domain.NIC; +import org.jclouds.cloudsigma.domain.ServerInfo; +import org.jclouds.cloudsigma.domain.ServerMetrics; +import org.jclouds.cloudsigma.domain.ServerStatus; +import org.jclouds.cloudsigma.domain.VNC; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.common.collect.Maps; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class MapToServerInfo implements Function, ServerInfo> { + private final Function, Map> mapToDevices; + private final Function, ServerMetrics> mapToMetrics; + private final Function, List> mapToNICs; + + @Inject + public MapToServerInfo(Function, Map> mapToDevices, + Function, ServerMetrics> mapToMetrics, Function, List> mapToNICs) { + this.mapToDevices = mapToDevices; + this.mapToMetrics = mapToMetrics; + this.mapToNICs = mapToNICs; + } + + @Override + public ServerInfo apply(Map from) { + if (from.size() == 0) + return null; + ServerInfo.Builder builder = new ServerInfo.Builder(); + builder.name(from.get("name")); + builder.description(from.get("description")); + builder.persistent(Boolean.parseBoolean(from.get("persistent"))); + if (from.containsKey("use")) + builder.use(Splitter.on(' ').split(from.get("use"))); + if (from.containsKey("status")) + builder.status(ServerStatus.fromValue(from.get("status"))); + if (from.containsKey("smp") && !"auto".equals(from.get("smp"))) + builder.smp(new Integer(from.get("smp"))); + builder.cpu(Integer.parseInt(from.get("cpu"))); + builder.mem(Integer.parseInt(from.get("mem"))); + builder.user(from.get("user")); + if (from.containsKey("started")) + builder.started(new Date(new Long(from.get("started")))); + builder.uuid(from.get("server")); + builder.vnc(new VNC(from.get("vnc:ip"), from.get("vnc:password"), from.containsKey("vnc:tls") + && Boolean.valueOf(from.get("vnc:tls")))); + if (from.containsKey("boot")) + builder.bootDeviceIds(Splitter.on(' ').split(from.get("boot"))); + + Map metadata = Maps.newLinkedHashMap(); + for (Entry entry : from.entrySet()) { + if (entry.getKey().startsWith("user:")) + metadata.put(entry.getKey().substring(entry.getKey().indexOf(':') + 1), entry.getValue()); + } + builder.nics(mapToNICs.apply(from)); + builder.devices(mapToDevices.apply(from)); + builder.metrics(mapToMetrics.apply(from)); + return builder.build(); + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToServerMetrics.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToServerMetrics.java new file mode 100644 index 0000000000..f982abf6a3 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/MapToServerMetrics.java @@ -0,0 +1,60 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.DriveMetrics; +import org.jclouds.cloudsigma.domain.ServerMetrics; + +import com.google.common.base.Function; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class MapToServerMetrics implements Function, ServerMetrics> { + private final Function, Map> mapToDriveMetrics; + + @Inject + public MapToServerMetrics(Function, Map> mapToDriveMetrics) { + this.mapToDriveMetrics = mapToDriveMetrics; + } + + public ServerMetrics apply(Map from) { + ServerMetrics.Builder metricsBuilder = new ServerMetrics.Builder(); + if (from.containsKey("tx:packets")) + metricsBuilder.txPackets(new Long(from.get("tx:packets"))); + if (from.containsKey("tx")) + metricsBuilder.tx(new Long(from.get("tx"))); + if (from.containsKey("rx:packets")) + metricsBuilder.rxPackets(new Long(from.get("rx:packets"))); + if (from.containsKey("rx")) + metricsBuilder.rx(new Long(from.get("rx"))); + metricsBuilder.driveMetrics(mapToDriveMetrics.apply(from)); + + ServerMetrics metrics = metricsBuilder.build(); + return metrics; + } +} \ No newline at end of file diff --git a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/LibvirtNodeToLocation.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ReturnPayload.java similarity index 68% rename from sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/LibvirtNodeToLocation.java rename to cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ReturnPayload.java index 9482ec7220..d7e7424467 100644 --- a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/LibvirtNodeToLocation.java +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ReturnPayload.java @@ -17,14 +17,12 @@ * ==================================================================== */ -package org.jclouds.vi.compute.functions; +package org.jclouds.cloudsigma.functions; import javax.inject.Singleton; -import org.jclouds.domain.Location; -import org.jclouds.domain.LocationScope; -import org.jclouds.domain.internal.LocationImpl; -import org.jclouds.vi.Datacenter; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payload; import com.google.common.base.Function; @@ -32,11 +30,9 @@ import com.google.common.base.Function; * @author Adrian Cole */ @Singleton -public class LibvirtNodeToLocation implements Function { +public class ReturnPayload implements Function { - @Override - public Location apply(Datacenter from) { - return new LocationImpl(LocationScope.ZONE, from.id + "", from.name, null); + public Payload apply(HttpResponse from) { + return from.getPayload(); } - -} +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ServerToMap.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ServerToMap.java new file mode 100644 index 0000000000..7c67b4996f --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/ServerToMap.java @@ -0,0 +1,81 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.Map.Entry; + +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.domain.Device; +import org.jclouds.cloudsigma.domain.NIC; +import org.jclouds.cloudsigma.domain.Server; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class ServerToMap implements Function> { + @Override + public Map apply(Server from) { + checkNotNull(from, "server"); + ImmutableMap.Builder builder = ImmutableMap.builder(); + builder.put("name", from.getName()); + builder.put("cpu", from.getCpu() + ""); + if (from.getSmp() != null) + builder.put("smp", from.getSmp() + ""); + else + builder.put("smp", "auto"); + builder.put("mem", from.getMem() + ""); + builder.put("persistent", from.isPersistent() + ""); + if (from.getBootDeviceIds().size() != 0) + builder.put("boot", Joiner.on(' ').join(from.getBootDeviceIds())); + for (Entry entry : from.getDevices().entrySet()) { + builder.put(entry.getKey(), entry.getValue().getDriveUuid()); + builder.put(entry.getKey() + ":media", entry.getValue().getMediaType().toString()); + } + int nicId = 0; + for (NIC nic : from.getNics()) { + builder.put("nic:" + nicId + ":model", nic.getModel().toString()); + if (nic.getDhcp() != null) + builder.put("nic:" + nicId + ":dhcp", nic.getDhcp()); + if (nic.getVlan() != null) + builder.put("nic:" + nicId + ":vlan", nic.getVlan()); + if (nic.getMac() != null) + builder.put("nic:" + nicId + ":mac", nic.getMac()); + nicId++; + } + builder.put("vnc:ip", from.getVnc().getIp() == null ? "auto" : from.getVnc().getIp()); + if (from.getVnc().getPassword() != null) + builder.put("vnc:password", from.getVnc().getPassword()); + if (from.getVnc().isTls()) + builder.put("vnc:tls", "on"); + if (from.getUse().size() != 0) + builder.put("use", Joiner.on(' ').join(from.getUse())); + return builder.build(); + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/SplitNewlines.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/SplitNewlines.java new file mode 100644 index 0000000000..b87fd5e4de --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/functions/SplitNewlines.java @@ -0,0 +1,55 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import static com.google.common.base.Predicates.equalTo; +import static com.google.common.base.Predicates.not; +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Sets.newTreeSet; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ReturnStringIf2xx; + +import com.google.common.base.Function; +import com.google.common.base.Splitter; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class SplitNewlines implements Function> { + private final ReturnStringIf2xx returnStringIf200; + + @Inject + SplitNewlines(ReturnStringIf2xx returnStringIf200) { + this.returnStringIf200 = returnStringIf200; + } + + @Override + public Set apply(HttpResponse response) { + return newTreeSet(filter(Splitter.on('\n').split(returnStringIf200.apply(response)), not(equalTo("")))); + } +} \ No newline at end of file diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/handlers/CloudSigmaErrorHandler.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/handlers/CloudSigmaErrorHandler.java new file mode 100644 index 0000000000..7c4f3dfc83 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/handlers/CloudSigmaErrorHandler.java @@ -0,0 +1,107 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.handlers; + +import java.io.IOException; + +import javax.annotation.Resource; +import javax.inject.Singleton; + +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; +import org.jclouds.logging.Logger; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.util.Utils; + +import com.google.common.base.Throwables; +import com.google.common.io.Closeables; + +/** + * This will parse and set an appropriate exception on the command object. + * + *

+ * Errors are returned with an appropriate HTTP status code, an X-Elastic- Error header specifying + * the error type, and a text description in the HTTP body. + * + * @author Adrian Cole + * + */ +@Singleton +public class CloudSigmaErrorHandler implements HttpErrorHandler { + @Resource + protected Logger logger = Logger.NULL; + + public void handleError(HttpCommand command, HttpResponse response) { + // it is important to always read fully and close streams + String message = parseMessage(response); + Exception exception = message != null ? new HttpResponseException(command, response, message) + : new HttpResponseException(command, response); + try { + message = message != null ? message : String.format("%s -> %s", command.getRequest().getRequestLine(), + response.getStatusLine()); + switch (response.getStatusCode()) { + case 400: + if ((command.getRequest().getEndpoint().getPath().endsWith("/info")) + || (message != null && message.indexOf("could not be found") != -1)) + exception = new ResourceNotFoundException(message, exception); + else + exception = new IllegalArgumentException(message, exception); + break; + case 401: + exception = new AuthorizationException(message, exception); + break; + case 404: + if (!command.getRequest().getMethod().equals("DELETE")) { + exception = new ResourceNotFoundException(message, exception); + } + break; + case 405: + exception = new IllegalArgumentException(message, exception); + break; + case 409: + exception = new IllegalStateException(message, exception); + break; + } + } finally { + if (response.getPayload() != null) + Closeables.closeQuietly(response.getPayload().getInput()); + command.setException(exception); + } + } + + public String parseMessage(HttpResponse response) { + if (response.getPayload() == null) + return null; + try { + return Utils.toStringAndClose(response.getPayload().getInput()); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + try { + response.getPayload().getInput().close(); + } catch (IOException e) { + Throwables.propagate(e); + } + } + } +} diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/options/CloneDriveOptions.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/options/CloneDriveOptions.java new file mode 100644 index 0000000000..df9f5c59a2 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/options/CloneDriveOptions.java @@ -0,0 +1,72 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.options; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; + +/** + * Contains options supported for clone drive operations.

+ * Usage

The recommended way to instantiate a CloneDriveOptions object is to statically import + * CloneDriveOptions.Builder.* and invoke a static creation method followed by an instance mutator + * (if needed): + *

+ * + * import static org.jclouds.cloudsigma.options.CloneDriveOptions.Builder.*; + * + * + * Payload payload = client.cloneDrive("drive-uuid","newName", size(2*1024*1024l)); + * + * + * @author Adrian Cole + * + */ +public class CloneDriveOptions { + private final Map options = Maps.newLinkedHashMap(); + + /** + * adjust to new size in bytes + */ + public CloneDriveOptions size(long size) { + checkArgument(size >= 0, "size must be >= 0"); + options.put("size", size + ""); + return this; + } + + public static class Builder { + + /** + * @see CloneDriveOptions#size + */ + public static CloneDriveOptions size(long size) { + CloneDriveOptions options = new CloneDriveOptions(); + return options.size(size); + } + + } + + public Map getOptions() { + return ImmutableMap.copyOf(options); + } +} diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/predicates/DriveClaimed.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/predicates/DriveClaimed.java new file mode 100644 index 0000000000..9160caa348 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/predicates/DriveClaimed.java @@ -0,0 +1,63 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.predicates; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudsigma.CloudSigmaClient; +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.logging.Logger; + +import com.google.common.base.Predicate; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class DriveClaimed implements Predicate { + + private final CloudSigmaClient client; + + @Resource + protected Logger logger = Logger.NULL; + + @Inject + public DriveClaimed(CloudSigmaClient client) { + this.client = client; + } + + public boolean apply(DriveInfo drive) { + logger.trace("looking for claims on drive %s", checkNotNull(drive, "drive")); + drive = refresh(drive); + if (drive == null) + return false; + logger.trace("%s: looking for drive claims: currently: %s", drive.getUuid(), drive.getClaimed()); + return drive.getClaimed().size() > 0; + } + + private DriveInfo refresh(DriveInfo drive) { + return client.getDriveInfo(drive.getUuid()); + } +} diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/reference/CloudSigmaConstants.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/reference/CloudSigmaConstants.java new file mode 100644 index 0000000000..7f19b80427 --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/reference/CloudSigmaConstants.java @@ -0,0 +1,33 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.reference; + +/** + * + * @author Adrian Cole + */ +public class CloudSigmaConstants { + + /** + * default VNC password used on new machines + */ + public static final String PROPERTY_VNC_PASSWORD = "jclouds.cloudsigma.vnc-password"; + +} diff --git a/cloudsigma/src/main/java/org/jclouds/cloudsigma/util/Servers.java b/cloudsigma/src/main/java/org/jclouds/cloudsigma/util/Servers.java new file mode 100644 index 0000000000..e452ee798c --- /dev/null +++ b/cloudsigma/src/main/java/org/jclouds/cloudsigma/util/Servers.java @@ -0,0 +1,54 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.util; + +import org.jclouds.cloudsigma.domain.IDEDevice; +import org.jclouds.cloudsigma.domain.Model; +import org.jclouds.cloudsigma.domain.NIC; +import org.jclouds.cloudsigma.domain.Server; +import org.jclouds.cloudsigma.domain.VNC; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class Servers { + /** + * Helper to create a small persistent server + * + * @param name + * what to name the server + * @param driveUuuid + * id of the boot drive + * @param vncPassword + * password for vnc + * @return a builder for a persistent 1Ghz 512m server with DHCP enabled network. + */ + public static Server.Builder small(String name, String driveUuuid, String vncPassword) { + return new Server.Builder().name(name).cpu(1000).mem(512).persistent(true) + .devices(ImmutableMap.of("ide:0:0", new IDEDevice.Builder(0, 0).uuid(driveUuuid).build())) + .bootDeviceIds(ImmutableSet.of("ide:0:0")) + .nics(ImmutableSet.of(new NIC.Builder().model(Model.E1000).dhcp("auto").build())) + .vnc(new VNC(null, vncPassword, false)); + } +} \ No newline at end of file diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaAsyncClientTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaAsyncClientTest.java new file mode 100644 index 0000000000..d4c89f84f5 --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaAsyncClientTest.java @@ -0,0 +1,441 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Properties; + +import org.jclouds.cloudsigma.binders.BindServerToPlainTextStringTest; +import org.jclouds.cloudsigma.domain.CreateDriveRequest; +import org.jclouds.cloudsigma.domain.Drive; +import org.jclouds.cloudsigma.domain.DriveData; +import org.jclouds.cloudsigma.domain.Server; +import org.jclouds.cloudsigma.functions.KeyValuesDelimitedByBlankLinesToDriveInfo; +import org.jclouds.cloudsigma.functions.KeyValuesDelimitedByBlankLinesToServerInfo; +import org.jclouds.cloudsigma.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet; +import org.jclouds.cloudsigma.functions.ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet; +import org.jclouds.cloudsigma.functions.SplitNewlines; +import org.jclouds.cloudsigma.options.CloneDriveOptions; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.http.functions.ReleasePayloadAndReturn; +import org.jclouds.rest.RestClientTest; +import org.jclouds.rest.RestContextFactory; +import org.jclouds.rest.RestContextSpec; +import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; +import org.jclouds.rest.internal.GeneratedHttpRequest; +import org.jclouds.rest.internal.RestAnnotationProcessor; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.inject.TypeLiteral; + +/** + * Tests annotation parsing of {@code CloudSigmaAsyncClient} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "cloudsigma.CloudSigmaAsyncClientTest") +public class CloudSigmaAsyncClientTest extends RestClientTest { + + public void testListStandardDrives() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("listStandardDrives"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/standard/list HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, SplitNewlines.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + } + + public void testListStandardCds() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("listStandardCds"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/standard/cd/list HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, SplitNewlines.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + } + + public void testListStandardImages() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("listStandardImages"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/standard/img/list HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, SplitNewlines.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + } + + public void testListDriveInfo() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("listDriveInfo"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/info HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + } + + public void testGetDriveInfo() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("getDriveInfo", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/uuid/info HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testCreateDrive() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("createDrive", Drive.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, + new CreateDriveRequest.Builder().name("foo").use(ImmutableList.of("production", "candy")).size(10000l) + .build()); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/drives/create HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, "name foo\nsize 10000\nuse production candy", "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testCloneDrive() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("cloneDrive", String.class, String.class, + CloneDriveOptions[].class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "sourceid", "newname"); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/drives/sourceid/clone HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, "name newname", "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + + } + + public void testCloneDriveOptions() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("cloneDrive", String.class, String.class, + CloneDriveOptions[].class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "sourceid", "newname", + new CloneDriveOptions().size(1024l)); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/drives/sourceid/clone HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, "name newname\nsize 1024", "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + + } + + public void testSetDriveData() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("setDriveData", String.class, DriveData.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", + new DriveData.Builder().name("foo").size(10000l).use(ImmutableList.of("production", "candy")).build()); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/drives/100/set HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, "name foo\nsize 10000\nuse production candy", "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + + } + + public void testListServers() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("listServers"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/servers/list HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + // now make sure request filters apply by replaying + Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); + Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/servers/list HTTP/1.1"); + // for example, using basic authentication, we should get "only one" + // header + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\nAuthorization: Basic Zm9vOmJhcg==\n"); + assertPayloadEquals(httpRequest, null, null, false); + + // TODO: insert expected response class, which probably extends ParseJson + assertResponseParserClassEquals(method, httpRequest, SplitNewlines.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + + } + + public void testListServerInfo() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("listServerInfo"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/servers/info HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + } + + public void testGetServerInfo() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("getServerInfo", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/servers/uuid/info HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToServerInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testCreateServer() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("createServer", Server.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, + BindServerToPlainTextStringTest.SERVER); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/servers/create HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, BindServerToPlainTextStringTest.CREATED_SERVER, "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToServerInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testSetServerConfiguration() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("setServerConfiguration", String.class, Server.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", + BindServerToPlainTextStringTest.SERVER); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/servers/100/set HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, BindServerToPlainTextStringTest.CREATED_SERVER, "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToServerInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testDestroyServer() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("destroyServer", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/servers/uuid/destroy HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testStartServer() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("startServer", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/servers/uuid/start HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + + } + + public void testStopServer() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("stopServer", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/servers/uuid/stop HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + + } + + public void testShutdownServer() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("shutdownServer", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/servers/uuid/shutdown HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + + } + + public void testResetServer() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("resetServer", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/servers/uuid/reset HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + + } + + public void testListDrives() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("listDrives"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/list HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + // now make sure request filters apply by replaying + Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); + Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); + + assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/list HTTP/1.1"); + // for example, using basic authentication, we should get "only one" + // header + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\nAuthorization: Basic Zm9vOmJhcg==\n"); + assertPayloadEquals(httpRequest, null, null, false); + + // TODO: insert expected response class, which probably extends ParseJson + assertResponseParserClassEquals(method, httpRequest, SplitNewlines.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + + } + + public void testDestroyDrive() throws SecurityException, NoSuchMethodException, IOException { + Method method = CloudSigmaAsyncClient.class.getMethod("destroyDrive", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/drives/uuid/destroy HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + @Override + protected void checkFilters(HttpRequest request) { + assertEquals(request.getFilters().size(), 1); + assertEquals(request.getFilters().get(0).getClass(), BasicAuthentication.class); + } + + @Override + protected TypeLiteral> createTypeLiteral() { + return new TypeLiteral>() { + }; + } + + @Override + public RestContextSpec createContextSpec() { + return new RestContextFactory().createContextSpec("cloudsigma", "foo", "bar", new Properties()); + } +} diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java new file mode 100644 index 0000000000..997fce89e8 --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java @@ -0,0 +1,379 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma; + +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.util.Properties; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +import org.jclouds.Constants; +import org.jclouds.cloudsigma.domain.ClaimType; +import org.jclouds.cloudsigma.domain.CreateDriveRequest; +import org.jclouds.cloudsigma.domain.DriveData; +import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.cloudsigma.domain.DriveStatus; +import org.jclouds.cloudsigma.domain.DriveType; +import org.jclouds.cloudsigma.domain.IDEDevice; +import org.jclouds.cloudsigma.domain.Model; +import org.jclouds.cloudsigma.domain.Server; +import org.jclouds.cloudsigma.domain.ServerInfo; +import org.jclouds.cloudsigma.domain.ServerStatus; +import org.jclouds.cloudsigma.options.CloneDriveOptions; +import org.jclouds.cloudsigma.predicates.DriveClaimed; +import org.jclouds.cloudsigma.util.Servers; +import org.jclouds.compute.ComputeServiceContextFactory; +import org.jclouds.domain.Credentials; +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.net.IPSocket; +import org.jclouds.predicates.InetSocketAddressConnect; +import org.jclouds.predicates.RetryablePredicate; +import org.jclouds.rest.RestContext; +import org.jclouds.ssh.ExecResponse; +import org.jclouds.ssh.SshClient; +import org.jclouds.ssh.jsch.config.JschSshClientModule; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.gson.Gson; +import com.google.inject.Guice; +import com.google.inject.Module; + +/** + * Tests behavior of {@code CloudSigmaClient} + * + * @author Adrian Cole + */ +@Test(groups = "live", testName = "cloudsigma.CloudSigmaClientLiveTest") +public class CloudSigmaClientLiveTest { + protected long driveSize = 8 * 1024 * 1024 * 1024l; + protected int maxDriveImageTime = 300; + protected String vncPassword = "Il0veVNC"; + protected CloudSigmaClient client; + protected RestContext context; + protected Predicate socketTester; + + protected String provider = "cloudsigma"; + protected String identity; + protected String credential; + protected String endpoint; + protected String apiversion; + protected Predicate driveNotClaimed; + + protected void setupCredentials() { + identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"); + credential = System.getProperty("test." + provider + ".credential"); + endpoint = System.getProperty("test." + provider + ".endpoint"); + apiversion = System.getProperty("test." + provider + ".apiversion"); + } + + protected Properties setupProperties() { + Properties overrides = new Properties(); + overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true"); + overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true"); + overrides.setProperty(provider + ".identity", identity); + if (credential != null) + overrides.setProperty(provider + ".credential", credential); + if (endpoint != null) + overrides.setProperty(provider + ".endpoint", endpoint); + if (apiversion != null) + overrides.setProperty(provider + ".apiversion", apiversion); + return overrides; + } + + @BeforeGroups(groups = "live") + public void setupClient() { + setupCredentials(); + Properties overrides = setupProperties(); + context = new ComputeServiceContextFactory().createContext(provider, + ImmutableSet. of(new Log4JLoggingModule()), overrides).getProviderSpecificContext(); + + client = context.getApi(); + driveNotClaimed = new RetryablePredicate(Predicates.not(new DriveClaimed(client)), maxDriveImageTime, + 1, TimeUnit.SECONDS); + socketTester = new RetryablePredicate(new InetSocketAddressConnect(), maxDriveImageTime, 1, + TimeUnit.SECONDS); + } + + @Test + public void testListServers() throws Exception { + Set servers = client.listServers(); + assertNotNull(servers); + } + + @Test + public void testListServerInfo() throws Exception { + Set servers = client.listServerInfo(); + assertNotNull(servers); + } + + @Test + public void testGetServer() throws Exception { + for (String serverUUID : client.listServers()) { + assert !"".equals(serverUUID); + assertNotNull(client.getServerInfo(serverUUID)); + } + } + + @Test + public void testListDrives() throws Exception { + Set drives = client.listDrives(); + assertNotNull(drives); + } + + @Test + public void testListDriveInfo() throws Exception { + Set drives = client.listDriveInfo(); + assertNotNull(drives); + } + + @Test + public void testGetDrive() throws Exception { + for (String driveUUID : client.listStandardDrives()) { + assert !"".equals(driveUUID); + DriveInfo drive = client.getDriveInfo(driveUUID); + assertNotNull(drive); + assert !drive.getType().equals(DriveType.UNRECOGNIZED) : drive; + if (drive.getType() == DriveType.DISK && drive.getDriveType().contains("preinstalled")) + System.out.println(drive.getName()); + } + } + + protected String prefix = System.getProperty("user.name") + ".test"; + protected DriveInfo drive; + + @Test + public void testCreateDrive() throws Exception { + drive = client.createDrive(new CreateDriveRequest.Builder().name(prefix).size(driveSize).build()); + checkCreatedDrive(); + + DriveInfo newInfo = client.getDriveInfo(drive.getUuid()); + checkDriveMatchesGet(newInfo); + + } + + protected void checkDriveMatchesGet(DriveInfo newInfo) { + assertEquals(newInfo.getUuid(), drive.getUuid()); + assertEquals(newInfo.getType(), DriveType.DISK); + } + + protected void checkCreatedDrive() { + assertNotNull(drive.getUuid()); + assertNotNull(drive.getUser()); + assertEquals(drive.getName(), prefix); + assertEquals(drive.getSize(), driveSize); + assertEquals(drive.getStatus(), DriveStatus.ACTIVE); + // for some reason, these occasionally return as 4096,1 + // assertEquals(info.getReadBytes(), 0l); + // assertEquals(info.getWriteBytes(), 0l); + // assertEquals(info.getReadRequests(), 0l); + // assertEquals(info.getWriteRequests(), 0l); + assertEquals(drive.getEncryptionCipher(), "aes-xts-plain"); + assertEquals(drive.getType(), null); + } + + @Test(dependsOnMethods = "testCreateDrive") + public void testSetDriveData() throws Exception { + + DriveInfo drive2 = client.setDriveData( + drive.getUuid(), + new DriveData.Builder().claimType(ClaimType.SHARED).name("rediculous") + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff")) + .use(ImmutableSet.of("networking", "security", "gateway")).build()); + + assertNotNull(drive2.getUuid(), drive.getUuid()); + assertEquals(drive2.getName(), "rediculous"); + assertEquals(drive2.getClaimType(), ClaimType.SHARED); + assertEquals(drive2.getReaders(), ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff")); + assertEquals(drive2.getUse(), ImmutableSet.of("networking", "security", "gateway")); + drive = drive2; + } + + protected ServerInfo server; + + @Test(dependsOnMethods = "testSetDriveData") + public void testCreateAndStartServer() throws Exception { + Logger.getAnonymousLogger().info("preparing drive"); + prepareDrive(); + + Server serverRequest = Servers.small(prefix, drive.getUuid(), vncPassword).build(); + + Logger.getAnonymousLogger().info("starting server"); + server = client.createServer(serverRequest); + client.startServer(server.getUuid()); + server = client.getServerInfo(server.getUuid()); + checkStartedServer(); + + Server newInfo = client.getServerInfo(server.getUuid()); + checkServerMatchesGet(newInfo); + + } + + protected void checkServerMatchesGet(Server newInfo) { + assertEquals(newInfo.getUuid(), server.getUuid()); + } + + protected void checkStartedServer() { + System.out.println(new Gson().toJson(server)); + assertNotNull(server.getUuid()); + assertNotNull(server.getUser()); + assertEquals(server.getName(), prefix); + assertEquals(server.isPersistent(), true); + assertEquals(server.getDevices(), + ImmutableMap.of("ide:0:0", new IDEDevice.Builder(0, 0).uuid(drive.getUuid()).build())); + assertEquals(server.getBootDeviceIds(), ImmutableSet.of("ide:0:0")); + assertEquals(server.getNics().get(0).getDhcp(), server.getVnc().getIp()); + assertEquals(server.getNics().get(0).getModel(), Model.E1000); + assertEquals(server.getStatus(), ServerStatus.ACTIVE); + } + + @Test(dependsOnMethods = "testCreateAndStartServer") + public void testConnectivity() throws Exception { + Logger.getAnonymousLogger().info("awaiting vnc"); + assert socketTester.apply(new IPSocket(server.getVnc().getIp(), 5900)) : server; + Logger.getAnonymousLogger().info("awaiting ssh"); + assert socketTester.apply(new IPSocket(server.getNics().get(0).getDhcp(), 22)) : server; + doConnectViaSsh(server, getSshCredentials(server)); + } + + @Test(dependsOnMethods = "testConnectivity") + public void testLifeCycle() throws Exception { + client.stopServer(server.getUuid()); + assertEquals(client.getServerInfo(server.getUuid()).getStatus(), ServerStatus.STOPPED); + + client.startServer(server.getUuid()); + assertEquals(client.getServerInfo(server.getUuid()).getStatus(), ServerStatus.ACTIVE); + + client.resetServer(server.getUuid()); + assertEquals(client.getServerInfo(server.getUuid()).getStatus(), ServerStatus.ACTIVE); + + client.shutdownServer(server.getUuid()); + // behavior on shutdown depends on how your server OS is set up to respond to an ACPI power + // button signal + assert (client.getServerInfo(server.getUuid()).getStatus() == ServerStatus.ACTIVE || client.getServerInfo( + server.getUuid()).getStatus() == ServerStatus.STOPPED); + } + + @Test(dependsOnMethods = "testLifeCycle") + public void testSetServerConfiguration() throws Exception { + client.stopServer(server.getUuid()); + assertEquals(client.getServerInfo(server.getUuid()).getStatus(), ServerStatus.STOPPED); + + ServerInfo server2 = client.setServerConfiguration( + server.getUuid(), + Server.Builder.fromServer(server).name("rediculous") + .use(ImmutableSet.of("networking", "security", "gateway")).build()); + + assertNotNull(server2.getUuid(), server.getUuid()); + assertEquals(server2.getName(), "rediculous"); + checkUse(server2); + server = server2; + } + + protected void checkUse(ServerInfo server2) { + // bug where use aren't updated + assertEquals(server2.getUse(), ImmutableSet. of()); + } + + @Test(dependsOnMethods = "testSetServerConfiguration") + public void testDestroyServer() throws Exception { + client.destroyServer(server.getUuid()); + assertEquals(client.getServerInfo(server.getUuid()), null); + } + + @Test(dependsOnMethods = "testDestroyServer") + public void testDestroyDrive() throws Exception { + client.destroyDrive(drive.getUuid()); + assertEquals(client.getDriveInfo(drive.getUuid()), null); + } + + protected void doConnectViaSsh(Server server, Credentials creds) throws IOException { + SshClient ssh = Guice.createInjector(new JschSshClientModule()).getInstance(SshClient.Factory.class) + .create(new IPSocket(server.getVnc().getIp(), 22), creds); + try { + ssh.connect(); + ExecResponse hello = ssh.exec("echo hello"); + assertEquals(hello.getOutput().trim(), "hello"); + System.err.println(ssh.exec("df -k").getOutput()); + System.err.println(ssh.exec("mount").getOutput()); + System.err.println(ssh.exec("uname -a").getOutput()); + } finally { + if (ssh != null) + ssh.disconnect(); + } + } + + @AfterGroups(groups = "live") + protected void tearDown() { + try { + client.destroyServer(server.getUuid()); + } catch (Exception e) { + // no need to check null or anything as we swallow all + } + try { + client.destroyDrive(drive.getUuid()); + } catch (Exception e) { + + } + if (context != null) + context.close(); + } + + @Test + public void testListStandardDrives() throws Exception { + Set drives = client.listStandardDrives(); + assertNotNull(drives); + } + + @Test + public void testListStandardCds() throws Exception { + Set drives = client.listStandardCds(); + assertNotNull(drives); + } + + @Test + public void testListStandardImages() throws Exception { + Set drives = client.listStandardImages(); + assertNotNull(drives); + } + + protected Credentials getSshCredentials(Server server) { + return new Credentials("cloudsigma", "cloudsigma"); + } + + protected void prepareDrive() { + client.destroyDrive(drive.getUuid()); + drive = client.cloneDrive("0b060e09-d98b-44cc-95a4-7e3a22ba1b53", drive.getName(), + new CloneDriveOptions().size(driveSize)); + assert driveNotClaimed.apply(drive) : client.getDriveInfo(drive.getUuid()); + System.err.println("after prepare" + client.getDriveInfo(drive.getUuid())); + } + +} diff --git a/sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/ProvidersInPropertiesTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/ProvidersInPropertiesTest.java similarity index 100% rename from sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/ProvidersInPropertiesTest.java rename to cloudsigma/src/test/java/org/jclouds/cloudsigma/ProvidersInPropertiesTest.java diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/binders/BindCloneDriveOptionsToPlainTextStringTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/binders/BindCloneDriveOptionsToPlainTextStringTest.java new file mode 100644 index 0000000000..8f9d0a5769 --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/binders/BindCloneDriveOptionsToPlainTextStringTest.java @@ -0,0 +1,78 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.binders; + +import static org.easymock.EasyMock.expect; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.easymock.classextension.EasyMock.verify; + +import java.io.IOException; + +import org.jclouds.cloudsigma.options.CloneDriveOptions; +import org.jclouds.io.MutableContentMetadata; +import org.jclouds.io.Payload; +import org.jclouds.rest.internal.GeneratedHttpRequest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class BindCloneDriveOptionsToPlainTextStringTest { + + private static final BindCloneDriveOptionsToPlainTextString binder = Guice.createInjector().getInstance( + BindCloneDriveOptionsToPlainTextString.class); + + public void testDefault() throws IOException { + assertInputAndArgsCreatesPayload(ImmutableMap.of("name", "newdrive"), new Object[] {}, "name newdrive"); + } + + public void testWithSize() throws IOException { + assertInputAndArgsCreatesPayload(ImmutableMap.of("name", "newdrive"), + new Object[] { new CloneDriveOptions().size(1024) }, "name newdrive\nsize 1024"); + } + + protected void assertInputAndArgsCreatesPayload(ImmutableMap inputMap, Object[] args, String expected) { + GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class); + expect(request.getArgs()).andReturn(args).atLeastOnce(); + request.setPayload(expected); + Payload payload = createMock(Payload.class); + expect(request.getPayload()).andReturn(payload); + MutableContentMetadata md = createMock(MutableContentMetadata.class); + expect(payload.getContentMetadata()).andReturn(md); + md.setContentType("text/plain"); + + replay(request); + replay(payload); + replay(md); + + binder.bindToRequest(request, inputMap); + + verify(request); + verify(payload); + verify(md); + } + +} \ No newline at end of file diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/binders/BindDriveDataToPlainTextStringTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/binders/BindDriveDataToPlainTextStringTest.java new file mode 100644 index 0000000000..fbd187970a --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/binders/BindDriveDataToPlainTextStringTest.java @@ -0,0 +1,87 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.binders; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.net.URI; +import java.util.Map; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.cloudsigma.domain.ClaimType; +import org.jclouds.cloudsigma.domain.Drive; +import org.jclouds.cloudsigma.domain.DriveData; +import org.jclouds.cloudsigma.functions.BaseDriveToMap; +import org.jclouds.cloudsigma.functions.DriveDataToMap; +import org.jclouds.http.HttpRequest; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class BindDriveDataToPlainTextStringTest { + + private static final BindDriveDataToPlainTextString FN = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral>>() { + }).to(BaseDriveToMap.class); + bind(new TypeLiteral>>() { + }).to(DriveDataToMap.class); + } + + }).getInstance(BindDriveDataToPlainTextString.class); + + public void testSimple() { + HttpRequest request = new HttpRequest("POST", URI.create("https://host/drives/create")); + FN.bindToRequest(request, new DriveData.Builder().name("foo").size(100l).build()); + assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.TEXT_PLAIN); + assertEquals(request.getPayload().getRawContent(), "name foo\nsize 100"); + } + + public void testComplete() throws IOException { + DriveData input = new DriveData.Builder().name("Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + // + .size(8589934592l)// + .claimType(ClaimType.SHARED)// + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff"))// + .use(ImmutableSet.of("tag1", "tag2"))// + .build(); + + HttpRequest request = new HttpRequest("POST", URI.create("https://host/drives/create")); + FN.bindToRequest(request, input); + assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.TEXT_PLAIN); + assertEquals(request.getPayload().getRawContent(), + Utils.toStringAndClose(BindDriveDataToPlainTextStringTest.class.getResourceAsStream("/drive_data.txt"))); + + } +} \ No newline at end of file diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/binders/BindDriveToPlainTextStringTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/binders/BindDriveToPlainTextStringTest.java new file mode 100644 index 0000000000..ce81c41a37 --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/binders/BindDriveToPlainTextStringTest.java @@ -0,0 +1,91 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.binders; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.net.URI; +import java.util.Map; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.cloudsigma.domain.ClaimType; +import org.jclouds.cloudsigma.domain.CreateDriveRequest; +import org.jclouds.cloudsigma.domain.Drive; +import org.jclouds.cloudsigma.domain.DriveData; +import org.jclouds.cloudsigma.functions.BaseDriveToMap; +import org.jclouds.cloudsigma.functions.DriveDataToMap; +import org.jclouds.http.HttpRequest; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class BindDriveToPlainTextStringTest { + + private static final BindDriveToPlainTextString FN = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral>>() { + }).to(BaseDriveToMap.class); + bind(new TypeLiteral>>() { + }).to(DriveDataToMap.class); + } + + }).getInstance(BindDriveToPlainTextString.class); + + public void testSimple() { + HttpRequest request = new HttpRequest("POST", URI.create("https://host/drives/create")); + FN.bindToRequest(request, new CreateDriveRequest.Builder().name("foo").size(100l).build()); + assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.TEXT_PLAIN); + assertEquals(request.getPayload().getRawContent(), "name foo\nsize 100"); + } + + public void testComplete() throws IOException { + CreateDriveRequest input = new CreateDriveRequest.Builder() + .name("Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + // + .size(8589934592l)// + .claimType(ClaimType.SHARED)// + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff"))// + .use(ImmutableSet.of("tag1", "tag2"))// + .encryptionCipher("aes-xts-plain").avoid(ImmutableSet.of("avoid1")).build(); + + HttpRequest request = new HttpRequest("POST", URI.create("https://host/drives/create")); + FN.bindToRequest(request, input); + assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.TEXT_PLAIN); + assertEquals(request.getPayload().getRawContent(), + Utils.toStringAndClose(BindDriveToPlainTextStringTest.class + .getResourceAsStream("/create_drive.txt"))); + + } + +} \ No newline at end of file diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/binders/BindServerToPlainTextStringTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/binders/BindServerToPlainTextStringTest.java new file mode 100644 index 0000000000..548c7a251f --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/binders/BindServerToPlainTextStringTest.java @@ -0,0 +1,92 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.binders; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.net.URI; +import java.util.Map; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.cloudsigma.domain.IDEDevice; +import org.jclouds.cloudsigma.domain.Model; +import org.jclouds.cloudsigma.domain.NIC; +import org.jclouds.cloudsigma.domain.Server; +import org.jclouds.cloudsigma.domain.VNC; +import org.jclouds.cloudsigma.functions.ServerToMap; +import org.jclouds.http.HttpRequest; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class BindServerToPlainTextStringTest { + + public static String CREATED_SERVER; + static { + try { + CREATED_SERVER = Utils.toStringAndClose(BindServerToPlainTextStringTest.class + .getResourceAsStream("/create_server.txt")); + } catch (IOException e) { + CREATED_SERVER = null; + } + } + public static final Server SERVER = new Server.Builder() + .name("TestServer") + .cpu(2000) + .mem(1024) + .devices( + ImmutableMap.of("ide:0:0", new IDEDevice.Builder(0, 0).uuid("08c92dd5-70a0-4f51-83d2-835919d254df") + .build())).bootDeviceIds(ImmutableSet.of("ide:0:0")) + .nics(ImmutableSet.of(new NIC.Builder().model(Model.E1000). + + build())).vnc(new VNC(null, "XXXXXXXX", false)).build(); + private static final BindServerToPlainTextString FN = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral>>() { + }).to(ServerToMap.class); + bind(new TypeLiteral>>() { + }).to(ServerToMap.class); + } + + }).getInstance(BindServerToPlainTextString.class); + + public void testSimple() throws IOException { + HttpRequest request = new HttpRequest("POST", URI.create("https://host/drives/create")); + FN.bindToRequest(request, SERVER); + assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.TEXT_PLAIN); + assertEquals(request.getPayload().getRawContent(), CREATED_SERVER); + } + +} \ No newline at end of file diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/compute/CloudSigmaComputeServiceLiveTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/compute/CloudSigmaComputeServiceLiveTest.java new file mode 100644 index 0000000000..be182ee43d --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/compute/CloudSigmaComputeServiceLiveTest.java @@ -0,0 +1,39 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.compute; + +import org.jclouds.compute.BaseComputeServiceLiveTest; +import org.jclouds.ssh.jsch.config.JschSshClientModule; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "live") +public class CloudSigmaComputeServiceLiveTest extends BaseComputeServiceLiveTest { + public CloudSigmaComputeServiceLiveTest() { + provider = "cloudsigma"; + } + + @Override + protected JschSshClientModule getSshModule() { + return new JschSshClientModule(); + } + +} diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/compute/CloudSigmaTemplateBuilderLiveTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/compute/CloudSigmaTemplateBuilderLiveTest.java new file mode 100644 index 0000000000..d8237511c6 --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/compute/CloudSigmaTemplateBuilderLiveTest.java @@ -0,0 +1,56 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.compute; + +import org.jclouds.compute.BaseTemplateBuilderLiveTest; +import org.jclouds.compute.domain.OsFamily; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; +import org.testng.annotations.Test; + +import com.google.common.base.Predicate; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "live") +public class CloudSigmaTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest { + + public CloudSigmaTemplateBuilderLiveTest() { + provider = "cloudsigma"; + } + + @Override + protected Predicate defineUnsupportedOperatingSystems() { + return new Predicate() { + + @Override + public boolean apply(OsFamilyVersion64Bit input) { + return ((input.family == OsFamily.RHEL) || // + (input.family == OsFamily.CENTOS && !(input.version.equals("5.5") && input.is64Bit)) || // + (input.family == OsFamily.UBUNTU && !(input.version.matches("10.[01][04]") && input.is64Bit)) || // + (input.family == OsFamily.WINDOWS && !((input.version.equals("2008 R2") && input.is64Bit) + || (input.version.equals("2008") && !input.is64Bit) || (input.version.equals("2003")))) // + ); + } + + }; + } +} \ No newline at end of file diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/BaseDriveToMapTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/BaseDriveToMapTest.java new file mode 100644 index 0000000000..4c6e11e37c --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/BaseDriveToMapTest.java @@ -0,0 +1,64 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.cloudsigma.domain.ClaimType; +import org.jclouds.cloudsigma.domain.Drive; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class BaseDriveToMapTest { + + private static final BaseDriveToMap BASEDRIVE_TO_MAP = new BaseDriveToMap(); + + public void testBasics() { + assertEquals(BASEDRIVE_TO_MAP.apply(new Drive.Builder().name("foo").size(100l).build()), + ImmutableMap.of("name", "foo", "size", "100")); + } + + public void testComplete() throws IOException { + Drive one = new Drive.Builder().name("Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + // + .size(8589934592l)// + .claimType(ClaimType.SHARED)// + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff"))// + .use(ImmutableSet.of("tag1", "tag2"))// + .build(); + assertEquals( + BASEDRIVE_TO_MAP.apply(one), + ImmutableMap.builder().put("name", "Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + .put("size", "8589934592").put("claim:type", "shared") + .put("readers", "ffffffff-ffff-ffff-ffff-ffffffffffff").put("use", "tag1 tag2").build() + + ); + + } +} \ No newline at end of file diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/DriveDataToMapTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/DriveDataToMapTest.java new file mode 100644 index 0000000000..24a4b00f77 --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/DriveDataToMapTest.java @@ -0,0 +1,65 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; + +import org.jclouds.cloudsigma.domain.ClaimType; +import org.jclouds.cloudsigma.domain.DriveData; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class DriveDataToMapTest { + + private static final DriveDataToMap BASEDRIVE_TO_MAP = Guice.createInjector().getInstance(DriveDataToMap.class); + + public void testBasics() { + assertEquals(BASEDRIVE_TO_MAP.apply(new DriveData.Builder().name("foo").size(100l).build()), + ImmutableMap.of("name", "foo", "size", "100")); + } + + public void testComplete() throws IOException { + DriveData one = new DriveData.Builder().name("Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + // + .size(8589934592l)// + .claimType(ClaimType.SHARED)// + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff"))// + .use(ImmutableSet.of("tag1", "tag2"))// + .build(); + assertEquals( + BASEDRIVE_TO_MAP.apply(one), + ImmutableMap.builder().put("name", "Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") + .put("size", "8589934592").put("claim:type", "shared") + .put("readers", "ffffffff-ffff-ffff-ffff-ffffffffffff").put("use", "tag1 tag2").build() + + ); + + } +} \ No newline at end of file diff --git a/sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java similarity index 100% rename from sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java rename to cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToServerInfoTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToServerInfoTest.java new file mode 100644 index 0000000000..62eadbf8ef --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/KeyValuesDelimitedByBlankLinesToServerInfoTest.java @@ -0,0 +1,81 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import static org.testng.Assert.assertEquals; + +import java.util.List; +import java.util.Map; + +import org.jclouds.cloudsigma.domain.Device; +import org.jclouds.cloudsigma.domain.DriveMetrics; +import org.jclouds.cloudsigma.domain.NIC; +import org.jclouds.cloudsigma.domain.ServerMetrics; +import org.jclouds.cloudsigma.functions.MapToDevices.DeviceToId; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class KeyValuesDelimitedByBlankLinesToServerInfoTest { + + private static final KeyValuesDelimitedByBlankLinesToServerInfo FN = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral, List>>() { + }).to(MapToNICs.class); + bind(new TypeLiteral, Map>>() { + }).to(MapToDevices.class); + bind(new TypeLiteral, Map>>() { + }).to(MapToDriveMetrics.class); + bind(new TypeLiteral, ServerMetrics>>() { + }).to(MapToServerMetrics.class); + bind(new TypeLiteral>() { + }).to(DeviceToId.class); + } + + }).getInstance(KeyValuesDelimitedByBlankLinesToServerInfo.class); + + public void testNone() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newStringPayload(""))), null); + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newStringPayload("\n\n"))), null); + assertEquals(FN.apply(new HttpResponse(200, "", null)), null); + } + + public void testOne() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newInputStreamPayload(MapToServerInfoTest.class + .getResourceAsStream("/servers.txt")))), MapToServerInfoTest.ONE); + } + + public void testNew() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newInputStreamPayload(MapToServerInfoTest.class + .getResourceAsStream("/new_server.txt")))), MapToServerInfoTest.NEW); + } +} \ No newline at end of file diff --git a/sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java similarity index 100% rename from sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java rename to cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest.java new file mode 100644 index 0000000000..1a5bb428ff --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest.java @@ -0,0 +1,66 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import static org.testng.Assert.assertEquals; + +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest { + + private static final ListOfKeyValuesDelimitedByBlankLinesToListOfMaps FN = new ListOfKeyValuesDelimitedByBlankLinesToListOfMaps(); + + public void testNone() { + assertEquals(FN.apply(""), Lists.newArrayList()); + assertEquals(FN.apply("\n\n\n"), Lists.newArrayList()); + } + + public void testOneMap() { + assertEquals(FN.apply("key1 value1\nkey2 value2"), + ImmutableList.of(ImmutableMap.of("key1", "value1", "key2", "value2"))); + assertEquals(FN.apply("key1 value1\nkey2 value2\n\n"), + ImmutableList.of(ImmutableMap.of("key1", "value1", "key2", "value2"))); + } + + public void testValueEncodesNewlines() { + assertEquals(FN.apply("key1 value1\\n\nkey2 value2"), + ImmutableList.of(ImmutableMap.of("key1", "value1\n", "key2", "value2"))); + } + + public void testTwoMaps() { + assertEquals( + FN.apply("key1 value1\nkey2 value2\n\nkey1 v1\nkey2 v2"), + ImmutableList.of(ImmutableMap.of("key1", "value1", "key2", "value2"), + ImmutableMap.of("key1", "v1", "key2", "v2"))); + assertEquals( + FN.apply("key1 value1\nkey2 value2\n\nkey1 v1\nkey2 v2\n\n"), + ImmutableList.of(ImmutableMap.of("key1", "value1", "key2", "value2"), + ImmutableMap.of("key1", "v1", "key2", "v2"))); + } +} \ No newline at end of file diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSetTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSetTest.java new file mode 100644 index 0000000000..90cd45cbbd --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSetTest.java @@ -0,0 +1,81 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import static org.testng.Assert.assertEquals; + +import java.util.List; +import java.util.Map; + +import org.jclouds.cloudsigma.domain.Device; +import org.jclouds.cloudsigma.domain.DriveMetrics; +import org.jclouds.cloudsigma.domain.NIC; +import org.jclouds.cloudsigma.domain.ServerInfo; +import org.jclouds.cloudsigma.domain.ServerMetrics; +import org.jclouds.cloudsigma.functions.MapToDevices.DeviceToId; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class ListOfKeyValuesDelimitedByBlankLinesToServerInfoSetTest { + + private static final ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet FN = Guice.createInjector( + new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral, List>>() { + }).to(MapToNICs.class); + bind(new TypeLiteral, Map>>() { + }).to(MapToDevices.class); + bind(new TypeLiteral, Map>>() { + }).to(MapToDriveMetrics.class); + bind(new TypeLiteral, ServerMetrics>>() { + }).to(MapToServerMetrics.class); + bind(new TypeLiteral>() { + }).to(DeviceToId.class); + } + + }).getInstance(ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.class); + + public void testNone() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newStringPayload(""))), ImmutableSet. of()); + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newStringPayload("\n\n"))), + ImmutableSet. of()); + assertEquals(FN.apply(new HttpResponse(200, "", null)), ImmutableSet. of()); + } + + public void testOne() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newInputStreamPayload(MapToServerInfoTest.class + .getResourceAsStream("/servers.txt")))), ImmutableSet. of(MapToServerInfoTest.ONE, + MapToServerInfoTest.TWO)); + } +} \ No newline at end of file diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest.java new file mode 100644 index 0000000000..fce825382c --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest.java @@ -0,0 +1,60 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import static org.testng.Assert.assertEquals; + +import java.util.Map; + +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest { + + private static final ListOfMapsToListOfKeyValuesDelimitedByBlankLines FN = new ListOfMapsToListOfKeyValuesDelimitedByBlankLines(); + + public void testNone() { + assertEquals(FN.apply(ImmutableList.> of()), ""); + } + + public void testOneMap() { + assertEquals( + FN.apply(ImmutableList.> of(ImmutableMap.of("key1", "value1", "key2", "value2"))), + "key1 value1\nkey2 value2"); + } + + public void testValueEncodesNewlines() { + assertEquals( + FN.apply(ImmutableList.> of(ImmutableMap.of("key1", "value1\n", "key2", "value2"))), + "key1 value1\\n\nkey2 value2"); + } + + public void testTwoMaps() { + assertEquals(FN.apply(ImmutableList.> of(ImmutableMap.of("key1", "value1", "key2", "value2"), + ImmutableMap.of("key1", "v1", "key2", "v2"))), "key1 value1\nkey2 value2\n\nkey1 v1\nkey2 v2"); + } +} \ No newline at end of file diff --git a/sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/MapToDriveInfoTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/MapToDriveInfoTest.java similarity index 89% rename from sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/MapToDriveInfoTest.java rename to cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/MapToDriveInfoTest.java index e630bf4572..f3ca0396d6 100644 --- a/sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/MapToDriveInfoTest.java +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/MapToDriveInfoTest.java @@ -25,12 +25,11 @@ import java.io.IOException; import java.net.URI; import java.util.Map; +import org.jclouds.cloudsigma.domain.ClaimType; import org.jclouds.cloudsigma.domain.DriveInfo; +import org.jclouds.cloudsigma.domain.DriveMetrics; +import org.jclouds.cloudsigma.domain.DriveStatus; import org.jclouds.cloudsigma.domain.DriveType; -import org.jclouds.elasticstack.domain.ClaimType; -import org.jclouds.elasticstack.domain.DriveMetrics; -import org.jclouds.elasticstack.domain.DriveStatus; -import org.jclouds.elasticstack.functions.ListOfKeyValuesDelimitedByBlankLinesToListOfMaps; import org.jclouds.util.Utils; import org.testng.annotations.Test; @@ -45,7 +44,7 @@ import com.google.common.collect.ImmutableSet; public class MapToDriveInfoTest { public static DriveInfo ONE = new DriveInfo.Builder() .status(DriveStatus.ACTIVE) - .tags(ImmutableSet.of("networking", "security", "gateway")) + .use(ImmutableSet.of("networking", "security", "gateway")) .name("Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System") .bits(64) .url(URI.create("http://www.ubuntu.com")) @@ -72,10 +71,9 @@ public class MapToDriveInfoTest { .free(true)// .type(DriveType.DISK)// .size(8589934592l)// - .userMetadata(ImmutableMap.of("foo", "bar", "baz", "raz")).build(); + .build(); - private static final MapToDriveInfo MAP_TO_DRIVE = new MapToDriveInfo( - new org.jclouds.elasticstack.functions.MapToDriveInfo()); + private static final MapToDriveInfo MAP_TO_DRIVE = new MapToDriveInfo(); public void testEmptyMapReturnsNull() { assertEquals(MAP_TO_DRIVE.apply(ImmutableMap. of()), null); diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/MapToServerInfoTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/MapToServerInfoTest.java new file mode 100644 index 0000000000..d7fe5a6ae8 --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/MapToServerInfoTest.java @@ -0,0 +1,162 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.util.Date; +import java.util.Map; + +import org.jclouds.cloudsigma.domain.DriveMetrics; +import org.jclouds.cloudsigma.domain.IDEDevice; +import org.jclouds.cloudsigma.domain.MediaType; +import org.jclouds.cloudsigma.domain.Model; +import org.jclouds.cloudsigma.domain.NIC; +import org.jclouds.cloudsigma.domain.ServerInfo; +import org.jclouds.cloudsigma.domain.ServerMetrics; +import org.jclouds.cloudsigma.domain.ServerStatus; +import org.jclouds.cloudsigma.domain.VNC; +import org.jclouds.cloudsigma.functions.MapToDevices.DeviceToId; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class MapToServerInfoTest { + public static ServerInfo ONE = new ServerInfo.Builder() + .persistent(true) + .uuid("f8bee9cd-8e4b-4a05-8593-1314e3bfe49b") + .cpu(2000) + .bootDeviceIds(ImmutableSet.of("ide:0:0")) + .smp(1) + .mem(1024) + .status(ServerStatus.ACTIVE) + .started(new Date(1291493868l)) + .user("2f6244eb-50bc-4403-847e-f03cc3706a1f") + .name("jo") + .vnc(new VNC("46.20.114.124", "HfHzVmLT", false)) + .nics(ImmutableSet.of(new NIC.Builder() + .model(Model.E1000) + .dhcp("46.20.114.124") + .block( + ImmutableList.of("tcp/43594", "tcp/5902", "udp/5060", "tcp/5900", "tcp/5901", "tcp/21", "tcp/22", + "tcp/23", "tcp/25", "tcp/110", "tcp/143", "tcp/43595")).build())) + .devices( + ImmutableMap.of("ide:0:0", + new IDEDevice.Builder((int) 0, (int) 0).uuid("4af85ed3-0caa-4736-8a26-a33d7de0a122").build() + + )) + .metrics( + new ServerMetrics.Builder() + .tx(2550) + .txPackets(31) + .rx(455530) + .rxPackets(7583) + .driveMetrics( + ImmutableMap.of("ide:0:0", new DriveMetrics.Builder().readRequests(11154) + .readBytes(45686784).writeRequests(3698).writeBytes(15147008).build())).build()) + .build(); + + public static ServerInfo TWO = new ServerInfo.Builder() + .status(ServerStatus.STOPPED) + .name("Demo") + .mem(1024) + .cpu(2000) + .persistent(true) + .uuid("0f962616-2071-4173-be79-7dd084271edf") + .bootDeviceIds(ImmutableSet.of("ide:0:0")) + .user("2f6244eb-50bc-4403-847e-f03cc3706a1f") + .vnc(new VNC("auto", "HWbjvrg2", false)) + .nics(ImmutableSet.of(new NIC.Builder().model(Model.E1000).dhcp("auto").build())) + .devices( + ImmutableMap.of( + "ide:0:0", + new IDEDevice.Builder((int) 0, (int) 0).uuid("853bb98a-4fff-4c2f-a265-97c363f19ea5") + .mediaType(MediaType.CDROM).build())) + .metrics( + new ServerMetrics.Builder().driveMetrics(ImmutableMap.of("ide:0:0", new DriveMetrics.Builder().build())) + .build()).build(); + + private static final MapToServerInfo MAP_TO_DRIVE = new MapToServerInfo(new MapToDevices(new DeviceToId()), + new MapToServerMetrics(new MapToDriveMetrics()), new MapToNICs()); + + public void testEmptyMapReturnsNull() { + assertEquals(MAP_TO_DRIVE.apply(ImmutableMap. of()), null); + } + + public void testBasics() { + ServerInfo expects = new ServerInfo.Builder().name("foo").uuid("hello").vnc(new VNC("auto", null, false)) + .cpu(1000).mem(2048).metrics(new ServerMetrics.Builder().build()).build(); + assertEquals(MAP_TO_DRIVE.apply(ImmutableMap.of("name", "foo", "server", "hello", "vnc:ip", "auto", "cpu", + "1000", "mem", "2048")), expects); + } + + public void testComplete() throws IOException { + + Map input = new ListOfKeyValuesDelimitedByBlankLinesToListOfMaps().apply( + Utils.toStringAndClose(MapToServerInfoTest.class.getResourceAsStream("/servers.txt"))).get(0); + + assertEquals(MAP_TO_DRIVE.apply(input), ONE); + + } + + public static ServerInfo NEW = new ServerInfo.Builder() + .persistent(true) + .uuid("bd98615a-6f74-4d63-ad1e-b13338b9356a") + .cpu(1000) + .bootDeviceIds(ImmutableSet.of("ide:0:0")) + .smp(1) + .mem(512) + .status(ServerStatus.ACTIVE) + .started(new Date(1292695612)) + .user("2f6244eb-50bc-4403-847e-f03cc3706a1f") + .name("adriancole.test") + .vnc(new VNC("83.222.249.221", "XXXXXXXX", false)) + .nics(ImmutableSet.of(new NIC.Builder() + .model(Model.E1000) + .block( + ImmutableList.of("tcp/43594", "tcp/5902", "udp/5060", "tcp/5900", "tcp/5901", "tcp/21", "tcp/22", + "tcp/23", "tcp/25", "tcp/110", "tcp/143", "tcp/43595")).build())) + .devices( + ImmutableMap.of("ide:0:0", + new IDEDevice.Builder((int) 0, (int) 0).uuid("403c9a86-0aab-4e47-aa95-e9768021c4c1").build() + + )) + .metrics( + new ServerMetrics.Builder().driveMetrics(ImmutableMap.of("ide:0:0", new DriveMetrics.Builder().build())) + .build()).build(); + + public void testNew() throws IOException { + + Map input = new ListOfKeyValuesDelimitedByBlankLinesToListOfMaps().apply( + Utils.toStringAndClose(MapToServerInfoTest.class.getResourceAsStream("/new_server.txt"))).get(0); + + assertEquals(MAP_TO_DRIVE.apply(input), NEW); + + } +} \ No newline at end of file diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ParseOsFamilyVersion64BitFromImageNameTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ParseOsFamilyVersion64BitFromImageNameTest.java new file mode 100644 index 0000000000..d31e5129df --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ParseOsFamilyVersion64BitFromImageNameTest.java @@ -0,0 +1,75 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.Lists.newArrayList; +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.Map.Entry; + +import org.jclouds.cloudsigma.compute.functions.ParseOsFamilyVersion64BitFromImageName; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; +import org.jclouds.json.Json; +import org.jclouds.json.internal.GsonWrapper; +import org.jclouds.util.Utils; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.gson.Gson; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ParseOsFamilyVersion64BitFromImageNameTest { + Json json = new GsonWrapper(new Gson()); + + @DataProvider(name = "data") + public Object[][] createData() throws IOException { + InputStream is = ParseOsFamilyVersion64BitFromImageNameTest.class.getResourceAsStream("/osmatches.json"); + Map values = json.fromJson(Utils.toStringAndClose(is), + new TypeLiteral>() { + }.getType()); + + return newArrayList( + transform(values.entrySet(), new Function, Object[]>() { + + @Override + public Object[] apply(Entry input) { + return new Object[] { input.getKey(), input.getValue() }; + } + + })).toArray(new Object[][] {}); + } + + ParseOsFamilyVersion64BitFromImageName parser = new ParseOsFamilyVersion64BitFromImageName(); + + @Test(dataProvider = "data") + public void test(String input, OsFamilyVersion64Bit expected) { + assertEquals(parser.apply(input), expected); + } +} diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ServerToMapTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ServerToMapTest.java new file mode 100644 index 0000000000..16d63f2222 --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/ServerToMapTest.java @@ -0,0 +1,66 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.functions; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.cloudsigma.domain.IDEDevice; +import org.jclouds.cloudsigma.domain.Model; +import org.jclouds.cloudsigma.domain.NIC; +import org.jclouds.cloudsigma.domain.Server; +import org.jclouds.cloudsigma.domain.VNC; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class ServerToMapTest { + + private static final ServerToMap SERVER_TO_MAP = new ServerToMap(); + + public void testBasics() { + assertEquals( + SERVER_TO_MAP.apply(new Server.Builder() + .name("TestServer") + .cpu(2000) + .mem(1024) + .devices( + ImmutableMap.of("ide:0:0", + new IDEDevice.Builder(0, 0).uuid("08c92dd5-70a0-4f51-83d2-835919d254df").build())) + .bootDeviceIds(ImmutableSet.of("ide:0:0")).nics(ImmutableSet.of(new NIC.Builder().model(Model.E1000). + + build())).vnc(new VNC(null, "XXXXXXXX", false)).build()), + ImmutableMap + .builder() + .putAll(ImmutableMap.of("name", "TestServer", "cpu", "2000", "smp", "auto", "mem", "1024")) + .putAll( + ImmutableMap.of("persistent", "false", "boot", "ide:0:0", "ide:0:0", + "08c92dd5-70a0-4f51-83d2-835919d254df")) + .putAll( + ImmutableMap.of("ide:0:0:media", "disk", "nic:0:model", "e1000", "vnc:ip", "auto", + "vnc:password", "XXXXXXXX")).build()); + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindReadDriveOptionsToPathTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/SplitNewlinesTest.java similarity index 50% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindReadDriveOptionsToPathTest.java rename to cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/SplitNewlinesTest.java index d7d9701b6c..f595c0647b 100644 --- a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindReadDriveOptionsToPathTest.java +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/functions/SplitNewlinesTest.java @@ -17,35 +17,38 @@ * ==================================================================== */ -package org.jclouds.elasticstack.binders; +package org.jclouds.cloudsigma.functions; import static org.testng.Assert.assertEquals; -import java.net.URI; +import java.io.InputStream; +import java.util.Set; -import org.jclouds.elasticstack.options.ReadDriveOptions; -import org.jclouds.http.HttpRequest; -import org.jclouds.logging.config.NullLoggingModule; -import org.jclouds.rest.BaseRestClientTest.MockModule; -import org.jclouds.rest.config.RestModule; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; import org.testng.annotations.Test; +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSortedSet; import com.google.inject.Guice; /** + * Tests behavior of {@code NewlineDelimitedStringHandler} * * @author Adrian Cole */ -@Test(groups = { "unit" }) -public class BindReadDriveOptionsToPathTest { +@Test(groups = "unit") +public class SplitNewlinesTest { - private static final BindReadDriveOptionsToPath FN = Guice.createInjector(new RestModule(), new MockModule(), - new NullLoggingModule()).getInstance(BindReadDriveOptionsToPath.class); - - public void testSimple() { - HttpRequest request = new HttpRequest("POST", URI.create("https://drives/read")); - FN.bindToRequest(request, new ReadDriveOptions().offset(1024l).size(2048l)); - assertEquals(request.getEndpoint().getPath(), "/read/1024/2048"); + static Function> createParser() { + return Guice.createInjector().getInstance(SplitNewlines.class); } -} \ No newline at end of file + public void test() { + InputStream is = SplitNewlinesTest.class.getResourceAsStream("/uuids.txt"); + Set list = createParser().apply(new HttpResponse(200, "ok", Payloads.newInputStreamPayload(is))); + assertEquals(list, ImmutableSortedSet.of("7e8ab721-81c9-4cb9-a651-4cafbfe1501c", + "ea6a8fdb-dab3-4d06-86c2-41a5835e6ed9", "74744450-d338-4087-b3b8-59b505110a57")); + } + +} diff --git a/cloudsigma/src/test/java/org/jclouds/cloudsigma/handlers/CloudSigmaErrorHandlerTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/handlers/CloudSigmaErrorHandlerTest.java new file mode 100644 index 0000000000..d613f4532f --- /dev/null +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/handlers/CloudSigmaErrorHandlerTest.java @@ -0,0 +1,141 @@ +/** + * + * Copyright (C) 2010 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.cloudsigma.handlers; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.reportMatcher; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.easymock.classextension.EasyMock.verify; + +import java.net.URI; + +import org.easymock.IArgumentMatcher; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class CloudSigmaErrorHandlerTest { + + @Test + public void test400MakesIllegalArgumentException() { + assertCodeMakes("GET", URI.create("https://cloudsigma.com/foo"), 400, "", "Bad Request", + IllegalArgumentException.class); + } + + @Test + public void test400MakesResourceNotFoundExceptionOnInfo() { + assertCodeMakes("GET", URI.create("https://cloudsigma.com/foo/info"), 400, "", "", + ResourceNotFoundException.class); + } + + @Test + public void test400MakesResourceNotFoundExceptionOnMessageNotFound() { + assertCodeMakes( + "GET", + URI.create("https://cloudsigma.com/foo"), + 400, + "", + "errors:system Drive 8f9b42b1-26de-49ad-a3fd-d4fa06524339 could not be found. Please re-validate your entry.", + ResourceNotFoundException.class); + } + + @Test + public void test401MakesAuthorizationException() { + assertCodeMakes("GET", URI.create("https://cloudsigma.com/foo"), 401, "", "Unauthorized", + AuthorizationException.class); + } + + @Test + public void test404MakesResourceNotFoundException() { + assertCodeMakes("GET", URI.create("https://cloudsigma.com/foo"), 404, "", "Not Found", + ResourceNotFoundException.class); + } + + @Test + public void test405MakesIllegalArgumentException() { + assertCodeMakes("GET", URI.create("https://cloudsigma.com/foo"), 405, "", "Method Not Allowed", + IllegalArgumentException.class); + } + + @Test + public void test409MakesIllegalStateException() { + assertCodeMakes("GET", URI.create("https://cloudsigma.com/foo"), 409, "", "Conflict", + IllegalStateException.class); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content, + Class expected) { + assertCodeMakes(method, uri, statusCode, message, "text/xml", content, expected); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType, + String content, Class expected) { + + CloudSigmaErrorHandler function = Guice.createInjector().getInstance(CloudSigmaErrorHandler.class); + + HttpCommand command = createMock(HttpCommand.class); + HttpRequest request = new HttpRequest(method, uri); + HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Utils + .toInputStream(content))); + response.getPayload().getContentMetadata().setContentType(contentType); + + expect(command.getRequest()).andReturn(request).atLeastOnce(); + command.setException(classEq(expected)); + + replay(command); + + function.handleError(command, response); + + verify(command); + } + + public static Exception classEq(final Class in) { + reportMatcher(new IArgumentMatcher() { + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("classEq("); + buffer.append(in); + buffer.append(")"); + } + + @Override + public boolean matches(Object arg) { + return arg.getClass() == in; + } + + }); + return null; + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/options/ReadDriveOptionsTest.java b/cloudsigma/src/test/java/org/jclouds/cloudsigma/options/CloneDriveOptionsTest.java similarity index 50% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/options/ReadDriveOptionsTest.java rename to cloudsigma/src/test/java/org/jclouds/cloudsigma/options/CloneDriveOptionsTest.java index 3e4e4a3a38..960cb766fb 100644 --- a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/options/ReadDriveOptionsTest.java +++ b/cloudsigma/src/test/java/org/jclouds/cloudsigma/options/CloneDriveOptionsTest.java @@ -17,62 +17,38 @@ * ==================================================================== */ -package org.jclouds.elasticstack.options; +package org.jclouds.cloudsigma.options; -import static org.jclouds.elasticstack.options.ReadDriveOptions.Builder.offset; -import static org.jclouds.elasticstack.options.ReadDriveOptions.Builder.size; +import static org.jclouds.cloudsigma.options.CloneDriveOptions.Builder.size; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import org.testng.annotations.Test; /** - * Tests possible uses of ReadDriveOptions and ReadDriveOptions.Builder.* + * Tests possible uses of CloneDriveOptions and CloneDriveOptions.Builder.* * * @author Adrian Cole */ @Test(groups = "unit") -public class ReadDriveOptionsTest { - - @Test - public void testNullOffset() { - ReadDriveOptions options = new ReadDriveOptions(); - assertNull(options.getOffset()); - } - - @Test - public void testOffset() { - ReadDriveOptions options = new ReadDriveOptions().offset(1024); - assertEquals(options.getOffset(), new Long(1024)); - } - - @Test - public void testOffsetStatic() { - ReadDriveOptions options = offset(1024); - assertEquals(options.getOffset(), new Long(1024)); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void testOffsetNegative() { - offset(-1); - } +public class CloneDriveOptionsTest { @Test public void testNullSize() { - ReadDriveOptions options = new ReadDriveOptions(); - assertNull(options.getSize()); + CloneDriveOptions options = new CloneDriveOptions(); + assertNull(options.getOptions().get("size")); } @Test public void testSize() { - ReadDriveOptions options = new ReadDriveOptions().size(1024); - assertEquals(options.getSize(), new Long(1024)); + CloneDriveOptions options = new CloneDriveOptions().size(1024); + assertEquals(options.getOptions().get("size"), "1024"); } @Test public void testSizeStatic() { - ReadDriveOptions options = size(1024); - assertEquals(options.getSize(), new Long(1024)); + CloneDriveOptions options = size(1024); + assertEquals(options.getOptions().get("size"), "1024"); } @Test(expectedExceptions = IllegalArgumentException.class) diff --git a/cloudsigma/src/test/resources/create_drive.txt b/cloudsigma/src/test/resources/create_drive.txt new file mode 100644 index 0000000000..44ce187567 --- /dev/null +++ b/cloudsigma/src/test/resources/create_drive.txt @@ -0,0 +1,5 @@ +name Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System +size 8589934592 +claim:type shared +readers ffffffff-ffff-ffff-ffff-ffffffffffff +use tag1 tag2 \ No newline at end of file diff --git a/cloudsigma/src/test/resources/create_server.txt b/cloudsigma/src/test/resources/create_server.txt new file mode 100644 index 0000000000..474d4d7ce1 --- /dev/null +++ b/cloudsigma/src/test/resources/create_server.txt @@ -0,0 +1,11 @@ +name TestServer +cpu 2000 +smp auto +mem 1024 +persistent false +boot ide:0:0 +ide:0:0 08c92dd5-70a0-4f51-83d2-835919d254df +ide:0:0:media disk +nic:0:model e1000 +vnc:ip auto +vnc:password XXXXXXXX \ No newline at end of file diff --git a/sandbox/cloudsigma/src/test/resources/drive.txt b/cloudsigma/src/test/resources/drive.txt similarity index 97% rename from sandbox/cloudsigma/src/test/resources/drive.txt rename to cloudsigma/src/test/resources/drive.txt index 04372bb776..63abfc8f14 100644 --- a/sandbox/cloudsigma/src/test/resources/drive.txt +++ b/cloudsigma/src/test/resources/drive.txt @@ -1,5 +1,5 @@ status active -use networking,security,gateway +use networking security gateway name Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System bits 64 url http://www.ubuntu.com diff --git a/cloudsigma/src/test/resources/drive_data.txt b/cloudsigma/src/test/resources/drive_data.txt new file mode 100644 index 0000000000..44ce187567 --- /dev/null +++ b/cloudsigma/src/test/resources/drive_data.txt @@ -0,0 +1,5 @@ +name Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System +size 8589934592 +claim:type shared +readers ffffffff-ffff-ffff-ffff-ffffffffffff +use tag1 tag2 \ No newline at end of file diff --git a/cloudsigma/src/test/resources/log4j.xml b/cloudsigma/src/test/resources/log4j.xml new file mode 100644 index 0000000000..7343ec00e2 --- /dev/null +++ b/cloudsigma/src/test/resources/log4j.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/cloudsigma/src/test/resources/new_server.txt b/cloudsigma/src/test/resources/new_server.txt new file mode 100644 index 0000000000..1dfbad99eb --- /dev/null +++ b/cloudsigma/src/test/resources/new_server.txt @@ -0,0 +1,24 @@ +ide:0:0:write:requests 0 +boot ide:0:0 +vnc:password XXXXXXXX +ide:0:0 403c9a86-0aab-4e47-aa95-e9768021c4c1 +ide:0:0:read:requests 0 +ide:0:0:read:bytes 0 +vnc:ip 83.222.249.221 +tx:packets 0 +tx 0 +rx 0 +smp 1 +mem 512 +nic:0:model e1000 +status active +started 1292695612 +rx:packets 0 +user 2f6244eb-50bc-4403-847e-f03cc3706a1f +ide:0:0:media disk +name adriancole.test +persistent true +nic:0:block tcp/43594 tcp/5902 udp/5060 tcp/5900 tcp/5901 tcp/21 tcp/22 tcp/23 tcp/25 tcp/110 tcp/143 tcp/43595 +server bd98615a-6f74-4d63-ad1e-b13338b9356a +ide:0:0:write:bytes 0 +cpu 1000 \ No newline at end of file diff --git a/cloudsigma/src/test/resources/osmatches.json b/cloudsigma/src/test/resources/osmatches.json new file mode 100644 index 0000000000..963b533fc5 --- /dev/null +++ b/cloudsigma/src/test/resources/osmatches.json @@ -0,0 +1,140 @@ +{ + + "Ubuntu 10.04 Server Edition Linux 64bit with Plesk": { + "family": "UBUNTU", + "version": "10.04", + "is64Bit": true + }, + + "CentOS 5.5 Linux 64bit Preinstalled System": { + "family": "CENTOS", + "version": "5.5", + "is64Bit": true + }, + + "Windows Server Standard 2008 R2 64bit English": { + "family": "WINDOWS", + "version": "2008 R2", + "is64Bit": true + }, + + "Ubuntu 10.04 Server Edition Linux 64bit": { + "family": "UBUNTU", + "version": "10.04", + "is64Bit": true + }, + + "Windows Server 2008 Standard 32bit English": { + "family": "WINDOWS", + "version": "2008", + "is64Bit": false + }, + + "Windows Server 2008 Standard 32bit English pub": { + "family": "WINDOWS", + "version": "2008", + "is64Bit": false + }, + + + "Fedora 14 Linux 64bit Preinstalled System": { + "family": "FEDORA", + "version": "14", + "is64Bit": true + }, + + "CentOS 5.5 Linux 64bit Preinstalled System with AppFirst Monitoring pub": { + "family": "CENTOS", + "version": "5.5", + "is64Bit": true + }, + + + "Ubuntu 10.10 Server Edition LAMP Linux 64bit Preinstalled System": { + "family": "UBUNTU", + "version": "10.10", + "is64Bit": true + }, + + "Ubuntu 10.10 Server Edition Linux 64bit Preinstalled System": { + "family": "UBUNTU", + "version": "10.10", + "is64Bit": true + }, + + "Windows Server Web 2008 R2 64bit English": { + "family": "WINDOWS", + "version": "2008 R2", + "is64Bit": true + }, + + + "SQL Server Standard 2008 R2 - Windows Server Standard 2008 R2 - 64bit English": { + "family": "WINDOWS", + "version": "2008 R2", + "is64Bit": true + }, + + + "Ubuntu 10.10 Desktop Edition 64bit Preinstalled System": { + "family": "UBUNTU", + "version": "10.10", + "is64Bit": true + }, + + "Ubuntu 10.04 Desktop Edition Linux 64bit Preinstalled System": { + "family": "UBUNTU", + "version": "10.04", + "is64Bit": true + }, + + "Debian 5.0 Preinstalled": { + "family": "DEBIAN", + "version": "5.0", + "is64Bit": true + }, + + "pfSense 2.0 BETA4-20101127-031119 Preinstalled System": { + "family": "UNRECOGNIZED", + "version": null, + "is64Bit": true + }, + + "FreeBSD 8.1 Preinstalled Base System": { + "family": "FREEBSD", + "version": "8.1", + "is64Bit": true + }, + + "CentOS 5.5 Linux 64bit Preinstalled System with AppFirst Monitoring": { + "family": "CENTOS", + "version": "5.5", + "is64Bit": true + }, + + "Fedora 13 Linux 64bit Preinstalled System": { + "family": "FEDORA", + "version": "13", + "is64Bit": true + }, + + "Windows Server 2003 Standard 32bit English": { + "family": "WINDOWS", + "version": "2003", + "is64Bit": false + }, + + "Windows Server 2003 Standard 64bit English": { + "family": "WINDOWS", + "version": "2003", + "is64Bit": true + }, + + "Debian 5.0 Preinstalled without X": { + "family": "DEBIAN", + "version": "5.0", + "is64Bit": true + } + + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/resources/servers.txt b/cloudsigma/src/test/resources/servers.txt similarity index 100% rename from sandbox/elasticstack/src/test/resources/servers.txt rename to cloudsigma/src/test/resources/servers.txt diff --git a/sandbox/elasticstack/src/test/resources/uuids.txt b/cloudsigma/src/test/resources/uuids.txt similarity index 100% rename from sandbox/elasticstack/src/test/resources/uuids.txt rename to cloudsigma/src/test/resources/uuids.txt diff --git a/compute/src/main/clojure/org/jclouds/compute.clj b/compute/src/main/clojure/org/jclouds/compute.clj index 0ee451a81a..e78dd3f697 100644 --- a/compute/src/main/clojure/org/jclouds/compute.clj +++ b/compute/src/main/clojure/org/jclouds/compute.clj @@ -22,7 +22,8 @@ Current supported services are: [ec2, rimuhosting, cloudservers, trmk-ecloud, trmk-vcloudexpress, vcloud, - bluelock, eucalyptus, slicehost] + bluelock, eucalyptus, slicehost, elastichosts-lon-p, elastichosts-sat-p, + elastichosts, elastichosts-lon-b, cloudsigma, stub] Here's an example of getting some compute configuration from rackspace: diff --git a/compute/src/main/clojure/org/jclouds/modules.clj b/compute/src/main/clojure/org/jclouds/modules.clj index a8d3ceda81..f49e6a9d5c 100644 --- a/compute/src/main/clojure/org/jclouds/modules.clj +++ b/compute/src/main/clojure/org/jclouds/modules.clj @@ -34,7 +34,9 @@ (defn compute-module [] - (org.jclouds.compute.config.JCloudsNativeStandaloneComputeServiceContextModule + (org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule + (class ComputeService) + (class ComputeService) (defrecord ClojureComputeServiceAdapter [] org.jclouds.compute.JCloudsNativeComputeServiceAdapter (^NodeMetadata runNodeWithTagAndNameAndStoreCredentials [this ^String tag ^String name ^Template template ^Map credentialStore] diff --git a/compute/src/main/java/org/jclouds/compute/ComputeServiceAdapter.java b/compute/src/main/java/org/jclouds/compute/ComputeServiceAdapter.java index bf13254eaa..55ec6ad6b1 100644 --- a/compute/src/main/java/org/jclouds/compute/ComputeServiceAdapter.java +++ b/compute/src/main/java/org/jclouds/compute/ComputeServiceAdapter.java @@ -25,7 +25,7 @@ import org.jclouds.compute.domain.Template; import org.jclouds.domain.Credentials; /** - * A means of specifying the interface between the {@link ComputeServices} and a concrete compute + * A means of specifying the interface between the {@link ComputeService ComputeServices} and a concrete compute * cloud implementation, jclouds or otherwise. * * @author Adrian Cole diff --git a/compute/src/main/java/org/jclouds/compute/config/StandaloneComputeServiceContextModule.java b/compute/src/main/java/org/jclouds/compute/config/ComputeServiceAdapterContextModule.java similarity index 87% rename from compute/src/main/java/org/jclouds/compute/config/StandaloneComputeServiceContextModule.java rename to compute/src/main/java/org/jclouds/compute/config/ComputeServiceAdapterContextModule.java index d9788657d5..160b147d84 100644 --- a/compute/src/main/java/org/jclouds/compute/config/StandaloneComputeServiceContextModule.java +++ b/compute/src/main/java/org/jclouds/compute/config/ComputeServiceAdapterContextModule.java @@ -27,7 +27,6 @@ import java.util.Set; import javax.inject.Singleton; -import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.domain.Hardware; @@ -49,20 +48,30 @@ import com.google.common.base.Supplier; import com.google.inject.Provides; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; +import com.google.inject.util.Types; /** * * @author Adrian Cole */ -public class StandaloneComputeServiceContextModule extends BaseComputeServiceContextModule { +public class ComputeServiceAdapterContextModule extends BaseComputeServiceContextModule { + private Class asyncClientType; + private Class syncClientType; + + public ComputeServiceAdapterContextModule(Class syncClientType, Class asyncClientType) { + this.syncClientType = syncClientType; + this.asyncClientType = asyncClientType; + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override protected void configure() { super.configure(); bindDefaultLocation(); bind(new TypeLiteral() { - }).to(new TypeLiteral>() { - }).in(Scopes.SINGLETON); + }).to((TypeLiteral) TypeLiteral.get(Types.newParameterizedType(ComputeServiceContextImpl.class, syncClientType, + asyncClientType))).in(Scopes.SINGLETON); } public class TransformingSetSupplier implements Supplier> { @@ -84,7 +93,7 @@ public class StandaloneComputeServiceContextModule extends BaseCompu @Provides @Singleton protected Supplier> provideHardware(final ComputeServiceAdapter adapter, - Function transformer) { + Function transformer) { return new TransformingSetSupplier(new Supplier>() { @Override @@ -98,7 +107,7 @@ public class StandaloneComputeServiceContextModule extends BaseCompu @Provides @Singleton protected Supplier> provideImages(final ComputeServiceAdapter adapter, - Function transformer) { + Function transformer) { return new TransformingSetSupplier(new Supplier>() { @Override @@ -117,7 +126,7 @@ public class StandaloneComputeServiceContextModule extends BaseCompu @Provides @Singleton protected Supplier> provideLocations(final ComputeServiceAdapter adapter, - Function transformer) { + Function transformer) { return new TransformingSetSupplier(new Supplier>() { @Override @@ -169,19 +178,4 @@ public class StandaloneComputeServiceContextModule extends BaseCompu protected SuspendNodeStrategy defineStopNodeStrategy(AdaptingComputeServiceStrategies in) { return in; } - - // enum singleton pattern - public static enum IdentityFunction implements Function { - INSTANCE; - - public Object apply(Object o) { - return o; - } - - @Override - public String toString() { - return "identity"; - } - } - } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/compute/config/JCloudsNativeStandaloneComputeServiceContextModule.java b/compute/src/main/java/org/jclouds/compute/config/JCloudsNativeComputeServiceAdapterContextModule.java similarity index 68% rename from compute/src/main/java/org/jclouds/compute/config/JCloudsNativeStandaloneComputeServiceContextModule.java rename to compute/src/main/java/org/jclouds/compute/config/JCloudsNativeComputeServiceAdapterContextModule.java index 48502b3c89..507f03c248 100644 --- a/compute/src/main/java/org/jclouds/compute/config/JCloudsNativeStandaloneComputeServiceContextModule.java +++ b/compute/src/main/java/org/jclouds/compute/config/JCloudsNativeComputeServiceAdapterContextModule.java @@ -32,12 +32,13 @@ import com.google.inject.TypeLiteral; * * @author Adrian Cole */ -public class JCloudsNativeStandaloneComputeServiceContextModule extends - StandaloneComputeServiceContextModule { - private final Class> adapter; +public class JCloudsNativeComputeServiceAdapterContextModule extends + ComputeServiceAdapterContextModule { + protected final Class> adapter; - public JCloudsNativeStandaloneComputeServiceContextModule( + public JCloudsNativeComputeServiceAdapterContextModule(Class syncClientType, Class asyncClientType, Class> adapter) { + super(syncClientType, asyncClientType); this.adapter = adapter; } @@ -52,14 +53,28 @@ public class JCloudsNativeStandaloneComputeServiceContextModule extends }).to(adapter); bind(IdentityFunction.class).toInstance(IdentityFunction.INSTANCE); bind(new TypeLiteral>() { - }).to((Class) StandaloneComputeServiceContextModule.IdentityFunction.class); + }).to((Class) IdentityFunction.class); bind(new TypeLiteral>() { - }).to((Class) StandaloneComputeServiceContextModule.IdentityFunction.class); + }).to((Class) IdentityFunction.class); bind(new TypeLiteral>() { - }).to((Class) StandaloneComputeServiceContextModule.IdentityFunction.class); + }).to((Class) IdentityFunction.class); bind(new TypeLiteral>() { - }).to((Class) StandaloneComputeServiceContextModule.IdentityFunction.class); + }).to((Class) IdentityFunction.class); super.configure(); } + // enum singleton pattern + public static enum IdentityFunction implements Function { + INSTANCE; + + public Object apply(Object o) { + return o; + } + + @Override + public String toString() { + return "identity"; + } + } + } \ No newline at end of file diff --git a/compute/src/test/java/org/jclouds/compute/OsFamilyVersion64Bit.java b/compute/src/main/java/org/jclouds/compute/domain/os/OsFamilyVersion64Bit.java similarity index 90% rename from compute/src/test/java/org/jclouds/compute/OsFamilyVersion64Bit.java rename to compute/src/main/java/org/jclouds/compute/domain/os/OsFamilyVersion64Bit.java index a2f13d634c..e015b580e6 100644 --- a/compute/src/test/java/org/jclouds/compute/OsFamilyVersion64Bit.java +++ b/compute/src/main/java/org/jclouds/compute/domain/os/OsFamilyVersion64Bit.java @@ -17,14 +17,24 @@ * ==================================================================== */ -package org.jclouds.compute; +package org.jclouds.compute.domain.os; import org.jclouds.compute.domain.OsFamily; +/** + * + * @author Adrian Cole + * + */ public class OsFamilyVersion64Bit { - public final OsFamily family; - public final String version; - public final boolean is64Bit; + public OsFamily family; + public String version; + public boolean is64Bit; + + // for serialization + OsFamilyVersion64Bit() { + + } public OsFamilyVersion64Bit(OsFamily family, String version, boolean is64Bit) { this.family = family; diff --git a/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceContextModule.java b/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceContextModule.java index fe61f1df32..a9547a6192 100644 --- a/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceContextModule.java +++ b/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceContextModule.java @@ -23,7 +23,7 @@ import java.util.concurrent.ConcurrentMap; import javax.inject.Singleton; -import org.jclouds.compute.config.JCloudsNativeStandaloneComputeServiceContextModule; +import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.concurrent.SingleThreaded; @@ -33,21 +33,21 @@ import com.google.inject.Provides; * * @author Adrian Cole */ +@SuppressWarnings("rawtypes") @SingleThreaded -public class StubComputeServiceContextModule extends JCloudsNativeStandaloneComputeServiceContextModule { +public class StubComputeServiceContextModule extends + JCloudsNativeComputeServiceAdapterContextModule { public StubComputeServiceContextModule() { - super(StubComputeServiceAdapter.class); + super(ConcurrentMap.class, ConcurrentMap.class, StubComputeServiceAdapter.class); } - // Ensure that a plain class is able to be bound as getProviderSpecificContext.getApi() - @SuppressWarnings("rawtypes") @Provides @Singleton ConcurrentMap provideApi(ConcurrentMap in) { return in; } - + @Override protected void configure() { install(new StubComputeServiceDependenciesModule()); diff --git a/compute/src/main/java/org/jclouds/compute/suppliers/DefaultLocationSupplier.java b/compute/src/main/java/org/jclouds/compute/suppliers/DefaultLocationSupplier.java index 50d42c0847..974f230b9e 100644 --- a/compute/src/main/java/org/jclouds/compute/suppliers/DefaultLocationSupplier.java +++ b/compute/src/main/java/org/jclouds/compute/suppliers/DefaultLocationSupplier.java @@ -19,6 +19,9 @@ package org.jclouds.compute.suppliers; +import static com.google.common.collect.Iterables.find; +import static com.google.common.collect.Iterables.getOnlyElement; + import java.util.Set; import javax.inject.Inject; @@ -30,7 +33,6 @@ import org.jclouds.domain.LocationScope; import com.google.common.base.Predicate; import com.google.common.base.Supplier; -import com.google.common.collect.Iterables; /** * @@ -48,7 +50,9 @@ public class DefaultLocationSupplier implements Supplier { @Override public Location get() { - return Iterables.find(locations.get(), new Predicate() { + if (locations.get().size() == 1) + return getOnlyElement(locations.get()); + return find(locations.get(), new Predicate() { @Override public boolean apply(Location input) { diff --git a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java index 72b376e831..8a84eb71f9 100755 --- a/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/BaseComputeServiceLiveTest.java @@ -474,6 +474,7 @@ public abstract class BaseComputeServiceLiveTest { template = client.templateBuilder().options(blockOnComplete(false).blockOnPort(8080, 600).inboundPorts(22, 8080)) .build(); + // note this is a dependency on the template resolution template.getOptions().runScript( RunScriptData.createScriptInstallAndStartJBoss(keyPair.get("public"), template.getImage() diff --git a/compute/src/test/java/org/jclouds/compute/BaseTemplateBuilderLiveTest.java b/compute/src/test/java/org/jclouds/compute/BaseTemplateBuilderLiveTest.java index ddf8fcc2e6..a40c075c42 100644 --- a/compute/src/test/java/org/jclouds/compute/BaseTemplateBuilderLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/BaseTemplateBuilderLiveTest.java @@ -36,6 +36,7 @@ import org.jclouds.Constants; import org.jclouds.compute.config.BaseComputeServiceContextModule; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.json.Json; import org.jclouds.json.config.GsonModule; diff --git a/compute/src/test/java/org/jclouds/compute/RunScriptData.java b/compute/src/test/java/org/jclouds/compute/RunScriptData.java index f09d10b758..1907c8de55 100644 --- a/compute/src/test/java/org/jclouds/compute/RunScriptData.java +++ b/compute/src/test/java/org/jclouds/compute/RunScriptData.java @@ -33,6 +33,7 @@ import org.jclouds.compute.predicates.OperatingSystemPredicates; import org.jclouds.scriptbuilder.InitBuilder; import org.jclouds.scriptbuilder.domain.AuthorizeRSAPublicKey; import org.jclouds.scriptbuilder.domain.Statement; +import org.jclouds.scriptbuilder.domain.Statements; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -56,32 +57,34 @@ public class RunScriptData { throw new IllegalArgumentException("don't know how to handle" + os.toString()); } + public static Statement authorizePortInIpTables(int port) { + return Statements.newStatementList(// just in case iptables are being used, try to open 8080 + exec("iptables -I INPUT 1 -p tcp --dport " + port + " -j ACCEPT"),// + // TODO gogrid rules only allow ports 22, 3389, 80 and 443. + // the above rule will be ignored, so we have to apply this + // directly + exec("iptables -I RH-Firewall-1-INPUT 1 -p tcp --dport " + port + " -j ACCEPT"),// + exec("iptables-save")); + } + public static Statement createScriptInstallAndStartJBoss(String publicKey, OperatingSystem os) { Map envVariables = ImmutableMap.of("jbossHome", jbossHome); Statement toReturn = new InitBuilder( - "jboss", - jbossHome, - jbossHome, - envVariables, - ImmutableList - . of( - new AuthorizeRSAPublicKey(publicKey),// - installJavaAndCurl(os),// - // just in case iptables are being used, try to open 8080 - exec("iptables -I INPUT 1 -p tcp --dport 8080 -j ACCEPT"),// - // TODO gogrid rules only allow ports 22, 3389, 80 and 443. - // the above rule will be ignored, so we have to apply this - // directly - exec("iptables -I RH-Firewall-1-INPUT 1 -p tcp --dport 8080 -j ACCEPT"),// - exec("iptables-save"),// - extractTargzIntoDirectory( - URI - .create("http://commondatastorage.googleapis.com/jclouds-repo/jboss-as-distribution-6.0.0.20100911-M5.tar.gz"), - "/usr/local"), exec("{md} " + jbossHome), exec("mv /usr/local/jboss-*/* " - + jbossHome),// - exec("chmod -R oug+r+w " + jbossHome)),// - ImmutableList - . of(interpret("java -Xms128m -Xmx512m -XX:MaxPermSize=256m -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Djava.endorsed.dirs=lib/endorsed -classpath bin/run.jar org.jboss.Main -b 0.0.0.0"))); + "jboss", + jbossHome, + jbossHome, + envVariables, + ImmutableList. of( + new AuthorizeRSAPublicKey(publicKey),// + installJavaAndCurl(os),// + authorizePortInIpTables(8080),// + extractTargzIntoDirectory( + URI.create("http://commondatastorage.googleapis.com/jclouds-repo/jboss-as-distribution-6.0.0.20100911-M5.tar.gz"), + "/usr/local"),// + exec("{md} " + jbossHome), exec("mv /usr/local/jboss-*/* " + jbossHome),// + exec("chmod -R oug+r+w " + jbossHome)),// + ImmutableList + . of(interpret("java -Xms128m -Xmx512m -XX:MaxPermSize=256m -Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Djava.endorsed.dirs=lib/endorsed -classpath bin/run.jar org.jboss.Main -b 0.0.0.0"))); return toReturn; } @@ -93,28 +96,28 @@ public class RunScriptData { } public static final Statement APT_RUN_SCRIPT = newStatementList(// - exec(installAfterUpdatingIfNotPresent("curl")),// - exec("(which java && java -fullversion 2>&1|egrep -q 1.6 ) ||"),// - execHttpResponse(URI.create("http://whirr.s3.amazonaws.com/0.2.0-incubating-SNAPSHOT/sun/java/install")),// - exec(new StringBuilder()// - .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")// - // jeos hasn't enough room! - .append("rm -rf /var/cache/apt /usr/lib/vmware-tools\n")// - .append("echo \"export PATH=\\\"\\$JAVA_HOME/bin/:\\$PATH\\\"\" >> /root/.bashrc")// - .toString())); + exec(installAfterUpdatingIfNotPresent("curl")),// + exec("(which java && java -fullversion 2>&1|egrep -q 1.6 ) ||"),// + execHttpResponse(URI.create("http://whirr.s3.amazonaws.com/0.2.0-incubating-SNAPSHOT/sun/java/install")),// + exec(new StringBuilder()// + .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")// + // jeos hasn't enough room! + .append("rm -rf /var/cache/apt /usr/lib/vmware-tools\n")// + .append("echo \"export PATH=\\\"\\$JAVA_HOME/bin/:\\$PATH\\\"\" >> /root/.bashrc")// + .toString())); public static final Statement YUM_RUN_SCRIPT = newStatementList( - exec("which curl ||yum --nogpgcheck -y install curl"),// - exec("(which java && java -fullversion 2>&1|egrep -q 1.6 ) ||"),// - execHttpResponse(URI.create("http://whirr.s3.amazonaws.com/0.2.0-incubating-SNAPSHOT/sun/java/install")),// - exec(new StringBuilder()// - .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n") // - .append("echo \"export PATH=\\\"\\$JAVA_HOME/bin/:\\$PATH\\\"\" >> /root/.bashrc")// - .toString())); + exec("which curl ||yum --nogpgcheck -y install curl"),// + exec("(which java && java -fullversion 2>&1|egrep -q 1.6 ) ||"),// + execHttpResponse(URI.create("http://whirr.s3.amazonaws.com/0.2.0-incubating-SNAPSHOT/sun/java/install")),// + exec(new StringBuilder()// + .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n") // + .append("echo \"export PATH=\\\"\\$JAVA_HOME/bin/:\\$PATH\\\"\" >> /root/.bashrc")// + .toString())); public static final Statement ZYPPER_RUN_SCRIPT = exec(new StringBuilder()// - .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")// - .append("which curl || zypper install curl\n")// - .append("(which java && java -fullversion 2>&1|egrep -q 1.6 ) || zypper install java-1.6.0-openjdk\n")// - .toString()); + .append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")// + .append("which curl || zypper install curl\n")// + .append("(which java && java -fullversion 2>&1|egrep -q 1.6 ) || zypper install java-1.6.0-openjdk\n")// + .toString()); } diff --git a/core/src/main/java/org/jclouds/io/MutableContentMetadata.java b/core/src/main/java/org/jclouds/io/MutableContentMetadata.java index 84953cface..60ff465e2f 100644 --- a/core/src/main/java/org/jclouds/io/MutableContentMetadata.java +++ b/core/src/main/java/org/jclouds/io/MutableContentMetadata.java @@ -30,7 +30,7 @@ public interface MutableContentMetadata extends ContentMetadata { void setContentMD5(@Nullable byte[] md5); - void setContentType(@Nullable String md5); + void setContentType(@Nullable String contentType); /** * Set Content Disposition of the payload diff --git a/core/src/main/java/org/jclouds/util/Utils.java b/core/src/main/java/org/jclouds/util/Utils.java index c0a745367a..a01198d1c7 100644 --- a/core/src/main/java/org/jclouds/util/Utils.java +++ b/core/src/main/java/org/jclouds/util/Utils.java @@ -66,6 +66,7 @@ import org.jclouds.domain.Credentials; import org.jclouds.logging.Logger; import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.RestContextBuilder; +import org.xml.sax.Attributes; import com.google.common.base.Charsets; import com.google.common.base.Function; @@ -88,6 +89,16 @@ import com.google.inject.spi.Message; * @author Adrian Cole */ public class Utils { + public static Map cleanseAttributes(Attributes in) { + Map attrs = Maps.newLinkedHashMap(); + for (int i = 0; i < in.getLength(); i++) { + String name = in.getQName(i); + if (name.indexOf(':') != -1) + name = name.substring(name.indexOf(':') + 1); + attrs.put(name, in.getValue(i)); + } + return attrs; + } /** * If the supplied map contains the key {@code k1}, its value will be assigned to the key diff --git a/core/src/main/resources/rest.properties b/core/src/main/resources/rest.properties index 465c817ad4..df5122d8ed 100644 --- a/core/src/main/resources/rest.properties +++ b/core/src/main/resources/rest.properties @@ -92,8 +92,27 @@ bluelock-vcdirector.propertiesbuilder=org.jclouds.vcloud.bluelock.BlueLockVCloud gogrid.propertiesbuilder=org.jclouds.gogrid.GoGridPropertiesBuilder gogrid.contextbuilder=org.jclouds.gogrid.GoGridContextBuilder +deltacloud.propertiesbuilder=org.jclouds.deltacloud.DeltacloudPropertiesBuilder +deltacloud.contextbuilder=org.jclouds.deltacloud.DeltacloudContextBuilder + elasticstack.propertiesbuilder=org.jclouds.elasticstack.ElasticStackPropertiesBuilder elasticstack.contextbuilder=org.jclouds.elasticstack.ElasticStackContextBuilder +elasticstack.apiversion=1.0 + +elastichosts-lon-p.propertiesbuilder=org.jclouds.elasticstack.ElasticStackPropertiesBuilder +elastichosts-lon-p.contextbuilder=org.jclouds.elasticstack.ElasticStackContextBuilder +elastichosts-lon-p.apiversion=1.0 +elastichosts-lon-p.endpoint=https://api.lon-p.elastichosts.com + +elastichosts-lon-b.propertiesbuilder=org.jclouds.elasticstack.ElasticStackPropertiesBuilder +elastichosts-lon-b.contextbuilder=org.jclouds.elasticstack.ElasticStackContextBuilder +elastichosts-lon-b.apiversion=1.0 +elastichosts-lon-b.endpoint=https://api.lon-b.elastichosts.com + +elastichosts-sat-p.propertiesbuilder=org.jclouds.elasticstack.ElasticStackPropertiesBuilder +elastichosts-sat-p.contextbuilder=org.jclouds.elasticstack.ElasticStackContextBuilder +elastichosts-sat-p.apiversion=1.0 +elastichosts-sat-p.endpoint=https://api.sat-p.elastichosts.com cloudsigma.propertiesbuilder=org.jclouds.cloudsigma.CloudSigmaPropertiesBuilder cloudsigma.contextbuilder=org.jclouds.cloudsigma.CloudSigmaContextBuilder diff --git a/sandbox/elasticstack/pom.xml b/elasticstack/pom.xml similarity index 90% rename from sandbox/elasticstack/pom.xml rename to elasticstack/pom.xml index d56c26367f..9afc7f0880 100644 --- a/sandbox/elasticstack/pom.xml +++ b/elasticstack/pom.xml @@ -28,7 +28,7 @@ org.jclouds jclouds-project 1.0-SNAPSHOT - ../../project/pom.xml + ../project/pom.xml org.jclouds jclouds-elasticstack @@ -61,9 +61,15 @@ ${project.groupId} - jclouds-core + jclouds-compute ${project.version} + + ${project.groupId} + jclouds-jsch + ${project.version} + test + ${project.groupId} jclouds-core @@ -71,6 +77,13 @@ test-jar test + + ${project.groupId} + jclouds-compute + ${project.version} + test-jar + test + log4j log4j diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackAsyncClient.java b/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackAsyncClient.java new file mode 100644 index 0000000000..a27bf24c37 --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackAsyncClient.java @@ -0,0 +1,258 @@ +/** + * + * Copyright (C) 2010 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.elasticstack; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.jclouds.elasticstack.binders.BindDriveDataToPlainTextString; +import org.jclouds.elasticstack.binders.BindDriveToPlainTextString; +import org.jclouds.elasticstack.binders.BindServerToPlainTextString; +import org.jclouds.elasticstack.domain.Drive; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.elasticstack.domain.ImageConversionType; +import org.jclouds.elasticstack.domain.Server; +import org.jclouds.elasticstack.domain.ServerInfo; +import org.jclouds.elasticstack.functions.KeyValuesDelimitedByBlankLinesToDriveInfo; +import org.jclouds.elasticstack.functions.KeyValuesDelimitedByBlankLinesToServerInfo; +import org.jclouds.elasticstack.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet; +import org.jclouds.elasticstack.functions.ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet; +import org.jclouds.elasticstack.functions.ReturnPayload; +import org.jclouds.elasticstack.functions.SplitNewlines; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.io.Payload; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to elasticstack via their REST API. + *

+ * + * @see ElasticStackClient + * @see + * @author Adrian Cole + */ +@RequestFilters(BasicAuthentication.class) +@Consumes(MediaType.TEXT_PLAIN) +public interface ElasticStackAsyncClient { + + /** + * @see ElasticStackClient#listServers() + */ + @GET + @Path("/servers/list") + @ResponseParser(SplitNewlines.class) + ListenableFuture> listServers(); + + /** + * @see ElasticStackClient#listServerInfo() + */ + @GET + @Path("/servers/info") + @ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.class) + ListenableFuture> listServerInfo(); + + /** + * @see ElasticStackClient#getServerInfo + */ + @GET + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToServerInfo.class) + @Path("/servers/{uuid}/info") + ListenableFuture getServerInfo(@PathParam("uuid") String uuid); + + /** + * @see ElasticStackClient#createServer + */ + @POST + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToServerInfo.class) + @Path("/servers/create/stopped") + ListenableFuture createServer( + @BinderParam(BindServerToPlainTextString.class) Server createServer); + + /** + * @see ElasticStackClient#setServerConfiguration + */ + @POST + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToServerInfo.class) + @Path("/servers/{uuid}/set") + ListenableFuture setServerConfiguration(@PathParam("uuid") String uuid, + @BinderParam(BindServerToPlainTextString.class) Server setServer); + + /** + * @see ElasticStackClient#destroyServer + */ + @POST + @Path("/servers/{uuid}/destroy") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture destroyServer(@PathParam("uuid") String uuid); + + /** + * @see ElasticStackClient#startServer + */ + @POST + @Path("/servers/{uuid}/start") + ListenableFuture startServer(@PathParam("uuid") String uuid); + + /** + * @see ElasticStackClient#stopServer + */ + @POST + @Path("/servers/{uuid}/stop") + ListenableFuture stopServer(@PathParam("uuid") String uuid); + + /** + * @see ElasticStackClient#shutdownServer + */ + @POST + @Path("/servers/{uuid}/shutdown") + ListenableFuture shutdownServer(@PathParam("uuid") String uuid); + + /** + * @see ElasticStackClient#resetServer + */ + @POST + @Path("/servers/{uuid}/reset") + ListenableFuture resetServer(@PathParam("uuid") String uuid); + + /** + * @see ElasticStackClient#listDrives() + */ + @GET + @Path("/drives/list") + @ResponseParser(SplitNewlines.class) + ListenableFuture> listDrives(); + + /** + * @see ElasticStackClient#listDriveInfo() + */ + @GET + @Path("/drives/info") + @ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class) + ListenableFuture> listDriveInfo(); + + /** + * @see ElasticStackClient#getDriveInfo + */ + @GET + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/{uuid}/info") + ListenableFuture getDriveInfo(@PathParam("uuid") String uuid); + + /** + * @see ElasticStackClient#createDrive + */ + @POST + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/create") + ListenableFuture createDrive(@BinderParam(BindDriveToPlainTextString.class) Drive createDrive); + + /** + * @see ElasticStackClient#setDriveData + */ + @POST + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) + @Path("/drives/{uuid}/set") + ListenableFuture setDriveData(@PathParam("uuid") String uuid, + @BinderParam(BindDriveDataToPlainTextString.class) DriveData setDrive); + + /** + * @see ElasticStackClient#destroyDrive + */ + @POST + @Path("/drives/{uuid}/destroy") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture destroyDrive(@PathParam("uuid") String uuid); + + /** + * @see ElasticStackClient#createAndStartServer + */ + @POST + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(KeyValuesDelimitedByBlankLinesToServerInfo.class) + @Path("/servers/create") + ListenableFuture createAndStartServer( + @BinderParam(BindServerToPlainTextString.class) Server createServer); + + /** + * @see ElasticStackClient#imageDrive(String,String) + */ + @POST + @Path("/drives/{destination}/image/{source}") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture imageDrive(@PathParam("source") String source, @PathParam("destination") String destination); + + /** + * @see ElasticStackClient#imageDrive(String,String,ImageConversionType) + */ + @POST + @Path("/drives/{destination}/image/{source}/{conversion}") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture imageDrive(@PathParam("source") String source, @PathParam("destination") String destination, + @PathParam("conversion") ImageConversionType conversionType); + + /** + * @see ElasticStackClient#readDrive + */ + @POST + @Consumes(MediaType.APPLICATION_OCTET_STREAM) + @Path("/drives/{uuid}/read/{offset}/{size}") + @ResponseParser(ReturnPayload.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture readDrive(@PathParam("uuid") String uuid, @PathParam("offset") long offset, + @PathParam("size") long size); + + /** + * @see ElasticStackClient#writeDrive(String, Payload) + */ + @POST + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Path("/drives/{uuid}/write") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture writeDrive(@PathParam("uuid") String uuid, Payload content); + + /** + * @see ElasticStackClient#writeDrive(String, Payload, long) + */ + @POST + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Path("/drives/{uuid}/write/{offset}") + @ExceptionParser(ReturnVoidOnNotFoundOr404.class) + ListenableFuture writeDrive(@PathParam("uuid") String uuid, Payload content, @PathParam("offset") long offset); +} diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackClient.java b/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackClient.java new file mode 100644 index 0000000000..763b04a2bf --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackClient.java @@ -0,0 +1,243 @@ +/** + * + * Copyright (C) 2010 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.elasticstack; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.elasticstack.domain.Drive; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.elasticstack.domain.ImageConversionType; +import org.jclouds.elasticstack.domain.Server; +import org.jclouds.elasticstack.domain.ServerInfo; +import org.jclouds.io.Payload; + +/** + * Provides synchronous access to elasticstack. + *

+ * + * @see ElasticStackAsyncClient + * @see + * @author Adrian Cole + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface ElasticStackClient { + /** + * list of server uuids in your account + * + * @return or empty set if no servers are found + */ + Set listServers(); + + /** + * Get all servers info + * + * @return or empty set if no servers are found + */ + Set listServerInfo(); + + /** + * @param uuid + * what to get + * @return null, if not found + */ + ServerInfo getServerInfo(String uuid); + + /** + * create a new server + * + * @param server + * @return newly created server + */ + ServerInfo createServer(Server server); + + /** + * set server configuration + * + * @param uuid + * what server to change + * @param serverData + * what values to change + * @return new data + */ + ServerInfo setServerConfiguration(String uuid, Server server); + + /** + * Destroy a server + * + * @param uuid + * what to destroy + */ + void destroyServer(String uuid); + + /** + * Start a server + * + * @param uuid + * what to start + */ + void startServer(String uuid); + + /** + * Stop a server + *

+ * Kills the server immediately, equivalent to a power failure. Server reverts to a stopped + * status if it is persistent and is automatically destroyed otherwise. + * + * @param uuid + * what to stop + */ + void stopServer(String uuid); + + /** + * Shutdown a server + *

+ * Sends the server an ACPI power-down event. Server reverts to a stopped status if it is + * persistent and is automatically destroyed otherwise. + *

note

behaviour on shutdown depends on how your server OS is set up to respond to an + * ACPI power button signal. + * + * @param uuid + * what to shutdown + */ + void shutdownServer(String uuid); + + /** + * Reset a server + * + * @param uuid + * what to reset + */ + void resetServer(String uuid); + + /** + * list of drive uuids in your account + * + * @return or empty set if no drives are found + */ + Set listDrives(); + + /** + * Get all drives info + * + * @return or empty set if no drives are found + */ + Set listDriveInfo(); + + /** + * @param uuid + * what to get + * @return null, if not found + */ + DriveInfo getDriveInfo(String uuid); + + /** + * create a new drive + * + * @param createDrive + * required parameters: name, size + * @return newly created drive + */ + DriveInfo createDrive(Drive createDrive); + + /** + * set extra drive data + * + * @param uuid + * what drive to change + * @param driveData + * what values to change + * @return new data + */ + DriveInfo setDriveData(String uuid, DriveData driveData); + + /** + * Destroy a drive + * + * @param uuid + * what to delete + */ + void destroyDrive(String uuid); + + /** + * create and start a new server + * + * @param server + * @return newly created server + */ + ServerInfo createAndStartServer(Server server); + + /** + * Image a drive from another drive. The actual imaging process is asynchronous, with progress + * reported via drive info. + * + * @param source + * drive to copy from + * @param destination + * drive to copy to + */ + void imageDrive(String source, String destination); + + /** + * @see #imageDrive(String, String) + * @param conversionType + * Supports 'gzip' or 'gunzip' conversions. + */ + void imageDrive(String source, String destination, ImageConversionType conversionType); + + /** + * Read binary data from a drive + * + * @param uuid + * drive to read + * @param offset + * start at the specified offset in bytes + * @param size + * the specified size in bytes; must be <=4096k + * @return binary content of the drive. + */ + Payload readDrive(String uuid, long offset, long size); + + /** + * Write binary data to a drive + * + * @param uuid + * drive to write + * @param content + * what to write. + *
    + *
  • Binary data (Content-Type: application/octet-stream)
  • + *
  • Supports raw data or Content-Encoding: gzip
  • + *
  • Does not support Transfer-Encoding: chunked
  • + *
+ */ + void writeDrive(String uuid, Payload content); + + /** + * @see ElasticStackClient#writeDrive(String, Payload) + * @param offset + * the byte offset in the target drive at which to start writing, not an offset in the + * input stream. + */ + void writeDrive(String uuid, Payload content, long offset); + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackContextBuilder.java b/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackContextBuilder.java similarity index 78% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackContextBuilder.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackContextBuilder.java index 9a072d3dac..5eec7f6ebc 100644 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackContextBuilder.java +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackContextBuilder.java @@ -22,8 +22,9 @@ package org.jclouds.elasticstack; import java.util.List; import java.util.Properties; +import org.jclouds.compute.ComputeServiceContextBuilder; +import org.jclouds.elasticstack.compute.config.ElasticStackComputeServiceContextModule; import org.jclouds.elasticstack.config.ElasticStackRestClientModule; -import org.jclouds.rest.RestContextBuilder; import com.google.inject.Module; @@ -32,11 +33,15 @@ import com.google.inject.Module; * @author Adrian Cole */ public class ElasticStackContextBuilder extends - RestContextBuilder { + ComputeServiceContextBuilder { public ElasticStackContextBuilder(Properties props) { super(ElasticStackClient.class, ElasticStackAsyncClient.class, props); } + @Override + protected void addContextModule(List modules) { + modules.add(new ElasticStackComputeServiceContextModule()); + } protected void addClientModule(List modules) { modules.add(new ElasticStackRestClientModule()); diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackPropertiesBuilder.java b/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackPropertiesBuilder.java new file mode 100644 index 0000000000..53a8f9b741 --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackPropertiesBuilder.java @@ -0,0 +1,56 @@ +/** + * + * Copyright (C) 2010 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.elasticstack; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.jclouds.Constants.PROPERTY_API_VERSION; +import static org.jclouds.elasticstack.reference.ElasticStackConstants.PROPERTY_VNC_PASSWORD; + +import java.util.Properties; + +import org.jclouds.PropertiesBuilder; + +/** + * Builds properties used in elasticstack Clients + * + * @author Adrian Cole + */ +public class ElasticStackPropertiesBuilder extends PropertiesBuilder { + @Override + protected Properties defaultProperties() { + Properties properties = super.defaultProperties(); + properties.setProperty(PROPERTY_API_VERSION, "1.0"); + properties.setProperty(PROPERTY_VNC_PASSWORD, "IL9vs34d"); + return properties; + } + + @Override + public Properties build() { + Properties props = super.build(); + checkArgument(props.getProperty(PROPERTY_VNC_PASSWORD).length() <= 8, + "vnc passwords should be less that 8 characters!"); + return props; + } + + public ElasticStackPropertiesBuilder(Properties properties) { + super(properties); + } + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextString.java b/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextString.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextString.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextString.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindDriveToPlainTextString.java b/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindDriveToPlainTextString.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindDriveToPlainTextString.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindDriveToPlainTextString.java diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindServerToPlainTextString.java b/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindServerToPlainTextString.java new file mode 100644 index 0000000000..ba5cfe4895 --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindServerToPlainTextString.java @@ -0,0 +1,61 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.binders; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.ws.rs.core.MediaType; + +import org.jclouds.elasticstack.domain.Server; +import org.jclouds.elasticstack.functions.ListOfMapsToListOfKeyValuesDelimitedByBlankLines; +import org.jclouds.http.HttpRequest; +import org.jclouds.rest.Binder; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class BindServerToPlainTextString implements Binder { + private final Function> createServerRequestToMap; + private final ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines; + + @Inject + public BindServerToPlainTextString(Function> createServerRequestToMap, + ListOfMapsToListOfKeyValuesDelimitedByBlankLines listOfMapsToListOfKeyValuesDelimitedByBlankLines) { + this.createServerRequestToMap = createServerRequestToMap; + this.listOfMapsToListOfKeyValuesDelimitedByBlankLines = listOfMapsToListOfKeyValuesDelimitedByBlankLines; + } + + public void bindToRequest(HttpRequest request, Object payload) { + checkArgument(payload instanceof Server, "this binder is only valid for Server!"); + Server create = Server.class.cast(payload); + Map map = createServerRequestToMap.apply(create); + request.setPayload(listOfMapsToListOfKeyValuesDelimitedByBlankLines.apply(ImmutableSet.of(map))); + request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_PLAIN); + } +} diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/compute/ElasticStackComputeServiceAdapter.java b/elasticstack/src/main/java/org/jclouds/elasticstack/compute/ElasticStackComputeServiceAdapter.java new file mode 100644 index 0000000000..0439ef8d14 --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/compute/ElasticStackComputeServiceAdapter.java @@ -0,0 +1,206 @@ +package org.jclouds.elasticstack.compute; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.notNull; +import static com.google.common.collect.Iterables.filter; +import static org.jclouds.concurrent.FutureIterables.transformParallel; +import static org.jclouds.elasticstack.util.Servers.small; + +import java.net.URI; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.Constants; +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.ComputeServiceAdapter; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.internal.VolumeImpl; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.domain.Credentials; +import org.jclouds.domain.Location; +import org.jclouds.domain.LocationScope; +import org.jclouds.domain.internal.LocationImpl; +import org.jclouds.elasticstack.ElasticStackAsyncClient; +import org.jclouds.elasticstack.ElasticStackClient; +import org.jclouds.elasticstack.domain.Device; +import org.jclouds.elasticstack.domain.Drive; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.elasticstack.domain.ImageConversionType; +import org.jclouds.elasticstack.domain.Server; +import org.jclouds.elasticstack.domain.ServerInfo; +import org.jclouds.elasticstack.domain.WellKnownImage; +import org.jclouds.elasticstack.reference.ElasticStackConstants; +import org.jclouds.logging.Logger; +import org.jclouds.rest.annotations.Provider; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; + +/** + * defines the connection between the {@link ElasticStackClient} implementation and the jclouds + * {@link ComputeService} + * + */ +@Singleton +public class ElasticStackComputeServiceAdapter implements + ComputeServiceAdapter { + private final ElasticStackClient client; + private final ElasticStackAsyncClient aclient; + private final Predicate driveNotClaimed; + private final Map preinstalledImages; + private final Map cache; + private final String providerName; + private final URI providerURI; + private final String defaultVncPassword; + private final ExecutorService executor; + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + protected Logger logger = Logger.NULL; + + @Inject + public ElasticStackComputeServiceAdapter(ElasticStackClient client, ElasticStackAsyncClient aclient, + Predicate driveNotClaimed, @Provider String providerName, @Provider URI providerURI, + Map preinstalledImages, Map cache, + @Named(ElasticStackConstants.PROPERTY_VNC_PASSWORD) String defaultVncPassword, + @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { + this.client = checkNotNull(client, "client"); + this.aclient = checkNotNull(aclient, "aclient"); + this.driveNotClaimed = checkNotNull(driveNotClaimed, "driveNotClaimed"); + this.providerName = checkNotNull(providerName, "providerName"); + this.providerURI = checkNotNull(providerURI, "providerURI"); + this.preinstalledImages = checkNotNull(preinstalledImages, "preinstalledImages"); + this.cache = checkNotNull(cache, "cache"); + this.defaultVncPassword = checkNotNull(defaultVncPassword, "defaultVncPassword"); + this.executor = checkNotNull(executor, "executor"); + } + + @Override + public ServerInfo runNodeWithTagAndNameAndStoreCredentials(String tag, String name, Template template, + Map credentialStore) { + long bootSize = (long) (template.getHardware().getVolumes().get(0).getSize() * 1024 * 1024 * 1024l); + logger.debug(">> creating boot drive bytes(%d)", bootSize); + DriveInfo drive = client.createDrive(new Drive.Builder().name(template.getImage().getName()).size(bootSize) + .build()); + logger.debug("<< drive(%s)", drive.getUuid()); + + logger.debug(">> imaging boot drive source(%s)", template.getImage().getId()); + client.imageDrive(template.getImage().getId(), drive.getUuid(), ImageConversionType.GUNZIP); + boolean success = driveNotClaimed.apply(drive); + logger.debug("<< imaged (%s)", success); + if (!success) { + client.destroyDrive(drive.getUuid()); + throw new IllegalStateException("could not image drive in time!"); + } + Server toCreate = small(name, drive.getUuid(), defaultVncPassword).mem(template.getHardware().getRam()) + .cpu((int) (template.getHardware().getProcessors().get(0).getSpeed())).build(); + + ServerInfo from = client.createAndStartServer(toCreate); + // store the credentials so that later functions can use them + credentialStore.put(from.getUuid() + "", new Credentials("toor", from.getVnc().getPassword())); + return from; + } + + @Override + public Iterable listHardwareProfiles() { + Builder hardware = ImmutableSet. builder(); + for (double cpu : new double[] { 1000, 5000, 10000, 20000 }) + for (int ram : new int[] { 512, 1024, 2048, 4096, 8192 }) { + final float size = (float) cpu / 1000; + String id = String.format("cpu=%f,ram=%s,disk=%f", cpu, ram, size); + hardware.add(new HardwareBuilder().supportsImage(new Predicate() { + + @Override + public boolean apply(Image input) { + String toParse = input.getUserMetadata().get("size"); + return (toParse != null && new Float(toParse) <= size); + } + + @Override + public String toString() { + return "sizeLessThanOrEqual(" + size + ")"; + } + + }).ids(id).ram(ram).processors(ImmutableList.of(new Processor(1, cpu))) + .volumes(ImmutableList. of(new VolumeImpl(size, true, true))).build()); + } + return hardware.build(); + } + + /** + * look up the current standard images and do not error out, if they are not found. + */ + @Override + public Iterable listImages() { + Iterable drives = transformParallel(preinstalledImages.keySet(), + new Function>() { + + @Override + public Future apply(String input) { + return aclient.getDriveInfo(input); + } + + }, executor, null, logger, "drives"); + Iterable returnVal = filter(drives, notNull()); + for (DriveInfo drive : returnVal) + cache.put(drive.getUuid(), drive); + return returnVal; + } + + @SuppressWarnings("unchecked") + @Override + public Iterable listNodes() { + return (Iterable) client.listServerInfo(); + } + + @Override + public Iterable listLocations() { + return ImmutableSet. of(new LocationImpl(LocationScope.PROVIDER, providerName, providerURI + .toASCIIString(), null)); + } + + @Override + public ServerInfo getNode(String id) { + return client.getServerInfo(id); + } + + @Override + public void destroyNode(String id) { + ServerInfo server = getNode(id); + if (server != null) { + client.destroyServer(id); + for (Device dev : server.getDevices().values()) + client.destroyDrive(dev.getDriveUuid()); + } + } + + @Override + public void rebootNode(String id) { + client.resetServer(id); + } + + @Override + public void resumeNode(String id) { + client.startServer(id); + + } + + @Override + public void suspendNode(String id) { + client.stopServer(id); + } +} \ No newline at end of file diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/compute/config/ElasticStackComputeServiceContextModule.java b/elasticstack/src/main/java/org/jclouds/elasticstack/compute/config/ElasticStackComputeServiceContextModule.java new file mode 100644 index 0000000000..604b8ac3fa --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/compute/config/ElasticStackComputeServiceContextModule.java @@ -0,0 +1,151 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.compute.config; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.ComputeServiceAdapter; +import org.jclouds.compute.config.ComputeServiceAdapterContextModule; +import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule.IdentityFunction; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.compute.suppliers.DefaultLocationSupplier; +import org.jclouds.domain.Location; +import org.jclouds.elasticstack.ElasticStackAsyncClient; +import org.jclouds.elasticstack.ElasticStackClient; +import org.jclouds.elasticstack.compute.ElasticStackComputeServiceAdapter; +import org.jclouds.elasticstack.compute.functions.ServerInfoToNodeMetadata; +import org.jclouds.elasticstack.compute.functions.ServerInfoToNodeMetadata.DeviceToVolume; +import org.jclouds.elasticstack.compute.functions.ServerInfoToNodeMetadata.FindImageForId; +import org.jclouds.elasticstack.compute.functions.ServerInfoToNodeMetadata.GetImageIdFromServer; +import org.jclouds.elasticstack.compute.functions.WellKnownImageToImage; +import org.jclouds.elasticstack.domain.Device; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.elasticstack.domain.Server; +import org.jclouds.elasticstack.domain.ServerInfo; +import org.jclouds.elasticstack.domain.WellKnownImage; +import org.jclouds.elasticstack.predicates.DriveClaimed; +import org.jclouds.json.Json; +import org.jclouds.predicates.RetryablePredicate; +import org.jclouds.util.Utils; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.collect.MapMaker; +import com.google.common.collect.Maps; +import com.google.inject.Provides; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +public class ElasticStackComputeServiceContextModule + extends + ComputeServiceAdapterContextModule { + + public ElasticStackComputeServiceContextModule() { + super(ElasticStackClient.class, ElasticStackAsyncClient.class); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + protected void configure() { + super.configure(); + bind(new TypeLiteral>() { + }).to(ElasticStackComputeServiceAdapter.class); + bind(IdentityFunction.class).toInstance(IdentityFunction.INSTANCE); + bind(new TypeLiteral>() { + }).to(DefaultLocationSupplier.class); + bind(new TypeLiteral>() { + }).to(ServerInfoToNodeMetadata.class); + bind(new TypeLiteral>() { + }).to((Class) IdentityFunction.class); + bind(new TypeLiteral>() { + }).to((Class) IdentityFunction.class); + bind(new TypeLiteral>() { + }).to((Class) IdentityFunction.class); + bind(new TypeLiteral>() { + }).to(DeviceToVolume.class); + bind(new TypeLiteral>() { + }).to(GetImageIdFromServer.class); + bind(new TypeLiteral>() { + }).to(FindImageForId.class); + bind(new TypeLiteral>() { + }).to(WellKnownImageToImage.class); + } + + @Provides + @Singleton + protected Map cache(GetDrive getDrive) { + return new MapMaker().makeComputingMap(getDrive); + } + + @Singleton + public static class GetDrive implements Function { + private final ElasticStackClient client; + + @Inject + public GetDrive(ElasticStackClient client) { + this.client = client; + } + + @Override + public DriveInfo apply(String input) { + return client.getDriveInfo(input); + } + } + + @Singleton + @Provides + protected Map provideImages(Json json) throws IOException { + List wellKnowns = json.fromJson( + Utils.toStringAndClose(getClass().getResourceAsStream("/preinstalled_images.json")), + new TypeLiteral>() { + }.getType()); + return Maps.uniqueIndex(wellKnowns, new Function() { + + @Override + public String apply(WellKnownImage input) { + return input.getUuid(); + } + + }); + } + + @Provides + @Singleton + protected Predicate supplyDriveUnclaimed(DriveClaimed driveClaimed, + ComputeServiceConstants.Timeouts timeouts) { + return new RetryablePredicate(Predicates.not(driveClaimed), timeouts.nodeRunning, 1000, + TimeUnit.MILLISECONDS); + } +} \ No newline at end of file diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/compute/functions/ServerInfoToNodeMetadata.java b/elasticstack/src/main/java/org/jclouds/elasticstack/compute/functions/ServerInfoToNodeMetadata.java new file mode 100644 index 0000000000..eed46bb5f6 --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/compute/functions/ServerInfoToNodeMetadata.java @@ -0,0 +1,181 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.compute.util.ComputeServiceUtils.parseTagFromName; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.collect.FindResourceInSet; +import org.jclouds.collect.Memoized; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.domain.NodeState; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.VolumeBuilder; +import org.jclouds.domain.Credentials; +import org.jclouds.domain.Location; +import org.jclouds.elasticstack.domain.Device; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.elasticstack.domain.Server; +import org.jclouds.elasticstack.domain.ServerInfo; +import org.jclouds.elasticstack.domain.ServerStatus; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +@Singleton +public class ServerInfoToNodeMetadata implements Function { + public static final Map serverStatusToNodeState = ImmutableMap + . builder().put(ServerStatus.ACTIVE, NodeState.RUNNING)// + .put(ServerStatus.STOPPED, NodeState.SUSPENDED)// + .put(ServerStatus.PAUSED, NodeState.SUSPENDED)// + .put(ServerStatus.DUMPED, NodeState.PENDING)// + .put(ServerStatus.DEAD, NodeState.TERMINATED)// + .put(ServerStatus.UNRECOGNIZED, NodeState.UNRECOGNIZED)// + .build(); + + private final Function getImageIdFromServer; + private final Function findImageForId; + private final Map credentialStore; + private final Supplier locationSupplier; + private final Function deviceToVolume; + + @Inject + ServerInfoToNodeMetadata(Map credentialStore, Function getImageIdFromServer, + Function findImageForId, Function deviceToVolume, + Supplier locationSupplier) { + this.credentialStore = checkNotNull(credentialStore, "credentialStore"); + this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier"); + this.deviceToVolume = checkNotNull(deviceToVolume, "deviceToVolume"); + this.findImageForId = checkNotNull(findImageForId, "findImageForId"); + this.getImageIdFromServer = checkNotNull(getImageIdFromServer, "getImageIdFromServer"); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public NodeMetadata apply(ServerInfo from) { + NodeMetadataBuilder builder = new NodeMetadataBuilder(); + builder.ids(from.getUuid()); + builder.name(from.getName()); + builder.location(locationSupplier.get()); + builder.tag(parseTagFromName(from.getName())); + + String imageId = getImageIdFromServer.apply(from); + if (imageId != null) { + Image image = findImageForId.apply(imageId); + if (image != null) { + builder.operatingSystem(image.getOperatingSystem()); + } + } + builder.hardware(new HardwareBuilder().ids(from.getUuid()) + .processors(ImmutableList.of(new Processor(1, from.getCpu()))).ram(from.getMem()) + .volumes((List) ImmutableList.of(Iterables.transform(from.getDevices().values(), deviceToVolume))).build()); + builder.state(serverStatusToNodeState.get(from.getStatus())); + builder.publicAddresses(ImmutableSet. of(from.getVnc().getIp())); + builder.privateAddresses(ImmutableSet. of()); + builder.credentials(credentialStore.get(from.getUuid())); + return builder.build(); + } + + @Singleton + public static final class DeviceToVolume implements Function { + private final Map cache; + + @Inject + public DeviceToVolume(Map cache) { + this.cache = checkNotNull(cache, "cache"); + } + + @Override + public Volume apply(Device input) { + VolumeBuilder builder = new VolumeBuilder(); + builder.id(input.getId()); + DriveInfo drive = cache.get(input.getDriveUuid()); + if (drive != null) { + builder.size(drive.getSize() / 1024 / 1024f); + } + return new VolumeBuilder().durable(true).type(Volume.Type.NAS).build(); + } + } + + /** + * When we create the boot drive of the server, by convention we set the name to the image it + * came from. + * + * @author Adrian Cole + * + */ + @Singleton + public static class GetImageIdFromServer implements Function { + private final Map cache; + + @Inject + public GetImageIdFromServer(Map cache) { + this.cache = cache; + } + + @Override + public String apply(Server from) { + String imageId = null; + String bootDeviceId = Iterables.get(from.getBootDeviceIds(), 0); + Device bootDevice = from.getDevices().get(bootDeviceId); + if (bootDevice != null) { + try { + imageId = cache.get(bootDevice.getDriveUuid()).getName(); + } catch (NullPointerException e) { + + } + } + return imageId; + } + } + + @Singleton + public static class FindImageForId extends FindResourceInSet { + + @Inject + public FindImageForId(@Memoized Supplier> images) { + super(images); + } + + @Override + public boolean matches(String from, Image input) { + return input.getProviderId().equals(from); + } + } + +} diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/compute/functions/WellKnownImageToImage.java b/elasticstack/src/main/java/org/jclouds/elasticstack/compute/functions/WellKnownImageToImage.java new file mode 100644 index 0000000000..ea12b435d2 --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/compute/functions/WellKnownImageToImage.java @@ -0,0 +1,70 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.compute.functions; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.domain.OperatingSystemBuilder; +import org.jclouds.domain.Credentials; +import org.jclouds.domain.Location; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.elasticstack.domain.WellKnownImage; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; + +/** + * @author Adrian Cole + */ +@Singleton +public class WellKnownImageToImage implements Function { + private final Supplier locationSupplier; + private final Map preinstalledImages; + + @Inject + public WellKnownImageToImage(Supplier locationSupplier, Map preinstalledImages) { + this.locationSupplier = locationSupplier; + this.preinstalledImages = preinstalledImages; + } + + @Override + public Image apply(DriveInfo drive) { + WellKnownImage input = preinstalledImages.get(drive.getUuid()); + return new ImageBuilder() + .ids(drive.getUuid()) + .userMetadata( + ImmutableMap. builder().putAll(drive.getUserMetadata()) + .put("size", input.getSize() + "").build()) + .defaultCredentials(new Credentials("toor", null)) + .location(locationSupplier.get()) + .name(input.getDescription()) + .description(drive.getName()) + .operatingSystem( + new OperatingSystemBuilder().family(input.getOsFamily()).version(input.getOsVersion()) + .name(input.getDescription()).description(drive.getName()).is64Bit(true).build()).version("") + .build(); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/config/ElasticStackRestClientModule.java b/elasticstack/src/main/java/org/jclouds/elasticstack/config/ElasticStackRestClientModule.java similarity index 94% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/config/ElasticStackRestClientModule.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/config/ElasticStackRestClientModule.java index 05435aecde..2ed5bf7f9e 100644 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/config/ElasticStackRestClientModule.java +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/config/ElasticStackRestClientModule.java @@ -29,10 +29,12 @@ import org.jclouds.elasticstack.domain.Drive; import org.jclouds.elasticstack.domain.DriveData; import org.jclouds.elasticstack.domain.DriveMetrics; import org.jclouds.elasticstack.domain.NIC; +import org.jclouds.elasticstack.domain.Server; import org.jclouds.elasticstack.domain.ServerMetrics; import org.jclouds.elasticstack.functions.CreateDriveRequestToMap; import org.jclouds.elasticstack.functions.DriveDataToMap; import org.jclouds.elasticstack.functions.MapToDevices; +import org.jclouds.elasticstack.functions.ServerToMap; import org.jclouds.elasticstack.functions.MapToDevices.DeviceToId; import org.jclouds.elasticstack.functions.MapToDriveMetrics; import org.jclouds.elasticstack.functions.MapToNICs; @@ -79,6 +81,8 @@ public class ElasticStackRestClientModule extends RestClientModule>() { }).to(DeviceToId.class); + bind(new TypeLiteral>>() { + }).to(ServerToMap.class); } @Override diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/BlockDevice.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/BlockDevice.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/BlockDevice.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/BlockDevice.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ClaimType.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ClaimType.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ClaimType.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/ClaimType.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/CreateDriveRequest.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/CreateDriveRequest.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/CreateDriveRequest.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/CreateDriveRequest.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Device.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Device.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Device.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/Device.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Drive.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Drive.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Drive.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/Drive.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveData.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveData.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveData.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveData.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveInfo.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveInfo.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveInfo.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveInfo.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveMetrics.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveMetrics.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveMetrics.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveMetrics.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveStatus.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveStatus.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveStatus.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/DriveStatus.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/IDEDevice.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/IDEDevice.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/IDEDevice.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/IDEDevice.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ImageConversionType.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ImageConversionType.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ImageConversionType.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/ImageConversionType.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Item.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Item.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Item.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/Item.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/MediaType.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/MediaType.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/MediaType.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/MediaType.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Model.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Model.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Model.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/Model.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/NIC.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/NIC.java similarity index 99% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/NIC.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/NIC.java index c553edd6de..371977f9db 100644 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/NIC.java +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/NIC.java @@ -37,6 +37,7 @@ public class NIC { private Model model; private String vlan; private String mac; + // TODO elasticstack specific private Set block = ImmutableSet.of(); public Builder dhcp(String dhcp) { diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/SCSIDevice.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/SCSIDevice.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/SCSIDevice.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/SCSIDevice.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Server.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Server.java similarity index 89% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Server.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/Server.java index dc50aa7b91..bfed641561 100644 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Server.java +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/Server.java @@ -46,8 +46,6 @@ public class Server extends Item { protected Set bootDeviceIds = ImmutableSet.of(); protected List nics = ImmutableList.of(); protected VNC vnc; - // TODO undocumented - protected String description; public Builder cpu(int cpu) { this.cpu = cpu; @@ -89,11 +87,6 @@ public class Server extends Item { return this; } - public Builder description(String description) { - this.description = description; - return this; - } - /** * {@inheritDoc} */ @@ -127,8 +120,13 @@ public class Server extends Item { } public Server build() { - return new Server(uuid, name, cpu, smp, mem, persistent, devices, tags, bootDeviceIds, userMetadata, nics, - vnc, description); + return new Server(uuid, name, cpu, smp, mem, persistent, devices, bootDeviceIds, tags, userMetadata, nics, vnc); + } + + public static Builder fromServer(Server in) { + return new Builder().uuid(in.getUuid()).name(in.getName()).cpu(in.getCpu()).mem(in.getMem()) + .persistent(in.isPersistent()).devices(in.getDevices()).bootDeviceIds(in.getBootDeviceIds()) + .tags(in.getTags()).userMetadata(in.getUserMetadata()).nics(in.getNics()).vnc(in.getVnc()); } } @@ -137,16 +135,14 @@ public class Server extends Item { protected final int mem; protected final boolean persistent; @Nullable - protected final Map devices; + protected final Map devices; protected final Set bootDeviceIds; protected final List nics; protected final VNC vnc; - @Nullable - private final String description; public Server(@Nullable String uuid, String name, int cpu, @Nullable Integer smp, int mem, boolean persistent, Map devices, Iterable bootDeviceIds, Iterable tags, - Map userMetadata, Iterable nics, VNC vnc, String description) { + Map userMetadata, Iterable nics, VNC vnc) { super(uuid, name, tags, userMetadata); this.cpu = cpu; this.smp = smp; @@ -156,7 +152,6 @@ public class Server extends Item { this.bootDeviceIds = ImmutableSet.copyOf(checkNotNull(bootDeviceIds, "bootDeviceIds")); this.nics = ImmutableList.copyOf(checkNotNull(nics, "nics")); this.vnc = checkNotNull(vnc, "vnc"); - this.description = description; } /** @@ -196,7 +191,7 @@ public class Server extends Item { * * @return devices present, mapped by id */ - public Map getDevices() { + public Map getDevices() { return devices; } @@ -217,18 +212,12 @@ public class Server extends Item { return vnc; } - // TODO undocumented - public String getDescription() { - return description; - } - @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((bootDeviceIds == null) ? 0 : bootDeviceIds.hashCode()); result = prime * result + cpu; - result = prime * result + ((description == null) ? 0 : description.hashCode()); result = prime * result + ((devices == null) ? 0 : devices.hashCode()); result = prime * result + mem; result = prime * result + ((nics == null) ? 0 : nics.hashCode()); @@ -254,11 +243,6 @@ public class Server extends Item { return false; if (cpu != other.cpu) return false; - if (description == null) { - if (other.description != null) - return false; - } else if (!description.equals(other.description)) - return false; if (devices == null) { if (other.devices != null) return false; @@ -290,8 +274,7 @@ public class Server extends Item { public String toString() { return "[uuid=" + uuid + ", name=" + name + ", tags=" + tags + ", userMetadata=" + userMetadata + ", cpu=" + cpu + ", smp=" + smp + ", mem=" + mem + ", persistent=" + persistent + ", devices=" + devices - + ", bootDeviceIds=" + bootDeviceIds + ", nics=" + nics + ", vnc=" + vnc + ", description=" + description - + "]"; + + ", bootDeviceIds=" + bootDeviceIds + ", nics=" + nics + ", vnc=" + vnc + "]"; } } \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerInfo.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerInfo.java similarity index 93% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerInfo.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerInfo.java index 0e5d3e2aa5..1240b2d9fd 100644 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerInfo.java +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerInfo.java @@ -120,14 +120,6 @@ public class ServerInfo extends Server { return Builder.class.cast(super.vnc(vnc)); } - /** - * {@inheritDoc} - */ - @Override - public Builder description(String description) { - return Builder.class.cast(super.description(description)); - } - /** * {@inheritDoc} */ @@ -161,8 +153,8 @@ public class ServerInfo extends Server { } public ServerInfo build() { - return new ServerInfo(uuid, name, cpu, smp, mem, persistent, devices, tags, bootDeviceIds, userMetadata, nics, - vnc, description, status, started, user, metrics); + return new ServerInfo(uuid, name, cpu, smp, mem, persistent, devices, bootDeviceIds, tags, userMetadata, nics, + vnc, status, started, user, metrics); } } @@ -175,9 +167,9 @@ public class ServerInfo extends Server { public ServerInfo(String uuid, String name, int cpu, Integer smp, int mem, boolean persistent, Map devices, Iterable bootDeviceIds, Iterable tags, - Map userMetadata, Iterable nics, VNC vnc, String description, ServerStatus status, - Date started, String user, @Nullable ServerMetrics metrics) { - super(uuid, name, cpu, smp, mem, persistent, devices, bootDeviceIds, tags, userMetadata, nics, vnc, description); + Map userMetadata, Iterable nics, VNC vnc, ServerStatus status, Date started, String user, + @Nullable ServerMetrics metrics) { + super(uuid, name, cpu, smp, mem, persistent, devices, bootDeviceIds, tags, userMetadata, nics, vnc); this.status = status; this.started = started; this.user = user; diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerMetrics.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerMetrics.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerMetrics.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerMetrics.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerStatus.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerStatus.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerStatus.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/ServerStatus.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/VNC.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/VNC.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/domain/VNC.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/domain/VNC.java diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/domain/WellKnownImage.java b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/WellKnownImage.java new file mode 100644 index 0000000000..b9544d303a --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/domain/WellKnownImage.java @@ -0,0 +1,82 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.domain; + +import org.jclouds.compute.domain.OsFamily; + +import com.google.common.base.Objects; + +/** + * + * @author Adrian Cole + */ +public class WellKnownImage { + private String uuid; + private String description; + private OsFamily osFamily; + private String osVersion; + private int size; + + // intended only for serialization + WellKnownImage() { + + } + + // performance isn't a concern on a infrequent object like this, so using shortcuts; + + public String getUuid() { + return uuid; + } + + public String getDescription() { + return description; + } + + public OsFamily getOsFamily() { + return osFamily; + } + + public String getOsVersion() { + return osVersion; + } + + public int getSize() { + return size; + } + + @Override + public int hashCode() { + return Objects.hashCode(uuid, description, osFamily, osVersion, size); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + return Objects.equal(this.toString(), that.toString()); + } + + @Override + public String toString() { + return Objects.toStringHelper(this).add("uuid", uuid).add("description", description).add("osFamily", osFamily) + .add("osVersion", osVersion).add("size", size).toString(); + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/BaseDriveToMap.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/BaseDriveToMap.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/BaseDriveToMap.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/BaseDriveToMap.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMap.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMap.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMap.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMap.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/DriveDataToMap.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/DriveDataToMap.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/DriveDataToMap.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/DriveDataToMap.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfo.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToServerInfo.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToServerInfo.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToServerInfo.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToServerInfo.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMaps.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMaps.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMaps.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMaps.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLines.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLines.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLines.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLines.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDevices.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDevices.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDevices.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDevices.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDriveInfo.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDriveInfo.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDriveInfo.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDriveInfo.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDriveMetrics.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDriveMetrics.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDriveMetrics.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToDriveMetrics.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToNICs.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToNICs.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToNICs.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToNICs.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToServerInfo.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToServerInfo.java similarity index 98% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToServerInfo.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToServerInfo.java index 8293bd1a0c..ae7671a1ff 100644 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToServerInfo.java +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToServerInfo.java @@ -62,7 +62,6 @@ public class MapToServerInfo implements Function, ServerInfo return null; ServerInfo.Builder builder = new ServerInfo.Builder(); builder.name(from.get("name")); - builder.description(from.get("description")); builder.persistent(Boolean.parseBoolean(from.get("persistent"))); if (from.containsKey("tags")) builder.tags(Splitter.on(' ').split(from.get("tags"))); diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToServerMetrics.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToServerMetrics.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToServerMetrics.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/MapToServerMetrics.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ReturnPayload.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ReturnPayload.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ReturnPayload.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/ReturnPayload.java diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ServerToMap.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ServerToMap.java new file mode 100644 index 0000000000..b6e846ce47 --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/ServerToMap.java @@ -0,0 +1,83 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.Map.Entry; + +import javax.inject.Singleton; + +import org.jclouds.elasticstack.domain.Device; +import org.jclouds.elasticstack.domain.NIC; +import org.jclouds.elasticstack.domain.Server; + +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableMap; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class ServerToMap implements Function> { + @Override + public Map apply(Server from) { + checkNotNull(from, "server"); + ImmutableMap.Builder builder = ImmutableMap.builder(); + builder.put("name", from.getName()); + builder.put("cpu", from.getCpu() + ""); + if (from.getSmp() != null) + builder.put("smp", from.getSmp() + ""); + else + builder.put("smp", "auto"); + builder.put("mem", from.getMem() + ""); + builder.put("persistent", from.isPersistent() + ""); + if (from.getBootDeviceIds().size() != 0) + builder.put("boot", Joiner.on(' ').join(from.getBootDeviceIds())); + for (Entry entry : from.getDevices().entrySet()) { + builder.put(entry.getKey(), entry.getValue().getDriveUuid()); + builder.put(entry.getKey() + ":media", entry.getValue().getMediaType().toString()); + } + int nicId = 0; + for (NIC nic : from.getNics()) { + builder.put("nic:" + nicId + ":model", nic.getModel().toString()); + if (nic.getDhcp() != null) + builder.put("nic:" + nicId + ":dhcp", nic.getDhcp()); + if (nic.getVlan() != null) + builder.put("nic:" + nicId + ":vlan", nic.getVlan()); + if (nic.getMac() != null) + builder.put("nic:" + nicId + ":mac", nic.getMac()); + nicId++; + } + builder.put("vnc:ip", from.getVnc().getIp() == null ? "auto" : from.getVnc().getIp()); + if (from.getVnc().getPassword() != null) + builder.put("vnc:password", from.getVnc().getPassword()); + if (from.getVnc().isTls()) + builder.put("vnc:tls", "on"); + if (from.getTags().size() != 0) + builder.put("tags", Joiner.on(' ').join(from.getTags())); + for (Entry entry : from.getUserMetadata().entrySet()) + builder.put("user:" + entry.getKey(), entry.getValue()); + return builder.build(); + } +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/SplitNewlines.java b/elasticstack/src/main/java/org/jclouds/elasticstack/functions/SplitNewlines.java similarity index 100% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/functions/SplitNewlines.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/functions/SplitNewlines.java diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandler.java b/elasticstack/src/main/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandler.java similarity index 95% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandler.java rename to elasticstack/src/main/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandler.java index cdc0c55e03..d578b7318f 100644 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandler.java +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandler.java @@ -61,7 +61,8 @@ public class ElasticStackErrorHandler implements HttpErrorHandler { response.getStatusLine()); switch (response.getStatusCode()) { case 400: - if (message != null && message.indexOf("could not be found") != -1) + if ((command.getRequest().getEndpoint().getPath().endsWith("/info")) + || (message != null && message.indexOf("could not be found") != -1)) exception = new ResourceNotFoundException(message, exception); else exception = new IllegalArgumentException(message, exception); diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/predicates/DriveClaimed.java b/elasticstack/src/main/java/org/jclouds/elasticstack/predicates/DriveClaimed.java new file mode 100644 index 0000000000..73af68828d --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/predicates/DriveClaimed.java @@ -0,0 +1,63 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.predicates; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.elasticstack.ElasticStackClient; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.logging.Logger; + +import com.google.common.base.Predicate; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class DriveClaimed implements Predicate { + + private final ElasticStackClient client; + + @Resource + protected Logger logger = Logger.NULL; + + @Inject + public DriveClaimed(ElasticStackClient client) { + this.client = client; + } + + public boolean apply(DriveInfo drive) { + logger.trace("looking for claims on drive %s", checkNotNull(drive, "drive")); + drive = refresh(drive); + if (drive == null) + return false; + logger.trace("%s: looking for drive claims: currently: %s", drive.getUuid(), drive.getClaimed()); + return drive.getClaimed().size() > 0; + } + + private DriveInfo refresh(DriveInfo drive) { + return client.getDriveInfo(drive.getUuid()); + } +} diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/reference/ElasticStackConstants.java b/elasticstack/src/main/java/org/jclouds/elasticstack/reference/ElasticStackConstants.java new file mode 100644 index 0000000000..f20736b5af --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/reference/ElasticStackConstants.java @@ -0,0 +1,34 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.reference; + +/** + * Common constants used in ElasticStack provider + * + * @author Adrian Cole + */ +public class ElasticStackConstants { + + /** + * default VNC password used on new machines + */ + public static final String PROPERTY_VNC_PASSWORD = "jclouds.elasticstack.vnc-password"; + +} diff --git a/elasticstack/src/main/java/org/jclouds/elasticstack/util/Servers.java b/elasticstack/src/main/java/org/jclouds/elasticstack/util/Servers.java new file mode 100644 index 0000000000..1d8564f0cc --- /dev/null +++ b/elasticstack/src/main/java/org/jclouds/elasticstack/util/Servers.java @@ -0,0 +1,54 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.util; + +import org.jclouds.elasticstack.domain.IDEDevice; +import org.jclouds.elasticstack.domain.Model; +import org.jclouds.elasticstack.domain.NIC; +import org.jclouds.elasticstack.domain.Server; +import org.jclouds.elasticstack.domain.VNC; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +public class Servers { + /** + * Helper to create a small persistent server + * + * @param name + * what to name the server + * @param driveUuuid + * id of the boot drive + * @param vncPassword + * password for vnc + * @return a builder for a persistent 1Ghz 512m server with DHCP enabled network. + */ + public static Server.Builder small(String name, String driveUuuid, String vncPassword) { + return new Server.Builder().name(name).cpu(1000).mem(512).persistent(true) + .devices(ImmutableMap.of("ide:0:0", new IDEDevice.Builder(0, 0).uuid(driveUuuid).build())) + .bootDeviceIds(ImmutableSet.of("ide:0:0")) + .nics(ImmutableSet.of(new NIC.Builder().model(Model.E1000).dhcp("auto").build())) + .vnc(new VNC(null, vncPassword, false)); + } +} \ No newline at end of file diff --git a/elasticstack/src/main/resources/preinstalled_images.json b/elasticstack/src/main/resources/preinstalled_images.json new file mode 100644 index 0000000000..dadd7b7441 --- /dev/null +++ b/elasticstack/src/main/resources/preinstalled_images.json @@ -0,0 +1,72 @@ +[ + { + "uuid": "38df0986-4d85-4b76-b502-3878ffc80161", + "description": "CentOS Linux 5.5", + "osFamily": "CENTOS", + "osVersion": "5.5", + "size": "3" + }, + { + "uuid": "980cf63c-f21e-4382-997b-6541d5809629", + "description": "Debian Linux 5.0", + "osFamily": "DEBIAN", + "osVersion": "5.0", + "size": "1" + }, + { + "uuid": "aee5589a-88c3-43ef-bb0a-9cab6e64192d", + "description": "Ubuntu Linux 10.04", + "osFamily": "UBUNTU", + "osVersion": "10.04", + "size": "1" + }, + { + "uuid": "bf1d943e-2a55-46bb-a8c7-6099e44a3dde", + "description": "Ubuntu Linux 8.10: Base system with X", + "osFamily": "UBUNTU", + "osVersion": "8.10", + "size": "3" + }, + { + "uuid": "757586d5-f1e9-4d9c-b215-5a391c9a24bf", + "description": "Ubuntu Linux 9.04: Base system with X", + "osFamily": "UBUNTU", + "osVersion": "9.04", + "size": "3" + }, + { + "uuid": "b9d0eb72-d273-43f1-98e3-0d4b87d372c0", + "description": "Windows Web Server 2008", + "osFamily": "WINDOWS", + "osVersion": "2008", + "size": "13" + }, + { + "uuid": "b405b598-4ae4-4ba8-8a2b-a9487d693f34", + "description": "Windows Web Server 2008 R2", + "osFamily": "WINDOWS", + "osVersion": "2008 R2", + "size": "13" + }, + { + "uuid": "9397d327-3bf6-46a2-abf6-69553dbb6927", + "description": "Windows Web Server 2008 R2 + SQL Server", + "osFamily": "WINDOWS", + "osVersion": "2008 R2", + "size": "13" + }, + { + "uuid": "10a88d1c-6575-46e3-8d2c-7744065ea530", + "description": "Windows Server 2008 Standard R2", + "osFamily": "WINDOWS", + "osVersion": "2008 R2", + "size": "13" + }, + { + "uuid": "662c5b3f-9828-4aa2-a866-7cfa53798cdf", + "description": "Windows Server 2008 Standard R2 + SQL Server", + "osFamily": "WINDOWS", + "osVersion": "2008 R2", + "size": "13" + } +] diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackAsyncClientTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackAsyncClientTest.java similarity index 71% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackAsyncClientTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackAsyncClientTest.java index 9cbe255b20..195c0380cc 100644 --- a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackAsyncClientTest.java +++ b/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackAsyncClientTest.java @@ -27,17 +27,18 @@ import java.util.Properties; import javax.ws.rs.core.MediaType; +import org.jclouds.elasticstack.binders.BindServerToPlainTextStringTest; import org.jclouds.elasticstack.domain.CreateDriveRequest; import org.jclouds.elasticstack.domain.Drive; import org.jclouds.elasticstack.domain.DriveData; import org.jclouds.elasticstack.domain.ImageConversionType; +import org.jclouds.elasticstack.domain.Server; import org.jclouds.elasticstack.functions.KeyValuesDelimitedByBlankLinesToDriveInfo; import org.jclouds.elasticstack.functions.KeyValuesDelimitedByBlankLinesToServerInfo; import org.jclouds.elasticstack.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet; import org.jclouds.elasticstack.functions.ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet; import org.jclouds.elasticstack.functions.ReturnPayload; import org.jclouds.elasticstack.functions.SplitNewlines; -import org.jclouds.elasticstack.options.ReadDriveOptions; import org.jclouds.http.HttpRequest; import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.functions.ReleasePayloadAndReturn; @@ -46,6 +47,7 @@ import org.jclouds.io.Payloads; import org.jclouds.rest.RestClientTest; import org.jclouds.rest.RestContextFactory; import org.jclouds.rest.RestContextSpec; +import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.rest.internal.GeneratedHttpRequest; @@ -121,6 +123,137 @@ public class ElasticStackAsyncClientTest extends RestClientTest httpRequest = processor.createRequest(method, + BindServerToPlainTextStringTest.SERVER); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/servers/create HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, BindServerToPlainTextStringTest.CREATED_SERVER, "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToServerInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testCreateServer() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("createServer", Server.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, + BindServerToPlainTextStringTest.SERVER); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/servers/create/stopped HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, BindServerToPlainTextStringTest.CREATED_SERVER, "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToServerInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testSetServerConfiguration() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("setServerConfiguration", String.class, Server.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", + BindServerToPlainTextStringTest.SERVER); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/servers/100/set HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, BindServerToPlainTextStringTest.CREATED_SERVER, "text/plain", false); + + assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToServerInfo.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testDestroyServer() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("destroyServer", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/servers/uuid/destroy HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + + public void testStartServer() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("startServer", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/servers/uuid/start HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + + } + + public void testStopServer() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("stopServer", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/servers/uuid/stop HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + + } + + public void testShutdownServer() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("shutdownServer", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/servers/uuid/shutdown HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + + } + + public void testResetServer() throws SecurityException, NoSuchMethodException, IOException { + Method method = ElasticStackAsyncClient.class.getMethod("resetServer", String.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/servers/uuid/reset HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class); + + checkFilters(httpRequest); + + } + public void testListDrives() throws SecurityException, NoSuchMethodException, IOException { Method method = ElasticStackAsyncClient.class.getMethod("listDrives"); GeneratedHttpRequest httpRequest = processor.createRequest(method); @@ -213,6 +346,22 @@ public class ElasticStackAsyncClientTest extends RestClientTest httpRequest = processor.createRequest(method, "uuid"); + + assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/drives/uuid/destroy HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); + + checkFilters(httpRequest); + + } + public void testImageDrive() throws SecurityException, NoSuchMethodException, IOException { Method method = ElasticStackAsyncClient.class.getMethod("imageDrive", String.class, String.class); GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", "200"); @@ -247,41 +396,9 @@ public class ElasticStackAsyncClientTest extends RestClientTest httpRequest = processor.createRequest(method, "uuid"); - - assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/drives/uuid/destroy HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); - assertPayloadEquals(httpRequest, null, null, false); - - assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); - assertSaxResponseParserClassEquals(method, null); - assertExceptionParserClassEquals(method, ReturnVoidOnNotFoundOr404.class); - - checkFilters(httpRequest); - - } - public void testReadDrive() throws SecurityException, NoSuchMethodException, IOException { - Method method = ElasticStackAsyncClient.class.getMethod("readDrive", String.class); - GeneratedHttpRequest httpRequest = processor.createRequest(method, "100"); - - assertRequestLineEquals(httpRequest, "GET https://api.elasticstack.com/drives/100/read HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: application/octet-stream\n"); - assertPayloadEquals(httpRequest, null, null, false); - - assertResponseParserClassEquals(method, httpRequest, ReturnPayload.class); - assertSaxResponseParserClassEquals(method, null); - assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); - - checkFilters(httpRequest); - } - - public void testReadDriveOptions() throws SecurityException, NoSuchMethodException, IOException { - Method method = ElasticStackAsyncClient.class.getMethod("readDrive", String.class, ReadDriveOptions.class); - GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", - new ReadDriveOptions().offset(1024).size(2048)); + Method method = ElasticStackAsyncClient.class.getMethod("readDrive", String.class, long.class, long.class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", 1024, 2048); assertRequestLineEquals(httpRequest, "POST https://api.elasticstack.com/drives/100/read/1024/2048 HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/octet-stream\n"); diff --git a/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java new file mode 100644 index 0000000000..9704ed8e69 --- /dev/null +++ b/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java @@ -0,0 +1,387 @@ +/** + * + * Copyright (C) 2010 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.elasticstack; + +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.util.Properties; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +import org.jclouds.Constants; +import org.jclouds.compute.ComputeServiceContextFactory; +import org.jclouds.domain.Credentials; +import org.jclouds.elasticstack.domain.ClaimType; +import org.jclouds.elasticstack.domain.CreateDriveRequest; +import org.jclouds.elasticstack.domain.DriveData; +import org.jclouds.elasticstack.domain.DriveInfo; +import org.jclouds.elasticstack.domain.DriveStatus; +import org.jclouds.elasticstack.domain.IDEDevice; +import org.jclouds.elasticstack.domain.ImageConversionType; +import org.jclouds.elasticstack.domain.Model; +import org.jclouds.elasticstack.domain.Server; +import org.jclouds.elasticstack.domain.ServerInfo; +import org.jclouds.elasticstack.domain.ServerStatus; +import org.jclouds.elasticstack.predicates.DriveClaimed; +import org.jclouds.elasticstack.util.Servers; +import org.jclouds.io.Payloads; +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.net.IPSocket; +import org.jclouds.predicates.InetSocketAddressConnect; +import org.jclouds.predicates.RetryablePredicate; +import org.jclouds.rest.RestContext; +import org.jclouds.ssh.ExecResponse; +import org.jclouds.ssh.SshClient; +import org.jclouds.ssh.jsch.config.JschSshClientModule; +import org.jclouds.util.Utils; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.gson.Gson; +import com.google.inject.Guice; +import com.google.inject.Module; + +/** + * Tests behavior of {@code ElasticStackClient} + * + * @author Adrian Cole + */ +@Test(groups = "live", testName = "elasticstack.ElasticStackClientLiveTest") +public class ElasticStackClientLiveTest { + + protected long driveSize = 1 * 1024 * 1024 * 1024l; + protected int maxDriveImageTime = 120; + protected String vncPassword = "Il0veVNC"; + protected ElasticStackClient client; + protected RestContext context; + protected Predicate socketTester; + + protected String provider = "elasticstack"; + protected String identity; + protected String credential; + protected String endpoint; + protected String apiversion; + protected Predicate driveNotClaimed; + + protected void setupCredentials() { + identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"); + credential = System.getProperty("test." + provider + ".credential"); + endpoint = System.getProperty("test." + provider + ".endpoint"); + apiversion = System.getProperty("test." + provider + ".apiversion"); + } + + protected Properties setupProperties() { + Properties overrides = new Properties(); + overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true"); + overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true"); + overrides.setProperty(provider + ".identity", identity); + if (credential != null) + overrides.setProperty(provider + ".credential", credential); + if (endpoint != null) + overrides.setProperty(provider + ".endpoint", endpoint); + if (apiversion != null) + overrides.setProperty(provider + ".apiversion", apiversion); + return overrides; + } + + @BeforeGroups(groups = "live") + public void setupClient() { + setupCredentials(); + Properties overrides = setupProperties(); + context = new ComputeServiceContextFactory().createContext(provider, + ImmutableSet. of(new Log4JLoggingModule()), overrides).getProviderSpecificContext(); + + client = context.getApi(); + driveNotClaimed = new RetryablePredicate(Predicates.not(new DriveClaimed(client)), maxDriveImageTime, + 1, TimeUnit.SECONDS); + socketTester = new RetryablePredicate(new InetSocketAddressConnect(), maxDriveImageTime, 1, + TimeUnit.SECONDS); + } + + @Test + public void testListServers() throws Exception { + Set servers = client.listServers(); + assertNotNull(servers); + } + + @Test + public void testListServerInfo() throws Exception { + Set servers = client.listServerInfo(); + assertNotNull(servers); + } + + @Test + public void testGetServer() throws Exception { + for (String serverUUID : client.listServers()) { + assert !"".equals(serverUUID); + assertNotNull(client.getServerInfo(serverUUID)); + } + } + + @Test + public void testListDrives() throws Exception { + Set drives = client.listDrives(); + assertNotNull(drives); + } + + @Test + public void testListDriveInfo() throws Exception { + Set drives = client.listDriveInfo(); + assertNotNull(drives); + } + + @Test + public void testGetDrive() throws Exception { + for (String driveUUID : client.listDrives()) { + assert !"".equals(driveUUID); + assertNotNull(client.getDriveInfo(driveUUID)); + } + } + + protected String prefix = System.getProperty("user.name") + ".test"; + protected DriveInfo drive; + + @Test + public void testCreateDrive() throws Exception { + drive = client.createDrive(new CreateDriveRequest.Builder().name(prefix).size(driveSize).build()); + checkCreatedDrive(); + + DriveInfo newInfo = client.getDriveInfo(drive.getUuid()); + checkDriveMatchesGet(newInfo); + + } + + protected void checkDriveMatchesGet(DriveInfo newInfo) { + assertEquals(newInfo.getUuid(), drive.getUuid()); + } + + protected void checkCreatedDrive() { + assertNotNull(drive.getUuid()); + assertNotNull(drive.getUser()); + assertEquals(drive.getName(), prefix); + assertEquals(drive.getSize(), driveSize); + assertEquals(drive.getStatus(), DriveStatus.ACTIVE); + // for some reason, these occasionally return as 4096,1 + // assertEquals(info.getReadBytes(), 0l); + // assertEquals(info.getWriteBytes(), 0l); + // assertEquals(info.getReadRequests(), 0l); + // assertEquals(info.getWriteRequests(), 0l); + assertEquals(drive.getEncryptionCipher(), "aes-xts-plain"); + } + + @Test(dependsOnMethods = "testCreateDrive") + public void testSetDriveData() throws Exception { + + DriveInfo drive2 = client.setDriveData( + drive.getUuid(), + new DriveData.Builder().claimType(ClaimType.SHARED).name("rediculous") + .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff")) + .tags(ImmutableSet.of("networking", "security", "gateway")) + .userMetadata(ImmutableMap.of("foo", "bar")).build()); + + assertNotNull(drive2.getUuid(), drive.getUuid()); + assertEquals(drive2.getName(), "rediculous"); + assertEquals(drive2.getClaimType(), ClaimType.SHARED); + assertEquals(drive2.getReaders(), ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff")); + assertEquals(drive2.getTags(), ImmutableSet.of("networking", "security", "gateway")); + assertEquals(drive2.getUserMetadata(), ImmutableMap.of("foo", "bar")); + drive = drive2; + } + + protected ServerInfo server; + + @Test(dependsOnMethods = "testSetDriveData") + public void testCreateAndStartServer() throws Exception { + Logger.getAnonymousLogger().info("preparing drive"); + prepareDrive(); + + Server serverRequest = Servers.small(prefix, drive.getUuid(), vncPassword).build(); + + Logger.getAnonymousLogger().info("starting server"); + server = client.createServer(serverRequest); + client.startServer(server.getUuid()); + server = client.getServerInfo(server.getUuid()); + checkStartedServer(); + + Server newInfo = client.getServerInfo(server.getUuid()); + checkServerMatchesGet(newInfo); + + } + + protected void checkServerMatchesGet(Server newInfo) { + assertEquals(newInfo.getUuid(), server.getUuid()); + } + + protected void checkStartedServer() { + System.out.println(new Gson().toJson(server)); + assertNotNull(server.getUuid()); + assertNotNull(server.getUser()); + assertEquals(server.getName(), prefix); + assertEquals(server.isPersistent(), true); + assertEquals(server.getDevices(), + ImmutableMap.of("ide:0:0", new IDEDevice.Builder(0, 0).uuid(drive.getUuid()).build())); + assertEquals(server.getBootDeviceIds(), ImmutableSet.of("ide:0:0")); + assertEquals(server.getNics().get(0).getDhcp(), server.getVnc().getIp()); + assertEquals(server.getNics().get(0).getModel(), Model.E1000); + assertEquals(server.getStatus(), ServerStatus.ACTIVE); + } + + @Test(dependsOnMethods = "testCreateAndStartServer") + public void testConnectivity() throws Exception { + Logger.getAnonymousLogger().info("awaiting vnc"); + assert socketTester.apply(new IPSocket(server.getVnc().getIp(), 5900)) : server; + Logger.getAnonymousLogger().info("awaiting ssh"); + assert socketTester.apply(new IPSocket(server.getNics().get(0).getDhcp(), 22)) : server; + doConnectViaSsh(server, getSshCredentials(server)); + } + + @Test(dependsOnMethods = "testConnectivity") + public void testLifeCycle() throws Exception { + client.stopServer(server.getUuid()); + assertEquals(client.getServerInfo(server.getUuid()).getStatus(), ServerStatus.STOPPED); + + client.startServer(server.getUuid()); + assertEquals(client.getServerInfo(server.getUuid()).getStatus(), ServerStatus.ACTIVE); + + client.resetServer(server.getUuid()); + assertEquals(client.getServerInfo(server.getUuid()).getStatus(), ServerStatus.ACTIVE); + + client.shutdownServer(server.getUuid()); + // behavior on shutdown depends on how your server OS is set up to respond to an ACPI power + // button signal + assert (client.getServerInfo(server.getUuid()).getStatus() == ServerStatus.ACTIVE || client.getServerInfo( + server.getUuid()).getStatus() == ServerStatus.STOPPED); + } + + @Test(dependsOnMethods = "testLifeCycle") + public void testSetServerConfiguration() throws Exception { + client.stopServer(server.getUuid()); + assertEquals(client.getServerInfo(server.getUuid()).getStatus(), ServerStatus.STOPPED); + + ServerInfo server2 = client.setServerConfiguration( + server.getUuid(), + Server.Builder.fromServer(server).name("rediculous") + .tags(ImmutableSet.of("networking", "security", "gateway")) + .userMetadata(ImmutableMap.of("foo", "bar")).build()); + + assertNotNull(server2.getUuid(), server.getUuid()); + assertEquals(server2.getName(), "rediculous"); + checkTagsAndMetadata(server2); + server = server2; + } + + protected void checkTagsAndMetadata(ServerInfo server2) { + assertEquals(server2.getTags(), ImmutableSet.of("networking", "security", "gateway")); + assertEquals(server2.getUserMetadata(), ImmutableMap.of("foo", "bar")); + } + + @Test(dependsOnMethods = "testSetServerConfiguration") + public void testDestroyServer() throws Exception { + client.destroyServer(server.getUuid()); + assertEquals(client.getServerInfo(server.getUuid()), null); + } + + @Test(dependsOnMethods = "testDestroyServer") + public void testDestroyDrive() throws Exception { + client.destroyDrive(drive.getUuid()); + assertEquals(client.getDriveInfo(drive.getUuid()), null); + } + + protected void doConnectViaSsh(Server server, Credentials creds) throws IOException { + SshClient ssh = Guice.createInjector(new JschSshClientModule()).getInstance(SshClient.Factory.class) + .create(new IPSocket(server.getVnc().getIp(), 22), creds); + try { + ssh.connect(); + ExecResponse hello = ssh.exec("echo hello"); + assertEquals(hello.getOutput().trim(), "hello"); + System.err.println(ssh.exec("df -k").getOutput()); + System.err.println(ssh.exec("mount").getOutput()); + System.err.println(ssh.exec("uname -a").getOutput()); + } finally { + if (ssh != null) + ssh.disconnect(); + } + } + + @AfterGroups(groups = "live") + protected void tearDown() { + try { + client.destroyServer(server.getUuid()); + } catch (Exception e) { + // no need to check null or anything as we swallow all + } + try { + client.destroyDrive(drive.getUuid()); + } catch (Exception e) { + + } + if (context != null) + context.close(); + } + + private DriveInfo drive2; + private DriveInfo drive3; + + public void testWeCanReadAndWriteToDrive() throws IOException { + drive2 = client.createDrive(new CreateDriveRequest.Builder().name(prefix + "2").size(1 * 1024 * 1024l).build()); + client.writeDrive(drive2.getUuid(), Payloads.newStringPayload("foo")); + assertEquals(Utils.toStringAndClose(client.readDrive(drive2.getUuid(), 0, 3).getInput()), "foo"); + } + + @Test(dependsOnMethods = "testWeCanReadAndWriteToDrive") + public void testWeCopyADriveContentsViaGzip() throws IOException { + try { + drive3 = client + .createDrive(new CreateDriveRequest.Builder().name(prefix + "3").size(1 * 1024 * 1024l).build()); + System.err.println("before image; drive 2" + client.getDriveInfo(drive2.getUuid())); + System.err.println("before image; drive 3" + client.getDriveInfo(drive3.getUuid())); + client.imageDrive(drive2.getUuid(), drive3.getUuid()); + assert driveNotClaimed.apply(drive3) : client.getDriveInfo(drive3.getUuid()); + assert driveNotClaimed.apply(drive2) : client.getDriveInfo(drive2.getUuid()); + System.err.println("after image; drive 2" + client.getDriveInfo(drive2.getUuid())); + System.err.println("after image; drive 3" + client.getDriveInfo(drive3.getUuid())); + assertEquals(Utils.toStringAndClose(client.readDrive(drive3.getUuid(), 0, 3).getInput()), "foo"); + } finally { + client.destroyDrive(drive2.getUuid()); + client.destroyDrive(drive3.getUuid()); + } + } + + protected Credentials getSshCredentials(Server server) { + return new Credentials("toor", server.getVnc().getPassword()); + } + + protected void prepareDrive() { + System.err.println("before prepare" + client.getDriveInfo(drive.getUuid())); + client.imageDrive("38df0986-4d85-4b76-b502-3878ffc80161", drive.getUuid(), ImageConversionType.GUNZIP); + assert driveNotClaimed.apply(drive) : client.getDriveInfo(drive.getUuid()); + System.err.println("after prepare" + client.getDriveInfo(drive.getUuid())); + } + +} diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ProvidersInPropertiesTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/ProvidersInPropertiesTest.java similarity index 62% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ProvidersInPropertiesTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/ProvidersInPropertiesTest.java index 1ecf6df951..1abd4ec256 100644 --- a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ProvidersInPropertiesTest.java +++ b/elasticstack/src/test/java/org/jclouds/elasticstack/ProvidersInPropertiesTest.java @@ -19,6 +19,7 @@ package org.jclouds.elasticstack; +import org.jclouds.compute.util.ComputeServiceUtils; import org.jclouds.util.Utils; import org.testng.annotations.Test; @@ -36,12 +37,18 @@ public class ProvidersInPropertiesTest { public void testSupportedProviders() { Iterable providers = Utils.getSupportedProviders(); assert Iterables.contains(providers, "elasticstack") : providers; + assert Iterables.contains(providers, "elastichosts-lon-p") : providers; + assert Iterables.contains(providers, "elastichosts-lon-b") : providers; + assert Iterables.contains(providers, "elastichosts-sat-p") : providers; + } + + @Test + public void testSupportedComputeServiceProviders() { + Iterable providers = ComputeServiceUtils.getSupportedProviders(); + assert Iterables.contains(providers, "elasticstack") : providers; + assert Iterables.contains(providers, "elastichosts-lon-p") : providers; + assert Iterables.contains(providers, "elastichosts-lon-b") : providers; + assert Iterables.contains(providers, "elastichosts-sat-p") : providers; } -// -// @Test -// public void testSupportedComputeServiceProviders() { -// Iterable providers = ComputeServiceUtils.getSupportedProviders(); -// assert Iterables.contains(providers, "cloudsigma") : providers; -// } } diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextStringTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextStringTest.java similarity index 100% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextStringTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindDriveDataToPlainTextStringTest.java diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindDriveToPlainTextStringTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindDriveToPlainTextStringTest.java similarity index 100% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindDriveToPlainTextStringTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindDriveToPlainTextStringTest.java diff --git a/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindServerToPlainTextStringTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindServerToPlainTextStringTest.java new file mode 100644 index 0000000000..d6fb33314d --- /dev/null +++ b/elasticstack/src/test/java/org/jclouds/elasticstack/binders/BindServerToPlainTextStringTest.java @@ -0,0 +1,92 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.binders; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.net.URI; +import java.util.Map; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.elasticstack.domain.IDEDevice; +import org.jclouds.elasticstack.domain.Model; +import org.jclouds.elasticstack.domain.NIC; +import org.jclouds.elasticstack.domain.Server; +import org.jclouds.elasticstack.domain.VNC; +import org.jclouds.elasticstack.functions.ServerToMap; +import org.jclouds.http.HttpRequest; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class BindServerToPlainTextStringTest { + + public static String CREATED_SERVER; + static { + try { + CREATED_SERVER = Utils.toStringAndClose(BindServerToPlainTextStringTest.class + .getResourceAsStream("/create_server.txt")); + } catch (IOException e) { + CREATED_SERVER = null; + } + } + public static final Server SERVER = new Server.Builder() + .name("TestServer") + .cpu(2000) + .mem(1024) + .devices( + ImmutableMap.of("ide:0:0", new IDEDevice.Builder(0, 0).uuid("08c92dd5-70a0-4f51-83d2-835919d254df") + .build())).bootDeviceIds(ImmutableSet.of("ide:0:0")) + .nics(ImmutableSet.of(new NIC.Builder().model(Model.E1000). + + build())).vnc(new VNC(null, "XXXXXXXX", false)).build(); + private static final BindServerToPlainTextString FN = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bind(new TypeLiteral>>() { + }).to(ServerToMap.class); + bind(new TypeLiteral>>() { + }).to(ServerToMap.class); + } + + }).getInstance(BindServerToPlainTextString.class); + + public void testSimple() throws IOException { + HttpRequest request = new HttpRequest("POST", URI.create("https://host/drives/create")); + FN.bindToRequest(request, SERVER); + assertEquals(request.getPayload().getContentMetadata().getContentType(), MediaType.TEXT_PLAIN); + assertEquals(request.getPayload().getRawContent(), CREATED_SERVER); + } + +} \ No newline at end of file diff --git a/elasticstack/src/test/java/org/jclouds/elasticstack/compute/ElasticStackComputeServiceLiveTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/compute/ElasticStackComputeServiceLiveTest.java new file mode 100644 index 0000000000..fa9c9c60bf --- /dev/null +++ b/elasticstack/src/test/java/org/jclouds/elasticstack/compute/ElasticStackComputeServiceLiveTest.java @@ -0,0 +1,39 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.compute; + +import org.jclouds.compute.BaseComputeServiceLiveTest; +import org.jclouds.ssh.jsch.config.JschSshClientModule; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "live") +public class ElasticStackComputeServiceLiveTest extends BaseComputeServiceLiveTest { + public ElasticStackComputeServiceLiveTest() { + provider = "elasticstack"; + } + + @Override + protected JschSshClientModule getSshModule() { + return new JschSshClientModule(); + } + +} diff --git a/elasticstack/src/test/java/org/jclouds/elasticstack/compute/ElasticStackTemplateBuilderLiveTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/compute/ElasticStackTemplateBuilderLiveTest.java new file mode 100644 index 0000000000..1808c71a83 --- /dev/null +++ b/elasticstack/src/test/java/org/jclouds/elasticstack/compute/ElasticStackTemplateBuilderLiveTest.java @@ -0,0 +1,56 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.compute; + +import org.jclouds.compute.BaseTemplateBuilderLiveTest; +import org.jclouds.compute.domain.OsFamily; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; +import org.testng.annotations.Test; + +import com.google.common.base.Predicate; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "live") +public class ElasticStackTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest { + + public ElasticStackTemplateBuilderLiveTest() { + provider = "elasticstack"; + } + + @Override + protected Predicate defineUnsupportedOperatingSystems() { + return new Predicate() { + + @Override + public boolean apply(OsFamilyVersion64Bit input) { + return ((input.family == OsFamily.RHEL) || // + (input.family == OsFamily.CENTOS && !(input.version.equals("5.5") && input.is64Bit)) || // + (input.family == OsFamily.UBUNTU && !(input.version.equals("10.04") && input.is64Bit)) || // + (input.family == OsFamily.WINDOWS && !((input.version.equals("2008") || input.version.equals("2008 R2")) && input.is64Bit)) // + ); + } + + }; + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/BaseDriveToMapTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/BaseDriveToMapTest.java similarity index 100% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/BaseDriveToMapTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/functions/BaseDriveToMapTest.java diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMapTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMapTest.java similarity index 100% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMapTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/functions/CreateDriveRequestToMapTest.java diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/DriveDataToMapTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/DriveDataToMapTest.java similarity index 100% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/DriveDataToMapTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/functions/DriveDataToMapTest.java diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java similarity index 100% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToDriveInfoTest.java diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToServerInfoTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToServerInfoTest.java similarity index 92% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToServerInfoTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToServerInfoTest.java index 37d3fa6292..8b27c55d89 100644 --- a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToServerInfoTest.java +++ b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/KeyValuesDelimitedByBlankLinesToServerInfoTest.java @@ -73,4 +73,9 @@ public class KeyValuesDelimitedByBlankLinesToServerInfoTest { assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newInputStreamPayload(MapToServerInfoTest.class .getResourceAsStream("/servers.txt")))), MapToServerInfoTest.ONE); } + + public void testNew() { + assertEquals(FN.apply(new HttpResponse(200, "", Payloads.newInputStreamPayload(MapToServerInfoTest.class + .getResourceAsStream("/new_server.txt")))), MapToServerInfoTest.NEW); + } } \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java similarity index 100% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest.java similarity index 100% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest.java diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSetTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSetTest.java similarity index 100% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSetTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfKeyValuesDelimitedByBlankLinesToServerInfoSetTest.java diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest.java similarity index 100% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/functions/ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest.java diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToDriveInfoTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToDriveInfoTest.java similarity index 100% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToDriveInfoTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToDriveInfoTest.java diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToServerInfoTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToServerInfoTest.java similarity index 77% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToServerInfoTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToServerInfoTest.java index b6ef223688..e3e28a1955 100644 --- a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToServerInfoTest.java +++ b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/MapToServerInfoTest.java @@ -124,4 +124,39 @@ public class MapToServerInfoTest { assertEquals(MAP_TO_DRIVE.apply(input), ONE); } + + public static ServerInfo NEW = new ServerInfo.Builder() + .persistent(true) + .uuid("bd98615a-6f74-4d63-ad1e-b13338b9356a") + .cpu(1000) + .bootDeviceIds(ImmutableSet.of("ide:0:0")) + .smp(1) + .mem(512) + .status(ServerStatus.ACTIVE) + .started(new Date(1292695612)) + .user("2f6244eb-50bc-4403-847e-f03cc3706a1f") + .name("adriancole.test") + .vnc(new VNC("83.222.249.221", "XXXXXXXX", false)) + .nics(ImmutableSet.of(new NIC.Builder() + .model(Model.E1000) + .block( + ImmutableList.of("tcp/43594", "tcp/5902", "udp/5060", "tcp/5900", "tcp/5901", "tcp/21", "tcp/22", + "tcp/23", "tcp/25", "tcp/110", "tcp/143", "tcp/43595")).build())) + .devices( + ImmutableMap.of("ide:0:0", + new IDEDevice.Builder((int) 0, (int) 0).uuid("403c9a86-0aab-4e47-aa95-e9768021c4c1").build() + + )) + .metrics( + new ServerMetrics.Builder().driveMetrics(ImmutableMap.of("ide:0:0", new DriveMetrics.Builder().build())) + .build()).build(); + + public void testNew() throws IOException { + + Map input = new ListOfKeyValuesDelimitedByBlankLinesToListOfMaps().apply( + Utils.toStringAndClose(MapToServerInfoTest.class.getResourceAsStream("/new_server.txt"))).get(0); + + assertEquals(MAP_TO_DRIVE.apply(input), NEW); + + } } \ No newline at end of file diff --git a/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ServerToMapTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ServerToMapTest.java new file mode 100644 index 0000000000..ea963ca3b8 --- /dev/null +++ b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/ServerToMapTest.java @@ -0,0 +1,66 @@ +/** + * + * Copyright (C) 2010 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.elasticstack.functions; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.elasticstack.domain.IDEDevice; +import org.jclouds.elasticstack.domain.Model; +import org.jclouds.elasticstack.domain.NIC; +import org.jclouds.elasticstack.domain.Server; +import org.jclouds.elasticstack.domain.VNC; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class ServerToMapTest { + + private static final ServerToMap SERVER_TO_MAP = new ServerToMap(); + + public void testBasics() { + assertEquals( + SERVER_TO_MAP.apply(new Server.Builder() + .name("TestServer") + .cpu(2000) + .mem(1024) + .devices( + ImmutableMap.of("ide:0:0", + new IDEDevice.Builder(0, 0).uuid("08c92dd5-70a0-4f51-83d2-835919d254df").build())) + .bootDeviceIds(ImmutableSet.of("ide:0:0")).nics(ImmutableSet.of(new NIC.Builder().model(Model.E1000). + + build())).vnc(new VNC(null, "XXXXXXXX", false)).build()), + ImmutableMap + .builder() + .putAll(ImmutableMap.of("name", "TestServer", "cpu", "2000", "smp", "auto", "mem", "1024")) + .putAll( + ImmutableMap.of("persistent", "false", "boot", "ide:0:0", "ide:0:0", + "08c92dd5-70a0-4f51-83d2-835919d254df")) + .putAll( + ImmutableMap.of("ide:0:0:media", "disk", "nic:0:model", "e1000", "vnc:ip", "auto", + "vnc:password", "XXXXXXXX")).build()); + } + +} \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/SplitNewlinesTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/functions/SplitNewlinesTest.java similarity index 100% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/functions/SplitNewlinesTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/functions/SplitNewlinesTest.java diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandlerTest.java b/elasticstack/src/test/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandlerTest.java similarity index 91% rename from sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandlerTest.java rename to elasticstack/src/test/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandlerTest.java index 0e23584cc0..e7165d0144 100644 --- a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandlerTest.java +++ b/elasticstack/src/test/java/org/jclouds/elasticstack/handlers/ElasticStackErrorHandlerTest.java @@ -52,9 +52,20 @@ public class ElasticStackErrorHandlerTest { IllegalArgumentException.class); } + @Test + public void test400MakesResourceNotFoundExceptionOnInfo() { + assertCodeMakes("GET", URI.create("https://elasticstack.com/foo/info"), 400, "", "", + ResourceNotFoundException.class); + } + @Test public void test400MakesResourceNotFoundExceptionOnMessageNotFound() { - assertCodeMakes("GET", URI.create("https://elasticstack.com/foo"), 400, "", "errors:system Drive 8f9b42b1-26de-49ad-a3fd-d4fa06524339 could not be found. Please re-validate your entry.", + assertCodeMakes( + "GET", + URI.create("https://elasticstack.com/foo"), + 400, + "", + "errors:system Drive 8f9b42b1-26de-49ad-a3fd-d4fa06524339 could not be found. Please re-validate your entry.", ResourceNotFoundException.class); } diff --git a/sandbox/elasticstack/src/test/resources/create_drive.txt b/elasticstack/src/test/resources/create_drive.txt similarity index 100% rename from sandbox/elasticstack/src/test/resources/create_drive.txt rename to elasticstack/src/test/resources/create_drive.txt diff --git a/elasticstack/src/test/resources/create_server.txt b/elasticstack/src/test/resources/create_server.txt new file mode 100644 index 0000000000..474d4d7ce1 --- /dev/null +++ b/elasticstack/src/test/resources/create_server.txt @@ -0,0 +1,11 @@ +name TestServer +cpu 2000 +smp auto +mem 1024 +persistent false +boot ide:0:0 +ide:0:0 08c92dd5-70a0-4f51-83d2-835919d254df +ide:0:0:media disk +nic:0:model e1000 +vnc:ip auto +vnc:password XXXXXXXX \ No newline at end of file diff --git a/sandbox/elasticstack/src/test/resources/drive.txt b/elasticstack/src/test/resources/drive.txt similarity index 100% rename from sandbox/elasticstack/src/test/resources/drive.txt rename to elasticstack/src/test/resources/drive.txt diff --git a/sandbox/elasticstack/src/test/resources/drive_data.txt b/elasticstack/src/test/resources/drive_data.txt similarity index 100% rename from sandbox/elasticstack/src/test/resources/drive_data.txt rename to elasticstack/src/test/resources/drive_data.txt diff --git a/elasticstack/src/test/resources/log4j.xml b/elasticstack/src/test/resources/log4j.xml new file mode 100644 index 0000000000..7343ec00e2 --- /dev/null +++ b/elasticstack/src/test/resources/log4j.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/elasticstack/src/test/resources/new_server.txt b/elasticstack/src/test/resources/new_server.txt new file mode 100644 index 0000000000..1dfbad99eb --- /dev/null +++ b/elasticstack/src/test/resources/new_server.txt @@ -0,0 +1,24 @@ +ide:0:0:write:requests 0 +boot ide:0:0 +vnc:password XXXXXXXX +ide:0:0 403c9a86-0aab-4e47-aa95-e9768021c4c1 +ide:0:0:read:requests 0 +ide:0:0:read:bytes 0 +vnc:ip 83.222.249.221 +tx:packets 0 +tx 0 +rx 0 +smp 1 +mem 512 +nic:0:model e1000 +status active +started 1292695612 +rx:packets 0 +user 2f6244eb-50bc-4403-847e-f03cc3706a1f +ide:0:0:media disk +name adriancole.test +persistent true +nic:0:block tcp/43594 tcp/5902 udp/5060 tcp/5900 tcp/5901 tcp/21 tcp/22 tcp/23 tcp/25 tcp/110 tcp/143 tcp/43595 +server bd98615a-6f74-4d63-ad1e-b13338b9356a +ide:0:0:write:bytes 0 +cpu 1000 \ No newline at end of file diff --git a/elasticstack/src/test/resources/servers.txt b/elasticstack/src/test/resources/servers.txt new file mode 100644 index 0000000000..a3d1ff1b46 --- /dev/null +++ b/elasticstack/src/test/resources/servers.txt @@ -0,0 +1,40 @@ +ide:0:0:write:requests 3698 +boot ide:0:0 +vnc:password HfHzVmLT +ide:0:0 4af85ed3-0caa-4736-8a26-a33d7de0a122 +ide:0:0:read:requests 11154 +ide:0:0:read:bytes 45686784 +vnc:ip 46.20.114.124 +tx:packets 31 +tx 2550 +rx 455530 +smp 1 +mem 1024 +nic:0:model e1000 +status active +started 1291493868 +rx:packets 7583 +user 2f6244eb-50bc-4403-847e-f03cc3706a1f +name jo +persistent true +nic:0:block tcp/43594 tcp/5902 udp/5060 tcp/5900 tcp/5901 tcp/21 tcp/22 tcp/23 tcp/25 tcp/110 tcp/143 tcp/43595 +server f8bee9cd-8e4b-4a05-8593-1314e3bfe49b +nic:0:dhcp 46.20.114.124 +ide:0:0:write:bytes 15147008 +cpu 2000 + +status stopped +name Demo +mem 1024 +boot ide:0:0 +vnc:password HWbjvrg2 +persistent true +server 0f962616-2071-4173-be79-7dd084271edf +smp auto +nic:0:dhcp auto +user 2f6244eb-50bc-4403-847e-f03cc3706a1f +nic:0:model e1000 +vnc:ip auto +ide:0:0 853bb98a-4fff-4c2f-a265-97c363f19ea5 +cpu 2000 +ide:0:0:media cdrom diff --git a/elasticstack/src/test/resources/uuids.txt b/elasticstack/src/test/resources/uuids.txt new file mode 100644 index 0000000000..092a4f8d6d --- /dev/null +++ b/elasticstack/src/test/resources/uuids.txt @@ -0,0 +1,3 @@ +7e8ab721-81c9-4cb9-a651-4cafbfe1501c +ea6a8fdb-dab3-4d06-86c2-41a5835e6ed9 +74744450-d338-4087-b3b8-59b505110a57 diff --git a/gogrid/src/test/java/org/jclouds/gogrid/compute/GoGridTemplateBuilderLiveTest.java b/gogrid/src/test/java/org/jclouds/gogrid/compute/GoGridTemplateBuilderLiveTest.java index ab09cf3337..57f881899b 100644 --- a/gogrid/src/test/java/org/jclouds/gogrid/compute/GoGridTemplateBuilderLiveTest.java +++ b/gogrid/src/test/java/org/jclouds/gogrid/compute/GoGridTemplateBuilderLiveTest.java @@ -25,9 +25,9 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.compute.BaseTemplateBuilderLiveTest; -import org.jclouds.compute.OsFamilyVersion64Bit; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; import org.testng.annotations.Test; import com.google.common.base.Predicate; diff --git a/pom.xml b/pom.xml index 6ff8b53bc2..798c852b84 100644 --- a/pom.xml +++ b/pom.xml @@ -50,6 +50,8 @@ rimuhosting vcloud gogrid + elasticstack + cloudsigma allcompute allblobstore all diff --git a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/handlers/ParseCloudFilesErrorFromHttpResponse.java b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/handlers/ParseCloudFilesErrorFromHttpResponse.java index 15d1f18d4a..d79b86be03 100644 --- a/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/handlers/ParseCloudFilesErrorFromHttpResponse.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/cloudfiles/handlers/ParseCloudFilesErrorFromHttpResponse.java @@ -46,9 +46,9 @@ import org.jclouds.util.Utils; public class ParseCloudFilesErrorFromHttpResponse implements HttpErrorHandler { @Resource protected Logger logger = Logger.NULL; - public static final String MOSSO_PREFIX = "^/v1[^/]*/MossoCloudFS_[^/]+/"; - public static final Pattern CONTAINER_PATH = Pattern.compile(MOSSO_PREFIX + "([^/]+)$"); - public static final Pattern CONTAINER_KEY_PATH = Pattern.compile(MOSSO_PREFIX + "([^/]+)/(.*)"); + public static final String PREFIX = "^/v[0-9][^/]*/[a-zA-Z]+_[^/]+/"; + public static final Pattern CONTAINER_PATH = Pattern.compile(PREFIX + "([^/]+)$"); + public static final Pattern CONTAINER_KEY_PATH = Pattern.compile(PREFIX + "([^/]+)/(.*)"); public void handleError(HttpCommand command, HttpResponse response) { Exception exception = new HttpResponseException(command, response); diff --git a/rackspace/src/main/java/org/jclouds/rackspace/functions/ParseAuthenticationResponseFromHeaders.java b/rackspace/src/main/java/org/jclouds/rackspace/functions/ParseAuthenticationResponseFromHeaders.java index baeef7961f..40f231364e 100755 --- a/rackspace/src/main/java/org/jclouds/rackspace/functions/ParseAuthenticationResponseFromHeaders.java +++ b/rackspace/src/main/java/org/jclouds/rackspace/functions/ParseAuthenticationResponseFromHeaders.java @@ -29,118 +29,115 @@ import static org.jclouds.rackspace.reference.RackspaceHeaders.STORAGE_URL; import java.net.URI; import javax.annotation.Resource; -import javax.inject.Singleton; +import javax.inject.Inject; +import javax.inject.Provider; +import javax.ws.rs.core.UriBuilder; +import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.logging.Logger; import org.jclouds.rackspace.RackspaceAuthAsyncClient.AuthenticationResponse; +import org.jclouds.rest.InvocationContext; import com.google.common.base.Function; +import com.google.common.base.Objects; /** * This parses {@link AuthenticationResponse} from HTTP headers. * * @author Adrian Cole */ -@Singleton -public class ParseAuthenticationResponseFromHeaders implements Function { +public class ParseAuthenticationResponseFromHeaders implements Function, + InvocationContext { public static final class AuthenticationResponseImpl implements AuthenticationResponse { - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((CDNManagementUrl == null) ? 0 : CDNManagementUrl.hashCode()); - result = prime * result + ((authToken == null) ? 0 : authToken.hashCode()); - result = prime * result + ((serverManagementUrl == null) ? 0 : serverManagementUrl.hashCode()); - result = prime * result + ((storageUrl == null) ? 0 : storageUrl.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; - AuthenticationResponseImpl other = (AuthenticationResponseImpl) obj; - if (CDNManagementUrl == null) { - if (other.CDNManagementUrl != null) - return false; - } else if (!CDNManagementUrl.equals(other.CDNManagementUrl)) - return false; - if (authToken == null) { - if (other.authToken != null) - return false; - } else if (!authToken.equals(other.authToken)) - return false; - if (serverManagementUrl == null) { - if (other.serverManagementUrl != null) - return false; - } else if (!serverManagementUrl.equals(other.serverManagementUrl)) - return false; - if (storageUrl == null) { - if (other.storageUrl != null) - return false; - } else if (!storageUrl.equals(other.storageUrl)) - return false; - return true; - } - private final String authToken; - private final String CDNManagementUrl; - private final String serverManagementUrl; - private final String storageUrl; + private final URI CDNManagementUrl; + private final URI serverManagementUrl; + private final URI storageUrl; - public AuthenticationResponseImpl(String authToken, String CDNManagementUrl, String serverManagementUrl, - String storageUrl) { + public AuthenticationResponseImpl(String authToken, URI CDNManagementUrl, URI serverManagementUrl, URI storageUrl) { this.authToken = authToken; this.CDNManagementUrl = CDNManagementUrl; this.serverManagementUrl = serverManagementUrl; this.storageUrl = storageUrl; } - @Override - public String toString() { - return "[CDNManagementUrl=" + CDNManagementUrl + ", serverManagementUrl=" + serverManagementUrl - + ", storageUrl=" + storageUrl + "]"; - } - public String getAuthToken() { return authToken; } public URI getCDNManagementUrl() { - return URI.create(CDNManagementUrl); + return CDNManagementUrl; } public URI getServerManagementUrl() { - return URI.create(serverManagementUrl); + return serverManagementUrl; } public URI getStorageUrl() { - return URI.create(storageUrl); + return storageUrl; } + + // performance isn't a concern on a infrequent object like this, so using shortcuts; + + @Override + public int hashCode() { + return Objects.hashCode(CDNManagementUrl, authToken, serverManagementUrl, storageUrl); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + return Objects.equal(this.toString(), that.toString()); + } + + @Override + public String toString() { + return Objects.toStringHelper(this).add("CDNManagementUrl", CDNManagementUrl) + .add("serverManagementUrl", serverManagementUrl).add("storageUrl", storageUrl).toString(); + } + } @Resource protected Logger logger = Logger.NULL; + private final Provider uriBuilderProvider; + private String hostToReplace; + + @Inject + public ParseAuthenticationResponseFromHeaders(Provider uriBuilderProvider) { + this.uriBuilderProvider = uriBuilderProvider; + } + /** - * parses the http response headers to create a new - * {@link AuthenticationResponse} object. + * parses the http response headers to create a new {@link AuthenticationResponse} object. */ public AuthenticationResponse apply(HttpResponse from) { releasePayload(from); - AuthenticationResponse response = new AuthenticationResponseImpl(checkNotNull(from - .getFirstHeaderOrNull(AUTH_TOKEN), AUTH_TOKEN), checkNotNull(from.getFirstHeaderOrNull(CDN_MANAGEMENT_URL), - CDN_MANAGEMENT_URL), checkNotNull(from.getFirstHeaderOrNull(SERVER_MANAGEMENT_URL), SERVER_MANAGEMENT_URL), - checkNotNull(from.getFirstHeaderOrNull(STORAGE_URL), STORAGE_URL + " not found in headers:" - + from.getStatusLine() + " - " + from.getHeaders())); + AuthenticationResponse response = new AuthenticationResponseImpl(checkNotNull( + from.getFirstHeaderOrNull(AUTH_TOKEN), AUTH_TOKEN), getURI(from, CDN_MANAGEMENT_URL), getURI(from, + SERVER_MANAGEMENT_URL), getURI(from, STORAGE_URL)); logger.debug("will connect to: ", response); return response; } + + protected URI getURI(HttpResponse from, String header) { + String headerValue = from.getFirstHeaderOrNull(header); + if (headerValue == null) + return null; + URI toReturn = URI.create(headerValue); + if (!"127.0.0.1".equals(toReturn.getHost())) + return toReturn; + return uriBuilderProvider.get().uri(toReturn).host(hostToReplace).build(); + } + + @Override + public Object setContext(HttpRequest request) { + hostToReplace = request.getEndpoint().getHost(); + return this; + } } \ No newline at end of file diff --git a/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseAuthenticationResponseFromHeadersTest.java b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseAuthenticationResponseFromHeadersTest.java new file mode 100644 index 0000000000..15c3fc5af1 --- /dev/null +++ b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/functions/ParseAuthenticationResponseFromHeadersTest.java @@ -0,0 +1,77 @@ +/** + * + * Copyright (C) 2010 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.rackspace.cloudfiles.functions; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import javax.ws.rs.core.UriBuilder; + +import org.jclouds.Constants; +import org.jclouds.blobstore.reference.BlobStoreConstants; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.rackspace.RackspaceAuthAsyncClient.AuthenticationResponse; +import org.jclouds.rackspace.functions.ParseAuthenticationResponseFromHeaders; +import org.testng.annotations.Test; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.google.inject.name.Names; +import com.sun.jersey.api.uri.UriBuilderImpl; + +/** + * Tests behavior of {@code ParseContainerListFromJsonResponse} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "cloudfiles.ParseAuthenticationResponseFromHeadersTest") +public class ParseAuthenticationResponseFromHeadersTest { + + Injector i = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bindConstant().annotatedWith(Names.named(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX)).to("sdf"); + bindConstant().annotatedWith(Names.named(Constants.PROPERTY_API_VERSION)).to("1"); + bind(UriBuilder.class).to(UriBuilderImpl.class); + } + + }); + + public void testReplaceLocalhost() { + ParseAuthenticationResponseFromHeaders parser = i.getInstance(ParseAuthenticationResponseFromHeaders.class); + HttpRequest request = new HttpRequest("GET", URI.create("http://realhost:11000/v1.0")); + parser.setContext(request); + + HttpResponse response = new HttpResponse(204, "No Content", null); + response.getHeaders().put("X-Auth-Token", "token"); + response.getHeaders().put("X-Storage-Token", "token"); + response.getHeaders().put("X-Storage-Url", "http://127.0.0.1:8080/v1/token"); + + AuthenticationResponse md = parser.apply(response); + assertEquals( + md, + new ParseAuthenticationResponseFromHeaders.AuthenticationResponseImpl("token", null, null, URI + .create("http://realhost:8080/v1/token"))); + } +} diff --git a/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/handlers/ParseCloudFilesErrorFromHttpResponseTest.java b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/handlers/ParseCloudFilesErrorFromHttpResponseTest.java new file mode 100644 index 0000000000..bebbd38916 --- /dev/null +++ b/rackspace/src/test/java/org/jclouds/rackspace/cloudfiles/handlers/ParseCloudFilesErrorFromHttpResponseTest.java @@ -0,0 +1,101 @@ +package org.jclouds.rackspace.cloudfiles.handlers; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.reportMatcher; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.easymock.classextension.EasyMock.verify; + +import java.net.URI; + +import org.easymock.IArgumentMatcher; +import org.jclouds.blobstore.ContainerNotFoundException; +import org.jclouds.blobstore.KeyNotFoundException; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class ParseCloudFilesErrorFromHttpResponseTest { + + @Test + public void test404SetsKeyNotFoundExceptionMosso() { + assertCodeMakes("HEAD", + URI.create("http://host/v1/MossoCloudFS_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1/key"), 404, + "Not Found", "", KeyNotFoundException.class); + } + + @Test + public void test404SetsKeyNotFoundExceptionSwift() { + assertCodeMakes("HEAD", + URI.create("http://67.202.39.175:8080/v1/AUTH_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1/key"), + 404, "Not Found", "", KeyNotFoundException.class); + } + + @Test + public void test404SetsContainerNotFoundExceptionMosso() { + assertCodeMakes("HEAD", + URI.create("http://host/v1/MossoCloudFS_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1"), 404, + "Not Found", "", ContainerNotFoundException.class); + } + + @Test + public void test404SetsContainerNotFoundExceptionSwift() { + assertCodeMakes("HEAD", + URI.create("http://67.202.39.175:8080/v1/AUTH_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1"), + 404, "Not Found", "", ContainerNotFoundException.class); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content, + Class expected) { + assertCodeMakes(method, uri, statusCode, message, "text/plain", content, expected); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType, + String content, Class expected) { + + ParseCloudFilesErrorFromHttpResponse function = new ParseCloudFilesErrorFromHttpResponse(); + + HttpCommand command = createMock(HttpCommand.class); + HttpRequest request = new HttpRequest(method, uri); + HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Utils + .toInputStream(content))); + response.getPayload().getContentMetadata().setContentType(contentType); + + expect(command.getRequest()).andReturn(request).atLeastOnce(); + command.setException(classEq(expected)); + + replay(command); + + function.handleError(command, response); + + verify(command); + } + + public static Exception classEq(final Class in) { + reportMatcher(new IArgumentMatcher() { + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("classEq("); + buffer.append(in); + buffer.append(")"); + } + + @Override + public boolean matches(Object arg) { + return arg.getClass() == in; + } + + }); + return null; + } + +} \ No newline at end of file diff --git a/rackspace/src/test/java/org/jclouds/rackspace/cloudservers/TestRackspaceAuthenticationRestClientModule.java b/rackspace/src/test/java/org/jclouds/rackspace/cloudservers/TestRackspaceAuthenticationRestClientModule.java index 7cf599465a..4f5e49b283 100644 --- a/rackspace/src/test/java/org/jclouds/rackspace/cloudservers/TestRackspaceAuthenticationRestClientModule.java +++ b/rackspace/src/test/java/org/jclouds/rackspace/cloudservers/TestRackspaceAuthenticationRestClientModule.java @@ -19,6 +19,7 @@ package org.jclouds.rackspace.cloudservers; +import java.net.URI; import java.util.Date; import org.jclouds.http.RequiresHttp; @@ -39,8 +40,8 @@ public class TestRackspaceAuthenticationRestClientModule extends RackspaceAuthen @Override protected AuthenticationResponse provideAuthenticationResponse(Supplier supplier) { - return new AuthenticationResponseImpl("authToken", "http://CDNManagementUrl", "http://serverManagementUrl", - "http://storageUrl"); + return new AuthenticationResponseImpl("authToken", URI.create("http://CDNManagementUrl"), + URI.create("http://serverManagementUrl"), URI.create("http://storageUrl")); } @Override diff --git a/rackspace/src/test/java/org/jclouds/rackspace/cloudservers/compute/CloudServersTemplateBuilderLiveTest.java b/rackspace/src/test/java/org/jclouds/rackspace/cloudservers/compute/CloudServersTemplateBuilderLiveTest.java index 0eb104d29a..8152a48dc7 100644 --- a/rackspace/src/test/java/org/jclouds/rackspace/cloudservers/compute/CloudServersTemplateBuilderLiveTest.java +++ b/rackspace/src/test/java/org/jclouds/rackspace/cloudservers/compute/CloudServersTemplateBuilderLiveTest.java @@ -20,8 +20,8 @@ package org.jclouds.rackspace.cloudservers.compute; import org.jclouds.compute.BaseTemplateBuilderLiveTest; -import org.jclouds.compute.OsFamilyVersion64Bit; import org.jclouds.compute.domain.OsFamily; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; import org.testng.annotations.Test; import com.google.common.base.Predicate; diff --git a/rimuhosting/src/test/java/org/jclouds/rimuhosting/miro/compute/RimuHostingTemplateBuilderLiveTest.java b/rimuhosting/src/test/java/org/jclouds/rimuhosting/miro/compute/RimuHostingTemplateBuilderLiveTest.java index 4206b962db..72256eea09 100644 --- a/rimuhosting/src/test/java/org/jclouds/rimuhosting/miro/compute/RimuHostingTemplateBuilderLiveTest.java +++ b/rimuhosting/src/test/java/org/jclouds/rimuhosting/miro/compute/RimuHostingTemplateBuilderLiveTest.java @@ -20,8 +20,8 @@ package org.jclouds.rimuhosting.miro.compute; import org.jclouds.compute.BaseTemplateBuilderLiveTest; -import org.jclouds.compute.OsFamilyVersion64Bit; import org.jclouds.compute.domain.OsFamily; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; import org.testng.annotations.Test; import com.google.common.base.Predicate; diff --git a/sandbox/boxdotnet/src/test/java/org/jclouds/boxdotnet/BoxDotNetAsyncClientTest.java b/sandbox/boxdotnet/src/test/java/org/jclouds/boxdotnet/BoxDotNetAsyncClientTest.java index 9845e8409d..8703f49368 100644 --- a/sandbox/boxdotnet/src/test/java/org/jclouds/boxdotnet/BoxDotNetAsyncClientTest.java +++ b/sandbox/boxdotnet/src/test/java/org/jclouds/boxdotnet/BoxDotNetAsyncClientTest.java @@ -30,7 +30,7 @@ import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.functions.ReleasePayloadAndReturn; import org.jclouds.http.functions.ReturnStringIf2xx; import org.jclouds.rest.RestClientTest; -import org.jclouds.rest.RestContextFactory.ContextSpec; +import org.jclouds.rest.RestContextSpec; import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; import org.jclouds.rest.internal.GeneratedHttpRequest; @@ -123,7 +123,7 @@ public class BoxDotNetAsyncClientTest extends RestClientTest createContextSpec() { + public RestContextSpec createContextSpec() { return contextSpec("boxdotnet", "https://www.box.net/api/1.0/rest", "1.0", "identity", "credential", BoxDotNetClient.class, BoxDotNetAsyncClient.class); } diff --git a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaAsyncClient.java b/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaAsyncClient.java deleted file mode 100644 index 4a0ba2fe95..0000000000 --- a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaAsyncClient.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * - * Copyright (C) 2010 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.cloudsigma; - -import java.util.Set; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.core.MediaType; - -import org.jclouds.cloudsigma.domain.DriveInfo; -import org.jclouds.cloudsigma.functions.KeyValuesDelimitedByBlankLinesToDriveInfo; -import org.jclouds.cloudsigma.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet; -import org.jclouds.elasticstack.CommonElasticStackAsyncClient; -import org.jclouds.elasticstack.ElasticStackClient; -import org.jclouds.elasticstack.binders.BindDriveDataToPlainTextString; -import org.jclouds.elasticstack.binders.BindDriveToPlainTextString; -import org.jclouds.elasticstack.domain.Drive; -import org.jclouds.elasticstack.domain.DriveData; -import org.jclouds.elasticstack.functions.SplitNewlines; -import org.jclouds.http.filters.BasicAuthentication; -import org.jclouds.rest.annotations.BinderParam; -import org.jclouds.rest.annotations.ExceptionParser; -import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; - -import com.google.common.util.concurrent.ListenableFuture; - -/** - * Provides asynchronous access to CloudSigma via their REST API. - *

- * - * @see ElasticStackClient - * @see - * @author Adrian Cole - */ -@RequestFilters(BasicAuthentication.class) -@Consumes(MediaType.TEXT_PLAIN) -public interface CloudSigmaAsyncClient extends CommonElasticStackAsyncClient { - - /** - * @see ElasticStackClient#listStandardDrives() - */ - @GET - @Path("/drives/standard/list") - @ResponseParser(SplitNewlines.class) - ListenableFuture> listStandardDrives(); - - /** - * @see ElasticStackClient#listStandardCds() - */ - @GET - @Path("/drives/standard/cd/list") - @ResponseParser(SplitNewlines.class) - ListenableFuture> listStandardCds(); - - /** - * @see ElasticStackClient#listStandardImages() - */ - @GET - @Path("/drives/standard/img/list") - @ResponseParser(SplitNewlines.class) - ListenableFuture> listStandardImages(); - - /** - * @see ElasticStackClient#listDriveInfo() - */ - @Override - @GET - @Path("/drives/info") - @ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class) - ListenableFuture> listDriveInfo(); - - /** - * @see ElasticStackClient#getDriveInfo - */ - @Override - @GET - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) - @Path("/drives/{uuid}/info") - ListenableFuture getDriveInfo(@PathParam("uuid") String uuid); - - /** - * @see ElasticStackClient#createDrive - */ - @Override - @POST - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) - @Path("/drives/create") - ListenableFuture createDrive(@BinderParam(BindDriveToPlainTextString.class) Drive createDrive); - - /** - * @see ElasticStackClient#setDriveData - */ - @POST - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) - @Path("/drives/{uuid}/set") - ListenableFuture setDriveData(@PathParam("uuid") String uuid, - @BinderParam(BindDriveDataToPlainTextString.class) DriveData createDrive); -} diff --git a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaClient.java b/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaClient.java deleted file mode 100644 index ecf4394a63..0000000000 --- a/sandbox/cloudsigma/src/main/java/org/jclouds/cloudsigma/CloudSigmaClient.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * - * Copyright (C) 2010 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.cloudsigma; - -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import org.jclouds.cloudsigma.domain.DriveInfo; -import org.jclouds.concurrent.Timeout; -import org.jclouds.elasticstack.CommonElasticStackClient; -import org.jclouds.elasticstack.domain.Drive; -import org.jclouds.elasticstack.domain.DriveData; - -/** - * Provides synchronous access to CloudSigma. - *

- * - * @see CloudSigmaAsyncClient - * @see - * @author Adrian Cole - */ -@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) -public interface CloudSigmaClient extends CommonElasticStackClient { - - /** - * list of drive uuids that are in the library - * - * @return or empty set if no drives are found - */ - Set listStandardDrives(); - - /** - * list of cd uuids that are in the library - * - * @return or empty set if no cds are found - */ - Set listStandardCds(); - - /** - * list of image uuids that are in the library - * - * @return or empty set if no images are found - */ - Set listStandardImages(); - - /** - * {@inheritDoc} - */ - @Override - Set listDriveInfo(); - - /** - * {@inheritDoc} - */ - @Override - DriveInfo getDriveInfo(String uuid); - - /** - * {@inheritDoc} - */ - @Override - DriveInfo createDrive(Drive createDrive); - - /** - * {@inheritDoc} - */ - @Override - DriveInfo setDriveData(String uuid, DriveData driveData); - -} diff --git a/sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaAsyncClientTest.java b/sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaAsyncClientTest.java deleted file mode 100644 index 51039a819d..0000000000 --- a/sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaAsyncClientTest.java +++ /dev/null @@ -1,181 +0,0 @@ -/** - * - * Copyright (C) 2010 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.cloudsigma; - -import static org.testng.Assert.assertEquals; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.Properties; - -import org.jclouds.cloudsigma.functions.KeyValuesDelimitedByBlankLinesToDriveInfo; -import org.jclouds.cloudsigma.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet; -import org.jclouds.elasticstack.domain.CreateDriveRequest; -import org.jclouds.elasticstack.domain.Drive; -import org.jclouds.elasticstack.domain.DriveData; -import org.jclouds.elasticstack.functions.SplitNewlines; -import org.jclouds.http.HttpRequest; -import org.jclouds.http.filters.BasicAuthentication; -import org.jclouds.rest.RestClientTest; -import org.jclouds.rest.RestContextFactory; -import org.jclouds.rest.RestContextSpec; -import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; -import org.jclouds.rest.internal.GeneratedHttpRequest; -import org.jclouds.rest.internal.RestAnnotationProcessor; -import org.testng.annotations.Test; - -import com.google.common.collect.ImmutableList; -import com.google.inject.TypeLiteral; - -/** - * Tests annotation parsing of {@code CloudSigmaAsyncClient} - * - * @author Adrian Cole - */ -@Test(groups = "unit", testName = "cloudsigma.CloudSigmaAsyncClientTest") -public class CloudSigmaAsyncClientTest extends RestClientTest { - - public void testListStandardDrives() throws SecurityException, NoSuchMethodException, IOException { - Method method = CloudSigmaAsyncClient.class.getMethod("listStandardDrives"); - GeneratedHttpRequest httpRequest = processor.createRequest(method); - - assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/standard/list HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); - assertPayloadEquals(httpRequest, null, null, false); - - assertResponseParserClassEquals(method, httpRequest, SplitNewlines.class); - assertSaxResponseParserClassEquals(method, null); - assertExceptionParserClassEquals(method, null); - - checkFilters(httpRequest); - } - - public void testListStandardCds() throws SecurityException, NoSuchMethodException, IOException { - Method method = CloudSigmaAsyncClient.class.getMethod("listStandardCds"); - GeneratedHttpRequest httpRequest = processor.createRequest(method); - - assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/standard/cd/list HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); - assertPayloadEquals(httpRequest, null, null, false); - - assertResponseParserClassEquals(method, httpRequest, SplitNewlines.class); - assertSaxResponseParserClassEquals(method, null); - assertExceptionParserClassEquals(method, null); - - checkFilters(httpRequest); - } - - public void testListStandardImages() throws SecurityException, NoSuchMethodException, IOException { - Method method = CloudSigmaAsyncClient.class.getMethod("listStandardImages"); - GeneratedHttpRequest httpRequest = processor.createRequest(method); - - assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/standard/img/list HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); - assertPayloadEquals(httpRequest, null, null, false); - - assertResponseParserClassEquals(method, httpRequest, SplitNewlines.class); - assertSaxResponseParserClassEquals(method, null); - assertExceptionParserClassEquals(method, null); - - checkFilters(httpRequest); - } - - public void testListDriveInfo() throws SecurityException, NoSuchMethodException, IOException { - Method method = CloudSigmaAsyncClient.class.getMethod("listDriveInfo"); - GeneratedHttpRequest httpRequest = processor.createRequest(method); - - assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/info HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); - assertPayloadEquals(httpRequest, null, null, false); - - assertResponseParserClassEquals(method, httpRequest, ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class); - assertSaxResponseParserClassEquals(method, null); - assertExceptionParserClassEquals(method, null); - - checkFilters(httpRequest); - } - - public void testGetDriveInfo() throws SecurityException, NoSuchMethodException, IOException { - Method method = CloudSigmaAsyncClient.class.getMethod("getDriveInfo", String.class); - GeneratedHttpRequest httpRequest = processor.createRequest(method, "uuid"); - - assertRequestLineEquals(httpRequest, "GET https://api.cloudsigma.com/drives/uuid/info HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); - assertPayloadEquals(httpRequest, null, null, false); - - assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); - assertSaxResponseParserClassEquals(method, null); - assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); - - checkFilters(httpRequest); - - } - - public void testCreateDrive() throws SecurityException, NoSuchMethodException, IOException { - Method method = CloudSigmaAsyncClient.class.getMethod("createDrive", Drive.class); - GeneratedHttpRequest httpRequest = processor.createRequest(method, - new CreateDriveRequest.Builder().name("foo").tags(ImmutableList.of("production", "candy")).size(10000l).build()); - - assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/drives/create HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); - assertPayloadEquals(httpRequest, "name foo\nsize 10000\nuse production,candy", "text/plain", false); - - assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); - assertSaxResponseParserClassEquals(method, null); - assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); - - checkFilters(httpRequest); - - } - - public void testSetDriveData() throws SecurityException, NoSuchMethodException, IOException { - Method method = CloudSigmaAsyncClient.class.getMethod("setDriveData", String.class, DriveData.class); - GeneratedHttpRequest httpRequest = processor.createRequest(method, "100", - new DriveData.Builder().name("foo").size(10000l).tags(ImmutableList.of("production", "candy")).build()); - - assertRequestLineEquals(httpRequest, "POST https://api.cloudsigma.com/drives/100/set HTTP/1.1"); - assertNonPayloadHeadersEqual(httpRequest, "Accept: text/plain\n"); - assertPayloadEquals(httpRequest, "name foo\nsize 10000\nuse production,candy", "text/plain", false); - - assertResponseParserClassEquals(method, httpRequest, KeyValuesDelimitedByBlankLinesToDriveInfo.class); - assertSaxResponseParserClassEquals(method, null); - assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); - - checkFilters(httpRequest); - - } - - @Override - protected void checkFilters(HttpRequest request) { - assertEquals(request.getFilters().size(), 1); - assertEquals(request.getFilters().get(0).getClass(), BasicAuthentication.class); - } - - @Override - protected TypeLiteral> createTypeLiteral() { - return new TypeLiteral>() { - }; - } - - @Override - public RestContextSpec createContextSpec() { - return new RestContextFactory().createContextSpec("cloudsigma", "foo", "bar", new Properties()); - } -} diff --git a/sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java b/sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java deleted file mode 100644 index 223fa37d14..0000000000 --- a/sandbox/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * - * Copyright (C) 2010 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.cloudsigma; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; - -import java.util.Set; - -import org.jclouds.cloudsigma.domain.DriveInfo; -import org.jclouds.cloudsigma.domain.DriveType; -import org.jclouds.elasticstack.CommonElasticStackClientLiveTest; -import org.testng.annotations.Test; - -/** - * Tests behavior of {@code CloudSigmaClient} - * - * @author Adrian Cole - */ -@Test(groups = "live", testName = "cloudsigma.CloudSigmaClientLiveTest") -public class CloudSigmaClientLiveTest extends CommonElasticStackClientLiveTest { - - public CloudSigmaClientLiveTest() { - provider = "cloudsigma"; - } - - @Test - public void testListStandardDrives() throws Exception { - Set drives = client.listStandardDrives(); - assertNotNull(drives); - } - - @Test - public void testListStandardCds() throws Exception { - Set drives = client.listStandardCds(); - assertNotNull(drives); - } - - @Test - public void testListStandardImages() throws Exception { - Set drives = client.listStandardImages(); - assertNotNull(drives); - } - @Override - protected void checkDriveMatchesGet(org.jclouds.elasticstack.domain.DriveInfo newInfo) { - super.checkDriveMatchesGet(newInfo); - assertEquals(DriveInfo.class.cast(newInfo).getType(), DriveType.DISK); - } - - @Override - protected void checkCreatedDrive() { - super.checkCreatedDrive(); - assertEquals(DriveInfo.class.cast(info).getType(), null); - } -} diff --git a/sandbox/deltacloud/README.txt b/sandbox/deltacloud/README.txt new file mode 100644 index 0000000000..ee1b021e83 --- /dev/null +++ b/sandbox/deltacloud/README.txt @@ -0,0 +1,9 @@ +To install deltacloud, do the following: + * OS/X and jruby + # brew install jruby + # jruby -S gem --version 1.1.0 install rack + # jruby -S gem install deltacloud-core + +To run a local deltacloud server, do the following: + * jruby + * jruby -S deltacloudd -i mock diff --git a/sandbox/deltacloud/pom.xml b/sandbox/deltacloud/pom.xml new file mode 100644 index 0000000000..d66b991628 --- /dev/null +++ b/sandbox/deltacloud/pom.xml @@ -0,0 +1,133 @@ + + + + 4.0.0 + + org.jclouds + jclouds-project + 1.0-SNAPSHOT + ../../project/pom.xml + + org.jclouds + jclouds-deltacloud + jclouds deltacloud core + jclouds components to access deltacloud + + + + + jclouds-googlecode-deploy + http://jclouds.googlecode.com/svn/repo + + + jclouds-rimu-snapshots-nexus + https://oss.sonatype.org/content/repositories/snapshots + + true + + + + + + + trmkrun-ccc,test.trmk-924 + http://localhost:3001/api + 1.0 + mockuser + mockpassword + + + + ${project.groupId} + jclouds-core + ${project.version} + + + ${project.groupId} + jclouds-core + ${project.version} + test-jar + test + + + log4j + log4j + 1.2.14 + test + + + ${project.groupId} + jclouds-log4j + ${project.version} + test + + + + + live + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration + integration-test + + test + + + + + test.deltacloud.endpoint + ${test.deltacloud.endpoint} + + + test.deltacloud.apiversion + ${test.deltacloud.apiversion} + + + test.deltacloud.identity + ${test.deltacloud.identity} + + + test.deltacloud.credential + ${test.deltacloud.credential} + + + jclouds.compute.blacklist-nodes + ${jclouds.compute.blacklist-nodes} + + + + + + + + + + + diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/DeltacloudAsyncClient.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/DeltacloudAsyncClient.java new file mode 100644 index 0000000000..86dac7b9e8 --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/DeltacloudAsyncClient.java @@ -0,0 +1,99 @@ +/** + * + * Copyright (C) 2010 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.deltacloud; + +import java.net.URI; +import java.util.Map; +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; + +import org.jclouds.deltacloud.collections.DeltacloudCollection; +import org.jclouds.deltacloud.collections.Images; +import org.jclouds.deltacloud.collections.Instances; +import org.jclouds.deltacloud.domain.Image; +import org.jclouds.deltacloud.options.CreateInstanceOptions; +import org.jclouds.deltacloud.xml.ImageHandler; +import org.jclouds.deltacloud.xml.ImagesHandler; +import org.jclouds.deltacloud.xml.LinksHandler; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.rest.annotations.Endpoint; +import org.jclouds.rest.annotations.EndpointParam; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.XMLResponseParser; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to deltacloud via their REST API. + *

+ * + * @see DeltacloudClient + * @see + * @author Adrian Cole + */ +@RequestFilters(BasicAuthentication.class) +@Consumes(MediaType.APPLICATION_XML) +public interface DeltacloudAsyncClient { + + /** + * @see DeltacloudClient#getCollections + */ + @GET + @Path("") + @XMLResponseParser(LinksHandler.class) + ListenableFuture> getCollections(); + + /** + * @see DeltacloudClient#listImages + */ + @GET + @Endpoint(Images.class) + @Path("") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + @XMLResponseParser(ImagesHandler.class) + ListenableFuture> listImages(); + + /** + * @see DeltacloudClient#getImage + */ + @GET + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @Path("") + @XMLResponseParser(ImageHandler.class) + ListenableFuture getImage(@EndpointParam URI imageHref); + + /** + * @see DeltacloudClient#createInstance + */ + @POST + @Endpoint(Instances.class) + @Path("") + ListenableFuture createInstance(@FormParam("image_id") String imageId, CreateInstanceOptions... options); + +} diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/DeltacloudClient.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/DeltacloudClient.java new file mode 100644 index 0000000000..a993777a56 --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/DeltacloudClient.java @@ -0,0 +1,80 @@ +/** + * + * Copyright (C) 2010 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.deltacloud; + +import java.net.URI; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.deltacloud.collections.DeltacloudCollection; +import org.jclouds.deltacloud.domain.Image; +import org.jclouds.deltacloud.options.CreateInstanceOptions; + +/** + * Provides synchronous access to deltacloud. + *

+ * + * @see DeltacloudAsyncClient + * @see + * @author Adrian Cole + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface DeltacloudClient { + /** + * The result of this entry-point is a set of entry-points into other collections, such as + * images, instances, hardware profiles and realms, among others. + * + * @return named links to available collections, or empty map, if no resources are found + */ + Map getCollections(); + + /** + * The images collection will return a set of all images available to the current user. + * + * @return images viewable to the user or empty set + */ + Set listImages(); + + /** + * + * @param imageHref + * @return image or null, if not found + */ + Image getImage(URI imageHref); + + /** + * Create a new Instance + * + *

Note

+ * + * If options realmId or hardwareProfileName are not specified, the provider must select + * reasonable defaults. The architecture of the selected hardware profile must match the + * architecture of the specified image. + * + * @param imageId + * The identifier (not URL) of the image from which to base the instance + * @param options + * includes realm, hardware profile, etc. + * @return newly-created instance including a URL to retrieve the instance in the future. + */ + String createInstance(String imageId, CreateInstanceOptions... options); +} diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/DeltacloudContextBuilder.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/DeltacloudContextBuilder.java new file mode 100644 index 0000000000..7704c625e1 --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/DeltacloudContextBuilder.java @@ -0,0 +1,45 @@ +/** + * + * Copyright (C) 2010 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.deltacloud; + +import java.util.List; +import java.util.Properties; + +import org.jclouds.deltacloud.config.DeltacloudRestClientModule; +import org.jclouds.rest.RestContextBuilder; + +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +public class DeltacloudContextBuilder extends + RestContextBuilder { + + public DeltacloudContextBuilder(Properties props) { + super(DeltacloudClient.class, DeltacloudAsyncClient.class, props); + } + + protected void addClientModule(List modules) { + modules.add(new DeltacloudRestClientModule()); + } + +} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackPropertiesBuilder.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/DeltacloudPropertiesBuilder.java similarity index 84% rename from sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackPropertiesBuilder.java rename to sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/DeltacloudPropertiesBuilder.java index 4f1b2bd9ee..5e10e40f57 100644 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackPropertiesBuilder.java +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/DeltacloudPropertiesBuilder.java @@ -17,7 +17,7 @@ * ==================================================================== */ -package org.jclouds.elasticstack; +package org.jclouds.deltacloud; import static org.jclouds.Constants.PROPERTY_API_VERSION; @@ -26,11 +26,11 @@ import java.util.Properties; import org.jclouds.PropertiesBuilder; /** - * Builds properties used in elasticstack Clients + * Builds properties used in deltacloud Clients * * @author Adrian Cole */ -public class ElasticStackPropertiesBuilder extends PropertiesBuilder { +public class DeltacloudPropertiesBuilder extends PropertiesBuilder { @Override protected Properties defaultProperties() { Properties properties = super.defaultProperties(); @@ -38,7 +38,7 @@ public class ElasticStackPropertiesBuilder extends PropertiesBuilder { return properties; } - public ElasticStackPropertiesBuilder(Properties properties) { + public DeltacloudPropertiesBuilder(Properties properties) { super(properties); } diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/collections/DeltacloudCollection.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/collections/DeltacloudCollection.java new file mode 100644 index 0000000000..6767cd083d --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/collections/DeltacloudCollection.java @@ -0,0 +1,36 @@ +package org.jclouds.deltacloud.collections; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.CaseFormat; + +/** + * + * @author Adrian Cole + */ +public enum DeltacloudCollection { + HARDWARE_PROFILES, INSTANCE_STATES, REALMS, + + @Images + IMAGES, + + @Instances + INSTANCES, UNRECOGNIZED; + + public String value() { + return (CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_UNDERSCORE, name())); + } + + @Override + public String toString() { + return value(); + } + + public static DeltacloudCollection fromValue(String link) { + try { + return valueOf(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(link, "link"))); + } catch (IllegalArgumentException e) { + return UNRECOGNIZED; + } + } +} \ No newline at end of file diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/collections/Images.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/collections/Images.java new file mode 100644 index 0000000000..58442ec4c4 --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/collections/Images.java @@ -0,0 +1,40 @@ +/** + * + * Copyright (C) 2010 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.deltacloud.collections; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.inject.Qualifier; + +/** + * The images collection will return a set of all images available to the current user. + * + * @author Adrian Cole + * + */ +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) +@Qualifier +public @interface Images { + +} \ No newline at end of file diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/collections/Instances.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/collections/Instances.java new file mode 100644 index 0000000000..22268849c7 --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/collections/Instances.java @@ -0,0 +1,40 @@ +/** + * + * Copyright (C) 2010 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.deltacloud.collections; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.inject.Qualifier; + +/** + * The instances collection will return a set of all instances available to the current user. + * + * @author Adrian Cole + * + */ +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) +@Qualifier +public @interface Instances { + +} \ No newline at end of file diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/config/DeltacloudRestClientModule.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/config/DeltacloudRestClientModule.java new file mode 100644 index 0000000000..0417749cfa --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/config/DeltacloudRestClientModule.java @@ -0,0 +1,109 @@ +/** + * + * Copyright (C) 2010 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.deltacloud.config; + +import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; + +import java.net.URI; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.deltacloud.DeltacloudAsyncClient; +import org.jclouds.deltacloud.DeltacloudClient; +import org.jclouds.deltacloud.collections.DeltacloudCollection; +import org.jclouds.deltacloud.collections.Images; +import org.jclouds.deltacloud.collections.Instances; +import org.jclouds.deltacloud.handlers.DeltacloudErrorHandler; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.RequiresHttp; +import org.jclouds.http.annotation.ClientError; +import org.jclouds.http.annotation.Redirection; +import org.jclouds.http.annotation.ServerError; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.config.RestClientModule; +import org.jclouds.rest.suppliers.RetryOnTimeOutButNotOnAuthorizationExceptionSupplier; + +import com.google.common.base.Supplier; +import com.google.inject.Provides; + +/** + * Configures the deltacloud connection. + * + * @author Adrian Cole + */ +@RequiresHttp +@ConfiguresRestClient +public class DeltacloudRestClientModule extends RestClientModule { + + public DeltacloudRestClientModule() { + super(DeltacloudClient.class, DeltacloudAsyncClient.class); + } + + @Override + protected void bindErrorHandlers() { + bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(DeltacloudErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(DeltacloudErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(DeltacloudErrorHandler.class); + } + + @Override + protected void bindRetryHandlers() { + // TODO + } + + protected AtomicReference authException = new AtomicReference(); + + @Provides + @Singleton + protected Supplier> provideCollections( + @Named(PROPERTY_SESSION_INTERVAL) long seconds, final DeltacloudClient client) { + return new RetryOnTimeOutButNotOnAuthorizationExceptionSupplier>(authException, + seconds, new Supplier>() { + @Override + public Map get() { + return client.getCollections(); + } + }); + } + + /** + * since the supplier is memoized, and there are no objects created here, this doesn't need to be + * singleton. + */ + @Provides + @Images + protected URI provideImageCollection(Supplier> collectionSupplier) { + return collectionSupplier.get().get(DeltacloudCollection.IMAGES); + } + + /** + * since the supplier is memoized, and there are no objects created here, this doesn't need to be + * singleton. + */ + @Provides + @Instances + protected URI provideInstanceCollection(Supplier> collectionSupplier) { + return collectionSupplier.get().get(DeltacloudCollection.INSTANCES); + } +} diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/domain/Architecture.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/domain/Architecture.java new file mode 100644 index 0000000000..394ad105f2 --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/domain/Architecture.java @@ -0,0 +1,29 @@ +/** + * + * Copyright (C) 2010 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.deltacloud.domain; + +/** + * + * @author Adrian Cole + */ +public interface Architecture { + public static final String I386 = "i386"; + public static final String X86_64 = "x86_64"; +} diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/domain/Image.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/domain/Image.java new file mode 100644 index 0000000000..9d3e876594 --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/domain/Image.java @@ -0,0 +1,164 @@ +/** + * + * Copyright (C) 2010 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.deltacloud.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; + +import javax.annotation.Nullable; + +/** + * An image is a platonic form of a machine. Images are not directly executable, but are a template + * for creating actual instances of machines. + * + * @author Adrian Cole + */ +public class Image { + private final URI href; + private final String id; + private final String ownerId; + @Nullable + private final String name; + @Nullable + private final String description; + private final String architecture; + + public Image(URI href, String id, String ownerId, @Nullable String name, String description, String architecture) { + this.href = checkNotNull(href, "href"); + this.id = checkNotNull(id, "id"); + this.ownerId = checkNotNull(ownerId, "ownerId"); + this.name = name; + this.description = description; + this.architecture = checkNotNull(architecture, "architecture"); + } + + /** + * + * @return URL to manipulate a specific image + */ + public URI getHref() { + return href; + } + + /** + * + * @return A unique identifier for the image + */ + public String getId() { + return id; + } + + /** + * + * @return An opaque identifier which indicates the owner of an image + */ + public String getOwnerId() { + return ownerId; + } + + /** + * + * @return An optional short label describing the image + */ + @Nullable + public String getName() { + return name; + } + + /** + * + * @return An optional description describing the image more fully + */ + @Nullable + public String getDescription() { + return description; + } + + /** + * + * @return A description of the machine architecture of the image which may contain values such + * as: i386, x86_64 + */ + public String getArchitecture() { + return architecture; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((architecture == null) ? 0 : architecture.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((href == null) ? 0 : href.hashCode()); + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((ownerId == null) ? 0 : ownerId.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; + Image other = (Image) obj; + if (architecture == null) { + if (other.architecture != null) + return false; + } else if (!architecture.equals(other.architecture)) + return false; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (href == null) { + if (other.href != null) + return false; + } else if (!href.equals(other.href)) + return false; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (ownerId == null) { + if (other.ownerId != null) + return false; + } else if (!ownerId.equals(other.ownerId)) + return false; + return true; + } + + @Override + public String toString() { + return "[href=" + href + ", id=" + id + ", ownerId=" + ownerId + ", name=" + name + ", description=" + + description + ", architecture=" + architecture + "]"; + } +} diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/handlers/DeltacloudErrorHandler.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/handlers/DeltacloudErrorHandler.java new file mode 100644 index 0000000000..4db7e6d89e --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/handlers/DeltacloudErrorHandler.java @@ -0,0 +1,98 @@ +/** + * + * Copyright (C) 2010 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.deltacloud.handlers; + +import java.io.IOException; + +import javax.annotation.Resource; +import javax.inject.Singleton; + +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; +import org.jclouds.logging.Logger; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.util.Utils; + +import com.google.common.base.Throwables; +import com.google.common.io.Closeables; + +/** + * + * @author Adrian Cole + * + */ +@Singleton +public class DeltacloudErrorHandler implements HttpErrorHandler { + @Resource + protected Logger logger = Logger.NULL; + + public void handleError(HttpCommand command, HttpResponse response) { + // it is important to always read fully and close streams + String message = parseMessage(response); + Exception exception = message != null ? new HttpResponseException(command, response, message) + : new HttpResponseException(command, response); + try { + message = message != null ? message : String.format("%s -> %s", command.getRequest().getRequestLine(), + response.getStatusLine()); + switch (response.getStatusCode()) { + case 400: + exception = new IllegalArgumentException(message, exception); + break; + case 401: + exception = new AuthorizationException(message, exception); + break; + case 404: + if (!command.getRequest().getMethod().equals("DELETE")) { + exception = new ResourceNotFoundException(message, exception); + } + break; + case 405: + exception = new IllegalArgumentException(message, exception); + break; + case 409: + exception = new IllegalStateException(message, exception); + break; + } + } finally { + if (response.getPayload() != null) + Closeables.closeQuietly(response.getPayload().getInput()); + command.setException(exception); + } + } + + public String parseMessage(HttpResponse response) { + if (response.getPayload() == null) + return null; + try { + return Utils.toStringAndClose(response.getPayload().getInput()); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + try { + response.getPayload().getInput().close(); + } catch (IOException e) { + Throwables.propagate(e); + } + } + } +} diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/options/CreateInstanceOptions.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/options/CreateInstanceOptions.java new file mode 100644 index 0000000000..25a1a92eb8 --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/options/CreateInstanceOptions.java @@ -0,0 +1,50 @@ +package org.jclouds.deltacloud.options; + +import static com.google.common.base.Preconditions.checkNotNull; + +import org.jclouds.http.options.BaseHttpRequestOptions; + +/** + * Contains options supported in the Deltacloud API for the Create Instance operation.

+ * Usage

The recommended way to instantiate a CreateInstanceOptions object is to statically + * import CreateInstanceOptions.Builder.* and invoke a static creation method followed by an + * instance mutator (if needed): + *

+ * + * import static org.jclouds.deltacloud.options.CreateInstanceOptions.Builder.* + *

+ * DeltacloudClient connection = // get connection + * ListenableFuture instance = client.createInstance(collection, "imageId", named("robot")); + * + * + * @author Adrian Cole + * @see + */ +public class CreateInstanceOptions extends BaseHttpRequestOptions { + public static final CreateInstanceOptions NONE = new CreateInstanceOptions(); + + /** + * A short label to identify the instance. + * + */ + public CreateInstanceOptions named(String name) { + formParameters.put("name", checkNotNull(name, "name")); + return this; + } + + public String getName() { + return this.getFirstFormOrNull("name"); + } + + public static class Builder { + + /** + * @see CreateInstanceOptions#named + */ + public static CreateInstanceOptions named(String name) { + CreateInstanceOptions options = new CreateInstanceOptions(); + return options.named(name); + } + + } +} diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/xml/ImageHandler.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/xml/ImageHandler.java new file mode 100644 index 0000000000..6b3a131a36 --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/xml/ImageHandler.java @@ -0,0 +1,87 @@ +/** + * + * Copyright (C) 2010 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.deltacloud.xml; + +import java.net.URI; +import java.util.Map; + +import org.jclouds.deltacloud.domain.Image; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.util.Utils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +/** + * @author Adrian Cole + */ +public class ImageHandler extends ParseSax.HandlerWithResult { + private StringBuilder currentText = new StringBuilder(); + + private URI href; + private String id; + private String ownerId; + private String name; + private String description; + private String architecture; + + private Image image; + + public Image getResult() { + return image; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { + Map attributes = Utils.cleanseAttributes(attrs); + if (qName.equals("image")) { + String href = attributes.get("href"); + if (href != null) { + this.href = URI.create(href); + } + this.id = attributes.get("id"); + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (qName.equalsIgnoreCase("owner_id")) { + this.ownerId = currentText.toString().trim(); + } else if (qName.equalsIgnoreCase("name")) { + this.name = currentText.toString().trim(); + } else if (qName.equalsIgnoreCase("description")) { + this.description = currentText.toString().trim(); + } else if (qName.equalsIgnoreCase("architecture")) { + this.architecture = currentText.toString().trim(); + } else if (qName.equalsIgnoreCase("image")) { + this.image = new Image(href, id, ownerId, name, description, architecture); + this.href = null; + this.id = null; + this.ownerId = null; + this.name = null; + this.description = null; + this.architecture = null; + } + currentText = new StringBuilder(); + } + + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } +} diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/xml/ImagesHandler.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/xml/ImagesHandler.java new file mode 100644 index 0000000000..96a40de254 --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/xml/ImagesHandler.java @@ -0,0 +1,69 @@ +/** + * + * Copyright (C) 2010 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.deltacloud.xml; + +import java.util.Set; + +import javax.inject.Inject; + +import org.jclouds.deltacloud.domain.Image; +import org.jclouds.http.functions.ParseSax; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import com.google.common.collect.Sets; + +/** + * @author Adrian Cole + */ +public class ImagesHandler extends ParseSax.HandlerWithResult> { + private StringBuilder currentText = new StringBuilder(); + + private Set images = Sets.newLinkedHashSet(); + private final ImageHandler imageHandler; + + @Inject + public ImagesHandler(ImageHandler locationHandler) { + this.imageHandler = locationHandler; + } + + public Set getResult() { + return images; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + imageHandler.startElement(uri, localName, qName, attributes); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + imageHandler.endElement(uri, localName, qName); + if (qName.equals("image") && currentText.toString().trim().equals("")) { + this.images.add(imageHandler.getResult()); + } + currentText = new StringBuilder(); + } + + public void characters(char ch[], int start, int length) { + imageHandler.characters(ch, start, length); + currentText.append(ch, start, length); + } +} diff --git a/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/xml/LinksHandler.java b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/xml/LinksHandler.java new file mode 100755 index 0000000000..e8fdf61c8f --- /dev/null +++ b/sandbox/deltacloud/src/main/java/org/jclouds/deltacloud/xml/LinksHandler.java @@ -0,0 +1,55 @@ +/** + * + * Copyright (C) 2010 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.links/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.deltacloud.xml; + +import java.net.URI; +import java.util.Map; + +import org.jclouds.deltacloud.collections.DeltacloudCollection; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.util.Utils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import com.google.common.collect.Maps; + +/** + * @author Adrian Cole + */ +public class LinksHandler extends ParseSax.HandlerWithResult> { + + private Map links = Maps.newLinkedHashMap(); + + public Map getResult() { + return links; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { + Map attributes = Utils.cleanseAttributes(attrs); + if (qName.equals("link")) { + String rel = attributes.get("rel"); + if (rel != null) { + DeltacloudCollection link = DeltacloudCollection.fromValue(rel); + links.put(link, URI.create(attributes.get("href"))); + } + } + } +} diff --git a/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/DeltacloudAsyncClientTest.java b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/DeltacloudAsyncClientTest.java new file mode 100644 index 0000000000..4455b7497b --- /dev/null +++ b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/DeltacloudAsyncClientTest.java @@ -0,0 +1,199 @@ +/** + * + * Copyright (C) 2010 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.deltacloud; + +import static org.testng.Assert.assertEquals; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.Map; +import java.util.Properties; + +import org.jclouds.deltacloud.collections.DeltacloudCollection; +import org.jclouds.deltacloud.config.DeltacloudRestClientModule; +import org.jclouds.deltacloud.options.CreateInstanceOptions; +import org.jclouds.deltacloud.xml.ImageHandler; +import org.jclouds.deltacloud.xml.ImagesHandler; +import org.jclouds.deltacloud.xml.LinksHandler; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.RequiresHttp; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.http.functions.ReturnStringIf2xx; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.RestClientTest; +import org.jclouds.rest.RestContextFactory; +import org.jclouds.rest.RestContextSpec; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.rest.internal.GeneratedHttpRequest; +import org.jclouds.rest.internal.RestAnnotationProcessor; +import org.testng.annotations.Test; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.Iterables; +import com.google.inject.Module; +import com.google.inject.TypeLiteral; + +/** + * Tests annotation parsing of {@code DeltacloudAsyncClient} + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "deltacloud.DeltacloudAsyncClientTest") +public class DeltacloudAsyncClientTest extends RestClientTest { + public void testGetCollections() throws SecurityException, NoSuchMethodException, IOException { + Method method = DeltacloudAsyncClient.class.getMethod("getCollections"); + GeneratedHttpRequest httpRequest = processor.createRequest(method); + + assertRequestLineEquals(httpRequest, "GET http://localhost:3001/api HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/xml\n"); + assertPayloadEquals(httpRequest, null, null, false); + + // now make sure request filters apply by replaying + Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); + Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest); + + assertRequestLineEquals(httpRequest, "GET http://localhost:3001/api HTTP/1.1"); + // for example, using basic authentication, we should get "only one" + // header + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/xml\nAuthorization: Basic Zm9vOmJhcg==\n"); + assertPayloadEquals(httpRequest, null, null, false); + + assertResponseParserClassEquals(method, httpRequest, ParseSax.class); + assertSaxResponseParserClassEquals(method, LinksHandler.class); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + + } + + public void testListImages() throws IOException, SecurityException, NoSuchMethodException { + Method method = DeltacloudAsyncClient.class.getMethod("listImages"); + HttpRequest request = processor.createRequest(method); + + assertRequestLineEquals(request, "GET http://localhost:3001/api/images HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/xml\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, ParseSax.class); + assertSaxResponseParserClassEquals(method, ImagesHandler.class); + assertExceptionParserClassEquals(method, ReturnEmptySetOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testGetImage() throws IOException, SecurityException, NoSuchMethodException { + Method method = DeltacloudAsyncClient.class.getMethod("getImage", URI.class); + HttpRequest request = processor.createRequest(method, URI.create("https://delta/image1")); + + assertRequestLineEquals(request, "GET https://delta/image1 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, "Accept: application/xml\n"); + assertPayloadEquals(request, null, null, false); + + assertResponseParserClassEquals(method, request, ParseSax.class); + assertSaxResponseParserClassEquals(method, ImageHandler.class); + assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); + + checkFilters(request); + } + + public void testCreateInstance() throws SecurityException, NoSuchMethodException, IOException { + Method method = DeltacloudAsyncClient.class.getMethod("createInstance", String.class, + CreateInstanceOptions[].class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "imageId-1"); + + assertRequestLineEquals(httpRequest, "POST http://localhost:3001/api/instances HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/xml\n"); + assertPayloadEquals(httpRequest, "image_id=imageId-1", "application/x-www-form-urlencoded", false); + + assertResponseParserClassEquals(method, httpRequest, ReturnStringIf2xx.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + + } + + public void testCreateInstanceWithOptions() throws SecurityException, NoSuchMethodException, IOException { + Method method = DeltacloudAsyncClient.class.getMethod("createInstance", String.class, + CreateInstanceOptions[].class); + GeneratedHttpRequest httpRequest = processor.createRequest(method, "imageId-1", + CreateInstanceOptions.Builder.named("foo")); + + assertRequestLineEquals(httpRequest, "POST http://localhost:3001/api/instances HTTP/1.1"); + assertNonPayloadHeadersEqual(httpRequest, "Accept: application/xml\n"); + assertPayloadEquals(httpRequest, "image_id=imageId-1&name=foo", "application/x-www-form-urlencoded", false); + + assertResponseParserClassEquals(method, httpRequest, ReturnStringIf2xx.class); + assertSaxResponseParserClassEquals(method, null); + assertExceptionParserClassEquals(method, null); + + checkFilters(httpRequest); + + } + + @Override + protected void checkFilters(HttpRequest request) { + assertEquals(request.getFilters().size(), 1); + assertEquals(request.getFilters().get(0).getClass(), BasicAuthentication.class); + } + + @Override + protected TypeLiteral> createTypeLiteral() { + return new TypeLiteral>() { + }; + } + + @Override + protected Module createModule() { + return new DeltacloudRestClientModuleExtension(); + } + + @RequiresHttp + @ConfiguresRestClient + public static class DeltacloudRestClientModuleExtension extends DeltacloudRestClientModule { + + @Override + protected Supplier> provideCollections(long seconds, DeltacloudClient client) { + return Suppliers.ofInstance(null); + } + + @Override + protected URI provideImageCollection(Supplier> collectionSupplier) { + return URI.create("http://localhost:3001/api/images"); + } + + @Override + protected URI provideInstanceCollection(Supplier> collectionSupplier) { + return URI.create("http://localhost:3001/api/instances"); + } + + } + + @Override + public RestContextSpec createContextSpec() { + Properties props = new Properties(); + props.setProperty("deltacloud.endpoint", "http://localhost:3001/api"); + return new RestContextFactory().createContextSpec("deltacloud", "foo", "bar", props); + } +} diff --git a/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/DeltacloudClientLiveTest.java b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/DeltacloudClientLiveTest.java new file mode 100644 index 0000000000..72e471db83 --- /dev/null +++ b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/DeltacloudClientLiveTest.java @@ -0,0 +1,128 @@ +/** + * + * Copyright (C) 2010 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.deltacloud; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import java.net.URI; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.jclouds.Constants; +import org.jclouds.deltacloud.collections.DeltacloudCollection; +import org.jclouds.deltacloud.domain.Image; +import org.jclouds.logging.log4j.config.Log4JLoggingModule; +import org.jclouds.rest.RestContext; +import org.jclouds.rest.RestContextFactory; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Module; + +/** + * Tests behavior of {@code DeltacloudClient} + * + * @author Adrian Cole + */ +@Test(groups = "live", sequential = true) +public class DeltacloudClientLiveTest { + + protected DeltacloudClient client; + protected RestContext context; + + protected String provider = "deltacloud"; + protected String identity; + protected String credential; + protected String endpoint; + protected String apiversion; + + protected void setupCredentials() { + identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"); + credential = System.getProperty("test." + provider + ".credential"); + endpoint = System.getProperty("test." + provider + ".endpoint"); + apiversion = System.getProperty("test." + provider + ".apiversion"); + } + + protected Properties setupProperties() { + Properties overrides = new Properties(); + overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true"); + overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true"); + overrides.setProperty(provider + ".identity", identity); + if (credential != null) + overrides.setProperty(provider + ".credential", credential); + if (endpoint != null) + overrides.setProperty(provider + ".endpoint", endpoint); + if (apiversion != null) + overrides.setProperty(provider + ".apiversion", apiversion); + return overrides; + } + + @BeforeGroups(groups = "live") + public void setupClient() { + setupCredentials(); + Properties overrides = setupProperties(); + context = new RestContextFactory().createContext(provider, ImmutableSet. of(new Log4JLoggingModule()), + overrides); + + client = context.getApi(); + } + + @AfterGroups(groups = "live") + void tearDown() { + if (context != null) + context.close(); + } + + @Test + public void testGetLinksContainsAll() throws Exception { + Map links = client.getCollections(); + assertNotNull(links); + for (DeltacloudCollection link : DeltacloudCollection.values()) + assert (links.get(link) != null) : link; + } + + public void testListAndGetImages() throws Exception { + Set response = client.listImages(); + assert null != response; + long imageCount = response.size(); + assertTrue(imageCount >= 0); + for (Image image : response) { + Image newDetails = client.getImage(image.getHref()); + assertEquals(image, newDetails); + } + } + + @Test + public void testCreateInstance() throws Exception { + // TODO + } + + @Test + public void testCreateInstanceWithOptions() throws Exception { + // TODO + } + +} diff --git a/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/handlers/DeltacloudErrorHandlerTest.java b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/handlers/DeltacloudErrorHandlerTest.java new file mode 100644 index 0000000000..d1f8c2c021 --- /dev/null +++ b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/handlers/DeltacloudErrorHandlerTest.java @@ -0,0 +1,123 @@ +/** + * + * Copyright (C) 2010 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.deltacloud.handlers; + +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.reportMatcher; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.easymock.classextension.EasyMock.verify; + +import java.net.URI; + +import org.easymock.IArgumentMatcher; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.jclouds.util.Utils; +import org.testng.annotations.Test; + +import com.google.inject.Guice; + +/** + * + * @author Adrian Cole + */ +@Test(groups = { "unit" }) +public class DeltacloudErrorHandlerTest { + + @Test + public void test400MakesIllegalArgumentException() { + assertCodeMakes("GET", URI.create("https://deltacloud.com/foo"), 400, "", "Bad Request", + IllegalArgumentException.class); + } + + @Test + public void test401MakesAuthorizationException() { + assertCodeMakes("GET", URI.create("https://deltacloud.com/foo"), 401, "", "Unauthorized", + AuthorizationException.class); + } + + @Test + public void test404MakesResourceNotFoundException() { + assertCodeMakes("GET", URI.create("https://deltacloud.com/foo"), 404, "", "Not Found", + ResourceNotFoundException.class); + } + + @Test + public void test405MakesIllegalArgumentException() { + assertCodeMakes("GET", URI.create("https://deltacloud.com/foo"), 405, "", "Method Not Allowed", + IllegalArgumentException.class); + } + + @Test + public void test409MakesIllegalStateException() { + assertCodeMakes("GET", URI.create("https://deltacloud.com/foo"), 409, "", "Conflict", IllegalStateException.class); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content, + Class expected) { + assertCodeMakes(method, uri, statusCode, message, "text/xml", content, expected); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType, + String content, Class expected) { + + DeltacloudErrorHandler function = Guice.createInjector().getInstance(DeltacloudErrorHandler.class); + + HttpCommand command = createMock(HttpCommand.class); + HttpRequest request = new HttpRequest(method, uri); + HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Utils + .toInputStream(content))); + response.getPayload().getContentMetadata().setContentType(contentType); + + expect(command.getRequest()).andReturn(request).atLeastOnce(); + command.setException(classEq(expected)); + + replay(command); + + function.handleError(command, response); + + verify(command); + } + + public static Exception classEq(final Class in) { + reportMatcher(new IArgumentMatcher() { + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("classEq("); + buffer.append(in); + buffer.append(")"); + } + + @Override + public boolean matches(Object arg) { + return arg.getClass() == in; + } + + }); + return null; + } + +} diff --git a/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/handlers/LinksHandlerTest.java b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/handlers/LinksHandlerTest.java new file mode 100644 index 0000000000..ebe6705ecc --- /dev/null +++ b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/handlers/LinksHandlerTest.java @@ -0,0 +1,58 @@ +/** + * + * Copyright (C) 2010 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.deltacloud.handlers; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.URI; +import java.util.Map; + +import org.jclouds.deltacloud.collections.DeltacloudCollection; +import org.jclouds.deltacloud.xml.LinksHandler; +import org.jclouds.http.functions.BaseHandlerTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; + +/** + * Tests behavior of {@code LinksHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class LinksHandlerTest extends BaseHandlerTest { + + public void test() { + InputStream is = getClass().getResourceAsStream("/links.xml"); + + Map result = factory.create(injector.getInstance(LinksHandler.class)).parse(is); + assertEquals(result, ImmutableMap.of(// + DeltacloudCollection.HARDWARE_PROFILES, URI.create("http://fancycloudprovider.com/api/hardware_profiles"),// + DeltacloudCollection.INSTANCE_STATES, URI.create("http://fancycloudprovider.com/api/instance_states"),// + DeltacloudCollection.REALMS, URI.create("http://fancycloudprovider.com/api/realms"),// + DeltacloudCollection.IMAGES, URI.create("http://fancycloudprovider.com/api/images"),// + DeltacloudCollection.INSTANCES, URI.create("http://fancycloudprovider.com/api/instances") + + )); + + } + +} diff --git a/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/options/CreateInstanceOptionsTest.java b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/options/CreateInstanceOptionsTest.java new file mode 100644 index 0000000000..296d2de6d6 --- /dev/null +++ b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/options/CreateInstanceOptionsTest.java @@ -0,0 +1,48 @@ +package org.jclouds.deltacloud.options; + +import static org.jclouds.deltacloud.options.CreateInstanceOptions.Builder.named; +import static org.testng.Assert.assertEquals; + +import java.util.Collections; + +import org.jclouds.http.options.HttpRequestOptions; +import org.testng.annotations.Test; + +/** + * Tests possible uses of CreateInstanceOptions and CreateInstanceOptions.Builder.* + * + * @author Adrian Cole + */ +public class CreateInstanceOptionsTest { + + @Test + public void testAssignability() { + assert HttpRequestOptions.class.isAssignableFrom(CreateInstanceOptions.class); + assert !String.class.isAssignableFrom(CreateInstanceOptions.class); + } + + @Test + public void testWithNamed() { + CreateInstanceOptions options = new CreateInstanceOptions(); + options.named("test"); + assertEquals(options.buildFormParameters().get("name"), Collections.singletonList("test")); + } + + @Test + public void testNullWithNamed() { + CreateInstanceOptions options = new CreateInstanceOptions(); + assertEquals(options.buildFormParameters().get("name"), Collections.EMPTY_LIST); + } + + @Test + public void testWithNamedStatic() { + CreateInstanceOptions options = named("test"); + assertEquals(options.buildFormParameters().get("name"), Collections.singletonList("test")); + } + + @Test(expectedExceptions = NullPointerException.class) + public void testWithNamedNPE() { + named(null); + } + +} diff --git a/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/xml/ImageHandlerTest.java b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/xml/ImageHandlerTest.java new file mode 100644 index 0000000000..4c6cdbfb44 --- /dev/null +++ b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/xml/ImageHandlerTest.java @@ -0,0 +1,65 @@ +/** + * + * Copyright (C) 2010 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.deltacloud.xml; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.URI; + +import org.jclouds.deltacloud.domain.Image; +import org.jclouds.deltacloud.xml.ImageHandler; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.http.functions.config.SaxParserModule; +import org.testng.annotations.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code ImageHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ImageHandlerTest { + + static ParseSax createParser() { + Injector injector = Guice.createInjector(new SaxParserModule()); + ParseSax parser = (ParseSax) injector.getInstance(ParseSax.Factory.class).create( + injector.getInstance(ImageHandler.class)); + return parser; + } + + public static Image parseImage() { + return parseImage("/test_get_image.xml"); + } + + public static Image parseImage(String resource) { + InputStream is = ImageHandlerTest.class.getResourceAsStream(resource); + return createParser().parse(is); + } + + public void test() { + Image expects = new Image(URI.create("http://fancycloudprovider.com/api/images/img1"), "img1", "fedoraproject", + "Fedora 10", "Fedora 10", "x86_64"); + assertEquals(parseImage(), expects); + } +} diff --git a/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/xml/ImagesHandlerTest.java b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/xml/ImagesHandlerTest.java new file mode 100644 index 0000000000..e5b080bb77 --- /dev/null +++ b/sandbox/deltacloud/src/test/java/org/jclouds/deltacloud/xml/ImagesHandlerTest.java @@ -0,0 +1,60 @@ +/** + * + * Copyright (C) 2010 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.deltacloud.xml; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.URI; +import java.util.Set; + +import org.jclouds.deltacloud.domain.Image; +import org.jclouds.deltacloud.xml.ImagesHandler; +import org.jclouds.http.functions.BaseHandlerTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * Tests behavior of {@code ImagesHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class ImagesHandlerTest extends BaseHandlerTest { + + @Test + public void test() { + InputStream is = getClass().getResourceAsStream("/test_list_images.xml"); + Set expects = ImmutableSet.of( + + new Image(URI.create("http://fancycloudprovider.com/api/images/img1"), "img1", "fedoraproject", "Fedora 10", + "Fedora 10", "x86_64"), new Image(URI.create("http://fancycloudprovider.com/api/images/img2"), "img2", + "fedoraproject", "Fedora 10", "Fedora 10", "i386"), + new Image(URI.create("http://fancycloudprovider.com/api/images/img3"), "img3", "ted", "JBoss", "JBoss", + "i386")); + System.out.println(factory); + System.out.println(injector); + + // not sure why this isn't always automatically called from surefire. + setUpInjector(); + assertEquals(factory.create(injector.getInstance(ImagesHandler.class)).parse(is), expects); + } +} diff --git a/sandbox/deltacloud/src/test/resources/links.xml b/sandbox/deltacloud/src/test/resources/links.xml new file mode 100644 index 0000000000..251d904b05 --- /dev/null +++ b/sandbox/deltacloud/src/test/resources/links.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/sandbox/deltacloud/src/test/resources/test_get_image.xml b/sandbox/deltacloud/src/test/resources/test_get_image.xml new file mode 100644 index 0000000000..9fd7f331a0 --- /dev/null +++ b/sandbox/deltacloud/src/test/resources/test_get_image.xml @@ -0,0 +1,7 @@ + + + fedoraproject + Fedora 10 + Fedora 10 + x86_64 + \ No newline at end of file diff --git a/sandbox/deltacloud/src/test/resources/test_list_images.xml b/sandbox/deltacloud/src/test/resources/test_list_images.xml new file mode 100644 index 0000000000..49c888d264 --- /dev/null +++ b/sandbox/deltacloud/src/test/resources/test_list_images.xml @@ -0,0 +1,20 @@ + + + fedoraproject + Fedora 10 + Fedora 10 + x86_64 + + + fedoraproject + Fedora 10 + Fedora 10 + i386 + + + ted + JBoss + JBoss + i386 + + \ No newline at end of file diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/CommonElasticStackAsyncClient.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/CommonElasticStackAsyncClient.java deleted file mode 100644 index c51cc6d76f..0000000000 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/CommonElasticStackAsyncClient.java +++ /dev/null @@ -1,142 +0,0 @@ -/** - * - * Copyright (C) 2010 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.elasticstack; - -import java.util.Set; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.core.MediaType; - -import org.jclouds.elasticstack.binders.BindDriveDataToPlainTextString; -import org.jclouds.elasticstack.binders.BindDriveToPlainTextString; -import org.jclouds.elasticstack.domain.Drive; -import org.jclouds.elasticstack.domain.DriveData; -import org.jclouds.elasticstack.domain.DriveInfo; -import org.jclouds.elasticstack.domain.ServerInfo; -import org.jclouds.elasticstack.functions.KeyValuesDelimitedByBlankLinesToDriveInfo; -import org.jclouds.elasticstack.functions.KeyValuesDelimitedByBlankLinesToServerInfo; -import org.jclouds.elasticstack.functions.ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet; -import org.jclouds.elasticstack.functions.ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet; -import org.jclouds.elasticstack.functions.SplitNewlines; -import org.jclouds.http.filters.BasicAuthentication; -import org.jclouds.rest.annotations.BinderParam; -import org.jclouds.rest.annotations.ExceptionParser; -import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; -import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; - -import com.google.common.util.concurrent.ListenableFuture; - -/** - * Provides asynchronous access to elasticstack via their REST API. - *

- * - * @see ElasticStackClient - * @see - * @author Adrian Cole - */ -@RequestFilters(BasicAuthentication.class) -@Consumes(MediaType.TEXT_PLAIN) -public interface CommonElasticStackAsyncClient { - - /** - * @see ElasticStackClient#listServers() - */ - @GET - @Path("/servers/list") - @ResponseParser(SplitNewlines.class) - ListenableFuture> listServers(); - - /** - * @see ElasticStackClient#listServerInfo() - */ - @GET - @Path("/servers/info") - @ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.class) - ListenableFuture> listServerInfo(); - - /** - * @see ElasticStackClient#getServerInfo - */ - @GET - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - @ResponseParser(KeyValuesDelimitedByBlankLinesToServerInfo.class) - @Path("/servers/{uuid}/info") - ListenableFuture getServerInfo(@PathParam("uuid") String uuid); - - /** - * @see ElasticStackClient#listDrives() - */ - @GET - @Path("/drives/list") - @ResponseParser(SplitNewlines.class) - ListenableFuture> listDrives(); - - /** - * @see ElasticStackClient#listDriveInfo() - */ - @GET - @Path("/drives/info") - @ResponseParser(ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.class) - ListenableFuture> listDriveInfo(); - - /** - * @see ElasticStackClient#getDriveInfo - */ - @GET - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) - @Path("/drives/{uuid}/info") - ListenableFuture getDriveInfo(@PathParam("uuid") String uuid); - - /** - * @see ElasticStackClient#createDrive - */ - @POST - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) - @Path("/drives/create") - ListenableFuture createDrive( - @BinderParam(BindDriveToPlainTextString.class) Drive createDrive); - - /** - * @see ElasticStackClient#setDriveData - */ - @POST - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - @ResponseParser(KeyValuesDelimitedByBlankLinesToDriveInfo.class) - @Path("/drives/{uuid}/set") - ListenableFuture setDriveData(@PathParam("uuid") String uuid, - @BinderParam(BindDriveDataToPlainTextString.class) DriveData setDrive); - - /** - * @see ElasticStackClient#destroyDrive - */ - @POST - @Path("/drives/{uuid}/destroy") - @ExceptionParser(ReturnVoidOnNotFoundOr404.class) - ListenableFuture destroyDrive(@PathParam("uuid") String uuid); - -} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/CommonElasticStackClient.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/CommonElasticStackClient.java deleted file mode 100644 index a611d5e99d..0000000000 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/CommonElasticStackClient.java +++ /dev/null @@ -1,111 +0,0 @@ -/** - * - * Copyright (C) 2010 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.elasticstack; - -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import org.jclouds.concurrent.Timeout; -import org.jclouds.elasticstack.domain.Drive; -import org.jclouds.elasticstack.domain.DriveData; -import org.jclouds.elasticstack.domain.DriveInfo; -import org.jclouds.elasticstack.domain.ServerInfo; - -/** - * Provides synchronous access to elasticstack. - *

- * - * @see ElasticStackAsyncClient - * @see - * @author Adrian Cole - */ -@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) -public interface CommonElasticStackClient { - /** - * list of server uuids in your account - * - * @return or empty set if no servers are found - */ - Set listServers(); - - /** - * Get all servers info - * - * @return or empty set if no servers are found - */ - Set listServerInfo(); - - /** - * @param uuid - * what to get - * @return null, if not found - */ - ServerInfo getServerInfo(String uuid); - - /** - * list of drive uuids in your account - * - * @return or empty set if no drives are found - */ - Set listDrives(); - - /** - * Get all drives info - * - * @return or empty set if no drives are found - */ - Set listDriveInfo(); - - /** - * @param uuid - * what to get - * @return null, if not found - */ - DriveInfo getDriveInfo(String uuid); - - /** - * create a new drive - * - * @param createDrive - * required parameters: name, size - * @return newly created drive - */ - DriveInfo createDrive(Drive createDrive); - - /** - * set extra drive data - * - * @param uuid - * what drive to change - * @param driveData - * what values to change - * @return new data - */ - DriveInfo setDriveData(String uuid, DriveData driveData); - - /** - * Destroy a drive - * - * @param uuid - * what to delete - */ - void destroyDrive(String uuid); - -} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackAsyncClient.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackAsyncClient.java deleted file mode 100644 index 4314cdfb24..0000000000 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackAsyncClient.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * - * Copyright (C) 2010 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.elasticstack; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - -import org.jclouds.elasticstack.binders.BindReadDriveOptionsToPath; -import org.jclouds.elasticstack.domain.ImageConversionType; -import org.jclouds.elasticstack.functions.ReturnPayload; -import org.jclouds.elasticstack.options.ReadDriveOptions; -import org.jclouds.http.filters.BasicAuthentication; -import org.jclouds.io.Payload; -import org.jclouds.rest.annotations.BinderParam; -import org.jclouds.rest.annotations.ExceptionParser; -import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.ResponseParser; -import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; -import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; - -import com.google.common.util.concurrent.ListenableFuture; - -/** - * Provides asynchronous access to elasticstack via their REST API. - *

- * - * @see ElasticStackClient - * @see - * @author Adrian Cole - */ -@RequestFilters(BasicAuthentication.class) -@Consumes(MediaType.TEXT_PLAIN) -public interface ElasticStackAsyncClient extends CommonElasticStackAsyncClient { - - /** - * @see ElasticStackClient#imageDrive(String,String) - */ - @POST - @Path("/drives/{destination}/image/{source}") - @ExceptionParser(ReturnVoidOnNotFoundOr404.class) - ListenableFuture imageDrive(@PathParam("source") String source, @PathParam("destination") String destination); - - /** - * @see ElasticStackClient#imageDrive(String,String,ImageConversionType) - */ - @POST - @Path("/drives/{destination}/image/{source}/{conversion}") - @ExceptionParser(ReturnVoidOnNotFoundOr404.class) - ListenableFuture imageDrive(@PathParam("source") String source, @PathParam("destination") String destination, - @PathParam("conversion") ImageConversionType conversionType); - - /** - * @see ElasticStackClient#readDrive(String) - */ - @GET - @Consumes(MediaType.APPLICATION_OCTET_STREAM) - @Path("/drives/{uuid}/read") - @ResponseParser(ReturnPayload.class) - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture readDrive(@PathParam("uuid") String uuid); - - /** - * @see ElasticStackClient#readDrive(String,ReadDriveOptions) - */ - @POST - @Consumes(MediaType.APPLICATION_OCTET_STREAM) - @Path("/drives/{uuid}/read") - @ResponseParser(ReturnPayload.class) - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture readDrive(@PathParam("uuid") String uuid, - @BinderParam(BindReadDriveOptionsToPath.class) ReadDriveOptions options); - - /** - * @see ElasticStackClient#writeDrive(String, Payload) - */ - @POST - @Produces(MediaType.APPLICATION_OCTET_STREAM) - @Path("/drives/{uuid}/write") - @ExceptionParser(ReturnVoidOnNotFoundOr404.class) - ListenableFuture writeDrive(@PathParam("uuid") String uuid, Payload content); - - /** - * @see ElasticStackClient#writeDrive(String, Payload, long) - */ - @POST - @Produces(MediaType.APPLICATION_OCTET_STREAM) - @Path("/drives/{uuid}/write/{offset}") - @ExceptionParser(ReturnVoidOnNotFoundOr404.class) - ListenableFuture writeDrive(@PathParam("uuid") String uuid, Payload content, @PathParam("offset") long offset); -} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackClient.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackClient.java deleted file mode 100644 index 5d4998c366..0000000000 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/ElasticStackClient.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * - * Copyright (C) 2010 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.elasticstack; - -import java.util.concurrent.TimeUnit; - -import org.jclouds.concurrent.Timeout; -import org.jclouds.elasticstack.domain.ImageConversionType; -import org.jclouds.elasticstack.options.ReadDriveOptions; -import org.jclouds.io.Payload; - -/** - * Provides synchronous access to elasticstack. - *

- * - * @see ElasticStackAsyncClient - * @see - * @author Adrian Cole - */ -@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) -public interface ElasticStackClient extends CommonElasticStackClient { - - /** - * Image a drive from another drive. The actual imaging process is asynchronous, with progress - * reported via drive info. - * - * @param source - * drive to copy from - * @param destination - * drive to copy to - */ - void imageDrive(String source, String destination); - - /** - * @see #imageDrive(String, String) - * @param conversionType - * Supports 'gzip' or 'gunzip' conversions. - */ - void imageDrive(String source, String destination, ImageConversionType conversionType); - - /** - * Read binary data from a drive - * - * @param uuid - * drive to read - * @return binary content of the drive. - */ - Payload readDrive(String uuid); - - /** - * @see #readDrive(String) - * @param options - * controls offset and size of the request - */ - Payload readDrive(String uuid, ReadDriveOptions options); - - /** - * Write binary data to a drive - * - * @param uuid - * drive to write - * @param content - * what to write. - *

- */ - void writeDrive(String uuid, Payload content); - - /** - * @see ElasticStackClient#writeDrive(String, Payload) - * @param offset - * the byte offset in the target drive at which to start writing, not an offset in the - * input stream. - */ - void writeDrive(String uuid, Payload content, long offset); - -} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindReadDriveOptionsToPath.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindReadDriveOptionsToPath.java deleted file mode 100644 index 878b4bca3a..0000000000 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/binders/BindReadDriveOptionsToPath.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * - * Copyright (C) 2010 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.elasticstack.binders; - -import static com.google.common.base.Preconditions.checkArgument; - -import javax.inject.Inject; -import javax.inject.Provider; -import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; - -import org.jclouds.elasticstack.options.ReadDriveOptions; -import org.jclouds.http.HttpRequest; -import org.jclouds.rest.Binder; - -/** - * - * @author Adrian Cole - */ -@Singleton -public class BindReadDriveOptionsToPath implements Binder { - private final Provider uriBuilderProvider; - - @Inject - public BindReadDriveOptionsToPath(Provider uriBuilderProvider) { - this.uriBuilderProvider = uriBuilderProvider; - } - - public void bindToRequest(HttpRequest request, Object payload) { - checkArgument(payload instanceof ReadDriveOptions, "this binder is only valid for ReadDriveOptions!"); - ReadDriveOptions options = ReadDriveOptions.class.cast(payload); - if (options.getOffset() != null || options.getSize() != null){ - UriBuilder builder = uriBuilderProvider.get().uri(request.getEndpoint()); - if (options.getOffset() != null) - builder.path("/"+options.getOffset()); - if (options.getSize() != null) - builder.path("/"+options.getSize()); - request.setEndpoint(builder.build()); - } - - } -} diff --git a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/options/ReadDriveOptions.java b/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/options/ReadDriveOptions.java deleted file mode 100644 index cfbe4af50e..0000000000 --- a/sandbox/elasticstack/src/main/java/org/jclouds/elasticstack/options/ReadDriveOptions.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * - * Copyright (C) 2010 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.elasticstack.options; - -import static com.google.common.base.Preconditions.checkArgument; - -/** - * Contains options supported for read drive operations.

- * Usage

The recommended way to instantiate a ReadDriveOptions object is to statically import - * ReadDriveOptions.Builder.* and invoke a static creation method followed by an instance mutator - * (if needed): - *

- * - * import static org.jclouds.elasticstack.options.ReadDriveOptions.Builder.*; - * - * - * // this will get the first 1024 bytes starting at offset 2048 - * Payload payload = client.readDrive("drive-uuid",offset(2048l).size(1024l)); - * - * - * @author Adrian Cole - * - */ -public class ReadDriveOptions { - - private Long offset; - private Long size; - - /** - * start at the specified offset in bytes - */ - public ReadDriveOptions offset(long offset) { - checkArgument(offset >= 0, "start must be >= 0"); - this.offset = offset; - return this; - } - - /** - * download the specified size in bytes - */ - public ReadDriveOptions size(long size) { - checkArgument(size >= 0, "start must be >= 0"); - this.size = size; - return this; - } - - public static class Builder { - - /** - * @see ReadDriveOptions#offset - */ - public static ReadDriveOptions offset(long offset) { - ReadDriveOptions options = new ReadDriveOptions(); - return options.offset(offset); - } - - /** - * @see ReadDriveOptions#size - */ - public static ReadDriveOptions size(long size) { - ReadDriveOptions options = new ReadDriveOptions(); - return options.size(size); - } - - } - - public Long getOffset() { - return offset; - } - - public Long getSize() { - return size; - } -} diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/CommonElasticStackClientLiveTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/CommonElasticStackClientLiveTest.java deleted file mode 100644 index cf2afcc2e7..0000000000 --- a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/CommonElasticStackClientLiveTest.java +++ /dev/null @@ -1,197 +0,0 @@ -/** - * - * Copyright (C) 2010 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.elasticstack; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; - -import java.util.Properties; -import java.util.Set; - -import org.jclouds.Constants; -import org.jclouds.elasticstack.domain.ClaimType; -import org.jclouds.elasticstack.domain.CreateDriveRequest; -import org.jclouds.elasticstack.domain.DriveData; -import org.jclouds.elasticstack.domain.DriveInfo; -import org.jclouds.elasticstack.domain.DriveStatus; -import org.jclouds.elasticstack.domain.ServerInfo; -import org.jclouds.logging.log4j.config.Log4JLoggingModule; -import org.jclouds.rest.RestContext; -import org.jclouds.rest.RestContextFactory; -import org.testng.annotations.AfterGroups; -import org.testng.annotations.BeforeGroups; -import org.testng.annotations.Test; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.inject.Module; - -/** - * Tests behavior of {@code CommonElasticStackClient} - * - * @author Adrian Cole - */ -@Test(groups = "live", sequential = true) -public abstract class CommonElasticStackClientLiveTest { - - protected S client; - protected RestContext context; - - protected String provider = "elasticstack"; - protected String identity; - protected String credential; - protected String endpoint; - protected String apiversion; - - protected void setupCredentials() { - identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"); - credential = System.getProperty("test." + provider + ".credential"); - endpoint = System.getProperty("test." + provider + ".endpoint"); - apiversion = System.getProperty("test." + provider + ".apiversion"); - } - - protected Properties setupProperties() { - Properties overrides = new Properties(); - overrides.setProperty(Constants.PROPERTY_TRUST_ALL_CERTS, "true"); - overrides.setProperty(Constants.PROPERTY_RELAX_HOSTNAME, "true"); - overrides.setProperty(provider + ".identity", identity); - if (credential != null) - overrides.setProperty(provider + ".credential", credential); - if (endpoint != null) - overrides.setProperty(provider + ".endpoint", endpoint); - if (apiversion != null) - overrides.setProperty(provider + ".apiversion", apiversion); - return overrides; - } - - @BeforeGroups(groups = "live") - public void setupClient() { - setupCredentials(); - Properties overrides = setupProperties(); - context = new RestContextFactory().createContext(provider, ImmutableSet. of(new Log4JLoggingModule()), - overrides); - - client = context.getApi(); - } - - @AfterGroups(groups = "live") - void tearDown() { - if (context != null) - context.close(); - } - - @Test - public void testListServers() throws Exception { - Set servers = client.listServers(); - assertNotNull(servers); - } - - @Test - public void testListServerInfo() throws Exception { - Set servers = client.listServerInfo(); - assertNotNull(servers); - } - - @Test - public void testGetServer() throws Exception { - for (String serverUUID : client.listServers()) { - assert !"".equals(serverUUID); - assertNotNull(client.getServerInfo(serverUUID)); - } - } - - @Test - public void testListDrives() throws Exception { - Set drives = client.listDrives(); - assertNotNull(drives); - } - - @Test - public void testListDriveInfo() throws Exception { - Set drives = client.listDriveInfo(); - assertNotNull(drives); - } - - @Test - public void testGetDrive() throws Exception { - for (String driveUUID : client.listDrives()) { - assert !"".equals(driveUUID); - assertNotNull(client.getDriveInfo(driveUUID)); - } - } - - protected String prefix = System.getProperty("user.name") + ".test"; - protected DriveInfo info; - - @Test - public void testCreate() throws Exception { - info = client.createDrive(new CreateDriveRequest.Builder().name(prefix).size(4 * 1024 * 1024l).build()); - checkCreatedDrive(); - - DriveInfo newInfo = client.getDriveInfo(info.getUuid()); - checkDriveMatchesGet(newInfo); - - } - - protected void checkDriveMatchesGet(DriveInfo newInfo) { - assertEquals(newInfo.getUuid(), info.getUuid()); - } - - protected void checkCreatedDrive() { - assertNotNull(info.getUuid()); - assertNotNull(info.getUser()); - assertEquals(info.getName(), prefix); - assertEquals(info.getSize(), 4 * 1024 * 1024l); - assertEquals(info.getStatus(), DriveStatus.ACTIVE); - // for some reason, these occasionally return as 4096,1 - // assertEquals(info.getReadBytes(), 0l); - // assertEquals(info.getWriteBytes(), 0l); - // assertEquals(info.getReadRequests(), 0l); - // assertEquals(info.getWriteRequests(), 0l); - assertEquals(info.getEncryptionCipher(), "aes-xts-plain"); - } - - @Test(dependsOnMethods = "testCreate") - public void testSetDriveData() throws Exception { - - DriveInfo info2 = client.setDriveData( - info.getUuid(), - new DriveData.Builder().claimType(ClaimType.SHARED).name("rediculous") - .readers(ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff")) - .tags(ImmutableSet.of("networking", "security", "gateway")) - .userMetadata(ImmutableMap.of("foo", "bar")).build()); - - assertNotNull(info2.getUuid(), info.getUuid()); - assertEquals(info2.getName(), "rediculous"); - assertEquals(info2.getClaimType(), ClaimType.SHARED); - assertEquals(info2.getReaders(), ImmutableSet.of("ffffffff-ffff-ffff-ffff-ffffffffffff")); - assertEquals(info2.getTags(), ImmutableSet.of("networking", "security", "gateway")); - assertEquals(info2.getUserMetadata(), ImmutableMap.of("foo", "bar")); - info = info2; - } - - @Test(dependsOnMethods = "testSetDriveData") - public void testDestroyDrive() throws Exception { - client.destroyDrive(info.getUuid()); - assertEquals(client.getDriveInfo(info.getUuid()), null); - } - -} diff --git a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java b/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java deleted file mode 100644 index ae102e8092..0000000000 --- a/sandbox/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * - * Copyright (C) 2010 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.elasticstack; - -import static org.testng.Assert.assertEquals; - -import java.io.IOException; - -import org.jclouds.elasticstack.domain.CreateDriveRequest; -import org.jclouds.elasticstack.domain.DriveInfo; -import org.jclouds.elasticstack.options.ReadDriveOptions; -import org.jclouds.io.Payloads; -import org.jclouds.util.Utils; -import org.testng.annotations.Test; - -/** - * Tests behavior of {@code ElasticStackClient} - * - * @author Adrian Cole - */ -@Test(groups = "live", testName = "elasticstack.ElasticStackClientLiveTest") -public class ElasticStackClientLiveTest extends - CommonElasticStackClientLiveTest { - private DriveInfo info2; - - @Override - public void testGetDrive() throws Exception { - super.testGetDrive(); - } - - @Override - public void testCreate() throws Exception { - super.testCreate(); - } - - @Override - public void testSetDriveData() throws Exception { - super.testSetDriveData(); - } - - @Override - public void testDestroyDrive() throws Exception { - super.testDestroyDrive(); - } - - @Test(dependsOnMethods = "testCreate") - public void testWeCanReadAndWriteToDrive() throws IOException { - client.writeDrive(info.getUuid(), Payloads.newStringPayload("foo")); - assertEquals(Utils.toStringAndClose(client.readDrive(info.getUuid(), ReadDriveOptions.Builder.offset(0).size(3)) - .getInput()), "foo"); - } - - @Test(dependsOnMethods = "testWeCanReadAndWriteToDrive") - public void testWeCopyADriveContentsViaGzip() throws IOException { - - try { - info2 = client.createDrive(new CreateDriveRequest.Builder().name(prefix + "2").size(4 * 1024 * 1024l).build()); - client.imageDrive(info.getUuid(), info2.getUuid()); - - // TODO block until complete - System.err.println("state " + client.getDriveInfo(info2.getUuid())); - assertEquals(Utils.toStringAndClose(client.readDrive(info2.getUuid(), - ReadDriveOptions.Builder.offset(0).size(3)).getInput()), "foo"); - } finally { - client.destroyDrive(info2.getUuid()); - } - - } - -} diff --git a/sandbox/elasticstack/src/test/resources/log4j.xml b/sandbox/elasticstack/src/test/resources/log4j.xml deleted file mode 100644 index 99fc6ca2a0..0000000000 --- a/sandbox/elasticstack/src/test/resources/log4j.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sandbox/libvirt/src/main/java/org/jclouds/libvirt/compute/domain/LibvirtComputeServiceContextModule.java b/sandbox/libvirt/src/main/java/org/jclouds/libvirt/compute/domain/LibvirtComputeServiceContextModule.java index 223b8ed737..c8932334f8 100644 --- a/sandbox/libvirt/src/main/java/org/jclouds/libvirt/compute/domain/LibvirtComputeServiceContextModule.java +++ b/sandbox/libvirt/src/main/java/org/jclouds/libvirt/compute/domain/LibvirtComputeServiceContextModule.java @@ -36,7 +36,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.WildcardFileFilter; import org.jclouds.Constants; import org.jclouds.compute.ComputeServiceAdapter; -import org.jclouds.compute.config.StandaloneComputeServiceContextModule; +import org.jclouds.compute.config.ComputeServiceAdapterContextModule; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.TemplateBuilder; @@ -73,78 +73,78 @@ import com.jamesmurty.utils.XMLBuilder; * @author Adrian Cole */ public class LibvirtComputeServiceContextModule extends -StandaloneComputeServiceContextModule { - @Override - protected void configure() { - super.configure(); - bind(new TypeLiteral>() { - }).to(LibvirtComputeServiceAdapter.class); - bind(new TypeLiteral>() { - }).to(DefaultLocationSupplier.class); - bind(new TypeLiteral>() { - }).to(DomainToNodeMetadata.class); - bind(new TypeLiteral>() { - }).to(LibvirtImageToImage.class); - bind(new TypeLiteral>() { - }).to(DomainToHardware.class); - bind(new TypeLiteral>() { - }).to(DatacenterToLocation.class); - - //bind(ComputeService.class).to(LibvirtComputeService.class); - } + ComputeServiceAdapterContextModule { + + public LibvirtComputeServiceContextModule() { + super(Connect.class, Connect.class); + } - @Provides - @Singleton - protected Connect createConnection(@Provider URI endpoint, @Named(Constants.PROPERTY_IDENTITY) String identity, - @Named(Constants.PROPERTY_CREDENTIAL) String credential) throws LibvirtException { - // ConnectAuth connectAuth = null; - return new Connect(endpoint.toASCIIString()); - } + @Override + protected void configure() { + super.configure(); + bind(new TypeLiteral>() { + }).to(LibvirtComputeServiceAdapter.class); + bind(new TypeLiteral>() { + }).to(DefaultLocationSupplier.class); + bind(new TypeLiteral>() { + }).to(DomainToNodeMetadata.class); + bind(new TypeLiteral>() { + }).to(LibvirtImageToImage.class); + bind(new TypeLiteral>() { + }).to(DomainToHardware.class); + bind(new TypeLiteral>() { + }).to(DatacenterToLocation.class); - @Override - protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) { - String domainDir = injector.getInstance(Key.get(String.class, Names.named(PROPERTY_LIBVIRT_DOMAIN_DIR))); - String hardwareId = searchForHardwareIdInDomainDir(domainDir); - String image = searchForImageIdInDomainDir(domainDir); - return template.hardwareId(hardwareId).imageId(image) ; - } + // bind(ComputeService.class).to(LibvirtComputeService.class); + } + @Provides + @Singleton + protected Connect createConnection(@Provider URI endpoint, @Named(Constants.PROPERTY_IDENTITY) String identity, + @Named(Constants.PROPERTY_CREDENTIAL) String credential) throws LibvirtException { + // ConnectAuth connectAuth = null; + return new Connect(endpoint.toASCIIString()); + } - private String searchForImageIdInDomainDir(String domainDir) { - // TODO - return "1"; - } - - @SuppressWarnings("unchecked") - private String searchForHardwareIdInDomainDir(String domainDir) { + @Override + protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) { + String domainDir = injector.getInstance(Key.get(String.class, Names.named(PROPERTY_LIBVIRT_DOMAIN_DIR))); + String hardwareId = searchForHardwareIdInDomainDir(domainDir); + String image = searchForImageIdInDomainDir(domainDir); + return template.hardwareId(hardwareId).imageId(image); + } - Collection xmlDomains = FileUtils.listFiles( new File(domainDir), new WildcardFileFilter("*.xml"), null); - String uuid = ""; - try { - String fromXML = Files.toString(Iterables.get(xmlDomains, 0), Charsets.UTF_8); - XMLBuilder builder = XMLBuilder.parse(new InputSource(new StringReader(fromXML))); - uuid = builder.xpathFind("/domain/uuid").getElement().getTextContent(); - } catch (IOException e) { - e.printStackTrace(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } catch (XPathExpressionException e) { - e.printStackTrace(); - } - return uuid; - } + private String searchForImageIdInDomainDir(String domainDir) { + // TODO + return "1"; + } - /* - * Map regions = newLinkedHashMap(); - for (String region : Splitter.on(',').split(regionString)) { - regions.put( - region, - URI.create(injector.getInstance(Key.get(String.class, - Names.named(Constants.PROPERTY_ENDPOINT + "." + region))))); + @SuppressWarnings("unchecked") + private String searchForHardwareIdInDomainDir(String domainDir) { + + Collection xmlDomains = FileUtils.listFiles(new File(domainDir), new WildcardFileFilter("*.xml"), null); + String uuid = ""; + try { + String fromXML = Files.toString(Iterables.get(xmlDomains, 0), Charsets.UTF_8); + XMLBuilder builder = XMLBuilder.parse(new InputSource(new StringReader(fromXML))); + uuid = builder.xpathFind("/domain/uuid").getElement().getTextContent(); + } catch (IOException e) { + e.printStackTrace(); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } catch (SAXException e) { + e.printStackTrace(); + } catch (XPathExpressionException e) { + e.printStackTrace(); } - return regions; - */ - + return uuid; + } + + /* + * Map regions = newLinkedHashMap(); for (String region : + * Splitter.on(',').split(regionString)) { regions.put( region, + * URI.create(injector.getInstance(Key.get(String.class, Names.named(Constants.PROPERTY_ENDPOINT + * + "." + region))))); } return regions; + */ + } \ No newline at end of file diff --git a/sandbox/vsphere/src/main/java/org/jclouds/vi/Image.java b/sandbox/vsphere/src/main/java/org/jclouds/vi/Image.java index 069b5bfd67..463029bbf6 100644 --- a/sandbox/vsphere/src/main/java/org/jclouds/vi/Image.java +++ b/sandbox/vsphere/src/main/java/org/jclouds/vi/Image.java @@ -28,10 +28,10 @@ import com.google.common.base.Objects; */ public class Image { - public int id; + public String id; public String name; - public Image(int id, String name) { + public Image(String id, String name) { this.id = id; this.name = name; } diff --git a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViComputeService.java b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViComputeService.java index f5b240a3fa..72a6fc5f8d 100644 --- a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViComputeService.java +++ b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViComputeService.java @@ -19,7 +19,6 @@ package org.jclouds.vi.compute; -import java.io.StringReader; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; @@ -49,12 +48,10 @@ import org.jclouds.compute.strategy.SuspendNodeStrategy; import org.jclouds.compute.util.ComputeUtils; import org.jclouds.domain.Credentials; import org.jclouds.domain.Location; -import org.xml.sax.InputSource; import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.base.Throwables; -import com.jamesmurty.utils.XMLBuilder; import com.vmware.vim25.mo.ServiceInstance; /** diff --git a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViComputeServiceContextBuilder.java b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViComputeServiceContextBuilder.java index 8baff48f3d..26565137e2 100644 --- a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViComputeServiceContextBuilder.java +++ b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViComputeServiceContextBuilder.java @@ -19,8 +19,6 @@ package org.jclouds.vi.compute; -import static org.jclouds.vi.ViConstants.PROPERTY_LIBVIRT_DOMAIN_DIR; - import java.util.List; import java.util.Properties; @@ -38,9 +36,6 @@ public class ViComputeServiceContextBuilder extends StandaloneComputeServiceCont public ViComputeServiceContextBuilder(Properties props) { super(ServiceInstance.class, props); - - if (!properties.containsKey(PROPERTY_LIBVIRT_DOMAIN_DIR)) - properties.setProperty(PROPERTY_LIBVIRT_DOMAIN_DIR, "/etc/libvirt/qemu"); } @Override diff --git a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViComputeServiceContextSpec.java b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViComputeServiceContextSpec.java index c28e15f75c..ad186a411a 100644 --- a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViComputeServiceContextSpec.java +++ b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViComputeServiceContextSpec.java @@ -33,7 +33,7 @@ public class ViComputeServiceContextSpec extends RestContextSpec modules) { - super("vsphere", endpoint, "1", identity, credential, ComputeService.class, ComputeService.class, + super("vi", endpoint, "1", identity, credential, ComputeService.class, ComputeService.class, PropertiesBuilder.class, (Class) ViComputeServiceContextBuilder.class, modules); } diff --git a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViPropertiesBuilder.java b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViPropertiesBuilder.java index 98a154751f..4823cdbcbb 100644 --- a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViPropertiesBuilder.java +++ b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/ViPropertiesBuilder.java @@ -29,7 +29,7 @@ import java.util.Properties; import org.jclouds.PropertiesBuilder; /** - * Builds properties used in Libvirt Clients + * Builds properties used in vi Clients * * @author Andrea Turli */ @@ -37,7 +37,7 @@ public class ViPropertiesBuilder extends PropertiesBuilder { @Override protected Properties defaultProperties() { Properties properties = super.defaultProperties(); - properties.setProperty(PROPERTY_LIBVIRT_DOMAIN_DIR, "/etc/libvirt/qemu"); +// properties.setProperty(PROPERTY_LIBVIRT_DOMAIN_DIR, "/etc/libvirt/qemu"); properties.setProperty(PROPERTY_TIMEOUT_NODE_SUSPENDED, 120 * 1000 + ""); // auth fail sometimes happens in EC2, as the rc.local script that injects the diff --git a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/config/ViComputeServiceContextModule.java b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/config/ViComputeServiceContextModule.java index 981bf94052..3abcba9e90 100644 --- a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/config/ViComputeServiceContextModule.java +++ b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/config/ViComputeServiceContextModule.java @@ -19,8 +19,6 @@ package org.jclouds.vi.compute.config; -import static org.jclouds.vi.ViConstants.PROPERTY_LIBVIRT_DOMAIN_DIR; - import java.io.File; import java.io.IOException; import java.io.StringReader; @@ -38,14 +36,13 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.WildcardFileFilter; import org.jclouds.Constants; import org.jclouds.compute.ComputeServiceAdapter; -import org.jclouds.compute.config.StandaloneComputeServiceContextModule; +import org.jclouds.compute.config.ComputeServiceAdapterContextModule; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.suppliers.DefaultLocationSupplier; import org.jclouds.domain.Location; import org.jclouds.rest.annotations.Provider; -import org.jclouds.vi.Datacenter; import org.jclouds.vi.Image; import org.jclouds.vi.compute.functions.DatacenterToLocation; import org.jclouds.vi.compute.functions.ViImageToImage; @@ -61,11 +58,10 @@ import com.google.common.base.Supplier; import com.google.common.collect.Iterables; import com.google.common.io.Files; import com.google.inject.Injector; -import com.google.inject.Key; import com.google.inject.Provides; import com.google.inject.TypeLiteral; -import com.google.inject.name.Names; import com.jamesmurty.utils.XMLBuilder; +import com.vmware.vim25.mo.Datacenter; import com.vmware.vim25.mo.ServiceInstance; import com.vmware.vim25.mo.VirtualMachine; @@ -73,8 +69,14 @@ import com.vmware.vim25.mo.VirtualMachine; * * @author Adrian Cole */ -public class ViComputeServiceContextModule extends - StandaloneComputeServiceContextModule { +public class ViComputeServiceContextModule + extends + ComputeServiceAdapterContextModule { + + public ViComputeServiceContextModule() { + super(ServiceInstance.class, ServiceInstance.class); + } + @Override protected void configure() { super.configure(); @@ -97,15 +99,14 @@ public class ViComputeServiceContextModule extends protected ServiceInstance createConnection(@Provider URI endpoint, @Named(Constants.PROPERTY_IDENTITY) String identity, @Named(Constants.PROPERTY_CREDENTIAL) String credential) throws RemoteException, MalformedURLException { - System.out.println(endpoint); - System.out.println(identity); - System.out.println(credential); return new ServiceInstance(endpoint.toURL(), identity, credential, true); } @Override protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) { - String domainDir = injector.getInstance(Key.get(String.class, Names.named(PROPERTY_LIBVIRT_DOMAIN_DIR))); + // String domainDir = injector.getInstance(Key.get(String.class, + // Names.named(PROPERTY_LIBVIRT_DOMAIN_DIR))); + String domainDir = ""; String hardwareId = searchForHardwareIdInDomainDir(domainDir); String image = searchForImageIdInDomainDir(domainDir); return template.hardwareId(hardwareId).imageId(image); diff --git a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/DatacenterToLocation.java b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/DatacenterToLocation.java index d5ac03464d..e07d865770 100644 --- a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/DatacenterToLocation.java +++ b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/DatacenterToLocation.java @@ -24,9 +24,9 @@ import javax.inject.Singleton; import org.jclouds.domain.Location; import org.jclouds.domain.LocationScope; import org.jclouds.domain.internal.LocationImpl; -import org.jclouds.vi.Datacenter; import com.google.common.base.Function; +import com.vmware.vim25.mo.Datacenter; /** * @author Adrian Cole @@ -36,7 +36,7 @@ public class DatacenterToLocation implements Function { @Override public Location apply(Datacenter from) { - return new LocationImpl(LocationScope.ZONE, from.id + "", from.name, null); + return new LocationImpl(LocationScope.ZONE, from.getName() + "", from.getName(), null); } } diff --git a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/ViImageToImage.java b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/ViImageToImage.java index 7fdedf6538..8275831d22 100644 --- a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/ViImageToImage.java +++ b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/ViImageToImage.java @@ -51,6 +51,7 @@ public class ViImageToImage implements Function { OsFamily family = null; try { + // TODO family = OsFamily.fromValue(from.name); builder.operatingSystem(new OperatingSystemBuilder().name(from.name).family(family).description(from.name).build()); } catch (IllegalArgumentException e) { diff --git a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/VirtualMachineToHardware.java b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/VirtualMachineToHardware.java index 281de80a11..8a6938766b 100644 --- a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/VirtualMachineToHardware.java +++ b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/VirtualMachineToHardware.java @@ -19,31 +19,23 @@ package org.jclouds.vi.compute.functions; -import java.io.IOException; -import java.io.StringReader; import java.util.List; import javax.inject.Singleton; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpression; -import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathFactory; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.HardwareBuilder; import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Volume; import org.jclouds.compute.domain.internal.VolumeImpl; -import org.w3c.dom.Document; -import org.w3c.dom.NodeList; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; import com.google.common.base.Function; import com.google.common.base.Throwables; import com.google.common.collect.Lists; -import com.jamesmurty.utils.XMLBuilder; +import com.vmware.vim25.VirtualDevice; +import com.vmware.vim25.VirtualDeviceBackingInfo; +import com.vmware.vim25.VirtualDisk; +import com.vmware.vim25.VirtualDiskFlatVer2BackingInfo; import com.vmware.vim25.mo.VirtualMachine; /** @@ -67,26 +59,21 @@ public class VirtualMachineToHardware implements Function volumes = Lists.newArrayList(); - - /* - XMLBuilder xmlBuilder = XMLBuilder.parse(new InputSource(new StringReader(from.getXMLDesc(0)))); - Document doc = xmlBuilder.getDocument(); - XPathExpression expr = XPathFactory.newInstance().newXPath().compile("//devices/disk[@device='disk']/source/@file"); - NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); - String diskFileName = nodes.item(0).getNodeValue(); - for (int i = 0; i < nodes.getLength(); i++) { - StorageVol storageVol = from.getConnect().storageVolLookupByPath(diskFileName); - String id = storageVol.getKey(); - float size = new Long(storageVol.getInfo().capacity).floatValue(); - volumes.add(new VolumeImpl(id, Volume.Type.LOCAL, size, null, true, false)); + // look for volumes + VirtualDevice[] devices = from.getConfig().getHardware().getDevice(); + for (VirtualDevice virtualDevice : devices) { + if(virtualDevice.getDeviceInfo().getLabel().contains("Hard disk")) { + if(virtualDevice instanceof VirtualDisk) { + VirtualDisk disk = (VirtualDisk) virtualDevice; + VirtualDeviceBackingInfo backingInfo = disk.getBacking(); + if(backingInfo instanceof VirtualDiskFlatVer2BackingInfo) { + VirtualDiskFlatVer2BackingInfo diskFlatVer2BackingInfo = (VirtualDiskFlatVer2BackingInfo) backingInfo; + volumes.add(new VolumeImpl(diskFlatVer2BackingInfo.getUuid(), Volume.Type.LOCAL, new Float(disk.getCapacityInKB() + ""), diskFlatVer2BackingInfo.getFileName(), true, false)); + } + } + } } - */ - - // TODO builder.volumes((List) volumes); - Float size = new Float(21345); - String id = "dglffdbdflmb"; - volumes.add(new VolumeImpl(id, Volume.Type.LOCAL, size, null, true, false)); return builder.build(); } diff --git a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/VirtualMachineToNodeMetadata.java b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/VirtualMachineToNodeMetadata.java index 6fd5d2d3d7..f11883f2a9 100644 --- a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/VirtualMachineToNodeMetadata.java +++ b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/functions/VirtualMachineToNodeMetadata.java @@ -59,18 +59,18 @@ public class VirtualMachineToNodeMetadata implements Function findHardwareForDomain; - private final FindLocationForDomain findLocationForDomain; - private final FindImageForDomain findImageForDomain; + private final Function findHardwareForVirtualMachine; + private final FindLocationForVirtualMachine findLocationForVirtualMachine; + private final FindImageForVirtualMachine findImageForVirtualMachine; private final Map credentialStore; @Inject - VirtualMachineToNodeMetadata(Map credentialStore, Function findHardwareForDomain, - FindLocationForDomain findLocationForDomain, FindImageForDomain findImageForDomain) { + VirtualMachineToNodeMetadata(Map credentialStore, Function findHardwareForVirtualMachine, + FindLocationForVirtualMachine findLocationForVirtualMachine, FindImageForVirtualMachine findImageForVirtualMachine) { this.credentialStore = checkNotNull(credentialStore, "credentialStore"); - this.findHardwareForDomain = checkNotNull(findHardwareForDomain, "findHardwareForDomain"); - this.findLocationForDomain = checkNotNull(findLocationForDomain, "findLocationForDomain"); - this.findImageForDomain = checkNotNull(findImageForDomain, "findImageForDomain"); + this.findHardwareForVirtualMachine = checkNotNull(findHardwareForVirtualMachine, "findHardwareForVirtualMachine"); + this.findLocationForVirtualMachine = checkNotNull(findLocationForVirtualMachine, "findLocationForVirtualMachine"); + this.findImageForVirtualMachine = checkNotNull(findImageForVirtualMachine, "findImageForVirtualMachine"); } @Override @@ -79,19 +79,23 @@ public class VirtualMachineToNodeMetadata implements Function of(from.publicAddress)); // builder.privateAddresses(ImmutableSet. of(from.privateAddress)); - builder.credentials(credentialStore.get("node#" + from.getMOR().get_value())); + builder.credentials(credentialStore.get("node#" + from.getName())); } catch (Exception e) { // TODO Auto-generated catch block @@ -101,10 +105,10 @@ public class VirtualMachineToNodeMetadata implements Function { + public static class FindImageForVirtualMachine extends FindResourceInSet { @Inject - public FindImageForDomain(@Memoized Supplier> hardware) { + public FindImageForVirtualMachine(@Memoized Supplier> hardware) { super(hardware); } @@ -117,10 +121,10 @@ public class VirtualMachineToNodeMetadata implements Function { + public static class FindLocationForVirtualMachine extends FindResourceInSet { @Inject - public FindLocationForDomain(@Memoized Supplier> hardware) { + public FindLocationForVirtualMachine(@Memoized Supplier> hardware) { super(hardware); } diff --git a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/strategy/ViComputeServiceAdapter.java b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/strategy/ViComputeServiceAdapter.java index a0ac47bec2..47326098f1 100644 --- a/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/strategy/ViComputeServiceAdapter.java +++ b/sandbox/vsphere/src/main/java/org/jclouds/vi/compute/strategy/ViComputeServiceAdapter.java @@ -20,7 +20,6 @@ package org.jclouds.vi.compute.strategy; import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.vi.ViConstants.PROPERTY_LIBVIRT_DOMAIN_DIR; import java.rmi.RemoteException; import java.util.List; @@ -33,14 +32,14 @@ import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.domain.Template; import org.jclouds.domain.Credentials; -import org.jclouds.vi.Datacenter; import org.jclouds.vi.Image; import com.google.common.base.Throwables; import com.google.common.collect.Lists; -import com.google.inject.name.Named; import com.vmware.vim25.InvalidProperty; import com.vmware.vim25.RuntimeFault; +import com.vmware.vim25.mo.Datacenter; +import com.vmware.vim25.mo.Folder; import com.vmware.vim25.mo.InventoryNavigator; import com.vmware.vim25.mo.ManagedEntity; import com.vmware.vim25.mo.ServiceInstance; @@ -116,25 +115,25 @@ public class ViComputeServiceAdapter implements ComputeServiceAdapter listHardwareProfiles() { - return listNodes(); + // TODO + return null; } @Override public Iterable listImages() { - /* - int i = 1; + List images = Lists.newArrayList(); try { - String[] domains = client.listDefinedDomains(); - List images = Lists.newArrayList(); - for (String domainName : domains) { - images.add(new Image(i++, domainName)); + + ManagedEntity[] entities = new InventoryNavigator( + client.getRootFolder()).searchManagedEntities("VirtualMachine"); + for (ManagedEntity entity : entities) { + VirtualMachine vm = (VirtualMachine) entity; + images.add(new Image(vm.getConfig().getGuestId(), vm.getConfig().getGuestFullName())); } return images; } catch (Exception e) { return propogate(e); } - */ - return null; } @Override @@ -143,8 +142,8 @@ public class ViComputeServiceAdapter implements ComputeServiceAdapter vms = Lists.newArrayList(); for (ManagedEntity entity : vmEntities) { - System.out.println(entity.getName()); - vms.add((VirtualMachine) entity); + VirtualMachine vm = (VirtualMachine) entity; + vms.add(vm); } return vms; } catch (InvalidProperty e) { @@ -164,7 +163,7 @@ public class ViComputeServiceAdapter implements ComputeServiceAdapter datacenters = Lists.newArrayList(); for (int i = 0; i< datacenterEntities.length; i++) { - datacenters.add(new Datacenter(i, datacenterEntities[i].getName())); + datacenters.add((Datacenter) datacenterEntities[i]); } return datacenters; } catch (InvalidProperty e) { @@ -178,18 +177,20 @@ public class ViComputeServiceAdapter implements ComputeServiceAdapter goGridContext = new ComputeServiceContextFactory().createContext( + RestContext viContext = new ComputeServiceContextFactory().createContext( provider, identity, credential).getProviderSpecificContext(); } } diff --git a/sandbox/vsphere/src/test/java/org/jclouds/vi/compute/ViExperimentLiveTest.java b/sandbox/vsphere/src/test/java/org/jclouds/vi/compute/ViExperimentLiveTest.java index c9bb37b772..f4a4859cee 100644 --- a/sandbox/vsphere/src/test/java/org/jclouds/vi/compute/ViExperimentLiveTest.java +++ b/sandbox/vsphere/src/test/java/org/jclouds/vi/compute/ViExperimentLiveTest.java @@ -25,9 +25,11 @@ import java.util.Set; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContextFactory; +import org.jclouds.compute.domain.ComputeMetadata; +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.domain.Template; -import org.jclouds.vi.compute.ViComputeServiceContextSpec; +import org.jclouds.domain.Location; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -57,37 +59,38 @@ public class ViExperimentLiveTest { try { context = new ComputeServiceContextFactory().createContext(new ViComputeServiceContextSpec( endpoint, identity, credential)); - context.getComputeService().listNodes(); - - /* - * /* System.out.println("images " + context.getComputeService().listImages()); - * System.out.println("nodes " + context.getComputeService().listNodes()); - * System.out.println("hardware profiles " + - * context.getComputeService().listHardwareProfiles()); - */ +// Set locations = context.getComputeService().listAssignableLocations(); +// +// Set nodes = context.getComputeService().listNodes(); - -/* Template defaultTemplate = context.getComputeService().templateBuilder() - .hardwareId("d106ae67-5a1b-8f91-b311-83c93bcb0a1f").imageId("1") //.locationId("") - .build();*/ - + // TODO +// Set hardwares = context.getComputeService().listHardwareProfiles(); +// +// Set images = context.getComputeService().listImages(); + + NodeMetadata node = context.getComputeService().getNodeMetadata("provaVM"); + System.out.println(node); /* * We will probably make a default template out of properties at some point You can control * the default template via overriding a method in standalonecomputeservicexontextmodule */ - - Set nodeMetadataSet = context.getComputeService().runNodesWithTag("tty", 1); + + /* Template defaultTemplate = context.getComputeService().templateBuilder() + .hardwareId("d106ae67-5a1b-8f91-b311-83c93bcb0a1f").imageId("1") //.locationId("") + .build(); + Set nodeMetadataSet = context.getComputeService().runNodesWithTag("MyServer", 1); for (NodeMetadata nodeMetadata : nodeMetadataSet) { - /* - * context.getComputeService().suspendNode(nodeMetadata.getId()); - * context.getComputeService().resumeNode(nodeMetadata.getId()); - */ + +// context.getComputeService().suspendNode(nodeMetadata.getId()); +// context.getComputeService().resumeNode(nodeMetadata.getId()); + context.getComputeService().destroyNode(nodeMetadata.getId()); } } catch (Exception e) { e.printStackTrace(); + */ } finally { if (context != null) context.close(); diff --git a/skeletons/standalone-compute/src/main/java/org/jclouds/servermanager/compute/config/ServerManagerComputeServiceContextModule.java b/skeletons/standalone-compute/src/main/java/org/jclouds/servermanager/compute/config/ServerManagerComputeServiceContextModule.java index 82f434858f..fac7624399 100644 --- a/skeletons/standalone-compute/src/main/java/org/jclouds/servermanager/compute/config/ServerManagerComputeServiceContextModule.java +++ b/skeletons/standalone-compute/src/main/java/org/jclouds/servermanager/compute/config/ServerManagerComputeServiceContextModule.java @@ -20,7 +20,7 @@ package org.jclouds.servermanager.compute.config; import org.jclouds.compute.ComputeServiceAdapter; -import org.jclouds.compute.config.StandaloneComputeServiceContextModule; +import org.jclouds.compute.config.ComputeServiceAdapterContextModule; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.suppliers.DefaultLocationSupplier; import org.jclouds.domain.Location; @@ -28,6 +28,7 @@ import org.jclouds.servermanager.Datacenter; import org.jclouds.servermanager.Hardware; import org.jclouds.servermanager.Image; import org.jclouds.servermanager.Server; +import org.jclouds.servermanager.ServerManager; import org.jclouds.servermanager.compute.functions.DatacenterToLocation; import org.jclouds.servermanager.compute.functions.ServerManagerHardwareToHardware; import org.jclouds.servermanager.compute.functions.ServerManagerImageToImage; @@ -43,7 +44,12 @@ import com.google.inject.TypeLiteral; * @author Adrian Cole */ public class ServerManagerComputeServiceContextModule extends - StandaloneComputeServiceContextModule { + ComputeServiceAdapterContextModule { + + public ServerManagerComputeServiceContextModule() { + super(ServerManager.class, ServerManager.class); + } + @Override protected void configure() { super.configure(); diff --git a/slicehost/src/test/java/org/jclouds/slicehost/compute/SlicehostTemplateBuilderLiveTest.java b/slicehost/src/test/java/org/jclouds/slicehost/compute/SlicehostTemplateBuilderLiveTest.java index cf88d5ac72..c001b33f05 100644 --- a/slicehost/src/test/java/org/jclouds/slicehost/compute/SlicehostTemplateBuilderLiveTest.java +++ b/slicehost/src/test/java/org/jclouds/slicehost/compute/SlicehostTemplateBuilderLiveTest.java @@ -25,9 +25,9 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.compute.BaseTemplateBuilderLiveTest; -import org.jclouds.compute.OsFamilyVersion64Bit; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; import org.testng.annotations.Test; import com.google.common.base.Predicate; diff --git a/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/compute/TerremarkECloudTemplateBuilderLiveTest.java b/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/compute/TerremarkECloudTemplateBuilderLiveTest.java index 95845f31a0..3770e566b8 100644 --- a/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/compute/TerremarkECloudTemplateBuilderLiveTest.java +++ b/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/compute/TerremarkECloudTemplateBuilderLiveTest.java @@ -25,9 +25,9 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.compute.BaseTemplateBuilderLiveTest; -import org.jclouds.compute.OsFamilyVersion64Bit; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; import org.testng.annotations.Test; import com.google.common.base.Predicate; diff --git a/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudExpressTemplateBuilderLiveTest.java b/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudExpressTemplateBuilderLiveTest.java index 514b15fac3..c30a81d0c4 100644 --- a/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudExpressTemplateBuilderLiveTest.java +++ b/vcloud/terremark/src/test/java/org/jclouds/vcloud/terremark/compute/TerremarkVCloudExpressTemplateBuilderLiveTest.java @@ -25,9 +25,9 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.compute.BaseTemplateBuilderLiveTest; -import org.jclouds.compute.OsFamilyVersion64Bit; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.Template; +import org.jclouds.compute.domain.os.OsFamilyVersion64Bit; import org.testng.annotations.Test; import com.google.common.base.Predicate;