diff options
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) |