Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / Query / Common.hs @ c92b4671

History | View | Annotate | Download (8.8 kB)

1 046fe3f5 Iustin Pop
{-| Implementation of the Ganeti Query2 common objects.
2 046fe3f5 Iustin Pop
3 046fe3f5 Iustin Pop
 -}
4 046fe3f5 Iustin Pop
5 046fe3f5 Iustin Pop
{-
6 046fe3f5 Iustin Pop
7 9c0a27d0 Iustin Pop
Copyright (C) 2012, 2013 Google Inc.
8 046fe3f5 Iustin Pop
9 046fe3f5 Iustin Pop
This program is free software; you can redistribute it and/or modify
10 046fe3f5 Iustin Pop
it under the terms of the GNU General Public License as published by
11 046fe3f5 Iustin Pop
the Free Software Foundation; either version 2 of the License, or
12 046fe3f5 Iustin Pop
(at your option) any later version.
13 046fe3f5 Iustin Pop
14 046fe3f5 Iustin Pop
This program is distributed in the hope that it will be useful, but
15 046fe3f5 Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
16 046fe3f5 Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 046fe3f5 Iustin Pop
General Public License for more details.
18 046fe3f5 Iustin Pop
19 046fe3f5 Iustin Pop
You should have received a copy of the GNU General Public License
20 046fe3f5 Iustin Pop
along with this program; if not, write to the Free Software
21 046fe3f5 Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 046fe3f5 Iustin Pop
02110-1301, USA.
23 046fe3f5 Iustin Pop
24 046fe3f5 Iustin Pop
-}
25 046fe3f5 Iustin Pop
26 046fe3f5 Iustin Pop
module Ganeti.Query.Common
27 d286d795 Hrvoje Ribicic
  ( NoDataRuntime(..)
28 d286d795 Hrvoje Ribicic
  , rsNoData
29 5227de56 Iustin Pop
  , rsUnavail
30 046fe3f5 Iustin Pop
  , rsNormal
31 a64cc96b Helga Velroyen
  , rsMaybeNoData
32 a64cc96b Helga Velroyen
  , rsMaybeUnavail
33 9491766c Hrvoje Ribicic
  , rsErrorNoData
34 046fe3f5 Iustin Pop
  , rsUnknown
35 046fe3f5 Iustin Pop
  , missingRuntime
36 4393e075 Agata Murawska
  , rpcErrorToStatus
37 046fe3f5 Iustin Pop
  , timeStampFields
38 046fe3f5 Iustin Pop
  , uuidFields
39 046fe3f5 Iustin Pop
  , serialFields
40 046fe3f5 Iustin Pop
  , tagsFields
41 046fe3f5 Iustin Pop
  , dictFieldGetter
42 046fe3f5 Iustin Pop
  , buildNdParamField
43 4e6f1cde Hrvoje Ribicic
  , buildBeParamField
44 4e6f1cde Hrvoje Ribicic
  , buildHvParamField
45 c2fe6008 Hrvoje Ribicic
  , getDefaultHypervisorSpec
46 c2fe6008 Hrvoje Ribicic
  , getHvParamsFromCluster
47 3fd38382 Hrvoje Ribicic
  , aliasFields
48 046fe3f5 Iustin Pop
  ) where
