public static void attachFacet(Run<?, ?> run, TaskListener listener) { final Executor executor = run.getExecutor(); if (executor == null) { return; } final Computer owner = executor.getOwner(); DockerComputer dockerComputer; if (owner instanceof DockerComputer) { dockerComputer = (DockerComputer) owner; try { DockerFingerprints.addRunFacet( createRecordFor(dockerComputer), run ); } catch (IOException | ParseException e) { listener.error("Can't add Docker fingerprint to run."); LOG.error("Can't add fingerprint to run {}", run, e); } } }
protected void done(Executor executor) { final AbstractCloudComputer<?> c = (AbstractCloudComputer) executor.getOwner(); Queue.Executable exec = executor.getCurrentExecutable(); if (executor instanceof OneOffExecutor) { LOG.debug("Not terminating {} because {} was a flyweight task", c.getName(), exec); return; } if (exec instanceof ContinuableExecutable && ((ContinuableExecutable) exec).willContinue()) { LOG.debug("not terminating {} because {} says it will be continued", c.getName(), exec); return; } LOG.debug("terminating {} since {} seems to be finished", c.getName(), exec); done(c); }
@Override public synchronized void onStarted(Run run, TaskListener listener) { JenkinsMetricProviderImpl instance = instance(); if (instance != null) { List<Timer.Context> contextList = new ArrayList<Timer.Context>(); contextList.add(instance.jenkinsJobBuildingTime.time()); Executor executor = run.getExecutor(); if (executor != null) { Computer computer = executor.getOwner(); Timer timer = instance.getOrCreateTimer(computer); contextList.add(timer.time()); } contexts.put(run, contextList); } ScheduledRate.instance().addAction(run); }
public void addAction(Run run) { Executor executor = run.getExecutor(); if (executor == null) { return; } WorkUnit workUnit = executor.getCurrentWorkUnit(); if (workUnit == null) { return; } WorkUnitContext context = workUnit.context; if (context == null) { return; } TimeInQueueAction action; synchronized (actions) { action = actions.remove(context); } if (action != null) { run.addAction(action); } }
public Result runScript(final ShellCommands commands) throws IOException, InterruptedException { Result r = Result.FAILURE; //Todo: use VitualChannel to figure out OS final String shellInterpreter = Functions.isWindows() ? "sh" : "/bin/bash"; final Run run = this.buildExecutionContext.getRun(); addExecutionInfoAction(run, commands); try { final Shell execution = new Shell("#!" + shellInterpreter + " -le \n" + commands.toShellScript()); if (this.buildExecutionContext.performStep(execution, this.listener)) { r = Result.SUCCESS; } } catch (final InterruptedException e) { r = Executor.currentExecutor().abortResult(); throw e; } finally { this.buildExecutionContext.setResult(r); } return r; }
@Override @Exported public Executor getExecutor() { final Jenkins jenkins = Jenkins.getInstance(); if (jenkins == null) { return null; } for (final Computer computer : jenkins.getComputers()) { for (final Executor executor : computer.getExecutors()) { if (isCurrent(executor)) { return executor; } } } return null; }
public void cancelSubBuilds(final PrintStream logger) { final Queue q = getJenkins().getQueue(); synchronized (q) { final int n = this.dynamicBuild.getNumber(); for (final Item i : q.getItems()) { final ParentBuildAction parentBuildAction = i.getAction(ParentBuildAction.class); if (parentBuildAction != null && this.dynamicBuild.equals(parentBuildAction.getParent())) { q.cancel(i); } } for (final DynamicSubProject c : this.dynamicBuild.getAllSubProjects()) { final DynamicSubBuild b = c.getBuildByNumber(n); if (b != null && b.isBuilding()) { final Executor exe = b.getExecutor(); if (exe != null) { logger.println(Messages.MatrixBuild_Interrupting(ModelHyperlinkNote.encodeTo(b))); exe.interrupt(); } } } } }
/** * Assign a ${@link Queue.Executable} to this OneShotSlave. By design, only one Queue.Executable can be assigned, then slave is shut down. * This method has to be called just as the ${@link Run} as been created. It run the actual launch of the executor * and use Run's ${@link hudson.model.BuildListener} as computer launcher listener to collect the startup log as part of the build. * <p> * Delaying launch of the executor until the Run is actually started allows to fail the build on launch failure, * so we have a strong 1:1 relation between a Run and it's Executor. * * @param listener */ synchronized void provision(TaskListener listener) { if (executable != null) { // already provisioned return; } final Executor executor = Executor.currentExecutor(); if (executor == null) { throw new IllegalStateException("running task without associated executor thread"); } try { realLauncher.launch(this.getComputer(), listener); final long launchTime = System.currentTimeMillis(); while (getComputer().isActuallyOffline() && TimeUnit2.SECONDS.toMillis(launchTimeout) > System.currentTimeMillis() - launchTime) { this.wait(1000); } if (getComputer().isActuallyOffline()) { provisionFailed(new IllegalStateException("Computer is offline after launch")); } } catch (Exception e) { provisionFailed(e); } executable = executor.getCurrentExecutable(); }
/** * Abort running builds when new build referencing same revision is scheduled to run */ @Override public void preCheckout(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { String abortOnRevisionId = getAbortOnRevisionId(build); // If ABORT_ON_REVISION_ID is available if (!CommonUtils.isBlank(abortOnRevisionId)) { // Create a cause of interruption PhabricatorCauseOfInterruption causeOfInterruption = new PhabricatorCauseOfInterruption(build.getUrl()); Run upstreamRun = getUpstreamRun(build); // Get the running builds that were scheduled before the current one RunList<AbstractBuild> runningBuilds = (RunList<AbstractBuild>) build.getProject().getBuilds(); for (AbstractBuild runningBuild : runningBuilds) { Executor executor = runningBuild.getExecutor(); Run runningBuildUpstreamRun = getUpstreamRun(runningBuild); // Ignore builds that were triggered by the same upstream build // Find builds triggered with the same ABORT_ON_REVISION_ID_FIELD if (runningBuild.isBuilding() && runningBuild.number < build.number && abortOnRevisionId.equals(getAbortOnRevisionId(runningBuild)) && (upstreamRun == null || runningBuildUpstreamRun == null || !upstreamRun.equals(runningBuildUpstreamRun)) && executor != null) { // Abort the builds executor.interrupt(Result.ABORTED, causeOfInterruption); } } } }
@Override public void taskCompleted(Executor executor, Queue.Task task, long durationMS) { LOG.debug("Computer {} taskCompleted", this); // May take the slave offline and remove it, in which case getNode() // above would return null and we'd not find our DockerSlave anymore. super.taskCompleted(executor, task, durationMS); }
@Override public void taskCompleted(Executor executor, Queue.Task task, long durationMS) { LOGGER.log(Level.FINE, " Computer " + this + " taskCompleted"); // May take the agent offline and remove it, in which case getNode() // above would return null and we'd not find our DockerSlave anymore. super.taskCompleted(executor, task, durationMS); }
@Override public String getToolHome(Node node, ToolInstallation installation, TaskListener log) throws IOException, InterruptedException { final Executor currentExecutor = Executor.currentExecutor(); if (installation.getHome() == null && currentExecutor != null && currentExecutor.getOwner().getNode() instanceof DeployNowSlave) { return "/notmaven"; } else { return null; } }
private void done(Executor executor) { final DockerComputer c = (DockerComputer) executor.getOwner(); Queue.Executable exec = executor.getCurrentExecutable(); if (exec instanceof ContinuableExecutable && ((ContinuableExecutable) exec).willContinue()) { LOGGER.log(Level.FINE, "not terminating {0} because {1} says it will be continued", new Object[]{c.getName(), exec}); return; } LOGGER.log(Level.FINE, "terminating {0} since {1} seems to be finished", new Object[]{c.getName(), exec}); done(c); }
@Override public Executor getOneOffExecutor() { for (final Computer c : Jenkins.getInstance().getComputers()) { for (final Executor e : c.getOneOffExecutors()) { if (isCurrent(e)) return e; } } return null; }
/** * Returns the current {@link Node} on which we are building. */ private final Node getCurrentNode() { Executor executor = Executor.currentExecutor(); if (executor != null) { Computer owner = executor.getOwner(); if (owner != null) { return owner.getNode(); } } return null; }
/** * Waits until Hudson finishes building everything, including those in the queue, or fail the test * if the specified timeout milliseconds is * * Ported from Jenkins 1.479. */ public void waitUntilNoActivityUpTo(int timeout) throws Exception { long startTime = System.currentTimeMillis(); int streak = 0; while (true) { Thread.sleep(10); if (isSomethingHappening()) streak=0; else streak++; if (streak>5) // the system is quiet for a while return; if (System.currentTimeMillis()-startTime > timeout) { List<Queue.Executable> building = new ArrayList<Queue.Executable>(); for (Computer c : jenkins.getComputers()) { for (Executor e : c.getExecutors()) { if (e.isBusy()) building.add(e.getCurrentExecutable()); } } throw new AssertionError(String.format("Hudson is still doing something after %dms: queue=%s building=%s", timeout, Arrays.asList(jenkins.getQueue().getItems()), building)); } } }
@Override public void taskAccepted(Executor executor, Queue.Task task) { super.taskAccepted(executor, task); LOGGER.log(Level.INFO, " Computer " + this + ": task accepted"); }
@Override public void taskCompleted(Executor executor, Queue.Task task, long durationMS) { super.taskCompleted(executor, task, durationMS); LOGGER.log(Level.INFO, " Computer " + this + ": task completed"); }
@Override public void taskCompletedWithProblems(Executor executor, Queue.Task task, long durationMS, Throwable problems) { super.taskCompletedWithProblems(executor, task, durationMS, problems); LOGGER.log(Level.WARNING, " Computer " + this + " task completed with problems"); }
@Override public void taskAccepted(Executor executor, Queue.Task task) { super.taskAccepted(executor, task); LOG.debug("Computer {} taskAccepted", this); }
@Override public void taskCompletedWithProblems(Executor executor, Queue.Task task, long durationMS, Throwable problems) { LOG.debug("Computer {} taskCompletedWithProblems", this); super.taskCompletedWithProblems(executor, task, durationMS, problems); }
@Override public void taskAccepted(Executor executor, Queue.Task task) { }
@Override public void taskCompleted(Executor executor, Queue.Task task, long durationMS) { done(executor); }
@Override public void taskCompletedWithProblems(Executor executor, Queue.Task task, long durationMS, Throwable problems) { done(executor); }
@Override public void buildEnvironmentFor(@Nonnull Run run, @Nonnull EnvVars envs, @Nonnull TaskListener listener) throws IOException, InterruptedException { final Executor executor = run.getExecutor(); if (executor != null && executor.getOwner() instanceof DockerComputer) { final DockerComputer dockerComputer = (DockerComputer) executor.getOwner(); DockerSlave node = dockerComputer.getNode(); if (isNull(node)) { LOG.debug("{} is missing it's node, skipping...", dockerComputer.getName()); return; } final DockerNodeProperty dProp = node.getNodeProperties().get(DockerNodeProperty.class); if (dProp == null) { return; } if (dProp.isContainerIdCheck()) { listener.getLogger().println("[YAD-PLUGIN] Injecting variable: " + dProp.getContainerId()); envs.put(dProp.getContainerId(), dockerComputer.getContainerId()); } if (dProp.isCloudIdCheck()) { listener.getLogger().println("[YAD-PLUGIN] Injecting variable: " + dProp.getCloudId()); envs.put(dProp.getCloudId(), dockerComputer.getCloudId()); } if (dProp.isDockerHostCheck()) { try { //replace http:// and https:// from docker-java to tcp:// final DockerCloud cloud = dockerComputer.getCloud(); // checkfornull if (cloud != null && cloud.getConnector() != null) { final URIBuilder uriBuilder = new URIBuilder(cloud.getConnector().getServerUrl()); if (!uriBuilder.getScheme().equals("unix")) { uriBuilder.setScheme("tcp"); } listener.getLogger().println("[YAD-PLUGIN] Injecting variable: " + dProp.getDockerHost()); envs.put(dProp.getDockerHost(), uriBuilder.toString()); } } catch (URISyntaxException e) { listener.error("Can't make variable: %s", dProp.getDockerHost(), e); LOG.error("Can't make '{}' variable: {}", dProp.getDockerHost(), e); } } } }
public static Result getInterruptStatus(Executor executor) throws IllegalAccessException { return (Result) FieldUtils.readField(executor, "interruptStatus", true); }
public static List<CauseOfInterruption> getInterruptCauses(Executor executor) throws IllegalAccessException { return (List<CauseOfInterruption>) FieldUtils.readField(executor, "causes", true); }
public synchronized int abortRunning(int number) throws IllegalAccessException { int aborted = 0; Computer[] computers = getJenkinsInstance().getComputers(); for (Computer computer : computers) { if (isNull(computer)) { continue; } List<Executor> executors = computer.getExecutors(); executors.addAll(computer.getOneOffExecutors()); for (Executor executor : executors) { if (isNull(executor) || !executor.isBusy() || nonNull(executor.getCauseOfDeath()) || !getInterruptCauses(executor).isEmpty() || getInterruptStatus(executor) == Result.ABORTED) { continue; } Queue.Executable executable = executor.getCurrentExecutable(); final SubTask parent = executable.getParent(); if (!(executable instanceof Run)) { continue; } final Run executableRun = (Run) executable; if (!(parent instanceof Job)) { continue; } final Job parentJob = (Job) parent; if (!parentJob.getFullName().equals(job.getFullName())) { // name doesn't match continue; } if (executableRun.getResult() == Result.ABORTED) { // was already aborted continue; } if (executableRun instanceof MatrixRun) { // the whole MatrixBuild will be aborted continue; } // if (executable instanceof MatrixBuild) { // final MatrixBuild executable1 = (MatrixBuild) executable; // executable1.doStop() // } final GitHubPRCause causeAction = (GitHubPRCause) executableRun.getCause(GitHubPRCause.class); if (nonNull(causeAction) && causeAction.getNumber() == number) { LOGGER.info("Aborting '{}', by interrupting '{}'", executableRun, executor); executor.interrupt(Result.ABORTED, new NewPRInterruptCause()); aborted++; } } } return aborted; }
@Override public void taskAccepted(Executor executor, Queue.Task task) { super.taskAccepted(executor, task); LOGGER.fine(" Computer " + this + " taskAccepted"); }
@Override public void taskCompletedWithProblems(Executor executor, Queue.Task task, long durationMS, Throwable problems) { super.taskCompletedWithProblems(executor, task, durationMS, problems); LOGGER.log(Level.FINE, " Computer " + this + " taskCompletedWithProblems"); }
@Override public void taskAccepted(final Executor executor, final Queue.Task task) { super.taskAccepted(executor, task); LOG.fine(format("Docker task accepted: task=%s", task.getName())); _hasAcceptedJob = true; }
@Override public void taskCompleted(final Executor executor, final Queue.Task task, final long durationMS) { super.taskCompleted(executor, task, durationMS); LOG.fine(format("Docker task completed: task=%s", task.getName())); terminate(); }
@Override public void taskCompletedWithProblems(final Executor executor, final Queue.Task task, final long durationMS, final Throwable problems) { super.taskCompletedWithProblems(executor, task, durationMS, problems); LOG.log(WARNING, format("Docker task completed with problems: task=%s", task.getName()), problems); terminate(); }
@Override public void taskCompleted(Executor executor, Queue.Task task, long durationMS) { checkLater(); }
@Override public void taskCompletedWithProblems(Executor executor, Queue.Task task, long durationMS, Throwable problems) { checkLater(); }
@Override @Exported public Executor getExecutor() { final Executor executor = super.getExecutor(); return executor == null ? getOneOffExecutor() : executor; }
private boolean isCurrent(final Executor executor) { final Executable currentExecutable = executor.getCurrentExecutable(); return currentExecutable != null && currentExecutable instanceof DbBackedBuild && this.equals(currentExecutable); }