Allow classic queries to use either names or UUIDs
authorHrvoje Ribicic <riba@google.com>
Thu, 6 Feb 2014 09:28:48 +0000 (09:28 +0000)
committerHrvoje Ribicic <riba@google.com>
Fri, 7 Feb 2014 13:42:38 +0000 (14:42 +0100)
When UUIDs are used in CLI commands, such addressing of objects fails
or succeeds inconsistently across object types. Worse yet, some calls
do not fail, but simply return no result. This is due to the way the
classical queries are handled in the Haskell code - a filter is built,
checking if the names match. If the names do not match, but the object
can still be retrieved through UUID, the query is successful, but there
is nothing to return.

This patch remedies the situation by extending the filter into an or
clause checking for either name or uuid. For objects that have no uuid
field, the name is reused, making the filter equivalent to the old one.

Works towards resolving issue 703.

Signed-off-by: Hrvoje Ribicic <riba@google.com>
Reviewed-by: Klaus Aehlig <aehlig@google.com>

src/Ganeti/Query/Query.hs
src/Ganeti/Query/Server.hs

index bce1f3f..f3c7ce5 100644 (file)
@@ -50,6 +50,7 @@ module Ganeti.Query.Query
     , queryCompat
     , getRequestedNames
     , nameField
+    , uuidField
     ) where
 
 import Control.DeepSeq
@@ -121,6 +122,13 @@ nameField (ItemTypeLuxi QRJob) = "id"
 nameField (ItemTypeOpCode QRExport) = "node"
 nameField _ = "name"
 
+-- | Computes the uuid field, or the best possible substitute, for different
+-- query types.
+uuidField :: ItemType -> FilterField
+uuidField (ItemTypeLuxi QRJob) = nameField (ItemTypeLuxi QRJob)
+uuidField (ItemTypeOpCode QRExport) = nameField (ItemTypeOpCode QRExport)
+uuidField _ = "uuid"
+
 -- | Extracts all quoted strings from a list, ignoring the
 -- 'NumericValue' entries.
 getAllQuotedStrings :: [FilterValue] -> [String]
index b38e556..33a052b 100644 (file)
@@ -69,7 +69,8 @@ handleClassicQuery :: ConfigData      -- ^ Cluster config
 handleClassicQuery _ _ _ _ True =
   return . Bad $ OpPrereqError "Sync queries are not allowed" ECodeInval
 handleClassicQuery cfg qkind names fields _ = do
-  let flt = makeSimpleFilter (nameField qkind) names
+  let simpleNameFilter field = makeSimpleFilter (field qkind) names
+      flt = Qlang.OrFilter $ map simpleNameFilter [nameField, uuidField]
   qr <- query cfg True (Qlang.Query qkind fields flt)
   return $ showJSON <$> (qr >>= queryCompat)