49 046fe3f5 Iustin Pop
50 3fd38382 Hrvoje Ribicic
import Control.Monad (guard)
51 046fe3f5 Iustin Pop
import qualified Data.Map as Map
52 046fe3f5 Iustin Pop
import Data.Maybe (fromMaybe)
53 046fe3f5 Iustin Pop
import Text.JSON (JSON, showJSON)
54 046fe3f5 Iustin Pop
55 9491766c Hrvoje Ribicic
import Ganeti.BasicTypes
56 046fe3f5 Iustin Pop
import qualified Ganeti.Constants as C
57 046fe3f5 Iustin Pop
import Ganeti.Config
58 9491766c Hrvoje Ribicic
import Ganeti.Errors
59 c2fe6008 Hrvoje Ribicic
import Ganeti.JSON
60 046fe3f5 Iustin Pop
import Ganeti.Objects
61 4393e075 Agata Murawska
import Ganeti.Rpc
62 4cab6703 Iustin Pop
import Ganeti.Query.Language
63 046fe3f5 Iustin Pop
import Ganeti.Query.Types
64 8e6ef316 Jose A. Lopes
import Ganeti.Types
65 046fe3f5 Iustin Pop
66 d286d795 Hrvoje Ribicic
-- | The runtime used by queries which retrieve no live data.
67 d286d795 Hrvoje Ribicic
data NoDataRuntime = NoDataRuntime
68 d286d795 Hrvoje Ribicic
69 046fe3f5 Iustin Pop
-- * Generic functions
70 046fe3f5 Iustin Pop
71 046fe3f5 Iustin Pop
-- | Conversion from 'VType' to 'FieldType'.
72 046fe3f5 Iustin Pop
vTypeToQFT :: VType -> FieldType
73 046fe3f5 Iustin Pop
vTypeToQFT VTypeString      = QFTOther
74 046fe3f5 Iustin Pop
vTypeToQFT VTypeMaybeString = QFTOther
75 046fe3f5 Iustin Pop
vTypeToQFT VTypeBool        = QFTBool
76 046fe3f5 Iustin Pop
vTypeToQFT VTypeSize        = QFTUnit
77 046fe3f5 Iustin Pop
vTypeToQFT VTypeInt         = QFTNumber
78 046fe3f5 Iustin Pop
79 046fe3f5 Iustin Pop
-- * Result helpers
80 046fe3f5 Iustin Pop
81 046fe3f5 Iustin Pop
-- | Helper for a result with no data.
82 046fe3f5 Iustin Pop
rsNoData :: ResultEntry
83 046fe3f5 Iustin Pop
rsNoData = ResultEntry RSNoData Nothing
84 046fe3f5 Iustin Pop
85 5227de56 Iustin Pop
-- | Helper for result for an entity which supports no such field.
86 5227de56 Iustin Pop
rsUnavail :: ResultEntry
87 5227de56 Iustin Pop
rsUnavail = ResultEntry RSUnavail Nothing
88 5227de56 Iustin Pop
89 046fe3f5 Iustin Pop
-- | Helper to declare a normal result.
90 046fe3f5 Iustin Pop
rsNormal :: (JSON a) => a -> ResultEntry
91 046fe3f5 Iustin Pop
rsNormal a = ResultEntry RSNormal $ Just (showJSON a)
92 046fe3f5 Iustin Pop
93 046fe3f5 Iustin Pop
-- | Helper to declare a result from a 'Maybe' (the item might be
94 046fe3f5 Iustin Pop
-- missing, in which case we return no data). Note that there's some
95 046fe3f5 Iustin Pop
-- ambiguity here: in some cases, we mean 'RSNoData', but in other
96 046fe3f5 Iustin Pop
-- 'RSUnavail'; this is easy to solve in simple cases, but not in
97 a64cc96b Helga Velroyen
-- nested dicts. If you want to return 'RSUnavail' in case of 'Nothing'
98 a64cc96b Helga Velroyen
-- use the function 'rsMaybeUnavail'.
99 a64cc96b Helga Velroyen
rsMaybeNoData :: (JSON a) => Maybe a -> ResultEntry
100 a64cc96b Helga Velroyen
rsMaybeNoData = maybe rsNoData rsNormal
101 a64cc96b Helga Velroyen
102 9491766c Hrvoje Ribicic
-- | Helper to declare a result from a 'ErrorResult' (an error happened
103 9491766c Hrvoje Ribicic
-- while retrieving the data from a config, or there was no data).
104 9491766c Hrvoje Ribicic
-- This function should be used if an error signals there was no data.
105 9491766c Hrvoje Ribicic
rsErrorNoData :: (JSON a) => ErrorResult a -> ResultEntry
106 9491766c Hrvoje Ribicic
rsErrorNoData res = case res of
107 9491766c Hrvoje Ribicic
  Ok  x -> rsNormal x
108 9491766c Hrvoje Ribicic
  Bad _ -> rsNoData
