Commit f65f63ef authored by Iustin Pop's avatar Iustin Pop
Browse files

Add a TailFile function

This patch adds a tail file function, to be used for parsing and returning in
the job log OS installation failures.

Reviewed-by: ultrotter
parent 51596eb2
......@@ -1713,6 +1713,32 @@ def SetupLogging(logfile, debug=False, stderr_logging=False, program=""):
raise
def TailFile(fname, lines=20):
"""Return the last lines from a file.
@note: this function will only read and parse the last 4KB of
the file; if the lines are very long, it could be that less
than the requested number of lines are returned
@param fname: the file name
@type lines: int
@param lines: the (maximum) number of lines to return
"""
fd = open(fname, "r")
try:
fd.seek(0, 2)
pos = fd.tell()
pos = max(0, pos-4096)
fd.seek(pos, 0)
raw_data = fd.read()
finally:
fd.close()
rows = raw_data.splitlines()
return rows[-lines:]
def LockedMethod(fn):
"""Synchronized object access decorator.
......
......@@ -42,7 +42,9 @@ from ganeti.utils import IsProcessAlive, RunCmd, \
RemoveFile, CheckDict, MatchNameComponent, FormatUnit, \
ParseUnit, AddAuthorizedKey, RemoveAuthorizedKey, \
ShellQuote, ShellQuoteArgs, TcpPing, ListVisibleFiles, \
SetEtcHostsEntry, RemoveEtcHostsEntry, FirstFree, OwnIpAddress
SetEtcHostsEntry, RemoveEtcHostsEntry, FirstFree, OwnIpAddress, \
TailFile
from ganeti.errors import LockError, UnitParseError, GenericError, \
ProgrammerError
......@@ -772,6 +774,48 @@ class TestFirstFree(unittest.TestCase):
self.failUnlessRaises(AssertionError, FirstFree, [0, 3, 4, 6], base=3)
class TestTailFile(testutils.GanetiTestCase):
"""Test case for the TailFile function"""
def testEmpty(self):
fname = self._CreateTempFile()
self.failUnlessEqual(TailFile(fname), [])
self.failUnlessEqual(TailFile(fname, lines=25), [])
def testAllLines(self):
data = ["test %d" % i for i in range(30)]
for i in range(30):
fname = self._CreateTempFile()
fd = open(fname, "w")
fd.write("\n".join(data[:i]))
if i > 0:
fd.write("\n")
fd.close()
self.failUnlessEqual(TailFile(fname, lines=i), data[:i])
def testPartialLines(self):
data = ["test %d" % i for i in range(30)]
fname = self._CreateTempFile()
fd = open(fname, "w")
fd.write("\n".join(data))
fd.write("\n")
fd.close()
for i in range(1, 30):
self.failUnlessEqual(TailFile(fname, lines=i), data[-i:])
def testBigFile(self):
data = ["test %d" % i for i in range(30)]
fname = self._CreateTempFile()
fd = open(fname, "w")
fd.write("X" * 1048576)
fd.write("\n")
fd.write("\n".join(data))
fd.write("\n")
fd.close()
for i in range(1, 30):
self.failUnlessEqual(TailFile(fname, lines=i), data[-i:])
class TestFileLock(unittest.TestCase):
"""Test case for the FileLock class"""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment