Revision c06e0c83
b/lib/backend.py | ||
---|---|---|
246 | 246 |
return (master_netdev, master_ip, master_node, primary_ip_family) |
247 | 247 |
|
248 | 248 |
|
249 |
def StartMaster(start_daemons, no_voting): |
|
249 |
def ActivateMasterIp(): |
|
250 |
"""Activate the IP address of the master daemon. |
|
251 |
|
|
252 |
""" |
|
253 |
# GetMasterInfo will raise an exception if not able to return data |
|
254 |
master_netdev, master_ip, _, family = GetMasterInfo() |
|
255 |
|
|
256 |
err_msg = None |
|
257 |
if netutils.TcpPing(master_ip, constants.DEFAULT_NODED_PORT): |
|
258 |
if netutils.IPAddress.Own(master_ip): |
|
259 |
# we already have the ip: |
|
260 |
logging.debug("Master IP already configured, doing nothing") |
|
261 |
else: |
|
262 |
err_msg = "Someone else has the master ip, not activating" |
|
263 |
logging.error(err_msg) |
|
264 |
else: |
|
265 |
ipcls = netutils.IP4Address |
|
266 |
if family == netutils.IP6Address.family: |
|
267 |
ipcls = netutils.IP6Address |
|
268 |
|
|
269 |
result = utils.RunCmd([constants.IP_COMMAND_PATH, "address", "add", |
|
270 |
"%s/%d" % (master_ip, ipcls.iplen), |
|
271 |
"dev", master_netdev, "label", |
|
272 |
"%s:0" % master_netdev]) |
|
273 |
if result.failed: |
|
274 |
err_msg = "Can't activate master IP: %s" % result.output |
|
275 |
logging.error(err_msg) |
|
276 |
|
|
277 |
# we ignore the exit code of the following cmds |
|
278 |
if ipcls == netutils.IP4Address: |
|
279 |
utils.RunCmd(["arping", "-q", "-U", "-c 3", "-I", master_netdev, "-s", |
|
280 |
master_ip, master_ip]) |
|
281 |
elif ipcls == netutils.IP6Address: |
|
282 |
try: |
|
283 |
utils.RunCmd(["ndisc6", "-q", "-r 3", master_ip, master_netdev]) |
|
284 |
except errors.OpExecError: |
|
285 |
# TODO: Better error reporting |
|
286 |
logging.warning("Can't execute ndisc6, please install if missing") |
|
287 |
|
|
288 |
if err_msg: |
|
289 |
_Fail(err_msg) |
|
290 |
|
|
291 |
|
|
292 |
def StartMasterDaemons(no_voting): |
|
250 | 293 |
"""Activate local node as master node. |
251 | 294 |
|
252 |
The function will either try activate the IP address of the master |
|
253 |
(unless someone else has it) or also start the master daemons, based |
|
254 |
on the start_daemons parameter. |
|
295 |
The function will start the master daemons (ganeti-masterd and ganeti-rapi). |
|
255 | 296 |
|
256 |
@type start_daemons: boolean |
|
257 |
@param start_daemons: whether to start the master daemons |
|
258 |
(ganeti-masterd and ganeti-rapi), or (if false) activate the |
|
259 |
master ip |
|
260 | 297 |
@type no_voting: boolean |
261 | 298 |
@param no_voting: whether to start ganeti-masterd without a node vote |
262 |
(if start_daemons is True), but still non-interactively
|
|
299 |
but still non-interactively |
|
263 | 300 |
@rtype: None |
264 | 301 |
|
265 | 302 |
""" |
266 |
# GetMasterInfo will raise an exception if not able to return data |
|
267 |
master_netdev, master_ip, _, family = GetMasterInfo() |
|
268 | 303 |
|
269 |
err_msgs = [] |
|
270 |
# either start the master and rapi daemons |
|
271 |
if start_daemons: |
|
272 |
if no_voting: |
|
273 |
masterd_args = "--no-voting --yes-do-it" |
|
274 |
else: |
|
275 |
masterd_args = "" |
|
276 |
|
|
277 |
env = { |
|
278 |
"EXTRA_MASTERD_ARGS": masterd_args, |
|
279 |
} |
|
280 |
|
|
281 |
result = utils.RunCmd([constants.DAEMON_UTIL, "start-master"], env=env) |
|
282 |
if result.failed: |
|
283 |
msg = "Can't start Ganeti master: %s" % result.output |
|
284 |
logging.error(msg) |
|
285 |
err_msgs.append(msg) |
|
286 |
# or activate the IP |
|
304 |
if no_voting: |
|
305 |
masterd_args = "--no-voting --yes-do-it" |
|
287 | 306 |
else: |
288 |
if netutils.TcpPing(master_ip, constants.DEFAULT_NODED_PORT): |
|
289 |
if netutils.IPAddress.Own(master_ip): |
|
290 |
# we already have the ip: |
|
291 |
logging.debug("Master IP already configured, doing nothing") |
|
292 |
else: |
|
293 |
msg = "Someone else has the master ip, not activating" |
|
294 |
logging.error(msg) |
|
295 |
err_msgs.append(msg) |
|
296 |
else: |
|
297 |
ipcls = netutils.IP4Address |
|
298 |
if family == netutils.IP6Address.family: |
|
299 |
ipcls = netutils.IP6Address |
|
300 |
|
|
301 |
result = utils.RunCmd([constants.IP_COMMAND_PATH, "address", "add", |
|
302 |
"%s/%d" % (master_ip, ipcls.iplen), |
|
303 |
"dev", master_netdev, "label", |
|
304 |
"%s:0" % master_netdev]) |
|
305 |
if result.failed: |
|
306 |
msg = "Can't activate master IP: %s" % result.output |
|
307 |
logging.error(msg) |
|
308 |
err_msgs.append(msg) |
|
309 |
|
|
310 |
# we ignore the exit code of the following cmds |
|
311 |
if ipcls == netutils.IP4Address: |
|
312 |
utils.RunCmd(["arping", "-q", "-U", "-c 3", "-I", master_netdev, "-s", |
|
313 |
master_ip, master_ip]) |
|
314 |
elif ipcls == netutils.IP6Address: |
|
315 |
try: |
|
316 |
utils.RunCmd(["ndisc6", "-q", "-r 3", master_ip, master_netdev]) |
|
317 |
except errors.OpExecError: |
|
318 |
# TODO: Better error reporting |
|
319 |
logging.warning("Can't execute ndisc6, please install if missing") |
|
320 |
|
|
321 |
if err_msgs: |
|
322 |
_Fail("; ".join(err_msgs)) |
|
307 |
masterd_args = "" |
|
323 | 308 |
|
309 |
env = { |
|
310 |
"EXTRA_MASTERD_ARGS": masterd_args, |
|
311 |
} |
|
324 | 312 |
|
325 |
def StopMaster(stop_daemons): |
|
326 |
"""Deactivate this node as master. |
|
313 |
result = utils.RunCmd([constants.DAEMON_UTIL, "start-master"], env=env) |
|
314 |
if result.failed: |
|
315 |
msg = "Can't start Ganeti master: %s" % result.output |
|
316 |
logging.error(msg) |
|
317 |
_Fail(msg) |
|
327 | 318 |
|
328 |
The function will always try to deactivate the IP address of the |
|
329 |
master. It will also stop the master daemons depending on the |
|
330 |
stop_daemons parameter. |
|
331 | 319 |
|
332 |
@type stop_daemons: boolean |
|
333 |
@param stop_daemons: whether to also stop the master daemons |
|
334 |
(ganeti-masterd and ganeti-rapi) |
|
335 |
@rtype: None |
|
320 |
def DeactivateMasterIp(): |
|
321 |
"""Deactivate the master IP on this node. |
|
336 | 322 |
|
337 | 323 |
""" |
338 | 324 |
# TODO: log and report back to the caller the error failures; we |
... | ... | |
352 | 338 |
logging.error("Can't remove the master IP, error: %s", result.output) |
353 | 339 |
# but otherwise ignore the failure |
354 | 340 |
|
355 |
if stop_daemons: |
|
356 |
result = utils.RunCmd([constants.DAEMON_UTIL, "stop-master"]) |
|
357 |
if result.failed: |
|
358 |
logging.error("Could not stop Ganeti master, command %s had exitcode %s" |
|
359 |
" and error %s", |
|
360 |
result.cmd, result.exit_code, result.output) |
|
341 |
|
|
342 |
def StopMasterDaemons(): |
|
343 |
"""Stop the master daemons on this node. |
|
344 |
|
|
345 |
Stop the master daemons (ganeti-masterd and ganeti-rapi) on this node. |
|
346 |
|
|
347 |
@rtype: None |
|
348 |
|
|
349 |
""" |
|
350 |
# TODO: log and report back to the caller the error failures; we |
|
351 |
# need to decide in which case we fail the RPC for this |
|
352 |
|
|
353 |
result = utils.RunCmd([constants.DAEMON_UTIL, "stop-master"]) |
|
354 |
if result.failed: |
|
355 |
logging.error("Could not stop Ganeti master, command %s had exitcode %s" |
|
356 |
" and error %s", |
|
357 |
result.cmd, result.exit_code, result.output) |
|
361 | 358 |
|
362 | 359 |
|
363 | 360 |
def EtcHostsModify(mode, host, ip): |
b/lib/bootstrap.py | ||
---|---|---|
560 | 560 |
""" |
561 | 561 |
cfg = config.ConfigWriter() |
562 | 562 |
modify_ssh_setup = cfg.GetClusterInfo().modify_ssh_setup |
563 |
result = rpc.RpcRunner.call_node_stop_master(master, True)
|
|
563 |
result = rpc.RpcRunner.call_node_stop_master(master) |
|
564 | 564 |
msg = result.fail_msg |
565 | 565 |
if msg: |
566 | 566 |
logging.warning("Could not disable the master role: %s", msg) |
... | ... | |
692 | 692 |
|
693 | 693 |
logging.info("Stopping the master daemon on node %s", old_master) |
694 | 694 |
|
695 |
result = rpc.RpcRunner.call_node_stop_master(old_master, True)
|
|
695 |
result = rpc.RpcRunner.call_node_stop_master(old_master) |
|
696 | 696 |
msg = result.fail_msg |
697 | 697 |
if msg: |
698 | 698 |
logging.error("Could not disable the master role on the old master" |
... | ... | |
721 | 721 |
|
722 | 722 |
logging.info("Starting the master daemons on the new master") |
723 | 723 |
|
724 |
result = rpc.RpcRunner.call_node_start_master(new_master, True, no_voting)
|
|
724 |
result = rpc.RpcRunner.call_node_start_master_daemons(new_master, no_voting)
|
|
725 | 725 |
msg = result.fail_msg |
726 | 726 |
if msg: |
727 | 727 |
logging.error("Could not start the master role on the new master" |
b/lib/cmdlib.py | ||
---|---|---|
1355 | 1355 |
# Run post hooks on master node before it's removed |
1356 | 1356 |
_RunPostHook(self, master) |
1357 | 1357 |
|
1358 |
result = self.rpc.call_node_stop_master(master, False)
|
|
1358 |
result = self.rpc.call_node_deactivate_master_ip(master)
|
|
1359 | 1359 |
result.Raise("Could not disable the master role") |
1360 | 1360 |
|
1361 | 1361 |
return master |
... | ... | |
3297 | 3297 |
|
3298 | 3298 |
# shutdown the master IP |
3299 | 3299 |
master = self.cfg.GetMasterNode() |
3300 |
result = self.rpc.call_node_stop_master(master, False)
|
|
3300 |
result = self.rpc.call_node_deactivate_master_ip(master)
|
|
3301 | 3301 |
result.Raise("Could not disable the master role") |
3302 | 3302 |
|
3303 | 3303 |
try: |
... | ... | |
3315 | 3315 |
pass |
3316 | 3316 |
_UploadHelper(self, node_list, constants.SSH_KNOWN_HOSTS_FILE) |
3317 | 3317 |
finally: |
3318 |
result = self.rpc.call_node_start_master(master, False, False)
|
|
3318 |
result = self.rpc.call_node_activate_master_ip(master)
|
|
3319 | 3319 |
msg = result.fail_msg |
3320 | 3320 |
if msg: |
3321 | 3321 |
self.LogWarning("Could not re-enable the master role on" |
... | ... | |
3648 | 3648 |
master = self.cfg.GetMasterNode() |
3649 | 3649 |
feedback_fn("Shutting down master ip on the current netdev (%s)" % |
3650 | 3650 |
self.cluster.master_netdev) |
3651 |
result = self.rpc.call_node_stop_master(master, False)
|
|
3651 |
result = self.rpc.call_node_deactivate_master_ip(master)
|
|
3652 | 3652 |
result.Raise("Could not disable the master ip") |
3653 | 3653 |
feedback_fn("Changing master_netdev from %s to %s" % |
3654 | 3654 |
(self.cluster.master_netdev, self.op.master_netdev)) |
... | ... | |
3659 | 3659 |
if self.op.master_netdev: |
3660 | 3660 |
feedback_fn("Starting the master ip on the new master netdev (%s)" % |
3661 | 3661 |
self.op.master_netdev) |
3662 |
result = self.rpc.call_node_start_master(master, False, False)
|
|
3662 |
result = self.rpc.call_node_activate_master_ip(master)
|
|
3663 | 3663 |
if result.fail_msg: |
3664 | 3664 |
self.LogWarning("Could not re-enable the master ip on" |
3665 | 3665 |
" the master, please restart manually: %s", |
b/lib/rpc.py | ||
---|---|---|
919 | 919 |
|
920 | 920 |
@classmethod |
921 | 921 |
@_RpcTimeout(_TMO_FAST) |
922 |
def call_node_start_master(cls, node, start_daemons, no_voting):
|
|
923 |
"""Tells a node to activate itself as a master.
|
|
922 |
def call_node_start_master_daemons(cls, node, no_voting):
|
|
923 |
"""Starts master daemons on a node.
|
|
924 | 924 |
|
925 | 925 |
This is a single-node call. |
926 | 926 |
|
927 | 927 |
""" |
928 |
return cls._StaticSingleNodeCall(node, "node_start_master", |
|
929 |
[start_daemons, no_voting])
|
|
928 |
return cls._StaticSingleNodeCall(node, "node_start_master_daemons",
|
|
929 |
[no_voting]) |
|
930 | 930 |
|
931 | 931 |
@classmethod |
932 | 932 |
@_RpcTimeout(_TMO_FAST) |
933 |
def call_node_stop_master(cls, node, stop_daemons):
|
|
934 |
"""Tells a node to demote itself from master status.
|
|
933 |
def call_node_activate_master_ip(cls, node):
|
|
934 |
"""Activates master IP on a node.
|
|
935 | 935 |
|
936 | 936 |
This is a single-node call. |
937 | 937 |
|
938 | 938 |
""" |
939 |
return cls._StaticSingleNodeCall(node, "node_stop_master", [stop_daemons]) |
|
939 |
return cls._StaticSingleNodeCall(node, "node_activate_master_ip", []) |
|
940 |
|
|
941 |
@classmethod |
|
942 |
@_RpcTimeout(_TMO_FAST) |
|
943 |
def call_node_stop_master(cls, node): |
|
944 |
"""Deactivates master IP and stops master daemons on a node. |
|
945 |
|
|
946 |
This is a single-node call. |
|
947 |
|
|
948 |
""" |
|
949 |
return cls._StaticSingleNodeCall(node, "node_stop_master", []) |
|
950 |
|
|
951 |
@classmethod |
|
952 |
@_RpcTimeout(_TMO_FAST) |
|
953 |
def call_node_deactivate_master_ip(cls, node): |
|
954 |
"""Deactivates master IP on a node. |
|
955 |
|
|
956 |
This is a single-node call. |
|
957 |
|
|
958 |
""" |
|
959 |
return cls._StaticSingleNodeCall(node, "node_deactivate_master_ip", []) |
|
940 | 960 |
|
941 | 961 |
@classmethod |
942 | 962 |
@_RpcTimeout(_TMO_URGENT) |
b/lib/server/masterd.py | ||
---|---|---|
524 | 524 |
def ActivateMasterIP(): |
525 | 525 |
# activate ip |
526 | 526 |
master_node = ssconf.SimpleStore().GetMasterNode() |
527 |
result = rpc.RpcRunner.call_node_start_master(master_node, False, False)
|
|
527 |
result = rpc.RpcRunner.call_node_activate_master_ip(master_node)
|
|
528 | 528 |
msg = result.fail_msg |
529 | 529 |
if msg: |
530 | 530 |
logging.error("Can't activate master IP address: %s", msg) |
b/lib/server/noded.py | ||
---|---|---|
677 | 677 |
return backend.VerifyNode(params[0], params[1]) |
678 | 678 |
|
679 | 679 |
@staticmethod |
680 |
def perspective_node_start_master(params): |
|
681 |
"""Promote this node to master status.
|
|
680 |
def perspective_node_start_master_daemons(params):
|
|
681 |
"""Start the master daemons on this node.
|
|
682 | 682 |
|
683 | 683 |
""" |
684 |
return backend.StartMaster(params[0], params[1]) |
|
684 |
return backend.StartMasterDaemons(params[0]) |
|
685 |
|
|
686 |
@staticmethod |
|
687 |
def perspective_node_activate_master_ip(params): |
|
688 |
"""Activate the master IP on this node. |
|
689 |
|
|
690 |
""" |
|
691 |
return backend.ActivateMasterIp() |
|
692 |
|
|
693 |
@staticmethod |
|
694 |
def perspective_node_deactivate_master_ip(params): |
|
695 |
"""Deactivate the master IP on this node. |
|
696 |
|
|
697 |
""" |
|
698 |
return backend.DeactivateMasterIp() |
|
685 | 699 |
|
686 | 700 |
@staticmethod |
687 | 701 |
def perspective_node_stop_master(params): |
688 |
"""Demote this node from master status. |
|
702 |
"""Deactivate the master IP and stops master daemons on this node. |
|
703 |
|
|
704 |
Sometimes both operations need to be executed at the same time (doing one of |
|
705 |
the two would make impossible to do the other one). |
|
689 | 706 |
|
690 | 707 |
""" |
691 |
return backend.StopMaster(params[0]) |
|
708 |
backend.DeactivateMasterIp() |
|
709 |
return backend.StopMasterDaemons() |
|
692 | 710 |
|
693 | 711 |
@staticmethod |
694 | 712 |
def perspective_node_leave_cluster(params): |
Also available in: Unified diff