summaryrefslogtreecommitdiffstats
path: root/doc/server/plugins/generators/packages.txt
blob: 774de44eeb3a2b9da1b23c3b92a8b8170bbb3c73 (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
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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
.. -*- mode: rst -*-

.. _server-plugins-generators-packages:

========
Packages
========

.. versionadded:: 1.0.0

This page documents the Packages plugin. Packages is an alternative to
:ref:`Pkgmgr <server-plugins-generators-pkgmgr>` for specifying package
entries for clients. Where Pkgmgr explicitly specifies package entry
information, Packages delegates control of package version information to
the underlying package manager, installing the latest version available
through those channels.

"Magic Groups"
==============

Packages is the only plugin that uses "magic groups". Most plugins
operate based on client group memberships, without any concern for the
particular names chosen for groups by the user. The Packages plugin is
the sole exception to this rule. Packages needs to "know" two different
sorts of facts about clients. The first is the basic OS/distro of the
client, enabling classes of sources. The second is the architecture of
the client, enabling sources for a given architecture. In addition to
these magic groups, each source may also specify a non-magic group to
limit the source's applicability to group member clients.

+-----------+----------+--------------+
| Source    | OS Group | Architecture |
+===========+==========+==============+
| APTSource | debian   | i386         |
+-----------+----------+--------------+
| APTSource | ubuntu   | amd64        |
+-----------+----------+--------------+
| APTSource | nexenta  |              |
+-----------+----------+--------------+
| YUMSource | redhat   | i386         |
+-----------+----------+--------------+
| YUMSource | centos   | x86_64       |
+-----------+----------+--------------+
| YUMSource | fedora   | x86_64       |
+-----------+----------+--------------+

Limiting sources to groups
==========================

Each source can also specify explicit group memberships. In the following
example, the ubuntu-hardy group is also required. Finally, clients must
be a member of the appropriate architecture group, in this case, either
i386 or amd64. In total, in order for this source to be associated with
a client is for the client to be in one of the sentinel groups (debian,
ubuntu, or nexenta), the explicit group ubuntu-hardy, and any of the
architecture groups (i386 or amd64).

Memberships in architecture groups is needed so that Packages can map
software sources to clients. There is no other way to handle this than
to impose membership in the appropriate architecture group.

When multiple sources are specified, clients are associated with each
source to which they apply (based on group memberships, as described
above). Packages and dependencies are resolved from all applicable
sources.

.. note:: To recap, a client needs to be a member of the **OS Group**,
          **Architecture** group, and any other groups defined in your
          ``Packages/config.xml`` file in order for the client to be
          associated to the proper sources.

Setup
=====

Three basic steps are required for Packages to work properly.

#. Create Packages/config.xml. This file should look approximately like the example below, and describes both which software repositories should be used, and which clients are eligible to use each one.
#. Ensure that clients are members of the proper groups. Each client should be a member of one of the sentinel groups listed above (debian/ubuntu/redhat/centos/nexenta), all of the groups listed in the source (like ubuntu-intrepid or centos-5.2 in the following examples), and one of the architecture groups listed in the source configuration (i386, amd64 or x86_64 in the following examples). '''Failure to do this will result in the source either not applying to the client, or only architecture independent packages being made available to the client.'''
#. Add Package entries to bundles.
#. Sit back and relax, as dependencies are resolved, and automatically added to client configurations.

Prerequisite Resolution
=======================

Packages provides a prerequisite resolution mechanism which has no
analogue in Pkgmgr. During configuration generation, all structures are
processed. After this phase, but before entry binding, a list of packages
and the client metadata instance is passed into Packages' resolver. This
process determines a superset of packages that will fully satisfy
dependencies of all package entries included in structures, and reports
any prerequisites that cannot be satisfied. This facility should largely
remove the need to use the :ref:`Base <server-plugins-structures-base>`
plugin.

Disabling dependency resolution
-------------------------------

.. versionadded:: 1.1.0

Dependency resolution can now be disabled by adding this to Sources in config.xml:

.. code-block:: xml

    <Sources>
        <Config resolver="disabled" />
        ...
    </Sources>

All metadata processing can be disabled as well:

.. code-block:: xml

    <Sources>
        <Config metadata="disabled" />
        ...
    </Sources>

.. _packages-exampleusage:

Example usage
=============

Create a config.xml file in the Packages directory that looks something
like this:

.. code-block:: xml

    <Sources>
      <APTSource>
        <Group>ubuntu-intrepid</Group>
        <URL>http://us.archive.ubuntu.com/ubuntu</URL>
        <Version>intrepid</Version>
        <Component>main</Component>
        <Component>universe</Component>
        <Arch>i386</Arch>
        <Arch>amd64</Arch>
      </APTSource>
    </Sources>

.. note::
    The default behavior of the Packages plugin is to not make
    any assumptions about which packages you want to have added
    automatically. For that reason, neither **Recommended**
    nor **Suggested** packages are added as dependencies by
    default. You will notice that the default behavior for apt is
    to add Recommended packages as dependencies. You can configure
    the Packages plugin to add recommended packages by adding
    the following line immediately following the URL:

    .. versionadded:: 1.1.0

    .. code-block:: xml

        <Recommended>True</Recommended>

Yum sources can be similarly specified:

.. code-block:: xml

    <Sources>
      <YUMSource>
        <Group>centos-5.2</Group>
        <URL>http://mirror.centos.org/centos/</URL>
        <Version>5.2</Version>
        <Component>os</Component>
        <Component>updates</Component>
        <Component>extras</Component>
        <Arch>i386</Arch>
        <Arch>x86_64</Arch>
      </YUMSource>
    </Sources>

.. note:: There is also a RawURL syntax for specifying APT or YUM sources that
          don't follow the conventional layout:

          .. code-block:: xml

              <Sources>
                <!-- CentOS (5.4) sources -->
                <YUMSource>
                  <Group>centos5.4</Group>
                  <RawURL>http://mrepo.ices.utexas.edu/centos5-x86_64/RPMS.os</RawURL>
                  <Arch>x86_64</Arch>
                </YUMSource>
                <YUMSource>
                  <Group>centos5.4</Group>
                  <RawURL>http://mrepo.ices.utexas.edu/centos5-x86_64/RPMS.updates</RawURL>
                  <Arch>x86_64</Arch>
                </YUMSource>
                <YUMSource>
                  <Group>centos5.4</Group>
                  <RawURL>http://mrepo.ices.utexas.edu/centos5-x86_64/RPMS.extras</RawURL>
                  <Arch>x86_64</Arch>
                </YUMSource>
              </Sources>

          .. code-block:: xml

              <Sources>
                <APTSource>
                  <Group>ubuntu-lucid</Group>
                  <RawURL>http://hudson-ci.org/debian/binary</RawURL>
                  <Arch>amd64</Arch>
                </APTSource>
                <APTSource>
                  <Group>ubuntu-lucid</Group>
                  <RawURL>http://hudson-ci.org/debian/binary</RawURL>
                  <Arch>i386</Arch>
                </APTSource>
              </Sources>

Configuration Updates
=====================

Packages will reload its configuration upon an explicit command via
bcfg2-admin.::

    [0:3711] bcfg2-admin xcmd Packages.Refresh
    True

During this command (which will take some time depending on the quantity
and size of the sources listed in the configuration file), the server
will report information like::

    Packages: Updating http://mirror.anl.gov/ubuntu//dists/jaunty/main/binary-i386/Packages.gz
    Packages: Updating http://mirror.anl.gov/ubuntu//dists/jaunty/main/binary-amd64/Packages.gz
    Packages: Updating http://mirror.anl.gov/ubuntu//dists/jaunty/universe/binary-i386/Packages.gz
    Packages: Updating http://mirror.anl.gov/ubuntu//dists/jaunty/universe/binary-amd64/Packages.gz
    ...
    Packages: Updating http://mirror.centos.org/centos/5/extras/x86_64/repodata/filelists.xml.gz
    Packages: Updating http://mirror.centos.org/centos/5/extras/x86_64/repodata/primary.xml.gz

Once line per file download needed. Packages/config.xml will be reloaded
at this time, so any source specification changes (new or modified
sources in this file) will be reflected by the server at this point.

Soft reload
-----------

.. versionadded:: 1.1.0

A soft reload can be performed to reread the configuration file and download only missing sources.::

    [0:3711] bcfg2-admin xcmd Packages.Reload
    True

Availability
============

Support for clients using yum and apt is currently available.  Support for
other package managers (Portage, Zypper, IPS, etc) remain to be added.

Validation
==========

A schema for Packages/config.xml is included; config.xml can be validated
using ``bcfg2-repo-validate``.

.. note:: The schema requires that elements be specified in the above order.

Limitations
===========

Packages does not do traditional caching as other plugins do. Changes
to the Packages config file require a server restart for the time being.

Package Verification
====================

In order to do disable per-package verification Pkgmgr style, you will
need to use :ref:`BoundEntries <boundentries>` like below

.. code-block:: xml

    <BoundPackage name="mem-agent" priority="1" version="auto" type="yum" verify="false"/>

Generating Client APT/Yum Configurations
========================================

.. versionadded:: 1.1.0

Client repository information can be generated automatically from
software sources using :doc:`./tgenshi/index` or :doc:`./tcheetah`.
A list of source urls are exposed in the client's metadata as
metadata.Packages.sources.

An example :doc:`./tgenshi/index` APT template::

    # bcfg2 maintained apt

    {% for s in metadata.Packages.sources %}\
    deb ${s.url}${s.version} ${s.groups[0]} {% for comp in s.components %}$comp {% end %}

    {% end %}\

An example :doc:`./tgenshi/index` YUM template::

    # bcfg2 maintained yum

    % for s in metadata.Packages.sources %}\
    [${s.groups[0]}_${s.component}]
    name=${s.groups[0]}_${s.component}
    baseurl=${s.url}

    {% end %}\

