====== Server internals ======
This section is targeted for developers only. Network administrators do not need to read this section in order to use DHCP Cluster at its full potential. Curious techies and developers will find below details of how the server works and how to extend it.
===== Hot data vs Cold data =====
DHCP Cluster makes a clear distinction between **cold data** (slowly changing) and **hot data** (real time).
**Cold data** is manually edited by the network administrator and contains global DHCP parameters, network topology and detailed options lists to be sent back to the clients. Cold data is stored in an XML file or in the backend database.
**Hot data** is automatically constructed in real time from client requests and server responses. It contains basically IP leases: addresses distributed to clients. Since it is critical that a specific IP address cannot be given to two different clients, this information is updated in real time by each node in the cluster. Hot data is always stored in the central database.
{{hotcold.png?nolink|}}
Isolating Cold data from Hot data allows some very aggressive optimisations. Hot data remains centrally stored in the database and is accessed in real-time. On the opposite, Cold data is cached in each front-end for maximum performance. The front-end checks periodically (every x minutes) to check whether the configurations has changed. Front-ends should reload most of its configuration on the fly without a server restart - especially network topology changes.
===== Fallback mode =====
The central database is obviously a SPOF (single point of failure). Special care must be taken to garantee that the database is always up and running (cluster, high availability solutions...).
May the front-end not be able to connect to the database, it enters "Fallback Mode". The front-end tries to response to clients the best way it can. It reloads the server configuration (network topology) cached from the database. This cache is a simple serialization of java objects locally stored on each front-end.
In fallback mode, front-ends are only able to renew existing leases. It is obviously not capable of distributing new addresses to new clients, as this would probably create IP conflicts.
===== Stored procedures only =====
Hot data is modified through stored procedure only. This allows a clear isolation from the different front-ends. Communication between front-end and back-end is done via JDBC. Stored procedures can be considered as "SQL Service" without polluting front-end code with tons of SQL.
====== How to launch the server ======
There are two ways to launch the server: through CLI, or programmatically in your own application.
===== CLI launch =====
The CLI interface is managed through the Service Wrapper module which provides UNIX/Windows launch scripts, and a watch-dog features automatically relaunching the server after an unexpected shutdown.
The ''main()'' function is in ''org.dhcpdj.Server'' Class.
CLI options are parsed by the arg4j library, looking for ''-c'' parameter to specify the bootstrap configuration file. The default location is '''./conf/dhcpd-j.properties'''.
The ''Server'' object is instanciated and the content of the properties file passed as intial parameters (see below).
===== Programatic launch =====
The DHCP Server can be launched programatically in any existing application. You should create a new ''org.dhcpd-j.Server'' object with a ''Properties'' map.
Valid parameters are:
^config.mode|Server configuration mode (xml, oracle...|
^config.xml.file|Location of the xml file containing the server 'cold' configuration|
^to be completed|TODO: add jdbc connection parameters|
You then call the ''run()'' method.
Properties props = new Properties();
props.load("[bootstrap file]");
Server server = new Server(props);
server.run();
Note: the method ''run()'' returns only at server shutdown.
You may want to run the server in a dedicated thread. To do so, the ''Server'' class implements the ''Runnable'' class and can be easily launched in a separate thread.
Properties props = new Properties();
props.load("[bootstrap file]");
Server server = new Server(props);
Thread dispatchThread = new Thread(server);
dispatchThread.start();
====== Server startup sequence ======
As seen in the previous section, the ''Server'' is launched with a ''Properties'' map passed either through CLI or through programmatic launch.
The first parameter checked is ''config.mode''.
^config.mode|Server configuration mode (xml, oracle...)|
The ''/org/dhcpdj/config/ConfigReader.properties'' contains the mapping between the selected mode and the concrete onfigReader factories to be used.
Currently:
^config.mode^Class^
|''xml''|''org.dhcpdj.config.xml.XmlConfigReader''|
|''oracle''|To be completed|
===== ConfigReader factory =====
The ''ConfigReader'' factory is then responsible to instanciate all specific config readers and concrete handling classes.
* configuration readers: ''GlobalConfig'', ''FrontendConfig'', ''TopologyConfig'' (including dynamic reloading)
* DHCP Servlet: ''MainServlet'': concrete DHCP Servlet class handling all requests
* Backend interface: ''BackendIntf'': generic requests to the back-end
public interface ConfigReader {
public void init(Server dhcpCoreServer, Properties configProperties) throws ConfigException;
public GlobalConfig getGlobalConfig();
public FrontendConfig getFrontEndConfig();
public TopologyConfig getTopologyConfig();
public TopologyConfig reloadTopologyConfig();
public MainServlet makeMainServlet(Server mainServer);
public BackendIntf makeBackEnd();
}
The default mappings are included by default, and should be changed only when introducing new major features:
^''config.mode''^''xml''^''oracle''^
^''ConfigReader''|''org.dhcpdj.config.xml.XmlConfigReader''|'' ''|
^''GlobalConfig''|''org.dhcpdj.config.xml.XmlGlobalConfigReader''|'' ''|
^''FrontendConfig''|''org.dhcpdj.config.xml.XmlFrontEndConfigReader''|'' ''|
^''TopologyConfig''|''org.dhcpdj.config.xml.XmlTopologyConfigReader''|'' ''|
^''MainServlet''|''org.dhcpdj.config.xml.XmlMainServlet''|'' ''|
^''BackendIntf''|''org.dhcpdj.backend.hsql.HsqlBackendServer''|'' ''|
To be completed
====== Configuration loading sequence ======
There is a generic object framework for the server front-end. 'Cold' data is loaded either from XML files or from JDBC database, depending on '''config.mode''' bootstrap parameter.
There are 4 partitions in the configuration (see [[Server configuration]] page):
- **front-end**
- **global server**
- **topology**
- **back-end**\\ (note: the back-end section is only present if the back-end is embedded in the server, otherwise configure the back-end database separately)
===== Using the basic mode (xml and hsql) =====
The configuration is loaded from an xml file, whose location is set in the ''onfig.xml.file'' properties parameter.
The corresponding configuration objects are created through the XmlConfigReader factory.
^Configuration base object^xml section in config file^
|org.dhcpdj.config.FrontendConfig|...|
|org.dhcpdj.config.GlobalConfig|...|
|org.dhcpdj.config.TopologyConfig|...|
|TODO|...|
Schema needed here
==== DHCP Servlet launching ====
When all configuration objects are loaded, the DHCP Servlet is created and launched, see [[API Documentation|dhcp4java api documentation]].
The following parameter are taken from the front-end section of the XML file:
^section in XML file^property equivalent for DHCP Servlet^
||serverAddress "ip:port"|
||serverThreads|
||serverThreadsMax|
||serverThreadsKeepalive|
The DHCP Servlet is running in the same thread as the ''org.dhcpdj.Server.run()'' method.
==== Reloading configuration ====
The Server is designed to be able to reload most configuration elements dynamically, without any server restart. This is true for **topology** section.
The ''ConfigReader'' can be asked to reload/reparse a TopologyConfiguration after the server has been started. You may add features to avoid too frequent reloading (1 per minute may be an acceptable limit).
===== Using the extended mode =====
TODO
====== Server execution ======
The ''Server.run()'' method calls the ''DHCPServlet.run()'' method, thus delegating request handling. The real work is done in the ''org.dhcpdj.MainServlet'' class.