summaryrefslogtreecommitdiffstats
path: root/doc/development/client-driver.txt
blob: 19da9cb673e3ae59e37e25662e143a0609cf908c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
.. -*- mode: rst -*-

.. _development-client-driver:

Writing A Client Tool Driver
============================

This page describes the step-by-step process of writing a client tool
driver for a configuration element type. The included example describes
an existing driver, and the process that was used to create it.

#. Pick a name for the driver. In this case, we picked the name RPM.
#. Add "RPM" to the ``__all__ list`` in ``src/lib/Client/Tools/__init__.py``
#. Create a file in ``src/lib/Client/Tools`` with the same name (RPM.py)
#. Create a class in this file with the same name (``class RPM``)

   * If it handles ``Package`` entries, subclass ``Bcfg2.Client.Tools.PkgTool``
     (from here referenced as branch [P])
   * If it handles ``Service`` entries, subclass ``Bcfg2.Client.Tools.SvcTool``
     (from here referenced as branch [S])
   * Otherwise, ``subclass Bcfg2.Client.Tools.Tool`` (from here referenced
     as branch [T])

#. Set ``__name__`` to "RPM"
#. Add any required executable programs to ``__execs__``
#. Set ``__handles__`` to a list of (``entry.tag``, ``entry.get('type')``)
   tuples. This determines which entries the Tool module can be used
   on. In this case, we set ``__handles__ = [('Package', 'rpm')]``.
#. Add verification. This method should return True/False depending
   on current entry installation status.

   * [T] Add a Verify<entry.tag> method.
   * [P] Add a VerifyPackage method.
   * [S] Add a VerifyService method.
   * In the failure path, the current state of failing entry
     attributes should be set in the entry, to aid in auditing.
     (For example, if a file should be mode 644, and is currently
     mode 600, then set attribute current_perms='600' in the input
     entry)

#. Add installation support. This method should return True/False
   depending on the results of the installation process.

   * [T,S] Add an Install<entry.tag> method.
   * [P] The PkgTool baseclass has a generic mechanism for performing
     all-at-once installations, followed, in the case of failures, 
     by single installations. To enable this support, set the pkgtype 
     attribute to the package type handled by this driver. Set the
     ``pkgtool`` to a tuple ("command string %s", ("per-package string
     format", [list of package entry fields])). For RPM, we have
     ``setup pkgtool =  ("rpm --oldpackage --replacepkgs --quiet -U %s", ("%s", ["url"]))``

#. Implement entry removal

   * [T,S] Implement a ``Remove`` method that removes all specified
     entries (``prototype Remove(self, entries)``)
   * [P] Implement a ``RemovePackages`` that removes all specified
     entries (same prototype as Remove)

#. Add a ``FindExtra`` method that locates entries not included in the
   configuration. This may or may not be required, certain drivers
   do not have the capability to find extra entries.
#. [P] Package drivers require a ``RefreshPackages`` method that updates
   the internal representation of the package database.

Writing Tool Driver Methods
---------------------------

#. Programs can be run using ``self.cmd.run``. This function returns a
   (return code, stdout list) tuple.
#. The configuration is available as ``self.config``
#. Runtime options are available in a dictionary as ``self.setup``
#. Informational, error, and debug messages can be produced by 
   running ``self.logger.info/error/debug``.