Revision e7c6e02b
b/lib/cmdlib.py | ||
---|---|---|
1 | 1 |
# |
2 | 2 |
# |
3 | 3 |
|
4 |
# Copyright (C) 2006, 2007 Google Inc. |
|
4 |
# Copyright (C) 2006, 2007, 2008 Google Inc.
|
|
5 | 5 |
# |
6 | 6 |
# This program is free software; you can redistribute it and/or modify |
7 | 7 |
# it under the terms of the GNU General Public License as published by |
... | ... | |
1641 | 1641 |
if not utils.IsValidIP(secondary_ip): |
1642 | 1642 |
raise errors.OpPrereqError("Invalid secondary IP given") |
1643 | 1643 |
self.op.secondary_ip = secondary_ip |
1644 |
|
|
1644 | 1645 |
node_list = cfg.GetNodeList() |
1645 |
if node in node_list: |
|
1646 |
raise errors.OpPrereqError("Node %s is already in the configuration" |
|
1647 |
% node) |
|
1646 |
if not self.op.readd and node in node_list: |
|
1647 |
raise errors.OpPrereqError("Node %s is already in the configuration" % |
|
1648 |
node) |
|
1649 |
elif self.op.readd and node not in node_list: |
|
1650 |
raise errors.OpPrereqError("Node %s is not in the configuration" % node) |
|
1648 | 1651 |
|
1649 | 1652 |
for existing_node_name in node_list: |
1650 | 1653 |
existing_node = cfg.GetNodeInfo(existing_node_name) |
1654 |
|
|
1655 |
if self.op.readd and node == existing_node_name: |
|
1656 |
if (existing_node.primary_ip != primary_ip or |
|
1657 |
existing_node.secondary_ip != secondary_ip): |
|
1658 |
raise errors.OpPrereqError("Readded node doesn't have the same IP" |
|
1659 |
" address configuration as before") |
|
1660 |
continue |
|
1661 |
|
|
1651 | 1662 |
if (existing_node.primary_ip == primary_ip or |
1652 | 1663 |
existing_node.secondary_ip == primary_ip or |
1653 | 1664 |
existing_node.primary_ip == secondary_ip or |
... | ... | |
1810 | 1821 |
if not self.ssh.CopyFileToNode(node, fname): |
1811 | 1822 |
logger.Error("could not copy file %s to node %s" % (fname, node)) |
1812 | 1823 |
|
1813 |
logger.Info("adding node %s to cluster.conf" % node) |
|
1814 |
self.cfg.AddNode(new_node) |
|
1824 |
if not self.op.readd: |
|
1825 |
logger.Info("adding node %s to cluster.conf" % node) |
|
1826 |
self.cfg.AddNode(new_node) |
|
1815 | 1827 |
|
1816 | 1828 |
|
1817 | 1829 |
class LUMasterFailover(LogicalUnit): |
b/lib/opcodes.py | ||
---|---|---|
257 | 257 |
class OpAddNode(OpCode): |
258 | 258 |
"""Add a node.""" |
259 | 259 |
OP_ID = "OP_NODE_ADD" |
260 |
__slots__ = ["node_name", "primary_ip", "secondary_ip"] |
|
260 |
__slots__ = ["node_name", "primary_ip", "secondary_ip", "readd"]
|
|
261 | 261 |
|
262 | 262 |
|
263 | 263 |
class OpQueryNodes(OpCode): |
b/man/gnt-node.sgml | ||
---|---|---|
20 | 20 |
<copyright> |
21 | 21 |
<year>2006</year> |
22 | 22 |
<year>2007</year> |
23 |
<year>2008</year> |
|
23 | 24 |
<holder>Google Inc.</holder> |
24 | 25 |
</copyright> |
25 | 26 |
&dhdate; |
... | ... | |
60 | 61 |
|
61 | 62 |
<cmdsynopsis> |
62 | 63 |
<command>add</command> |
64 |
<arg>--readd</arg> |
|
63 | 65 |
<arg>-s <replaceable>secondary_ip</replaceable></arg> |
64 | 66 |
<arg choice="req"><replaceable>nodename</replaceable></arg> |
65 | 67 |
</cmdsynopsis> |
... | ... | |
92 | 94 |
</para> |
93 | 95 |
|
94 | 96 |
<para> |
97 |
In case you're readding a node after hardware failure, you |
|
98 |
can use the <option>--readd</option> parameter. |
|
99 |
</para> |
|
100 |
|
|
101 |
<para> |
|
95 | 102 |
Example: |
96 | 103 |
<screen> |
97 | 104 |
# gnt-node add node5.example.com |
b/qa/ganeti-qa.py | ||
---|---|---|
263 | 263 |
if qa_config.TestEnabled('tags'): |
264 | 264 |
RunTest(qa_tags.TestNodeTags, pnode) |
265 | 265 |
|
266 |
if qa_config.TestEnabled('node-readd'): |
|
267 |
RunTest(qa_node.TestNodeReadd, pnode) |
|
268 |
|
|
266 | 269 |
if qa_config.TestEnabled('instance-add-plain-disk'): |
267 | 270 |
instance = RunTest(qa_instance.TestInstanceAddWithPlainDisk, pnode) |
268 | 271 |
RunCommonInstanceTests(instance) |
b/qa/qa-sample.yaml | ||
---|---|---|
41 | 41 |
|
42 | 42 |
node-info: True |
43 | 43 |
node-volumes: True |
44 |
node-readd: True |
|
44 | 45 |
|
45 | 46 |
# This test needs at least three nodes |
46 | 47 |
node-evacuate: False |
b/qa/qa_node.py | ||
---|---|---|
29 | 29 |
|
30 | 30 |
|
31 | 31 |
@qa_utils.DefineHook('node-add') |
32 |
def _NodeAdd(node): |
|
32 |
def _NodeAdd(node, readd=False):
|
|
33 | 33 |
master = qa_config.GetMasterNode() |
34 | 34 |
|
35 |
if node.get('_added', False): |
|
35 |
if not readd and node.get('_added', False):
|
|
36 | 36 |
raise qa_error.Error("Node %s already in cluster" % node['primary']) |
37 |
elif readd and not node.get('_added', False): |
|
38 |
raise qa_error.Error("Node not yet %s in cluster" % node['primary']) |
|
37 | 39 |
|
38 | 40 |
cmd = ['gnt-node', 'add'] |
39 | 41 |
if node.get('secondary', None): |
40 | 42 |
cmd.append('--secondary-ip=%s' % node['secondary']) |
43 |
if readd: |
|
44 |
cmd.append('--readd') |
|
41 | 45 |
cmd.append(node['primary']) |
42 | 46 |
AssertEqual(StartSSH(master['primary'], |
43 | 47 |
utils.ShellQuoteArgs(cmd)).wait(), 0) |
... | ... | |
60 | 64 |
master = qa_config.GetMasterNode() |
61 | 65 |
for node in qa_config.get('nodes'): |
62 | 66 |
if node != master: |
63 |
_NodeAdd(node) |
|
67 |
_NodeAdd(node, readd=False)
|
|
64 | 68 |
|
65 | 69 |
|
66 | 70 |
def TestNodeRemoveAll(): |
... | ... | |
71 | 75 |
_NodeRemove(node) |
72 | 76 |
|
73 | 77 |
|
78 |
@qa_utils.DefineHook('node-readd') |
|
79 |
def TestNodeReadd(node): |
|
80 |
"""gnt-node add --readd""" |
|
81 |
_NodeAdd(node, readd=True) |
|
82 |
|
|
83 |
|
|
74 | 84 |
@qa_utils.DefineHook('node-info') |
75 | 85 |
def TestNodeInfo(): |
76 | 86 |
"""gnt-node info""" |
b/scripts/gnt-node | ||
---|---|---|
1 | 1 |
#!/usr/bin/python |
2 | 2 |
# |
3 | 3 |
|
4 |
# Copyright (C) 2006, 2007 Google Inc. |
|
4 |
# Copyright (C) 2006, 2007, 2008 Google Inc.
|
|
5 | 5 |
# |
6 | 6 |
# This program is free software; you can redistribute it and/or modify |
7 | 7 |
# it under the terms of the GNU General Public License as published by |
... | ... | |
36 | 36 |
"Performing this operation is going to replace the ssh daemon keypair\n" |
37 | 37 |
"on the target machine (%s) with the ones of the current one\n" |
38 | 38 |
"and grant full intra-cluster ssh root access to/from it\n" % args[0]) |
39 |
op = opcodes.OpAddNode(node_name=args[0], secondary_ip=opts.secondary_ip) |
|
39 |
op = opcodes.OpAddNode(node_name=args[0], secondary_ip=opts.secondary_ip, |
|
40 |
readd=opts.readd) |
|
40 | 41 |
SubmitOpCode(op) |
41 | 42 |
|
42 | 43 |
|
... | ... | |
279 | 280 |
[DEBUG_OPT, |
280 | 281 |
make_option("-s", "--secondary-ip", dest="secondary_ip", |
281 | 282 |
help="Specify the secondary ip for the node", |
282 |
metavar="ADDRESS", default=None),], |
|
283 |
metavar="ADDRESS", default=None), |
|
284 |
make_option("--readd", dest="readd", |
|
285 |
default=False, action="store_true", |
|
286 |
help="Readd old node after replacing it"), |
|
287 |
], |
|
283 | 288 |
"[-s ip] <node_name>", "Add a node to the cluster"), |
284 | 289 |
'evacuate': (EvacuateNode, ARGS_FIXED(2), |
285 | 290 |
[DEBUG_OPT, FORCE_OPT], |
Also available in: Unified diff