diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/FirmwareController.php b/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/FirmwareController.php
index 8c3a5ce3faa..cbb4e282fcf 100644
--- a/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/FirmwareController.php
+++ b/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/FirmwareController.php
@@ -323,7 +323,7 @@ public function statusAction()
$response['status_msg'] = sprintf(
'%s %s',
$response['status_msg'],
- gettext('This update requires a reboot.')
+ gettext('This update requires a reboot/ power off.')
);
}
$response['status_reboot'] = $active_reboot;
@@ -466,12 +466,15 @@ public function updateAction()
if ($this->request->isPost()) {
$this->getLogger('audit')->notice(sprintf("[Firmware] User %s executed a firmware update", $this->getUserName()));
$backend->configdRun('firmware flush');
- $response['msg_uuid'] = trim($backend->configdRun('firmware update', true));
+
+ $cmd = 'firmware update';
+ if ($this->request->getPost('shutdown') === '1') {
+ $cmd .= ' shutdown';
+ }
+
+ $response['msg_uuid'] = trim($backend->configdRun($cmd, true));
$response['status'] = 'ok';
- } else {
- $response['status'] = 'failure';
}
-
return $response;
}
@@ -487,12 +490,15 @@ public function upgradeAction()
if ($this->request->isPost()) {
$this->getLogger('audit')->notice(sprintf("[Firmware] User %s executed a firmware upgrade", $this->getUserName()));
$backend->configdRun('firmware flush');
- $response['msg_uuid'] = trim($backend->configdRun('firmware upgrade', true));
+
+ $cmd = 'firmware upgrade';
+ if ($this->request->getPost('shutdown') === '1') {
+ $cmd .= ' shutdown';
+ }
+
+ $response['msg_uuid'] = trim($backend->configdRun($cmd, true));
$response['status'] = 'ok';
- } else {
- $response['status'] = 'failure';
}
-
return $response;
}
@@ -769,6 +775,8 @@ public function upgradestatusAction()
$result['status'] = 'done';
} elseif (strpos($cmd_result, '***REBOOT***') !== false) {
$result['status'] = 'reboot';
+ } elseif (strpos($cmd_result, '***POWER OFF***') !== false) {
+ $result['status'] = 'shutdown';
}
return $result;
diff --git a/src/opnsense/mvc/app/views/OPNsense/Core/firmware.volt b/src/opnsense/mvc/app/views/OPNsense/Core/firmware.volt
index 7acd66bd63d..0322bc1116f 100644
--- a/src/opnsense/mvc/app/views/OPNsense/Core/firmware.volt
+++ b/src/opnsense/mvc/app/views/OPNsense/Core/firmware.volt
@@ -131,8 +131,11 @@
/**
* perform backend action and install poller to update status
*/
- function backend(type) {
+ function backend(type, data) {
$.upgrade_check = type == 'check';
+ if (data === undefined) {
+ data = {};
+ }
$('#update_status').html('');
$('#updatelist').hide();
@@ -140,7 +143,7 @@
$('#updatetab > a').tab('show');
$('#updatetab_progress').addClass("fa fa-spinner fa-pulse");
- ajaxCall('/api/core/firmware/' + type, {}, function () {
+ ajaxCall('/api/core/firmware/' + type, data, function () {
setTimeout(trackStatus, 500);
});
}
@@ -247,21 +250,43 @@
if (major === true) {
reboot_msg = "{{ lang._('The firewall will download all firmware sets and reboot multiple times for this upgrade. All operating system files and packages will be reinstalled as a consequence. This may take several minutes to complete.') }}";
}
+ reboot_msg += '
';
// reboot required, inform the user.
+ let countdownSeconds = 30;
+ let countdownTimer = null;
BootstrapDialog.show({
type:BootstrapDialog.TYPE_WARNING,
- title: "{{ lang._('Reboot required') }}",
+ title: "{{ lang._('Reboot/ Power off required') }}",
message: reboot_msg,
+ onshown: function(dialogRef) {
+ let $btn = dialogRef.getButton('btn-reboot');
+ countdownTimer = setInterval(function () {
+ countdownSeconds--;
+ $btn.text('{{ lang._("Confirm") }} (' + countdownSeconds + ')');
+ if (countdownSeconds <= 0) {
+ clearInterval(countdownTimer);
+ $btn.trigger('click');
+ }
+ }, 1000);
+ },
+ onhidden: function() {
+ if (countdownTimer) clearInterval(countdownTimer);
+ },
buttons: [{
- label: "{{ lang._('OK') }}",
+ id: 'btn-reboot',
+ label: '{{ lang._("Confirm") }} (' + countdownSeconds + ')',
cssClass: 'btn-warning',
action: function(dialogRef){
+ if (countdownTimer) clearInterval(countdownTimer);
+ let doShutdown = $('#upgrade_shutdown_cb').is(':checked') ? '1' : '0';
dialogRef.close();
- backend(major === true ? 'upgrade' : 'update');
+ backend(major === true ? 'upgrade' : 'update', {'shutdown': doShutdown});
}
},{
label: "{{ lang._('Cancel') }}",
action: function(dialogRef){
+ if (countdownTimer) clearInterval(countdownTimer);
dialogRef.close();
}
}]
@@ -314,6 +339,14 @@
setTimeout(rebootWait, 45000);
},
});
+ } else if (data['status'] == 'shutdown') {
+ BootstrapDialog.show({
+ type:BootstrapDialog.TYPE_INFO,
+ title: "{{ lang._('Shutting down after update') }}",
+ closable: false,
+ message: "{{ lang._('The system is shutting down. You chose to power off instead of reboot. The system will need to be started manually.') }}" +
+ ' ',
+ });
} else {
// schedule next poll
setTimeout(trackStatus, 500);
@@ -848,7 +881,7 @@
-