diff --git a/lib/opcodes.py b/lib/opcodes.py
index e15716625ecfbae22114cd2d2eb198489f111ff6..4512d7b123933dcdc39f28cf9b268183d2f38311 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -1,7 +1,7 @@
 #
 #
 
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 Google Inc.
+# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -289,12 +289,15 @@ class OpCode(BaseOpCode):
                       method for details).
   @cvar OP_PARAMS: List of opcode attributes, the default values they should
                    get if not already defined, and types they must match.
+  @cvar WITH_LU: Boolean that specifies whether this should be included in
+      mcpu's dispatch table
   @ivar dry_run: Whether the LU should be run in dry-run mode, i.e. just
                  the check steps
   @ivar priority: Opcode priority for queue
 
   """
   OP_ID = "OP_ABSTRACT"
+  WITH_LU = True
   OP_PARAMS = [
     ("dry_run", None, ht.TMaybeBool),
     ("debug_level", None, ht.TOr(ht.TNone, ht.TPositiveInt)),
@@ -1271,6 +1274,7 @@ class OpTestDummy(OpCode):
     ("messages", ht.NoDefault, ht.NoType),
     ("fail", ht.NoDefault, ht.NoType),
     ]
+  WITH_LU = False
 
 
 def _GetOpList():
@@ -1281,7 +1285,7 @@ def _GetOpList():
   """
   return [v for v in globals().values()
           if (isinstance(v, type) and issubclass(v, OpCode) and
-              hasattr(v, "OP_ID"))]
+              hasattr(v, "OP_ID") and v is not OpCode)]
 
 
 OP_MAPPING = dict((v.OP_ID, v) for v in _GetOpList())
diff --git a/test/ganeti.mcpu_unittest.py b/test/ganeti.mcpu_unittest.py
index 9f5687068491edb057d43787a824546097323598..aeca84d053c57d8171ea6b79fe0eafe4c1c2985a 100755
--- a/test/ganeti.mcpu_unittest.py
+++ b/test/ganeti.mcpu_unittest.py
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 #
 
-# Copyright (C) 2009 Google Inc.
+# Copyright (C) 2009, 2011 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -58,10 +58,10 @@ class TestLockAttemptTimeoutStrategy(unittest.TestCase):
 class TestDispatchTable(unittest.TestCase):
   def test(self):
     for opcls in opcodes.OP_MAPPING.values():
-      if opcls is opcodes.OpCode or opcls is opcodes.OpTestDummy:
+      if not opcls.WITH_LU:
         continue
-      self.assert_(opcls in mcpu.Processor.DISPATCH_TABLE,
-                   msg="%s missing handler class" % opcls)
+      self.assertTrue(opcls in mcpu.Processor.DISPATCH_TABLE,
+                      msg="%s missing handler class" % opcls)
 
 
 if __name__ == "__main__":
diff --git a/test/ganeti.opcodes_unittest.py b/test/ganeti.opcodes_unittest.py
index ff52381f945ee995a05ec4ca30140eb6dc3891a2..bb77ca2115e3e6e6773b81683e302af3ecf75a83 100755
--- a/test/ganeti.opcodes_unittest.py
+++ b/test/ganeti.opcodes_unittest.py
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 #
 
-# Copyright (C) 2010 Google Inc.
+# Copyright (C) 2010, 2011 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -123,10 +123,10 @@ class TestOpcodes(unittest.TestCase):
   def testParams(self):
     supported_by_all = set(["debug_level", "dry_run", "priority"])
 
-    self.assert_(opcodes.BaseOpCode not in opcodes.OP_MAPPING.values())
-    self.assert_(opcodes.OpCode in opcodes.OP_MAPPING.values())
+    self.assertTrue(opcodes.BaseOpCode not in opcodes.OP_MAPPING.values())
+    self.assertTrue(opcodes.OpCode not in opcodes.OP_MAPPING.values())
 
-    for cls in opcodes.OP_MAPPING.values():
+    for cls in opcodes.OP_MAPPING.values() + [opcodes.OpCode]:
       all_slots = cls._all_slots()
 
       self.assertEqual(len(set(all_slots) & supported_by_all), 3,