Commit a5bc662a authored by Iustin Pop's avatar Iustin Pop

Implement gnt-node evacuate

This patch adds a new 'evacuate' subcommand to gnt-node. The command
will do a replace disks for all instances having that node as secondary
with the new target being the new node given.

The syntax is:
  gnt-node evacuate src_node target_node

The command by itself doesn't do any resource checks, and instead relies
on the LUFailoverInstance code to do that.

Reviewed-by: imsnah
parent f00b46bc
...@@ -91,8 +91,10 @@ INISECT_EXP = "export" ...@@ -91,8 +91,10 @@ INISECT_EXP = "export"
INISECT_INS = "instance" INISECT_INS = "instance"
# common exit codes # common exit codes
EXIT_CONFIRMATION = 13 # need user confirmation
# tags # tags
TAG_CLUSTER = "cluster" TAG_CLUSTER = "cluster"
...@@ -125,6 +125,31 @@ ...@@ -125,6 +125,31 @@
</para> </para>
</refsect2> </refsect2>
<arg choice="req"><replaceable>source_node</replaceable></arg>
<arg choice="req"><replaceable>destination_node</replaceable></arg>
This command will change the secondary node from the source
node to the destination node for all instances having the
source node as secondary. It works only for instances having
a remote raid disk layout.
# gnt-node evacuate
<refsect2> <refsect2>
<title>FAILOVER</title> <title>FAILOVER</title>
...@@ -94,6 +94,65 @@ def ListNodes(opts, args): ...@@ -94,6 +94,65 @@ def ListNodes(opts, args):
return 0 return 0
def EvacuateNode(opts, args):
"""Relocate all secondary instance from a node.
force = opts.force
selected_fields = ["name", "sinst_list"]
src_node, dst_node = args
op = opcodes.OpQueryNodes(output_fields=selected_fields, names=[src_node])
result = SubmitOpCode(op)
src_node, sinst = result[0]
op = opcodes.OpQueryNodes(output_fields=["name"], names=[dst_node])
result = SubmitOpCode(op)
dst_node = result[0][0]
if src_node == dst_node:
raise errors.OpPrereqError("Evacuate node needs different source and"
" target nodes (node %s given twice)" %
if not sinst:
logger.ToStderr("No secondary instances on node %s, exiting." % src_node)
return constants.EXIT_SUCCESS
sinst = utils.NiceSort(sinst)
retcode = constants.EXIT_SUCCESS
if not force and not AskUser("Relocate instance(s) %s from node\n"
" %s to node\n %s?" %
(",".join("'%s'" % name for name in sinst),
src_node, dst_node)):
return constants.EXIT_CONFIRMATION
good_cnt = bad_cnt = 0
for iname in sinst:
op = opcodes.OpReplaceDisks(instance_name=iname,
logger.ToStdout("Replacing disks for instance %s" % iname)
logger.ToStdout("Instance %s has been relocated" % iname)
good_cnt += 1
except errors.GenericError, err:
nret, msg = FormatError(err)
retcode |= nret
logger.ToStderr("Error replacing disks for instance %s: %s" %
(iname, msg))
bad_cnt += 1
if retcode == constants.EXIT_SUCCESS:
logger.ToStdout("All %d instance(s) relocated successfully." % good_cnt)
logger.ToStdout("There were errors during the relocation:\n"
"%d error(s) out of %d instance(s)." %
(bad_cnt, good_cnt + bad_cnt))
return retcode
def FailoverNode(opts, args): def FailoverNode(opts, args):
"""Failover all primary instance on a node. """Failover all primary instance on a node.
...@@ -220,6 +279,11 @@ commands = { ...@@ -220,6 +279,11 @@ commands = {
help="Specify the secondary ip for the node", help="Specify the secondary ip for the node",
metavar="ADDRESS", default=None),], metavar="ADDRESS", default=None),],
"<node_name>", "Add a node to the cluster"), "<node_name>", "Add a node to the cluster"),
'evacuate': (EvacuateNode, ARGS_FIXED(2),
"[-f] <src_node> <dst_node>",
"Relocate the secondary instances from the first node"
" to the second one (only for instances of type remote_raid1)"),
'failover': (FailoverNode, ARGS_ONE, 'failover': (FailoverNode, ARGS_ONE,
make_option("--ignore-consistency", dest="ignore_consistency", make_option("--ignore-consistency", dest="ignore_consistency",
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment