-
Notifications
You must be signed in to change notification settings - Fork 1
Update Concepts
The updater has a number of design goals, and might be better labeled the "FabMo Agent" - in addition to essential software update functions, it also manages network interfaces, performs system maintenance tasks, loads firmware and collates and reports various software version identifiers.
The mechanics of an actual update should be as follows:
- Updates should be deliverable without an internet connection
- Updates should be able to be initiated by the user, or happen automatically
- Automatic updates should require user consent
- Updates should be checked for consistency when applied (Some kind of MD5 sum or hash)
- System functions affected by an update should be inaccessible while the update is conducted
- Updates should not perturb user configuration values if they don't have to
- Updates may perturb user configuration values if a compatibility-breaking change is introduced
- Updater should be able to update itself
- A failed update should result in a restoration to the previous factory state (or the most recently updated state?)
- Update packages should not be generic scripts that can perform any function (constrained function to actual updates only)
- Updates can and should be able to include things like apps, configuration changes, macros, etc
- Updates should include a changelog and other relevant information for users
- Updated software systems should know when they have just been updated so they can take appropriate steps in their user interactions
- There should be a system for doing development updates, the way we do now, with pulling changes from git/npm
The implication here is that an update package (like an FMU, but targeted specifically at updates) Should be able to be sent to the updater, and executed without ever having to leave access point mode, or ever having to connect to an internet-connected network, in the case of networked machines with no internet access. To this end:
- Update packages should be self-contained, single files, signed somehow by the provider and identified with included version information
- The upload functionality of the updater should account for the fact that update packages might be large - progress reporting support for file upload and/or resumable file uploads should be supported
The user should control the update process ultimately, but the updater can provide services that make updates easier - the user has the final say, but there's no reason not to check for available updates, download version manifests, or download entire updates in preparation for the users confirmation of the intent to update. So:
- Update providers should provide a list of versions available with links to the appropriate packages (JSON?)
- Updater should periodically check for and possibly download (if bandwidth allows) the appropriate update
- Updater may indicate to the user that the update is available, and perhaps present a changelog with the update confirmation
To this end, the updater should provide a data endpoint that indicates when (or what) updates are available so that frontends can produce a dialog/confirmation.
The MD5 hash for the updates should be included in the update package, as well as in the manifest that points to the update files
The engine, for example, should be shut down when the engine is updated. The catch here is that if the updater is updating itself, shutting down loses any kind of progress indication that it might have provided to the user. To this end a progress process might be spawned to keep the user experience alive while the update is being conducted?
It may make sense to provide a language for updates to add/remove and change configuration values, rather than replacing files wholesale. G2 configuration values for instance that are deprecated should be removed from the appropriate files, and it is burdensome to have the engine scrubbing files at startup. Radical sweeping changes however, may make this confusing and/or complicated. Additionally, it might make sense to make backups of configuration and settings before conducting an update.
A simple process for this is outlined below:
- A version token (say,
version.json
) lives alongside the software in the main directory (for instance, in /fabmo/engine) - If the version token is present, it is assumed that the software was installed correctly by an updater
- If the version token is missing, the software is assumed to be invalid
- If the software is invalid, a reset to factory state is triggered, the factory software is unzipped to the appropriate directories, and the system settings are cleared. The version token file is written to indicate that this operation is successful.
- An additional token is written to indicate that a factory reset has taken place, this token could go in the same place as a similar token that indicates that a normal update has taken place
- The factory reset check is a run-once service that happens at boot time (but could be run on demand say, after an update procedure, to shore up any botched update activity)
To deliver an update there are a couple of core functions, and everything else might be handled by scaffolding.
- Delete the version token
- Stop key services (stop the engine if you're updating the engine, for example)
- Unlock partitions
- Delete/copy files
- Update configuration values
- Write the version token
- Write the "just updated" token
- Lock partitions
- Restart services
Implied from the above requirements, an update package should contain (at least)
- A manifest that includes:
- The product to update
- The new product version
- A minimum version for the updater to successfully execute (ie you need at least updater 2.1 to run this package)
- A changelog
- An MD5 Sum
- A platform and operating system specification
- A list of affected services
- A list of operations to be conducted in order, which may include
- Deleting files/directories
- Copying files/directories (may be expanded from tarball)
- Add/Update/Delete configuration JSON values
{
product : 'FabMo-Engine',
repository : 'https://github.com/FabMo/FabMo-Engine.git'
os : 'linux',
platform : 'edison',
version : '1.2.3',
md5 : '3b85ec9ab2984b91070128be6aae25eb',
changeLogFile : 'changelog.txt',
services : ['fabmo'],
operations : [
{
op : 'deleteFiles'
paths : [
'/fabmo/engine/*'
'/opt/fabmo/log'
]
}
]
}