diff --git a/lib/cli.py b/lib/cli.py
index 57ff3eb0a9dfbe724dfd58e88e1756b34b618df7..60e86e7376d74777752f6e7cd047694ae9bb30ef 100644
--- a/lib/cli.py
+++ b/lib/cli.py
@@ -69,6 +69,7 @@ __all__ = [
   "DRAINED_OPT",
   "DRY_RUN_OPT",
   "DRBD_HELPER_OPT",
+  "DST_NODE_OPT",
   "EARLY_RELEASE_OPT",
   "ENABLED_HV_OPT",
   "ERROR_CODES_OPT",
@@ -839,6 +840,11 @@ REMOVE_INSTANCE_OPT = cli_option("--remove-instance", dest="remove_instance",
                                  action="store_true", default=False,
                                  help="Remove the instance from the cluster")
 
+DST_NODE_OPT = cli_option("-n", "--target-node", dest="dst_node",
+                               help="Specifies the new node for the instance",
+                               metavar="NODE", default=None,
+                               completion_suggest=OPT_COMPL_ONE_NODE)
+
 NEW_SECONDARY_OPT = cli_option("-n", "--new-secondary", dest="dst_node",
                                help="Specifies the new secondary node",
                                metavar="NODE", default=None,
diff --git a/lib/client/gnt_instance.py b/lib/client/gnt_instance.py
index 66d030f7fb965c93e6861dd62ed3a89e13c15de6..8b2524f0e57c77c1f0790bd405d92fe5b39f05f4 100644
--- a/lib/client/gnt_instance.py
+++ b/lib/client/gnt_instance.py
@@ -755,6 +755,12 @@ def FailoverInstance(opts, args):
   cl = GetClient()
   instance_name = args[0]
   force = opts.force
+  iallocator = opts.iallocator
+  target_node = opts.dst_node
+
+  if iallocator and target_node:
+    raise errors.OpPrereqError("Specify either an iallocator (-I), or a target"
+                               " node (-n) but not both", errors.ECODE_INVAL)
 
   if not force:
     _EnsureInstancesExist(cl, [instance_name])
@@ -767,7 +773,9 @@ def FailoverInstance(opts, args):
 
   op = opcodes.OpInstanceFailover(instance_name=instance_name,
                                   ignore_consistency=opts.ignore_consistency,
-                                  shutdown_timeout=opts.shutdown_timeout)
+                                  shutdown_timeout=opts.shutdown_timeout,
+                                  iallocator=iallocator,
+                                  target_node=target_node)
   SubmitOrSend(op, opts, cl=cl)
   return 0
 
@@ -787,6 +795,12 @@ def MigrateInstance(opts, args):
   cl = GetClient()
   instance_name = args[0]
   force = opts.force
+  iallocator = opts.iallocator
+  target_node = opts.dst_node
+
+  if iallocator and target_node:
+    raise errors.OpPrereqError("Specify either an iallocator (-I), or a target"
+                               " node (-n) but not both", errors.ECODE_INVAL)
 
   if not force:
     _EnsureInstancesExist(cl, [instance_name])
@@ -814,7 +828,8 @@ def MigrateInstance(opts, args):
     mode = opts.migration_mode
 
   op = opcodes.OpInstanceMigrate(instance_name=instance_name, mode=mode,
-                                 cleanup=opts.cleanup)
+                                 cleanup=opts.cleanup, iallocator=iallocator,
+                                 target_node=target_node)
   SubmitOpCode(op, cl=cl, opts=opts)
   return 0
 
@@ -1344,15 +1359,15 @@ commands = {
   'failover': (
     FailoverInstance, ARGS_ONE_INSTANCE,
     [FORCE_OPT, IGNORE_CONSIST_OPT, SUBMIT_OPT, SHUTDOWN_TIMEOUT_OPT,
-     DRY_RUN_OPT, PRIORITY_OPT],
+     DRY_RUN_OPT, PRIORITY_OPT, DST_NODE_OPT, IALLOCATOR_OPT],
     "[-f] <instance>", "Stops the instance and starts it on the backup node,"
-    " using the remote mirror (only for instances of type drbd)"),
+    " using the remote mirror (only for mirrored instances)"),
   'migrate': (
     MigrateInstance, ARGS_ONE_INSTANCE,
     [FORCE_OPT, NONLIVE_OPT, MIGRATION_MODE_OPT, CLEANUP_OPT, DRY_RUN_OPT,
-     PRIORITY_OPT],
+     PRIORITY_OPT, DST_NODE_OPT, IALLOCATOR_OPT],
     "[-f] <instance>", "Migrate instance to its secondary node"
-    " (only for instances of type drbd)"),
+    " (only for mirrored instances)"),
   'move': (
     MoveInstance, ARGS_ONE_INSTANCE,
     [FORCE_OPT, SUBMIT_OPT, SINGLE_NODE_OPT, SHUTDOWN_TIMEOUT_OPT,
diff --git a/lib/client/gnt_node.py b/lib/client/gnt_node.py
index d88c517aa2dd41a5ff5acd8bb4251f41bcae3e1c..8420c88c72838279ae2d08a4ebf53614e66960cb 100644
--- a/lib/client/gnt_node.py
+++ b/lib/client/gnt_node.py
@@ -338,7 +338,8 @@ def FailoverNode(opts, args):
   jex = JobExecutor(cl=cl, opts=opts)
   for iname in pinst:
     op = opcodes.OpInstanceFailover(instance_name=iname,
-                                    ignore_consistency=opts.ignore_consistency)
+                                    ignore_consistency=opts.ignore_consistency,
+                                    iallocator=opts.iallocator)
     jex.QueueJob(iname, op)
   results = jex.GetResults()
   bad_cnt = len([row for row in results if not row[0]])
@@ -380,7 +381,8 @@ def MigrateNode(opts, args):
     mode = constants.HT_MIGRATION_NONLIVE
   else:
     mode = opts.migration_mode
-  op = opcodes.OpNodeMigrate(node_name=args[0], mode=mode)
+  op = opcodes.OpNodeMigrate(node_name=args[0], mode=mode,
+                             iallocator=opts.iallocator)
   SubmitOpCode(op, cl=cl, opts=opts)
 
 
@@ -815,13 +817,15 @@ commands = {
     "Relocate the secondary instances from a node"
     " to other nodes (only for instances with drbd disk template)"),
   'failover': (
-    FailoverNode, ARGS_ONE_NODE, [FORCE_OPT, IGNORE_CONSIST_OPT, PRIORITY_OPT],
+    FailoverNode, ARGS_ONE_NODE, [FORCE_OPT, IGNORE_CONSIST_OPT,
+                                  IALLOCATOR_OPT, PRIORITY_OPT],
     "[-f] <node>",
     "Stops the primary instances on a node and start them on their"
     " secondary node (only for instances with drbd disk template)"),
   'migrate': (
     MigrateNode, ARGS_ONE_NODE,
-    [FORCE_OPT, NONLIVE_OPT, MIGRATION_MODE_OPT, PRIORITY_OPT],
+    [FORCE_OPT, NONLIVE_OPT, MIGRATION_MODE_OPT,
+     IALLOCATOR_OPT, PRIORITY_OPT],
     "[-f] <node>",
     "Migrate all the primary instance on a node away from it"
     " (only for instances of type drbd)"),