module Ganeti.Ssconf
( SSKey(..)
, sSKeyToRaw
, sSKeyFromRaw
, getPrimaryIPFamily
, getMasterCandidatesIps
, getMasterNode
, keyToFilename
, sSFilePrefix
) where
import Control.Exception
import Control.Monad (liftM)
import Data.Maybe (fromMaybe)
import qualified Network.Socket as Socket
import System.FilePath ((</>))
import System.IO.Error (isDoesNotExistError)
import qualified AutoConf
import Ganeti.BasicTypes
import qualified Ganeti.Constants as C
import qualified Ganeti.Path as Path
import Ganeti.THH
import Ganeti.Utils
maxFileSize :: Int
maxFileSize = 131072
sSFilePrefix :: FilePath
sSFilePrefix = C.ssconfFileprefix
$(declareSADT "SSKey"
[ ("SSClusterName", 'C.ssClusterName)
, ("SSClusterTags", 'C.ssClusterTags)
, ("SSFileStorageDir", 'C.ssFileStorageDir)
, ("SSSharedFileStorageDir", 'C.ssSharedFileStorageDir)
, ("SSMasterCandidates", 'C.ssMasterCandidates)
, ("SSMasterCandidatesIps", 'C.ssMasterCandidatesIps)
, ("SSMasterIp", 'C.ssMasterIp)
, ("SSMasterNetdev", 'C.ssMasterNetdev)
, ("SSMasterNetmask", 'C.ssMasterNetmask)
, ("SSMasterNode", 'C.ssMasterNode)
, ("SSNodeList", 'C.ssNodeList)
, ("SSNodePrimaryIps", 'C.ssNodePrimaryIps)
, ("SSNodeSecondaryIps", 'C.ssNodeSecondaryIps)
, ("SSOfflineNodes", 'C.ssOfflineNodes)
, ("SSOnlineNodes", 'C.ssOnlineNodes)
, ("SSPrimaryIpFamily", 'C.ssPrimaryIpFamily)
, ("SSInstanceList", 'C.ssInstanceList)
, ("SSReleaseVersion", 'C.ssReleaseVersion)
, ("SSHypervisorList", 'C.ssHypervisorList)
, ("SSMaintainNodeHealth", 'C.ssMaintainNodeHealth)
, ("SSUidPool", 'C.ssUidPool)
, ("SSNodegroups", 'C.ssNodegroups)
])
keyToFilename :: FilePath
-> SSKey
-> FilePath
keyToFilename cfgpath key =
cfgpath </> sSFilePrefix ++ sSKeyToRaw key
catchIOErrors :: Maybe a
-> IO a
-> IO (Result a)
catchIOErrors def action =
Control.Exception.catch
(do
result <- action
return (Ok result)
) (\err -> let bad_result = Bad (show err)
in return $ if isDoesNotExistError err
then maybe bad_result Ok def
else bad_result)
readSSConfFile :: Maybe FilePath
-> Maybe String
-> SSKey
-> IO (Result String)
readSSConfFile optpath def key = do
dpath <- Path.dataDir
result <- catchIOErrors def . readFile .
keyToFilename (fromMaybe dpath optpath) $ key
return (liftM (take maxFileSize) result)
parseIPFamily :: Int -> Result Socket.Family
parseIPFamily fam | fam == AutoConf.pyAfInet4 = Ok Socket.AF_INET
| fam == AutoConf.pyAfInet6 = Ok Socket.AF_INET6
| otherwise = Bad $ "Unknown af_family value: " ++ show fam
getPrimaryIPFamily :: Maybe FilePath -> IO (Result Socket.Family)
getPrimaryIPFamily optpath = do
result <- readSSConfFile optpath
(Just (show AutoConf.pyAfInet4))
SSPrimaryIpFamily
return (liftM rStripSpace result >>=
tryRead "Parsing af_family" >>= parseIPFamily)
getMasterCandidatesIps :: Maybe FilePath -> IO (Result [String])
getMasterCandidatesIps optPath = do
result <- readSSConfFile optPath Nothing SSMasterCandidatesIps
return $ liftM lines result
getMasterNode :: Maybe FilePath -> IO (Result String)
getMasterNode optPath = do
result <- readSSConfFile optPath Nothing SSMasterNode
return (liftM rStripSpace result)