Statistics
| Branch: | Tag: | Revision:

root / src / Ganeti / Query / Common.hs @ 8e6ef316

History | View | Annotate | Download (6.1 kB)

1
{-| Implementation of the Ganeti Query2 common objects.
2

    
3
 -}
4

    
5
{-
6

    
7
Copyright (C) 2012, 2013 Google Inc.
8

    
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.
13

    
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.
18

    
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
22
02110-1301, USA.
23

    
24
-}
25

    
26
module Ganeti.Query.Common
27
  ( rsNoData
28
  , rsUnavail
29
  , rsNormal
30
  , rsMaybeNoData
31
  , rsMaybeUnavail
32
  , rsUnknown
33
  , missingRuntime
34
  , rpcErrorToStatus
35
  , timeStampFields
36
  , uuidFields
37
  , serialFields
38
  , tagsFields
39
  , dictFieldGetter
40
  , buildQFTLookup
41
  , buildNdParamField
42
  ) where
43

    
44
import qualified Data.Map as Map
45
import Data.Maybe (fromMaybe)
46
import Text.JSON (JSON, showJSON)
47

    
48
import qualified Ganeti.Constants as C
49
import Ganeti.Config
50
import Ganeti.Objects
51
import Ganeti.Rpc
52
import Ganeti.Query.Language
53
import Ganeti.Query.Types
54
import Ganeti.Types
55

    
56
-- * Generic functions
57

    
58
-- | Conversion from 'VType' to 'FieldType'.
59
vTypeToQFT :: VType -> FieldType
60
vTypeToQFT VTypeString      = QFTOther
61
vTypeToQFT VTypeMaybeString = QFTOther
62
vTypeToQFT VTypeBool        = QFTBool
63
vTypeToQFT VTypeSize        = QFTUnit
64
vTypeToQFT VTypeInt         = QFTNumber
65

    
66
-- * Result helpers
67

    
68
-- | Helper for a result with no data.
69
rsNoData :: ResultEntry
70
rsNoData = ResultEntry RSNoData Nothing
71

    
72
-- | Helper for result for an entity which supports no such field.
73
rsUnavail :: ResultEntry
74
rsUnavail = ResultEntry RSUnavail Nothing
75

    
76
-- | Helper to declare a normal result.
77
rsNormal :: (JSON a) => a -> ResultEntry
78
rsNormal a = ResultEntry RSNormal $ Just (showJSON a)
79

    
80
-- | Helper to declare a result from a 'Maybe' (the item might be
81
-- missing, in which case we return no data). Note that there's some
82
-- ambiguity here: in some cases, we mean 'RSNoData', but in other
83
-- 'RSUnavail'; this is easy to solve in simple cases, but not in
84
-- nested dicts. If you want to return 'RSUnavail' in case of 'Nothing'
85
-- use the function 'rsMaybeUnavail'.
86
rsMaybeNoData :: (JSON a) => Maybe a -> ResultEntry
87
rsMaybeNoData = maybe rsNoData rsNormal
88

    
89
-- | Helper to declare a result from a 'Maybe'. This version returns
90
-- a 'RSUnavail' in case of 'Nothing'. It should be used for optional
91
-- fields that are not set. For cases where 'Nothing' means that there
92
-- was an error, consider using 'rsMaybe' instead.
93
rsMaybeUnavail :: (JSON a) => Maybe a -> ResultEntry
94
rsMaybeUnavail = maybe rsUnavail rsNormal
95

    
96
-- | Helper for unknown field result.
97
rsUnknown :: ResultEntry
98
rsUnknown = ResultEntry RSUnknown Nothing
99

    
100
-- | Helper for a missing runtime parameter.
101
missingRuntime :: FieldGetter a b
102
missingRuntime = FieldRuntime (\_ _ -> ResultEntry RSNoData Nothing)
103

    
104
-- * Error conversion
105

    
106
-- | Convert RpcError to ResultStatus
107
rpcErrorToStatus :: RpcError -> ResultStatus
108
rpcErrorToStatus OfflineNodeError = RSOffline
109
rpcErrorToStatus _ = RSNoData
110

    
111
-- * Common fields
112

    
113
-- | The list of timestamp fields.
114
timeStampFields :: (TimeStampObject a) => FieldList a b
115
timeStampFields =
116
  [ (FieldDefinition "ctime" "CTime" QFTTimestamp "Creation timestamp",
117
     FieldSimple (rsNormal . cTimeOf), QffNormal)
118
  , (FieldDefinition "mtime" "MTime" QFTTimestamp "Modification timestamp",
119
     FieldSimple (rsNormal . mTimeOf), QffNormal)
120
  ]
