diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/Bcfg2/Bcfg2Py3k.py (renamed from src/lib/Bcfg2Py3k.py) | 11 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Frame.py (renamed from src/lib/Client/Frame.py) | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/APK.py (renamed from src/lib/Client/Tools/APK.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/APT.py (renamed from src/lib/Client/Tools/APT.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Action.py (renamed from src/lib/Client/Tools/Action.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Blast.py (renamed from src/lib/Client/Tools/Blast.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Chkconfig.py (renamed from src/lib/Client/Tools/Chkconfig.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/DebInit.py (renamed from src/lib/Client/Tools/DebInit.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Encap.py (renamed from src/lib/Client/Tools/Encap.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/FreeBSDInit.py (renamed from src/lib/Client/Tools/FreeBSDInit.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/FreeBSDPackage.py (renamed from src/lib/Client/Tools/FreeBSDPackage.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/IPS.py (renamed from src/lib/Client/Tools/IPS.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/MacPorts.py (renamed from src/lib/Client/Tools/MacPorts.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/POSIX.py (renamed from src/lib/Client/Tools/POSIX.py) | 23 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Pacman.py (renamed from src/lib/Client/Tools/Pacman.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Portage.py | 125 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/RPMng.py (renamed from src/lib/Client/Tools/RPMng.py) | 10 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/RcUpdate.py (renamed from src/lib/Client/Tools/RcUpdate.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/SMF.py (renamed from src/lib/Client/Tools/SMF.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/SYSV.py (renamed from src/lib/Client/Tools/SYSV.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Systemd.py (renamed from src/lib/Client/Tools/Systemd.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/Upstart.py (renamed from src/lib/Client/Tools/Upstart.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/VCS.py (renamed from src/lib/Client/Tools/VCS.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/YUM24.py (renamed from src/lib/Client/Tools/YUM24.py) | 7 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/YUMng.py (renamed from src/lib/Client/Tools/YUMng.py) | 10 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/__init__.py (renamed from src/lib/Client/Tools/__init__.py) | 5 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/Tools/launchd.py (renamed from src/lib/Client/Tools/launchd.py) | 1 | ||||
-rwxr-xr-x | src/lib/Bcfg2/Client/Tools/rpmtools.py (renamed from src/lib/Client/Tools/rpmtools.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/XML.py (renamed from src/lib/Client/XML.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Client/__init__.py (renamed from src/lib/Client/__init__.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Component.py (renamed from src/lib/Component.py) | 6 | ||||
-rw-r--r-- | src/lib/Bcfg2/Logger.py (renamed from src/lib/Logger.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Options.py (renamed from src/lib/Options.py) | 15 | ||||
-rw-r--r-- | src/lib/Bcfg2/Proxy.py (renamed from src/lib/Proxy.py) | 5 | ||||
-rw-r--r-- | src/lib/Bcfg2/SSLServer.py (renamed from src/lib/SSLServer.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Backup.py (renamed from src/lib/Server/Admin/Backup.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Bundle.py (renamed from src/lib/Server/Admin/Bundle.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Client.py (renamed from src/lib/Server/Admin/Client.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Compare.py (renamed from src/lib/Server/Admin/Compare.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Group.py (renamed from src/lib/Server/Admin/Group.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Init.py (renamed from src/lib/Server/Admin/Init.py) | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Minestruct.py (renamed from src/lib/Server/Admin/Minestruct.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Perf.py (renamed from src/lib/Server/Admin/Perf.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Pull.py (renamed from src/lib/Server/Admin/Pull.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Query.py (renamed from src/lib/Server/Admin/Query.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Reports.py (renamed from src/lib/Server/Admin/Reports.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Snapshots.py (renamed from src/lib/Server/Admin/Snapshots.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Tidy.py (renamed from src/lib/Server/Admin/Tidy.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Viz.py (renamed from src/lib/Server/Admin/Viz.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/Xcmd.py (renamed from src/lib/Server/Admin/Xcmd.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Admin/__init__.py (renamed from src/lib/Server/Admin/__init__.py) | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Core.py (renamed from src/lib/Server/Core.py) | 3 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/FileMonitor.py (renamed from src/lib/Server/FileMonitor.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/.gitignore (renamed from src/lib/Server/Hostbase/.gitignore) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/__init__.py (renamed from src/lib/Server/Hostbase/__init__.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/backends.py (renamed from src/lib/Server/Hostbase/backends.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/__init__.py (renamed from src/lib/Server/Hostbase/hostbase/__init__.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/admin.py (renamed from src/lib/Server/Hostbase/hostbase/admin.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/models.py (renamed from src/lib/Server/Hostbase/hostbase/models.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/sql/zone.sql (renamed from src/lib/Server/Hostbase/hostbase/sql/zone.sql) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/urls.py (renamed from src/lib/Server/Hostbase/hostbase/urls.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/views.py (renamed from src/lib/Server/Hostbase/hostbase/views.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/base.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/base.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/confirm.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/confirm.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/copy.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/copy.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/dns.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/dns.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/dnsedit.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/dnsedit.html) | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/edit.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/edit.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/errors.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/errors.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/host.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/host.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/hostbase/host_confirm_delete.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/hostbase/host_confirm_delete.html) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/hostbase/log_detail.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/hostbase/log_detail.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/index.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/index.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/login.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/login.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/logout.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/logout.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/logout.tmpl (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/logout.tmpl) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/logviewer.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/logviewer.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/navbar.tmpl (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/navbar.tmpl) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/new.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/new.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/remove.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/remove.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/results.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/results.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/search.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/search.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/zoneedit.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/zoneedit.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/zonenew.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/zonenew.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/zones.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/zones.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/zoneview.html (renamed from src/lib/Server/Hostbase/hostbase/webtemplates/zoneview.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/ldapauth.py (renamed from src/lib/Server/Hostbase/ldapauth.py) | 0 | ||||
-rwxr-xr-x | src/lib/Bcfg2/Server/Hostbase/manage.py (renamed from src/lib/Server/Hostbase/manage.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/media/base.css (renamed from src/lib/Server/Hostbase/media/base.css) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/media/boxypastel.css (renamed from src/lib/Server/Hostbase/media/boxypastel.css) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/media/global.css (renamed from src/lib/Server/Hostbase/media/global.css) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/media/layout.css (renamed from src/lib/Server/Hostbase/media/layout.css) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/nisauth.py (renamed from src/lib/Server/Hostbase/nisauth.py) | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/regex.py (renamed from src/lib/Server/Hostbase/regex.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/settings.py (renamed from src/lib/Server/Hostbase/settings.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/templates/batchadd.tmpl (renamed from src/lib/Server/Hostbase/templates/batchadd.tmpl) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/templates/dhcpd.conf.head (renamed from src/lib/Server/Hostbase/templates/dhcpd.conf.head) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/templates/dhcpd.tmpl (renamed from src/lib/Server/Hostbase/templates/dhcpd.tmpl) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/templates/hosts.tmpl (renamed from src/lib/Server/Hostbase/templates/hosts.tmpl) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/templates/hostsappend.tmpl (renamed from src/lib/Server/Hostbase/templates/hostsappend.tmpl) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/templates/named.tmpl (renamed from src/lib/Server/Hostbase/templates/named.tmpl) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/templates/namedviews.tmpl (renamed from src/lib/Server/Hostbase/templates/namedviews.tmpl) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/templates/reverseappend.tmpl (renamed from src/lib/Server/Hostbase/templates/reverseappend.tmpl) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/templates/reversesoa.tmpl (renamed from src/lib/Server/Hostbase/templates/reversesoa.tmpl) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/templates/zone.tmpl (renamed from src/lib/Server/Hostbase/templates/zone.tmpl) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/test/harness.py (renamed from src/lib/Server/Hostbase/test/harness.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/test/test_environ_settings.py (renamed from src/lib/Server/Hostbase/test/test_environ_settings.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/test/test_ldapauth.py (renamed from src/lib/Server/Hostbase/test/test_ldapauth.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/test/test_settings.py (renamed from src/lib/Server/Hostbase/test/test_settings.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Hostbase/urls.py (renamed from src/lib/Server/Hostbase/urls.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Lint/Bundles.py (renamed from src/lib/Server/Lint/Bundles.py) | 21 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Lint/Comments.py (renamed from src/lib/Server/Lint/Comments.py) | 15 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Lint/Deltas.py | 5 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Lint/Duplicates.py (renamed from src/lib/Server/Lint/Duplicates.py) | 10 | ||||
-rwxr-xr-x | src/lib/Bcfg2/Server/Lint/Genshi.py (renamed from src/lib/Server/Lint/Genshi.py) | 12 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Lint/GroupPatterns.py (renamed from src/lib/Server/Lint/GroupPatterns.py) | 8 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Lint/InfoXML.py (renamed from src/lib/Server/Lint/InfoXML.py) | 8 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Lint/MergeFiles.py (renamed from src/lib/Server/Lint/MergeFiles.py) | 11 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Lint/Pkgmgr.py (renamed from src/lib/Server/Lint/Pkgmgr.py) | 5 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Lint/RequiredAttrs.py (renamed from src/lib/Server/Lint/RequiredAttrs.py) | 9 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Lint/TemplateHelper.py | 64 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Lint/Validate.py (renamed from src/lib/Server/Lint/Validate.py) | 16 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Lint/__init__.py (renamed from src/lib/Server/Lint/__init__.py) | 52 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugin.py (renamed from src/lib/Server/Plugin.py) | 64 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Account.py (renamed from src/lib/Server/Plugins/Account.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/BB.py (renamed from src/lib/Server/Plugins/BB.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Base.py (renamed from src/lib/Server/Plugins/Base.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Bundler.py (renamed from src/lib/Server/Plugins/Bundler.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Bzr.py (renamed from src/lib/Server/Plugins/Bzr.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Cfg.py (renamed from src/lib/Server/Plugins/Cfg.py) | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Cvs.py (renamed from src/lib/Server/Plugins/Cvs.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/DBStats.py (renamed from src/lib/Server/Plugins/DBStats.py) | 3 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Darcs.py (renamed from src/lib/Server/Plugins/Darcs.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Decisions.py (renamed from src/lib/Server/Plugins/Decisions.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Defaults.py (renamed from src/lib/Server/Plugins/Defaults.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Deps.py (renamed from src/lib/Server/Plugins/Deps.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Editor.py (renamed from src/lib/Server/Plugins/Editor.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/FileProbes.py (renamed from src/lib/Server/Plugins/FileProbes.py) | 12 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Fossil.py (renamed from src/lib/Server/Plugins/Fossil.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Git.py (renamed from src/lib/Server/Plugins/Git.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/GroupPatterns.py (renamed from src/lib/Server/Plugins/GroupPatterns.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Guppy.py (renamed from src/lib/Server/Plugins/Guppy.py) | 5 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Hg.py (renamed from src/lib/Server/Plugins/Hg.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Hostbase.py (renamed from src/lib/Server/Plugins/Hostbase.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Ldap.py (renamed from src/lib/Server/Plugins/Ldap.py) | 53 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Metadata.py (renamed from src/lib/Server/Plugins/Metadata.py) | 634 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/NagiosGen.py (renamed from src/lib/Server/Plugins/NagiosGen.py) | 7 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Ohai.py (renamed from src/lib/Server/Plugins/Ohai.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Packages/Apt.py (renamed from src/lib/Server/Plugins/Packages/Apt.py) | 7 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Packages/Collection.py (renamed from src/lib/Server/Plugins/Packages/Collection.py) | 8 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Packages/Pac.py (renamed from src/lib/Server/Plugins/Packages/Pac.py) | 9 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Packages/PackagesConfig.py (renamed from src/lib/Server/Plugins/Packages/PackagesConfig.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Packages/PackagesSources.py (renamed from src/lib/Server/Plugins/Packages/PackagesSources.py) | 16 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Packages/Source.py (renamed from src/lib/Server/Plugins/Packages/Source.py) | 6 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Packages/Yum.py (renamed from src/lib/Server/Plugins/Packages/Yum.py) | 34 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Packages/__init__.py (renamed from src/lib/Server/Plugins/Packages/__init__.py) | 12 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Pkgmgr.py (renamed from src/lib/Server/Plugins/Pkgmgr.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Probes.py (renamed from src/lib/Server/Plugins/Probes.py) | 5 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Properties.py (renamed from src/lib/Server/Plugins/Properties.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Rules.py (renamed from src/lib/Server/Plugins/Rules.py) | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/SGenshi.py (renamed from src/lib/Server/Plugins/SGenshi.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/SSHbase.py (renamed from src/lib/Server/Plugins/SSHbase.py) | 14 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/SSLCA.py (renamed from src/lib/Server/Plugins/SSLCA.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Snapshots.py (renamed from src/lib/Server/Plugins/Snapshots.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Statistics.py (renamed from src/lib/Server/Plugins/Statistics.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Svcmgr.py (renamed from src/lib/Server/Plugins/Svcmgr.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Svn.py (renamed from src/lib/Server/Plugins/Svn.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Svn2.py (renamed from src/lib/Server/Plugins/Svn2.py) | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/TCheetah.py (renamed from src/lib/Server/Plugins/TCheetah.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/TGenshi.py (renamed from src/lib/Server/Plugins/TGenshi.py) | 8 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/TemplateHelper.py | 83 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/Trigger.py (renamed from src/lib/Server/Plugins/Trigger.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Plugins/__init__.py (renamed from src/lib/Server/Plugins/__init__.py) | 3 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/__init__.py (renamed from src/lib/Server/Reports/__init__.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/backends.py (renamed from src/lib/Server/Reports/backends.py) | 0 | ||||
-rwxr-xr-x | src/lib/Bcfg2/Server/Reports/importscript.py (renamed from src/lib/Server/Reports/importscript.py) | 11 | ||||
-rwxr-xr-x | src/lib/Bcfg2/Server/Reports/manage.py (renamed from src/lib/Server/Reports/manage.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/nisauth.py (renamed from src/lib/Server/Reports/nisauth.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/__init__.py (renamed from src/lib/Server/Reports/reports/__init__.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/fixtures/initial_version.xml (renamed from src/lib/Server/Reports/reports/fixtures/initial_version.xml) | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/models.py (renamed from src/lib/Server/Reports/reports/models.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/sql/client.sql (renamed from src/lib/Server/Reports/reports/sql/client.sql) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/404.html (renamed from src/lib/Server/Reports/reports/templates/404.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/base-timeview.html (renamed from src/lib/Server/Reports/reports/templates/base-timeview.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/base.html (renamed from src/lib/Server/Reports/reports/templates/base.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/clients/detail.html (renamed from src/lib/Server/Reports/reports/templates/clients/detail.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/clients/detailed-list.html (renamed from src/lib/Server/Reports/reports/templates/clients/detailed-list.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/clients/history.html (renamed from src/lib/Server/Reports/reports/templates/clients/history.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/clients/index.html (renamed from src/lib/Server/Reports/reports/templates/clients/index.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/clients/manage.html (renamed from src/lib/Server/Reports/reports/templates/clients/manage.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/config_items/item.html (renamed from src/lib/Server/Reports/reports/templates/config_items/item.html) | 15 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/config_items/listing.html (renamed from src/lib/Server/Reports/reports/templates/config_items/listing.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/displays/summary.html (renamed from src/lib/Server/Reports/reports/templates/displays/summary.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/displays/timing.html (renamed from src/lib/Server/Reports/reports/templates/displays/timing.html) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/widgets/filter_bar.html (renamed from src/lib/Server/Reports/reports/templates/widgets/filter_bar.html) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/widgets/interaction_list.inc (renamed from src/lib/Server/Reports/reports/templates/widgets/interaction_list.inc) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templates/widgets/page_bar.html (renamed from src/lib/Server/Reports/reports/templates/widgets/page_bar.html) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templatetags/__init__.py (renamed from src/lib/Server/Reports/reports/templatetags/__init__.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templatetags/bcfg2_tags.py (renamed from src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py) | 4 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templatetags/split.py | 8 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/templatetags/syntax_coloring.py (renamed from src/lib/Server/Reports/reports/templatetags/syntax_coloring.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/urls.py (renamed from src/lib/Server/Reports/reports/urls.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/reports/views.py (renamed from src/lib/Server/Reports/reports/views.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/settings.py (renamed from src/lib/Server/Reports/settings.py) | 12 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/updatefix.py (renamed from src/lib/Server/Reports/updatefix.py) | 97 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Reports/urls.py (renamed from src/lib/Server/Reports/urls.py) | 0 | ||||
-rwxr-xr-x | src/lib/Bcfg2/Server/Reports/utils.py (renamed from src/lib/Server/Reports/utils.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Snapshots/__init__.py (renamed from src/lib/Server/Snapshots/__init__.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/Snapshots/model.py (renamed from src/lib/Server/Snapshots/model.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/Server/__init__.py (renamed from src/lib/Server/__init__.py) | 2 | ||||
-rw-r--r-- | src/lib/Bcfg2/Statistics.py (renamed from src/lib/Statistics.py) | 0 | ||||
-rw-r--r-- | src/lib/Bcfg2/__init__.py (renamed from src/lib/__init__.py) | 1 | ||||
-rw-r--r-- | src/lib/Bcfg2Py3Incompat.py | 2 | ||||
-rw-r--r-- | src/lib/Client/Tools/Portage.py | 72 | ||||
-rwxr-xr-x | src/sbin/bcfg2 | 1 | ||||
-rwxr-xr-x | src/sbin/bcfg2-admin | 3 | ||||
-rwxr-xr-x | src/sbin/bcfg2-build-reports | 2 | ||||
-rwxr-xr-x | src/sbin/bcfg2-info | 190 | ||||
-rwxr-xr-x | src/sbin/bcfg2-lint | 25 | ||||
-rwxr-xr-x | src/sbin/bcfg2-ping-sweep | 2 | ||||
-rwxr-xr-x | src/sbin/bcfg2-reports | 1 | ||||
-rwxr-xr-x | src/sbin/bcfg2-server | 1 | ||||
-rwxr-xr-x | src/sbin/bcfg2-yum-helper | 2 |
223 files changed, 1142 insertions, 860 deletions
diff --git a/src/lib/Bcfg2Py3k.py b/src/lib/Bcfg2/Bcfg2Py3k.py index ee05b7e41..6af8b3e5c 100644 --- a/src/lib/Bcfg2Py3k.py +++ b/src/lib/Bcfg2/Bcfg2Py3k.py @@ -75,17 +75,6 @@ def u_str(string, encoding=None): else: return unicode(string) -""" -In order to use the new syntax for printing to a file, we need to do -a conditional import because there is a syntax incompatibility between -the two versions of python. -""" -if sys.hexversion >= 0x03000000: - from Bcfg2.Bcfg2Py3Incompat import fprint -else: - def fprint(s, f): - print >> f, s - if sys.hexversion >= 0x03000000: from io import FileIO as file else: diff --git a/src/lib/Client/Frame.py b/src/lib/Bcfg2/Client/Frame.py index d17f70f1b..9ad669ad6 100644 --- a/src/lib/Client/Frame.py +++ b/src/lib/Bcfg2/Client/Frame.py @@ -2,7 +2,6 @@ Frame is the Client Framework that verifies and installs entries, and generates statistics. """ -__revision__ = '$Revision$' import logging import sys @@ -292,7 +291,7 @@ class Frame: if self.setup['interactive']: promptFilter(prompt, actions) self.DispatchInstallCalls(actions) - + # need to test to fail entries in whitelist if False in [self.states[a] for a in actions]: # then display bundles forced off with entries @@ -427,7 +426,6 @@ class Frame: stats = Bcfg2.Client.XML.SubElement(feedback, 'Statistics', total=str(len(self.states)), - client_version=__revision__, version='2.0', revision=self.config.get('revision', '-1')) good = len([key for key, val in list(self.states.items()) if val]) diff --git a/src/lib/Client/Tools/APK.py b/src/lib/Bcfg2/Client/Tools/APK.py index 6a6fd51b3..aaaf2472f 100644 --- a/src/lib/Client/Tools/APK.py +++ b/src/lib/Bcfg2/Client/Tools/APK.py @@ -1,5 +1,4 @@ """This provides Bcfg2 support for Alpine Linux APK packages.""" -__revision__ = '$Revision$' import Bcfg2.Client.Tools diff --git a/src/lib/Client/Tools/APT.py b/src/lib/Bcfg2/Client/Tools/APT.py index db8cd56e7..6b839ffbc 100644 --- a/src/lib/Client/Tools/APT.py +++ b/src/lib/Bcfg2/Client/Tools/APT.py @@ -1,5 +1,4 @@ """This is the Bcfg2 support for apt-get.""" -__revision__ = '$Revision$' # suppress apt API warnings import warnings diff --git a/src/lib/Client/Tools/Action.py b/src/lib/Bcfg2/Client/Tools/Action.py index c089cde1d..dc49347e9 100644 --- a/src/lib/Client/Tools/Action.py +++ b/src/lib/Bcfg2/Client/Tools/Action.py @@ -1,5 +1,4 @@ """Action driver""" -__revision__ = '$Revision$' import Bcfg2.Client.Tools from Bcfg2.Client.Frame import matches_white_list, passes_black_list diff --git a/src/lib/Client/Tools/Blast.py b/src/lib/Bcfg2/Client/Tools/Blast.py index 29cdfa116..5d5e74ab2 100644 --- a/src/lib/Client/Tools/Blast.py +++ b/src/lib/Bcfg2/Client/Tools/Blast.py @@ -1,6 +1,4 @@ -# This is the bcfg2 support for blastwave packages (pkg-get) """This provides Bcfg2 support for Blastwave.""" -__revision__ = '$Revision$' import tempfile import Bcfg2.Client.Tools.SYSV diff --git a/src/lib/Client/Tools/Chkconfig.py b/src/lib/Bcfg2/Client/Tools/Chkconfig.py index 17e8bf09b..12ea5f132 100644 --- a/src/lib/Client/Tools/Chkconfig.py +++ b/src/lib/Bcfg2/Client/Tools/Chkconfig.py @@ -1,8 +1,6 @@ # This is the bcfg2 support for chkconfig -# $Id$ """This is chkconfig support.""" -__revision__ = '$Revision$' import os diff --git a/src/lib/Client/Tools/DebInit.py b/src/lib/Bcfg2/Client/Tools/DebInit.py index 022332602..ca6fc439e 100644 --- a/src/lib/Client/Tools/DebInit.py +++ b/src/lib/Bcfg2/Client/Tools/DebInit.py @@ -1,5 +1,4 @@ """Debian Init Support for Bcfg2""" -__revision__ = '$Revision$' import glob import os diff --git a/src/lib/Client/Tools/Encap.py b/src/lib/Bcfg2/Client/Tools/Encap.py index 92062a750..fa09c3ec7 100644 --- a/src/lib/Client/Tools/Encap.py +++ b/src/lib/Bcfg2/Client/Tools/Encap.py @@ -1,7 +1,5 @@ """Bcfg2 Support for Encap Packages""" -__revision__ = '$Revision$' - import glob import re import Bcfg2.Client.Tools diff --git a/src/lib/Client/Tools/FreeBSDInit.py b/src/lib/Bcfg2/Client/Tools/FreeBSDInit.py index 10f0f2e93..10f0f2e93 100644 --- a/src/lib/Client/Tools/FreeBSDInit.py +++ b/src/lib/Bcfg2/Client/Tools/FreeBSDInit.py diff --git a/src/lib/Client/Tools/FreeBSDPackage.py b/src/lib/Bcfg2/Client/Tools/FreeBSDPackage.py index 04c05adaa..3e6f2b6bb 100644 --- a/src/lib/Client/Tools/FreeBSDPackage.py +++ b/src/lib/Bcfg2/Client/Tools/FreeBSDPackage.py @@ -1,5 +1,4 @@ """This is the Bcfg2 tool for the FreeBSD package system.""" -__revision__ = '$Rev$' # TODO # - actual package installation diff --git a/src/lib/Client/Tools/IPS.py b/src/lib/Bcfg2/Client/Tools/IPS.py index 9afd23143..e30bbd2a4 100644 --- a/src/lib/Client/Tools/IPS.py +++ b/src/lib/Bcfg2/Client/Tools/IPS.py @@ -1,5 +1,4 @@ """This is the Bcfg2 support for OpenSolaris packages.""" -__revision__ = '$Revision$' import pkg.client.image as image import pkg.client.progress as progress diff --git a/src/lib/Client/Tools/MacPorts.py b/src/lib/Bcfg2/Client/Tools/MacPorts.py index 2a7ba9eb9..9724fab57 100644 --- a/src/lib/Client/Tools/MacPorts.py +++ b/src/lib/Bcfg2/Client/Tools/MacPorts.py @@ -1,5 +1,4 @@ """This provides Bcfg2 support for macports packages.""" -__revision__ = '$Revision$' import Bcfg2.Client.Tools diff --git a/src/lib/Client/Tools/POSIX.py b/src/lib/Bcfg2/Client/Tools/POSIX.py index 3591c33ad..0d67dbbab 100644 --- a/src/lib/Client/Tools/POSIX.py +++ b/src/lib/Bcfg2/Client/Tools/POSIX.py @@ -1,5 +1,4 @@ """All POSIX Type client support for Bcfg2.""" -__revision__ = '$Revision$' import binascii from datetime import datetime @@ -21,7 +20,7 @@ import Bcfg2.Client.Tools import Bcfg2.Options from Bcfg2.Client import XML -log = logging.getLogger('posix') +log = logging.getLogger('POSIX') # map between dev_type attribute and stat constants device_map = {'block': stat.S_IFBLK, @@ -259,8 +258,8 @@ class POSIX(Bcfg2.Client.Tools.Tool): if entry.get('perms') == None or \ entry.get('owner') == None or \ entry.get('group') == None: - self.logger.error('Entry %s not completely specified. ' - 'Try running bcfg2-lint.' % (entry.get('name'))) + self.logger.error("POSIX: Entry %s not completely specified. " + "Try running bcfg2-lint." % (entry.get('name'))) return False while len(entry.get('perms', '')) < 4: entry.set('perms', '0' + entry.get('perms', '')) @@ -268,15 +267,15 @@ class POSIX(Bcfg2.Client.Tools.Tool): ondisk = os.stat(entry.get('name')) except OSError: entry.set('current_exists', 'false') - self.logger.debug("%s %s does not exist" % + self.logger.info("POSIX: %s %s does not exist" % (entry.tag, entry.get('name'))) return False try: owner = str(ondisk[stat.ST_UID]) group = str(ondisk[stat.ST_GID]) except (OSError, KeyError): - self.logger.error('User/Group resolution failed for path %s' % \ - entry.get('name')) + self.logger.info("POSIX: User/Group resolution failed " + "for path %s" % entry.get('name')) owner = 'root' group = '0' finfo = os.stat(entry.get('name')) @@ -301,11 +300,11 @@ class POSIX(Bcfg2.Client.Tools.Tool): ex_ents = [e for e in entries if e not in modlist] if ex_ents: pruneTrue = False - self.logger.debug("Directory %s contains extra entries:" % \ - entry.get('name')) - self.logger.debug(ex_ents) + self.logger.info("POSIX: Directory %s contains " + "extra entries:" % entry.get('name')) + self.logger.info(ex_ents) nqtext = entry.get('qtext', '') + '\n' - nqtext += "Directory %s contains extra entries:" % \ + nqtext += "Directory %s contains extra entries: " % \ entry.get('name') nqtext += ":".join(ex_ents) entry.set('qtest', nqtext) @@ -496,7 +495,7 @@ class POSIX(Bcfg2.Client.Tools.Tool): (err.filename, err)) return False different = content != tempdata - + if different: if self.setup['interactive']: prompt = [entry.get('qtext', '')] diff --git a/src/lib/Client/Tools/Pacman.py b/src/lib/Bcfg2/Client/Tools/Pacman.py index c8c05061c..c8c05061c 100644 --- a/src/lib/Client/Tools/Pacman.py +++ b/src/lib/Bcfg2/Client/Tools/Pacman.py diff --git a/src/lib/Bcfg2/Client/Tools/Portage.py b/src/lib/Bcfg2/Client/Tools/Portage.py new file mode 100644 index 000000000..4516f419d --- /dev/null +++ b/src/lib/Bcfg2/Client/Tools/Portage.py @@ -0,0 +1,125 @@ +"""This is the Bcfg2 tool for the Gentoo Portage system.""" + +import re +import Bcfg2.Client.Tools +from Bcfg2.Bcfg2Py3k import ConfigParser + + +class Portage(Bcfg2.Client.Tools.PkgTool): + """The Gentoo toolset implements package and service operations and + inherits the rest from Toolset.Toolset.""" + name = 'Portage' + __execs__ = ['/usr/bin/emerge', '/usr/bin/equery'] + __handles__ = [('Package', 'ebuild')] + __req__ = {'Package': ['name', 'version']} + pkgtype = 'ebuild' + # requires a working PORTAGE_BINHOST in make.conf + _binpkgtool = ('emerge --getbinpkgonly %s', ('=%s-%s', \ + ['name', 'version'])) + pkgtool = ('emerge %s', ('=%s-%s', ['name', 'version'])) + + def __init__(self, logger, cfg, setup): + self._initialised = False + Bcfg2.Client.Tools.PkgTool.__init__(self, logger, cfg, setup) + self._initialised = True + self.__important__ = self.__important__ + ['/etc/make.conf'] + self._pkg_pattern = re.compile('(.*)-(\d.*)') + self._ebuild_pattern = re.compile('(ebuild|binary)') + self.cfg = cfg + self.installed = {} + self._binpkgonly = True + + # Used to get options from configuration file + parser = ConfigParser.ConfigParser() + parser.read(self.setup.get('setup')) + for opt in ['binpkgonly']: + if parser.has_option(self.name, opt): + setattr(self, ('_%s' % opt), + self._StrToBoolIfBool(parser.get(self.name, opt))) + + if self._binpkgonly: + self.pkgtool = self._binpkgtool + self.RefreshPackages() + + def _StrToBoolIfBool(self, s): + """Returns a boolean if the string specifies a boolean value. + Returns a string otherwise""" + if s.lower() in ('true', 'yes', 't', 'y', '1'): + return True + elif s.lower() in ('false', 'no', 'f', 'n', '0'): + return False + else: + return s + + def RefreshPackages(self): + """Refresh memory hashes of packages.""" + if not self._initialised: + return + self.logger.info('Getting list of installed packages') + cache = self.cmd.run("equery -q list '*'")[1] + self.installed = {} + for pkg in cache: + if self._pkg_pattern.match(pkg): + name = self._pkg_pattern.match(pkg).group(1) + version = self._pkg_pattern.match(pkg).group(2) + self.installed[name] = version + else: + self.logger.info("Failed to parse pkg name %s" % pkg) + + def VerifyPackage(self, entry, modlist): + """Verify package for entry.""" + if not 'version' in entry.attrib: + self.logger.info("Cannot verify unversioned package %s" % + (entry.get('name'))) + return False + + if not (entry.get('name') in self.installed): + # Can't verify package that isn't installed + entry.set('current_exists', 'false') + return False + + # get the installed version + version = self.installed[entry.get('name')] + entry.set('current_version', version) + + if not self.setup['quick']: + if ('verify' not in entry.attrib) or \ + self._StrToBoolIfBool(entry.get('verify')): + + # Check the package if: + # - Not running in quick mode + # - No verify option is specified in the literal configuration + # OR + # - Verify option is specified and is true + + self.logger.debug('Running equery check on %s' % + entry.get('name')) + output = self.cmd.run("/usr/bin/equery -N check '=%s-%s' " + "2>&1 | grep '!!!' | awk '{print $2}'" + % ((entry.get('name'), version)))[1] + if [filename for filename in output \ + if filename not in modlist]: + return False + + # By now the package must be in one of the following states: + # - Not require checking + # - Have no files modified at all + # - Have modified files in the modlist only + if self.installed[entry.get('name')] == version: + # Specified package version is installed + # Specified package version may be any in literal configuration + return True + + # Something got skipped. Indicates a bug + return False + + def RemovePackages(self, packages): + """Deal with extra configuration detected.""" + pkgnames = " ".join([pkg.get('name') for pkg in packages]) + if len(packages) > 0: + self.logger.info('Removing packages:') + self.logger.info(pkgnames) + self.cmd.run("emerge --unmerge --quiet %s" % + " ".join(pkgnames.split(' '))) + self.RefreshPackages() + self.extra = self.FindExtraPackages() diff --git a/src/lib/Client/Tools/RPMng.py b/src/lib/Bcfg2/Client/Tools/RPMng.py index 5376118c2..00dd00d71 100644 --- a/src/lib/Client/Tools/RPMng.py +++ b/src/lib/Bcfg2/Client/Tools/RPMng.py @@ -1,7 +1,5 @@ """Bcfg2 Support for RPMS""" -__revision__ = '$Revision$' - import os.path import rpm import rpmtools @@ -9,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' @@ -461,7 +453,7 @@ class RPMng(Bcfg2.Client.Tools.PkgTool): packages is a list of Package Entries with Instances generated by FindExtraPackages(). - + """ self.logger.debug('Running RPMng.RemovePackages()') diff --git a/src/lib/Client/Tools/RcUpdate.py b/src/lib/Bcfg2/Client/Tools/RcUpdate.py index d832d98a8..1b9a29478 100644 --- a/src/lib/Client/Tools/RcUpdate.py +++ b/src/lib/Bcfg2/Client/Tools/RcUpdate.py @@ -1,5 +1,4 @@ """This is rc-update support.""" -__revision__ = '$Revision$' import os import Bcfg2.Client.Tools diff --git a/src/lib/Client/Tools/SMF.py b/src/lib/Bcfg2/Client/Tools/SMF.py index 944408326..f824410ad 100644 --- a/src/lib/Client/Tools/SMF.py +++ b/src/lib/Bcfg2/Client/Tools/SMF.py @@ -1,5 +1,4 @@ """SMF support for Bcfg2""" -__revision__ = '$Revision$' import glob import os diff --git a/src/lib/Client/Tools/SYSV.py b/src/lib/Bcfg2/Client/Tools/SYSV.py index b5e1f1c59..eb4a13dfb 100644 --- a/src/lib/Client/Tools/SYSV.py +++ b/src/lib/Bcfg2/Client/Tools/SYSV.py @@ -1,6 +1,4 @@ -# This is the bcfg2 support for solaris sysv packages """This provides bcfg2 support for Solaris SYSV packages.""" -__revision__ = '$Revision$' import tempfile diff --git a/src/lib/Client/Tools/Systemd.py b/src/lib/Bcfg2/Client/Tools/Systemd.py index e3f6a4169..e3f6a4169 100644 --- a/src/lib/Client/Tools/Systemd.py +++ b/src/lib/Bcfg2/Client/Tools/Systemd.py diff --git a/src/lib/Client/Tools/Upstart.py b/src/lib/Bcfg2/Client/Tools/Upstart.py index 41a585c23..7afc8edd7 100644 --- a/src/lib/Client/Tools/Upstart.py +++ b/src/lib/Bcfg2/Client/Tools/Upstart.py @@ -1,5 +1,4 @@ """Upstart support for Bcfg2.""" -__revision__ = '$Revision$' import glob import re diff --git a/src/lib/Client/Tools/VCS.py b/src/lib/Bcfg2/Client/Tools/VCS.py index e6081dc1c..e6081dc1c 100644 --- a/src/lib/Client/Tools/VCS.py +++ b/src/lib/Bcfg2/Client/Tools/VCS.py diff --git a/src/lib/Client/Tools/YUM24.py b/src/lib/Bcfg2/Client/Tools/YUM24.py index 66768fb34..4e488b9da 100644 --- a/src/lib/Client/Tools/YUM24.py +++ b/src/lib/Bcfg2/Client/Tools/YUM24.py @@ -1,5 +1,4 @@ """This provides bcfg2 support for yum.""" -__revision__ = '$Revision: $' import copy import os.path @@ -10,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/Bcfg2/Client/Tools/YUMng.py index 9b999df92..244b66cf4 100644 --- a/src/lib/Client/Tools/YUMng.py +++ b/src/lib/Bcfg2/Client/Tools/YUMng.py @@ -1,5 +1,4 @@ """This provides bcfg2 support for yum.""" -__revision__ = '$Revision$' import copy import os.path @@ -16,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.""" @@ -760,7 +753,8 @@ class YUMng(Bcfg2.Client.Tools.PkgTool): else: self.logger.error("Second pass yum install failed.") self.logger.debug(" %s" % restring) - except yum.Errors.YumBaseError, e: + except yum.Errors.YumBaseError: + e = sys.exc_info()[1] self.logger.error("Yum transaction error: %s" % str(e)) self.yb.conf.skip_broken = skipBroken diff --git a/src/lib/Client/Tools/__init__.py b/src/lib/Bcfg2/Client/Tools/__init__.py index e879d7dd6..c6cb6e239 100644 --- a/src/lib/Client/Tools/__init__.py +++ b/src/lib/Bcfg2/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 @@ -10,7 +6,6 @@ from subprocess import Popen, PIPE import time import Bcfg2.Client.XML -__revision__ = '$Revision$' __all__ = [tool.split('.')[0] \ for tool in os.listdir(os.path.dirname(__file__)) \ diff --git a/src/lib/Client/Tools/launchd.py b/src/lib/Bcfg2/Client/Tools/launchd.py index d7cbfa07f..c022d32ae 100644 --- a/src/lib/Client/Tools/launchd.py +++ b/src/lib/Bcfg2/Client/Tools/launchd.py @@ -1,5 +1,4 @@ """launchd support for Bcfg2.""" -__revision__ = '$Revision$' import os diff --git a/src/lib/Client/Tools/rpmtools.py b/src/lib/Bcfg2/Client/Tools/rpmtools.py index 3cd2b7014..7441b2c06 100755 --- a/src/lib/Client/Tools/rpmtools.py +++ b/src/lib/Bcfg2/Client/Tools/rpmtools.py @@ -18,7 +18,6 @@ Run 'rpmtools' -h for the options. """ -__revision__ = '$Revision$' import grp import optparse diff --git a/src/lib/Client/XML.py b/src/lib/Bcfg2/Client/XML.py index 42b1017ac..858479611 100644 --- a/src/lib/Client/XML.py +++ b/src/lib/Bcfg2/Client/XML.py @@ -1,5 +1,4 @@ '''XML lib compatibility layer for the Bcfg2 client''' -__revision__ = '$Revision$' # library will use lxml, then builtin xml.etree, then ElementTree diff --git a/src/lib/Client/__init__.py b/src/lib/Bcfg2/Client/__init__.py index ea60a4259..6ed37b257 100644 --- a/src/lib/Client/__init__.py +++ b/src/lib/Bcfg2/Client/__init__.py @@ -1,4 +1,3 @@ """This contains all Bcfg2 Client modules""" -__revision__ = '$Revision$' __all__ = ["Frame", "Tools", "XML"] diff --git a/src/lib/Component.py b/src/lib/Bcfg2/Component.py index caea3eda9..eb9ea166a 100644 --- a/src/lib/Component.py +++ b/src/lib/Bcfg2/Component.py @@ -1,7 +1,5 @@ """Cobalt component base.""" -__revision__ = '$Revision$' - __all__ = ["Component", "exposed", "automatic", "run_component"] import inspect @@ -16,7 +14,7 @@ import Bcfg2.Logger from Bcfg2.Statistics import Statistics from Bcfg2.SSLServer import XMLRPCServer # Compatibility import -from Bcfg2.Bcfg2Py3k import xmlrpclib, urlparse, fprint +from Bcfg2.Bcfg2Py3k import xmlrpclib, urlparse logger = logging.getLogger() @@ -57,7 +55,7 @@ def run_component(component_cls, listen_all, location, daemon, pidfile_name, os.chdir(os.sep) pidfile = open(pidfile_name or "/dev/null", "w") - fprint(os.getpid(), pidfile) + pidfile.write("%s\n" % os.getpid()) pidfile.close() component = component_cls(cfile=cfile, **cls_kwargs) diff --git a/src/lib/Logger.py b/src/lib/Bcfg2/Logger.py index e8f9ecd47..06aae615e 100644 --- a/src/lib/Logger.py +++ b/src/lib/Bcfg2/Logger.py @@ -1,5 +1,4 @@ """Bcfg2 logging support""" -__revision__ = '$Revision$' import copy import fcntl diff --git a/src/lib/Options.py b/src/lib/Bcfg2/Options.py index b55a8a55a..dc14eaf00 100644 --- a/src/lib/Options.py +++ b/src/lib/Bcfg2/Options.py @@ -1,7 +1,7 @@ """Option parsing library for utilities.""" -__revision__ = '$Revision$' import getopt +import re import os import sys import shlex @@ -135,7 +135,12 @@ class OptionSet(dict): def buildHelpMessage(self): if hasattr(self, 'hm'): return self.hm - return ' '.join([opt.buildHelpMessage() for opt in list(self.values())]) + hlist = [] # list of _non-empty_ help messages + for opt in list(self.values()): + hm = opt.buildHelpMessage() + if hm != '': + hlist.append(hm) + return ' '.join(hlist) def helpExit(self, msg='', code=1): if msg: @@ -167,8 +172,10 @@ class OptionSet(dict): val = option.value self[key] = val -list_split = lambda x:x.replace(' ','').split(',') -flist_split = lambda x:list_split(x.replace(':', '').lower()) +def list_split(c_string): + if c_string: + return re.split("\s*,\s*", c_string) + return [] def colon_split(c_string): if c_string: diff --git a/src/lib/Proxy.py b/src/lib/Bcfg2/Proxy.py index fe2b18de8..422d642db 100644 --- a/src/lib/Proxy.py +++ b/src/lib/Bcfg2/Proxy.py @@ -8,9 +8,6 @@ load_config -- read configuration files """ -__revision__ = '$Revision: $' - - import logging import re import socket @@ -315,7 +312,7 @@ class XMLRPCTransport(xmlrpclib.Transport): 408, str(err), self._extra_headers)) - + if errcode != 200: raise ProxyError(xmlrpclib.ProtocolError(host + handler, errcode, diff --git a/src/lib/SSLServer.py b/src/lib/Bcfg2/SSLServer.py index 32ab9933b..418e259cc 100644 --- a/src/lib/SSLServer.py +++ b/src/lib/Bcfg2/SSLServer.py @@ -1,7 +1,5 @@ """Bcfg2 SSL server.""" -__revision__ = '$Revision$' - __all__ = [ "SSLServer", "XMLRPCRequestHandler", "XMLRPCServer", ] diff --git a/src/lib/Server/Admin/Backup.py b/src/lib/Bcfg2/Server/Admin/Backup.py index 3744abca3..3744abca3 100644 --- a/src/lib/Server/Admin/Backup.py +++ b/src/lib/Bcfg2/Server/Admin/Backup.py diff --git a/src/lib/Server/Admin/Bundle.py b/src/lib/Bcfg2/Server/Admin/Bundle.py index 89c099602..89c099602 100644 --- a/src/lib/Server/Admin/Bundle.py +++ b/src/lib/Bcfg2/Server/Admin/Bundle.py diff --git a/src/lib/Server/Admin/Client.py b/src/lib/Bcfg2/Server/Admin/Client.py index 4d580c54c..4d580c54c 100644 --- a/src/lib/Server/Admin/Client.py +++ b/src/lib/Bcfg2/Server/Admin/Client.py diff --git a/src/lib/Server/Admin/Compare.py b/src/lib/Bcfg2/Server/Admin/Compare.py index 050dd69f8..050dd69f8 100644 --- a/src/lib/Server/Admin/Compare.py +++ b/src/lib/Bcfg2/Server/Admin/Compare.py diff --git a/src/lib/Server/Admin/Group.py b/src/lib/Bcfg2/Server/Admin/Group.py index 16a773d6f..16a773d6f 100644 --- a/src/lib/Server/Admin/Group.py +++ b/src/lib/Bcfg2/Server/Admin/Group.py diff --git a/src/lib/Server/Admin/Init.py b/src/lib/Bcfg2/Server/Admin/Init.py index 832190b7d..c1f9ed484 100644 --- a/src/lib/Server/Admin/Init.py +++ b/src/lib/Bcfg2/Server/Admin/Init.py @@ -55,6 +55,7 @@ groups = '''<Groups version='3.0'> <Group name='suse'/> <Group name='mandrake'/> <Group name='solaris'/> + <Group name='arch'/> </Groups> ''' @@ -71,7 +72,8 @@ os_list = [('Red Hat/Fedora/RHEL/RHAS/Centos', 'redhat'), ('Debian', 'debian'), ('Ubuntu', 'ubuntu'), ('Gentoo', 'gentoo'), - ('FreeBSD', 'freebsd')] + ('FreeBSD', 'freebsd'), + ('Arch', 'arch')] # Complete list of plugins plugin_list = ['Account', diff --git a/src/lib/Server/Admin/Minestruct.py b/src/lib/Bcfg2/Server/Admin/Minestruct.py index b929a9a8c..b929a9a8c 100644 --- a/src/lib/Server/Admin/Minestruct.py +++ b/src/lib/Bcfg2/Server/Admin/Minestruct.py diff --git a/src/lib/Server/Admin/Perf.py b/src/lib/Bcfg2/Server/Admin/Perf.py index 411442698..411442698 100644 --- a/src/lib/Server/Admin/Perf.py +++ b/src/lib/Bcfg2/Server/Admin/Perf.py diff --git a/src/lib/Server/Admin/Pull.py b/src/lib/Bcfg2/Server/Admin/Pull.py index daf353107..daf353107 100644 --- a/src/lib/Server/Admin/Pull.py +++ b/src/lib/Bcfg2/Server/Admin/Pull.py diff --git a/src/lib/Server/Admin/Query.py b/src/lib/Bcfg2/Server/Admin/Query.py index 3dd326645..3dd326645 100644 --- a/src/lib/Server/Admin/Query.py +++ b/src/lib/Bcfg2/Server/Admin/Query.py diff --git a/src/lib/Server/Admin/Reports.py b/src/lib/Bcfg2/Server/Admin/Reports.py index 974cdff9d..974cdff9d 100644 --- a/src/lib/Server/Admin/Reports.py +++ b/src/lib/Bcfg2/Server/Admin/Reports.py diff --git a/src/lib/Server/Admin/Snapshots.py b/src/lib/Bcfg2/Server/Admin/Snapshots.py index 8bc56f1f1..8bc56f1f1 100644 --- a/src/lib/Server/Admin/Snapshots.py +++ b/src/lib/Bcfg2/Server/Admin/Snapshots.py diff --git a/src/lib/Server/Admin/Tidy.py b/src/lib/Bcfg2/Server/Admin/Tidy.py index 82319b93e..82319b93e 100644 --- a/src/lib/Server/Admin/Tidy.py +++ b/src/lib/Bcfg2/Server/Admin/Tidy.py diff --git a/src/lib/Server/Admin/Viz.py b/src/lib/Bcfg2/Server/Admin/Viz.py index 2faa423c1..2faa423c1 100644 --- a/src/lib/Server/Admin/Viz.py +++ b/src/lib/Bcfg2/Server/Admin/Viz.py diff --git a/src/lib/Server/Admin/Xcmd.py b/src/lib/Bcfg2/Server/Admin/Xcmd.py index 140465468..140465468 100644 --- a/src/lib/Server/Admin/Xcmd.py +++ b/src/lib/Bcfg2/Server/Admin/Xcmd.py diff --git a/src/lib/Server/Admin/__init__.py b/src/lib/Bcfg2/Server/Admin/__init__.py index a9f0b8cd6..fdb9a0972 100644 --- a/src/lib/Server/Admin/__init__.py +++ b/src/lib/Bcfg2/Server/Admin/__init__.py @@ -1,5 +1,3 @@ -__revision__ = '$Revision$' - __all__ = [ 'Backup', 'Bundle', @@ -108,7 +106,7 @@ class MetadataCore(Mode): """Base class for admin-modes that handle metadata.""" __plugin_whitelist__ = None __plugin_blacklist__ = None - + def __init__(self, setup): Mode.__init__(self, setup) if self.__plugin_whitelist__ is not None: diff --git a/src/lib/Server/Core.py b/src/lib/Bcfg2/Server/Core.py index 8f02e0a40..4321c060b 100644 --- a/src/lib/Server/Core.py +++ b/src/lib/Bcfg2/Server/Core.py @@ -1,5 +1,4 @@ """Bcfg2.Server.Core provides the runtime support for Bcfg2 modules.""" -__revision__ = '$Revision$' import atexit import logging @@ -326,7 +325,7 @@ class Core(Component): except: logger.error("error in BindStructure", exc_info=1) self.validate_goals(meta, config) - + sort_xml(config, key=lambda e: e.get('name')) logger.info("Generated config for %s in %.03f seconds" % \ diff --git a/src/lib/Server/FileMonitor.py b/src/lib/Bcfg2/Server/FileMonitor.py index d6b313e6b..d6b313e6b 100644 --- a/src/lib/Server/FileMonitor.py +++ b/src/lib/Bcfg2/Server/FileMonitor.py diff --git a/src/lib/Server/Hostbase/.gitignore b/src/lib/Bcfg2/Server/Hostbase/.gitignore index 8e15b5395..8e15b5395 100644 --- a/src/lib/Server/Hostbase/.gitignore +++ b/src/lib/Bcfg2/Server/Hostbase/.gitignore diff --git a/src/lib/Server/Hostbase/__init__.py b/src/lib/Bcfg2/Server/Hostbase/__init__.py index e69de29bb..e69de29bb 100644 --- a/src/lib/Server/Hostbase/__init__.py +++ b/src/lib/Bcfg2/Server/Hostbase/__init__.py diff --git a/src/lib/Server/Hostbase/backends.py b/src/lib/Bcfg2/Server/Hostbase/backends.py index bf774f695..ecaf3c109 100644 --- a/src/lib/Server/Hostbase/backends.py +++ b/src/lib/Bcfg2/Server/Hostbase/backends.py @@ -2,8 +2,6 @@ from django.contrib.auth.models import User #from ldapauth import * from nisauth import * -__revision__ = '$Revision$' - ## class LDAPBackend(object): ## def authenticate(self,username=None,password=None): diff --git a/src/lib/Server/Hostbase/hostbase/__init__.py b/src/lib/Bcfg2/Server/Hostbase/hostbase/__init__.py index e69de29bb..e69de29bb 100644 --- a/src/lib/Server/Hostbase/hostbase/__init__.py +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/__init__.py diff --git a/src/lib/Server/Hostbase/hostbase/admin.py b/src/lib/Bcfg2/Server/Hostbase/hostbase/admin.py index 70a2233cc..70a2233cc 100644 --- a/src/lib/Server/Hostbase/hostbase/admin.py +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/admin.py diff --git a/src/lib/Server/Hostbase/hostbase/models.py b/src/lib/Bcfg2/Server/Hostbase/hostbase/models.py index 3f08a09a0..3f08a09a0 100644 --- a/src/lib/Server/Hostbase/hostbase/models.py +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/models.py diff --git a/src/lib/Server/Hostbase/hostbase/sql/zone.sql b/src/lib/Bcfg2/Server/Hostbase/hostbase/sql/zone.sql index b78187ab2..b78187ab2 100644 --- a/src/lib/Server/Hostbase/hostbase/sql/zone.sql +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/sql/zone.sql diff --git a/src/lib/Server/Hostbase/hostbase/urls.py b/src/lib/Bcfg2/Server/Hostbase/hostbase/urls.py index 0ee204abe..0ee204abe 100644 --- a/src/lib/Server/Hostbase/hostbase/urls.py +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/urls.py diff --git a/src/lib/Server/Hostbase/hostbase/views.py b/src/lib/Bcfg2/Server/Hostbase/hostbase/views.py index ff1d4710d..57ef5eff8 100644 --- a/src/lib/Server/Hostbase/hostbase/views.py +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/views.py @@ -2,8 +2,6 @@ Contains all the views associated with the hostbase app Also has does form validation """ -__revision__ = "$Revision: $" - from django.http import HttpResponse, HttpResponseRedirect from django.contrib.auth.decorators import login_required diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/base.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/base.html index 1d7c5565b..1d7c5565b 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/base.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/base.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/confirm.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/confirm.html index ca8b0cc07..ca8b0cc07 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/confirm.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/confirm.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/copy.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/copy.html index 400ef58f2..400ef58f2 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/copy.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/copy.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/dns.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/dns.html index da179e5a1..da179e5a1 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/dns.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/dns.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/dnsedit.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/dnsedit.html index 18bd7ab83..b1b71ab67 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/dnsedit.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/dnsedit.html @@ -73,7 +73,7 @@ <td> <input name="{{ name.id }}priority" type="text" size="6"> <input name="{{ name.id }}mx" type="text"></td></tr> {% endfor %} - <tr> <td> <b>name</b></td> + <tr> <td> <b>name</b></td> <td> <input name="{{ ip.0.ip_addr }}name" type="text"> <select name="{{ ip.0.ip_addr }}dns_view"> {% for choice in DNS_CHOICES %} @@ -86,7 +86,7 @@ <td> <input name="{{ ip.0.ip_addr }}priority" type="text" size="6"> <input name="{{ ip.0.ip_addr }}mx" type="text"></td></tr> <tr><td></td></tr> - <tr><td><hr></td><td><hr></td></tr> + <tr><td><hr></td><td><hr></td></tr> {% endifequal %} {% endfor %} {% endfor %} diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/edit.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/edit.html index 961c9d143..961c9d143 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/edit.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/edit.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/errors.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/errors.html index e5429b86c..e5429b86c 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/errors.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/errors.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/host.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/host.html index d6b8873bc..d6b8873bc 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/host.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/host.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/hostbase/host_confirm_delete.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/hostbase/host_confirm_delete.html index 551bf3254..b5d794b50 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/hostbase/host_confirm_delete.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/hostbase/host_confirm_delete.html @@ -24,7 +24,7 @@ <col width="150"> <col width="*"> <tr> <td> <b>hostname</b></td> - <td> {{ object.hostname }}</td></tr> + <td> {{ object.hostname }}</td></tr> <tr> <td> <b>whatami</b></td> <td> {{ object.whatami }}</td></tr> <tr> <td> <b>netgroup</b></td> diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/hostbase/log_detail.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/hostbase/log_detail.html index aa9679cbd..aa9679cbd 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/hostbase/log_detail.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/hostbase/log_detail.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/index.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/index.html index 92258b648..92258b648 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/index.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/index.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/login.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/login.html index ec24a0fc0..ec24a0fc0 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/login.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/login.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/logout.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/logout.html index 994f631a8..994f631a8 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/logout.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/logout.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/logout.tmpl b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/logout.tmpl index e71e90e76..e71e90e76 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/logout.tmpl +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/logout.tmpl diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/logviewer.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/logviewer.html index 806ccd63d..806ccd63d 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/logviewer.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/logviewer.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/navbar.tmpl b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/navbar.tmpl index 877d427d0..877d427d0 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/navbar.tmpl +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/navbar.tmpl diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/new.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/new.html index 2dcd6271f..2dcd6271f 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/new.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/new.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/remove.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/remove.html index 4329200dd..4329200dd 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/remove.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/remove.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/results.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/results.html index 45b22058d..45b22058d 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/results.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/results.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/search.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/search.html index 409d418fe..409d418fe 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/search.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/search.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/zoneedit.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/zoneedit.html index ee355ee87..ee355ee87 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/zoneedit.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/zoneedit.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/zonenew.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/zonenew.html index b59fa9e3c..b59fa9e3c 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/zonenew.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/zonenew.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/zones.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/zones.html index c773e7922..c773e7922 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/zones.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/zones.html diff --git a/src/lib/Server/Hostbase/hostbase/webtemplates/zoneview.html b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/zoneview.html index fa12e3ec5..fa12e3ec5 100644 --- a/src/lib/Server/Hostbase/hostbase/webtemplates/zoneview.html +++ b/src/lib/Bcfg2/Server/Hostbase/hostbase/webtemplates/zoneview.html diff --git a/src/lib/Server/Hostbase/ldapauth.py b/src/lib/Bcfg2/Server/Hostbase/ldapauth.py index f3db26f67..f3db26f67 100644 --- a/src/lib/Server/Hostbase/ldapauth.py +++ b/src/lib/Bcfg2/Server/Hostbase/ldapauth.py diff --git a/src/lib/Server/Hostbase/manage.py b/src/lib/Bcfg2/Server/Hostbase/manage.py index 5e78ea979..5e78ea979 100755 --- a/src/lib/Server/Hostbase/manage.py +++ b/src/lib/Bcfg2/Server/Hostbase/manage.py diff --git a/src/lib/Server/Hostbase/media/base.css b/src/lib/Bcfg2/Server/Hostbase/media/base.css index ddbf02165..ddbf02165 100644 --- a/src/lib/Server/Hostbase/media/base.css +++ b/src/lib/Bcfg2/Server/Hostbase/media/base.css diff --git a/src/lib/Server/Hostbase/media/boxypastel.css b/src/lib/Bcfg2/Server/Hostbase/media/boxypastel.css index 7ae0684ef..7ae0684ef 100644 --- a/src/lib/Server/Hostbase/media/boxypastel.css +++ b/src/lib/Bcfg2/Server/Hostbase/media/boxypastel.css diff --git a/src/lib/Server/Hostbase/media/global.css b/src/lib/Bcfg2/Server/Hostbase/media/global.css index 73451e1bc..73451e1bc 100644 --- a/src/lib/Server/Hostbase/media/global.css +++ b/src/lib/Bcfg2/Server/Hostbase/media/global.css diff --git a/src/lib/Server/Hostbase/media/layout.css b/src/lib/Bcfg2/Server/Hostbase/media/layout.css index 9085cc220..9085cc220 100644 --- a/src/lib/Server/Hostbase/media/layout.css +++ b/src/lib/Bcfg2/Server/Hostbase/media/layout.css diff --git a/src/lib/Server/Hostbase/nisauth.py b/src/lib/Bcfg2/Server/Hostbase/nisauth.py index 9c7da8c0a..ae4c6c021 100644 --- a/src/lib/Server/Hostbase/nisauth.py +++ b/src/lib/Bcfg2/Server/Hostbase/nisauth.py @@ -1,10 +1,8 @@ +"""Checks with NIS to see if the current user is in the support group""" import os import crypt, nis from Bcfg2.Server.Hostbase.settings import AUTHORIZED_GROUP -"""Checks with NIS to see if the current user is in the support group""" - -__revision__ = "$Revision: $" class NISAUTHError(Exception): """NISAUTHError is raised when somehting goes boom.""" diff --git a/src/lib/Server/Hostbase/regex.py b/src/lib/Bcfg2/Server/Hostbase/regex.py index 41cc0f6f0..41cc0f6f0 100644 --- a/src/lib/Server/Hostbase/regex.py +++ b/src/lib/Bcfg2/Server/Hostbase/regex.py diff --git a/src/lib/Server/Hostbase/settings.py b/src/lib/Bcfg2/Server/Hostbase/settings.py index 4e641f13c..4e641f13c 100644 --- a/src/lib/Server/Hostbase/settings.py +++ b/src/lib/Bcfg2/Server/Hostbase/settings.py diff --git a/src/lib/Server/Hostbase/templates/batchadd.tmpl b/src/lib/Bcfg2/Server/Hostbase/templates/batchadd.tmpl index 74ea3c047..74ea3c047 100644 --- a/src/lib/Server/Hostbase/templates/batchadd.tmpl +++ b/src/lib/Bcfg2/Server/Hostbase/templates/batchadd.tmpl diff --git a/src/lib/Server/Hostbase/templates/dhcpd.conf.head b/src/lib/Bcfg2/Server/Hostbase/templates/dhcpd.conf.head index a3d19547e..a3d19547e 100644 --- a/src/lib/Server/Hostbase/templates/dhcpd.conf.head +++ b/src/lib/Bcfg2/Server/Hostbase/templates/dhcpd.conf.head diff --git a/src/lib/Server/Hostbase/templates/dhcpd.tmpl b/src/lib/Bcfg2/Server/Hostbase/templates/dhcpd.tmpl index 757b263cd..757b263cd 100644 --- a/src/lib/Server/Hostbase/templates/dhcpd.tmpl +++ b/src/lib/Bcfg2/Server/Hostbase/templates/dhcpd.tmpl diff --git a/src/lib/Server/Hostbase/templates/hosts.tmpl b/src/lib/Bcfg2/Server/Hostbase/templates/hosts.tmpl index 251cb5a79..251cb5a79 100644 --- a/src/lib/Server/Hostbase/templates/hosts.tmpl +++ b/src/lib/Bcfg2/Server/Hostbase/templates/hosts.tmpl diff --git a/src/lib/Server/Hostbase/templates/hostsappend.tmpl b/src/lib/Bcfg2/Server/Hostbase/templates/hostsappend.tmpl index 00e0d5d04..00e0d5d04 100644 --- a/src/lib/Server/Hostbase/templates/hostsappend.tmpl +++ b/src/lib/Bcfg2/Server/Hostbase/templates/hostsappend.tmpl diff --git a/src/lib/Server/Hostbase/templates/named.tmpl b/src/lib/Bcfg2/Server/Hostbase/templates/named.tmpl index 03e054198..03e054198 100644 --- a/src/lib/Server/Hostbase/templates/named.tmpl +++ b/src/lib/Bcfg2/Server/Hostbase/templates/named.tmpl diff --git a/src/lib/Server/Hostbase/templates/namedviews.tmpl b/src/lib/Bcfg2/Server/Hostbase/templates/namedviews.tmpl index 52021620e..52021620e 100644 --- a/src/lib/Server/Hostbase/templates/namedviews.tmpl +++ b/src/lib/Bcfg2/Server/Hostbase/templates/namedviews.tmpl diff --git a/src/lib/Server/Hostbase/templates/reverseappend.tmpl b/src/lib/Bcfg2/Server/Hostbase/templates/reverseappend.tmpl index 6ed520c98..6ed520c98 100644 --- a/src/lib/Server/Hostbase/templates/reverseappend.tmpl +++ b/src/lib/Bcfg2/Server/Hostbase/templates/reverseappend.tmpl diff --git a/src/lib/Server/Hostbase/templates/reversesoa.tmpl b/src/lib/Bcfg2/Server/Hostbase/templates/reversesoa.tmpl index d142eaf7f..d142eaf7f 100644 --- a/src/lib/Server/Hostbase/templates/reversesoa.tmpl +++ b/src/lib/Bcfg2/Server/Hostbase/templates/reversesoa.tmpl diff --git a/src/lib/Server/Hostbase/templates/zone.tmpl b/src/lib/Bcfg2/Server/Hostbase/templates/zone.tmpl index aad48d179..aad48d179 100644 --- a/src/lib/Server/Hostbase/templates/zone.tmpl +++ b/src/lib/Bcfg2/Server/Hostbase/templates/zone.tmpl diff --git a/src/lib/Server/Hostbase/test/harness.py b/src/lib/Bcfg2/Server/Hostbase/test/harness.py index befcff5c0..befcff5c0 100644 --- a/src/lib/Server/Hostbase/test/harness.py +++ b/src/lib/Bcfg2/Server/Hostbase/test/harness.py diff --git a/src/lib/Server/Hostbase/test/test_environ_settings.py b/src/lib/Bcfg2/Server/Hostbase/test/test_environ_settings.py index ad35c624e..ad35c624e 100644 --- a/src/lib/Server/Hostbase/test/test_environ_settings.py +++ b/src/lib/Bcfg2/Server/Hostbase/test/test_environ_settings.py diff --git a/src/lib/Server/Hostbase/test/test_ldapauth.py b/src/lib/Bcfg2/Server/Hostbase/test/test_ldapauth.py index 7fc009ad2..7fc009ad2 100644 --- a/src/lib/Server/Hostbase/test/test_ldapauth.py +++ b/src/lib/Bcfg2/Server/Hostbase/test/test_ldapauth.py diff --git a/src/lib/Server/Hostbase/test/test_settings.py b/src/lib/Bcfg2/Server/Hostbase/test/test_settings.py index 0dfc30f38..0dfc30f38 100644 --- a/src/lib/Server/Hostbase/test/test_settings.py +++ b/src/lib/Bcfg2/Server/Hostbase/test/test_settings.py diff --git a/src/lib/Server/Hostbase/urls.py b/src/lib/Bcfg2/Server/Hostbase/urls.py index 01fe97d4f..01fe97d4f 100644 --- a/src/lib/Server/Hostbase/urls.py +++ b/src/lib/Bcfg2/Server/Hostbase/urls.py diff --git a/src/lib/Server/Lint/Bundles.py b/src/lib/Bcfg2/Server/Lint/Bundles.py index 472915cfd..e6b6307f2 100644 --- a/src/lib/Server/Lint/Bundles.py +++ b/src/lib/Bcfg2/Server/Lint/Bundles.py @@ -1,9 +1,8 @@ import lxml.etree import Bcfg2.Server.Lint - + class Bundles(Bcfg2.Server.Lint.ServerPlugin): """ Perform various bundle checks """ - def Run(self): """ run plugin """ if 'Bundler' in self.core.plugins: @@ -15,6 +14,11 @@ class Bundles(Bcfg2.Server.Lint.ServerPlugin): Bcfg2.Server.Plugins.SGenshi.SGenshiTemplateFile): self.bundle_names(bundle) + @classmethod + def Errors(cls): + return {"bundle-not-found":"error", + "inconsistent-bundle-name":"warning"} + def missing_bundles(self): """ find bundles listed in Metadata but not implemented in Bundler """ if self.files is None: @@ -41,21 +45,10 @@ class Bundles(Bcfg2.Server.Lint.ServerPlugin): except AttributeError: # genshi template xdata = lxml.etree.parse(bundle.template.filepath).getroot() - + fname = bundle.name.split('Bundler/')[1].split('.')[0] bname = xdata.get('name') if fname != bname: self.LintError("inconsistent-bundle-name", "Inconsistent bundle name: filename is %s, bundle name is %s" % (fname, bname)) - - def sgenshi_groups(self, bundle): - """ ensure that Genshi Bundles do not include <Group> tags, - which are not supported """ - xdata = lxml.etree.parse(bundle.name) - groups = [self.RenderXML(g) - for g in xdata.getroottree().findall("//Group")] - if groups: - self.LintError("group-tag-not-allowed", - "<Group> tag is not allowed in SGenshi Bundle:\n%s" % - "\n".join(groups)) diff --git a/src/lib/Server/Lint/Comments.py b/src/lib/Bcfg2/Server/Lint/Comments.py index 19fae1b08..3b9370c3b 100644 --- a/src/lib/Server/Lint/Comments.py +++ b/src/lib/Bcfg2/Server/Lint/Comments.py @@ -16,6 +16,13 @@ class Comments(Bcfg2.Server.Lint.ServerPlugin): self.check_infoxml() self.check_probes() + @classmethod + def Errors(cls): + return {"unexpanded-keywords":"warning", + "keywords-not-found":"warning", + "comments-not-found":"warning", + "broken-xinclude-chain":"warning"} + def required_keywords(self, rtype): """ given a file type, fetch the list of required VCS keywords from the bcfg2-lint config """ @@ -31,13 +38,13 @@ class Comments(Bcfg2.Server.Lint.ServerPlugin): fetch the list of required items from the bcfg2-lint config """ if itype not in self.config_cache: self.config_cache[itype] = {} - + if rtype not in self.config_cache[itype]: rv = [] global_item = "global_%ss" % itype if global_item in self.config: rv.extend(self.config[global_item].split(",")) - + item = "%s_%ss" % (rtype.lower(), itype) if item in self.config: if self.config[item]: @@ -128,7 +135,7 @@ class Comments(Bcfg2.Server.Lint.ServerPlugin): # None == found but not expanded # True == found and expanded found = dict((k, False) for k in self.required_keywords(rtype)) - + for line in lines: # we check for both '$<keyword>:' and '$<keyword>$' to see # if the keyword just hasn't been expanded @@ -155,7 +162,7 @@ class Comments(Bcfg2.Server.Lint.ServerPlugin): # next, check for required comments. found is just # boolean found = dict((k, False) for k in self.required_comments(rtype)) - + for line in lines: for (comment, status) in found.items(): if not status: diff --git a/src/lib/Bcfg2/Server/Lint/Deltas.py b/src/lib/Bcfg2/Server/Lint/Deltas.py index cf91d1d13..de2e0668f 100644 --- a/src/lib/Bcfg2/Server/Lint/Deltas.py +++ b/src/lib/Bcfg2/Server/Lint/Deltas.py @@ -10,6 +10,11 @@ class Deltas(Bcfg2.Server.Lint.ServerPlugin): for basename, entry in list(cfg.entries.items()): self.check_entry(basename, entry) + @classmethod + def Errors(cls): + return {"cat-file-used":"warning", + "diff-file-used":"warning"} + def check_entry(self, basename, entry): for fname in list(entry.entries.keys()): if self.HandlesFile(fname): diff --git a/src/lib/Server/Lint/Duplicates.py b/src/lib/Bcfg2/Server/Lint/Duplicates.py index 75f620603..ee6b7a2e6 100644 --- a/src/lib/Server/Lint/Duplicates.py +++ b/src/lib/Bcfg2/Server/Lint/Duplicates.py @@ -22,6 +22,14 @@ class Duplicates(Bcfg2.Server.Lint.ServerPlugin): if self.clients_xdata is not None: self.duplicate_clients() + @classmethod + def Errors(cls): + return {"broken-xinclude-chain":"warning", + "duplicate-client":"error", + "duplicate-group":"error", + "duplicate-package":"error", + "multiple-default-groups":"error"} + def load_xdata(self): """ attempt to load XML data for groups and clients. only actually load data if all documents reference in XIncludes can @@ -30,7 +38,7 @@ class Duplicates(Bcfg2.Server.Lint.ServerPlugin): self.groups_xdata = self.metadata.clients_xml.xdata if self.has_all_xincludes("clients.xml"): self.clients_xdata = self.metadata.clients_xml.xdata - + def duplicate_groups(self): """ find duplicate groups """ self.duplicate_entries(self.clients_xdata.xpath('//Groups/Group'), diff --git a/src/lib/Server/Lint/Genshi.py b/src/lib/Bcfg2/Server/Lint/Genshi.py index 56803246c..b6007161e 100755 --- a/src/lib/Server/Lint/Genshi.py +++ b/src/lib/Bcfg2/Server/Lint/Genshi.py @@ -1,9 +1,8 @@ import genshi.template import Bcfg2.Server.Lint - + class Genshi(Bcfg2.Server.Lint.ServerPlugin): """ Check Genshi templates for syntax errors """ - def Run(self): """ run plugin """ loader = genshi.template.TemplateLoader() @@ -12,10 +11,14 @@ class Genshi(Bcfg2.Server.Lint.ServerPlugin): self.check_files(self.core.plugins[plugin].entries, loader=loader) + @classmethod + def Errors(cls): + return {"genshi-syntax-error":"error"} + def check_files(self, entries, loader=None): if loader is None: loader = genshi.template.TemplateLoader() - + for eset in entries.values(): for fname, sdata in list(eset.entries.items()): if (self.HandlesFile(fname) and @@ -23,6 +26,7 @@ class Genshi(Bcfg2.Server.Lint.ServerPlugin): try: loader.load(sdata.name, cls=genshi.template.NewTextTemplate) - except genshi.template.TemplateSyntaxError, err: + except genshi.template.TemplateSyntaxError: + err = sys.exc_info()[1] self.LintError("genshi-syntax-error", "Genshi syntax error: %s" % err) diff --git a/src/lib/Server/Lint/GroupPatterns.py b/src/lib/Bcfg2/Server/Lint/GroupPatterns.py index b69d7a5d8..431ba4056 100644 --- a/src/lib/Server/Lint/GroupPatterns.py +++ b/src/lib/Bcfg2/Server/Lint/GroupPatterns.py @@ -1,7 +1,7 @@ import sys import Bcfg2.Server.Lint from Bcfg2.Server.Plugins.GroupPatterns import PatternMap - + class GroupPatterns(Bcfg2.Server.Lint.ServerPlugin): """ Check Genshi templates for syntax errors """ @@ -14,12 +14,16 @@ class GroupPatterns(Bcfg2.Server.Lint.ServerPlugin): self.check(entry, groups, ptype='NamePattern') self.check(entry, groups, ptype='NameRange') + @classmethod + def Errors(cls): + return {"pattern-fails-to-initialize":"error"} + def check(self, entry, groups, ptype="NamePattern"): if ptype == "NamePattern": pmap = lambda p: PatternMap(p, None, groups) else: pmap = lambda p: PatternMap(None, p, groups) - + for el in entry.findall(ptype): pat = el.text try: diff --git a/src/lib/Server/Lint/InfoXML.py b/src/lib/Bcfg2/Server/Lint/InfoXML.py index 2054e23bf..7b89e86b2 100644 --- a/src/lib/Server/Lint/InfoXML.py +++ b/src/lib/Bcfg2/Server/Lint/InfoXML.py @@ -4,7 +4,6 @@ import Bcfg2.Server.Lint class InfoXML(Bcfg2.Server.Lint.ServerPlugin): """ ensure that all config files have an info.xml file""" - def Run(self): if 'Cfg' in self.core.plugins: for filename, entryset in self.core.plugins['Cfg'].entries.items(): @@ -18,6 +17,13 @@ class InfoXML(Bcfg2.Server.Lint.ServerPlugin): self.LintError("no-infoxml", "No info.xml found for %s" % filename) + @classmethod + def Errors(cls): + return {"no-infoxml":"warning", + "paranoid-false":"warning", + "broken-xinclude-chain":"warning", + "required-infoxml-attrs-missing":"error"} + def check_infoxml(self, fname, xdata): for info in xdata.getroottree().findall("//Info"): required = [] diff --git a/src/lib/Server/Lint/MergeFiles.py b/src/lib/Bcfg2/Server/Lint/MergeFiles.py index ff6e3449a..797de6ed9 100644 --- a/src/lib/Server/Lint/MergeFiles.py +++ b/src/lib/Bcfg2/Server/Lint/MergeFiles.py @@ -6,13 +6,18 @@ import Bcfg2.Server.Lint class MergeFiles(Bcfg2.Server.Lint.ServerPlugin): """ find Probes or Cfg files with multiple similar files that might be merged into one """ - def Run(self): if 'Cfg' in self.core.plugins: self.check_cfg() if 'Probes' in self.core.plugins: self.check_probes() + @classmethod + def Errors(cls): + return {"merge-cfg":"warning", + "merge-probes":"warning"} + + def check_cfg(self): for filename, entryset in self.core.plugins['Cfg'].entries.items(): for mset in self.get_similar(entryset.entries): @@ -26,7 +31,7 @@ class MergeFiles(Bcfg2.Server.Lint.ServerPlugin): def check_probes(self): probes = self.core.plugins['Probes'].probes.entries for mset in self.get_similar(probes): - self.LintError("merge-cfg", + self.LintError("merge-probes", "The following probes are similar: %s. " "Consider merging them into a single probe." % ", ".join([p for p in mset])) @@ -66,4 +71,4 @@ class MergeFiles(Bcfg2.Server.Lint.ServerPlugin): threshold)) return rv - + diff --git a/src/lib/Server/Lint/Pkgmgr.py b/src/lib/Bcfg2/Server/Lint/Pkgmgr.py index 8f099163a..ceb46238a 100644 --- a/src/lib/Server/Lint/Pkgmgr.py +++ b/src/lib/Bcfg2/Server/Lint/Pkgmgr.py @@ -4,7 +4,6 @@ import Bcfg2.Server.Lint class Pkgmgr(Bcfg2.Server.Lint.ServerlessPlugin): """ find duplicate Pkgmgr entries with the same priority """ - def Run(self): pset = set() for pfile in glob.glob("%s/Pkgmgr/*.xml" % self.config['repo']): @@ -33,3 +32,7 @@ class Pkgmgr(Bcfg2.Server.Lint.ServerlessPlugin): (pkg.get('name'), priority, ptype)) else: pset.add(ptuple) + + @classmethod + def Errors(cls): + return {"duplicate-packages":"error"} diff --git a/src/lib/Server/Lint/RequiredAttrs.py b/src/lib/Bcfg2/Server/Lint/RequiredAttrs.py index 55206d2ba..6f76cf2db 100644 --- a/src/lib/Server/Lint/RequiredAttrs.py +++ b/src/lib/Bcfg2/Server/Lint/RequiredAttrs.py @@ -6,7 +6,6 @@ from Bcfg2.Server.Plugins.Packages import Apt, Yum class RequiredAttrs(Bcfg2.Server.Lint.ServerPlugin): """ verify attributes for configuration entries (as defined in doc/server/configurationentries) """ - def __init__(self, *args, **kwargs): Bcfg2.Server.Lint.ServerPlugin.__init__(self, *args, **kwargs) self.required_attrs = { @@ -38,6 +37,14 @@ class RequiredAttrs(Bcfg2.Server.Lint.ServerPlugin): self.check_rules() self.check_bundles() + @classmethod + def Errors(cls): + return {"unknown-entry-type":"error", + "unknown-entry-tag":"error", + "required-attrs-missing":"error", + "extra-attrs":"warning"} + + def check_packages(self): """ check package sources for Source entries with missing attrs """ if 'Packages' in self.core.plugins: diff --git a/src/lib/Bcfg2/Server/Lint/TemplateHelper.py b/src/lib/Bcfg2/Server/Lint/TemplateHelper.py new file mode 100644 index 000000000..be270a59c --- /dev/null +++ b/src/lib/Bcfg2/Server/Lint/TemplateHelper.py @@ -0,0 +1,64 @@ +import sys +import imp +import glob +import Bcfg2.Server.Lint +from Bcfg2.Server.Plugins.TemplateHelper import HelperModule + +class TemplateHelper(Bcfg2.Server.Lint.ServerlessPlugin): + """ find duplicate Pkgmgr entries with the same priority """ + def __init__(self, *args, **kwargs): + Bcfg2.Server.Lint.ServerlessPlugin.__init__(self, *args, **kwargs) + hm = HelperModule("foo.py", None, None) + self.reserved_keywords = dir(hm) + + def Run(self): + for helper in glob.glob("%s/TemplateHelper/*.py" % self.config['repo']): + if not self.HandlesFile(helper): + continue + + match = HelperModule._module_name_re.search(helper) + if match: + module_name = match.group(1) + else: + module_name = helper + + try: + module = imp.load_source(module_name, helper) + except: + err = sys.exc_info()[1] + self.LintError("templatehelper-import-error", + "Failed to import %s: %s" % + (helper, err)) + continue + + if not hasattr(module, "__export__"): + self.LintError("templatehelper-no-export", + "%s has no __export__ list" % helper) + continue + elif not isinstance(module.__export__, list): + self.LintError("templatehelper-nonlist-export", + "__export__ is not a list in %s" % helper) + continue + + for sym in module.__export__: + if not hasattr(module, sym): + self.LintError("templatehelper-nonexistent-export", + "%s: exported symbol %s does not exist" % + (helper, sym)) + elif sym in self.reserved_keywords: + self.LintError("templatehelper-reserved-export", + "%s: exported symbol %s is reserved" % + (helper, sym)) + elif sym.startswith("_"): + self.LintError("templatehelper-underscore-export", + "%s: exported symbol %s starts with underscore" % + (helper, sym)) + + @classmethod + def Errors(cls): + return {"templatehelper-import-error":"error", + "templatehelper-no-export":"error", + "templatehelper-nonlist-export":"error", + "templatehelper-nonexistent-export":"error", + "templatehelper-reserved-export":"error", + "templatehelper-underscore-export":"warning"} diff --git a/src/lib/Server/Lint/Validate.py b/src/lib/Bcfg2/Server/Lint/Validate.py index 952a65365..05fedc313 100644 --- a/src/lib/Server/Lint/Validate.py +++ b/src/lib/Bcfg2/Server/Lint/Validate.py @@ -36,7 +36,7 @@ class Validate(Bcfg2.Server.Lint.ServerlessPlugin): def Run(self): schemadir = self.config['schema'] - + for path, schemaname in self.filesets.items(): try: filelist = self.filelists[path] @@ -63,6 +63,16 @@ class Validate(Bcfg2.Server.Lint.ServerlessPlugin): self.check_properties() + @classmethod + def Errors(cls): + return {"broken-xinclude-chain":"warning", + "schema-failed-to-parse":"warning", + "properties-schema-not-found":"warning", + "xml-failed-to-parse":"error", + "xml-failed-to-read":"error", + "xml-failed-to-verify":"error", + "input-output-error":"error"} + def check_properties(self): """ check Properties files against their schemas """ for filename in self.filelists['props']: @@ -98,7 +108,7 @@ class Validate(Bcfg2.Server.Lint.ServerlessPlugin): self.LintError("xml-failed-to-read", "Failed to open file %s" % filename) return False - + if not schema.validate(datafile): cmd = ["xmllint"] if self.files is None: @@ -180,7 +190,7 @@ class Validate(Bcfg2.Server.Lint.ServerlessPlugin): included = set([ent.get('href') for ent in xdata.findall('./{http://www.w3.org/2001/XInclude}include')]) rv = [] - + while included: try: filename = included.pop() diff --git a/src/lib/Server/Lint/__init__.py b/src/lib/Bcfg2/Server/Lint/__init__.py index 4d6df8c8f..5d7dd707b 100644 --- a/src/lib/Server/Lint/__init__.py +++ b/src/lib/Bcfg2/Server/Lint/__init__.py @@ -1,5 +1,3 @@ -__revision__ = '$Revision$' - __all__ = ['Bundles', 'Comments', 'Duplicates', @@ -56,14 +54,20 @@ class Plugin (object): self.config = config self.logger = logging.getLogger('bcfg2-lint') if errorhandler is None: - self.errorHandler = ErrorHandler() + self.errorhandler = ErrorHandler() else: - self.errorHandler = errorhandler + self.errorhandler = errorhandler + self.errorhandler.RegisterErrors(self.Errors()) def Run(self): """ run the plugin. must be overloaded by child classes """ pass + @classmethod + def Errors(cls): + """ returns a dict of errors the plugin supplies. must be + overloaded by child classes """ + def HandlesFile(self, fname): """ returns true if the given file should be handled by the plugin according to the files list, false otherwise """ @@ -75,8 +79,8 @@ class Plugin (object): fname)) in self.files) def LintError(self, err, msg): - self.errorHandler.dispatch(err, msg) - + self.errorhandler.dispatch(err, msg) + def RenderXML(self, element): """render an XML element for error output -- line number prefixed, no children""" @@ -93,37 +97,6 @@ class Plugin (object): class ErrorHandler (object): - # how to handle different errors by default - _errors = {"no-infoxml":"warning", - "paranoid-false":"warning", - "bundle-not-found":"error", - "inconsistent-bundle-name":"warning", - "group-tag-not-allowed":"error", - "unexpanded-keywords":"warning", - "keywords-not-found":"warning", - "comments-not-found":"warning", - "broken-xinclude-chain":"warning", - "duplicate-client":"error", - "duplicate-group":"error", - "duplicate-package":"error", - "multiple-default-groups":"error", - "required-infoxml-attrs-missing":"error", - "unknown-entry-type":"error", - "required-attrs-missing":"error", - "extra-attrs":"warning", - "schema-failed-to-parse":"warning", - "properties-schema-not-found":"warning", - "xml-failed-to-parse":"error", - "xml-failed-to-read":"error", - "xml-failed-to-verify":"error", - "merge-cfg":"warning", - "merge-probes":"warning", - "input-output-error":"error", - "genshi-syntax-error":"error", - "pattern-fails-to-initialize":"error", - "cat-file-used":"warning", - "diff-file-used":"warning"} - def __init__(self, config=None): self.errors = 0 self.warnings = 0 @@ -149,7 +122,8 @@ class ErrorHandler (object): else: self._handlers[err] = self.debug - for err, action in self._errors.items(): + def RegisterErrors(self, errors): + for err, action in errors.items(): if err not in self._handlers: if "warn" in action: self._handlers[err] = self.warn @@ -157,7 +131,7 @@ class ErrorHandler (object): self._handlers[err] = self.error else: self._handlers[err] = self.debug - + def dispatch(self, err, msg): if err in self._handlers: self._handlers[err](msg) diff --git a/src/lib/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index 9b3c5814f..41314bbea 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -1,5 +1,4 @@ """This module provides the baseclass for Bcfg2 Server Plugins.""" -__revision__ = '$Revision$' import copy import logging @@ -71,7 +70,7 @@ class Debuggable(object): self.__class__.__name__) self.debug_flag = False self.logger = logging.getLogger(name) - + def toggle_debug(self): self.debug_flag = not self.debug_flag @@ -84,7 +83,6 @@ class Plugin(Debuggable): """This is the base class for all Bcfg2 Server plugins. Several attributes must be defined in the subclass: name : the name of the plugin - __version__ : a version string __author__ : the author/contact for the plugin Plugins can provide three basic types of functionality: @@ -93,7 +91,6 @@ class Plugin(Debuggable): - Data collection (overloading GetProbes/ReceiveData) """ name = 'Plugin' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' experimental = False deprecated = False @@ -106,14 +103,14 @@ class Plugin(Debuggable): def __init__(self, core, datastore): """Initialize the plugin. - + :param core: the Bcfg2.Server.Core initializing the plugin :param datastore: the filesystem path of Bcfg2's repository """ object.__init__(self) self.Entries = {} self.core = core - self.data = "%s/%s" % (datastore, self.name) + self.data = os.path.join(datastore, self.name) self.running = True Debuggable.__init__(self, name=self.name) @@ -365,7 +362,7 @@ class FileBacked(object): object.__init__(self) self.data = '' self.name = name - + def HandleEvent(self, event=None): """Read file upon update.""" if event and event.code2str() not in ['exists', 'changed', 'created']: @@ -400,7 +397,7 @@ class DirectoryBacked(object): :param data: the path to the data directory that will be monitored. :param fam: The FileMonitor object used to receive - notifications of changes. + notifications of changes. """ object.__init__(self) @@ -458,7 +455,7 @@ class DirectoryBacked(object): def HandleEvent(self, event): """Handle FAM/Gamin events. - + This method is invoked by FAM/Gamin when it detects a change to a filesystem object we have requsted to be monitored. @@ -594,6 +591,29 @@ class SingleXMLFileBacked(XMLFileBacked): self.fam = fam self.fam.AddMonitor(filename, self) + def _follow_xincludes(self, fname=None, xdata=None): + ''' follow xincludes, adding included files to fam and to + self.extras ''' + if xdata is None: + if fname is None: + xdata = self.xdata.getroottree() + else: + xdata = lxml.etree.parse(fname) + included = [ent.get('href') + for ent in xdata.findall('//{http://www.w3.org/2001/XInclude}include')] + for name in included: + if name not in self.extras: + if name.startswith("/"): + fpath = name + else: + fpath = os.path.join(os.path.dirname(self.name), name) + self.add_monitor(fpath, name) + self._follow_xincludes(fname=fpath) + + def add_monitor(self, fpath, fname): + self.fam.AddMonitor(fpath, self) + self.extras.append(fname) + def Index(self): """Build local data structures.""" try: @@ -603,22 +623,14 @@ class SingleXMLFileBacked(XMLFileBacked): logger.error("Failed to parse %s: %s" % (self.name, err)) raise Bcfg2.Server.Plugin.PluginInitError - included = [ent.get('href') - for ent in self.xdata.findall('./{http://www.w3.org/2001/XInclude}include')] - if included: - for name in included: - if name not in self.extras: - self.fam.AddMonitor(os.path.join(os.path.dirname(self.name), - name), - self) - self.extras.append(name) + self._follow_xincludes() + if self.extras: try: self.xdata.getroottree().xinclude() except lxml.etree.XIncludeError: err = sys.exc_info()[1] logger.error("XInclude failed on %s: %s" % (self.name, err)) - self.entries = self.xdata.getchildren() if self.__identifier__ is not None: self.label = self.xdata.attrib[self.__identifier__] @@ -627,7 +639,7 @@ class SingleXMLFileBacked(XMLFileBacked): class StructFile(XMLFileBacked): """This file contains a set of structure file formatting logic.""" __identifier__ = None - + def __init__(self, name): XMLFileBacked.__init__(self, name) @@ -660,7 +672,7 @@ class StructFile(XMLFileBacked): for child in item.iterchildren(): rv.extend(self._match(child, metadata)) return [rv] - + def Match(self, metadata): """Return matching fragments of independent.""" rv = [] @@ -834,7 +846,7 @@ class PrioDir(Plugin, Generator, XMLDirectoryBacked): attrs = self.get_attrs(entry, metadata) for key, val in list(attrs.items()): entry.attrib[key] = val - + def get_attrs(self, entry, metadata): """ get a list of attributes to add to the entry during the bind """ for src in self.entries.values(): @@ -937,7 +949,7 @@ class SpecificData(object): logger.error("Failed to read file %s" % self.name) -class EntrySet: +class EntrySet(object): """Entry sets deal with the host- and group-specific entries.""" ignore = re.compile("^(\.#.*|.*~|\\..*\\.(sw[px])|.*\\.genshi_include)$") @@ -1013,7 +1025,8 @@ class EntrySet: spec = self.specificity_from_filename(event.filename) except SpecificityError: if not self.ignore.match(event.filename): - logger.error("Could not process filename %s; ignoring" % fpath) + logger.error("Could not process filename %s; ignoring" % + fpath) return self.entries[event.filename] = self.entry_type(fpath, spec, self.encoding) @@ -1093,7 +1106,6 @@ class EntrySet: class GroupSpool(Plugin, Generator): """Unified interface for handling group-specific data (e.g. .G## files).""" name = 'GroupSpool' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' filename_pattern = "" es_child_cls = object @@ -1184,7 +1196,7 @@ class SimpleConfig(FileBacked, ConfigParser.SafeConfigParser): ''' a simple plugin config using ConfigParser ''' _required = True - + def __init__(self, plugin): filename = os.path.join(plugin.data, plugin.name.lower() + ".conf") self.plugin = plugin diff --git a/src/lib/Server/Plugins/Account.py b/src/lib/Bcfg2/Server/Plugins/Account.py index f67819b9d..f2703dccb 100644 --- a/src/lib/Server/Plugins/Account.py +++ b/src/lib/Bcfg2/Server/Plugins/Account.py @@ -1,5 +1,4 @@ """This handles authentication setup.""" -__revision__ = '$Revision$' import Bcfg2.Server.Plugin @@ -16,7 +15,6 @@ class Account(Bcfg2.Server.Plugin.Plugin, """ name = 'Account' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): diff --git a/src/lib/Server/Plugins/BB.py b/src/lib/Bcfg2/Server/Plugins/BB.py index 137142b66..c015ec47c 100644 --- a/src/lib/Server/Plugins/BB.py +++ b/src/lib/Bcfg2/Server/Plugins/BB.py @@ -62,7 +62,6 @@ class BB(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Connector): """The BB plugin maps users to machines and metadata to machines.""" name = 'BB' - version = '$Revision$' deprecated = True def __init__(self, core, datastore): diff --git a/src/lib/Server/Plugins/Base.py b/src/lib/Bcfg2/Server/Plugins/Base.py index e8d798ae4..389ca7a95 100644 --- a/src/lib/Server/Plugins/Base.py +++ b/src/lib/Bcfg2/Server/Plugins/Base.py @@ -1,5 +1,4 @@ """This module sets up a base list of configuration entries.""" -__revision__ = '$Revision$' import copy import lxml.etree @@ -18,7 +17,6 @@ class Base(Bcfg2.Server.Plugin.Plugin, needed for most actual systems. """ name = 'Base' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' __child__ = Bcfg2.Server.Plugin.StructFile deprecated = True diff --git a/src/lib/Server/Plugins/Bundler.py b/src/lib/Bcfg2/Server/Plugins/Bundler.py index a58257712..ccb99481e 100644 --- a/src/lib/Server/Plugins/Bundler.py +++ b/src/lib/Bcfg2/Server/Plugins/Bundler.py @@ -1,5 +1,4 @@ """This provides bundle clauses with translation functionality.""" -__revision__ = '$Revision$' import copy import lxml.etree @@ -35,7 +34,6 @@ class Bundler(Bcfg2.Server.Plugin.Plugin, bundle/translation scheme from Bcfg1. """ name = 'Bundler' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' patterns = re.compile('^(?P<name>.*)\.(xml|genshi)$') diff --git a/src/lib/Server/Plugins/Bzr.py b/src/lib/Bcfg2/Server/Plugins/Bzr.py index a9a5eb814..a71021cb5 100644 --- a/src/lib/Server/Plugins/Bzr.py +++ b/src/lib/Bcfg2/Server/Plugins/Bzr.py @@ -10,7 +10,6 @@ class Bzr(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Version): """Bzr is a version plugin for dealing with Bcfg2 repos.""" name = 'Bzr' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): diff --git a/src/lib/Server/Plugins/Cfg.py b/src/lib/Bcfg2/Server/Plugins/Cfg.py index 9ec39e108..81904d082 100644 --- a/src/lib/Server/Plugins/Cfg.py +++ b/src/lib/Bcfg2/Server/Plugins/Cfg.py @@ -1,5 +1,4 @@ """This module implements a config file repository.""" -__revision__ = '$Revision$' import binascii import logging @@ -64,7 +63,7 @@ def process_delta(data, delta): basefile.write(data) basefile.close() os.close(basehandle) - + cmd = ["patch", "-u", "-f", basefile.name] patch = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) stderr = patch.communicate(input=delta.data)[1] @@ -281,7 +280,6 @@ class Cfg(Bcfg2.Server.Plugin.GroupSpool, Bcfg2.Server.Plugin.PullTarget): """This generator in the configuration file repository for Bcfg2.""" name = 'Cfg' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' es_cls = CfgEntrySet es_child_cls = Bcfg2.Server.Plugin.SpecificData diff --git a/src/lib/Server/Plugins/Cvs.py b/src/lib/Bcfg2/Server/Plugins/Cvs.py index ea898c023..6ce72acd2 100644 --- a/src/lib/Server/Plugins/Cvs.py +++ b/src/lib/Bcfg2/Server/Plugins/Cvs.py @@ -10,7 +10,6 @@ class Cvs(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Version): """CVS is a version plugin for dealing with Bcfg2 repository.""" name = 'Cvs' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' experimental = True diff --git a/src/lib/Server/Plugins/DBStats.py b/src/lib/Bcfg2/Server/Plugins/DBStats.py index 8761d282d..999e078b9 100644 --- a/src/lib/Server/Plugins/DBStats.py +++ b/src/lib/Bcfg2/Server/Plugins/DBStats.py @@ -22,7 +22,6 @@ class DBStats(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.ThreadedStatistics, Bcfg2.Server.Plugin.PullSource): name = 'DBStats' - __version__ = '$Id$' def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) @@ -100,6 +99,8 @@ class DBStats(Bcfg2.Server.Plugin.Plugin, ret.append(getattr(entry.reason, "current_%s" % t)) if entry.reason.is_sensitive: raise Bcfg2.Server.Plugin.PluginExecutionError + elif len(entry.reason.unpruned) != 0: + ret.append('\n'.join(entry.reason.unpruned)) elif entry.reason.current_diff != '': if entry.reason.is_binary: ret.append(binascii.a2b_base64(entry.reason.current_diff)) diff --git a/src/lib/Server/Plugins/Darcs.py b/src/lib/Bcfg2/Server/Plugins/Darcs.py index eb34a52c4..9fb9ff4f1 100644 --- a/src/lib/Server/Plugins/Darcs.py +++ b/src/lib/Bcfg2/Server/Plugins/Darcs.py @@ -10,7 +10,6 @@ class Darcs(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Version): """Darcs is a version plugin for dealing with Bcfg2 repos.""" name = 'Darcs' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' experimental = True diff --git a/src/lib/Server/Plugins/Decisions.py b/src/lib/Bcfg2/Server/Plugins/Decisions.py index 556f75502..b432474f2 100644 --- a/src/lib/Server/Plugins/Decisions.py +++ b/src/lib/Bcfg2/Server/Plugins/Decisions.py @@ -50,7 +50,6 @@ class Decisions(DecisionSet, Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Decision): name = 'Decisions' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): diff --git a/src/lib/Server/Plugins/Defaults.py b/src/lib/Bcfg2/Server/Plugins/Defaults.py index b208c1126..718192e2a 100644 --- a/src/lib/Server/Plugins/Defaults.py +++ b/src/lib/Bcfg2/Server/Plugins/Defaults.py @@ -1,5 +1,4 @@ """This generator provides rule-based entry mappings.""" -__revision__ = '$Revision$' import re import Bcfg2.Server.Plugin @@ -9,7 +8,6 @@ class Defaults(Bcfg2.Server.Plugins.Rules.Rules, Bcfg2.Server.Plugin.StructureValidator): """Set default attributes on bound entries""" name = 'Defaults' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' # Rules is a Generator that happens to implement all of the diff --git a/src/lib/Server/Plugins/Deps.py b/src/lib/Bcfg2/Server/Plugins/Deps.py index 482d457af..9b848baae 100644 --- a/src/lib/Server/Plugins/Deps.py +++ b/src/lib/Bcfg2/Server/Plugins/Deps.py @@ -1,5 +1,4 @@ """This plugin provides automatic dependency handling.""" -__revision__ = '$Revision$' import lxml.etree @@ -45,7 +44,6 @@ class DepXMLSrc(Bcfg2.Server.Plugin.XMLSrc): class Deps(Bcfg2.Server.Plugin.PrioDir, Bcfg2.Server.Plugin.StructureValidator): name = 'Deps' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' __child__ = DepXMLSrc diff --git a/src/lib/Server/Plugins/Editor.py b/src/lib/Bcfg2/Server/Plugins/Editor.py index 76a03a325..c0d2cfbad 100644 --- a/src/lib/Server/Plugins/Editor.py +++ b/src/lib/Bcfg2/Server/Plugins/Editor.py @@ -59,7 +59,6 @@ class EditEntrySet(Bcfg2.Server.Plugin.EntrySet): class Editor(Bcfg2.Server.Plugin.GroupSpool, Bcfg2.Server.Plugin.Probing): name = 'Editor' - __version__ = '$Id$' __author__ = 'bcfg2-dev@mcs.anl.gov' filename_pattern = 'edits' es_child_cls = EditDirectives diff --git a/src/lib/Server/Plugins/FileProbes.py b/src/lib/Bcfg2/Server/Plugins/FileProbes.py index c58040b65..5beec7be0 100644 --- a/src/lib/Server/Plugins/FileProbes.py +++ b/src/lib/Bcfg2/Server/Plugins/FileProbes.py @@ -3,7 +3,6 @@ added to the specification. On subsequent runs, the file will be replaced on the client if it is missing; if it has changed on the client, it can either be updated in the specification or replaced on the client """ -__revision__ = '$Revision: 1465 $' import os import sys @@ -55,7 +54,6 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin, name = 'FileProbes' experimental = True - __version__ = '$Id$' __author__ = 'chris.a.st.pierre@gmail.com' def __init__(self, core, datastore): @@ -133,7 +131,7 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin, else: entrydata = entry.text - if create: + if create: self.logger.info("Writing new probed file %s" % fileloc) self.write_file(fileloc, contents) self.verify_file(filename, contents, metadata) @@ -193,7 +191,7 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin, except Bcfg2.Server.Plugin.PluginExecutionError: tries += 1 continue - + # get current entry data if entry.get("encoding") == "base64": entrydata = binascii.a2b_base64(entry.text) @@ -202,12 +200,12 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin, 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,7 +218,7 @@ class FileProbes(Bcfg2.Server.Plugin.Plugin, Bcfg2.Options.MDATA_PERMS.value), encoding=entry.get("encoding", Bcfg2.Options.ENCODING.value)) - + root = lxml.etree.Element("FileInfo") root.append(info) try: diff --git a/src/lib/Server/Plugins/Fossil.py b/src/lib/Bcfg2/Server/Plugins/Fossil.py index 57d427673..1b1627688 100644 --- a/src/lib/Server/Plugins/Fossil.py +++ b/src/lib/Bcfg2/Server/Plugins/Fossil.py @@ -10,7 +10,6 @@ class Fossil(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Version): """Fossil is a version plugin for dealing with Bcfg2 repos.""" name = 'Fossil' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): diff --git a/src/lib/Server/Plugins/Git.py b/src/lib/Bcfg2/Server/Plugins/Git.py index aaeac12ae..8f8ea87f1 100644 --- a/src/lib/Server/Plugins/Git.py +++ b/src/lib/Bcfg2/Server/Plugins/Git.py @@ -13,7 +13,6 @@ class Git(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Version): """Git is a version plugin for dealing with Bcfg2 repos.""" name = 'Git' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): diff --git a/src/lib/Server/Plugins/GroupPatterns.py b/src/lib/Bcfg2/Server/Plugins/GroupPatterns.py index 58b4d4afb..58b4d4afb 100644 --- a/src/lib/Server/Plugins/GroupPatterns.py +++ b/src/lib/Bcfg2/Server/Plugins/GroupPatterns.py diff --git a/src/lib/Server/Plugins/Guppy.py b/src/lib/Bcfg2/Server/Plugins/Guppy.py index b217378d6..eea92f30f 100644 --- a/src/lib/Server/Plugins/Guppy.py +++ b/src/lib/Bcfg2/Server/Plugins/Guppy.py @@ -12,7 +12,7 @@ python -c "from guppy import hpy;hpy().monitor()" For example: # python -c "from guppy import hpy;hpy().monitor()" -<Monitor> +<Monitor> *** Connection 1 opened *** <Monitor> lc CID PID ARGV @@ -21,7 +21,7 @@ CID PID ARGV Remote connection 1. To return to Monitor, type <Ctrl-C> or .<RETURN> <Annex> int Remote interactive console. To return to Annex, type '-'. ->>> hp.heap() +>>> hp.heap() ... @@ -32,7 +32,6 @@ import Bcfg2.Server.Plugin class Guppy(Bcfg2.Server.Plugin.Plugin): """Guppy is a debugging plugin to help trace memory leaks""" name = 'Guppy' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' experimental = True diff --git a/src/lib/Server/Plugins/Hg.py b/src/lib/Bcfg2/Server/Plugins/Hg.py index 70e33ef1f..0c3537613 100644 --- a/src/lib/Server/Plugins/Hg.py +++ b/src/lib/Bcfg2/Server/Plugins/Hg.py @@ -10,7 +10,6 @@ class Hg(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Version): """Mercurial is a version plugin for dealing with Bcfg2 repository.""" name = 'Mercurial' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' experimental = True diff --git a/src/lib/Server/Plugins/Hostbase.py b/src/lib/Bcfg2/Server/Plugins/Hostbase.py index 4180fd716..e9c1c1cff 100644 --- a/src/lib/Server/Plugins/Hostbase.py +++ b/src/lib/Bcfg2/Server/Plugins/Hostbase.py @@ -2,7 +2,6 @@ This file provides the Hostbase plugin. It manages dns/dhcp/nis host information """ -__revision__ = '$Revision$' import os os.environ['DJANGO_SETTINGS_MODULE'] = 'Bcfg2.Server.Hostbase.settings' @@ -23,7 +22,6 @@ class Hostbase(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Generator): """The Hostbase plugin handles host/network info.""" name = 'Hostbase' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' filepath = '/my/adm/hostbase/files/bind' diff --git a/src/lib/Server/Plugins/Ldap.py b/src/lib/Bcfg2/Server/Plugins/Ldap.py index f1e2198d2..29abf5b13 100644 --- a/src/lib/Server/Plugins/Ldap.py +++ b/src/lib/Bcfg2/Server/Plugins/Ldap.py @@ -50,7 +50,7 @@ class ConfigFile(Bcfg2.Server.Plugin.FileBacked): def Index(self): """ Reregisters the queries in the config file - + The config will take care of actually registering the queries, so we just load it once and don't keep it. """ @@ -63,24 +63,23 @@ class Ldap(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Connector): The Ldap plugin allows adding data from an LDAP server to your metadata. """ name = "Ldap" - version = "$Revision: $" experimental = True debug_flag = False - + def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) Bcfg2.Server.Plugin.Connector.__init__(self) self.config = ConfigFile(self.data + "/config.py", core.fam) - + def debug_log(self, message, flag = None): if (flag is None) and self.debug_flag or flag: self.logger.error(message) - + def get_additional_data(self, metadata): query = None try: data = {} - self.debug_log("LdapPlugin debug: found queries " + + self.debug_log("LdapPlugin debug: found queries " + str(LDAP_QUERIES)) for QueryClass in LDAP_QUERIES: query = QueryClass() @@ -95,14 +94,14 @@ class Ldap(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Connector): except Exception: if hasattr(query, "name"): Bcfg2.Server.Plugin.logger.error("LdapPlugin error: " + - "Exception during processing of query named '" + + "Exception during processing of query named '" + str(query.name) + - "', query results will be empty" + + "', query results will be empty" + " and may cause bind failures") for line in traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]): - Bcfg2.Server.Plugin.logger.error("LdapPlugin error: " + + Bcfg2.Server.Plugin.logger.error("LdapPlugin error: " + line.replace("\n", "")) return {} @@ -110,23 +109,23 @@ class LdapConnection(object): """ Connection to an LDAP server. """ - def __init__(self, host = "localhost", port = 389, + def __init__(self, host = "localhost", port = 389, binddn = None, bindpw = None): self.host = host self.port = port self.binddn = binddn self.bindpw = bindpw self.conn = None - + def __del__(self): if self.conn: self.conn.unbind() - + def init_conn(self): self.conn = ldap.initialize(self.url) if self.binddn is not None and self.bindpw is not None: self.conn.simple_bind_s(self.binddn, self.bindpw) - + def run_query(self, query): result = None for attempt in range(RETRY_COUNT + 1): @@ -148,17 +147,17 @@ class LdapConnection(object): self.conn = None time.sleep(RETRY_DELAY) return result - + @property def url(self): return "ldap://" + self.host + ":" + str(self.port) - + class LdapQuery(object): """ Query referencing an LdapConnection and providing several methods for query manipulation. """ - + name = "unknown" base = "" scope = "sub" @@ -166,10 +165,10 @@ class LdapQuery(object): attrs = None connection = None result = None - + def __unicode__(self): return "LdapQuery:" + self.name - + def is_applicable(self, metadata): """ Overrideable method to determine if the query is to be executed for @@ -177,27 +176,27 @@ class LdapQuery(object): Defaults to true. """ return True - + def prepare_query(self, metadata): """ Overrideable method to alter the query based on metadata. Defaults to doing nothing. In most cases, you will do something like - + self.filter = "(cn=" + metadata.hostname + ")" - + here. """ pass - + def process_result(self, metadata): """ Overrideable method to post-process the query result. Defaults to returning the unaltered result. """ return self.result - + def get_result(self, metadata): """ Method to handle preparing, executing and processing the query. @@ -208,7 +207,7 @@ class LdapQuery(object): self.result = self.process_result(metadata) return self.result else: - Bcfg2.Server.Plugin.logger.error("LdapPlugin error: " + + Bcfg2.Server.Plugin.logger.error("LdapPlugin error: " + "No valid connection defined for query " + str(self)) return None @@ -224,14 +223,14 @@ class LdapSubQuery(LdapQuery): Defaults to doing nothing. """ pass - + def process_result(self, metadata, **kwargs): """ Overrideable method to post-process the query result. Defaults to returning the unaltered result. """ return self.result - + def get_result(self, metadata, **kwargs): """ Method to handle preparing, executing and processing the query. @@ -241,6 +240,6 @@ class LdapSubQuery(LdapQuery): self.result = self.connection.run_query(self) return self.process_result(metadata, **kwargs) else: - Bcfg2.Server.Plugin.logger.error("LdapPlugin error: " + + Bcfg2.Server.Plugin.logger.error("LdapPlugin error: " + "No valid connection defined for query " + str(self)) return None diff --git a/src/lib/Server/Plugins/Metadata.py b/src/lib/Bcfg2/Server/Plugins/Metadata.py index cc1f78456..970126b80 100644 --- a/src/lib/Server/Plugins/Metadata.py +++ b/src/lib/Bcfg2/Server/Plugins/Metadata.py @@ -2,8 +2,6 @@ This file stores persistent metadata for the Bcfg2 Configuration Repository. """ -__revision__ = '$Revision$' - import copy import fcntl import lxml.etree @@ -38,13 +36,16 @@ class MetadataRuntimeError(Exception): pass -class XMLMetadataConfig(object): +class XMLMetadataConfig(Bcfg2.Server.Plugin.SingleXMLFileBacked): """Handles xml config files and all XInclude statements""" def __init__(self, metadata, watch_clients, basefile): + Bcfg2.Server.Plugin.SingleXMLFileBacked.__init__(self, + os.path.join(metadata.data, + basefile), + metadata.core.fam) self.metadata = metadata self.basefile = basefile self.should_monitor = watch_clients - self.extras = [] self.data = None self.basedata = None self.basedir = metadata.data @@ -64,43 +65,40 @@ class XMLMetadataConfig(object): raise MetadataRuntimeError return self.basedata - def add_monitor(self, fname): + def add_monitor(self, fpath, fname): """Add a fam monitor for an included file""" if self.should_monitor: - self.metadata.core.fam.AddMonitor("%s/%s" % (self.basedir, fname), - self.metadata) + self.metadata.core.fam.AddMonitor(fpath, self.metadata) self.extras.append(fname) def load_xml(self): """Load changes from XML""" try: - xdata = lxml.etree.parse("%s/%s" % (self.basedir, self.basefile)) + xdata = lxml.etree.parse(os.path.join(self.basedir, self.basefile)) except lxml.etree.XMLSyntaxError: - self.logger.error('Failed to parse %s' % (self.basefile)) + self.logger.error('Failed to parse %s' % self.basefile) return + self.extras = [] self.basedata = copy.copy(xdata) - included = [ent.get('href') for ent in \ - xdata.findall('./{http://www.w3.org/2001/XInclude}include')] - if included: - for name in included: - if name not in self.extras: - self.add_monitor(name) + self._follow_xincludes(xdata=xdata) + if self.extras: try: xdata.xinclude() except lxml.etree.XIncludeError: - self.logger.error("Failed to process XInclude for file %s" % self.basefile) + self.logger.error("Failed to process XInclude for file %s" % + self.basefile) self.data = xdata def write(self): """Write changes to xml back to disk.""" - self.write_xml("%s/%s" % (self.basedir, self.basefile), + self.write_xml(os.path.join(self.basedir, self.basefile), self.basedata) def write_xml(self, fname, xmltree): """Write changes to xml back to disk.""" tmpfile = "%s.new" % fname try: - datafile = open("%s" % tmpfile, 'w') + datafile = open(tmpfile, 'w') except IOError: e = sys.exc_info()[1] self.logger.error("Failed to write %s: %s" % (tmpfile, e)) @@ -116,40 +114,42 @@ class XMLMetadataConfig(object): datafile.write(newcontents) except: fcntl.lockf(fd, fcntl.LOCK_UN) - self.logger.error("Metadata: Failed to write new xml data to %s" % tmpfile, exc_info=1) - os.unlink("%s" % tmpfile) + self.logger.error("Metadata: Failed to write new xml data to %s" % + tmpfile, exc_info=1) + os.unlink(tmpfile) raise MetadataRuntimeError datafile.close() # check if clients.xml is a symlink - xmlfile = "%s" % fname - if os.path.islink(xmlfile): - xmlfile = os.readlink(xmlfile) + if os.path.islink(fname): + fname = os.readlink(fname) try: - os.rename("%s" % tmpfile, xmlfile) + os.rename(tmpfile, fname) except: self.logger.error("Metadata: Failed to rename %s" % tmpfile) raise MetadataRuntimeError def find_xml_for_xpath(self, xpath): - """Find and load xml data containing the xpath query""" + """Find and load xml file containing the xpath query""" if self.pseudo_monitor: # Reload xml if we don't have a real monitor self.load_xml() cli = self.basedata.xpath(xpath) if len(cli) > 0: - return {'filename': "%s/%s" % (self.basedir, self.basefile), + return {'filename': os.path.join(self.basedir, self.basefile), 'xmltree': self.basedata, 'xquery': cli} else: """Try to find the data in included files""" for included in self.extras: try: - xdata = lxml.etree.parse("%s/%s" % (self.basedir, included)) + xdata = lxml.etree.parse(os.path.join(self.basedir, + included)) cli = xdata.xpath(xpath) if len(cli) > 0: - return {'filename': "%s/%s" % (self.basedir, included), + return {'filename': os.path.join(self.basedir, + included), 'xmltree': xdata, 'xquery': cli} except lxml.etree.XMLSyntaxError: @@ -221,7 +221,6 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Metadata, Bcfg2.Server.Plugin.Statistics): """This class contains data for bcfg2 server metadata.""" - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' name = "Metadata" sort_order = 500 @@ -232,8 +231,8 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Statistics.__init__(self) if watch_clients: try: - core.fam.AddMonitor("%s/%s" % (self.data, "groups.xml"), self) - core.fam.AddMonitor("%s/%s" % (self.data, "clients.xml"), self) + core.fam.AddMonitor(os.path.join(self.data, "groups.xml"), self) + core.fam.AddMonitor(os.path.join(self.data, "clients.xml"), self) except: print("Unable to add file monitor for groups.xml or clients.xml") raise Bcfg2.Server.Plugin.PluginInitError @@ -274,269 +273,241 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, @classmethod def init_repo(cls, repo, groups, os_selection, clients): - path = '%s/%s' % (repo, cls.name) + path = os.path.join(repo, cls.name) os.makedirs(path) - open("%s/Metadata/groups.xml" % - repo, "w").write(groups % os_selection) - open("%s/Metadata/clients.xml" % - repo, "w").write(clients % socket.getfqdn()) + open(os.path.join(repo, "Metadata", "groups.xml"), + "w").write(groups % os_selection) + open(os.path.join(repo, "Metadata", "clients.xml"), + "w").write(clients % socket.getfqdn()) def get_groups(self): '''return groups xml tree''' - groups_tree = lxml.etree.parse(self.data + "/groups.xml") + groups_tree = lxml.etree.parse(os.path.join(self.data, "groups.xml")) root = groups_tree.getroot() return root - def search_group(self, group_name, tree): - """Find a group.""" - for node in tree.findall("//Group"): - if node.get("name") == group_name: + def _search_xdata(self, tag, name, tree, alias=False): + for node in tree.findall("//%s" % tag): + if node.get("name") == name: return node - for child in node: - if child.tag == "Alias" and child.attrib["name"] == group_name: - return node + elif alias: + for child in node: + if (child.tag == "Alias" and + child.attrib["name"] == name): + return node return None - def add_group(self, group_name, attribs): - """Add group to groups.xml.""" + def search_group(self, group_name, tree): + """Find a group.""" + return self._search_xdata("Group", group_name, tree) + + def search_bundle(self, bundle_name, tree): + """Find a bundle.""" + return self._search_xdata("Bundle", bundle_name, tree) + + def search_client(self, client_name, tree): + return self._search_xdata("Client", client_name, tree, alias=True) - node = self.search_group(group_name, self.groups_xml.xdata) + def _add_xdata(self, config, tag, name, attribs=None, alias=False): + node = self._search_xdata(tag, name, config.xdata, alias=alias) if node != None: - self.logger.error("Group \"%s\" already exists" % (group_name)) + self.logger.error("%s \"%s\" already exists" % (tag, name)) raise MetadataConsistencyError + element = lxml.etree.SubElement(config.base_xdata.getroot(), + tag, name=name) + if attribs: + for key, val in list(attribs.items()): + element.set(key, val) + config.write() - element = lxml.etree.SubElement(self.groups_xml.base_xdata.getroot(), - "Group", name=group_name) - for key, val in list(attribs.items()): - element.set(key, val) - self.groups_xml.write() + def add_group(self, group_name, attribs): + """Add group to groups.xml.""" + return self._add_xdata(self.groups_xml, "Group", group_name, + attribs=attribs) - def update_group(self, group_name, attribs): - """Update a groups attributes.""" - node = self.search_group(group_name, self.groups_xml.xdata) + def add_bundle(self, bundle_name): + """Add bundle to groups.xml.""" + return self._add_xdata(self.groups_xml, "Bundle", bundle_name) + + def add_client(self, client_name, attribs): + """Add client to clients.xml.""" + return self._add_xdata(self.clients_xml, "Client", client_name, + attribs=attribs, alias=True) + + def _update_xdata(self, config, tag, name, attribs, alias=False): + node = self._search_xdata(tag, name, config.xdata, alias=alias) if node == None: - self.logger.error("Group \"%s\" does not exist" % (group_name)) + self.logger.error("%s \"%s\" does not exist" % (tag, name)) raise MetadataConsistencyError - xdict = self.groups_xml.find_xml_for_xpath('.//Group[@name="%s"]' % (node.get('name'))) + xdict = config.find_xml_for_xpath('.//%s[@name="%s"]' % + (tag, node.get('name'))) if not xdict: - self.logger.error("Unexpected error finding group") + self.logger.error("Unexpected error finding %s \"%s\"" % + (tag, name)) raise MetadataConsistencyError - for key, val in list(attribs.items()): xdict['xquery'][0].set(key, val) - self.groups_xml.write_xml(xdict['filename'], xdict['xmltree']) + config.write_xml(xdict['filename'], xdict['xmltree']) - def remove_group(self, group_name): - """Remove a group.""" - node = self.search_group(group_name, self.groups_xml.xdata) + def update_group(self, group_name, attribs): + """Update a groups attributes.""" + return self._update_xdata(self.groups_xml, "Group", group_name, attribs) + + def update_client(self, client_name, attribs): + """Update a clients attributes.""" + return self._update_xdata(self.clients_xml, "Client", client_name, + attribs, alias=True) + + def _remove_xdata(self, config, tag, name, alias=False): + node = self._search_xdata(tag, name, config.xdata) if node == None: - self.logger.error("Group \"%s\" does not exist" % (group_name)) + self.logger.error("%s \"%s\" does not exist" % (tag, name)) raise MetadataConsistencyError - xdict = self.groups_xml.find_xml_for_xpath('.//Group[@name="%s"]' % (node.get('name'))) + xdict = config.find_xml_for_xpath('.//%s[@name="%s"]' % + (tag, node.get('name'))) if not xdict: - self.logger.error("Unexpected error finding group") + self.logger.error("Unexpected error finding %s \"%s\"" % + (tag, name)) raise MetadataConsistencyError xdict['xquery'][0].getparent().remove(xdict['xquery'][0]) self.groups_xml.write_xml(xdict['filename'], xdict['xmltree']) - def add_bundle(self, bundle_name): - """Add bundle to groups.xml.""" - tree = lxml.etree.parse(self.data + "/groups.xml") - root = tree.getroot() - element = lxml.etree.Element("Bundle", name=bundle_name) - node = self.search_group(bundle_name, tree) - if node != None: - self.logger.error("Bundle \"%s\" already exists" % (bundle_name)) - raise MetadataConsistencyError - root.append(element) - group_tree = open(self.data + "/groups.xml", "w") - fd = group_tree.fileno() - while True: - try: - fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) - except IOError: - continue - else: - break - tree.write(group_tree) - fcntl.lockf(fd, fcntl.LOCK_UN) - group_tree.close() + def remove_group(self, group_name): + """Remove a group.""" + return self._remove_xdata(self.groups_xml, "Group", group_name) def remove_bundle(self, bundle_name): """Remove a bundle.""" - tree = lxml.etree.parse(self.data + "/groups.xml") - root = tree.getroot() - node = self.search_group(bundle_name, tree) - if node == None: - self.logger.error("Bundle \"%s\" not found" % (bundle_name)) - raise MetadataConsistencyError - root.remove(node) - group_tree = open(self.data + "/groups.xml", "w") - fd = group_tree.fileno() - while True: - try: - fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) - except IOError: - continue - else: - break - tree.write(group_tree) - fcntl.lockf(fd, fcntl.LOCK_UN) - group_tree.close() - - def search_client(self, client_name, tree): - """Find a client.""" - for node in tree.findall("//Client"): - if node.get("name") == client_name: - return node - for child in node: - if child.tag == "Alias" and child.attrib["name"] == client_name: - return node - return None - - def add_client(self, client_name, attribs): - """Add client to clients.xml.""" - node = self.search_client(client_name, self.clients_xml.xdata) - if node != None: - self.logger.error("Client \"%s\" already exists" % (client_name)) - raise MetadataConsistencyError - - element = lxml.etree.SubElement(self.clients_xml.base_xdata.getroot(), - "Client", name=client_name) - for key, val in list(attribs.items()): - element.set(key, val) - self.clients_xml.write() - - def update_client(self, client_name, attribs): - """Update a clients attributes.""" - node = self.search_client(client_name, self.clients_xml.xdata) - if node == None: - self.logger.error("Client \"%s\" does not exist" % (client_name)) - raise MetadataConsistencyError - - xdict = self.clients_xml.find_xml_for_xpath('.//Client[@name="%s"]' % (node.get('name'))) - if not xdict: - self.logger.error("Unexpected error finding client") - raise MetadataConsistencyError + return self._remove_xdata(self.groups_xml, "Bundle", bundle_name) - node = xdict['xquery'][0] - [node.set(key, value) for key, value in list(attribs.items())] - self.clients_xml.write_xml(xdict['filename'], xdict['xmltree']) + def _handle_clients_xml_event(self, event): + xdata = self.clients_xml.xdata + self.clients = {} + self.aliases = {} + self.raliases = {} + self.bad_clients = {} + self.secure = [] + self.floating = [] + self.addresses = {} + self.raddresses = {} + for client in xdata.findall('.//Client'): + clname = client.get('name').lower() + if 'address' in client.attrib: + caddr = client.get('address') + if caddr in self.addresses: + self.addresses[caddr].append(clname) + else: + self.addresses[caddr] = [clname] + if clname not in self.raddresses: + self.raddresses[clname] = set() + self.raddresses[clname].add(caddr) + if 'auth' in client.attrib: + self.auth[client.get('name')] = client.get('auth', + 'cert+password') + if 'uuid' in client.attrib: + self.uuid[client.get('uuid')] = clname + if client.get('secure', 'false') == 'true': + self.secure.append(clname) + if client.get('location', 'fixed') == 'floating': + self.floating.append(clname) + if 'password' in client.attrib: + self.passwords[clname] = client.get('password') + + self.raliases[clname] = set() + for alias in client.findall('Alias'): + self.aliases.update({alias.get('name'): clname}) + self.raliases[clname].add(alias.get('name')) + if 'address' not in alias.attrib: + continue + if alias.get('address') in self.addresses: + self.addresses[alias.get('address')].append(clname) + else: + self.addresses[alias.get('address')] = [clname] + if clname not in self.raddresses: + self.raddresses[clname] = set() + self.raddresses[clname].add(alias.get('address')) + self.clients.update({clname: client.get('profile')}) + self.states['clients.xml'] = True + + def _handle_groups_xml_event(self, event): + xdata = self.groups_xml.xdata + self.public = [] + self.private = [] + self.profiles = [] + self.groups = {} + grouptmp = {} + self.categories = {} + groupseen = list() + for group in xdata.xpath('//Groups/Group'): + if group.get('name') not in groupseen: + groupseen.append(group.get('name')) + else: + self.logger.error("Metadata: Group %s defined multiply" % + group.get('name')) + grouptmp[group.get('name')] = \ + ([item.get('name') for item in group.findall('./Bundle')], + [item.get('name') for item in group.findall('./Group')]) + grouptmp[group.get('name')][1].append(group.get('name')) + if group.get('default', 'false') == 'true': + self.default = group.get('name') + if group.get('profile', 'false') == 'true': + self.profiles.append(group.get('name')) + if group.get('public', 'false') == 'true': + self.public.append(group.get('name')) + elif group.get('public', 'true') == 'false': + self.private.append(group.get('name')) + if 'category' in group.attrib: + self.categories[group.get('name')] = group.get('category') + + for group in grouptmp: + # self.groups[group] => (bundles, groups, categories) + self.groups[group] = (set(), set(), {}) + tocheck = [group] + group_cat = self.groups[group][2] + while tocheck: + now = tocheck.pop() + self.groups[group][1].add(now) + if now in grouptmp: + (bundles, groups) = grouptmp[now] + for ggg in groups: + if ggg in self.groups[group][1]: + continue + if (ggg not in self.categories or \ + self.categories[ggg] not in self.groups[group][2]): + self.groups[group][1].add(ggg) + tocheck.append(ggg) + if ggg in self.categories: + group_cat[self.categories[ggg]] = ggg + elif ggg in self.categories: + self.logger.info("Group %s: %s cat-suppressed %s" % \ + (group, + group_cat[self.categories[ggg]], + ggg)) + [self.groups[group][0].add(bund) for bund in bundles] + self.states['groups.xml'] = True def HandleEvent(self, event): """Handle update events for data files.""" if self.clients_xml.HandleEvent(event): - xdata = self.clients_xml.xdata - self.clients = {} - self.aliases = {} - self.raliases = {} - self.bad_clients = {} - self.secure = [] - self.floating = [] - self.addresses = {} - self.raddresses = {} - for client in xdata.findall('.//Client'): - clname = client.get('name').lower() - if 'address' in client.attrib: - caddr = client.get('address') - if caddr in self.addresses: - self.addresses[caddr].append(clname) - else: - self.addresses[caddr] = [clname] - if clname not in self.raddresses: - self.raddresses[clname] = set() - self.raddresses[clname].add(caddr) - if 'auth' in client.attrib: - self.auth[client.get('name')] = client.get('auth', - 'cert+password') - if 'uuid' in client.attrib: - self.uuid[client.get('uuid')] = clname - if client.get('secure', 'false') == 'true': - self.secure.append(clname) - if client.get('location', 'fixed') == 'floating': - self.floating.append(clname) - if 'password' in client.attrib: - self.passwords[clname] = client.get('password') - for alias in [alias for alias in client.findall('Alias')\ - if 'address' in alias.attrib]: - if alias.get('address') in self.addresses: - self.addresses[alias.get('address')].append(clname) - else: - self.addresses[alias.get('address')] = [clname] - if clname not in self.raddresses: - self.raddresses[clname] = set() - self.raddresses[clname].add(alias.get('address')) - self.clients.update({clname: client.get('profile')}) - [self.aliases.update({alias.get('name'): clname}) \ - for alias in client.findall('Alias')] - self.raliases[clname] = set() - [self.raliases[clname].add(alias.get('name')) for alias \ - in client.findall('Alias')] - self.states['clients.xml'] = True + self._handle_clients_xml_event(event) elif self.groups_xml.HandleEvent(event): - xdata = self.groups_xml.xdata - self.public = [] - self.private = [] - self.profiles = [] - self.groups = {} - grouptmp = {} - self.categories = {} - groupseen = list() - for group in xdata.xpath('//Groups/Group'): - if group.get('name') not in groupseen: - groupseen.append(group.get('name')) - else: - self.logger.error("Metadata: Group %s defined multiply" % (group.get('name'))) - grouptmp[group.get('name')] = tuple([[item.get('name') for item in group.findall(spec)] - for spec in ['./Bundle', './Group']]) - grouptmp[group.get('name')][1].append(group.get('name')) - if group.get('default', 'false') == 'true': - self.default = group.get('name') - if group.get('profile', 'false') == 'true': - self.profiles.append(group.get('name')) - if group.get('public', 'false') == 'true': - self.public.append(group.get('name')) - elif group.get('public', 'true') == 'false': - self.private.append(group.get('name')) - if 'category' in group.attrib: - self.categories[group.get('name')] = group.get('category') - for group in grouptmp: - # self.groups[group] => (bundles, groups, categories) - self.groups[group] = (set(), set(), {}) - tocheck = [group] - group_cat = self.groups[group][2] - while tocheck: - now = tocheck.pop() - self.groups[group][1].add(now) - if now in grouptmp: - (bundles, groups) = grouptmp[now] - for ggg in [ggg for ggg in groups if ggg not in self.groups[group][1]]: - if ggg not in self.categories or \ - self.categories[ggg] not in self.groups[group][2]: - self.groups[group][1].add(ggg) - tocheck.append(ggg) - if ggg in self.categories: - group_cat[self.categories[ggg]] = ggg - elif ggg in self.categories: - self.logger.info("Group %s: %s cat-suppressed %s" % \ - (group, - group_cat[self.categories[ggg]], - ggg)) - [self.groups[group][0].add(bund) for bund in bundles] - self.states['groups.xml'] = True + self._handle_groups_xml_event(event) + if False not in list(self.states.values()): # check that all client groups are real and complete real = list(self.groups.keys()) for client in list(self.clients.keys()): if self.clients[client] not in self.profiles: - self.logger.error("Client %s set as nonexistent or incomplete group %s" \ - % (client, self.clients[client])) - self.logger.error("Removing client mapping for %s" % (client)) + self.logger.error("Client %s set as nonexistent or " + "incomplete group %s" % + (client, self.clients[client])) + self.logger.error("Removing client mapping for %s" % client) self.bad_clients[client] = self.clients[client] del self.clients[client] for bclient in list(self.bad_clients.keys()): if self.bad_clients[bclient] in self.profiles: - self.logger.info("Restored profile mapping for client %s" % bclient) + self.logger.info("Restored profile mapping for client %s" % + bclient) self.clients[bclient] = self.bad_clients[bclient] del self.bad_clients[bclient] @@ -546,42 +517,37 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, if False in list(self.states.values()): raise MetadataRuntimeError if profile not in self.public: - self.logger.error("Failed to set client %s to private group %s" % (client, profile)) + self.logger.error("Failed to set client %s to private group %s" % + (client, profile)) raise MetadataConsistencyError if client in self.clients: - self.logger.info("Changing %s group from %s to %s" % (client, self.clients[client], profile)) - xdict = self.clients_xml.find_xml_for_xpath('.//Client[@name="%s"]' % (client)) - if not xdict: - self.logger.error("Metadata: Unable to update profile for client %s. Use of Xinclude?" % client) - raise MetadataConsistencyError - xdict['xquery'][0].set('profile', profile) - self.clients_xml.write_xml(xdict['filename'], xdict['xmltree']) + self.logger.info("Changing %s group from %s to %s" % + (client, self.clients[client], profile)) + self.update_client(client, dict(profile=profile)) else: - self.logger.info("Creating new client: %s, profile %s" % \ + self.logger.info("Creating new client: %s, profile %s" % (client, profile)) if addresspair in self.session_cache: # we are working with a uuid'd client - lxml.etree.SubElement(self.clients_xml.base_xdata.getroot(), - 'Client', - name=self.session_cache[addresspair][1], - uuid=client, profile=profile, - address=addresspair[0]) + self.add_client(self.session_cache[addresspair][1], + dict(uuid=client, profile=profile, + address=addresspair[0])) else: - lxml.etree.SubElement(self.clients_xml.base_xdata.getroot(), - 'Client', name=client, - profile=profile) + self.add_client(client, dict(profile=profile)) self.clients[client] = profile self.clients_xml.write() def resolve_client(self, addresspair, cleanup_cache=False): """Lookup address locally or in DNS to get a hostname.""" if addresspair in self.session_cache: - # client _was_ cached, so there can be some expired entries - # we need to clean them up to avoid potentially infinite memory swell + # client _was_ cached, so there can be some expired + # entries. we need to clean them up to avoid potentially + # infinite memory swell cache_ttl = 90 if cleanup_cache: - # remove entries for this client's IP address with _any_ port numbers - # - perhaps a priority queue could be faster? + # remove entries for this client's IP address with + # _any_ port numbers - perhaps a priority queue could + # be faster? curtime = time.time() for addrpair in self.session_cache.keys(): if addresspair[0] == addrpair[0]: @@ -589,13 +555,18 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, if curtime - stamp > cache_ttl: del self.session_cache[addrpair] # return the cached data - (stamp, uuid) = self.session_cache[addresspair] - if time.time() - stamp < cache_ttl: - return self.session_cache[addresspair][1] + try: + (stamp, uuid) = self.session_cache[addresspair] + if time.time() - stamp < cache_ttl: + return self.session_cache[addresspair][1] + except KeyError: + # we cleaned all cached data for this client in cleanup_cache + pass address = addresspair[0] if address in self.addresses: if len(self.addresses[address]) != 1: - self.logger.error("Address %s has multiple reverse assignments; a uuid must be used" % (address)) + self.logger.error("Address %s has multiple reverse assignments; " + "a uuid must be used" % (address)) raise MetadataConsistencyError return self.addresses[address][0] try: @@ -620,7 +591,8 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, (bundles, groups, categories) = self.groups[profile] else: if self.default == None: - self.logger.error("Cannot set group for client %s; no default group set" % (client)) + self.logger.error("Cannot set group for client %s; " + "no default group set" % client) raise MetadataConsistencyError self.set_profile(client, self.default, (None, None)) profile = self.default @@ -635,7 +607,8 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, password = self.passwords[client] else: password = None - uuids = [item for item, value in list(self.uuid.items()) if value == client] + uuids = [item for item, value in list(self.uuid.items()) + if value == client] if uuids: uuid = uuids[0] else: @@ -649,7 +622,8 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, [newgroups.add(g) for g in ngroups if g not in newgroups] newcategories.update(ncategories) return ClientMetadata(client, profile, newgroups, newbundles, aliases, - addresses, newcategories, uuid, password, self.query) + addresses, newcategories, uuid, password, + self.query) def get_all_group_names(self): all_groups = set() @@ -673,22 +647,27 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, def merge_additional_groups(self, imd, groups): for group in groups: - if group in self.categories and \ - self.categories[group] in imd.categories: + if (group in self.categories and + self.categories[group] in imd.categories): continue - nb, ng, _ = self.groups.get(group, (list(), [group], dict())) - for b in nb: - if b not in imd.bundles: - imd.bundles.add(b) - for g in ng: - if g not in imd.groups: - if g in self.categories and \ - self.categories[g] in imd.categories: + newbundles, newgroups, _ = self.groups.get(group, + (list(), + [group], + dict())) + for newbundle in newbundles: + if newbundle not in imd.bundles: + imd.bundles.add(newbundle) + for newgroup in newgroups: + if newgroup not in imd.groups: + if (newgroup in self.categories and + self.categories[newgroup] in imd.categories): continue - if g in self.private: - self.logger.error("Refusing to add dynamic membership in private group %s for client %s" % (g, imd.hostname)) + if newgroup in self.private: + self.logger.error("Refusing to add dynamic membership " + "in private group %s for client %s" % + (newgroup, imd.hostname)) continue - imd.groups.add(g) + imd.groups.add(newgroup) def merge_additional_data(self, imd, source, data): if not hasattr(imd, source): @@ -703,18 +682,19 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, return True if address in self.addresses: if client in self.addresses[address]: - self.debug_log("Client %s matches address %s" % (client, address)) + self.debug_log("Client %s matches address %s" % + (client, address)) return True else: - self.logger.error("Got request for non-float client %s from %s" \ - % (client, address)) + self.logger.error("Got request for non-float client %s from %s" % + (client, address)) return False resolved = self.resolve_client(addresspair) if resolved.lower() == client.lower(): return True else: - self.logger.error("Got request for %s from incorrect address %s" \ - % (client, address)) + self.logger.error("Got request for %s from incorrect address %s" % + (client, address)) self.logger.error("Resolved to %s" % resolved) return False @@ -732,7 +712,8 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, try: client = self.resolve_client(address) except MetadataConsistencyError: - self.logger.error("Client %s failed to resolve; metadata problem" % (address[0])) + self.logger.error("Client %s failed to resolve; metadata problem" + % address[0]) return False else: id_method = 'uuid' @@ -764,10 +745,12 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, if client not in self.passwords: if client in self.secure: - self.logger.error("Client %s in secure mode but has no password" % (address[0])) + self.logger.error("Client %s in secure mode but has no password" + % address[0]) return False if password != self.password: - self.logger.error("Client %s used incorrect global password" % (address[0])) + self.logger.error("Client %s used incorrect global password" % + address[0]) return False if client not in self.secure: if client in self.passwords: @@ -775,14 +758,14 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, else: plist = [self.password] if password not in plist: - self.logger.error("Client %s failed to use either allowed password" % \ - (address[0])) + self.logger.error("Client %s failed to use either allowed " + "password" % address[0]) return False else: # client in secure mode and has a client password if password != self.passwords[client]: - self.logger.error("Client %s failed to use client password in secure mode" % \ - (address[0])) + self.logger.error("Client %s failed to use client password in " + "secure mode" % address[0]) return False # populate the session cache if user.decode('utf-8') != 'root': @@ -793,13 +776,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, """Hook into statistics interface to toggle clients in bootstrap mode.""" client = meta.hostname if client in self.auth and self.auth[client] == 'bootstrap': - self.logger.info("Asserting client %s auth mode to cert" % client) - xdict = self.clients_xml.find_xml_for_xpath('.//Client[@name="%s"]' % (client)) - if not xdict: - self.logger.error("Metadata: Unable to update profile for client %s. Use of Xinclude?" % client) - raise MetadataConsistencyError - xdict['xquery'][0].set('auth', 'cert') - self.clients_xml.write_xml(xdict['filename'], xdict['xmltree']) + self.update_client(client, dict(auth='cert')) def viz(self, hosts, bundles, key, only_client, colors): """Admin mode viz support.""" @@ -814,8 +791,8 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, def include_group(group): return not only_client or group in clientmeta.groups - - groups_tree = lxml.etree.parse(self.data + "/groups.xml") + + groups_tree = lxml.etree.parse(os.path.join(self.data, "groups.xml")) try: groups_tree.xinclude() except lxml.etree.XIncludeError: @@ -823,7 +800,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, (dest, sys.exc_info()[1])) groups = groups_tree.getroot() categories = {'default': 'grey83'} - viz_str = "" + viz_str = [] egroups = groups.findall("Group") + groups.findall('.//Groups/Group') for group in egroups: if not group.get('category') in categories: @@ -843,10 +820,10 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, instances[profile] = [client] for profile, clist in list(instances.items()): clist.sort() - viz_str += '''\t"%s-instances" [ label="%s", shape="record" ];\n''' \ - % (profile, '|'.join(clist)) - viz_str += '''\t"%s-instances" -> "group-%s";\n''' \ - % (profile, profile) + viz_str.append('"%s-instances" [ label="%s", shape="record" ];' % + (profile, '|'.join(clist))) + viz_str.append('"%s-instances" -> "group-%s";' % + (profile, profile)) if bundles: bundles = [] [bundles.append(bund.get('name')) \ @@ -855,8 +832,8 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, and include_bundle(bund.get('name'))] bundles.sort() for bundle in bundles: - viz_str += '''\t"bundle-%s" [ label="%s", shape="septagon"];\n''' \ - % (bundle, bundle) + viz_str.append('"bundle-%s" [ label="%s", shape="septagon"];' % + (bundle, bundle)) gseen = [] for group in egroups: if group.get('profile', 'false') == 'true': @@ -865,24 +842,25 @@ class Metadata(Bcfg2.Server.Plugin.Plugin, style = "filled" gseen.append(group.get('name')) if include_group(group.get('name')): - viz_str += '\t"group-%s" [label="%s", style="%s", fillcolor=%s];\n' % \ - (group.get('name'), group.get('name'), style, group.get('color')) + viz_str.append('"group-%s" [label="%s", style="%s", fillcolor=%s];' % + (group.get('name'), group.get('name'), style, + group.get('color'))) if bundles: for bundle in group.findall('Bundle'): - viz_str += '\t"group-%s" -> "bundle-%s";\n' % \ - (group.get('name'), bundle.get('name')) - gfmt = '\t"group-%s" [label="%s", style="filled", fillcolor="grey83"];\n' + viz_str.append('"group-%s" -> "bundle-%s";' % + (group.get('name'), bundle.get('name'))) + gfmt = '"group-%s" [label="%s", style="filled", fillcolor="grey83"];' for group in egroups: for parent in group.findall('Group'): if parent.get('name') not in gseen and include_group(parent.get('name')): - viz_str += gfmt % (parent.get('name'), parent.get('name')) + viz_str.append(gfmt % (parent.get('name'), + parent.get('name'))) gseen.append(parent.get("name")) if include_group(group.get('name')): - viz_str += '\t"group-%s" -> "group-%s" ;\n' % \ - (group.get('name'), parent.get('name')) + viz_str.append('"group-%s" -> "group-%s";' % + (group.get('name'), parent.get('name'))) if key: for category in categories: - viz_str += '''\t"''' + category + '''" [label="''' + category + \ - '''", shape="record", style="filled", fillcolor=''' + \ - categories[category] + '''];\n''' - return viz_str + viz_str.append('"%s" [label="%s", shape="record", style="filled", fillcolor="%s"];' % + (category, category, categories[category])) + return "\n".join("\t" + s for s in viz_str) diff --git a/src/lib/Server/Plugins/NagiosGen.py b/src/lib/Bcfg2/Server/Plugins/NagiosGen.py index 8a76c130d..4dbd57d16 100644 --- a/src/lib/Server/Plugins/NagiosGen.py +++ b/src/lib/Bcfg2/Server/Plugins/NagiosGen.py @@ -20,14 +20,13 @@ class NagiosGenConfig(Bcfg2.Server.Plugin.SingleXMLFileBacked, Bcfg2.Server.Plugin.SingleXMLFileBacked.__init__(self, filename, fam) Bcfg2.Server.Plugin.StructFile.__init__(self, filename) - + class NagiosGen(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Generator): """NagiosGen is a Bcfg2 plugin that dynamically generates Nagios configuration file based on Bcfg2 data. """ name = 'NagiosGen' - __version__ = '0.7' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): @@ -131,14 +130,14 @@ class NagiosGen(Bcfg2.Server.Plugin.Plugin, group_data = [] for host in host_configs: host_data.append(open(host, 'r').read()) - + for group in group_configs: group_name = re.sub("(-group.cfg|.*/(?=[^/]+))", "", group) if "\n".join(host_data).find(group_name) != -1: groupfile = open(group, 'r') group_data.append(groupfile.read()) groupfile.close() - + entry.text = "%s\n\n%s" % ("\n".join(group_data), "\n".join(host_data)) [entry.attrib.__setitem__(key, value) for (key, value) in list(self.server_attrib.items())] diff --git a/src/lib/Server/Plugins/Ohai.py b/src/lib/Bcfg2/Server/Plugins/Ohai.py index 5fff20d98..5fff20d98 100644 --- a/src/lib/Server/Plugins/Ohai.py +++ b/src/lib/Bcfg2/Server/Plugins/Ohai.py diff --git a/src/lib/Server/Plugins/Packages/Apt.py b/src/lib/Bcfg2/Server/Plugins/Packages/Apt.py index f76bf7fa1..49e9d417b 100644 --- a/src/lib/Server/Plugins/Packages/Apt.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Apt.py @@ -50,10 +50,9 @@ class AptSource(Source): def read_files(self): bdeps = dict() bprov = dict() + depfnames = ['Depends', 'Pre-Depends'] if self.recommended: - depfnames = ['Depends', 'Pre-Depends', 'Recommends'] - else: - depfnames = ['Depends', 'Pre-Depends'] + depfnames.append('Recommends') for fname in self.files: if not self.rawurl: barch = [x @@ -77,6 +76,8 @@ class AptSource(Source): pkgname = words[1].strip().rstrip() self.pkgnames.add(pkgname) bdeps[barch][pkgname] = [] + elif words[0] == 'Essential' and self.essential: + self.essentialpkgs.add(pkgname) elif words[0] in depfnames: vindex = 0 for dep in words[1].split(','): diff --git a/src/lib/Server/Plugins/Packages/Collection.py b/src/lib/Bcfg2/Server/Plugins/Packages/Collection.py index 32eeda1ec..959dac03b 100644 --- a/src/lib/Server/Plugins/Packages/Collection.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Collection.py @@ -97,6 +97,12 @@ class Collection(Bcfg2.Server.Plugin.Debuggable): return source.get_deps(self.metadata, package) return [] + def get_essential(self): + essential = set() + for source in self.sources: + essential |= source.essentialpkgs + return essential + def get_provides(self, package): for source in self.sources: providers = source.get_provides(self.metadata, package) @@ -295,7 +301,7 @@ def factory(metadata, sources, basepath, debug=False): # if sources.xml has not received a FAM event yet, defer; # instantiate a dummy Collection object return Collection(metadata, [], basepath) - + sclasses = set() relevant = list() diff --git a/src/lib/Server/Plugins/Packages/Pac.py b/src/lib/Bcfg2/Server/Plugins/Packages/Pac.py index 9db6b0535..99a090739 100644 --- a/src/lib/Server/Plugins/Packages/Pac.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Pac.py @@ -6,7 +6,7 @@ from Bcfg2.Server.Plugins.Packages.Source import Source class PacCollection(Collection): def get_group(self, group): - self.logger.warning("Packages: Package groups are not supported by APT") + self.logger.warning("Packages: Package groups are not supported by Pacman") return [] class PacSource(Source): @@ -51,10 +51,9 @@ class PacSource(Source): bdeps = dict() bprov = dict() + depfnames = ['Depends', 'Pre-Depends'] if self.recommended: - depfnames = ['Depends', 'Pre-Depends', 'Recommends'] - else: - depfnames = ['Depends', 'Pre-Depends'] + depfnames.append('Recommends') for fname in self.files: if not self.rawurl: @@ -63,7 +62,7 @@ class PacSource(Source): # RawURL entries assume that they only have one <Arch></Arch> # element and that it is the architecture of the source. barch = self.arches[0] - + if barch not in bdeps: bdeps[barch] = dict() bprov[barch] = dict() diff --git a/src/lib/Server/Plugins/Packages/PackagesConfig.py b/src/lib/Bcfg2/Server/Plugins/Packages/PackagesConfig.py index 7950f15e6..3846c06ce 100644 --- a/src/lib/Server/Plugins/Packages/PackagesConfig.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/PackagesConfig.py @@ -2,7 +2,7 @@ import Bcfg2.Server.Plugin class PackagesConfig(Bcfg2.Server.Plugin.SimpleConfig): _required = False - + def Index(self): """ Build local data structures """ Bcfg2.Server.Plugin.SimpleConfig.Index(self) diff --git a/src/lib/Server/Plugins/Packages/PackagesSources.py b/src/lib/Bcfg2/Server/Plugins/Packages/PackagesSources.py index e03303d30..a966268c0 100644 --- a/src/lib/Server/Plugins/Packages/PackagesSources.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/PackagesSources.py @@ -8,7 +8,7 @@ class PackagesSources(Bcfg2.Server.Plugin.SingleXMLFileBacked, Bcfg2.Server.Plugin.StructFile, Bcfg2.Server.Plugin.Debuggable): __identifier__ = None - + def __init__(self, filename, cachepath, fam, packages, config): Bcfg2.Server.Plugin.Debuggable.__init__(self) try: @@ -43,8 +43,18 @@ class PackagesSources(Bcfg2.Server.Plugin.SingleXMLFileBacked, def HandleEvent(self, event=None): Bcfg2.Server.Plugin.SingleXMLFileBacked.HandleEvent(self, event=event) - if event.filename != self.name: - self.parsed.add(os.path.basename(event.filename)) + if event and event.filename != self.name: + for fname in self.extras: + fpath = None + if fname.startswith("/"): + fpath = os.path.abspath(fname) + else: + fpath = \ + os.path.abspath(os.path.join(os.path.dirname(self.name), + fname)) + if fpath == os.path.abspath(event.filename): + self.parsed.add(fname) + break if self.config.loaded and self.loaded: self.logger.info("Reloading Packages plugin") diff --git a/src/lib/Server/Plugins/Packages/Source.py b/src/lib/Bcfg2/Server/Plugins/Packages/Source.py index 5b0aa4213..ada04c067 100644 --- a/src/lib/Server/Plugins/Packages/Source.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Source.py @@ -41,6 +41,7 @@ class Source(Bcfg2.Server.Plugin.Debuggable): self.basepath = basepath self.xsource = xsource self.config = config + self.essentialpkgs = set() try: self.version = xsource.find('Version').text @@ -54,8 +55,9 @@ class Source(Bcfg2.Server.Plugin.Debuggable): self.gpgkeys = [el.text for el in xsource.findall("GPGKey")] + self.essential = xsource.get('essential', 'true').lower() == 'true' self.recommended = xsource.get('recommended', 'false').lower() == 'true' - + self.rawurl = xsource.get('rawurl', '') if self.rawurl and not self.rawurl.endswith("/"): self.rawurl += "/" @@ -112,7 +114,7 @@ class Source(Bcfg2.Server.Plugin.Debuggable): if os.path.exists(self.cachefile): try: self.load_state() - should_read = False + should_read = False except: self.logger.error("Packages: Cachefile %s load failed; " "falling back to file read" % self.cachefile) diff --git a/src/lib/Server/Plugins/Packages/Yum.py b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py index be5a68aa1..941203db3 100644 --- a/src/lib/Server/Plugins/Packages/Yum.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/Yum.py @@ -72,7 +72,7 @@ def _setup_pulp(config): PULPCONFIG = ConsumerConfig() serveropts = PULPCONFIG.server - + PULPSERVER = server.PulpServer(serveropts['host'], int(serveropts['port']), serveropts['scheme'], @@ -86,7 +86,7 @@ class YumCollection(Collection): # options that are included in the [yum] section but that should # not be included in the temporary yum.conf we write out option_blacklist = ["use_yum_libraries", "helper"] - + def __init__(self, metadata, sources, basepath, debug=False): Collection.__init__(self, metadata, sources, basepath, debug=debug) self.keypath = os.path.join(self.basepath, "keys") @@ -101,7 +101,7 @@ class YumCollection(Collection): "cache-%s" % self.cachekey) if not os.path.exists(self.cachefile): os.mkdir(self.cachefile) - + self.configdir = os.path.join(self.basepath, "yum") if not os.path.exists(self.configdir): os.mkdir(self.configdir) @@ -133,7 +133,7 @@ class YumCollection(Collection): if not os.path.exists(self.cfgfile): yumconf = self.get_config(raw=True) yumconf.add_section("main") - + mainopts = dict(cachedir=self.cachefile, keepcache="0", sslverify="0", @@ -173,7 +173,7 @@ class YumCollection(Collection): else: rid = 1 reponame = "%s-%d" % (basereponame, rid) - + config.set(reponame, "name", reponame) config.set(reponame, "baseurl", url_map['url']) config.set(reponame, "enabled", "1") @@ -233,7 +233,7 @@ class YumCollection(Collection): remotekey = os.path.join(keydir, os.path.basename(key)) localkey = os.path.join(self.keypath, os.path.basename(key)) kdata = open(localkey).read() - + # copy the key to the client keypath = lxml.etree.Element("BoundPath", name=remotekey, encoding='ascii', @@ -299,12 +299,12 @@ class YumCollection(Collection): # include gpg key data if not has_yum: return - + try: kinfo = yum.misc.getgpgkeyinfo(keydata) version = yum.misc.keyIdToRPMVer(kinfo['keyid']) release = yum.misc.keyIdToRPMVer(kinfo['timestamp']) - + lxml.etree.SubElement(keyentry, 'Instance', version=version, release=release, @@ -384,7 +384,7 @@ class YumCollection(Collection): unknown = set([str(p) for p in result['unknown']]) self.filter_unknown(unknown) - + return packages, unknown def call_helper(self, command, input=None): @@ -410,7 +410,7 @@ class YumCollection(Collection): self.logger.error("Packages: Failed to execute %s: %s" % (" ".join(cmd), err)) return None - + if input: idata = json.dumps(input) (stdout, stderr) = helper.communicate(idata) @@ -442,7 +442,7 @@ class YumCollection(Collection): os.unlink(self.cfgfile) self.write_config() - + if force_update: self.call_helper("clean") @@ -456,7 +456,7 @@ class YumSource(Source): self.pulp_id = None if has_pulp and xsource.get("pulp_id"): self.pulp_id = xsource.get("pulp_id") - + _setup_pulp(self.config) repoapi = RepositoryAPI() try: @@ -484,7 +484,7 @@ class YumSource(Source): self.rawurl = "%s/%s" % (PULPCONFIG.cds['baseurl'], self.repo['relative_path']) self.arches = [self.repo['arch']] - + if not self.rawurl: self.baseurl = self.url + "%(version)s/%(component)s/%(arch)s/" else: @@ -508,7 +508,7 @@ class YumSource(Source): cPickle.dump((self.packages, self.deps, self.provides, self.filemap, self.url_map), cache, 2) cache.close() - + def load_state(self): if not self.use_yum: @@ -524,7 +524,7 @@ class YumSource(Source): usettings = [{'version':self.version, 'component':comp, 'arch':arch} for comp in self.components] - else: # rawurl given + else: # rawurl given usettings = [{'version':self.version, 'component':None, 'arch':arch}] @@ -542,7 +542,7 @@ class YumSource(Source): def _get_urls_from_repodata(self, url, arch): if self.use_yum: return [url] - + rmdurl = '%srepodata/repomd.xml' % url try: repomd = fetch_url(rmdurl) @@ -659,7 +659,7 @@ class YumSource(Source): def get_vpkgs(self, metadata): if self.use_yum: return dict() - + rv = Source.get_vpkgs(self, metadata) for arch, fmdata in list(self.filemap.items()): if arch not in metadata.groups and arch != 'global': diff --git a/src/lib/Server/Plugins/Packages/__init__.py b/src/lib/Bcfg2/Server/Plugins/Packages/__init__.py index da5832e90..e4793a28d 100644 --- a/src/lib/Server/Plugins/Packages/__init__.py +++ b/src/lib/Bcfg2/Server/Plugins/Packages/__init__.py @@ -88,6 +88,9 @@ class Packages(Bcfg2.Server.Plugin.Plugin, if entry.tag == 'Package': collection = self._get_collection(metadata) entry.set('version', 'auto') + entry.set('version', self.config.get("global", + "version", + default="auto")) entry.set('type', collection.ptype) elif entry.tag == 'Path': if (entry.get("name") == self.config.get("global", "yum_config", @@ -143,6 +146,8 @@ class Packages(Bcfg2.Server.Plugin.Plugin, initial = set() # base is the set of initial packages with groups expanded base = set() + # essential pkgs are those marked as such by the distribution + essential = collection.get_essential() to_remove = [] for struct in structures: for pkg in struct.xpath('//Package | //BoundPackage'): @@ -164,7 +169,7 @@ class Packages(Bcfg2.Server.Plugin.Plugin, else: self.logger.error("Packages: Malformed Package: %s" % lxml.etree.tostring(pkg)) - base.update(initial) + base.update(initial | essential) for el in to_remove: el.getparent().remove(el) @@ -178,8 +183,9 @@ class Packages(Bcfg2.Server.Plugin.Plugin, newpkgs.sort() for pkg in newpkgs: lxml.etree.SubElement(independent, 'BoundPackage', name=pkg, - version='auto', type=collection.ptype, - origin='Packages') + version=self.config.get("global", "version", + default="auto"), + type=collection.ptype, origin='Packages') def Refresh(self): '''Packages.Refresh() => True|False\nReload configuration diff --git a/src/lib/Server/Plugins/Pkgmgr.py b/src/lib/Bcfg2/Server/Plugins/Pkgmgr.py index bc11bfdcf..e9254cdcc 100644 --- a/src/lib/Server/Plugins/Pkgmgr.py +++ b/src/lib/Bcfg2/Server/Plugins/Pkgmgr.py @@ -1,5 +1,4 @@ '''This module implements a package management scheme for all images''' -__revision__ = '$Revision$' import logging import re @@ -135,7 +134,6 @@ class PkgSrc(Bcfg2.Server.Plugin.XMLSrc): class Pkgmgr(Bcfg2.Server.Plugin.PrioDir): """This is a generator that handles package assignments.""" name = 'Pkgmgr' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' __child__ = PkgSrc __element__ = 'Package' diff --git a/src/lib/Server/Plugins/Probes.py b/src/lib/Bcfg2/Server/Plugins/Probes.py index ae1ed4c2b..af908eee8 100644 --- a/src/lib/Server/Plugins/Probes.py +++ b/src/lib/Bcfg2/Server/Plugins/Probes.py @@ -51,10 +51,10 @@ class ProbeData(object): def __str__(self): return str(self.data) - + def __repr__(self): return repr(self.data) - + def __getattr__(self, name): """ make ProbeData act like a str object """ return getattr(self.data, name) @@ -181,7 +181,6 @@ class Probes(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Connector): """A plugin to gather information from a client machine.""" name = 'Probes' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): diff --git a/src/lib/Server/Plugins/Properties.py b/src/lib/Bcfg2/Server/Plugins/Properties.py index 76945b3a0..680881858 100644 --- a/src/lib/Server/Plugins/Properties.py +++ b/src/lib/Bcfg2/Server/Plugins/Properties.py @@ -60,7 +60,6 @@ class Properties(Bcfg2.Server.Plugin.Plugin, files into client metadata instances. """ name = 'Properties' - version = '$Revision$' def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) diff --git a/src/lib/Server/Plugins/Rules.py b/src/lib/Bcfg2/Server/Plugins/Rules.py index c66276179..b80ef351a 100644 --- a/src/lib/Server/Plugins/Rules.py +++ b/src/lib/Bcfg2/Server/Plugins/Rules.py @@ -1,5 +1,4 @@ """This generator provides rule-based entry mappings.""" -__revision__ = '$Revision$' import re import Bcfg2.Server.Plugin @@ -10,7 +9,6 @@ class RulesConfig(Bcfg2.Server.Plugin.SimpleConfig): class Rules(Bcfg2.Server.Plugin.PrioDir): """This is a generator that handles service assignments.""" name = 'Rules' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): @@ -52,6 +50,6 @@ class Rules(Bcfg2.Server.Plugin.PrioDir): if self._regex_cache[rule].match(entry.get('name')): return True return False - + def _regex_enabled(self): return self.config.getboolean("rules", "regex", default=False) diff --git a/src/lib/Server/Plugins/SGenshi.py b/src/lib/Bcfg2/Server/Plugins/SGenshi.py index f6a98c141..0ba08125e 100644 --- a/src/lib/Server/Plugins/SGenshi.py +++ b/src/lib/Bcfg2/Server/Plugins/SGenshi.py @@ -1,5 +1,4 @@ '''This module implements a templating generator based on Genshi''' -__revision__ = '$Revision$' import genshi.input import genshi.template @@ -84,7 +83,6 @@ class SGenshi(SGenshiEntrySet, Bcfg2.Server.Plugin.Structure): """The SGenshi plugin provides templated structures.""" name = 'SGenshi' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' deprecated = True diff --git a/src/lib/Server/Plugins/SSHbase.py b/src/lib/Bcfg2/Server/Plugins/SSHbase.py index eb91bea39..ac281ad1a 100644 --- a/src/lib/Server/Plugins/SSHbase.py +++ b/src/lib/Bcfg2/Server/Plugins/SSHbase.py @@ -1,5 +1,4 @@ '''This module manages ssh key files for bcfg2''' -__revision__ = '$Revision$' import binascii import re @@ -23,7 +22,7 @@ class KeyData(Bcfg2.Server.Plugin.SpecificData): Bcfg2.Server.Plugin.SpecificData.__init__(self, name, specific, encoding) self.encoding = encoding - + def bind_entry(self, entry, metadata): entry.set('type', 'file') if entry.get('encoding') == 'base64': @@ -99,7 +98,6 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin, """ name = 'SSHbase' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' keypatterns = ["ssh_host_dsa_key", @@ -148,7 +146,7 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin, for s in list(self.static.values())] mquery = self.core.metadata.query - + # build hostname cache names = dict() for cmeta in mquery.all(): @@ -206,13 +204,13 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin, # have no clients yet. don't warn about # this. continue - + if key not in self.badnames: self.badnames[key] = True self.logger.info("Ignoring key for unknown %s %s" % (ktype, key)) continue - + skn.append("%s %s" % (','.join(hostnames), entry.data.decode().rstrip())) @@ -230,7 +228,7 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin, action = event.code2str() if action == "endExist" or event.filename == self.data: return - + for entry in list(self.entries.values()): if entry.specific.match(event.filename): entry.handle_event(event) @@ -371,7 +369,7 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin, else: self.logger.error("Unknown key filename: %s" % filename) return - + fileloc = "%s/%s" % (self.data, hostkey) publoc = self.data + '/' + ".".join([hostkey.split('.')[0], 'pub', "H_%s" % client]) diff --git a/src/lib/Server/Plugins/SSLCA.py b/src/lib/Bcfg2/Server/Plugins/SSLCA.py index 7b4a08ae1..0072dc62d 100644 --- a/src/lib/Server/Plugins/SSLCA.py +++ b/src/lib/Bcfg2/Server/Plugins/SSLCA.py @@ -16,7 +16,6 @@ class SSLCA(Bcfg2.Server.Plugin.GroupSpool): management of ssl certificates and their keys. """ name = 'SSLCA' - __version__ = '$Id:$' __author__ = 'g.hagger@gmail.com' __child__ = Bcfg2.Server.Plugin.FileBacked key_specs = {} diff --git a/src/lib/Server/Plugins/Snapshots.py b/src/lib/Bcfg2/Server/Plugins/Snapshots.py index aeb3b9f74..aeb3b9f74 100644 --- a/src/lib/Server/Plugins/Snapshots.py +++ b/src/lib/Bcfg2/Server/Plugins/Snapshots.py diff --git a/src/lib/Server/Plugins/Statistics.py b/src/lib/Bcfg2/Server/Plugins/Statistics.py index 9dbbeec28..265ef95a8 100644 --- a/src/lib/Server/Plugins/Statistics.py +++ b/src/lib/Bcfg2/Server/Plugins/Statistics.py @@ -1,5 +1,4 @@ '''This file manages the statistics collected by the BCFG2 Server''' -__revision__ = '$Revision$' import binascii import copy @@ -117,7 +116,6 @@ class Statistics(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.ThreadedStatistics, Bcfg2.Server.Plugin.PullSource): name = 'Statistics' - __version__ = '$Id$' def __init__(self, core, datastore): Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) diff --git a/src/lib/Server/Plugins/Svcmgr.py b/src/lib/Bcfg2/Server/Plugins/Svcmgr.py index 6d25c1a6d..f4232ad5c 100644 --- a/src/lib/Server/Plugins/Svcmgr.py +++ b/src/lib/Bcfg2/Server/Plugins/Svcmgr.py @@ -1,5 +1,4 @@ """This generator provides service mappings.""" -__revision__ = '$Revision$' import Bcfg2.Server.Plugin @@ -7,6 +6,5 @@ import Bcfg2.Server.Plugin class Svcmgr(Bcfg2.Server.Plugin.PrioDir): """This is a generator that handles service assignments.""" name = 'Svcmgr' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' deprecated = True diff --git a/src/lib/Server/Plugins/Svn.py b/src/lib/Bcfg2/Server/Plugins/Svn.py index 9fd6f1051..ae43388ea 100644 --- a/src/lib/Server/Plugins/Svn.py +++ b/src/lib/Bcfg2/Server/Plugins/Svn.py @@ -12,7 +12,6 @@ class Svn(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Version): """Svn is a version plugin for dealing with Bcfg2 repos.""" name = 'Svn' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): diff --git a/src/lib/Server/Plugins/Svn2.py b/src/lib/Bcfg2/Server/Plugins/Svn2.py index b8a8e6b7e..e4df9574f 100644 --- a/src/lib/Server/Plugins/Svn2.py +++ b/src/lib/Bcfg2/Server/Plugins/Svn2.py @@ -9,7 +9,6 @@ class Svn2(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Version): """Svn is a version plugin for dealing with Bcfg2 repos.""" name = 'Svn2' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' conflicts = ['Svn'] @@ -72,7 +71,8 @@ class Svn2(Bcfg2.Server.Plugin.Plugin, self.revision = self.client.update(self.datastore, recurse=True)[0] self.logger.info("Svn2: Commited changes. At %s" % self.revision.number) - except Exception, err: + except Exception: + err = sys.exc_info()[1] # try to be smart about the error we got back details = None if "callback_ssl_server_trust_prompt" in str(err): diff --git a/src/lib/Server/Plugins/TCheetah.py b/src/lib/Bcfg2/Server/Plugins/TCheetah.py index 49be88881..8879fdef1 100644 --- a/src/lib/Server/Plugins/TCheetah.py +++ b/src/lib/Bcfg2/Server/Plugins/TCheetah.py @@ -1,5 +1,4 @@ '''This module implements a templating generator based on Cheetah''' -__revision__ = '$Revision$' import binascii import logging @@ -76,7 +75,6 @@ class TemplateFile: class TCheetah(Bcfg2.Server.Plugin.GroupSpool): """The TCheetah generator implements a templating mechanism for configuration files.""" name = 'TCheetah' - __version__ = '$Id$' __author__ = 'bcfg-dev@mcs.anl.gov' filename_pattern = 'template' es_child_cls = TemplateFile diff --git a/src/lib/Server/Plugins/TGenshi.py b/src/lib/Bcfg2/Server/Plugins/TGenshi.py index 072f5cd7b..c4dd40614 100644 --- a/src/lib/Server/Plugins/TGenshi.py +++ b/src/lib/Bcfg2/Server/Plugins/TGenshi.py @@ -1,5 +1,4 @@ """This module implements a templating generator based on Genshi.""" -__revision__ = '$Revision$' import binascii import logging @@ -115,11 +114,13 @@ class TemplateFile: if entry.text == '': entry.set('empty', 'true') except TemplateError: + err = sys.exc_info()[1] logger.exception('Genshi template error') - raise Bcfg2.Server.Plugin.PluginExecutionError + raise Bcfg2.Server.Plugin.PluginExecutionError('Genshi template error: %s' % err) except AttributeError: + err = sys.exc_info()[1] logger.exception('Genshi template loading error') - raise Bcfg2.Server.Plugin.PluginExecutionError + raise Bcfg2.Server.Plugin.PluginExecutionError('Genshi template loading error: %s' % err) class TGenshi(Bcfg2.Server.Plugin.GroupSpool): @@ -129,7 +130,6 @@ class TGenshi(Bcfg2.Server.Plugin.GroupSpool): """ name = 'TGenshi' - __version__ = '$Id$' __author__ = 'jeff@ocjtech.us' filename_pattern = 'template\.(txt|newtxt|xml)' es_child_cls = TemplateFile diff --git a/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py b/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py new file mode 100644 index 000000000..2c0ee03e0 --- /dev/null +++ b/src/lib/Bcfg2/Server/Plugins/TemplateHelper.py @@ -0,0 +1,83 @@ +import re +import imp +import sys +import logging +import Bcfg2.Server.Plugin + +logger = logging.getLogger(__name__) + +class HelperModule(Bcfg2.Server.Plugin.SpecificData): + _module_name_re = re.compile(r'([^/]+?)\.py') + + def __init__(self, name, specific, encoding): + Bcfg2.Server.Plugin.SpecificData.__init__(self, name, specific, + encoding) + match = self._module_name_re.search(self.name) + if match: + self._module_name = match.group(1) + else: + self._module_name = name + self._attrs = [] + + def handle_event(self, event): + Bcfg2.Server.Plugin.SpecificData.handle_event(self, event) + try: + module = imp.load_source(self._module_name, self.name) + except: + err = sys.exc_info()[1] + logger.error("TemplateHelper: Failed to import %s: %s" % + (self.name, err)) + return + + if not hasattr(module, "__export__"): + logger.error("TemplateHelper: %s has no __export__ list" % + self.name) + return + + for sym in module.__export__: + if sym not in self._attrs and hasattr(self, sym): + logger.warning("TemplateHelper: %s: %s is a reserved keyword, " + "skipping export" % (self.name, sym)) + setattr(self, sym, getattr(module, sym)) + # remove old exports + for sym in set(self._attrs) - set(module.__export__): + delattr(self, sym) + + self._attrs = module.__export__ + + +class HelperSet(Bcfg2.Server.Plugin.EntrySet): + ignore = re.compile("^(\.#.*|.*~|\\..*\\.(sw[px])|.*\.py[co])$") + + def __init__(self, path, fam, encoding, plugin_name): + fpattern = '[0-9A-Za-z_\-]+\.py' + self.plugin_name = plugin_name + Bcfg2.Server.Plugin.EntrySet.__init__(self, fpattern, path, + HelperModule, encoding) + fam.AddMonitor(path, self) + + def HandleEvent(self, event): + if (event.filename != self.path and + not self.ignore.match(event.filename)): + return self.handle_event(event) + + +class TemplateHelper(Bcfg2.Server.Plugin.Plugin, + Bcfg2.Server.Plugin.Connector): + """ A plugin to provide helper classes and functions to templates """ + name = 'TemplateHelper' + __author__ = 'chris.a.st.pierre@gmail.com' + + def __init__(self, core, datastore): + Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore) + Bcfg2.Server.Plugin.Connector.__init__(self) + + try: + self.helpers = HelperSet(self.data, core.fam, core.encoding, + self.name) + except: + raise Bcfg2.Server.Plugin.PluginInitError + + def get_additional_data(self, metadata): + return dict([(h._module_name, h) + for h in list(self.helpers.entries.values())]) diff --git a/src/lib/Server/Plugins/Trigger.py b/src/lib/Bcfg2/Server/Plugins/Trigger.py index eb3310a4e..b0d21545c 100644 --- a/src/lib/Server/Plugins/Trigger.py +++ b/src/lib/Bcfg2/Server/Plugins/Trigger.py @@ -17,7 +17,6 @@ class Trigger(Bcfg2.Server.Plugin.Plugin, Bcfg2.Server.Plugin.Statistics): """Trigger is a plugin that calls external scripts (on the server).""" name = 'Trigger' - __version__ = '$Id' __author__ = 'bcfg-dev@mcs.anl.gov' def __init__(self, core, datastore): diff --git a/src/lib/Server/Plugins/__init__.py b/src/lib/Bcfg2/Server/Plugins/__init__.py index c69c37452..f9f1b4e52 100644 --- a/src/lib/Server/Plugins/__init__.py +++ b/src/lib/Bcfg2/Server/Plugins/__init__.py @@ -1,5 +1,4 @@ """Imports for Bcfg2.Server.Plugins.""" -__revision__ = '$Revision$' __all__ = [ 'Account', @@ -8,7 +7,7 @@ __all__ = [ 'Bzr', 'Cfg', 'Cvs', - 'Darcs', + 'Darcs', 'Decisions', 'Fossil', 'Git', diff --git a/src/lib/Server/Reports/__init__.py b/src/lib/Bcfg2/Server/Reports/__init__.py index bdf908f4a..bdf908f4a 100644 --- a/src/lib/Server/Reports/__init__.py +++ b/src/lib/Bcfg2/Server/Reports/__init__.py diff --git a/src/lib/Server/Reports/backends.py b/src/lib/Bcfg2/Server/Reports/backends.py index 85241932f..85241932f 100644 --- a/src/lib/Server/Reports/backends.py +++ b/src/lib/Bcfg2/Server/Reports/backends.py diff --git a/src/lib/Server/Reports/importscript.py b/src/lib/Bcfg2/Server/Reports/importscript.py index 7dfac6fae..16df86a9b 100755 --- a/src/lib/Server/Reports/importscript.py +++ b/src/lib/Bcfg2/Server/Reports/importscript.py @@ -3,7 +3,6 @@ Imports statistics.xml and clients.xml files in to database backend for new statistics engine """ -__revision__ = '$Revision$' import binascii import os @@ -41,6 +40,7 @@ from Bcfg2.Bcfg2Py3k import ConfigParser def build_reason_kwargs(r_ent, encoding, logger): binary_file = False sensitive_file = False + unpruned_entries = '' if r_ent.get('sensitive') in ['true', 'True']: sensitive_file = True rc_diff = '' @@ -58,6 +58,10 @@ def build_reason_kwargs(r_ent, encoding, logger): rc_diff = r_ent.get('current_diff') else: rc_diff = '' + # detect unmanaged entries in pruned directories + if r_ent.get('prune', 'false') == 'true' and r_ent.get('qtest'): + unpruned_elist = [e.get('path') for e in r_ent.findall('Prune')] + unpruned_entries = "\n".join(unpruned_elist) if not binary_file: try: rc_diff = rc_diff.decode(encoding) @@ -79,7 +83,8 @@ def build_reason_kwargs(r_ent, encoding, logger): current_exists=r_ent.get('current_exists', default="True").capitalize() == "True", current_diff=rc_diff, is_binary=binary_file, - is_sensitive=sensitive_file) + is_sensitive=sensitive_file, + unpruned=unpruned_entries) def load_stats(cdata, sdata, encoding, vlevel, logger, quick=False, location=''): @@ -118,8 +123,6 @@ def load_stats(cdata, sdata, encoding, vlevel, logger, quick=False, location='') default="unknown"), repo_rev_code=statistics.get('revision', default="unknown"), - client_version=statistics.get('client_version', - default="unknown"), goodcount=statistics.get('good', default="0"), totalcount=statistics.get('total', diff --git a/src/lib/Server/Reports/manage.py b/src/lib/Bcfg2/Server/Reports/manage.py index 858bddeca..858bddeca 100755 --- a/src/lib/Server/Reports/manage.py +++ b/src/lib/Bcfg2/Server/Reports/manage.py diff --git a/src/lib/Server/Reports/nisauth.py b/src/lib/Bcfg2/Server/Reports/nisauth.py index 6fc346f1e..b3e37113b 100644 --- a/src/lib/Server/Reports/nisauth.py +++ b/src/lib/Bcfg2/Server/Reports/nisauth.py @@ -4,8 +4,6 @@ from Bcfg2.Server.Reports.settings import AUTHORIZED_GROUP """Checks with NIS to see if the current user is in the support group""" -__revision__ = "$Revision: $" - class NISAUTHError(Exception): """NISAUTHError is raised when somehting goes boom.""" diff --git a/src/lib/Server/Reports/reports/__init__.py b/src/lib/Bcfg2/Server/Reports/reports/__init__.py index ccdce8943..ccdce8943 100644 --- a/src/lib/Server/Reports/reports/__init__.py +++ b/src/lib/Bcfg2/Server/Reports/reports/__init__.py diff --git a/src/lib/Server/Reports/reports/fixtures/initial_version.xml b/src/lib/Bcfg2/Server/Reports/reports/fixtures/initial_version.xml index 919265d48..bde236989 100644 --- a/src/lib/Server/Reports/reports/fixtures/initial_version.xml +++ b/src/lib/Bcfg2/Server/Reports/reports/fixtures/initial_version.xml @@ -36,4 +36,8 @@ <field type='IntegerField' name='version'>18</field> <field type='DateTimeField' name='updated'>2011-06-30 00:00:00</field> </object> + <object pk="8" model="reports.internaldatabaseversion"> + <field type='IntegerField' name='version'>19</field> + <field type='DateTimeField' name='updated'>2012-03-28 00:00:00</field> + </object> </django-objects> diff --git a/src/lib/Server/Reports/reports/models.py b/src/lib/Bcfg2/Server/Reports/reports/models.py index 870239641..0438ea133 100644 --- a/src/lib/Server/Reports/reports/models.py +++ b/src/lib/Bcfg2/Server/Reports/reports/models.py @@ -156,7 +156,6 @@ class Interaction(models.Model): timestamp = models.DateTimeField() # Timestamp for this record state = models.CharField(max_length=32) # good/bad/modified/etc repo_rev_code = models.CharField(max_length=64) # repo revision at time of interaction - client_version = models.CharField(max_length=32) # Client Version goodcount = models.IntegerField() # of good config-items totalcount = models.IntegerField() # of total config-items server = models.CharField(max_length=256) # Name of the server used for the interaction @@ -278,6 +277,7 @@ class Reason(models.Model): current_diff = models.TextField(max_length=1280, blank=True) is_binary = models.BooleanField(default=False) is_sensitive = models.BooleanField(default=False) + unpruned = models.TextField(max_length=1280, blank=True) def _str_(self): return "Reason" diff --git a/src/lib/Server/Reports/reports/sql/client.sql b/src/lib/Bcfg2/Server/Reports/reports/sql/client.sql index 8c63754c9..8c63754c9 100644 --- a/src/lib/Server/Reports/reports/sql/client.sql +++ b/src/lib/Bcfg2/Server/Reports/reports/sql/client.sql diff --git a/src/lib/Server/Reports/reports/templates/404.html b/src/lib/Bcfg2/Server/Reports/reports/templates/404.html index 168bd9fec..168bd9fec 100644 --- a/src/lib/Server/Reports/reports/templates/404.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/404.html diff --git a/src/lib/Server/Reports/reports/templates/base-timeview.html b/src/lib/Bcfg2/Server/Reports/reports/templates/base-timeview.html index 842de36f0..842de36f0 100644 --- a/src/lib/Server/Reports/reports/templates/base-timeview.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/base-timeview.html diff --git a/src/lib/Server/Reports/reports/templates/base.html b/src/lib/Bcfg2/Server/Reports/reports/templates/base.html index f541c0d2b..f541c0d2b 100644 --- a/src/lib/Server/Reports/reports/templates/base.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/base.html diff --git a/src/lib/Server/Reports/reports/templates/clients/detail.html b/src/lib/Bcfg2/Server/Reports/reports/templates/clients/detail.html index dd4295f21..dd4295f21 100644 --- a/src/lib/Server/Reports/reports/templates/clients/detail.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/clients/detail.html diff --git a/src/lib/Server/Reports/reports/templates/clients/detailed-list.html b/src/lib/Bcfg2/Server/Reports/reports/templates/clients/detailed-list.html index 0c1fae8d5..0c1fae8d5 100644 --- a/src/lib/Server/Reports/reports/templates/clients/detailed-list.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/clients/detailed-list.html diff --git a/src/lib/Server/Reports/reports/templates/clients/history.html b/src/lib/Bcfg2/Server/Reports/reports/templates/clients/history.html index 01d4ec2f4..01d4ec2f4 100644 --- a/src/lib/Server/Reports/reports/templates/clients/history.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/clients/history.html diff --git a/src/lib/Server/Reports/reports/templates/clients/index.html b/src/lib/Bcfg2/Server/Reports/reports/templates/clients/index.html index e0c0d2d7a..e0c0d2d7a 100644 --- a/src/lib/Server/Reports/reports/templates/clients/index.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/clients/index.html diff --git a/src/lib/Server/Reports/reports/templates/clients/manage.html b/src/lib/Bcfg2/Server/Reports/reports/templates/clients/manage.html index 5725ae577..5725ae577 100644 --- a/src/lib/Server/Reports/reports/templates/clients/manage.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/clients/manage.html diff --git a/src/lib/Server/Reports/reports/templates/config_items/item.html b/src/lib/Bcfg2/Server/Reports/reports/templates/config_items/item.html index cc99ef503..cadc178a7 100644 --- a/src/lib/Server/Reports/reports/templates/config_items/item.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/config_items/item.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load split %} {% load syntax_coloring %} @@ -91,6 +92,20 @@ div.entry_list h3 { </div> {% endif %} + <!-- display extra directory entries --> + {% if item.reason.unpruned %} + <div class='entry_list'> + <div class='entry_list_head'> + <h3>Extra entries found</h3> + </div> + <table class='entry_list' cellpadding='3'> + {% for unpruned_item in item.reason.unpruned|split %} + <tr><td>{{ unpruned_item }}</td></tr> + {% endfor %} + </table> + </div> + {% endif %} + <div class='entry_list'> <div class='entry_list_head'> diff --git a/src/lib/Server/Reports/reports/templates/config_items/listing.html b/src/lib/Bcfg2/Server/Reports/reports/templates/config_items/listing.html index 9b1026a08..9b1026a08 100644 --- a/src/lib/Server/Reports/reports/templates/config_items/listing.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/config_items/listing.html diff --git a/src/lib/Server/Reports/reports/templates/displays/summary.html b/src/lib/Bcfg2/Server/Reports/reports/templates/displays/summary.html index b9847cf96..b9847cf96 100644 --- a/src/lib/Server/Reports/reports/templates/displays/summary.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/displays/summary.html diff --git a/src/lib/Server/Reports/reports/templates/displays/timing.html b/src/lib/Bcfg2/Server/Reports/reports/templates/displays/timing.html index 47accb2cb..ff775ded5 100644 --- a/src/lib/Server/Reports/reports/templates/displays/timing.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/displays/timing.html @@ -20,7 +20,7 @@ <td>Install</td> <td>Config</td> <td>Total</td> - </tr> + </tr> {% for metric in metrics|dictsort:"name" %} <tr class='{% cycle listview,listview_alt %}'> <td><a style='font-size: 100%' diff --git a/src/lib/Server/Reports/reports/templates/widgets/filter_bar.html b/src/lib/Bcfg2/Server/Reports/reports/templates/widgets/filter_bar.html index 6b57baf6a..6fbe585ab 100644 --- a/src/lib/Server/Reports/reports/templates/widgets/filter_bar.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/widgets/filter_bar.html @@ -2,7 +2,7 @@ {% if filters %} {% for filter, filter_url in filters %} {% if forloop.first %} - <div class="filter_bar">Active filters (click to remove): + <div class="filter_bar">Active filters (click to remove): {% endif %} <a href='{{ filter_url }}'>{{ filter|capfirst }}</a>{% if not forloop.last %}, {% endif %} {% if forloop.last %} diff --git a/src/lib/Server/Reports/reports/templates/widgets/interaction_list.inc b/src/lib/Bcfg2/Server/Reports/reports/templates/widgets/interaction_list.inc index 8f2dec1dc..8f2dec1dc 100644 --- a/src/lib/Server/Reports/reports/templates/widgets/interaction_list.inc +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/widgets/interaction_list.inc diff --git a/src/lib/Server/Reports/reports/templates/widgets/page_bar.html b/src/lib/Bcfg2/Server/Reports/reports/templates/widgets/page_bar.html index aa0def83e..aa0def83e 100644 --- a/src/lib/Server/Reports/reports/templates/widgets/page_bar.html +++ b/src/lib/Bcfg2/Server/Reports/reports/templates/widgets/page_bar.html diff --git a/src/lib/Server/Reports/reports/templatetags/__init__.py b/src/lib/Bcfg2/Server/Reports/reports/templatetags/__init__.py index e69de29bb..e69de29bb 100644 --- a/src/lib/Server/Reports/reports/templatetags/__init__.py +++ b/src/lib/Bcfg2/Server/Reports/reports/templatetags/__init__.py diff --git a/src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py b/src/lib/Bcfg2/Server/Reports/reports/templatetags/bcfg2_tags.py index 629984f26..f738f7bdd 100644 --- a/src/lib/Server/Reports/reports/templatetags/bcfg2_tags.py +++ b/src/lib/Bcfg2/Server/Reports/reports/templatetags/bcfg2_tags.py @@ -81,7 +81,7 @@ def page_navigator(context): fragment['pager'] = pager fragment['page_limits'] = page_limits - + except Resolver404: path = "404" except NoReverseMatch: @@ -155,7 +155,7 @@ def isstale(timestamp, entry_max=None): """ Check for a stale timestamp - Compares two timestamps and returns True if the + Compares two timestamps and returns True if the difference is greater then 24 hours. """ if not entry_max: diff --git a/src/lib/Bcfg2/Server/Reports/reports/templatetags/split.py b/src/lib/Bcfg2/Server/Reports/reports/templatetags/split.py new file mode 100644 index 000000000..a9b4f0371 --- /dev/null +++ b/src/lib/Bcfg2/Server/Reports/reports/templatetags/split.py @@ -0,0 +1,8 @@ +from django import template +register = template.Library() + + +@register.filter +def split(s): + """split by newlines""" + return s.split('\n') diff --git a/src/lib/Server/Reports/reports/templatetags/syntax_coloring.py b/src/lib/Bcfg2/Server/Reports/reports/templatetags/syntax_coloring.py index 2e30125f9..2e30125f9 100644 --- a/src/lib/Server/Reports/reports/templatetags/syntax_coloring.py +++ b/src/lib/Bcfg2/Server/Reports/reports/templatetags/syntax_coloring.py diff --git a/src/lib/Server/Reports/reports/urls.py b/src/lib/Bcfg2/Server/Reports/reports/urls.py index 434ce07b7..434ce07b7 100644 --- a/src/lib/Server/Reports/reports/urls.py +++ b/src/lib/Bcfg2/Server/Reports/reports/urls.py diff --git a/src/lib/Server/Reports/reports/views.py b/src/lib/Bcfg2/Server/Reports/reports/views.py index ccd71a60e..ccd71a60e 100644 --- a/src/lib/Server/Reports/reports/views.py +++ b/src/lib/Bcfg2/Server/Reports/reports/views.py diff --git a/src/lib/Server/Reports/settings.py b/src/lib/Bcfg2/Server/Reports/settings.py index 952e3eae6..4d567f1a2 100644 --- a/src/lib/Server/Reports/settings.py +++ b/src/lib/Bcfg2/Server/Reports/settings.py @@ -64,10 +64,10 @@ if django.VERSION[0] == 1 and django.VERSION[1] < 2: # Local time zone for this installation. All choices can be found here: # http://docs.djangoproject.com/en/dev/ref/settings/#time-zone -try: - TIME_ZONE = c.get('statistics', 'time_zone') -except: - if django.VERSION[0] == 1 and django.VERSION[1] > 2: +if django.VERSION[0] == 1 and django.VERSION[1] > 2: + try: + TIME_ZONE = c.get('statistics', 'time_zone') + except: TIME_ZONE = None # Language code for this installation. All choices can be found here: @@ -124,8 +124,8 @@ except ImportError: django.contrib.auth.LOGIN_URL = '/login' SESSION_EXPIRE_AT_BROWSER_CLOSE = True - - + + TEMPLATE_DIRS = ( # Put strings here, like "/home/html/django_templates". diff --git a/src/lib/Server/Reports/updatefix.py b/src/lib/Bcfg2/Server/Reports/updatefix.py index 7cebaaca9..39fc10b56 100644 --- a/src/lib/Server/Reports/updatefix.py +++ b/src/lib/Bcfg2/Server/Reports/updatefix.py @@ -1,8 +1,9 @@ import Bcfg2.Server.Reports.settings -from django.db import connection +from django.db import connection, DatabaseError import django.core.management import logging +import sys import traceback from Bcfg2.Server.Reports.reports.models import InternalDatabaseVersion, \ TYPE_BAD, TYPE_MODIFIED, TYPE_EXTRA @@ -16,9 +17,9 @@ def _merge_database_table_entries(): find_cursor = connection.cursor() cursor.execute(""" Select name, kind from reports_bad - union + union select name, kind from reports_modified - union + union select name, kind from reports_extra """) # this fetch could be better done @@ -51,7 +52,7 @@ def _merge_database_table_entries(): def _interactions_constraint_or_idx(): - '''sqlite doesn't support alter tables.. or constraints''' + """sqlite doesn't support alter tables.. or constraints""" cursor = connection.cursor() try: cursor.execute('alter table reports_interaction add constraint reports_interaction_20100601 unique (client_id,timestamp)') @@ -59,6 +60,72 @@ def _interactions_constraint_or_idx(): cursor.execute('create unique index reports_interaction_20100601 on reports_interaction (client_id,timestamp)') +def _remove_table_column(tbl, col): + """sqlite doesn't support deleting a column via alter table""" + cursor = connection.cursor() + try: + cursor.execute('alter table %s ' + 'drop column %s;' % (tbl, col)) + except DatabaseError: + # sqlite wants us to create a new table containing the columns we want + # and copy into it http://www.sqlite.org/faq.html#q11 + + tmptbl_name = "t_backup" + _tmptbl_create = \ +"""create temporary table "%s" ( + "id" integer NOT NULL PRIMARY KEY, + "client_id" integer NOT NULL REFERENCES "reports_client" ("id"), + "timestamp" datetime NOT NULL, + "state" varchar(32) NOT NULL, + "repo_rev_code" varchar(64) NOT NULL, + "goodcount" integer NOT NULL, + "totalcount" integer NOT NULL, + "server" varchar(256) NOT NULL, + "bad_entries" integer NOT NULL, + "modified_entries" integer NOT NULL, + "extra_entries" integer NOT NULL, + UNIQUE ("client_id", "timestamp") +);""" % tmptbl_name + _newtbl_create = \ +"""create table "%s" ( + "id" integer NOT NULL PRIMARY KEY, + "client_id" integer NOT NULL REFERENCES "reports_client" ("id"), + "timestamp" datetime NOT NULL, + "state" varchar(32) NOT NULL, + "repo_rev_code" varchar(64) NOT NULL, + "goodcount" integer NOT NULL, + "totalcount" integer NOT NULL, + "server" varchar(256) NOT NULL, + "bad_entries" integer NOT NULL, + "modified_entries" integer NOT NULL, + "extra_entries" integer NOT NULL, + UNIQUE ("client_id", "timestamp") +);""" % tbl + new_cols = "id,\ + client_id,\ + timestamp,\ + state,\ + repo_rev_code,\ + goodcount,\ + totalcount,\ + server,\ + bad_entries,\ + modified_entries,\ + extra_entries" + + delete_col = [_tmptbl_create, + "insert into %s select %s from %s;" % (tmptbl_name, new_cols, tbl), + "drop table %s" % tbl, + _newtbl_create, + "create index reports_interaction_client_id on %s (client_id);" % tbl, + "insert into %s select %s from %s;" % (tbl, new_cols, + tmptbl_name), + "drop table %s;" % tmptbl_name] + + for sql in delete_col: + cursor.execute(sql) + + def _populate_interaction_entry_counts(): '''Populate up the type totals for the interaction table''' cursor = connection.cursor() @@ -103,6 +170,8 @@ _fixes = [_merge_database_table_entries, _interactions_constraint_or_idx, 'alter table reports_reason add is_binary bool NOT NULL default False;', 'alter table reports_reason add is_sensitive bool NOT NULL default False;', + _remove_table_column('reports_interaction', 'client_version'), + "alter table reports_reason add unpruned varchar(1280) not null default 'N/A';", ] # this will calculate the last possible version of the database @@ -110,7 +179,7 @@ lastversion = len(_fixes) def rollupdate(current_version): - """ function responsible to coordinates all the updates + """function responsible to coordinates all the updates need current_version as integer """ ret = None @@ -122,8 +191,10 @@ def rollupdate(current_version): else: _fixes[i]() except: - logger.error("Failed to perform db update %s" % (_fixes[i]), exc_info=1) - # since array start at 0 but version start at 1 we add 1 to the normal count + logger.error("Failed to perform db update %s" % (_fixes[i]), + exc_info=1) + # since the array starts at 0 but version + # starts at 1 we add 1 to the normal count ret = InternalDatabaseVersion.objects.create(version=i + 1) return ret else: @@ -135,16 +206,19 @@ def dosync(): # try to detect if it's a fresh new database try: cursor = connection.cursor() - # If this table goes missing then don't forget to change it to the new one + # If this table goes missing, + # don't forget to change it to the new one cursor.execute("Select * from reports_client") # if we get here with no error then the database has existing tables fresh = False except: - logger.debug("there was an error while detecting the freshness of the database") + logger.debug("there was an error while detecting " + "the freshness of the database") #we should get here if the database is new fresh = True - # ensure database connection are close, so that the management can do it's job right + # ensure database connections are closed + # so that the management can do its job right try: cursor.close() connection.close() @@ -169,7 +243,8 @@ def dosync(): def update_database(): - ''' methode to search where we are in the revision of the database models and update them ''' + """method to search where we are in the revision + of the database models and update them""" try: logger.debug("Running upgrade of models to the new one") dosync() diff --git a/src/lib/Server/Reports/urls.py b/src/lib/Bcfg2/Server/Reports/urls.py index d7ff1eee5..d7ff1eee5 100644 --- a/src/lib/Server/Reports/urls.py +++ b/src/lib/Bcfg2/Server/Reports/urls.py diff --git a/src/lib/Server/Reports/utils.py b/src/lib/Bcfg2/Server/Reports/utils.py index e0b6ead59..e0b6ead59 100755 --- a/src/lib/Server/Reports/utils.py +++ b/src/lib/Bcfg2/Server/Reports/utils.py diff --git a/src/lib/Server/Snapshots/__init__.py b/src/lib/Bcfg2/Server/Snapshots/__init__.py index 7c901adb2..7c901adb2 100644 --- a/src/lib/Server/Snapshots/__init__.py +++ b/src/lib/Bcfg2/Server/Snapshots/__init__.py diff --git a/src/lib/Server/Snapshots/model.py b/src/lib/Bcfg2/Server/Snapshots/model.py index 5d7973c16..5d7973c16 100644 --- a/src/lib/Server/Snapshots/model.py +++ b/src/lib/Bcfg2/Server/Snapshots/model.py diff --git a/src/lib/Server/__init__.py b/src/lib/Bcfg2/Server/__init__.py index 25f397565..96777b0bf 100644 --- a/src/lib/Server/__init__.py +++ b/src/lib/Bcfg2/Server/__init__.py @@ -1,6 +1,4 @@ -# $Id$ """This is the set of modules for Bcfg2.Server.""" -__revision__ = '$Revision$' __all__ = ["Admin", "Core", "FileMonitor", "Plugin", "Plugins", "Hostbase", "Reports", "Snapshots"] diff --git a/src/lib/Statistics.py b/src/lib/Bcfg2/Statistics.py index a0cb8f39b..a0cb8f39b 100644 --- a/src/lib/Statistics.py +++ b/src/lib/Bcfg2/Statistics.py diff --git a/src/lib/__init__.py b/src/lib/Bcfg2/__init__.py index d36c0a00a..357f66f6d 100644 --- a/src/lib/__init__.py +++ b/src/lib/Bcfg2/__init__.py @@ -1,4 +1,3 @@ """Base modules definition.""" -__revision__ = '$Revision$' __all__ = ['Server', 'Client', 'Component', 'Logger', 'Options', 'Proxy', 'Statistics'] diff --git a/src/lib/Bcfg2Py3Incompat.py b/src/lib/Bcfg2Py3Incompat.py deleted file mode 100644 index 6b66e72b0..000000000 --- a/src/lib/Bcfg2Py3Incompat.py +++ /dev/null @@ -1,2 +0,0 @@ -def fprint(s, f): - print(s, file=f) diff --git a/src/lib/Client/Tools/Portage.py b/src/lib/Client/Tools/Portage.py deleted file mode 100644 index 17163afa9..000000000 --- a/src/lib/Client/Tools/Portage.py +++ /dev/null @@ -1,72 +0,0 @@ -"""This is the Bcfg2 tool for the Gentoo Portage system.""" -__revision__ = '$Revision$' - -import re -import Bcfg2.Client.Tools - - -class Portage(Bcfg2.Client.Tools.PkgTool): - """The Gentoo toolset implements package and service operations and - inherits the rest from Toolset.Toolset.""" - name = 'Portage' - __execs__ = ['/usr/bin/emerge', '/usr/bin/equery'] - __handles__ = [('Package', 'ebuild')] - __req__ = {'Package': ['name', 'version']} - pkgtype = 'ebuild' - # requires a working PORTAGE_BINHOST in make.conf - pkgtool = ('emerge --getbinpkgonly %s', ('=%s-%s', ['name', 'version'])) - - def __init__(self, logger, cfg, setup): - Bcfg2.Client.Tools.PkgTool.__init__(self, logger, cfg, setup) - self.__important__ = self.__important__ + ['/etc/make.conf'] - self.cfg = cfg - self.installed = {} - self.RefreshPackages() - - def RefreshPackages(self): - """Refresh memory hashes of packages.""" - ret, cache = self.cmd.run("equery -q list '*'") - if ret == 2: - cache = self.cmd.run("equery -q list '*'")[1] - pattern = re.compile('(.*)-(\d.*)') - self.installed = {} - for pkg in cache: - if pattern.match(pkg): - name = pattern.match(pkg).group(1) - version = pattern.match(pkg).group(2) - self.installed[name] = version - else: - self.logger.info("Failed to parse pkg name %s" % pkg) - - def VerifyPackage(self, entry, modlist): - """Verify package for entry.""" - if not 'version' in entry.attrib: - self.logger.info("Cannot verify unversioned package %s" % - (entry.attrib['name'])) - return False - if entry.attrib['name'] in self.installed: - if self.installed[entry.attrib['name']] == entry.attrib['version']: - if not self.setup['quick'] and \ - entry.get('verify', 'true') == 'true': - output = self.cmd.run("/usr/bin/equery -N check '=%s-%s' 2>&1 " - "| grep '!!!' | awk '{print $2}'" \ - % (entry.get('name'), entry.get('version')))[1] - if [filename for filename in output \ - if filename not in modlist]: - return False - return True - else: - entry.set('current_version', self.installed[entry.get('name')]) - return False - entry.set('current_exists', 'false') - return False - - def RemovePackages(self, packages): - """Deal with extra configuration detected.""" - pkgnames = " ".join([pkg.get('name') for pkg in packages]) - if len(packages) > 0: - self.logger.info('Removing packages:') - self.logger.info(pkgnames) - self.cmd.run("emerge --unmerge --quiet %s" % " ".join(pkgnames.split(' '))) - self.RefreshPackages() - self.extra = self.FindExtraPackages() diff --git a/src/sbin/bcfg2 b/src/sbin/bcfg2 index 1d1cc8424..fb34e627b 100755 --- a/src/sbin/bcfg2 +++ b/src/sbin/bcfg2 @@ -1,7 +1,6 @@ #!/usr/bin/env python """Bcfg2 Client""" -__revision__ = '$Revision$' import fcntl import logging diff --git a/src/sbin/bcfg2-admin b/src/sbin/bcfg2-admin index 5cb69d747..d3b06733f 100755 --- a/src/sbin/bcfg2-admin +++ b/src/sbin/bcfg2-admin @@ -50,8 +50,7 @@ def main(): } setup = Bcfg2.Options.OptionParser(optinfo) # override default help message to include description of all modes - setup.hm = "Usage:\n %s\n%s" % (setup.buildHelpMessage(), - create_description()) + setup.hm = "%s\n%s" % (setup.buildHelpMessage(), create_description()) setup.parse(sys.argv[1:]) log_args = dict(to_syslog=False, to_console=logging.WARNING) diff --git a/src/sbin/bcfg2-build-reports b/src/sbin/bcfg2-build-reports index 7122fb300..7fa08110a 100755 --- a/src/sbin/bcfg2-build-reports +++ b/src/sbin/bcfg2-build-reports @@ -4,8 +4,6 @@ bcfg2-build-reports generates & distributes reports of statistic information for Bcfg2.""" -__revision__ = '$Revision$' - import copy import getopt import re diff --git a/src/sbin/bcfg2-info b/src/sbin/bcfg2-info index e09b7ed87..5e260d94d 100755 --- a/src/sbin/bcfg2-info +++ b/src/sbin/bcfg2-info @@ -1,17 +1,16 @@ #!/usr/bin/env python - """This tool loads the Bcfg2 core into an interactive debugger.""" -__revision__ = '$Revision$' -from code import InteractiveConsole +import os +import sys import cmd import errno import getopt +import fnmatch import logging -import lxml.etree -import os -import sys import tempfile +import lxml.etree +from code import InteractiveConsole try: try: @@ -34,7 +33,8 @@ logger = logging.getLogger('bcfg2-info') USAGE = """Commands: build <hostname> <filename> - Build config for hostname, writing to filename builddir <hostname> <dirname> - Build config for hostname, writing separate files to dirname -buildall <directory> - Build configs for all clients in directory +buildall <directory> [<hostnames*>] - Build configs for all clients in directory +buildallfile <directory> <filename> [<hostnames*>] - Build config file for all clients in directory buildfile <filename> <hostname> - Build config file for hostname (not written to disk) buildbundle <bundle> <hostname> - Render a templated bundle for hostname (not written to disk) bundles - Print out group/bundle information @@ -51,8 +51,7 @@ profile <command> <args> - Profile a single bcfg2-info command quit - Exit the bcfg2-info command line showentries <hostname> <type> - Show abstract configuration entries for a given host showclient <client1> <client2> - Show metadata for given hosts -update - Process pending file events -version - Print version of this tool""" +update - Process pending file events""" BUILDDIR_USAGE = """Usage: builddir [-f] <hostname> <output dir> @@ -78,10 +77,12 @@ class mockLog(object): def debug(self, *args, **kwargs): pass + class dummyError(Exception): """This is just a dummy.""" pass + class FileNotBuilt(Exception): """Thrown when File entry contains no content.""" def __init__(self, value): @@ -90,6 +91,30 @@ class FileNotBuilt(Exception): def __str__(self): return repr(self.value) + +def getClientList(hostglobs): + """ given a host glob, get a list of clients that match it """ + # special cases to speed things up: + if '*' in hostglobs: + return list(self.metadata.clients.keys()) + has_wildcards = False + for glob in hostglobs: + # check if any wildcard characters are in the string + if set('*?[]') & set(glob): + has_wildcards = True + break + if not has_wildcards: + return hostglobs + + rv = set() + clist = set(self.metadata.clients.keys()) + for glob in hostglobs: + for client in clist: + if fnmatch.fnmatch(client, glob): + rv.update(client) + clist.difference_update(rv) + return list(rv) + def printTabular(rows): """Print data in tabular format.""" cmax = tuple([max([len(str(row[index])) for row in rows]) + 1 \ @@ -197,10 +222,6 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): """Process pending filesystem events.""" self.fam.handle_events_in_interval(0.1) - def do_version(self, _): - """Print out code version.""" - print(__revision__) - def do_build(self, args): """Build client configuration.""" alist = args.split() @@ -257,42 +278,101 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): self.help_builddir() def do_buildall(self, args): - if len(args.split()) != 1: - print("Usage: buildall <directory>") + alist = args.split() + if len(alist) < 1: + print("Usage: buildall <directory> [<hostnames*>]") return + + destdir = alist[0] + try: + os.mkdir(destdir) + except OSError: + err = sys.exc_info()[1] + if err.errno != 17: + print("Could not create %s: %s" % (destdir, err)) + if len(alist) > 1: + clients = getClientList(alist[1:]) + else: + clients = list(self.metadata.clients.keys()) + for client in clients: + self.do_build("%s %s" % (client, os.path.join(destdir, + client + ".xml"))) + + def do_buildallfile(self, args): + """Build a config file for all clients.""" + usage = 'Usage: buildallfile [--altsrc=<altsrc>] <directory> <filename> [<hostnames*>]' try: - os.mkdir(args) + opts, args = getopt.gnu_getopt(args.split(), '', ['altsrc=']) except: - pass - for client in self.metadata.clients: - self.do_build("%s %s/%s.xml" % (client, args, client)) + print(usage) + return + altsrc = None + for opt in opts: + if opt[0] == '--altsrc': + altsrc = opt[1] + if len(args) < 2: + print(usage) + return + + destdir = args[0] + filename = args[1] + try: + os.mkdir(destdir) + except OSError: + err = sys.exc_info()[1] + if err.errno != 17: + print("Could not create %s: %s" % (destdir, err)) + if len(args) > 2: + clients = getClientList(args[1:]) + else: + clients = list(self.metadata.clients.keys()) + if altsrc: + args = "--altsrc %s -f %%s %%s %%s" % altsrc + else: + args = "-f %s %s %s" + for client in clients: + self.do_buildfile(args % (os.path.join(destdir, client), + filename, client)) def do_buildfile(self, args): """Build a config file for client.""" - usage = 'Usage: buildfile [--altsrc=<altsrc>] filename hostname' + usage = 'Usage: buildfile [-f <outfile>] [--altsrc=<altsrc>] filename hostname' try: - opts, alist = getopt.gnu_getopt(args.split(), '', ['altsrc=']) + opts, alist = getopt.gnu_getopt(args.split(), 'f:', ['altsrc=']) except: print(usage) return altsrc = None + outfile = None for opt in opts: if opt[0] == '--altsrc': altsrc = opt[1] - if len(alist) == 2: - fname, client = alist - entry = lxml.etree.Element('Path', type='file', name=fname) - if altsrc: - entry.set("altsrc", altsrc) - try: - metadata = self.build_metadata(client) - self.Bind(entry, metadata) - print(lxml.etree.tostring(entry, encoding="UTF-8", - xml_declaration=True)) - except: - print("Failed to build entry %s for host %s" % (fname, client)) - else: + elif opt[0] == '-f': + outfile = opt[1] + if len(alist) != 2: print(usage) + return + + fname, client = alist + entry = lxml.etree.Element('Path', type='file', name=fname) + if altsrc: + entry.set("altsrc", altsrc) + try: + metadata = self.build_metadata(client) + self.Bind(entry, metadata) + data = lxml.etree.tostring(entry, encoding="UTF-8", + xml_declaration=True) + if outfile: + open(outfile, 'w').write(data) + else: + print(data) + except IOError: + err = sys.exc_info()[1] + print("Could not write to %s: %s" % (outfile, err)) + print(data) + except Exception: + print("Failed to build entry %s for host %s" % (fname, client)) + raise def do_buildbundle(self, args): """Render a bundle for client.""" @@ -533,7 +613,7 @@ class infoCore(cmd.Cmd, Bcfg2.Server.Core.Core): if len(source.whitelist): print(" Whitelist: %s" % ", ".join(source.whitelist)) print("") - + def do_profile(self, arg): """.""" if not have_profile: @@ -557,27 +637,25 @@ if __name__ == '__main__': optinfo = { 'configfile': Bcfg2.Options.CFILE, 'help': Bcfg2.Options.HELP, - } - optinfo.update({ - 'event debug': Bcfg2.Options.DEBUG, - 'profile': Bcfg2.Options.CORE_PROFILE, - 'encoding': Bcfg2.Options.ENCODING, - # Server options - 'repo': Bcfg2.Options.SERVER_REPOSITORY, - 'plugins': Bcfg2.Options.SERVER_PLUGINS, - 'password': Bcfg2.Options.SERVER_PASSWORD, - 'mconnect': Bcfg2.Options.SERVER_MCONNECT, - 'filemonitor': Bcfg2.Options.SERVER_FILEMONITOR, - 'location': Bcfg2.Options.SERVER_LOCATION, - 'static': Bcfg2.Options.SERVER_STATIC, - 'key': Bcfg2.Options.SERVER_KEY, - 'cert': Bcfg2.Options.SERVER_CERT, - 'ca': Bcfg2.Options.SERVER_CA, - 'password': Bcfg2.Options.SERVER_PASSWORD, - 'protocol': Bcfg2.Options.SERVER_PROTOCOL, - # More options - 'logging': Bcfg2.Options.LOGGING_FILE_PATH - }) + 'event debug': Bcfg2.Options.DEBUG, + 'profile': Bcfg2.Options.CORE_PROFILE, + 'encoding': Bcfg2.Options.ENCODING, + # Server options + 'repo': Bcfg2.Options.SERVER_REPOSITORY, + 'plugins': Bcfg2.Options.SERVER_PLUGINS, + 'password': Bcfg2.Options.SERVER_PASSWORD, + 'mconnect': Bcfg2.Options.SERVER_MCONNECT, + 'filemonitor': Bcfg2.Options.SERVER_FILEMONITOR, + 'location': Bcfg2.Options.SERVER_LOCATION, + 'static': Bcfg2.Options.SERVER_STATIC, + 'key': Bcfg2.Options.SERVER_KEY, + 'cert': Bcfg2.Options.SERVER_CERT, + 'ca': Bcfg2.Options.SERVER_CA, + 'password': Bcfg2.Options.SERVER_PASSWORD, + 'protocol': Bcfg2.Options.SERVER_PROTOCOL, + # More options + 'logging': Bcfg2.Options.LOGGING_FILE_PATH + } setup = Bcfg2.Options.OptionParser(optinfo) setup.hm = "Usage:\n %s\n%s" % (setup.buildHelpMessage(), USAGE) diff --git a/src/sbin/bcfg2-lint b/src/sbin/bcfg2-lint index 2d371f4aa..5ee88535d 100755 --- a/src/sbin/bcfg2-lint +++ b/src/sbin/bcfg2-lint @@ -1,7 +1,6 @@ #!/usr/bin/env python """This tool examines your Bcfg2 specifications for errors.""" -__revision__ = '$Revision$' import sys import inspect @@ -115,21 +114,6 @@ if __name__ == '__main__': config.read(setup['configfile']) config.read(setup['config']) - if setup['showerrors']: - if config.has_section("errors"): - econf = dict(config.items("errors")) - else: - econf = dict() - - print("%-35s %-35s" % ("Error name", "Handler (Default)")) - for err, default in Bcfg2.Server.Lint.ErrorHandler._errors.items(): - if err in econf and econf[err] != default: - handler = "%s (%s)" % (econf[err], default) - else: - handler = default - print("%-35s %-35s" % (err, handler)) - raise SystemExit(0) - # get list of plugins to run if setup['args']: allplugins = setup['args'] @@ -170,6 +154,15 @@ if __name__ == '__main__': errorhandler = get_errorhandler(config) + if setup['showerrors']: + for plugin in serverplugins.values() + serverlessplugins.values(): + errorhandler.RegisterErrors(getattr(plugin, 'Errors')()) + + print("%-35s %-35s" % ("Error name", "Handler")) + for err, handler in errorhandler._handlers.items(): + print("%-35s %-35s" % (err, handler.__name__)) + raise SystemExit(0) + run_serverless_plugins(serverlessplugins, errorhandler=errorhandler, config=config, setup=setup) diff --git a/src/sbin/bcfg2-ping-sweep b/src/sbin/bcfg2-ping-sweep index 70f718690..be8994be3 100755 --- a/src/sbin/bcfg2-ping-sweep +++ b/src/sbin/bcfg2-ping-sweep @@ -3,8 +3,6 @@ """Generates hostinfo.xml at a regular interval.""" -__revision__ = '$Revision$' - from os import dup2, execl, fork, uname, wait import sys import time diff --git a/src/sbin/bcfg2-reports b/src/sbin/bcfg2-reports index 6acdd27e3..1f101b9a7 100755 --- a/src/sbin/bcfg2-reports +++ b/src/sbin/bcfg2-reports @@ -1,6 +1,5 @@ #!/usr/bin/env python """Query reporting system for client status.""" -__revision__ = '$Revision$' import os import sys diff --git a/src/sbin/bcfg2-server b/src/sbin/bcfg2-server index 546d5a249..89bc7c331 100755 --- a/src/sbin/bcfg2-server +++ b/src/sbin/bcfg2-server @@ -1,7 +1,6 @@ #!/usr/bin/env python """The XML-RPC Bcfg2 server.""" -__revision__ = '$Revision$' import logging import os.path diff --git a/src/sbin/bcfg2-yum-helper b/src/sbin/bcfg2-yum-helper index dc46bb81a..2da7c6336 100755 --- a/src/sbin/bcfg2-yum-helper +++ b/src/sbin/bcfg2-yum-helper @@ -5,8 +5,6 @@ the right way to get around that in long-running processes it to have a short-lived helper. No, seriously -- check out the yum-updatesd code. It's pure madness. """ -__revision__ = '$Revision$' - import os import sys import yum |