Commit e7c6e02b authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

Add --readd option to “gnt-node add”

This allows us to readd a node after it failed and required a
reinstallation or replacement.

Reviewed-by: iustinp
parent 35a0d128
#
#
# Copyright (C) 2006, 2007 Google Inc.
# Copyright (C) 2006, 2007, 2008 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -1641,13 +1641,24 @@ class LUAddNode(LogicalUnit):
if not utils.IsValidIP(secondary_ip):
raise errors.OpPrereqError("Invalid secondary IP given")
self.op.secondary_ip = secondary_ip
node_list = cfg.GetNodeList()
if node in node_list:
raise errors.OpPrereqError("Node %s is already in the configuration"
% node)
if not self.op.readd and node in node_list:
raise errors.OpPrereqError("Node %s is already in the configuration" %
node)
elif self.op.readd and node not in node_list:
raise errors.OpPrereqError("Node %s is not in the configuration" % node)
for existing_node_name in node_list:
existing_node = cfg.GetNodeInfo(existing_node_name)
if self.op.readd and node == existing_node_name:
if (existing_node.primary_ip != primary_ip or
existing_node.secondary_ip != secondary_ip):
raise errors.OpPrereqError("Readded node doesn't have the same IP"
" address configuration as before")
continue
if (existing_node.primary_ip == primary_ip or
existing_node.secondary_ip == primary_ip or
existing_node.primary_ip == secondary_ip or
......@@ -1810,8 +1821,9 @@ class LUAddNode(LogicalUnit):
if not self.ssh.CopyFileToNode(node, fname):
logger.Error("could not copy file %s to node %s" % (fname, node))
logger.Info("adding node %s to cluster.conf" % node)
self.cfg.AddNode(new_node)
if not self.op.readd:
logger.Info("adding node %s to cluster.conf" % node)
self.cfg.AddNode(new_node)
class LUMasterFailover(LogicalUnit):
......
......@@ -257,7 +257,7 @@ class OpRemoveNode(OpCode):
class OpAddNode(OpCode):
"""Add a node."""
OP_ID = "OP_NODE_ADD"
__slots__ = ["node_name", "primary_ip", "secondary_ip"]
__slots__ = ["node_name", "primary_ip", "secondary_ip", "readd"]
class OpQueryNodes(OpCode):
......
......@@ -20,6 +20,7 @@
<copyright>
<year>2006</year>
<year>2007</year>
<year>2008</year>
<holder>Google Inc.</holder>
</copyright>
&dhdate;
......@@ -60,6 +61,7 @@
<cmdsynopsis>
<command>add</command>
<arg>--readd</arg>
<arg>-s <replaceable>secondary_ip</replaceable></arg>
<arg choice="req"><replaceable>nodename</replaceable></arg>
</cmdsynopsis>
......@@ -91,6 +93,11 @@
informations.
</para>
<para>
In case you're readding a node after hardware failure, you
can use the <option>--readd</option> parameter.
</para>
<para>
Example:
<screen>
......
......@@ -263,6 +263,9 @@ def main():
if qa_config.TestEnabled('tags'):
RunTest(qa_tags.TestNodeTags, pnode)
if qa_config.TestEnabled('node-readd'):
RunTest(qa_node.TestNodeReadd, pnode)
if qa_config.TestEnabled('instance-add-plain-disk'):
instance = RunTest(qa_instance.TestInstanceAddWithPlainDisk, pnode)
RunCommonInstanceTests(instance)
......
......@@ -41,6 +41,7 @@ tests:
node-info: True
node-volumes: True
node-readd: True
# This test needs at least three nodes
node-evacuate: False
......
......@@ -29,15 +29,19 @@ from qa_utils import AssertEqual, StartSSH
@qa_utils.DefineHook('node-add')
def _NodeAdd(node):
def _NodeAdd(node, readd=False):
master = qa_config.GetMasterNode()
if node.get('_added', False):
if not readd and node.get('_added', False):
raise qa_error.Error("Node %s already in cluster" % node['primary'])
elif readd and not node.get('_added', False):
raise qa_error.Error("Node not yet %s in cluster" % node['primary'])
cmd = ['gnt-node', 'add']
if node.get('secondary', None):
cmd.append('--secondary-ip=%s' % node['secondary'])
if readd:
cmd.append('--readd')
cmd.append(node['primary'])
AssertEqual(StartSSH(master['primary'],
utils.ShellQuoteArgs(cmd)).wait(), 0)
......@@ -60,7 +64,7 @@ def TestNodeAddAll():
master = qa_config.GetMasterNode()
for node in qa_config.get('nodes'):
if node != master:
_NodeAdd(node)
_NodeAdd(node, readd=False)
def TestNodeRemoveAll():
......@@ -71,6 +75,12 @@ def TestNodeRemoveAll():
_NodeRemove(node)
@qa_utils.DefineHook('node-readd')
def TestNodeReadd(node):
"""gnt-node add --readd"""
_NodeAdd(node, readd=True)
@qa_utils.DefineHook('node-info')
def TestNodeInfo():
"""gnt-node info"""
......
#!/usr/bin/python
#
# Copyright (C) 2006, 2007 Google Inc.
# Copyright (C) 2006, 2007, 2008 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -36,7 +36,8 @@ def AddNode(opts, args):
"Performing this operation is going to replace the ssh daemon keypair\n"
"on the target machine (%s) with the ones of the current one\n"
"and grant full intra-cluster ssh root access to/from it\n" % args[0])
op = opcodes.OpAddNode(node_name=args[0], secondary_ip=opts.secondary_ip)
op = opcodes.OpAddNode(node_name=args[0], secondary_ip=opts.secondary_ip,
readd=opts.readd)
SubmitOpCode(op)
......@@ -279,7 +280,11 @@ commands = {
[DEBUG_OPT,
make_option("-s", "--secondary-ip", dest="secondary_ip",
help="Specify the secondary ip for the node",
metavar="ADDRESS", default=None),],
metavar="ADDRESS", default=None),
make_option("--readd", dest="readd",
default=False, action="store_true",
help="Readd old node after replacing it"),
],
"[-s ip] <node_name>", "Add a node to the cluster"),
'evacuate': (EvacuateNode, ARGS_FIXED(2),
[DEBUG_OPT, FORCE_OPT],
......
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