// Fires up an instance, finds its root volume ID, takes a snapshot, then
  // terminates the instance.
  private Snapshot createSnapshot() throws RunNodesException {

    String instanceId = null;
    try {
      RunningInstance instance =
          getOnlyElement(
              concat(
                  ec2Client
                      .getInstanceServices()
                      .runInstancesInRegion(regionId, null, imageId, 1, 1)));
      instanceId = instance.getId();

      assertTrue(runningTester.apply(instance), instanceId + "didn't achieve the state running!");

      instance =
          getOnlyElement(
              concat(
                  ec2Client.getInstanceServices().describeInstancesInRegion(regionId, instanceId)));
      BlockDevice device = instance.getEbsBlockDevices().get("/dev/sda1");
      assertNotNull(device, "device: /dev/sda1 not present on: " + instance);
      Snapshot snapshot =
          ec2Client
              .getElasticBlockStoreServices()
              .createSnapshotInRegion(regionId, device.getVolumeId());
      snapshotsToDelete.add(snapshot.getId());
      return snapshot;
    } finally {
      if (instanceId != null)
        ec2Client.getInstanceServices().terminateInstancesInRegion(regionId, instanceId);
    }
  }
  @Test
  public void testCreateAndListEBSBackedImage() throws Exception {
    Snapshot snapshot = createSnapshot();

    // List of images before...
    int sizeBefore = client.describeImagesInRegion(regionId).size();

    // Register a new image...
    ebsBackedImageId =
        client.registerUnixImageBackedByEbsInRegion(
            regionId,
            ebsBackedImageName,
            snapshot.getId(),
            addNewBlockDevice("/dev/sda2", "myvirtual", 1).withDescription("adrian"));
    imagesToDeregister.add(ebsBackedImageId);
    final Image ebsBackedImage =
        getOnlyElement(client.describeImagesInRegion(regionId, imageIds(ebsBackedImageId)));
    assertEquals(ebsBackedImage.getName(), ebsBackedImageName);
    assertEquals(ebsBackedImage.getImageType(), ImageType.MACHINE);
    assertEquals(ebsBackedImage.getRootDeviceType(), RootDeviceType.EBS);
    assertEquals(ebsBackedImage.getRootDeviceName(), "/dev/sda1");
    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());

    // List of images after - should be one larger than before
    int after = client.describeImagesInRegion(regionId).size();
    assertEquals(after, sizeBefore + 1);
  }
 private void verifyImage() {
   assertEquals(ebsImage.getImageType(), ImageType.MACHINE);
   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());
 }
  @AfterTest
  void cleanup() {
    if (ebsInstance != null) {
      try {
        client
            .getInstanceServices()
            .terminateInstancesInRegion(ebsInstance.getRegion(), ebsInstance.getId());
        terminatedTester.apply(ebsInstance);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    if (ebsImage != null) {
      try {
        client.getAMIServices().deregisterImageInRegion(ebsImage.getRegion(), ebsImage.getId());
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    if (snapshot != null) {
      try {
        client
            .getElasticBlockStoreServices()
            .deleteSnapshotInRegion(snapshot.getRegion(), snapshot.getId());
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    if (attachment != null) {
      try {
        client
            .getElasticBlockStoreServices()
            .detachVolumeInRegion(volume.getRegion(), volume.getId(), true);
        assert volumeTester.apply(volume);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    if (instance != null) {
      try {
        client
            .getInstanceServices()
            .terminateInstancesInRegion(instance.getRegion(), instance.getId());
        terminatedTester.apply(instance);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    if (volume != null) {
      try {
        client
            .getElasticBlockStoreServices()
            .deleteVolumeInRegion(volume.getRegion(), volume.getId());
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    if (keyPair != null) {
      try {
        client
            .getKeyPairServices()
            .deleteKeyPairInRegion(keyPair.getRegion(), keyPair.getKeyName());
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    if (securityGroupName != null) {
      try {
        client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
  @Test(enabled = false, dependsOnMethods = "testBundleInstance")
  void testAMIFromBundle() {
    volume =
        Iterables.getOnlyElement(
            client
                .getElasticBlockStoreServices()
                .describeVolumesInRegion(volume.getRegion(), volume.getId()));
    if (volume.getAttachments().size() > 0) {
      // should be cleanly unmounted, so force is not necessary.
      client
          .getElasticBlockStoreServices()
          .detachVolumeInRegion(instance.getRegion(), volume.getId(), false);
      System.out.printf(
          "%d: %s awaiting detachment to complete%n", System.currentTimeMillis(), volume.getId());
      assert volumeTester.apply(volume);
    } else {
      attachment = null; // protect test closer so that it doesn't try to
      // detach
    }
    snapshot =
        client
            .getElasticBlockStoreServices()
            .createSnapshotInRegion(
                volume.getRegion(), volume.getId(), withDescription("EBS Ubuntu Hardy"));

    System.out.printf(
        "%d: %s awaiting snapshot to complete%n", System.currentTimeMillis(), snapshot.getId());

    assert snapshotTester.apply(snapshot);
    Image image =
        Iterables.getOnlyElement(
            client
                .getAMIServices()
                .describeImagesInRegion(snapshot.getRegion(), imageIds(IMAGE_ID)));
    String description = image.getDescription() == null ? "jclouds" : image.getDescription();

    System.out.printf(
        "%d: %s creating ami from snapshot%n", System.currentTimeMillis(), snapshot.getId());

    String amiId =
        client
            .getAMIServices()
            .registerUnixImageBackedByEbsInRegion(
                snapshot.getRegion(),
                "ebsboot-" + image.getId(),
                snapshot.getId(),
                withKernelId(image.getKernelId())
                    .withRamdisk(image.getRamdiskId())
                    .withDescription(description)
                    .asArchitecture(Architecture.I386));
    try {
      ebsImage =
          Iterables.getOnlyElement(
              client
                  .getAMIServices()
                  .describeImagesInRegion(snapshot.getRegion(), imageIds(amiId)));
    } catch (AWSResponseException e) {
      // TODO add a retry handler for this HTTP code 400 and the below error
      if (e.getError().getClass().equals("InvalidAMIID.NotFound"))
        ebsImage =
            Iterables.getOnlyElement(
                client
                    .getAMIServices()
                    .describeImagesInRegion(snapshot.getRegion(), imageIds(amiId)));
      else throw e;
    }
    verifyImage();
  }