allocateOnPair :: Node.List -> Instance.Instance -> Ndx -> Ndx
               -> OpResult Node.AllocElement
allocateOnPair nl inst new_pdx new_sdx =
  let tgt_p = Container.find new_pdx nl
      tgt_s = Container.find new_sdx nl
  in do
    Instance.instMatchesPolicy inst (Node.iPolicy tgt_p)
      (Node.exclStorage tgt_p)
    new_p <- Node.addPri tgt_p inst
    new_s <- Node.addSec tgt_s inst new_pdx
    let new_inst = Instance.setBoth inst new_pdx new_sdx
        new_nl = Container.addTwo new_pdx new_p new_sdx new_s nl
    return (new_nl, new_inst, [new_p, new_s], compCV new_nl)

-- | Tries to perform an instance move and returns the best table
-- between the original one and the new one.
allocateOnPair :: Node.List -> Instance.Instance -> Ndx -> Ndx
               -> OpResult Node.AllocElement
allocateOnPair nl inst new_pdx new_sdx =
  let tgt_p = Container.find new_pdx nl
      tgt_s = Container.find new_sdx nl
  in do
    Instance.instMatchesPolicy inst (Node.iPolicy tgt_p)
      (Node.exclStorage tgt_p)
    new_p <- Node.addPri tgt_p inst
    new_s <- Node.addSec tgt_s inst new_pdx
    let new_inst = Instance.setBoth inst new_pdx new_sdx
        new_nl = Container.addTwo new_pdx new_p new_sdx new_s nl
    return (new_nl, new_inst, [new_p, new_s], compCV new_nl)

-- | Tries to perform an instance move and returns the best table
-- between the original one and the new one.
allocateOnPair nl inst new_pdx new_sdx =
  let tgt_p = Container.find new_pdx nl
      tgt_s = Container.find new_sdx nl
  in do
    Instance.instMatchesPolicy inst (Node.iPolicy tgt_p)
      (Node.exclStorage tgt_p)
    new_p <- Node.addPri tgt_p inst
    new_s <- Node.addSec tgt_s inst new_pdx
    let new_inst = Instance.setBoth inst new_pdx new_sdx
        new_nl = Container.addTwo new_pdx new_p new_sdx new_s nl
    return (new_nl, new_inst, [new_p, new_s], compCV new_nl)

-- | Tries to perform an instance move and returns the best table
-- between the original one and the new one.