summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2012-07-31 09:12:01 -0400
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2012-07-31 09:12:07 -0400
commit111193ef96adb711b1b1b4859291c77197eb8ea8 (patch)
tree6e5fbb39ec3aca1daffc107407fddf58260983b6 /src
parent211864073d9254f9d116ee052092f1949775f544 (diff)
downloadbcfg2-111193ef96adb711b1b1b4859291c77197eb8ea8.tar.gz
bcfg2-111193ef96adb711b1b1b4859291c77197eb8ea8.tar.bz2
bcfg2-111193ef96adb711b1b1b4859291c77197eb8ea8.zip
unified Metadata/DBMetadata plugins
made django optional
Diffstat (limited to 'src')
-rw-r--r--src/lib/Bcfg2/Server/Plugin.py21
-rw-r--r--src/lib/Bcfg2/Server/Plugins/DBMetadata.py128
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Metadata.py179
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Probes.py34
-rw-r--r--src/lib/Bcfg2/settings.py11
5 files changed, 191 insertions, 182 deletions
diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py
index 696dacc06..2a68ea3b7 100644
--- a/src/lib/Bcfg2/Server/Plugin.py
+++ b/src/lib/Bcfg2/Server/Plugin.py
@@ -11,9 +11,14 @@ import sys
import threading
import Bcfg2.Server
from Bcfg2.Bcfg2Py3k import ConfigParser
-
import Bcfg2.Options
+try:
+ import django
+ has_django = True
+except ImportError:
+ has_django = False
+
# py3k compatibility
if sys.hexversion >= 0x03000000:
from functools import reduce
@@ -106,6 +111,20 @@ class DatabaseBacked(object):
def __init__(self):
pass
+ @property
+ def _use_db(self):
+ use_db = self.core.setup.cfp.getboolean(self.name.lower(),
+ "use_database",
+ default=False)
+ if use_db and has_django:
+ return True
+ elif not use_db:
+ return False
+ else:
+ self.logger.error("use_database is true but django not found")
+ return False
+
+
class PluginDatabaseModel(object):
class Meta:
diff --git a/src/lib/Bcfg2/Server/Plugins/DBMetadata.py b/src/lib/Bcfg2/Server/Plugins/DBMetadata.py
deleted file mode 100644
index 16a6e0dcc..000000000
--- a/src/lib/Bcfg2/Server/Plugins/DBMetadata.py
+++ /dev/null
@@ -1,128 +0,0 @@
-import os
-import sys
-from UserDict import DictMixin
-from django.db import models
-import Bcfg2.Server.Lint
-import Bcfg2.Server.Plugin
-from Bcfg2.Server.Plugins.Metadata import *
-
-class MetadataClientModel(models.Model,
- Bcfg2.Server.Plugin.PluginDatabaseModel):
- hostname = models.CharField(max_length=255, primary_key=True)
- version = models.CharField(max_length=31, null=True)
-
-
-class ClientVersions(DictMixin):
- def __getitem__(self, key):
- try:
- return MetadataClientModel.objects.get(hostname=key).version
- except MetadataClientModel.DoesNotExist:
- raise KeyError(key)
-
- def __setitem__(self, key, value):
- client = MetadataClientModel.objects.get_or_create(hostname=key)[0]
- client.version = value
- client.save()
-
- def keys(self):
- return [c.hostname for c in MetadataClientModel.objects.all()]
-
- def __contains__(self, key):
- try:
- client = MetadataClientModel.objects.get(hostname=key)
- return True
- except MetadataClientModel.DoesNotExist:
- return False
-
-
-class DBMetadata(Metadata, Bcfg2.Server.Plugin.DatabaseBacked):
- __files__ = ["groups.xml"]
- experimental = True
- conflicts = ['Metadata']
-
- def __init__(self, core, datastore, watch_clients=True):
- Metadata.__init__(self, core, datastore, watch_clients=watch_clients)
- Bcfg2.Server.Plugin.DatabaseBacked.__init__(self)
- if os.path.exists(os.path.join(self.data, "clients.xml")):
- self.logger.warning("DBMetadata: clients.xml found, parsing in "
- "compatibility mode")
- self._handle_file("clients.xml")
- self.versions = ClientVersions()
-
- def add_group(self, group_name, attribs):
- msg = "DBMetadata does not support adding groups"
- self.logger.error(msg)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
-
- def add_bundle(self, bundle_name):
- msg = "DBMetadata does not support adding bundles"
- self.logger.error(msg)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
-
- def add_client(self, client_name):
- """Add client to clients database."""
- client = MetadataClientModel(hostname=client_name)
- client.save()
- self.clients = self.list_clients()
- return client
-
- def update_group(self, group_name, attribs):
- msg = "DBMetadata does not support updating groups"
- self.logger.error(msg)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
-
- def update_bundle(self, bundle_name):
- msg = "DBMetadata does not support updating bundles"
- self.logger.error(msg)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
-
- def update_client(self, client_name, attribs):
- msg = "DBMetadata does not support updating clients"
- self.logger.error(msg)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
-
- def list_clients(self):
- """ List all clients in client database """
- return set([c.hostname for c in MetadataClientModel.objects.all()])
-
- def remove_group(self, group_name, attribs):
- msg = "DBMetadata does not support removing groups"
- self.logger.error(msg)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
-
- def remove_bundle(self, bundle_name):
- msg = "DBMetadata does not support removing bundles"
- self.logger.error(msg)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
-
- def remove_client(self, client_name):
- """Remove a client"""
- try:
- client = MetadataClientModel.objects.get(hostname=client_name)
- except MetadataClientModel.DoesNotExist:
- msg = "Client %s does not exist" % client_name
- self.logger.warning(msg)
- raise MetadataConsistencyError(msg)
- client.delete()
- self.clients = self.list_clients()
-
- def _set_profile(self, client, profile, addresspair):
- if client not in self.clients:
- # adding a new client
- self.add_client(client)
- if client not in self.clientgroups:
- self.clientgroups[client] = [profile]
- else:
- msg = "DBMetadata does not support asserting client profiles"
- self.logger.error(msg)
- raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
-
- def _handle_clients_xml_event(self, event):
- # clients.xml is parsed and the options specified in it are
- # understood, but it does _not_ assert client existence.
- Metadata._handle_clients_xml_event(self, event)
- self.clients = self.list_clients()
-
-
-class DBMetadataLint(MetadataLint):
- pass
diff --git a/src/lib/Bcfg2/Server/Plugins/Metadata.py b/src/lib/Bcfg2/Server/Plugins/Metadata.py
index 5dcaa8bdb..07659b62a 100644
--- a/src/lib/Bcfg2/Server/Plugins/Metadata.py
+++ b/src/lib/Bcfg2/Server/Plugins/Metadata.py
@@ -3,19 +3,27 @@ This file stores persistent metadata for the Bcfg2 Configuration Repository.
"""
import re
-import copy
-import fcntl
-import lxml.etree
import os
-import socket
import sys
import time
+import copy
+import fcntl
+import socket
+import lxml.etree
import Bcfg2.Server
import Bcfg2.Server.Lint
import Bcfg2.Server.Plugin
import Bcfg2.Server.FileMonitor
+from UserDict import DictMixin
from Bcfg2.version import Bcfg2VersionInfo
+try:
+ from django.db import models
+ has_django = True
+except ImportError:
+ has_django = False
+
+
def locked(fd):
"""Aquire a lock on a file"""
try:
@@ -25,6 +33,35 @@ def locked(fd):
return False
+if has_django:
+ class MetadataClientModel(models.Model,
+ Bcfg2.Server.Plugin.PluginDatabaseModel):
+ hostname = models.CharField(max_length=255, primary_key=True)
+ version = models.CharField(max_length=31, null=True)
+
+ class ClientVersions(DictMixin):
+ def __getitem__(self, key):
+ try:
+ return MetadataClientModel.objects.get(hostname=key).version
+ except MetadataClientModel.DoesNotExist:
+ raise KeyError(key)
+
+ def __setitem__(self, key, value):
+ client = MetadataClientModel.objects.get_or_create(hostname=key)[0]
+ client.version = value
+ client.save()
+
+ def keys(self):
+ return [c.hostname for c in MetadataClientModel.objects.all()]
+
+ def __contains__(self, key):
+ try:
+ client = MetadataClientModel.objects.get(hostname=key)
+ return True
+ except MetadataClientModel.DoesNotExist:
+ return False
+
+
class MetadataConsistencyError(Exception):
"""This error gets raised when metadata is internally inconsistent."""
pass
@@ -264,23 +301,30 @@ class MetadataGroup(tuple):
class Metadata(Bcfg2.Server.Plugin.Plugin,
Bcfg2.Server.Plugin.Metadata,
- Bcfg2.Server.Plugin.Statistics):
+ Bcfg2.Server.Plugin.Statistics,
+ Bcfg2.Server.Plugin.DatabaseBacked):
"""This class contains data for bcfg2 server metadata."""
__author__ = 'bcfg-dev@mcs.anl.gov'
name = "Metadata"
sort_order = 500
- __files__ = ["groups.xml", "clients.xml"]
def __init__(self, core, datastore, watch_clients=True):
Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
Bcfg2.Server.Plugin.Metadata.__init__(self)
Bcfg2.Server.Plugin.Statistics.__init__(self)
+ Bcfg2.Server.Plugin.DatabaseBacked.__init__(self)
self.watch_clients = watch_clients
self.states = dict()
self.extra = dict()
self.handlers = []
- for fname in self.__files__:
- self._handle_file(fname)
+ self._handle_file("groups.xml")
+ if (self._use_db and
+ os.path.exists(os.path.join(self.data, "clients.xml"))):
+ self.logger.warning("Metadata: database enabled but clients.xml"
+ "found, parsing in compatibility mode")
+ self._handle_file("clients.xml")
+ elif not self._use_db:
+ self._handle_file("clients.xml")
# mapping of clientname -> authtype
self.auth = dict()
@@ -304,7 +348,10 @@ class Metadata(Bcfg2.Server.Plugin.Plugin,
self.group_membership = dict()
self.negated_groups = dict()
# mapping of hostname -> version string
- self.versions = dict()
+ if self._use_db:
+ self.versions = ClientVersions()
+ else:
+ self.versions = dict()
self.uuid = {}
self.session_cache = {}
self.default = None
@@ -322,7 +369,7 @@ class Metadata(Bcfg2.Server.Plugin.Plugin,
# must use super here; inheritance works funny with class methods
super(Metadata, cls).init_repo(repo)
- for fname in cls.__files__:
+ for fname in ["clients.xml", "groups.xml"]:
aname = re.sub(r'[^A-z0-9_]', '_', fname)
if aname in kwargs:
open(os.path.join(repo, cls.name, fname),
@@ -380,17 +427,36 @@ class Metadata(Bcfg2.Server.Plugin.Plugin,
def add_group(self, group_name, attribs):
"""Add group to groups.xml."""
- return self._add_xdata(self.groups_xml, "Group", group_name,
- attribs=attribs)
+ if self._use_db:
+ msg = "Metadata does not support adding groups with use_database enabled"
+ self.logger.error(msg)
+ raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+ else:
+ return self._add_xdata(self.groups_xml, "Group", group_name,
+ attribs=attribs)
def add_bundle(self, bundle_name):
"""Add bundle to groups.xml."""
- return self._add_xdata(self.groups_xml, "Bundle", bundle_name)
+ if self._use_db:
+ msg = "Metadata does not support adding bundles with use_database enabled"
+ self.logger.error(msg)
+ raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+ else:
+ return self._add_xdata(self.groups_xml, "Bundle", bundle_name)
- def add_client(self, client_name, attribs):
+ def add_client(self, client_name, attribs=None):
"""Add client to clients.xml."""
- return self._add_xdata(self.clients_xml, "Client", client_name,
- attribs=attribs, alias=True)
+ print "add_client(%s, attribs=%s)" % (client_name, attribs)
+ if attribs is None:
+ attribs = dict()
+ if self._use_db:
+ client = MetadataClientModel(hostname=client_name)
+ client.save()
+ self.clients = self.list_clients()
+ return client
+ else:
+ 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)
@@ -409,12 +475,30 @@ class Metadata(Bcfg2.Server.Plugin.Plugin,
def update_group(self, group_name, attribs):
"""Update a groups attributes."""
- return self._update_xdata(self.groups_xml, "Group", group_name, attribs)
+ if self._use_db:
+ msg = "Metadata does not support updating groups with use_database enabled"
+ self.logger.error(msg)
+ raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+ else:
+ 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)
+ if self._use_db:
+ msg = "Metadata does not support updating clients with use_database enabled"
+ self.logger.error(msg)
+ raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+ else:
+ return self._update_xdata(self.clients_xml, "Client", client_name,
+ attribs, alias=True)
+
+ def list_clients(self):
+ """ List all clients in client database """
+ if self._use_db:
+ return set([c.hostname for c in MetadataClientModel.objects.all()])
+ else:
+ return self.clients
def _remove_xdata(self, config, tag, name, alias=False):
node = self._search_xdata(tag, name, config.xdata)
@@ -432,15 +516,35 @@ class Metadata(Bcfg2.Server.Plugin.Plugin,
def remove_group(self, group_name):
"""Remove a group."""
- return self._remove_xdata(self.groups_xml, "Group", group_name)
+ if self._use_db:
+ msg = "Metadata does not support removing groups with use_database enabled"
+ self.logger.error(msg)
+ raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+ else:
+ return self._remove_xdata(self.groups_xml, "Group", group_name)
def remove_bundle(self, bundle_name):
"""Remove a bundle."""
- return self._remove_xdata(self.groups_xml, "Bundle", bundle_name)
+ if self._use_db:
+ msg = "Metadata does not support removing bundles with use_database enabled"
+ self.logger.error(msg)
+ raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+ else:
+ return self._remove_xdata(self.groups_xml, "Bundle", bundle_name)
def remove_client(self, client_name):
"""Remove a bundle."""
- return self._remove_xdata(self.clients_xml, "Client", client_name)
+ if self._use_db:
+ try:
+ client = MetadataClientModel.objects.get(hostname=client_name)
+ except MetadataClientModel.DoesNotExist:
+ msg = "Client %s does not exist" % client_name
+ self.logger.warning(msg)
+ raise MetadataConsistencyError(msg)
+ client.delete()
+ self.clients = self.list_clients()
+ else:
+ return self._remove_xdata(self.clients_xml, "Client", client_name)
def _handle_clients_xml_event(self, event):
xdata = self.clients_xml.xdata
@@ -497,6 +601,8 @@ class Metadata(Bcfg2.Server.Plugin.Plugin,
except KeyError:
self.clientgroups[clname] = [client.get('profile')]
self.states['clients.xml'] = True
+ if self._use_db:
+ self.clients = self.list_clients()
def _handle_groups_xml_event(self, event):
self.groups = {}
@@ -627,10 +733,13 @@ class Metadata(Bcfg2.Server.Plugin.Plugin,
msg = "Cannot set client %s to private group %s" % (client, profile)
self.logger.error(msg)
raise MetadataConsistencyError(msg)
- self._set_profile(client, profile, addresspair)
- def _set_profile(self, client, profile, addresspair):
if client in self.clients:
+ if self._use_db:
+ msg = "DBMetadata does not support asserting client profiles"
+ self.logger.error(msg)
+ raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
+
profiles = [g for g in self.clientgroups[client]
if g in self.groups and self.groups[g].is_profile]
self.logger.info("Changing %s profile from %s to %s" %
@@ -645,16 +754,20 @@ class Metadata(Bcfg2.Server.Plugin.Plugin,
else:
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
- self.add_client(self.session_cache[addresspair][1],
- dict(uuid=client, profile=profile,
- address=addresspair[0]))
+ if self._use_db:
+ self.add_client(client)
else:
- self.add_client(client, dict(profile=profile))
- self.clients.append(client)
- self.clientgroups[client] = [profile]
- self.clients_xml.write()
+ if addresspair in self.session_cache:
+ # we are working with a uuid'd client
+ self.add_client(self.session_cache[addresspair][1],
+ dict(uuid=client, profile=profile,
+ address=addresspair[0]))
+ else:
+ self.add_client(client, dict(profile=profile))
+ self.clients.append(client)
+ self.clientgroups[client] = [profile]
+ if not self._use_db:
+ self.clients_xml.write()
def set_version(self, client, version):
"""Set group parameter for provided client."""
diff --git a/src/lib/Bcfg2/Server/Plugins/Probes.py b/src/lib/Bcfg2/Server/Plugins/Probes.py
index 3932c44d1..114a9bbd8 100644
--- a/src/lib/Bcfg2/Server/Plugins/Probes.py
+++ b/src/lib/Bcfg2/Server/Plugins/Probes.py
@@ -5,10 +5,15 @@ import time
import operator
import lxml.etree
import Bcfg2.Server
-from django.db import models
import Bcfg2.Server.Plugin
try:
+ from django.db import models
+ has_django = True
+except ImportError:
+ has_django = False
+
+try:
import json
has_json = True
except ImportError:
@@ -32,18 +37,18 @@ except ImportError:
import Bcfg2.Server.Plugin
-class ProbesDataModel(models.Model,
- Bcfg2.Server.Plugin.PluginDatabaseModel):
- hostname = models.CharField(max_length=255)
- probe = models.CharField(max_length=255)
- timestamp = models.DateTimeField(auto_now=True)
- data = models.TextField(null=True)
+if has_django:
+ class ProbesDataModel(models.Model,
+ Bcfg2.Server.Plugin.PluginDatabaseModel):
+ hostname = models.CharField(max_length=255)
+ probe = models.CharField(max_length=255)
+ timestamp = models.DateTimeField(auto_now=True)
+ data = models.TextField(null=True)
-
-class ProbesGroupsModel(models.Model,
- Bcfg2.Server.Plugin.PluginDatabaseModel):
- hostname = models.CharField(max_length=255)
- group = models.CharField(max_length=255)
+ class ProbesGroupsModel(models.Model,
+ Bcfg2.Server.Plugin.PluginDatabaseModel):
+ hostname = models.CharField(max_length=255)
+ group = models.CharField(max_length=255)
class ClientProbeDataSet(dict):
@@ -172,11 +177,6 @@ class Probes(Bcfg2.Server.Plugin.Plugin,
self.cgroups = dict()
self.load_data()
- @property
- def _use_db(self):
- return self.core.setup.cfp.getboolean("probes", "use_database",
- default=False)
-
def write_data(self, client):
"""Write probe data out for use with bcfg2-info."""
if self._use_db:
diff --git a/src/lib/Bcfg2/settings.py b/src/lib/Bcfg2/settings.py
index 5de590fec..c72ef0ebe 100644
--- a/src/lib/Bcfg2/settings.py
+++ b/src/lib/Bcfg2/settings.py
@@ -1,7 +1,12 @@
import sys
-import django
import Bcfg2.Options
+try:
+ import django
+ has_django = True
+except:
+ has_django = False
+
DATABASES = dict()
# Django < 1.2 compat
@@ -39,7 +44,7 @@ def read_config(cfile='/etc/bcfg2.conf', repo=None, quiet=False):
HOST=setup['db_host'],
PORT=setup['db_port'])
- if django.VERSION[0] == 1 and django.VERSION[1] < 2:
+ if has_django and django.VERSION[0] == 1 and django.VERSION[1] < 2:
DATABASE_ENGINE = setup['db_engine']
DATABASE_NAME = DATABASES['default']['NAME']
DATABASE_USER = DATABASES['default']['USER']
@@ -51,7 +56,7 @@ def read_config(cfile='/etc/bcfg2.conf', repo=None, quiet=False):
# this lets manage.py work in all cases
read_config(quiet=True)
-if django.VERSION[0] == 1 and django.VERSION[1] > 2:
+if has_django and django.VERSION[0] == 1 and django.VERSION[1] > 2:
TIME_ZONE = None
DEBUG = False