summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--debian/changelog6
-rw-r--r--doc/appendix/guides/ubuntu.txt2
-rw-r--r--doc/conf.py2
-rw-r--r--doc/installation/source.txt3
-rw-r--r--doc/server/plugins/grouping/metadata.txt29
-rw-r--r--examples/bcfg2-lint.conf2
-rw-r--r--misc/bcfg2.spec194
-rw-r--r--osx/Makefile4
-rw-r--r--redhat/VERSION2
-rw-r--r--reports/xsl-transforms/xsl-transform-includes/html-templates.xsl2
-rwxr-xr-xsetup.py2
-rw-r--r--solaris/Makefile22
-rw-r--r--solaris/gen-prototypes.sh24
-rw-r--r--solaris/pkginfo.bcfg22
-rw-r--r--solaris/pkginfo.bcfg2-server2
-rw-r--r--src/lib/Client/Tools/RPMng.py6
-rw-r--r--src/lib/Client/Tools/YUM24.py6
-rw-r--r--src/lib/Client/Tools/YUMng.py6
-rw-r--r--src/lib/Client/Tools/__init__.py4
-rw-r--r--src/lib/Options.py19
-rw-r--r--src/lib/Server/Plugin.py11
-rw-r--r--src/lib/Server/Plugins/Cfg.py20
-rw-r--r--src/lib/Server/Plugins/FileProbes.py148
-rw-r--r--src/lib/Server/Plugins/Packages/Source.py10
-rw-r--r--src/lib/Server/Plugins/Packages/Yum.py6
-rw-r--r--src/lib/Server/Plugins/SSHbase.py4
-rw-r--r--src/lib/Server/Plugins/Trigger.py13
-rw-r--r--src/lib/Server/Reports/reports/templates/base.html2
28 files changed, 378 insertions, 175 deletions
diff --git a/debian/changelog b/debian/changelog
index 5722eeb97..2557dd66a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+bcfg2 (1.2.2-0.0) unstable; urgency=low
+
+ * New upstream release
+
+ -- Sol Jerome <sol.jerome@gmail.com> Sat, 17 Mar 2012 14:41:17 -0500
+
bcfg2 (1.2.1-0.0) unstable; urgency=low
* New upstream release
diff --git a/doc/appendix/guides/ubuntu.txt b/doc/appendix/guides/ubuntu.txt
index d85c34b02..f72247220 100644
--- a/doc/appendix/guides/ubuntu.txt
+++ b/doc/appendix/guides/ubuntu.txt
@@ -154,7 +154,7 @@ Create Packages layout (as per :ref:`packages-exampleusage`) in
[global]
root@lucid:~# cat /var/lib/bcfg2/Packages/sources.xml
<Sources>
- <Group name="lucid">
+ <Group name="ubuntu-lucid">
<Source type="apt" url="http://archive.ubuntu.com/ubuntu" version="lucid">
<Component>main</Component>
<Component>multiverse</Component>
diff --git a/doc/conf.py b/doc/conf.py
index 7e9c8b59c..38160715d 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -55,7 +55,7 @@ else:
# The short X.Y version.
version = '1.2'
# The full version, including alpha/beta/rc tags.
-release = '1.2.1'
+release = '1.2.2'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/doc/installation/source.txt b/doc/installation/source.txt
index 3ea0404ad..1406a5ceb 100644
--- a/doc/installation/source.txt
+++ b/doc/installation/source.txt
@@ -2,6 +2,7 @@
.. _GPG1: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x75BF2C177F7D197E
.. _GPG2: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x80B8492FA88FFF4B
+.. _Download: http://trac.mcs.anl.gov/projects/bcfg2/wiki/Download
.. _source:
@@ -14,7 +15,7 @@ Download
Tarball
^^^^^^^
-The Bcfg2 source tarball can be grabbed from the Download_ page.
+The Bcfg2 source tarball can be grabbed from the `Download`_ page.
All tarballs are signed with GPG keys `7F7D197E <GPG1>`_ or `A88FFF4B
<GPG2>`_. You can verify your download by importing the keys and running ::
diff --git a/doc/server/plugins/grouping/metadata.txt b/doc/server/plugins/grouping/metadata.txt
index c52ac7612..305857578 100644
--- a/doc/server/plugins/grouping/metadata.txt
+++ b/doc/server/plugins/grouping/metadata.txt
@@ -276,22 +276,37 @@ A special client metadata class is available to the
MetadataQuery
-------------
-This class provides query routines for the servers Metadata.
+This class provides query methods for the metadata of all clients
+known to the Bcfg2 server. Note that ``*by_groups()`` and
+``*by_profiles()`` behave differently; for a client to be included in
+the return value of a ``by_groups()`` method, it must be a member of
+*all* groups listed in the argument; for a client to be included in
+the return value of a ``by_profiles()`` method, it must have any group
+listed as its profile group.
+------------------------------+------------------------------------------------+-------------------+
| Method | Description | Value |
+==============================+================================================+===================+
| by_name(client) | Get ClientMetadata object for 'client' | ClientMetadata |
+------------------------------+------------------------------------------------+-------------------+
-| names_by_groups(groups) | All client names in the list of 'groups' | List |
+| by_groups(groups) | Get ClientMetadata object for clients in all | List of |
+| | listed groups | ClientMetadata |
+------------------------------+------------------------------------------------+-------------------+
-| names_by_profiles(profiles) | All client names in the list of 'profiles' | List |
+| by_profiles(client) | Get ClientMetadata objects for clients whose | List of |
+| | profile matches any listed profile group | ClientMetadata |
+------------------------------+------------------------------------------------+-------------------+
-| all_clients() | All known client hostnames | List |
+| names_by_groups(groups) | Get the names of all clients in all listed | List of strings |
+| | groups | |
+------------------------------+------------------------------------------------+-------------------+
-| all_groups() | All known group names | List |
+| names_by_profiles(profiles) | Get the names of clients whose profile matches | List of strings |
+| | any listed profile group | |
+------------------------------+------------------------------------------------+-------------------+
-| all_groups_in_category(cat) | All groups in category 'cat' | List |
+| all_clients() | All known client hostnames | List of strings |
+------------------------------+------------------------------------------------+-------------------+
-| all() | Get ClientMetadata for all clients | List |
+| all_groups() | All known group names | List of strings |
++------------------------------+------------------------------------------------+-------------------+
+| all_groups_in_category(cat) | The names of all groups in category 'cat' | List of strings |
++------------------------------+------------------------------------------------+-------------------+
+| all() | Get ClientMetadata for all clients | List of |
+| | | ClientMetadata |
+------------------------------+------------------------------------------------+-------------------+
diff --git a/examples/bcfg2-lint.conf b/examples/bcfg2-lint.conf
index 9c0d2c72a..6ca3fb61f 100644
--- a/examples/bcfg2-lint.conf
+++ b/examples/bcfg2-lint.conf
@@ -22,7 +22,7 @@ cfg_keywords =
probe_comments = Maintainer,Purpose,Groups,Other Output
[Validate]
-schema=/usr/share/bcfg2/schema
+schema=/usr/share/bcfg2/schemas
[MergeFiles]
threshold=85
diff --git a/misc/bcfg2.spec b/misc/bcfg2.spec
index 982f5795c..9fa119edf 100644
--- a/misc/bcfg2.spec
+++ b/misc/bcfg2.spec
@@ -6,33 +6,61 @@
%{!?_initrddir: %define _initrddir %{_sysconfdir}/rc.d/init.d}
Name: bcfg2
-Version: 1.2.1
+Version: 1.2.2
Release: %{release}
Summary: Configuration management system
+%if 0%{?suse_version}
+# http://en.opensuse.org/openSUSE:Package_group_guidelines
+Group: System/Management
+%else
Group: Applications/System
+%endif
License: BSD
URL: http://bcfg2.org
Source0: ftp://ftp.mcs.anl.gov/pub/bcfg/%{name}-%{version}.tar.gz
+%if 0%{?suse_version}
+# SUSEs OBS does not understand the id macro below.
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}
+%else
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-
+%endif
BuildArch: noarch
BuildRequires: python-devel
BuildRequires: python-lxml
+%if 0%{?mandriva_version}
+# mandriva seems to behave differently than other distros and needs this explicitly.
+BuildRequires: python-setuptools
+%endif
+%if 0%{?mandriva_version} == 201100
+# mandriva 2011 has multiple providers for libsane, so (at least when building on OBS)
+# one must be chosen explicitly:
+# "have choice for libsane.so.1 needed by python-imaging: libsane1 sane-backends-iscan"
+BuildRequires: libsane1
+%endif
# %{rhel} wasn't set before rhel 6. so this checks for old RHEL
# %systems (and potentially very old Fedora systems, too)
-%if "%{_vendor}" == "redhat" && 0%{?rhel} <= 6 && 0%{?fedora} == 0
-BuildRequires: python-sphinx10
+%if "%{_vendor}" == "redhat" && 0%{?rhel} < 6 && 0%{?fedora} == 0
+BuildRequires: python-sphinx10
# the python-sphinx10 package doesn't set sys.path correctly, so we
# have to do it for them
-%define pythonpath /usr/lib/python%{py_ver}/site-packages/Sphinx-1.0.4-py%{py_ver}.egg
+%define pythonpath %(find /usr/lib/python%{py_ver}/site-packages -name %Sphinx*.egg)
%else
-BuildRequires: python-sphinx >= 0.6
+BuildRequires: python-sphinx >= 0.6
%endif
Requires: python-lxml >= 0.9
+%if 0%{?rhel_version}
+# the debian init script needs redhat-lsb.
+# iff we switch to the redhat one, this might not be needed anymore.
+Requires: redhat-lsb
+%endif
+%if 0%{?fedora} == 0
+# fedora 15 and 16 (and possibly other distros) do not know this tag.
+Recommends: cron
+%endif
%description
Bcfg2 helps system administrators produce a consistent, reproducible,
@@ -60,17 +88,23 @@ systems are constantly changing; if required in your environment,
Bcfg2 can enable the construction of complex change management and
deployment strategies.
+This package includes the Bcfg2 client software.
+
%package -n bcfg2-server
-Version: %{version}
-Summary: Bcfg2 Server
-Group: System Tools
-Requires: bcfg2
+Version: 1.2.2
+Summary: Bcfg2 Server
+%if 0%{?suse_version}
+Group: System/Management
+%else
+Group: System Tools
+%endif
+Requires: bcfg2
%if "%{py_ver}" < "2.6"
Requires: python-ssl
%endif
Requires: python-lxml >= 1.2.1
%if "%{_vendor}" == "redhat"
-Requires: gamin-python
+Requires: gamin-python
%endif
%description -n bcfg2-server
@@ -99,24 +133,59 @@ systems are constantly changing; if required in your environment,
Bcfg2 can enable the construction of complex change management and
deployment strategies.
+This package includes the Bcfg2 server software.
+
%package -n bcfg2-doc
Summary: Configuration management system documentation
+%if 0%{?suse_version}
+Group: Documentation/HTML
+%else
Group: Documentation
+%endif
%description -n bcfg2-doc
-Configuration management system documentation
+Bcfg2 helps system administrators produce a consistent, reproducible,
+and verifiable description of their environment, and offers
+visualization and reporting tools to aid in day-to-day administrative
+tasks. It is the fifth generation of configuration management tools
+developed in the Mathematics and Computer Science Division of Argonne
+National Laboratory.
+
+It is based on an operational model in which the specification can be
+used to validate and optionally change the state of clients, but in a
+feature unique to bcfg2 the client's response to the specification can
+also be used to assess the completeness of the specification. Using
+this feature, bcfg2 provides an objective measure of how good a job an
+administrator has done in specifying the configuration of client
+systems. Bcfg2 is therefore built to help administrators construct an
+accurate, comprehensive specification.
+
+Bcfg2 has been designed from the ground up to support gentle
+reconciliation between the specification and current client states. It
+is designed to gracefully cope with manual system modifications.
+
+Finally, due to the rapid pace of updates on modern networks, client
+systems are constantly changing; if required in your environment,
+Bcfg2 can enable the construction of complex change management and
+deployment strategies.
+
+This package includes the Bcfg2 documentation.
%package -n bcfg2-web
-Version: %{version}
-Summary: Bcfg2 Web Reporting Interface
-Group: System Tools
-Requires: bcfg2-server
-Requires: httpd,Django
+Version: 1.2.2
+Summary: Bcfg2 Web Reporting Interface
+%if 0%{?suse_version}
+Group: System/Management
+%else
+Group: System Tools
+%endif
+Requires: bcfg2-server
+Requires: httpd,Django
%if "%{_vendor}" == "redhat"
-Requires: mod_wsgi
+Requires: mod_wsgi
%define apache_conf %{_sysconfdir}/httpd
%else
-Requires: apache2-mod_wsgi
+Requires: apache2-mod_wsgi
%define apache_conf %{_sysconfdir}/apache2
%endif
@@ -146,6 +215,8 @@ systems are constantly changing; if required in your environment,
Bcfg2 can enable the construction of complex change management and
deployment strategies.
+This package includes the Bcfg2 reports web frontend.
+
%prep
%setup -q -n bcfg2-%{version}
@@ -166,6 +237,9 @@ deployment strategies.
%{__install} -d %{buildroot}%{_sysconfdir}/cron.hourly
%{__install} -d %{buildroot}%{_prefix}/lib/bcfg2
mkdir -p %{buildroot}%{_defaultdocdir}/bcfg2-doc-%{version}
+%if 0%{?suse_version}
+%{__install} -d %{buildroot}/var/adm/fillup-templates
+%endif
%{__mv} %{buildroot}/usr/bin/bcfg2* %{buildroot}%{_sbindir}
%{__install} -m 755 debian/bcfg2.init %{buildroot}%{_initrddir}/bcfg2
@@ -175,6 +249,12 @@ mkdir -p %{buildroot}%{_defaultdocdir}/bcfg2-doc-%{version}
%{__install} -m 755 debian/bcfg2.cron.daily %{buildroot}%{_sysconfdir}/cron.daily/bcfg2
%{__install} -m 755 debian/bcfg2.cron.hourly %{buildroot}%{_sysconfdir}/cron.hourly/bcfg2
%{__install} -m 755 tools/bcfg2-cron %{buildroot}%{_prefix}/lib/bcfg2/bcfg2-cron
+%if 0%{?suse_version}
+%{__install} -m 755 debian/bcfg2.default %{buildroot}/var/adm/fillup-templates/sysconfig.bcfg2
+%{__install} -m 755 debian/bcfg2-server.default %{buildroot}/var/adm/fillup-templates/sysconfig.bcfg2-server
+ln -s %{_initrddir}/bcfg2 %{buildroot}%{_sbindir}/rcbcfg2
+ln -s %{_initrddir}/bcfg2-server %{buildroot}%{_sbindir}/rcbcfg2-server
+%endif
mv build/sphinx/html/* %{buildroot}%{_defaultdocdir}/bcfg2-doc-%{version}
mv build/dtd %{buildroot}%{_defaultdocdir}/bcfg2-doc-%{version}/
@@ -190,7 +270,9 @@ mv build/dtd %{buildroot}%{_defaultdocdir}/bcfg2-doc-%{version}/
%files -n bcfg2
%defattr(-,root,root,-)
%{_sbindir}/bcfg2
+%dir %{python_sitelib}/Bcfg2
%{python_sitelib}/Bcfg2/*.py*
+%dir %{python_sitelib}/Bcfg2/Client
%{python_sitelib}/Bcfg2/Client/*
%{_mandir}/man1/bcfg2.1*
%{_mandir}/man5/bcfg2.conf.5*
@@ -200,15 +282,59 @@ mv build/dtd %{buildroot}%{_defaultdocdir}/bcfg2-doc-%{version}/
%{_sysconfdir}/cron.daily/bcfg2
%{_prefix}/lib/bcfg2/bcfg2-cron
%{_localstatedir}/cache/bcfg2
+%if 0%{?suse_version}
+%{_sbindir}/rcbcfg2
+%config(noreplace) /var/adm/fillup-templates/sysconfig.bcfg2
+%endif
+%if 0%{?mandriva_version} == 0
+# mandriva (on OBS, at least) can't handle %ghost
+%ghost %attr(0600,root,root) %{_sysconfdir}/bcfg2.conf
+%endif
%post -n bcfg2-server
-/sbin/chkconfig --add bcfg2-server
+# enable daemon on first install only (not on update).
+if [ $1 -eq 1 ]; then
+%if 0%{?suse_version}
+ %fillup_and_insserv -f bcfg2-server
+%else
+ /sbin/chkconfig --add bcfg2-server
+%endif
+fi
+
+%preun -n bcfg2
+%if 0%{?suse_version}
+# stop on removal (not on update).
+if [ $1 -eq 0 ]; then
+ %stop_on_removal bcfg2
+fi
+%endif
+
+%preun -n bcfg2-server
+%if 0%{?suse_version}
+if [ $1 -eq 0 ]; then
+ %stop_on_removal bcfg2-server
+fi
+%endif
+
+%postun -n bcfg2
+%if 0%{?suse_version}
+if [ $1 -eq 0 ]; then
+ %insserv_cleanup
+fi
+%endif
+
+%postun -n bcfg2-server
+%if 0%{?suse_version}
+if [ $1 -eq 0 ]; then
+ # clean up on removal.
+ %insserv_cleanup
+fi
+%endif
%files -n bcfg2-server
%defattr(-,root,root,-)
-
%{_initrddir}/bcfg2-server
-
+%dir %{python_sitelib}/Bcfg2
%{python_sitelib}/Bcfg2/Server
%if "%{pythonversion}" >= "2.5"
@@ -230,24 +356,42 @@ mv build/dtd %{buildroot}%{_defaultdocdir}/bcfg2-doc-%{version}/
%{_sbindir}/bcfg2-server
%{_sbindir}/bcfg2-yum-helper
%{_sbindir}/bcfg2-test
+%if 0%{?suse_version}
+%{_sbindir}/rcbcfg2-server
+%config(noreplace) /var/adm/fillup-templates/sysconfig.bcfg2-server
+%endif
%{_mandir}/man5/bcfg2-lint.conf.5*
%{_mandir}/man8/*.8*
%dir %{_prefix}/lib/bcfg2
+%if 0%{?mandriva_version} == 0
+%ghost %attr(0600,root,root) %{_sysconfdir}/bcfg2.conf
+%endif
-%files doc
+%files -n bcfg2-doc
%defattr(-,root,root,-)
%doc %{_defaultdocdir}/bcfg2-doc-%{version}
%files -n bcfg2-web
%defattr(-,root,root,-)
-
%{_datadir}/bcfg2/reports.wsgi
%{_datadir}/bcfg2/site_media
-
+%dir %{apache_conf}
+%dir %{apache_conf}/conf.d
%config(noreplace) %{apache_conf}/conf.d/wsgi_bcfg2.conf
+%if 0%{?mandriva_version} == 0
+%ghost %attr(0600,root,root) %{_sysconfdir}/bcfg2-web.conf
+%endif
%changelog
+* Sat Feb 18 2012 Christopher 'm4z' Holm <686f6c6d@googlemail.com> 1.2.1
+- Added Fedora and Mandriva compatibilty (for Open Build Service).
+- Added missing dependency redhat-lsb.
+
+* Tue Feb 14 2012 Christopher 'm4z' Holm <686f6c6d@googlemail.com> 1.2.1
+- Added openSUSE compatibility.
+- Various changes to satisfy rpmlint.
+
* Thu Jan 27 2011 Chris St. Pierre <stpierreca@ornl.gov> 1.2.0pre1-0.0
- Added -doc sub-package
diff --git a/osx/Makefile b/osx/Makefile
index 279ad0f6f..72751ff32 100644
--- a/osx/Makefile
+++ b/osx/Makefile
@@ -29,9 +29,9 @@ SITELIBDIR = /Library/Python/${PYVERSION}/site-packages
# an Info.plist file for packagemaker to look at for package creation
# and substitute the version strings. Major/Minor versions can only be
# integers (e.g. "1" and "00" for bcfg2 version 1.0.0.
-BCFGVER = 1.2.1
+BCFGVER = 1.2.2
MAJOR = 1
-MINOR = 21
+MINOR = 22
default: clean client
diff --git a/redhat/VERSION b/redhat/VERSION
index 6085e9465..23aa83906 100644
--- a/redhat/VERSION
+++ b/redhat/VERSION
@@ -1 +1 @@
-1.2.1
+1.2.2
diff --git a/reports/xsl-transforms/xsl-transform-includes/html-templates.xsl b/reports/xsl-transforms/xsl-transform-includes/html-templates.xsl
index 74adbfe94..ad29f0411 100644
--- a/reports/xsl-transforms/xsl-transform-includes/html-templates.xsl
+++ b/reports/xsl-transforms/xsl-transform-includes/html-templates.xsl
@@ -4,7 +4,7 @@
<xsl:if test="count(Statistics/Good)+count(Statistics/Bad)+count(Statistics/Extra)+count(Statistics/Modified)+count(Statistics/Stale) > 0">
<a name="{Client/@name}}"></a>
- <div class="nodebox"">
+ <div class="nodebox">
<span class="notebox">Time Ran: <xsl:value-of select="Statistics/@time" /></span>
<span class="configbox">(<xsl:value-of select="Client/@profile" />)</span>
diff --git a/setup.py b/setup.py
index da84b9756..ece7b4a24 100755
--- a/setup.py
+++ b/setup.py
@@ -121,7 +121,7 @@ if sys.hexversion < 0x03000000 and os.path.exists(py3lib):
setup(cmdclass=cmdclass,
name="Bcfg2",
- version="1.2.1",
+ version="1.2.2",
description="Bcfg2 Server",
author="Narayan Desai",
author_email="desai@mcs.anl.gov",
diff --git a/solaris/Makefile b/solaris/Makefile
index be98f345d..77d9019eb 100644
--- a/solaris/Makefile
+++ b/solaris/Makefile
@@ -1,26 +1,28 @@
#!/usr/sfw/bin/gmake
-PYTHON="/opt/csw/bin/python"
-VERS=1.2.1-1
+PYTHON="/usr/local/bin/python"
+VERS=1.2.2-1
PYVERSION := $(shell $(PYTHON) -c "import sys; print sys.version[0:3]")
default: clean package
package:
- -mkdir tmp tmp/bcfg2-server tmp/bcfg2
- -cd ../ && $(PYTHON) setup.py install --prefix=$(PWD)
+ -mkdir tmp tmp/bcfg2-server tmp/bcfg2
+ -mkdir -p build/lib/$(PYVERSION)/site-packages
+ -cd ../ && PYTHONPATH=$(PYTHONPATH):$(PWD)/build/lib/python2.6/site-packages/ $(PYTHON) setup.py install --single-version-externally-managed --record=/dev/null --prefix=$(PWD)/build
+ #setuptools appears to use a restictive umask
+ -chmod -R o+r build/
-cat bin/bcfg2 | sed -e 's!/usr/bin/python!$(PYTHON)!' > bin/bcfg2.new && mv bin/bcfg2.new bin/bcfg2
- # Set python version to whichever version is installed
- -cat prototype.bcfg2 | sed -e 's!PYVERSION!python$(PYVERSION)!' > prototype.bcfg2.fixed
- -cat prototype.bcfg2-server | sed -e 's!PYVERSION!python$(PYVERSION)!' > prototype.bcfg2-server.fixed
- -pkgmk -o -a `uname -m` -f prototype.bcfg2.fixed -d $(PWD)/tmp -r $(PWD)
- -pkgmk -o -a `uname -m` -f prototype.bcfg2-server.fixed -d $(PWD)/tmp -r $(PWD)
+ -./gen-prototypes.sh
+ -pkgmk -o -a `uname -m` -f prototype.bcfg2 -d $(PWD)/tmp -r $(PWD)/build
+ -pkgmk -o -a `uname -m` -f prototype.bcfg2-server -d $(PWD)/tmp -r $(PWD)/build
-pkgtrans -o -s $(PWD)/tmp $(PWD)/bcfg2-$(VERS) SCbcfg2
-pkgtrans -o -s $(PWD)/tmp $(PWD)/bcfg2-server-$(VERS) SCbcfg2-server
-gzip -f $(PWD)/bcfg2-$(VERS)
-gzip -f $(PWD)/bcfg2-server-$(VERS)
clean:
- -rm -rf tmp bin lib share
+ -rm -rf tmp build
-rm -rf bcfg2-$(VERS).gz bcfg2-server-$(VERS).gz
-rm -rf prototype.bcfg2.fixed prototype.bcfg2-server.fixed
+ -rm -f prototype.*
diff --git a/solaris/gen-prototypes.sh b/solaris/gen-prototypes.sh
new file mode 100644
index 000000000..ea0b4bb13
--- /dev/null
+++ b/solaris/gen-prototypes.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+cd build
+PP="./"`ls -1d lib/*`"/site-packages/"
+
+#bcfg2
+echo "i pkginfo=./pkginfo.bcfg2" > ../prototype.tmp
+find . | grep man[15] | pkgproto >> ../prototype.tmp
+echo "./bin" | pkgproto >> ../prototype.tmp
+echo "./bin/bcfg2" | pkgproto >> ../prototype.tmp
+echo "${PP}Bcfg2" | pkgproto >> ../prototype.tmp
+ls -1 ${PP}Bcfg2/*.py | pkgproto >> ../prototype.tmp
+find ${PP}Bcfg2/Client/ ! -name "*.pyc" | pkgproto >> ../prototype.tmp
+sed "s/`id | sed 's/uid=[0-9]*(\(.*\)) gid=[0-9]*(\(.*\))/\1 \2/'`/bin bin/" ../prototype.tmp > ../prototype.bcfg2
+
+#bcfg2-server
+echo "i pkginfo=./pkginfo.bcfg2-server" > ../prototype.tmp
+find . | grep man8 | pkgproto >> ../prototype.tmp
+find share/bcfg2 | pkgproto >> ../prototype.tmp
+echo "./bin" | pkgproto >> ../prototype.tmp
+ls -1 bin/bcfg2-* | pkgproto >> ../prototype.tmp
+find ${PP}Bcfg2/Server/ ! -name "*.pyc" | pkgproto >> ../prototype.tmp
+sed "s/`id | sed 's/uid=[0-9]*(\(.*\)) gid=[0-9]*(\(.*\))/\1 \2/'`/bin bin/" ../prototype.tmp > ../prototype.bcfg2-server
+
+rm ../prototype.tmp
diff --git a/solaris/pkginfo.bcfg2 b/solaris/pkginfo.bcfg2
index c4633f209..0ff18516d 100644
--- a/solaris/pkginfo.bcfg2
+++ b/solaris/pkginfo.bcfg2
@@ -1,7 +1,7 @@
PKG="SCbcfg2"
NAME="bcfg2"
ARCH="sparc"
-VERSION="1.2.1"
+VERSION="1.2.2"
CATEGORY="application"
VENDOR="Argonne National Labratory"
EMAIL="bcfg-dev@mcs.anl.gov"
diff --git a/solaris/pkginfo.bcfg2-server b/solaris/pkginfo.bcfg2-server
index 762625967..a0958f9e4 100644
--- a/solaris/pkginfo.bcfg2-server
+++ b/solaris/pkginfo.bcfg2-server
@@ -1,7 +1,7 @@
PKG="SCbcfg2-server"
NAME="bcfg2-server"
ARCH="sparc"
-VERSION="1.2.1"
+VERSION="1.2.2"
CATEGORY="application"
VENDOR="Argonne National Labratory"
EMAIL="bcfg-dev@mcs.anl.gov"
diff --git a/src/lib/Client/Tools/RPMng.py b/src/lib/Client/Tools/RPMng.py
index 00f4aedd7..b28bec030 100644
--- a/src/lib/Client/Tools/RPMng.py
+++ b/src/lib/Client/Tools/RPMng.py
@@ -7,12 +7,6 @@ import Bcfg2.Client.Tools
# Compatibility import
from Bcfg2.Bcfg2Py3k import ConfigParser
-# Fix for python2.3
-try:
- set
-except NameError:
- from sets import Set as set
-
class RPMng(Bcfg2.Client.Tools.PkgTool):
"""Support for RPM packages."""
name = 'RPMng'
diff --git a/src/lib/Client/Tools/YUM24.py b/src/lib/Client/Tools/YUM24.py
index cee1319a8..4e488b9da 100644
--- a/src/lib/Client/Tools/YUM24.py
+++ b/src/lib/Client/Tools/YUM24.py
@@ -9,12 +9,6 @@ import Bcfg2.Client.Tools.RPMng
# Compatibility import
from Bcfg2.Bcfg2Py3k import ConfigParser
-# Fix for python2.3
-try:
- set
-except NameError:
- from sets import Set as set
-
YAD = True
CP = ConfigParser.ConfigParser()
try:
diff --git a/src/lib/Client/Tools/YUMng.py b/src/lib/Client/Tools/YUMng.py
index 967221b8b..154676764 100644
--- a/src/lib/Client/Tools/YUMng.py
+++ b/src/lib/Client/Tools/YUMng.py
@@ -15,12 +15,6 @@ import Bcfg2.Client.Tools
# Compatibility import
from Bcfg2.Bcfg2Py3k import ConfigParser
-# Fix for python2.3
-try:
- set
-except NameError:
- from sets import Set as set
-
def build_yname(pkgname, inst):
"""Build yum appropriate package name."""
diff --git a/src/lib/Client/Tools/__init__.py b/src/lib/Client/Tools/__init__.py
index 924ede9a2..c6cb6e239 100644
--- a/src/lib/Client/Tools/__init__.py
+++ b/src/lib/Client/Tools/__init__.py
@@ -1,8 +1,4 @@
"""This contains all Bcfg2 Tool modules"""
-# suppress popen2 warnings for python 2.3
-import warnings
-warnings.filterwarnings("ignore", "The popen2 module is deprecated.*",
- DeprecationWarning)
import os
import stat
import sys
diff --git a/src/lib/Options.py b/src/lib/Options.py
index dc2d06eea..527b42d00 100644
--- a/src/lib/Options.py
+++ b/src/lib/Options.py
@@ -26,12 +26,7 @@ class Option(object):
def getCFP(self):
if not self.__cfp:
self.__cfp = ConfigParser.ConfigParser()
- # FIXME: Remove this hack when except: pass below is fixed
- try:
- self.__cfp.readfp(open(self.cfpath))
- except IOError:
- e = sys.exc_info()[1]
- print("Unable to read bcfg2.conf: %s" % e)
+ self.__cfp.readfp(open(self.cfpath))
return self.__cfp
cfp = property(getCFP)
@@ -115,11 +110,7 @@ class Option(object):
self.value = self.get_cooked_value(os.environ[self.env])
return
if self.cf:
- """
- FIXME: This is masking any sort of error present in getCFP, we
- need to remove this catchall exception and figure out something
- better
- """
+ # FIXME: This is potentially masking a lot of errors
try:
self.value = self.get_cooked_value(self.cfp.get(*self.cf))
return
@@ -382,3 +373,9 @@ class OptionParser(OptionSet):
Option.cfpath = self.Bootstrap['configfile']
Option.__cfp = False
OptionSet.__init__(self, args)
+ try:
+ f = open(Option.cfpath, 'r')
+ f.close()
+ except IOError:
+ e = sys.exc_info()[1]
+ print("Warning! Unable to read specified configuration file: %s" % e)
diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py
index db4cbaee7..e66c23b2b 100644
--- a/src/lib/Server/Plugin.py
+++ b/src/lib/Server/Plugin.py
@@ -989,6 +989,12 @@ class EntrySet:
self.entry_init(event)
else:
if event.filename not in self.entries:
+ logger.warning("Got %s event for unknown file %s" %
+ (action, event.filename))
+ if action == 'changed':
+ # received a bogus changed event; warn, but treat
+ # it like a created event
+ self.entry_init(event)
return
if action == 'changed':
self.entries[event.filename].handle_event(event)
@@ -1153,8 +1159,11 @@ class GroupSpool(Plugin, Generator):
# a directory was deleted
del self.entries[fbase]
del self.Entries['Path'][fbase]
- else:
+ elif ident in self.entries:
self.entries[ident].handle_event(event)
+ elif ident not in self.entries:
+ self.logger.warning("Got deleted event for unknown file %s" %
+ ident)
def AddDirectoryMonitor(self, relative):
"""Add new directory to FAM structures."""
diff --git a/src/lib/Server/Plugins/Cfg.py b/src/lib/Server/Plugins/Cfg.py
index d5de086a5..03d56fdc2 100644
--- a/src/lib/Server/Plugins/Cfg.py
+++ b/src/lib/Server/Plugins/Cfg.py
@@ -220,32 +220,32 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet):
return "%s.H_%s" % (bfname, specific.hostname)
def write_update(self, specific, new_entry, log):
- # FIXME: need to redo print with python's logging module
if 'text' in new_entry:
name = self.build_filename(specific)
if os.path.exists("%s.genshi" % name):
- print("Cfg: Unable to pull data for genshi types")
+ self.logger.error("Cfg: Unable to pull data for genshi types")
raise Bcfg2.Server.Plugin.PluginExecutionError
elif os.path.exists("%s.cheetah" % name):
- print("Cfg: Unable to pull data for cheetah types")
+ self.logger.error("Cfg: Unable to pull data for cheetah types")
raise Bcfg2.Server.Plugin.PluginExecutionError
try:
etext = new_entry['text'].encode(self.encoding)
except:
- print("Cfg: Cannot encode content of %s as %s" % (name, self.encoding))
+ self.logger.error("Cfg: Cannot encode content of %s as %s" % (name, self.encoding))
raise Bcfg2.Server.Plugin.PluginExecutionError
open(name, 'w').write(etext)
- if log:
- print("Wrote file %s" % name)
+ self.debug_log("Wrote file %s" % name, flag=log)
badattr = [attr for attr in ['owner', 'group', 'perms']
if attr in new_entry]
if badattr:
# check for info files and inform user of their removal
if os.path.exists(self.path + "/:info"):
- print("Removing :info file and replacing with info.xml")
+ self.logger.info("Removing :info file and replacing with "
+ "info.xml")
os.remove(self.path + "/:info")
if os.path.exists(self.path + "/info"):
- print("Removing info file and replacing with info.xml")
+ self.logger.info("Removing info file and replacing with "
+ "info.xml")
os.remove(self.path + "/info")
metadata_updates = {}
metadata_updates.update(self.metadata)
@@ -258,8 +258,8 @@ class CfgEntrySet(Bcfg2.Server.Plugin.EntrySet):
ofile = open(self.path + "/info.xml", "w")
ofile.write(lxml.etree.tostring(infoxml, pretty_print=True))
ofile.close()
- if log:
- print("Wrote file %s" % (self.path + "/info.xml"))
+ self.debug_log("Wrote file %s" % (self.path + "/info.xml"),
+ flag=log)
class Cfg(Bcfg2.Server.Plugin.GroupSpool,
diff --git a/src/lib/Server/Plugins/FileProbes.py b/src/lib/Server/Plugins/FileProbes.py
index 98c1f66bf..a76d7cac4 100644
--- a/src/lib/Server/Plugins/FileProbes.py
+++ b/src/lib/Server/Plugins/FileProbes.py
@@ -5,6 +5,7 @@ client, it can either be updated in the specification or replaced on
the client """
import os
+import sys
import errno
import binascii
import lxml.etree
@@ -87,33 +88,27 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin,
interpreter="/usr/bin/env python")
probe.text = probecode % path
self.probes[metadata.hostname].append(probe)
- self.logger.debug("Adding file probe for %s to %s" %
- (path, metadata.hostname))
+ self.debug_log("Adding file probe for %s to %s" %
+ (path, metadata.hostname))
return self.probes[metadata.hostname]
def ReceiveData(self, metadata, datalist):
"""Receive data from probe."""
- self.logger.debug("Receiving file probe data from %s" %
- metadata.hostname)
+ self.debug_log("Receiving file probe data from %s" % metadata.hostname)
for data in datalist:
if data.text is None:
self.logger.error("Got null response to %s file probe from %s" %
(data.get('name'), metadata.hostname))
else:
- self.logger.debug("%s:fileprobe:%s:%s" %
- (metadata.hostname,
- data.get("name"),
- data.text))
try:
- filedata = lxml.etree.XML(data.text)
- self.write_file(filedata, metadata)
+ self.write_data(lxml.etree.XML(data.text), metadata)
except lxml.etree.XMLSyntaxError:
# if we didn't get XML back from the probe, assume
# it's an error message
self.logger.error(data.text)
- def write_file(self, data, metadata):
+ def write_data(self, data, metadata):
"""Write the probed file data to the bcfg2 specification."""
filename = data.get("name")
contents = binascii.a2b_base64(data.text)
@@ -137,74 +132,80 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin,
entrydata = entry.text
if create:
- self.logger.info("Writing new probed file %s" % fileloc)
- try:
- os.makedirs(os.path.dirname(fileloc))
- except OSError, err:
- if err.errno == errno.EEXIST:
- pass
- else:
- raise
- open(fileloc, 'wb').write(contents)
-
- infoxml = os.path.join("%s%s" % (cfg.data, filename),
- "info.xml")
- if not os.path.exists(infoxml):
- self.write_infoxml(infoxml, entry, data)
-
- # Service the FAM events queued up by the key generation
- # so the data structure entries will be available for
- # binding.
- #
- # NOTE: We wait for up to ten seconds. There is some
- # potential for race condition, because if the file
- # monitor doesn't get notified about the new key files in
- # time, those entries won't be available for binding. In
- # practice, this seems "good enough".
- tries = 0
- is_bound = False
- while not is_bound:
- if tries >= 10:
- self.logger.error("%s still not registered" % filename)
- raise Bcfg2.Server.Plugin.PluginExecutionError
- self.core.fam.handle_events_in_interval(1)
- try:
- cfg.entries[filename].bind_entry(entry, metadata)
- is_bound = True
- except Bcfg2.Server.Plugin.PluginExecutionError:
- pass
- tries += 1
+ self.logger.info("Writing new probed file %s" % fileloc)
+ self.write_file(fileloc, contents)
+ self.verify_file(filename, contents, metadata)
+ infoxml = os.path.join("%s%s" % (cfg.data, filename), "info.xml")
+ self.write_infoxml(infoxml, entry, data)
elif entrydata == contents:
- self.logger.debug("Existing %s contents match probed contents" %
- filename)
+ self.debug_log("Existing %s contents match probed contents" %
+ filename)
return
elif (entry.get('update', 'false').lower() == "true"):
self.logger.info("Writing updated probed file %s" % fileloc)
- open(fileloc, 'wb').write(contents)
-
- # service FAM events
- tries = 0
- updated = False
- while not updated:
- if tries >= 10:
- self.logger.error("%s still not registered" % filename)
- raise Bcfg2.Server.Plugin.PluginExecutionError
- self.core.fam.handle_events_in_interval(1)
- cfg.entries[filename].bind_entry(entry, metadata)
- # get current entry data
- if entry.get("encoding") == "base64":
- entrydata = binascii.a2b_base64(entry.text)
- else:
- entrydata = entry.text
- if entrydata == contents:
- updated = True
- tries += 1
+ self.write_file(fileloc, contents)
+ self.verify_file(filename, contents, metadata)
else:
self.logger.info("Skipping updated probed file %s" % fileloc)
return
+
+ def write_file(self, fileloc, contents):
+ try:
+ os.makedirs(os.path.dirname(fileloc))
+ except OSError:
+ err = sys.exc_info()[1]
+ if err.errno == errno.EEXIST:
+ pass
+ else:
+ self.logger.error("Could not create parent directories for %s: "
+ "%s" % (fileloc, err))
+ return
+
+ try:
+ open(fileloc, 'wb').write(contents)
+ except IOError:
+ err = sys.exc_info()[1]
+ self.logger.error("Could not write %s: %s" % (fileloc, err))
+ return
+
+ def verify_file(self, filename, contents, metadata):
+ # Service the FAM events queued up by the key generation so
+ # the data structure entries will be available for binding.
+ #
+ # NOTE: We wait for up to ten seconds. There is some potential
+ # for race condition, because if the file monitor doesn't get
+ # notified about the new key files in time, those entries
+ # won't be available for binding. In practice, this seems
+ # "good enough".
+ entry = self.entries[metadata.hostname][filename]
+ cfg = self.core.plugins['Cfg']
+ tries = 0
+ updated = False
+ while not updated:
+ if tries >= 10:
+ self.logger.error("%s still not registered" % filename)
+ return
+ self.core.fam.handle_events_in_interval(1)
+ try:
+ cfg.entries[filename].bind_entry(entry, metadata)
+ except Bcfg2.Server.Plugin.PluginExecutionError:
+ tries += 1
+ continue
+
+ # get current entry data
+ if entry.get("encoding") == "base64":
+ entrydata = binascii.a2b_base64(entry.text)
+ else:
+ entrydata = entry.text
+ if entrydata == contents:
+ updated = True
+ tries += 1
def write_infoxml(self, infoxml, entry, data):
""" write an info.xml for the file """
+ if os.path.exists(infoxml):
+ return
+
self.logger.info("Writing info.xml at %s for %s" %
(infoxml, data.get("name")))
info = \
@@ -220,5 +221,10 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin,
root = lxml.etree.Element("FileInfo")
root.append(info)
- open(infoxml, "w").write(lxml.etree.tostring(root,
- pretty_print=True))
+ try:
+ open(infoxml, "w").write(lxml.etree.tostring(root,
+ pretty_print=True))
+ except IOError:
+ err = sys.exc_info()[1]
+ self.logger.error("Could not write %s: %s" % (fileloc, err))
+ return
diff --git a/src/lib/Server/Plugins/Packages/Source.py b/src/lib/Server/Plugins/Packages/Source.py
index 910a90cac..1dfeecc40 100644
--- a/src/lib/Server/Plugins/Packages/Source.py
+++ b/src/lib/Server/Plugins/Packages/Source.py
@@ -136,7 +136,7 @@ class Source(Bcfg2.Server.Plugin.Debuggable):
def get_repo_name(self, url_map):
# try to find a sensible name for a repo
if url_map['component']:
- return url_map['component']
+ rname = url_map['component']
else:
name = None
for repo_re in (self.mrepo_re,
@@ -144,14 +144,18 @@ class Source(Bcfg2.Server.Plugin.Debuggable):
self.genericrepo_re):
match = repo_re.search(url_map['url'])
if match:
- name = match.group(1).replace('/', '-')
break
if name is None:
# couldn't figure out the name from the URL or URL map
# (which probably means its a screwy URL), so we just
# generate a random one
name = base64.b64encode(os.urandom(16))[:-2]
- return "%s-%s" % (self.groups[0], name)
+ rname = "%s-%s" % (self.groups[0], name)
+ # see yum/__init__.py in the yum source, lines 441-449, for
+ # the source of this regex. yum doesn't like anything but
+ # string.ascii_letters, string.digits, and [-_.:]. There
+ # doesn't seem to be a reason for this, because yum.
+ return re.sub(r'[^A-Za-z0-9-_.:]', '-', rname)
def __str__(self):
if self.rawurl:
diff --git a/src/lib/Server/Plugins/Packages/Yum.py b/src/lib/Server/Plugins/Packages/Yum.py
index a5fe706cd..416602b27 100644
--- a/src/lib/Server/Plugins/Packages/Yum.py
+++ b/src/lib/Server/Plugins/Packages/Yum.py
@@ -124,6 +124,7 @@ class YumCollection(Collection):
mainopts = dict(cachedir=self.cachefile,
keepcache="0",
sslverify="0",
+ debuglevel="0",
reposdir="/dev/null")
try:
for opt in self.config.options("yum"):
@@ -394,6 +395,11 @@ class YumCollection(Collection):
if rv:
self.logger.error("Packages: error running bcfg2-yum-helper "
"(returned %d): %s" % (rv, stderr))
+ elif self.debug_flag:
+ self.logger.debug("Packages: debug info from bcfg2-yum-helper: %s" %
+ stderr)
+ self.logger.debug("Packages: output from bcfg2-yum-helper: %s" %
+ stderr)
try:
return json.loads(stdout)
except ValueError:
diff --git a/src/lib/Server/Plugins/SSHbase.py b/src/lib/Server/Plugins/SSHbase.py
index 4db5fc379..2e247caa7 100644
--- a/src/lib/Server/Plugins/SSHbase.py
+++ b/src/lib/Server/Plugins/SSHbase.py
@@ -233,6 +233,8 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin,
if entry.specific.match(event.filename):
entry.handle_event(event)
if event.filename.endswith(".pub"):
+ self.logger.info("New public key %s; invalidating "
+ "ssh_known_hosts cache" % event.filename)
self.skn = False
return
@@ -242,6 +244,8 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin,
return
if event.filename.endswith('.static'):
+ self.logger.info("Static key %s %s; invalidating ssh_known_hosts "
+ "cache" % (event.filename, action))
if action == "deleted" and event.filename in self.static:
del self.static[event.filename]
self.skn = False
diff --git a/src/lib/Server/Plugins/Trigger.py b/src/lib/Server/Plugins/Trigger.py
index 9c0994ebe..b0d21545c 100644
--- a/src/lib/Server/Plugins/Trigger.py
+++ b/src/lib/Server/Plugins/Trigger.py
@@ -25,12 +25,19 @@ class Trigger(Bcfg2.Server.Plugin.Plugin,
try:
os.stat(self.data)
except:
- self.logger.error("Trigger: spool directory %s does not exist; unloading" % self.data)
+ self.logger.error("Trigger: spool directory %s does not exist; "
+ "unloading" % self.data)
raise Bcfg2.Server.Plugin.PluginInitError
def process_statistics(self, metadata, _):
args = [metadata.hostname, '-p', metadata.profile, '-g',
':'.join([g for g in metadata.groups])]
for notifier in os.listdir(self.data):
- n = self.data + '/' + notifier
- async_run(n, args)
+ if ((notifier[-1] == '~') or
+ (notifier[:2] == '.#') or
+ (notifier[-4:] == '.swp') or
+ (notifier in ['SCCS', '.svn', '4913'])):
+ continue
+ npath = self.data + '/' + notifier
+ self.logger.debug("Running %s %s" % (npath, " ".join(args)))
+ async_run(npath, args)
diff --git a/src/lib/Server/Reports/reports/templates/base.html b/src/lib/Server/Reports/reports/templates/base.html
index a12bf66ba..f541c0d2b 100644
--- a/src/lib/Server/Reports/reports/templates/base.html
+++ b/src/lib/Server/Reports/reports/templates/base.html
@@ -87,7 +87,7 @@
<div style='clear:both'></div>
</div><!-- document -->
<div id="footer">
- <span>Bcfg2 Version 1.2.1</span>
+ <span>Bcfg2 Version 1.2.2</span>
</div>
<div id="calendar_div" style='position:absolute; visibility:hidden; background-color:white; layer-background-color:white;'></div>