diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 7514255aa899b4c9091d87767d1844b878229983..d3d1ca3ee0e42f5058585b802a342e40f7f89a00 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -3571,6 +3571,29 @@ class LUReplaceDisks(LogicalUnit):
   HTYPE = constants.HTYPE_INSTANCE
   _OP_REQP = ["instance_name", "mode", "disks"]
 
+  def _RunAllocator(self):
+    """Compute a new secondary node using an IAllocator.
+
+    """
+    ial = IAllocator(self.cfg, self.sstore,
+                     mode=constants.IALLOCATOR_MODE_RELOC,
+                     name=self.op.instance_name,
+                     relocate_from=[self.sec_node])
+
+    ial.Run(self.op.iallocator)
+
+    if not ial.success:
+      raise errors.OpPrereqError("Can't compute nodes using"
+                                 " iallocator '%s': %s" % (self.op.iallocator,
+                                                           ial.info))
+    if len(ial.nodes) != ial.required_nodes:
+      raise errors.OpPrereqError("iallocator '%s' returned invalid number"
+                                 " of nodes (%s), required %s" %
+                                 (len(ial.nodes), ial.required_nodes))
+    self.op.remote_node = ial.nodes[0]
+    logger.ToStdout("Selected new secondary for the instance: %s" %
+                    self.op.remote_node)
+
   def BuildHooksEnv(self):
     """Build hooks env.
 
@@ -3597,6 +3620,9 @@ class LUReplaceDisks(LogicalUnit):
     This checks that the instance is in the cluster.
 
     """
+    if not hasattr(self.op, "remote_node"):
+      self.op.remote_node = None
+
     instance = self.cfg.GetInstanceInfo(
       self.cfg.ExpandInstanceName(self.op.instance_name))
     if instance is None:
@@ -3616,7 +3642,14 @@ class LUReplaceDisks(LogicalUnit):
 
     self.sec_node = instance.secondary_nodes[0]
 
-    remote_node = getattr(self.op, "remote_node", None)
+    ia_name = getattr(self.op, "iallocator", None)
+    if ia_name is not None:
+      if self.op.remote_node is not None:
+        raise errors.OpPrereqError("Give either the iallocator or the new"
+                                   " secondary, not both")
+      self.op.remote_node = self._RunAllocator()
+
+    remote_node = self.op.remote_node
     if remote_node is not None:
       remote_node = self.cfg.ExpandNodeName(remote_node)
       if remote_node is None:
diff --git a/lib/opcodes.py b/lib/opcodes.py
index 289d971b16d0ed82b024ea5b9e86f23be5c8d6fe..ad4716956f28ebd7bb5a576d6c955e00e4b14363 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -328,7 +328,7 @@ class OpRebootInstance(OpCode):
 class OpReplaceDisks(OpCode):
   """Replace the disks of an instance."""
   OP_ID = "OP_INSTANCE_REPLACE_DISKS"
-  __slots__ = ["instance_name", "remote_node", "mode", "disks"]
+  __slots__ = ["instance_name", "remote_node", "mode", "disks", "iallocator"]
 
 
 class OpFailoverInstance(OpCode):
diff --git a/scripts/gnt-instance b/scripts/gnt-instance
index 9a02927c873431eb45c1e66977642d58dc91e1de..43c4506eeb5249d207f9fec7755e56c6a3373a5c 100755
--- a/scripts/gnt-instance
+++ b/scripts/gnt-instance
@@ -448,6 +448,7 @@ def ReplaceDisks(opts, args):
   """
   instance_name = args[0]
   new_2ndary = opts.new_secondary
+  iallocator = opts.iallocator
   if opts.disks is None:
     disks = ["sda", "sdb"]
   else:
@@ -456,14 +457,16 @@ def ReplaceDisks(opts, args):
     mode = constants.REPLACE_DISK_ALL
   elif opts.on_primary: # only on primary:
     mode = constants.REPLACE_DISK_PRI
-    if new_2ndary is not None:
+    if new_2ndary is not None or iallocator is not None:
       raise errors.OpPrereqError("Can't change secondary node on primary disk"
                                  " replacement")
-  elif opts.on_secondary is not None: # only on secondary
+  elif opts.on_secondary is not None or iallocator is not None:
+    # only on secondary
     mode = constants.REPLACE_DISK_SEC
 
   op = opcodes.OpReplaceDisks(instance_name=args[0], disks=disks,
-                              remote_node=new_2ndary, mode=mode)
+                              remote_node=new_2ndary, mode=mode,
+                              iallocator=iallocator)
   SubmitOpCode(op)
   return 0
 
@@ -841,6 +844,12 @@ commands = {
                                  help=("Comma-separated list of disks"
                                        " to replace (e.g. sda) (optional,"
                                        " defaults to all disks")),
+                     make_option("--iallocator", metavar="<NAME>",
+                                 help="Select new secondary for the instance"
+                                 " automatically using the"
+                                 " <NAME> iallocator plugin (enables"
+                                 " secondary node replacement)",
+                                 default=None, type="string"),
                      ],
                     "[-s|-p|-n NODE] <instance>",
                     "Replaces all disks for the instance"),
diff --git a/tools/burnin b/tools/burnin
index 23a82e649622e505fc5834bc0fbe4470c2586982..3a63d9b185a62271c245a99d3cb99b5a756ed7b1 100755
--- a/tools/burnin
+++ b/tools/burnin
@@ -257,9 +257,12 @@ class Burner(object):
     mytor = izip(islice(cycle(self.nodes), 2, None),
                  self.instances)
     for tnode, instance in mytor:
+      if self.opts.iallocator:
+        tnode = None
       op = opcodes.OpReplaceDisks(instance_name=instance,
                                   mode=mode,
                                   remote_node=tnode,
+                                  iallocator=self.opts.iallocator,
                                   disks=["sda", "sdb"])
       Log("- Replace secondary (%s) for instance %s" % (mode, instance))
       self.ExecOp(op)