private List<BlockDeviceMapping> getNewEphemeralDeviceMapping() {

    final List<BlockDeviceMapping> oldDeviceMapping = getAmiBlockDeviceMappings();

    final Set<String> occupiedDevices = new HashSet<String>();
    for (final BlockDeviceMapping mapping : oldDeviceMapping) {

      occupiedDevices.add(mapping.getDeviceName());
    }

    final List<String> available =
        new ArrayList<String>(
            Arrays.asList("ephemeral0", "ephemeral1", "ephemeral2", "ephemeral3"));

    final List<BlockDeviceMapping> newDeviceMapping = new ArrayList<BlockDeviceMapping>(4);
    for (char suffix = 'b'; suffix <= 'z' && !available.isEmpty(); suffix++) {

      final String deviceName = String.format("/dev/xvd%s", suffix);

      if (occupiedDevices.contains(deviceName)) continue;

      final BlockDeviceMapping newMapping =
          new BlockDeviceMapping().withDeviceName(deviceName).withVirtualName(available.get(0));

      newDeviceMapping.add(newMapping);
      available.remove(0);
    }

    return newDeviceMapping;
  }
  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;

    if (obj instanceof BlockDeviceMapping == false) return false;
    BlockDeviceMapping other = (BlockDeviceMapping) obj;

    if (other.getVirtualName() == null ^ this.getVirtualName() == null) return false;
    if (other.getVirtualName() != null
        && other.getVirtualName().equals(this.getVirtualName()) == false) return false;
    if (other.getDeviceName() == null ^ this.getDeviceName() == null) return false;
    if (other.getDeviceName() != null
        && other.getDeviceName().equals(this.getDeviceName()) == false) return false;
    if (other.getEbs() == null ^ this.getEbs() == null) return false;
    if (other.getEbs() != null && other.getEbs().equals(this.getEbs()) == false) return false;
    if (other.getNoDevice() == null ^ this.getNoDevice() == null) return false;
    if (other.getNoDevice() != null && other.getNoDevice().equals(this.getNoDevice()) == false)
      return false;
    return true;
  }
  public Request<CreateImageRequest> marshall(CreateImageRequest createImageRequest) {

    if (createImageRequest == null) {
      throw new AmazonClientException("Invalid argument passed to marshall(...)");
    }

    Request<CreateImageRequest> request =
        new DefaultRequest<CreateImageRequest>(createImageRequest, "AmazonEC2");
    request.addParameter("Action", "CreateImage");
    request.addParameter("Version", "2014-06-15");

    if (createImageRequest.getInstanceId() != null) {
      request.addParameter(
          "InstanceId", StringUtils.fromString(createImageRequest.getInstanceId()));
    }
    if (createImageRequest.getName() != null) {
      request.addParameter("Name", StringUtils.fromString(createImageRequest.getName()));
    }
    if (createImageRequest.getDescription() != null) {
      request.addParameter(
          "Description", StringUtils.fromString(createImageRequest.getDescription()));
    }
    if (createImageRequest.isNoReboot() != null) {
      request.addParameter("NoReboot", StringUtils.fromBoolean(createImageRequest.isNoReboot()));
    }

    java.util.List<BlockDeviceMapping> blockDeviceMappingsList =
        createImageRequest.getBlockDeviceMappings();
    int blockDeviceMappingsListIndex = 1;

    for (BlockDeviceMapping blockDeviceMappingsListValue : blockDeviceMappingsList) {
      BlockDeviceMapping blockDeviceMappingMember = blockDeviceMappingsListValue;
      if (blockDeviceMappingMember != null) {
        if (blockDeviceMappingMember.getVirtualName() != null) {
          request.addParameter(
              "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".VirtualName",
              StringUtils.fromString(blockDeviceMappingMember.getVirtualName()));
        }
        if (blockDeviceMappingMember.getDeviceName() != null) {
          request.addParameter(
              "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".DeviceName",
              StringUtils.fromString(blockDeviceMappingMember.getDeviceName()));
        }
        EbsBlockDevice ebsBlockDeviceEbs = blockDeviceMappingMember.getEbs();
        if (ebsBlockDeviceEbs != null) {
          if (ebsBlockDeviceEbs.getSnapshotId() != null) {
            request.addParameter(
                "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".Ebs.SnapshotId",
                StringUtils.fromString(ebsBlockDeviceEbs.getSnapshotId()));
          }
          if (ebsBlockDeviceEbs.getVolumeSize() != null) {
            request.addParameter(
                "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".Ebs.VolumeSize",
                StringUtils.fromInteger(ebsBlockDeviceEbs.getVolumeSize()));
          }
          if (ebsBlockDeviceEbs.isDeleteOnTermination() != null) {
            request.addParameter(
                "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".Ebs.DeleteOnTermination",
                StringUtils.fromBoolean(ebsBlockDeviceEbs.isDeleteOnTermination()));
          }
          if (ebsBlockDeviceEbs.getVolumeType() != null) {
            request.addParameter(
                "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".Ebs.VolumeType",
                StringUtils.fromString(ebsBlockDeviceEbs.getVolumeType()));
          }
          if (ebsBlockDeviceEbs.getIops() != null) {
            request.addParameter(
                "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".Ebs.Iops",
                StringUtils.fromInteger(ebsBlockDeviceEbs.getIops()));
          }
          if (ebsBlockDeviceEbs.isEncrypted() != null) {
            request.addParameter(
                "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".Ebs.Encrypted",
                StringUtils.fromBoolean(ebsBlockDeviceEbs.isEncrypted()));
          }
        }
        if (blockDeviceMappingMember.getNoDevice() != null) {
          request.addParameter(
              "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".NoDevice",
              StringUtils.fromString(blockDeviceMappingMember.getNoDevice()));
        }
      }

      blockDeviceMappingsListIndex++;
    }

    return request;
  }
  public Request<RegisterImageRequest> marshall(RegisterImageRequest registerImageRequest) {

    if (registerImageRequest == null) {
      throw new AmazonClientException("Invalid argument passed to marshall(...)");
    }

    Request<RegisterImageRequest> request =
        new DefaultRequest<RegisterImageRequest>(registerImageRequest, "AmazonEC2");
    request.addParameter("Action", "RegisterImage");
    request.addParameter("Version", "2014-05-01");

    if (registerImageRequest.getImageLocation() != null) {
      request.addParameter(
          "ImageLocation", StringUtils.fromString(registerImageRequest.getImageLocation()));
    }
    if (registerImageRequest.getName() != null) {
      request.addParameter("Name", StringUtils.fromString(registerImageRequest.getName()));
    }
    if (registerImageRequest.getDescription() != null) {
      request.addParameter(
          "Description", StringUtils.fromString(registerImageRequest.getDescription()));
    }
    if (registerImageRequest.getArchitecture() != null) {
      request.addParameter(
          "Architecture", StringUtils.fromString(registerImageRequest.getArchitecture()));
    }
    if (registerImageRequest.getKernelId() != null) {
      request.addParameter("KernelId", StringUtils.fromString(registerImageRequest.getKernelId()));
    }
    if (registerImageRequest.getRamdiskId() != null) {
      request.addParameter(
          "RamdiskId", StringUtils.fromString(registerImageRequest.getRamdiskId()));
    }
    if (registerImageRequest.getRootDeviceName() != null) {
      request.addParameter(
          "RootDeviceName", StringUtils.fromString(registerImageRequest.getRootDeviceName()));
    }

    java.util.List<BlockDeviceMapping> blockDeviceMappingsList =
        registerImageRequest.getBlockDeviceMappings();
    int blockDeviceMappingsListIndex = 1;

    for (BlockDeviceMapping blockDeviceMappingsListValue : blockDeviceMappingsList) {
      BlockDeviceMapping blockDeviceMappingMember = blockDeviceMappingsListValue;
      if (blockDeviceMappingMember != null) {
        if (blockDeviceMappingMember.getVirtualName() != null) {
          request.addParameter(
              "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".VirtualName",
              StringUtils.fromString(blockDeviceMappingMember.getVirtualName()));
        }
        if (blockDeviceMappingMember.getDeviceName() != null) {
          request.addParameter(
              "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".DeviceName",
              StringUtils.fromString(blockDeviceMappingMember.getDeviceName()));
        }
        EbsBlockDevice ebsBlockDeviceEbs = blockDeviceMappingMember.getEbs();
        if (ebsBlockDeviceEbs != null) {
          if (ebsBlockDeviceEbs.getSnapshotId() != null) {
            request.addParameter(
                "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".Ebs.SnapshotId",
                StringUtils.fromString(ebsBlockDeviceEbs.getSnapshotId()));
          }
          if (ebsBlockDeviceEbs.getVolumeSize() != null) {
            request.addParameter(
                "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".Ebs.VolumeSize",
                StringUtils.fromInteger(ebsBlockDeviceEbs.getVolumeSize()));
          }
          if (ebsBlockDeviceEbs.isDeleteOnTermination() != null) {
            request.addParameter(
                "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".Ebs.DeleteOnTermination",
                StringUtils.fromBoolean(ebsBlockDeviceEbs.isDeleteOnTermination()));
          }
          if (ebsBlockDeviceEbs.getVolumeType() != null) {
            request.addParameter(
                "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".Ebs.VolumeType",
                StringUtils.fromString(ebsBlockDeviceEbs.getVolumeType()));
          }
          if (ebsBlockDeviceEbs.getIops() != null) {
            request.addParameter(
                "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".Ebs.Iops",
                StringUtils.fromInteger(ebsBlockDeviceEbs.getIops()));
          }
          if (ebsBlockDeviceEbs.isEncrypted() != null) {
            request.addParameter(
                "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".Ebs.Encrypted",
                StringUtils.fromBoolean(ebsBlockDeviceEbs.isEncrypted()));
          }
        }
        if (blockDeviceMappingMember.getNoDevice() != null) {
          request.addParameter(
              "BlockDeviceMapping." + blockDeviceMappingsListIndex + ".NoDevice",
              StringUtils.fromString(blockDeviceMappingMember.getNoDevice()));
        }
      }

      blockDeviceMappingsListIndex++;
    }
    if (registerImageRequest.getVirtualizationType() != null) {
      request.addParameter(
          "VirtualizationType",
          StringUtils.fromString(registerImageRequest.getVirtualizationType()));
    }
    if (registerImageRequest.getSriovNetSupport() != null) {
      request.addParameter(
          "SriovNetSupport", StringUtils.fromString(registerImageRequest.getSriovNetSupport()));
    }

    return request;
  }
  /** @param args */
  public static void main(String[] args) {
    // ============================================================================================//
    // =============================== Submitting a Request
    // =======================================//
    // ============================================================================================//

    // Create the AmazonEC2Client object so we can call various APIs.
    AmazonEC2 ec2 = new AmazonEC2Client(new ClasspathPropertiesFileCredentialsProvider());
    Region usWest2 = Region.getRegion(Regions.US_WEST_2);
    ec2.setRegion(usWest2);

    // Initializes a Spot Instance Request
    RequestSpotInstancesRequest requestRequest = new RequestSpotInstancesRequest();

    // *************************** Required Parameters Settings ************************//
    // Request 1 x t1.micro instance with a bid price of $0.03.
    requestRequest.setSpotPrice("0.03");
    requestRequest.setInstanceCount(Integer.valueOf(1));

    // Setup the specifications of the launch. This includes the instance type (e.g. t1.micro)
    // and the latest Amazon Linux AMI id available. Note, you should always use the latest
    // Amazon Linux AMI id or another of your choosing.
    LaunchSpecification launchSpecification = new LaunchSpecification();
    launchSpecification.setImageId("ami-8c1fece5");
    launchSpecification.setInstanceType("t1.micro");

    // Add the security group to the request.
    ArrayList<String> securityGroups = new ArrayList<String>();
    securityGroups.add("GettingStartedGroup");
    launchSpecification.setSecurityGroups(securityGroups);

    // *************************** Bid Type Settings ************************//
    // Set the type of the bid to persistent.
    requestRequest.setType("persistent");

    // *************************** Valid From/To Settings ************************//
    // Set the valid start time to be two minutes from now.
    Calendar from = Calendar.getInstance();
    from.add(Calendar.MINUTE, 2);
    requestRequest.setValidFrom(from.getTime());

    // Set the valid end time to be two minutes and two hours from now.
    Calendar until = (Calendar) from.clone();
    until.add(Calendar.HOUR, 2);
    requestRequest.setValidUntil(until.getTime());

    // *************************** Launch Group Settings ************************//
    // Set the launch group.
    requestRequest.setLaunchGroup("ADVANCED-DEMO-LAUNCH-GROUP");

    // *************************** Availability Zone Group Settings ************************//
    // Set the availability zone group.
    requestRequest.setAvailabilityZoneGroup("ADVANCED-DEMO-AZ-GROUP");

    // *************************** Add the block device mapping ************************//

    // Goal: Setup block device mappings to ensure that we will not delete
    // the root partition on termination.

    // Create the block device mapping to describe the root partition.
    BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping();
    blockDeviceMapping.setDeviceName("/dev/sda1");

    // Set the delete on termination flag to false.
    EbsBlockDevice ebs = new EbsBlockDevice();
    ebs.setDeleteOnTermination(Boolean.FALSE);
    blockDeviceMapping.setEbs(ebs);

    // Add the block device mapping to the block list.
    ArrayList<BlockDeviceMapping> blockList = new ArrayList<BlockDeviceMapping>();
    blockList.add(blockDeviceMapping);

    // Set the block device mapping configuration in the launch specifications.
    launchSpecification.setBlockDeviceMappings(blockList);

    // *************************** Add the availability zone ************************//
    // Setup the availability zone to use. Note we could retrieve the availability
    // zones using the ec2.describeAvailabilityZones() API. For this demo we will just use
    // us-east-1b.
    SpotPlacement placement = new SpotPlacement("us-east-1b");
    launchSpecification.setPlacement(placement);

    // *************************** Add the placement group ************************//
    // Setup the placement group to use with whatever name you desire.
    // For this demo we will just use "ADVANCED-DEMO-PLACEMENT-GROUP".
    // Note: We have commented this out, because we are not leveraging cc1.4xlarge or
    // cg1.4xlarge in this example.
    /*
    SpotPlacement pg = new SpotPlacement();
    pg.setGroupName("ADVANCED-DEMO-PLACEMENT-GROUP");
    launchSpecification.setPlacement(pg);
    */

    // *************************** Add the launch specification ************************//
    // Add the launch specification.
    requestRequest.setLaunchSpecification(launchSpecification);

    // ============================================================================================//
    // =========================== Getting the Request ID from the Request
    // ========================//
    // ============================================================================================//

    // Call the RequestSpotInstance API.
    RequestSpotInstancesResult requestResult = ec2.requestSpotInstances(requestRequest);
    List<SpotInstanceRequest> requestResponses = requestResult.getSpotInstanceRequests();

    // Setup an arraylist to collect all of the request ids we want to watch hit the running
    // state.
    ArrayList<String> spotInstanceRequestIds = new ArrayList<String>();

    // Add all of the request ids to the hashset, so we can determine when they hit the
    // active state.
    for (SpotInstanceRequest requestResponse : requestResponses) {
      System.out.println("Created Spot Request: " + requestResponse.getSpotInstanceRequestId());
      spotInstanceRequestIds.add(requestResponse.getSpotInstanceRequestId());
    }

    // ============================================================================================//
    // =========================== Determining the State of the Spot Request
    // ======================//
    // ============================================================================================//

    // Create a variable that will track whether there are any requests still in the open state.
    boolean anyOpen;

    // Initialize variables.
    ArrayList<String> instanceIds = new ArrayList<String>();

    do {
      // Create the describeRequest with tall of the request id to monitor (e.g. that we started).
      DescribeSpotInstanceRequestsRequest describeRequest =
          new DescribeSpotInstanceRequestsRequest();
      describeRequest.setSpotInstanceRequestIds(spotInstanceRequestIds);

      // Initialize the anyOpen variable to false ??? which assumes there are no requests open
      // unless
      // we find one that is still open.
      anyOpen = false;

      try {
        // Retrieve all of the requests we want to monitor.
        DescribeSpotInstanceRequestsResult describeResult =
            ec2.describeSpotInstanceRequests(describeRequest);
        List<SpotInstanceRequest> describeResponses = describeResult.getSpotInstanceRequests();

        // Look through each request and determine if they are all in the active state.
        for (SpotInstanceRequest describeResponse : describeResponses) {
          // If the state is open, it hasn't changed since we attempted to request it.
          // There is the potential for it to transition almost immediately to closed or
          // cancelled so we compare against open instead of active.
          if (describeResponse.getState().equals("open")) {
            anyOpen = true;
            break;
          }

          // Add the instance id to the list we will eventually terminate.
          instanceIds.add(describeResponse.getInstanceId());
        }
      } catch (AmazonServiceException e) {
        // If we have an exception, ensure we don't break out of the loop.
        // This prevents the scenario where there was blip on the wire.
        anyOpen = true;
      }

      try {
        // Sleep for 60 seconds.
        Thread.sleep(60 * 1000);
      } catch (Exception e) {
        // Do nothing because it woke up early.
      }
    } while (anyOpen);

    // ============================================================================================//
    // ====================================== Canceling the Request ==============================//
    // ============================================================================================//

    try {
      // Cancel requests.
      CancelSpotInstanceRequestsRequest cancelRequest =
          new CancelSpotInstanceRequestsRequest(spotInstanceRequestIds);
      ec2.cancelSpotInstanceRequests(cancelRequest);
    } catch (AmazonServiceException e) {
      // Write out any exceptions that may have occurred.
      System.out.println("Error cancelling instances");
      System.out.println("Caught Exception: " + e.getMessage());
      System.out.println("Reponse Status Code: " + e.getStatusCode());
      System.out.println("Error Code: " + e.getErrorCode());
      System.out.println("Request ID: " + e.getRequestId());
    }

    // ============================================================================================//
    // =================================== Terminating any Instances
    // ==============================//
    // ============================================================================================//
    try {
      // Terminate instances.
      TerminateInstancesRequest terminateRequest = new TerminateInstancesRequest(instanceIds);
      ec2.terminateInstances(terminateRequest);
    } catch (AmazonServiceException e) {
      // Write out any exceptions that may have occurred.
      System.out.println("Error terminating instances");
      System.out.println("Caught Exception: " + e.getMessage());
      System.out.println("Reponse Status Code: " + e.getStatusCode());
      System.out.println("Error Code: " + e.getErrorCode());
      System.out.println("Request ID: " + e.getRequestId());
    }
  }