| Path: | doc/src/developer-overview |
| Last Update: | Fri Oct 13 15:35:37 +0200 2006 |
Dsadmin is divided into two main components: admind, the distributed daemon running on the hosts to be administered (the part that does the real work) and webfe, the user friendly web frontend. In addition to that a few commandline utilities are bundled (most notably admindctl, and for testing / debugging purposes admindcmd).
The different parts communicate by sending requests via a custom protocol over TCP/IP connections.
The communication architecture between admind instances is a mix of master/slave and peer-to-peer. All instances can communicate equally with each other, but a designated instance (the "master") has a few special properties:
The "main class" or "entry point" for admind is class Dsadmin::Admind::AdminDaemon. It
Shutdown and restart are also initiated here (see Dsadmin::Admind::AdminDaemon#shutdown). Note that for a restart, admind simply exec()s itself after some cleanup, so the process ID as well as stdout / stderr are not affected. On the master instance it is also possible to trigger a system-wide shutdown / restart (i.e. affecting all admind instances).
A note about admin‘s (E)UID: admind has always to be started as UID 0 (root). Immediately after startup (after starting to listen on its — potentially privileged — TCP port to be precise) it drops to EUID/EGID nobody/nogroup, and only changes this for operations that specifically need to be run as different user (see Dsadmin::System#runAs). While admind is running as different user/group, all threading is disabled to prevent accidents.
The actual processing of requests in admind is implemented in so-called "controllers" and their "actions". This is modeled after rails’ ActionController, with Dsadmin::Admind::AdmindController taking on the role of the base class.
rails application, with some custom twists.
Most aspects of dsadmin can (and often have to) be customized in a set of configuration files. The document ./files/doc/src/config.html describes the general mechanisms that are and/or can be used in these files, and class Dsadmin::BaseConfigManager has info on how to access them from the code. For info on their content, have a look at the (well-commented) example files in config/.
Please note that all dsadmin components only read their config file(s) once - at program startup. So every configfile change requires a restart of the respective component (admind or webfe). In the case of admind, all instances also have to use the same configfiles (i.e. identical contents). On a properly configured and running system, script/admindctl.rb —sync will take care of both the configfile distribution and the subsequent restart of all instances.
Class Dsadmin::Logger
In most cases, error handling (recovery from unexpected problems) is done via a rather simple mechanism:
An exception is raised, cascading upwards until either
The first case is obviously the desirable, but less common than the second one.
If an exception is caught by a high-level catch-all, this obviously means something truly unexpected happened, so the system logs it as a "bug" (see Dsadmin::Logger), aborts the current operation and returns an "internal error" response to the client. This means that an error (including bugs in the code) should only affect the current request (never other requests or even the entire system!) and result in an at least halfway graceful aborting of that operation.
The code also makes frequent use of the assertions provided by Dsadmin::Contractor, implementing a simple variant of Design by Contract. Since the assertions simply throw an exception on failure (Test::Unit::AssertionFailedError), this integrates nicely into the core error handling described above.
See ./files/doc/src/projectdb.html
FIXME: To be written. Until then, look at the following:
All shown classes are in module Dsadmin::Admind.
All shown classes are in module Dsadmin::Admind. And there‘s of course also the Mirror and MirrorUpdate classes.