Issue 448: new EC2 EBS support

This commit is contained in:
Adrian Cole 2011-01-31 14:14:05 -08:00
parent 5a044b3c0e
commit a1dbbd203c
15 changed files with 374 additions and 333 deletions

View File

@ -69,6 +69,8 @@ public class EC2TemplateBuilderImpl extends TemplateBuilderImpl {
eTo.securityGroups(eFrom.getGroupIds());
if (eFrom.getKeyPair() != null)
eTo.keyPair(eFrom.getKeyPair());
if (eFrom.getBlockDeviceMappings().size() > 0)
eTo.blockDeviceMappings(eFrom.getBlockDeviceMappings());
if (!eFrom.shouldAutomaticallyCreateKeyPair())
eTo.noKeyPair();
if (eFrom.getUserData() != null)

View File

@ -24,7 +24,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nullable;
@ -123,34 +122,34 @@ public class EC2TemplateOptions extends TemplateOptions {
* Specifies the block device mappings to be used to run the instance
*/
public EC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId,
@Nullable Integer sizeInGib, @Nullable Boolean deleteOnTermination) {
@Nullable Integer sizeInGib, boolean deleteOnTermination) {
checkNotNull(deviceName, "deviceName cannot be null");
Preconditions2.checkNotEmpty(deviceName, "deviceName must be non-empty");
checkNotNull(snapshotId, "snapshotId cannot be null");
Preconditions2.checkNotEmpty(snapshotId, "snapshotId must be non-empty");
Set<BlockDeviceMapping> mappings = new HashSet<BlockDeviceMapping>();
com.google.common.collect.ImmutableSet.Builder<BlockDeviceMapping> mappings = ImmutableSet
.<BlockDeviceMapping> builder();
mappings.addAll(blockDeviceMappings);
MapEBSSnapshotToDevice mapping = new MapEBSSnapshotToDevice(deviceName, snapshotId, sizeInGib,
deleteOnTermination);
mappings.add(mapping);
blockDeviceMappings = ImmutableSet.copyOf(mappings);
blockDeviceMappings = mappings.build();
return this;
}
/**
* Specifies the block device mappings to be used to run the instance
*/
public EC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, Integer sizeInGib,
@Nullable Boolean deleteOnTermination) {
public EC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib, boolean deleteOnTermination) {
checkNotNull(deviceName, "deviceName cannot be null");
Preconditions2.checkNotEmpty(deviceName, "deviceName must be non-empty");
checkNotNull(sizeInGib, "sizeInGib cannot be null");
Set<BlockDeviceMapping> mappings = new HashSet<BlockDeviceMapping>();
com.google.common.collect.ImmutableSet.Builder<BlockDeviceMapping> mappings = ImmutableSet
.<BlockDeviceMapping> builder();
mappings.addAll(blockDeviceMappings);
MapNewVolumeToDevice mapping = new MapNewVolumeToDevice(deviceName, sizeInGib, deleteOnTermination);
mappings.add(mapping);
blockDeviceMappings = ImmutableSet.copyOf(mappings);
blockDeviceMappings = mappings.build();
return this;
}
@ -163,11 +162,12 @@ public class EC2TemplateOptions extends TemplateOptions {
checkNotNull(virtualName, "virtualName cannot be null");
Preconditions2.checkNotEmpty(virtualName, "virtualName must be non-empty");
Set<BlockDeviceMapping> mappings = new HashSet<BlockDeviceMapping>();
com.google.common.collect.ImmutableSet.Builder<BlockDeviceMapping> mappings = ImmutableSet
.<BlockDeviceMapping> builder();
mappings.addAll(blockDeviceMappings);
MapEphemeralDeviceToDevice mapping = new MapEphemeralDeviceToDevice(deviceName, virtualName);
mappings.add(mapping);
blockDeviceMappings = ImmutableSet.copyOf(mappings);
blockDeviceMappings = mappings.build();
return this;
}
@ -178,11 +178,12 @@ public class EC2TemplateOptions extends TemplateOptions {
checkNotNull(deviceName, "deviceName cannot be null");
Preconditions2.checkNotEmpty(deviceName, "deviceName must be non-empty");
Set<BlockDeviceMapping> mappings = new HashSet<BlockDeviceMapping>();
com.google.common.collect.ImmutableSet.Builder<BlockDeviceMapping> mappings = ImmutableSet
.<BlockDeviceMapping> builder();
mappings.addAll(blockDeviceMappings);
UnmapDeviceNamed mapping = new UnmapDeviceNamed(deviceName);
mappings.add(mapping);
blockDeviceMappings = ImmutableSet.copyOf(mappings);
blockDeviceMappings = mappings.build();
return this;
}
@ -195,6 +196,47 @@ public class EC2TemplateOptions extends TemplateOptions {
}
public static class Builder {
/**
* @see EC2TemplateOptions#blockDeviceMappings
*/
public static EC2TemplateOptions blockDeviceMappings(Set<? extends BlockDeviceMapping> blockDeviceMappings) {
EC2TemplateOptions options = new EC2TemplateOptions();
return options.blockDeviceMappings(blockDeviceMappings);
}
/**
* @see EC2TemplateOptions#mapEBSSnapshotToDeviceName
*/
public static EC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId,
@Nullable Integer sizeInGib, boolean deleteOnTermination) {
EC2TemplateOptions options = new EC2TemplateOptions();
return options.mapEBSSnapshotToDeviceName(deviceName, snapshotId, sizeInGib, deleteOnTermination);
}
/**
* @see EC2TemplateOptions#mapNewVolumeToDeviceName
*/
public static EC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib,
boolean deleteOnTermination) {
EC2TemplateOptions options = new EC2TemplateOptions();
return options.mapNewVolumeToDeviceName(deviceName, sizeInGib, deleteOnTermination);
}
/**
* @see EC2TemplateOptions#mapEphemeralDeviceToDeviceName
*/
public static EC2TemplateOptions mapEphemeralDeviceToDeviceName(String deviceName, String virtualName) {
EC2TemplateOptions options = new EC2TemplateOptions();
return options.mapEphemeralDeviceToDeviceName(deviceName, virtualName);
}
/**
* @see EC2TemplateOptions#unmapDeviceNamed
*/
public static EC2TemplateOptions unmapDeviceNamed(String deviceName) {
EC2TemplateOptions options = new EC2TemplateOptions();
return options.unmapDeviceNamed(deviceName);
}
/**
* @see EC2TemplateOptions#securityGroups(Iterable<String>)
@ -494,8 +536,7 @@ public class EC2TemplateOptions extends TemplateOptions {
@Override
public String toString() {
return "EC2TemplateOptions [groupIds=" + groupIds + ", keyPair=" + keyPair + ", noKeyPair=" + noKeyPair
+ ", userData=" + Arrays.toString(userData) + ", blockDeviceMappings=" + blockDeviceMappings + "]";
return "[groupIds=" + groupIds + ", keyPair=" + keyPair + ", noKeyPair=" + noKeyPair + ", userData="
+ Arrays.toString(userData) + ", blockDeviceMappings=" + blockDeviceMappings + "]";
}
}

View File

@ -79,6 +79,7 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
String keyPairName = createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, template.getOptions());
addSecurityGroups(region, tag, template, instanceOptions);
if (template.getOptions() instanceof EC2TemplateOptions) {
if (keyPairName != null)
instanceOptions.withKeyName(keyPairName);
@ -90,11 +91,12 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
Set<BlockDeviceMapping> blockDeviceMappings = EC2TemplateOptions.class.cast(template.getOptions())
.getBlockDeviceMappings();
if (blockDeviceMappings != null && blockDeviceMappings.size() > 0) {
if (blockDeviceMappings.size() > 0) {
checkState("ebs".equals(template.getImage().getUserMetadata().get("rootDeviceType")),
"BlockDeviceMapping only available on ebs boot");
instanceOptions.withBlockDeviceMappings(blockDeviceMappings);
}
}
return instanceOptions;
}

View File

@ -37,7 +37,6 @@ public class BlockDevice {
private final boolean deleteOnTermination;
public BlockDevice(String volumeId, Status attachmentStatus, Date attachTime, boolean deleteOnTermination) {
super();
this.volumeId = volumeId;
this.attachmentStatus = attachmentStatus;
this.attachTime = attachTime;

View File

@ -42,15 +42,15 @@ public class BlockDeviceMapping {
private static final Integer VOLUME_SIZE_MIN_VALUE = 1;
private static final Integer VOLUME_SIZE_MAX_VALUE = 1000;
public BlockDeviceMapping(String deviceName, @Nullable String virtualName, @Nullable String snapshotId,
BlockDeviceMapping(String deviceName, @Nullable String virtualName, @Nullable String snapshotId,
@Nullable Integer sizeInGib, @Nullable Boolean noDevice, @Nullable Boolean deleteOnTermination) {
checkNotNull(deviceName, "deviceName cannot be null");
Preconditions2.checkNotEmpty(deviceName, "the deviceName must be non-empty");
if (sizeInGib != null) {
checkArgument((sizeInGib >= VOLUME_SIZE_MIN_VALUE && sizeInGib <= VOLUME_SIZE_MAX_VALUE),
String.format("Size in Gib must be between %s and %s GB", VOLUME_SIZE_MIN_VALUE, VOLUME_SIZE_MAX_VALUE));
checkArgument((sizeInGib >= VOLUME_SIZE_MIN_VALUE && sizeInGib <= VOLUME_SIZE_MAX_VALUE), String.format(
"Size in Gib must be between %s and %s GB", VOLUME_SIZE_MIN_VALUE, VOLUME_SIZE_MAX_VALUE));
}
this.deviceName = deviceName;
this.virtualName = virtualName;
@ -88,7 +88,12 @@ public class BlockDeviceMapping {
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((deleteOnTermination == null) ? 0 : deleteOnTermination.hashCode());
result = prime * result + ((deviceName == null) ? 0 : deviceName.hashCode());
result = prime * result + ((noDevice == null) ? 0 : noDevice.hashCode());
result = prime * result + ((sizeInGib == null) ? 0 : sizeInGib.hashCode());
result = prime * result + ((snapshotId == null) ? 0 : snapshotId.hashCode());
result = prime * result + ((virtualName == null) ? 0 : virtualName.hashCode());
return result;
}
@ -101,19 +106,44 @@ public class BlockDeviceMapping {
if (getClass() != obj.getClass())
return false;
BlockDeviceMapping other = (BlockDeviceMapping) obj;
if (deleteOnTermination == null) {
if (other.deleteOnTermination != null)
return false;
} else if (!deleteOnTermination.equals(other.deleteOnTermination))
return false;
if (deviceName == null) {
if (other.deviceName != null)
return false;
} else if (!deviceName.equals(other.deviceName))
return false;
if (noDevice == null) {
if (other.noDevice != null)
return false;
} else if (!noDevice.equals(other.noDevice))
return false;
if (sizeInGib == null) {
if (other.sizeInGib != null)
return false;
} else if (!sizeInGib.equals(other.sizeInGib))
return false;
if (snapshotId == null) {
if (other.snapshotId != null)
return false;
} else if (!snapshotId.equals(other.snapshotId))
return false;
if (virtualName == null) {
if (other.virtualName != null)
return false;
} else if (!virtualName.equals(other.virtualName))
return false;
return true;
}
@Override
public String toString() {
return "BlockDeviceMapping [deviceName=" + deviceName + ", virtualName=" + virtualName + ", snapshotId="
+ snapshotId + ", sizeInGib=" + sizeInGib + ", noDevice=" + noDevice + ", deleteOnTermination="
+ deleteOnTermination + "]";
return "[deviceName=" + deviceName + ", virtualName=" + virtualName + ", snapshotId=" + snapshotId
+ ", sizeInGib=" + sizeInGib + ", noDevice=" + noDevice + ", deleteOnTermination=" + deleteOnTermination
+ "]";
}
public static class MapEBSSnapshotToDevice extends BlockDeviceMapping {

View File

@ -153,7 +153,7 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
public RunInstancesOptions withBlockDeviceMappings(Set<? extends BlockDeviceMapping> mappings) {
int i = 1;
for (BlockDeviceMapping mapping : mappings) {
for (BlockDeviceMapping mapping : checkNotNull(mappings, "mappings")) {
checkNotNull(mapping.getDeviceName(), "deviceName");
formParameters.put(String.format("BlockDeviceMapping.%d.DeviceName", i), mapping.getDeviceName());
if (mapping.getVirtualName() != null)

View File

@ -22,7 +22,6 @@ package org.jclouds.ec2.compute;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertNotNull;
import java.util.Map;
import java.util.Set;
@ -34,10 +33,12 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.NodePredicates;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.AvailabilityZone;
import org.jclouds.ec2.domain.BlockDevice;
import org.jclouds.ec2.domain.InstanceType;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.RunningInstance;
@ -51,6 +52,7 @@ import org.jclouds.ec2.services.SecurityGroupClient;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
@ -136,8 +138,8 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
assertEquals(instance.getKeyName(), tag);
// make sure we made our dummy group and also let in the user's group
assertEquals(Sets.newTreeSet(instance.getGroupIds()),
ImmutableSortedSet.<String> of("jclouds#" + tag + "#" + instance.getRegion(), tag));
assertEquals(Sets.newTreeSet(instance.getGroupIds()), ImmutableSortedSet.<String> of("jclouds#" + tag + "#"
+ instance.getRegion(), tag));
// make sure our dummy group has no rules
SecurityGroup group = Iterables.getOnlyElement(securityGroupClient.describeSecurityGroupsInRegion(null,
@ -145,8 +147,8 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
assert group.getIpPermissions().size() == 0 : group;
// try to run a script with the original keyPair
runScriptWithCreds(tag, first.getOperatingSystem(),
new Credentials(first.getCredentials().identity, result.getKeyMaterial()));
runScriptWithCreds(tag, first.getOperatingSystem(), new Credentials(first.getCredentials().identity, result
.getKeyMaterial()));
} finally {
client.destroyNodesMatching(NodePredicates.withTag(tag));
@ -159,235 +161,78 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
}
}
@Test(enabled = true, dependsOnMethods = "testCompareSizes")
public void testExtendedOptionsNoKeyPair() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices();
String tag = this.tag + "k";
TemplateOptions options = client.templateOptions();
options.as(EC2TemplateOptions.class).securityGroups(tag);
options.as(EC2TemplateOptions.class).noKeyPair();
String startedId = null;
try {
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
// create the security group
securityGroupClient.createSecurityGroupInRegion(null, tag, tag);
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options);
Credentials creds = nodes.iterator().next().getCredentials();
assert creds == null;
startedId = Iterables.getOnlyElement(nodes).getProviderId();
RunningInstance instance = getInstance(instanceClient, startedId);
assertEquals(instance.getKeyName(), null);
// make sure we made our dummy group and also let in the user's group
assertEquals(Sets.newTreeSet(instance.getGroupIds()),
ImmutableSortedSet.<String> of(tag, String.format("jclouds#%s#%s", tag, instance.getRegion())));
// make sure our dummy group has no rules
SecurityGroup group = Iterables.getOnlyElement(securityGroupClient.describeSecurityGroupsInRegion(null,
String.format("jclouds#%s#%s", tag, instance.getRegion())));
assert group.getIpPermissions().size() == 0 : group;
} finally {
client.destroyNodesMatching(NodePredicates.withTag(tag));
if (startedId != null) {
// ensure we didn't delete these resources!
assertEquals(securityGroupClient.describeSecurityGroupsInRegion(null, tag).size(), 1);
}
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
}
}
/**
* Note we cannot use the micro size as it has no ephemeral space.
*/
@Test(enabled = true)
public void testMapNewVolumeToDeviceName() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices();
String tag = this.tag + "BDM1";
int volumeSize = 120;
TemplateOptions options = client.templateOptions();
options.as(EC2TemplateOptions.class).securityGroups(tag);
options.as(EC2TemplateOptions.class).noKeyPair();
options.as(EC2TemplateOptions.class).mapNewVolumeToDeviceName("/dev/sda1", volumeSize, true);
String startedId = null;
try {
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
// create the security group
securityGroupClient.createSecurityGroupInRegion(null, tag, tag);
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options);
Credentials creds = nodes.iterator().next().getCredentials();
assert creds == null;
NodeMetadata node = nodes.iterator().next();
startedId = node.getId();
Map<String, BlockDevice> devices = instanceClient
.getBlockDeviceMappingForInstanceInRegion(node.getLocation()
.getParent().getId(), node.getProviderId());
BlockDevice device = devices.get("/dev/sda1");
//check delete on termination
assertTrue(device.isDeleteOnTermination());
ElasticBlockStoreClient ebsClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getElasticBlockStoreServices();
Set<Volume> volumes = ebsClient.describeVolumesInRegion(node
.getLocation().getParent().getId(), device.getVolumeId());
// check volume size
assertEquals(volumeSize, volumes.iterator().next().getSize());
} finally {
client.destroyNodesMatching(NodePredicates.withTag(tag));
if (startedId != null) {
// ensure we didn't delete these resources!
assertEquals(securityGroupClient.describeSecurityGroupsInRegion(null, tag).size(), 1);
}
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
}
}
@Test(enabled = true)
public void testMapEBSSnapshotToDeviceName() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getKeyPairServices();
public void testMapEBS() throws Exception {
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices();
ElasticBlockStoreClient ebsClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getElasticBlockStoreServices();
//create snapshot
Volume volume = ebsClient.createVolumeInAvailabilityZone(AvailabilityZone.US_EAST_1A, 4);
String tag = this.tag + "e";
int volumeSize = 8;
Location zone = Iterables.find(context.getComputeService().listAssignableLocations(), new Predicate<Location>() {
@Override
public boolean apply(Location arg0) {
return arg0.getScope() == LocationScope.ZONE;
}
});
// create volume only to make a snapshot
Volume volume = ebsClient.createVolumeInAvailabilityZone(zone.getId(), 4);
Snapshot snapshot = ebsClient.createSnapshotInRegion(volume.getRegion(), volume.getId());
ebsClient.deleteVolumeInRegion(volume.getRegion(), volume.getId());
String tag = this.tag + "BDM2";
int volumeSize = 120;
TemplateOptions options = client.templateOptions();
Template template = context.getComputeService().templateBuilder().locationId(volume.getRegion()).hardwareId(
InstanceType.M1_SMALL).imageDescriptionMatches(".*ebs.*").build();
options.as(EC2TemplateOptions.class).securityGroups(tag);
options.as(EC2TemplateOptions.class).noKeyPair();
options.as(EC2TemplateOptions.class).mapEBSSnapshotToDeviceName("/dev/sda1", snapshot.getId(), 120, true);
template.getOptions().as(EC2TemplateOptions.class)//
// .unmapDeviceNamed("/dev/foo)
.mapEphemeralDeviceToDeviceName("/dev/sdm", "ephemeral0")//
.mapNewVolumeToDeviceName("/dev/sdn", volumeSize, true)//
.mapEBSSnapshotToDeviceName("/dev/sdo", snapshot.getId(), volumeSize, true);
String startedId = null;
try {
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
NodeMetadata node = Iterables.getOnlyElement(client.runNodesWithTag(tag, 1, template));
// create the security group
securityGroupClient.createSecurityGroupInRegion(null, tag, tag);
// TODO figure out how to validate the ephemeral drive. perhaps with df -k?
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options);
Credentials creds = nodes.iterator().next().getCredentials();
assert creds == null;
NodeMetadata node = nodes.iterator().next();
Map<String, BlockDevice> devices = instanceClient
.getBlockDeviceMappingForInstanceInRegion(node.getLocation()
Map<String, BlockDevice> devices = instanceClient.getBlockDeviceMappingForInstanceInRegion(node.getLocation()
.getParent().getId(), node.getProviderId());
BlockDevice device = devices.get("/dev/sda1");
//check delete on termination
BlockDevice device = devices.get("/dev/sdn");
// check delete on termination
assertTrue(device.isDeleteOnTermination());
Set<Volume> volumes = ebsClient.describeVolumesInRegion(node
.getLocation().getParent().getId(), device.getVolumeId());
volume = Iterables.getOnlyElement(ebsClient.describeVolumesInRegion(node.getLocation().getParent().getId(),
device.getVolumeId()));
// check volume size
assertEquals(volumeSize, volumes.iterator().next().getSize());
//check volume's snapshot id
assertEquals(snapshot.getId(), volumes.iterator().next().getSnapshotId());
assertEquals(volumeSize, volume.getSize());
device = devices.get("/dev/sdo");
// check delete on termination
assertTrue(device.isDeleteOnTermination());
volume = Iterables.getOnlyElement(ebsClient.describeVolumesInRegion(node.getLocation().getParent().getId(),
device.getVolumeId()));
// check volume size
assertEquals(volumeSize, volume.getSize());
// check volume's snapshot id
assertEquals(snapshot.getId(), volume.getSnapshotId());
} finally {
client.destroyNodesMatching(NodePredicates.withTag(tag));
ebsClient.deleteSnapshotInRegion(snapshot.getRegion(), snapshot.getId());
ebsClient.deleteVolumeInRegion(volume.getRegion(), volume.getId());
if (startedId != null) {
// ensure we didn't delete these resources!
assertEquals(securityGroupClient.describeSecurityGroupsInRegion(null, tag).size(), 1);
}
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
}
}
@Test(enabled = true)
public void testMapEphemeralDeviceToDeviceName() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices();
String tag = this.tag + "BDM3";
TemplateOptions options = client.templateOptions();
options.as(EC2TemplateOptions.class).securityGroups(tag);
options.as(EC2TemplateOptions.class).noKeyPair();
options.as(EC2TemplateOptions.class).mapEphemeralDeviceToDeviceName("/dev/sdh", "ephemeral0");
String startedId = null;
try {
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
// create the security group
securityGroupClient.createSecurityGroupInRegion(null, tag, tag);
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options);
Credentials creds = nodes.iterator().next().getCredentials();
assert creds == null;
NodeMetadata node = nodes.iterator().next();
startedId = node.getId();
Map<String, BlockDevice> devices = instanceClient
.getBlockDeviceMappingForInstanceInRegion(node.getLocation()
.getParent().getId(), node.getProviderId());
BlockDevice device = devices.get("/dev/sdh");
assertNotNull(device);
} finally {
client.destroyNodesMatching(NodePredicates.withTag(tag));
if (startedId != null) {
// ensure we didn't delete these resources!
assertEquals(securityGroupClient.describeSecurityGroupsInRegion(null, tag).size(), 1);
}
cleanupExtendedStuff(securityGroupClient, keyPairClient, tag);
}
}
protected RunningInstance getInstance(InstanceClient instanceClient, String id) {
RunningInstance instance = Iterables.getOnlyElement(Iterables.getOnlyElement(instanceClient
.describeInstancesInRegion(null, id)));

View File

@ -29,14 +29,14 @@ import static org.jclouds.ec2.options.RunInstancesOptions.Builder.withUserData;
import static org.testng.Assert.assertEquals;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.jclouds.ec2.domain.BlockDeviceMapping;
import org.jclouds.ec2.domain.InstanceType;
import org.jclouds.http.options.HttpRequestOptions;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Tests possible uses of RunInstancesOptions and RunInstancesOptions.Builder.*
*
@ -213,11 +213,9 @@ public class RunInstancesOptionsTest {
@Test
public void testWithBlockDeviceMapping() {
RunInstancesOptions options = new RunInstancesOptions();
BlockDeviceMapping mapping = new BlockDeviceMapping("/dev/sda1", null, null, 120, null, true);
Set<BlockDeviceMapping> mappings = new HashSet<BlockDeviceMapping>();
mappings.add(mapping);
options.withBlockDeviceMappings(mappings);
BlockDeviceMapping mapping = new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true);
RunInstancesOptions options = new RunInstancesOptions().withBlockDeviceMappings(ImmutableSet
.<BlockDeviceMapping> of(mapping));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.DeviceName"), Collections
.singletonList("/dev/sda1"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.VolumeSize"), Collections
@ -234,10 +232,9 @@ public class RunInstancesOptionsTest {
@Test
public void testWithBlockDeviceMappingStatic() {
BlockDeviceMapping mapping = new BlockDeviceMapping("/dev/sda1", null, null, 120, null, true);
Set<BlockDeviceMapping> mappings = new HashSet<BlockDeviceMapping>();
mappings.add(mapping);
RunInstancesOptions options = withBlockDeviceMappings(mappings);
BlockDeviceMapping mapping = new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true);
RunInstancesOptions options = withBlockDeviceMappings(ImmutableSet
.<BlockDeviceMapping> of(mapping));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.DeviceName"), Collections
.singletonList("/dev/sda1"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.VolumeSize"), Collections

View File

@ -41,18 +41,6 @@ public class EucalyptusComputeServiceLiveTest extends EC2ComputeServiceLiveTest
tag = "eu";
}
@Override
@Test(enabled = false)
public void testExtendedOptionsAndLogin() throws Exception {
// euc does not support monitoring
}
@Override
@Test(enabled = false)
public void testExtendedOptionsNoKeyPair() throws Exception {
// euc does not support multiple security groups
}
@Override
protected void assertDefaultWorks() {
Template defaultTemplate = client.templateBuilder().build();

View File

@ -19,9 +19,12 @@
package org.jclouds.location.functions;
import static com.google.common.base.Preconditions.checkArgument;
import java.net.URI;
import java.util.Map;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -35,6 +38,7 @@ import com.google.common.base.Function;
*/
@Singleton
public class ZoneToEndpoint implements Function<Object, URI> {
private final Map<String, URI> zoneToEndpoint;
@Inject
@ -42,8 +46,9 @@ public class ZoneToEndpoint implements Function<Object, URI> {
this.zoneToEndpoint = zoneToEndpoint;
}
public URI apply(Object from) {
@Override
public URI apply(@Nullable Object from) {
checkArgument(from != null, "you must specify a zone");
return zoneToEndpoint.get(from);
}
}

View File

@ -102,18 +102,22 @@ public class AWSEC2ComputeService extends EC2ComputeService {
void deletePlacementGroup(String region, String tag) {
Preconditions2.checkNotEmpty(tag, "tag");
String group = String.format("jclouds#%s#%s", tag, region);
try {
if (ec2Client.getPlacementGroupServices().describePlacementGroupsInRegion(region, group).size() > 0) {
logger.debug(">> deleting placementGroup(%s)", group);
try {
ec2Client.getPlacementGroupServices().deletePlacementGroupInRegion(region, group);
checkState(placementGroupDeleted.apply(new PlacementGroup(region, group, "cluster", State.PENDING)), String
.format("placementGroup region(%s) name(%s) failed to delete", region, group));
checkState(placementGroupDeleted.apply(new PlacementGroup(region, group, "cluster", State.PENDING)),
String.format("placementGroup region(%s) name(%s) failed to delete", region, group));
placementGroupMap.remove(new RegionAndName(region, group));
logger.debug("<< deleted placementGroup(%s)", group);
} catch (IllegalStateException e) {
logger.debug("<< inUse placementGroup(%s)", group);
}
}
} catch (UnsupportedOperationException e) {
logger.trace("<< placementGroups unsupported in region %s", region);
}
}
protected void cleanUpIncidentalResources(Entry<String, String> regionTag) {

View File

@ -23,10 +23,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.Arrays;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.BlockDeviceMapping;
import org.jclouds.io.Payload;
import org.jclouds.scriptbuilder.domain.Statement;
import org.jclouds.util.Preconditions2;
@ -98,13 +102,54 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
}
public static class Builder {
/**
* @see EC2TemplateOptions#blockDeviceMappings
*/
public static AWSEC2TemplateOptions blockDeviceMappings(Set<? extends BlockDeviceMapping> blockDeviceMappings) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return options.blockDeviceMappings(blockDeviceMappings);
}
/**
* @see EC2TemplateOptions#mapEBSSnapshotToDeviceName
*/
public static AWSEC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId,
@Nullable Integer sizeInGib, boolean deleteOnTermination) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return options.mapEBSSnapshotToDeviceName(deviceName, snapshotId, sizeInGib, deleteOnTermination);
}
/**
* @see EC2TemplateOptions#mapNewVolumeToDeviceName
*/
public static AWSEC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib,
boolean deleteOnTermination) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return options.mapNewVolumeToDeviceName(deviceName, sizeInGib, deleteOnTermination);
}
/**
* @see EC2TemplateOptions#mapEphemeralDeviceToDeviceName
*/
public static AWSEC2TemplateOptions mapEphemeralDeviceToDeviceName(String deviceName, String virtualName) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return options.mapEphemeralDeviceToDeviceName(deviceName, virtualName);
}
/**
* @see EC2TemplateOptions#unmapDeviceNamed
*/
public static AWSEC2TemplateOptions unmapDeviceNamed(String deviceName) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return options.unmapDeviceNamed(deviceName);
}
/**
* @see AWSEC2TemplateOptions#securityGroups(Iterable<String>)
*/
public static AWSEC2TemplateOptions securityGroups(String... groupIds) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.securityGroups(groupIds));
return options.securityGroups(groupIds);
}
/**
@ -112,7 +157,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions securityGroups(Iterable<String> groupIds) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.securityGroups(groupIds));
return options.securityGroups(groupIds);
}
/**
@ -120,7 +165,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions keyPair(String keyPair) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.keyPair(keyPair));
return options.keyPair(keyPair);
}
/**
@ -128,7 +173,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions userData(byte[] unencodedData) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.userData(unencodedData));
return options.userData(unencodedData);
}
/**
@ -136,7 +181,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions noKeyPair() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.noKeyPair());
return options.noKeyPair();
}
/**
@ -144,7 +189,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions placementGroup(String placementGroup) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.placementGroup(placementGroup));
return options.placementGroup(placementGroup);
}
/**
@ -152,7 +197,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions noPlacementGroup() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.noPlacementGroup());
return options.noPlacementGroup();
}
/**
@ -160,7 +205,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions enableMonitoring() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.enableMonitoring());
return options.enableMonitoring();
}
// methods that only facilitate returning the correct object type
@ -169,7 +214,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions inboundPorts(int... ports) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.inboundPorts(ports));
return options.inboundPorts(ports);
}
/**
@ -177,7 +222,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions blockOnPort(int port, int seconds) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.blockOnPort(port, seconds));
return options.blockOnPort(port, seconds);
}
/**
@ -185,7 +230,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions runScript(byte[] script) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.runScript(script));
return options.runScript(script);
}
/**
@ -193,7 +238,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions installPrivateKey(String rsaKey) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.installPrivateKey(rsaKey));
return options.installPrivateKey(rsaKey);
}
/**
@ -201,7 +246,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions authorizePublicKey(String rsaKey) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.authorizePublicKey(rsaKey));
return options.authorizePublicKey(rsaKey);
}
/**
@ -209,7 +254,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions withDetails() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.withMetadata());
return options.withMetadata();
}
/**
@ -217,12 +262,96 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
*/
public static AWSEC2TemplateOptions subnetId(String subnetId) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return AWSEC2TemplateOptions.class.cast(options.subnetId(subnetId));
return options.subnetId(subnetId);
}
}
// methods that only facilitate returning the correct object type
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions blockDeviceMappings(Set<? extends BlockDeviceMapping> blockDeviceMappings) {
return AWSEC2TemplateOptions.class.cast(super.blockDeviceMappings(blockDeviceMappings));
}
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions keyPair(String keyPair) {
return AWSEC2TemplateOptions.class.cast(super.keyPair(keyPair));
}
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId, Integer sizeInGib,
boolean deleteOnTermination) {
return AWSEC2TemplateOptions.class.cast(super.mapEBSSnapshotToDeviceName(deviceName, snapshotId, sizeInGib,
deleteOnTermination));
}
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions mapEphemeralDeviceToDeviceName(String deviceName, String virtualName) {
return AWSEC2TemplateOptions.class.cast(super.mapEphemeralDeviceToDeviceName(deviceName, virtualName));
}
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib, boolean deleteOnTermination) {
return AWSEC2TemplateOptions.class.cast(super
.mapNewVolumeToDeviceName(deviceName, sizeInGib, deleteOnTermination));
}
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions noKeyPair() {
return AWSEC2TemplateOptions.class.cast(super.noKeyPair());
}
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions securityGroups(Iterable<String> groupIds) {
return AWSEC2TemplateOptions.class.cast(super.securityGroups(groupIds));
}
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions securityGroups(String... groupIds) {
return AWSEC2TemplateOptions.class.cast(super.securityGroups(groupIds));
}
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions unmapDeviceNamed(String deviceName) {
return AWSEC2TemplateOptions.class.cast(super.unmapDeviceNamed(deviceName));
}
/**
* {@inheritDoc}
*/
@Override
public AWSEC2TemplateOptions userData(byte[] unencodedData) {
return AWSEC2TemplateOptions.class.cast(super.userData(unencodedData));
}
/**
* {@inheritDoc}
*/
@ -414,7 +543,7 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions {
@Override
public String toString() {
return "AWSEC2TemplateOptions [groupIds=" + getGroupIds() + ", keyPair=" + getKeyPair() + ", noKeyPair="
return "[groupIds=" + getGroupIds() + ", keyPair=" + getKeyPair() + ", noKeyPair="
+ !shouldAutomaticallyCreateKeyPair() + ", monitoringEnabled=" + monitoringEnabled + ", placementGroup="
+ placementGroup + ", noPlacementGroup=" + noPlacementGroup + ", subnetId=" + subnetId + ", userData="
+ Arrays.toString(getUserData()) + ", blockDeviceMappings=" + getBlockDeviceMappings() + "]";

View File

@ -22,7 +22,6 @@ package org.jclouds.aws.ec2.compute.config;
import static org.jclouds.compute.domain.OsFamily.AMZN_LINUX;
import org.jclouds.aws.ec2.compute.AWSEC2TemplateBuilderImpl;
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
import org.jclouds.aws.ec2.compute.strategy.AWSEC2ReviseParsedImage;
import org.jclouds.aws.ec2.compute.strategy.CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions;
import org.jclouds.aws.ec2.compute.suppliers.AWSEC2HardwareSupplier;
@ -30,7 +29,6 @@ import org.jclouds.aws.ec2.compute.suppliers.AWSRegionAndNameToImageSupplier;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.ec2.compute.config.EC2ComputeServiceContextModule;
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.compute.strategy.CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
import org.jclouds.ec2.compute.strategy.ReviseParsedImage;
import org.jclouds.ec2.compute.suppliers.EC2HardwareSupplier;
@ -58,7 +56,6 @@ public class AWSEC2ComputeServiceContextModule extends EC2ComputeServiceContextM
bind(EC2HardwareSupplier.class).to(AWSEC2HardwareSupplier.class);
bind(RegionAndNameToImageSupplier.class).to(AWSRegionAndNameToImageSupplier.class);
bind(EC2TemplateBuilderImpl.class).to(AWSEC2TemplateBuilderImpl.class);
bind(EC2TemplateOptions.class).to(AWSEC2TemplateOptions.class);
}
@Override

View File

@ -32,6 +32,7 @@ import javax.inject.Singleton;
import org.jclouds.aws.ec2.AWSEC2AsyncClient;
import org.jclouds.aws.ec2.AWSEC2Client;
import org.jclouds.aws.ec2.compute.AWSEC2ComputeService;
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
import org.jclouds.aws.ec2.domain.PlacementGroup;
import org.jclouds.aws.ec2.predicates.PlacementGroupAvailable;
import org.jclouds.aws.ec2.predicates.PlacementGroupDeleted;
@ -48,7 +49,6 @@ import org.jclouds.ec2.compute.functions.CreateSecurityGroupIfNeeded;
import org.jclouds.ec2.compute.functions.CredentialsForInstance;
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
@ -69,7 +69,7 @@ public class AWSEC2ComputeServiceDependenciesModule extends EC2ComputeServiceDep
@Override
protected void configure() {
bind(TemplateBuilder.class).to(EC2TemplateBuilderImpl.class);
bind(TemplateOptions.class).to(EC2TemplateOptions.class);
bind(TemplateOptions.class).to(AWSEC2TemplateOptions.class);
bind(ComputeService.class).to(AWSEC2ComputeService.class);
bind(new TypeLiteral<Function<RunningInstance, NodeMetadata>>() {
}).to(RunningInstanceToNodeMetadata.class);

View File

@ -31,14 +31,14 @@ import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.withUse
import static org.testng.Assert.assertEquals;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.jclouds.ec2.domain.BlockDeviceMapping;
import org.jclouds.ec2.domain.InstanceType;
import org.jclouds.http.options.HttpRequestOptions;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Tests possible uses of AWSRunInstancesOptions and AWSRunInstancesOptions.Builder.*
*
@ -258,14 +258,15 @@ public class AWSRunInstancesOptionsTest {
@Test
public void testWithBlockDeviceMapping() {
AWSRunInstancesOptions options = new AWSRunInstancesOptions();
BlockDeviceMapping mapping = new BlockDeviceMapping("/dev/sda1", null, null, 120, null, true);
Set<BlockDeviceMapping> mappings = new HashSet<BlockDeviceMapping>();
mappings.add(mapping);
options.withBlockDeviceMappings(mappings);
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.DeviceName"), Collections.singletonList("/dev/sda1"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.VolumeSize"), Collections.singletonList("120"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.DeleteOnTermination"), Collections.singletonList("true"));
BlockDeviceMapping mapping = new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true);
AWSRunInstancesOptions options = new AWSRunInstancesOptions().withBlockDeviceMappings(ImmutableSet
.<BlockDeviceMapping> of(mapping));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.DeviceName"), Collections
.singletonList("/dev/sda1"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.VolumeSize"), Collections
.singletonList("120"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.DeleteOnTermination"), Collections
.singletonList("true"));
}
@Test
@ -276,13 +277,14 @@ public class AWSRunInstancesOptionsTest {
@Test
public void testWithBlockDeviceMappingStatic() {
BlockDeviceMapping mapping = new BlockDeviceMapping("/dev/sda1", null, null, 120, null, true);
Set<BlockDeviceMapping> mappings = new HashSet<BlockDeviceMapping>();
mappings.add(mapping);
AWSRunInstancesOptions options = withBlockDeviceMappings(mappings);
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.DeviceName"), Collections.singletonList("/dev/sda1"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.VolumeSize"), Collections.singletonList("120"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.DeleteOnTermination"), Collections.singletonList("true"));
BlockDeviceMapping mapping = new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true);
AWSRunInstancesOptions options = withBlockDeviceMappings(ImmutableSet.<BlockDeviceMapping> of(mapping));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.DeviceName"), Collections
.singletonList("/dev/sda1"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.VolumeSize"), Collections
.singletonList("120"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.DeleteOnTermination"), Collections
.singletonList("true"));
}
@Test(expectedExceptions = NullPointerException.class)