summaryrefslogtreecommitdiffstats
path: root/doc/development.xml
blob: b6e7b62cec533f7aa5bc69be451e8342e1a772ff (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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
<chapter id='chap:development'>
<title>Developing for Bcfg2</title>

  <para>
    While the Bcfg2 server provides a good interface for representing
    general system configurations, its plugin interface offers the
    ability to implement configuration interfaces and representation
    tailored to problems encountered by a particular site. This
    chapter describes what plugins are good for, what they can do, and
    how to implement them.
  </para>
  
  <section id='sec:plugins'>
    <title>Bcfg2 Plugins</title>

    <para>
      Bcfg2 plugins are loadable python modules that the Bcfg2 server
      loads at initialization time. These plugins can contribute to
      the functions already offered by the Bcfg2 server or can extend
      its functionality. In general, plugins will provide some portion
      of the configuration for clients, with a data representation
      that is tuned for a set of common tasks. Much of the core
      functionality of Bcfg2 is implemented by several plugins,
      however, they are not special in any way; new plugins could
      easily supplant one or all of them. 
    </para>

    <table id='table:plugin-functions'>
      <title>Bcfg2 Plugin Functions</title>
      <tgroup cols='2'>
	<colspec colnum='1'/>
	<colspec colnum='2'/>
	<thead>
	  <row><entry>Name</entry><entry>Description</entry></row>
	</thead>
	<tbody>
	  <row><entry>Probes</entry><entry>Plugins can send executable
	  code to clients, where local contributions to configuration
	  state can be gathered.</entry></row>
	  <row><entry>Abstract Configuration Structures</entry>
	    <entry>A plugin can define new groups of interdependent
	    and independent configuration entities</entry></row>
	  <row><entry>Literal Configuration Entities</entry>
	    <entry>Plugins can provide literal configuration entity
	    information.</entry></row>
	  <row><entry>XML-RPC Functions</entry>
	    <entry>Plugins can expose a set of functions through the
	    Bcfg2 server's authenticated XML-RPC interface.</entry></row>
	</tbody>
      </tgroup>
    </table>

  </section>

  <section id='sec:writing-plugins'>
    <title>Writing Bcfg2 Plugins</title>

    <para>
      Bcfg2 plugins are python classes that subclass from
      Bcfg2.Server.Plugin.Plugin. Several plugin-specific values must
      be set in the new plugin. These values dictate how the new
      plugin will behave with respect to the above four functions.
    </para>


    <table id='table:plugin-members'>
      <title>Bcfg2 Plugin Members</title>
      <tgroup cols='3'>
	<colspec colnum='1' colwidth='1*'/>
	<colspec colnum='2' colwidth='3*'/>
	<colspec colnum='3' colwidth='2*'/>
	<thead>
	  <row><entry>Name</entry><entry>Description</entry><entry>Format</entry></row>
	</thead>
	<tbody>
	  <row><entry>__name__</entry><entry>The name of the
	      plugin</entry><entry>string</entry>
	  </row>
	  <row><entry>__version__</entry>
	    <entry>The plugin version (generally tied to revctl
	    keyword expansion).</entry><entry>string</entry></row>
	  <row><entry>__author__</entry>
	    <entry>The plugin author.</entry><entry>string</entry></row>
	  <row><entry>__rmi__</entry>
	    <entry>Set of functions to be exposed as XML-RPC
	    functions</entry>
	    <entry>List of function names (strings)</entry></row>
	  <row><entry>Entries</entry><entry>Multidimentional
	  dictionary of keys that point to the function used to bind
	  literal contents for a given configuration
	  entity.</entry><entry>Dictionary of
	  ConfigurationEntityType, Name keys and function reference
	  values</entry></row>
	  <row><entry>BuildStructures</entry><entry>Function that
	  returns a list of the structures for a given
	  client</entry><entry>Member function</entry></row>
	  <row><entry>GetProbes</entry><entry>Function that returns a
	  list of probes that a given client should
	  execute</entry><entry>Member function</entry></row>
	  <row><entry>ReceiveData</entry><entry>Function that accepts
	  the probe results for a given client.</entry><entry>Member
	  function</entry></row>
	</tbody>
      </tgroup>
    </table>
    
    <section id='sec:example-plugin'>
      <title>An Example Plugin</title>

      <example id='ex:simple-plugin'>
	<title>A Simple Plugin</title>
      <programlisting>import socket, Bcfg2.Server.Plugin

class Chiba(Bcfg2.Server.Plugin.Plugin):
    '''the Chiba plugin builds the following files:
      -> /etc/network/interfaces'''

    __name__ = 'Chiba'
    __version__ = '$Id: chiba.py 1702 2006-01-19 20:20:51Z desai '
    __author__ = 'bcfg-dev@mcs.anl.gov'
    Entries = {'ConfigFile':{}}

    def __init__(self, core, datastore):
        Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
        self.repo = Bcfg2.Server.Plugin.DirectoryBacked(self.data, 
	  self.core.fam)
        self.Entries['ConfigFile']['/etc/network/interfaces'] \ 
	  = self.build_interfaces

    def build_interfaces(self, entry, metadata):
        '''build network configs for clients'''
        entry.attrib['owner'] = 'root'
        entry.attrib['group'] = 'root'
        entry.attrib['perms'] = '0644'
        try:
            myriaddr = socket.gethostbyname("%s-myr" % \
	  metadata.hostname)
        except socket.gaierror:
            self.LogError("Failed to resolve %s-myr"% metadata.hostname)
            raise Bcfg2.Server.Plugin.PluginExecutionError, ("%s-myr" \
            % metadata.hostname, 'lookup')
        entry.text = self.repo.entries['interfaces-template'].data % \
	  myriaddr
      </programlisting>
    </example>

    <para>
	Bcfg2 server plugins must subclass the
	Bcfg2.Server.Plugin.Plugin class. Plugin constructors must
	take two arguments: an instance of a Bcfg2.Core object, and a
	location for a datastore. __name__, __version__, __author__,
	and Entries are used to describe what the plugin is and how it
	works. Entries describes a set of configuration entries that
	can be provided by the generator, and a set of handlers that
	can bind in the proper data. build_interfaces is an example of
	a handler. It gets client metadata and an configuration entry
	passed in, and binds data into entry as appropriate. This
	results in a <filename>/etc/network/interfaces</filename> file
	that has static information derived from DNS for a given host.
    </para>

    </section>

  </section>
</chapter>