diff --git a/doc/examples/dumb-allocator b/doc/examples/dumb-allocator
index f6d6560fd440b66fa3a981b79e513efacb95f1c8..641c418354f605b09ad773611bc84f84757bf3a7 100755
--- a/doc/examples/dumb-allocator
+++ b/doc/examples/dumb-allocator
@@ -47,16 +47,17 @@ def SelectNode(nodes, request, to_skip):
   return selected
 
 
-def OutputError(text):
+def OutputError(text, exit_code=1):
   """Builds an error response with a given info message.
 
   """
   error = {
     "success": False,
     "info": text,
+    "nodes": [],
     }
   print simplejson.dumps(error, indent=2)
-  return 1
+  return exit_code
 
 
 def main():
@@ -78,14 +79,14 @@ def main():
 
   npri = SelectNode(nodes, request, [])
   if npri is None:
-    return OutputError("Can't find a suitable primary node")
+    return OutputError("Can't find a suitable primary node", exit_code=0)
 
   result_nodes = [npri]
   if request["disk_template"] == "drbd":
     nsec = SelectNode(nodes, request, result_nodes)
     if nsec is None:
       return OutputError("Can't find a suitable secondary node (%s selected"
-                         " as primary)" % npri)
+                         " as primary)" % npri, exit_code=0)
     result_nodes.append(nsec)
 
   result = {
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 9c3e5608212b926bd3e428a4bc4fb7da0ca3a846..5d18c2f7b908c66e0d2c796ee88af8c0e68b7f8f 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -3126,10 +3126,59 @@ class LUCreateInstance(LogicalUnit):
   """
   HPATH = "instance-add"
   HTYPE = constants.HTYPE_INSTANCE
-  _OP_REQP = ["instance_name", "mem_size", "disk_size", "pnode",
+  _OP_REQP = ["instance_name", "mem_size", "disk_size",
               "disk_template", "swap_size", "mode", "start", "vcpus",
               "wait_for_sync", "ip_check", "mac"]
 
+  def _RunAllocator(self):
+    """Run the allocator based on input opcode.
+
+    """
+    al_data = _IAllocatorGetClusterData(self.cfg, self.sstore)
+    disks = [{"size": self.op.disk_size, "mode": "w"},
+             {"size": self.op.swap_size, "mode": "w"}]
+    nics = [{"mac": self.op.mac, "ip": getattr(self.op, "ip", None),
+             "bridge": self.op.bridge}]
+    op = opcodes.OpTestAllocator(name=self.op.instance_name,
+                                 disk_template=self.op.disk_template,
+                                 tags=[],
+                                 os=self.op.os_type,
+                                 vcpus=self.op.vcpus,
+                                 mem_size=self.op.mem_size,
+                                 disks=disks,
+                                 nics=nics)
+
+    _IAllocatorAddNewInstance(al_data, op)
+
+    if _JSON_INDENT is None:
+      text = simplejson.dumps(al_data)
+    else:
+      text = simplejson.dumps(al_data, indent=_JSON_INDENT)
+
+    result = _IAllocatorRun(self.op.iallocator, text)
+
+    result = _IAllocatorValidateResult(result)
+
+    if not result["success"]:
+      raise errors.OpPrereqError("Can't compute nodes using"
+                                 " iallocator '%s': %s" % (self.op.iallocator,
+                                                           result["info"]))
+    req_nodes = 1
+    if self.op.disk_template in constants.DTS_NET_MIRROR:
+      req_nodes += 1
+
+    if len(result["nodes"]) != req_nodes:
+      raise errors.OpPrereqError("iallocator '%s' returned invalid number"
+                                 " of nodes (%s), required %s" %
+                                 (len(result["nodes"]), req_nodes))
+    self.op.pnode = result["nodes"][0]
+    logger.ToStdout("Selected nodes for the instance: %s" %
+                    (", ".join(result["nodes"]),))
+    logger.Info("Selected nodes for instance %s via iallocator %s: %s" %
+                (self.op.instance_name, self.op.iallocator, result["nodes"]))
+    if req_nodes == 2:
+      self.op.snode = result["nodes"][1]
+
   def BuildHooksEnv(self):
     """Build hooks env.
 
@@ -3166,7 +3215,9 @@ class LUCreateInstance(LogicalUnit):
     """Check prerequisites.
 
     """
-    for attr in ["kernel_path", "initrd_path", "hvm_boot_order"]:
+    # set optional parameters to none if they don't exist
+    for attr in ["kernel_path", "initrd_path", "hvm_boot_order", "pnode",
+                 "iallocator"]:
       if not hasattr(self.op, attr):
         setattr(self.op, attr, None)
 
@@ -3284,6 +3335,14 @@ class LUCreateInstance(LogicalUnit):
     if self.op.file_storage_dir and os.path.isabs(self.op.file_storage_dir):
         raise errors.OpPrereqError("File storage directory not a relative"
                                    " path")
+    #### allocator run
+
+    if [self.op.iallocator, self.op.pnode].count(None) != 1:
+      raise errors.OpPrereqError("One and only one of iallocator and primary"
+                                 " node must be given")
+
+    if self.op.iallocator is not None:
+      self._RunAllocator()
 
     #### node related checks
 
@@ -4784,7 +4843,7 @@ def _IAllocatorRun(name, data):
   alloc_script = utils.FindFile(name, constants.IALLOCATOR_SEARCH_PATH,
                                 os.path.isfile)
   if alloc_script is None:
-    raise errors.OpExecError("Can't find allocator")
+    raise errors.OpExecError("Can't find allocator '%s'" % name)
 
   fd, fin_name = tempfile.mkstemp(prefix="ganeti-iallocator.")
   try:
@@ -4800,6 +4859,29 @@ def _IAllocatorRun(name, data):
   return result.stdout
 
 
+def _IAllocatorValidateResult(data):
+  """Process the allocator results.
+
+  """
+  try:
+    rdict = simplejson.loads(data)
+  except Exception, err:
+    raise errors.OpExecError("Can't parse iallocator results: %s" % str(err))
+
+  if not isinstance(rdict, dict):
+    raise errors.OpExecError("Can't parse iallocator results: not a dict")
+
+  for key in "success", "info", "nodes":
+    if key not in rdict:
+      raise errors.OpExecError("Can't parse iallocator results:"
+                               " missing key '%s'" % key)
+
+  if not isinstance(rdict["nodes"], list):
+    raise errors.OpExecError("Can't parse iallocator results: 'nodes' key"
+                             " is not a list")
+  return rdict
+
+
 class LUTestAllocator(NoHooksLU):
   """Run allocator tests.
 
diff --git a/lib/opcodes.py b/lib/opcodes.py
index a80bb166c254f56926aad8dc7e45759c6d679119..117757f9f2896889d858a41c7c092db3f4003f6b 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -284,6 +284,7 @@ class OpCreateInstance(OpCode):
     "wait_for_sync", "ip_check", "mac",
     "kernel_path", "initrd_path", "hvm_boot_order",
     "file_storage_dir", "file_driver",
+    "iallocator",
     ]
 
 
diff --git a/scripts/gnt-backup b/scripts/gnt-backup
index 2876b25d6801866581586e06571ba6df5f98a450..c250e250d9626abfeed5273b2c1352215f03de90 100755
--- a/scripts/gnt-backup
+++ b/scripts/gnt-backup
@@ -99,7 +99,8 @@ def ImportInstance(opts, args):
                                 vcpus=opts.vcpus, ip_check=opts.ip_check,
                                 ip=opts.ip, bridge=opts.bridge, start=False,
                                 src_node=opts.src_node, src_path=opts.src_dir,
-                                wait_for_sync=opts.wait_for_sync, mac="auto")
+                                wait_for_sync=opts.wait_for_sync, mac="auto",
+                                iallocator=opts.iallocator)
   SubmitOpCode(op)
   return 0
 
@@ -137,6 +138,9 @@ import_opts = [
   make_option("--no-ip-check", dest="ip_check", default=True,
               action="store_false", help="Don't check that the instance's IP"
               " is alive"),
+  make_option("--iallocator", metavar="<NAME>",
+              help="Select nodes for the instance automatically using the"
+              " <NAME> iallocator plugin", default=None, type="string"),
   ]
 
 commands = {
diff --git a/scripts/gnt-instance b/scripts/gnt-instance
index 19b10940c1118dc3a9c0d282b56cde3e8744f5e3..eb9752103af95924c74b4e78ff6acf6a185b5f88 100755
--- a/scripts/gnt-instance
+++ b/scripts/gnt-instance
@@ -261,7 +261,8 @@ def AddInstance(opts, args):
                                 initrd_path=initrd_path,
                                 hvm_boot_order=opts.hvm_boot_order,
                                 file_storage_dir = opts.file_storage_dir,
-                                file_driver = opts.file_driver)
+                                file_driver = opts.file_driver,
+                                iallocator=opts.iallocator)
   SubmitOpCode(op)
   return 0
 
@@ -760,14 +761,17 @@ add_opts = [
               default=None,
               type="string", metavar="<FILENAME>"),
   make_option("--hvm-boot-order", dest="hvm_boot_order",
-              help="boot device order for HVM (one or more of [acdn])",
+              help="Boot device order for HVM (one or more of [acdn])",
               default=None, type="string", metavar="<BOOTORDER>"),
   make_option("--file-storage-dir", dest="file_storage_dir",
               help="Relative path under default cluster-wide file storage dir"
               " to store file-based disks", default=None,
               metavar="<DIR>"),
   make_option("--file-driver", dest="file_driver", help="Driver to use"
-              " for image files", default="loop", metavar="<DRIVER>")
+              " for image files", default="loop", metavar="<DRIVER>"),
+  make_option("--iallocator", metavar="<NAME>",
+              help="Select nodes for the instance automatically using the"
+              " <NAME> iallocator plugin", default=None, type="string"),
   ]
 
 commands = {