diff --git a/lib/masterd/iallocator.py b/lib/masterd/iallocator.py
index 2db8ac4b8fa6c60ab9ca0469441d8c3eb80c5441..45b0ba1b538806741f5218cf3fce4802a164a1e6 100644
--- a/lib/masterd/iallocator.py
+++ b/lib/masterd/iallocator.py
@@ -153,6 +153,7 @@ class IAReqInstanceAlloc(IARequestBase):
     ("nics", ht.TListOf(ht.TDict)),
     ("vcpus", ht.TInt),
     ("hypervisor", ht.TString),
+    ("node_whitelist", ht.TMaybeListOf(ht.TNonEmptyString)),
     ]
   REQ_RESULT = ht.TList
 
@@ -421,10 +422,13 @@ class IAllocator(object):
 
     if isinstance(self.req, IAReqInstanceAlloc):
       hypervisor_name = self.req.hypervisor
+      node_whitelist = self.req.node_whitelist
     elif isinstance(self.req, IAReqRelocate):
       hypervisor_name = cfg.GetInstanceInfo(self.req.name).hypervisor
+      node_whitelist = None
     else:
       hypervisor_name = cluster_info.primary_hypervisor
+      node_whitelist = None
 
     node_data = self.rpc.call_node_info(node_list, [cfg.GetVGName()],
                                         [hypervisor_name])
@@ -434,7 +438,7 @@ class IAllocator(object):
 
     data["nodegroups"] = self._ComputeNodeGroupData(cfg)
 
-    config_ndata = self._ComputeBasicNodeData(cfg, ninfo)
+    config_ndata = self._ComputeBasicNodeData(cfg, ninfo, node_whitelist)
     data["nodes"] = self._ComputeDynamicNodeData(ninfo, node_data, node_iinfo,
                                                  i_list, config_ndata)
     assert len(data["nodes"]) == len(ninfo), \
@@ -461,7 +465,7 @@ class IAllocator(object):
     return ng
 
   @staticmethod
-  def _ComputeBasicNodeData(cfg, node_cfg):
+  def _ComputeBasicNodeData(cfg, node_cfg, node_whitelist):
     """Compute global node data.
 
     @rtype: dict
@@ -473,7 +477,9 @@ class IAllocator(object):
       "tags": list(ninfo.GetTags()),
       "primary_ip": ninfo.primary_ip,
       "secondary_ip": ninfo.secondary_ip,
-      "offline": ninfo.offline,
+      "offline": (ninfo.offline or
+                  not (node_whitelist is None or
+                       ninfo.name in node_whitelist)),
       "drained": ninfo.drained,
       "master_candidate": ninfo.master_candidate,
       "group": ninfo.group,
diff --git a/test/ganeti.masterd.iallocator_unittest.py b/test/ganeti.masterd.iallocator_unittest.py
index 8aa2bd05bf6d2108ec35203f446a096addee1edb..85b88a9af16d67b1a3d2f14c1ebbf09f0042e8b0 100755
--- a/test/ganeti.masterd.iallocator_unittest.py
+++ b/test/ganeti.masterd.iallocator_unittest.py
@@ -26,6 +26,7 @@ import unittest
 from ganeti import compat
 from ganeti import constants
 from ganeti import errors
+from ganeti import objects
 from ganeti import ht
 from ganeti.masterd import iallocator
 
@@ -88,5 +89,94 @@ class TestIARequestBase(unittest.TestCase):
     stub.ValidateResult(_StubIAllocator(False), "foo")
 
 
+class _FakeConfigWithNdParams:
+  def GetNdParams(self, _):
+    return None
+
+
+class TestComputeBasicNodeData(unittest.TestCase):
+  def setUp(self):
+    self.fn = compat.partial(iallocator.IAllocator._ComputeBasicNodeData,
+                             _FakeConfigWithNdParams())
+
+  def testEmpty(self):
+    self.assertEqual(self.fn({}, None), {})
+
+  def testSimple(self):
+    node1 = objects.Node(name="node1",
+                         primary_ip="192.0.2.1",
+                         secondary_ip="192.0.2.2",
+                         offline=False,
+                         drained=False,
+                         master_candidate=True,
+                         master_capable=True,
+                         group="11112222",
+                         vm_capable=False)
+
+    node2 = objects.Node(name="node2",
+                         primary_ip="192.0.2.3",
+                         secondary_ip="192.0.2.4",
+                         offline=True,
+                         drained=False,
+                         master_candidate=False,
+                         master_capable=False,
+                         group="11112222",
+                         vm_capable=True)
+
+    assert node1 != node2
+
+    ninfo = {
+      "#unused-1#": node1,
+      "#unused-2#": node2,
+      }
+
+    self.assertEqual(self.fn(ninfo, None), {
+      "node1": {
+        "tags": [],
+        "primary_ip": "192.0.2.1",
+        "secondary_ip": "192.0.2.2",
+        "offline": False,
+        "drained": False,
+        "master_candidate": True,
+        "group": "11112222",
+        "master_capable": True,
+        "vm_capable": False,
+        "ndparams": None,
+        },
+      "node2": {
+        "tags": [],
+        "primary_ip": "192.0.2.3",
+        "secondary_ip": "192.0.2.4",
+        "offline": True,
+        "drained": False,
+        "master_candidate": False,
+        "group": "11112222",
+        "master_capable": False,
+        "vm_capable": True,
+        "ndparams": None,
+        },
+      })
+
+  def testOfflineNode(self):
+    for whitelist in [None, [], set(), ["node1"], ["node2"]]:
+      result = self.fn({
+        "node1": objects.Node(name="node1", offline=True)
+        }, whitelist)
+      self.assertEqual(len(result), 1)
+      self.assertTrue(result["node1"]["offline"])
+
+  def testWhitelist(self):
+    for whitelist in [None, [], set(), ["node1"], ["node2"]]:
+      result = self.fn({
+        "node1": objects.Node(name="node1", offline=False)
+        }, whitelist)
+      self.assertEqual(len(result), 1)
+
+      if whitelist is None or "node1" in whitelist:
+        self.assertFalse(result["node1"]["offline"])
+      else:
+        self.assertTrue(result["node1"]["offline"])
+
+
 if __name__ == "__main__":
   testutils.GanetiTestProgram()