Commit c450e9b0 authored by Iustin Pop's avatar Iustin Pop

Implement node failover

This patch implements a simple failover command for failing over all
primary instances. This is just a batched form of gnt-instance failover.

Reviewed-by: imsnah
parent 86208a02
......@@ -125,6 +125,37 @@
</para>
</refsect2>
<refsect2>
<title>FAILOVER</title>
<cmdsynopsis>
<command>failover</command>
<arg>-f</arg>
<arg>--ignore-consistency</arg>
<arg choice="req"><replaceable>node</replaceable></arg>
</cmdsynopsis>
<para>
This command will fail over all instances having the given
node as primary to their secondary nodes. This works only for
instances having a remote raid disk layout.
</para>
<para>
Normally the failover will check the consistency of the disks
before failing over the instance. If you are trying to migrate
instances off a dead node, this will fail. Use the
<option>--ignore-consistency</option> option for this purpose.
</para>
<para>
Example:
<screen>
# gnt-node failover node1.example.com
</screen>
</para>
</refsect2>
<refsect2>
<title>INFO</title>
......
......@@ -27,6 +27,7 @@ from ganeti import opcodes
from ganeti import logger
from ganeti import utils
from ganeti import constants
from ganeti import errors
def AddNode(opts, args):
......@@ -93,6 +94,53 @@ def ListNodes(opts, args):
return 0
def FailoverNode(opts, args):
"""Failover all primary instance on a node.
"""
force = opts.force
selected_fields = ["name", "pinst_list"]
op = opcodes.OpQueryNodes(output_fields=selected_fields, names=args)
result = SubmitOpCode(op)
node, pinst = result[0]
if not pinst:
logger.ToStderr("No primary instances on node %s, exiting." % node)
return 0
pinst = utils.NiceSort(pinst)
retcode = 0
if not force and not AskUser("Fail over instance(s) %s?" %
(",".join("'%s'" % name for name in pinst))):
return 2
good_cnt = bad_cnt = 0
for iname in pinst:
op = opcodes.OpFailoverInstance(instance_name=iname,
ignore_consistency=opts.ignore_consistency)
try:
logger.ToStdout("Failing over instance %s" % iname)
SubmitOpCode(op)
logger.ToStdout("Instance %s has been failed over" % iname)
good_cnt += 1
except errors.GenericError, err:
nret, msg = FormatError(err)
retcode |= nret
logger.ToStderr("Error failing over instance %s: %s" % (iname, msg))
bad_cnt += 1
if retcode == 0:
logger.ToStdout("All %d instance(s) failed over successfully." % good_cnt)
else:
logger.ToStdout("There were errors during the failover:\n"
"%d error(s) out of %d instance(s)." %
(bad_cnt, good_cnt + bad_cnt))
return retcode
def ShowNodeConfig(opts, args):
"""Show node information.
......@@ -172,6 +220,16 @@ commands = {
help="Specify the secondary ip for the node",
metavar="ADDRESS", default=None),],
"<node_name>", "Add a node to the cluster"),
'failover': (FailoverNode, ARGS_ONE,
[DEBUG_OPT, FORCE_OPT,
make_option("--ignore-consistency", dest="ignore_consistency",
action="store_true", default=False,
help="Ignore the consistency of the disks on"
" the secondary"),
],
"[-f] <node>",
"Stops the primary instances on a node and start them on their"
" secondary node (only for instances of type remote_raid1)"),
'info': (ShowNodeConfig, ARGS_ANY, [DEBUG_OPT],
"[<node_name>...]", "Show information about the node(s)"),
'list': (ListNodes, ARGS_NONE,
......
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