A new printer administration tool
TimWaugh
Problems
Alchemist
There are various reasons for redesigning the current system-config-printer configuration tool. A brief summary is:
- the XML file format it uses is inflexible
- the configuration options are limited to those common to both spoolers we were shipping at the time the XML format was decided
- it is VERY SLOW: you can't *modify* configuration, only write out entirely new configurations (i.e. trigger the back-end)
- again, due to the XML format chosen, we are tied to the foomatic database in such as way that we absolutely require foomatic to know about the printer before we can configure it. Even if you have the manufacturer's PPD file, there is very little you can do to get your printer working.
- changes made using the CUPS configuration interface (http://localhost:631/), or any other method external to system-config-printer, are not reflected in the XML file and so cannot be modified and often get overwritten.
- new CUPS backends such as hpfax or cups-pdf cannot be used without patching system-config-printer.
Stateless Linux
An extra consideration to take into account when re-designing the administration tool is Stateless Linux. The requirement from that project is that users may specify their own (private) queues for submitting jobs to.
For example, a particular user may want to print to an SMB printer, with certain default settings such as which input tray to use. With Stateless Linux, this queue definition will be tied to the user's home directory so that they can log in on any stateless workstation and be able to print to their queue.
Solution
Stateless Linux
A Stateless Linux configuration has /etc read-only. This causes a problem with local printers: automatic detection of a local printer needs to add a queue. This runtime configuration means that the CUPS configuration files, currently stored in /etc/cups, should be moved to /var/run. Since /var/run does not preserve data over a reboot, this should only be done for stateless configurations. One possible trigger for this special stateless behaviour would be for CUPS to detect that /etc is read-only -- or else, it could be a configuration option.
Per-user queues in system CUPS daemon
At session start, for each per-user queue defined by the user, the CUPS daemon is notified that a per-user queue needs to be created (if it does not already exist). This could be done using D-BUS.
Firstly, the CUPS daemon is told to remove all per-user queues for this user IF they are not processing jobs. Then, for each per-user queue the CUPS daemon is given the PPD file from the user's home directory, and the URI for the printer, as well as the queue name.
Given this information, the CUPS daemon will then:
- copy the PPD into its ppd directory
- set up a queue if it does not already exist
This new queue will NOT be advertised in IPP "browse" broadcasts. Jobs may only be submitted to this queue by the owning user at the local machine, i.e.:
cupsd.conf:
Allow from localhost
AuthClass Basic
printers.conf:
AllowUser the_user
In addition to the current "certificates" method of avoiding the need to type in a password when submitting jobs, we could patch CUPS to use D-BUS for the same purpose.
Remaining questions:
Should steps be taken to avoid accidentally forming round-robin classes with other per-user or remote queues of the same name as the user-defined queue? One suggestion is to use 'user-$uid-$queue' as the real name, but present it to the user as '$queue'.
Better configuration method
It will solve many of the configuration issues mentioned in 1.1 if a new printer administration tool would configure CUPS directly rather than maintaining a separate configuration file. There are two main ways of doing this:
- using the command-line tools such as lpadmin and lpoptions
- using IPP to communicate with the CUPS daemon directly
Using IPP directly will offer more flexibility. Some of the more subtle changes we will need to make may not be possible using command-line tools alone. Additionally, using IPP for configuration allows the possibility of configuring remote CUPS instances using the graphical tool, and this will be important for print servers that do not have a full graphical interface installed.
Additionally, the user interface must provide a method for the administrator to enable and disable queues. Some queues can get disabled as a result of an error detected by the backend, and there is currently no means of re-enabling the queue using the existing graphical interface.
Configuration file parsing
In order to configure items in /etc/cups/cupsd.conf, the file must be altered and the CUPS daemon told to re-read its configuration. The IPP interface allows us to change this file and cause the configuration file to be re-read. However, changes must be made to the text file, which involves parsing and understanding it.
Things that the administration tool may need to change that reside in cupsd.conf:
- access controls for each local queue
- whether to enable CUPS browsing (both listening and broadcasting)
- what network interfaces to listen on
Previously these settings were stored in alchemist and written out to cupsd.conf, over-writing any previous conflicting settings. It is very important that cupsd.conf be the canonical place for these settings. The existing settings should be shown to the user so that they can be modified. Editing cupsd.conf by hand must not cause any problems with the administration tool.
IPP authentication
There are two options:
- The admin tool runs with user privileges. An authentication dialog box will appear when configuring the CUPS daemon using IPP. Some mechanism similar to consolehelper needs to be devised in order to avoid the need to keep asking for passwords. (This is my preferred alternative.)
-or-
- The admin tool uses consolehelper as before, but can run in unprivileged mode in order to configure only per-user queues.
Modifying PPD options
The new printer administration tool will be responsible for providing a graphical interface for changing the "InstallableOptions" (such as whether a duplexer is installed) and the default queue options such as
duplexing, page size, and print quality. All of these options are stored in the PPD file representing the queue, and this is modified by the CUPS daemon when it receives the IPP request to do so.
The GTK+ print dialog will also allow these settings (except those in the InstallableOptions group) to be over-ridden on a per-job basis. The user interface will be largely the same, and there is opportunity
for code-sharing here. Some aspects of PPD option representation (such as grouping and constraints) require careful implementation in the user interface, and so it would be better not to duplicate this
work.
Page size as a special case
When adding a new queue for an automatically detected printer, an appropriate default page size should be chosen based on the system locale.
CUPS will already do this for us when a new queue is created, so there is no action to be taken.
Persistent settings
Unplugging a USB printer and re-attaching it must retain the settings it had prior to unplugging. This needs to be handled by HAL.
Simple persistence
One easy method is to avoid automatically removing queues at all. Instead, the queue could be disabled (i.e. cupsdisable) when the device is unplugged, and enabled when inserted.
For this to be feasible, it must be possible to identify a newly-inserted printer as being the same one that had been unplugged previously. Many USB printers provide a serial number in their IEEE 1284 Device ID string which can be used for this purpose.
If there is no serial number available, the manufacturer and model strings could be used to identify the correct queue to act upon. If there is no (disabled) queue identified, a new queue would be created as in 2.7 "Automatic detection", below.
The proposal that persistent settings be handled by simply disabling/enabling queues rather than removing queues altogether means that persistent settings can be managed entirely by HAL.
More advanced persistence
Once the new administration tool works well, the persistent settings idea could be made more advanced. See 2.10.3 "More advanced persistence" for how this could work.
Automatic detection
A local printer will be automatically detected by HAL and an appropriate queue created for it.
Remote discovery
For remote printers, the common types are: SMB, JetDirect, and IPP/CUPS. IPP/CUPS instances can broadcast browse packets to facilitate automatic detection for clients. We already make use of this.
For JetDirect printers there is no way of automatically finding them other than probing each address on the subnet.
For SMB printers there may very well be a means of actively discovering remote queues automatically, perhaps by querying the domain server and then each named SMB host in turn. However, I think authentication details (such as username/password) need to be configured when you create a queue, rather than when a job is submitted -- the information is placed into the URI for the queue.
I am not aware of a passive discovery method for SMB.
It has been suggested that UPnP could be used for remote discovery of some newer network printers.
Method for creating a queue
The vast majority of printers provide IEEE 1284 Device ID strings to identify themselves. These strings provide: manufacturer name, model name, description, and command sets understood by the device. For example:
MFG:EPSON;CMD:ESCPL2,BDC,D4;MDL:Stylus Photo 830U;CLS:PRINTER;DES:EPSON Stylus Photo 830U;
or:
MFG:Hewlett-Packard;CMD:PJL,MLC,PCL,PCLXL,POSTSCRIPT;MDL:HP LaserJet
1200;CLS:PRINTER;DES:Hewlett-Packard Laser
Jet 1200;MEM:8MB
The foomatic RPM package provides a database of printers and printer drivers. It stores IEEE 1284 Device ID strings for a large number of printers. It also stores information about which drivers may be used with a given device, and which of those is recommended.
When a local printer is detected, its IEEE 1284 Device ID string should be retrieved. For parallel port printers, /proc/sys/dev/parport/*/autoprobe provides this; for USB printers, /sys/devices/*/*/usb*/*/*/ieee1284_id provides it in newer kernels (>= 2.6.15-1.1826.2.6.FC5).
The foomatic database should then be consulted to look up a printer model based on the manufacturer and model IEEE 1284 Device ID fields. (NB: printconf currently uses some tricks to match printer models for those whose IEEE 1284 Device IDs are not known to foomatic).
If no printer is found, the command set field should be examined. If "POSTSCRIPT" is found, the generic PostScript driver can be used. If "PCLXL" is found, the generic PCL 6/PCL XL driver can be used. If
"PCL" is found, the generic PCL 3 driver can be used. Otherwise, a manufacturer's PPD is required from the user.
If the printer was found, and there is a manufacturer-provided PPD available for the recommended driver for it (a PPD is specific to a printer model and driver combination), the queue is set up automatically and needs no user intervention.
If the printer was not found in the database, or it was found, is PostScript-capable, and there was no manufacturer-provided PPD, the user should be asked to see if they have a manufacturer-provided PPD file. Potentially the www.linuxprinting.org website could be checked to see if the online foomatic database has a PPD to use.
If there was a manufacturer-provided PPD, and it has an InstallableOptions section, those options should be set appropriately. If it is not possible to determine the correct settings automatically, the user should be queried for them.
Code sharing
IEEE 1284 Device ID strings may also be provided by remote printers that are SNMP-capable. There are some subtleties in creating a new queue, such as altering the page size.
As a result, the mechanism for creating a queue outlined in 2.7.1 needs to be used for:
- automatically detected printers
- adding printers using the admin tool
- adding per-user remote queues
Admin tool for creating system queues and per-user queues
If it makes sense from a user interface perspective, it would be useful to combine the facility for creating and editing per-user queues into the admin tool, since a lot of the same functionality is needed.
Additionally, in order to keep the queue creation logic in one place, it might very well make sense for HAL to hand off the IEEE 1284 information from a detected local printer to the admin tool rather than trying to configure a queue on its own.
(NB: This bit needs someone with some user interface sense:)
Perhaps the interface could have two tabs, one for "System print queues" and another for "My print queues". Browsed queues would not be shown.
For each tab, the queues could be listed exactly as they are in the GTK+ print dialog (including number of jobs in queue, and the location).
Queue sharing will be allowed for "System queues" (as currently) but not for "My queues".
Editing a queue will allow the same things to be edited as currently: which driver to use; driver options; queue options such as banner pages.
This combined printer administration tool would be launched by the GTK+ print dialog's "Add printer" button.
Ability to specify queue URI
The new administration tool must allow the user to specify a queue URI in the same manner as the http://localhost:631/ interface does. In other words, a list of possible URIs obtained using the IPP equivalent of '/usr/sbin/lpinfo -v', with the possibility of editing the URI.
Error handling
The foomatic we are shipping for Fedora Core 5 provides a special CUPS backend: beh (backend error handler). It allows the administrator to modify the behaviour of the backends when errors are encountered: whether to try again, how many times to do that, and so on.
It would be useful to be able to offer this in a user interface. The per-user queues would mean that an unprivileged user would even be able to modify error handling for their own jobs.
Future directions
The main aim is to re-implement the current limited functionality of system-config-printer in such a way that it is no longer tied to alchemist. Having an administration tool which can configure CUPS directly and interact with queues created by other means (such as http://localhost:631/ or the lpadmin command) will allow future enhancements.
Some such enhancements are listed below.
Ink levels and maintenance functions
Although there is no unified way of doing so yet, a future enhancement to the administration tool would be to allow the administrator to check ink levels and perform functions like aligning/changing cartridges, for printers that have such a facility.
Classes
Once the new administration tool works well, support could be added for configuring collections of printers (CUPS classes), where a job sent to a class is directed to the first available printer in that class.
More advanced persistence
HAL could (call a program which would) maintain a simple database mapping printer models to PPDs.
When a printer is unplugged, the associated queue would be located and the PPD retrieved from the CUPS daemon. The manufacturer and model would be remembered and stored with the PPD.
When a printer of the same manufacturer and model is inserted at a later time, the remembered PPD would be used rather than consulting foomatic (see 2.7.1 "Method for creating a queue").
This will preserve:
- which driver to use
- the default values for options
- the Installable
Options (such as whether a duplexer is available)
Online foomatic database
If the on-disk foomatic database does not have information about a particular printer, the user could be asked whether they would like to try the online foomatic database. This would probably need some changes to the www.linuxprinting.org website in order to index by IEEE 1284 MFR / MDL strings -- or hosting our own.
Beyond scope
There are other things that need fixing with printing, such as status feedback to find out if the ink has hit the paper. These are beyond the scope of the administration tool.