+{-| Computes the pair of bad nodes and instances.
+
+The bad node list is computed via a simple 'verifyN1' check, and the
+bad instance list is the list of primary and secondary instances of
+those nodes.
+
+-}
+computeBadItems :: Node.List -> Instance.List ->
+ ([Node.Node], [Instance.Instance])
+computeBadItems nl il =
+ let bad_nodes = verifyN1 $ getOnline nl
+ bad_instances = map (\idx -> Container.find idx il) $
+ sort $ nub $ concat $
+ map (\ n -> (Node.slist n) ++ (Node.plist n)) bad_nodes
+ in
+ (bad_nodes, bad_instances)
+
+-- | Compute the total free disk and memory in the cluster.
+totalResources :: Node.List -> (Int, Int)
+totalResources nl =
+ foldl'
+ (\ (mem, dsk) node -> (mem + (Node.f_mem node),
+ dsk + (Node.f_dsk node)))
+ (0, 0) (Container.elems nl)
+
+-- | Compute the mem and disk covariance.
+compDetailedCV :: Node.List -> (Double, Double, Double, Double, Double)
+compDetailedCV nl =
+ let
+ all_nodes = Container.elems nl
+ (offline, nodes) = partition Node.offline all_nodes
+ mem_l = map Node.p_mem nodes
+ dsk_l = map Node.p_dsk nodes
+ mem_cv = varianceCoeff mem_l
+ dsk_cv = varianceCoeff dsk_l
+ n1_l = length $ filter Node.failN1 nodes
+ n1_score = (fromIntegral n1_l) / (fromIntegral $ length nodes)
+ res_l = map Node.p_rem nodes
+ res_cv = varianceCoeff res_l
+ offline_inst = sum . map (\n -> (length . Node.plist $ n) +
+ (length . Node.slist $ n)) $ offline
+ online_inst = sum . map (\n -> (length . Node.plist $ n) +
+ (length . Node.slist $ n)) $ nodes
+ off_score = (fromIntegral offline_inst) /
+ (fromIntegral $ online_inst + offline_inst)
+ in (mem_cv, dsk_cv, n1_score, res_cv, off_score)
+
+-- | Compute the /total/ variance.
+compCV :: Node.List -> Double
+compCV nl =
+ let (mem_cv, dsk_cv, n1_score, res_cv, off_score) = compDetailedCV nl
+ in mem_cv + dsk_cv + n1_score + res_cv + off_score
+
+-- | Compute online nodes from a Node.List
+getOnline :: Node.List -> [Node.Node]
+getOnline = filter (not . Node.offline) . Container.elems
+
+-- * hn1 functions
+
+-- | Add an instance and return the new node and instance maps.
+addInstance :: Node.List -> Instance.Instance ->
+ Node.Node -> Node.Node -> Maybe Node.List