下面列出了怎么用hudson.model.Executor的API类实例代码及写法,或者点击链接到github查看源代码。
@Exported(inline=true)
public Container<ExecutorInfo> getExecutors() {
final List<ExecutorInfo> out = new ArrayList<>();
if (computer != null) {
for (Executor e : computer.getExecutors()) {
out.add(new ExecutorInfo(this, e));
}
}
return new Container() {
@Override
public Object get(String string) {
throw new UnsupportedOperationException("Not supported.");
}
@Override
public Iterator iterator() {
return out.iterator();
}
@Override
public Link getLink() {
return parent.rel("executors");
}
};
}
@Override
public Launcher createLauncher(TaskListener listener) {
Launcher launcher = super.createLauncher(listener);
if (template != null) {
Executor executor = Executor.currentExecutor();
if (executor != null) {
Queue.Executable currentExecutable = executor.getCurrentExecutable();
if (currentExecutable != null && executables.add(currentExecutable)) {
listener.getLogger().println(Messages.KubernetesSlave_AgentIsProvisionedFromTemplate(
ModelHyperlinkNote.encodeTo("/computer/" + getNodeName(), getNodeName()),
getTemplate().getName())
);
printAgentDescription(listener);
checkHomeAndWarnIfNeeded(listener);
}
}
}
return launcher;
}
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);
}
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();
}
}
}
}
}
private void done(Executor executor) {
final DockerSwarmComputer c = (DockerSwarmComputer) 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);
}
public Queue.Executable getCurrentBuild() {
if (!Iterables.isEmpty(getExecutors())) {
final Executor exec = getExecutors().get(0);
return exec.getCurrentExecutable() == null ? null : exec.getCurrentExecutable();
}
return null;
}
/**
* Waits until Jenkins finishes building everything, including those builds in the queue, or fail the test
* if the specified timeout milliseconds is exceeded.
*/
protected void waitUntilNoActivityUpTo(int timeout) throws Exception {
long startTime = System.currentTimeMillis();
int streak = 0;
while (true) {
Thread.sleep(100);
if (isSomethingHappening())
streak=0;
else
streak++;
if (streak>2) // the system is quiet for a while
return;
if (System.currentTimeMillis()-startTime > timeout) {
List<Executable> building = new ArrayList<Executable>();
for (Computer c : jenkins.getComputers()) {
for (Executor e : c.getExecutors()) {
if (e.isBusy())
building.add(e.getCurrentExecutable());
}
}
throw new AssertionError(String.format("Jenkins is still doing something after %dms: queue=%s building=%s",
timeout, Arrays.asList(jenkins.getQueue().getItems()), building));
}
}
}
/**
* 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) {
Queue.Executable exec = executor.getCurrentExecutable();
LOGGER.log(Level.FINE, " Computer {0} completed task {1}", new Object[] {this, exec});
// 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 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 taskAccepted(Executor executor, Queue.Task task) {
super.taskAccepted(executor, task);
LOGGER.log(Level.INFO, "[{0}]: JobName: {1}", new Object[] {this.getName(), task.getDisplayName()});
LOGGER.log(Level.INFO, "[{0}]: JobUrl: {1}", new Object[] {this.getName(), task.getUrl()});
LOGGER.log(Level.FINE, "[{0}]: taskAccepted", this);
}
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;
}
private void interruptTermKill(WorkflowRun b) throws Exception {
if (b != null) {
Executor ex = b.getExecutor();
assertNotNull(ex);
ex.interrupt();
j.waitForCompletion(b);
j.assertBuildStatus(Result.ABORTED, b);
}
}
@Override
public void taskAccepted(Executor executor, Queue.Task task) {
}
@Override
public void taskCompleted(Executor executor, Queue.Task task, long durationMS) {
this.isTaskCompleted = true;
getLogger(executor).println("Task completed: " + task.getFullDisplayName());
done(executor);
}
private PrintStream getLogger(Executor executor) {
final DockerSwarmComputer c = (DockerSwarmComputer) executor.getOwner();
return c.getListener().getLogger();
}
@Override
public void taskCompletedWithProblems(Executor executor, Queue.Task task, long durationMS, Throwable problems) {
taskCompleted(executor, task, durationMS);
}
@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");
}
private ExecutorInfo(Resource parent, Executor executor) {
this.parent = parent;
this.executor = executor;
}
/**
* {@link ComputerLauncher#afterDisconnect(SlaveComputer, TaskListener)}
* <p>
* EC2 Fleet plugin overrides this method to detect jobs which were failed because of
* EC2 instance was terminated/stopped. It could be manual stop or because of Spot marked.
* In all cases as soon as job aborted because of broken connection and slave is offline
* it will try to resubmit aborted job back to the queue, so user doesn't need to do that manually
* and another slave could take it.
* <p>
* Implementation details
* <p>
* There is no official recommendation about way how to resubmit job according to
* https://issues.jenkins-ci.org/browse/JENKINS-49707 moreover some of Jenkins code says it impossible.
* <p>
* method checks {@link SlaveComputer#getOfflineCause()} for disconnect because of EC2 instance termination
* it returns
* <code>
* result = {[email protected]} "Connection was broken: java.io.IOException:
* Unexpected termination of the channel\n\tat hudson.remoting.SynchronousCommandTransport$ReaderThread...
* cause = {[email protected]} "java.io.IOException: Unexpected termination of the channel"
* timestamp = 1561067177837
* </code>
*
* @param computer computer
* @param listener listener
*/
@Override
public void afterDisconnect(final SlaveComputer computer, final TaskListener listener) {
// according to jenkins docs could be null in edge cases, check ComputerLauncher.afterDisconnect
if (computer == null) return;
// in some multi-thread edge cases cloud could be null for some time, just be ok with that
final EC2FleetCloud cloud = ((EC2FleetNodeComputer) computer).getCloud();
if (cloud == null) {
LOGGER.warning("Edge case cloud is null for computer " + computer.getDisplayName()
+ " should be autofixed in a few minutes, if no please create issue for plugin");
return;
}
final boolean unexpectedDisconnect = computer.isOffline() && computer.getOfflineCause() instanceof OfflineCause.ChannelTermination;
if (!cloud.isDisableTaskResubmit() && unexpectedDisconnect) {
final List<Executor> executors = computer.getExecutors();
LOGGER.log(LOG_LEVEL, "Unexpected " + computer.getDisplayName()
+ " termination, resubmit");
for (Executor executor : executors) {
if (executor.getCurrentExecutable() != null) {
executor.interrupt(Result.ABORTED, new EC2TerminationCause(computer.getDisplayName()));
final Queue.Executable executable = executor.getCurrentExecutable();
// if executor is not idle
if (executable != null) {
final SubTask subTask = executable.getParent();
final Queue.Task task = subTask.getOwnerTask();
List<Action> actions = new ArrayList<>();
if (executable instanceof Actionable) {
actions = ((Actionable) executable).getActions();
}
Queue.getInstance().schedule2(task, RESCHEDULE_QUIET_PERIOD_SEC, actions);
LOGGER.log(LOG_LEVEL, "Unexpected " + computer.getDisplayName()
+ " termination, resubmit " + task + " with actions " + actions);
}
}
}
LOGGER.log(LOG_LEVEL, "Unexpected " + computer.getDisplayName()
+ " termination, resubmit finished");
} else {
LOGGER.log(LOG_LEVEL, "Unexpected " + computer.getDisplayName()
+ " termination but resubmit disabled, no actions, disableTaskResubmit: "
+ cloud.isDisableTaskResubmit() + ", offline: " + computer.isOffline()
+ ", offlineCause: " + (computer.getOfflineCause() != null ? computer.getOfflineCause().getClass() : "null"));
}
// call parent
super.afterDisconnect(computer, listener);
}
@Override
public void taskAccepted(Executor executor, Queue.Task task) {
super.taskAccepted(executor, task);
Queue.Executable exec = executor.getCurrentExecutable();
LOGGER.log(Level.FINE, " Computer {0} accepted task {1}", new Object[] {this, exec});
}
@Override
public void taskCompletedWithProblems(Executor executor, Queue.Task task, long durationMS, Throwable problems) {
super.taskCompletedWithProblems(executor, task, durationMS, problems);
Queue.Executable exec = executor.getCurrentExecutable();
LOGGER.log(Level.FINE, " Computer {0} completed task {1} with problems", new Object[] {this, exec});
}
@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);
}