@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(); }