diff --git a/htest/Test/Ganeti/OpCodes.hs b/htest/Test/Ganeti/OpCodes.hs
index daebf4d5d540ca2f63b463ffb5a6a5ae0b0c0fb3..e2bc8a468ce1a869fc4299f728404978482f83d4 100644
--- a/htest/Test/Ganeti/OpCodes.hs
+++ b/htest/Test/Ganeti/OpCodes.hs
@@ -71,6 +71,10 @@ instance Arbitrary OpCodes.OpCode where
       "OP_INSTANCE_MIGRATE" ->
         OpCodes.OpInstanceMigrate <$> getFQDN <*> arbitrary <*>
           arbitrary <*> arbitrary <*> getMaybe getFQDN
+      "OP_TAGS_SET" ->
+        OpCodes.OpTagsSet <$> arbitrary <*> genTags <*> getMaybe getFQDN
+      "OP_TAGS_DEL" ->
+        OpCodes.OpTagsSet <$> arbitrary <*> genTags <*> getMaybe getFQDN
       _ -> fail "Wrong opcode"
 
 -- * Test cases
diff --git a/htools/Ganeti/OpCodes.hs b/htools/Ganeti/OpCodes.hs
index 6daa6e69091f19cfd32a038630dad5da184227c0..789d84a04f411e0b1e57a2e350c4edf78a49ea45 100644
--- a/htools/Ganeti/OpCodes.hs
+++ b/htools/Ganeti/OpCodes.hs
@@ -79,8 +79,8 @@ instance JSON DiskIndex where
 
 -- | OpCode representation.
 --
--- We only implement a subset of Ganeti opcodes, but only what we
--- actually use in the htools codebase.
+-- We only implement a subset of Ganeti opcodes: those which are actually used
+-- in the htools codebase.
 $(genOpCode "OpCode"
   [ ("OpTestDelay",
      [ simpleField "duration"  [t| Double   |]
@@ -106,6 +106,16 @@ $(genOpCode "OpCode"
      , defaultField [| False |] $ simpleField "allow_failover" [t| Bool |]
      , optionalField $ simpleField "target_node" [t| String |]
      ])
+  , ("OpTagsSet",
+     [ simpleField "kind" [t| TagObject |]
+     , simpleField "tags" [t| [String]  |]
+     , optionalNullSerField $ simpleField "name" [t| String |]
+     ])
+  , ("OpTagsDel",
+     [ simpleField "kind" [t| TagObject |]
+     , simpleField "tags" [t| [String]  |]
+     , optionalNullSerField $ simpleField "name" [t| String |]
+     ])
   ])
 
 -- | Returns the OP_ID for a given opcode value.