File: frontend.xml

package info (click to toggle)
configlet 1.8
  • links: PTS
  • area: main
  • in suites: woody
  • size: 1,044 kB
  • ctags: 211
  • sloc: python: 1,417; xml: 709; makefile: 139; sh: 44
file content (265 lines) | stat: -rw-r--r-- 13,057 bytes parent folder | download
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
<chapter>
    <chapterinfo>
      <releaseinfo>$Progeny: frontend.xml,v 1.19 2002/01/18 06:19:44 dsp Exp $</releaseinfo>
    </chapterinfo>

  <title>Front End Programming</title>

  <section>
    <title>Introduction</title>

    <para>
 The <emphasis>front end</emphasis> is the program that takes care of
 much of the housekeeping duties for the configlets.  It is
 responsible for starting the configlets, providing them a GUI
 toplevel widget of some kind to live in, handling global user
 interaction (such as navigation between the configlets), reading from
 and writing to the &debconf; database, and so on.
    </para>

    <para>
 Front ends generally distinguish themselves by the way they allow
 navigation between the configlets, as most of the rest of the front
 end's duties are rather mundane.  For example, the front end that
 ships with the configlet <ulink url="api/index.html">API</ulink> package places each configlet in a
 separate tab; other front ends exist that present the configlets in a
 &gnome; Druid widget (similar to Microsoft's Wizards) or that present
 the configlets as items in the &gnome; Control Center.  For this
 reason, most of the housekeeping code is provided by the <ulink url="api/index.html">API</ulink> itself,
 leaving the front end with little else except presentation and
 navigation functions.
    </para>

  </section>

  <section>
    <title>Writing a Front End</title>

    <para>
 Front ends generally perform a standard set of tasks in the same
 order.
    </para>

    <itemizedlist>

      <listitem>
        <para>
 Initialize and start the configlet(s) to be displayed.
        </para>
      </listitem>

      <listitem>
        <para>
 Read the &debconf; database, and pass that data to the configlets.
        </para>
      </listitem>

      <listitem>
        <para>
 Draw (or otherwise create) the top level widgets to contain the
 configlets, and insert the configlets into them.
        </para>
      </listitem>

      <listitem>
        <para>
 Interact with the user.  This includes handling of navigation events,
 OK/Cancel, or other possible events that could be generated by the
 user. 
        </para>
      </listitem>

      <listitem>
        <para>
 When the user is finished with the configlets, read the changed
 &debconf; information back from them and write it to the &debconf;
 database.
        </para>
      </listitem>

      <listitem>
        <para>
 Shut down the configlets, destroy the user interface, and terminate.
        </para>
      </listitem>

    </itemizedlist>

    <section id="sec-basicconfiggroup">
        <title>The <classname>BasicConfigGroup</classname> Class</title>

      <para>
 For many of these functions, the <ulink url="api/index.html">API</ulink> provides helper functions that
 handle the most common cases.  These functions are provided as
 methods to the <ulink url="api/configlet_BasicConfigGroup.py.html"><classname>BasicConfigGroup</classname></ulink> class.  Most
 front ends will need to merely create an instance of this class, or
 optionally inherit from it and create an instance of the derived
 class.
      </para>

      <para>
 A <ulink url="api/configlet_BasicConfigGroup.py.html"><classname>BasicConfigGroup</classname></ulink> object presents the
 interface of a Python sequence, containing a set of configlets in
 priority-sorted order.  This sequence is created by the constructor
 using a directory path; this directory is search for subdirectories
 containing configlets, and each configlet found is instantiated and
 added to the sequence.  The directory defaults to
 <filename>/usr/share/configlets</filename>, which means that the
 group will instantiate all configlets installed in the standard
 location by default.
      </para>

      <para>
 In addition to the normal sequence interface,
 <ulink url="api/configlet_BasicConfigGroup.py.html"><classname>BasicConfigGroup</classname></ulink> provides other helper methods
 which act on all configlets within the group.  These will be
 described below.
      </para>

    </section>

    <section>
      <title>Starting Configlets</title>

      <para>
 All configlets must be started using the
 <ulink url="api/configlet.py.html#start_configlet"><function>start_configlet</function></ulink> function.  It takes one
 argument: the directory in which the configlet resides.  It returns a
 fully instantiated configlet object.
      </para>

      <para>
 Configlets are only meant to be instantiated once.  If
 <ulink url="api/configlet.py.html#start_configlet"><function>start_configlet</function></ulink> is called more than once for the
 same directory, it will return a reference to the object it created
 previously, rather than creating a new one.
      </para>

      <para>
 If you use <ulink url="api/configlet_BasicConfigGroup.py.html"><classname>BasicConfigGroup</classname></ulink>, it uses
 <ulink url="api/configlet.py.html#start_configlet"><function>start_configlet</function></ulink> to start all of the configlets
 it finds.  Thus, you do not need to call
 <ulink url="api/configlet.py.html#start_configlet"><function>start_configlet</function></ulink> yourself.  Be aware, however,
 that the configlets in <ulink url="api/configlet_BasicConfigGroup.py.html"><classname>BasicConfigGroup</classname></ulink> have
 been created this way, and in particular cannot be "recreated"
 outside the group.
      </para>

    </section>

    <section>
      <title>Interacting with Debconf</title>

      <para>
 In order for the configlets to be useful, they need to be fed data
 from the &debconf; database, and they need to be able to feed changes
 back to &debconf;.  The front end is responsible for doing this, using
 two classes from the <ulink url="api/index.html">API</ulink>: the privileged runner classes and the
 <ulink url="api/configlet_DebConf.py.html"><classname>DebConf</classname></ulink> class.
      </para>

      <para>
 The privileged runner classes are intended to provide an interface
 for front ends to perform tasks as root.  They have a simple
 interface: a <ulink url="api/configlet_SimplePrivilegedRunner.py.html#run"><function>run</function></ulink> function, that takes the
 command to run as the only argument.  No return value is provided;
 <ulink url="api/configlet_SimplePrivilegedRunner.py.html#run"><function>run</function></ulink> will throw a RuntimeError exception if there
 is any problem running the command.  Because the interface is so
 simple, the privileged runner classes do not inherit; a class only
 needs to provide a <function>run</function> method in order to be a
 privileged runner.
      </para>

      <para>
 The <ulink url="api/index.html">API</ulink> provides two privileged runner classes: <ulink
url="api/configlet_SimplePrivilegedRunner.py.html"><classname>SimplePrivilegedRunner</classname></ulink>
and <ulink url="api/configlet_GnomeSudoPrivilegedRunner.py.html"><classname>GnomeSudoPrivilegedRunner</classname></ulink>.  The default
privileged runner, <ulink
url="api/configlet_SimplePrivilegedRunner.py.html"><classname>SimplePrivilegedRunner</classname></ulink>,
simply assumes that the front end already has root privileges and runs
commands accordingly.  <ulink url="api/configlet_GnomeSudoPrivilegedRunner.py.html"><classname>GnomeSudoPrivilegedRunner</classname></ulink>
uses the <command>gnome-sudo</command> command to obtain root to run the
command; this provides a nice graphical password dialog to the user when
root privilege is needed and caches the successful authentication for
subsequent commands.  See the <command>gnome-sudo</command> documentation
for setting this up properly.
      </para>

      <para>
 The <ulink url="api/configlet_DebConf.py.html"><classname>DebConf</classname></ulink> class does the actual work of
 getting and setting the &debconf; information.  A proper
 <ulink url="api/configlet_DebConf.py.html"><classname>DebConf</classname></ulink> object for the version of &debconf; can
 be obtained by calling <ulink url="api/configlet.py.html#get_debconf"><function>get_debconf</function></ulink>, passing in
 the list of packages that the configlets configure.  (This
 information can be retrieved by calling <function>get_packages</function> on the
 configlet, and calling get_packages on a
 <ulink url="api/configlet_BasicConfigGroup.py.html"><classname>BasicConfigGroup</classname></ulink> will get all of the packages
 configured by all of the configlets in the group.)  As the
 <ulink url="api/configlet_DebConf.py.html"><classname>DebConf</classname></ulink> class uses a privileged runner class
 to do its work, you should set an appropriate privileged runner class
 for it by calling the <ulink url="api/configlet_BasicConfigGroup.py.html#set_privileged_runner"><function>set_privileged_runner</function></ulink>
 method, passing in the privileged runner object as an argument.
      </para>

      <para>
 Once the DebConf object is set up, it provides three methods:
 <ulink url="api/configlet_DebConf.py.html#get"><function>get</function></ulink>, <ulink url="api/configlet_DebConf.py.html#set"><function>set</function></ulink>, and
 <ulink url="api/configlet_DebConf.py.html#commit"><function>commit</function></ulink>.  The <ulink url="api/configlet_DebConf.py.html#get"><function>get</function></ulink> method
 returns an array of strings containing the &debconf; data in the format
 the configlets need.  The <ulink url="api/configlet_DebConf.py.html#set"><function>set</function></ulink> method takes a
 similarly formatted array of strings as &debconf; data and sets it in
 the database.  The <ulink url="api/configlet_DebConf.py.html#commit"><function>commit</function></ulink> method takes it upon
 itself to cause the configured packages to reread their &debconf; data
 and reconfigure themselves accordingly.
      </para>

      <para>
 Once &debconf; information is read, it must be passed to the
 configlets.  This is done by taking the data returned from the
 <ulink url="api/configlet_DebConf.py.html#get"><function>get</function></ulink> method and passing it to the configlet's
 <ulink url="api/configlet_Configlet.py.html#load_debconf"><function>load_debconf</function></ulink> method.  The configlet will search
 through the data, finding the appropriate values it needs and saving
 them internally in some way.
      </para>

      <para>
 Saving &debconf; information involves several more steps.  First, all
 configlets must be told to prepare for shutdown; this is done with
 the <ulink url="api/configlet_Configlet.py.html#on_gnome_close"><function>on_gnome_close</function></ulink> method.  Then, call
 <ulink url="api/configlet_Configlet.py.html#report_debconf"><function>report_debconf</function></ulink> on each configlet, merge the
 results into a single array of strings, and pass that array to
 <ulink url="api/configlet_DebConf.py.html"><classname>DebConf</classname></ulink>'s <ulink url="api/configlet_DebConf.py.html#set"><function>set</function></ulink> method.
          Finally, call <ulink url="api/configlet_DebConf.py.html#commit"><function>DebConf.commit</function></ulink> to cause the
 packages to reconfigure.
      </para>

      <para>
 The <ulink url="api/configlet_BasicConfigGroup.py.html"><classname>BasicConfigGroup</classname></ulink> class does much of this
 work for you.  By calling the <ulink url="api/configlet_BasicConfigGroup.py.html#load_all_debconf"><function>load_all_debconf</function></ulink>
 method, you can cause the group to load the &debconf; information and
 send it to all of the configlets in the group.  Similarly, the
<ulink url="api/configlet_BasicConfigGroup.py.html#save_and_commit_all_debconf"><function>save_and_commit_all_debconf</function></ulink> method will read all
 of the &debconf; information from the configlets, save it to the
 &debconf; database, and commit it.  The
 <ulink url="api/configlet_BasicConfigGroup.py.html"><classname>BasicConfigGroup</classname></ulink> takes care of creating a
 DebConf object and managing it for you; you should, however, create
 an appropriate privileged runner and set it for the group by calling
 the group's <ulink url="api/configlet_BasicConfigGroup.py.html#set_privileged_runner"><function>set_privileged_runner</function></ulink> method on it.
 As an alternative, you can get access to the group's
 <ulink url="api/configlet_DebConf.py.html"><classname>DebConf</classname></ulink> object with the
 <ulink url="api/configlet.py.html#get_debconf"><function>get_debconf</function></ulink> method; you can then iterate across
 all of the configlets in the group to load or save data, or use the
 group's <ulink url="api/configlet_Configlet.py.html#load_debconf"><function>load_debconf</function></ulink> and
 <ulink url="api/configlet_Configlet.py.html#report_debconf"><function>report_debconf</function></ulink> methods, which do the iteration
 for you.
      </para>

    </section>

  </section>

</chapter>

<!--  Local variables: -->
<!--  eval: (sgml-load-dtd "../../doctools/docbook.ced") -->
<!--  End: -->