summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml18
-rw-r--r--debian/bcfg2-server.install1
-rw-r--r--debian/bcfg2-utils.install1
-rw-r--r--debian/bcfg2.install1
-rw-r--r--debian/changelog6
-rw-r--r--debian/control14
-rwxr-xr-xdebian/rules4
-rw-r--r--doc/conf.py2
-rw-r--r--doc/development/compat.txt2
-rw-r--r--doc/releases/index.txt1
-rw-r--r--doc/server/plugins/generators/packages.txt6
-rw-r--r--doc/server/plugins/grouping/metadata.txt3
-rw-r--r--doc/server/plugins/structures/bundler/index.txt2
-rw-r--r--doc/unsorted/vim_snippet.txt2
-rw-r--r--src/lib/Bcfg2/DBSettings.py3
-rw-r--r--src/lib/Bcfg2/Server/Core.py2
-rwxr-xr-xsrc/lib/Bcfg2/Server/Encryption.py2
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Ldap.py17
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Metadata.py6
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Packages/Apt.py10
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Probes.py5
-rw-r--r--src/lib/Bcfg2/Server/migrations/0001_initial.py45
-rw-r--r--src/lib/Bcfg2/Server/migrations/__init__.py0
-rw-r--r--src/lib/Bcfg2/Server/models.py34
-rw-r--r--src/lib/Bcfg2/Server/south_migrations/0001_initial.py70
-rw-r--r--src/lib/Bcfg2/Server/south_migrations/__init__.py0
-rwxr-xr-xsrc/lib/Bcfg2/manage.py22
-rw-r--r--testsuite/Testsrc/test_code_checks.py2
-rw-r--r--testsuite/Testsrc/test_doc.py39
-rw-r--r--testsuite/common.py14
-rwxr-xr-xtestsuite/install.sh20
31 files changed, 294 insertions, 60 deletions
diff --git a/.travis.yml b/.travis.yml
index 8b336e7f8..b868e83b1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,13 +1,17 @@
language: python
-python:
- - "2.6"
- - "2.7_with_system_site_packages"
-env:
- - WITH_OPTIONAL_DEPS=yes
- - WITH_OPTIONAL_DEPS=no
+matrix:
+ include:
+ - python: "2.6"
+ env: WITH_OPTIONAL_DEPS=no TEST_SPHINX=no
+ - python: "2.6"
+ env: WITH_OPTIONAL_DEPS=yes TEST_SPHINX=no
+ - python: "2.7_with_system_site_packages"
+ env: WITH_OPTIONAL_DEPS=no TEST_SPHINX=no
+ - python: "2.7_with_system_site_packages"
+ env: WITH_OPTIONAL_DEPS=yes TEST_SPHINX=yes
install:
- testsuite/install.sh
- - pip install --use-mirrors -e .
+ - pip install -e .
script:
- nosetests testsuite
after_failure:
diff --git a/debian/bcfg2-server.install b/debian/bcfg2-server.install
index 3f1a73b06..cea918d00 100644
--- a/debian/bcfg2-server.install
+++ b/debian/bcfg2-server.install
@@ -5,3 +5,4 @@ debian/tmp/usr/lib/python*/*-packages/Bcfg2/Reporting/*
debian/tmp/usr/share/bcfg2/schemas/*
debian/tmp/usr/share/bcfg2/xsl-transforms/*
debian/tmp/usr/share/man/man8/*
+debian/tmp/etc/bash_completion.d/*
diff --git a/debian/bcfg2-utils.install b/debian/bcfg2-utils.install
new file mode 100644
index 000000000..ccddfa1af
--- /dev/null
+++ b/debian/bcfg2-utils.install
@@ -0,0 +1 @@
+tools/* usr/share/bcfg2
diff --git a/debian/bcfg2.install b/debian/bcfg2.install
index a240dac53..eaf58141c 100644
--- a/debian/bcfg2.install
+++ b/debian/bcfg2.install
@@ -7,4 +7,3 @@ debian/tmp/usr/share/man/man5/*
examples/bcfg2.conf usr/share/bcfg2
debian/bcfg2.default usr/share/bcfg2
tools/bcfg2-cron usr/lib/bcfg2
-tools/bcfg2-import-config usr/share/bcfg2
diff --git a/debian/changelog b/debian/changelog
index 789891961..f6b395624 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+bcfg2 (1.4.0pre2-0.1) UNRELEASED; urgency=low
+
+ * Helper scripts packed in bcfg2-utils
+
+ -- Holger Mueller <zarath@gmx.de> Wed, 07 Aug 2013 21:41:10 +0200
+
bcfg2 (1.4.0pre2-0.0) unstable; urgency=low
* New upstream release
diff --git a/debian/control b/debian/control
index 452fa3d5f..f131bbe05 100644
--- a/debian/control
+++ b/debian/control
@@ -17,8 +17,8 @@ Build-Depends: debhelper (>= 7.0.50~),
python-m2crypto,
python-doc,
python-mock,
- python-mock-doc
-Build-Depends-Indep: python-support (>= 0.5.3)
+ python-mock-doc,
+ dh-python
Standards-Version: 3.8.0.0
Homepage: http://bcfg2.org/
@@ -51,6 +51,16 @@ Description: Configuration management web interface
for clients bound by client profiles.
bcfg2-web is the reporting server for bcfg2.
+Package: bcfg2-utils
+Architecture: all
+Depends: ${python:Depends}, ${misc:Depends}, bcfg2 (= ${binary:Version})
+Suggests: bcfg2-doc (= ${binary:Version})
+Description: Configuration management helper package
+ Bcfg2 is a configuration management system that generates configuration sets
+ for clients bound by client profiles.
+ bcfg2-utils contains scripts for gethering useful information for config
+ creation.
+
Package: bcfg2-doc
Section: doc
Architecture: all
diff --git a/debian/rules b/debian/rules
index eaf80a4d7..102a340e9 100755
--- a/debian/rules
+++ b/debian/rules
@@ -23,3 +23,7 @@ override_dh_auto_build:
override_dh_auto_clean:
dh_auto_clean
rm -rf build
+
+override_dh_auto_install:
+ dh_auto_install
+ install -m 644 -D tools/bcfg2-completion.bash debian/tmp/etc/bash_completion.d/bcfg2
diff --git a/doc/conf.py b/doc/conf.py
index 1da6b3b01..6af9fba05 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -133,7 +133,7 @@ html_theme_options = {
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
-html_favicon = 'favicon.ico'
+html_favicon = '_static/favicon.ico'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
diff --git a/doc/development/compat.txt b/doc/development/compat.txt
index 132bf67c0..a6a85cbab 100644
--- a/doc/development/compat.txt
+++ b/doc/development/compat.txt
@@ -129,7 +129,7 @@ below, since some of these implementations may be feature-incomplete.
+----------------+--------------------------------+--------------------------------------------+
| MutableMapping | :class:`UserDict.DictMixin` | :class:`collections.MutableMapping` (2.6+) |
+----------------+--------------------------------+--------------------------------------------+
-| literal_eval | :func:`eval` | :func:`ast.literal_eval`(2.6+) |
+| literal_eval | :func:`eval` | :func:`ast.literal_eval` (2.6+) |
+----------------+--------------------------------+--------------------------------------------+
walk_packages
diff --git a/doc/releases/index.txt b/doc/releases/index.txt
index db9ba989c..911fe070f 100644
--- a/doc/releases/index.txt
+++ b/doc/releases/index.txt
@@ -11,5 +11,6 @@ Release Announcements
1.4.0pre2
1.4.0pre1
+ 1.3.6
1.3.5
1.3.4
diff --git a/doc/server/plugins/generators/packages.txt b/doc/server/plugins/generators/packages.txt
index 2fe71f895..eea6c6659 100644
--- a/doc/server/plugins/generators/packages.txt
+++ b/doc/server/plugins/generators/packages.txt
@@ -213,7 +213,7 @@ something like this:
Packages plugin to add recommended packages by adding the
:xml:attribute:`SourceType:recommended` attribute, e.g.:
- .. code-block:: xml
+ .. code-block:: none
<Source type="apt" recommended="true" ...>
@@ -222,9 +222,9 @@ something like this:
setting the :xml:attribute:`SourceType:essential`
attribute to *false*:
- .. code-block:: xml
+ .. code-block:: none
- <Source type="apt" essential="false" ...>
+ <Source type="apt" essential="false" ...>
Yum sources can be similarly specified:
diff --git a/doc/server/plugins/grouping/metadata.txt b/doc/server/plugins/grouping/metadata.txt
index 832b1a13f..f0ff2b29c 100644
--- a/doc/server/plugins/grouping/metadata.txt
+++ b/doc/server/plugins/grouping/metadata.txt
@@ -175,6 +175,9 @@ groups:
<Group name="selinux-enabled" negate="true"/>
</Client>
+Negated groups can also be used to declare other Group assignments,
+but not to declare Bundle assignments.
+
.. note::
Nested Group conditionals, Client tags, and negated Group tags are
diff --git a/doc/server/plugins/structures/bundler/index.txt b/doc/server/plugins/structures/bundler/index.txt
index f8962d42c..afdbbecf2 100644
--- a/doc/server/plugins/structures/bundler/index.txt
+++ b/doc/server/plugins/structures/bundler/index.txt
@@ -269,7 +269,7 @@ or alternately
<Path name="/etc/bacula/bconsole.conf"/>
<Path name="/etc/bacula/bacula-fd.conf"/>
<Path name="/etc/bacula/bacula-sd.conf"/>
- <py:if="metadata.hostname == 'foo.bar.com'">
+ <py:if test="metadata.hostname == 'foo.bar.com'">
<Path name="/etc/bacula/bacula-dir.conf"/>
</py:if>
</Bundle>
diff --git a/doc/unsorted/vim_snippet.txt b/doc/unsorted/vim_snippet.txt
index 4598b5c1d..537bb00a2 100644
--- a/doc/unsorted/vim_snippet.txt
+++ b/doc/unsorted/vim_snippet.txt
@@ -13,7 +13,7 @@ that allow quick composition of bundles and base files.
#. Install it using the install instructions (unzip snipMate.zip -d ~/.vim or equivalent, e.g. $HOME\vimfiles on Windows)
#. Add the following to ``~/.vim/snippets/xml.snippets``
- .. code-block:: cl
+ .. code-block:: none
# Bundle
snippet <Bundle
diff --git a/src/lib/Bcfg2/DBSettings.py b/src/lib/Bcfg2/DBSettings.py
index 03e34bbc3..3b5cbbbd8 100644
--- a/src/lib/Bcfg2/DBSettings.py
+++ b/src/lib/Bcfg2/DBSettings.py
@@ -79,7 +79,8 @@ if HAS_DJANGO and django.VERSION[0] == 1 and django.VERSION[1] >= 7:
elif HAS_SOUTH:
settings['INSTALLED_APPS'] += ('south', 'Bcfg2.Reporting')
settings['SOUTH_MIGRATION_MODULES'] = {
- 'Bcfg2.Reporting': 'Bcfg2.Reporting.south_migrations'
+ 'Reporting': 'Bcfg2.Reporting.south_migrations',
+ 'Server': 'Bcfg2.Server.south_migrations',
}
if 'BCFG2_LEGACY_MODELS' in os.environ:
settings['INSTALLED_APPS'] += ('Bcfg2.Server.Reports.reports',)
diff --git a/src/lib/Bcfg2/Server/Core.py b/src/lib/Bcfg2/Server/Core.py
index ad78800fb..445bc17b5 100644
--- a/src/lib/Bcfg2/Server/Core.py
+++ b/src/lib/Bcfg2/Server/Core.py
@@ -91,7 +91,7 @@ def close_db_connection(func):
for connection in django.db.connections.all():
connection.close()
else:
- django.db.close_connection()
+ django.db.close_connection() # pylint: disable=E1101
return rv
return inner
diff --git a/src/lib/Bcfg2/Server/Encryption.py b/src/lib/Bcfg2/Server/Encryption.py
index b60302871..c6cd4232e 100755
--- a/src/lib/Bcfg2/Server/Encryption.py
+++ b/src/lib/Bcfg2/Server/Encryption.py
@@ -176,7 +176,7 @@ def ssl_encrypt(plaintext, passwd, algorithm=None, salt=None):
def is_encrypted(val):
""" Make a best guess if the value is encrypted or not. This just
checks to see if ``val`` is a base64-encoded string whose content
- starts with "Salted__", so it may have (rare) false positives. It
+ starts with "Salted\\_\\_", so it may have (rare) false positives. It
will not have false negatives. """
try:
return b64decode(val).startswith("Salted__")
diff --git a/src/lib/Bcfg2/Server/Plugins/Ldap.py b/src/lib/Bcfg2/Server/Plugins/Ldap.py
index 895c6380f..757150300 100644
--- a/src/lib/Bcfg2/Server/Plugins/Ldap.py
+++ b/src/lib/Bcfg2/Server/Plugins/Ldap.py
@@ -119,22 +119,27 @@ class Ldap(Bcfg2.Server.Plugin.Plugin,
class LdapConnection(Debuggable):
""" Connection to an LDAP server. """
- __scopes__ = {
- 'base': ldap.SCOPE_BASE,
- 'one': ldap.SCOPE_ONELEVEL,
- 'sub': ldap.SCOPE_SUBTREE,
- }
-
def __init__(self, host="localhost", port=389, binddn=None,
bindpw=None):
Debuggable.__init__(self)
+ if HAS_LDAP:
+ msg = "Python ldap module is required for Ldap plugin"
+ self.logger.error(msg)
+ raise Bcfg2.Server.Plugin.PluginInitError(msg)
+
self.host = host
self.port = port
self.binddn = binddn
self.bindpw = bindpw
self.conn = None
+ self.__scopes__ = {
+ 'base': ldap.SCOPE_BASE,
+ 'one': ldap.SCOPE_ONELEVEL,
+ 'sub': ldap.SCOPE_SUBTREE,
+ }
+
def __del__(self):
""" Disconnection if the instance is destroyed. """
self.disconnect()
diff --git a/src/lib/Bcfg2/Server/Plugins/Metadata.py b/src/lib/Bcfg2/Server/Plugins/Metadata.py
index 30f60fffe..40504e15e 100644
--- a/src/lib/Bcfg2/Server/Plugins/Metadata.py
+++ b/src/lib/Bcfg2/Server/Plugins/Metadata.py
@@ -42,6 +42,9 @@ def load_django_models():
HAS_DJANGO = False
return
+ if django.VERSION[0] == 1 and django.VERSION[1] >= 7:
+ django.setup() # pylint: disable=E1101
+
class MetadataClientModel(models.Model, # pylint: disable=W0621
Bcfg2.Server.Plugin.PluginDatabaseModel):
""" django model for storing clients in the database """
@@ -100,9 +103,6 @@ def load_django_models():
except MetadataClientModel.DoesNotExist:
return False
- if django.VERSION[0] == 1 and django.VERSION[1] >= 7:
- django.setup() # pylint: disable=E1101
-
class XMLMetadataConfig(Bcfg2.Server.Plugin.XMLFileBacked):
"""Handles xml config files and all XInclude statements"""
diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/Apt.py b/src/lib/Bcfg2/Server/Plugins/Packages/Apt.py
index 7de79e2f3..2637fadfe 100644
--- a/src/lib/Bcfg2/Server/Plugins/Packages/Apt.py
+++ b/src/lib/Bcfg2/Server/Plugins/Packages/Apt.py
@@ -34,8 +34,12 @@ class AptCollection(Collection):
for source in self:
if source.rawurl:
- self.logger.info("Packages: Skipping rawurl %s" %
- source.rawurl)
+ if source.rawurl[-1] != '/':
+ source.rawurl = source.rawurl + "/"
+ index = source.rawurl.rfind("/", 0, -1)
+ lines.append("deb %s %s" %
+ (source.rawurl[:index],
+ source.rawurl[index + 1:]))
else:
lines.append("deb %s %s %s" % (source.url, source.version,
" ".join(source.components)))
@@ -44,7 +48,7 @@ class AptCollection(Collection):
(source.url,
source.version,
" ".join(source.components)))
- lines.append("")
+ lines.append("")
return "\n".join(lines)
diff --git a/src/lib/Bcfg2/Server/Plugins/Probes.py b/src/lib/Bcfg2/Server/Plugins/Probes.py
index 573c9af71..33b0d4284 100644
--- a/src/lib/Bcfg2/Server/Plugins/Probes.py
+++ b/src/lib/Bcfg2/Server/Plugins/Probes.py
@@ -27,13 +27,18 @@ def load_django_models():
# pylint: disable=W0602
global ProbesDataModel, ProbesGroupsModel, HAS_DJANGO
# pylint: enable=W0602
+
try:
+ import django
from django.db import models
HAS_DJANGO = True
except ImportError:
HAS_DJANGO = False
return
+ if django.VERSION[0] == 1 and django.VERSION[1] >= 7:
+ django.setup() # pylint: disable=E1101
+
class ProbesDataModel(models.Model, # pylint: disable=W0621,W0612
Bcfg2.Server.Plugin.PluginDatabaseModel):
""" The database model for storing probe data """
diff --git a/src/lib/Bcfg2/Server/migrations/0001_initial.py b/src/lib/Bcfg2/Server/migrations/0001_initial.py
new file mode 100644
index 000000000..3b3dca455
--- /dev/null
+++ b/src/lib/Bcfg2/Server/migrations/0001_initial.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.9 on 2016-08-17 18:52
+from __future__ import unicode_literals
+
+import Bcfg2.Server.Plugin.helpers
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='MetadataClientModel',
+ fields=[
+ ('hostname', models.CharField(max_length=255, primary_key=True, serialize=False)),
+ ('version', models.CharField(max_length=31, null=True)),
+ ],
+ bases=(models.Model, Bcfg2.Server.Plugin.helpers.PluginDatabaseModel),
+ ),
+ migrations.CreateModel(
+ name='ProbesDataModel',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('hostname', models.CharField(max_length=255)),
+ ('probe', models.CharField(max_length=255)),
+ ('timestamp', models.DateTimeField(auto_now=True)),
+ ('data', models.TextField(null=True)),
+ ],
+ bases=(models.Model, Bcfg2.Server.Plugin.helpers.PluginDatabaseModel),
+ ),
+ migrations.CreateModel(
+ name='ProbesGroupsModel',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('hostname', models.CharField(max_length=255)),
+ ('group', models.CharField(max_length=255)),
+ ],
+ bases=(models.Model, Bcfg2.Server.Plugin.helpers.PluginDatabaseModel),
+ ),
+ ]
diff --git a/src/lib/Bcfg2/Server/migrations/__init__.py b/src/lib/Bcfg2/Server/migrations/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/lib/Bcfg2/Server/migrations/__init__.py
diff --git a/src/lib/Bcfg2/Server/models.py b/src/lib/Bcfg2/Server/models.py
index 9c0153c74..7f28fd0d8 100644
--- a/src/lib/Bcfg2/Server/models.py
+++ b/src/lib/Bcfg2/Server/models.py
@@ -4,20 +4,44 @@ import sys
import logging
import Bcfg2.Options
import Bcfg2.Server.Plugins
+from Bcfg2.Compat import walk_packages
-LOGGER = logging.getLogger(__name__)
+LOGGER = logging.getLogger('Bcfg2.Server.models')
MODELS = []
INTERNAL_DATABASE_VERSION = None
-class _OptionContainer(object):
- """Options for Bcfg2 database models."""
+def _get_all_plugins():
+ rv = []
+ for submodule in walk_packages(path=Bcfg2.Server.Plugins.__path__,
+ prefix="Bcfg2.Server.Plugins."):
+ module = submodule[1].rsplit('.', 1)[-1]
+ if module == 'Reporting':
+ # Exclude Reporting plugin. The reporting database
+ # is handled separately in Bcfg2.Reporting.
+ continue
+ if submodule[1] == "Bcfg2.Server.Plugins.%s" % module:
+ # we only include direct children of
+ # Bcfg2.Server.Plugins -- e.g., all_plugins should
+ # include Bcfg2.Server.Plugins.Cfg, but not
+ # Bcfg2.Server.Plugins.Cfg.CfgInfoXML
+ rv.append(module)
+ return rv
+
+
+_ALL_PLUGINS = _get_all_plugins()
+
+class _OptionContainer(object):
# we want to provide a different default plugin list --
# namely, _all_ plugins, so that the database is guaranteed to
# work, even if /etc/bcfg2.conf isn't set up properly
- options = [Bcfg2.Options.Common.plugins]
+ options = [
+ Bcfg2.Options.Option(
+ cf=('server', 'plugins'), type=Bcfg2.Options.Types.comma_list,
+ default=_ALL_PLUGINS, dest="models_plugins",
+ action=Bcfg2.Options.PluginsAction)]
@staticmethod
def options_parsed_hook():
@@ -39,7 +63,7 @@ def load_models(plugins=None):
global MODELS
if not plugins:
- plugins = Bcfg2.Options.setup.plugins
+ plugins = Bcfg2.Options.setup.models_plugins
if MODELS:
# load_models() has been called once, so first unload all of
diff --git a/src/lib/Bcfg2/Server/south_migrations/0001_initial.py b/src/lib/Bcfg2/Server/south_migrations/0001_initial.py
new file mode 100644
index 000000000..864c311e5
--- /dev/null
+++ b/src/lib/Bcfg2/Server/south_migrations/0001_initial.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+from south.utils import datetime_utils as datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding model 'MetadataClientModel'
+ db.create_table(u'Server_metadataclientmodel', (
+ ('hostname', self.gf('django.db.models.fields.CharField')(max_length=255, primary_key=True)),
+ ('version', self.gf('django.db.models.fields.CharField')(max_length=31, null=True)),
+ ))
+ db.send_create_signal('Server', ['MetadataClientModel'])
+
+ # Adding model 'ProbesDataModel'
+ db.create_table(u'Server_probesdatamodel', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('hostname', self.gf('django.db.models.fields.CharField')(max_length=255)),
+ ('probe', self.gf('django.db.models.fields.CharField')(max_length=255)),
+ ('timestamp', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
+ ('data', self.gf('django.db.models.fields.TextField')(null=True)),
+ ))
+ db.send_create_signal('Server', ['ProbesDataModel'])
+
+ # Adding model 'ProbesGroupsModel'
+ db.create_table(u'Server_probesgroupsmodel', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('hostname', self.gf('django.db.models.fields.CharField')(max_length=255)),
+ ('group', self.gf('django.db.models.fields.CharField')(max_length=255)),
+ ))
+ db.send_create_signal('Server', ['ProbesGroupsModel'])
+
+
+ def backwards(self, orm):
+ # Deleting model 'MetadataClientModel'
+ db.delete_table(u'Server_metadataclientmodel')
+
+ # Deleting model 'ProbesDataModel'
+ db.delete_table(u'Server_probesdatamodel')
+
+ # Deleting model 'ProbesGroupsModel'
+ db.delete_table(u'Server_probesgroupsmodel')
+
+
+ models = {
+ 'Server.metadataclientmodel': {
+ 'Meta': {'object_name': 'MetadataClientModel'},
+ 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '255', 'primary_key': 'True'}),
+ 'version': ('django.db.models.fields.CharField', [], {'max_length': '31', 'null': 'True'})
+ },
+ 'Server.probesdatamodel': {
+ 'Meta': {'object_name': 'ProbesDataModel'},
+ 'data': ('django.db.models.fields.TextField', [], {'null': 'True'}),
+ 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'probe': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
+ },
+ 'Server.probesgroupsmodel': {
+ 'Meta': {'object_name': 'ProbesGroupsModel'},
+ 'group': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'hostname': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+ }
+ }
+
+ complete_apps = ['Server'] \ No newline at end of file
diff --git a/src/lib/Bcfg2/Server/south_migrations/__init__.py b/src/lib/Bcfg2/Server/south_migrations/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/lib/Bcfg2/Server/south_migrations/__init__.py
diff --git a/src/lib/Bcfg2/manage.py b/src/lib/Bcfg2/manage.py
index f88233133..b156deb0f 100755
--- a/src/lib/Bcfg2/manage.py
+++ b/src/lib/Bcfg2/manage.py
@@ -5,19 +5,19 @@ import django
import Bcfg2.Options
import Bcfg2.DBSettings
-Bcfg2.Options.get_parser().parse()
+try:
+ import Bcfg2.Server.models
+except ImportError:
+ pass
-if django.VERSION[0] == 1 and django.VERSION[1] <= 6:
- try:
- imp.find_module('settings') # Assumed to be in the same directory.
- except ImportError:
- import sys
- sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
- sys.exit(1)
+parser = Bcfg2.Options.get_parser()
+parser.add_options([Bcfg2.Options.PositionalArgument('django_command', nargs='*')])
+parser.parse()
if __name__ == "__main__":
- if django.VERSION[0] == 1 and django.VERSION[1] >= 7:
+ if django.VERSION[0] == 1 and django.VERSION[1] >= 6:
from django.core.management import execute_from_command_line
- execute_from_command_line(sys.argv)
+ execute_from_command_line(sys.argv[:1] + Bcfg2.Options.setup.django_command)
else:
- execute_manager(settings)
+ from django.core.management import execute_manager
+ execute_manager(Bcfg2.DBSettings.settings)
diff --git a/testsuite/Testsrc/test_code_checks.py b/testsuite/Testsrc/test_code_checks.py
index 6d3c4c714..c26d8c139 100644
--- a/testsuite/Testsrc/test_code_checks.py
+++ b/testsuite/Testsrc/test_code_checks.py
@@ -76,6 +76,8 @@ no_checks = {
"lib/Bcfg2": ["manage.py"],
"lib/Bcfg2/Server/Reports": ["manage.py"],
"lib/Bcfg2/Server/Plugins": ["Base.py"],
+ "lib/Bcfg2/Server/migrations": ["*.py"],
+ "lib/Bcfg2/Server/south_migrations": ["*.py"],
}
if sys.version_info < (2, 6):
# multiprocessing core requires py2.6
diff --git a/testsuite/Testsrc/test_doc.py b/testsuite/Testsrc/test_doc.py
new file mode 100644
index 000000000..93c8d1bb4
--- /dev/null
+++ b/testsuite/Testsrc/test_doc.py
@@ -0,0 +1,39 @@
+import os
+import sys
+
+# add all parent testsuite directories to sys.path to allow (most)
+# relative imports in python 2.4
+_path = os.path.dirname(__file__)
+while _path != '/':
+ if os.path.basename(_path).lower().startswith("test"):
+ sys.path.append(_path)
+ if os.path.basename(_path) == "testsuite":
+ break
+ _path = os.path.dirname(_path)
+from common import *
+
+
+try:
+ from sphinx.application import Sphinx
+ HAS_SPHINX = True
+except ImportError:
+ HAS_SPHINX = False
+
+
+TEST_SPHINX = bool(os.environ.get('TEST_SPHINX', 'yes') != 'no')
+
+
+class DocTest(Bcfg2TestCase):
+ top = os.path.join(os.path.dirname(__file__), '..', '..')
+ source_dir = os.path.join(top, 'doc/')
+ doctree_dir = os.path.join(top, 'build', 'doctree')
+
+ @skipUnless(HAS_SPHINX, 'Sphinx not found')
+ @skipUnless(TEST_SPHINX, 'Documentation testing disabled')
+ def test_html_documentation(self):
+ output_dir = os.path.join(self.top, 'build', 'html')
+
+ app = Sphinx(self.source_dir, self.source_dir, output_dir,
+ self.doctree_dir, buildername='html',
+ warningiserror=True)
+ app.build(force_all=True)
diff --git a/testsuite/common.py b/testsuite/common.py
index 396f1887b..9db2cb94a 100644
--- a/testsuite/common.py
+++ b/testsuite/common.py
@@ -219,12 +219,18 @@ class DBModelTestCase(Bcfg2TestCase):
def test_syncdb(self):
""" Create the test database and sync the schema """
if self.models:
- import django.core.management
import django
- if django.VERSION[0] == 1 and django.VERSION[1] >= 7:
- django.setup()
+ import django.core.management
+ from django.core.exceptions import ImproperlyConfigured
+
+ if django.VERSION[0] == 1 and django.VERSION[1] < 7:
+ try:
+ django.core.management.call_command('syncdb', interactive=False,
+ verbosity=0)
+ except ImproperlyConfigured:
+ pass
- django.core.management.call_command("syncdb", interactive=False,
+ django.core.management.call_command('migrate', interactive=False,
verbosity=0)
self.assertTrue(
os.path.exists(
diff --git a/testsuite/install.sh b/testsuite/install.sh
index 42d5bbadb..d8e5079be 100755
--- a/testsuite/install.sh
+++ b/testsuite/install.sh
@@ -10,19 +10,23 @@ pip install -r testsuite/requirements.txt
PYVER=$(python -c 'import sys;print(".".join(str(v) for v in sys.version_info[0:2]))')
if [[ ${PYVER:0:1} == "2" && $PYVER != "2.7" ]]; then
- pip install --use-mirrors unittest2
+ pip install unittest2
fi
if [[ "$WITH_OPTIONAL_DEPS" == "yes" ]]; then
- sudo apt-get install -y yum libaugeas0 augeas-lenses libacl1-dev libssl-dev
+ sudo apt-get install -y yum libaugeas0 augeas-lenses libacl1-dev libssl-dev \
+ python-gamin python-selinux
- pip install --use-mirrors PyYAML pyinotify boto pylibacl 'django<1.5' \
- Jinja2 mercurial guppy
+ pip install PyYAML pyinotify boto pylibacl Jinja2 mercurial guppy cherrypy
easy_install https://fedorahosted.org/released/python-augeas/python-augeas-0.4.1.tar.gz
+
if [[ ${PYVER:0:1} == "2" ]]; then
- # django supports py3k, but South doesn't, and the django bits
- # in bcfg2 require South
- pip install cheetah 'South<0.8'
- pip install m2crypto
+ pip install cheetah m2crypto
+
+ if [[ $PYVER != "2.7" ]]; then
+ pip install 'django<1.7' 'South<0.8'
+ else
+ pip install 'django<1.10'
+ fi
fi
fi