summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--schemas/pathentry.xsd3
-rw-r--r--schemas/rules.xsd13
-rw-r--r--schemas/types.xsd2
-rw-r--r--src/lib/Client/Tools/POSIX.py101
-rw-r--r--src/lib/Server/Plugins/POSIXCompat.py16
5 files changed, 112 insertions, 23 deletions
diff --git a/schemas/pathentry.xsd b/schemas/pathentry.xsd
index 5e129fa75..7be0e37e2 100644
--- a/schemas/pathentry.xsd
+++ b/schemas/pathentry.xsd
@@ -8,10 +8,7 @@
</xsd:documentation>
</xsd:annotation>
- <xsd:include schemaLocation="types.xsd"/>
-
<xsd:complexType name='PathEntry'>
<xsd:attribute type='xsd:string' name='name' use='required'/>
- <xsd:attribute name='type' use='required' type='PathTypeEnum' />
</xsd:complexType>
</xsd:schema>
diff --git a/schemas/rules.xsd b/schemas/rules.xsd
index 0baa1e25f..d9b99d63d 100644
--- a/schemas/rules.xsd
+++ b/schemas/rules.xsd
@@ -33,6 +33,18 @@
<xsd:attribute type='xsd:string' name='to' use='required'/>
</xsd:complexType>
+ <xsd:complexType name='PathType'>
+ <xsd:attribute type='PathTypeEnum' name='type' use='required'/>
+ <xsd:attribute type='xsd:string' name='name' use='required'/>
+ <xsd:attribute type='xsd:string' name='dev_type'/>
+ <xsd:attribute type='xsd:string' name='major'/>
+ <xsd:attribute type='xsd:string' name='minor'/>
+ <xsd:attribute type='xsd:string' name='mode'/>
+ <xsd:attribute type='xsd:string' name='perms'/>
+ <xsd:attribute type='xsd:string' name='owner'/>
+ <xsd:attribute type='xsd:string' name='group'/>
+ </xsd:complexType>
+
<xsd:complexType name='PermissionsType'>
<xsd:attribute type='xsd:string' name='name' use='required'/>
<xsd:attribute type='xsd:string' name='perms' use='required'/>
@@ -63,6 +75,7 @@
<xsd:element name='Directory' type='DirectoryType'/>
<xsd:element name='SymLink' type='SymLinkType'/>
<xsd:element name='Package' type='PackageType'/>
+ <xsd:element name='Path' type='PathType'/>
<xsd:element name='Permissions' type='PermissionsType'/>
<xsd:element name='Action' type='ActionType'/>
<xsd:element name='Group' type='RContainerType'/>
diff --git a/schemas/types.xsd b/schemas/types.xsd
index db85bbaab..f04c3140f 100644
--- a/schemas/types.xsd
+++ b/schemas/types.xsd
@@ -24,7 +24,7 @@
<xsd:simpleType name='PathTypeEnum'>
<xsd:restriction base='xsd:string'>
<xsd:enumeration value='ConfigFile' />
- <xsd:enumeration value='Device' />
+ <xsd:enumeration value='device' />
<xsd:enumeration value='Directory' />
<xsd:enumeration value='HardLink' />
<xsd:enumeration value='Perms' />
diff --git a/src/lib/Client/Tools/POSIX.py b/src/lib/Client/Tools/POSIX.py
index d956abf3a..917dc6620 100644
--- a/src/lib/Client/Tools/POSIX.py
+++ b/src/lib/Client/Tools/POSIX.py
@@ -12,11 +12,20 @@ import logging
import os
import pwd
import shutil
+import stat
import string
import time
import Bcfg2.Client.Tools
import Bcfg2.Options
+log = logging.getLogger('posix')
+
+# map between dev_type attribute and stat constants
+device_map = {'block': stat.S_IFBLK,
+ 'char': stat.S_IFCHR,
+ 'fifo': stat.S_IFIFO}
+
+
def calcPerms(initial, perms):
'''This compares ondisk permissions with specified ones'''
pdisp = [{1:S_ISVTX, 2:S_ISGID, 4:S_ISUID},
@@ -33,8 +42,6 @@ def calcPerms(initial, perms):
tempperms |= perm
return tempperms
-log = logging.getLogger('posix')
-
def normUid(entry):
'''
This takes a user name or uid and
@@ -82,7 +89,7 @@ class POSIX(Bcfg2.Client.Tools.Tool):
__handles__ = [('ConfigFile', None),
('Directory', None),
('Path', 'ConfigFile'),
- ('Path', 'Device'),
+ ('Path', 'device'),
('Path', 'Directory'),
('Path', 'HardLink'),
('Path', 'Perms'),
@@ -140,10 +147,11 @@ class POSIX(Bcfg2.Client.Tools.Tool):
fmode = os.lstat(entry.get('name'))[ST_MODE]
if S_ISREG(fmode) or S_ISLNK(fmode):
self.logger.debug("Non-directory entry already exists at "
- "%s. Unlinking entry." % (entry.get('name')))
+ "%s. Unlinking entry." % \
+ (entry.get('name')))
os.unlink(entry.get('name'))
elif S_ISDIR(fmode):
- self.logger.debug("Directory entry already exists at %s" % \
+ self.logger.debug("Directory entry already exists at %s" %\
(entry.get('name')))
self.cmd.run("mv %s/ %s.bak" % \
(entry.get('name'),
@@ -158,12 +166,6 @@ class POSIX(Bcfg2.Client.Tools.Tool):
except OSError:
return False
- def VerifyDevice(self, entry, _):
- return False
-
- def InstallDevice(self, entry):
- return False
-
def VerifyDirectory(self, entry, modlist):
'''Verify Directory Entry'''
while len(entry.get('perms', '')) < 4:
@@ -254,7 +256,6 @@ class POSIX(Bcfg2.Client.Tools.Tool):
entry.set('qtext', nnqtext)
return pTrue and pruneTrue
-
def InstallDirectory(self, entry):
'''Install Directory Entry'''
self.logger.info("Installing Directory %s" % (entry.get('name')))
@@ -382,6 +383,82 @@ class POSIX(Bcfg2.Client.Tools.Tool):
(entry.get('name')))
return False
+ def Verifydevice(self, entry, _):
+ '''Verify device entry'''
+ try:
+ # check for file existence
+ filestat = os.stat(entry.get('name'))
+ except OSError:
+ entry.set('current_exists', 'false')
+ self.logger.debug("%s %s does not exist" %
+ (entry.tag, entry.get('name')))
+ return False
+
+ try:
+ # attempt to verify device properties as specified in config
+ dev_type = entry.get('dev_type')
+ mode = calcPerms(device_map[dev_type],
+ entry.get('mode', '0600'))
+ owner = entry.get('owner')
+ group = entry.get('group')
+ if dev_type in ['block', 'char']:
+ major = int(entry.get('major'))
+ minor = int(entry.get('minor'))
+ if major == os.major(filestat.st_rdev) and \
+ minor == os.minor(filestat.st_rdev) and \
+ mode == filestat.st_mode and \
+ owner == filestat.st_uid and \
+ group == filestat.st_gid:
+ return True
+ else:
+ return False
+ elif dev_type == 'fifo' and \
+ mode == filestat.st_mode and \
+ owner == filestat.st_uid and \
+ group == filestat.st_gid:
+ return True
+ else:
+ self.logger.info('Device properties for %s incorrect' % \
+ entry.get('name'))
+ return False
+ except OSError:
+ self.logger.debug("%s %s failed to verify" %
+ (entry.tag, entry.get('name')))
+ return False
+
+ def Installdevice(self, entry):
+ '''Install device entries'''
+ try:
+ # check for existing paths and remove them
+ filestat = os.lstat(entry.get('name'))
+ try:
+ os.unlink(entry.get('name'))
+ exists = False
+ except OSError:
+ self.logger.info('Failed to unlink %s' % \
+ entry.get('name'))
+ return False
+ except OSError:
+ exists = False
+
+ if not exists:
+ try:
+ dev_type = entry.get('dev_type')
+ mode = calcPerms(device_map[dev_type],
+ entry.get('mode', '0600'))
+ if dev_type in ['block', 'char']:
+ major = int(entry.get('major'))
+ minor = int(entry.get('minor'))
+ device = os.makedev(major, minor)
+ os.mknod(entry.get('name'), mode, device)
+ else:
+ os.mknod(entry.get('name'), mode)
+ os.chown(entry.get('name'), normUid(entry), normGid(entry))
+ return True
+ except OSError:
+ self.logger.error('Failed to install %s' % entry.get('name'))
+ return False
+
def Verifynonexistent(self, entry, _):
'''Verify nonexistent entry'''
# return true if path does _not_ exist
diff --git a/src/lib/Server/Plugins/POSIXCompat.py b/src/lib/Server/Plugins/POSIXCompat.py
index 00fdbf65c..d2e530407 100644
--- a/src/lib/Server/Plugins/POSIXCompat.py
+++ b/src/lib/Server/Plugins/POSIXCompat.py
@@ -8,11 +8,12 @@ import Bcfg2.Server.Plugin
# FIXME: We will need this mapping if we decide to change the
# specification to use lowercase types for new POSIX entry types
-#COMPAT_DICT = {'configfile': 'ConfigFile',
-# 'device': 'Device',
-# 'directory': 'Directory',
-# 'permissions': 'Permissions',
-# 'symlink': 'SymLink'}
+COMPAT_DICT = {'configfile': 'ConfigFile',
+ 'device': 'device',
+ 'directory': 'Directory',
+ 'nonexistent': 'nonexistent',
+ 'permissions': 'Permissions',
+ 'symlink': 'SymLink'}
class POSIXCompat(Bcfg2.Server.Plugin.Plugin,
Bcfg2.Server.Plugin.GoalValidator):
@@ -27,9 +28,10 @@ class POSIXCompat(Bcfg2.Server.Plugin.Plugin,
def validate_goals(self, metadata, goals):
for goal in goals:
for entry in goal.getchildren():
- if entry.tag == 'Path' and entry.get('type') != 'nonexistent':
+ if entry.tag == 'Path' and \
+ entry.get('type') not in ['nonexistent', 'device']:
oldentry = entry
- entry.tag = entry.get('type')
+ entry.tag = COMPAT_DICT[entry.get('type')]
del entry.attrib['type']
# FIXME: use another attribute? old clients only
# know about type=None