Revision fb460cf7
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 | ||
---|---|---|
944 | 944 |
|
945 | 945 |
@classmethod |
946 | 946 |
@_RpcTimeout(_TMO_FAST) |
947 |
def call_node_start_master(cls, node, start_daemons, no_voting):
|
|
948 |
"""Tells a node to activate itself as a master.
|
|
947 |
def call_node_start_master_daemons(cls, node, no_voting):
|
|
948 |
"""Starts master daemons on a node.
|
|
949 | 949 |
|
950 | 950 |
This is a single-node call. |
951 | 951 |
|
952 | 952 |
""" |
953 |
return cls._StaticSingleNodeCall(node, "node_start_master", |
|
954 |
[start_daemons, no_voting])
|
|
953 |
return cls._StaticSingleNodeCall(node, "node_start_master_daemons",
|
|
954 |
[no_voting]) |
|
955 | 955 |
|
956 | 956 |
@classmethod |
957 | 957 |
@_RpcTimeout(_TMO_FAST) |
958 |
def call_node_stop_master(cls, node, stop_daemons):
|
|
959 |
"""Tells a node to demote itself from master status.
|
|
958 |
def call_node_activate_master_ip(cls, node):
|
|
959 |
"""Activates master IP on a node.
|
|
960 | 960 |
|
961 | 961 |
This is a single-node call. |
962 | 962 |
|
963 | 963 |
""" |
964 |
return cls._StaticSingleNodeCall(node, "node_stop_master", [stop_daemons]) |
|
964 |
return cls._StaticSingleNodeCall(node, "node_activate_master_ip", []) |
|
965 |
|
|
966 |
@classmethod |
|
967 |
@_RpcTimeout(_TMO_FAST) |
|
968 |
def call_node_stop_master(cls, node): |
|
969 |
"""Deactivates master IP and stops master daemons on a node. |
|
970 |
|
|
971 |
This is a single-node call. |
|
972 |
|
|
973 |
""" |
|
974 |
return cls._StaticSingleNodeCall(node, "node_stop_master", []) |
|
975 |
|
|
976 |
@classmethod |
|
977 |
@_RpcTimeout(_TMO_FAST) |
|
978 |
def call_node_deactivate_master_ip(cls, node): |
|
979 |
"""Deactivates master IP on a node. |
|
980 |
|
|
981 |
This is a single-node call. |
|
982 |
|
|
983 |
""" |
|
984 |
return cls._StaticSingleNodeCall(node, "node_deactivate_master_ip", []) |
|
965 | 985 |
|
966 | 986 |
@classmethod |
967 | 987 |
@_RpcTimeout(_TMO_URGENT) |
b/lib/server/masterd.py | ||
---|---|---|
527 | 527 |
def ActivateMasterIP(): |
528 | 528 |
# activate ip |
529 | 529 |
master_node = ssconf.SimpleStore().GetMasterNode() |
530 |
result = rpc.RpcRunner.call_node_start_master(master_node, False, False)
|
|
530 |
result = rpc.RpcRunner.call_node_activate_master_ip(master_node)
|
|
531 | 531 |
msg = result.fail_msg |
532 | 532 |
if msg: |
533 | 533 |
logging.error("Can't activate master IP address: %s", msg) |
b/lib/server/noded.py | ||
---|---|---|
694 | 694 |
return backend.VerifyNode(params[0], params[1]) |
695 | 695 |
|
696 | 696 |
@staticmethod |
697 |
def perspective_node_start_master(params): |
|
698 |
"""Promote this node to master status.
|
|
697 |
def perspective_node_start_master_daemons(params):
|
|
698 |
"""Start the master daemons on this node.
|
|
699 | 699 |
|
700 | 700 |
""" |
701 |
return backend.StartMaster(params[0], params[1]) |
|
701 |
return backend.StartMasterDaemons(params[0]) |
|
702 |
|
|
703 |
@staticmethod |
|
704 |
def perspective_node_activate_master_ip(params): |
|
705 |
"""Activate the master IP on this node. |
|
706 |
|
|
707 |
""" |
|
708 |
return backend.ActivateMasterIp() |
|
709 |
|
|
710 |
@staticmethod |
|
711 |
def perspective_node_deactivate_master_ip(params): |
|
712 |
"""Deactivate the master IP on this node. |
|
713 |
|
|
714 |
""" |
|
715 |
return backend.DeactivateMasterIp() |
|
702 | 716 |
|
703 | 717 |
@staticmethod |
704 | 718 |
def perspective_node_stop_master(params): |
705 |
"""Demote this node from master status. |
|
719 |
"""Deactivate the master IP and stops master daemons on this node. |
|
720 |
|
|
721 |
Sometimes both operations need to be executed at the same time (doing one of |
|
722 |
the two would make impossible to do the other one). |
|
706 | 723 |
|
707 | 724 |
""" |
708 |
return backend.StopMaster(params[0]) |
|
725 |
backend.DeactivateMasterIp() |
|
726 |
return backend.StopMasterDaemons() |
|
709 | 727 |
|
710 | 728 |
@staticmethod |
711 | 729 |
def perspective_node_leave_cluster(params): |
Also available in: Unified diff