#
#
-# 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
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
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):
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):
<copyright>
<year>2006</year>
<year>2007</year>
+ <year>2008</year>
<holder>Google Inc.</holder>
</copyright>
&dhdate;
<cmdsynopsis>
<command>add</command>
+ <arg>--readd</arg>
<arg>-s <replaceable>secondary_ip</replaceable></arg>
<arg choice="req"><replaceable>nodename</replaceable></arg>
</cmdsynopsis>
</para>
<para>
+ In case you're readding a node after hardware failure, you
+ can use the <option>--readd</option> parameter.
+ </para>
+
+ <para>
Example:
<screen>
# gnt-node add node5.example.com
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)
node-info: True
node-volumes: True
+ node-readd: True
# This test needs at least three nodes
node-evacuate: False
@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)
master = qa_config.GetMasterNode()
for node in qa_config.get('nodes'):
if node != master:
- _NodeAdd(node)
+ _NodeAdd(node, readd=False)
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
"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)
[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],