summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTim Laszlo <tim.laszlo@gmail.com>2012-12-03 16:16:41 -0600
committerTim Laszlo <tim.laszlo@gmail.com>2012-12-03 16:16:41 -0600
commit350db854319af526818c2ffcac285ae445b0213d (patch)
treed13d486ab856c37ad194653f46ac329bb75b3338 /src
parenta8c2c14b0bf39d101f3ecc4b3aafc01fabad02d5 (diff)
parent2983b0c358ef25e7c34ccdeb3ab1f8d6a6f9ae90 (diff)
downloadbcfg2-350db854319af526818c2ffcac285ae445b0213d.tar.gz
bcfg2-350db854319af526818c2ffcac285ae445b0213d.tar.bz2
bcfg2-350db854319af526818c2ffcac285ae445b0213d.zip
Merge branch 'master' of github.com:Bcfg2/bcfg2
Diffstat (limited to 'src')
-rw-r--r--src/lib/Bcfg2/Client/Client.py4
-rw-r--r--src/lib/Bcfg2/Client/Frame.py11
-rw-r--r--src/lib/Bcfg2/Client/Tools/POSIX/File.py4
-rw-r--r--src/lib/Bcfg2/Client/Tools/POSIXUsers.py300
-rw-r--r--src/lib/Bcfg2/Client/Tools/SELinux.py117
-rw-r--r--src/lib/Bcfg2/Client/Tools/__init__.py1
-rw-r--r--src/lib/Bcfg2/Server/Plugins/SEModules.py6
7 files changed, 380 insertions, 63 deletions
diff --git a/src/lib/Bcfg2/Client/Client.py b/src/lib/Bcfg2/Client/Client.py
index f197a9074..45e0b64e6 100644
--- a/src/lib/Bcfg2/Client/Client.py
+++ b/src/lib/Bcfg2/Client/Client.py
@@ -56,8 +56,8 @@ class Client(object):
self.logger.error("Service removal is nonsensical; "
"removed services will only be disabled")
if (self.setup['remove'] and
- self.setup['remove'].lower() not in ['all', 'services',
- 'packages']):
+ self.setup['remove'].lower() not in ['all', 'services', 'packages',
+ 'users']):
self.logger.error("Got unknown argument %s for -r" %
self.setup['remove'])
if self.setup["file"] and self.setup["cache"]:
diff --git a/src/lib/Bcfg2/Client/Frame.py b/src/lib/Bcfg2/Client/Frame.py
index 53180ab68..4f3ff1820 100644
--- a/src/lib/Bcfg2/Client/Frame.py
+++ b/src/lib/Bcfg2/Client/Frame.py
@@ -105,6 +105,10 @@ class Frame(object):
if deprecated:
self.logger.warning("Loaded deprecated tool drivers:")
self.logger.warning(deprecated)
+ experimental = [tool.name for tool in self.tools if tool.experimental]
+ if experimental:
+ self.logger.warning("Loaded experimental tool drivers:")
+ self.logger.warning(experimental)
# find entries not handled by any tools
self.unhandled = [entry for struct in config
@@ -281,12 +285,15 @@ class Frame(object):
if self.setup['remove']:
if self.setup['remove'] == 'all':
self.removal = self.extra
- elif self.setup['remove'] in ['services', 'Services']:
+ elif self.setup['remove'].lower() == 'services':
self.removal = [entry for entry in self.extra
if entry.tag == 'Service']
- elif self.setup['remove'] in ['packages', 'Packages']:
+ elif self.setup['remove'].lower() == 'packages':
self.removal = [entry for entry in self.extra
if entry.tag == 'Package']
+ elif self.setup['remove'].lower() == 'users':
+ self.removal = [entry for entry in self.extra
+ if entry.tag in ['POSIXUser', 'POSIXGroup']]
candidates = [entry for entry in self.states
if not self.states[entry]]
diff --git a/src/lib/Bcfg2/Client/Tools/POSIX/File.py b/src/lib/Bcfg2/Client/Tools/POSIX/File.py
index 5842c4e1f..9b95d2234 100644
--- a/src/lib/Bcfg2/Client/Tools/POSIX/File.py
+++ b/src/lib/Bcfg2/Client/Tools/POSIX/File.py
@@ -188,6 +188,10 @@ class POSIXFile(POSIXTool):
prompt.append(udiff)
except UnicodeEncodeError:
prompt.append("Could not encode diff")
+ elif entry.get("empty", "true"):
+ # the file doesn't exist on disk, but there's no
+ # expected content
+ prompt.append("%s does not exist" % entry.get("name"))
else:
prompt.append("Diff took too long to compute, no "
"printable diff")
diff --git a/src/lib/Bcfg2/Client/Tools/POSIXUsers.py b/src/lib/Bcfg2/Client/Tools/POSIXUsers.py
new file mode 100644
index 000000000..78734f5c2
--- /dev/null
+++ b/src/lib/Bcfg2/Client/Tools/POSIXUsers.py
@@ -0,0 +1,300 @@
+""" A tool to handle creating users and groups with useradd/mod/del
+and groupadd/mod/del """
+
+import sys
+import pwd
+import grp
+import Bcfg2.Client.XML
+import subprocess
+import Bcfg2.Client.Tools
+
+
+class ExecutionError(Exception):
+ """ Raised when running an external command fails """
+
+ def __init__(self, msg, retval=None):
+ Exception.__init__(self, msg)
+ self.retval = retval
+
+ def __str__(self):
+ return "%s (rv: %s)" % (Exception.__str__(self),
+ self.retval)
+
+
+class Executor(object):
+ """ A better version of Bcfg2.Client.Tool.Executor, which captures
+ stderr, raises exceptions on error, and doesn't use the shell to
+ execute by default """
+
+ def __init__(self, logger):
+ self.logger = logger
+ self.stdout = None
+ self.stderr = None
+ self.retval = None
+
+ def run(self, command, inputdata=None, shell=False):
+ """ Run a command, given as a list, optionally giving it the
+ specified input data """
+ self.logger.debug("Running: %s" % " ".join(command))
+ proc = subprocess.Popen(command, shell=shell, bufsize=16384,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, close_fds=True)
+ if inputdata:
+ for line in inputdata.splitlines():
+ self.logger.debug('> %s' % line)
+ (self.stdout, self.stderr) = proc.communicate(inputdata)
+ else:
+ (self.stdout, self.stderr) = proc.communicate()
+ for line in self.stdout.splitlines(): # pylint: disable=E1103
+ self.logger.debug('< %s' % line)
+ self.retval = proc.wait()
+ if self.retval == 0:
+ for line in self.stderr.splitlines(): # pylint: disable=E1103
+ self.logger.warning(line)
+ return True
+ else:
+ raise ExecutionError(self.stderr, self.retval)
+
+
+class POSIXUsers(Bcfg2.Client.Tools.Tool):
+ """ A tool to handle creating users and groups with
+ useradd/mod/del and groupadd/mod/del """
+ __execs__ = ['/usr/sbin/useradd', '/usr/sbin/usermod', '/usr/sbin/userdel',
+ '/usr/sbin/groupadd', '/usr/sbin/groupmod',
+ '/usr/sbin/groupdel']
+ __handles__ = [('POSIXUser', None),
+ ('POSIXGroup', None)]
+ __req__ = dict(POSIXUser=['name'],
+ POSIXGroup=['name'])
+ experimental = True
+
+ # A mapping of XML entry attributes to the indexes of
+ # corresponding values in the get*ent data structures
+ attr_mapping = dict(POSIXUser=dict(name=0, uid=2, gecos=4, home=5,
+ shell=6),
+ POSIXGroup=dict(name=0, gid=2))
+
+ def __init__(self, logger, setup, config):
+ Bcfg2.Client.Tools.Tool.__init__(self, logger, setup, config)
+ self.set_defaults = dict(POSIXUser=self.populate_user_entry,
+ POSIXGroup=lambda g: g)
+ self.cmd = Executor(logger)
+ self._existing = None
+
+ @property
+ def existing(self):
+ """ Get a dict of existing users and groups """
+ if self._existing is None:
+ self._existing = dict(POSIXUser=dict([(u[0], u)
+ for u in pwd.getpwall()]),
+ POSIXGroup=dict([(g[0], g)
+ for g in grp.getgrall()]))
+ return self._existing
+
+ def Inventory(self, states, structures=None):
+ if not structures:
+ structures = self.config.getchildren()
+ # we calculate a list of all POSIXUser and POSIXGroup entries,
+ # and then add POSIXGroup entries that are required to create
+ # the primary group for each user to the structures. this is
+ # sneaky and possibly evil, but it works great.
+ groups = []
+ for struct in structures:
+ groups.extend([e.get("name")
+ for e in struct.findall("POSIXGroup")])
+ for struct in structures:
+ for entry in struct.findall("POSIXUser"):
+ group = self.set_defaults[entry.tag](entry).get('group')
+ if group and group not in groups:
+ self.logger.debug("POSIXUsers: Adding POSIXGroup entry "
+ "'%s' for user '%s'" %
+ (group, entry.get("name")))
+ struct.append(Bcfg2.Client.XML.Element("POSIXGroup",
+ name=group))
+ return Bcfg2.Client.Tools.Tool.Inventory(self, states, structures)
+
+ def FindExtra(self):
+ extra = []
+ for handles in self.__handles__:
+ tag = handles[0]
+ specified = []
+ for entry in self.getSupportedEntries():
+ if entry.tag == tag:
+ specified.append(entry.get("name"))
+ extra.extend([Bcfg2.Client.XML.Element(tag, name=e)
+ for e in self.existing[tag].keys()
+ if e not in specified])
+ return extra
+
+ def populate_user_entry(self, entry):
+ """ Given a POSIXUser entry, set all of the 'missing' attributes
+ with their defaults """
+ defaults = dict(group=entry.get('name'),
+ gecos=entry.get('name'),
+ shell='/bin/bash')
+ if entry.get('name') == 'root':
+ defaults['home'] = '/root'
+ else:
+ defaults['home'] = '/home/%s' % entry.get('name')
+ for key, val in defaults.items():
+ if entry.get(key) is None:
+ entry.set(key, val)
+ if entry.get('group') in self.existing['POSIXGroup']:
+ entry.set('gid',
+ str(self.existing['POSIXGroup'][entry.get('group')][2]))
+ return entry
+
+ def user_supplementary_groups(self, entry):
+ """ Get a list of supplmentary groups that the user in the
+ given entry is a member of """
+ return [g for g in self.existing['POSIXGroup'].values()
+ if entry.get("name") in g[3] and g[0] != entry.get("group")]
+
+ def VerifyPOSIXUser(self, entry, _):
+ """ Verify a POSIXUser entry """
+ rv = self._verify(self.populate_user_entry(entry))
+ if entry.get("current_exists", "true") == "true":
+ # verify supplemental groups
+ actual = [g[0] for g in self.user_supplementary_groups(entry)]
+ expected = [e.text for e in entry.findall("MemberOf")]
+ if set(expected) != set(actual):
+ entry.set('qtext',
+ "\n".join([entry.get('qtext', '')] +
+ ["%s %s has incorrect supplemental group "
+ "membership. Currently: %s. Should be: %s"
+ % (entry.tag, entry.get("name"),
+ actual, expected)]))
+ rv = False
+ if self.setup['interactive'] and not rv:
+ entry.set('qtext',
+ '%s\nInstall %s %s: (y/N) ' %
+ (entry.get('qtext', ''), entry.tag, entry.get('name')))
+ return rv
+
+ def VerifyPOSIXGroup(self, entry, _):
+ """ Verify a POSIXGroup entry """
+ rv = self._verify(entry)
+ if self.setup['interactive'] and not rv:
+ entry.set('qtext',
+ '%s\nInstall %s %s: (y/N) ' %
+ (entry.get('qtext', ''), entry.tag, entry.get('name')))
+ return rv
+
+ def _verify(self, entry):
+ """ Perform most of the actual work of verification """
+ errors = []
+ if entry.get("name") not in self.existing[entry.tag]:
+ entry.set('current_exists', 'false')
+ errors.append("%s %s does not exist" % (entry.tag,
+ entry.get("name")))
+ else:
+ for attr, idx in self.attr_mapping[entry.tag].items():
+ val = str(self.existing[entry.tag][entry.get("name")][idx])
+ entry.set("current_%s" % attr, val)
+ if attr in ["uid", "gid"]:
+ if entry.get(attr) is None:
+ # no uid/gid specified, so we let the tool
+ # automatically determine one -- i.e., it always
+ # verifies
+ continue
+ if val != entry.get(attr):
+ errors.append("%s for %s %s is incorrect. Current %s is "
+ "%s, but should be %s" %
+ (attr.title(), entry.tag, entry.get("name"),
+ attr, entry.get(attr), val))
+
+ if errors:
+ for error in errors:
+ self.logger.debug("%s: %s" % (self.name, error))
+ entry.set('qtext', "\n".join([entry.get('qtext', '')] + errors))
+ return len(errors) == 0
+
+ def Install(self, entries, states):
+ for entry in entries:
+ # install groups first, so that all groups exist for
+ # users that might need them
+ if entry.tag == 'POSIXGroup':
+ states[entry] = self._install(entry)
+ for entry in entries:
+ if entry.tag == 'POSIXUser':
+ states[entry] = self._install(entry)
+ self._existing = None
+
+ def _install(self, entry):
+ """ add or modify a user or group using the appropriate command """
+ if entry.get("name") not in self.existing[entry.tag]:
+ action = "add"
+ else:
+ action = "mod"
+ try:
+ self.cmd.run(self._get_cmd(action,
+ self.set_defaults[entry.tag](entry)))
+ self.modified.append(entry)
+ return True
+ except ExecutionError:
+ self.logger.error("POSIXUsers: Error creating %s %s: %s" %
+ (entry.tag, entry.get("name"),
+ sys.exc_info()[1]))
+ return False
+
+ def _get_cmd(self, action, entry):
+ """ Get a command to perform the appropriate action (add, mod,
+ del) on the given entry. The command is always the same; we
+ set all attributes on a given user or group when modifying it
+ rather than checking which ones need to be changed. This
+ makes things fail as a unit (e.g., if a user is logged in, you
+ can't change its home dir, but you could change its GECOS, but
+ the whole operation fails), but it also makes this function a
+ lot, lot easier and simpler."""
+ cmd = ["/usr/sbin/%s%s" % (entry.tag[5:].lower(), action)]
+ if action != 'del':
+ if entry.tag == 'POSIXGroup':
+ if entry.get('gid'):
+ cmd.extend(['-g', entry.get('gid')])
+ elif entry.tag == 'POSIXUser':
+ cmd.append('-m')
+ if entry.get('uid'):
+ cmd.extend(['-u', entry.get('uid')])
+ cmd.extend(['-g', entry.get('group')])
+ extras = [e.text for e in entry.findall("MemberOf")]
+ if extras:
+ cmd.extend(['-G', ",".join(extras)])
+ cmd.extend(['-d', entry.get('home')])
+ cmd.extend(['-s', entry.get('shell')])
+ cmd.extend(['-c', entry.get('gecos')])
+ cmd.append(entry.get('name'))
+ return cmd
+
+ def Remove(self, entries):
+ for entry in entries:
+ # remove users first, so that all users have been removed
+ # from groups before we remove them
+ if entry.tag == 'POSIXUser':
+ self._remove(entry)
+ for entry in entries:
+ if entry.tag == 'POSIXGroup':
+ try:
+ grp.getgrnam(entry.get("name"))
+ self._remove(entry)
+ except KeyError:
+ # at least some versions of userdel automatically
+ # remove the primary group for a user if the group
+ # name is the same as the username, and no other
+ # users are in the group
+ self.logger.info("POSIXUsers: Group %s does not exist. "
+ "It may have already been removed when "
+ "its users were deleted" %
+ entry.get("name"))
+ self._existing = None
+ self.extra = self.FindExtra()
+
+ def _remove(self, entry):
+ """ Remove an entry """
+ try:
+ self.cmd.run(self._get_cmd("del", entry))
+ return True
+ except ExecutionError:
+ self.logger.error("POSIXUsers: Error deleting %s %s: %s" %
+ (entry.tag, entry.get("name"),
+ sys.exc_info()[1]))
+ return False
diff --git a/src/lib/Bcfg2/Client/Tools/SELinux.py b/src/lib/Bcfg2/Client/Tools/SELinux.py
index fc47883c9..7aa0e8a20 100644
--- a/src/lib/Bcfg2/Client/Tools/SELinux.py
+++ b/src/lib/Bcfg2/Client/Tools/SELinux.py
@@ -58,36 +58,44 @@ def netmask_itoa(netmask, proto="ipv4"):
class SELinux(Bcfg2.Client.Tools.Tool):
""" SELinux entry support """
name = 'SELinux'
- __handles__ = [('SELinux', 'boolean'),
- ('SELinux', 'port'),
- ('SELinux', 'fcontext'),
- ('SELinux', 'node'),
- ('SELinux', 'login'),
- ('SELinux', 'user'),
- ('SELinux', 'interface'),
- ('SELinux', 'permissive'),
- ('SELinux', 'module')]
- __req__ = dict(SELinux=dict(boolean=['name', 'value'],
- module=['name'],
- port=['name', 'selinuxtype'],
- fcontext=['name', 'selinuxtype'],
- node=['name', 'selinuxtype', 'proto'],
- login=['name', 'selinuxuser'],
- user=['name', 'roles', 'prefix'],
- interface=['name', 'selinuxtype'],
- permissive=['name']))
+ __handles__ = [('SEBoolean', None),
+ ('SEFcontext', None),
+ ('SEInterface', None),
+ ('SELogin', None),
+ ('SEModule', None),
+ ('SENode', None),
+ ('SEPermissive', None),
+ ('SEPort', None),
+ ('SEUser', None)]
+ __req__ = dict(SEBoolean=['name', 'value'],
+ SEFcontext=['name', 'selinuxtype'],
+ SEInterface=['name', 'selinuxtype'],
+ SELogin=['name', 'selinuxuser'],
+ SEModule=['name'],
+ SENode=['name', 'selinuxtype', 'proto'],
+ SEPermissive=['name'],
+ SEPort=['name', 'selinuxtype'],
+ SEUser=['name', 'roles', 'prefix'])
def __init__(self, logger, setup, config):
Bcfg2.Client.Tools.Tool.__init__(self, logger, setup, config)
self.handlers = {}
- for handles in self.__handles__:
- etype = handles[1]
+ for handler in self.__handles__:
+ etype = handler[0]
self.handlers[etype] = \
globals()["SELinux%sHandler" % etype.title()](self, logger,
setup, config)
self.txn = False
self.post_txn_queue = []
+ def __getattr__(self, attr):
+ if attr.startswith("VerifySE"):
+ return self.GenericSEVerify
+ elif attr.startswith("InstallSE"):
+ return self.GenericSEInstall
+ else:
+ return object.__getattr__(self, attr)
+
def BundleUpdated(self, _, states):
for handler in self.handlers.values():
handler.BundleUpdated(states)
@@ -100,12 +108,12 @@ class SELinux(Bcfg2.Client.Tools.Tool):
def canInstall(self, entry):
return (Bcfg2.Client.Tools.Tool.canInstall(self, entry) and
- self.handlers[entry.get('type')].canInstall(entry))
+ self.handlers[entry.tag].canInstall(entry))
def primarykey(self, entry):
""" return a string that should be unique amongst all entries
in the specification """
- return self.handlers[entry.get('type')].primarykey(entry)
+ return self.handlers[entry.tag].primarykey(entry)
def Install(self, entries, states):
# start a transaction
@@ -125,32 +133,32 @@ class SELinux(Bcfg2.Client.Tools.Tool):
for func, arg, kwargs in self.post_txn_queue:
states[arg] = func(*arg, **kwargs)
- def InstallSELinux(self, entry):
- """Dispatch install to the proper method according to type"""
- return self.handlers[entry.get('type')].Install(entry)
+ def GenericSEInstall(self, entry):
+ """Dispatch install to the proper method according to entry tag"""
+ return self.handlers[entry.tag].Install(entry)
- def VerifySELinux(self, entry, _):
- """Dispatch verify to the proper method according to type"""
- rv = self.handlers[entry.get('type')].Verify(entry)
+ def GenericSEVerify(self, entry, _):
+ """Dispatch verify to the proper method according to entry tag"""
+ rv = self.handlers[entry.tag].Verify(entry)
if entry.get('qtext') and self.setup['interactive']:
entry.set('qtext',
- '%s\nInstall SELinux %s %s: (y/N) ' %
+ '%s\nInstall %s: (y/N) ' %
(entry.get('qtext'),
- entry.get('type'),
- self.handlers[entry.get('type')].tostring(entry)))
+ self.handlers[entry.tag].tostring(entry)))
return rv
def Remove(self, entries):
- """Dispatch verify to the proper removal method according to type"""
+ """Dispatch verify to the proper removal
+ method according to entry tag"""
# sort by type
types = list()
for entry in entries:
- if entry.get('type') not in types:
- types.append(entry.get('type'))
+ if entry.tag not in types:
+ types.append(entry.tag)
for etype in types:
self.handlers[etype].Remove([e for e in entries
- if e.get('type') == etype])
+ if e.tag == etype])
class SELinuxEntryHandler(object):
@@ -253,8 +261,7 @@ class SELinuxEntryHandler(object):
def key2entry(self, key):
""" Generate an XML entry from an SELinux record key """
attrs = self._key2attrs(key)
- attrs["type"] = self.etype
- return Bcfg2.Client.XML.Element("SELinux", **attrs)
+ return Bcfg2.Client.XML.Element(self.etype, **attrs)
def _args(self, entry, method):
""" Get the argument list for invoking _modify or _add, or
@@ -279,7 +286,7 @@ class SELinuxEntryHandler(object):
""" return a string that should be unique amongst all entries
in the specification. some entry types are not universally
disambiguated by tag:type:name alone """
- return ":".join([entry.tag, entry.get("type"), entry.get("name")])
+ return ":".join([entry.tag, entry.get("name")])
def exists(self, entry):
""" return True if the entry already exists in the record list """
@@ -303,8 +310,8 @@ class SELinuxEntryHandler(object):
continue
if current_attrs[attr] != desired_attrs[attr]:
entry.set('current_%s' % attr, current_attrs[attr])
- errors.append("SELinux %s %s has wrong %s: %s, should be %s" %
- (self.etype, self.tostring(entry), attr,
+ errors.append("%s %s has wrong %s: %s, should be %s" %
+ (entry.tag, entry.get('name'), attr,
current_attrs[attr], desired_attrs[attr]))
if errors:
@@ -331,8 +338,8 @@ class SELinuxEntryHandler(object):
return True
except ValueError:
err = sys.exc_info()[1]
- self.logger.debug("Failed to %s SELinux %s %s: %s" %
- (method, self.etype, self.tostring(entry), err))
+ self.logger.info("Failed to %s SELinux %s %s: %s" %
+ (method, self.etype, self.tostring(entry), err))
return False
def Remove(self, entries):
@@ -365,7 +372,7 @@ class SELinuxEntryHandler(object):
pass
-class SELinuxBooleanHandler(SELinuxEntryHandler):
+class SELinuxSebooleanHandler(SELinuxEntryHandler):
""" handle SELinux boolean entries """
etype = "boolean"
value_format = ("value",)
@@ -414,7 +421,7 @@ class SELinuxBooleanHandler(SELinuxEntryHandler):
SELinuxEntryHandler.canInstall(self, entry))
-class SELinuxPortHandler(SELinuxEntryHandler):
+class SELinuxSeportHandler(SELinuxEntryHandler):
""" handle SELinux port entries """
etype = "port"
value_format = ('selinuxtype', None)
@@ -486,7 +493,7 @@ class SELinuxPortHandler(SELinuxEntryHandler):
return tuple(entry.get("name").split("/"))
-class SELinuxFcontextHandler(SELinuxEntryHandler):
+class SELinuxSefcontextHandler(SELinuxEntryHandler):
""" handle SELinux file context entries """
etype = "fcontext"
@@ -556,11 +563,11 @@ class SELinuxFcontextHandler(SELinuxEntryHandler):
'', '')
def primarykey(self, entry):
- return ":".join([entry.tag, entry.get("type"), entry.get("name"),
+ return ":".join([entry.tag, entry.get("name"),
entry.get("filetype", "all")])
-class SELinuxNodeHandler(SELinuxEntryHandler):
+class SELinuxSenodeHandler(SELinuxEntryHandler):
""" handle SELinux node entries """
etype = "node"
@@ -592,7 +599,7 @@ class SELinuxNodeHandler(SELinuxEntryHandler):
entry.get("selinuxtype"))
-class SELinuxLoginHandler(SELinuxEntryHandler):
+class SELinuxSeloginHandler(SELinuxEntryHandler):
""" handle SELinux login entries """
etype = "login"
@@ -603,7 +610,7 @@ class SELinuxLoginHandler(SELinuxEntryHandler):
return (entry.get("name"), entry.get("selinuxuser"), "")
-class SELinuxUserHandler(SELinuxEntryHandler):
+class SELinuxSeuserHandler(SELinuxEntryHandler):
""" handle SELinux user entries """
etype = "user"
@@ -652,7 +659,7 @@ class SELinuxUserHandler(SELinuxEntryHandler):
return tuple(rv)
-class SELinuxInterfaceHandler(SELinuxEntryHandler):
+class SELinuxSeinterfaceHandler(SELinuxEntryHandler):
""" handle SELinux interface entries """
etype = "interface"
@@ -663,7 +670,7 @@ class SELinuxInterfaceHandler(SELinuxEntryHandler):
return (entry.get("name"), '', entry.get("selinuxtype"))
-class SELinuxPermissiveHandler(SELinuxEntryHandler):
+class SELinuxSepermissiveHandler(SELinuxEntryHandler):
""" handle SELinux permissive domain entries """
etype = "permissive"
@@ -695,7 +702,7 @@ class SELinuxPermissiveHandler(SELinuxEntryHandler):
return (entry.get("name"),)
-class SELinuxModuleHandler(SELinuxEntryHandler):
+class SELinuxSemoduleHandler(SELinuxEntryHandler):
""" handle SELinux module entries """
etype = "module"
@@ -808,10 +815,9 @@ class SELinuxModuleHandler(SELinuxEntryHandler):
def Install(self, entry, _=None):
if not self.filetool.install(self._pathentry(entry)):
return False
- if hasattr(self, 'records'):
+ if hasattr(seobject, 'moduleRecords'):
# if seobject has the moduleRecords attribute, install the
# module using the seobject library
- self.records # pylint: disable=W0104
return self._install_seobject(entry)
else:
# seobject doesn't have the moduleRecords attribute, so
@@ -891,8 +897,7 @@ class SELinuxModuleHandler(SELinuxEntryHandler):
def FindExtra(self):
specified = [self._key(e)
- for e in self.tool.getSupportedEntries()
- if e.get("type") == self.etype]
+ for e in self.tool.getSupportedEntries()]
rv = []
for module in self._all_records_from_filesystem().keys():
if module not in specified:
diff --git a/src/lib/Bcfg2/Client/Tools/__init__.py b/src/lib/Bcfg2/Client/Tools/__init__.py
index 927b25ba8..d5f55759f 100644
--- a/src/lib/Bcfg2/Client/Tools/__init__.py
+++ b/src/lib/Bcfg2/Client/Tools/__init__.py
@@ -61,6 +61,7 @@ class Tool(object):
__req__ = {}
__important__ = []
deprecated = False
+ experimental = False
def __init__(self, logger, setup, config):
self.setup = setup
diff --git a/src/lib/Bcfg2/Server/Plugins/SEModules.py b/src/lib/Bcfg2/Server/Plugins/SEModules.py
index 3edfb72a3..fa47f9496 100644
--- a/src/lib/Bcfg2/Server/Plugins/SEModules.py
+++ b/src/lib/Bcfg2/Server/Plugins/SEModules.py
@@ -40,8 +40,8 @@ class SEModules(Bcfg2.Server.Plugin.GroupSpool):
#: objects as its EntrySet children.
es_child_cls = SEModuleData
- #: SEModules manages ``SELinux`` entries
- entry_type = 'SELinux'
+ #: SEModules manages ``SEModule`` entries
+ entry_type = 'SEModule'
#: The SEModules plugin is experimental
experimental = True
@@ -68,7 +68,7 @@ class SEModules(Bcfg2.Server.Plugin.GroupSpool):
return name.lstrip("/")
def HandlesEntry(self, entry, metadata):
- if entry.tag in self.Entries and entry.get('type') == 'module':
+ if entry.tag in self.Entries:
return self._get_module_filename(entry) in self.Entries[entry.tag]
return Bcfg2.Server.Plugin.GroupSpool.HandlesEntry(self, entry,
metadata)