1 {-| Implementation of the Ganeti Query2 common objects.
7 Copyright (C) 2012 Google Inc.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 module Ganeti.Query.Common
41 import qualified Data.Map as Map
42 import Data.Maybe (fromMaybe)
43 import Text.JSON (JSON, showJSON)
45 import qualified Ganeti.Constants as C
49 import Ganeti.Query.Types
51 -- * Generic functions
53 -- | Conversion from 'VType' to 'FieldType'.
54 vTypeToQFT :: VType -> FieldType
55 vTypeToQFT VTypeString = QFTOther
56 vTypeToQFT VTypeMaybeString = QFTOther
57 vTypeToQFT VTypeBool = QFTBool
58 vTypeToQFT VTypeSize = QFTUnit
59 vTypeToQFT VTypeInt = QFTNumber
63 -- | Helper for a result with no data.
64 rsNoData :: ResultEntry
65 rsNoData = ResultEntry RSNoData Nothing
67 -- | Helper to declare a normal result.
68 rsNormal :: (JSON a) => a -> ResultEntry
69 rsNormal a = ResultEntry RSNormal $ Just (showJSON a)
71 -- | Helper to declare a result from a 'Maybe' (the item might be
72 -- missing, in which case we return no data). Note that there's some
73 -- ambiguity here: in some cases, we mean 'RSNoData', but in other
74 -- 'RSUnavail'; this is easy to solve in simple cases, but not in
76 rsMaybe :: (JSON a) => Maybe a -> ResultEntry
77 rsMaybe = maybe rsNoData rsNormal
79 -- | Helper for unknown field result.
80 rsUnknown :: ResultEntry
81 rsUnknown = ResultEntry RSUnknown Nothing
83 -- | Helper for a missing runtime parameter.
84 missingRuntime :: FieldGetter a b
85 missingRuntime = FieldRuntime (\_ _ -> ResultEntry RSNoData Nothing)
89 -- | The list of timestamp fields.
90 timeStampFields :: (TimeStampObject a) => FieldList a b
92 [ (FieldDefinition "ctime" "CTime" QFTTimestamp "Creation timestamp",
93 FieldSimple (rsNormal . cTimeOf))
94 , (FieldDefinition "mtime" "MTime" QFTTimestamp "Modification timestamp",
95 FieldSimple (rsNormal . mTimeOf))
98 -- | The list of UUID fields.
99 uuidFields :: (UuidObject a) => String -> FieldList a b
101 [ (FieldDefinition "uuid" "UUID" QFTText (name ++ " UUID"),
102 FieldSimple (rsNormal . uuidOf)) ]
104 -- | The list of serial number fields.
105 serialFields :: (SerialNoObject a) => String -> FieldList a b
107 [ (FieldDefinition "serial_no" "SerialNo" QFTNumber
108 (name ++ " object serial number, incremented on each modification"),
109 FieldSimple (rsNormal . serialOf)) ]
111 -- | The list of tag fields.
112 tagsFields :: (TagsObject a) => FieldList a b
114 [ (FieldDefinition "tags" "Tags" QFTOther "Tags",
115 FieldSimple (rsNormal . tagsOf)) ]
117 -- * Generic parameter functions
119 -- | Returns a field from a (possibly missing) 'DictObject'. This is
120 -- used by parameter dictionaries, usually. Note that we have two
121 -- levels of maybe: the top level dict might be missing, or one key in
122 -- the dictionary might be.
123 dictFieldGetter :: (DictObject a) => String -> Maybe a -> ResultEntry
124 dictFieldGetter k = maybe rsNoData (rsMaybe . lookup k . toDict)
126 -- | Build an optimised lookup map from a Python _PARAMETER_TYPES
128 buildQFTLookup :: [(String, String)] -> Map.Map String FieldType
131 map (\(k, v) -> (k, maybe QFTOther vTypeToQFT (vTypeFromRaw v)))
133 -- | Ndparams optimised lookup map.
134 ndParamTypes :: Map.Map String FieldType
135 ndParamTypes = buildQFTLookup C.ndsParameterTypes
137 -- | Ndparams title map.
138 ndParamTitles :: Map.Map String FieldTitle
139 ndParamTitles = Map.fromList C.ndsParameterTitles
141 -- | Ndparam getter builder: given a field, it returns a FieldConfig
142 -- getter, that is a function that takes the config and the object and
143 -- returns the Ndparam field specified when the getter was built.
144 ndParamGetter :: (NdParamObject a) =>
145 String -- ^ The field we're building the getter for
146 -> ConfigData -> a -> ResultEntry
147 ndParamGetter field config =
148 dictFieldGetter field . getNdParamsOf config
150 -- | Builds the ndparam fields for an object.
151 buildNdParamField :: (NdParamObject a) => String -> FieldData a b
152 buildNdParamField field =
153 let full_name = "ndp/" ++ field
154 title = fromMaybe field $ field `Map.lookup` ndParamTitles
155 qft = fromMaybe QFTOther $ field `Map.lookup` ndParamTypes
156 desc = "The \"" ++ field ++ "\" node parameter"
157 in (FieldDefinition full_name title qft desc,
158 FieldConfig (ndParamGetter field))