diff --git a/lib/utils.py b/lib/utils.py
index 919eab11cf0f14051382879bd9ddf266546e3a9f..aa84cb1f806d03363e651df9fd476769c9253597 100644
--- a/lib/utils.py
+++ b/lib/utils.py
@@ -1872,6 +1872,46 @@ def WriteFile(file_name, fn=None, data=None,
   return result
 
 
+def GetFileID(path=None, fd=None):
+  """Returns the file 'id', i.e. the dev/inode and mtime information.
+
+  Either the path to the file or the fd must be given.
+
+  @param path: the file path
+  @param fd: a file descriptor
+  @return: a tuple of (device number, inode number, mtime)
+
+  """
+  if [path, fd].count(None) != 1:
+    raise errors.ProgrammerError("One and only one of fd/path must be given")
+
+  if fd is None:
+    st = os.stat(path)
+  else:
+    st = os.fstat(fd)
+
+  return (st.st_dev, st.st_ino, st.st_mtime)
+
+
+def VerifyFileID(fi_disk, fi_ours):
+  """Verifies that two file IDs are matching.
+
+  Differences in the inode/device are not accepted, but and older
+  timestamp for fi_disk is accepted.
+
+  @param fi_disk: tuple (dev, inode, mtime) representing the actual
+      file data
+  @param fi_ours: tuple (dev, inode, mtime) representing the last
+      written file data
+  @rtype: boolean
+
+  """
+  (d1, i1, m1) = fi_disk
+  (d2, i2, m2) = fi_ours
+
+  return (d1, i1) == (d2, i2) and m1 <= m2
+
+
 def ReadOneLineFile(file_name, strict=False):
   """Return the first non-empty line from a file.
 
diff --git a/test/ganeti.utils_unittest.py b/test/ganeti.utils_unittest.py
index 08c753e3b5b10b2b73afbc820612c5e2e3fb18d1..7fc93db1f63ab98187ea536e3d397ccce9a3df2c 100755
--- a/test/ganeti.utils_unittest.py
+++ b/test/ganeti.utils_unittest.py
@@ -2356,5 +2356,24 @@ class TestFindMatch(unittest.TestCase):
     self.assert_(utils.FindMatch(data, "Hello World") is None)
 
 
+class TestFileID(testutils.GanetiTestCase):
+  def testEquality(self):
+    name = self._CreateTempFile()
+    oldi = utils.GetFileID(path=name)
+    self.failUnless(utils.VerifyFileID(oldi, oldi))
+
+  def testUpdate(self):
+    name = self._CreateTempFile()
+    oldi = utils.GetFileID(path=name)
+    os.utime(name, None)
+    fd = os.open(name, os.O_RDWR)
+    try:
+      newi = utils.GetFileID(fd=fd)
+      self.failUnless(utils.VerifyFileID(oldi, newi))
+      self.failUnless(utils.VerifyFileID(newi, oldi))
+    finally:
+      os.close(fd)
+
+
 if __name__ == '__main__':
   testutils.GanetiTestProgram()