diff --git a/daemons/ganeti-watcher b/daemons/ganeti-watcher
index 351f4d83b6f068b4406725854eb71d117d037350..3d4357f266a8d9fcd1e26e3022a9b7f39fe4c0fc 100755
--- a/daemons/ganeti-watcher
+++ b/daemons/ganeti-watcher
@@ -94,6 +94,31 @@ def StartNodeDaemons():
   EnsureDaemon(constants.CONFD)
 
 
+def RunWatcherHooks():
+  """Run the watcher hooks.
+
+  """
+  hooks_dir = os.path.join(constants.HOOKS_BASE_DIR,
+                           constants.HOOKS_NAME_WATCHER)
+
+  try:
+    results = utils.RunParts(hooks_dir)
+  except Exception, msg: # pylint: disable-msg=W0703
+    logging.critical("RunParts %s failed: %s", hooks_dir, msg)
+
+  for (relname, status, runresult) in results:
+    if status == constants.RUNPARTS_SKIP:
+      logging.debug("Watcher hook %s: skipped", relname)
+    elif status == constants.RUNPARTS_ERR:
+      logging.warning("Watcher hook %s: error (%s)", relname, runresult)
+    elif status == constants.RUNPARTS_RUN:
+      if runresult.failed:
+        logging.warning("Watcher hook %s: failed (exit: %d) (output: %s)",
+                        relname, runresult.exit_code, runresult.output)
+      else:
+        logging.debug("Watcher hook %s: success (output: %s)", relname,
+                      runresult.output)
+
 class WatcherState(object):
   """Interface to a state file recording restart attempts.
 
@@ -488,6 +513,7 @@ def main():
   update_file = False
   try:
     StartNodeDaemons()
+    RunWatcherHooks()
 
     notepad = WatcherState()
     try:
diff --git a/lib/constants.py b/lib/constants.py
index 4fff9e7133b0ec34a1a1acbe3d33de3faca1af8e..20d63fe7781f501315c4a4ccb970dc87b0d4d608 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -191,6 +191,7 @@ HOOKS_BASE_DIR = CONF_DIR + "/hooks"
 HOOKS_PHASE_PRE = "pre"
 HOOKS_PHASE_POST = "post"
 HOOKS_NAME_CFGUPDATE = "config-update"
+HOOKS_NAME_WATCHER = "watcher"
 HOOKS_VERSION = 2
 
 # hooks subject type (what object type does the LU deal with)