121

    
122
-- | The list of UUID fields.
123
uuidFields :: (UuidObject a) => String -> FieldList a b
124
uuidFields name =
125
  [ (FieldDefinition "uuid" "UUID" QFTText  (name ++ " UUID"),
126
     FieldSimple (rsNormal . uuidOf), QffNormal) ]
127

    
128
-- | The list of serial number fields.
129
serialFields :: (SerialNoObject a) => String -> FieldList a b
130
serialFields name =
131
  [ (FieldDefinition "serial_no" "SerialNo" QFTNumber
132
     (name ++ " object serial number, incremented on each modification"),
133
     FieldSimple (rsNormal . serialOf), QffNormal) ]
134

    
135
-- | The list of tag fields.
136
tagsFields :: (TagsObject a) => FieldList a b
137
tagsFields =
138
  [ (FieldDefinition "tags" "Tags" QFTOther "Tags",
139
     FieldSimple (rsNormal . tagsOf), QffNormal) ]
140

    
141
-- * Generic parameter functions
142

    
143
-- | Returns a field from a (possibly missing) 'DictObject'. This is
144
-- used by parameter dictionaries, usually. Note that we have two
145
-- levels of maybe: the top level dict might be missing, or one key in
146
-- the dictionary might be.
147
dictFieldGetter :: (DictObject a) => String -> Maybe a -> ResultEntry
148
dictFieldGetter k = maybe rsNoData (rsMaybeNoData . lookup k . toDict)
149

    
150
-- | Build an optimised lookup map from a Python _PARAMETER_TYPES
151
-- association list.
152
buildQFTLookup :: [(String, String)] -> Map.Map String FieldType
153
buildQFTLookup =
154
  Map.fromList .
155
  map (\(k, v) -> (k, maybe QFTOther vTypeToQFT (vTypeFromRaw v)))
156

    
157
-- | Ndparams optimised lookup map.
158
ndParamTypes :: Map.Map String FieldType
159
ndParamTypes = buildQFTLookup C.ndsParameterTypes
160

    
161
-- | Ndparams title map.
162
ndParamTitles :: Map.Map String FieldTitle
163
ndParamTitles = Map.fromList C.ndsParameterTitles
164

    
165
-- | Ndparam getter builder: given a field, it returns a FieldConfig
166
-- getter, that is a function that takes the config and the object and
167
-- returns the Ndparam field specified when the getter was built.
168
ndParamGetter :: (NdParamObject a) =>
169
                 String -- ^ The field we're building the getter for
170
              -> ConfigData -> a -> ResultEntry
171
ndParamGetter field config =
172
  dictFieldGetter field . getNdParamsOf config
173

    
174
-- | Builds the ndparam fields for an object.
175
buildNdParamField :: (NdParamObject a) => String -> FieldData a b
176
buildNdParamField field =
177
  let full_name = "ndp/" ++ field
178
      title = fromMaybe field $ field `Map.lookup` ndParamTitles
179
      qft = fromMaybe QFTOther $ field `Map.lookup` ndParamTypes
180
      desc = "The \"" ++ field ++ "\" node parameter"
181
  in (FieldDefinition full_name title qft desc,
182
      FieldConfig (ndParamGetter field), QffNormal)