Store keys as ByteStrings
[ganeti-github.git] / src / Ganeti / Query / Network.hs
1 {-| Implementation of the Ganeti Query2 node group queries.
2
3 -}
4
5 {-
6
7 Copyright (C) 2012, 2013 Google Inc.
8 All rights reserved.
9
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are
12 met:
13
14 1. Redistributions of source code must retain the above copyright notice,
15 this list of conditions and the following disclaimer.
16
17 2. Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
25 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 -}
34
35 module Ganeti.Query.Network
36 ( getGroupConnection
37 , getNetworkUuid
38 , instIsConnected
39 , fieldsMap
40 ) where
41
42 -- FIXME: everything except fieldsMap
43 -- is only exported for testing.
44
45 import qualified Data.ByteString.UTF8 as UTF8
46 import qualified Data.Map as Map
47 import Data.Maybe (fromMaybe, mapMaybe)
48 import Data.List (find, intercalate)
49
50 import Ganeti.JSON
51 import Ganeti.Network
52 import Ganeti.Objects
53 import qualified Ganeti.Objects.BitArray as BA
54 import Ganeti.Query.Language
55 import Ganeti.Query.Common
56 import Ganeti.Query.Types
57 import Ganeti.Types
58
59 networkFields :: FieldList Network NoDataRuntime
60 networkFields =
61 [ (FieldDefinition "name" "Network" QFTText "Name",
62 FieldSimple (rsNormal . networkName), QffNormal)
63 , (FieldDefinition "network" "Subnet" QFTText "IPv4 subnet",
64 FieldSimple (rsNormal . networkNetwork), QffNormal)
65 , (FieldDefinition "gateway" "Gateway" QFTOther "IPv4 gateway",
66 FieldSimple (rsMaybeUnavail . networkGateway), QffNormal)
67 , (FieldDefinition "network6" "IPv6Subnet" QFTOther "IPv6 subnet",
68 FieldSimple (rsMaybeUnavail . networkNetwork6), QffNormal)
69 , (FieldDefinition "gateway6" "IPv6Gateway" QFTOther "IPv6 gateway",
70 FieldSimple (rsMaybeUnavail . networkGateway6), QffNormal)
71 , (FieldDefinition "mac_prefix" "MacPrefix" QFTOther "MAC address prefix",
72 FieldSimple (rsMaybeUnavail . networkMacPrefix), QffNormal)
73 , (FieldDefinition "free_count" "FreeCount" QFTNumber "Number of available\
74 \ addresses",
75 FieldSimple (rsNormal . getFreeCount),
76 QffNormal)
77 , (FieldDefinition "map" "Map" QFTText "Actual mapping",
78 FieldSimple (rsNormal . getMap),
79 QffNormal)
80 , (FieldDefinition "reserved_count" "ReservedCount" QFTNumber
81 "Number of reserved addresses",
82 FieldSimple (rsNormal . getReservedCount),
83 QffNormal)
84 , (FieldDefinition "group_list" "GroupList" QFTOther
85 "List of nodegroups (group name, NIC mode, NIC link)",
86 FieldConfig (\cfg -> rsNormal . getGroupConnections cfg . uuidOf),
87 QffNormal)
88 , (FieldDefinition "group_cnt" "NodeGroups" QFTNumber "Number of nodegroups",
89 FieldConfig (\cfg -> rsNormal . length . getGroupConnections cfg
90 . uuidOf), QffNormal)
91 , (FieldDefinition "inst_list" "InstanceList" QFTOther "List of instances",
92 FieldConfig (\cfg -> rsNormal . getInstances cfg . uuidOf),
93 QffNormal)
94 , (FieldDefinition "inst_cnt" "Instances" QFTNumber "Number of instances",
95 FieldConfig (\cfg -> rsNormal . length . getInstances cfg
96 . uuidOf), QffNormal)
97 , (FieldDefinition "external_reservations" "ExternalReservations" QFTText
98 "External reservations",
99 FieldSimple getExtReservationsString, QffNormal)
100 ] ++
101 timeStampFields ++
102 uuidFields "Network" ++
103 serialFields "Network" ++
104 tagsFields
105
106 -- | The group fields map.
107 fieldsMap :: FieldMap Network NoDataRuntime
108 fieldsMap = fieldListToFieldMap networkFields
109
110 -- TODO: the following fields are not implemented yet: external_reservations
111
112 -- | Given a network's UUID, this function lists all connections from
113 -- the network to nodegroups including the respective mode and links.
114 getGroupConnections ::
115 ConfigData -> String -> [(String, String, String, String)]
116 getGroupConnections cfg network_uuid =
117 mapMaybe (getGroupConnection network_uuid)
118 ((Map.elems . fromContainer . configNodegroups) cfg)
119
120 -- | Given a network's UUID and a node group, this function assembles
121 -- a tuple of the group's name, the mode and the link by which the
122 -- network is connected to the group. Returns 'Nothing' if the network
123 -- is not connected to the group.
124 getGroupConnection ::
125 String -> NodeGroup -> Maybe (String, String, String, String)
126 getGroupConnection network_uuid group =
127 let networks = fromContainer . groupNetworks $ group
128 in case Map.lookup (UTF8.fromString network_uuid) networks of
129 Nothing -> Nothing
130 Just net ->
131 Just (groupName group, getNicMode net, getNicLink net, getNicVlan net)
132
133 -- | Retrieves the network's mode and formats it human-readable,
134 -- also in case it is not available.
135 getNicMode :: PartialNicParams -> String
136 getNicMode nic_params =
137 maybe "-" nICModeToRaw $ nicpModeP nic_params
138
139 -- | Retrieves the network's vlan and formats it human-readable, also in
140 -- case it it not available.
141 getNicLink :: PartialNicParams -> String
142 getNicLink nic_params = fromMaybe "-" (nicpLinkP nic_params)
143
144 -- | Retrieves the network's link and formats it human-readable, also in
145 -- case it it not available.
146 getNicVlan :: PartialNicParams -> String
147 getNicVlan nic_params = fromMaybe "-" (nicpVlanP nic_params)
148
149 -- | Retrieves the network's instances' names.
150 getInstances :: ConfigData -> String -> [String]
151 getInstances cfg network_uuid =
152 mapMaybe instName (filter (instIsConnected network_uuid)
153 ((Map.elems . fromContainer . configInstances) cfg))
154
155 -- | Helper function that checks if an instance is linked to the given network.
156 instIsConnected :: String -> Instance -> Bool
157 instIsConnected network_uuid inst =
158 network_uuid `elem` mapMaybe nicNetwork (instNics inst)
159
160 -- | Helper function to look up a network's UUID by its name
161 getNetworkUuid :: ConfigData -> String -> Maybe String
162 getNetworkUuid cfg name =
163 let net = find (\n -> name == fromNonEmpty (networkName n))
164 ((Map.elems . fromContainer . configNetworks) cfg)
165 in fmap uuidOf net
166
167 -- | Computes the reservations list for a network.
168 --
169 -- This doesn't use the netmask for validation of the length, instead
170 -- simply iterating over the reservations.
171 getReservations :: Ip4Network -> Maybe AddressPool -> [Ip4Address]
172 getReservations _ Nothing = []
173 getReservations net (Just pool) =
174 map snd . filter fst
175 $ zip (BA.toList . apReservations $ pool)
176 (iterate nextIp4Address $ ip4BaseAddr net)
177
178 -- | Computes the external reservations as string for a network.
179 getExtReservationsString :: Network -> ResultEntry
180 getExtReservationsString net =
181 let addrs = getReservations (networkNetwork net)
182 (networkExtReservations net)
183 in rsNormal . intercalate ", " $ map show addrs