summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSol Jerome <solj@ices.utexas.edu>2009-10-01 16:47:07 +0000
committerSol Jerome <solj@ices.utexas.edu>2009-10-01 16:47:07 +0000
commit3cd34d135d6f3705862f0d1625c06a1669ec0023 (patch)
tree59b2318ff469544f85d568b2bfac5a4d113e6fc7 /src
parent3b729603e422786b9d44fee50f2ec255503d1d43 (diff)
downloadbcfg2-3cd34d135d6f3705862f0d1625c06a1669ec0023.tar.gz
bcfg2-3cd34d135d6f3705862f0d1625c06a1669ec0023.tar.bz2
bcfg2-3cd34d135d6f3705862f0d1625c06a1669ec0023.zip
POSIX: Add block/character/fifo devices (ticket #477)
This commit adds support for posix device types via Path entries in Bundler. The 'type' attribute for Path entries is now all lowercase. Signed-off-by: Sol Jerome <solj@ices.utexas.edu> git-svn-id: https://svn.mcs.anl.gov/repos/bcfg/trunk/bcfg2@5470 ce84e21b-d406-0410-9b95-82705330c041
Diffstat (limited to 'src')
-rw-r--r--src/lib/Client/Tools/POSIX.py101
-rw-r--r--src/lib/Server/Plugins/POSIXCompat.py16
2 files changed, 98 insertions, 19 deletions
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