You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ab...@apache.org on 2014/06/20 22:51:52 UTC

[3/3] git commit: JCLOUDS-602 - Add support for volumeType, iops and encrypted to EBS.

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.


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/6451098f
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/6451098f
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/6451098f

Branch: refs/heads/master
Commit: 6451098f72de17ed2c6978af82db120b1e9bd08b
Parents: da50cd6
Author: Andrew Bayer <an...@gmail.com>
Authored: Thu Jun 19 11:24:29 2014 -0700
Committer: Andrew Bayer <an...@gmail.com>
Committed: Fri Jun 20 12:27:17 2014 -0700

----------------------------------------------------------------------
 .../ec2/compute/options/EC2TemplateOptions.java |  19 ++-
 .../jclouds/ec2/domain/BlockDeviceMapping.java  |  82 ++++++++--
 .../main/java/org/jclouds/ec2/domain/Image.java |  39 ++++-
 .../java/org/jclouds/ec2/domain/Volume.java     |  72 ++++++++-
 .../ec2/features/ElasticBlockStoreApi.java      |  31 ++++
 .../ec2/options/CreateVolumeOptions.java        | 146 +++++++++++++++++
 .../RegisterImageBackedByEbsOptions.java        | 115 +++++++++++++-
 .../ec2/options/RunInstancesOptions.java        |   9 +-
 .../ec2/xml/CreateVolumeResponseHandler.java    |  29 +++-
 .../ec2/xml/DescribeImagesResponseHandler.java  |  32 ++--
 .../org/jclouds/ec2/EBSBootEC2ApiLiveTest.java  |   2 +-
 .../jclouds/ec2/features/AMIApiLiveTest.java    |   6 +-
 .../EC2ElasticBlockStoreApiExpectTest.java      |  73 ++++++---
 .../features/ElasticBlockStoreApiLiveTest.java  |  37 ++++-
 .../ec2/options/CreateVolumeOptionsTest.java    | 156 +++++++++++++++++++
 .../RegisterImageBackedByEbsOptionsTest.java    |  75 ++++++++-
 .../ec2/options/RunInstancesOptionsTest.java    |  12 +-
 .../xml/CreateVolumeResponseHandlerTest.java    |   6 +-
 .../xml/DescribeImagesResponseHandlerTest.java  |  16 +-
 .../xml/DescribeVolumesResponseHandlerTest.java |  13 +-
 apis/ec2/src/test/resources/created_volume.xml  |   3 +
 .../src/test/resources/describe_images_ebs.xml  |   4 +
 .../ec2/src/test/resources/describe_volumes.xml |   6 +
 .../test/resources/describe_volumes_single.xml  |   3 +
 .../aws/ec2/domain/LaunchSpecification.java     |  18 ++-
 .../jclouds/aws/ec2/features/AWSAMIApiTest.java |  33 ++--
 .../ec2/options/AWSRunInstancesOptionsTest.java |  10 +-
 27 files changed, 934 insertions(+), 113 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/main/java/org/jclouds/ec2/compute/options/EC2TemplateOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/options/EC2TemplateOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/options/EC2TemplateOptions.java
index f535815..64c1ccd 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/options/EC2TemplateOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/options/EC2TemplateOptions.java
@@ -187,12 +187,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;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/main/java/org/jclouds/ec2/domain/BlockDeviceMapping.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/domain/BlockDeviceMapping.java b/apis/ec2/src/main/java/org/jclouds/ec2/domain/BlockDeviceMapping.java
index 79367af..fbf5f97 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/domain/BlockDeviceMapping.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/domain/BlockDeviceMapping.java
@@ -34,6 +34,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;
@@ -65,8 +68,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() {
@@ -76,6 +95,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;
       }
    }
@@ -86,13 +108,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");
@@ -107,6 +133,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() {
@@ -133,6 +162,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;
@@ -143,6 +184,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;
    }
 
