Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
24be93a
Allow custom message and more user information for safe restarts
meiswjn Nov 10, 2022
dbf0194
Merge branch 'master' into feature/improve-safe-restart-messages
meiswjn Nov 10, 2022
3c4b989
Fix linting
meiswjn Nov 11, 2022
4beaa7b
Merge branch 'feature/improve-safe-restart-messages' of https://githu…
meiswjn Nov 11, 2022
7121f6d
Fix linter issues and deprecations
meiswjn Nov 11, 2022
9980d18
Minor changes to formulations and style
meiswjn Nov 11, 2022
feaf3a1
Minor changes to formulations and style
meiswjn Nov 11, 2022
4fc22a2
Fix CI issues
meiswjn Nov 16, 2022
b5b35f5
Merge branch 'master' into feature/improve-safe-restart-messages
meiswjn Nov 16, 2022
650eed0
Use TODO tag in javadoc since-param
meiswjn Nov 16, 2022
a344b08
Merge branch 'jenkinsci:master' into feature/improve-safe-restart-mes…
meiswjn Nov 16, 2022
99d5ed6
Merge branch 'feature/improve-safe-restart-messages' of https://githu…
meiswjn Nov 16, 2022
c7f7795
Merge branch 'master' into feature/improve-safe-restart-messages
meiswjn Nov 18, 2022
bcbffe1
Restrict isPreparingSafeRestart()
meiswjn Nov 18, 2022
8635553
Merge branch 'master' into feature/improve-safe-restart-messages
NotMyFault Jan 13, 2023
fb4eecd
Merge branch 'master' into feature/improve-safe-restart-messages
meiswjn Jan 16, 2023
402b30c
Remove duplicate code
meiswjn Jan 16, 2023
6e1b715
Merge branch 'feature/improve-safe-restart-messages' of https://githu…
meiswjn Jan 16, 2023
d4fe2b7
Add conditional jelly tag for safe restart
meiswjn Jan 17, 2023
5abd8c0
Adapt translation
meiswjn Jan 17, 2023
0f1fba9
Merge branch 'master' into feature/improve-safe-restart-messages
meiswjn Jan 17, 2023
8a4ff7c
Fix spotbugs and checkstyle
meiswjn Jan 17, 2023
ea7bc73
Merge branch 'feature/improve-safe-restart-messages' of https://githu…
meiswjn Jan 17, 2023
b0178b1
Another try for spotbugs null path
meiswjn Jan 18, 2023
25ce12e
Another try for spotbugs null path
meiswjn Jan 18, 2023
12e0483
Apply suggestions from code review
meiswjn Jan 18, 2023
09243fc
Adapt comments, messages and translations
meiswjn Jan 18, 2023
1e5074e
Adapt translation
meiswjn Jan 18, 2023
989d836
Update translations and move messages to dedicated file
meiswjn Jan 19, 2023
7f792a3
Apply suggestions from @timja
meiswjn Feb 2, 2023
5c4b20f
Merge branch 'feature/improve-safe-restart-messages' of https://githu…
meiswjn Feb 2, 2023
0ec3323
Fix message display logic
meiswjn Feb 2, 2023
75710c0
Use pre-defined colors
meiswjn Feb 2, 2023
612aa46
Update core/src/main/resources/hudson/util/HudsonIsRestarting/index_d…
meiswjn Feb 2, 2023
f961cd7
Replace br tag with css
meiswjn Feb 2, 2023
6b16167
Merge branch 'master' into feature/improve-safe-restart-messages
meiswjn Feb 2, 2023
33681e1
Use pre-defined color
meiswjn Feb 2, 2023
c9dd18d
Merge branch 'feature/improve-safe-restart-messages' of https://githu…
meiswjn Feb 2, 2023
326ebfb
Apply yarn fix
meiswjn Feb 2, 2023
67b92a2
Fix spotbugs
meiswjn Feb 2, 2023
9446037
Add SafeRestart CLI Command
meiswjn Feb 13, 2023
c6ffe16
Merge branch 'master' into feature/improve-safe-restart-messages
meiswjn Feb 13, 2023
ebb285d
Fix spotbugs issues
meiswjn Feb 14, 2023
bd250a2
Merge branch 'feature/improve-safe-restart-messages' of https://githu…
meiswjn Feb 14, 2023
4779b46
Update SafeRestartCommand.java
meiswjn Feb 21, 2023
459ec06
Update SafeRestartCommand.java
meiswjn Feb 21, 2023
8571d73
Merge branch 'master' into feature/improve-safe-restart-messages
meiswjn Feb 21, 2023
773b1bd
Update SafeRestartCommand.java
meiswjn Feb 21, 2023
2d82089
Merge branch 'master' into feature/improve-safe-restart-messages
NotMyFault Mar 25, 2023
7730051
Merge branch 'master' into feature/improve-safe-restart-messages
timja Apr 21, 2023
f11d5eb
Merge branch 'master' into feature/improve-safe-restart-messages
daniel-beck May 12, 2023
66900a3
Merge branch 'jenkinsci:master' into feature/improve-safe-restart-mes…
meiswjn May 22, 2023
de78fce
chore: answer review comments
meiswjn May 22, 2023
1553c03
fix: undo translation change
meiswjn May 23, 2023
b80928c
Improve UI
timja May 23, 2023
b6f78bb
UI improvements (and simplified translating of page)
timja May 23, 2023
e177791
Merge branch 'master' into feature/improve-safe-restart-messages
NotMyFault Jun 8, 2023
8b657f4
Merge branch 'master' into feature/improve-safe-restart-messages
meiswjn Jun 23, 2023
85dc1bd
chore: fix description
meiswjn Jun 29, 2023
23107ec
Merge branch 'master' into feature/improve-safe-restart-messages
NotMyFault Jun 30, 2023
1bee860
Merge branch 'master' into feature/improve-safe-restart-messages
meiswjn Jul 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 88 additions & 20 deletions core/src/main/java/jenkins/model/Jenkins.java
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@
import jenkins.security.stapler.StaplerFilteredActionListener;
import jenkins.security.stapler.TypedFilter;
import jenkins.slaves.WorkspaceLocator;
import jenkins.util.JenkinsIsSafeRestarting;
import jenkins.util.JenkinsJVM;
import jenkins.util.Listeners;
import jenkins.util.SystemProperties;
Expand Down Expand Up @@ -482,6 +483,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve

