summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2013-09-05 13:07:42 -0400
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2013-09-05 13:07:43 -0400
commitf8416134cc80d704e6f139aa1ab1ce47e00e4f7f (patch)
tree517443490d17699c0c40ee165adb0ae80ab6146d /src/lib
parent5c9cd24767bcbc8cdb39eebf2fd81e9c814c01af (diff)
downloadbcfg2-f8416134cc80d704e6f139aa1ab1ce47e00e4f7f.tar.gz
bcfg2-f8416134cc80d704e6f139aa1ab1ce47e00e4f7f.tar.bz2
bcfg2-f8416134cc80d704e6f139aa1ab1ce47e00e4f7f.zip
Allow Connector to create new groups
Connector plugins can now create new groups, including the full range of options on those groups (profile, public, category, etc.).
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/Bcfg2/Server/Core.py36
-rw-r--r--src/lib/Bcfg2/Server/Plugin/interfaces.py24
-rw-r--r--src/lib/Bcfg2/Server/Plugins/GroupLogic.py11
3 files changed, 66 insertions, 5 deletions
diff --git a/src/lib/Bcfg2/Server/Core.py b/src/lib/Bcfg2/Server/Core.py
index a8601fd08..5482e32fe 100644
--- a/src/lib/Bcfg2/Server/Core.py
+++ b/src/lib/Bcfg2/Server/Core.py
@@ -22,6 +22,7 @@ from Bcfg2.Compat import xmlrpclib # pylint: disable=W0622
from Bcfg2.Server.Plugin.exceptions import * # pylint: disable=W0401,W0614
from Bcfg2.Server.Plugin.interfaces import * # pylint: disable=W0401,W0614
from Bcfg2.Server.Plugin import track_statistics
+from Bcfg2.Server.Plugins.Metadata import MetadataGroup
try:
import psyco
@@ -200,6 +201,10 @@ class BaseCore(object):
# load plugins
Bcfg2.settings.read_config(repo=self.datastore)
+ # mapping of group name => plugin name to record where groups
+ # that are created by Connector plugins came from
+ self._dynamic_groups = dict()
+
#: Whether or not it's possible to use the Django database
#: backend for plugins that have that capability
self._database_available = False
@@ -882,8 +887,35 @@ class BaseCore(object):
(client_name, sys.exc_info()[1]))
connectors = self.plugins_by_type(Connector)
for conn in connectors:
- grps = conn.get_additional_groups(imd)
- self.metadata.merge_additional_groups(imd, grps)
+ groups = conn.get_additional_groups(imd)
+ groupnames = []
+ for group in groups:
+ if isinstance(group, MetadataGroup):
+ groupname = group.name
+ if groupname in self._dynamic_groups:
+ if self._dynamic_groups[groupname] == conn.name:
+ self.metadata.groups[groupname] = group
+ else:
+ self.logger.warning(
+ "Refusing to clobber dynamic group %s "
+ "defined by %s" %
+ (self._dynamic_groups[groupname],
+ groupname))
+ elif groupname in self.metadata.groups:
+ # not recorded as a dynamic group, but
+ # present in metadata.groups -- i.e., a
+ # static group
+ self.logger.warning(
+ "Refusing to clobber predefined group %s" %
+ groupname)
+ else:
+ self.metadata.groups[groupname] = group
+ self._dynamic_groups[groupname] = conn.name
+ groupnames.append(groupname)
+ else:
+ groupnames.append(group)
+
+ self.metadata.merge_additional_groups(imd, groupnames)
for conn in connectors:
data = conn.get_additional_data(imd)
self.metadata.merge_additional_data(imd, conn.name, data)
diff --git a/src/lib/Bcfg2/Server/Plugin/interfaces.py b/src/lib/Bcfg2/Server/Plugin/interfaces.py
index 376030792..33f6d338c 100644
--- a/src/lib/Bcfg2/Server/Plugin/interfaces.py
+++ b/src/lib/Bcfg2/Server/Plugin/interfaces.py
@@ -220,10 +220,32 @@ class Connector(object):
def get_additional_groups(self, metadata): # pylint: disable=W0613
""" Return a list of additional groups for the given client.
+ Each group can be either the name of a group (a string), or a
+ :class:`Bcfg2.Server.Plugins.Metadata.MetadataGroup` object
+ that defines other data besides just the name. Note that you
+ cannot return a
+ :class:`Bcfg2.Server.Plugins.Metadata.MetadataGroup` object
+ that clobbers a group defined by another plugin; the original
+ group will be used instead. For instance, assume the
+ following in ``Metadata/groups.xml``:
+
+ .. code-block:: xml
+
+ <Groups>
+ ...
+ <Group name="foo" public="false"/>
+ </Groups>
+
+ You could not subsequently return a
+ :class:`Bcfg2.Server.Plugins.Metadata.MetadataGroup` object
+ with ``public=True``; a warning would be issued, and the
+ original (non-public) ``foo`` group would be used.
:param metadata: The client metadata
:type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata
- :return: list of strings
+ :return: list of strings or
+ :class:`Bcfg2.Server.Plugins.Metadata.MetadataGroup`
+ objects.
"""
return list()
diff --git a/src/lib/Bcfg2/Server/Plugins/GroupLogic.py b/src/lib/Bcfg2/Server/Plugins/GroupLogic.py
index 810b273af..e581ebc6a 100644
--- a/src/lib/Bcfg2/Server/Plugins/GroupLogic.py
+++ b/src/lib/Bcfg2/Server/Plugins/GroupLogic.py
@@ -4,6 +4,7 @@ template to dynamically set additional groups for clients. """
import os
import lxml.etree
import Bcfg2.Server.Plugin
+from Bcfg2.Server.Plugins.Metadata import MetadataGroup
try:
from Bcfg2.Server.Plugins.Bundler import BundleTemplateFile
except ImportError:
@@ -43,5 +44,11 @@ class GroupLogic(Bcfg2.Server.Plugin.Plugin,
core.fam)
def get_additional_groups(self, metadata):
- return [el.get("name")
- for el in self.config.get_xml_value(metadata).findall("Group")]
+ rv = []
+ for el in self.config.get_xml_value(metadata).findall("Group"):
+ if el.get("category"):
+ rv.append(MetadataGroup(el.get("name"),
+ category=el.get("category")))
+ else:
+ rv.append(el.get("name"))
+ return rv