From 91d6fa9dab843ccd41ea95859ac17425b8bc5c25 Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Mon, 15 Feb 2021 16:43:14 +0100 Subject: [PATCH] firmware: upgrade sets into updatelist #4500 While here the API now tells the page what it should do. We always consume updates first and then tell the user it is all well or that an upgrade is available. Errors are shown as well although when the API has a fatal issue we don't want to try to force a reaction and instead just log to console. The major upgrade needs another fold to be made even quicker than before but for today that is enough. --- .../OPNsense/Core/Api/FirmwareController.php | 48 +++++- .../mvc/app/views/OPNsense/Core/firmware.volt | 157 ++++++++++-------- 2 files changed, 132 insertions(+), 73 deletions(-) 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 be92d697b..d1150d7c6 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/FirmwareController.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/FirmwareController.php @@ -99,6 +99,7 @@ class FirmwareController extends ApiControllerBase } $packages_size = !empty($response['download_size']) ? $response['download_size'] : 0; + $upgrade_size = 0; $sets_size = 0; if (!empty($response['upgrade_packages'])) { @@ -131,7 +132,7 @@ class FirmwareController extends ApiControllerBase $download_size = $this->formatBytes($packages_size + $sets_size); - $sorted = array(); + $sorted = []; foreach ( array('new_packages', 'reinstall_packages', 'upgrade_packages', @@ -200,6 +201,32 @@ class FirmwareController extends ApiControllerBase $response['all_packages'] = $sorted; + $sorted = []; + + if (isset($response['upgrade_sets'])) { + foreach ($response['upgrade_sets'] as $value) { + if (!empty($value['size'])) { + $upgrade_size += $value['size']; + } + $sorted[$value['name']] = array( + 'reason' => gettext('upgrade'), + 'old' => empty($value['current_version']) ? + gettext('N/A') : $value['current_version'], + 'new' => $value['new_version'], + 'repository' => $value['repository'], + 'name' => $value['name'], + ); + } + } + + $upgrade_size = $this->formatBytes($upgrade_size); + + uksort($sorted, function ($a, $b) { + return strnatcasecmp($a, $b); + }); + + $response['all_sets'] = $sorted; + if (array_key_exists('connection', $response) && $response['connection'] == 'unresolved') { $response['status_msg'] = gettext('No address record found for the selected mirror.'); $response['status'] = 'error'; @@ -262,7 +289,24 @@ class FirmwareController extends ApiControllerBase gettext('This update requires a reboot.') ); } - $response['status'] = 'ok'; + $response['status'] = 'update'; + } elseif (array_key_exists('upgrade_sets', $response) && count($response['upgrade_sets'])) { + if (count($response['upgrade_sets']) == 1) { + /* keep this dynamic for template translation even though %s is always '1' */ + $response['status_msg'] = sprintf( + gettext('There is %s update available, total download size is %s.'), + count($response['upgrade_sets']), + $upgrade_size + ); + } else { + $response['status_msg'] = sprintf( + gettext('There are %s updates available, total download size is %s.'), + count($response['upgrade_sets']), + $upgrade_size + ); + } + $response['status_msg'] = sprintf( '%s %s', $response['status_msg'], gettext('This update requires multiple reboots.')); + $response['status'] = 'upgrade'; } elseif (array_key_exists('updates', $response) && $response['updates'] == 0) { $response['status_msg'] = gettext('There are no updates available on the selected mirror.'); $response['status'] = 'none'; diff --git a/src/opnsense/mvc/app/views/OPNsense/Core/firmware.volt b/src/opnsense/mvc/app/views/OPNsense/Core/firmware.volt index 166eecb5d..ac55ee145 100644 --- a/src/opnsense/mvc/app/views/OPNsense/Core/firmware.volt +++ b/src/opnsense/mvc/app/views/OPNsense/Core/firmware.volt @@ -61,19 +61,27 @@ * retrieve update status from backend */ function updateStatus() { - // update UI - $('#major-upgrade').hide(); - $('#upgrade_maj').prop('disabled', true); - $.upgrade_major_message = ''; - $.upgrade_major_version = ''; + $('#upgrade_maj').hide(); + $('#upgrade').hide(); - // request status ajaxGet('/api/core/firmware/status', {}, function (data, status){ - if (data['status'] == "ok") { + let upgrade_major_message = ''; + let upgrade_major_version = ''; + + if ('upgrade_major_message' in data) { + upgrade_major_message = data['upgrade_major_message']; + } + if ('upgrade_major_version' in data) { + upgrade_major_version = data['upgrade_major_version']; + } + + if (data['status'] == "update") { + let show_log = ''; + $.upgrade_needs_reboot = data['upgrade_needs_reboot']; - $.upgrade_show_log = ''; // show upgrade list + $('#upgrade').show(); $('#updatestatus').html(data['status_msg']); $('#updatelist > tbody').empty(); $('#updatetab > a').tab('show'); @@ -83,23 +91,64 @@ row['reason']+''+row['repository'] + ''); if (row['name'] == data['product_target'] && row['new'] != 'N/A') { - $.upgrade_show_log = row['new'].replace(/[_-].*/, ''); + show_log = row['new'].replace(/[_-].*/, ''); } }); $('#update_status_container').hide(); $('#updatelist').show(); // display the current changelog if one was found - if ($.upgrade_show_log != '') { - changelog($.upgrade_show_log); + if (show_log != '') { + changelog(show_log); } // update list so plugins sync as well (no logs) packagesInfo(false); - } else { - // ok or an error of some sort: make this official + } else if (data['status'] == "upgrade") { + if (upgrade_major_message == '') { + upgrade_major_message = '{{ lang._('This software release has reached its designated end of life.') }}'; + upgrade_major_message += ' {{ lang._('The next major release is:') }} ' + upgrade_major_version; + } + BootstrapDialog.show({ - type: data['status'] != "error" ? BootstrapDialog.TYPE_SUCCESS : BootstrapDialog.TYPE_DANGER, + type: BootstrapDialog.TYPE_WARNING, + title: '{{ lang._('Upgrade instructions') }}', + /* we trust this data, it was signed by us and secured by csrf */ + message: htmlDecode(upgrade_major_message), + buttons: [{ + label: "{{ lang._('Unlock') }}", + cssClass: 'btn-warning', + action: function (dialogRef) { + dialogRef.close(); + + // show upgrade list + $('#upgrade_maj').show(); + $('#updatestatus').html(data['status_msg']); + $('#updatelist > tbody').empty(); + $('#updatetab > a').tab('show'); + $.each(data['all_sets'], function (index, row) { + $('#updatelist > tbody').append(''+row['name']+'' + + ''+row['old']+''+row['new']+'' + + row['reason']+''+row['repository'] + ''); + }); + $('#update_status_container').hide(); + $('#updatelist').show(); + + changelog(upgrade_major_version); + } + },{ + label: "{{ lang._('Cancel') }}", + action: function (dialogRef) { + dialogRef.close(); + } + }] + }); + + // update list so plugins sync as well (all) + packagesInfo(true); + } else if (data['status'] == "error") { + BootstrapDialog.show({ + type: BootstrapDialog.TYPE_DANGER, title: "{{ lang._('Status') }}", onshow:function(dialogRef){ dialogRef.getModalBody().html(data['status_msg']); @@ -114,17 +163,27 @@ // update list so plugins sync as well (all) packagesInfo(true); - } + } else if (data['status'] == "none") { + BootstrapDialog.show({ + type: BootstrapDialog.TYPE_SUCCESS, + title: "{{ lang._('Status') }}", + onshow:function(dialogRef){ + dialogRef.getModalBody().html(data['status_msg']); + }, + buttons: [{ + label: "{{ lang._('Close') }}", + action: function(dialogRef){ + dialogRef.close(); + } + }] + }); - if ('upgrade_major_message' in data) { - $.upgrade_major_message = data['upgrade_major_message']; - } - if ('upgrade_major_version' in data) { - $.upgrade_major_version = data['upgrade_major_version']; - } - if ($.upgrade_major_version != '') { - $('#upgrade-version').text($.upgrade_major_version); - $('#major-upgrade').show(); + // update list so plugins sync as well (all) + packagesInfo(true); + } else { + // in case new responses are added + console.log('Unknown check response'); + console.log(data); } }); } @@ -134,8 +193,7 @@ */ function backend(type) { if ($.upgrade_action == 'maj') { - $("#upgrade_maj").attr("style",""); - $('#updatetab_progress').addClass("fa fa-spinner fa-pulse"); + // leave upgrade action as is } else if (type == 'check') { $.upgrade_action = 'check'; } else { @@ -308,8 +366,6 @@ } if (data['status'] == 'done') { $('#updatetab_progress').removeClass("fa fa-spinner fa-pulse"); - $('#major-upgrade').hide(); - $('#upgrade_maj').prop('disabled', true); if ($.upgrade_action == 'check') { updateStatus(); } else { @@ -608,34 +664,6 @@ $.upgrade_action = 'maj'; upgrade_ui(); }); - $('#checkupdate_maj').click(function () { - if ($.upgrade_major_message == "") { - $('#upgrade_maj').prop('disabled', false); - changelog($.upgrade_major_version); - } else { - BootstrapDialog.show({ - type:BootstrapDialog.TYPE_WARNING, - title: "{{ lang._('Upgrade instructions') }}", - /* we trust this data, it was signed by us and secured by csrf */ - message: htmlDecode($.upgrade_major_message), - buttons: [{ - label: "{{ lang._('Unlock') }}", - cssClass: 'btn-warning', - action: function (dialogRef) { - dialogRef.close(); - $('#upgrade_maj').prop('disabled', false); - changelog($.upgrade_major_version); - } - },{ - label: "{{ lang._('Cancel') }}", - action: function (dialogRef) { - dialogRef.close(); - } - }] - }); - packagesInfo(true); - } - }); // populate package information packagesInfo(true); @@ -794,20 +822,6 @@ }
-
- -