Add list of enabled hypervisors, cluster wide parameter for user shutdown, and a list of nodes and their respective vm capable attributes to Ssconf. This will be needed by the KVM daemon to determine whether it should start on a particular node.
Signed-off-by: Jose A. Lopes <[email protected]> --- lib/config.py | 5 +++++ lib/ssconf.py | 22 ++++++++++++++++++++++ src/Ganeti/Constants.hs | 6 ++++++ src/Ganeti/Ssconf.hs | 40 +++++++++++++++++++++++++++++++++++++++- src/Ganeti/Types.hs | 1 + 5 files changed, 73 insertions(+), 1 deletion(-) diff --git a/lib/config.py b/lib/config.py index dd38a22..6ea2083 100644 --- a/lib/config.py +++ b/lib/config.py @@ -2614,6 +2614,8 @@ class ConfigWriter(object): for ninfo in node_infos] node_snd_ips = ["%s %s" % (ninfo.name, ninfo.secondary_ip) for ninfo in node_infos] + node_vm_capable = ["%s=%s" % (ninfo.name, str(ninfo.vm_capable)) + for ninfo in node_infos] instance_data = fn(instance_names) off_data = fn(node.name for node in node_infos if node.offline) @@ -2624,6 +2626,7 @@ class ConfigWriter(object): node_data = fn(node_names) node_pri_ips_data = fn(node_pri_ips) node_snd_ips_data = fn(node_snd_ips) + node_vm_capable_data = fn(node_vm_capable) cluster = self._config_data.cluster cluster_tags = fn(cluster.GetTags()) @@ -2660,6 +2663,7 @@ class ConfigWriter(object): constants.SS_NODE_LIST: node_data, constants.SS_NODE_PRIMARY_IPS: node_pri_ips_data, constants.SS_NODE_SECONDARY_IPS: node_snd_ips_data, + constants.SS_NODE_VM_CAPABLE: node_vm_capable_data, constants.SS_OFFLINE_NODES: off_data, constants.SS_ONLINE_NODES: on_data, constants.SS_PRIMARY_IP_FAMILY: str(cluster.primary_ip_family), @@ -2670,6 +2674,7 @@ class ConfigWriter(object): constants.SS_UID_POOL: uid_pool, constants.SS_NODEGROUPS: nodegroups_data, constants.SS_NETWORKS: networks_data, + constants.SS_ENABLED_USER_SHUTDOWN: str(cluster.enabled_user_shutdown), } ssconf_values = self._ExtendByAllHvparamsStrings(ssconf_values, all_hvparams) diff --git a/lib/ssconf.py b/lib/ssconf.py index a2a660f..55f9df1 100644 --- a/lib/ssconf.py +++ b/lib/ssconf.py @@ -57,6 +57,7 @@ _VALID_KEYS = compat.UniqueFrozenset([ constants.SS_NODE_LIST, constants.SS_NODE_PRIMARY_IPS, constants.SS_NODE_SECONDARY_IPS, + constants.SS_NODE_VM_CAPABLE, constants.SS_OFFLINE_NODES, constants.SS_ONLINE_NODES, constants.SS_PRIMARY_IP_FAMILY, @@ -73,6 +74,7 @@ _VALID_KEYS = compat.UniqueFrozenset([ constants.SS_HVPARAMS_XEN_KVM, constants.SS_HVPARAMS_XEN_CHROOT, constants.SS_HVPARAMS_XEN_LXC, + constants.SS_ENABLED_USER_SHUTDOWN, ]) #: Maximum size for ssconf files @@ -321,6 +323,20 @@ class SimpleStore(object): nl = data.splitlines(False) return nl + def GetNodesVmCapable(self): + """Return the cluster nodes' vm capable value. + + @rtype: dict of string to bool + @return: mapping of node names to vm capable values + + """ + data = self._ReadFile(constants.SS_NODE_VM_CAPABLE) + vm_capable = {} + for line in data.splitlines(False): + (node_uuid, node_vm_capable) = line.split("=") + vm_capable[node_uuid] = node_vm_capable + return vm_capable + def GetNodegroupList(self): """Return the list of nodegroups. @@ -415,6 +431,12 @@ class SimpleStore(object): raise errors.ConfigurationError("Error while trying to parse primary IP" " family: %s" % err) + def GetEnabledUserShutdown(self): + """Return whether user shutdown is enabled. + + """ + return self._ReadFile(constants.SS_ENABLED_USER_SHUTDOWN) == "True" + def WriteSsconfFiles(values, dry_run=False): """Update all ssconf files. diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs index c13d6d6..c87510b 100644 --- a/src/Ganeti/Constants.hs +++ b/src/Ganeti/Constants.hs @@ -3570,6 +3570,9 @@ ssNodePrimaryIps = "node_primary_ips" ssNodeSecondaryIps :: String ssNodeSecondaryIps = "node_secondary_ips" +ssNodeVmCapable :: String +ssNodeVmCapable = "node_vm_capable" + ssOfflineNodes :: String ssOfflineNodes = "offline_nodes" @@ -3637,6 +3640,9 @@ validSsHvparamsKeys = ssFilePerms :: Int ssFilePerms = 0o444 +ssEnabledUserShutdown :: String +ssEnabledUserShutdown = "enabled_user_shutdown" + -- | Cluster wide default parameters defaultEnabledHypervisor :: String defaultEnabledHypervisor = htXenPvm diff --git a/src/Ganeti/Ssconf.hs b/src/Ganeti/Ssconf.hs index 3f7a64b..3704c36 100644 --- a/src/Ganeti/Ssconf.hs +++ b/src/Ganeti/Ssconf.hs @@ -30,8 +30,11 @@ module Ganeti.Ssconf , sSKeyToRaw , sSKeyFromRaw , getPrimaryIPFamily + , getNodesVmCapable , getMasterCandidatesIps , getMasterNode + , getHypervisorList + , getEnabledUserShutdown , keyToFilename , sSFilePrefix ) where @@ -48,6 +51,8 @@ import Ganeti.BasicTypes import qualified Ganeti.Constants as C import qualified Ganeti.Path as Path import Ganeti.THH +import Ganeti.Types (Hypervisor) +import qualified Ganeti.Types as Types import Ganeti.Utils -- | Maximum ssconf file size we support. @@ -73,6 +78,7 @@ $(declareSADT "SSKey" , ("SSNodeList", 'C.ssNodeList) , ("SSNodePrimaryIps", 'C.ssNodePrimaryIps) , ("SSNodeSecondaryIps", 'C.ssNodeSecondaryIps) + , ("SSNodeVmCapable", 'C.ssNodeVmCapable) , ("SSOfflineNodes", 'C.ssOfflineNodes) , ("SSOnlineNodes", 'C.ssOnlineNodes) , ("SSPrimaryIpFamily", 'C.ssPrimaryIpFamily) @@ -82,6 +88,7 @@ $(declareSADT "SSKey" , ("SSMaintainNodeHealth", 'C.ssMaintainNodeHealth) , ("SSUidPool", 'C.ssUidPool) , ("SSNodegroups", 'C.ssNodegroups) + , ("SSEnabledUserShutdown", 'C.ssEnabledUserShutdown) ]) -- | Convert a ssconf key into a (full) file path. @@ -118,6 +125,14 @@ readSSConfFile optpath def key = do keyToFilename (fromMaybe dpath optpath) $ key return (liftM (take maxFileSize) result) +-- | Parses a key-value pair of the form "key=value" from 'str', fails +-- with 'desc' otherwise. +parseKeyValue :: Monad m => String -> String -> m (String, String) +parseKeyValue desc str = + case sepSplit '=' str of + [key, value] -> return (key, value) + _ -> fail $ "Failed to parse key-value pair for " ++ desc + -- | Parses a string containing an IP family parseIPFamily :: Int -> Result Socket.Family parseIPFamily fam | fam == AutoConf.pyAfInet4 = Ok Socket.AF_INET @@ -133,6 +148,17 @@ getPrimaryIPFamily optpath = do return (liftM rStripSpace result >>= tryRead "Parsing af_family" >>= parseIPFamily) +-- | Read the nodes vm capable value. +getNodesVmCapable :: Maybe FilePath -> IO (Result [(String, Bool)]) +getNodesVmCapable optPath = do + result <- readSSConfFile optPath Nothing SSNodeVmCapable + return $ + liftM lines result >>= + mapM (parseKeyValue "Parsing node_vm_capable") >>= + mapM (\(x, y) -> + do val <- tryRead "Parsing value of node_vm_capable" y + return (x, val)) + -- | Read the list of IP addresses of the master candidates of the cluster. getMasterCandidatesIps :: Maybe FilePath -> IO (Result [String]) getMasterCandidatesIps optPath = do @@ -143,4 +169,16 @@ getMasterCandidatesIps optPath = do getMasterNode :: Maybe FilePath -> IO (Result String) getMasterNode optPath = do result <- readSSConfFile optPath Nothing SSMasterNode - return (liftM rStripSpace result) + return $ liftM rStripSpace result + +-- | Read the list of enabled hypervisors +getHypervisorList :: Maybe FilePath -> IO (Result [Hypervisor]) +getHypervisorList optPath = do + result <- readSSConfFile optPath Nothing SSHypervisorList + return $ mapM Types.hypervisorFromRaw =<< liftM lines result + +-- | Read whether user shutdown is enabled +getEnabledUserShutdown :: Maybe FilePath -> IO (Result Bool) +getEnabledUserShutdown optPath = do + result <- readSSConfFile optPath Nothing SSEnabledUserShutdown + return $ tryRead "Parsing enabled_user_shutdown" =<< liftM rStripSpace result diff --git a/src/Ganeti/Types.hs b/src/Ganeti/Types.hs index 38d71b3..e61b983 100644 --- a/src/Ganeti/Types.hs +++ b/src/Ganeti/Types.hs @@ -75,6 +75,7 @@ module Ganeti.Types , CVErrorCode(..) , cVErrorCodeToRaw , Hypervisor(..) + , hypervisorFromRaw , hypervisorToRaw , OobCommand(..) , oobCommandToRaw -- 2.0.0.526.g5318336
