@Override
  protected OneAndOneApi create(Properties props, Iterable<Module> modules) {
    Injector injector = newBuilder().modules(modules).overrides(props).buildInjector();
    constants = injector.getInstance(OneAndOneConstants.class);
    Predicate<Server> serverAvailableCheck =
        new Predicate<Server>() {
          @Override
          public boolean apply(Server currentServer) {
            Server server = api.serverApi().get(currentServer.id());

            if ((server.status().state() != Types.ServerState.POWERED_OFF
                    && server.status().state() != Types.ServerState.POWERED_ON)
                || server.status().percent() != 0) {
              return false;
            } else {
              return true;
            }
          }
        };

    Predicate<ServerPrivateNetworkRef> privateNetworkAvailableCheck =
        new Predicate<ServerPrivateNetworkRef>() {
          @Override
          public boolean apply(ServerPrivateNetworkRef networkRef) {
            PrivateNetwork server =
                api.serverApi()
                    .getPrivateNetwork(networkRef.serverId(), networkRef.privateNetworkId());
            return server.state() != Types.GenericState.ACTIVE;
          }
        };
    waitUntilPrivateNetworkReady =
        Predicates2.retry(
            privateNetworkAvailableCheck,
            constants.pollTimeout(),
            constants.pollPeriod(),
            constants.pollMaxPeriod(),
            TimeUnit.SECONDS);
    waitUntilServerReady =
        Predicates2.retry(
            serverAvailableCheck,
            constants.pollTimeout(),
            constants.pollPeriod(),
            constants.pollMaxPeriod(),
            TimeUnit.SECONDS);
    return injector.getInstance(OneAndOneApi.class);
  }
  // Suggest at least 15 minutes for timeout
  public static String waitForPasswordOnAws(
      ComputeService computeService, final NodeMetadata node, long timeout, TimeUnit timeUnit)
      throws TimeoutException {
    ComputeServiceContext computeServiceContext = computeService.getContext();
    AWSEC2Api ec2Client = computeServiceContext.unwrapApi(AWSEC2Api.class);
    final WindowsApi client = ec2Client.getWindowsApi().get();
    final String region = node.getLocation().getParent().getId();

    // The Administrator password will take some time before it is ready - Amazon says sometimes 15
    // minutes.
    // So we create a predicate that tests if the password is ready, and wrap it in a retryable
    // predicate.
    Predicate<String> passwordReady =
        new Predicate<String>() {
          @Override
          public boolean apply(String s) {
            if (Strings.isNullOrEmpty(s)) return false;
            PasswordData data = client.getPasswordDataInRegion(region, s);
            if (data == null) return false;
            return !Strings.isNullOrEmpty(data.getPasswordData());
          }
        };

    LOG.info("Waiting for password, for " + node.getProviderId() + ":" + node.getId());
    Predicate<String> passwordReadyRetryable =
        Predicates2.retry(
            passwordReady, timeUnit.toMillis(timeout), 10 * 1000, TimeUnit.MILLISECONDS);
    boolean ready = passwordReadyRetryable.apply(node.getProviderId());
    if (!ready)
      throw new TimeoutException(
          "Password not available for "
              + node
              + " in region "
              + region
              + " after "
              + timeout
              + " "
              + timeUnit.name());

    // Now pull together Amazon's encrypted password blob, and the private key that jclouds
    // generated
    PasswordDataAndPrivateKey dataAndKey =
        new PasswordDataAndPrivateKey(
            client.getPasswordDataInRegion(region, node.getProviderId()),
            node.getCredentials().getPrivateKey());

    // And apply it to the decryption function
    WindowsLoginCredentialsFromEncryptedData f =
        computeServiceContext
            .utils()
            .injector()
            .getInstance(WindowsLoginCredentialsFromEncryptedData.class);
    LoginCredentials credentials = f.apply(dataAndKey);

    return credentials.getPassword();
  }
 protected void waitForEvent(Integer eventId) {
   Predicates2.retry(
           new Predicate<Integer>() {
             @Override
             public boolean apply(Integer input) {
               Event event = api.getEventApi().get(input);
               return Event.Status.DONE == event.getStatus();
             }
           },
           DEFAULT_TIMEOUT_SECONDS,
           DEFAULT_POLL_SECONDS,
           TimeUnit.SECONDS)
       .apply(eventId);
 }