Add Template Haskell 'declareLADT'
[ganeti-local] / src / Ganeti / Network.hs
1 {-| Implementation of the Ganeti network objects.
2
3 This is does not (yet) cover all methods that are provided in the
4 corresponding python implementation (network.py).
5
6 -}
7
8 {-
9
10 Copyright (C) 2011, 2012, 2013 Google Inc.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 02110-1301, USA.
26
27 -}
28
29 module Ganeti.Network
30   ( AddressPool(..)
31   , createAddressPool
32   , bitStringToBitVector
33   , allReservations
34   , getReservedCount
35   , getFreeCount
36   , isFull
37   , getMap
38   , networkIsValid
39   ) where
40
41 import qualified Data.Vector.Unboxed as V
42
43 import Ganeti.Objects
44
45 -- | An address pool, holding a network plus internal and external
46 -- reservations.
47 data AddressPool = AddressPool { network :: Network,
48                                  reservations :: V.Vector Bool,
49                                  extReservations :: V.Vector Bool }
50                                  deriving (Show)
51
52 -- | Create an address pool from a network.
53 createAddressPool :: Network -> Maybe AddressPool
54 createAddressPool n
55   | networkIsValid n =
56       let res = maybeStr2BitVec $ networkReservations n
57           ext_res = maybeStr2BitVec $ networkExtReservations n
58       in  Just AddressPool { reservations = res
59                            , extReservations = ext_res
60                            , network = n }
61   | otherwise = Nothing
62
63 -- | Checks the consistency of the network object. So far, only checks the
64 -- length of the reservation strings.
65 networkIsValid :: Network -> Bool
66 networkIsValid n =
67   sameLength (networkReservations n) (networkExtReservations n)
68
69 -- | Checks if two maybe strings are both nothing or of equal length.
70 sameLength :: Maybe String -> Maybe String -> Bool
71 sameLength Nothing Nothing = True
72 sameLength (Just s1) (Just s2) = length s1 == length s2
73 sameLength _ _ = False
74
75 -- | Converts a maybe bit string to a bit vector. Returns an empty bit vector on
76 -- nothing.
77 maybeStr2BitVec :: Maybe String -> V.Vector Bool
78 maybeStr2BitVec (Just s) = bitStringToBitVector s
79 maybeStr2BitVec Nothing = V.fromList ([]::[Bool])
80
81 -- | Converts a string to a bit vector. The character '0' is interpreted
82 -- as 'False', all others as 'True'.
83 bitStringToBitVector :: String -> V.Vector Bool
84 bitStringToBitVector = V.fromList . map (/= '0')
85
86 -- | Get a bit vector of all reservations (internal and external) combined.
87 allReservations :: AddressPool -> V.Vector Bool
88 allReservations a = V.zipWith (||) (reservations a) (extReservations a)
89
90 -- | Get the count of reserved addresses.
91 getReservedCount :: AddressPool -> Int
92 getReservedCount = V.length . V.filter (== True) . allReservations
93
94 -- | Get the count of free addresses.
95 getFreeCount :: AddressPool -> Int
96 getFreeCount = V.length . V.filter (== False) . allReservations
97
98 -- | Check whether the network is full.
99 isFull :: AddressPool -> Bool
100 isFull = V.and . allReservations
101
102 -- | Return a textual representation of the network's occupation status.
103 getMap :: AddressPool -> String
104 getMap = V.toList . V.map mapPixel . allReservations
105   where mapPixel c = if c then 'X' else '.'