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

Reply via email to