16624
Comment: update link to config-model wiki
|
16680
mentions that upstream LCDd.conf is now delivered for reference, but is not used by lcdproc or cme
|
Deletions are marked like this. | Additions are marked like this. |
Line 87: | Line 87: |
* `/etc/LCDd.conf` is no longer a [[http://raphaelhertzog.com/2010/09/21/debian-conffile-configuration-file-managed-by-dpkg/|conffile]]. It is now delivered in `/usr/share/doc/lcdproc` and not in `/etc/`. See commit [[http://anonscm.debian.org/gitweb/?p=collab-maint/lcdproc.git;a=commitdiff;h=4f4c2c0c3ba339697a8eca3ebcef01a2750b81df|1]] and [[http://anonscm.debian.org/gitweb/?p=collab-maint/lcdproc.git;a=commitdiff;h=024fa30fdadfc2f6d46dea6dbaadb8d62a720a80|2]] | * `/etc/LCDd.conf` is no longer used by lcdproc or by cme. The upstream file is now delivered in `/usr/share/doc/lcdproc` as a reference file. See commit [[http://anonscm.debian.org/gitweb/?p=collab-maint/lcdproc.git;a=commitdiff;h=4f4c2c0c3ba339697a8eca3ebcef01a2750b81df|1]] and [[http://anonscm.debian.org/gitweb/?p=collab-maint/lcdproc.git;a=commitdiff;h=024fa30fdadfc2f6d46dea6dbaadb8d62a720a80|2]] |
Line 250: | Line 250: |
* What is a [[http://raphaelhertzog.com/2010/09/21/debian-conffile-configuration-file-managed-by-dpkg/|conffile]] ? |
Translation(s): none
This page contains a proposal for a way to handle upgrades where a user's data and the package maintainer data are merged with minimal interaction with user. The package approx will be used as an example.
Configuration upgrade by package
Contents
- Configuration upgrade by package
Status
Automatic configuration merge is provided with lcdproc >= 0.5.6
Introduction
For a casual user (like you mother-in-law or your neighbor), the questions asked during package upgrades can be intimidating. Casual users barely know that some files exist outside of their home directory and are completely lost when looking at the /etc directory. Unfortunately, during package upgrade, user is faced with cryptic questions whether to keep his configuration, use the maintainers configuration or look at a diff. The casual user will seldom know what to do in this case.
This situation can be made worse if user's configuration was edited with a tool (e.g. cups configuration is edited through a web browser): the user has no knowledge of the syntax of the configuration file.
This proposal aims to provide a way for Debian package to minimize the number of questions raised to the user when upgrading packages. If questions are necessary, an interface will be provided to the user. Hopefully, manual editing of configuration files will not be necessary.
Upgrades with Config::Model
Config-Model provides a framework for editing and validating the content of any configuration file or data. With a configuration model (expressed in a data structure), Config-Model provides a user interface and a tool to validate configuration.
A typical configuration model contains the following specifications :
The structure of the configuration model. This structure is a tree that can be flat (for simple files like approx.conf) or quite deep (for complex configuration like xorg.conf). The configuration tree nodes are instances of configuration class and the tree leaves contain the configuration values.
The constraints of the leaf values (i.e. integer, enum type, min values, max values ...)
the default values where the default value must be written in the configuration file.
the built-in default value where the value need not be written in the configuration file. This default value is built in the application.
- Help text displayed with interactive configuration editor.
This notion of default value versus built-in default value is important to distinguish:
- the values that were customized by the user (or sysadmin)
the value that are recommended by the package maintainer (and specified as default in the model)
the value that are provided upstream (specified as upstream_default)
When creating a model just for upgrades, a model does not need to feature:
- constraints. Because the configuration file to be upgraded is supposed to be correct
- help text, because the upgrade is done in non-interactive mode
- built-in default values because they are not used during upgrades
During a package upgrade we want to:
- propagate values from the old configuration file to new configuration file.
- discard obsolete data (if any)
- introduce new mandatory values (if any)
- migrate (or translate) data from old format to new format
So the idea is:
- Upgrade the packages files as usual (including upgrade of configuration model)
In postinst, run cme to load old configuration file using new configuration model and write back the updated data in new configuration file (i.e. merged values from user's data and data from new configuration model).
If the last step fails, inform the user to launch cme in interactive mode
The same principles can be applied to downgrade with some limitations (see below for more details)
Apply configuration upgrade using an existing model: lcdproc example
This is a real use case implemented for lcdproc
Current lcdproc situation
Up to version 0.5.5, lcdproc is shipped with several configuration files, including /etc/LCDd.conf. This file is modified upstream at every lcdproc release to bring configuration for new lcdproc drivers. On the other hand, this file is always customized to suit the specific hardware of the user's system. So upgrading a package will *always* lead to a conflict during upgrade. User will always be required to choose whether to use current version or upstream version.
libconfig-model-lcdproc-perl provides a configuration model for lcdproc. This blog explains how this model is generated from upstream LCDd.conf. But this is off topic for this page.
What will change for user
When lcdproc is upgraded to the new version featuring automatic upgrade, the following changes will be visible: * lcdproc will depend on libconfig-model-lcdproc-perl * user will be asked *once* by debconf whether to use automatic configuration upgrades or not. * no further question will be asked (no ucf style questions).
Note: the automatic upgrade currently applies only to LCDd.conf. The other configuration files of lcdproc are handled the usual way.
lcdproc package changes for automatic upgrades
lcdproc package was changed the following way:
dh is now run with --with cme_upgrade option (see debian/rules)
/etc/LCDd.conf is no longer used by lcdproc or by cme. The upstream file is now delivered in /usr/share/doc/lcdproc as a reference file. See commit 1 and 2
A new file is added to debian directory to specify upgrade instructions: debian/lcdproc.config-model
This file contains the following lines:
cme-model-package: libconfig-model-lcdproc-perl: specifies the debian package containing lcdproc configuration model
cme-model-version: 2.040 specifies the minimum version of the above package. These 2 parameters are used to construct a dependency which is added to lcdproc package.
cme-app-name: lcdproc specifies the application name passed to cme
cme-command: fix specifies the command used by cme. By default, cme will use migrate command during upgrade. Due to multi arch, DriverPath may contain library path without multi-arch triplet. Using fix will ensure that DriverPath is set to the correct multi-arch path.
cme-options: -force is required to upgrade LCDd.conf from upstream. Upstream config contains configuration for driver which are removed from Debian. This configuration must also be removed from the file. Using -force will ensure that.
cme-purge: /etc/LCDd.conf*: with this option, dh_cme_upgrade will insert a postinst script that will remove the specified file on package purge.
For more information, see dh_cme_upgrade man page.
If you want to apply config-model based upgrades to your favorite package
lcdproc did start from an existing configuration model. Let's see what is required to create a minimal configuration model so that your package can also feature automatic configuration upgrade.
You will have to:
- Create a minimal model that describe:
- items that need special treatment during upgrades
- how to handle other parameters
Find a backend that supports the syntax of the configuration file of your package. If none exists, ask on config-model-users at lists.sourceforge.net, we'll find a solution that won't require you to learn Perl.
Well, that was the theory. Let's experiment with Approx configuration file and work out the details.
Approx example
configuration analysis
From approx.conf(5) man page, we find that approx has a very simple configuration. Approx will need one configuration class that will have:
- a bunch configuration parameters, either boolean, integer or string. All of them have default built in approx.
a hash containing distribution names and their URL. These will be modeled with a hash of uniline values
The syntax of approx.conf is fairly simple but there's no Perl module available to read and write it. A dedicated parser/writer will be required. I.e. a Perl class that will inherit http://search.cpan.org/dist/Config-Model/lib/Config/Model/Backend/Any.pm. Well, you can cheat and look at the source of the actual Approx backend.
Upgrade scenario
For the sake of the example, let's assume that offline parameter was named nointernet in previous versions of Approx. This is of course not true. Apologies to Eric Cooper for such a ludicrous idea.
So the upgrade model must feature:
instructions to migrate nointernet content to offline parameter
- instructions to handle other leaf parameters (the one that will not be described in your minimal model)
instructions to handle distributions as we must avoid collisions between distribution names and approx parameter names (the syntax of approx.conf was changed with version 2.9.0 for the same reason)
Approx configuration model
To create the Approx configuration model, you can use the GUI provided by libconfig-model-itself-perl.
In a empty directory, run config-edit-model -model Approx and fill the fields as required.
You will have to:
Create the Approx configuration class
handle the old hypothetical nointernet parameter:
create a leaf parameter with value_type set to boolean
set a deprecated status as this parameter is to be migrated
handle the new offline parameter:
create a leaf parameter with value_type set to boolean
- specify migration instruction where:
the old parameter is specified in a variable (- nointernet)
- the formula specifies how is used the old value. In this case, it's a simple substitution.
handle the distribution parameter (a hash of unilines)
- specify all mandatory parameters with thier default values (fortunately, there's no such parameter for Approx)
specify what to do with unknown parameters. The accept instruction will match any other parameter (with the '.*' regexp) and use them as uniline values
In the end you will get :
[ { 'name' => 'Approx', 'element' => [ nointernet => { type => 'leaf', value_type => 'boolean', status => 'deprecated' }, offline => { type => 'leaf', value_type => 'boolean', migrate_from => { variables => { old => '- nointernet' } , formula => '$old', } }, 'distributions', { type => 'hash', index_type => 'string' , cargo => { value_type => 'uniline', type => 'leaf',}, } ], 'accept' => [ '.*' => { type => 'leaf', value_type => 'uniline', }, ], } ] ;
You can view the actual model on Approx model on github. This model is more complex as all parameters and help text are provided.
Any Debian specific requirement (e.g. default value) will have to be implemented in the model and not in the template configuration file provided to the user (e.g. not in /etc/approx/approx.conf)
Configuraion upgrade during package upgrade
This can use modification similar to the lcdproc example shown above.
Config::Model commands to manage configuration upgrade
For reference, cme can also be used outside of package script to manually migrate a configuration file. These commands are not specific to Debian and can be applied to other distros or OS.
Let's start with a simple approx.conf file:
debian http://ftp.fr.debian.org/debian $max_wait 12
In most cases, simply running cme migrate will be enough to upgrade a configuration files. Even if the configuration model is changed from package version N to version N+1, the upgrade will work most to the time. cme will exit on error if some data to upgrade are not recognized.
cme migrate approx
cme will:
- parse the old configuration file (or create one in case of first installation)
- validate all values (possibly discarding or migrating obsolete parameters) FIXME add link to details
- add new values declared in N+1 model (if any)
- write back the configuration file (comments are preserved)
After upgrade, approx.conf has:
# This file was written by Config::Model with Approx model # You may modify the content of this file. Configuration # modification will be preserved. $max_wait 12 debian http://ftp.fr.debian.org/debian
If you want to keep a backup of the old configuration file, you can run cme migrate approx -backup. The old configuration will be in approx.conf.old
Working with Debconf
Warning: just a bunch of ideas, no working implementation
Main ideas:
Run config-edit -ui debconf -saveindebconf in pre-inst
Run config-edit -ui debconf -loadfromdebconf -save in postinst
- Translate data from model into debconf template. Debconf template will be used by
C::M::Debconf::Wizard and Config::Moldel::WizardHelper to scan configuration tree and ask question in case of error or missing mandatory values (or may be different level of scanning to match debconf's priority. See Config::Model::DebConfUI (still coding...))
Fortunately, the semantic of Config::Model value_type mostly matches debconf's type:
Config::Model
Debconf
uniline
string
integer
string
number
string
string
string (problem with multi-line ?)
boolean
boolean
enum
select
checklist
multiselect
help stored in model
note
$@ from eval{die ...}
error
title
not necessary
Links
Thanks
- To Damyan Ivanov (first review)
- To Jonas Smedegaard for the constructive exchange and the helper scripts and /var/lib/ storage ideas
- The Gregor Hermann for sponsoring all the libconfig-model-* packages