diff --git a/htest/Test/Ganeti/OpCodes.hs b/htest/Test/Ganeti/OpCodes.hs
index 346a890a9d9010e7041ecf203b263ba5ae3262bf..983be4f925dcbd122ee38f8d9e53de84d1b76abf 100644
--- a/htest/Test/Ganeti/OpCodes.hs
+++ b/htest/Test/Ganeti/OpCodes.hs
@@ -36,16 +36,19 @@ import Test.QuickCheck
 
 import Control.Applicative
 import Data.List
+import qualified Data.Map as Map
 import qualified Text.JSON as J
 
 import Test.Ganeti.TestHelper
 import Test.Ganeti.TestCommon
 import Test.Ganeti.Types ()
+import Test.Ganeti.Query.Language
 
 import qualified Ganeti.Constants as C
 import qualified Ganeti.OpCodes as OpCodes
 import Ganeti.Types
 import Ganeti.OpParams
+import Ganeti.JSON
 
 {-# ANN module "HLint: ignore Use camelCase" #-}
 
@@ -63,6 +66,8 @@ $(genArbitrary ''OpCodes.ReplaceDisksMode)
 instance Arbitrary OpCodes.DiskIndex where
   arbitrary = choose (0, C.maxDisks - 1) >>= OpCodes.mkDiskIndex
 
+$(genArbitrary ''INicParams)
+
 instance Arbitrary OpCodes.OpCode where
   arbitrary = do
     op_id <- elements OpCodes.allOpIDs
@@ -83,10 +88,100 @@ instance Arbitrary OpCodes.OpCode where
         OpCodes.OpTagsSet <$> arbitrary <*> genTags
       "OP_TAGS_DEL" ->
         OpCodes.OpTagsSet <$> arbitrary <*> genTags
-      _ -> fail "Wrong opcode"
+      "OP_CLUSTER_POST_INIT" -> pure OpCodes.OpClusterPostInit
+      "OP_CLUSTER_DESTROY" -> pure OpCodes.OpClusterDestroy
+      "OP_CLUSTER_QUERY" -> pure OpCodes.OpClusterQuery
+      "OP_CLUSTER_VERIFY" ->
+        OpCodes.OpClusterVerify <$> arbitrary <*> arbitrary <*>
+          genSet Nothing <*> genSet Nothing <*> arbitrary <*> arbitrary
+      "OP_CLUSTER_VERIFY_CONFIG" ->
+        OpCodes.OpClusterVerifyConfig <$> arbitrary <*> arbitrary <*>
+          genSet Nothing <*> arbitrary
+      "OP_CLUSTER_VERIFY_GROUP" ->
+        OpCodes.OpClusterVerifyGroup <$> arbitrary <*> arbitrary <*>
+          arbitrary <*> genSet Nothing <*> genSet Nothing <*> arbitrary
+      "OP_CLUSTER_VERIFY_DISKS" -> pure OpCodes.OpClusterVerifyDisks
+      "OP_GROUP_VERIFY_DISKS" ->
+        OpCodes.OpGroupVerifyDisks <$> arbitrary
+      "OP_CLUSTER_REPAIR_DISK_SIZES" ->
+        OpCodes.OpClusterRepairDiskSizes <$>
+          resize maxNodes (listOf (getFQDN >>= mkNonEmpty))
+      "OP_CLUSTER_CONFIG_QUERY" ->
+        OpCodes.OpClusterConfigQuery <$> resize maxNodes arbitrary
+      "OP_CLUSTER_RENAME" ->
+        OpCodes.OpClusterRename <$> (getName >>= mkNonEmpty)
+      "OP_CLUSTER_SET_PARAMS" ->
+        OpCodes.OpClusterSetParams <$> emptyMUD <*> emptyMUD <*>
+          arbitrary <*> getMaybe (listOf1 arbitrary >>= mkNonEmpty) <*>
+          getMaybe genEmptyContainer <*> emptyMUD <*>
+          getMaybe genEmptyContainer <*> getMaybe genEmptyContainer <*>
+          getMaybe genEmptyContainer <*> getMaybe arbitrary <*>
+          arbitrary <*> arbitrary <*> arbitrary <*>
+          arbitrary <*> arbitrary <*> arbitrary <*>
+          emptyMUD <*> emptyMUD <*> arbitrary <*>
+          arbitrary <*> arbitrary <*> arbitrary <*>
+          arbitrary <*> arbitrary <*> arbitrary
+      "OP_CLUSTER_REDIST_CONF" -> pure OpCodes.OpClusterRedistConf
+      "OP_CLUSTER_ACTIVATE_MASTER_IP" ->
+        pure OpCodes.OpClusterActivateMasterIp
+      "OP_CLUSTER_DEACTIVATE_MASTER_IP" ->
+        pure OpCodes.OpClusterDeactivateMasterIp
+      "OP_QUERY" ->
+        OpCodes.OpQuery <$> arbitrary <*> arbitrary <*> arbitrary <*> genFilter
+      "OP_QUERY_FIELDS" ->
+        OpCodes.OpQueryFields <$> arbitrary <*> arbitrary
+      "OP_OOB_COMMAND" ->
+        OpCodes.OpOobCommand <$> genNodeNamesNE <*> arbitrary <*>
+          arbitrary <*> arbitrary <*> (arbitrary `suchThat` (>0))
+      "OP_NODE_REMOVE" -> OpCodes.OpNodeRemove <$> (getFQDN >>= mkNonEmpty)
+      "OP_NODE_ADD" ->
+        OpCodes.OpNodeAdd <$> (getFQDN >>= mkNonEmpty) <*>
+          emptyMUD <*> emptyMUD <*>
+          arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*>
+          arbitrary <*> arbitrary <*> emptyMUD
+      "OP_NODE_QUERY" ->
+        OpCodes.OpNodeQuery <$> arbitrary <*> arbitrary <*> arbitrary
+      "OP_NODE_QUERYVOLS" ->
+        OpCodes.OpNodeQueryvols <$> arbitrary <*> genNodeNamesNE
+      "OP_NODE_QUERY_STORAGE" ->
+        OpCodes.OpNodeQueryStorage <$> arbitrary <*> arbitrary <*>
+          genNodeNamesNE <*> arbitrary
+      "OP_NODE_MODIFY_STORAGE" ->
+        OpCodes.OpNodeModifyStorage <$> genNodeNameNE <*> arbitrary <*>
+          arbitrary <*> pure emptyJSObject
+      "OP_REPAIR_NODE_STORAGE" ->
+        OpCodes.OpRepairNodeStorage <$> genNodeNameNE <*> arbitrary <*>
+          arbitrary <*> arbitrary
+      "OP_NODE_SET_PARAMS" ->
+        OpCodes.OpNodeSetParams <$> genNodeNameNE <*> arbitrary <*>
+          emptyMUD <*> emptyMUD <*> arbitrary <*> arbitrary <*> arbitrary <*>
+          arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*>
+          emptyMUD
+      "OP_NODE_POWERCYCLE" ->
+        OpCodes.OpNodePowercycle <$> genNodeNameNE <*> arbitrary
+      "OP_NODE_MIGRATE" ->
+        OpCodes.OpNodeMigrate <$> genNodeNameNE <*> arbitrary <*>
+          arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*>
+          arbitrary
+      "OP_NODE_EVACUATE" ->
+        OpCodes.OpNodeEvacuate <$> arbitrary <*> genNodeNameNE <*>
+          getMaybe genNodeNameNE <*> arbitrary <*> arbitrary
+      _ -> fail $ "Undefined arbitrary for opcode " ++ op_id
 
 -- * Helper functions
 
+-- | Empty JSObject.
+emptyJSObject :: J.JSObject J.JSValue
+emptyJSObject = J.toJSObject []
+
+-- | Empty maybe unchecked dictionary.
+emptyMUD :: Gen (Maybe (J.JSObject J.JSValue))
+emptyMUD = getMaybe $ pure emptyJSObject
+
+-- | Generates an empty container.
+genEmptyContainer :: (Ord a) => Gen (GenericContainer a b)
+genEmptyContainer = pure . GenericContainer $ Map.fromList []
+
 -- | Generates list of disk indices.
 genDiskIndices :: Gen [DiskIndex]
 genDiskIndices = do
@@ -97,6 +192,10 @@ genDiskIndices = do
 genNodeNames :: Gen [String]
 genNodeNames = resize maxNodes (listOf getFQDN)
 
+-- | Generates a list of node names in non-empty string type.
+genNodeNamesNE :: Gen [NonEmptyString]
+genNodeNamesNE = genNodeNames >>= mapM (mkNonEmpty)
+
 -- | Gets a node name in non-empty type.
 genNodeNameNE :: Gen NonEmptyString
 genNodeNameNE = getFQDN >>= mkNonEmpty
diff --git a/htools/Ganeti/OpCodes.hs b/htools/Ganeti/OpCodes.hs
index e22dbd0ac05ca7de4ca7bd4af12390e88c92ec08..033a68bc92bb46f0efa6623157dc03bd8be33cbc 100644
--- a/htools/Ganeti/OpCodes.hs
+++ b/htools/Ganeti/OpCodes.hs
@@ -82,6 +82,165 @@ $(genOpCode "OpCode"
      [ pTagsObject
      , pTagsList
      ])
+  , ("OpClusterPostInit", [])
+  , ("OpClusterDestroy", [])
+  , ("OpClusterQuery", [])
+  , ("OpClusterVerify",
+     [ pDebugSimulateErrors
+     , pErrorCodes
+     , pSkipChecks
+     , pIgnoreErrors
+     , pVerbose
+     , pOptGroupName
+     ])
+  , ("OpClusterVerifyConfig",
+     [ pDebugSimulateErrors
+     , pErrorCodes
+     , pIgnoreErrors
+     , pVerbose
+     ])
+  , ("OpClusterVerifyGroup",
+     [ pGroupName
+     , pDebugSimulateErrors
+     , pErrorCodes
+     , pSkipChecks
+     , pIgnoreErrors
+     , pVerbose
+     ])
+  , ("OpClusterVerifyDisks", [])
+  , ("OpGroupVerifyDisks",
+     [ pGroupName
+     ])
+  , ("OpClusterRepairDiskSizes",
+     [ pInstances
+     ])
+  , ("OpClusterConfigQuery",
+     [ pOutputFields
+     ])
+  , ("OpClusterRename",
+     [ pName
+     ])
+  , ("OpClusterSetParams",
+     [ pHvState
+     , pDiskState
+     , pVgName
+     , pEnabledHypervisors
+     , pClusterHvParams
+     , pClusterBeParams
+     , pOsHvp
+     , pOsParams
+     , pDiskParams
+     , pCandidatePoolSize
+     , pUidPool
+     , pAddUids
+     , pRemoveUids
+     , pMaintainNodeHealth
+     , pPreallocWipeDisks
+     , pNicParams
+     , pNdParams
+     , pIpolicy
+     , pDrbdHelper
+     , pDefaultIAllocator
+     , pMasterNetdev
+     , pReservedLvs
+     , pHiddenOs
+     , pBlacklistedOs
+     , pUseExternalMipScript
+     ])
+  , ("OpClusterRedistConf", [])
+  , ("OpClusterActivateMasterIp", [])
+  , ("OpClusterDeactivateMasterIp", [])
+  , ("OpQuery",
+     [ pQueryWhat
+     , pUseLocking
+     , pQueryFields
+     , pQueryFilter
+     ])
+  , ("OpQueryFields",
+     [ pQueryWhat
+     , pQueryFields
+     ])
+  , ("OpOobCommand",
+     [ pNodeNames
+     , pOobCommand
+     , pOobTimeout
+     , pIgnoreStatus
+     , pPowerDelay
+     ])
+  , ("OpNodeRemove", [ pNodeName ])
+  , ("OpNodeAdd",
+     [ pNodeName
+     , pHvState
+     , pDiskState
+     , pPrimaryIp
+     , pSecondaryIp
+     , pReadd
+     , pNodeGroup
+     , pMasterCapable
+     , pVmCapable
+     , pNdParams
+    ])
+  , ("OpNodeQuery",
+     [ pOutputFields
+     , pUseLocking
+     , pNames
+     ])
+  , ("OpNodeQueryvols",
+     [ pOutputFields
+     , pNodes
+     ])
+  , ("OpNodeQueryStorage",
+     [ pOutputFields
+     , pStorageType
+     , pNodes
+     , pStorageName
+     ])
+  , ("OpNodeModifyStorage",
+     [ pNodeName
+     , pStorageType
+     , pStorageName
+     , pStorageChanges
+     ])
+  , ("OpRepairNodeStorage",
+     [ pNodeName
+     , pStorageType
+     , pStorageName
+     , pIgnoreConsistency
+     ])
+  , ("OpNodeSetParams",
+     [ pNodeName
+     , pForce
+     , pHvState
+     , pDiskState
+     , pMasterCandidate
+     , pOffline
+     , pDrained
+     , pAutoPromote
+     , pMasterCapable
+     , pVmCapable
+     , pSecondaryIp
+     , pNdParams
+     ])
+  , ("OpNodePowercycle",
+     [ pNodeName
+     , pForce
+     ])
+  , ("OpNodeMigrate",
+     [ pNodeName
+     , pMigrationMode
+     , pMigrationLive
+     , pMigrationTargetNode
+     , pAllowRuntimeChgs
+     , pIgnoreIpolicy
+     , pIallocator
+     ])
+  , ("OpNodeEvacuate",
+     [ pEarlyRelease
+     , pNodeName
+     , pRemoteNode
+     , pIallocator
+     , pEvacMode
+     ])
   ])
 
 -- | Returns the OP_ID for a given opcode value.