diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java index 215c0fcd24..96c8db569b 100755 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/config/EC2ComputeServiceContextModule.java @@ -34,6 +34,8 @@ import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import com.google.inject.Scopes; +import com.google.inject.TypeLiteral; import org.jclouds.aws.domain.Region; import org.jclouds.aws.ec2.EC2; import org.jclouds.aws.ec2.EC2AsyncClient; @@ -52,6 +54,7 @@ import org.jclouds.aws.ec2.config.EC2ContextModule; import org.jclouds.aws.ec2.domain.AvailabilityZone; import org.jclouds.aws.ec2.domain.KeyPair; import org.jclouds.aws.ec2.domain.RunningInstance; +import org.jclouds.aws.ec2.functions.RunningInstanceToStorageMappingUnix; import org.jclouds.aws.ec2.services.InstanceClient; import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeServiceContext; @@ -88,6 +91,7 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.inject.Provides; +import org.jclouds.util.Jsr330; /** * Configures the {@link ComputeServiceContext}; requires {@link EC2ComputeService} bound. @@ -105,6 +109,9 @@ public class EC2ComputeServiceContextModule extends EC2ContextModule { bind(GetNodeMetadataStrategy.class).to(EC2GetNodeMetadataStrategy.class); bind(RebootNodeStrategy.class).to(EC2RebootNodeStrategy.class); bind(DestroyNodeStrategy.class).to(EC2DestroyNodeStrategy.class); + bind(new TypeLiteral>>(){}). + annotatedWith(Jsr330.named("volumeMapping")). + to(RunningInstanceToStorageMappingUnix.class).in(Scopes.SINGLETON); } @Provides diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java index 9e90c4c7cc..37f24262f2 100644 --- a/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java @@ -27,13 +27,13 @@ import java.util.Map; import java.util.Set; import javax.inject.Inject; +import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.aws.ec2.compute.domain.RegionTag; import org.jclouds.aws.ec2.domain.InstanceState; import org.jclouds.aws.ec2.domain.KeyPair; import org.jclouds.aws.ec2.domain.RunningInstance; -import org.jclouds.aws.ec2.functions.InstanceTypeToStorageMappingUnix; import org.jclouds.aws.ec2.options.DescribeImagesOptions; import org.jclouds.aws.ec2.services.AMIClient; import org.jclouds.compute.domain.Image; @@ -65,16 +65,19 @@ public class RunningInstanceToNodeMetadata implements Function images; private final Map locations; + private final Function> instanceToStorageMapping; @Inject RunningInstanceToNodeMetadata(AMIClient amiClient, Map credentialsMap, PopulateDefaultLoginCredentialsForImageStrategy credentialProvider, - Map images, Map locations) { + Map images, Map locations, + @Named("volumeMapping") Function> instanceToStorageMapping) { this.amiClient = checkNotNull(amiClient, "amiClient"); this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap"); this.credentialProvider = checkNotNull(credentialProvider, "credentialProvider"); this.images = checkNotNull(images, "images"); this.locations = checkNotNull(locations, "locations"); + this.instanceToStorageMapping = checkNotNull(instanceToStorageMapping); } @Override @@ -123,8 +126,7 @@ public class RunningInstanceToNodeMetadata implements Function - * - * ==================================================================== - * 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.aws.ec2.functions; - -import com.google.common.base.Function; -import com.google.common.collect.Maps; -import org.jclouds.aws.ec2.domain.InstanceType; - -import java.util.Map; - -import static org.jclouds.compute.reference.ComputeServiceConstants.LOCAL_PARTITION_GB_PATTERN; - -/** - * Map the instance type to storage information known about it. This information is statically set as described by Amazon. - * - * Note that having the partitions available doesn't mean they're formatted/mounted by default. The links below - * describe what partitions are formatted initially. To format/mount an available device, refer to - * this article. - * - * @see - * @see - * - * @author Oleksiy Yarmula - */ -public class InstanceTypeToStorageMappingUnix implements Function> { - - public final static String ROOT_PARTITION_NAME_UNIX = "/dev/sda1"; - - @Override - public Map apply(InstanceType instanceType) { - Map mapping = Maps.newHashMap(); - - //root partition - mapping.put(String.format(LOCAL_PARTITION_GB_PATTERN, ROOT_PARTITION_NAME_UNIX), - getRootPartitionSizeForInstanceType(instanceType) + ""); - - //primary partition (always formatted/mounted) - mapping.put(String.format(LOCAL_PARTITION_GB_PATTERN, getPrimaryPartitionDeviceName(instanceType)), - getPrimaryPartitionSizeForInstanceType(instanceType) + ""); - - //additional partitions if any - for(Map.Entry entry : getAdditionalPartitionsMapping(instanceType).entrySet()) { - mapping.put(String.format(LOCAL_PARTITION_GB_PATTERN, entry.getKey()), - entry.getValue() + ""); - } - - return mapping; - } - - /** - * Retrieve the root partition size. - * Note, this is usually a rather small partition. Refer to - * {@link #getPrimaryPartitionSizeForInstanceType()} to determine the - * size of the primary (usually, biggest) partition. In some cases, - * for large instances there are several partitions of the size of primary partition. - * - * @param instanceType for which the root partition size is to be determined - * @return size in GB - * - * @see - * @see - */ - public int getRootPartitionSizeForInstanceType(InstanceType instanceType) { - /* per documentation at - http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?instance-types.html - M2 XLARGE doesn't have the root partition - TODO verify - */ - if(InstanceType.M2_XLARGE == instanceType) return 0; - - //other types have 10 GB root partition - return 10; - } - - public static String getPrimaryPartitionDeviceName(InstanceType instanceType) { - if(InstanceType.M1_SMALL == instanceType || InstanceType.C1_MEDIUM == instanceType) - return "/dev/sda2"; - return "/dev/sdb"; - } - - /** - * Retrieve the primary partition size. - * - * This is usually the biggest partition. In some cases, - * for large instances there are several partitions of the size of primary partition. - * - * @param instanceType for which the primary partition size is to be determined - * @return size in GB - */ - public static int getPrimaryPartitionSizeForInstanceType(InstanceType instanceType) { - switch(instanceType) { - case M1_SMALL: - return 150; - - case M1_LARGE: - return 420; - - case M1_XLARGE: - return 420; - - case C1_MEDIUM: - return 340; - - case C1_XLARGE: - return 420; - - case M2_XLARGE: - return 420; - - case M2_2XLARGE: - return 840; - - case M2_4XLARGE: - return 840; - } - throw new RuntimeException("Unknown instance type"); - } - - /** - * Retrieve additional devices mapping (non-root and non-primary) for the instance type. - * - * @param instanceType - * @return map with device name(s) and size(s) or empty map if the instance doesn't - * have any additional - * - * @see - */ - public static Map getAdditionalPartitionsMapping(InstanceType instanceType) { - Map mapping = Maps.newHashMap(); - - int size = 0; - switch(instanceType) { - case M1_LARGE: - case M1_XLARGE: - case C1_XLARGE: - size = 420; - break; - - case M2_4XLARGE: - size = 840; - break; - } - - //m1.large, m1.xlarge, and c1.xlarge - if(InstanceType.M1_LARGE == instanceType || InstanceType.M1_XLARGE == instanceType || - InstanceType.C1_XLARGE == instanceType || InstanceType.M2_4XLARGE == instanceType) { - - mapping.put("/dev/sdc", size); - } - - if(InstanceType.M1_XLARGE == instanceType || InstanceType.C1_XLARGE == instanceType) { - mapping.put("/dev/sdd", size); - } - - if(InstanceType.M1_XLARGE == instanceType || InstanceType.C1_XLARGE == instanceType) { - mapping.put("/dev/sde", size); - } - - return mapping; - } -} diff --git a/aws/core/src/main/java/org/jclouds/aws/ec2/functions/RunningInstanceToStorageMappingUnix.java b/aws/core/src/main/java/org/jclouds/aws/ec2/functions/RunningInstanceToStorageMappingUnix.java new file mode 100644 index 0000000000..c09e87d20f --- /dev/null +++ b/aws/core/src/main/java/org/jclouds/aws/ec2/functions/RunningInstanceToStorageMappingUnix.java @@ -0,0 +1,180 @@ +/** + * + * 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.aws.ec2.functions; + +import com.google.common.base.Function; +import com.google.common.collect.Maps; +import org.jclouds.aws.ec2.domain.InstanceType; +import org.jclouds.aws.ec2.domain.RunningInstance; + +import java.util.Map; + +import static org.jclouds.compute.reference.ComputeServiceConstants.LOCAL_PARTITION_GB_PATTERN; + +/** + * Map the instance to storage information known about it. This information is statically set as described by Amazon. + * + * Note that having the partitions available doesn't mean they're formatted/mounted by default. The links below + * describe what partitions are formatted initially. To format/mount an available device, refer to + * this article. + * + * @see + * @see + * + * @author Oleksiy Yarmula + */ +public class RunningInstanceToStorageMappingUnix implements Function> { + + public final static String ROOT_PARTITION_NAME_UNIX = "/dev/sda1"; + + @Override + public Map apply(RunningInstance instance) { + final InstanceType instanceType = instance.getInstanceType(); + + Map mapping = Maps.newHashMap(); + + //root partition + mapping.put(String.format(LOCAL_PARTITION_GB_PATTERN, ROOT_PARTITION_NAME_UNIX), + getRootPartitionSizeForInstanceType(instanceType) + ""); + + //primary partition (always formatted/mounted) + mapping.put(String.format(LOCAL_PARTITION_GB_PATTERN, getPrimaryPartitionDeviceName(instanceType)), + getPrimaryPartitionSizeForInstanceType(instanceType) + ""); + + //additional partitions if any + for(Map.Entry entry : getAdditionalPartitionsMapping(instanceType).entrySet()) { + mapping.put(String.format(LOCAL_PARTITION_GB_PATTERN, entry.getKey()), + entry.getValue() + ""); + } + + return mapping; + } + + /** + * Retrieve the root partition size. + * Note, this is usually a rather small partition. Refer to + * {@link #getPrimaryPartitionSizeForInstanceType} to determine the + * size of the primary (usually, biggest) partition. In some cases, + * for large instances there are several partitions of the size of primary partition. + * + * @param instanceType for which the root partition size is to be determined + * @return size in GB + * + * @see + * @see + */ + public int getRootPartitionSizeForInstanceType(InstanceType instanceType) { + /* per documentation at + http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?instance-types.html + M2 XLARGE doesn't have the root partition + TODO verify + */ + if(InstanceType.M2_XLARGE == instanceType) return 0; + + //other types have 10 GB root partition + return 10; + } + + public static String getPrimaryPartitionDeviceName(InstanceType instanceType) { + if(InstanceType.M1_SMALL == instanceType || InstanceType.C1_MEDIUM == instanceType) + return "/dev/sda2"; + return "/dev/sdb"; + } + + /** + * Retrieve the primary partition size. + * + * This is usually the biggest partition. In some cases, + * for large instances there are several partitions of the size of primary partition. + * + * @param instanceType for which the primary partition size is to be determined + * @return size in GB + */ + public static int getPrimaryPartitionSizeForInstanceType(InstanceType instanceType) { + switch(instanceType) { + case M1_SMALL: + return 150; + + case M1_LARGE: + return 420; + + case M1_XLARGE: + return 420; + + case C1_MEDIUM: + return 340; + + case C1_XLARGE: + return 420; + + case M2_XLARGE: + return 420; + + case M2_2XLARGE: + return 840; + + case M2_4XLARGE: + return 840; + } + throw new RuntimeException("Unknown instance type"); + } + + /** + * Retrieve additional devices mapping (non-root and non-primary) for the instance type. + * + * @param instanceType + * @return map with device name(s) and size(s) or empty map if the instance doesn't + * have any additional + * + * @see + */ + public static Map getAdditionalPartitionsMapping(InstanceType instanceType) { + Map mapping = Maps.newHashMap(); + + int size = 0; + switch(instanceType) { + case M1_LARGE: + case M1_XLARGE: + case C1_XLARGE: + size = 420; + break; + + case M2_4XLARGE: + size = 840; + break; + } + + //m1.large, m1.xlarge, and c1.xlarge + if(InstanceType.M1_LARGE == instanceType || InstanceType.M1_XLARGE == instanceType || + InstanceType.C1_XLARGE == instanceType || InstanceType.M2_4XLARGE == instanceType) { + + mapping.put("/dev/sdc", size); + } + + if(InstanceType.M1_XLARGE == instanceType || InstanceType.C1_XLARGE == instanceType) { + mapping.put("/dev/sdd", size); + } + + if(InstanceType.M1_XLARGE == instanceType || InstanceType.C1_XLARGE == instanceType) { + mapping.put("/dev/sde", size); + } + + return mapping; + } +} diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadataTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadataTest.java index 7a1959f3f6..cb44e80ee2 100644 --- a/aws/core/src/test/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadataTest.java +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadataTest.java @@ -38,6 +38,7 @@ import org.jclouds.aws.ec2.domain.InstanceState; import org.jclouds.aws.ec2.domain.InstanceType; import org.jclouds.aws.ec2.domain.KeyPair; import org.jclouds.aws.ec2.domain.RunningInstance; +import org.jclouds.aws.ec2.functions.RunningInstanceToStorageMappingUnix; import org.jclouds.aws.ec2.services.AMIClient; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy; @@ -94,7 +95,8 @@ public class RunningInstanceToNodeMetadataTest { replay(locations); RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(amiClient, - credentialsMap, credentialProvider, images, locations); + credentialsMap, credentialProvider, images, locations, + new RunningInstanceToStorageMappingUnix()); NodeMetadata metadata = parser.apply(instance); assertEquals(metadata.getLocation(), location); @@ -162,7 +164,8 @@ public class RunningInstanceToNodeMetadataTest { replay(locations); RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(amiClient, - credentialsMap, credentialProvider, images, locations); + credentialsMap, credentialProvider, images, locations, + new RunningInstanceToStorageMappingUnix()); NodeMetadata metadata = parser.apply(instance); diff --git a/aws/core/src/test/java/org/jclouds/aws/ec2/functions/RunningInstanceToStorageMappingUnixTest.java b/aws/core/src/test/java/org/jclouds/aws/ec2/functions/RunningInstanceToStorageMappingUnixTest.java new file mode 100644 index 0000000000..a6000fa1a0 --- /dev/null +++ b/aws/core/src/test/java/org/jclouds/aws/ec2/functions/RunningInstanceToStorageMappingUnixTest.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.aws.ec2.functions; + +import org.jclouds.aws.ec2.domain.InstanceType; +import org.jclouds.aws.ec2.domain.RunningInstance; +import org.testng.annotations.Test; + +import java.util.Map; + +import static org.easymock.EasyMock.expect; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; + +/** + * @author Oleksiy Yarmula + */ +public class RunningInstanceToStorageMappingUnixTest { + + @Test + public void testMappingForM1LargeInstance() { + RunningInstanceToStorageMappingUnix volumeMapping = new RunningInstanceToStorageMappingUnix(); + RunningInstance instance = createMock(RunningInstance.class); + expect(instance.getInstanceType()).andStubReturn(InstanceType.M1_LARGE); + replay(instance); + + Map mappingReturned = volumeMapping.apply(instance); + assert mappingReturned.size() == 3 : String.format( + "Expected size of mapping devices: %d. Found: %d", 3, mappingReturned.size()); + + assert mappingReturned.containsKey("disk_drive//dev/sda1/gb"); + assert mappingReturned.containsKey("disk_drive//dev/sdb/gb"); + assert mappingReturned.containsKey("disk_drive//dev/sdc/gb"); + } + + @Test + public void testMappingForM1XLargeInstance() { + RunningInstanceToStorageMappingUnix volumeMapping = new RunningInstanceToStorageMappingUnix(); + RunningInstance instance = createMock(RunningInstance.class); + expect(instance.getInstanceType()).andStubReturn(InstanceType.M1_XLARGE); + replay(instance); + + Map mappingReturned = volumeMapping.apply(instance); + assert mappingReturned.size() == 5 : String.format( + "Expected size of mapping devices: %d. Found: %d", 5, mappingReturned.size()); + + assert mappingReturned.containsKey("disk_drive//dev/sda1/gb"); + assert mappingReturned.containsKey("disk_drive//dev/sdb/gb"); + assert mappingReturned.containsKey("disk_drive//dev/sdc/gb"); + assert mappingReturned.containsKey("disk_drive//dev/sdd/gb"); + assert mappingReturned.containsKey("disk_drive//dev/sde/gb"); + } + +}