@Override
  public Response createPoly(byte[] inputToAutodetectType) {
    log.debug("Creating app from autodetecting input");

    boolean looksLikeLegacy = false;
    Exception legacyFormatException = null;
    // attempt legacy format
    try {
      ApplicationSpec appSpec = mapper().readValue(inputToAutodetectType, ApplicationSpec.class);
      if (appSpec.getType() != null || appSpec.getEntities() != null) {
        looksLikeLegacy = true;
      }
      return createFromAppSpec(appSpec);
    } catch (Exception e) {
      Exceptions.propagateIfFatal(e);
      legacyFormatException = e;
      log.debug("Input is not legacy ApplicationSpec JSON (will try others): " + e, e);
    }

    // TODO infer encoding from request
    String potentialYaml = new String(inputToAutodetectType);
    EntitySpec<? extends Application> spec = createEntitySpecForApplication(potentialYaml);

    // TODO not json - try ZIP, etc

    if (spec != null) {
      return launch(potentialYaml, spec);
    } else if (looksLikeLegacy) {
      throw Throwables.propagate(legacyFormatException);
    } else {
      return Response.serverError().entity("Unsupported format; not able to autodetect.").build();
    }
  }
 public static Map<String, Object> getSensorMap(String sensor, Iterable<Entity> descs) {
   if (Iterables.isEmpty(descs)) return Collections.emptyMap();
   Map<String, Object> result = MutableMap.of();
   Iterator<Entity> di = descs.iterator();
   Sensor<?> s = null;
   while (di.hasNext()) {
     Entity potentialSource = di.next();
     s = potentialSource.getEntityType().getSensor(sensor);
     if (s != null) break;
   }
   if (s == null) s = Sensors.newSensor(Object.class, sensor);
   if (!(s instanceof AttributeSensor<?>)) {
     log.warn("Cannot retrieve non-attribute sensor " + s + " for entities; returning empty map");
     return result;
   }
   for (Entity e : descs) {
     Object v = null;
     try {
       v = e.getAttribute((AttributeSensor<?>) s);
     } catch (Exception exc) {
       Exceptions.propagateIfFatal(exc);
       log.warn("Error retrieving sensor " + s + " for " + e + " (ignoring): " + exc);
     }
     if (v != null) result.put(e.getId(), v);
   }
   return result;
 }
  @Override
  public void release(DockerContainerLocation machine) {
    lock.readLock().lock();
    try {
      LOG.info("Releasing {}", machine);

      DynamicCluster cluster = dockerHost.getDockerContainerCluster();
      DockerContainer container = machine.getOwner();
      if (cluster.removeMember(container)) {
        LOG.info("Docker Host {}: member {} released", dockerHost.getDockerHostName(), machine);
      } else {
        LOG.warn(
            "Docker Host {}: member {} not found for release",
            dockerHost.getDockerHostName(),
            machine);
      }

      // Now close and unmange the container
      try {
        machine.close();
        container.stop();
      } catch (Exception e) {
        LOG.warn("Error stopping container: " + container, e);
        Exceptions.propagateIfFatal(e);
      } finally {
        Entities.unmanage(container);
      }
    } finally {
      lock.readLock().unlock();
    }
  }
 /**
  * attempts to resolve hostnameTarget from origin
  *
  * @return null if it definitively can't be resolved, best-effort IP address if possible, or blank
  *     if we could not run ssh or make sense of the output
  */
 public static String getResolvedAddress(
     Entity entity, SshMachineLocation origin, String hostnameTarget) {
   ProcessTaskWrapper<Integer> task =
       SshTasks.newSshExecTaskFactory(origin, "ping -c 1 -t 1 " + hostnameTarget)
           .summary("checking resolution of " + hostnameTarget)
           .allowingNonZeroExitCode()
           .newTask();
   DynamicTasks.queueIfPossible(task).orSubmitAndBlock(entity).asTask().blockUntilEnded();
   if (task.asTask().isError()) {
     log.warn(
         "ping could not be run, at "
             + entity
             + " / "
             + origin
             + ": "
             + Tasks.getError(task.asTask()));
     return "";
   }
   if (task.getExitCode() == null || task.getExitCode() != 0) {
     if (task.getExitCode() != null && task.getExitCode() < 10) {
       // small number means ping failed to resolve or ping the hostname
       log.debug(
           "not able to resolve "
               + hostnameTarget
               + " from "
               + origin
               + " for "
               + entity
               + " because exit code was "
               + task.getExitCode());
       return null;
     }
     // large number means ping probably did not run
     log.warn(
         "ping not run as expected, at "
             + entity
             + " / "
             + origin
             + " (code "
             + task.getExitCode()
             + "):\n"
             + task.getStdout().trim()
             + " --- "
             + task.getStderr().trim());
     return "";
   }
   String out = task.getStdout();
   try {
     String line1 = Strings.getFirstLine(out);
     String ip = Strings.getFragmentBetween(line1, "(", ")");
     if (Strings.isNonBlank(ip)) return ip;
   } catch (Exception e) {
     Exceptions.propagateIfFatal(e);
     /* ignore non-parseable output */
   }
   if (out.contains("127.0.0.1")) return "127.0.0.1";
   return "";
 }
  @Override
  public String getBroadcastAddress() {
    String sensorName = getConfig(BROADCAST_ADDRESS_SENSOR);
    if (Strings.isNonBlank(sensorName))
      return Entities.submit(
              this,
              DependentConfiguration.attributeWhenReady(this, Sensors.newStringSensor(sensorName)))
          .getUnchecked();

    String snitchName = getConfig(CassandraNode.ENDPOINT_SNITCH_NAME);
    if (snitchName.equals("Ec2MultiRegionSnitch") || snitchName.contains("MultiCloudSnitch")) {
      // http://www.datastax.com/documentation/cassandra/2.0/mobile/cassandra/architecture/architectureSnitchEC2MultiRegion_c.html
      // describes that the listen_address is set to the private IP, and the broadcast_address is
      // set to the public IP.
      return getAttribute(CassandraNode.ADDRESS);
    } else if (!getDriver().isClustered()) {
      return getListenAddress();
    } else {
      // In other situations, prefer the hostname, so other regions can see it
      // *Unless* hostname resolves at the target to a local-only interface which is different to
      // ADDRESS
      // (workaround for issue deploying to localhost)
      String hostname = getAttribute(CassandraNode.HOSTNAME);
      try {
        String resolvedAddress = getDriver().getResolvedAddress(hostname);
        if (resolvedAddress == null) {
          log.debug(
              "Cassandra using broadcast address "
                  + getListenAddress()
                  + " for "
                  + this
                  + " because hostname "
                  + hostname
                  + " could not be resolved at remote machine");
          return getListenAddress();
        }
        if (resolvedAddress.equals("127.0.0.1")) {
          log.debug(
              "Cassandra using broadcast address "
                  + getListenAddress()
                  + " for "
                  + this
                  + " because hostname "
                  + hostname
                  + " resolves to 127.0.0.1");
          return getListenAddress();
        }
        return hostname;
      } catch (Exception e) {
        Exceptions.propagateIfFatal(e);
        log.warn("Error resolving hostname " + hostname + " for " + this + ": " + e, e);
        return hostname;
      }
    }
  }
 public void rebootAndWait() {
   try {
     executePsScriptNoRetry(ImmutableList.of("Restart-Computer -Force"));
   } catch (Exception e) {
     // Restarting the computer will cause the command to fail; ignore the exception and continue
     Exceptions.propagateIfFatal(e);
   }
   waitForWinRmStatus(false, entity.getConfig(VanillaWindowsProcess.REBOOT_BEGUN_TIMEOUT));
   waitForWinRmStatus(true, entity.getConfig(VanillaWindowsProcess.REBOOT_COMPLETED_TIMEOUT))
       .getWithError();
 }
 /**
  * Returns a wrapped map, if the object is YAML which parses as a map; otherwise returns absent
  * capable of throwing an error with more details
  */
 @SuppressWarnings("unchecked")
 public static Maybe<Map<?, ?>> getAsYamlMap(Object planData) {
   if (!(planData instanceof String)) return Maybe.absent("not a string");
   Iterable<Object> result;
   try {
     result = Yamls.parseAll((String) planData);
   } catch (Exception e) {
     Exceptions.propagateIfFatal(e);
     return Maybe.absent(e);
   }
   Iterator<Object> ri = result.iterator();
   if (!ri.hasNext()) return Maybe.absent("YAML has no elements in it");
   Object r1 = ri.next();
   if (ri.hasNext()) return Maybe.absent("YAML has multiple elements in it");
   if (r1 instanceof Map) return (Maybe<Map<?, ?>>) (Maybe<?>) Maybe.of(r1);
   return Maybe.absent("YAML does not contain a map");
 }
  @Test
  public void testTagsSanity() throws Exception {
    entity.tags().addTag("foo");

    Response response =
        client().path(entityEndpoint + "/tags").accept(MediaType.APPLICATION_JSON_TYPE).get();
    String data = response.readEntity(String.class);

    try {
      List<Object> tags = new ObjectMapper().readValue(data, new TypeReference<List<Object>>() {});
      Assert.assertTrue(tags.contains("foo"));
      Assert.assertFalse(tags.contains("bar"));
    } catch (Exception e) {
      Exceptions.propagateIfFatal(e);
      throw new IllegalStateException(
          "Error with deserialization of tags list: " + e + "\n" + data, e);
    }
  }
  public static String getFirstReachableAddress(ComputeServiceContext context, NodeMetadata node) {
    // To pick the address, it relies on jclouds `sshForNode().apply(Node)` to check all IPs of node
    // (private+public),
    // to find one that is reachable. It does `openSocketFinder.findOpenSocketOnNode(node,
    // node.getLoginPort(), ...)`.
    // This keeps trying for time
    // org.jclouds.compute.reference.ComputeServiceConstants.Timeouts.portOpen.
    // TODO Want to configure this timeout here.
    //
    // TODO We could perhaps instead just set `templateOptions.blockOnPort(loginPort, 120)`, but
    // need
    // to be careful to only set that if config WAIT_FOR_SSHABLE is true. For some advanced
    // networking examples
    // (e.g. using DNAT on CloudStack), the brooklyn machine won't be able to reach the VM until
    // some additional
    // setup steps have been done. See links from Andrea:
    //     https://github.com/jclouds/jclouds/pull/895
    //     https://issues.apache.org/jira/browse/WHIRR-420
    //     jclouds.ssh.max-retries
    //     jclouds.ssh.retry-auth

    SshClient client;
    try {
      client = context.utils().sshForNode().apply(node);
    } catch (Exception e) {
      Exceptions.propagateIfFatal(e);
      /* i've seen: java.lang.IllegalStateException: Optional.get() cannot be called on an absent value
       * from org.jclouds.crypto.ASN1Codec.createASN1Sequence(ASN1Codec.java:86), if the ssh key has a passphrase, against AWS.
       *
       * others have reported: java.lang.IllegalArgumentException: DER length more than 4 bytes
       * when using a key with a passphrase (perhaps from other clouds?); not sure if that's this callpath or a different one.
       */
      throw new IllegalStateException(
          "Unable to connect SshClient to "
              + node
              + "; check that the node is accessible and that the SSH key exists and is correctly configured, including any passphrase defined",
          e);
    }
    return client.getHostAddress();
  }