.. -*- mode: rst -*-

.. _server-plugins-grouping-metadata:

========
Metadata
========

The metadata mechanism has two types of information, client metadata
and group metadata. The client metadata describes which top level
group a client is associated with.The group metadata describes groups
in terms of what bundles and other groups they include. Group data and
clients' memberships are reflected in the `groups.xml`_ and
`clients.xml`_ files, respectively.

Usage of Groups in Metadata
===========================

Clients are assigned membership of groups in the Metadata
descriptions.  Clients can be directly assigned to *'profile'* or
*'public'* groups.  Client membership of all other groups is by those
groups being associated with the profile or public groups. This file
can be indirectly modified from clients through use of the ``-p`` flag
to ``bcfg2``.

Clients are associated with profile groups in `clients.xml`_
as shown below.

.. _server-plugins-grouping-metadata-clients-xml:

clients.xml
===========

The ``clients.xml`` file contains the mappings of Profile Groups
to clients. The file is just a series of ``<Client />`` tags, each of which
describe one host. A sample file is below:

.. code-block:: xml

    <Clients version="3.0">
      <Client profile="backup-server" name="backup.example.com"/>
      <Client profile="console-server" name="con.example.com"/>
      <Client profile="kerberos-master" name="kdc.example.com"/>
      <Client profile="mail-server" name="mail.example.com"/>
      <Client name='foo' address='10.0.0.1'>
        <Alias name='foo-mgmt' address='10.1.0.1'/>
      </Client>
    </Clients>

.. xml:schema:: clients.xsd

For detailed information on client authentication see
:ref:`appendix-guides-authentication`

.. _server-plugins-grouping-metadata-clients-database:

Clients Database
----------------

.. versionadded:: 1.3.0

It is also possible to store client records in a database rather than
writing back to `clients.xml`_.  This provides several advantages:

* `clients.xml`_ will never be written by the server, removing an
  area of contention between the user and server.
* `clients.xml`_ can be removed entirely for many sites.
* The Bcfg2 client list can be queried by other machines without
  obtaining and parsing `clients.xml`_.
* A single client list can be shared amongst multiple Bcfg2 servers.

In general, storing clients in the database works almost the same as
`clients.xml`_.  `groups.xml`_ is parsed identically.  If
`clients.xml`_ is present, it is parsed, but ``<Client>`` tags in
`clients.xml`_ *do not* assert client existence; they are only used
to set client options *if* the client exists (in the database).  That
is, the two purposes of `clients.xml`_ -- to track which clients
exist, and to set client options -- have been separated.

With the improvements in `groups.xml`_ parsing in 1.3, client groups
can now be set directly in `groups.xml`_ with ``<Client>`` tags. (See
:xml:type:`clientType` for more details.)  As a result, `clients.xml`_
is only necessary if you need to set options (e.g., aliases, floating
clients, per-client passwords, etc.) on clients.

To use the database backend instead of `clients.xml`_, set
``use_database`` in the ``[metadata]`` section of ``bcfg2.conf`` to
``true``.  You will also need to configure the :ref:`Global Server
Database Settings <server-database>`.

The `clients.xml`_-based model remains the default.

groups.xml
==========

The ``groups.xml`` file contains Group and Profile definitions. Here's
a simple ``groups.xml`` file:

.. code-block:: xml

    <Groups>
      <Group name='mail-server' profile='true'
                                comment='Top level mail server group' >
        <Bundle name='mail-server'/>
        <Bundle name='mailman-server'/>
        <Group name='apache-server'/>
        <Group name='nfs-client'/>
        <Group name='server'/>
        <Group name='rhel5'>
          <Group name='sendmail-server'/>
        </Group>
        <Group name='rhel6'>
          <Group name='postfix-server'/>
        </Group>
      </Group>
      <Group name='rhel'>
        <Group name='selinux-enabled'/>
      </Group>
      <Group name='oracle-server'>
        <Group name='selinux-enabled' negate='true'/>
      </Group>
      <Client name='foo.example.com'>
        <Group name='oracle-server'/>
        <Group name='apache-server'/>
      </Client>
    </Groups>

A Group tag that does not contain any child tags is a declaration of
membership; a Group or Client tag that does contain children is a
conditional.  So the example above does not assign either the
``rhel5`` or ``rhel6`` groups to machines in the ``mail-server``
group, but conditionally assigns the ``sendmail-server`` or
``postfix-server`` groups depending on the OS of the client.
(Presumably in this example the OS groups are set by a probe.)

