|
|
15f218 |
From 32d9dde2936b9f8b690ce3dd6c9bdc685f3ac5f0 Mon Sep 17 00:00:00 2001
|
|
|
15f218 |
From: Tomas Jelinek <tojeline@redhat.com>
|
|
|
15f218 |
Date: Mon, 11 Jul 2016 15:19:30 +0200
|
|
|
15f218 |
Subject: [PATCH] cli: improve quorum device commands syntax
|
|
|
15f218 |
|
|
|
15f218 |
* add alias "pcs status quorum" to "pcs quorum status"
|
|
|
15f218 |
* add alias "pcs status qdevice" to "pcs qdevice status"
|
|
|
15f218 |
* add alias "pcs quorum" to "pcs quorum config"
|
|
|
15f218 |
---
|
|
|
15f218 |
pcs/cluster.py | 59 +++------------------------------------------------
|
|
|
15f218 |
pcs/pcs.8 | 8 ++++++-
|
|
|
15f218 |
pcs/quorum.py | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
|
|
|
15f218 |
pcs/status.py | 25 ++++++++++++++++++++++
|
|
|
15f218 |
pcs/usage.py | 10 ++++++++-
|
|
|
15f218 |
5 files changed, 106 insertions(+), 63 deletions(-)
|
|
|
15f218 |
|
|
|
15f218 |
diff --git a/pcs/cluster.py b/pcs/cluster.py
|
|
|
15f218 |
index 9d4798c..4155103 100644
|
|
|
15f218 |
--- a/pcs/cluster.py
|
|
|
15f218 |
+++ b/pcs/cluster.py
|
|
|
15f218 |
@@ -26,7 +26,7 @@ from pcs import (
|
|
|
15f218 |
constraint,
|
|
|
15f218 |
node,
|
|
|
15f218 |
pcsd,
|
|
|
15f218 |
- prop,
|
|
|
15f218 |
+ quorum,
|
|
|
15f218 |
resource,
|
|
|
15f218 |
settings,
|
|
|
15f218 |
status,
|
|
|
15f218 |
@@ -143,9 +143,9 @@ def cluster_cmd(argv):
|
|
|
15f218 |
cluster_report(argv)
|
|
|
15f218 |
elif (sub_cmd == "quorum"):
|
|
|
15f218 |
if argv and argv[0] == "unblock":
|
|
|
15f218 |
- cluster_quorum_unblock(argv[1:])
|
|
|
15f218 |
+ quorum.quorum_unblock_cmd(argv[1:])
|
|
|
15f218 |
else:
|
|
|
15f218 |
- usage.cluster(["quorum"])
|
|
|
15f218 |
+ usage.cluster()
|
|
|
15f218 |
sys.exit(1)
|
|
|
15f218 |
else:
|
|
|
15f218 |
usage.cluster()
|
|
|
15f218 |
@@ -1890,56 +1890,3 @@ def cluster_remote_node(argv):
|
|
|
15f218 |
usage.cluster(["remote-node"])
|
|
|
15f218 |
sys.exit(1)
|
|
|
15f218 |
|
|
|
15f218 |
-def cluster_quorum_unblock(argv):
|
|
|
15f218 |
- if len(argv) > 0:
|
|
|
15f218 |
- usage.quorum(["unblock"])
|
|
|
15f218 |
- sys.exit(1)
|
|
|
15f218 |
-
|
|
|
15f218 |
- if utils.is_rhel6():
|
|
|
15f218 |
- utils.err("operation is not supported on CMAN clusters")
|
|
|
15f218 |
-
|
|
|
15f218 |
- output, retval = utils.run(
|
|
|
15f218 |
- ["corosync-cmapctl", "-g", "runtime.votequorum.wait_for_all_status"]
|
|
|
15f218 |
- )
|
|
|
15f218 |
- if retval != 0:
|
|
|
15f218 |
- utils.err("unable to check quorum status")
|
|
|
15f218 |
- if output.split("=")[-1].strip() != "1":
|
|
|
15f218 |
- utils.err("cluster is not waiting for nodes to establish quorum")
|
|
|
15f218 |
-
|
|
|
15f218 |
- unjoined_nodes = (
|
|
|
15f218 |
- set(utils.getNodesFromCorosyncConf())
|
|
|
15f218 |
- -
|
|
|
15f218 |
- set(utils.getCorosyncActiveNodes())
|
|
|
15f218 |
- )
|
|
|
15f218 |
- if not unjoined_nodes:
|
|
|
15f218 |
- utils.err("no unjoined nodes found")
|
|
|
15f218 |
- if "--force" not in utils.pcs_options:
|
|
|
15f218 |
- answer = utils.get_terminal_input(
|
|
|
15f218 |
- (
|
|
|
15f218 |
- "WARNING: If node(s) {nodes} are not powered off or they do"
|
|
|
15f218 |
- + " have access to shared resources, data corruption and/or"
|
|
|
15f218 |
- + " cluster failure may occur. Are you sure you want to"
|
|
|
15f218 |
- + " continue? [y/N] "
|
|
|
15f218 |
- ).format(nodes=", ".join(unjoined_nodes))
|
|
|
15f218 |
- )
|
|
|
15f218 |
- if answer.lower() not in ["y", "yes"]:
|
|
|
15f218 |
- print("Canceled")
|
|
|
15f218 |
- return
|
|
|
15f218 |
- for node in unjoined_nodes:
|
|
|
15f218 |
- stonith.stonith_confirm([node], skip_question=True)
|
|
|
15f218 |
-
|
|
|
15f218 |
- output, retval = utils.run(
|
|
|
15f218 |
- ["corosync-cmapctl", "-s", "quorum.cancel_wait_for_all", "u8", "1"]
|
|
|
15f218 |
- )
|
|
|
15f218 |
- if retval != 0:
|
|
|
15f218 |
- utils.err("unable to cancel waiting for nodes")
|
|
|
15f218 |
- print("Quorum unblocked")
|
|
|
15f218 |
-
|
|
|
15f218 |
- startup_fencing = prop.get_set_properties().get("startup-fencing", "")
|
|
|
15f218 |
- utils.set_cib_property(
|
|
|
15f218 |
- "startup-fencing",
|
|
|
15f218 |
- "false" if startup_fencing.lower() != "false" else "true"
|
|
|
15f218 |
- )
|
|
|
15f218 |
- utils.set_cib_property("startup-fencing", startup_fencing)
|
|
|
15f218 |
- print("Waiting for nodes canceled")
|
|
|
15f218 |
-
|
|
|
15f218 |
diff --git a/pcs/pcs.8 b/pcs/pcs.8
|
|
|
15f218 |
index 223ef1b..a26c94b 100644
|
|
|
15f218 |
--- a/pcs/pcs.8
|
|
|
15f218 |
+++ b/pcs/pcs.8
|
|
|
15f218 |
@@ -543,7 +543,7 @@ disable <device model>
|
|
|
15f218 |
Configure specified model of quorum device provider to not start on boot.
|
|
|
15f218 |
.SS "quorum"
|
|
|
15f218 |
.TP
|
|
|
15f218 |
-config
|
|
|
15f218 |
+[config]
|
|
|
15f218 |
Show quorum configuration.
|
|
|
15f218 |
.TP
|
|
|
15f218 |
status
|
|
|
15f218 |
@@ -590,6 +590,12 @@ View current cluster status.
|
|
|
15f218 |
corosync
|
|
|
15f218 |
View current membership information as seen by corosync.
|
|
|
15f218 |
.TP
|
|
|
15f218 |
+quorum
|
|
|
15f218 |
+View current quorum status.
|
|
|
15f218 |
+.TP
|
|
|
15f218 |
+qdevice <device model> [\fB\-\-full\fR] [<cluster name>]
|
|
|
15f218 |
+Show runtime status of specified model of quorum device provider. Using \fB\-\-full\fR will give more detailed output. If <cluster name> is specified, only information about the specified cluster will be displayed.
|
|
|
15f218 |
+.TP
|
|
|
15f218 |
nodes [corosync|both|config]
|
|
|
15f218 |
View current status of nodes from pacemaker. If 'corosync' is specified, print nodes currently configured in corosync, if 'both' is specified, print nodes from both corosync & pacemaker. If 'config' is specified, print nodes from corosync & pacemaker configuration.
|
|
|
15f218 |
.TP
|
|
|
15f218 |
diff --git a/pcs/quorum.py b/pcs/quorum.py
|
|
|
15f218 |
index 2d54ed7..a849282 100644
|
|
|
15f218 |
--- a/pcs/quorum.py
|
|
|
15f218 |
+++ b/pcs/quorum.py
|
|
|
15f218 |
@@ -8,10 +8,11 @@ from __future__ import (
|
|
|
15f218 |
import sys
|
|
|
15f218 |
|
|
|
15f218 |
from pcs import (
|
|
|
15f218 |
+ prop,
|
|
|
15f218 |
+ stonith,
|
|
|
15f218 |
usage,
|
|
|
15f218 |
utils,
|
|
|
15f218 |
)
|
|
|
15f218 |
-from pcs.cluster import cluster_quorum_unblock
|
|
|
15f218 |
from pcs.cli.common import parse_args
|
|
|
15f218 |
from pcs.cli.common.console_report import indent
|
|
|
15f218 |
from pcs.cli.common.errors import CmdLineInputError
|
|
|
15f218 |
@@ -19,10 +20,10 @@ from pcs.lib.errors import LibraryError
|
|
|
15f218 |
|
|
|
15f218 |
def quorum_cmd(lib, argv, modificators):
|
|
|
15f218 |
if len(argv) < 1:
|
|
|
15f218 |
- usage.quorum()
|
|
|
15f218 |
- sys.exit(1)
|
|
|
15f218 |
+ sub_cmd, argv_next = "config", []
|
|
|
15f218 |
+ else:
|
|
|
15f218 |
+ sub_cmd, argv_next = argv[0], argv[1:]
|
|
|
15f218 |
|
|
|
15f218 |
- sub_cmd, argv_next = argv[0], argv[1:]
|
|
|
15f218 |
try:
|
|
|
15f218 |
if sub_cmd == "help":
|
|
|
15f218 |
usage.quorum(argv)
|
|
|
15f218 |
@@ -35,7 +36,8 @@ def quorum_cmd(lib, argv, modificators):
|
|
|
15f218 |
elif sub_cmd == "device":
|
|
|
15f218 |
quorum_device_cmd(lib, argv_next, modificators)
|
|
|
15f218 |
elif sub_cmd == "unblock":
|
|
|
15f218 |
- cluster_quorum_unblock(argv_next)
|
|
|
15f218 |
+ # TODO switch to new architecture
|
|
|
15f218 |
+ quorum_unblock_cmd(argv_next)
|
|
|
15f218 |
elif sub_cmd == "update":
|
|
|
15f218 |
quorum_update_cmd(lib, argv_next, modificators)
|
|
|
15f218 |
else:
|
|
|
15f218 |
@@ -185,3 +187,58 @@ def quorum_device_update_cmd(lib, argv, modificators):
|
|
|
15f218 |
force_options=modificators["force"],
|
|
|
15f218 |
skip_offline_nodes=modificators["skip_offline_nodes"]
|
|
|
15f218 |
)
|
|
|
15f218 |
+
|
|
|
15f218 |
+# TODO switch to new architecture, move to lib
|
|
|
15f218 |
+def quorum_unblock_cmd(argv):
|
|
|
15f218 |
+ if len(argv) > 0:
|
|
|
15f218 |
+ usage.quorum(["unblock"])
|
|
|
15f218 |
+ sys.exit(1)
|
|
|
15f218 |
+
|
|
|
15f218 |
+ if utils.is_rhel6():
|
|
|
15f218 |
+ utils.err("operation is not supported on CMAN clusters")
|
|
|
15f218 |
+
|
|
|
15f218 |
+ output, retval = utils.run(
|
|
|
15f218 |
+ ["corosync-cmapctl", "-g", "runtime.votequorum.wait_for_all_status"]
|
|
|
15f218 |
+ )
|
|
|
15f218 |
+ if retval != 0:
|
|
|
15f218 |
+ utils.err("unable to check quorum status")
|
|
|
15f218 |
+ if output.split("=")[-1].strip() != "1":
|
|
|
15f218 |
+ utils.err("cluster is not waiting for nodes to establish quorum")
|
|
|
15f218 |
+
|
|
|
15f218 |
+ unjoined_nodes = (
|
|
|
15f218 |
+ set(utils.getNodesFromCorosyncConf())
|
|
|
15f218 |
+ -
|
|
|
15f218 |
+ set(utils.getCorosyncActiveNodes())
|
|
|
15f218 |
+ )
|
|
|
15f218 |
+ if not unjoined_nodes:
|
|
|
15f218 |
+ utils.err("no unjoined nodes found")
|
|
|
15f218 |
+ if "--force" not in utils.pcs_options:
|
|
|
15f218 |
+ answer = utils.get_terminal_input(
|
|
|
15f218 |
+ (
|
|
|
15f218 |
+ "WARNING: If node(s) {nodes} are not powered off or they do"
|
|
|
15f218 |
+ + " have access to shared resources, data corruption and/or"
|
|
|
15f218 |
+ + " cluster failure may occur. Are you sure you want to"
|
|
|
15f218 |
+ + " continue? [y/N] "
|
|
|
15f218 |
+ ).format(nodes=", ".join(unjoined_nodes))
|
|
|
15f218 |
+ )
|
|
|
15f218 |
+ if answer.lower() not in ["y", "yes"]:
|
|
|
15f218 |
+ print("Canceled")
|
|
|
15f218 |
+ return
|
|
|
15f218 |
+ for node in unjoined_nodes:
|
|
|
15f218 |
+ stonith.stonith_confirm([node], skip_question=True)
|
|
|
15f218 |
+
|
|
|
15f218 |
+ output, retval = utils.run(
|
|
|
15f218 |
+ ["corosync-cmapctl", "-s", "quorum.cancel_wait_for_all", "u8", "1"]
|
|
|
15f218 |
+ )
|
|
|
15f218 |
+ if retval != 0:
|
|
|
15f218 |
+ utils.err("unable to cancel waiting for nodes")
|
|
|
15f218 |
+ print("Quorum unblocked")
|
|
|
15f218 |
+
|
|
|
15f218 |
+ startup_fencing = prop.get_set_properties().get("startup-fencing", "")
|
|
|
15f218 |
+ utils.set_cib_property(
|
|
|
15f218 |
+ "startup-fencing",
|
|
|
15f218 |
+ "false" if startup_fencing.lower() != "false" else "true"
|
|
|
15f218 |
+ )
|
|
|
15f218 |
+ utils.set_cib_property("startup-fencing", startup_fencing)
|
|
|
15f218 |
+ print("Waiting for nodes canceled")
|
|
|
15f218 |
+
|
|
|
15f218 |
diff --git a/pcs/status.py b/pcs/status.py
|
|
|
15f218 |
index e1f367f..bdfcc85 100644
|
|
|
15f218 |
--- a/pcs/status.py
|
|
|
15f218 |
+++ b/pcs/status.py
|
|
|
15f218 |
@@ -13,6 +13,9 @@ from pcs import (
|
|
|
15f218 |
usage,
|
|
|
15f218 |
utils,
|
|
|
15f218 |
)
|
|
|
15f218 |
+from pcs.qdevice import qdevice_status_cmd
|
|
|
15f218 |
+from pcs.quorum import quorum_status_cmd
|
|
|
15f218 |
+from pcs.cli.common.errors import CmdLineInputError
|
|
|
15f218 |
from pcs.lib.errors import LibraryError
|
|
|
15f218 |
from pcs.lib.pacemaker_state import ClusterState
|
|
|
15f218 |
|
|
|
15f218 |
@@ -38,6 +41,28 @@ def status_cmd(argv):
|
|
|
15f218 |
xml_status()
|
|
|
15f218 |
elif (sub_cmd == "corosync"):
|
|
|
15f218 |
corosync_status()
|
|
|
15f218 |
+ elif sub_cmd == "qdevice":
|
|
|
15f218 |
+ try:
|
|
|
15f218 |
+ qdevice_status_cmd(
|
|
|
15f218 |
+ utils.get_library_wrapper(),
|
|
|
15f218 |
+ argv,
|
|
|
15f218 |
+ utils.get_modificators()
|
|
|
15f218 |
+ )
|
|
|
15f218 |
+ except LibraryError as e:
|
|
|
15f218 |
+ utils.process_library_reports(e.args)
|
|
|
15f218 |
+ except CmdLineInputError as e:
|
|
|
15f218 |
+ utils.exit_on_cmdline_input_errror(e, "status", sub_cmd)
|
|
|
15f218 |
+ elif sub_cmd == "quorum":
|
|
|
15f218 |
+ try:
|
|
|
15f218 |
+ quorum_status_cmd(
|
|
|
15f218 |
+ utils.get_library_wrapper(),
|
|
|
15f218 |
+ argv,
|
|
|
15f218 |
+ utils.get_modificators()
|
|
|
15f218 |
+ )
|
|
|
15f218 |
+ except LibraryError as e:
|
|
|
15f218 |
+ utils.process_library_reports(e.args)
|
|
|
15f218 |
+ except CmdLineInputError as e:
|
|
|
15f218 |
+ utils.exit_on_cmdline_input_errror(e, "status", sub_cmd)
|
|
|
15f218 |
else:
|
|
|
15f218 |
usage.status()
|
|
|
15f218 |
sys.exit(1)
|
|
|
15f218 |
diff --git a/pcs/usage.py b/pcs/usage.py
|
|
|
15f218 |
index 77b496e..0605cd7 100644
|
|
|
15f218 |
--- a/pcs/usage.py
|
|
|
15f218 |
+++ b/pcs/usage.py
|
|
|
15f218 |
@@ -1118,6 +1118,14 @@ Commands:
|
|
|
15f218 |
corosync
|
|
|
15f218 |
View current membership information as seen by corosync.
|
|
|
15f218 |
|
|
|
15f218 |
+ quorum
|
|
|
15f218 |
+ View current quorum status.
|
|
|
15f218 |
+
|
|
|
15f218 |
+ qdevice <device model> [--full] [<cluster name>]
|
|
|
15f218 |
+ Show runtime status of specified model of quorum device provider. Using
|
|
|
15f218 |
+ --full will give more detailed output. If <cluster name> is specified,
|
|
|
15f218 |
+ only information about the specified cluster will be displayed.
|
|
|
15f218 |
+
|
|
|
15f218 |
nodes [corosync|both|config]
|
|
|
15f218 |
View current status of nodes from pacemaker. If 'corosync' is
|
|
|
15f218 |
specified, print nodes currently configured in corosync, if 'both'
|
|
|
15f218 |
@@ -1322,7 +1330,7 @@ Usage: pcs quorum <command>
|
|
|
15f218 |
Manage cluster quorum settings.
|
|
|
15f218 |
|
|
|
15f218 |
Commands:
|
|
|
15f218 |
- config
|
|
|
15f218 |
+ [config]
|
|
|
15f218 |
Show quorum configuration.
|
|
|
15f218 |
|
|
|
15f218 |
status
|
|
|
15f218 |
--
|
|
|
15f218 |
1.8.3.1
|
|
|
15f218 |
|