Debugging unexpected behavior
=============================

Using bcfg2-info
----------------

The dependency resolver used in Packages can be run in debug mode::


    $ bcfg2-info
    ...
    Handled 20 events in 0.004s
    > debug
    dropping to python interpreter; press ^D to resume
    ...
    (debug_shell)
    >>> m = self.build_metadata('ubik3')
    >>> self.plugins['Packages'].complete(m, ['ssh'], debug=True)
    Package ssh: adding new deps ['openssh-client', 'openssh-server']
    Package openssh-server: adding new deps ['libc6', 'libcomerr2', 'libkrb53', 'libpam0g', 'libselinux1', 'libssl0.9.8
    ', 'libwrap0', 'zlib1g', 'debconf', 'libpam-runtime', 'libpam-modules', 'adduser', 'dpkg', 'lsb-base']
    Package debconf: adding new deps ['debconf-i18n']
    Package libpam-modules: adding new deps ['libdb4.7']
    Package openssh-client: adding new deps ['libedit2', 'libncurses5', 'passwd']
    Package lsb-base: adding new deps ['sed', 'ncurses-bin']
    Package adduser: adding new deps ['perl-base']
    Package debconf-i18n: adding new deps ['liblocale-gettext-perl', 'libtext-iconv-perl', 'libtext-wrapi18n-perl', 'libtext-charwidth-perl']
    Package passwd: adding new deps ['debianutils']
    Package libtext-charwidth-perl: adding new deps ['perlapi-5.10.0']
    VPackage perlapi-5.10.0: got provides ['perl-base']
    Package libkrb53: adding new deps ['libkeyutils1']
    Package libtext-iconv-perl: adding new deps ['perlapi-5.10.0']
    Package libc6: adding new deps ['libgcc1', 'findutils']
    Package libgcc1: adding new deps ['gcc-4.3-base']
    (set(['debconf', 'libgcc1', 'lsb-base', 'libtext-wrapi18n-perl', 'libtext-iconv-perl', 'sed', 'passwd', 'findutils', 'libpam0g', 'openssh-client', 'debconf-i18n', 'libselinux1', 'zlib1g', 'adduser', 'libwrap0', 'ncurses-bin', 'libssl0.9.8', 'liblocale-gettext-perl', 'libkeyutils1', 'libpam-runtime', 'libpam-modules', 'openssh-server', 'libkrb53', 'ssh', 'libncurses5', 'libc6', 'libedit2', 'libcomerr2', 'dpkg', 'perl-base', 'libdb4.7', 'libtext-charwidth-perl', 'gcc-4.3-base', 'debianutils']), set([]), 'deb')

This will show why the resolver is acting as it is. Replace "ubik3" and
['ssh'] with a client name and list of packages, respectively. Also,
a more polished interface to this functionality is coming as well.

Each line starting with Package: <name> describes a set of new
prerequisites pulled in by a package. Lines starting with VPackage <vname>
describe provides entries and their mappings to required names. The last
line describes the overall results of the resolver, with three fields:
a list of packages that should be installed, a list of unresolved
requirements, and a type for these packages.

Using bcfg2-server
------------------

Once the server is started, enable debugging via bcfg2-admin::

    $ bcfg2-admin xcmd Packages.toggle_debug

TODO list
=========

* Zypper support
* Portage support
* Explicit version pinning (a la Pkgmgr)

Developing for Packages
=======================

In order to support a given client package tool driver, that driver
must support use of the auto value for the version attribute in Package
entries. In this case, the tool driver views the current state of
available packages, and uses the underlying package manager's choice of
correct package version in lieu of an explicit, centrally-specified,
version. This support enables Packages to provide a list of Package
entries with version='auto'. Currently, the APT and YUMng drivers support
this feature. Note that package management systems without any network
support cannot operate in this fashion, so RPMng and SYSV will never be
able to use Packages. Emerge, Zypper, IPS, and Blastwave all have the
needed features to be supported by Packages, but support has not yet
been written.

Packages fills two major functions in configuration generation. The first
is to provide entry level binding support for Package entries included
in client configurations. This function is quite easy to implement;
Packages determines (based on client group membership) if the package
is available for the client system, and which type it has. Because
version='auto' is used, no version determination needs to be done.

The second major function is more complex. Packages ensures that client
configurations include all package-level prerequisites for package entries
explicitly included in the configuration. In order to support this,
Packages needs to directly process network data for package management
systems (the network sources for apt or yum, for examples), process
these files, and build data structures describing prerequisites and the
providers of those functions/paths. To simplify implementations of this,
there is a generic base class (Bcfg2.Server.Plugins.Packages.Source)
that provides a framework for fetching network data via HTTP, processing
those sources (with subclass defined methods for processing the specific
format provided by the tool), a generic dependency resolution method,
and a caching mechanism that greatly speeds up server/bcfg2-info startup.

Each source type must define:

* a get_urls attribute (and associated urls property) that describes
  the URLS where to get data from.
* a read_files method that reads and processes the downloaded files

Sources may define a get_provides method, if provides are complex. For
example, provides in rpm can be either rpm names or file paths, so
multiple data sources need to be multiplexed.

The APT source in ``src/lib/Server/Plugins/Packages.py`` provides a
relatively simple implementation of a source.