@Override
 public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(
     Predicate<ComputeMetadata> filter) {
   return Iterables.filter(
       Iterables.transform(client.getServerServices().getServerList(), serverToNodeMetadata),
       filter);
 }
 private Server addServer(String name, Template template, Ip availableIp) {
   Server addedServer =
       client
           .getServerServices()
           .addServer(
               name,
               checkNotNull(template.getImage().getProviderId()),
               sizeToRam.apply(template.getHardware()),
               availableIp.getIp());
   return addedServer;
 }
 @Override
 public NodeMetadata createNodeWithGroupEncodedIntoName(
     String group, String name, Template template) {
   Server addedServer = null;
   boolean notStarted = true;
   int numOfRetries = 20;
   GetIpListOptions unassignedIps =
       new GetIpListOptions()
           .onlyUnassigned()
           .inDatacenter(template.getLocation().getId())
           .onlyWithType(IpType.PUBLIC);
   // lock-free consumption of a shared resource: IP address pool
   while (notStarted) { // TODO: replace with Predicate-based thread
     // collision avoidance for simplicity
     Set<Ip> availableIps = client.getIpServices().getIpList(unassignedIps);
     if (availableIps.isEmpty()) throw new RuntimeException("No IPs available on this identity.");
     int ipIndex = new SecureRandom().nextInt(availableIps.size());
     Ip availableIp = Iterables.get(availableIps, ipIndex);
     try {
       addedServer = addServer(name, template, availableIp);
       notStarted = false;
     } catch (Exception e) {
       if (--numOfRetries == 0) Throwables.propagate(e);
       notStarted = true;
     }
   }
   if (template.getOptions().shouldBlockUntilRunning()) {
     serverLatestJobCompleted.apply(addedServer);
     client.getServerServices().power(addedServer.getName(), PowerCommand.START);
     serverLatestJobCompletedShort.apply(addedServer);
     addedServer =
         Iterables.getOnlyElement(
             client.getServerServices().getServersByName(addedServer.getName()));
   }
   Credentials credentials =
       client.getServerServices().getServerCredentialsList().get(addedServer.getName());
   if (credentials != null) credentialStore.put("node#" + addedServer.getId(), credentials);
   else logger.warn("couldn't get credentials for server %s", addedServer.getName());
   return serverToNodeMetadata.apply(addedServer);
 }