Delta updates (Preview)
Delta updates allow you to generate small updates that represent only the changes between two full updates, a source image and a target image. This approach is ideal for reducing the bandwidth used to download an update to a device, especially if there are only a few changes between the source and target updates.
Note
The delta update feature in Azure Device Update for IoT Hub is currently in public preview.
Requirements for using delta updates in Device Update for IoT Hub
- The source and target update files must be in SWUpdate (SWU) format.
- Within each SWUpdate file, there must be a raw image that uses the Ext2, Ext3, or Ext4 filesystem.
The delta generation process recompresses the target SWU update using gzip compression to produce an optimal delta. You import the recompressed target SWU update to the Device Update service along with the generated delta update file.
Device Update agent configuration for the delta processor component
To download and install delta updates from the Device Update service, your device needs the Device Update agent with the update handler and delta processor component present and configured.
Device Update agent
The Device Update agent orchestrates the update process on the device, including download, install, and restart actions. To add the Device Update agent to a device and configure it for use, see Device Update agent provisioning. Use agent version 1.0 or later.
Update handler
An update handler integrates with the Device Update agent to perform the actual update install. For delta updates, start with the microsoft/swupdate:2
update handler if you don't already have your own SWUpdate update handler that you want to modify.
Delta processor
The delta processor at Azure/iot-hub-device-update-delta re-creates the original SWU image file on your device after the delta file downloads, so your update handler can install the SWU file. To add the delta processor component to your device image and configure it for use, you can download a Debian package for Ubuntu 20.04 and later from https://github.com/Azure/iot-hub-device-update-delta/tree/main/preview/2.0.0.
If you use another distro, follow the README.md instructions to use CMAKE to build the delta processor from source instead. From there, install the shared object libadudiffapi.so directly by copying it to the /usr/lib directory, as follows:
sudo cp <path to libadudiffapi.so> /usr/lib/libadudiffapi.so
sudo ldconfig
Add a source SWU image file to your device
After the delta update file downloads to a device, it is compared against a valid <source_archive>
previously cached on the device. This process enables the delta update to recreate the full target image.
The simplest way to populate this cached image is to import and deploy a full image update to the device via the Device Update service. If the device is configured with Device Update agent version 1.0 or later and the delta processor, the agent caches the installed SWU file automatically for later delta update use.
If you want to directly prepopulate the source image on your device instead, the path where the image is expected is <BASE_SOURCE_DOWNLOAD_CACHE_PATH>/sha256-<ENCODED HASH>
. By default, <BASE_SOURCE_DOWNLOAD_CACHE_PATH>
is the path /var/lib/adu/sdc/<provider>. The provider
value is the provider
part of the updateId for the source SWU file.
ENCODED_HASH
is the base64 hex string of the SHA256 of the binary, but after encoding to base64 hex string, it encodes the characters as follows:
+
encoded asoctets _2B
/
encoded asoctets _2F
=
encoded asoctets _3D
Delta update generation using the DiffGen tool
You can create delta updates by using the Diff Generation (DiffGen) tool.
Environment prerequisites
Before you create deltas with DiffGen, you need to download and install several things on the environment machine. Ideally, use an Ubuntu 20.04 Linux environment, or Windows Subsystem for Linux if you're on Windows.
The following table shows the content needed, where to get it, and recommended installation if necessary.
Binary name | Where to acquire | How to install |
---|---|---|
DiffGen | Azure/iot-hub-device-update-delta GitHub repo | Download the version matching the OS or distro on the machine to be used to generate delta updates. |
.NETCore runtime, version 8.0.0 | Via Terminal or package managers | Install .NET on Linux. Only the runtime is required. |
Delta update creation using DiffGen
The DiffGen tool runs with the following required arguments and syntax:
DiffGenTool <source_archive> <target_archive> <output_path> <log_folder> <working_folder> <recompressed_target_archive>
The preceding command runs the recompress_tool.py script, which creates the <recompressed_target_file>
. DiffGen then uses the <recompressed_target_file>
instead of <target_archive>
as the target file for creating the diff. Image files within the <recompressed_target_archive>
are compressed with gzip.
If your SWU files are signed, they also require the <signing_command>
argument in the DiffGen command:
DiffGenTool <source_archive> <target_archive> <output_path> <log_folder> <working_folder> <recompressed_target_archive> "<signing_command>"
The DiffGenTool with signing command string parameter runs the recompress_and_sign_tool.py script. This script creates the <recompressed_target_file>
. In addition, this script also signs the sw-description file within the archive to create a sw-description.sig file.
You can use the sample sign_file.sh script from the Azure/iot-hub-device-update-delta GitHub repo to create a diff between the input source file and a recompressed and re-signed target file. Open the script, edit it to add the path to your private key file, and save it. See the Examples section for sample usage.
The following table describes the arguments in more detail:
Argument | Description |
---|---|
<source_archive> |
The base image that DiffGen uses as a starting point to create the delta. Important: This image must be identical to the image already present on the device, for example cached from a previous update. |
<target_archive> |
The image that the delta updates the device to. |
<output_path> |
The path on the host machine to place the delta file in after creation, including desired name of the generated delta file. If the path doesn't exist, the tool creates it. |
<log_folder> |
The path on the host machine to create logs in. It's best to define this location as a subfolder of the output path. If the path doesn't exist, the tool creates it. |
<working_folder> |
The path on the machine to place collateral and other working files in during the delta generation. It's best to define this location as a subfolder of the output path. If the path doesn't exist, the tool creates it. |
<recompressed_target_archive> |
The path on the host machine to create the <recompressed_target_file> in. The <recompressed_target_file> is used instead of the <target_archive> as the target file for diff generation. If this path exists before calling the DiffGen tool, it's overwritten. It's best to define this file in a subfolder of the output path. |
"<signing_command>" (optional) |
A customizable command for signing the sw-description file within the <recompressed_target_archive> . The sw-description file in the recompressed archive is used as an input parameter for the signing command. DiffGen expects the signing command to create a new signature file, using the name of the input with .sig appended.You must surround the parameter with double quotes to pass in the whole command as a single parameter. Also avoid using the ~ character in a key path used for signing, and use the full home path instead. For example, use /home/USER/keys/priv.pem instead of ~/keys/priv.pem. |
DiffGen examples
The following examples operate out of the /mnt/o/temp directory in Windows Subsystem for Linux.
The following code creates a diff between the input source file and a recompressed target file:
sudo ./DiffGenTool
/mnt/o/temp/<source file>.swu
/mnt/o/temp/<target file>.swu
/mnt/o/temp/<delta file to create>
/mnt/o/temp/logs
/mnt/o/temp/working
/mnt/o/temp/<recompressed target file to create>.swu
If you also use the signing parameter, which you must if your SWU file is signed, you can use the sample sign_file.sh script mentioned previously. Open the script, edit it to add the path to your private key file, save the script, and then run DiffGen as follows.
The following code creates a diff between the input source file and a recompressed and re-signed target file:
sudo ./DiffGenTool
/mnt/o/temp/<source file>.swu
/mnt/o/temp/<target file>.swu
/mnt/o/temp/<delta file to create>
/mnt/o/temp/logs
/mnt/o/temp/working
/mnt/o/temp/<recompressed target file to create>.swu
/mnt/o/temp/<path to script>/<sign_file>.sh
Generated delta update import
The basic process of importing a delta update to the Device Update service is the same as for any other update. If you haven't already, be sure to review How to prepare an update to be imported into Azure Device Update for IoT Hub.
Generate the import manifest
To import an update into the Device Update service, you must have or create an import manifest file. For more information, see Importing updates into Device Update.
Import manifest files for delta updates must reference the following files that the DiffGen tool created:
- The
<recompressed_target_file>
SWU image - The
<delta file>
The delta update feature uses a capability called related files that requires a version 5 or later import manifest. To use the related files feature, you must include the relatedFiles and downloadHandler objects in your import manifest.
You use the relatedFiles
object to specify information about the delta update file, including the file name, file size, and sha256 hash. Most importantly, you must also specify the following two properties that are unique to the delta update feature:
"properties": {
"microsoft.sourceFileHashAlgorithm": "sha256",
"microsoft.sourceFileHash": "<source SWU image file hash>"
}
Both properties are specific to the <source image file>
you used as an input to the DiffGen tool when you created your delta update. The import manifest needs the information about the source SWU image even though you don't actually import the source image. The delta components on the device use this metadata about the source image to locate that image on the device after they download the delta update.
Use the downloadHandler
object to specify how the Device Update agent orchestrates the delta update using the related files feature. Unless you customize your own version of the Device Update agent for delta functionality, use the following downloadHandler
:
"downloadHandler": {
"id": "microsoft/delta:1"
}
You can use the Azure CLI az iot du update init v5
command to generate an import manifest for your delta update. For more information, see Create a basic import manifest.
--update-provider <replace with your Provider> --update-name <replace with your update Name> --update-version <replace with your update Version> --compat manufacturer=<replace with the value your device will report> model=<replace with the value your device will report> --step handler=microsoft/swupdate:2 properties=<replace with any desired handler properties (JSON-formatted), such as '{"installedCriteria": "1.0"}'> --file path=<replace with path(s) to your update file(s), including the full file name> downloadHandler=microsoft/delta:1 --related-file path=<replace with path(s) to your delta file(s), including the full file name> properties='{"microsoft.sourceFileHashAlgorithm": "sha256", "microsoft.sourceFileHash": "<replace with the source SWU image file hash>"}'
Save your generated import manifest JSON with the file extension .importmanifest.json.
Import using the Azure portal
Once you create your import manifest, import the delta update by following the instructions in Add an update to Device Update for IoT Hub. You must include the following items in the import:
- The *importmanifest.json file that you previously created in the earlier steps
- The
<recompressed_target_file>
SWU image the DiffGen tool created - The
<delta file>
the DiffGen tool created
Delta update deployment to devices
The delta update deployment experience in the Azure portal is the same as deploying a regular image update. For more information, see Deploy an update by using Device Update.
Once you create the deployment for your delta update, the Device Update service and client automatically determine if there's a valid delta update for each device you're deploying to. If they find a valid delta, they download and install the delta update on that device.
If they don't find a valid delta update, the full image update (the recompressed target SWU image) is downloaded instead as a fallback. This approach ensures that all devices you're deploying the update to get to the appropriate version.
There are three possible outcomes for a delta update deployment:
- The delta update installed successfully and the device is on the new version.
- The delta update was unavailable or failed to install, but a fallback install of the full image was successful, and the device is on the new version.
- Both the delta and fallback installs failed, and the device is still on the old version.
To determine which failure outcome occurred, you can view the install results with error code and extended error code by selecting any device that's in a failed state. You can also collect logs from multiple failed devices if necessary.
If a delta update succeeded, the device shows a Succeeded status.
If a delta update failed but the fallback to the full image succeeded, the device shows the following error status:
resultCode
: <value greater than 0>extendedResultCode
: <non-zero value>
Troubleshoot failed updates
Unsuccessful updates display an error status that you can interpret using the following instructions. Start with the Device Update agent errors in result.h.
Errors from the Device Update agent that are specific to the delta updates download handler functionality begin with 0x9
:
Component | Decimal | Hex | Note |
---|---|---|---|
EXTENSION_MANAGER | 0 | 0x00 | Indicates errors from extension manager download handler logic. Example: 0x900XXXXX |
PLUGIN | 1 | 0x01 | Indicates errors with usage of download handler plugin shared libraries. Example: 0x901XXXXX |
RESERVED | 2 - 7 | 0x02 - 0x07 | Reserved for download handler. Example: 0x902XXXXX |
COMMON | 8 | 0x08 | Indicates errors in delta download handler extension top-level logic. Example: 0x908XXXXX |
SOURCE_UPDATE_CACHE | 9 | 0x09 | Indicates errors in delta download handler extension source update cache. Example: 0x909XXXXX |
DELTA_PROCESSOR | 10 | 0x0A | Error code for errors from delta processor API. Example: 0x90AXXXXX |
If the error code isn't present in result.h, it's probably an error in the delta processor component, separate from the Device Update agent. If so, the extendedResultCode
is a negative decimal value in the hexadecimal format 0x90AXXXXX
.
9
is "Delta Facility"0A
is "Delta Processor Component" (ADUC_COMPONENT_DELTA_DOWNLOAD_HANDLER_DELTA_PROCESSOR)XXXXX
is the 20-bit error code from the Field Installation Tool (FIT) delta processor
If you can't solve the issue based on the error code information, file a GitHub issue to get further assistance.