summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Server
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2013-08-16 10:53:23 -0400
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2013-08-16 10:53:23 -0400
commit38f3cfcfdbf36bca3b048cc87e6d11e0c883673b (patch)
tree6a12ce51ad9078dd843dc41f668da3a77e889979 /src/lib/Bcfg2/Server
parent35498c8b849c15632d720656d5736c4c85f76b53 (diff)
downloadbcfg2-38f3cfcfdbf36bca3b048cc87e6d11e0c883673b.tar.gz
bcfg2-38f3cfcfdbf36bca3b048cc87e6d11e0c883673b.tar.bz2
bcfg2-38f3cfcfdbf36bca3b048cc87e6d11e0c883673b.zip
Rewrote arbitrary data cache system
The caching facilities in Bcfg2.Server.Cache provided basically no features. This rewrites that to allow for much more powerful cache expiration, with a particular focus on interoperation between different components and plugins to let caches be expired as necessary. (E.g., the Probes plugin can expire the Metadata cache.) This does not affect any of the file data cached by Bcfg2, only the caches that are populated with arbitrary data (Metadata, Packages, Probes, etc.).
Diffstat (limited to 'src/lib/Bcfg2/Server')
-rw-r--r--src/lib/Bcfg2/Server/Cache.py178
-rw-r--r--src/lib/Bcfg2/Server/Core.py20
-rw-r--r--src/lib/Bcfg2/Server/MultiprocessingCore.py46
-rw-r--r--src/lib/Bcfg2/Server/Plugin/helpers.py2
-rw-r--r--src/lib/Bcfg2/Server/Plugin/interfaces.py19
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Metadata.py18
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Packages/__init__.py62
-rw-r--r--src/lib/Bcfg2/Server/Plugins/SSHbase.py5
8 files changed, 209 insertions, 141 deletions
diff --git a/src/lib/Bcfg2/Server/Cache.py b/src/lib/Bcfg2/Server/Cache.py
index 842098eda..18b668b55 100644
--- a/src/lib/Bcfg2/Server/Cache.py
+++ b/src/lib/Bcfg2/Server/Cache.py
@@ -1,14 +1,176 @@
-""" An implementation of a simple memory-backed cache. Right now this
-doesn't provide many features, but more (time-based expiration, etc.)
-can be added as necessary. """
+""" ``Bcfg2.Server.Cache`` is an implementation of a simple
+memory-backed cache. Right now this doesn't provide many features, but
+more (time-based expiration, etc.) can be added as necessary.
+The normal workflow is to get a Cache object, which is simply a dict
+interface to the unified cache that automatically uses a certain tag
+set. For instance:
-class Cache(dict):
- """ an implementation of a simple memory-backed cache """
+.. code-block:: python
+
+ groupcache = Bcfg2.Server.Cache.Cache("Probes", "probegroups")
+ groupcache['foo.example.com'] = ['group1', 'group2']
+
+This would create a Cache object that automatically tags its entries
+with ``frozenset(["Probes", "probegroups"])``, and store the list
+``['group1', 'group1']`` with the *additional* tag
+``foo.example.com``. So the unified backend cache would then contain
+a single entry:
+
+.. code-block:: python
+
+ {frozenset(["Probes", "probegroups", "foo.example.com"]):
+ ['group1', 'group2']}
+
+In addition to the dict interface, Cache objects (returned from
+:func:`Bcfg2.Server.Cache.Cache`) have one additional method,
+``expire()``, which is mostly identical to
+:func:`Bcfg2.Server.Cache.expire`, except that it is specific to the
+tag set of the cache object. E.g., to expire all ``foo.example.com``
+records for a given cache, you could do:
+
+.. code-block:: python
+
+ groupcache = Bcfg2.Server.Cache.Cache("Probes", "probegroups")
+ groupcache.expire("foo.example.com")
+
+This is mostly functionally identical to:
+
+.. code-block:: python
+
+ Bcfg2.Server.Cache.expire("Probes", "probegroups", "foo.example.com")
+
+It's not completely identical, though; the first example will expire,
+at most, exactly one item from the cache. The second example will
+expire all items that are tagged with a superset of the given tags.
+To illustrate the difference, consider the following two examples:
+
+.. code-block:: python
+
+ groupcache = Bcfg2.Server.Cache.Cache("Probes")
+ groupcache.expire("probegroups")
+
+ Bcfg2.Server.Cache.expire("Probes", "probegroups")
+
+The former will not expire any data, because there is no single datum
+tagged with ``"Probes", "probegroups"``. The latter will expire *all*
+items tagged with ``"Probes", "probegroups"`` -- i.e., the entire
+cache. In this case, the latter call is equivalent to:
+
+.. code-block:: python
+
+ groupcache = Bcfg2.Server.Cache.Cache("Probes", "probegroups")
+ groupcache.expire()
+
+"""
+
+from Bcfg2.Compat import MutableMapping
+
+
+class _Cache(MutableMapping):
+ """ The object returned by :func:`Bcfg2.Server.Cache.Cache` that
+ presents a dict-like interface to the portion of the unified cache
+ that uses the specified tags. """
+ def __init__(self, registry, tags):
+ self._registry = registry
+ self._tags = tags
+
+ def __getitem__(self, key):
+ return self._registry[self._tags | set([key])]
+
+ def __setitem__(self, key, value):
+ self._registry[self._tags | set([key])] = value
+
+ def __delitem__(self, key):
+ del self._registry[self._tags | set([key])]
+
+ def __iter__(self):
+ for item in self._registry.iterate(*self._tags):
+ yield list(item.difference(self._tags))[0]
+
+ def keys(self):
+ return list(iter(self))
+
+ def __len__(self):
+ return len(list(iter(self)))
def expire(self, key=None):
""" expire all items, or a specific item, from the cache """
if key is None:
- self.clear()
- elif key in self:
- del self[key]
+ expire(*self._tags)
+ else:
+ tags = self._tags | set([key])
+ expire(*tags, exact=True)
+
+ def __repr__(self):
+ return repr(dict(self))
+
+ def __str__(self):
+ return str(dict(self))
+
+
+class _CacheRegistry(dict):
+ """ The grand unified cache backend which contains all cache
+ items. """
+
+ def iterate(self, *tags):
+ """ Iterate over all items that match the given tags *and*
+ have exactly one additional tag. This is used to get items
+ for :class:`Bcfg2.Server.Cache._Cache` objects that have been
+ instantiated via :func:`Bcfg2.Server.Cache.Cache`. """
+ tags = frozenset(tags)
+ for key in self.keys():
+ if key.issuperset(tags) and len(key.difference(tags)) == 1:
+ yield key
+
+ def iter_all(self, *tags):
+ """ Iterate over all items that match the given tags,
+ regardless of how many additional tags they have (or don't
+ have). This is used to expire all cache data that matches a
+ set of tags. """
+ tags = frozenset(tags)
+ for key in self.keys():
+ if key.issuperset(tags):
+ yield key
+
+
+_cache = _CacheRegistry() # pylint: disable=C0103
+_hooks = [] # pylint: disable=C0103
+
+
+def Cache(*tags): # pylint: disable=C0103
+ """ A dict interface to the cache data tagged with the given
+ tags. """
+ return _Cache(_cache, frozenset(tags))
+
+
+def expire(*tags, **kwargs):
+ """ Expire all items, a set of items, or one specific item from
+ the cache. If ``exact`` is set to True, then if the given tag set
+ doesn't match exactly one item in the cache, nothing will be
+ expired. """
+ exact = kwargs.pop("exact", False)
+ count = 0
+ if not tags:
+ count = len(_cache)
+ _cache.clear()
+ elif exact:
+ if frozenset(tags) in _cache:
+ count = 1
+ del _cache[frozenset(tags)]
+ else:
+ for match in _cache.iter_all(*tags):
+ count += 1
+ del _cache[match]
+
+ for hook in _hooks:
+ hook(tags, exact, count)
+
+
+def add_expire_hook(func):
+ """ Add a hook that will be called when an item is expired from
+ the cache. The callable passed in must take three options: the
+ first will be the tag set that was expired; the second will be the
+ state of the ``exact`` flag (True or False); and the third will be
+ the number of items that were expired from the cache. """
+ _hooks.append(func)
diff --git a/src/lib/Bcfg2/Server/Core.py b/src/lib/Bcfg2/Server/Core.py
index 501a78bc0..b0b80e956 100644
--- a/src/lib/Bcfg2/Server/Core.py
+++ b/src/lib/Bcfg2/Server/Core.py
@@ -207,7 +207,7 @@ class Core(object):
#: A :class:`Bcfg2.Server.Cache.Cache` object for caching client
#: metadata
- self.metadata_cache = Cache()
+ self.metadata_cache = Cache("Metadata")
#: Whether or not it's possible to use the Django database
#: backend for plugins that have that capability
@@ -227,20 +227,6 @@ class Core(object):
self.logger.error("Updating database %s failed: %s" %
(Bcfg2.Options.setup.db_name, err))
- def expire_caches_by_type(self, base_cls, key=None):
- """ Expire caches for all
- :class:`Bcfg2.Server.Plugin.interfaces.Caching` plugins that
- are instances of ``base_cls``.
-
- :param base_cls: The base plugin interface class to match (see
- :mod:`Bcfg2.Server.Plugin.interfaces`)
- :type base_cls: type
- :param key: The cache key to expire
- """
- for plugin in self.plugins_by_type(base_cls):
- if isinstance(plugin, Bcfg2.Server.Plugin.Caching):
- plugin.expire_cache(key)
-
def plugins_by_type(self, base_cls):
""" Return a list of loaded plugins that match the passed type.
@@ -683,7 +669,7 @@ class Core(object):
if event.code2str() == 'deleted':
return
Bcfg2.Options.get_parser().reparse()
- self.expire_caches_by_type(Bcfg2.Server.Plugin.Metadata)
+ self.metadata_cache.expire()
def block_for_fam_events(self, handle_events=False):
""" Block until all fam events have been handleed, optionally
@@ -1070,7 +1056,7 @@ class Core(object):
# that's created for RecvProbeData doesn't get cached.
# I.e., the next metadata object that's built, after probe
# data is processed, is cached.
- self.expire_caches_by_type(Bcfg2.Server.Plugin.Metadata)
+ self.metadata_cache.expire(client)
try:
xpdata = lxml.etree.XML(probedata.encode('utf-8'),
parser=Bcfg2.Server.XMLParser)
diff --git a/src/lib/Bcfg2/Server/MultiprocessingCore.py b/src/lib/Bcfg2/Server/MultiprocessingCore.py
index 517140178..c42009bdd 100644
--- a/src/lib/Bcfg2/Server/MultiprocessingCore.py
+++ b/src/lib/Bcfg2/Server/MultiprocessingCore.py
@@ -16,32 +16,15 @@ import threading
import lxml.etree
import multiprocessing
import Bcfg2.Options
+import Bcfg2.Server.Cache
import Bcfg2.Server.Plugin
from itertools import cycle
-from Bcfg2.Server.Cache import Cache
from Bcfg2.Compat import Queue, Empty, wraps
from Bcfg2.Server.Core import Core, exposed
from Bcfg2.Server.BuiltinCore import BuiltinCore
from multiprocessing.connection import Listener, Client
-class DispatchingCache(Cache, Bcfg2.Server.Plugin.Debuggable):
- """ Implementation of :class:`Bcfg2.Cache.Cache` that propagates
- cache expiration events to child nodes. """
-
- #: The method to send over the pipe to expire the cache
- method = "expire_metadata_cache"
-
- def __init__(self, *args, **kwargs):
- self.rpc_q = kwargs.pop("queue")
- Bcfg2.Server.Plugin.Debuggable.__init__(self)
- Cache.__init__(self, *args, **kwargs)
-
- def expire(self, key=None):
- self.rpc_q.publish(self.method, args=[key])
- Cache.expire(self, key=key)
-
-
class RPCQueue(Bcfg2.Server.Plugin.Debuggable):
""" An implementation of a :class:`multiprocessing.Queue` designed
for several additional use patterns:
@@ -304,16 +287,9 @@ class ChildCore(Core):
return rmi
@exposed
- def expire_metadata_cache(self, client=None):
- """ Expire the metadata cache for a client """
- self.metadata_cache.expire(client)
-
- @exposed
- def RecvProbeData(self, address, _):
- """ Expire the probe cache for a client """
- self.expire_caches_by_type(Bcfg2.Server.Plugin.Probing,
- key=self.resolve_client(address,
- metadata=False)[0])
+ def expire_cache(self, *tags, **kwargs):
+ """ Expire cached data """
+ Bcfg2.Server.Cache.expire(*tags, exact=kwargs.pop("exact", False))
@exposed
def GetConfig(self, client):
@@ -368,8 +344,6 @@ class MultiprocessingCore(BuiltinCore):
#: used to send or publish commands to children.
self.rpc_q = RPCQueue()
- self.metadata_cache = DispatchingCache(queue=self.rpc_q)
-
#: A list of children that will be cycled through
self._all_children = []
@@ -392,6 +366,7 @@ class MultiprocessingCore(BuiltinCore):
self.logger.debug("Started %s children: %s" % (len(self._all_children),
self._all_children))
self.children = cycle(self._all_children)
+ Bcfg2.Server.Cache.add_expire_hook(self.cache_dispatch)
return BuiltinCore._run(self)
def shutdown(self):
@@ -464,16 +439,11 @@ class MultiprocessingCore(BuiltinCore):
def set_debug(self, address, debug):
self.rpc_q.set_debug(debug)
self.rpc_q.publish("set_debug", args=[address, debug])
- self.metadata_cache.set_debug(debug)
return BuiltinCore.set_debug(self, address, debug)
- @exposed
- def RecvProbeData(self, address, probedata):
- rv = BuiltinCore.RecvProbeData(self, address, probedata)
- # we don't want the children to actually process probe data,
- # so we don't send the data, just the fact that we got some.
- self.rpc_q.publish("RecvProbeData", args=[address, None])
- return rv
+ def cache_dispatch(self, tags, exact, _):
+ """ Publish cache expiration events to child nodes. """
+ self.rpc_q.publish("expire_cache", args=tags, kwargs=dict(exact=exact))
@exposed
def GetConfig(self, address):
diff --git a/src/lib/Bcfg2/Server/Plugin/helpers.py b/src/lib/Bcfg2/Server/Plugin/helpers.py
index cfdb25cd6..38491b05d 100644
--- a/src/lib/Bcfg2/Server/Plugin/helpers.py
+++ b/src/lib/Bcfg2/Server/Plugin/helpers.py
@@ -961,6 +961,8 @@ class PrioDir(Plugin, Generator, XMLDirectoryBacked):
self.Entries = {}
for src in self.entries.values():
for child in src.xdata.iterchildren():
+ if child.tag in ['Group', 'Client']:
+ continue
if child.tag not in self.Entries:
self.Entries[child.tag] = dict()
self.Entries[child.tag][child.get("name")] = self.BindEntry
diff --git a/src/lib/Bcfg2/Server/Plugin/interfaces.py b/src/lib/Bcfg2/Server/Plugin/interfaces.py
index 30275f6ad..619d72afd 100644
--- a/src/lib/Bcfg2/Server/Plugin/interfaces.py
+++ b/src/lib/Bcfg2/Server/Plugin/interfaces.py
@@ -632,22 +632,3 @@ class ClientACLs(object):
:returns: bool
"""
return True
-
-
-class Caching(object):
- """ A plugin that caches more than just the data received from the
- FAM. This presents a unified interface to clear the cache. """
-
- def expire_cache(self, key=None):
- """ Expire the cache associated with the given key.
-
- :param key: The key to expire the cache for. Because cache
- implementations vary tremendously between plugins,
- this could be any number of things, but generally
- a hostname. It also may or may not be possible to
- expire the cache for a single host; this interface
- does not require any guarantee about that.
- :type key: varies
- :returns: None
- """
- raise NotImplementedError
diff --git a/src/lib/Bcfg2/Server/Plugins/Metadata.py b/src/lib/Bcfg2/Server/Plugins/Metadata.py
index 3a470b8de..75cf6454c 100644
--- a/src/lib/Bcfg2/Server/Plugins/Metadata.py
+++ b/src/lib/Bcfg2/Server/Plugins/Metadata.py
@@ -17,10 +17,10 @@ import Bcfg2.Options
import Bcfg2.Server.Plugin
import Bcfg2.Server.FileMonitor
from Bcfg2.Utils import locked
+from Bcfg2.Server.Cache import Cache
from Bcfg2.Compat import MutableMapping, all, wraps # pylint: disable=W0622
from Bcfg2.version import Bcfg2VersionInfo
-
# pylint: disable=C0103
ClientVersions = None
MetadataClientModel = None
@@ -90,7 +90,7 @@ def load_django_models():
def keys(self):
""" Get keys for the mapping """
- return [c.hostname for c in MetadataClientModel.objects.all()]
+ return list(iter(self))
def __contains__(self, key):
try:
@@ -513,7 +513,6 @@ class MetadataGroup(tuple): # pylint: disable=E0012,R0924
class Metadata(Bcfg2.Server.Plugin.Metadata,
- Bcfg2.Server.Plugin.Caching,
Bcfg2.Server.Plugin.ClientRunHooks,
Bcfg2.Server.Plugin.DatabaseBacked):
"""This class contains data for bcfg2 server metadata."""
@@ -533,7 +532,6 @@ class Metadata(Bcfg2.Server.Plugin.Metadata,
def __init__(self, core, datastore, watch_clients=True):
Bcfg2.Server.Plugin.Metadata.__init__(self)
- Bcfg2.Server.Plugin.Caching.__init__(self)
Bcfg2.Server.Plugin.ClientRunHooks.__init__(self)
Bcfg2.Server.Plugin.DatabaseBacked.__init__(self, core, datastore)
self.watch_clients = watch_clients
@@ -578,6 +576,7 @@ class Metadata(Bcfg2.Server.Plugin.Metadata,
self.versions = dict()
self.uuid = {}
self.session_cache = {}
+ self.cache = Cache("Metadata")
self.default = None
self.pdirty = False
self.password = Bcfg2.Options.setup.password
@@ -977,16 +976,13 @@ class Metadata(Bcfg2.Server.Plugin.Metadata,
self.groups[gname]
self.states['groups.xml'] = True
- def expire_cache(self, key=None):
- self.core.metadata_cache.expire(key)
-
def HandleEvent(self, event):
"""Handle update events for data files."""
for handles, event_handler in self.handlers.items():
if handles(event):
# clear the entire cache when we get an event for any
# metadata file
- self.expire_cache()
+ self.cache.expire()
event_handler(event)
if False not in list(self.states.values()) and self.debug_flag:
@@ -1147,8 +1143,8 @@ class Metadata(Bcfg2.Server.Plugin.Metadata,
raise Bcfg2.Server.Plugin.MetadataRuntimeError("Metadata has not "
"been read yet")
client = client.lower()
- if client in self.core.metadata_cache:
- return self.core.metadata_cache[client]
+ if client in self.cache:
+ return self.cache[client]
if client in self.aliases:
client = self.aliases[client]
@@ -1243,7 +1239,7 @@ class Metadata(Bcfg2.Server.Plugin.Metadata,
addresses, categories, uuid, password, version,
self.query)
if self.core.metadata_cache_mode == 'initial':
- self.core.metadata_cache[client] = rv
+ self.cache[client] = rv
return rv
def get_all_group_names(self):
diff --git a/src/lib/Bcfg2/Server/Plugins/Packages/__init__.py b/src/lib/Bcfg2/Server/Plugins/Packages/__init__.py
index 5af9c1591..56285705a 100644
--- a/src/lib/Bcfg2/Server/Plugins/Packages/__init__.py
+++ b/src/lib/Bcfg2/Server/Plugins/Packages/__init__.py
@@ -8,6 +8,7 @@ import glob
import shutil
import lxml.etree
import Bcfg2.Options
+import Bcfg2.Server.Cache
import Bcfg2.Server.Plugin
from Bcfg2.Compat import urlopen, HTTPError, URLError, MutableMapping
from Bcfg2.Server.Plugins.Packages.Collection import Collection, \
@@ -81,7 +82,6 @@ class OnDemandDict(MutableMapping):
class Packages(Bcfg2.Server.Plugin.Plugin,
- Bcfg2.Server.Plugin.Caching,
Bcfg2.Server.Plugin.StructureValidator,
Bcfg2.Server.Plugin.Generator,
Bcfg2.Server.Plugin.Connector,
@@ -136,12 +136,8 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
#: and :func:`Reload`
__rmi__ = Bcfg2.Server.Plugin.Plugin.__rmi__ + ['Refresh', 'Reload']
- __child_rmi__ = Bcfg2.Server.Plugin.Plugin.__child_rmi__ + \
- [('Refresh', 'expire_cache'), ('Reload', 'expire_cache')]
-
def __init__(self, core, datastore):
Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
- Bcfg2.Server.Plugin.Caching.__init__(self)
Bcfg2.Server.Plugin.StructureValidator.__init__(self)
Bcfg2.Server.Plugin.Generator.__init__(self)
Bcfg2.Server.Plugin.Connector.__init__(self)
@@ -185,7 +181,7 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
#: :attr:`Bcfg2.Server.Plugins.Packages.Collection.Collection.cachekey`,
#: a unique key identifying the collection by its *config*,
#: which could be shared among multiple clients.
- self.collections = dict()
+ self.collections = Bcfg2.Server.Cache.Cache("Packages", "collections")
#: clients is a cache mapping of hostname ->
#: :attr:`Bcfg2.Server.Plugins.Packages.Collection.Collection.cachekey`
@@ -193,21 +189,8 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
#: :class:`Bcfg2.Server.Plugins.Packages.Collection.Collection`
#: object when one is requested, so each entry is very
#: short-lived -- it's purged at the end of each client run.
- self.clients = dict()
-
- #: groupcache caches group lookups. It maps Collections (via
- #: :attr:`Bcfg2.Server.Plugins.Packages.Collection.Collection.cachekey`)
- #: to sets of package groups, and thence to the packages
- #: indicated by those groups.
- self.groupcache = dict()
-
- #: pkgcache caches complete package sets. It maps Collections
- #: (via
- #: :attr:`Bcfg2.Server.Plugins.Packages.Collection.Collection.cachekey`)
- #: to sets of initial packages, and thence to the final
- #: (complete) package selections resolved from the initial
- #: packages
- self.pkgcache = dict()
+ self.clients = Bcfg2.Server.Cache.Cache("Packages", "cache")
+
# pylint: enable=C0301
__init__.__doc__ = Bcfg2.Server.Plugin.Plugin.__init__.__doc__
@@ -400,11 +383,12 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
groups.sort()
# check for this set of groups in the group cache
+ gcache = Bcfg2.Server.Cache.Cache("Packages", "pkg_groups",
+ collection.cachekey)
gkey = hash(tuple(groups))
- if gkey not in self.groupcache[collection.cachekey]:
- self.groupcache[collection.cachekey][gkey] = \
- collection.get_groups(groups)
- for pkgs in self.groupcache[collection.cachekey][gkey].values():
+ if gkey not in gcache:
+ gcache[gkey] = collection.get_groups(groups)
+ for pkgs in gcache[gkey].values():
base.update(pkgs)
# essential pkgs are those marked as such by the distribution
@@ -412,10 +396,11 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
# check for this set of packages in the package cache
pkey = hash(tuple(base))
- if pkey not in self.pkgcache[collection.cachekey]:
- self.pkgcache[collection.cachekey][pkey] = \
- collection.complete(base)
- packages, unknown = self.pkgcache[collection.cachekey][pkey]
+ pcache = Bcfg2.Server.Cache.Cache("Packages", "pkg_sets",
+ collection.cachekey)
+ if pkey not in pcache:
+ pcache[pkey] = collection.complete(base)
+ packages, unknown = pcache[pkey]
if unknown:
self.logger.info("Packages: Got %d unknown entries" % len(unknown))
self.logger.info("Packages: %s" % list(unknown))
@@ -441,7 +426,8 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
self._load_config()
return True
- def expire_cache(self, _=None):
+ def child_reload(self, _=None):
+ """ Reload the Packages configuration on a child process. """
self.Reload()
def _load_config(self, force_update=False):
@@ -472,10 +458,7 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
collection.setup_data(force_update)
# clear Collection and package caches
- self.clients = dict()
- self.collections = dict()
- self.groupcache = dict()
- self.pkgcache = dict()
+ Bcfg2.Server.Cache.expire("Packages")
for source in self.sources.entries:
cachefiles.add(source.cachefile)
@@ -551,11 +534,7 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
if not self.sources.loaded:
# if sources.xml has not received a FAM event yet, defer;
# instantiate a dummy Collection object
- collection = Collection(metadata, [], self.cachepath, self.data)
- ckey = collection.cachekey
- self.groupcache.setdefault(ckey, dict())
- self.pkgcache.setdefault(ckey, dict())
- return collection
+ return Collection(metadata, [], self.cachepath, self.data)
if metadata.hostname in self.clients:
return self.collections[self.clients[metadata.hostname]]
@@ -592,8 +571,6 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
if cclass != Collection:
self.clients[metadata.hostname] = ckey
self.collections[ckey] = collection
- self.groupcache.setdefault(ckey, dict())
- self.pkgcache.setdefault(ckey, dict())
return collection
def get_additional_data(self, metadata):
@@ -642,8 +619,7 @@ class Packages(Bcfg2.Server.Plugin.Plugin,
:param metadata: The client metadata
:type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata
"""
- if metadata.hostname in self.clients:
- del self.clients[metadata.hostname]
+ self.clients.expire(metadata.hostname)
def end_statistics(self, metadata):
""" Hook to clear the cache for this client in :attr:`clients`
diff --git a/src/lib/Bcfg2/Server/Plugins/SSHbase.py b/src/lib/Bcfg2/Server/Plugins/SSHbase.py
index 8ce4e8a54..374711ca5 100644
--- a/src/lib/Bcfg2/Server/Plugins/SSHbase.py
+++ b/src/lib/Bcfg2/Server/Plugins/SSHbase.py
@@ -89,7 +89,6 @@ class KnownHostsEntrySet(Bcfg2.Server.Plugin.EntrySet):
class SSHbase(Bcfg2.Server.Plugin.Plugin,
- Bcfg2.Server.Plugin.Caching,
Bcfg2.Server.Plugin.Generator,
Bcfg2.Server.Plugin.PullTarget):
"""
@@ -123,7 +122,6 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin,
def __init__(self, core, datastore):
Bcfg2.Server.Plugin.Plugin.__init__(self, core, datastore)
- Bcfg2.Server.Plugin.Caching.__init__(self)
Bcfg2.Server.Plugin.Generator.__init__(self)
Bcfg2.Server.Plugin.PullTarget.__init__(self)
self.ipcache = {}
@@ -150,9 +148,6 @@ class SSHbase(Bcfg2.Server.Plugin.Plugin,
self.Entries['Path']["/etc/ssh/" + keypattern] = self.build_hk
self.cmd = Executor()
- def expire_cache(self, key=None):
- self.__skn = False
-
def get_skn(self):
"""Build memory cache of the ssh known hosts file."""
if not self.__skn: