summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--debian/control3
-rw-r--r--doc/appendix/guides/centos.txt8
-rw-r--r--doc/appendix/guides/fedora.txt2
-rw-r--r--doc/appendix/guides/import-existing-ssh-keys.txt128
-rw-r--r--doc/appendix/guides/ubuntu.txt4
-rw-r--r--doc/appendix/guides/web-reports-install.txt7
-rw-r--r--doc/reports/dynamic.txt2
-rw-r--r--doc/reports/static.txt2
-rw-r--r--doc/server/plugins/generators/nagiosgen.txt2
-rw-r--r--doc/server/plugins/generators/tcheetah.txt8
-rw-r--r--doc/server/plugins/generators/tgenshi/clientsxml.txt6
-rw-r--r--doc/server/plugins/generators/tgenshi/index.txt2
-rw-r--r--doc/server/plugins/generators/tgenshi/test.txt34
-rw-r--r--doc/server/plugins/probes/group.txt8
-rw-r--r--doc/server/plugins/probes/index.txt10
-rw-r--r--doc/server/plugins/statistics/dbstats.txt2
-rw-r--r--examples/metadata.xml13
-rw-r--r--gentoo/bcfg2-1.1.1.ebuild19
-rw-r--r--src/lib/Client/Tools/APT.py21
-rw-r--r--src/lib/Client/Tools/DebInit.py8
-rw-r--r--src/lib/Client/Tools/YUM24.py421
-rw-r--r--src/lib/Component.py4
-rw-r--r--src/lib/Server/Admin/Init.py162
-rw-r--r--src/lib/Server/Plugin.py10
-rw-r--r--src/lib/Server/Plugins/Packages.py4
-rw-r--r--src/lib/Server/Plugins/Probes.py2
-rwxr-xr-xsrc/sbin/bcfg22
-rwxr-xr-xsrc/sbin/bcfg2-admin5
28 files changed, 732 insertions, 167 deletions
diff --git a/debian/control b/debian/control
index 4db926f77..881052dd6 100644
--- a/debian/control
+++ b/debian/control
@@ -1,7 +1,8 @@
Source: bcfg2
Section: admin
Priority: optional
-Maintainer: Sami Haahtinen <ressu@debian.org>
+Maintainer: Arto Jantunen <viiru@debian.org>
+Uploaders: Sami Haahtinen <ressu@debian.org>
Build-Depends: debhelper (>= 7.0.50~), python (>= 2.3.5-7)
Build-Depends-Indep: python-support (>= 0.5.3)
Standards-Version: 3.8.0.0
diff --git a/doc/appendix/guides/centos.txt b/doc/appendix/guides/centos.txt
index db463b210..b0321eebc 100644
--- a/doc/appendix/guides/centos.txt
+++ b/doc/appendix/guides/centos.txt
@@ -248,7 +248,7 @@ arch group membership. For this, we will make use of the
Probes to your plugins line in ``bcfg2.conf`` and create the Probe.::
[root@centos ~]# grep plugins /etc/bcfg2.conf
- plugins = Base,Bundler,Cfg,Metadata,Packages,Probes,Rules,SSHbase
+ plugins = Base,Bundler,Cfg,...,Probes
[root@centos ~]# mkdir /var/lib/bcfg2/Probes
[root@centos ~]# cat /var/lib/bcfg2/Probes/groups
#!/bin/sh
@@ -259,8 +259,8 @@ Now we restart the bcfg2-server::
[root@centos ~]# /etc/init.d/bcfg2-server restart
-If you tail ``/var/log/syslog`` now, you will see the Packages plugin in
-action, updating the cache.
+If you now ``tail -f /var/log/messages``, you will see the Packages
+plugin in action, updating the cache.
Start managing packages
-----------------------
@@ -569,4 +569,4 @@ Now we run the client and see there are no more unmanaged entries! ::
Dynamic (web) reports
=====================
-See installation instructions at :ref:`server-reports-install`
+See installation instructions at :ref:`reports-dynamic`
diff --git a/doc/appendix/guides/fedora.txt b/doc/appendix/guides/fedora.txt
index 1dd4f6db0..f32eaa8c6 100644
--- a/doc/appendix/guides/fedora.txt
+++ b/doc/appendix/guides/fedora.txt
@@ -139,7 +139,7 @@ The ``bcfg2.conf`` file contains only standard plugins so far.
[server]
repository = /var/lib/bcfg2
- plugins = Base,Bundler,Cfg,Metadata,Pkgmgr,Rules,SSHbase
+ plugins = SSHbase,Cfg,Pkgmgr,Rules,Metadata,Base,Bundler
[statistics]
sendmailpath = /usr/lib/sendmail
diff --git a/doc/appendix/guides/import-existing-ssh-keys.txt b/doc/appendix/guides/import-existing-ssh-keys.txt
new file mode 100644
index 000000000..d0f679b59
--- /dev/null
+++ b/doc/appendix/guides/import-existing-ssh-keys.txt
@@ -0,0 +1,128 @@
+.. -*- mode: rst -*-
+
+.. _appendix-guides-import-existing-ssh-keys:
+
+========================
+Import existing ssh keys
+========================
+
+.. note::
+
+ In order for the instructions in this guide to work, you will need
+ to first setup the :ref:`reporting system <reports-dynamic>` so that
+ the server has the information needed to create the existing
+ entries.
+
+This guide details the process for importing existing ssh keys into your
+server repository.
+
+Add a bundle for ssh
+====================
+
+After verifying that SSHbase is listed on the plugins line in
+``/etc/bcfg2.conf``, you need to create a bundle containing the
+appropriate entries.::
+
+ cat > /tmp/ssh.xml << EOF
+ <Bundle name='ssh'>
+ <Path name='/etc/ssh/ssh_host_dsa_key'/>
+ <Path name='/etc/ssh/ssh_host_rsa_key'/>
+ <Path name='/etc/ssh/ssh_host_dsa_key.pub'/>
+ <Path name='/etc/ssh/ssh_host_rsa_key.pub'/>
+ <Path name='/etc/ssh/ssh_host_key'/>
+ <Path name='/etc/ssh/ssh_host_key.pub'/>
+ <Path name='/etc/ssh/ssh_known_hosts'/>
+ </Bundle>
+
+::
+
+ mv /tmp/ssh.xml /var/lib/bcfg2/Bundle
+
+Next, you need to add the ssh bundle to the client's metadata in
+groups.xml.
+
+Validate your repository
+========================
+
+Validation can be performed using the following command::
+
+ ``bcfg2-repo-validate -v``
+
+Run the bcfg2 client
+====================
+
+::
+ bcfg2 -vqn
+
+You will see the incorrect entries for the ssh files::
+
+ Phase: initial
+ Correct entries: 0
+ Incorrect entries: 7
+ Total managed entries: 7
+ Unmanaged entries: 649
+
+ In dryrun mode: suppressing entry installation for:
+ Path:/etc/ssh/ssh_host_dsa_key Path:/etc/ssh/ssh_host_rsa_key
+ Path:/etc/ssh/ssh_host_dsa_key.pub Path:/etc/ssh/ssh_host_rsa_key.pub
+ Path:/etc/ssh/ssh_host_key Path:/etc/ssh/ssh_known_hosts
+ Path:/etc/ssh/ssh_host_key.pub
+
+ Phase: final
+ Correct entries: 0
+ Incorrect entries: 7
+ Path:/etc/ssh/ssh_host_dsa_key Path:/etc/ssh/ssh_host_rsa_key
+ Path:/etc/ssh/ssh_host_dsa_key.pub Path:/etc/ssh/ssh_host_rsa_key.pub
+ Path:/etc/ssh/ssh_host_key Path:/etc/ssh/ssh_known_hosts
+ Path:/etc/ssh/ssh_host_key.pub
+ Total managed entries: 7
+ Unmanaged entries: 649
+
+Install the client's ssh keys into the Bcfg2 repository
+=======================================================
+
+Now, we pull the ssh host key data for the client out of the uploaded
+stats and insert it as host-specific copies of these files in
+``/var/lib/bcfg2/SSHBase``.::
+
+ for key in ssh_host_dsa_key ssh_host_key; do
+ sudo bcfg2-admin pull <clientname> Path /etc/ssh/$key
+ sudo bcfg2-admin pull <clientname> Path /etc/ssh/${key}.pub
+ done
+
+This for loop pulls data that was collected by the bcfg2 client out of
+the statistics file and installs it into the repository. This means that
+the client will keep the same ssh keys and the bcfg2 server can start
+generating a correct ssh_known_hosts file for the client.
+
+Run the bcfg2 client (again)
+============================
+
+::
+ bcfg2 -vqn
+
+This time, we will only see 1 incorrect entry.::
+
+ Phase: initial
+ Correct entries: 6
+ Incorrect entries: 1
+ Total managed entries: 7
+ Unmanaged entries: 649
+
+ In dryrun mode: suppressing entry installation for:
+ Path:/etc/ssh/ssh_known_hosts
+
+ Phase: final
+ Correct entries: 6
+ Incorrect entries: 1
+ Path:/etc/ssh/ssh_known_hosts
+ Total managed entries: 7
+ Unmanaged entries: 649
+
+Now, the only wrong entry is the ssh_known_hosts file!, so go ahead
+and install it::
+
+ bcfg2 -vqI
+
+After answering 'y' to the interactive prompt, the client will install
+the known_hosts file successfully.
diff --git a/doc/appendix/guides/ubuntu.txt b/doc/appendix/guides/ubuntu.txt
index 595005018..54aa62cce 100644
--- a/doc/appendix/guides/ubuntu.txt
+++ b/doc/appendix/guides/ubuntu.txt
@@ -119,7 +119,7 @@ Replace Pkgmgr with Packages in the plugins line of ``bcfg2.conf``::
root@lucid:~# cat /etc/bcfg2.conf
[server]
repository = /var/lib/bcfg2
- plugins = Base,Bundler,Cfg,Metadata,Packages,Rules,SSHbase
+ plugins = SSHbase,Cfg,Packages,Rules,Metadata,Base,Bundler
[statistics]
sendmailpath = /usr/lib/sendmail
@@ -207,7 +207,7 @@ Probes to your plugins line in ``bcfg2.conf`` and create the Probe.
.. code-block:: sh
root@lucid:~# grep plugins /etc/bcfg2.conf
- plugins = Base,Bundler,Cfg,Metadata,Packages,Probes,Rules,SSHbase
+ plugins = Base,Bundler,Cfg,...,Probes
root@lucid:~# mkdir /var/lib/bcfg2/Probes
root@lucid:~# cat /var/lib/bcfg2/Probes/groups
#!/bin/sh
diff --git a/doc/appendix/guides/web-reports-install.txt b/doc/appendix/guides/web-reports-install.txt
index af2e240fa..7ec7efb4e 100644
--- a/doc/appendix/guides/web-reports-install.txt
+++ b/doc/appendix/guides/web-reports-install.txt
@@ -136,7 +136,7 @@ Add DBStats to the plugins line of ``bcfg2.conf``. The resulting
[server]
repository = /var/lib/bcfg2
- plugins = Base,Bundler,Cfg,DBStats,Metadata,Packages,Probes,Rules,SSHbase
+ plugins = Base,Bundler,Cfg,...,DBStats
Start/restart the Bcfg2 server::
@@ -148,8 +148,9 @@ statistics to the database).
Download the static reports content::
+ [root@system01 ~]# git clone git://git.mcs.anl.gov/bcfg2
[root@system01 ~]# cd /var/www/
- [root@system01 ~]# svn co https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2/reports
+ [root@system01 ~]# mv /path/to/bcfg2/checkout/reports ./
Configure Apache using :ref:`dynamic-http-install` as a guide
@@ -159,7 +160,7 @@ then have something like this::
[server]
repository = /var/lib/bcfg2
- plugins = Base,Bundler,Cfg,DBStats,Metadata,Packages,Probes,Rules,SSHbase
+ plugins = Base,Bundler,Cfg,...,DBStats
[statistics]
sendmailpath = /usr/lib/sendmail
diff --git a/doc/reports/dynamic.txt b/doc/reports/dynamic.txt
index f798529eb..0c65bc7d2 100644
--- a/doc/reports/dynamic.txt
+++ b/doc/reports/dynamic.txt
@@ -1,6 +1,6 @@
.. -*- mode: rst -*-
-.. _server-reports-dynamic:
+.. _reports-dynamic:
==============================
Bcfg2 Dynamic Reporting System
diff --git a/doc/reports/static.txt b/doc/reports/static.txt
index 67ba38a14..00c1867f8 100644
--- a/doc/reports/static.txt
+++ b/doc/reports/static.txt
@@ -1,6 +1,6 @@
.. -*- mode: rst -*-
-.. _server-reports-static:
+.. _reports-static:
=============================
Bcfg2 Static Reporting System
diff --git a/doc/server/plugins/generators/nagiosgen.txt b/doc/server/plugins/generators/nagiosgen.txt
index 0ab2868e8..8cd18ca4f 100644
--- a/doc/server/plugins/generators/nagiosgen.txt
+++ b/doc/server/plugins/generators/nagiosgen.txt
@@ -12,7 +12,7 @@ This page describes the installation and use of the `NagiosGen`_ plugin.
Update ``/etc/bcfg2.conf``, adding NagiosGen to plugins::
- plugins = SSHbase,Cfg,Pkgmgr,Rules,TCheetah,TWbase,NagiosGen
+ plugins = Base,Bundler,Cfg,...,NagiosGen
Create the NagiosGen directory::
diff --git a/doc/server/plugins/generators/tcheetah.txt b/doc/server/plugins/generators/tcheetah.txt
index 5819bba96..8077d313e 100644
--- a/doc/server/plugins/generators/tcheetah.txt
+++ b/doc/server/plugins/generators/tcheetah.txt
@@ -19,7 +19,7 @@ engine from http://www.cheetahtemplate.org/. Once it is installed,
you can enable it by adding ``TCheetah`` to the ``plugins`` line in
``/etc/bcfg2.conf`` on your Bcfg server. For example::
- plugins = Cfg,Metadata,Pkgmgr,Rules,SSHbase,TCheetah
+ plugins = Base,Bundler,Cfg,...,TCheetah
The ``TCheetah`` plugin makes use of a ``Cfg``-like directory structure
located in in a ``TCheetah`` subdirectory of your repository, usually
@@ -28,7 +28,7 @@ files, ``template`` and ``info``. The template is a standard Cheetah
template with two additions:
* `self.metadata` is the client's :ref:`metadata <server-plugins-grouping-metadata-clientmetadata>`
-* `self.metadata.Properties` is an xml document of unstructured data
+* `self.metadata.Properties.data` is an xml document of unstructured data
The ``info`` file is formatted like ``:info`` files from Cfg.
@@ -47,10 +47,10 @@ self.metadata variables
self.metadata is an instance of the class ClientMetadata and documented
:ref:`here <server-plugins-grouping-metadata-clientmetadata>`.
-self.metadata.Properties
+self.metadata.Properties.data
========================
-Properties is a python `ElementTree <http://codespeak.net/lxml/>`_
+Properties.data is a python `ElementTree <http://codespeak.net/lxml/>`_
object, loaded from the data in ``/var/lib/bcfg2/Properties/<properties
file>.xml``. That file should have a ``Properties`` node at its root.
diff --git a/doc/server/plugins/generators/tgenshi/clientsxml.txt b/doc/server/plugins/generators/tgenshi/clientsxml.txt
index 10be3232c..7305ba70d 100644
--- a/doc/server/plugins/generators/tgenshi/clientsxml.txt
+++ b/doc/server/plugins/generators/tgenshi/clientsxml.txt
@@ -22,7 +22,7 @@ There are two main advantages:
thing to note is how the `name` variable is handled - when
just referring to it the standard `${name}` syntax is used, but
when it is used as a variable in the expression to get the password,
- `password="${metadata.Properties['passwords.xml'].find('password').find('bcfg2-client').find(name).text}"`,
+ `password="${metadata.Properties['passwords.xml'].data.find('password').find('bcfg2-client').find(name).text}"`,
it is just referred to as `name`.
There is the disadvantage that sometimes 2 passes will be needed to get
@@ -53,7 +53,7 @@ Possible improvements:
profile="${profile}"
name="${name}"
uuid="${name}"
- password="${metadata.Properties['passwords.xml'].find('password').find('bcfg2-client').find(name).text}"
+ password="${metadata.Properties['passwords.xml'].data.find('password').find('bcfg2-client').find(name).text}"
address="${address}"
location="fixed"
secure="true"
@@ -64,7 +64,7 @@ Possible improvements:
profile="${profile}"
name="${name}"
uuid="${name}"
- password="${metadata.Properties['passwords.xml'].find('password').find('bcfg2-client').find(name).text}"
+ password="${metadata.Properties['passwords.xml'].data.find('password').find('bcfg2-client').find(name).text}"
location="floating"
secure="true"
/>\
diff --git a/doc/server/plugins/generators/tgenshi/index.txt b/doc/server/plugins/generators/tgenshi/index.txt
index 425b3a289..c1970ee0d 100644
--- a/doc/server/plugins/generators/tgenshi/index.txt
+++ b/doc/server/plugins/generators/tgenshi/index.txt
@@ -24,7 +24,7 @@ To install on CentOS or RHEL 5, run::
Once it is installed, you can enable it by adding ``TGenshi`` to the
generators line in ``/etc/bcfg2.conf`` on your Bcfg server. For example::
- generators = SSHbase,Cfg,Pkgmgr,Svcmgr,Rules,TGenshi
+ plugins = Base,Bundler,Cfg,...,TGenshi
The TGenshi plugin makes use of a Cfg-like directory structure
located in in a TGenshi subdirectory of your repository, usually
diff --git a/doc/server/plugins/generators/tgenshi/test.txt b/doc/server/plugins/generators/tgenshi/test.txt
index 1348a0603..dca578434 100644
--- a/doc/server/plugins/generators/tgenshi/test.txt
+++ b/doc/server/plugins/generators/tgenshi/test.txt
@@ -45,8 +45,8 @@ This file just shows you what's available. It assumes a
{% end %}\
Two main ways to get the same property value:
- ${metadata.Properties['test.xml'].find('password').find('bcfg2').text}
- ${metadata.Properties['test.xml'].xpath('password/bcfg2')[0].text}
+ ${metadata.Properties['test.xml'].data.find('password').find('bcfg2').text}
+ ${metadata.Properties['test.xml'].data.xpath('password/bcfg2')[0].text}
One way to get information about metadata and properties:
@@ -55,28 +55,28 @@ This file just shows you what's available. It assumes a
${var} \
{% end %}
- dir(properties):
- {% for var in dir(properties) %}\
+ dir(metadata.Properties.data):
+ {% for var in dir(metadata.Properties.data) %}\
${var} \
{% end %}
- dir(properties.entries):
- {% for var in dir(properties.entries) %}\
+ dir(metadata.Properties.data.entries):
+ {% for var in dir(metadata.Properties.data.entries) %}\
${var} \
{% end %}
- dir(properties.label):
- {% for var in dir(properties.label) %}\
+ dir(metadata.Properties.data.label):
+ {% for var in dir(metadata.Properties.data.label) %}\
${var} \
{% end %}
- dir(properties.name):
- {% for var in dir(properties.name) %}\
+ dir(metadata.Properties.data.name):
+ {% for var in dir(metadata.Properties.data.name) %}\
${var} \
{% end %}
- dir(properties.properties):
- {% for var in dir(properties.properties) %}\
+ dir(metadata.Properties.data.properties):
+ {% for var in dir(metadata.Properties.data.properties) %}\
${var} \
{% end %}
@@ -113,13 +113,13 @@ this (below reformatted a little bit to fit in 80 columns)::
__weakref__ all bundles categories get_clients_by_group get_clients_by_profile
groups hostname inGrouppassword probes uuid
- dir(properties):
+ dir(metadata.Properties.data):
HandleEvent Index __class__ __delattr__ __dict__ __doc__ __getattribute__
__hash__ __identifier__ __init__ __iter__ __module__ __new__ __reduce__
__reduce_ex__ __repr__ __setattr__ __str__ __weakref__ entries label name
properties
- dir(properties.entries):
+ dir(metadata.Properties.data.entries):
__add__ __class__ __contains__ __delattr__ __delitem__ __delslice__ __doc__
__eq__ __ge__ __getattribute__ __getitem__ __getslice__ __gt__ __hash__
__iadd__ __imul__ __init__ __iter__ __le__ __len__ __lt__ __mul__ __ne__
@@ -127,7 +127,7 @@ this (below reformatted a little bit to fit in 80 columns)::
__setitem__ __setslice__ __str__ append count extend index insert pop remove
reverse sort
- dir(properties.label):
+ dir(metadata.Properties.data.label):
__add__ __class__ __contains__ __delattr__ __doc__ __eq__ __ge__
__getattribute__ __getitem__ __getnewargs__ __getslice__ __gt__ __hash__
__init__ __le__ __len__ __lt__ __mod__ __mul__ __ne__ __new__ __reduce__
@@ -137,7 +137,7 @@ this (below reformatted a little bit to fit in 80 columns)::
rfind rindex rjust rpartition rsplit rstrip split splitlinesstartswith strip
swapcase title translate upper zfill
- dir(properties.name):
+ dir(metadata.Properties.data.name):
__add__ __class__ __contains__ __delattr__ __doc__ __eq__ __ge__
__getattribute__ __getitem__ __getnewargs__ __getslice__ __gt__ __hash__
__init__ __le__ __len__ __lt__ __mod__ __mul__ __ne__ __new__ __reduce__
@@ -147,7 +147,7 @@ this (below reformatted a little bit to fit in 80 columns)::
rfind rindex rjust rpartition rsplit rstrip split splitlinesstartswith strip
swapcase title translate upper zfill
- dir(properties.properties):
+ dir(metadata.Properties.data.properties):
__class__ __contains__ __copy__ __deepcopy__ __delattr__ __delitem__
__delslice__ __doc__ __getattribute__ __getitem__ __getslice__ __hash__
__init__ __iter__ __len__ __new__ __nonzero__ __reduce__ __reduce_ex__
diff --git a/doc/server/plugins/probes/group.txt b/doc/server/plugins/probes/group.txt
index f529b8b3e..dfe64cc60 100644
--- a/doc/server/plugins/probes/group.txt
+++ b/doc/server/plugins/probes/group.txt
@@ -52,15 +52,15 @@ Probe used to dynamically set client groups based on OS/distro.
# redhat based
if [ -x /bin/rpm ]; then
OUTPUT="${OUTPUT}\ngroup:rpm"
- OS_GROUP=`bin/rpm -q --qf "%{NAME}" --whatprovides redhat-release | sed 's/-release.*//' | tr '[A-Z]' '[a-z]'`
- REDHAT_VERSION=`bin/rpm -q --qf "%{VERSION}" --whatprovides redhat-release`
+ OS_GROUP=`/bin/rpm -q --qf "%{NAME}" --whatprovides redhat-release | sed 's/-release.*//' | tr '[A-Z]' '[a-z]'`
+ REDHAT_VERSION=`/bin/rpm -q --qf "%{VERSION}" --whatprovides redhat-release`
case "$OS_GROUP" in
"centos" | "fedora")
OUTPUT="${OUTPUT}\ngroup:${OS_GROUP}"
OUTPUT="${OUTPUT}\ngroup:${OS_GROUP}-${REDHAT_VERSION}"
;;
"redhat")
- REDHAT_RELEASE=`bin/rpm -q --qf "%{RELEASE}" --whatprovides redhat-release| cut -d. -f1`
+ REDHAT_RELEASE=`/bin/rpm -q --qf "%{RELEASE}" --whatprovides redhat-release| cut -d. -f1`
OUTPUT="${OUTPUT}\ngroup:${OS_GROUP}"
OUTPUT="${OUTPUT}\ngroup:${OS_GROUP}-${REDHAT_VERSION}"
OUTPUT="${OUTPUT}\ngroup:${OS_GROUP}-${REDHAT_RELEASE}"
@@ -88,7 +88,7 @@ Probe used to dynamically set client groups based on OS/distro.
ARCH=`uname -m`
case "$ARCH" in
"x86_64")
- if [ "$OS_GROUP" == 'centos' ]; then
+ if [ "$OS_GROUP" == 'centos' -o "$OS_GROUP" == 'redhat' ]; then
OUTPUT="$OUTPUT\ngroup:${ARCH}"
else
OUTPUT="$OUTPUT\ngroup:amd64"
diff --git a/doc/server/plugins/probes/index.txt b/doc/server/plugins/probes/index.txt
index 9b6f37b26..87fd2ba2c 100644
--- a/doc/server/plugins/probes/index.txt
+++ b/doc/server/plugins/probes/index.txt
@@ -13,8 +13,14 @@ the system disk, you would want to know this information to correctly
generate an `/etc/auto.master` autofs config file for each type. Here
we will look at how to do this.
-First you will need to set up the TCheetah plugin, as described on the
-:ref:`server-plugins-generators-tcheetah` page.
+For the purposes of this example, you will need to set up the TCheetah
+plugin, as described on the :ref:`server-plugins-generators-tcheetah`
+page.
+
+.. note::
+
+ This does **not** mean that TCheetah is required in order for Probes
+ to operate properly.
Next, we need to create a ``Probes`` directory in our toplevel repository
location::
diff --git a/doc/server/plugins/statistics/dbstats.txt b/doc/server/plugins/statistics/dbstats.txt
index 8e50df822..dd25fe9ab 100644
--- a/doc/server/plugins/statistics/dbstats.txt
+++ b/doc/server/plugins/statistics/dbstats.txt
@@ -9,7 +9,7 @@ DBStats
DBStats can be enabled by adding DBStats to the plugins line in
``/etc/bcfg2.conf``:
- plugins = DBStats
+ plugins = Base,Bundler,Cfg,...,DBStats
For more information on how to use DBStats to setup reporting, see
:ref:`server-reports-dynamic`.
diff --git a/examples/metadata.xml b/examples/metadata.xml
deleted file mode 100644
index 73b0b0ee0..000000000
--- a/examples/metadata.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<Metadata version='2.0'>
- <Client name='topaz' image='chiba-rh73'>
- <Class name='laptop'/>
- <Attribute scope='powermgmt' name='apm'/>
- <Attribute scope='webserver' name='php'/>
- </Client>
- <Client name='ccprez' image='debian-3.1'/>
- <Class name='laptop'>
- <Bundle name='powermgmt'/>
- <Bundle name='ssh'/>
- </Class>
-</Metadata>
-
diff --git a/gentoo/bcfg2-1.1.1.ebuild b/gentoo/bcfg2-1.1.1.ebuild
index 6b41c16ea..7b4bd7888 100644
--- a/gentoo/bcfg2-1.1.1.ebuild
+++ b/gentoo/bcfg2-1.1.1.ebuild
@@ -1,4 +1,4 @@
-# Copyright 1999-2010 Gentoo Foundation
+# Copyright 1999-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
@@ -31,23 +31,28 @@ RDEPEND="${DEPEND}"
PYTHON_MODNAME="Bcfg2"
+distutils_src_install_post_hook() {
+ if ! use server; then
+ rm -f "${T}/images/${PYTHON_ABI}${EPREFIX}/usr/sbin/bcfg2-"*
+ fi
+}
+
src_install() {
- distutils_src_install --record=PY_SERVER_LIBS --install-scripts "${EPREFIX}"/usr/sbin
+ distutils_src_install --record=PY_SERVER_LIBS --install-scripts "${EPREFIX}/usr/sbin"
# Remove files only necessary for a server installation
if ! use server; then
- rm -rf "${ED}"usr/sbin/bcfg2-*
- rm -rf "${ED}"usr/share/bcfg2
- rm -rf "${ED}"usr/share/man/man8
+ rm -rf "${ED}usr/share/bcfg2"
+ rm -rf "${ED}usr/share/man/man8"
fi
# Install a server init.d script
if use server; then
- newinitd "${FILESDIR}"/bcfg2-server.rc bcfg2-server
+ newinitd "${FILESDIR}/bcfg2-server.rc" bcfg2-server
fi
insinto /etc
- doins examples/bcfg2.conf
+ doins examples/bcfg2.conf || die "doins failed"
}
pkg_postinst () {
diff --git a/src/lib/Client/Tools/APT.py b/src/lib/Client/Tools/APT.py
index 2afe2eab7..cc445f961 100644
--- a/src/lib/Client/Tools/APT.py
+++ b/src/lib/Client/Tools/APT.py
@@ -37,17 +37,22 @@ class APT(Bcfg2.Client.Tools.Tool):
__execs__ = [DEBSUMS, APTGET, DPKG]
__handles__ = [('Package', 'deb')]
__req__ = {'Package': ['name', 'version']}
- pkgcmd = '%s ' % APTGET + \
- '-o DPkg::Options::=--force-overwrite ' + \
- '-o DPkg::Options::=--force-confold ' + \
- '-o DPkg::Options::=--force-confmiss ' + \
- '--reinstall ' + \
- '-q=2 ' + \
- '--force-yes ' + \
- '-y install %s'
def __init__(self, logger, setup, config):
Bcfg2.Client.Tools.Tool.__init__(self, logger, setup, config)
+ path_entries = os.environ['PATH'].split(':')
+ for reqdir in ['/sbin', '/usr/sbin']:
+ if reqdir not in path_entries:
+ os.environ['PATH'] = os.environ['PATH'] + ':' + reqdir
+ self.pkgcmd = '%s ' % APTGET + \
+ '-o DPkg::Options::=--force-overwrite ' + \
+ '-o DPkg::Options::=--force-confold ' + \
+ '-o DPkg::Options::=--force-confmiss ' + \
+ '--reinstall ' + \
+ '--force-yes '
+ if not self.setup['debug']:
+ self.pkgcmd += '-q=2 '
+ self.pkgcmd += '-y install %s'
self.__important__ = self.__important__ + \
["%s/cache/debconf/config.dat" % var_path,
"%s/cache/debconf/templates.dat" % var_path,
diff --git a/src/lib/Client/Tools/DebInit.py b/src/lib/Client/Tools/DebInit.py
index aee8ffd65..119036b32 100644
--- a/src/lib/Client/Tools/DebInit.py
+++ b/src/lib/Client/Tools/DebInit.py
@@ -7,10 +7,7 @@ import re
import Bcfg2.Client.Tools
# Debian squeeze and beyond uses a dependecy based boot sequence
-DEBIAN_OLD_STYLE_BOOT_SEQUENCE = (
- 'etch', '4.0',
- 'lenny', '5.0', '5.0.1', '5.0.2', '5.0.3', '5.0.4', '5.0.4', '5.0.5',
- )
+DEBIAN_OLD_STYLE_BOOT_SEQUENCE = ('etch', '4.0', 'lenny')
class DebInit(Bcfg2.Client.Tools.SvcTool):
@@ -33,7 +30,8 @@ class DebInit(Bcfg2.Client.Tools.SvcTool):
deb_version = 'unknown'
if entry.get('sequence'):
- if (deb_version in DEBIAN_OLD_STYLE_BOOT_SEQUENCE):
+ if (deb_version in DEBIAN_OLD_STYLE_BOOT_SEQUENCE or
+ deb_version.startswith('5')):
start_sequence = int(entry.get('sequence'))
kill_sequence = 100 - start_sequence
else:
diff --git a/src/lib/Client/Tools/YUM24.py b/src/lib/Client/Tools/YUM24.py
new file mode 100644
index 000000000..efe92a059
--- /dev/null
+++ b/src/lib/Client/Tools/YUM24.py
@@ -0,0 +1,421 @@
+"""This provides bcfg2 support for yum."""
+__revision__ = '$Revision: $'
+
+import ConfigParser
+import copy
+import os.path
+import sys
+import yum
+import Bcfg2.Client.XML
+import Bcfg2.Client.Tools.RPMng
+
+# Fix for python2.3
+try:
+ set
+except NameError:
+ from sets import Set as set
+
+YAD = True
+CP = ConfigParser.ConfigParser()
+try:
+ if '-C' in sys.argv:
+ CP.read([sys.argv[sys.argv.index('-C') + 1]])
+ else:
+ CP.read(['/etc/bcfg2.conf'])
+ if CP.get('YUMng', 'autodep').lower() == 'false':
+ YAD = False
+except:
+ pass
+
+if not hasattr(Bcfg2.Client.Tools.RPMng, 'RPMng'):
+ raise ImportError
+
+def build_yname(pkgname, inst):
+ """Build yum appropriate package name."""
+ ypname = pkgname
+ if inst.get('version') != 'any':
+ ypname += '-'
+ if inst.get('epoch', False):
+ ypname += "%s:" % inst.get('epoch')
+ if inst.get('version', False) and inst.get('version') != 'any':
+ ypname += "%s" % (inst.get('version'))
+ if inst.get('release', False) and inst.get('release') != 'any':
+ ypname += "-%s" % (inst.get('release'))
+ if inst.get('arch', False) and inst.get('arch') != 'any':
+ ypname += ".%s" % (inst.get('arch'))
+ return ypname
+
+class YUM24(Bcfg2.Client.Tools.RPMng.RPMng):
+ """Support for Yum packages."""
+ pkgtype = 'yum'
+
+ name = 'YUM24'
+ __execs__ = ['/usr/bin/yum', '/var/lib/rpm']
+ __handles__ = [('Package', 'yum'),
+ ('Package', 'rpm'),
+ ('Path', 'ignore')]
+
+ __req__ = {'Package': ['name', 'version']}
+ __ireq__ = {'Package': ['name']}
+ #__ireq__ = {'Package': ['name', 'version']}
+
+ __new_req__ = {'Package': ['name'], 'Instance': ['version', 'release', 'arch']}
+ __new_ireq__ = {'Package': ['name'], \
+ 'Instance': []}
+ #__new_ireq__ = {'Package': ['name', 'uri'], \
+ # 'Instance': ['simplefile', 'version', 'release', 'arch']}
+
+ __gpg_req__ = {'Package': ['name', 'version']}
+ __gpg_ireq__ = {'Package': ['name', 'version']}
+
+ __new_gpg_req__ = {'Package': ['name'], 'Instance': ['version', 'release']}
+ __new_gpg_ireq__ = {'Package': ['name'], 'Instance': ['version', 'release']}
+
+ conflicts = ['YUMng', 'RPMng']
+
+ def __init__(self, logger, setup, config):
+ Bcfg2.Client.Tools.RPMng.RPMng.__init__(self, logger, setup, config)
+ self.__important__ = self.__important__ + \
+ [entry.get('name') for struct in config \
+ for entry in struct \
+ if entry.tag in ['Path', 'ConfigFile'] and \
+ (entry.get('name').startswith('/etc/yum.d') \
+ or entry.get('name').startswith('/etc/yum.repos.d')) \
+ or entry.get('name') == '/etc/yum.conf']
+ self.yum_avail = dict()
+ self.yum_installed = dict()
+ self.yb = yum.YumBase()
+ self.yb.doConfigSetup()
+ self.yb.doTsSetup()
+ self.yb.doRpmDBSetup()
+ yup = self.yb.doPackageLists(pkgnarrow='updates')
+ if hasattr(self.yb.rpmdb, 'pkglist'):
+ yinst = self.yb.rpmdb.pkglist
+ else:
+ yinst = self.yb.rpmdb.getPkgList()
+ for dest, source in [(self.yum_avail, yup.updates),
+ (self.yum_installed, yinst)]:
+ for pkg in source:
+ if dest is self.yum_avail:
+ pname = pkg.name
+ data = {pkg.arch: (pkg.epoch, pkg.version, pkg.release)}
+ else:
+ pname = pkg[0]
+ if pkg[1] is None: a = 'noarch'
+ else: a = pkg[1]
+ if pkg[2] is None: e = '0'
+ else: e = pkg[2]
+ data = {a: (e, pkg[3], pkg[4])}
+ if pname in dest:
+ dest[pname].update(data)
+ else:
+ dest[pname] = dict(data)
+
+ def VerifyPackage(self, entry, modlist):
+ pinned_version = None
+ if entry.get('version', False) == 'auto':
+ # old style entry; synthesize Instances from current installed
+ if entry.get('name') not in self.yum_installed and \
+ entry.get('name') not in self.yum_avail:
+ # new entry; fall back to default
+ entry.set('version', 'any')
+ else:
+ data = copy.copy(self.yum_installed[entry.get('name')])
+ if entry.get('name') in self.yum_avail:
+ # installed but out of date
+ data.update(self.yum_avail[entry.get('name')])
+ for (arch, (epoch, vers, rel)) in list(data.items()):
+ x = Bcfg2.Client.XML.SubElement(entry, "Instance",
+ name=entry.get('name'),
+ version=vers, arch=arch,
+ release=rel, epoch=epoch)
+ if 'verify_flags' in entry.attrib:
+ x.set('verify_flags', entry.get('verify_flags'))
+ if 'verify' in entry.attrib:
+ x.set('verify', entry.get('verify'))
+
+ if entry.get('type', False) == 'yum':
+ # Check for virtual provides or packages. If we don't have
+ # this package use Yum to resolve it to a real package name
+ knownPkgs = self.yum_installed.keys() + self.yum_avail.keys()
+ if entry.get('name') not in knownPkgs:
+ # If the package name matches something installed
+ # or available the that's the correct package.
+ try:
+ pkgDict = dict( [ (i.name, i) for i in \
+ self.yb.returnPackagesByDep(entry.get('name')) ] )
+ except yum.Errors.YumBaseError, e:
+ self.logger.error('Yum Error Depsolving for %s: %s' % \
+ (entry.get('name'), str(e)))
+ pkgDict = {}
+
+ if len(pkgDict) > 1:
+ # What do we do with multiple packages?
+ s = "YUMng: returnPackagesByDep(%s) returned many packages"
+ self.logger.info(s % entry.get('name'))
+ s = "YUMng: matching packages: %s"
+ self.logger.info(s % str(pkgDict.keys()))
+ pkgs = set(pkgDict.keys()) & set(self.yum_installed.keys())
+ if len(pkgs) > 0:
+ # Virtual packages matches an installed real package
+ pkg = pkgDict[pkgs.pop()]
+ s = "YUMng: chosing: %s" % pkg.name
+ self.logger.info(s)
+ else:
+ # What's the right package? This will fail verify
+ # and Yum should Do The Right Thing on package install
+ pkg = None
+ elif len(pkgDict) == 1:
+ pkg = pkgDict.values()[0]
+ else: # len(pkgDict) == 0
+ s = "YUMng: returnPackagesByDep(%s) returned no results"
+ self.logger.info(s % entry.get('name'))
+ pkg = None
+
+ if pkg is not None:
+ s = "YUMng: remapping virtual package %s to %s"
+ self.logger.info(s % (entry.get('name'), pkg.name))
+ entry.set('name', pkg.name)
+
+ return Bcfg2.Client.Tools.RPMng.RPMng.VerifyPackage(self, entry,
+ modlist)
+
+ def Install(self, packages, states):
+ """
+ Try and fix everything that RPMng.VerifyPackages() found wrong for
+ each Package Entry. This can result in individual RPMs being
+ installed (for the first time), deleted, downgraded
+ or upgraded.
+
+ NOTE: YUM can not reinstall a package that it thinks is already
+ installed.
+
+ packages is a list of Package Elements that has
+ states[<Package Element>] == False
+
+ The following effects occur:
+ - states{} is conditionally updated for each package.
+ - self.installed{} is rebuilt, possibly multiple times.
+ - self.instance_status{} is conditionally updated for each instance
+ of a package.
+ - Each package will be added to self.modified[] if its states{}
+ entry is set to True.
+
+ """
+ self.logger.info('Running YUMng.Install()')
+
+ install_pkgs = []
+ gpg_keys = []
+ upgrade_pkgs = []
+
+ # Remove extra instances.
+ # Can not reverify because we don't have a package entry.
+ if len(self.extra_instances) > 0:
+ if (self.setup.get('remove') == 'all' or \
+ self.setup.get('remove') == 'packages'):
+ self.RemovePackages(self.extra_instances)
+ else:
+ self.logger.info("The following extra package instances will be removed by the '-r' option:")
+ for pkg in self.extra_instances:
+ for inst in pkg:
+ self.logger.info(" %s %s" % \
+ ((pkg.get('name'), self.str_evra(inst))))
+
+ # Figure out which instances of the packages actually need something
+ # doing to them and place in the appropriate work 'queue'.
+ for pkg in packages:
+ insts = [pinst for pinst in pkg \
+ if pinst.tag in ['Instance', 'Package']]
+ if insts:
+ for inst in insts:
+ if self.FixInstance(inst, self.instance_status[inst]):
+ if self.instance_status[inst].get('installed', False) \
+ == False:
+ if pkg.get('name') == 'gpg-pubkey':
+ gpg_keys.append(inst)
+ else:
+ install_pkgs.append(inst)
+ elif self.instance_status[inst].get('version_fail', \
+ False) == True:
+ upgrade_pkgs.append(inst)
+ else:
+ install_pkgs.append(pkg)
+
+ # Install GPG keys.
+ # Alternatively specify the required keys using 'gpgkey' in the
+ # repository definition in yum.conf. YUM will install the keys
+ # automatically.
+ if len(gpg_keys) > 0:
+ for inst in gpg_keys:
+ self.logger.info("Installing GPG keys.")
+ if inst.get('simplefile') is None:
+ self.logger.error("GPG key has no simplefile attribute")
+ continue
+ key_arg = os.path.join(self.instance_status[inst].get('pkg').get('uri'), \
+ inst.get('simplefile'))
+ cmdrc, output = self.cmd.run("rpm --import %s" % key_arg)
+ if cmdrc != 0:
+ self.logger.debug("Unable to install %s-%s" % \
+ (self.instance_status[inst].get('pkg').get('name'), \
+ self.str_evra(inst)))
+ else:
+ self.logger.debug("Installed %s-%s-%s" % \
+ (self.instance_status[inst].get('pkg').get('name'), \
+ inst.get('version'), inst.get('release')))
+ self.RefreshPackages()
+ self.gpg_keyids = self.getinstalledgpg()
+ pkg = self.instance_status[gpg_keys[0]].get('pkg')
+ states[pkg] = self.VerifyPackage(pkg, [])
+
+ # Install packages.
+ if len(install_pkgs) > 0:
+ self.logger.info("Attempting to install packages")
+
+ if YAD:
+ pkgtool = "/usr/bin/yum -d0 -y install %s"
+ else:
+ pkgtool = "/usr/bin/yum -d0 install %s"
+
+ install_args = []
+ for inst in install_pkgs:
+ pkg_arg = self.instance_status[inst].get('pkg').get('name')
+ install_args.append(build_yname(pkg_arg, inst))
+
+ cmdrc, output = self.cmd.run(pkgtool % " ".join(install_args))
+ if cmdrc == 0:
+ # The yum command succeeded. All packages installed.
+ self.logger.info("Single Pass for Install Succeeded")
+ self.RefreshPackages()
+ else:
+ # The yum command failed. No packages installed.
+ # Try installing instances individually.
+ self.logger.error("Single Pass Install of Packages Failed")
+ installed_instances = []
+ for inst in install_pkgs:
+ pkg_arg = build_yname(self.instance_status[inst].get('pkg').get('name'), inst)
+
+ cmdrc, output = self.cmd.run(pkgtool % pkg_arg)
+ if cmdrc == 0:
+ installed_instances.append(inst)
+ else:
+ self.logger.debug("%s %s would not install." % \
+ (self.instance_status[inst].get('pkg').get('name'), \
+ self.str_evra(inst)))
+ self.RefreshPackages()
+
+ # Fix upgradeable packages.
+ if len(upgrade_pkgs) > 0:
+ self.logger.info("Attempting to upgrade packages")
+
+ if YAD:
+ pkgtool = "/usr/bin/yum -d0 -y update %s"
+ else:
+ pkgtool = "/usr/bin/yum -d0 update %s"
+
+ upgrade_args = []
+ for inst in upgrade_pkgs:
+ pkg_arg = build_yname(self.instance_status[inst].get('pkg').get('name'), inst)
+ upgrade_args.append(pkg_arg)
+
+ cmdrc, output = self.cmd.run(pkgtool % " ".join(upgrade_args))
+ if cmdrc == 0:
+ # The yum command succeeded. All packages installed.
+ self.logger.info("Single Pass for Install Succeeded")
+ self.RefreshPackages()
+ else:
+ # The yum command failed. No packages installed.
+ # Try installing instances individually.
+ self.logger.error("Single Pass Install of Packages Failed")
+ installed_instances = []
+ for inst in upgrade_pkgs:
+ pkg_arg = build_yname(self.instance_status[inst].get('pkg').get('name'), inst)
+ cmdrc, output = self.cmd.run(pkgtool % pkg_arg)
+ if cmdrc == 0:
+ installed_instances.append(inst)
+ else:
+ self.logger.debug("%s %s would not install." % \
+ (self.instance_status[inst].get('pkg').get('name'), \
+ self.str_evra(inst)))
+
+ self.RefreshPackages()
+
+ if not self.setup['kevlar']:
+ for pkg_entry in [p for p in packages if self.canVerify(p)]:
+ self.logger.debug("Reverifying Failed Package %s" % (pkg_entry.get('name')))
+ states[pkg_entry] = self.VerifyPackage(pkg_entry, \
+ self.modlists.get(pkg_entry, []))
+
+ for entry in [ent for ent in packages if states[ent]]:
+ self.modified.append(entry)
+
+ def RemovePackages(self, packages):
+ """
+ Remove specified entries.
+
+ packages is a list of Package Entries with Instances generated
+ by FindExtraPackages().
+ """
+ self.logger.debug('Running YUMng.RemovePackages()')
+
+ if YAD:
+ pkgtool = "/usr/bin/yum -d0 -y erase %s"
+ else:
+ pkgtool = "/usr/bin/yum -d0 erase %s"
+
+ erase_args = []
+ for pkg in packages:
+ for inst in pkg:
+ if pkg.get('name') != 'gpg-pubkey':
+ pkg_arg = pkg.get('name') + '-'
+ if inst.get('epoch', False):
+ pkg_arg = pkg_arg + inst.get('epoch') + ':'
+ pkg_arg = pkg_arg + inst.get('version') + '-' + inst.get('release')
+ if inst.get('arch', False):
+ pkg_arg = pkg_arg + '.' + inst.get('arch')
+ erase_args.append(pkg_arg)
+ else:
+ pkgspec = { 'name':pkg.get('name'),
+ 'version':inst.get('version'),
+ 'release':inst.get('release')}
+ self.logger.info("WARNING: gpg-pubkey package not in configuration %s %s"\
+ % (pkgspec.get('name'), self.str_evra(pkgspec)))
+ self.logger.info(" This package will be deleted in a future version of the RPMng driver.")
+
+ cmdrc, output = self.cmd.run(pkgtool % " ".join(erase_args))
+ if cmdrc == 0:
+ self.modified += packages
+ for pkg in erase_args:
+ self.logger.info("Deleted %s" % (pkg))
+ else:
+ self.logger.info("Bulk erase failed with errors:")
+ self.logger.debug("Erase results = %s" % output)
+ self.logger.info("Attempting individual erase for each package.")
+ for pkg in packages:
+ pkg_modified = False
+ for inst in pkg:
+ if pkg.get('name') != 'gpg-pubkey':
+ pkg_arg = pkg.get('name') + '-'
+ if inst.attrib.has_key('epoch'):
+ pkg_arg = pkg_arg + inst.get('epoch') + ':'
+ pkg_arg = pkg_arg + inst.get('version') + '-' + inst.get('release')
+ if 'arch' in inst.attrib:
+ pkg_arg = pkg_arg + '.' + inst.get('arch')
+ else:
+ self.logger.info("WARNING: gpg-pubkey package not in configuration %s %s"\
+ % (pkg.get('name'), self.str_evra(pkg)))
+ self.logger.info(" This package will be deleted in a future version of the RPMng driver.")
+ continue
+
+ cmdrc, output = self.cmd.run(self.pkgtool % pkg_arg)
+ if cmdrc == 0:
+ pkg_modified = True
+ self.logger.info("Deleted %s" % pkg_arg)
+ else:
+ self.logger.error("unable to delete %s" % pkg_arg)
+ self.logger.debug("Failure = %s" % output)
+ if pkg_modified == True:
+ self.modified.append(pkg)
+
+
+ self.RefreshPackages()
+ self.extra = self.FindExtraPackages()
diff --git a/src/lib/Component.py b/src/lib/Component.py
index 2a3ef20e1..33b1c9289 100644
--- a/src/lib/Component.py
+++ b/src/lib/Component.py
@@ -239,15 +239,14 @@ class Component (object):
raise xmlrpclib.Fault(getattr(e, "fault_code", 1), str(e))
return result
- @exposed
def listMethods(self):
"""Custom XML-RPC introspective method list."""
return [
name for name, func in inspect.getmembers(self, callable)
if getattr(func, "exposed", False)
]
+ listMethods = exposed(listMethods)
- @exposed
def methodHelp(self, method_name):
"""Custom XML-RPC introspective method help.
@@ -260,6 +259,7 @@ class Component (object):
except NoExposedMethod:
return ""
return pydoc.getdoc(func)
+ methodHelp = exposed(methodHelp)
def get_name(self):
"""The name of the component."""
diff --git a/src/lib/Server/Admin/Init.py b/src/lib/Server/Admin/Init.py
index aee91b244..8f54b836e 100644
--- a/src/lib/Server/Admin/Init.py
+++ b/src/lib/Server/Admin/Init.py
@@ -65,55 +65,50 @@ clients = '''<Clients version="3.0">
'''
# Mapping of operating system names to groups
-os_list = [
- ('Red Hat/Fedora/RHEL/RHAS/Centos', 'redhat'),
- ('SUSE/SLES', 'suse'),
- ('Mandrake', 'mandrake'),
- ('Debian', 'debian'),
- ('Ubuntu', 'ubuntu'),
- ('Gentoo', 'gentoo'),
- ('FreeBSD', 'freebsd')
- ]
+os_list = [('Red Hat/Fedora/RHEL/RHAS/Centos', 'redhat'),
+ ('SUSE/SLES', 'suse'),
+ ('Mandrake', 'mandrake'),
+ ('Debian', 'debian'),
+ ('Ubuntu', 'ubuntu'),
+ ('Gentoo', 'gentoo'),
+ ('FreeBSD', 'freebsd')]
# Complete list of plugins
-plugin_list = [
- 'Account',
- 'Base',
- 'Bundler',
- 'Bzr',
- 'Cfg',
- 'Decisions',
- 'Deps',
- 'Git',
- 'Guppy',
- 'Hg',
- 'Metadata',
- 'NagiosGen',
- 'Ohai',
- 'Packages',
- 'Pkgmgr',
- 'Probes',
- 'Properties',
- 'Rules',
- 'Snapshots',
- 'SSHbase',
- 'SSLCA',
- 'Statistics',
- 'Svcmgr',
- 'TCheetah',
- 'TGenshi'
- ]
+plugin_list = ['Account',
+ 'Base',
+ 'Bundler',
+ 'Bzr',
+ 'Cfg',
+ 'Decisions',
+ 'Deps',
+ 'Git',
+ 'Guppy',
+ 'Hg',
+ 'Metadata',
+ 'NagiosGen',
+ 'Ohai',
+ 'Packages',
+ 'Pkgmgr',
+ 'Probes',
+ 'Properties',
+ 'Rules',
+ 'Snapshots',
+ 'SSHbase',
+ 'SSLCA',
+ 'Statistics',
+ 'Svcmgr',
+ 'TCheetah',
+ 'TGenshi']
# Default list of plugins to use
-default_plugins = [
- 'Base',
- 'Bundler'
- 'Cfg',
- 'Metadata',
- 'Pkgmgr',
- 'Rules',
- 'SSHbase'
- ]
+default_plugins = ['Base',
+ 'Bundler',
+ 'Cfg',
+ 'Metadata',
+ 'Pkgmgr',
+ 'Rules',
+ 'SSHbase']
+
def gen_password(length):
"""Generates a random alphanumeric password with length characters."""
@@ -123,14 +118,28 @@ def gen_password(length):
newpasswd = newpasswd + random.choice(chars)
return newpasswd
+
def create_key(hostname, keypath, certpath, country, state, location):
"""Creates a bcfg2.key at the directory specifed by keypath."""
- kcstr = "openssl req -batch -x509 -nodes -subj '/C=%s/ST=%s/L=%s/CN=%s' -days 1000 -newkey rsa:2048 -keyout %s -noout" % (country, state, location, hostname, keypath)
+ kcstr = ("openssl req -batch -x509 -nodes -subj '/C=%s/ST=%s/L=%s/CN=%s' "
+ "-days 1000 -newkey rsa:2048 -keyout %s -noout" % (country,
+ state,
+ location,
+ hostname,
+ keypath))
subprocess.call((kcstr), shell=True)
- ccstr = "openssl req -batch -new -subj '/C=%s/ST=%s/L=%s/CN=%s' -key %s | openssl x509 -req -days 1000 -signkey %s -out %s" % (country, state, location, hostname, keypath, keypath, certpath)
+ ccstr = ("openssl req -batch -new -subj '/C=%s/ST=%s/L=%s/CN=%s' -key %s "
+ "| openssl x509 -req -days 1000 -signkey %s -out %s" % (country,
+ state,
+ location,
+ hostname,
+ keypath,
+ keypath,
+ certpath))
subprocess.call((ccstr), shell=True)
os.chmod(keypath, 0600)
+
def create_conf(confpath, confdata):
# Don't overwrite existing bcfg2.conf file
if os.path.exists(confpath):
@@ -153,15 +162,14 @@ class Init(Bcfg2.Server.Admin.Mode):
__shorthelp__ = ("Interactively initialize a new repository.")
__longhelp__ = __shorthelp__ + "\n\nbcfg2-admin init"
__usage__ = "bcfg2-admin init"
- options = {
- 'configfile': Bcfg2.Options.CFILE,
- 'plugins' : Bcfg2.Options.SERVER_PLUGINS,
- 'proto' : Bcfg2.Options.SERVER_PROTOCOL,
- 'repo' : Bcfg2.Options.SERVER_REPOSITORY,
- 'sendmail' : Bcfg2.Options.SENDMAIL_PATH,
- }
+ options = {'configfile': Bcfg2.Options.CFILE,
+ 'plugins': Bcfg2.Options.SERVER_PLUGINS,
+ 'proto': Bcfg2.Options.SERVER_PROTOCOL,
+ 'repo': Bcfg2.Options.SERVER_REPOSITORY,
+ 'sendmail': Bcfg2.Options.SENDMAIL_PATH}
repopath = ""
response = ""
+
def __init__(self, configfile):
Bcfg2.Server.Admin.Mode.__init__(self, configfile)
@@ -196,8 +204,8 @@ class Init(Bcfg2.Server.Admin.Mode):
def _prompt_hostname(self):
"""Ask for the server hostname."""
- data = raw_input("What is the server's hostname [%s]: " %
- socket.getfqdn())
+ data = raw_input("What is the server's hostname [%s]: " %
+ socket.getfqdn())
if data != '':
self.shostname = data
else:
@@ -254,8 +262,8 @@ class Init(Bcfg2.Server.Admin.Mode):
continue
def _prompt_plugins(self):
- default = raw_input("Use default plugins? (%s) [Y/n]: " %
- ''.join(default_plugins)).lower()
+ default = raw_input("Use default plugins? (%s) [Y/n]: " %
+ ''.join(default_plugins)).lower()
if default != 'y' or default != '':
while True:
plugins_are_valid = True
@@ -271,8 +279,8 @@ class Init(Bcfg2.Server.Admin.Mode):
def _prompt_certificate(self):
"""Ask for the key details (country, state, and location)."""
- print "The following questions affects the certificate."
- print "If there are no data provided the default values are used."
+ print "The following questions affect SSL certificate generation."
+ print "If no data is provided, the default values are used."
newcountry = raw_input("Country name (2 letter code) for certificate: ")
if newcountry != '':
if len(newcountry) == 2:
@@ -302,8 +310,10 @@ class Init(Bcfg2.Server.Admin.Mode):
"""Initialize each plugin-specific portion of the repository."""
for plugin in self.plugins:
if plugin == 'Metadata':
- Bcfg2.Server.Plugins.Metadata.Metadata.init_repo(self.repopath,
- groups, self.os_sel, clients)
+ Bcfg2.Server.Plugins.Metadata.Metadata.init_repo(self.repopath,
+ groups,
+ self.os_sel,
+ clients)
else:
try:
module = __import__("Bcfg2.Server.Plugins.%s" % plugin, '',
@@ -311,30 +321,28 @@ class Init(Bcfg2.Server.Admin.Mode):
cls = getattr(module, plugin)
cls.init_repo(self.repopath)
except Exception, e:
- print 'Plugin setup for %s failed: %s'
- print 'Check that dependencies are installed?' % (plugin, e)
+ print("Plugin setup for %s failed: %s\n"
+ "Check that dependencies are installed?" % (plugin, e))
def init_repo(self):
"""Setup a new repo and create the content of the configuration file."""
keypath = os.path.dirname(os.path.abspath(self.configfile))
- confdata = config % (
- self.repopath,
- ','.join(self.opts['plugins']),
- self.opts['sendmail'],
- self.opts['proto'],
- self.password,
- keypath, 'bcfg2.crt',
- keypath, 'bcfg2.key',
- keypath, 'bcfg2.crt',
- self.server_uri
- )
+ confdata = config % (self.repopath,
+ ','.join(self.opts['plugins']),
+ self.opts['sendmail'],
+ self.opts['proto'],
+ self.password,
+ keypath, 'bcfg2.crt',
+ keypath, 'bcfg2.key',
+ keypath, 'bcfg2.crt',
+ self.server_uri)
# Create the configuration file and SSL key
create_conf(self.configfile, confdata)
kpath = keypath + '/bcfg2.key'
cpath = keypath + '/bcfg2.crt'
- create_key(self.shostname, kpath, cpath, self.country,
- self.state, self.location)
+ create_key(self.shostname, kpath, cpath, self.country,
+ self.state, self.location)
# Create the repository
path = "%s/%s" % (self.repopath, 'etc')
diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py
index 186d1198a..73d054409 100644
--- a/src/lib/Server/Plugin.py
+++ b/src/lib/Server/Plugin.py
@@ -680,7 +680,7 @@ class SpecificData(object):
class EntrySet:
"""Entry sets deal with the host- and group-specific entries."""
- ignore = re.compile("^(\.#.*|.*~|\\..*\\.(sw[px]))$")
+ ignore = re.compile("^(\.#.*|.*~|\\..*\\.(sw[px])|.*\\.genshi_include)$")
def __init__(self, basename, path, entry_type, encoding):
self.path = path
self.entry_type = entry_type
@@ -784,10 +784,10 @@ class EntrySet:
return cmp(x.specific.prio, y.specific.prio)
def bind_info_to_entry(self, entry, metadata):
- if not self.infoxml:
- for key in self.metadata:
- entry.set(key, self.metadata[key])
- else:
+ # first set defaults from global metadata/:info
+ for key in self.metadata:
+ entry.set(key, self.metadata[key])
+ if self.infoxml:
mdata = {}
self.infoxml.pnode.Match(metadata, mdata)
if 'Info' not in mdata:
diff --git a/src/lib/Server/Plugins/Packages.py b/src/lib/Server/Plugins/Packages.py
index ee21fb622..438c1d5c0 100644
--- a/src/lib/Server/Plugins/Packages.py
+++ b/src/lib/Server/Plugins/Packages.py
@@ -280,12 +280,12 @@ class YUMSource(Source):
sdata = self.packages.values()
self.packages['global'] = copy.deepcopy(sdata.pop())
while sdata:
- self.packages['global'].intersection(sdata.pop())
+ self.packages['global'] = self.packages['global'].intersection(sdata.pop())
for key in self.packages:
if key == 'global':
continue
- self.packages[key] = self.packages['global'].difference(self.packages[key])
+ self.packages[key] = self.packages[key].difference(self.packages['global'])
self.save_state()
def parse_filelist(self, data, arch):
diff --git a/src/lib/Server/Plugins/Probes.py b/src/lib/Server/Plugins/Probes.py
index c00185732..7ffc65bac 100644
--- a/src/lib/Server/Plugins/Probes.py
+++ b/src/lib/Server/Plugins/Probes.py
@@ -73,7 +73,7 @@ class Probes(Bcfg2.Server.Plugin.Plugin,
def write_data(self):
"""Write probe data out for use with bcfg2-info."""
top = lxml.etree.Element("Probed")
- for client, probed in self.probedata.iteritems():
+ for client, probed in sorted(self.probedata.items()):
cx = lxml.etree.SubElement(top, 'Client', name=client)
for probe in probed:
lxml.etree.SubElement(cx, 'Probe', name=probe,
diff --git a/src/sbin/bcfg2 b/src/sbin/bcfg2
index 10262e4a9..9bc50fe65 100755
--- a/src/sbin/bcfg2
+++ b/src/sbin/bcfg2
@@ -111,6 +111,8 @@ class Client:
if (self.setup["file"] != False) and (self.setup["cache"] != False):
print("cannot use -f and -c together")
raise SystemExit(1)
+ if not self.setup['server'].startswith('https://'):
+ self.setup['server'] = 'https://' + self.setup['server']
def run_probe(self, probe):
"""Execute probe."""
diff --git a/src/sbin/bcfg2-admin b/src/sbin/bcfg2-admin
index 872ecef0f..2c9a43859 100755
--- a/src/sbin/bcfg2-admin
+++ b/src/sbin/bcfg2-admin
@@ -77,4 +77,7 @@ def main():
raise SystemExit(1)
if __name__ == '__main__':
- main()
+ try:
+ main()
+ except KeyboardInterrupt:
+ raise SystemExit(1)