109 9491766c Hrvoje Ribicic
110 a64cc96b Helga Velroyen
-- | Helper to declare a result from a 'Maybe'. This version returns
111 a64cc96b Helga Velroyen
-- a 'RSUnavail' in case of 'Nothing'. It should be used for optional
112 a64cc96b Helga Velroyen
-- fields that are not set. For cases where 'Nothing' means that there
113 a64cc96b Helga Velroyen
-- was an error, consider using 'rsMaybe' instead.
114 a64cc96b Helga Velroyen
rsMaybeUnavail :: (JSON a) => Maybe a -> ResultEntry
115 a64cc96b Helga Velroyen
rsMaybeUnavail = maybe rsUnavail rsNormal
116 046fe3f5 Iustin Pop
117 046fe3f5 Iustin Pop
-- | Helper for unknown field result.
118 046fe3f5 Iustin Pop
rsUnknown :: ResultEntry
119 046fe3f5 Iustin Pop
rsUnknown = ResultEntry RSUnknown Nothing
120 046fe3f5 Iustin Pop
121 046fe3f5 Iustin Pop
-- | Helper for a missing runtime parameter.
122 046fe3f5 Iustin Pop
missingRuntime :: FieldGetter a b
123 046fe3f5 Iustin Pop
missingRuntime = FieldRuntime (\_ _ -> ResultEntry RSNoData Nothing)
124 046fe3f5 Iustin Pop
125 4393e075 Agata Murawska
-- * Error conversion
126 4393e075 Agata Murawska
127 4393e075 Agata Murawska
-- | Convert RpcError to ResultStatus
128 4393e075 Agata Murawska
rpcErrorToStatus :: RpcError -> ResultStatus
129 9c0a27d0 Iustin Pop
rpcErrorToStatus OfflineNodeError = RSOffline
130 4393e075 Agata Murawska
rpcErrorToStatus _ = RSNoData
131 4393e075 Agata Murawska
132 046fe3f5 Iustin Pop
-- * Common fields
133 046fe3f5 Iustin Pop
134 046fe3f5 Iustin Pop
-- | The list of timestamp fields.
135 046fe3f5 Iustin Pop
timeStampFields :: (TimeStampObject a) => FieldList a b
136 046fe3f5 Iustin Pop
timeStampFields =
137 046fe3f5 Iustin Pop
  [ (FieldDefinition "ctime" "CTime" QFTTimestamp "Creation timestamp",
138 74b3f734 Petr Pudlak
     FieldSimple (rsNormal . TimeAsDoubleJSON . cTimeOf), QffNormal)
139 046fe3f5 Iustin Pop
  , (FieldDefinition "mtime" "MTime" QFTTimestamp "Modification timestamp",
140 74b3f734 Petr Pudlak
     FieldSimple (rsNormal . TimeAsDoubleJSON . mTimeOf), QffNormal)
141 046fe3f5 Iustin Pop
  ]
142 046fe3f5 Iustin Pop
143 046fe3f5 Iustin Pop
-- | The list of UUID fields.
144 046fe3f5 Iustin Pop
uuidFields :: (UuidObject a) => String -> FieldList a b
145 046fe3f5 Iustin Pop
uuidFields name =
146 046fe3f5 Iustin Pop
  [ (FieldDefinition "uuid" "UUID" QFTText  (name ++ " UUID"),
147 f94a9680 Iustin Pop
     FieldSimple (rsNormal . uuidOf), QffNormal) ]
148 046fe3f5 Iustin Pop
149 046fe3f5 Iustin Pop
-- | The list of serial number fields.
150 046fe3f5 Iustin Pop
serialFields :: (SerialNoObject a) => String -> FieldList a b
151 046fe3f5 Iustin Pop
serialFields name =
152 046fe3f5 Iustin Pop
  [ (FieldDefinition "serial_no" "SerialNo" QFTNumber
153 046fe3f5 Iustin Pop
     (name ++ " object serial number, incremented on each modification"),
154 f94a9680 Iustin Pop
     FieldSimple (rsNormal . serialOf), QffNormal) ]
155 046fe3f5 Iustin Pop
156 046fe3f5 Iustin Pop
-- | The list of tag fields.
157 046fe3f5 Iustin Pop
tagsFields :: (TagsObject a) => FieldList a b
158 046fe3f5 Iustin Pop
tagsFields =
159 046fe3f5 Iustin Pop
  [ (FieldDefinition "tags" "Tags" QFTOther "Tags",
160 f94a9680 Iustin Pop
     FieldSimple (rsNormal . tagsOf), QffNormal) ]
