diff --git a/lib/utils.py b/lib/utils.py
index d0d07bcdcd1a9a76138046eaae4b2e1ac8e88964..20a3b9b3f9a3937c2ec23df2cc1310f83a852ff0 100644
--- a/lib/utils.py
+++ b/lib/utils.py
@@ -55,6 +55,11 @@ except ImportError:
   import sha
   sha1 = sha.new
 
+try:
+  import functools
+except ImportError:
+  functools = None
+
 from ganeti import errors
 from ganeti import constants
 
@@ -1501,6 +1506,31 @@ def any(seq, pred=bool): # pylint: disable-msg=W0622
   return False
 
 
+# Even though we're using Python's built-in "partial" function if available,
+# this one is always defined for testing.
+def _partial(func, *args, **keywords): # pylint: disable-msg=W0622
+  """Decorator with partial application of arguments and keywords.
+
+  This function was copied from Python's documentation.
+
+  """
+  def newfunc(*fargs, **fkeywords):
+    newkeywords = keywords.copy()
+    newkeywords.update(fkeywords)
+    return func(*(args + fargs), **newkeywords) # pylint: disable-msg=W0142
+
+  newfunc.func = func
+  newfunc.args = args
+  newfunc.keywords = keywords
+  return newfunc
+
+
+if functools is None:
+  partial = _partial
+else:
+  partial = functools.partial
+
+
 def SingleWaitForFdCondition(fdobj, event, timeout):
   """Waits for a condition to occur on the socket.
 
diff --git a/test/ganeti.utils_unittest.py b/test/ganeti.utils_unittest.py
index 6adb630b885a5074d1b9b89badb8830e604ef6b8..fa900c934a3881b6b3b0847f20870200087e48e9 100755
--- a/test/ganeti.utils_unittest.py
+++ b/test/ganeti.utils_unittest.py
@@ -1592,5 +1592,32 @@ class TestLineSplitter(unittest.TestCase):
                              "", "x"])
 
 
+class TestPartial(testutils.GanetiTestCase):
+  def test(self):
+    self._Test(utils.partial)
+    self._Test(utils._partial)
+
+  def _Test(self, fn):
+    def _TestFunc1(x, power=2):
+      return x ** power
+
+    cubic = fn(_TestFunc1, power=3)
+    self.assertEqual(cubic(1), 1)
+    self.assertEqual(cubic(3), 27)
+    self.assertEqual(cubic(4), 64)
+
+    def _TestFunc2(*args, **kwargs):
+      return (args, kwargs)
+
+    self.assertEqualValues(fn(_TestFunc2, "Hello", "World")("Foo"),
+                           (("Hello", "World", "Foo"), {}))
+
+    self.assertEqualValues(fn(_TestFunc2, "Hello", xyz=123)("Foo"),
+                           (("Hello", "Foo"), {"xyz": 123}))
+
+    self.assertEqualValues(fn(_TestFunc2, xyz=123)("Foo", xyz=999),
+                           (("Foo", ), {"xyz": 999,}))
+
+
 if __name__ == '__main__':
   testutils.GanetiTestProgram()