@@ -185,41 +229,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);
       }
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/main/java/org/jclouds/ec2/domain/Image.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/domain/Image.java b/apis/ec2/src/main/java/org/jclouds/ec2/domain/Image.java
index 0525b05..42136cd 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/domain/Image.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/domain/Image.java
@@ -159,11 +159,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() {
@@ -178,6 +185,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;
@@ -185,6 +204,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;
       }
 
@@ -199,11 +221,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;
@@ -212,7 +246,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 + "]";
       }
 
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java b/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java
index 9f66c4e..1b8987a 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/domain/Volume.java
@@ -98,6 +98,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;
@@ -143,15 +148,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);
       }
    }
 
@@ -165,8 +186,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;
@@ -174,6 +201,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);
    }
 
@@ -212,6 +242,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;
    }
@@ -228,7 +270,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
@@ -277,6 +322,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;
    }
 
@@ -288,7 +345,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
+              +"]";
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java
index 01ee459..0da808b 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java
@@ -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;
@@ -165,6 +166,36 @@ public interface ElasticBlockStoreApi {
             @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
     * EBS, go to the Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateVolumeOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateVolumeOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateVolumeOptions.java
new file mode 100644
index 0000000..9c2e182
--- /dev/null
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateVolumeOptions.java
@@ -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);
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptions.java
index d1e4259..813593a 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptions.java
@@ -94,9 +94,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
@@ -105,7 +186,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 {
       }
 
       /**
+       * @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 {
       }
 
       /**
+       * @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)
        */
       public static RegisterImageBackedByEbsOptions addNewEphemeralBlockDevice(String deviceName,

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/main/java/org/jclouds/ec2/options/RunInstancesOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/RunInstancesOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/RunInstancesOptions.java
index 073c688..aa48c65 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/RunInstancesOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/RunInstancesOptions.java
@@ -139,6 +139,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;
@@ -179,7 +186,7 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
       }
 
       /**
-       * @see RunInstancesOptions#asType(InstanceType)
+       * @see RunInstancesOptions#asType(String)
        */
       public static RunInstancesOptions asType(String instanceType) {
          RunInstancesOptions options = new RunInstancesOptions();

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/main/java/org/jclouds/ec2/xml/CreateVolumeResponseHandler.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/xml/CreateVolumeResponseHandler.java b/apis/ec2/src/main/java/org/jclouds/ec2/xml/CreateVolumeResponseHandler.java
index 99b1966..af910a7 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/xml/CreateVolumeResponseHandler.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/xml/CreateVolumeResponseHandler.java
@@ -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;
@@ -37,11 +40,6 @@ import org.jclouds.location.Zone;
 import org.jclouds.rest.internal.GeneratedHttpRequest;
 import org.xml.sax.Attributes;
 
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
 public class CreateVolumeResponseHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Volume> {
    protected final DateCodec dateCodec;
    protected final Supplier<String> defaultRegion;
@@ -73,6 +71,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;
 
@@ -125,6 +126,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));
@@ -140,7 +149,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;
@@ -148,6 +158,9 @@ public class CreateVolumeResponseHandler extends ParseSax.HandlerForGeneratedReq
       volumeStatus = null;
       createTime = null;
       attachments = Sets.newLinkedHashSet();
+      volumeType = null;
+      iops = null;
+      encrypted = false;
       return volume;
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java
index 3f9e257..8cfea0f 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java
@@ -19,30 +19,28 @@ 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 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.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.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;
 
-import com.google.common.base.Supplier;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
 /**
  * Parses the following XML document:
  * <p/>
@@ -94,7 +92,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() {
@@ -159,6 +159,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")) {
@@ -171,11 +177,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;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ApiLiveTest.java
index a77558b..ff18a9d 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ApiLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ApiLiveTest.java
@@ -396,7 +396,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() {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
index 3c97e8d..3c242b8 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
@@ -182,7 +182,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);
@@ -192,8 +192,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,

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java
index f01ebab..df71112 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java
@@ -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;
@@ -36,14 +37,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();
@@ -63,7 +66,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";
       
@@ -72,16 +106,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();
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java
index 0f62bca..e6bbc6f 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java
@@ -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}
  */
