/** * creates the given exception, but without propagating it, for use when caller will be wrapping */ public static RuntimeException create( @Nullable String prefix, Collection<? extends Throwable> exceptions) { if (exceptions.size() == 1) { Throwable e = exceptions.iterator().next(); if (Strings.isBlank(prefix)) return new PropagatedRuntimeException(e); return new PropagatedRuntimeException(prefix + ": " + Exceptions.collapseText(e), e); } if (exceptions.isEmpty()) { if (Strings.isBlank(prefix)) return new CompoundRuntimeException("(empty compound exception)", exceptions); return new CompoundRuntimeException(prefix, exceptions); } if (Strings.isBlank(prefix)) return new CompoundRuntimeException( exceptions.size() + " errors, including: " + Exceptions.collapseText(exceptions.iterator().next()), exceptions); return new CompoundRuntimeException( prefix + ", " + exceptions.size() + " errors including: " + Exceptions.collapseText(exceptions.iterator().next()), exceptions); }
/** * Runs the given callable. Repeats until the operation succeeds or {@link #isExceptionRetryable} * indicates that the request cannot be retried. */ protected <T> T runOperationWithRetry(Callable<T> operation) { int backoff = 64; Exception lastException = null; for (int retries = 0; retries < 100; retries++) { try { return operation.call(); } catch (Exception e) { lastException = e; if (isExceptionRetryable.apply(e)) { LOG.debug("Attempt #{} failed to add security group: {}", retries + 1, e.getMessage()); try { Thread.sleep(backoff); } catch (InterruptedException e1) { throw Exceptions.propagate(e1); } backoff = backoff << 1; } else { break; } } } throw new RuntimeException( "Unable to add security group rule; repeated errors from provider", lastException); }
@Override public String execCommandTimeout(String command, Duration timeout) { ProcessTaskWrapper<String> task = SshEffectorTasks.ssh(command) .environmentVariables( ((AbstractSoftwareProcessSshDriver) getDriver()).getShellEnvironment()) .configure(SshTool.PROP_ALLOCATE_PTY, true) // TODO configure globally .requiringZeroAndReturningStdout() .machine(getMachine()) .summary(command) .newTask(); try { String result = DynamicTasks.queueIfPossible(task) .executionContext(this) .orSubmitAsync() .asTask() .get(timeout); return result; } catch (TimeoutException te) { throw new IllegalStateException("Timed out running command: " + command); } catch (Exception e) { Integer exitCode = task.getExitCode(); LOG.warn( "Command failed, return code {}: {}", exitCode == null ? -1 : exitCode, task.getStderr()); throw Exceptions.propagate(e); } }
private void copy(String src, File dst) { try { copy(new ReaderInputStream(new StringReader(src), "UTF-8"), dst); } catch (Exception e) { throw Exceptions.propagate(e); } }
@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(); } }
private Response launch(String yaml, EntitySpec<? extends Application> spec) { try { Application app = EntityManagementUtils.createUnstarted(mgmt(), spec); CreationResult<Application, Void> result = EntityManagementUtils.start(app); boolean isEntitled = Entitlements.isEntitled( mgmt().getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, StringAndArgument.of(Startable.START.getName(), null))); if (!isEntitled) { throw WebResourceUtils.unauthorized( "User '%s' is not authorized to start application %s", Entitlements.getEntitlementContext().user(), spec.getType()); } log.info("Launched from YAML: " + yaml + " -> " + app + " (" + result.task() + ")"); URI ref = URI.create(app.getApplicationId()); ResponseBuilder response = created(ref); if (result.task() != null) response.entity(TaskTransformer.FROM_TASK.apply(result.task())); return response.build(); } catch (ConstraintViolationException e) { throw new UserFacingException(e); } catch (Exception e) { throw Exceptions.propagate(e); } }
@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(); } }
@Override public final T get() { if (log.isDebugEnabled()) log.debug("Queuing task to resolve " + dsl + ", called by " + Tasks.current()); EntityInternal entity = (EntityInternal) BrooklynTaskTags.getTargetOrContextEntity(Tasks.current()); ExecutionContext exec = (entity != null) ? entity.getExecutionContext() : BasicExecutionContext.getCurrentExecutionContext(); if (exec == null) { throw new IllegalStateException("No execution context available to resolve " + dsl); } Task<T> task = newTask(); T result; try { result = exec.submit(task).get(); } catch (InterruptedException | ExecutionException e) { Task<?> currentTask = Tasks.current(); if (currentTask != null && currentTask.isCancelled()) { task.cancel(true); } throw Exceptions.propagate(e); } if (log.isDebugEnabled()) log.debug("Resolved " + result + " from " + dsl); return result; }
@Override public void doStart(Collection<? extends Location> locs) { List<Location> locations = MutableList.of(); sensors().set(SERVICE_UP, Boolean.FALSE); ServiceStateLogic.setExpectedState(this, Lifecycle.STARTING); LOG.info("Creating new MesosLocation"); createLocation(MutableMap.<String, Object>of()); // Start frameworks try { Group frameworks = sensors().get(MESOS_FRAMEWORKS); Entities.invokeEffectorList( this, frameworks.getMembers(), Startable.START, ImmutableMap.of("locations", locations)) .getUnchecked(); } catch (Exception e) { LOG.warn("Error starting frameworks", e); ServiceStateLogic.setExpectedState(this, Lifecycle.ON_FIRE); Exceptions.propagate(e); } super.doStart(locations); connectSensors(); ServiceStateLogic.setExpectedState(this, Lifecycle.RUNNING); sensors().set(SERVICE_UP, Boolean.TRUE); }
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; }
/** * as {@link #waitOnForExpiry(Object)} but catches and wraps InterruptedException as unchecked * RuntimeInterruptedExcedption */ public boolean waitOnForExpiryUnchecked(Object waitTarget) { try { return waitOnForExpiry(waitTarget); } catch (InterruptedException e) { throw Exceptions.propagate(e); } }
@Override public EntitySpec<? extends Application> createApplicationSpec(String plan) { try { CampPlatform camp = CampCatalogUtils.getCampPlatform(mgmt); BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt); AssemblyTemplate at = CampUtils.registerDeploymentPlan(plan, loader, camp); AssemblyTemplateInstantiator instantiator = CampUtils.getInstantiator(at); if (instantiator instanceof AssemblyTemplateSpecInstantiator) { return ((AssemblyTemplateSpecInstantiator) instantiator) .createApplicationSpec(at, camp, loader); } else { // The unknown instantiator can create the app (Assembly), but not a spec. // Currently, all brooklyn plans should produce the above. if (at.getPlatformComponentTemplates() == null || at.getPlatformComponentTemplates().isEmpty()) { if (at.getCustomAttributes().containsKey("brooklyn.catalog")) throw new IllegalArgumentException( "Unrecognized application blueprint format: expected an application, not a brooklyn.catalog"); throw new PlanNotRecognizedException( "Unrecognized application blueprint format: no services defined"); } // map this (expected) error to a nicer message throw new PlanNotRecognizedException("Unrecognized application blueprint format"); } } catch (Exception e) { // TODO how do we figure out that the plan is not supported vs. invalid to wrap in a // PlanNotRecognizedException? if (log.isDebugEnabled()) log.debug("Failed to create entity from CAMP spec:\n" + plan, e); throw Exceptions.propagate(e); } }
protected void onUpdated() { try { emit(targetSensor, compute()); } catch (Throwable t) { LOG.warn("Error calculating and setting aggregate for enricher " + this, t); throw Exceptions.propagate(t); } }
private EntitySpec<? extends Application> createEntitySpecForApplication(String potentialYaml) { try { return EntityManagementUtils.createEntitySpecForApplication(mgmt(), potentialYaml); } catch (Exception e) { // An IllegalArgumentException for creating the entity spec gets wrapped in a ISE, and // possibly a Compound. // But we want to return a 400 rather than 500, so ensure we throw IAE. IllegalArgumentException iae = (IllegalArgumentException) Exceptions.getFirstThrowableOfType(e, IllegalArgumentException.class); if (iae != null) { throw new IllegalArgumentException("Cannot create spec for app: " + iae.getMessage(), e); } else { throw Exceptions.propagate(e); } } }
public void waitForImage(String imageName) { try { CountDownLatch latch = images.get(imageName); if (latch != null) latch.await(15, TimeUnit.MINUTES); } catch (InterruptedException ie) { throw Exceptions.propagate(ie); } }
/** * 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 InetAddress getAddress() { String address = getOwner().sensors().get(Attributes.ADDRESS); try { return InetAddress.getByName(address); } catch (UnknownHostException e) { throw Exceptions.propagate(e); } }
private void copy(InputStream in, File tmpJar) { try { OutputStream out = new FileOutputStream(tmpJar); ByteStreams.copy(in, out); Streams.closeQuietly(in); Streams.closeQuietly(out); } catch (Exception e) { throw Exceptions.propagate(e); } }
@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(); }
@Override public InetAddress getNextAgentAddress(String agentId) { Entity agent = getManagementContext().getEntityManager().getEntity(agentId); String address = agent.sensors().get(CalicoNode.DOCKER_HOST).sensors().get(Attributes.SUBNET_ADDRESS); try { return InetAddress.getByName(address); } catch (UnknownHostException uhe) { throw Exceptions.propagate(uhe); } }
@Override public boolean apply(Exception input) { @SuppressWarnings("ThrowableResultOfMethodCallIgnored") AWSResponseException exception = Exceptions.getFirstThrowableOfType(input, AWSResponseException.class); if (exception != null) { String code = exception.getError().getCode(); return AWS_ERRORS_TO_RETRY.contains(code); } return false; }
/** * runs the tasks needed to start, wrapped by setting {@link Attributes#SERVICE_STATE_EXPECTED} * appropriately */ public void start(Collection<? extends Location> locations) { ServiceStateLogic.setExpectedState(entity(), Lifecycle.STARTING); try { startInLocations(locations); DynamicTasks.waitForLast(); ServiceStateLogic.setExpectedState(entity(), Lifecycle.RUNNING); } catch (Throwable t) { ServiceStateLogic.setExpectedState(entity(), Lifecycle.ON_FIRE); throw Exceptions.propagate(t); } }
@Override public void close() throws IOException { LOG.info("Close called on Docker host {}: {}", machine, this); try { machine.close(); } catch (Exception e) { LOG.info("{}: Closing Docker host: {}", e.getMessage(), this); throw Exceptions.propagate(e); } finally { LOG.info("Docker host closed: {}", this); } }
@Override public void close() throws IOException { LOG.debug("Close called on Marathon task: {}", this); try { if (marathonTask.sensors().get(MarathonTask.SERVICE_UP)) { LOG.info("Stopping Marathon task entity for {}: {}", this, marathonTask); marathonTask.stop(); } LOG.info("Marathon task closed: {}", this); } catch (Exception e) { LOG.warn("Error closing Marathon task {}: {}", this, e.getMessage()); throw Exceptions.propagate(e); } }
@Override public void onManagementStarting() { super.onManagementStarting(); sensors().set(TOPIC_NAME, getName()); try { String virtualHost = getParent().getVirtualHost(); exchange = new ObjectName( format( "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=\"%s\",name=\"%s\",ExchangeType=topic", virtualHost, getExchangeName())); } catch (MalformedObjectNameException e) { throw Exceptions.propagate(e); } }
/** builds remote keystores, stores config keys/certs, and copies necessary files across */ public void install() { try { // build truststore and keystore FluentKeySigner signer = getBrooklynRootSigner(); KeyPair jmxAgentKey = SecureKeys.newKeyPair(); X509Certificate jmxAgentCert = signer.newCertificateFor("jmxmp-agent", jmxAgentKey); agentKeyStore = SecureKeys.newKeyStore(); agentKeyStore.setKeyEntry( "jmxmp-agent", jmxAgentKey.getPrivate(), // TODO jmx.ssl.agent.keyPassword "".toCharArray(), new Certificate[] {jmxAgentCert}); ByteArrayOutputStream agentKeyStoreBytes = new ByteArrayOutputStream(); agentKeyStore.store( agentKeyStoreBytes, // TODO jmx.ssl.agent.keyStorePassword "".toCharArray()); agentTrustStore = SecureKeys.newKeyStore(); agentTrustStore.setCertificateEntry("brooklyn", getJmxAccessCert()); ByteArrayOutputStream agentTrustStoreBytes = new ByteArrayOutputStream(); agentTrustStore.store(agentTrustStoreBytes, "".toCharArray()); // install the truststore and keystore and rely on JmxSupport to install the agent Tasks.setBlockingDetails("Copying keystore and truststore to the server."); try { jmxSupport .getMachine() .get() .copyTo( new ByteArrayInputStream(agentKeyStoreBytes.toByteArray()), getJmxSslKeyStoreFilePath()); jmxSupport .getMachine() .get() .copyTo( new ByteArrayInputStream(agentTrustStoreBytes.toByteArray()), getJmxSslTrustStoreFilePath()); } finally { Tasks.resetBlockingDetails(); } } catch (Exception e) { throw Exceptions.propagate(e); } }
/** * 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"); }
private <T> T resolve(ConfigKey<T> key, Object value) { Object transformed = transform(key, value); Object result; if (transformed instanceof DeferredSupplier) { ExecutionContext exec = mgmt.getServerExecutionContext(); try { result = Tasks.resolveValue(transformed, key.getType(), exec); } catch (ExecutionException | InterruptedException e) { throw Exceptions.propagate(e); } } else { result = transformed; } return TypeCoercions.coerce(result, key.getTypeToken()); }
@Override public List<Application> rebind( ClassLoader classLoaderO, RebindExceptionHandler exceptionHandlerO, ManagementNodeState modeO) { final ClassLoader classLoader = classLoaderO != null ? classLoaderO : managementContext.getCatalogClassLoader(); final RebindExceptionHandler exceptionHandler = exceptionHandlerO != null ? exceptionHandlerO : RebindExceptionHandlerImpl.builder() .danglingRefFailureMode(danglingRefFailureMode) .danglingRefQuorumRequiredHealthy(danglingRefsQuorumRequiredHealthy) .rebindFailureMode(rebindFailureMode) .addConfigFailureMode(addConfigFailureMode) .addPolicyFailureMode(addPolicyFailureMode) .loadPolicyFailureMode(loadPolicyFailureMode) .build(); final ManagementNodeState mode = modeO != null ? modeO : getRebindMode(); if (mode != ManagementNodeState.MASTER && mode != ManagementNodeState.HOT_STANDBY && mode != ManagementNodeState.HOT_BACKUP) throw new IllegalStateException( "Must be either master or hot standby/backup to rebind (mode " + mode + ")"); ExecutionContext ec = BasicExecutionContext.getCurrentExecutionContext(); if (ec == null) { ec = managementContext.getServerExecutionContext(); Task<List<Application>> task = ec.submit( new Callable<List<Application>>() { @Override public List<Application> call() throws Exception { return rebindImpl(classLoader, exceptionHandler, mode); } }); try { return task.get(); } catch (Exception e) { throw Exceptions.propagate(e); } } else { return rebindImpl(classLoader, exceptionHandler, mode); } }