JCLOUDS-602 - Add support for volumeType, iops and encrypted to EBS.

Adds CreateVolumeOptions for volume creation, adds support for the
above EBS configs in Image, Volume, BlockDeviceMapping, etc.

Conflicts:
	apis/ec2/src/main/java/org/jclouds/ec2/xml/CreateVolumeResponseHandler.java
This commit is contained in:
Andrew Bayer 2014-06-19 11:24:29 -07:00
parent bfc000b171
commit 2ba0092817
27 changed files with 942 additions and 120 deletions

View File

@ -189,12 +189,27 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
public EC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId,
@Nullable Integer sizeInGib, boolean deleteOnTermination) {
blockDeviceMappings.add(new MapEBSSnapshotToDevice(deviceName, snapshotId, sizeInGib, deleteOnTermination));
return mapEBSSnapshotToDeviceName(deviceName, snapshotId, sizeInGib, deleteOnTermination, null, null, false);
}
public EC2TemplateOptions mapEBSSnapshotToDeviceName(String deviceName, String snapshotId,
@Nullable Integer sizeInGib, boolean deleteOnTermination,
@Nullable String volumeType, @Nullable Integer iops,
boolean encrypted) {
blockDeviceMappings.add(new MapEBSSnapshotToDevice(deviceName, snapshotId, sizeInGib, deleteOnTermination,
volumeType, iops, encrypted));
return this;
}
public EC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib, boolean deleteOnTermination) {
blockDeviceMappings.add(new MapNewVolumeToDevice(deviceName, sizeInGib, deleteOnTermination));
return mapNewVolumeToDeviceName(deviceName, sizeInGib, deleteOnTermination, null, null, false);
}
public EC2TemplateOptions mapNewVolumeToDeviceName(String deviceName, int sizeInGib, boolean deleteOnTermination,
@Nullable String volumeType, @Nullable Integer iops,
boolean encrypted) {
blockDeviceMappings.add(new MapNewVolumeToDevice(deviceName, sizeInGib, deleteOnTermination, volumeType,
iops, encrypted));
return this;
}

View File

@ -38,6 +38,9 @@ public class BlockDeviceMapping implements Comparable<BlockDeviceMapping> {
private Integer sizeInGib;
private Boolean noDevice;
private Boolean deleteOnTermination;
private String volumeType;
private Integer iops;
private Boolean encrypted;
public Builder deviceName(String deviceName) {
this.deviceName = deviceName;
@ -69,8 +72,24 @@ public class BlockDeviceMapping implements Comparable<BlockDeviceMapping> {
return this;
}
public Builder volumeType(String volumeType) {
this.volumeType = volumeType;
return this;
}
public Builder iops(Integer iops) {
this.iops = iops;
return this;
}
public Builder encrypted(Boolean encrypted) {
this.encrypted = encrypted;
return this;
}
public BlockDeviceMapping build() {
return new BlockDeviceMapping(deviceName, virtualName, snapshotId, sizeInGib, noDevice, deleteOnTermination);
return new BlockDeviceMapping(deviceName, virtualName, snapshotId, sizeInGib, noDevice, deleteOnTermination,
volumeType, iops, encrypted);
}
public Builder clear() {
@ -80,6 +99,9 @@ public class BlockDeviceMapping implements Comparable<BlockDeviceMapping> {
this.sizeInGib = null;
this.noDevice = null;
this.deleteOnTermination = null;
this.volumeType = null;
this.iops = null;
this.encrypted = null;
return this;
}
}
@ -90,13 +112,17 @@ public class BlockDeviceMapping implements Comparable<BlockDeviceMapping> {
private final Integer sizeInGib;
private final Boolean noDevice;
private final Boolean deleteOnTermination;
private final String volumeType;
private final Integer iops;
private final Boolean encrypted;
// values expressed in GB
private static final Integer VOLUME_SIZE_MIN_VALUE = 1;
private static final Integer VOLUME_SIZE_MAX_VALUE = 1000;
BlockDeviceMapping(String deviceName, @Nullable String virtualName, @Nullable String snapshotId,
@Nullable Integer sizeInGib, @Nullable Boolean noDevice, @Nullable Boolean deleteOnTermination) {
@Nullable Integer sizeInGib, @Nullable Boolean noDevice, @Nullable Boolean deleteOnTermination,
@Nullable String volumeType, @Nullable Integer iops, @Nullable Boolean encrypted) {
checkNotNull(deviceName, "deviceName cannot be null");
checkNotNull(emptyToNull(deviceName), "deviceName must be defined");
@ -111,6 +137,9 @@ public class BlockDeviceMapping implements Comparable<BlockDeviceMapping> {
this.sizeInGib = sizeInGib;
this.noDevice = noDevice;
this.deleteOnTermination = deleteOnTermination;
this.volumeType = volumeType;
this.iops = iops;
this.encrypted = encrypted;
}
public String getDeviceName() {
@ -137,6 +166,18 @@ public class BlockDeviceMapping implements Comparable<BlockDeviceMapping> {
return deleteOnTermination;
}
public String getEbsVolumeType() {
return volumeType;
}
public Integer getEbsIops() {
return iops;
}
public Boolean getEbsEncrypted() {
return encrypted;
}
@Override
public int hashCode() {
final int prime = 31;
@ -147,6 +188,9 @@ public class BlockDeviceMapping implements Comparable<BlockDeviceMapping> {
result = prime * result + ((sizeInGib == null) ? 0 : sizeInGib.hashCode());
result = prime * result + ((snapshotId == null) ? 0 : snapshotId.hashCode());
result = prime * result + ((virtualName == null) ? 0 : virtualName.hashCode());
result = prime * result + ((volumeType == null) ? 0 : volumeType.hashCode());
result = prime * result + ((iops == null) ? 0 : iops.hashCode());
result = prime * result + ((encrypted == null ) ? 0 : encrypted.hashCode());
return result;
}
@ -189,41 +233,59 @@ public class BlockDeviceMapping implements Comparable<BlockDeviceMapping> {
return false;
} else if (!virtualName.equals(other.virtualName))
return false;
if (volumeType == null) {
if (other.volumeType != null)
return false;
} else if (!volumeType.equals(other.volumeType))
return false;
if (iops== null) {
if (other.iops != null)
return false;
} else if (!iops.equals(other.iops))
return false;
if (encrypted == null) {
if (other.encrypted != null)
return false;
} else if (!encrypted.equals(other.encrypted))
return false;
return true;
}
@Override
public String toString() {
return "[deviceName=" + deviceName + ", virtualName=" + virtualName + ", snapshotId=" + snapshotId
+ ", sizeInGib=" + sizeInGib + ", noDevice=" + noDevice + ", deleteOnTermination=" + deleteOnTermination
+ "]";
+ ", sizeInGib=" + sizeInGib + ", noDevice=" + noDevice + ", deleteOnTermination=" + deleteOnTermination
+ ", volumeType=" + volumeType + ", iops=" + iops + ", encrypted=" + encrypted
+ "]";
}
public static class MapEBSSnapshotToDevice extends BlockDeviceMapping {
public MapEBSSnapshotToDevice(String deviceName, String snapshotId, @Nullable Integer sizeInGib,
@Nullable Boolean deleteOnTermination) {
super(deviceName, null, snapshotId, sizeInGib, null, deleteOnTermination);
@Nullable Boolean deleteOnTermination, @Nullable String volumeType,
@Nullable Integer iops, @Nullable Boolean encrypted) {
super(deviceName, null, snapshotId, sizeInGib, null, deleteOnTermination, volumeType, iops, encrypted);
checkNotNull(emptyToNull(snapshotId), "snapshotId must be defined");
}
}
public static class MapNewVolumeToDevice extends BlockDeviceMapping {
public MapNewVolumeToDevice(String deviceName, Integer sizeInGib, @Nullable Boolean deleteOnTermination) {
super(deviceName, null, null, sizeInGib, null, deleteOnTermination);
public MapNewVolumeToDevice(String deviceName, Integer sizeInGib, @Nullable Boolean deleteOnTermination,
@Nullable String volumeType, @Nullable Integer iops, @Nullable Boolean encrypted) {
super(deviceName, null, null, sizeInGib, null, deleteOnTermination, volumeType, iops, encrypted);
checkNotNull(sizeInGib, "sizeInGib cannot be null");
}
}
public static class MapEphemeralDeviceToDevice extends BlockDeviceMapping {
public MapEphemeralDeviceToDevice(String deviceName, String virtualName) {
super(deviceName, virtualName, null, null, null, null);
super(deviceName, virtualName, null, null, null, null, null, null, null);
checkNotNull(emptyToNull(virtualName), "virtualName must be defined");
}
}
public static class UnmapDeviceNamed extends BlockDeviceMapping {
public UnmapDeviceNamed(String deviceName) {
super(deviceName, null, null, null, true, null);
super(deviceName, null, null, null, true, null, null, null, null);
}
}

View File

@ -160,11 +160,18 @@ public class Image implements Comparable<Image> {
private final String snapshotId;
private final long volumeSize;
private final boolean deleteOnTermination;
private final String volumeType;
private final Integer iops;
private final boolean encrypted;
public EbsBlockDevice(@Nullable String snapshotId, long volumeSize, boolean deleteOnTermination) {
public EbsBlockDevice(@Nullable String snapshotId, long volumeSize, boolean deleteOnTermination,
@Nullable String volumeType, @Nullable Integer iops, boolean encrypted) {
this.snapshotId = snapshotId;
this.volumeSize = volumeSize;
this.deleteOnTermination = deleteOnTermination;
this.volumeType = volumeType;
this.iops = iops;
this.encrypted = encrypted;
}
public String getSnapshotId() {
@ -179,6 +186,18 @@ public class Image implements Comparable<Image> {
return deleteOnTermination;
}
public String getVolumeType() {
return volumeType;
}
public Integer getIops() {
return iops;
}
public boolean isEncrypted() {
return encrypted;
}
@Override
public int hashCode() {
final int prime = 31;
@ -186,6 +205,9 @@ public class Image implements Comparable<Image> {
result = prime * result + (deleteOnTermination ? 1231 : 1237);
result = prime * result + ((snapshotId == null) ? 0 : snapshotId.hashCode());
result = prime * result + (int) (volumeSize ^ (volumeSize >>> 32));
result = prime * result + (encrypted ? 1249 : 1259);
result = prime * result + ((volumeType == null) ? 0 : volumeType.hashCode());
result = prime * result + ((iops == null) ? 0 : iops.hashCode());
return result;
}
@ -200,11 +222,23 @@ public class Image implements Comparable<Image> {
EbsBlockDevice other = (EbsBlockDevice) obj;
if (deleteOnTermination != other.deleteOnTermination)
return false;
if (encrypted != other.encrypted)
return false;
if (snapshotId == null) {
if (other.snapshotId != null)
return false;
} else if (!snapshotId.equals(other.snapshotId))
return false;
if (volumeType == null) {
if (other.volumeType != null)
return false;
} else if (!volumeType.equals(other.volumeType))
return false;
if (iops == null) {
if (other.iops != null)
return false;
} else if (!iops.equals(other.iops))
return false;
if (volumeSize != other.volumeSize)
return false;
return true;
@ -213,7 +247,8 @@ public class Image implements Comparable<Image> {
@Override
public String toString() {
return "EbsBlockDevice [deleteOnTermination=" + deleteOnTermination + ", snapshotId=" + snapshotId
+ ", volumeSize=" + volumeSize + "]";
+ ", volumeSize=" + volumeSize + ", volumeType=" + volumeType + ", iops=" + iops
+ ", encrypted=" + encrypted + "]";
}
}

View File

@ -100,6 +100,11 @@ public class Volume implements Comparable<Volume> {
private Status status;
private Date createTime;
private Set<Attachment> attachments = ImmutableSet.of();
@Nullable
private String volumeType;
@Nullable
private Integer iops;
private boolean encrypted = false;
public Builder region(String region) {
this.region = region;
@ -145,15 +150,31 @@ public class Volume implements Comparable<Volume> {
this.attachments = ImmutableSet.copyOf(attachments);
return this;
}
public Builder volumeType(String volumeType) {
this.volumeType = volumeType;
return this;
}
public Builder iops(Integer iops) {
this.iops = iops;
return this;
}
public Builder encrypted(boolean encrypted) {
this.encrypted = encrypted;
return this;
}
public Volume build() {
return new Volume(region, id, size, snapshotId, availabilityZone, status, createTime, attachments);
return new Volume(region, id, size, snapshotId, availabilityZone, status, createTime,
volumeType, iops, encrypted, attachments);
}
public Builder fromVolume(Volume in) {
return region(in.region).id(in.id).size(in.size).snapshotId(in.snapshotId)
.availabilityZone(in.availabilityZone).status(in.status).createTime(in.createTime)
.attachments(in.attachments);
.volumeType(in.volumeType).iops(in.iops).encrypted(in.encrypted).attachments(in.attachments);
}
}
@ -167,8 +188,14 @@ public class Volume implements Comparable<Volume> {
private final Date createTime;
private final Set<Attachment> attachments;
@Nullable
private final String volumeType;
@Nullable
private final Integer iops;
private final boolean encrypted;
public Volume(String region, String id, int size, String snapshotId, String availabilityZone, Volume.Status status,
Date createTime, Iterable<Attachment> attachments) {
Date createTime, String volumeType, Integer iops, boolean encrypted, Iterable<Attachment> attachments) {
this.region = checkNotNull(region, "region");
this.id = id;
this.size = size;
@ -176,6 +203,9 @@ public class Volume implements Comparable<Volume> {
this.availabilityZone = availabilityZone;
this.status = status;
this.createTime = createTime;
this.volumeType = volumeType;
this.iops = iops;
this.encrypted = encrypted;
this.attachments = ImmutableSet.copyOf(attachments);
}
@ -214,6 +244,18 @@ public class Volume implements Comparable<Volume> {
return createTime;
}
public String getVolumeType() {
return volumeType;
}
public Integer getIops() {
return iops;
}
public boolean getEncrypted() {
return encrypted;
}
public Set<Attachment> getAttachments() {
return attachments;
}
@ -230,7 +272,10 @@ public class Volume implements Comparable<Volume> {
result = prime * result + size;
result = prime * result + ((snapshotId == null) ? 0 : snapshotId.hashCode());
result = prime * result + ((status == null) ? 0 : status.hashCode());
return result;
result = prime * result + ((volumeType == null) ? 0 : volumeType.hashCode());
result = prime * result + ((iops == null) ? 0 : iops.hashCode());
result = prime * result + (encrypted ? 1249 : 1259);
return result;
}
@Override
@ -279,6 +324,18 @@ public class Volume implements Comparable<Volume> {
return false;
} else if (!status.equals(other.status))
return false;
if (volumeType == null) {
if (other.volumeType != null)
return false;
} else if (!volumeType.equals(other.volumeType))
return false;
if (iops == null) {
if (other.iops != null)
return false;
} else if (!iops.equals(other.iops))
return false;
if (encrypted != other.encrypted)
return false;
return true;
}
@ -290,7 +347,8 @@ public class Volume implements Comparable<Volume> {
@Override
public String toString() {
return "Volume [attachments=" + attachments + ", availabilityZone=" + availabilityZone + ", createTime="
+ createTime + ", id=" + id + ", region=" + region + ", size=" + size + ", snapshotId=" + snapshotId
+ ", status=" + status + "]";
+ createTime + ", id=" + id + ", region=" + region + ", size=" + size + ", snapshotId=" + snapshotId
+ ", status=" + status + ", volumeType=" + volumeType + ", iops=" + iops + ", encrypted=" + encrypted
+"]";
}
}

View File

@ -37,6 +37,7 @@ import org.jclouds.ec2.domain.Permission;
import org.jclouds.ec2.domain.Snapshot;
import org.jclouds.ec2.domain.Volume;
import org.jclouds.ec2.options.CreateSnapshotOptions;
import org.jclouds.ec2.options.CreateVolumeOptions;
import org.jclouds.ec2.options.DescribeSnapshotsOptions;
import org.jclouds.ec2.options.DetachVolumeOptions;
import org.jclouds.ec2.xml.AttachmentHandler;
@ -166,6 +167,36 @@ public interface ElasticBlockStoreApi {
@EndpointParam(parser = ZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
@FormParam("Size") int size);
/**
* Creates a new Amazon EBS volume to which any Amazon EC2 instance can attach within the same
* Availability Zone. For more information about Amazon EBS, go to the Amazon Elastic Compute
* Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
*
* @param availabilityZone
* An Amazon EBS volume must be located within the same Availability Zone as the
* instance to which it attaches.
* @param options
* options like specifying a snapshot, EBS volume type, etc
*
*
* @see #describeVolumesInRegion
* @see #deleteVolumeInRegion
* @see #attachVolumeInRegion
* @see #detachVolumeInRegion
* @see AvailabilityZoneAndRegionApi#describeAvailabilityZonesInRegion
* @see <a href=
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateVolume.html"
* />
*/
@Named("CreateVolume")
@POST
@Path("/")
@FormParams(keys = ACTION, values = "CreateVolume")
@XMLResponseParser(CreateVolumeResponseHandler.class)
Volume createVolumeInAvailabilityZone(
@EndpointParam(parser = ZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
CreateVolumeOptions... options);
/**
* Describes the specified Amazon EBS volumes that you own. If you do not specify one or more
* volume IDs, Amazon EBS describes all volumes that you own. For more information about Amazon

View File

@ -0,0 +1,146 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.ec2.options;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
/**
* Contains options supported in the Form API for the CreateVolume operation. <h2>
* Usage</h2> The recommended way to instantiate a CreateVolumeOptions object is to statically
* import CreateVolumeOptions.Builder.* and invoke a static creation method followed by an
* instance mutator (if needed):
* <p/>
* <code>
* import static org.jclouds.ec2.options.CreateVolumeOptions.Builder.*
* <p/>
* EC2Api connection = // get connection
* Volume volume = connection.getElasticBlockStoreApi().get().createVolumeInAvailabilityZone(availabilityZone, fromSnapshotId("123125"));
* <code>
*
* @see <a
* href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/ApiReference-query-CreateVolume.html"
* />
*/
public class CreateVolumeOptions extends BaseEC2RequestOptions {
/**
* Snapshot ID to create this volume from.
*/
public CreateVolumeOptions withSize(int size) {
formParameters.put("Size", Integer.toString(size));
return this;
}
public int getSize() {
return Integer.parseInt(getFirstFormOrNull("Size"));
}
/**
* Snapshot ID to create this volume from.
*/
public CreateVolumeOptions fromSnapshotId(String snapshotId) {
formParameters.put("SnapshotId", checkNotNull(snapshotId, "snapshotId"));
return this;
}
public String getSnapshotId() {
return getFirstFormOrNull("SnapshotId");
}
/**
* EBS volume type to use - if not specified, will be "standard".
*/
public CreateVolumeOptions volumeType(String volumeType) {
formParameters.put("VolumeType", checkNotNull(volumeType, "volumeType"));
return this;
}
public String getVolumeType() {
return getFirstFormOrNull("VolumeType");
}
/**
* EBS provisioned IOPS
*/
public CreateVolumeOptions withIops(Integer iops) {
formParameters.put("Iops", checkNotNull(iops, "iops").toString());
return this;
}
public Integer getIops() {
return Integer.valueOf(getFirstFormOrNull("Iops"));
}
/**
* Should this EBS volume be encrypted?
*/
public CreateVolumeOptions isEncrypted(boolean encrypted) {
if (encrypted)
formParameters.put("Encrypted", "true");
return this;
}
public boolean getEncrypted() {
return Boolean.parseBoolean(getFirstFormOrNull("Encrypted"));
}
public static class Builder {
/**
* @see CreateVolumeOptions#fromSnapshotId(String)
*/
public static CreateVolumeOptions fromSnapshotId(String snapshotId) {
CreateVolumeOptions options = new CreateVolumeOptions();
return options.fromSnapshotId(snapshotId);
}
/**
* @see CreateVolumeOptions#withSize(int)
*/
public static CreateVolumeOptions withSize(int size) {
CreateVolumeOptions options = new CreateVolumeOptions();
return options.withSize(size);
}
/**
* @see CreateVolumeOptions#volumeType(String)
*/
public static CreateVolumeOptions volumeType(String volumeType) {
CreateVolumeOptions options = new CreateVolumeOptions();
return options.volumeType(volumeType);
}
/**
* @see CreateVolumeOptions#withIops(Integer)
*/
public static CreateVolumeOptions withIops(Integer iops) {
CreateVolumeOptions options = new CreateVolumeOptions();
return options.withIops(iops);
}
/**
* @see CreateVolumeOptions#isEncrypted(boolean)
*/
public static CreateVolumeOptions isEncrypted(boolean encrypted) {
CreateVolumeOptions options = new CreateVolumeOptions();
return options.isEncrypted(encrypted);
}
}
}

View File

@ -95,9 +95,90 @@ public class RegisterImageBackedByEbsOptions extends RegisterImageOptions {
/**
*
* adds a block device to the image from an ebs snapshot.
*
* @param deviceName
* The device name (e.g., /dev/sdh).
* @param virtualName
* The virtual device name. (nullable)
* @param snapshotId
* The ID of the snapshot.
* @param deleteOnTermination
* Whether this volume should be automatically deleted on instance termination.
* Defaults to false.
* @param volumeType
* What EBS volume type should be used.
* @param iops
* EBS provisioned IOPS for this volume.
* @param encrypted
* Whether this volume should be encrypted.
*/
public RegisterImageBackedByEbsOptions addBlockDeviceFromSnapshot(String deviceName,
@Nullable String virtualName, String snapshotId, boolean deleteOnTermination,
@Nullable String volumeType, @Nullable Integer iops, boolean encrypted) {
addAdvancedEbsOptions(deleteOnTermination, volumeType, iops, encrypted);
addEphemeralBlockDeviceFromSnapshot(deviceName, virtualName, snapshotId);
return this;
}
/**
*
* adds a new block device to the image.
*
* @param deviceName
* The device name (e.g., /dev/sdh).
* @param virtualName
* The virtual device name. (nullable)
* @param volumeSize
* The size of the volume, in GiBs..
* @param deleteOnTermination
* Whether this volume should be automatically deleted on instance termination.
* Defaults to false.
* @param volumeType
* What EBS volume type should be used.
* @param iops
* EBS provisioned IOPS for this volume.
* @param encrypted
* Whether this volume should be encrypted.
*/
public RegisterImageBackedByEbsOptions addNewBlockDevice(String deviceName,
@Nullable String virtualName,
int volumeSize,
boolean deleteOnTermination,
@Nullable String volumeType,
@Nullable Integer iops,
boolean encrypted) {
addAdvancedEbsOptions(deleteOnTermination, volumeType, iops, encrypted);
addNewEphemeralBlockDevice(deviceName, virtualName, volumeSize);
return this;
}
private RegisterImageBackedByEbsOptions addAdvancedEbsOptions(boolean deleteOnTermination,
@Nullable String volumeType,
@Nullable Integer iops,
boolean encrypted) {
formParameters.put("BlockDeviceMapping." + deviceIndex + ".Ebs.DeleteOnTermination",
Boolean.toString(deleteOnTermination));
if (volumeType != null)
formParameters.put("BlockDeviceMapping." + deviceIndex + ".Ebs.VolumeType", volumeType);
if (iops != null)
formParameters.put("BlockDeviceMapping." + deviceIndex + ".Ebs.Iops", iops.toString());
if (encrypted)
formParameters.put("BlockDeviceMapping." + deviceIndex + ".Ebs.Encrypted", "true");
return this;
}
/**
*
* adds a block device to the image from an ebs snapshot. This device is retained on instance
* termination.
*
*
* @param name
* The device name (e.g., /dev/sdh).
* @param virtualName
@ -106,7 +187,7 @@ public class RegisterImageBackedByEbsOptions extends RegisterImageOptions {
* The ID of the snapshot.
*/
public RegisterImageBackedByEbsOptions addBlockDeviceFromSnapshot(String deviceName,
@Nullable String virtualName, String snapshotId) {
@Nullable String virtualName, String snapshotId) {
formParameters.put("BlockDeviceMapping." + deviceIndex + ".Ebs.DeleteOnTermination", "false");
addEphemeralBlockDeviceFromSnapshot(deviceName, virtualName, snapshotId);
return this;
@ -172,6 +253,21 @@ public class RegisterImageBackedByEbsOptions extends RegisterImageOptions {
return options.addBlockDeviceFromSnapshot(deviceName, virtualName, snapshotId);
}
/**
* @see RegisterImageBackedByEbsOptions#addBlockDeviceFromSnapshot(String, String, String, boolean, String, Integer, boolean)
*/
public static RegisterImageBackedByEbsOptions addBlockDeviceFromSnapshot(String deviceName,
@Nullable String virtualName,
String snapshotId,
boolean deleteOnTermination,
@Nullable String volumeType,
@Nullable Integer iops,
boolean encrypted) {
RegisterImageBackedByEbsOptions options = new RegisterImageBackedByEbsOptions();
return options.addBlockDeviceFromSnapshot(deviceName, virtualName, snapshotId, deleteOnTermination,
volumeType, iops, encrypted);
}
/**
* @see RegisterImageBackedByEbsOptions#addEphemeralBlockDeviceFromSnapshot(String, String,
* String)
@ -191,6 +287,21 @@ public class RegisterImageBackedByEbsOptions extends RegisterImageOptions {
return options.addNewBlockDevice(deviceName, virtualName, volumeSize);
}
/**
* @see RegisterImageBackedByEbsOptions#addNewBlockDevice(String, String, int, boolean, String, Integer, boolean)
*/
public static RegisterImageBackedByEbsOptions addNewBlockDevice(String deviceName,
@Nullable String virtualName,
int volumeSize,
boolean deleteOnTermination,
@Nullable String volumeType,
@Nullable Integer iops,
boolean encrypted) {
RegisterImageBackedByEbsOptions options = new RegisterImageBackedByEbsOptions();
return options.addNewBlockDevice(deviceName, virtualName, volumeSize, deleteOnTermination,
volumeType, iops, encrypted);
}
/**
* @see RegisterImageBackedByEbsOptions#addNewEphemeralBlockDevice(String, String, int)
*/

View File

@ -140,6 +140,13 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
if (mapping.getEbsDeleteOnTermination() != null)
formParameters.put(String.format("BlockDeviceMapping.%d.Ebs.DeleteOnTermination", i),
String.valueOf(mapping.getEbsDeleteOnTermination()));
if (mapping.getEbsVolumeType() != null)
formParameters.put(String.format("BlockDeviceMapping.%d.Ebs.VolumeType", i), mapping.getEbsVolumeType());
if (mapping.getEbsIops() != null)
formParameters.put(String.format("BlockDeviceMapping.%d.Ebs.Iops", i),
String.valueOf(mapping.getEbsIops()));
if (mapping.getEbsEncrypted() != null)
formParameters.put(String.format("BlockDeviceMapping.%d.Ebs.Encrypted", i), String.valueOf(mapping.getEbsEncrypted()));
i++;
}
return this;
@ -180,7 +187,7 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
}
/**
* @see RunInstancesOptions#asType(InstanceType)
* @see RunInstancesOptions#asType(String)
*/
public static RunInstancesOptions asType(String instanceType) {
RunInstancesOptions options = new RunInstancesOptions();

View File

@ -18,13 +18,16 @@ package org.jclouds.ec2.xml;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.inject.Inject;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.date.DateCodec;
import org.jclouds.date.DateCodecFactory;
@ -42,10 +45,6 @@ import com.google.common.base.Suppliers;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
*
* @author Adrian Cole
*/
public class CreateVolumeResponseHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Volume> {
protected final DateCodec dateCodec;
protected final Supplier<String> defaultRegion;
@ -77,6 +76,9 @@ public class CreateVolumeResponseHandler extends ParseSax.HandlerForGeneratedReq
protected String device;
protected Attachment.Status attachmentStatus;
protected Date attachTime;
protected String volumeType;
protected Integer iops;
protected boolean encrypted;
protected boolean inAttachmentSet;
@ -129,6 +131,14 @@ public class CreateVolumeResponseHandler extends ParseSax.HandlerForGeneratedReq
device = currentText.toString().trim();
} else if (qName.equals("attachTime")) {
attachTime = dateCodec.toDate(currentText.toString().trim());
} else if (qName.equals("volumeType")) {
volumeType = currentText.toString().trim();
if (volumeType.equals(""))
volumeType = null;
} else if (qName.equals("iops")) {
iops = Integer.parseInt(currentText.toString().trim());
} else if (qName.equals("encrypted")) {
encrypted = Boolean.parseBoolean(currentText.toString().trim());
} else if (qName.equals("item")) {
if (inAttachmentSet) {
attachments.add(new Attachment(region, volumeId, instanceId, device, attachmentStatus, attachTime));
@ -144,7 +154,8 @@ public class CreateVolumeResponseHandler extends ParseSax.HandlerForGeneratedReq
}
private Volume newVolume() {
Volume volume = new Volume(region, id, size, snapshotId, availabilityZone, volumeStatus, createTime, attachments);
Volume volume = new Volume(region, id, size, snapshotId, availabilityZone, volumeStatus, createTime,
volumeType, iops, encrypted, attachments);
id = null;
size = 0;
snapshotId = null;
@ -152,6 +163,9 @@ public class CreateVolumeResponseHandler extends ParseSax.HandlerForGeneratedReq
volumeStatus = null;
createTime = null;
attachments = Sets.newLinkedHashSet();
volumeType = null;
iops = null;
encrypted = false;
return volume;
}

View File

@ -19,29 +19,27 @@ package org.jclouds.ec2.xml;
import static org.jclouds.util.SaxUtils.currentOrNull;
import static org.jclouds.util.SaxUtils.equalsOrSuffix;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.ec2.domain.Hypervisor;
import org.jclouds.ec2.domain.Image;
import org.jclouds.ec2.domain.RootDeviceType;
import org.jclouds.ec2.domain.VirtualizationType;
import org.jclouds.ec2.domain.Image.Architecture;
import org.jclouds.ec2.domain.Image.EbsBlockDevice;
import org.jclouds.ec2.domain.Image.ImageState;
import org.jclouds.ec2.domain.Image.ImageType;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.location.Region;
import org.jclouds.logging.Logger;
import org.xml.sax.Attributes;
import java.util.Map;
import java.util.Set;
import com.google.common.base.Supplier;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.ec2.domain.Hypervisor;
import org.jclouds.ec2.domain.Image;
import org.jclouds.ec2.domain.Image.Architecture;
import org.jclouds.ec2.domain.Image.EbsBlockDevice;
import org.jclouds.ec2.domain.Image.ImageState;
import org.jclouds.ec2.domain.Image.ImageType;
import org.jclouds.ec2.domain.RootDeviceType;
import org.jclouds.ec2.domain.VirtualizationType;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.location.Region;
import org.jclouds.logging.Logger;
import org.xml.sax.Attributes;
/**
* Parses the following XML document:
@ -95,7 +93,9 @@ public class DescribeImagesResponseHandler extends ParseSax.HandlerForGeneratedR
private int volumeSize;
private boolean deleteOnTermination = true;// correct default is true.
private boolean encrypted = false;
private String volumeType;
private Integer iops;
private String rootDeviceName;
public Set<Image> getResult() {
@ -160,6 +160,12 @@ public class DescribeImagesResponseHandler extends ParseSax.HandlerForGeneratedR
volumeSize = Integer.parseInt(currentText.toString().trim());
} else if (qName.equals("deleteOnTermination")) {
deleteOnTermination = Boolean.parseBoolean(currentText.toString().trim());
} else if (qName.equals("encrypted")) {
encrypted = Boolean.parseBoolean(currentText.toString().trim());
} else if (qName.equals("iops")) {
iops = Integer.valueOf(currentText.toString().trim());
} else if (qName.equals("volumeType")) {
volumeType = currentText.toString().trim();
} else if (qName.equals("ramdiskId")) {
ramdiskId = currentText.toString().trim();
} else if (qName.equals("rootDeviceType")) {
@ -172,11 +178,15 @@ public class DescribeImagesResponseHandler extends ParseSax.HandlerForGeneratedR
hypervisor = Hypervisor.fromValue(currentText.toString().trim());
} else if (qName.equals("item")) {
if (inBlockDeviceMapping) {
ebsBlockDevices.put(deviceName, new Image.EbsBlockDevice(snapshotId, volumeSize, deleteOnTermination));
ebsBlockDevices.put(deviceName, new Image.EbsBlockDevice(snapshotId, volumeSize, deleteOnTermination,
volumeType, iops, encrypted));
this.deviceName = null;
this.snapshotId = null;
this.volumeSize = 0;
this.deleteOnTermination = true;
this.encrypted = false;
this.volumeType = null;
this.iops = null;
} else if (!inTagSet && !inProductCodes) {
try {
String region = getRequest() != null ? AWSUtils.findRegionInArgsOrNull(getRequest()) : null;

View File

@ -398,7 +398,7 @@ public class EBSBootEC2ApiLiveTest extends BaseComputeServiceContextLiveTest {
assertEquals(ebsImage.getRootDeviceType(), RootDeviceType.EBS);
assertEquals(ebsImage.getRootDeviceName(), "/dev/sda1");
assertEquals(ebsImage.getEbsBlockDevices().entrySet(),
ImmutableMap.of("/dev/sda1", new Image.EbsBlockDevice(snapshot.getId(), VOLUME_SIZE, true)).entrySet());
ImmutableMap.of("/dev/sda1", new Image.EbsBlockDevice(snapshot.getId(), VOLUME_SIZE, true, "standard", null, false)).entrySet());
}
private void tryToChangeStuff() {

View File

@ -184,7 +184,7 @@ public class AMIApiLiveTest extends BaseComputeServiceContextLiveTest {
// Register a new image...
ebsBackedImageId = client.registerUnixImageBackedByEbsInRegion(regionId, ebsBackedImageName, snapshot.getId(),
addNewBlockDevice("/dev/sda2", "myvirtual", 1).withDescription("adrian"));
addNewBlockDevice("/dev/sda2", "myvirtual", 1, false, "gp2", null, false).withDescription("adrian"));
imagesToDeregister.add(ebsBackedImageId);
final Image ebsBackedImage = getOnlyElement(client.describeImagesInRegion(regionId, imageIds(ebsBackedImageId)));
assertEquals(ebsBackedImage.getName(), ebsBackedImageName);
@ -194,8 +194,8 @@ public class AMIApiLiveTest extends BaseComputeServiceContextLiveTest {
assertEquals(ebsBackedImage.getDescription(), "adrian");
assertEquals(
ebsBackedImage.getEbsBlockDevices().entrySet(),
ImmutableMap.of("/dev/sda1", new Image.EbsBlockDevice(snapshot.getId(), snapshot.getVolumeSize(), true),
"/dev/sda2", new Image.EbsBlockDevice(null, 1, false)).entrySet());
ImmutableMap.of("/dev/sda1", new Image.EbsBlockDevice(snapshot.getId(), snapshot.getVolumeSize(), true, "standard", null, false),
"/dev/sda2", new Image.EbsBlockDevice(null, 1, false, "gp2", null, false)).entrySet());
// List of images after - should be one larger than before
int after = client.describeImagesInRegionWithFilter(regionId,

View File

@ -23,6 +23,7 @@ import org.jclouds.ec2.EC2Api;
import org.jclouds.ec2.domain.Snapshot;
import org.jclouds.ec2.domain.Volume;
import org.jclouds.ec2.internal.BaseEC2ApiExpectTest;
import org.jclouds.ec2.options.CreateVolumeOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.ResourceNotFoundException;
@ -39,14 +40,16 @@ import com.google.common.collect.ImmutableSet;
@Test(groups = "unit", testName = "EC2ElasticBlockStoreApiExpectTest")
public class EC2ElasticBlockStoreApiExpectTest extends BaseEC2ApiExpectTest<EC2Api> {
Volume creating = Volume.builder()
.id("vol-2a21e543")
.status(Volume.Status.CREATING)
.availabilityZone("us-east-1a")
.region("us-east-1")
.id("vol-2a21e543")
.size(1)
.createTime(dateService.iso8601DateParse("2009-12-28T05:42:53.000Z"))
.build();
.id("vol-2a21e543")
.status(Volume.Status.CREATING)
.availabilityZone("us-east-1a")
.region("us-east-1")
.id("vol-2a21e543")
.volumeType("standard")
.iops(0)
.size(1)
.createTime(dateService.iso8601DateParse("2009-12-28T05:42:53.000Z"))
.build();
public void testCreateVolumeInAvailabilityZone() {
Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse>builder();
@ -66,7 +69,38 @@ public class EC2ElasticBlockStoreApiExpectTest extends BaseEC2ApiExpectTest<EC2A
assertEquals(client.createVolumeInAvailabilityZone("us-east-1a", 4), creating);
}
public void testCreateVolumeInAvailabilityZoneWithOptions() {
Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse>builder();
builder.put(describeRegionsRequest, describeRegionsResponse);
builder.putAll(describeAvailabilityZonesRequestResponse);
builder.put(
HttpRequest.builder()
.method("POST")
.endpoint("https://ec2.us-east-1.amazonaws.com/")
.addHeader("Host", "ec2.us-east-1.amazonaws.com")
.payload(payloadFromStringWithContentType("Action=CreateVolume" +
"&AvailabilityZone=us-east-1a" +
"&Iops=0" +
"&Signature=uI5tXrwV4zXB3uh0OP4RkfU2HMdQ2yICfpo4gKrajMI%3D" +
"&SignatureMethod=HmacSHA256" +
"&SignatureVersion=2" +
"&Size=4" +
"&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
"&Version=2010-08-31" +
"&VolumeType=standard" +
"&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
HttpResponse.builder()
.statusCode(200)
.payload(payloadFromResource("/created_volume.xml")).build());
ElasticBlockStoreApi client = requestsSendResponses(builder.build()).getElasticBlockStoreApi().get();
assertEquals(client.createVolumeInAvailabilityZone("us-east-1a",
CreateVolumeOptions.Builder.withSize(4).isEncrypted(false).volumeType("standard").withIops(0)),
creating);
}
public void testCreateVolumeFromSnapshotInAvailabilityZoneEuSetsCorrectEndpoint() {
String region = "eu-west-1";
@ -75,16 +109,17 @@ public class EC2ElasticBlockStoreApiExpectTest extends BaseEC2ApiExpectTest<EC2A
builder.putAll(describeAvailabilityZonesRequestResponse);
builder.put(
formSigner.filter(HttpRequest.builder()
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "CreateVolume")
.addFormParam("AvailabilityZone", "eu-west-1a")
.addFormParam("Size", "1")
.addFormParam("SnapshotId", "snap-8b7ffbdd").build()),
HttpResponse.builder()
.statusCode(200)
.payload(payloadFromResource("/created_volume.xml")).build());
.method("POST")
.endpoint("https://ec2." + region + ".amazonaws.com/")
.addHeader("Host", "ec2." + region + ".amazonaws.com")
.addFormParam("Action", "CreateVolume")
.addFormParam("AvailabilityZone", "eu-west-1a")
.addFormParam("Size", "1")
.addFormParam("SnapshotId", "snap-8b7ffbdd")
.build()),
HttpResponse.builder()
.statusCode(200)
.payload(payloadFromResource("/created_volume.xml")).build());
ElasticBlockStoreApi client = requestsSendResponses(builder.build()).getElasticBlockStoreApi().get();

View File

@ -17,6 +17,8 @@
package org.jclouds.ec2.features;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.jclouds.ec2.options.CreateVolumeOptions.Builder.fromSnapshotId;
import static org.jclouds.ec2.options.CreateVolumeOptions.Builder.volumeType;
import static org.jclouds.ec2.options.DescribeSnapshotsOptions.Builder.snapshotIds;
import static org.jclouds.util.Predicates2.retry;
import static org.testng.Assert.assertEquals;
@ -26,6 +28,11 @@ import static org.testng.Assert.assertNotNull;
import java.util.Set;
import java.util.SortedSet;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.ec2.EC2Api;
@ -38,12 +45,6 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* Tests behavior of {@code ElasticBlockStoreApi}
*
@ -118,10 +119,11 @@ public class ElasticBlockStoreApiLiveTest extends BaseComputeServiceContextLiveT
@Test
void testCreateVolumeInAvailabilityZone() {
Volume expected = client.createVolumeInAvailabilityZone(defaultZone, 1);
Volume expected = client.createVolumeInAvailabilityZone(defaultZone,
volumeType("gp2"));
assertNotNull(expected);
assertEquals(expected.getAvailabilityZone(), defaultZone);
assertEquals(expected.getVolumeType(), "gp2");
this.volumeId = expected.getId();
Set<Volume> result = Sets.newLinkedHashSet(client.describeVolumesInRegion(defaultRegion, expected.getId()));
@ -129,6 +131,7 @@ public class ElasticBlockStoreApiLiveTest extends BaseComputeServiceContextLiveT
assertEquals(result.size(), 1);
Volume volume = result.iterator().next();
assertEquals(volume.getId(), expected.getId());
assertEquals(volume.getVolumeType(), expected.getVolumeType());
}
@Test(dependsOnMethods = "testCreateVolumeInAvailabilityZone")
@ -161,6 +164,24 @@ public class ElasticBlockStoreApiLiveTest extends BaseComputeServiceContextLiveT
client.deleteVolumeInRegion(snapshot.getRegion(), volume.getId());
}
@Test(dependsOnMethods = "testCreateSnapshotInRegion")
void testCreateVolumeFromSnapshotInAvailabilityZoneWithOptions() {
Volume volume = client.createVolumeInAvailabilityZone(defaultZone,
fromSnapshotId(snapshot.getId()));
assertNotNull(volume);
Predicate<Volume> availabile = retry(new VolumeAvailable(client), 600, 10, SECONDS);
assert availabile.apply(volume);
Volume result = Iterables.getOnlyElement(client.describeVolumesInRegion(snapshot.getRegion(), volume.getId()));
assertEquals(volume.getId(), result.getId());
assertEquals(volume.getSnapshotId(), snapshot.getId());
assertEquals(volume.getAvailabilityZone(), defaultZone);
assertEquals(result.getStatus(), Volume.Status.AVAILABLE);
client.deleteVolumeInRegion(snapshot.getRegion(), volume.getId());
}
@Test(dependsOnMethods = "testCreateSnapshotInRegion")
void testCreateVolumeFromSnapshotInAvailabilityZoneWithSize() {
Volume volume = client.createVolumeFromSnapshotInAvailabilityZone(defaultZone, 2, snapshot.getId());

View File

@ -0,0 +1,156 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.ec2.options;
import static org.jclouds.ec2.options.CreateVolumeOptions.Builder.fromSnapshotId;
import static org.jclouds.ec2.options.CreateVolumeOptions.Builder.isEncrypted;
import static org.jclouds.ec2.options.CreateVolumeOptions.Builder.volumeType;
import static org.jclouds.ec2.options.CreateVolumeOptions.Builder.withIops;
import static org.jclouds.ec2.options.CreateVolumeOptions.Builder.withSize;
import static org.testng.Assert.assertEquals;
import com.google.common.collect.ImmutableList;
import org.jclouds.http.options.HttpRequestOptions;
import org.testng.annotations.Test;
/**
* Tests possible uses of CreateVolumeOptions and CreateVolumeOptions.Builder.*
*/
public class CreateVolumeOptionsTest {
@Test
public void testAssignability() {
assert HttpRequestOptions.class.isAssignableFrom(CreateVolumeOptions.class);
assert !String.class.isAssignableFrom(CreateVolumeOptions.class);
}
@Test
public void testVolumeType() {
CreateVolumeOptions options = new CreateVolumeOptions();
options.volumeType("test");
assertEquals(options.buildFormParameters().get("VolumeType"),
ImmutableList.of("test"));
}
@Test
public void testNullVolumeType() {
CreateVolumeOptions options = new CreateVolumeOptions();
assertEquals(options.buildFormParameters().get("VolumeType"), ImmutableList.of());
}
@Test
public void testVolumeTypeStatic() {
CreateVolumeOptions options = volumeType("test");
assertEquals(options.buildFormParameters().get("VolumeType"),
ImmutableList.of("test"));
}
@Test(expectedExceptions = NullPointerException.class)
public void testVolmeTypeNPE() {
volumeType(null);
}
@Test
public void testFromSnapshotId() {
CreateVolumeOptions options = new CreateVolumeOptions();
options.fromSnapshotId("test");
assertEquals(options.buildFormParameters().get("SnapshotId"),
ImmutableList.of("test"));
}
@Test
public void testNullFromSnapshotId() {
CreateVolumeOptions options = new CreateVolumeOptions();
assertEquals(options.buildFormParameters().get("SnapshotId"), ImmutableList.of());
}
@Test
public void testWithSnapshotIdStatic() {
CreateVolumeOptions options = fromSnapshotId("test");
assertEquals(options.buildFormParameters().get("SnapshotId"),
ImmutableList.of("test"));
}
@Test(expectedExceptions = NullPointerException.class)
public void testFromSnapshotIdNPE() {
fromSnapshotId(null);
}
@Test
public void testWithIops() {
CreateVolumeOptions options = new CreateVolumeOptions();
options.withIops(5);
assertEquals(options.buildFormParameters().get("Iops"),
ImmutableList.of("5"));
}
@Test
public void testNullWithIops() {
CreateVolumeOptions options = new CreateVolumeOptions();
assertEquals(options.buildFormParameters().get("Iops"), ImmutableList.of());
}
@Test
public void testWithIopsStatic() {
CreateVolumeOptions options = withIops(5);
assertEquals(options.buildFormParameters().get("Iops"),
ImmutableList.of("5"));
}
@Test
public void testWithSize() {
CreateVolumeOptions options = new CreateVolumeOptions();
options.withSize(5);
assertEquals(options.buildFormParameters().get("Size"),
ImmutableList.of("5"));
}
@Test
public void testNullWithSize() {
CreateVolumeOptions options = new CreateVolumeOptions();
assertEquals(options.buildFormParameters().get("Size"), ImmutableList.of());
}
@Test
public void testWithSizeStatic() {
CreateVolumeOptions options = withSize(5);
assertEquals(options.buildFormParameters().get("Size"),
ImmutableList.of("5"));
}
@Test
public void testIsEncrypted() {
CreateVolumeOptions options = new CreateVolumeOptions();
options.isEncrypted(true);
assertEquals(options.buildFormParameters().get("Encrypted"),
ImmutableList.of("true"));
}
@Test
public void testNullIsEncrypted() {
CreateVolumeOptions options = new CreateVolumeOptions();
assertEquals(options.buildFormParameters().get("Encrypted"), ImmutableList.of());
}
@Test
public void testIsEncryptedStatic() {
CreateVolumeOptions options = isEncrypted(true);
assertEquals(options.buildFormParameters().get("Encrypted"),
ImmutableList.of("true"));
}
}

View File

@ -26,13 +26,12 @@ import static org.jclouds.ec2.options.RegisterImageBackedByEbsOptions.Builder.wi
import static org.jclouds.ec2.options.RegisterImageBackedByEbsOptions.Builder.withRamdisk;
import static org.testng.Assert.assertEquals;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import org.jclouds.ec2.domain.Image.Architecture;
import org.jclouds.http.options.HttpRequestOptions;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
/**
* Tests possible uses of RegisterImageBackedByEbsOptions and
* RegisterImageBackedByEbsOptions.Builder.*
@ -190,6 +189,41 @@ public class RegisterImageBackedByEbsOptionsTest {
addBlockDeviceFromSnapshot(null, null, null);
}
@Test
public void testAdvancedAddBlockDeviceFromSnapshot() {
RegisterImageBackedByEbsOptions options = new RegisterImageBackedByEbsOptions();
options.addBlockDeviceFromSnapshot("deviceName", "virtualName", "snapshotId", true, "gp2", 0, false);
assertEquals(options.buildFormParameters().entries(), ImmutableMultimap.builder()
.put("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "true")
.put("BlockDeviceMapping.1.Ebs.VolumeType", "gp2")
.put("BlockDeviceMapping.1.Ebs.Iops", "0")
.put("BlockDeviceMapping.1.DeviceName", "deviceName")
.put("BlockDeviceMapping.1.VirtualName", "virtualName")
.put("BlockDeviceMapping.1.Ebs.SnapshotId", "snapshotId")
.build()
.entries());
}
@Test
public void testAdvancedAddBlockDeviceFromSnapshotStatic() {
RegisterImageBackedByEbsOptions options = addBlockDeviceFromSnapshot("deviceName", "virtualName", "snapshotId", true, "gp2", 0, true);
assertEquals(options.buildFormParameters().entries(), ImmutableMultimap.builder()
.put("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "true")
.put("BlockDeviceMapping.1.Ebs.VolumeType", "gp2")
.put("BlockDeviceMapping.1.Ebs.Iops", "0")
.put("BlockDeviceMapping.1.Ebs.Encrypted", "true")
.put("BlockDeviceMapping.1.DeviceName", "deviceName")
.put("BlockDeviceMapping.1.VirtualName", "virtualName")
.put("BlockDeviceMapping.1.Ebs.SnapshotId", "snapshotId")
.build()
.entries());
}
@Test(expectedExceptions = NullPointerException.class)
public void testAdvancedAddBlockDeviceFromSnapshotNPE() {
addBlockDeviceFromSnapshot(null, null, null, false, null, null, false);
}
@Test
public void testAddEphemeralBlockDeviceFromSnapshot() {
RegisterImageBackedByEbsOptions options = new RegisterImageBackedByEbsOptions();
@ -269,6 +303,41 @@ public class RegisterImageBackedByEbsOptionsTest {
addNewBlockDevice(null, null, 1);
}
@Test
public void testAdvancedAddNewBlockDevice() {
RegisterImageBackedByEbsOptions options = new RegisterImageBackedByEbsOptions();
options.addNewBlockDevice("deviceName", "virtualName", 5, true, "gp2", 0, true);
assertEquals(options.buildFormParameters().entries(), ImmutableMultimap.builder()
.put("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "true")
.put("BlockDeviceMapping.1.Ebs.VolumeType", "gp2")
.put("BlockDeviceMapping.1.Ebs.Iops", "0")
.put("BlockDeviceMapping.1.Ebs.Encrypted", "true")
.put("BlockDeviceMapping.1.DeviceName", "deviceName")
.put("BlockDeviceMapping.1.VirtualName", "virtualName")
.put("BlockDeviceMapping.1.Ebs.VolumeSize", "5")
.build()
.entries());
}
@Test
public void testAdvancedAddNewBlockDeviceStatic() {
RegisterImageBackedByEbsOptions options = addNewBlockDevice("deviceName", "virtualName", 5, true, "gp2", 0, false);
assertEquals(options.buildFormParameters().entries(), ImmutableMultimap.builder()
.put("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "true")
.put("BlockDeviceMapping.1.Ebs.VolumeType", "gp2")
.put("BlockDeviceMapping.1.Ebs.Iops", "0")
.put("BlockDeviceMapping.1.DeviceName", "deviceName")
.put("BlockDeviceMapping.1.VirtualName", "virtualName")
.put("BlockDeviceMapping.1.Ebs.VolumeSize", "5")
.build()
.entries());
}
@Test(expectedExceptions = NullPointerException.class)
public void testAdvancedAddNewBlockDeviceNPE() {
addNewBlockDevice(null, null, 5, false, null, null, false);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testAddNewBlockDeviceTooBig() {
addNewBlockDevice("deviceName", "virtualName", 1025);

View File

@ -209,7 +209,7 @@ public class RunInstancesOptionsTest {
@Test
public void testWithBlockDeviceMapping() {
BlockDeviceMapping mapping = new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true);
BlockDeviceMapping mapping = new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true, "gp2", 10, true);
RunInstancesOptions options = new RunInstancesOptions().withBlockDeviceMappings(ImmutableSet
.<BlockDeviceMapping> of(mapping));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.DeviceName"),
@ -218,6 +218,12 @@ public class RunInstancesOptionsTest {
ImmutableList.of("120"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.DeleteOnTermination"),
ImmutableList.of("true"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.VolumeType"),
ImmutableList.of("gp2"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.Iops"),
ImmutableList.of("10"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.Encrypted"),
ImmutableList.of("true"));
}
@Test
@ -228,7 +234,7 @@ public class RunInstancesOptionsTest {
@Test
public void testWithBlockDeviceMappingStatic() {
BlockDeviceMapping mapping = new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true);
BlockDeviceMapping mapping = new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true, null, null, false);
RunInstancesOptions options = withBlockDeviceMappings(ImmutableSet
.<BlockDeviceMapping> of(mapping));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.DeviceName"),
@ -237,6 +243,8 @@ public class RunInstancesOptionsTest {
ImmutableList.of("120"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.DeleteOnTermination"),
ImmutableList.of("true"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.VolumeType"),
ImmutableList.of());
}
@Test(expectedExceptions = NullPointerException.class)

View File

@ -43,9 +43,9 @@ public class CreateVolumeResponseHandlerTest extends BaseEC2HandlerTest {
InputStream is = getClass().getResourceAsStream("/created_volume.xml");
Volume expected = new Volume(Region.US_EAST_1, "vol-2a21e543", 1, null,
"us-east-1a", Volume.Status.CREATING, dateService
.iso8601DateParse("2009-12-28T05:42:53.000Z"), Sets
.<Attachment> newLinkedHashSet());
"us-east-1a", Volume.Status.CREATING, dateService
.iso8601DateParse("2009-12-28T05:42:53.000Z"), "standard", 0, false,
Sets.<Attachment> newLinkedHashSet());
CreateVolumeResponseHandler handler = injector.getInstance(CreateVolumeResponseHandler.class);
addDefaultRegionToHandler(handler);

View File

@ -18,6 +18,7 @@ package org.jclouds.ec2.xml;
import static com.google.common.collect.Iterables.get;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.io.InputStream;
import java.util.Set;
@ -85,17 +86,22 @@ public class DescribeImagesResponseHandlerTest {
public void testEBS() {
Set<Image> contents = ImmutableSet.of(new Image("us-east-1", Architecture.I386, "websrv_2009-12-10",
"Web Server AMI", "ami-246f8d4d", "706093390852/websrv_2009-12-10", "706093390852",
ImageState.AVAILABLE, "available", ImageType.MACHINE, true, Sets.<String> newHashSet(), null, "windows", null,
RootDeviceType.EBS, "/dev/sda1", ImmutableMap.<String, EbsBlockDevice> of("/dev/sda1",
new EbsBlockDevice("snap-d01272b9", 30, true), "xvdf", new EbsBlockDevice("snap-d31272ba", 250,
false)), ImmutableMap.<String, String> of(), VirtualizationType.HVM, Hypervisor.XEN));
"Web Server AMI", "ami-246f8d4d", "706093390852/websrv_2009-12-10", "706093390852",
ImageState.AVAILABLE, "available", ImageType.MACHINE, true, Sets.<String> newHashSet(), null, "windows", null,
RootDeviceType.EBS, "/dev/sda1",
ImmutableMap.<String, EbsBlockDevice> of("/dev/sda1",
new EbsBlockDevice("snap-d01272b9", 30, true, "standard", null, false),
"xvdf", new EbsBlockDevice("snap-d31272ba", 250, false, "standard", null, false)),
ImmutableMap.<String, String> of(), VirtualizationType.HVM, Hypervisor.XEN));
Set<Image> result = parseImages("/describe_images_ebs.xml");
assertEquals(result.toString(), contents.toString());
assertEquals(get(result, 0).getImageState(), ImageState.AVAILABLE);
assertEquals(get(result, 0).getRawState(), "available");
assertEquals(get(result, 0).getEbsBlockDevices().get("/dev/sda1").getVolumeType(), "standard");
assertEquals(get(result, 0).getEbsBlockDevices().get("/dev/sda1").isEncrypted(), false);
assertNull(get(result, 0).getEbsBlockDevices().get("/dev/sda1").getIops());
}
public void testTags() {

View File

@ -45,13 +45,14 @@ public class DescribeVolumesResponseHandlerTest extends BaseEC2HandlerTest {
Set<Volume> expected = Sets.newLinkedHashSet();
expected.add(new Volume(defaultRegion, "vol-2a21e543", 1, null, "us-east-1a",
Volume.Status.AVAILABLE, dateService.iso8601DateParse("2009-12-28T05:42:53.000Z"),
Sets.<Attachment> newLinkedHashSet()));
"standard", 0, false, Sets.<Attachment> newLinkedHashSet()));
expected.add(new Volume(defaultRegion, "vol-4282672b", 800, "snap-536d1b3a",
"us-east-1a", Volume.Status.IN_USE, dateService
.iso8601DateParse("2008-05-07T11:51:50.000Z"), Sets
.<Attachment> newHashSet(new Attachment(defaultRegion, "vol-4282672b", "i-6058a509",
"/dev/sdh", Attachment.Status.ATTACHED, dateService
.iso8601DateParse("2008-05-07T12:51:50.000Z")))));
"us-east-1a", Volume.Status.IN_USE, dateService
.iso8601DateParse("2008-05-07T11:51:50.000Z"),
"standard", 0, false,
Sets.<Attachment> newHashSet(new Attachment(defaultRegion, "vol-4282672b", "i-6058a509",
"/dev/sdh", Attachment.Status.ATTACHED, dateService
.iso8601DateParse("2008-05-07T12:51:50.000Z")))));
DescribeVolumesResponseHandler handler = injector
.getInstance(DescribeVolumesResponseHandler.class);

View File

@ -6,4 +6,7 @@
<availabilityZone>us-east-1a</availabilityZone>
<status>creating</status>
<createTime>2009-12-28T05:42:53.000Z</createTime>
<volumeType>standard</volumeType>
<iops>0</iops>
<encrypted>false</encrypted>
</CreateVolumeResponse>

View File

@ -23,6 +23,8 @@
<snapshotId>snap-d01272b9</snapshotId>
<volumeSize>30</volumeSize>
<deleteOnTermination>true</deleteOnTermination>
<volumeType>standard</volumeType>
<encrypted>false</encrypted>
</ebs>
</item>
<item>
@ -31,6 +33,8 @@
<snapshotId>snap-d31272ba</snapshotId>
<volumeSize>250</volumeSize>
<deleteOnTermination>false</deleteOnTermination>
<volumeType>standard</volumeType>
<encrypted>false</encrypted>
</ebs>
</item>
</blockDeviceMapping>

View File

@ -9,6 +9,9 @@
<availabilityZone>us-east-1a</availabilityZone>
<status>available</status>
<createTime>2009-12-28T05:42:53.000Z</createTime>
<volumeType>standard</volumeType>
<iops>0</iops>
<encrypted>false</encrypted>
<attachmentSet />
</item>
<item>
@ -18,6 +21,9 @@
<availabilityZone>us-east-1a</availabilityZone>
<status>in-use</status>
<createTime>2008-05-07T11:51:50.000Z</createTime>
<volumeType>standard</volumeType>
<iops>0</iops>
<encrypted>false</encrypted>
<attachmentSet>
<item>
<volumeId>vol-4282672b</volumeId>

View File

@ -9,6 +9,9 @@
<availabilityZone>us-east-1a</availabilityZone>
<status>in-use</status>
<createTime>2008-05-07T11:51:50.000Z</createTime>
<volumeType>standard</volumeType>
<iops>0</iops>
<encrypted>false</encrypted>
<attachmentSet />
</item>
</volumeSet>

View File

@ -139,12 +139,26 @@ public class LaunchSpecification {
public Builder mapEBSSnapshotToDevice(String deviceName, String snapshotId, @Nullable Integer sizeInGib,
boolean deleteOnTermination) {
blockDeviceMappings.add(new MapEBSSnapshotToDevice(deviceName, snapshotId, sizeInGib, deleteOnTermination));
return mapEBSSnapshotToDevice(deviceName, snapshotId, sizeInGib, deleteOnTermination, null, null, null);
}
public Builder mapEBSSnapshotToDevice(String deviceName, String snapshotId, @Nullable Integer sizeInGib,
boolean deleteOnTermination, @Nullable String volumeType,
@Nullable Integer iops, @Nullable Boolean encrypted) {
blockDeviceMappings.add(new MapEBSSnapshotToDevice(deviceName, snapshotId, sizeInGib, deleteOnTermination,
volumeType, iops, encrypted));
return this;
}
public Builder mapNewVolumeToDevice(String deviceName, int sizeInGib, boolean deleteOnTermination) {
blockDeviceMappings.add(new MapNewVolumeToDevice(deviceName, sizeInGib, deleteOnTermination));
return mapNewVolumeToDevice(deviceName, sizeInGib, deleteOnTermination, null, null, null);
}
public Builder mapNewVolumeToDevice(String deviceName, int sizeInGib, boolean deleteOnTermination,
@Nullable String volumeType, @Nullable Integer iops,
@Nullable Boolean encrypted) {
blockDeviceMappings.add(new MapNewVolumeToDevice(deviceName, sizeInGib, deleteOnTermination,
volumeType, iops, encrypted));
return this;
}

View File

@ -265,28 +265,29 @@ public class AWSAMIApiTest extends BaseAWSEC2ApiTest<AWSAMIApi> {
}
HttpRequest registerImageBackedByEBSOptions = HttpRequest.builder().method("POST")
.endpoint("https://ec2.us-east-1.amazonaws.com/")
.addHeader("Host", "ec2.us-east-1.amazonaws.com")
.addFormParam("Action", "RegisterImage")
.addFormParam("BlockDeviceMapping.0.DeviceName", "/dev/sda1")
.addFormParam("BlockDeviceMapping.0.Ebs.SnapshotId", "snapshotId")
.addFormParam("BlockDeviceMapping.1.DeviceName", "/dev/device")
.addFormParam("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "false")
.addFormParam("BlockDeviceMapping.1.Ebs.SnapshotId", "snapshot")
.addFormParam("BlockDeviceMapping.2.DeviceName", "/dev/newdevice")
.addFormParam("BlockDeviceMapping.2.Ebs.DeleteOnTermination", "false")
.addFormParam("BlockDeviceMapping.2.Ebs.VolumeSize", "100")
.addFormParam("BlockDeviceMapping.2.VirtualName", "newblock")
.addFormParam("Description", "description")
.addFormParam("Name", "imageName")
.addFormParam("RootDeviceName", "/dev/sda1").build();
.endpoint("https://ec2.us-east-1.amazonaws.com/")
.addHeader("Host", "ec2.us-east-1.amazonaws.com")
.addFormParam("Action", "RegisterImage")
.addFormParam("BlockDeviceMapping.0.DeviceName", "/dev/sda1")
.addFormParam("BlockDeviceMapping.0.Ebs.SnapshotId", "snapshotId")
.addFormParam("BlockDeviceMapping.1.DeviceName", "/dev/device")
.addFormParam("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "false")
.addFormParam("BlockDeviceMapping.1.Ebs.SnapshotId", "snapshot")
.addFormParam("BlockDeviceMapping.1.Ebs.VolumeType", "gp2")
.addFormParam("BlockDeviceMapping.2.DeviceName", "/dev/newdevice")
.addFormParam("BlockDeviceMapping.2.Ebs.DeleteOnTermination", "false")
.addFormParam("BlockDeviceMapping.2.Ebs.VolumeSize", "100")
.addFormParam("BlockDeviceMapping.2.VirtualName", "newblock")
.addFormParam("Description", "description")
.addFormParam("Name", "imageName")
.addFormParam("RootDeviceName", "/dev/sda1").build();
public void testRegisterImageBackedByEBSOptions() throws SecurityException, NoSuchMethodException, IOException {
Invokable<?, ?> method = method(AWSAMIApi.class, "registerUnixImageBackedByEbsInRegion", String.class,
String.class, String.class, RegisterImageBackedByEbsOptions[].class);
GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageName", "snapshotId",
new RegisterImageBackedByEbsOptions().withDescription("description").addBlockDeviceFromSnapshot(
"/dev/device", null, "snapshot").addNewBlockDevice("/dev/newdevice", "newblock", 100)));
"/dev/device", null, "snapshot", false, "gp2", null, false).addNewBlockDevice("/dev/newdevice", "newblock", 100)));
request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);

View File

@ -333,7 +333,7 @@ public class AWSRunInstancesOptionsTest {
@Test
public void testWithBlockDeviceMapping() {
BlockDeviceMapping mapping = new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true);
BlockDeviceMapping mapping = new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true, "gp2", 10, true);
AWSRunInstancesOptions options = new AWSRunInstancesOptions().withBlockDeviceMappings(ImmutableSet
.<BlockDeviceMapping> of(mapping));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.DeviceName"),
@ -342,6 +342,12 @@ public class AWSRunInstancesOptionsTest {
ImmutableList.of("120"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.DeleteOnTermination"),
ImmutableList.of("true"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.VolumeType"),
ImmutableList.of("gp2"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.Iops"),
ImmutableList.of("10"));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.Ebs.Encrypted"),
ImmutableList.of("true"));
}
@Test
@ -352,7 +358,7 @@ public class AWSRunInstancesOptionsTest {
@Test
public void testWithBlockDeviceMappingStatic() {
BlockDeviceMapping mapping = new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true);
BlockDeviceMapping mapping = new BlockDeviceMapping.MapNewVolumeToDevice("/dev/sda1", 120, true, null, null, false);
AWSRunInstancesOptions options = withBlockDeviceMappings(ImmutableSet.<BlockDeviceMapping> of(mapping));
assertEquals(options.buildFormParameters().get("BlockDeviceMapping.1.DeviceName"),
ImmutableList.of("/dev/sda1"));