Revision f65f63ef

b/lib/utils.py
1713 1713
      raise
1714 1714

  
1715 1715

  
1716
def TailFile(fname, lines=20):
1717
  """Return the last lines from a file.
1718

  
1719
  @note: this function will only read and parse the last 4KB of
1720
      the file; if the lines are very long, it could be that less
1721
      than the requested number of lines are returned
1722

  
1723
  @param fname: the file name
1724
  @type lines: int
1725
  @param lines: the (maximum) number of lines to return
1726

  
1727
  """
1728
  fd = open(fname, "r")
1729
  try:
1730
    fd.seek(0, 2)
1731
    pos = fd.tell()
1732
    pos = max(0, pos-4096)
1733
    fd.seek(pos, 0)
1734
    raw_data = fd.read()
1735
  finally:
1736
    fd.close()
1737

  
1738
  rows = raw_data.splitlines()
1739
  return rows[-lines:]
1740

  
1741

  
1716 1742
def LockedMethod(fn):
1717 1743
  """Synchronized object access decorator.
1718 1744

  
b/test/ganeti.utils_unittest.py
42 42
     RemoveFile, CheckDict, MatchNameComponent, FormatUnit, \
43 43
     ParseUnit, AddAuthorizedKey, RemoveAuthorizedKey, \
44 44
     ShellQuote, ShellQuoteArgs, TcpPing, ListVisibleFiles, \
45
     SetEtcHostsEntry, RemoveEtcHostsEntry, FirstFree, OwnIpAddress
45
     SetEtcHostsEntry, RemoveEtcHostsEntry, FirstFree, OwnIpAddress, \
46
     TailFile
47

  
46 48
from ganeti.errors import LockError, UnitParseError, GenericError, \
47 49
     ProgrammerError
48 50

  
......
772 774
    self.failUnlessRaises(AssertionError, FirstFree, [0, 3, 4, 6], base=3)
773 775

  
774 776

  
777
class TestTailFile(testutils.GanetiTestCase):
778
  """Test case for the TailFile function"""
779

  
780
  def testEmpty(self):
781
    fname = self._CreateTempFile()
782
    self.failUnlessEqual(TailFile(fname), [])
783
    self.failUnlessEqual(TailFile(fname, lines=25), [])
784

  
785
  def testAllLines(self):
786
    data = ["test %d" % i for i in range(30)]
787
    for i in range(30):
788
      fname = self._CreateTempFile()
789
      fd = open(fname, "w")
790
      fd.write("\n".join(data[:i]))
791
      if i > 0:
792
        fd.write("\n")
793
      fd.close()
794
      self.failUnlessEqual(TailFile(fname, lines=i), data[:i])
795

  
796
  def testPartialLines(self):
797
    data = ["test %d" % i for i in range(30)]
798
    fname = self._CreateTempFile()
799
    fd = open(fname, "w")
800
    fd.write("\n".join(data))
801
    fd.write("\n")
802
    fd.close()
803
    for i in range(1, 30):
804
      self.failUnlessEqual(TailFile(fname, lines=i), data[-i:])
805

  
806
  def testBigFile(self):
807
    data = ["test %d" % i for i in range(30)]
808
    fname = self._CreateTempFile()
809
    fd = open(fname, "w")
810
    fd.write("X" * 1048576)
811
    fd.write("\n")
812
    fd.write("\n".join(data))
813
    fd.write("\n")
814
    fd.close()
815
    for i in range(1, 30):
816
      self.failUnlessEqual(TailFile(fname, lines=i), data[-i:])
817

  
818

  
775 819
class TestFileLock(unittest.TestCase):
776 820
  """Test case for the FileLock class"""
777 821

  

Also available in: Unified diff