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
43 import qualified Data.Map as Map
44 import Data.Maybe (fromMaybe)
45 import Text.JSON (JSON, showJSON)
47 import qualified Ganeti.Constants as C
51 import Ganeti.Query.Language
52 import Ganeti.Query.Types
54 -- * Generic functions
56 -- | Conversion from 'VType' to 'FieldType'.
57 vTypeToQFT :: VType -> FieldType
58 vTypeToQFT VTypeString = QFTOther
59 vTypeToQFT VTypeMaybeString = QFTOther
60 vTypeToQFT VTypeBool = QFTBool
61 vTypeToQFT VTypeSize = QFTUnit
62 vTypeToQFT VTypeInt = QFTNumber
66 -- | Helper for a result with no data.
67 rsNoData :: ResultEntry
68 rsNoData = ResultEntry RSNoData Nothing
70 -- | Helper for result for an entity which supports no such field.
71 rsUnavail :: ResultEntry
72 rsUnavail = ResultEntry RSUnavail Nothing
74 -- | Helper to declare a normal result.
75 rsNormal :: (JSON a) => a -> ResultEntry
76 rsNormal a = ResultEntry RSNormal $ Just (showJSON a)
78 -- | Helper to declare a result from a 'Maybe' (the item might be
79 -- missing, in which case we return no data). Note that there's some
80 -- ambiguity here: in some cases, we mean 'RSNoData', but in other
81 -- 'RSUnavail'; this is easy to solve in simple cases, but not in
83 rsMaybe :: (JSON a) => Maybe a -> ResultEntry
84 rsMaybe = maybe rsNoData rsNormal
86 -- | Helper for unknown field result.
87 rsUnknown :: ResultEntry
88 rsUnknown = ResultEntry RSUnknown Nothing
90 -- | Helper for a missing runtime parameter.
91 missingRuntime :: FieldGetter a b
92 missingRuntime = FieldRuntime (\_ _ -> ResultEntry RSNoData Nothing)
96 -- | Convert RpcError to ResultStatus
97 rpcErrorToStatus :: RpcError -> ResultStatus
98 rpcErrorToStatus (OfflineNodeError _) = RSOffline
99 rpcErrorToStatus _ = RSNoData
103 -- | The list of timestamp fields.
104 timeStampFields :: (TimeStampObject a) => FieldList a b
106 [ (FieldDefinition "ctime" "CTime" QFTTimestamp "Creation timestamp",
107 FieldSimple (rsNormal . cTimeOf))
108 , (FieldDefinition "mtime" "MTime" QFTTimestamp "Modification timestamp",
109 FieldSimple (rsNormal . mTimeOf))
112 -- | The list of UUID fields.
113 uuidFields :: (UuidObject a) => String -> FieldList a b
115 [ (FieldDefinition "uuid" "UUID" QFTText (name ++ " UUID"),
116 FieldSimple (rsNormal . uuidOf)) ]
118 -- | The list of serial number fields.
119 serialFields :: (SerialNoObject a) => String -> FieldList a b
121 [ (FieldDefinition "serial_no" "SerialNo" QFTNumber
122 (name ++ " object serial number, incremented on each modification"),
123 FieldSimple (rsNormal . serialOf)) ]
125 -- | The list of tag fields.
126 tagsFields :: (TagsObject a) => FieldList a b
128 [ (FieldDefinition "tags" "Tags" QFTOther "Tags",
129 FieldSimple (rsNormal . tagsOf)) ]
131 -- * Generic parameter functions
133 -- | Returns a field from a (possibly missing) 'DictObject'. This is
134 -- used by parameter dictionaries, usually. Note that we have two
135 -- levels of maybe: the top level dict might be missing, or one key in
136 -- the dictionary might be.
137 dictFieldGetter :: (DictObject a) => String -> Maybe a -> ResultEntry
138 dictFieldGetter k = maybe rsNoData (rsMaybe . lookup k . toDict)
140 -- | Build an optimised lookup map from a Python _PARAMETER_TYPES
142 buildQFTLookup :: [(String, String)] -> Map.Map String FieldType
145 map (\(k, v) -> (k, maybe QFTOther vTypeToQFT (vTypeFromRaw v)))
147 -- | Ndparams optimised lookup map.
148 ndParamTypes :: Map.Map String FieldType
149 ndParamTypes = buildQFTLookup C.ndsParameterTypes
151 -- | Ndparams title map.
152 ndParamTitles :: Map.Map String FieldTitle
153 ndParamTitles = Map.fromList C.ndsParameterTitles
155 -- | Ndparam getter builder: given a field, it returns a FieldConfig
156 -- getter, that is a function that takes the config and the object and
157 -- returns the Ndparam field specified when the getter was built.
158 ndParamGetter :: (NdParamObject a) =>
159 String -- ^ The field we're building the getter for
160 -> ConfigData -> a -> ResultEntry
161 ndParamGetter field config =
162 dictFieldGetter field . getNdParamsOf config
164 -- | Builds the ndparam fields for an object.
165 buildNdParamField :: (NdParamObject a) => String -> FieldData a b
166 buildNdParamField field =
167 let full_name = "ndp/" ++ field
168 title = fromMaybe field $ field `Map.lookup` ndParamTitles
169 qft = fromMaybe QFTOther $ field `Map.lookup` ndParamTypes
170 desc = "The \"" ++ field ++ "\" node parameter"
171 in (FieldDefinition full_name title qft desc,
172 FieldConfig (ndParamGetter field))