Viewing File: /usr/local/cpanel/whostmgr/docroot/templates/graceful_reboot_landing.tmpl
[% WRAPPER 'master_templates/master.tmpl'
theme="bootstrap"
header = locale.maketext('Graceful Server Reboot')
breadcrumburl = '/scripts/graceful_reboot_landing'
app_key = 'graceful_server_reboot'
extrastyle = '
.dialog-content {
color: #333333;
}
.dialog-submit {
margin-top: 20px;
text-align: right;
}
.dialog-box {
background-color: #F3F3F3;
border: 1px solid #DCDFE3;
margin: 10px 0 10px 0;
padding: 10px;
}
.cjt-pagenotice-container {
display:none;
}
.hide {
display: none!important;
}
.show {
display: block;
}
.callout a.btn.no-margin-top {
margin-top:0;
}
'
%]
<div class="row">
<div class="col-xs-12 col-md-8">
<div id="initialMessage" class="dialog-box">
<div>
<h4>[% locale.maketext("Warning: This will reboot your system!") %]</h4>
<div class="dialog-submit">
<input id="proceedBtn" type="submit" class="btn btn-primary" value="[% locale.maketext('Proceed') %] >>">
</div>
</div>
</div>
<div id="doneRebooting" class="dialog-box hide">
<h4>[% locale.maketext("The system has been rebooted.") %]</h4>
</div>
<div id="rebootInitiated" class="dialog-box hide">
<h4>[% locale.maketext("A reboot has been initiated but the system status could not be determined.") %]</h4>
</div>
<div id="unableToReachServer" class="dialog-box hide">
<h4>[% locale.maketext("Unable to initiate a reboot. Please access the server directly to reboot it.") %]</h4>
</div>
<div id="actionMsg" class="callout callout-warning callout-top hide" role="alert">
<h4>
<i class="fas fa-spinner fa-spin" aria-hidden="true"></i>
[% locale.maketext("A reboot is now in progress …") %]
</h4>
</div>
[% IF data.kernelcare_suggestion %]
<div class="callout callout-info callout-top" role="alert">
<h4>[% data.kernelcare_suggestion.title %]</h4>
<p>
[% data.kernelcare_suggestion.details %]
<div>
<a
class="btn btn-link no-margin-top"
href="[% data.kernelcare_suggestion.link.url %]"
title="[% data.kernelcare_suggestion.link.label %]"
target="[% data.kernelcare_suggestion.link.target %]">
[% data.kernelcare_suggestion.link.label %]
<i class="fas fa-external-link-alt" aria-hidden="true"></i>
</a>
</div>
</p>
[% IF data.kernelcare_suggestion.note %]
<p><strong>[% locale.maketext('Note:') %]</strong> <em>[% data.kernelcare_suggestion.note %]</em></p>
[% END %]
</div>
[% END %]
</div>
</div>
<script>
;(() => {
'use strict';
// ======================================== UI ======================================== //
// UI elements
const domElements = {
proceedBtnEl: document.getElementById("proceedBtn"),
actionMsgEl: document.getElementById("actionMsg"),
initialMessageEl: document.getElementById("initialMessage"),
doneRebootingEl: document.getElementById("doneRebooting"),
rebootInitiatedEl: document.getElementById("rebootInitiated"),
unableToReachServerEl: document.getElementById("unableToReachServer"),
};
// UI utility functions
function disableButton(buttonEl){
buttonEl.setAttribute("disabled", true);
}
function showElement(element) {
element.classList.remove("hide");
}
function hideElement(element) {
element.classList.add("hide");
}
// UI functions
function uiShowsRebootInProgress() {
const { proceedBtnEl, actionMsgEl, initialMessageEl } = domElements;
disableButton(proceedBtnEl);
showElement(actionMsgEl);
hideElement(initialMessageEl);
}
function uiShowsRebootIsDone() {
const { actionMsgEl, doneRebootingEl } = domElements;
hideElement(actionMsgEl);
showElement(doneRebootingEl);
}
function uiShowsRebootInitiated() {
const { actionMsgEl, rebootInitiatedEl } = domElements;
hideElement(actionMsgEl);
showElement(rebootInitiatedEl);
}
function uiShowsUnableToReachServer() {
const { actionMsgEl, unableToReachServerEl } = domElements;
hideElement(actionMsgEl);
showElement(unableToReachServerEl);
}
// ======================================== Fetch ======================================== //
// Fetch utility functions
function sendError(fetchArguments, issue) {
const customError = new Error();
const initiatingReboot = !!fetchArguments.waitingOnRebootTime;
const issueIsAnError = issue instanceof Error;
if (initiatingReboot && issueIsAnError) {
customError.name = "fetchErrorCantReboot";
customError.message = `Received an error when trying to reach the server endpoint at ${fetchArguments.endpointUrl}. ${issue}`;
} else {
customError.name = "unexpectedIssue";
customError.message = "Encountered an unexpected issue.";
}
throw customError;
}
async function handleResponse(response, fetchArguments) {
const { lastrebooted } = await response.json();
const initiatingReboot = !!fetchArguments.waitingOnRebootTime;
const rebootTimeChanged = fetchArguments.rebootTime !== lastrebooted;
if (initiatingReboot || rebootTimeChanged) {
return lastrebooted;
} else {
return fetchArguments.additionalTries > 0 ? tryFetchingAgain(fetchArguments) : sendError(fetchArguments);
};
}
// Fetch functions
function tryFetchingAgain(fetchArguments) {
fetchArguments.additionalTries--;
return new Promise((resolve) => {
setTimeout(() => {
resolve(fetchData(fetchArguments));
}, fetchArguments.timeUntilNextTry);
});
}
function fetchData(fetchArguments) {
return fetch(fetchArguments.endpointUrl)
.catch((fetchError) => {
return fetchArguments.additionalTries > 0 ? tryFetchingAgain(fetchArguments) : sendError(fetchArguments, fetchError);
})
.then(response => {
const responseAfterFetchRetry = typeof response === 'string' || response === null || response === true;
if (response?.ok) {
return handleResponse(response, fetchArguments);
} else if (responseAfterFetchRetry) {
return response;
} else {
return fetchArguments.additionalTries > 0 ? tryFetchingAgain(fetchArguments) : sendError(fetchArguments);
}
});
}
// ======================================== Main ======================================== //
// Utility function for endpoint-request setup
function calculateAdditionalTries(totalMinutesToContinueRetrying, timeUntilNextTry) {
const secondsPerMinute = 60;
const millisecondsPerSecond = 1_000;
// additional tries = (minutes) * (60 seconds/minute) * (1000 milliseconds/second) / milliseconds
return (totalMinutesToContinueRetrying * secondsPerMinute * millisecondsPerSecond) / timeUntilNextTry;
}
// Endpoint-request setup functions
function checkIfServerHasRebooted(rebootTimeReportedByServer) {
// We're binding to the window so that we can override the value with something shorter during testing
window.checkFn_totalMinutesToContinueRetrying = window.checkFn_totalMinutesToContinueRetrying || 15;
window.checkFn_timeUntilNextTry = window.checkFn_timeUntilNextTry || 15_000;
const fetchArguments = {
endpointUrl: "[% cp_security_token %]/scripts/get_btime",
timeUntilNextTry: window.checkFn_timeUntilNextTry,
additionalTries: calculateAdditionalTries(window.checkFn_totalMinutesToContinueRetrying, window.rebootFn_timeUntilNextTry),
rebootTime: rebootTimeReportedByServer,
}
return fetchData(fetchArguments);
}
function rebootServer() {
// We're binding to the window so that we can override the value with something shorter during testing
window.rebootFn_totalMinutesToContinueRetrying = window.rebootFn_totalMinutesToContinueRetrying || 5;
window.rebootFn_timeUntilNextTry = window.rebootFn_timeUntilNextTry || 10_000;
const fetchArguments = {
endpointUrl: "[% cp_security_token %]/scripts/reboot_and_get_btime",
timeUntilNextTry: window.rebootFn_timeUntilNextTry,
additionalTries: calculateAdditionalTries(window.rebootFn_totalMinutesToContinueRetrying, window.rebootFn_timeUntilNextTry),
waitingOnRebootTime: true,
}
return fetchData(fetchArguments);
}
// Main function
function rebootWithPolling() {
uiShowsRebootInProgress();
rebootServer()
.then(checkIfServerHasRebooted)
.then(uiShowsRebootIsDone)
.catch((error) => {
if (error.name === "fetchErrorCantReboot") uiShowsUnableToReachServer();
else uiShowsRebootInitiated();
});
}
domElements.proceedBtnEl.addEventListener('click', rebootWithPolling);
})();
</script>
[% END -%]
Back to Directory
File Manager