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