Consequently, a client that is RHEL 5 and a member of the
``mail-server`` profile group would also be a member of the
``apache-server``, ``nfs-client``, ``server``, and ``sendmail-server``
groups; a RHEL 6 client that is a member of the ``mail-server``
profile group would be a member of the ``apache-server``,
``nfs-client``, ``server``, and ``postfix-server`` groups.

Client tags in `groups.xml`_ allow you to supplement the profile
group declarations in `clients.xml`_ and/or client group assignments
with the :ref:`server-plugins-grouping-grouppatterns` plugin.  They
should be used sparingly.  (They are more useful when you are using
the database backend for client records.)

You can also declare that a group should be negated; this allows you
to set defaults and override them efficiently.  Negation is applied
after other group memberships are calculated, so it doesn't matter how
many times a client is assigned to a group or how many times it is
negated; a single group negation is sufficient to remove a client from
that group.  For instance, in the following example,
``foo.example.com`` is **not** a member of ``selinux-enabled``, even
though it is a member of the ``foo-server`` and ``every-server``
groups:

.. code-block:: xml

    <Groups>
      <Group name="foo-server">
        <Group name="apache-server"/>
        <Group name="selinux-enabled"/>
      </Group>
      <Group name="apache-server">
        <Group name="selinux-enabled"/>
      </Group>
      <Group name="every-server">
        <Group name="selinux-enabled"/>
      </Group>
      <Client name="foo.example.com">
        <Group name="selinux-enabled" negate="true"/>
      </Client>

.. note::

    Nested Group conditionals, Client tags, and negated Group tags are
    all new in 1.3.0.

.. xml:schema:: metadata.xsd


XInclude
========

.. versionadded:: 0.9.0

`XInclude <http://www.w3.org/TR/xinclude/>`_ is a W3C specification
for the inclusion of external XML documents into XML source files,
allowing complex definitions to be split into smaller, more manageable
pieces. The `Metadata`_ plugin supports the use of XInclude
specifications to split the `clients.xml`_ and `groups.xml`_
files. This mechanism allows the following specification to produce
useful results:

.. code-block:: xml

    <Groups xmlns:xi="http://www.w3.org/2001/XInclude">
      <xi:include href="my-groups.xml" />
      <xi:include href="their-groups.xml" />
    </Groups>

Each of the included groups files has the same format. These files are
properly validated by ``bcfg2-lint``. This mechanism is useful for
composing group definitions from multiple sources, or setting
different permissions in an svn repository.

You can also optionally include a file that may or may not exist with
the ``fallback`` tag:

.. code-block:: xml

    <Groups xmlns:xi="http://www.w3.org/2001/XInclude">
      <xi:include href="my-groups.xml"/>
      <xi:include href="their-groups.xml"><xi:fallback/></xi:include>
    </Groups>

In this case, if ``their-groups.xml`` does not exist, no error will be
raised and everything will work fine.  (You can also use ``fallback``
to include a different file, or explicit content in the case that the
parent include does not exist.)

Wildcard XInclude
-----------------

.. versionadded:: 1.3.1

Bcfg2 supports an extension to XInclude that allows you to use shell
globbing in the hrefs.  (Stock XInclude doesn't support this, since
the href is supposed to be a URL.)

For instance:

.. code-block:: xml

    <Groups xmlns:xi="http://www.w3.org/2001/XInclude">
      <xi:include href="groups/*.xml"/>
    </Groups>

This would include all ``*.xml`` files in the ``groups`` subdirectory.

Note that if a glob finds no files, that is treated the same as if a
single included file does not exist.  You should use the ``fallback``
tag, described above, if a glob may potentially find no files.

Probes
======

The metadata plugin includes client-side probing functionality. This
is fully documented :ref:`here <server-plugins-probes-index>`.

Metadata Caching
================

.. versionadded:: 1.3.0

Client metadata can be cached in order to improve performance.  This
is particularly important if you have lots of templates that use
metadata from other clients (e.g., with the `MetadataQuery`_ interface
described below.  See :ref:`server-caching` for a full description of
the caching features available.

.. _server-plugins-grouping-metadata-clientmetadata:


ClientMetadata
==============

A special client metadata class is available to
:ref:`server-plugins-generators-cfg-genshi` and
:ref:`server-plugins-generators-cfg-cheetah`.

.. autoclass:: Bcfg2.Server.Plugins.Metadata.ClientMetadata

MetadataQuery
-------------

.. autoclass:: Bcfg2.Server.Plugins.Metadata.MetadataQuery
