balanceTask :: IORef MemoryState
            -> (Node.List, Instance.List) -- ^ current cluster configuration
            -> Set.Set Int -- ^ node indices on which actions may be taken
            -> Double -- ^ threshold for improvement
            -> ResultT String IO [JobId] -- ^ jobs submitted
balanceTask memstate (nl, il) okNodes threshold = do
  logDebug "Collecting dynamic load values"
  evacuated <- getEvacuated memstate
  logDebug $ "Not expecting load data from: " ++ show evacuated
  reports <- queryLoad nl
  xenInstances <- getXenInstances
  (nl', il') <- mkResultT . return
                  $ updateCPULoad (nl, il) reports xenInstances evacuated
  liftIO $ mapM_ (cleanUpEvacuation memstate il reports) evacuated
  let ngroups = ClusterUtils.splitCluster nl' il'
  luxiSocket <- liftIO Path.defaultQuerySocket
  bracket (liftIO $ L.getLuxiClient luxiSocket) (liftIO . L.closeClient) $ \c ->
    liftM concat $ mapM (balanceGroup memstate xenInstances c okNodes threshold)
                        ngroups
balanceTask :: IORef MemoryState
            -> (Node.List, Instance.List) -- ^ current cluster configuration
            -> Set.Set Int -- ^ node indices on which actions may be taken
            -> Double -- ^ threshold for improvement
            -> ResultT String IO [JobId]
balanceTask memstate (nl, il) okNodes threshold = do
  logDebug "Collecting dynamic load values"
  evacuated <- getEvacuated memstate
  logDebug $ "Not expecting load data from: " ++ show evacuated
  reports <- queryLoad nl
  xenInstances <- getXenInstances
  (nl', il') <- mkResultT . return
                  $ updateCPULoad (nl, il) reports xenInstances evacuated
  liftIO $ mapM_ (cleanUpEvacuation memstate il reports) evacuated
  let ngroups = ClusterUtils.splitCluster nl' il'
  luxiSocket <- liftIO Path.defaultQuerySocket
  bracket (liftIO $ L.getLuxiClient luxiSocket) (liftIO . L.closeClient) $ \c ->
    liftM concat $ mapM (balanceGroup memstate xenInstances c okNodes threshold)
                        ngroups
balanceTask memstate (nl, il) okNodes threshold = do
  logDebug "Collecting dynamic load values"
  evacuated <- getEvacuated memstate
  logDebug $ "Not expecting load data from: " ++ show evacuated
  reports <- queryLoad nl
  xenInstances <- getXenInstances
  (nl', il') <- mkResultT . return
                  $ updateCPULoad (nl, il) reports xenInstances evacuated
  liftIO $ mapM_ (cleanUpEvacuation memstate il reports) evacuated
  let ngroups = ClusterUtils.splitCluster nl' il'
  luxiSocket <- liftIO Path.defaultQuerySocket
  bracket (liftIO $ L.getLuxiClient luxiSocket) (liftIO . L.closeClient) $ \c ->
    liftM concat $ mapM (balanceGroup memstate xenInstances c okNodes threshold)
                        ngroups