htools: change behaviour for offline instances
[ganeti-local] / htools / Ganeti / HTools / Instance.hs
index dc070e4..22d3c96 100644 (file)
@@ -31,6 +31,10 @@ module Ganeti.HTools.Instance
     , AssocList
     , List
     , create
+    , instanceRunning
+    , instanceOffline
+    , instanceDown
+    , applyIfOnline
     , setIdx
     , setName
     , setAlias
@@ -40,13 +44,19 @@ module Ganeti.HTools.Instance
     , setMovable
     , specOf
     , shrinkByType
-    , runningStates
+    , localStorageTemplates
+    , hasSecondary
+    , requiredNodes
+    , allNodes
+    , usesLocalStorage
     ) where
 
 import qualified Ganeti.HTools.Types as T
 import qualified Ganeti.HTools.Container as Container
 import qualified Ganeti.Constants as C
 
+import Ganeti.HTools.Utils
+
 -- * Type declarations
 
 -- | The instance type.
@@ -56,13 +66,12 @@ data Instance = Instance
     , mem          :: Int       -- ^ Memory of the instance
     , dsk          :: Int       -- ^ Disk size of instance
     , vcpus        :: Int       -- ^ Number of VCPUs
-    , running      :: Bool      -- ^ Is the instance running?
-    , runSt        :: String    -- ^ Original (text) run status
+    , runSt        :: T.InstanceStatus -- ^ Original run status
     , pNode        :: T.Ndx     -- ^ Original primary node
     , sNode        :: T.Ndx     -- ^ Original secondary node
     , idx          :: T.Idx     -- ^ Internal index
     , util         :: T.DynUtil -- ^ Dynamic resource usage
-    , movable      :: Bool      -- ^ Can the instance be moved?
+    , movable      :: Bool      -- ^ Can and should the instance be moved?
     , autoBalance  :: Bool      -- ^ Is the instance auto-balanced?
     , tags         :: [String]  -- ^ List of instance tags
     , diskTemplate :: T.DiskTemplate -- ^ The disk template of the instance
@@ -75,9 +84,46 @@ instance T.Element Instance where
     setIdx   = setIdx
     allNames n = [name n, alias n]
 
--- | Constant holding the running instance states.
-runningStates :: [String]
-runningStates = [C.inststRunning, C.inststErrorup]
+-- | Check if instance is running.
+instanceRunning :: Instance -> Bool
+instanceRunning (Instance {runSt = T.Running}) = True
+instanceRunning (Instance {runSt = T.ErrorUp}) = True
+instanceRunning _                               = False
+
+-- | Check if instance is offline.
+instanceOffline :: Instance -> Bool
+instanceOffline (Instance {runSt = T.AdminOffline}) = True
+instanceOffline _                                    = False
+
+-- | Check if instance is down.
+instanceDown :: Instance -> Bool
+instanceDown inst | instanceRunning inst = False
+instanceDown inst | instanceOffline inst = False
+instanceDown _                           = True
+
+-- | Apply the function if the instance is online. Otherwise use
+-- the initial value
+applyIfOnline :: Instance -> (a -> a) -> a -> a
+applyIfOnline = applyIf . not . instanceOffline
+
+-- | Constant holding the local storage templates.
+--
+-- /Note:/ Currently Ganeti only exports node total/free disk space
+-- for LVM-based storage; file-based storage is ignored in this model,
+-- so even though file-based storage uses in reality disk space on the
+-- node, in our model it won't affect it and we can't compute whether
+-- there is enough disk space for a file-based instance. Therefore we
+-- will treat this template as \'foreign\' storage.
+localStorageTemplates :: [T.DiskTemplate]
+localStorageTemplates = [ T.DTDrbd8, T.DTPlain ]
+
+-- | Constant holding the movable disk templates.
+--
+-- This only determines the initial 'movable' state of the
+-- instance. Further the movable state can be restricted more due to
+-- user choices, etc.
+movableDiskTemplates :: [T.DiskTemplate]
+movableDiskTemplates = [ T.DTDrbd8, T.DTBlock, T.DTSharedFile ]
 
 -- | A simple name for the int, instance association list.
 type AssocList = [(T.Idx, Instance)]
@@ -91,7 +137,7 @@ type List = Container.Container Instance
 --
 -- Some parameters are not initialized by function, and must be set
 -- later (via 'setIdx' for example).
-create :: String -> Int -> Int -> Int -> String
+create :: String -> Int -> Int -> Int -> T.InstanceStatus
        -> [String] -> Bool -> T.Ndx -> T.Ndx -> T.DiskTemplate -> Instance
 create name_init mem_init dsk_init vcpus_init run_init tags_init
        auto_balance_init pn sn dt =
@@ -100,14 +146,13 @@ create name_init mem_init dsk_init vcpus_init run_init tags_init
              , mem = mem_init
              , dsk = dsk_init
              , vcpus = vcpus_init
-             , running = run_init `elem` runningStates
              , runSt = run_init
              , pNode = pn
              , sNode = sn
              , idx = -1
              , util = T.baseUtil
              , tags = tags_init
-             , movable = True
+             , movable = supportsMoves dt
              , autoBalance = auto_balance_init
              , diskTemplate = dt
              }
@@ -157,6 +202,7 @@ setBoth :: Instance  -- ^ the original instance
          -> Instance -- ^ the modified instance
 setBoth t p s = t { pNode = p, sNode = s }
 
+-- | Sets the movable flag on an instance.
 setMovable :: Instance -- ^ The original instance
            -> Bool     -- ^ New movable flag
            -> Instance -- ^ The modified instance
@@ -183,3 +229,29 @@ shrinkByType _ f = T.Bad $ "Unhandled failure mode " ++ show f
 specOf :: Instance -> T.RSpec
 specOf Instance { mem = m, dsk = d, vcpus = c } =
     T.RSpec { T.rspecCpu = c, T.rspecMem = m, T.rspecDsk = d }
+
+-- | Checks whether the instance uses a secondary node.
+--
+-- /Note:/ This should be reconciled with @'sNode' ==
+-- 'Node.noSecondary'@.
+hasSecondary :: Instance -> Bool
+hasSecondary = (== T.DTDrbd8) . diskTemplate
+
+-- | Computed the number of nodes for a given disk template.
+requiredNodes :: T.DiskTemplate -> Int
+requiredNodes T.DTDrbd8 = 2
+requiredNodes _         = 1
+
+-- | Computes all nodes of an instance.
+allNodes :: Instance -> [T.Ndx]
+allNodes inst = case diskTemplate inst of
+                  T.DTDrbd8 -> [pNode inst, sNode inst]
+                  _ -> [pNode inst]
+
+-- | Checks whether a given disk template uses local storage.
+usesLocalStorage :: Instance -> Bool
+usesLocalStorage = (`elem` localStorageTemplates) . diskTemplate
+
+-- | Checks whether a given disk template supported moves.
+supportsMoves :: T.DiskTemplate -> Bool
+supportsMoves = (`elem` movableDiskTemplates)