mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-14 00:24:40 +00:00
We can now safely check packages kernel and base set version from opnsense-update. The basic idea is still that a packages set marker is included now so we can refrain from updating packages once we are crossing over a major version barrier using said packages set.
397 lines
17 KiB
Bash
Executable File
397 lines
17 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# Copyright (C) 2015-2022 Franco Fichtner <franco@opnsense.org>
|
|
# Copyright (C) 2014 Deciso B.V.
|
|
# All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions are met:
|
|
#
|
|
# 1. Redistributions of source code must retain the above copyright notice,
|
|
# this list of conditions and the following disclaimer.
|
|
#
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
|
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
# POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
# This script generates a json structured file with the following content:
|
|
#
|
|
# connection: error|unauthenticated|misconfigured|unresolved|ok
|
|
# repository: error|untrusted|unsigned|revoked|incomplete|forbidden|ok
|
|
# last_ckeck: <date_time_stamp>
|
|
# download_size: <size_of_total_downloads>[,<size_of_total_downloads>]
|
|
# new_packages: array with { name: <package_name>, version: <package_version> }
|
|
# reinstall_packages: array with { name: <package_name>, version: <package_version> }
|
|
# remove_packages: array with { name: <package_name>, version: <package_version> }
|
|
# downgrade_packages: array with { name: <package_name>, current_version: <current_version>, new_version: <new_version> }
|
|
# upgrade_packages: array with { name: <package_name>, current_version: <current_version>, new_version: <new_version> }
|
|
|
|
JSONFILE="/tmp/pkg_upgrade.json"
|
|
LOCKFILE="/tmp/pkg_upgrade.progress"
|
|
OUTFILE="/tmp/pkg_update.out"
|
|
TEE="/usr/bin/tee -a"
|
|
|
|
CUSTOMPKG=${1}
|
|
|
|
rm -f ${JSONFILE}
|
|
: > ${LOCKFILE}
|
|
|
|
base_to_reboot=
|
|
connection="error"
|
|
download_size=
|
|
force_all=
|
|
itemcount=0
|
|
kernel_to_reboot=
|
|
last_check="unknown"
|
|
linecount=0
|
|
needs_reboot="0"
|
|
packages_downgraded=
|
|
packages_new=
|
|
packages_upgraded=
|
|
product_repo="OPNsense"
|
|
repository="error"
|
|
sets_upgraded=
|
|
upgrade_needs_reboot="0"
|
|
|
|
product_suffix="-$(pluginctl -g system.firmware.type)"
|
|
if [ "${product_suffix}" = "-" ]; then
|
|
product_suffix=
|
|
fi
|
|
|
|
last_check=$(date)
|
|
os_version=$(uname -sr)
|
|
product_id=$(opnsense-version -n)
|
|
product_target=opnsense${product_suffix}
|
|
product_version=$(opnsense-version -v)
|
|
product_abi=$(opnsense-version -a)
|
|
product_xabi=$(opnsense-version -x)
|
|
|
|
if [ -n "${product_xabi}" -a "${product_abi}" != "${product_xabi}" ]; then
|
|
force_all="-f"
|
|
fi
|
|
|
|
echo "***GOT REQUEST TO CHECK FOR UPDATES***" >> ${LOCKFILE}
|
|
echo "Currently running $(opnsense-version) at $(date)" >> ${LOCKFILE}
|
|
|
|
echo -n "Fetching changelog information, please wait... " >> ${LOCKFILE}
|
|
if /usr/local/opnsense/scripts/firmware/changelog.sh fetch >> ${LOCKFILE} 2>&1; then
|
|
echo "done" >> ${LOCKFILE}
|
|
fi
|
|
|
|
: > ${OUTFILE}
|
|
(pkg update -f 2>&1) | ${TEE} ${LOCKFILE} ${OUTFILE}
|
|
|
|
# always update pkg so we can see the real updates directly
|
|
(pkg upgrade -r ${product_repo} -Uy pkg 2>&1) | ${TEE} ${LOCKFILE}
|
|
|
|
# parse early errors
|
|
if grep -q 'No address record' ${OUTFILE}; then
|
|
# DNS resolution failed
|
|
connection="unresolved"
|
|
elif grep -q 'Cannot parse configuration' ${OUTFILE}; then
|
|
# configuration error
|
|
connection="misconfigured"
|
|
elif grep -q 'Authentication error' ${OUTFILE}; then
|
|
# TLS or authentication error
|
|
connection="unauthenticated"
|
|
elif grep -q 'No trusted public keys found' ${OUTFILE}; then
|
|
# fingerprint mismatch
|
|
repository="untrusted"
|
|
connection="ok"
|
|
elif grep -q 'At least one of the certificates has been revoked' ${OUTFILE}; then
|
|
# fingerprint mismatch
|
|
repository="revoked"
|
|
connection="ok"
|
|
elif grep -q 'No signature found' ${OUTFILE}; then
|
|
# fingerprint not found
|
|
repository="unsigned"
|
|
connection="ok"
|
|
elif grep -q 'Forbidden' ${OUTFILE}; then
|
|
# access not granted
|
|
repository="forbidden"
|
|
connection="ok"
|
|
elif grep -q 'Unable to update repository' ${OUTFILE}; then
|
|
# repository not found
|
|
connection="ok"
|
|
else
|
|
# connection is still ok
|
|
connection="ok"
|
|
|
|
: > ${OUTFILE}
|
|
|
|
# now check what happens when we would go ahead
|
|
(pkg upgrade ${force_all} -Un 2>&1) | ${TEE} ${LOCKFILE} ${OUTFILE}
|
|
if [ -n "${CUSTOMPKG}" ]; then
|
|
(pkg install -Un "${CUSTOMPKG}" 2>&1) | ${TEE} ${LOCKFILE} ${OUTFILE}
|
|
elif [ "${product_id}" != "${product_target}" ]; then
|
|
(pkg install -r ${product_repo} -Un "${product_target}" 2>&1) | ${TEE} ${LOCKFILE} ${OUTFILE}
|
|
elif [ -z "$(pkg rquery %n ${product_id})" ]; then
|
|
# although this should say "to update matching" we emulate for check below as pkg does not catch this
|
|
echo "self: No packages available to install matching '${product_id}'" | ${TEE} ${LOCKFILE} ${OUTFILE}
|
|
fi
|
|
|
|
# Check for additional repository errors
|
|
if grep -q 'Unable to update repository' ${OUTFILE}; then
|
|
repository="error" # already set but reset here for clarity
|
|
elif [ -n "${CUSTOMPKG}" ] && grep -q "No packages available to install matching..${CUSTOMPKG}" ${OUTFILE}; then
|
|
repository="incomplete"
|
|
elif grep -q "No packages available to install matching..${product_target}" ${OUTFILE}; then
|
|
repository="incomplete"
|
|
else
|
|
# Repository can be used for updates
|
|
repository="ok"
|
|
|
|
MODE=
|
|
|
|
while read LINE; do
|
|
REPO=$(echo "${LINE}" | grep -o '\[.*\]' | tr -d '[]')
|
|
if [ -z "${REPO}" ]; then
|
|
REPO=${product_repo}
|
|
fi
|
|
|
|
for i in $(echo "${LINE}" | tr '[' '(' | cut -d '(' -f1); do
|
|
case ${MODE} in
|
|
DOWNGRADED:)
|
|
if [ "$(expr $linecount + 4)" -eq "$itemcount" ]; then
|
|
if [ "${i%:*}" = "${i}" ]; then
|
|
itemcount=0 # This is not a valid item so reset item count
|
|
MODE=
|
|
else
|
|
i=$(echo $i | tr -d :)
|
|
if [ -n "$packages_downgraded" ]; then
|
|
packages_downgraded=$packages_downgraded","
|
|
fi
|
|
packages_downgraded=$packages_downgraded"{\"name\":\"$i\",\"repository\":\"${REPO}\","
|
|
fi
|
|
fi
|
|
if [ "$(expr $linecount + 3)" -eq "$itemcount" ]; then
|
|
packages_downgraded=$packages_downgraded"\"current_version\":\"$i\","
|
|
fi
|
|
if [ "$(expr $linecount + 1)" -eq "$itemcount" ]; then
|
|
packages_downgraded=$packages_downgraded"\"new_version\":\"$i\"}"
|
|
itemcount=$(expr $itemcount + 4) # get ready for next item
|
|
fi
|
|
;;
|
|
INSTALLED:)
|
|
if [ "$(expr $linecount + 2)" -eq "$itemcount" ]; then
|
|
if [ "${i%:*}" = "${i}" ]; then
|
|
itemcount=0 # This is not a valid item so reset item count
|
|
MODE=
|
|
else
|
|
i=$(echo $i | tr -d :)
|
|
if [ -n "$packages_new" ]; then
|
|
packages_new=$packages_new","
|
|
fi
|
|
packages_new=$packages_new"{\"name\":\"$i\",\"repository\":\"${REPO}\","
|
|
fi
|
|
fi
|
|
if [ "$(expr $linecount + 1)" -eq "$itemcount" ]; then
|
|
packages_new=$packages_new"\"version\":\"$i\"}"
|
|
itemcount=$(expr $itemcount + 2) # get ready for next item
|
|
fi
|
|
;;
|
|
REINSTALLED:)
|
|
if [ "$(expr $linecount + 1)" -eq "$itemcount" ]; then
|
|
if [ "${i%-*}" = "${i}" ]; then
|
|
itemcount=0 # This is not a valid item so reset item count
|
|
MODE=
|
|
else
|
|
name=${i%-*}
|
|
version=${i##*-}
|
|
itemcount="$(expr $itemcount + 1)" # get ready for next item
|
|
if [ -n "$packages_reinstall" ]; then
|
|
packages_reinstall=$packages_reinstall"," # separator for next item
|
|
fi
|
|
packages_reinstall=$packages_reinstall"{\"name\":\"$name\",\"version\":\"$version\",\"repository\":\"${REPO}\"}"
|
|
fi
|
|
fi
|
|
;;
|
|
REMOVED:)
|
|
if [ "$(expr $linecount + 2)" -eq "$itemcount" ]; then
|
|
if [ "${i%:*}" = "${i}" ]; then
|
|
itemcount=0 # This is not a valid item so reset item count
|
|
MODE=
|
|
else
|
|
i=$(echo $i | tr -d :)
|
|
if [ -n "$packages_removed" ]; then
|
|
packages_removed=$packages_removed","
|
|
fi
|
|
packages_removed=$packages_removed"{\"name\":\"$i\",\"repository\":\"$(pkg query %R ${i})\","
|
|
fi
|
|
fi
|
|
if [ "$(expr $linecount + 1)" -eq "$itemcount" ]; then
|
|
packages_removed=$packages_removed"\"version\":\"$i\"}"
|
|
itemcount=$(expr $itemcount + 2) # get ready for next item
|
|
fi
|
|
;;
|
|
UPGRADED:)
|
|
if [ "$(expr $linecount + 4)" -eq "$itemcount" ]; then
|
|
if [ "${i%:*}" = "${i}" ]; then
|
|
itemcount=0 # This is not a valid item so reset item count
|
|
MODE=
|
|
else
|
|
i=$(echo $i | tr -d :)
|
|
if [ -n "$packages_upgraded" ]; then
|
|
packages_upgraded=$packages_upgraded","
|
|
fi
|
|
packages_upgraded=$packages_upgraded"{\"name\":\"$i\",\"repository\":\"${REPO}\","
|
|
fi
|
|
fi
|
|
if [ "$(expr $linecount + 3)" -eq "$itemcount" ]; then
|
|
packages_upgraded=$packages_upgraded"\"current_version\":\"$i\","
|
|
fi
|
|
if [ "$(expr $linecount + 1)" -eq "$itemcount" ]; then
|
|
packages_upgraded=$packages_upgraded"\"new_version\":\"$i\"}"
|
|
itemcount=$(expr $itemcount + 4) # get ready for next item
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
linecount=$(expr $linecount + 1)
|
|
|
|
case $i in
|
|
INSTALLED:|REMOVED:)
|
|
itemcount=$(expr $linecount + 2)
|
|
MODE=$i
|
|
;;
|
|
REINSTALLED:)
|
|
itemcount=$(expr $linecount + 1)
|
|
MODE=$i
|
|
;;
|
|
DOWNGRADED:|UPGRADED:)
|
|
itemcount=$(expr $linecount + 4)
|
|
MODE=$i
|
|
;;
|
|
esac
|
|
done
|
|
done < ${OUTFILE}
|
|
|
|
# if we run twice give values as CSV for later processing
|
|
download_size=$(grep 'to be downloaded' ${OUTFILE} | awk -F '[ ]' '{print $1$2}' | tr '\n' ',' | sed 's/,$//')
|
|
|
|
# see if packages indicate a new version (not revision) of base / kernel
|
|
LQUERY=$(pkg query %v opnsense-update)
|
|
LQUERY=${LQUERY%%_*}
|
|
RQUERY=$(pkg rquery %v opnsense-update)
|
|
RQUERY=${RQUERY%%_*}
|
|
|
|
if [ -n "${force_all}" -o "$(pkg version -t ${LQUERY} ${RQUERY})" = "<" ]; then
|
|
kernel_to_reboot="${RQUERY}"
|
|
base_to_reboot="${RQUERY}"
|
|
fi
|
|
|
|
if [ -z "${base_to_reboot}" ]; then
|
|
if opnsense-update -cbf; then
|
|
base_to_reboot="$(opnsense-update -v)"
|
|
fi
|
|
fi
|
|
|
|
if [ -n "${base_to_reboot}" ]; then
|
|
base_to_delete="$(opnsense-update -vk base)"
|
|
base_is_size="$(opnsense-update -bfSr ${base_to_reboot})"
|
|
if [ "${base_to_reboot}" != "${base_to_delete}" -a -n "${base_is_size}" ]; then
|
|
# XXX this could be a downgrade or reinstall
|
|
if [ -n "${packages_upgraded}" ]; then
|
|
packages_upgraded=${packages_upgraded}","
|
|
fi
|
|
packages_upgraded=${packages_upgraded}"{\"name\":\"base\",\"size\":\"${base_is_size}\","
|
|
packages_upgraded=${packages_upgraded}"\"repository\":\"${product_repo}\","
|
|
packages_upgraded=${packages_upgraded}"\"current_version\":\"${base_to_delete}\","
|
|
packages_upgraded=${packages_upgraded}"\"new_version\":\"${base_to_reboot}\"}"
|
|
needs_reboot="1"
|
|
fi
|
|
fi
|
|
|
|
if [ -z "${kernel_to_reboot}" ]; then
|
|
if opnsense-update -cfk; then
|
|
kernel_to_reboot="$(opnsense-update -v)"
|
|
fi
|
|
fi
|
|
|
|
if [ -n "${kernel_to_reboot}" ]; then
|
|
kernel_to_delete="$(opnsense-update -vk)"
|
|
kernel_is_size="$(opnsense-update -fkSr ${kernel_to_reboot})"
|
|
if [ "${kernel_to_reboot}" != "${kernel_to_delete}" -a -n "${kernel_is_size}" ]; then
|
|
# XXX this could be a downgrade or reinstall
|
|
if [ -n "${packages_upgraded}" ]; then
|
|
packages_upgraded=${packages_upgraded}","
|
|
fi
|
|
packages_upgraded=${packages_upgraded}"{\"name\":\"kernel\",\"size\":\"${kernel_is_size}\","
|
|
packages_upgraded=${packages_upgraded}"\"repository\":\"${product_repo}\","
|
|
packages_upgraded=${packages_upgraded}"\"current_version\":\"${kernel_to_delete}\","
|
|
packages_upgraded=${packages_upgraded}"\"new_version\":\"${kernel_to_reboot}\"}"
|
|
needs_reboot="1"
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
packages_is_size="$(opnsense-update -SRp)"
|
|
if [ -n "${packages_is_size}" ]; then
|
|
upgrade_major_version=$(opnsense-update -vR)
|
|
|
|
upgrade_major_message=$(sed -e 's/"/\\&/g' -e "s/%%UPGRADE_RELEASE%%/${upgrade_major_version}/g" /usr/local/opnsense/data/firmware/upgrade.html 2> /dev/null | tr '\n' ' ')
|
|
|
|
packages_to_delete="$(opnsense-update -vp)"
|
|
if [ "${packages_to_delete}" != "${upgrade_major_version}" ]; then
|
|
sets_upgraded="{\"name\":\"packages\",\"size\":\"${packages_is_size}\",\"current_version\":\"${packages_to_delete}\",\"new_version\":\"${upgrade_major_version}\",\"repository\":\"${product_repo}\"}"
|
|
upgrade_needs_reboot="1"
|
|
fi
|
|
|
|
kernel_to_delete="$(opnsense-update -vk)"
|
|
if [ "${kernel_to_delete}" != "${upgrade_major_version}" ]; then
|
|
kernel_is_size="$(opnsense-update -SRk)"
|
|
if [ -n "${kernel_is_size}" ]; then
|
|
sets_upgraded="${sets_upgraded},{\"name\":\"kernel\",\"size\":\"${kernel_is_size}\",\"current_version\":\"${kernel_to_delete}\",\"new_version\":\"${upgrade_major_version}\",\"repository\":\"${product_repo}\"}"
|
|
upgrade_needs_reboot="1"
|
|
fi
|
|
fi
|
|
|
|
base_to_delete="$(opnsense-update -vb)"
|
|
if [ "${base_to_delete}" != "${upgrade_major_version}" ]; then
|
|
base_is_size="$(opnsense-update -SRb)"
|
|
if [ -n "${base_is_size}" ]; then
|
|
sets_upgraded="${sets_upgraded},{\"name\":\"base\",\"size\":\"${base_is_size}\",\"current_version\":\"${base_to_delete}\",\"new_version\":\"${upgrade_major_version}\",\"repository\":\"${product_repo}\"}"
|
|
upgrade_needs_reboot="1"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# write our json structure
|
|
cat > ${JSONFILE} << EOF
|
|
{
|
|
"api_version":"2",
|
|
"connection":"${connection}",
|
|
"downgrade_packages":[${packages_downgraded}],
|
|
"download_size":"${download_size}",
|
|
"last_check":"${last_check}",
|
|
"needs_reboot":"${needs_reboot}",
|
|
"new_packages":[${packages_new}],
|
|
"os_version":"${os_version}",
|
|
"product_id":"${product_id}",
|
|
"product_target":"${product_target}",
|
|
"product_version":"${product_version}",
|
|
"reinstall_packages":[${packages_reinstall}],
|
|
"remove_packages":[${packages_removed}],
|
|
"repository":"${repository}",
|
|
"upgrade_major_message":"${upgrade_major_message}",
|
|
"upgrade_major_version":"${upgrade_major_version}",
|
|
"upgrade_needs_reboot":"${upgrade_needs_reboot}",
|
|
"upgrade_packages":[${packages_upgraded}],
|
|
"upgrade_sets":[${sets_upgraded}]
|
|
}
|
|
EOF
|
|
|
|
echo '***DONE***' >> ${LOCKFILE}
|