@CheckForNull
private transient volatile QuietDownInfo quietDownInfo;

Comment thread
meiswjn marked this conversation as resolved.
private transient volatile boolean terminating;
@GuardedBy("Jenkins.class")
private transient boolean cleanUpStarted;
Expand Down Expand Up @@ -2923,6 +2925,18 @@ public boolean isQuietingDown() {
return quietDownInfo != null;
}

/**
* Returns if the quietingDown is a safe restart.
* @since TODO
*/
public boolean isPreparingSafeRestart() {
Comment thread
meiswjn marked this conversation as resolved.
if (quietDownInfo == null) {
return false;
}
return quietDownInfo.isSafeRestart();

}

/**
* Returns quiet down reason if it was indicated.
* @return
Expand All @@ -2933,7 +2947,7 @@ public boolean isQuietingDown() {
@CheckForNull
public String getQuietDownReason() {
final QuietDownInfo info = quietDownInfo;
return info != null ? info.reason : null;
return info != null ? info.message : null;
}

/**
Expand Down Expand Up @@ -4070,7 +4084,7 @@ public synchronized HttpRedirect doQuietDown() {
*
* @param block Block until the system really quiets down and no builds are running
* @param timeout If non-zero, only block up to the specified number of milliseconds
* @deprecated since 2.267; use {@link #doQuietDown(boolean, int, String)} instead.
* @deprecated since 2.267; use {@link #doQuietDown2(boolean, int, String, boolean)} instead.
Comment thread
meiswjn marked this conversation as resolved.
Outdated
*/
@Deprecated
public synchronized HttpRedirect doQuietDown(boolean block, int timeout) {
Expand All @@ -4086,16 +4100,33 @@ public synchronized HttpRedirect doQuietDown(boolean block, int timeout) {
*
* @param block Block until the system really quiets down and no builds are running
* @param timeout If non-zero, only block up to the specified number of milliseconds
* @param reason Quiet reason that will be visible to user
* @since 2.267
* @param message Quiet reason that will be visible to user
* @deprecated since TODO; use {@link #doQuietDown2(boolean, int, String, boolean)} instead.
*/
@RequirePOST
@Deprecated
public HttpRedirect doQuietDown(@QueryParameter boolean block,
@QueryParameter int timeout,
@QueryParameter @CheckForNull String reason) throws InterruptedException, IOException {
@QueryParameter @CheckForNull String message) throws InterruptedException, IOException {

return doQuietDown2(block, timeout, message, false);
}

/**
* Quiet down Jenkins - preparation for a restart
*
* @param block Block until the system really quiets down and no builds are running
* @param timeout If non-zero, only block up to the specified number of milliseconds
* @param message Quiet reason that will be visible to user
* @param safeRestart If the quietDown is for a safeRestart
* @since TODO
*/
@RequirePOST
public HttpRedirect doQuietDown2(@QueryParameter boolean block,
Comment thread
meiswjn marked this conversation as resolved.
Outdated
@QueryParameter int timeout,
@QueryParameter @CheckForNull String message, @QueryParameter boolean safeRestart) throws InterruptedException, IOException {
Comment thread
meiswjn marked this conversation as resolved.
Outdated
synchronized (this) {
checkPermission(MANAGE);
quietDownInfo = new QuietDownInfo(reason);
quietDownInfo = new QuietDownInfo(message, safeRestart);
}
if (block) {
long waitUntil = timeout;
Expand Down Expand Up @@ -4494,16 +4525,29 @@ public void doRestart(StaplerRequest req, StaplerResponse rsp) throws IOExceptio
*
* This first replaces "app" to {@link HudsonIsRestarting}
*
* @since 1.332

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@meiswjn ⬆️

* @deprecated since TODO; use {@link #doSafeRestart2(StaplerRequest, String)} instead.
*
*/
@CLIMethod(name = "safe-restart")
@Deprecated
Comment thread
meiswjn marked this conversation as resolved.
Outdated
public HttpResponse doSafeRestart(StaplerRequest req) throws IOException, ServletException, RestartNotSupportedException {
return doSafeRestart2(req, null);
}

/**
* Queues up a restart of Jenkins for when there are no builds running, if we can.
*
* This first replaces "app" to {@link HudsonIsRestarting}
Comment thread
meiswjn marked this conversation as resolved.
Outdated
*
* @since TODO
*/
@CLIMethod(name = "safe-restart")
Comment thread
meiswjn marked this conversation as resolved.
Outdated
public HttpResponse doSafeRestart2(StaplerRequest req, @QueryParameter("message") String message) throws IOException, ServletException, RestartNotSupportedException {
checkPermission(MANAGE);
if (req != null && req.getMethod().equals("GET"))
return HttpResponses.forwardToView(this, "_safeRestart.jelly");

if (req == null || req.getMethod().equals("POST")) {
safeRestart();
safeRestart(message);
}

return HttpResponses.redirectToDot();
Expand Down Expand Up @@ -4548,12 +4592,22 @@ public void run() {

/**
* Queues up a restart to be performed once there are no builds currently running.
* @since 1.332
Comment thread
meiswjn marked this conversation as resolved.
* @deprecated since TODO; use {@link #safeRestart(String)} instead.
*/
@Deprecated
Comment thread
meiswjn marked this conversation as resolved.
Outdated
public void safeRestart() throws RestartNotSupportedException {
safeRestart(null);
}

/**
* Queues up a restart to be performed once there are no builds currently running.
* @param message the message to show to users in the shutdown banner.
* @since TODO
*/
public void safeRestart(String message) throws RestartNotSupportedException {
final Lifecycle lifecycle = restartableLifecycle();
// Quiet down so that we won't launch new builds.
quietDownInfo = new QuietDownInfo();
quietDownInfo = new QuietDownInfo(message, true);

new Thread("safe-restart thread") {
final String exitUser = getAuthentication2().getName();
Expand All @@ -4562,11 +4616,10 @@ public void run() {
try (ACLContext ctx = ACL.as2(ACL.SYSTEM2)) {

// Wait 'til we have no active executors.
doQuietDown(true, 0, null);

doQuietDown2(true, 0, message, true);
// Make sure isQuietingDown is still true.
if (isQuietingDown()) {
servletContext.setAttribute("app", new HudsonIsRestarting());
servletContext.setAttribute("app", new JenkinsIsSafeRestarting());
Comment thread
meiswjn marked this conversation as resolved.
Outdated
// give some time for the browser to load the "reloading" page
lifecycle.onStatusUpdate("Restart in 10 seconds");
Thread.sleep(TimeUnit.SECONDS.toMillis(10));
Expand Down Expand Up @@ -5742,16 +5795,31 @@ private static void _setJenkinsJVM(boolean jenkinsJVM) {
}

private static final class QuietDownInfo {

@CheckForNull
final String reason;
final String message;

@NonNull
private boolean safeRestart;

QuietDownInfo() {
this(null);
this(null, false);
}

QuietDownInfo(final String message) {
this(message, false);
}

QuietDownInfo(final String message, final boolean safeRestart) {
this.message = message;
this.safeRestart = safeRestart;
}

boolean isSafeRestart() {
return safeRestart;
}

QuietDownInfo(final String reason) {
this.reason = reason;
void setSafeRestart(boolean safeRestart) {
this.safeRestart = safeRestart;
}
}
}
48 changes: 48 additions & 0 deletions core/src/main/java/jenkins/util/JenkinsIsSafeRestarting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package jenkins.util;

import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;

import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

/**
* Model object used to display "Hudson is restarting".
* <p>
* Set this object to {@link ServletContext#setAttribute(String, Object)} "app" while
* the loading activity is taking place.
*
* @author Kohsuke Kawaguchi
*/
public class JenkinsIsSafeRestarting {
public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, InterruptedException {
rsp.setStatus(SC_SERVICE_UNAVAILABLE);
req.getView(this, "index.jelly").forward(req, rsp);
}
}
16 changes: 14 additions & 2 deletions core/src/main/resources/jenkins/model/Jenkins/_safeRestart.jelly
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,27 @@ THE SOFTWARE.
<l:main-panel>
<j:choose>
<j:when test="${app.lifecycle.canRestart()}">
<form method="post" action="safeRestart">
<form method="post" action="safeRestart2">
<f:entry title="${%Restart Message}">
<f:textbox name="message" value="${%The Jenkins Controller is restarting gently. Running jobs can continue. No new jobs are accepted.}"/>
Comment thread
meiswjn marked this conversation as resolved.
Outdated
</f:entry>
${%confirmRestart}
<f:submit value="${%Yes}" />
<f:bottomButtonBar>
<f:submit clazz="jenkins-!-destructive-color" value="${%Restart}" />
Comment thread
daniel-beck marked this conversation as resolved.
Outdated
</f:bottomButtonBar>
</form>
</j:when>
<j:otherwise>
${%Jenkins cannot restart itself as currently configured.}
</j:otherwise>
</j:choose>
<j:if test="${app.isQuietingDown()}">
<f:form method="post" action="cancelQuietDown" name="cancelRestart">
<f:bottomButtonBar>
<f:submit value="${%Cancel}" />
</f:bottomButtonBar>
</f:form>
</j:if>
</l:main-panel>
</l:layout>
</j:jelly>
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@

confirmRestart=\
Are you sure you want to restart Jenkins? \
Jenkins will restart once all running jobs are finished. \
Jenkins will restart once all running jobs are either finished. \
Comment thread
meiswjn marked this conversation as resolved.
Outdated
(Pipeline builds may prevent Jenkins from restarting for a short period of time in some cases, but if so, they will be paused at the next available opportunity and then resumed after Jenkins restarts.)
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<!--
Comment thread
meiswjn marked this conversation as resolved.
Outdated
The MIT License

Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:x="jelly:xml">
<j:new var="h" className="hudson.Functions" />
<st:statusCode value="503" /><!-- SERVICE NOT AVAILABLE -->
<st:header name="Expires" value="0" />
<st:header name="Cache-Control" value="no-cache,no-store,must-revalidate" />
<!-- response contentType header -->
<st:contentType value="text/html;charset=UTF-8" />
<!-- get default/common page variable -->
${h.initPageVariables(context)}
<x:doctype name="html" />
<html lang="${request.getLocale().toLanguageTag()}">
<head data-rooturl="${rootURL}" data-resurl="${resURL}" data-imagesurl="${imagesURL}" resURL="${resURL}">
<title>${%Restarting Jenkins}</title>
<!-- we do not want bots on this page -->
<meta name="ROBOTS" content="NOFOLLOW" />
<!-- mobile friendly layout -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="${resURL}/jsbundles/simple-page.css" type="text/css" />
<link rel="stylesheet" href="${resURL}/css/loading.css" type="text/css" />
</head>
<body>
<div class="simple-page" role="main">
<div class="modal signup">
<div class="signupIntroDefault">
<div class="logo">
<img src="${imagesURL}/svgs/logo.svg" alt="Jenkins logo" />
</div>
<h1 class="loading">
${%Please wait while the Jenkins Controller is restarting}
<span>.</span><span>.</span><span>.</span>
</h1>
<p class="restarting">
${%Your browser will reload automatically when Jenkins is ready.}
</p>
<p class="safe-restarting">
<b>${%Safe Restart}</b><br/> ${%Jobs on agents can usually continue.}
</p>
</div>
</div>
</div>
<script src="${resURL}/scripts/loading.js" type="text/javascript" />
</body>
</html>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# The MIT License
#
# Bulgarian translation: Copyright (c) 2016, Alexander Shopov <ash@kambanaria.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

Please\ wait\ while\ Jenkins\ is\ restarting=\
Изчакайте докато Jenkins рестартира
Your\ browser\ will\ reload\ automatically\ when\ Jenkins\ is\ ready.=\
Браузър ви автоматично ще презареди страницата, когато Jenkins е готов.
Loading