diff --git a/htools/Ganeti/HTools/QC.hs b/htools/Ganeti/HTools/QC.hs
index 2410bdbbe6494141b2b1c99c5de68982502b4438..611d74dcd46ee16417ea5ddac2a14ab352b1d7a2 100644
--- a/htools/Ganeti/HTools/QC.hs
+++ b/htools/Ganeti/HTools/QC.hs
@@ -57,6 +57,7 @@ import Test.QuickCheck.Monadic (assert, monadicIO, run, stop)
 import Text.Printf (printf)
 import Data.List (intercalate, nub, isPrefixOf)
 import Data.Maybe
+import qualified Data.Set as Set
 import Control.Monad
 import Control.Applicative
 import qualified System.Console.GetOpt as GetOpt
@@ -548,6 +549,7 @@ instance Arbitrary Objects.Node where
               <*> arbitrary <*> arbitrary <*> arbitrary <*> getFQDN
               <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
               <*> arbitrary <*> arbitrary <*> getFQDN <*> arbitrary
+              <*> (Set.fromList <$> genTags)
 
 instance Arbitrary Rpc.RpcCallAllInstancesInfo where
   arbitrary = Rpc.RpcCallAllInstancesInfo <$> arbitrary
diff --git a/htools/Ganeti/Objects.hs b/htools/Ganeti/Objects.hs
index 380524c03419e992d9d29a2fe566f6ba85ddaac7..75e1d6bb7250a12b1d6bc50e246eb80f34f0f468 100644
--- a/htools/Ganeti/Objects.hs
+++ b/htools/Ganeti/Objects.hs
@@ -293,7 +293,8 @@ $(buildObject "Instance" "inst" $
   ]
   ++ timeStampFields
   ++ uuidFields
-  ++ serialFields)
+  ++ serialFields
+  ++ tagsFields)
 
 -- * IPolicy definitions
 
@@ -374,7 +375,8 @@ $(buildObject "Node" "node" $
   ]
   ++ timeStampFields
   ++ uuidFields
-  ++ serialFields)
+  ++ serialFields
+  ++ tagsFields)
 
 -- * NodeGroup definitions
 
@@ -402,7 +404,8 @@ $(buildObject "NodeGroup" "group" $
   ]
   ++ timeStampFields
   ++ uuidFields
-  ++ serialFields)
+  ++ serialFields
+  ++ tagsFields)
 
 -- | IP family type
 $(declareIADT "IpFamily"
diff --git a/htools/Ganeti/Queryd.hs b/htools/Ganeti/Queryd.hs
index 4f265bdfb5e5c63877782ee6b2e1c13c1f54f259..1ac44fc16768c89cd8bbbb4496def12c39ae73af 100644
--- a/htools/Ganeti/Queryd.hs
+++ b/htools/Ganeti/Queryd.hs
@@ -29,6 +29,7 @@ module Ganeti.Queryd
 
 where
 
+import Control.Applicative
 import Control.Concurrent
 import Control.Exception
 import Data.Bits (bitSize)
@@ -41,7 +42,7 @@ import System.Info (arch)
 
 import qualified Ganeti.Constants as C
 import Ganeti.Objects
---import Ganeti.Config
+import qualified Ganeti.Config as Config
 import Ganeti.BasicTypes
 import Ganeti.Logging
 import Ganeti.Luxi
@@ -118,6 +119,14 @@ handleCall cdata QueryClusterInfo =
 
   in return . Ok . J.makeObj $ obj
 
+handleCall cfg (QueryTags kind name) =
+  let tags = case kind of
+               TagCluster -> Ok . clusterTags $ configCluster cfg
+               TagGroup -> groupTags <$> Config.getGroup cfg name
+               TagNode -> nodeTags <$> Config.getNode cfg name
+               TagInstance -> instTags <$> Config.getInstance cfg name
+  in return (J.showJSON <$> tags)
+
 handleCall _ op =
   return . Bad $ "Luxi call '" ++ strOfOp op ++ "' not implemented"
 
diff --git a/lib/cli.py b/lib/cli.py
index 44d854dd4b077f1c30c736aa8f03c4eb71949292..845c8a7bc53e4771d458ce3d3ab76d6667267c65 100644
--- a/lib/cli.py
+++ b/lib/cli.py
@@ -464,7 +464,7 @@ def ListTags(opts, args):
 
   """
   kind, name = _ExtractTagsObject(opts, args)
-  cl = GetClient()
+  cl = GetClient(query=True)
   result = cl.QueryTags(kind, name)
   result = list(result)
   result.sort()
diff --git a/lib/rapi/rlib2.py b/lib/rapi/rlib2.py
index addb938c1b65ebfc76b99a883ef9524431ffc771..4259a6e34d91b7496662866b166456849a3a273c 100644
--- a/lib/rapi/rlib2.py
+++ b/lib/rapi/rlib2.py
@@ -1339,7 +1339,7 @@ class _R_Tags(baserlib.OpcodeResource):
       if not self.name:
         raise http.HttpBadRequest("Missing name on tag request")
 
-      cl = self.GetClient()
+      cl = self.GetClient(query=True)
       tags = list(cl.QueryTags(kind, self.name))
 
     elif kind == constants.TAG_CLUSTER: