diff options
Diffstat (limited to 'classes/swupd-image.bbclass')
-rw-r--r-- | classes/swupd-image.bbclass | 224 |
1 files changed, 170 insertions, 54 deletions
diff --git a/classes/swupd-image.bbclass b/classes/swupd-image.bbclass index 0cac12d..5ba9cfb 100644 --- a/classes/swupd-image.bbclass +++ b/classes/swupd-image.bbclass @@ -32,11 +32,47 @@ SWUPD_IMAGE_PN = "${@ d.getVar('PN_BASE', True) or d.getVar('PN', True)}" # to be published will be in the "www" sub-directory. DEPLOY_DIR_SWUPD = "${DEPLOY_DIR}/swupd/${MACHINE}/${SWUPD_IMAGE_PN}" -# The current format has to match the the source code of the -# swupd-client that is in the image. This recipe picks a suitable -# swupd-client via the client's RPROVIDES. -SWUPD_FORMAT ??= "3" -IMAGE_INSTALL_append = " swupd-client-format${SWUPD_FORMAT}" +# The "format" needs to be bumped for different reasons: +# - the output of the swupd-server changes in a way that +# a swupd-client currently installed on devices will not +# understand it (example: changing file names or using +# a new compression method for archives) +# - the content of the distro changes such that a device +# cannot update directly to the latest build (example: +# the distro changes the boot loader and some swupd postinst +# helper which knows about that change must be installed on +# the device first before actually switching) +# +# meta-swupd handles the first case with SWUPD_TOOLS_FORMAT. +# The default value matches the default versions of the swupd-server +# and swupd-client. Distros can override this if they need to pick +# non-default versions of the tools, but that is not tested. +# +# Distros need to handle the second case by preparing and releasing +# a build that devices can update to (i.e. the version URL the devices +# check must have that update), then make the incompatible change and +# in the next build bump the SWUPD_DISTRO_FORMAT. +# +# In both cases, SWUPD_FORMAT gets bumped. meta-swupd notices that +# and then prepares a special transitional update: +# - the rootfs is configured to use the new SWUUPD_FORMAT and +# OS_VERSION +# - a fake OS_VERSION-1 release is built using a swupd-server that is +# compatible with the swupd-client before the bump +# - the OS_VERSION release then is the first one using the new format +# +# This way, devices are forced to update to OS_VERSION-1 because that +# will forever be the "latest" version for their current format. +# Once they have updated, the device really is on OS_VERSION, configured +# to use the new format, and the next update check will see future +# releases again. +# +# For this to work, "swupd-client" should always be invoked without +# explicit format parameter. +SWUPD_TOOLS_FORMAT ?= "4" +SWUPD_DISTRO_FORMAT ?= "0" +SWUPD_FORMAT = "${@ str(int('${SWUPD_TOOLS_FORMAT}') + int('${SWUPD_DISTRO_FORMAT}')) }" +IMAGE_INSTALL_append = " swupd-client-format${SWUPD_TOOLS_FORMAT}" # The information about where to find version information and actual # content is needed in several places: @@ -70,6 +106,11 @@ SWUPD_LOG_FN ??= "bbdebug 1" # a non-negative integer that fits in an int. OS_VERSION ??= "${DISTRO_VERSION}" +# When doing format changes, this version number is used for the intermediate +# release. Default is OS_VERSION - 1. There's a separate sanity check for +# OS_VERSION below, so this code should always work. +OS_VERSION_INTERIM ?= "${@ ${OS_VERSION} - 1 }" + # We need to preserve xattrs, which works with bsdtar out of the box. # It also has saner file handling (less syscalls per file) than GNU tar. # Last but not least, GNU tar 1.27.1 had weird problems extracting @@ -325,6 +366,65 @@ do_swupd_update () { fi fi + swupd_format_of_version () { + if [ ! -f ${DEPLOY_DIR_SWUPD}/www/$1/Manifest.MoM ]; then + bbfatal "Cannot determine swupd format of $1, ${DEPLOY_DIR_SWUPD}/www/$1/Manifest.MoM not found." + exit 1 + fi + format=`head -1 ${DEPLOY_DIR_SWUPD}/www/$1/Manifest.MoM | perl -n -e '/^MANIFEST\s(\d+)$/ && print $1'` + if [ ! "$format" ]; then + bbfatal "Cannot determine swupd format of $1, ${DEPLOY_DIR_SWUPD}/www/$1/Manifest.MoM does not have MANIFEST with format number in first line." + exit 1 + fi + echo $format + } + + # do_fetch_swupd_inputs() creates this file when a content + # URL was set, so creating an empty file shouldn't be necessary + # in most cases. Also determine whether we are switching + # formats. + # + # When the new format is different compared to what was used by + # latest.version, then swupd-server will automatically ignore + # the old content. That includes the case where tool format + # hasn't changed and only the distro format was bumped. In that + # case, reusing old content would be possible, but swupd-server + # would have to be improved to know that. + if [ -e ${DEPLOY_DIR_SWUPD}/image/latest.version ]; then + PREVREL=`cat ${DEPLOY_DIR_SWUPD}/image/latest.version` + if [ ! -e ${DEPLOY_DIR_SWUPD}/www/$PREVREL/Manifest.MoM ]; then + bbfatal "${DEPLOY_DIR_SWUPD}/image/latest.version specifies $PREVREL as last version, but there is no corresponding ${DEPLOY_DIR_SWUPD}/www/$PREVREL/Manifest.MoM." + exit 1 + fi + PREVFORMAT=`swupd_format_of_version $PREVREL` + if [ ! "$PREVFORMAT" ]; then + bbfatal "Format number not found in first line of ${DEPLOY_DIR_SWUPD}/www/$PREVREL/Manifest.MoM" + exit 1 + fi + # For now assume that SWUPD_DISTRO_FORMAT is always 0 and that thus + # $PREVFORMAT also is the format of the previous tools. + PREVTOOLSFORMAT=$PREVFORMAT + + if [ $PREVFORMAT -ne ${SWUPD_FORMAT} ] && [ $PREVREL -ge ${OS_VERSION_INTERIM} ]; then + bbfatal "Building two releases because of a format change, so OS_VERSION - 1 = ${OS_VERSION_INTERIM} must be higher than last version $PREVREL." + elif [ $PREVREL -ge ${OS_VERSION} ]; then + bbfatal "OS_VERSION = ${OS_VERSION} must be higher than last version $PREVREL." + exit 1 + fi + else + bbdebug 2 "Stubbing out empty latest.version file" + touch ${DEPLOY_DIR_SWUPD}/image/latest.version + PREVREL="0" + PREVFORMAT=${SWUPD_FORMAT} + PREVTOOLSFORMAT=${SWUPD_FORMAT} + fi + + # swupd-server >= 3.2.8 uses a different name. Support old and new names + # via symlinking. + ln -sf latest.version ${DEPLOY_DIR_SWUPD}/image/LAST_VER + + ${SWUPD_LOG_FN} "Generating update from $PREVREL (format $PREVFORMAT) to ${OS_VERSION} (format ${SWUPD_FORMAT})" + # Generate swupd-server configuration bbdebug 2 "Writing ${DEPLOY_DIR_SWUPD}/server.ini" if [ -e "${DEPLOY_DIR_SWUPD}/server.ini" ]; then @@ -337,17 +437,6 @@ outputdir=${DEPLOY_DIR_SWUPD}/www/ emptydir=${DEPLOY_DIR_SWUPD}/empty/ END - # do_fetch_swupd_inputs() creates this file when a content - # URL was set, so creating an empty file shouldn't be necessary - # in most cases. - if [ -e ${DEPLOY_DIR_SWUPD}/image/latest.version ]; then - PREVREL=`cat ${DEPLOY_DIR_SWUPD}/image/latest.version` - else - bbdebug 2 "Stubbing out empty latest.version file" - touch ${DEPLOY_DIR_SWUPD}/image/latest.version - PREVREL="0" - fi - GROUPS_INI="${DEPLOY_DIR_SWUPD}/groups.ini" bbdebug 2 "Writing ${GROUPS_INI}" if [ -e "${DEPLOY_DIR_SWUPD}/groups.ini" ]; then @@ -400,64 +489,91 @@ END done } - ${SWUPD_LOG_FN} "Generating update from $PREVREL to ${OS_VERSION}" - # env $PSEUDO bsdtar -acf ${DEPLOY_DIR}/swupd-before-create-update.tar.gz -C ${DEPLOY_DIR} swupd - invoke_swupd ${STAGING_BINDIR_NATIVE}/swupd_create_update --log-stdout -S ${DEPLOY_DIR_SWUPD} --osversion ${OS_VERSION} --format ${SWUPD_FORMAT} - - ${SWUPD_LOG_FN} "Generating fullfiles for ${OS_VERSION}" - # env $PSEUDO bsdtar -acf ${DEPLOY_DIR}/swupd-before-make-fullfiles.tar.gz -C ${DEPLOY_DIR} swupd - invoke_swupd ${STAGING_BINDIR_NATIVE}/swupd_make_fullfiles --log-stdout -S ${DEPLOY_DIR_SWUPD} ${OS_VERSION} - if [ "${SWUPD_CONTENT_URL}" ]; then content_url_parameter="--content-url ${SWUPD_CONTENT_URL}" else content_url_parameter="" fi - ${SWUPD_LOG_FN} "Generating zero packs, this can take some time." - # env $PSEUDO bsdtar -acf ${DEPLOY_DIR}/swupd-before-make-zero-pack.tar.gz -C ${DEPLOY_DIR} swupd - # Generating zero packs isn't parallelized internally. Mostly it just - # spends its time compressing a single tar archive. Therefore we parallelize - # by forking each command and then waiting for all of them to complete. - jobs="" - for bndl in ${ALL_BUNDLES}; do - ${SWUPD_LOG_FN} "Generating zero pack for $bndl" - # The zero packs are used by the swupd client when adding bundles. - # The zero pack for os-core is not needed by the swupd client itself; - # in Clear Linux OS it is used by the installer. We could use some - # space by skipping the os-core zero bundle, but for now it gets - # generated, just in case that it has some future use. - invoke_swupd ${STAGING_BINDIR_NATIVE}/swupd_make_pack --log-stdout $content_url_parameter -S ${DEPLOY_DIR_SWUPD} 0 ${OS_VERSION} $bndl & - jobs="$jobs $!" - done + create_version () { + swupd_format=$1 + tool_format=$2 + os_version=$3 + + # env $PSEUDO bsdtar -acf ${DEPLOY_DIR}/swupd-before-create-update.tar.gz -C ${DEPLOY_DIR} swupd + invoke_swupd ${STAGING_BINDIR_NATIVE}/swupd_create_update_$tool_format --log-stdout -S ${DEPLOY_DIR_SWUPD} --osversion $os_version --format $swupd_format + + ${SWUPD_LOG_FN} "Generating fullfiles for $os_version" + # env $PSEUDO bsdtar -acf ${DEPLOY_DIR}/swupd-before-make-fullfiles.tar.gz -C ${DEPLOY_DIR} swupd + invoke_swupd ${STAGING_BINDIR_NATIVE}/swupd_make_fullfiles_$tool_format --log-stdout -S ${DEPLOY_DIR_SWUPD} $os_version - # Generate delta-packs against previous versions chosen by our caller. - # env $PSEUDO bsdtar -acf ${DEPLOY_DIR}/swupd-before-make-delta-pack.tar.gz -C ${DEPLOY_DIR} swupd - for prevver in ${SWUPD_DELTAPACK_VERSIONS}; do + ${SWUPD_LOG_FN} "Generating zero packs, this can take some time." + # env $PSEUDO bsdtar -acf ${DEPLOY_DIR}/swupd-before-make-zero-pack.tar.gz -C ${DEPLOY_DIR} swupd + # Generating zero packs isn't parallelized internally. Mostly it just + # spends its time compressing a single tar archive. Therefore we parallelize + # by forking each command and then waiting for all of them to complete. + jobs="" for bndl in ${ALL_BUNDLES}; do - bndlcnt=0 - ${SWUPD_LOG_FN} "Generating delta pack from $prevver to ${OS_VERSION} for $bndl" - invoke_swupd ${STAGING_BINDIR_NATIVE}/swupd_make_pack --log-stdout $content_url_parameter -S ${DEPLOY_DIR_SWUPD} $prevver ${OS_VERSION} $bndl | sed -u -e "s/^/$prevver $bndl: /" & + # The zero packs are used by the swupd client when adding bundles. + # The zero pack for os-core is not needed by the swupd client itself; + # in Clear Linux OS it is used by the installer. We could use some + # space by skipping the os-core zero bundle, but for now it gets + # generated, just in case that it has some future use. + invoke_swupd ${STAGING_BINDIR_NATIVE}/swupd_make_pack_$tool_format --log-stdout $content_url_parameter -S ${DEPLOY_DIR_SWUPD} 0 $os_version $bndl | sed -u -e "s/^/$bndl: /" & jobs="$jobs $!" done - done - waitall $jobs + # Generate delta-packs against previous versions chosen by our caller, + # if possible. Different formats make this useless because the previous + # version won't be able to update to the new version directly. + # env $PSEUDO bsdtar -acf ${DEPLOY_DIR}/swupd-before-make-delta-pack.tar.gz -C ${DEPLOY_DIR} swupd + for prevver in ${SWUPD_DELTAPACK_VERSIONS}; do + old_swupd_format=`swupd_format_of_version $prevver` + if [ $old_swupd_format -eq $swupd_format ]; then + for bndl in ${ALL_BUNDLES}; do + ${SWUPD_LOG_FN} "Generating delta pack from $prevver to $os_version for $bndl" + invoke_swupd ${STAGING_BINDIR_NATIVE}/swupd_make_pack_$tool_format --log-stdout $content_url_parameter -S ${DEPLOY_DIR_SWUPD} $prevver $os_version $bndl | sed -u -e "s/^/$prevver $bndl: /" & + jobs="$jobs $!" + done + fi + done + + waitall $jobs - # Write version to www/version/format${SWUPD_FORMAT}/latest and image/latest.version - bbdebug 2 "Writing latest file" - mkdir -p ${DEPLOY_DIR_SWUPD}/www/version/format${SWUPD_FORMAT} - echo ${OS_VERSION} > ${DEPLOY_DIR_SWUPD}/www/version/format${SWUPD_FORMAT}/latest + # Write version to www/version/format$swupd_format/latest. + bbdebug 2 "Writing latest file" + mkdir -p ${DEPLOY_DIR_SWUPD}/www/version/format$swupd_format + echo $os_version > ${DEPLOY_DIR_SWUPD}/www/version/format$swupd_format/latest + # env $PSEUDO bsdtar -acf ${DEPLOY_DIR}/swupd-done.tar.gz -C ${DEPLOY_DIR} swupd + } + + if [ $PREVFORMAT -ne ${SWUPD_FORMAT} ]; then + # Exact same content (including the OS_VERSION in the os-release file), + # just different tool and/or format in the manifests. + ln -sf ${OS_VERSION} ${DEPLOY_DIR_SWUPD}/image/${OS_VERSION_INTERIM} + echo $PREVREL > ${DEPLOY_DIR_SWUPD}/image/latest.version + create_version $PREVFORMAT $PREVTOOLSFORMAT ${OS_VERSION_INTERIM} + fi + echo $PREVREL > ${DEPLOY_DIR_SWUPD}/image/latest.version + create_version ${SWUPD_FORMAT} ${SWUPD_TOOLS_FORMAT} ${OS_VERSION} echo ${OS_VERSION} > ${DEPLOY_DIR_SWUPD}/image/latest.version - # env $PSEUDO bsdtar -acf ${DEPLOY_DIR}/swupd-done.tar.gz -C ${DEPLOY_DIR} swupd } SWUPDDEPENDS = "\ virtual/fakeroot-native:do_populate_sysroot \ rsync-native:do_populate_sysroot \ bsdiff-native:do_populate_sysroot \ - swupd-server-native:do_populate_sysroot \ " + +# We don't know exactly which formats will be in use during +# do_swupd_update. It depends on the content of the update +# repo, which is unavailable when dependencies are evaluated +# in preparation of the build. +# +# For now we simply build all supported server versions. +SWUPD_SERVER_FORMATS = "3 4" +SWUPDDEPENDS += "${@ ' '.join(['swupd-server-format%s-native:do_populate_sysroot' % x for x in '${SWUPD_SERVER_FORMATS}'.split()])}" + addtask swupd_update after do_image_complete before do_build do_swupd_update[depends] = "${SWUPDDEPENDS}" |