/** Common implementation for stop in parent nodes; just invokes stop on all children of the entity */ public static void stop(Entity e) { log.debug("Stopping entity "+e); DynamicTasks.queueIfPossible(stoppingChildren(e)).orSubmitAsync(e).getTask().getUnchecked(); if (log.isDebugEnabled()) log.debug("Stopped entity "+e); }
/** Common implementation for restart in parent nodes; just invokes restart on all children of the entity */ public static void restart(Entity e) { log.debug("Restarting entity "+e); DynamicTasks.queueIfPossible(restartingChildren(e)).orSubmitAsync(e).getTask().getUnchecked(); if (log.isDebugEnabled()) log.debug("Restarted entity "+e); }
@Override public Entity addExistingMachine(MachineLocation machine) { LOG.info("Adding additional machine to {}: {}", this, machine); Entity added = addNode(machine, MutableMap.of(REMOVABLE, false)); Map<String, ?> args = ImmutableMap.of("locations", ImmutableList.of(machine)); Task<Void> task = Effectors.invocation(added, Startable.START, args).asTask(); DynamicTasks.queueIfPossible(task).orSubmitAsync(this); return added; }
@Override public String execCommandTimeout(String command, Duration timeout) { AbstractSoftwareProcessSshDriver driver = (AbstractSoftwareProcessSshDriver) getDriver(); if (driver == null) { throw new NullPointerException("No driver for "+this); } ProcessTaskWrapper<String> task = SshEffectorTasks.ssh(command) .environmentVariables(driver.getShellEnvironment()) .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); } }
@Override public int execCommandStatusTimeout(String command, Duration timeout) { ProcessTaskWrapper<Object> task = SshEffectorTasks.ssh(command) .environmentVariables(((AbstractSoftwareProcessSshDriver) getDriver()).getShellEnvironment()) .returning(ScriptReturnType.EXIT_CODE) .allowingNonZeroExitCode() .machine(getMachine()) .summary(command) .newTask(); try { Object result = DynamicTasks.queueIfPossible(task) .executionContext(this) .orSubmitAsync() .asTask() .get(timeout); return (Integer) 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); } }
@Override public void undeploy(String targetName) { checkNotNull(targetName, "targetName"); targetName = FILENAME_TO_WEB_CONTEXT_MAPPER.convertDeploymentTargetNameToContext(targetName); // set it up so future nodes get the right wars if (!removeFromWarsByContext(this, targetName)) { DynamicTasks.submit(Tasks.warning("Context "+targetName+" not known at "+this+"; attempting to undeploy regardless", null), this); } log.debug("Undeploying "+targetName+" across cluster "+this+"; WARs now "+getConfig(WARS_BY_CONTEXT)); Iterable<CanDeployAndUndeploy> targets = Iterables.filter(getChildren(), CanDeployAndUndeploy.class); TaskBuilder<Void> tb = Tasks.<Void>builder().parallel(true).displayName("Undeploy "+targetName+" across cluster (size "+Iterables.size(targets)+")"); for (Entity target: targets) { tb.add(whenServiceUp(target, Effectors.invocation(target, UNDEPLOY, MutableMap.of("targetName", targetName)), "Undeploy "+targetName+" at "+target+" when ready")); } DynamicTasks.queueIfPossible(tb.build()).orSubmitAsync(this).asTask().getUnchecked(); // Update attribute Set<String> deployedWars = MutableSet.copyOf(getAttribute(DEPLOYED_WARS)); deployedWars.remove( FILENAME_TO_WEB_CONTEXT_MAPPER.convertDeploymentTargetNameToContext(targetName) ); sensors().set(DEPLOYED_WARS, deployedWars); }
@Override public void deploy(String url, String targetName) { checkNotNull(url, "url"); checkNotNull(targetName, "targetName"); targetName = FILENAME_TO_WEB_CONTEXT_MAPPER.convertDeploymentTargetNameToContext(targetName); // set it up so future nodes get the right wars addToWarsByContext(this, url, targetName); log.debug("Deploying "+targetName+"->"+url+" across cluster "+this+"; WARs now "+getConfig(WARS_BY_CONTEXT)); Iterable<CanDeployAndUndeploy> targets = Iterables.filter(getChildren(), CanDeployAndUndeploy.class); TaskBuilder<Void> tb = Tasks.<Void>builder().parallel(true).displayName("Deploy "+targetName+" to cluster (size "+Iterables.size(targets)+")"); for (Entity target: targets) { tb.add(whenServiceUp(target, Effectors.invocation(target, DEPLOY, MutableMap.of("url", url, "targetName", targetName)), "Deploy "+targetName+" to "+target+" when ready")); } DynamicTasks.queueIfPossible(tb.build()).orSubmitAsync(this).asTask().getUnchecked(); // Update attribute // TODO support for atomic sensor update (should be part of standard tooling; NB there is some work towards this, according to @aledsage) Set<String> deployedWars = MutableSet.copyOf(getAttribute(DEPLOYED_WARS)); deployedWars.add(targetName); sensors().set(DEPLOYED_WARS, deployedWars); }
protected void connectSensorsAsync() { Callable<Void> asyncTask = new Callable<Void>() { @Override public Void call() throws Exception { //blocks until available (could be a task) String mirroredEntityUrl = getConfig(MIRRORED_ENTITY_URL); Preconditions.checkNotNull(mirroredEntityUrl, "Required config: "+MIRRORED_ENTITY_URL); connectSensors(mirroredEntityUrl); return null; } }; DynamicTasks.queueIfPossible( Tasks.<Void>builder() .displayName("Start entity mirror feed") .body(asyncTask) .build()) .orSubmitAsync(this); }
public static void addExtraPublicKeys(Entity entity, SshMachineLocation location) { String extraPublicKey = location.config().get(JcloudsLocationConfig.EXTRA_PUBLIC_KEY_DATA_TO_AUTH); if (extraPublicKey == null) { // Custom location config doesn't get passed through because locations are cached for performance reasons. // As a fallback check the entity config. extraPublicKey = entity.config().get(JcloudsLocationConfig.EXTRA_PUBLIC_KEY_DATA_TO_AUTH); } if (extraPublicKey != null) { LOG.info(location + ": Adding public key " + extraPublicKey); String cmd = "mkdir -p ~/.ssh && cat <<EOF >> ~/.ssh/authorized_keys\n" + extraPublicKey + "\nEOF\n"; ProcessTaskWrapper<Integer> task = SshTasks.newSshExecTaskFactory(location, cmd) .summary("Add public key") .requiringExitCodeZero().newTask(); BrooklynTaskTags.markInessential(task); DynamicTasks.queueIfPossible(task).orSubmitAsync(entity); } } }
public void apply(final Entity source, final Object valueIgnored) { T val = (T) attribute.getValue(); if (!readiness.apply(val)) { log.warn("Skipping {} for {} because attribute {} not ready", new Object[]{description, attribute.getEntity(), attribute.getAttribute()}); return; } final Task<Void> task = TaskBuilder.<Void>builder().displayName(description).body(runnable).build(); DynamicTasks.queueIfPossible(task).orSubmitAsync(source).asTask(); if (blockUntilEnded) { final String originalBlock = Tasks.setBlockingDetails(description); try { task.blockUntilEnded(); } finally { Tasks.setBlockingDetails(originalBlock); } } } }
@Override public void redeployAll() { Map<String, String> wars = MutableMap.copyOf(getConfig(WARS_BY_CONTEXT)); String redeployPrefix = "Redeploy all WARs (count "+wars.size()+")"; log.debug("Redeplying all WARs across cluster "+this+": "+getConfig(WARS_BY_CONTEXT)); Iterable<CanDeployAndUndeploy> targetEntities = Iterables.filter(getChildren(), CanDeployAndUndeploy.class); TaskBuilder<Void> tb = Tasks.<Void>builder().parallel(true).displayName(redeployPrefix+" across cluster (size "+Iterables.size(targetEntities)+")"); for (Entity targetEntity: targetEntities) { TaskBuilder<Void> redeployAllToTarget = Tasks.<Void>builder().displayName(redeployPrefix+" at "+targetEntity+" (after ready check)"); for (String warContextPath: wars.keySet()) { redeployAllToTarget.add(Effectors.invocation(targetEntity, DEPLOY, MutableMap.of("url", wars.get(warContextPath), "targetName", warContextPath))); } tb.add(whenServiceUp(targetEntity, redeployAllToTarget.build(), redeployPrefix+" at "+targetEntity+" when ready")); } DynamicTasks.queueIfPossible(tb.build()).orSubmitAsync(this).asTask().getUnchecked(); }
@Override public Boolean execute(final boolean shouldThrow) { Task<Boolean> t = Tasks.<Boolean>builder() .body(new Callable<Boolean>() { @Override public Boolean call() { if (shouldThrow) { throw new IllegalArgumentException("exception in feed task"); } return true; } }) .build(); return DynamicTasks.queueIfPossible(t).orSubmitAsync().asTask().getUnchecked(); } }
@Override public void rebind() { super.rebind(); Task<String> task = new BasicTask<String>(new Callable<String>() { @Override public String call() { return "abc"; }}); String val = DynamicTasks.queueIfPossible(task) .orSubmitAsync() .asTask() .getUnchecked(); sensors().set(TestEntity.NAME, val); } }
@Override protected String startProcessesAtMachine(Supplier<MachineLocation> machineS) { DynamicTasks.queueIfPossible(StartableMethods.startingChildren(entity(), machineS.get())) .orSubmitAsync(entity()) .getTask() .getUnchecked(); DynamicTasks.waitForLast(); return "children started"; }
/** Common implementation for start in parent nodes; just invokes start on all children of the entity */ public static void start(Entity e, Collection<? extends Location> locations) { log.debug("Starting entity "+e+" at "+locations); DynamicTasks.queueIfPossible(startingChildren(e, locations)).orSubmitAsync(e).getTask().getUnchecked(); }
/** * Creates a MachineDetails for the given location by SSHing to the machine and * running a Bash script to gather data. Should only be called from within a * task context. If this might not be the case then use {@link * #taskForSshMachineLocation(SshMachineLocation)} instead. */ @Beta public static BasicMachineDetails forSshMachineLocationLive(SshMachineLocation location) { return TaskTags.markInessential(DynamicTasks.queueIfPossible(taskForSshMachineLocation(location)) .orSubmitAsync() .asTask()) .getUnchecked(); }
/** queues the task if possible, otherwise submits it asynchronously; returns the task for callers to * {@link Task#getUnchecked()} or {@link Task#blockUntilEnded()} */ public static <T> Task<T> submit(TaskAdaptable<T> task, Entity entity) { return queueIfPossible(task).orSubmitAsync(entity).asTask(); }
protected void stopAndRemoveNode(Entity member) { removeMember(member); try { if (member instanceof Startable) { Task<?> task = newThrottledEffectorTask(member, Startable.STOP, Collections.<String, Object>emptyMap()); DynamicTasks.queueIfPossible(task).orSubmitAsync(); task.getUnchecked(); } } finally { Entities.unmanage(member); } }
/** convenience for setting {@link #executionContext(ExecutionContext)} then submitting async */ public TaskQueueingResult<T> orSubmitAsync(Entity entity) { executionContext(entity); return orSubmitAsync(); } /** causes the task to be submitted *synchronously* if it hasn't already been submitted;
@Override public Boolean call() throws Exception { Task<Entity> first = DependentConfiguration.attributeWhenReady(cluster, DynamicCluster.FIRST); DynamicTasks.queueIfPossible(first).orSubmitAsync(); final Entity source = first.get(); final Task<Boolean> booleanTask = DependentConfiguration.attributeWhenReady(source, Attributes.SERVICE_UP); DynamicTasks.queueIfPossible(booleanTask).orSubmitAsync(); return booleanTask.get(); } })