private RunningInstance blockUntilWeCanSshIntoInstance(RunningInstance instance)
      throws UnknownHostException {
    System.out.printf(
        "%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance.getId());
    assert runningTester.apply(instance);

    // search my identity for the instance I just created
    Set<? extends Reservation<? extends RunningInstance>> reservations =
        client
            .getInstanceServices()
            .describeInstancesInRegion(instance.getRegion(), instance.getId()); // last
    // parameter
    // (ids)
    // narrows
    // the
    // search

    instance = Iterables.getOnlyElement(Iterables.getOnlyElement(reservations));

    System.out.printf(
        "%d: %s awaiting ssh service to start%n",
        System.currentTimeMillis(), instance.getIpAddress());
    assert socketTester.apply(new IPSocket(instance.getIpAddress(), 22));
    System.out.printf(
        "%d: %s ssh service started%n", System.currentTimeMillis(), instance.getDnsName());
    sshPing(instance);
    System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instance.getId());
    return instance;
  }
  protected NodeMetadataBuilder buildInstance(
      final RunningInstance instance, NodeMetadataBuilder builder) {
    builder.providerId(instance.getId());
    builder.id(instance.getRegion() + "/" + instance.getId());
    String group = getGroupForInstance(instance);
    builder.group(group);
    // standard convention from aws-ec2, which might not be re-used outside.
    if (instance.getPrivateDnsName() != null)
      builder.hostname(instance.getPrivateDnsName().replaceAll("\\..*", ""));
    addCredentialsForInstance(builder, instance);
    builder.status(instanceToNodeStatus.get(instance.getInstanceState()));
    builder.backendStatus(instance.getRawState());

    // collect all ip addresses into one bundle in case the api mistakenly put a private address
    // into the public address field
    Builder<String> addressesBuilder = ImmutableSet.builder();
    if (Strings.emptyToNull(instance.getIpAddress()) != null)
      addressesBuilder.add(instance.getIpAddress());
    // Add dnsName (if available) to addresses, when the IPAddress is null
    // happens on Eucalyptus sometimes.
    else if (Strings.emptyToNull(instance.getDnsName()) != null)
      addressesBuilder.add(instance.getDnsName());
    if (Strings.emptyToNull(instance.getPrivateIpAddress()) != null)
      addressesBuilder.add(instance.getPrivateIpAddress());

    Set<String> addresses = addressesBuilder.build();

    builder.publicAddresses(filter(addresses, not(IsPrivateIPAddress.INSTANCE)));
    builder.privateAddresses(filter(addresses, IsPrivateIPAddress.INSTANCE));
    builder.hardware(parseHardware(instance));
    Location location = getLocationForAvailabilityZoneOrRegion(instance);
    builder.location(location);
    builder.imageId(instance.getRegion() + "/" + instance.getImageId());

    // extract the operating system from the image
    RegionAndName regionAndName = new RegionAndName(instance.getRegion(), instance.getImageId());
    try {
      Image image = imageMap.get().getUnchecked(regionAndName);
      if (image != null) builder.operatingSystem(image.getOperatingSystem());
    } catch (CacheLoader.InvalidCacheLoadException e) {
      logger.debug("image not found for %s: %s", regionAndName, e);
    } catch (UncheckedExecutionException e) {
      logger.debug("error getting image for %s: %s", regionAndName, e);
    }
    return builder;
  }