161 046fe3f5 Iustin Pop
162 046fe3f5 Iustin Pop
-- * Generic parameter functions
163 046fe3f5 Iustin Pop
164 046fe3f5 Iustin Pop
-- | Returns a field from a (possibly missing) 'DictObject'. This is
165 046fe3f5 Iustin Pop
-- used by parameter dictionaries, usually. Note that we have two
166 046fe3f5 Iustin Pop
-- levels of maybe: the top level dict might be missing, or one key in
167 046fe3f5 Iustin Pop
-- the dictionary might be.
168 046fe3f5 Iustin Pop
dictFieldGetter :: (DictObject a) => String -> Maybe a -> ResultEntry
169 a64cc96b Helga Velroyen
dictFieldGetter k = maybe rsNoData (rsMaybeNoData . lookup k . toDict)
170 046fe3f5 Iustin Pop
171 046fe3f5 Iustin Pop
-- | Ndparams optimised lookup map.
172 046fe3f5 Iustin Pop
ndParamTypes :: Map.Map String FieldType
173 ecf43dcb Jose A. Lopes
ndParamTypes = Map.map vTypeToQFT C.ndsParameterTypes
174 046fe3f5 Iustin Pop
175 046fe3f5 Iustin Pop
-- | Ndparams title map.
176 046fe3f5 Iustin Pop
ndParamTitles :: Map.Map String FieldTitle
177 ecf43dcb Jose A. Lopes
ndParamTitles = C.ndsParameterTitles
178 046fe3f5 Iustin Pop
179 046fe3f5 Iustin Pop
-- | Ndparam getter builder: given a field, it returns a FieldConfig
180 046fe3f5 Iustin Pop
-- getter, that is a function that takes the config and the object and
181 046fe3f5 Iustin Pop
-- returns the Ndparam field specified when the getter was built.
182 046fe3f5 Iustin Pop
ndParamGetter :: (NdParamObject a) =>
183 046fe3f5 Iustin Pop
                 String -- ^ The field we're building the getter for
184 046fe3f5 Iustin Pop
              -> ConfigData -> a -> ResultEntry
185 046fe3f5 Iustin Pop
ndParamGetter field config =
186 046fe3f5 Iustin Pop
  dictFieldGetter field . getNdParamsOf config
187 046fe3f5 Iustin Pop
188 046fe3f5 Iustin Pop
-- | Builds the ndparam fields for an object.
189 046fe3f5 Iustin Pop
buildNdParamField :: (NdParamObject a) => String -> FieldData a b
190 4e6f1cde Hrvoje Ribicic
buildNdParamField =
191 4e6f1cde Hrvoje Ribicic
  buildParamField "ndp" "node" ndParamTitles ndParamTypes ndParamGetter
192 4e6f1cde Hrvoje Ribicic
193 4e6f1cde Hrvoje Ribicic
-- | Beparams optimised lookup map.
194 4e6f1cde Hrvoje Ribicic
beParamTypes :: Map.Map String FieldType
195 4e6f1cde Hrvoje Ribicic
beParamTypes = Map.map vTypeToQFT C.besParameterTypes
196 4e6f1cde Hrvoje Ribicic
197 4e6f1cde Hrvoje Ribicic
-- | Builds the beparam fields for an object.
198 4e6f1cde Hrvoje Ribicic
buildBeParamField :: (String -> ConfigData -> a -> ResultEntry)
199 4e6f1cde Hrvoje Ribicic
                  -> String
200 4e6f1cde Hrvoje Ribicic
                  -> FieldData a b
201 4e6f1cde Hrvoje Ribicic
buildBeParamField =
202 4e6f1cde Hrvoje Ribicic
  buildParamField "be" "backend" C.besParameterTitles beParamTypes
203 4e6f1cde Hrvoje Ribicic
204 4e6f1cde Hrvoje Ribicic
-- | Hvparams optimised lookup map.
205 4e6f1cde Hrvoje Ribicic
hvParamTypes :: Map.Map String FieldType
206 4e6f1cde Hrvoje Ribicic
hvParamTypes = Map.map vTypeToQFT C.hvsParameterTypes
207 4e6f1cde Hrvoje Ribicic
208 4e6f1cde Hrvoje Ribicic
-- | Builds the beparam fields for an object.
209 4e6f1cde Hrvoje Ribicic
buildHvParamField :: (String -> ConfigData -> a -> ResultEntry)
210 4e6f1cde Hrvoje Ribicic
                  -> String
211 4e6f1cde Hrvoje Ribicic
                  -> FieldData a b
