Skip to content
Ryan Sturmer edited this page Sep 17, 2016 · 5 revisions

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.

Requirements

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

Design Detail

Updates should be deliverable without an internet connection

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

Updates should be able to be initiated by the user, or happen automatically

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

Automatic updates should require user consent

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.

Updates should be checked for consistency when applied

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

System functions affected by updates should be shut down when updates are conducted

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?

Updates should manage configuration changes appropriately

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 failed update should result in the restoration to a previous or factory state

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)

An update should not be a generic script that can do any old thing

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'
         ]
      }
   ]
}
Clone this wiki locally