Commit 5fc6cd1b authored by Franco Fichtner's avatar Franco Fichtner

firmware: major upgrade through GUI and Cron improvements

(cherry picked from commit 7e7af55d)
(cherry picked from commit 70253d94)
(cherry picked from commit 0502860e)
(cherry picked from commit 386ea4f4)
(cherry picked from commit 5198b7d4)
(cherry picked from commit b73c0e7d)
(cherry picked from commit 4f88f025)
(cherry picked from commit 650254c1)
(cherry picked from commit e9f999d0)
(cherry picked from commit 5f5e438f)
(cherry picked from commit 5daf7785)
(cherry picked from commit f83f556a)
(cherry picked from commit 39710372)
(cherry picked from commit 321c46c4)
(cherry picked from commit 6a745665)
(cherry picked from commit c985c5d5)
(cherry picked from commit d80cb40a)
(cherry picked from commit 29899040)
(cherry picked from commit ebdc35c5)
(cherry picked from commit 951ea35c)
(cherry picked from commit 93072dd8)
(cherry picked from commit a42e3b68)
parent 9374b8ad
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
/usr/local/etc/pkg/fingerprints/OPNsense/revoked/pkg.opnsense.org.20160630 /usr/local/etc/pkg/fingerprints/OPNsense/revoked/pkg.opnsense.org.20160630
/usr/local/etc/pkg/fingerprints/OPNsense/trusted/opnsense-update.deciso.com.20160725 /usr/local/etc/pkg/fingerprints/OPNsense/trusted/opnsense-update.deciso.com.20160725
/usr/local/etc/pkg/fingerprints/OPNsense/trusted/pkg.opnsense.org.20161210 /usr/local/etc/pkg/fingerprints/OPNsense/trusted/pkg.opnsense.org.20161210
/usr/local/etc/pkg/fingerprints/OPNsense/trusted/pkg.opnsense.org.20170625
/usr/local/etc/rc /usr/local/etc/rc
/usr/local/etc/rc.backup_captiveportal /usr/local/etc/rc.backup_captiveportal
/usr/local/etc/rc.backup_dhcpleases /usr/local/etc/rc.backup_dhcpleases
......
function: "sha256"
fingerprint: "296005724e9b270b56c442ef753ccc8aa05253d8b45eaaf68b1aa7b5d24ef942"
#!/bin/sh #!/bin/sh
# Copyright (c) 2015-2016 Franco Fichtner <franco@opnsense.org> # Copyright (c) 2015-2017 Franco Fichtner <franco@opnsense.org>
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions # modification, are permitted provided that the following conditions
...@@ -30,6 +30,13 @@ set -e ...@@ -30,6 +30,13 @@ set -e
LOCKFILE="/tmp/pkg_upgrade.progress" LOCKFILE="/tmp/pkg_upgrade.progress"
PIPEFILE="/tmp/pkg_upgrade.pipe" PIPEFILE="/tmp/pkg_upgrade.pipe"
TEE="/usr/bin/tee -a" TEE="/usr/bin/tee -a"
RELEASE=
if [ "${1}" = "upgrade" -a -n "${2}" ]; then
RELEASE=${2}
elif [ "${1}" = "ALLOW_RISKY_MAJOR_UPGRADE" ]; then
RELEASE=$(cat /usr/local/opnsense/firmware-upgrade 2> /dev/null)
fi
: > ${LOCKFILE} : > ${LOCKFILE}
rm -f ${PIPEFILE} rm -f ${PIPEFILE}
...@@ -37,7 +44,7 @@ mkfifo ${PIPEFILE} ...@@ -37,7 +44,7 @@ mkfifo ${PIPEFILE}
echo "***GOT REQUEST TO UPGRADE***" >> ${LOCKFILE} echo "***GOT REQUEST TO UPGRADE***" >> ${LOCKFILE}
if [ -z "${1}" ]; then if [ -z "${RELEASE}" ]; then
# upgrade all packages if possible # upgrade all packages if possible
${TEE} ${LOCKFILE} < ${PIPEFILE} & ${TEE} ${LOCKFILE} < ${PIPEFILE} &
opnsense-update -p 2>&1 > ${PIPEFILE} opnsense-update -p 2>&1 > ${PIPEFILE}
...@@ -55,10 +62,10 @@ if [ -z "${1}" ]; then ...@@ -55,10 +62,10 @@ if [ -z "${1}" ]; then
/usr/local/etc/rc.reboot /usr/local/etc/rc.reboot
fi fi
fi fi
elif [ "${1}" = "upgrade" -a -n "${2}" ]; then else
# upgrade to a major release # upgrade to a major release
${TEE} ${LOCKFILE} < ${PIPEFILE} & ${TEE} ${LOCKFILE} < ${PIPEFILE} &
if opnsense-update -ur ${2} 2>&1 > ${PIPEFILE}; then if opnsense-update -ur ${RELEASE} 2>&1 > ${PIPEFILE}; then
echo '***REBOOT***' >> ${LOCKFILE} echo '***REBOOT***' >> ${LOCKFILE}
sleep 5 sleep 5
/usr/local/etc/rc.reboot /usr/local/etc/rc.reboot
......
...@@ -47,6 +47,7 @@ class FirmwareController extends ApiControllerBase ...@@ -47,6 +47,7 @@ class FirmwareController extends ApiControllerBase
{ {
$this->sessionClose(); // long running action, close session $this->sessionClose(); // long running action, close session
$backend = new Backend(); $backend = new Backend();
$backend->configdRun('firmware changelog fetch');
$response = json_decode(trim($backend->configdRun('firmware check')), true); $response = json_decode(trim($backend->configdRun('firmware check')), true);
if ($response != null) { if ($response != null) {
...@@ -171,13 +172,20 @@ class FirmwareController extends ApiControllerBase ...@@ -171,13 +172,20 @@ class FirmwareController extends ApiControllerBase
$backend = new Backend(); $backend = new Backend();
$response = array(); $response = array();
if ($this->request->isPost()) { if (!$this->request->isPost()) {
return $response;
}
// sanitize package name // sanitize package name
$filter = new \Phalcon\Filter(); $filter = new \Phalcon\Filter();
$filter->add('version', function ($value) { $filter->add('version', function ($value) {
return preg_replace('/[^0-9a-zA-Z\.]/', '', $value); return preg_replace('/[^0-9a-zA-Z\.]/', '', $value);
}); });
$version = $filter->sanitize($version, 'version'); $version = $filter->sanitize($version, 'version');
if ($version == 'update') {
$backend->configdRun('firmware changelog fetch');
} else {
$text = trim($backend->configdRun(sprintf('firmware changelog text %s', $version))); $text = trim($backend->configdRun(sprintf('firmware changelog text %s', $version)));
$html = trim($backend->configdRun(sprintf('firmware changelog html %s', $version))); $html = trim($backend->configdRun(sprintf('firmware changelog html %s', $version)));
if (!empty($text)) { if (!empty($text)) {
...@@ -266,12 +274,14 @@ class FirmwareController extends ApiControllerBase ...@@ -266,12 +274,14 @@ class FirmwareController extends ApiControllerBase
{ {
$backend = new Backend(); $backend = new Backend();
$response = array(); $response = array();
if ($this->request->hasPost("upgrade")) { if ($this->request->hasPost('upgrade')) {
$response['status'] = 'ok'; $response['status'] = 'ok';
if ($this->request->getPost("upgrade") == "pkg") { if ($this->request->getPost('upgrade') == 'pkg') {
$action = "firmware upgrade pkg"; $action = 'firmware upgrade pkg';
} elseif ($this->request->getPost('upgrade') == 'maj') {
$action = 'firmware upgrade maj';
} else { } else {
$action = "firmware upgrade all"; $action = 'firmware upgrade all';
} }
$response['msg_uuid'] = trim($backend->configdRun($action, true)); $response['msg_uuid'] = trim($backend->configdRun($action, true));
} else { } else {
......
...@@ -113,8 +113,12 @@ POSSIBILITY OF SUCH DAMAGE. ...@@ -113,8 +113,12 @@ POSSIBILITY OF SUCH DAMAGE.
$('#updatetab > a').tab('show'); $('#updatetab > a').tab('show');
$('#updatestatus').html("{{ lang._('Upgrading...') }}"); $('#updatestatus').html("{{ lang._('Upgrading...') }}");
$("#audit").attr("style","display:none"); $("#audit").attr("style","display:none");
$("#upgrade").attr("style",""); maj_suffix = '';
$("#upgrade_progress").addClass("fa fa-spinner fa-pulse"); if ($.upgrade_action == 'maj') {
maj_suffix = '_maj';
}
$("#upgrade" + maj_suffix).attr("style","");
$("#upgrade_progress" + maj_suffix).addClass("fa fa-spinner fa-pulse");
ajaxCall('/api/core/firmware/upgrade',{upgrade:$.upgrade_action},function() { ajaxCall('/api/core/firmware/upgrade',{upgrade:$.upgrade_action},function() {
$('#updatelist').empty(); $('#updatelist').empty();
...@@ -207,21 +211,27 @@ POSSIBILITY OF SUCH DAMAGE. ...@@ -207,21 +211,27 @@ POSSIBILITY OF SUCH DAMAGE.
/** /**
* check if a reboot is required, warn user or just upgrade * check if a reboot is required, warn user or just upgrade
*/ */
function upgrade_ui(){ function upgrade_ui()
{
if ( $.upgrade_needs_reboot == "1" ) { if ( $.upgrade_needs_reboot == "1" ) {
reboot_mgs = "{{ lang._('The firewall will reboot directly after this firmware update.') }}";
if ($.upgrade_action == 'maj') {
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 required, inform the user. // reboot required, inform the user.
BootstrapDialog.show({ BootstrapDialog.show({
type:BootstrapDialog.TYPE_WARNING, type:BootstrapDialog.TYPE_WARNING,
title: 'Reboot required', title: "{{ lang._('Reboot required') }}",
message: 'The firewall will be rebooted directly after this firmware update.', message: reboot_msg,
buttons: [{ buttons: [{
label: 'Ok', label: "{{ lang._('OK') }}",
cssClass: 'btn-warning',
action: function(dialogRef){ action: function(dialogRef){
dialogRef.close(); dialogRef.close();
upgrade(); upgrade();
} }
},{ },{
label: 'Abort', label: "{{ lang._('Abort') }}",
action: function(dialogRef){ action: function(dialogRef){
dialogRef.close(); dialogRef.close();
} }
...@@ -253,8 +263,10 @@ POSSIBILITY OF SUCH DAMAGE. ...@@ -253,8 +263,10 @@ POSSIBILITY OF SUCH DAMAGE.
$('#update_status').scrollTop($('#update_status')[0].scrollHeight); $('#update_status').scrollTop($('#update_status')[0].scrollHeight);
} }
if (data['status'] == 'done') { if (data['status'] == 'done') {
$("#upgrade_progress_maj").removeClass("fa fa-spinner fa-pulse");
$("#upgrade_progress").removeClass("fa fa-spinner fa-pulse"); $("#upgrade_progress").removeClass("fa fa-spinner fa-pulse");
$("#audit_progress").removeClass("fa fa-spinner fa-pulse"); $("#audit_progress").removeClass("fa fa-spinner fa-pulse");
$("#upgrade_maj").attr("style","display:none");
$("#upgrade").attr("style","display:none"); $("#upgrade").attr("style","display:none");
$("#audit").attr("style",""); $("#audit").attr("style","");
if ($.upgrade_action == 'pkg') { if ($.upgrade_action == 'pkg') {
...@@ -471,10 +483,40 @@ POSSIBILITY OF SUCH DAMAGE. ...@@ -471,10 +483,40 @@ POSSIBILITY OF SUCH DAMAGE.
$('#checkupdate').click(updateStatus); $('#checkupdate').click(updateStatus);
$('#upgrade').click(upgrade_ui); $('#upgrade').click(upgrade_ui);
$('#audit').click(audit); $('#audit').click(audit);
// show upgrade message if there $('#upgrade_maj').click(function () {
if ($('#message').html() != '') { $.upgrade_needs_reboot = 1;
$('#message').attr('style', ''); $.upgrade_action = 'maj';
upgrade_ui();
});
$('#checkupdate_maj').click(function () {
$("#checkupdate_progress_maj").addClass("fa fa-spinner fa-pulse");
// empty call refreshes changelogs in the background
ajaxCall('/api/core/firmware/changelog/update', {}, function () {
$("#checkupdate_progress_maj").removeClass("fa fa-spinner fa-pulse");
BootstrapDialog.show({
type:BootstrapDialog.TYPE_WARNING,
title: "{{ lang._('Upgrade instructions') }}",
message: $('#firmware-message').html(),
buttons: [{
<?php if (file_exists('/usr/local/opnsense/firmware-upgrade')): ?>
label: "{{ lang._('Unlock upgrade') }}",
cssClass: 'btn-warning',
action: function (dialogRef) {
dialogRef.close();
$("#upgrade_maj").attr("style","");
changelog($('#firmware-upgrade').text());
}
},{
<?php endif ?>
label: "{{ lang._('Close') }}",
action: function (dialogRef) {
dialogRef.close();
} }
}]
});
packagesInfo(true);
});
});
// populate package information // populate package information
packagesInfo(true); packagesInfo(true);
...@@ -600,9 +642,17 @@ POSSIBILITY OF SUCH DAMAGE. ...@@ -600,9 +642,17 @@ POSSIBILITY OF SUCH DAMAGE.
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div id="message" style="display:none" class="alert alert-warning" role="alert"><?= @file_get_contents('/usr/local/opnsense/firmware-message') ?></div> <?php if (file_exists('/usr/local/opnsense/firmware-message')): ?>
<div id="firmware-upgrade" style="display:none;"><?= @file_get_contents('/usr/local/opnsense/firmware-upgrade') ?></div>
<div id="firmware-message" style="display:none;"><?= @file_get_contents('/usr/local/opnsense/firmware-message') ?></div>
<div class="alert alert-warning" role="alert" style="min-height: 65px;">
<button class='btn btn-primary pull-right' id="upgrade_maj" style="display:none;"><i id="upgrade_progress_maj" class=""></i> {{ lang._('Upgrade now') }}</button>
<button class='btn pull-right' id="checkupdate_maj" style="margin-right: 8px;"><i id="checkupdate_progress_maj" class=""></i> {{ lang._('Check for upgrade') }}</button>
<div style="margin-top: 8px;">{{ lang._('This software release has reached its designated end of life.') }}</div>
</div>
<?php endif ?>
<div class="alert alert-info" role="alert" style="min-height: 65px;"> <div class="alert alert-info" role="alert" style="min-height: 65px;">
<button class='btn btn-primary pull-right' id="upgrade" style="display:none"><i id="upgrade_progress" class=""></i> {{ lang._('Upgrade now') }}</button> <button class='btn btn-primary pull-right' id="upgrade" style="display:none"><i id="upgrade_progress" class=""></i> {{ lang._('Update now') }}</button>
<button class='btn btn-primary pull-right' id="audit"><i id="audit_progress" class=""></i> {{ lang._('Audit now') }}</button> <button class='btn btn-primary pull-right' id="audit"><i id="audit_progress" class=""></i> {{ lang._('Audit now') }}</button>
<button class='btn btn-default pull-right' id="checkupdate" style="margin-right: 8px;"><i id="checkupdate_progress" class=""></i> {{ lang._('Check for updates')}}</button> <button class='btn btn-default pull-right' id="checkupdate" style="margin-right: 8px;"><i id="checkupdate_progress" class=""></i> {{ lang._('Check for updates')}}</button>
<div style="margin-top: 8px;" id="updatestatus">{{ lang._('Click to check for updates.')}}</div> <div style="margin-top: 8px;" id="updatestatus">{{ lang._('Click to check for updates.')}}</div>
......
...@@ -54,7 +54,7 @@ download_size="none" ...@@ -54,7 +54,7 @@ download_size="none"
itemcount=0 itemcount=0
linecount=0 linecount=0
timer=0 timer=0
timeout=30 # Wait for a maximum number of seconds to determine connection issues timeout=45 # Wait for a maximum number of seconds to determine connection issues
# File location variables # File location variables
tmp_pkg_output_file="/tmp/packages.output" tmp_pkg_output_file="/tmp/packages.output"
...@@ -63,8 +63,6 @@ tmp_pkg_update_file="/tmp/pkg_updates.output" ...@@ -63,8 +63,6 @@ tmp_pkg_update_file="/tmp/pkg_updates.output"
# Check if pkg is already runnig # Check if pkg is already runnig
pkg_running=`ps -x | grep "pkg " | grep -v "grep"` pkg_running=`ps -x | grep "pkg " | grep -v "grep"`
if [ "$pkg_running" == "" ]; then if [ "$pkg_running" == "" ]; then
# load changelogs first
/usr/local/opnsense/scripts/firmware/changelog.sh fetch
# start pkg update # start pkg update
pkg update -f > $tmp_pkg_update_file & pkg update -f > $tmp_pkg_update_file &
pkg_running="started" # Set running state to arbitrary value pkg_running="started" # Set running state to arbitrary value
......
#!/bin/sh #!/bin/sh
# Copyright (C) 2015-2016 Franco Fichtner <franco@opnsense.org> # Copyright (C) 2015-2017 Franco Fichtner <franco@opnsense.org>
# Copyright (C) 2014 Deciso B.V. # Copyright (C) 2014 Deciso B.V.
# All rights reserved. # All rights reserved.
# #
...@@ -45,6 +45,20 @@ if [ "$PACKAGE" == "all" ]; then ...@@ -45,6 +45,20 @@ if [ "$PACKAGE" == "all" ]; then
REBOOT=1 REBOOT=1
fi fi
fi fi
elif [ "$PACKAGE" == "maj" ]; then
# extract info for major upgrade
UPGRADE="/usr/local/opnsense/firmware-upgrade"
NAME=unknown
if [ -f ${UPGRADE} ]; then
NAME=$(cat ${UPGRADE})
fi
# perform first half of major upgrade
# (download all + kernel install)
if opnsense-update -ur "${NAME}" >> ${PKG_PROGRESS_FILE} 2>&1; then
REBOOT=1
fi
# second half reboots multiple times,
# but will snap the GUI back when done
elif [ "$PACKAGE" == "pkg" ]; then elif [ "$PACKAGE" == "pkg" ]; then
pkg upgrade -y $PACKAGE >> ${PKG_PROGRESS_FILE} 2>&1 pkg upgrade -y $PACKAGE >> ${PKG_PROGRESS_FILE} 2>&1
echo "*** PLEASE CHECK FOR MORE UPGRADES" echo "*** PLEASE CHECK FOR MORE UPGRADES"
......
...@@ -135,6 +135,6 @@ message:issued firmware power off ...@@ -135,6 +135,6 @@ message:issued firmware power off
[auto-update] [auto-update]
command:/usr/local/etc/rc.firmware command:/usr/local/etc/rc.firmware
description:Automatic firmware update description:Automatic firmware update
parameters: parameters:%s
type:script type:script
message:attempting automatic firmware update message:attempting automatic firmware update
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment