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
|
""" Handle <Path type='directory' ...> entries """
import os
import sys
import stat
import shutil
import Bcfg2.Client.XML
from Bcfg2.Client.Tools.POSIX.base import POSIXTool
class POSIXDirectory(POSIXTool):
""" Handle <Path type='directory' ...> entries """
__req__ = ['name', 'mode', 'owner', 'group']
def verify(self, entry, modlist):
ondisk = self._exists(entry)
if not ondisk:
return False
if not stat.S_ISDIR(ondisk[stat.ST_MODE]):
self.logger.info("POSIX: %s is not a directory" %
entry.get('name'))
return False
prune = True
if entry.get('prune', 'false').lower() == 'true':
# check for any extra entries when prune='true' attribute is set
try:
extras = [os.path.join(entry.get('name'), ent)
for ent in os.listdir(entry.get('name'))
if os.path.join(entry.get('name'),
ent) not in modlist]
if extras:
prune = False
msg = "Directory %s contains extra entries: %s" % \
(entry.get('name'), "; ".join(extras))
self.logger.info("POSIX: " + msg)
entry.set('qtext', entry.get('qtext', '') + '\n' + msg)
for extra in extras:
Bcfg2.Client.XML.SubElement(entry, 'Prune', path=extra)
except OSError:
prune = True
return POSIXTool.verify(self, entry, modlist) and prune
def install(self, entry):
"""Install device entries."""
fmode = self._exists(entry)
if fmode and not stat.S_ISDIR(fmode[stat.ST_MODE]):
self.logger.info("POSIX: Found a non-directory entry at %s, "
"removing" % entry.get('name'))
try:
os.unlink(entry.get('name'))
fmode = False
except OSError:
err = sys.exc_info()[1]
self.logger.error("POSIX: Failed to unlink %s: %s" %
(entry.get('name'), err))
return False
elif fmode:
self.logger.debug("POSIX: Found a pre-existing directory at %s" %
entry.get('name'))
rv = True
if not fmode:
rv &= self._makedirs(entry)
if entry.get('prune', 'false') == 'true':
ulfailed = False
for pent in entry.findall('Prune'):
pname = pent.get('path')
ulfailed = False
if os.path.isdir(pname):
remove = shutil.rmtree
else:
remove = os.unlink
try:
self.logger.debug("POSIX: Removing %s" % pname)
remove(pname)
except OSError:
err = sys.exc_info()[1]
self.logger.error("POSIX: Failed to unlink %s: %s" %
(pname, err))
ulfailed = True
if ulfailed:
# even if prune failed, we still want to install the
# entry to make sure that we get permissions and
# whatnot set
rv = False
return POSIXTool.install(self, entry) and rv
|