@@ -116,10 +117,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()));
@@ -127,6 +129,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")
@@ -160,6 +163,24 @@ public class ElasticBlockStoreApiLiveTest extends BaseComputeServiceContextLiveT
    }
 
    @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());
       assertNotNull(volume);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/java/org/jclouds/ec2/options/CreateVolumeOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/options/CreateVolumeOptionsTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/options/CreateVolumeOptionsTest.java
new file mode 100644
index 0000000..20f7475
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/options/CreateVolumeOptionsTest.java
@@ -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"));
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptionsTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptionsTest.java
index b7926b3..9d1612a 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptionsTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptionsTest.java
@@ -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.*
@@ -189,6 +188,41 @@ public class RegisterImageBackedByEbsOptionsTest {
    }
 
    @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();
       options.addEphemeralBlockDeviceFromSnapshot("deviceName", "virtualName", "snapshotId");
@@ -267,6 +301,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);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/java/org/jclouds/ec2/options/RunInstancesOptionsTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/options/RunInstancesOptionsTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/options/RunInstancesOptionsTest.java
index b8d27c3..a519541 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/options/RunInstancesOptionsTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/options/RunInstancesOptionsTest.java
@@ -207,7 +207,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"),
@@ -216,6 +216,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
@@ -226,7 +232,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"),
@@ -235,6 +241,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)

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/java/org/jclouds/ec2/xml/CreateVolumeResponseHandlerTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/xml/CreateVolumeResponseHandlerTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/xml/CreateVolumeResponseHandlerTest.java
index 3bba00d..278b978 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/xml/CreateVolumeResponseHandlerTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/xml/CreateVolumeResponseHandlerTest.java
@@ -41,9 +41,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);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeImagesResponseHandlerTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeImagesResponseHandlerTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeImagesResponseHandlerTest.java
index 2db5b30..d44efa6 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeImagesResponseHandlerTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeImagesResponseHandlerTest.java
@@ -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;
@@ -83,17 +84,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() {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeVolumesResponseHandlerTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeVolumesResponseHandlerTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeVolumesResponseHandlerTest.java
index e8693ad..aba1d1b 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeVolumesResponseHandlerTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeVolumesResponseHandlerTest.java
@@ -43,13 +43,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);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/resources/created_volume.xml
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/resources/created_volume.xml b/apis/ec2/src/test/resources/created_volume.xml
index acca927..4fbcabe 100644
--- a/apis/ec2/src/test/resources/created_volume.xml
+++ b/apis/ec2/src/test/resources/created_volume.xml
@@ -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>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/resources/describe_images_ebs.xml
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/resources/describe_images_ebs.xml b/apis/ec2/src/test/resources/describe_images_ebs.xml
index 12830ab..794cd76 100644
--- a/apis/ec2/src/test/resources/describe_images_ebs.xml
+++ b/apis/ec2/src/test/resources/describe_images_ebs.xml
@@ -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>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/resources/describe_volumes.xml
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/resources/describe_volumes.xml b/apis/ec2/src/test/resources/describe_volumes.xml
index 45b3efa..8861d6a 100644
--- a/apis/ec2/src/test/resources/describe_volumes.xml
+++ b/apis/ec2/src/test/resources/describe_volumes.xml
@@ -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>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/apis/ec2/src/test/resources/describe_volumes_single.xml
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/resources/describe_volumes_single.xml b/apis/ec2/src/test/resources/describe_volumes_single.xml
index fcc10a5..5d501ea 100644
--- a/apis/ec2/src/test/resources/describe_volumes_single.xml
+++ b/apis/ec2/src/test/resources/describe_volumes_single.xml
@@ -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>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/6451098f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/LaunchSpecification.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/LaunchSpecification.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/LaunchSpecification.java
index 02bf9fe..2972dd5 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/LaunchSpecification.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/LaunchSpecification.java
@@ -138,12 +138,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;
       }