[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Configuration management, revision 4



[ This is a moification of Wichert's original proposal. I'm posting this
because I've gotten some mail that made me think some people haven't grasped
exactly how my suggestions for modifications of this proposal worked. I hope
some context and examples will make it clear. I've also worked in some 
suggestions from others. Changes are marked with "!".]

                             Configuration Management
  
                           Managing configuration data
                           ===========================

  1. The configuration space
  All configuration information is stored in what I call the configuration
  space. This is a database with a special design which resembles to method
  we look at configuration information. This is done by defining a hierarchy
! of information. Each package receives its own space in the hierarchy (this
! may not be at the top of the hierarchy, it may first be divided by machine
! name, etc. This isn't flused out yet). Each package is free to use a flat
! space, or divide its space further into subhierarchies. If multiple 
! packages share a common purpose they may use a shared
  hierarchy, preferably with the same name as a shared (virtual) packagename
  (for example, both mutt and elm can use mail-reader, strn an nn could use
  news-reader).  This shared tree can also be used as a default, ie a variable
! news-reader/nntpserver can be used by strn if strn/nntpserver does not
  exist.

! Frontends (see below) may offer the user various ways to navigate the
! configuration space and change values in it. This is independent of the
! configuration modules defined below, which walk the user sequentially 
! through parts of the configuration space.

  2. Types of variables
  Multiple types of variables can be stored in the configuration space. A
! preliminary list of types is: booleans, strings, numbers, lists, hostnames, 
! IP addresses. Each variable has, at a minimum, the following meta-data
! associated with it: long description, short description, type, default,
! and priority. The "priority" flag states how important this variable is. 
! This can be used by the frontend to weed out unimportant questions.

  3. Accessing the configuration
[ Omitted for now, this is an implementation detail. ]

                            Install-time configuration
                            ==========================

  We want to make a package which does not break older dpkg's, and we want
  to be able to get the configuration information before the package is
! unpacked. To do this we add a new .tar.gz archive to the package, call it
! config.tar.gz .
  Since all installation-software (apt, dselect, dpkg) download the package
! before installing it, we can extract this data before the package is
  unpacked.  Since older dpkg's will not process the extra file, we can do to
  things: either create an extra assertion "--assert-configmodule" in dpkg which
! is checked in the preinst, or up the versionnumber of the deb package.
  
! 0. The variable definition file.
! This file, named "vars" is contained inside the config.tar.gz file of a
! package. It is a simple text file that defines each variable used by the
! package's configuration module (see below). This information is merged
! into the configuration space when a package is installed or upgraded, and
! may be removed when the package is purged.
!
! The format of this file parallels a Packages file and is as follows:
!    Variable: <variable name>
!    Type: <variable type>
!    Default: <default value>
!    Priority: <priority of variable>
!    Description: <short description of variable>
!      <long description of variable (same format as extended package 
!       description>
!
!    Variable: ....

  1. The configuration module.
! This is a file named "config" in the config.tar.gz file of a package.
! It is an executable program.

  2. What does the configuration module do?
  The configmodule is the part of a package that will determine the
  configuration before the package is installed. This means it is run _before_
  the preinst, and before the package is unpacked! Unless pre-depends are
  used, this will mean that the module can only assume the base-system is
  installed.

  3. How does the configmodule get its information?
  The configmodule needs a way to retrieve information from the configuration
  space, ask the user for information if necessary, etc. But we don't want
  to implement a user interface for each package. To solve this we use a
  seperate frontend, which provides the configmodule with a method to
  access the configuration space and interact with the user.

  4. How do the configmodule and the frontend interact?
  Of course the configmodule and the frontend must exchange data to do their
  work. We do this in a very simple manor: dpkg starts both the configmodule
  and the frontend, and connect the stdin/stdout from the module to the
  stdout/stdin of the frontend. We can then use stdin/stdout to communicate,
  while still having stderr available to report errors.

  5. The frontend
  There are two types of frontends possible: interactive and non-interactive.
  Interactive frontends allow the user to answers questions and see messages.
  Non-interactive frontends get all information from a database (SQL, LDAP,
  db, textfiles, etc.). If a non-interactive frontend is used and the
  configmodule refuses to accept the information the frontend retrieves, it can
  exit with a non-zero exit code, indicating to dpkg it's not possible to install
  the package with the current configuration database.

  6. Communication language
  This communication between the frontend and the configmodule should be as
  simple as possible. Since most IO implementations default to line-buffered IO,
  so we use a simple language where each command is exactly one line. A
  prelimary list of commands is:

  General commands:
    VERSION <number>
       The version-number of the communication-language the module will use.
    CAPB <capabilities>
!      Describes to the frontend what capabilities the script supports. Gets
!      back from the frontend for a list of capabilities the frontend supports.
!      This includes interactiveness!
    STOP
       We are finished. Store the new variables now if transactions are used
       and flush the diskcache to make sure we don't loose anything.
  Interface commands:
    RESET
       Clear the accumalated set of TEXT and INPUT commands
    TEXT <string>
       Show a string to the user. The string need not be shown until a GO
       command is given.
    INPUT [quiet] <variable>
!      Instructs the frontend to display a variable and its description to 
!      the user and allow the user to modify its value. If "quiet" is
!      specified, it will omit from displaying the variable's description.
    BEGINBLOCK ... ENDBLOCK
       Define the beginning and end of a block of interface commands
    GO
       Show the current set of accumulated questions to the user and allow the
       user to change the answers.
!      The config module returns a status code.

  Configuration space access:
    UNSET <variable>
       Remove <variable> from the configurationspace
!   SET <variable> <value>
!      Set a variable <variable> to <value>
!   RESET <variable>
!      Reset a variable to its default value.
    GET <variable>
       Return the value of variable <variable>

  The frontend responds to each command by returning a status code and,
  if needed, extra data after the status code.

  The frontend has complete responsibility for the layout of the questions,
  with the exception that the ordering of interface information within a block
  may not be changed.

! The configuration language interprets each line beginning with a "#" as a
! comment, and ignores them.

  7. Extra note(s)
  Some people wondered how to manage shared configuration-data such as
  install-mime. Actually this is quite easy: simply call a special
  install-mime which can interact with the frontend from your configmodule
  and let that do the configuration.

! In some situations it will be nice for the user to be able to move
! backwards to a previous question the configmodule asked (of course, it's
! always possible to step back to an entirely different configmodule as well).
! To accomplish this, a configmodule can use the CAPB command to tell the
! frontend it supports moving backward. (Ie, "CAPB backup"). Any script that
! does this should check the return value from the GO command to see if the
! frontend has returned a status code asking it to back up a step. If so, it
! should back up (ie, jump back to where it asked the configmodule to
! present the previous block of questions. This obviously will make the
! configmodule more complicated and won't be needed in simple cases. The 
! frontend's most likely response if the configmodule indicates it has
! this capability is to add a "go back" option/button to each prompt it 
! displays.

! 8. Examples
! Here are two examples of converting packages to use this proposal.
!  
!  a. Xfig
!  Xfig has a simple postinst that just needs to know if the user wants
!  a monochrome or a color xfig (or it had it, this seems to have been
!  removed from the package now).
!
!  Xfig's vars file will look like this:
!
!  Variable: xfig/color
!  Type: boolean
!  Default: yes
!  Priority: low
!  Description: Should xfig use color?
!    Xfig can run in either color or monochrome mode. Chose to use color
!    unless you have a monochrome display or find the default xfig color
!    setup too colorful for your tastes.
!
!  The config script will look like this (I could have used /bin/sh and
!  echo'd the commands, but why bother when it's this simple, a cat "script"
!  will suffice!):
!    
!  #!/bin/cat
!  INPUT xfig/color
!  GO
!
!  b. Lilo is more complicated. Actually I've probably missed some details
!  but you'll get the idea. It needs to know if the user wants to install
!  lilo on the boot block using the current lilo configuration, and if the
!  user answers no, it needs to run through a series of several questions 
!  to set up the lilo configuration.
!
!  Lilo's vars file will look like:
!
!  Variable: lilo/usedefault
!  Type: boolean
!  Default: yes
!  Priority: high
!  Description: Install a boot block using your current LILO configuration?
!    LILO, the LInux LOader, sets up your system to boot Linux directly
!    from your hard disk, without the need for a boot floppy.
!    .  
!    You already have a LILO configuration in the file /etc/lilo.conf
!
!  Variable: lilo/reconfigure
!  Type: boolean
!  Default: no
!  Priority: medium
!  Description: Wipe out your old LILO configuration and make a new one?
!    You currently have a LILO configuration. Should it be wiped out and a
!    new one made?
!
!  Variable: lilo/install-partition-boot-record
!  Type: boolean
!  Default: yes
!  Priority: medium
!  Description: Install a partition boot record to boot Linux?
!    This will set up the system to boot linux from your primary linux
!    partition.
!
!  Variable: lilo/install-mbr
!  Type: boolean
!  Default: no
!  Priority: medium
!  Description: Install a master boot record to run lilo?
!    A master boot record is required to run the paritition boot record.
!    If you are already using a boot manager, and want to keep it,
!    answer "no" to the following question. If you don't know
!    what a boot manager is or whether you have one, answer "yes".
!
!  Variable: lilo/make-linux-partition-active
!  Type: boolean
!  Default: yes
!  Priority: medium
!  Description: Make your linux partition active?
!    The master boot record will boot the active partition.
!    If you want your system to boot another operating system,
!    such as DOS or Windows, by default, answer "no" to the following
!    question. You may still use your boot manager or the master
!    boot record to boot Linux. If you want the system to boot Linux.
!    by default, answer "yes".
!
!  The config script will look something like this:
!
!  #!/usr/bin/perl -w
!
!  # Start by telling the frontend our capabilities (we can back up!)
!  print "CAPB reverse\n";
!  <>; # ignore frontend's capabilities (for now).
!
!  AskDefault(); # Start at the first question.
!  
!  # Ask the user if they want to use the defaults in lilo.conf.
!  sub AskDefault {
!      	print "INPUT lilo/usedefault\n";
!       print "GO\n";
!	my $ret=<>;
!	chomp $ret;
!	if ($ret eq 'backup') {
!		# This makes no sense. Just redisplay.
!		# Alternatively, we could maybe do some magic to back up 
!		# to the previous config module.
!		AskDefault();
!	}
!	else {
!		print "GET lilo/usedefault\n";
!	        my $usedefault=<>;
!		chomp $usedefault;
!		if ($usedefault ne 'yes') {
!			AskReconfigure();
!		}
!	}
!  }
!
!  # Ask the user if they want to reconfigure lilo.
!  sub AskReconfigure {
!   	print "INPUT lilo/reconfigure\n";
!	print "GO\n";
!	my $ret=<>;
!	chomp $ret;
!	if ($ret eq 'backup') {
!		# Go back to asking if the default should be used.
!		AskDefault();
!	}
!	else {
!	     print "GET lilo/reconfigure\n";
!	     my $reconfigure=<>;
!	     chomp $reconfigure;
!	     if ($reconfigure eq 'yes') {
!	     		AskConfig();
!	     }
!	}
!  }
!
!  # Ask several questions, which combined tell us all we need to know
!  # to reconfigure lilo.
!  sub AskConfig {
!   	print "BEGINBLOCK\n";
!	print "INPUT lilo/install-partition-boot-record\n";
!	print "INPUT lilo/install-mbr\n";
!	print "INPUT lilo/make-linux-partition-active\n";
!	print "ENDBLOCK\n";
!	print "GO\n";
!	my $ret=<>;
!	chomp $ret;
!	if ($ret eq 'backup') {
!		# Go back to asking if they want to reconfigure.
!		AskReconfigure();
!	}
!	else {
!		# Cool, we're done.
!       }
!  }

-- 
see shy jo


--  
To UNSUBSCRIBE, email to debian-policy-request@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster@lists.debian.org


Reply to: