summaryrefslogtreecommitdiffstats
path: root/src/lib/Server/Lint/RequiredAttrs.py
blob: cbb4395c4d070bb0f0af8da9c261ba4c7f8c53e8 (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
import os.path
import lxml.etree
import Bcfg2.Server.Lint

class RequiredAttrs(Bcfg2.Server.Lint.ServerPlugin):
    """ verify attributes for configuration entries (as defined in
    doc/server/configurationentries) """

    def __init__(self, *args, **kwargs):
        Bcfg2.Server.Lint.ServerPlugin.__init__(self, *args, **kwargs)
        self.required_attrs = {
            'device': ['name', 'owner', 'group', 'dev_type'],
            'directory': ['name', 'owner', 'group', 'perms'],
            'file': ['name', 'owner', 'group', 'perms'],
            'hardlink': ['name', 'to'],
            'symlink': ['name', 'to'],
            'ignore': ['name'],
            'nonexistent': ['name'],
            'permissions': ['name', 'owner', 'group', 'perms']}

    @Bcfg2.Server.Lint.returnErrors
    def Run(self):
        self.check_rules()
        self.check_bundles()

    def check_rules(self):
        """ check Rules for Path entries with missing attrs """
        if 'Rules' in self.core.plugins:
            for rules in self.core.plugins['Rules'].entries.values():
                xdata = rules.pnode.data
                for path in xdata.xpath("//Path"):
                    self.check_entry(path, os.path.join(self.config['repo'],
                                                        rules.name))

    def check_bundles(self):
        """ check bundles for BoundPath entries with missing attrs """
        if 'Bundler' in self.core.plugins:
            for bundle in self.core.plugins['Bundler'].entries.values():
                try:
                    xdata = lxml.etree.XML(bundle.data)
                except AttributeError:
                    xdata = lxml.etree.parse(bundle.template.filepath).getroot()

                for path in xdata.xpath("//BoundPath"):
                    self.check_entry(path, bundle.name)

    def check_entry(self, entry, filename):
        """ generic entry check """
        if self.HandlesFile(filename):
            pathname = entry.get('name')
            pathtype = entry.get('type')
            pathset = set(entry.attrib.keys())
            try:
                required_attrs = set(self.required_attrs[pathtype] + ['type'])
            except KeyError:
                self.LintError("unknown-path-type",
                               "Unknown path type %s: %s" %
                               (pathtype, self.RenderXML(entry)))

            if 'dev_type' in required_attrs:
                dev_type = entry.get('dev_type')
                if dev_type in ['block', 'char']:
                    # check if major/minor are specified
                    required_attrs |= set(['major', 'minor'])
            if not pathset.issuperset(required_attrs):
                self.LintError("required-attrs-missing",
                               "The required attributes %s are missing for %s %sin %s:\n%s" %
                               (",".join([attr
                                          for attr in
                                          required_attrs.difference(pathset)]),
                                entry.tag, pathname, filename,
                                self.RenderXML(entry)))