summaryrefslogtreecommitdiffstats
path: root/src/lib/Client/Tools/POSIX.py
diff options
context:
space:
mode:
authorSol Jerome <sol.jerome@gmail.com>2010-10-18 11:43:37 -0500
committerSol Jerome <sol.jerome@gmail.com>2010-10-18 11:46:55 -0500
commit8a70dbabd08308403ad8296979f50c379c707df9 (patch)
tree37d9604b3c6132b1c71622c8cd7cda319dab76c1 /src/lib/Client/Tools/POSIX.py
parent16807d819b63384a0f588b4ea881c7b043571875 (diff)
downloadbcfg2-8a70dbabd08308403ad8296979f50c379c707df9.tar.gz
bcfg2-8a70dbabd08308403ad8296979f50c379c707df9.tar.bz2
bcfg2-8a70dbabd08308403ad8296979f50c379c707df9.zip
POSIX: Remove client-side support for old POSIX types
Signed-off-by: Sol Jerome <sol.jerome@gmail.com>
Diffstat (limited to 'src/lib/Client/Tools/POSIX.py')
-rw-r--r--src/lib/Client/Tools/POSIX.py636
1 files changed, 328 insertions, 308 deletions
diff --git a/src/lib/Client/Tools/POSIX.py b/src/lib/Client/Tools/POSIX.py
index a4417297a..d2611130c 100644
--- a/src/lib/Client/Tools/POSIX.py
+++ b/src/lib/Client/Tools/POSIX.py
@@ -1,11 +1,11 @@
"""All POSIX Type client support for Bcfg2."""
__revision__ = '$Revision$'
-from datetime import datetime
from stat import S_ISVTX, S_ISGID, S_ISUID, S_IXUSR, S_IWUSR, S_IRUSR, S_IXGRP
from stat import S_IWGRP, S_IRGRP, S_IXOTH, S_IWOTH, S_IROTH, ST_MODE, S_ISDIR
from stat import S_IFREG, ST_UID, ST_GID, S_ISREG, S_IFDIR, S_ISLNK, ST_MTIME
import binascii
+from datetime import datetime
import difflib
import errno
import grp
@@ -14,7 +14,6 @@ import os
import pwd
import shutil
import stat
-import string
import time
import Bcfg2.Client.Tools
import Bcfg2.Options
@@ -45,21 +44,6 @@ def calcPerms(initial, perms):
return tempperms
-def normUid(entry):
- """
- This takes a user name or uid and
- returns the corresponding uid or False.
- """
- try:
- try:
- return int(entry.get('owner'))
- except:
- return int(pwd.getpwnam(entry.get('owner'))[2])
- except (OSError, KeyError):
- log.error('UID normalization failed for %s' % (entry.get('name')))
- return False
-
-
def normGid(entry):
"""
This takes a group name or gid and
@@ -74,40 +58,33 @@ def normGid(entry):
log.error('GID normalization failed for %s' % (entry.get('name')))
return False
-text_chars = "".join([chr(y) for y in range(32, 127)] + list("\n\r\t\b"))
-notrans = string.maketrans("", "")
-
-def isString(strng):
- """Returns true if a string contains no binary chars."""
- if "\0" in strng:
+def normUid(entry):
+ """
+ This takes a user name or uid and
+ returns the corresponding uid or False.
+ """
+ try:
+ try:
+ return int(entry.get('owner'))
+ except:
+ return int(pwd.getpwnam(entry.get('owner'))[2])
+ except (OSError, KeyError):
+ log.error('UID normalization failed for %s' % (entry.get('name')))
return False
- if not strng:
- return True
-
- return len(strng.translate(notrans, text_chars)) == 0
-
class POSIX(Bcfg2.Client.Tools.Tool):
"""POSIX File support code."""
name = 'POSIX'
- __handles__ = [('ConfigFile', None),
- ('Directory', None),
- ('Path', 'device'),
+ __handles__ = [('Path', 'device'),
('Path', 'directory'),
('Path', 'file'),
('Path', 'hardlink'),
('Path', 'nonexistent'),
('Path', 'permissions'),
- ('Path', 'symlink'),
- ('Permissions', None),
- ('SymLink', None)]
- __req__ = {'ConfigFile': ['name', 'owner', 'group', 'perms'],
- 'Directory': ['name', 'owner', 'group', 'perms'],
- 'Path': ['name', 'type'],
- 'Permissions': ['name', 'owner', 'group', 'perms'],
- 'SymLink': ['name', 'to']}
+ ('Path', 'symlink')]
+ __req__ = {'Path': ['name', 'type']}
# grab paranoid options from /etc/bcfg2.conf
opts = {'ppath': Bcfg2.Options.PARANOID_PATH,
@@ -120,64 +97,150 @@ class POSIX(Bcfg2.Client.Tools.Tool):
def canInstall(self, entry):
"""Check if entry is complete for installation."""
if Bcfg2.Client.Tools.Tool.canInstall(self, entry):
- if (entry.tag, entry.text, entry.get('empty', 'false')) == \
- ('ConfigFile', None, 'false'):
+ if (entry.tag,
+ entry.get('type'),
+ entry.text,
+ entry.get('empty', 'false')) == ('Path',
+ 'file',
+ None,
+ 'false'):
return False
return True
else:
return False
- def VerifySymLink(self, entry, _):
- """Verify SymLink Entry."""
- try:
- sloc = os.readlink(entry.get('name'))
- if sloc == entry.get('to'):
- return True
- self.logger.debug("Symlink %s points to %s, should be %s" % \
- (entry.get('name'), sloc, entry.get('to')))
- entry.set('current_to', sloc)
- entry.set('qtext', "Link %s to %s? [y/N] " % (entry.get('name'),
- entry.get('to')))
+ def gatherCurrentData(self, entry):
+ if entry.tag == 'Path' and entry.get('type') == 'file':
+ try:
+ ondisk = 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:
+ entry.set('current_owner', str(ondisk[ST_UID]))
+ entry.set('current_group', str(ondisk[ST_GID]))
+ except (OSError, KeyError):
+ pass
+ entry.set('perms', str(oct(ondisk[ST_MODE])[-4:]))
+ try:
+ content = open(entry.get('name')).read()
+ entry.set('current_bfile', binascii.b2a_base64(content))
+ except IOError, error:
+ self.logger.error("Failed to read %s: %s" % (error.filename,
+ error.strerror))
+
+ def Verifydevice(self, entry, _):
+ """Verify device entry."""
+ if entry.get('dev_type') == None or \
+ entry.get('owner') == None or \
+ entry.get('group') == None:
+ self.logger.error('Entry %s not completely specified. '
+ 'Try running bcfg2-repo-validate.' % (entry.get('name')))
return False
+ if entry.get('dev_type') in ['block', 'char']:
+ # check if major/minor are properly specified
+ if entry.get('major') == None or \
+ entry.get('minor') == None:
+ self.logger.error('Entry %s not completely specified. '
+ 'Try running bcfg2-repo-validate.' % (entry.get('name')))
+ return False
+ try:
+ # check for file existence
+ filestat = os.stat(entry.get('name'))
except OSError:
entry.set('current_exists', 'false')
- entry.set('qtext', "Link %s to %s? [y/N] " % (entry.get('name'),
- entry.get('to')))
+ self.logger.debug("%s %s does not exist" %
+ (entry.tag, entry.get('name')))
return False
- def InstallSymLink(self, entry):
- """Install SymLink entry."""
- self.logger.info("Installing Symlink %s" % (entry.get('name')))
- if os.path.lexists(entry.get('name')):
- try:
- 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')))
- os.unlink(entry.get('name'))
- elif S_ISDIR(fmode):
- self.logger.debug("Directory entry already exists at %s" %\
- (entry.get('name')))
- self.cmd.run("mv %s/ %s.bak" % \
- (entry.get('name'),
- entry.get('name')))
- else:
- os.unlink(entry.get('name'))
- except OSError:
- self.logger.info("Symlink %s cleanup failed" %\
- (entry.get('name')))
try:
- os.symlink(entry.get('to'), entry.get('name'))
- return True
+ # 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 = normUid(entry)
+ group = normGid(entry)
+ if dev_type in ['block', 'char']:
+ # check for incompletely specified entries
+ if entry.get('major') == None or \
+ entry.get('minor') == None:
+ self.logger.error('Entry %s not completely specified. '
+ 'Try running bcfg2-repo-validate.' % (entry.get('name')))
+ return False
+ 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 VerifyDirectory(self, entry, modlist):
- """Verify Directory entry."""
+ def Installdevice(self, entry):
+ """Install device entries."""
+ try:
+ # check for existing paths and remove them
+ 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']:
+ # check if major/minor are properly specified
+ if entry.get('major') == None or \
+ entry.get('minor') == None:
+ self.logger.error('Entry %s not completely specified. '
+ 'Try running bcfg2-repo-validate.' % (entry.get('name')))
+ return False
+ 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 KeyError:
+ self.logger.error('Failed to install %s' % entry.get('name'))
+ except OSError:
+ self.logger.error('Failed to install %s' % entry.get('name'))
+ return False
+
+ def Verifydirectory(self, entry, modlist):
+ """Verify Path type='directory' entry."""
if entry.get('perms') == None or \
entry.get('owner') == None or \
entry.get('group') == None:
+ self.logger.error('Entry %s not completely specified. '
+ 'Try running bcfg2-repo-validate.' % (entry.get('name')))
return False
while len(entry.get('perms', '')) < 4:
entry.set('perms', '0' + entry.get('perms', ''))
@@ -210,9 +273,8 @@ class POSIX(Bcfg2.Client.Tools.Tool):
pruneTrue = True
ex_ents = []
if entry.get('prune', 'false') == 'true' \
- and (entry.tag == 'Directory' or
- entry.get('type') == 'directory'):
- # FIXME: need to verify both old and new POSIX types
+ and (entry.tag == 'Path' and entry.get('type') == 'directory'):
+ # check for any extra entries when prune='true' attribute is set
try:
entries = ['/'.join([entry.get('name'), ent]) \
for ent in os.listdir(entry.get('name'))]
@@ -227,7 +289,8 @@ class POSIX(Bcfg2.Client.Tools.Tool):
entry.get('name')
nqtext += ":".join(ex_ents)
entry.set('qtest', nqtext)
- [entry.append(XML.Element('Prune', path=x)) for x in ex_ents]
+ [entry.append(XML.Element('Prune', path=x)) \
+ for x in ex_ents]
except OSError:
ex_ents = []
pruneTrue = True
@@ -243,7 +306,8 @@ class POSIX(Bcfg2.Client.Tools.Tool):
entry.set('qtext', nqtext)
if group != str(normGid(entry)):
entry.set('current_group', group)
- self.logger.debug("%s %s group wrong" % (entry.tag, entry.get('name')))
+ self.logger.debug("%s %s group wrong" % \
+ (entry.tag, entry.get('name')))
nqtext = entry.get('qtext', '') + '\n'
nqtext += "%s group is %s should be %s" % \
(entry.get('name'), group, entry.get('group'))
@@ -251,10 +315,16 @@ class POSIX(Bcfg2.Client.Tools.Tool):
if perms != entry.get('perms'):
entry.set('current_perms', perms)
self.logger.debug("%s %s permissions are %s should be %s" %
- (entry.tag, entry.get('name'), perms, entry.get('perms')))
+ (entry.tag,
+ entry.get('name'),
+ perms,
+ entry.get('perms')))
nqtext = entry.get('qtext', '') + '\n'
- nqtext += "%s perms are %s should be %s" % \
- (entry.get('name'), perms, entry.get('perms'))
+ nqtext += "%s %s perms are %s should be %s" % \
+ (entry.tag,
+ entry.get('name'),
+ perms,
+ entry.get('perms'))
entry.set('qtext', nqtext)
if mtime != entry.get('mtime', '-1'):
entry.set('current_mtime', mtime)
@@ -265,21 +335,23 @@ class POSIX(Bcfg2.Client.Tools.Tool):
nqtext += "%s mtime is %s should be %s" % \
(entry.get('name'), mtime, entry.get('mtime'))
entry.set('qtext', nqtext)
- if entry.tag != 'ConfigFile':
+ if entry.get('type') != 'file':
nnqtext = entry.get('qtext')
- nnqtext += '\nInstall %s %s: (y/N) ' % (entry.tag, entry.get('name'))
+ nnqtext += '\nInstall %s %s: (y/N) ' % (entry.get('type'),
+ entry.get('name'))
entry.set('qtext', nnqtext)
return pTrue and pruneTrue
- def InstallDirectory(self, entry):
- """Install Directory entry."""
+ def Installdirectory(self, entry):
+ """Install Path type='directory' entry."""
if entry.get('perms') == None or \
entry.get('owner') == None or \
entry.get('group') == None:
self.logger.error('Entry %s not completely specified. '
- 'Try running bcfg2-repo-validate.' % (entry.get('name')))
+ 'Try running bcfg2-repo-validate.' % \
+ (entry.get('name')))
return False
- self.logger.info("Installing Directory %s" % (entry.get('name')))
+ self.logger.info("Installing directory %s" % (entry.get('name')))
try:
fmode = os.lstat(entry.get('name'))
if not S_ISDIR(fmode[ST_MODE]):
@@ -289,7 +361,8 @@ class POSIX(Bcfg2.Client.Tools.Tool):
os.unlink(entry.get('name'))
exists = False
except OSError:
- self.logger.info("Failed to unlink %s" % (entry.get('name')))
+ self.logger.info("Failed to unlink %s" % \
+ (entry.get('name')))
return False
else:
self.logger.debug("Found a pre-existing directory at %s" % \
@@ -334,7 +407,8 @@ class POSIX(Bcfg2.Client.Tools.Tool):
pname = pent.get('path')
ulfailed = False
if os.path.isdir(pname):
- self.logger.info("Not removing extra directory %s, please check and remove manually" % pname)
+ self.logger.info("Not removing extra directory %s, "
+ "please check and remove manually" % pname)
continue
try:
self.logger.debug("Unlinking file %s" % pname)
@@ -344,188 +418,12 @@ class POSIX(Bcfg2.Client.Tools.Tool):
ulfailed = True
if ulfailed:
return False
- return self.InstallPermissions(entry)
-
- def VerifyhardLink(self, entry, _):
- """Verify HardLink entry."""
- try:
- if os.path.samefile(entry.get('name'), entry.get('to')):
- return True
- self.logger.debug("Hardlink %s is incorrect" % \
- entry.get('name'))
- entry.set('qtext', "Link %s to %s? [y/N] " % \
- (entry.get('name'),
- entry.get('to')))
- return False
- except OSError:
- entry.set('current_exists', 'false')
- entry.set('qtext', "Link %s to %s? [y/N] " % \
- (entry.get('name'),
- entry.get('to')))
- return False
-
- def InstallhardLink(self, entry):
- """Install HardLink entry."""
- self.logger.info("Installing Hardlink %s" % (entry.get('name')))
- if os.path.lexists(entry.get('name')):
- try:
- 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')))
- os.unlink(entry.get('name'))
- elif S_ISDIR(fmode):
- self.logger.debug("Directory entry already exists at %s" % \
- (entry.get('name')))
- self.cmd.run("mv %s/ %s.bak" % \
- (entry.get('name'),
- entry.get('name')))
- else:
- os.unlink(entry.get('name'))
- except OSError:
- self.logger.info("Hardlink %s cleanup failed" % (entry.get('name')))
- try:
- os.link(entry.get('to'), entry.get('name'))
- return True
- except OSError:
- return False
-
- def VerifyPermissions(self, entry, _):
- """Verify Permissions entry"""
- return self.VerifyDirectory(entry, _)
-
- def InstallPermissions(self, entry):
- """Install POSIX permissions"""
- if entry.get('perms') == None or \
- entry.get('owner') == None or \
- entry.get('group') == None:
- self.logger.error('Entry %s not completely specified. '
- 'Try running bcfg2-repo-validate.' % (entry.get('name')))
- return False
- try:
- os.chown(entry.get('name'), normUid(entry), normGid(entry))
- os.chmod(entry.get('name'), calcPerms(S_IFDIR, entry.get('perms')))
- return True
- except (OSError, KeyError):
- self.logger.error('Permission fixup failed for %s' % \
- (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
+ return self.Installpermissions(entry)
- def Verifynonexistent(self, entry, _):
- """Verify nonexistent entry."""
- # return true if path does _not_ exist
- return not os.path.lexists(entry.get('name'))
-
- def Installnonexistent(self, entry):
- '''Remove nonexistent entries'''
- try:
- os.remove(entry.get('name'))
- return True
- except OSError:
- self.logger.error('Failed to remove %s' % entry.get('name'))
- return False
-
- def gatherCurrentData(self, entry):
- if entry.tag == 'ConfigFile':
- try:
- ondisk = 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:
- entry.set('current_owner', str(ondisk[ST_UID]))
- entry.set('current_group', str(ondisk[ST_GID]))
- except (OSError, KeyError):
- pass
- entry.set('perms', str(oct(ondisk[ST_MODE])[-4:]))
- try:
- content = open(entry.get('name')).read()
- entry.set('current_bfile', binascii.b2a_base64(content))
- except IOError, error:
- self.logger.error("Failed to read %s: %s" % (error.filename, error.strerror))
-
- def VerifyConfigFile(self, entry, _):
- """Install ConfigFile entry."""
- # configfile verify is permissions check + content check
- permissionStatus = self.VerifyDirectory(entry, _)
+ def Verifyfile(self, entry, _):
+ """Verify Path type='file' entry."""
+ # permissions check + content check
+ permissionStatus = self.Verifydirectory(entry, _)
tbin = False
if entry.get('encoding', 'ascii') == 'base64':
tempdata = binascii.a2b_base64(entry.text)
@@ -534,8 +432,8 @@ class POSIX(Bcfg2.Client.Tools.Tool):
tempdata = ''
else:
if entry.text == None:
- self.logger.error("Cannot verify incomplete ConfigFile %s" % \
- (entry.get('name')))
+ self.logger.error("Cannot verify incomplete Path type='%s' %s" % \
+ (entry.get('type'), entry.get('name')))
return False
tempdata = entry.text
if type(tempdata) == unicode:
@@ -558,7 +456,12 @@ class POSIX(Bcfg2.Client.Tools.Tool):
# md5sum so it would be faster for big binary files
contentStatus = content == tempdata
if not contentStatus:
- if tbin or not isString(content):
+ try:
+ content.decode('ascii')
+ isstring = True
+ except:
+ isstring = False
+ if tbin or not isstring:
entry.set('current_bfile', binascii.b2a_base64(content))
nqtext = entry.get('qtext', '')
nqtext += '\nBinary file, no printable diff'
@@ -567,7 +470,8 @@ class POSIX(Bcfg2.Client.Tools.Tool):
rawdiff = []
start = time.time()
longtime = False
- for x in difflib.ndiff(content.split('\n'), tempdata.split('\n')):
+ for x in difflib.ndiff(content.split('\n'),
+ tempdata.split('\n')):
now = time.time()
rawdiff.append(x)
if now - start > 5 and not longtime:
@@ -606,9 +510,9 @@ class POSIX(Bcfg2.Client.Tools.Tool):
entry.set('qtext', qtxt)
return contentStatus and permissionStatus
- def InstallConfigFile(self, entry):
- """Install ConfigFile entry."""
- self.logger.info("Installing ConfigFile %s" % (entry.get('name')))
+ def Installfile(self, entry):
+ """Install Path type='file' entry."""
+ self.logger.info("Installing file %s" % (entry.get('name')))
parent = "/".join(entry.get('name').split('/')[:-1])
if parent:
@@ -642,9 +546,9 @@ class POSIX(Bcfg2.Client.Tools.Tool):
self.setup.get("paranoid", False) and not \
(entry.get('current_exists', 'true') == 'false'):
bkupnam = entry.get('name').replace('/', '_')
- # current list of backups for this ConfigFile
+ # current list of backups for this file
bkuplist = [f for f in os.listdir(self.ppath) if
- f.startswith(bkupnam)]
+ f.startswith(bkupnam)]
bkuplist.sort()
if len(bkuplist) == int(self.max_copies):
# remove the oldest backup available
@@ -663,7 +567,7 @@ class POSIX(Bcfg2.Client.Tools.Tool):
self.logger.info("Backup of %s saved to %s" %
(entry.get('name'), self.ppath))
except IOError, e:
- self.logger.error("Failed to create backup file for ConfigFile %s" % \
+ self.logger.error("Failed to create backup file for %s" % \
(entry.get('name')))
self.logger.error(e)
return False
@@ -694,7 +598,7 @@ class POSIX(Bcfg2.Client.Tools.Tool):
os.utime(entry.get('name'), (int(entry.get('mtime')),
int(entry.get('mtime'))))
except:
- self.logger.error("ConfigFile %s mtime fix failed" \
+ self.logger.error("File %s mtime fix failed" \
% (entry.get('name')))
return False
return True
@@ -705,42 +609,158 @@ class POSIX(Bcfg2.Client.Tools.Tool):
print(err)
return False
- def Verifydirectory(self, entry, _):
- ret = getattr(self, 'VerifyDirectory')
- return ret(entry, _)
+ def Verifyhardlink(self, entry, _):
+ """Verify HardLink entry."""
+ if entry.get('to') == None:
+ self.logger.error('Entry %s not completely specified. '
+ 'Try running bcfg2-repo-validate.' % \
+ (entry.get('name')))
+ return False
+ try:
+ if os.path.samefile(entry.get('name'), entry.get('to')):
+ return True
+ self.logger.debug("Hardlink %s is incorrect" % \
+ entry.get('name'))
+ entry.set('qtext', "Link %s to %s? [y/N] " % \
+ (entry.get('name'),
+ entry.get('to')))
+ return False
+ except OSError:
+ entry.set('current_exists', 'false')
+ entry.set('qtext', "Link %s to %s? [y/N] " % \
+ (entry.get('name'),
+ entry.get('to')))
+ return False
- def Installdirectory(self, entry):
- ret = getattr(self, 'InstallDirectory')
- return ret(entry)
+ def Installhardlink(self, entry):
+ """Install HardLink entry."""
+ if entry.get('to') == None:
+ self.logger.error('Entry %s not completely specified. '
+ 'Try running bcfg2-repo-validate.' % \
+ (entry.get('name')))
+ return False
+ self.logger.info("Installing Hardlink %s" % (entry.get('name')))
+ if os.path.lexists(entry.get('name')):
+ try:
+ 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')))
+ os.unlink(entry.get('name'))
+ elif S_ISDIR(fmode):
+ self.logger.debug("Directory already exists at %s" % \
+ (entry.get('name')))
+ self.cmd.run("mv %s/ %s.bak" % \
+ (entry.get('name'),
+ entry.get('name')))
+ else:
+ os.unlink(entry.get('name'))
+ except OSError:
+ self.logger.info("Hardlink %s cleanup failed" % \
+ (entry.get('name')))
+ try:
+ os.link(entry.get('to'), entry.get('name'))
+ return True
+ except OSError:
+ return False
- def Verifyfile(self, entry, _):
- ret = getattr(self, 'VerifyConfigFile')
- return ret(entry, _)
+ def Verifynonexistent(self, entry, _):
+ """Verify nonexistent entry."""
+ # return true if path does _not_ exist
+ return not os.path.lexists(entry.get('name'))
- def Installfile(self, entry):
- ret = getattr(self, 'InstallConfigFile')
- return ret(entry)
+ def Installnonexistent(self, entry):
+ '''Remove nonexistent entries'''
+ try:
+ os.remove(entry.get('name'))
+ return True
+ except OSError:
+ self.logger.error('Failed to remove %s' % entry.get('name'))
+ return False
def Verifypermissions(self, entry, _):
- ret = getattr(self, 'VerifyPermissions')
- return ret(entry, _)
+ """Verify Path type='permissions' entry"""
+ return self.Verifydirectory(entry, _)
def Installpermissions(self, entry):
- ret = getattr(self, 'InstallPermissions')
- return ret(entry)
+ """Install POSIX permissions"""
+ if entry.get('perms') == None or \
+ entry.get('owner') == None or \
+ entry.get('group') == None:
+ self.logger.error('Entry %s not completely specified. '
+ 'Try running bcfg2-repo-validate.' % (entry.get('name')))
+ return False
+ try:
+ os.chown(entry.get('name'), normUid(entry), normGid(entry))
+ os.chmod(entry.get('name'), calcPerms(S_IFDIR, entry.get('perms')))
+ return True
+ except (OSError, KeyError):
+ self.logger.error('Permission fixup failed for %s' % \
+ (entry.get('name')))
+ return False
def Verifysymlink(self, entry, _):
- ret = getattr(self, 'VerifySymLink')
- return ret(entry, _)
+ """Verify Path type='symlink' entry."""
+ if entry.get('to') == None:
+ self.logger.error('Entry %s not completely specified. '
+ 'Try running bcfg2-repo-validate.' % \
+ (entry.get('name')))
+ return False
+ try:
+ sloc = os.readlink(entry.get('name'))
+ if sloc == entry.get('to'):
+ return True
+ self.logger.debug("Symlink %s points to %s, should be %s" % \
+ (entry.get('name'), sloc, entry.get('to')))
+ entry.set('current_to', sloc)
+ entry.set('qtext', "Link %s to %s? [y/N] " % (entry.get('name'),
+ entry.get('to')))
+ return False
+ except OSError:
+ entry.set('current_exists', 'false')
+ entry.set('qtext', "Link %s to %s? [y/N] " % (entry.get('name'),
+ entry.get('to')))
+ return False
def Installsymlink(self, entry):
- ret = getattr(self, 'InstallSymLink')
- return ret(entry)
+ """Install Path type='symlink' entry."""
+ if entry.get('to') == None:
+ self.logger.error('Entry %s not completely specified. '
+ 'Try running bcfg2-repo-validate.' % \
+ (entry.get('name')))
+ return False
+ self.logger.info("Installing symlink %s" % (entry.get('name')))
+ if os.path.lexists(entry.get('name')):
+ try:
+ 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')))
+ os.unlink(entry.get('name'))
+ elif S_ISDIR(fmode):
+ self.logger.debug("Directory already exists at %s" %\
+ (entry.get('name')))
+ self.cmd.run("mv %s/ %s.bak" % \
+ (entry.get('name'),
+ entry.get('name')))
+ else:
+ os.unlink(entry.get('name'))
+ except OSError:
+ self.logger.info("Symlink %s cleanup failed" %\
+ (entry.get('name')))
+ try:
+ os.symlink(entry.get('to'), entry.get('name'))
+ return True
+ except OSError:
+ return False
def InstallPath(self, entry):
+ """Dispatch install to the proper method according to type"""
ret = getattr(self, 'Install%s' % entry.get('type'))
return ret(entry)
def VerifyPath(self, entry, _):
+ """Dispatch verify to the proper method according to type"""
ret = getattr(self, 'Verify%s' % entry.get('type'))
return ret(entry, _)