Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / Query / Node.hs @ 7f0fd838

History | View | Annotate | Download (6.7 kB)

1
{-| Implementation of the Ganeti Query2 node queries.
2

    
3
 -}
4

    
5
{-
6

    
7
Copyright (C) 2012 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.Node
27
  ( NodeRuntime
28
  , nodeFieldsMap
29
  ) where
30

    
31
import Control.Applicative
32
import Data.List
33
import qualified Data.Map as Map
34

    
35
import Ganeti.Config
36
import Ganeti.Objects
37
import Ganeti.Rpc
38
import Ganeti.Query.Language
39
import Ganeti.Query.Common
40
import Ganeti.Query.Types
41

    
42
-- | NodeRuntime is the resulting type for NodeInfo call.
43
type NodeRuntime = Either RpcError RpcResultNodeInfo
44

    
45
-- | List of node live fields, all ignored for now (no RPC).
46
nodeLiveFieldsDefs :: [(FieldName, FieldTitle, FieldType, String, FieldDoc)]
47
nodeLiveFieldsDefs =
48
  [ ("bootid", "BootID", QFTText, "bootid",
49
     "Random UUID renewed for each system reboot, can be used\
50
     \ for detecting reboots by tracking changes")
51
  , ("cnodes", "CNodes", QFTNumber, "cpu_nodes",
52
     "Number of NUMA domains on node (if exported by hypervisor)")
53
  , ("csockets", "CSockets", QFTNumber, "cpu_sockets",
54
     "Number of physical CPU sockets (if exported by hypervisor)")
55
  , ("ctotal", "CTotal", QFTNumber, "cpu_total",
56
     "Number of logical processors")
57
  , ("dfree", "DFree", QFTUnit, "vg_free",
58
     "Available disk space in volume group")
59
  , ("dtotal", "DTotal", QFTUnit, "vg_size",
60
     "Total disk space in volume group used for instance disk allocation")
61
  , ("mfree", "MFree", QFTUnit, "memory_free",
62
     "Memory available for instance allocations")
63
  , ("mnode", "MNode", QFTUnit, "memory_dom0",
64
     "Amount of memory used by node (dom0 for Xen)")
65
  , ("mtotal", "MTotal", QFTUnit, "memory_total",
66
     "Total amount of memory of physical machine")
67
  ]
68

    
69
-- | Builder for node live fields.
70
nodeLiveFieldBuilder :: (FieldName, FieldTitle, FieldType, String, FieldDoc)
71
                     -> FieldData Node NodeRuntime
72
nodeLiveFieldBuilder (fname, ftitle, ftype, _, fdoc) =
73
  (FieldDefinition fname ftitle ftype fdoc, missingRuntime)
74

    
75
-- | The docstring for the node role. Note that we use 'reverse in
76
-- order to keep the same order as Python.
77
nodeRoleDoc :: String
78
nodeRoleDoc =
79
  "Node role; " ++
80
  intercalate ", "
81
   (map (\role ->
82
          "\"" ++ nodeRoleToRaw role ++ "\" for " ++ roleDescription role)
83
   (reverse [minBound..maxBound]))
84

    
85
-- | List of all node fields.
86
nodeFields :: FieldList Node NodeRuntime
87
nodeFields =
88
  [ (FieldDefinition "drained" "Drained" QFTBool "Whether node is drained",
89
     FieldSimple (rsNormal . nodeDrained))
90
  , (FieldDefinition "master_candidate" "MasterC" QFTBool
91
       "Whether node is a master candidate",
92
     FieldSimple (rsNormal . nodeMasterCandidate))
93
  , (FieldDefinition "master_capable" "MasterCapable" QFTBool
94
       "Whether node can become a master candidate",
95
     FieldSimple (rsNormal . nodeMasterCapable))
96
  , (FieldDefinition "name" "Node" QFTText "Node name",
97
     FieldSimple (rsNormal . nodeName))
98
  , (FieldDefinition "offline" "Offline" QFTBool
99
       "Whether node is marked offline",
100
     FieldSimple (rsNormal . nodeOffline))
101
  , (FieldDefinition "vm_capable" "VMCapable" QFTBool
102
       "Whether node can host instances",
103
     FieldSimple (rsNormal . nodeVmCapable))
104
  , (FieldDefinition "pip" "PrimaryIP" QFTText "Primary IP address",
105
     FieldSimple (rsNormal . nodePrimaryIp))
106
  , (FieldDefinition "sip" "SecondaryIP" QFTText "Secondary IP address",
107
     FieldSimple (rsNormal . nodeSecondaryIp))
108
  , (FieldDefinition "master" "IsMaster" QFTBool "Whether node is master",
109
     FieldConfig (\cfg node ->
110
                    rsNormal (nodeName node ==
111
                              clusterMasterNode (configCluster cfg))))
112
  , (FieldDefinition "group" "Group" QFTText "Node group",
113
     FieldConfig (\cfg node ->
114
                    rsMaybe (groupName <$> getGroupOfNode cfg node)))
115
  , (FieldDefinition "group.uuid" "GroupUUID" QFTText "UUID of node group",
116
     FieldSimple (rsNormal . nodeGroup))
117
  ,  (FieldDefinition "ndparams" "NodeParameters" QFTOther
118
        "Merged node parameters",
119
      FieldConfig ((rsMaybe .) . getNodeNdParams))
120
  , (FieldDefinition "custom_ndparams" "CustomNodeParameters" QFTOther
121
                       "Custom node parameters",
122
     FieldSimple (rsNormal . nodeNdparams))
123
  -- FIXME: the below could be generalised a bit, like in Python
124
  , (FieldDefinition "pinst_cnt" "Pinst" QFTNumber
125
       "Number of instances with this node as primary",
126
     FieldConfig (\cfg ->
127
                    rsNormal . length . fst . getNodeInstances cfg . nodeName))
128
  , (FieldDefinition "sinst_cnt" "Sinst" QFTNumber
129
       "Number of instances with this node as secondary",
130
     FieldConfig (\cfg ->
131
                    rsNormal . length . snd . getNodeInstances cfg . nodeName))
132
  , (FieldDefinition "pinst_list" "PriInstances" QFTOther
133
       "List of instances with this node as primary",
134
     FieldConfig (\cfg -> rsNormal . map instName . fst .
135
                          getNodeInstances cfg . nodeName))
136
  , (FieldDefinition "sinst_list" "SecInstances" QFTOther
137
       "List of instances with this node as secondary",
138
     FieldConfig (\cfg -> rsNormal . map instName . snd .
139
                          getNodeInstances cfg . nodeName))
140
  , (FieldDefinition "role" "Role" QFTText nodeRoleDoc,
141
     FieldConfig ((rsNormal .) . getNodeRole))
142
  -- FIXME: the powered state is special (has an different context,
143
  -- not runtime) in Python
144
  , (FieldDefinition "powered" "Powered" QFTBool
145
       "Whether node is thought to be powered on",
146
     missingRuntime)
147
  -- FIXME: the two fields below are incomplete in Python, part of the
148
  -- non-implemented node resource model; they are declared just for
149
  -- parity, but are not functional
150
  , (FieldDefinition "hv_state" "HypervisorState" QFTOther "Hypervisor state",
151
     missingRuntime)
152
  , (FieldDefinition "disk_state" "DiskState" QFTOther "Disk state",
153
     missingRuntime)
154
  ] ++
155
  map nodeLiveFieldBuilder nodeLiveFieldsDefs ++
156
  map buildNdParamField allNDParamFields ++
157
  timeStampFields ++
158
  uuidFields "Node" ++
159
  serialFields "Node" ++
160
  tagsFields
161

    
162
-- | The node fields map.
163
nodeFieldsMap :: FieldMap Node NodeRuntime
164
nodeFieldsMap = Map.fromList $ map (\v -> (fdefName (fst v), v)) nodeFields