On Wed, Sep 26, 2012 at 9:39 AM, Iustin Pop <[email protected]> wrote:
> On Tue, Sep 25, 2012 at 06:43:47PM +0200, Agata Murawska wrote:
>> Implementation of nodegroup queries in Haskell. This is not yet
>> complete as we are missing merged disk parameters and option
>> want_diskparams is not implemented.
>>
>> Signed-off-by: Agata Murawska <[email protected]>
>> ---
>> Makefile.am | 1 +
>> htools/Ganeti/Query/Group.hs | 89
>> ++++++++++++++++++++++++++++++++++++++++++
>> htools/Ganeti/Query/Query.hs | 22 ++++++++++
>> 3 files changed, 112 insertions(+), 0 deletions(-)
>> create mode 100644 htools/Ganeti/Query/Group.hs
>>
>> diff --git a/Makefile.am b/Makefile.am
>> index 7ae24ef..1e13fdb 100644
>> --- a/Makefile.am
>> +++ b/Makefile.am
>> @@ -434,6 +434,7 @@ HS_LIB_SRCS = \
>> htools/Ganeti/Path.hs \
>> htools/Ganeti/Query/Common.hs \
>> htools/Ganeti/Query/Filter.hs \
>> + htools/Ganeti/Query/Group.hs \
>> htools/Ganeti/Query/Language.hs \
>> htools/Ganeti/Query/Node.hs \
>> htools/Ganeti/Query/Query.hs \
>> diff --git a/htools/Ganeti/Query/Group.hs b/htools/Ganeti/Query/Group.hs
>> new file mode 100644
>> index 0000000..b4fc758
>> --- /dev/null
>> +++ b/htools/Ganeti/Query/Group.hs
>> @@ -0,0 +1,89 @@
>> +{-| Implementation of the Ganeti Query2 node group queries.
>> +
>> + -}
>> +
>> +{-
>> +
>> +Copyright (C) 2012 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
>> +the Free Software Foundation; either version 2 of the License, or
>> +(at your option) any later version.
>> +
>> +This program is distributed in the hope that it will be useful, but
>> +WITHOUT ANY WARRANTY; without even the implied warranty of
>> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> +General Public License for more details.
>> +
>> +You should have received a copy of the GNU General Public License
>> +along with this program; if not, write to the Free Software
>> +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>> +02110-1301, USA.
>> +
>> +-}
>> +
>> +module Ganeti.Query.Group
>> + ( GroupRuntime(..)
>> + , groupFieldsMap
>> + ) where
>> +
>> +import qualified Data.Map as Map
>> +
>> +import Ganeti.Config
>> +import Ganeti.Objects
>> +import Ganeti.Query.Language
>> +import Ganeti.Query.Common
>> +import Ganeti.Query.Types
>> +
>> +-- | There is no runtime.
>> +data GroupRuntime = GroupRuntime
>> +
>> +groupFields :: FieldList NodeGroup GroupRuntime
>> +groupFields =
>> + [ (FieldDefinition "alloc_policy" "AllocPolicy" QFTText
>> + "Allocation policy for group",
>> + FieldSimple (rsNormal . groupAllocPolicy))
>> + , (FieldDefinition "custom_diskparams" "CustomDiskParameters" QFTOther
>> + "Custom disk parameters",
>> + FieldSimple (rsNormal . groupDiskparams))
>> + , (FieldDefinition "custom_ipolicy" "CustomInstancePolicy" QFTOther
>> + "Custom instance policy limitations",
>> + FieldSimple (rsNormal . groupIpolicy))
>> + , (FieldDefinition "custom_ndparams" "CustomNDParams" QFTOther
>> + "Custom node parameters",
>> + FieldSimple (rsNormal . groupNdparams))
>> + -- This is deliberate - I do not think we want to have RSUnknown here
>
> Indeed, but I fear rsNormal is not good - this would fail unittests, I
> think. You need rsNoData.
Ack, fixed (though it didn't fail the tests we have for groups, just FYI ;) )
>
>> + , (FieldDefinition "diskparams" "DiskParameters" QFTOther
>> + "Disk parameters (merged)",
>> + FieldSimple (\ _ -> rsNormal (Nothing:: Maybe DiskParams)))
>> + , (FieldDefinition "ipolicy" "InstancePolicy" QFTOther
>> + "Instance policy limitations (merged)",
>> + FieldConfig (\cfg ng -> rsNormal (getGroupIpolicy cfg ng)))
>> + , (FieldDefinition "name" "Group" QFTText "Group name",
>> + FieldSimple (rsNormal . groupName))
>> + , (FieldDefinition "ndparams" "NDParams" QFTOther "Node parameters",
>> + FieldConfig (\cfg ng -> rsNormal (getGroupNdParams cfg ng)))
>> + , (FieldDefinition "node_cnt" "Nodes" QFTNumber "Number of nodes",
>> + FieldConfig (\cfg -> rsNormal . length . getGroupNodes cfg .
>> groupName))
>> + , (FieldDefinition "node_list" "NodeList" QFTOther "List of nodes",
>> + FieldConfig (\cfg -> rsNormal . map nodeName .
>> + getGroupNodes cfg . groupName))
>> + , (FieldDefinition "pinst_cnt" "Instances" QFTNumber
>> + "Number of primary instances",
>> + FieldConfig
>> + (\cfg -> rsNormal . length . fst . getGroupInstances cfg .
>> groupName))
>> + , (FieldDefinition "pinst_list" "InstanceList" QFTOther
>> + "List of primary instances",
>> + FieldConfig (\cfg -> rsNormal . map instName . fst .
>> + getGroupInstances cfg . groupName))
>> + ] ++
>> + map buildNdParamField allNDParamFields ++
>> + timeStampFields ++
>> + uuidFields "Group" ++
>> + serialFields "Group" ++
>> + tagsFields
>> +
>> +-- | The group fields map.
>> +groupFieldsMap :: FieldMap NodeGroup GroupRuntime
>> +groupFieldsMap = Map.fromList $ map (\v -> (fdefName (fst v), v))
>> groupFields
>> diff --git a/htools/Ganeti/Query/Query.hs b/htools/Ganeti/Query/Query.hs
>> index 5b09c63..8fc4b4a 100644
>> --- a/htools/Ganeti/Query/Query.hs
>> +++ b/htools/Ganeti/Query/Query.hs
>> @@ -61,6 +61,7 @@ import Ganeti.Query.Common
>> import Ganeti.Query.Filter
>> import Ganeti.Query.Types
>> import Ganeti.Query.Node
>> +import Ganeti.Query.Group
>> import Ganeti.Objects
>>
>> -- * Helper functions
>> @@ -109,6 +110,20 @@ query cfg (Query QRNode fields qfilter) = return $ do
>> fnodes
>> return QueryResult { qresFields = fdefs, qresData = fdata }
>>
>> +query cfg (Query QRGroup fields qfilter) = return $ do
>> + -- FIXME: want_diskparams is defaulted to false and not taken as parameter
>> + -- This is because the type for DiskParams is right now too generic for
>> merges
>> + -- (or else I cannot see how to do this with curent implementation)
>
> This should be doable already with Ganeti/Objects/fillDict, which was
> added for this purpose. It's not yet used, so I don't know how well it
> works. Please commit as is for now and we'll see later about migrating
> to that.
Ack
>
>> + cfilter <- compileFilter groupFieldsMap qfilter
>> + let selected = getSelectedFields groupFieldsMap fields
>> + (fdefs, fgetters) = unzip selected
>> + groups = Map.elems . fromContainer $ configNodegroups cfg
>> + -- there is no live data for groups, so filtering is much simpler
>> + fgroups <- filterM (\n -> evaluateFilter cfg Nothing n cfilter) groups
>> + let fdata = map (\node ->
>> + map (execGetter cfg GroupRuntime node) fgetters)
>> fgroups
>> + return QueryResult {qresFields = fdefs, qresData = fdata }
>> +
>> query _ (Query qkind _ _) =
>> return . Bad $ "Query '" ++ show qkind ++ "' not supported"
>>
>> @@ -120,5 +135,12 @@ queryFields (QueryFields QRNode fields) =
>> else getSelectedFields nodeFieldsMap fields
>> in Ok $ QueryFieldsResult (map fst selected)
>>
>> +queryFields (QueryFields QRGroup fields) =
>> + let selected = if null fields
>> + then map snd $ Map.toAscList groupFieldsMap
>> + else getSelectedFields groupFieldsMap fields
>> + in Ok $ QueryFieldsResult (map fst selected)
>
> Hmm, this being identical to the QueryField QRNode one, it smells like a
> type class. Please add a FIXME, this should be generalisable easily.
Ack
>
> LGTM after fixing rsNormal/rsNoData above.
>
> thanks!
> iustin
Interdiff:
diff --git a/htools/Ganeti/Query/Group.hs b/htools/Ganeti/Query/Group.hs
index b4fc758..b76d6c3 100644
--- a/htools/Ganeti/Query/Group.hs
+++ b/htools/Ganeti/Query/Group.hs
@@ -53,10 +53,8 @@ groupFields =
, (FieldDefinition "custom_ndparams" "CustomNDParams" QFTOther
"Custom node parameters",
FieldSimple (rsNormal . groupNdparams))
- -- This is deliberate - I do not think we want to have RSUnknown here
, (FieldDefinition "diskparams" "DiskParameters" QFTOther
- "Disk parameters (merged)",
- FieldSimple (\ _ -> rsNormal (Nothing:: Maybe DiskParams)))
+ "Disk parameters (merged)", FieldSimple (\_ -> rsNoData))
, (FieldDefinition "ipolicy" "InstancePolicy" QFTOther
"Instance policy limitations (merged)",
FieldConfig (\cfg ng -> rsNormal (getGroupIpolicy cfg ng)))
diff --git a/htools/Ganeti/Query/Query.hs b/htools/Ganeti/Query/Query.hs
index 8fc4b4a..d348be1 100644
--- a/htools/Ganeti/Query/Query.hs
+++ b/htools/Ganeti/Query/Query.hs
@@ -128,6 +128,7 @@ query _ (Query qkind _ _) =
return . Bad $ "Query '" ++ show qkind ++ "' not supported"
-- | Query fields call.
+-- FIXME: Looks generic enough to use a typeclass
queryFields :: QueryFields -> Result QueryFieldsResult
queryFields (QueryFields QRNode fields) =
let selected = if null fields