summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Server/Plugin/base.py
blob: 8d288f835f2d0fc96f94d42cdf4e8cfbbea27be8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
"""This module provides the base class for Bcfg2 server plugins."""

import os
import logging


class Debuggable(object):
    """ Mixin to add a debugging interface to an object and expose it
    via XML-RPC on :class:`Bcfg2.Server.Plugin.base.Plugin` objects """

    #: List of names of methods to be exposed as XML-RPC functions
    __rmi__ = ['toggle_debug']

    def __init__(self, name=None):
        """
        :param name: The name of the logger object to get.  If none is
                     supplied, the full name of the class (including
                     module) will be used.
        :type name: string

        .. autoattribute:: __rmi__
        """
        if name is None:
            name = "%s.%s" % (self.__class__.__module__,
                              self.__class__.__name__)
        self.debug_flag = False
        self.logger = logging.getLogger(name)

    def toggle_debug(self):
        """ Turn debugging output on or off.  This method is exposed
        via XML-RPC.

        :returns: bool - The new value of the debug flag
        """
        self.debug_flag = not self.debug_flag
        self.debug_log("%s: debug_flag = %s" % (self.__class__.__name__,
                                                self.debug_flag),
                       flag=True)
        return self.debug_flag

    def debug_log(self, message, flag=None):
        """ Log a message at the debug level.

        :param message: The message to log
        :type message: string
        :param flag: Override the current debug flag with this value
        :type flag: bool
        :returns: None
        """
        if (flag is None and self.debug_flag) or flag:
            self.logger.error(message)


class ClassName(object):
    """ This very simple descriptor class exists only to get the name
    of the owner class.  This is used because, for historical reasons,
    we expect every plugin to have a ``name`` attribute that is in
    almost all cases the same as the ``__class__.__name__`` attribute
    of the plugin object.  This makes that more dynamic so that each
    plugin isn't repeating its own name. """

    def __get__(self, inst, owner):
        return owner.__name__


class Plugin(Debuggable):
    """ The base class for all Bcfg2 Server plugins. """

    #: The name of the plugin.
    name = ClassName()

    #: The email address of the plugin author.
    __author__ = 'bcfg-dev@mcs.anl.gov'

    #: Plugin is experimental.  Use of this plugin will produce a log
    #: message alerting the administrator that an experimental plugin
    #: is in use.
    experimental = False

    #: Plugin is deprecated and will be removed in a future release.
    #: Use of this plugin will produce a log message alerting the
    #: administrator that an experimental plugin is in use.
    deprecated = False

    #: Plugin conflicts with the list of other plugin names
    conflicts = []

    #: Plugins of the same type are processed in order of ascending
    #: sort_order value. Plugins with the same sort_order are sorted
    #: alphabetically by their name.
    sort_order = 500

    #: List of names of methods to be exposed as XML-RPC functions
    __rmi__ = Debuggable.__rmi__

    def __init__(self, core, datastore):
        """
        :param core: The Bcfg2.Server.Core initializing the plugin
        :type core: Bcfg2.Server.Core
        :param datastore: The path to the Bcfg2 repository on the
                          filesystem
        :type datastore: string
        :raises: :class:`Bcfg2.Server.Plugin.exceptions.PluginInitError`

        .. autoattribute:: Bcfg2.Server.Plugin.base.Debuggable.__rmi__
        """
        self.Entries = {}
        self.core = core
        self.data = os.path.join(datastore, self.name)
        self.running = True
        Debuggable.__init__(self, name=self.name)

    @classmethod
    def init_repo(cls, repo):
        """ Perform any tasks necessary to create an initial Bcfg2
        repository.

        :param repo: The path to the Bcfg2 repository on the filesystem
        :type repo: string
        :returns: None
        """
        os.makedirs(os.path.join(repo, cls.name))

    def shutdown(self):
        """ Perform shutdown tasks for the plugin

        :returns: None """
        self.running = False

    def __str__(self):
        return "%s Plugin" % self.__class__.__name__