212 4e6f1cde Hrvoje Ribicic
buildHvParamField =
213 4e6f1cde Hrvoje Ribicic
  buildParamField "hv" "hypervisor" C.hvsParameterTitles hvParamTypes
214 4e6f1cde Hrvoje Ribicic
215 4e6f1cde Hrvoje Ribicic
-- | Builds a param field for a certain getter class
216 4e6f1cde Hrvoje Ribicic
buildParamField :: String -- ^ Prefix
217 4e6f1cde Hrvoje Ribicic
                -> String -- ^ Parameter group name
218 4e6f1cde Hrvoje Ribicic
                -> Map.Map String String -- ^ Parameter title map
219 4e6f1cde Hrvoje Ribicic
                -> Map.Map String FieldType -- ^ Parameter type map
220 4e6f1cde Hrvoje Ribicic
                -> (String -> ConfigData -> a -> ResultEntry)
221 4e6f1cde Hrvoje Ribicic
                -> String -- ^ The parameter name
222 4e6f1cde Hrvoje Ribicic
                -> FieldData a b
223 4e6f1cde Hrvoje Ribicic
buildParamField prefix paramGroupName titleMap typeMap getter field =
224 4e6f1cde Hrvoje Ribicic
  let full_name = prefix ++ "/" ++ field
225 4e6f1cde Hrvoje Ribicic
      title = fromMaybe full_name $ field `Map.lookup` titleMap
226 4e6f1cde Hrvoje Ribicic
      qft = fromMaybe QFTOther $ field `Map.lookup` typeMap
227 4e6f1cde Hrvoje Ribicic
      desc = "The \"" ++ field ++ "\" " ++ paramGroupName ++ " parameter"
228 4e6f1cde Hrvoje Ribicic
  in ( FieldDefinition full_name title qft desc
229 4e6f1cde Hrvoje Ribicic
     , FieldConfig (getter field), QffNormal
230 4e6f1cde Hrvoje Ribicic
     )
231 c2fe6008 Hrvoje Ribicic
232 c2fe6008 Hrvoje Ribicic
-- | Looks up the default hypervisor and its hvparams
233 c2fe6008 Hrvoje Ribicic
getDefaultHypervisorSpec :: ConfigData -> (Hypervisor, HvParams)
234 c2fe6008 Hrvoje Ribicic
getDefaultHypervisorSpec cfg = (hv, getHvParamsFromCluster cfg hv)
235 c2fe6008 Hrvoje Ribicic
  where hv = getDefaultHypervisor cfg
236 c2fe6008 Hrvoje Ribicic
237 c2fe6008 Hrvoje Ribicic
-- | Looks up the cluster's hvparams of the given hypervisor
238 c2fe6008 Hrvoje Ribicic
getHvParamsFromCluster :: ConfigData -> Hypervisor -> HvParams
239 c2fe6008 Hrvoje Ribicic
getHvParamsFromCluster cfg hv =
240 c2fe6008 Hrvoje Ribicic
  fromMaybe (GenericContainer Map.empty) .
241 c2fe6008 Hrvoje Ribicic
    Map.lookup (hypervisorToRaw hv) .
242 c2fe6008 Hrvoje Ribicic
      fromContainer . clusterHvparams $ configCluster cfg
243 3fd38382 Hrvoje Ribicic
244 3fd38382 Hrvoje Ribicic
-- | Given an alias list and a field list, copies field definitions under a
245 3fd38382 Hrvoje Ribicic
-- new field name. Aliases should be tested - see the test module
246 3fd38382 Hrvoje Ribicic
-- 'Test.Ganeti.Query.Aliases'!
247 3fd38382 Hrvoje Ribicic
aliasFields :: [(FieldName, FieldName)] -> FieldList a b -> FieldList a b
248 3fd38382 Hrvoje Ribicic
aliasFields aliases fieldList = fieldList ++ do
249 3fd38382 Hrvoje Ribicic
  alias <- aliases
250 3fd38382 Hrvoje Ribicic
  (FieldDefinition name d1 d2 d3, v1, v2) <- fieldList
251 3fd38382 Hrvoje Ribicic
  guard (snd alias == name)
252 3fd38382 Hrvoje Ribicic
  return (FieldDefinition (fst alias) d1 d2 d3, v1, v2)