From b8b59f772b2bbdb9728b32c674e69df851f82397 Mon Sep 17 00:00:00 2001
From: Ivan Devat <idevat@redhat.com>
Date: Tue, 30 May 2017 16:56:50 +0200
Subject: [PATCH] squash bz1176018 pcs/pcsd should be able to config
43aeca1 fix --skip-offline without effect problem
38de786 clean remote/guest node before pushing cib
---
pcs/cli/cluster/command.py | 15 +++++----
pcs/lib/commands/cluster.py | 65 ++++++++++++++++++++----------------
pcs/lib/nodes_task.py | 13 ++++++--
pcs/lib/test/test_nodes_task.py | 4 ---
pcs/test/test_cluster_pcmk_remote.py | 16 +++++----
5 files changed, 66 insertions(+), 47 deletions(-)
diff --git a/pcs/cli/cluster/command.py b/pcs/cli/cluster/command.py
index f725326..963bd8c 100644
--- a/pcs/cli/cluster/command.py
+++ b/pcs/cli/cluster/command.py
@@ -35,6 +35,7 @@ def node_add_remote(lib, arg_list, modifiers):
parts = parse_resource_create_args(rest_args)
force = modifiers["force"]
+ skip_offline = modifiers["skip_offline_nodes"]
lib.cluster.node_add_remote(
node_host,
@@ -42,8 +43,8 @@ def node_add_remote(lib, arg_list, modifiers):
parts["op"],
parts["meta"],
parts["options"],
- allow_incomplete_distribution=force,
- allow_pacemaker_remote_service_fail=force,
+ allow_incomplete_distribution=skip_offline,
+ allow_pacemaker_remote_service_fail=skip_offline,
allow_invalid_operation=force,
allow_invalid_instance_attributes=force,
use_default_operations=not modifiers["no-default-ops"],
@@ -58,7 +59,7 @@ def create_node_remove_remote(remove_resource):
arg_list[0],
remove_resource,
allow_remove_multiple_nodes=modifiers["force"],
- allow_pacemaker_remote_service_fail=modifiers["force"],
+ allow_pacemaker_remote_service_fail=modifiers["skip_offline_nodes"],
)
return node_remove_remote
@@ -71,14 +72,14 @@ def node_add_guest(lib, arg_list, modifiers):
resource_id = arg_list[1]
meta_options = prepare_options(arg_list[2:])
- force = modifiers["force"]
+ skip_offline = modifiers["skip_offline_nodes"]
lib.cluster.node_add_guest(
node_name,
resource_id,
meta_options,
- allow_incomplete_distribution=force,
- allow_pacemaker_remote_service_fail=force,
+ allow_incomplete_distribution=skip_offline,
+ allow_pacemaker_remote_service_fail=skip_offline,
wait=modifiers["wait"],
)
@@ -89,7 +90,7 @@ def node_remove_guest(lib, arg_list, modifiers):
lib.cluster.node_remove_guest(
arg_list[0],
allow_remove_multiple_nodes=modifiers["force"],
- allow_pacemaker_remote_service_fail=modifiers["force"],
+ allow_pacemaker_remote_service_fail=modifiers["skip_offline_nodes"],
wait=modifiers["wait"],
)
diff --git a/pcs/lib/commands/cluster.py b/pcs/lib/commands/cluster.py
index 0bafef5..fe883f3 100644
--- a/pcs/lib/commands/cluster.py
+++ b/pcs/lib/commands/cluster.py
@@ -21,13 +21,16 @@ from pcs.lib.errors import LibraryError
from pcs.lib.pacemaker import state
from pcs.lib.pacemaker.live import remove_node
-def _ensure_can_add_node_to_remote_cluster(env, node_addresses):
+def _ensure_can_add_node_to_remote_cluster(
+ env, node_addresses, warn_on_communication_exception=False
+):
report_items = []
nodes_task.check_can_add_node_to_cluster(
env.node_communicator(),
node_addresses,
report_items,
- check_response=nodes_task.availability_checker_remote_node
+ check_response=nodes_task.availability_checker_remote_node,
+ warn_on_communication_exception=warn_on_communication_exception,
)
env.report_processor.process_list(report_items)
@@ -88,7 +91,11 @@ def _prepare_pacemaker_remote_environment(
return
candidate_node = NodeAddresses(node_host)
- _ensure_can_add_node_to_remote_cluster(env, candidate_node)
+ _ensure_can_add_node_to_remote_cluster(
+ env,
+ candidate_node,
+ allow_incomplete_distribution
+ )
_share_authkey(
env,
current_nodes,
@@ -296,17 +303,13 @@ def _find_resources_to_remove(
return resource_element_list
-def _remove_pcmk_remote_from_cib(
- nodes, resource_element_list, get_host, remove_resource
-):
+def _get_node_addresses_from_resources(nodes, resource_element_list, get_host):
node_addresses_set = set()
for resource_element in resource_element_list:
for node in nodes:
#remote nodes uses ring0 only
if get_host(resource_element) == node.ring0:
node_addresses_set.add(node)
- remove_resource(resource_element)
-
return sorted(node_addresses_set, key=lambda node: node.ring0)
def _destroy_pcmk_remote_env(env, node_addresses_list, allow_fails):
@@ -382,28 +385,31 @@ def node_remove_remote(
allow_remove_multiple_nodes,
remote_node.find_node_resources,
)
- node_addresses_list = _remove_pcmk_remote_from_cib(
+
+ node_addresses_list = _get_node_addresses_from_resources(
get_nodes_remote(cib),
resource_element_list,
remote_node.get_host,
- lambda resource_element: remove_resource(
- resource_element.attrib["id"],
- is_remove_remote_context=True,
- )
)
+
if not env.is_corosync_conf_live:
env.report_processor.process_list(
_report_skip_live_parts_in_remove(node_addresses_list)
)
- return
+ else:
+ _destroy_pcmk_remote_env(
+ env,
+ node_addresses_list,
+ allow_pacemaker_remote_service_fail
+ )
#remove node from pcmk caches is currently integrated in remove_resource
#function
- _destroy_pcmk_remote_env(
- env,
- node_addresses_list,
- allow_pacemaker_remote_service_fail
- )
+ for resource_element in resource_element_list:
+ remove_resource(
+ resource_element.attrib["id"],
+ is_remove_remote_context=True,
+ )
def node_remove_guest(
env, node_identifier,
@@ -435,29 +441,32 @@ def node_remove_guest(
guest_node.find_node_resources,
)
- node_addresses_list = _remove_pcmk_remote_from_cib(
+ node_addresses_list = _get_node_addresses_from_resources(
get_nodes_guest(cib),
resource_element_list,
guest_node.get_host,
- guest_node.unset_guest,
)
- env.push_cib(cib, wait)
if not env.is_corosync_conf_live:
env.report_processor.process_list(
_report_skip_live_parts_in_remove(node_addresses_list)
)
- return
+ else:
+ _destroy_pcmk_remote_env(
+ env,
+ node_addresses_list,
+ allow_pacemaker_remote_service_fail
+ )
+
+ for resource_element in resource_element_list:
+ guest_node.unset_guest(resource_element)
+
+ env.push_cib(cib, wait)
#remove node from pcmk caches
for node_addresses in node_addresses_list:
remove_node(env.cmd_runner(), node_addresses.name)
- _destroy_pcmk_remote_env(
- env,
- node_addresses_list,
- allow_pacemaker_remote_service_fail
- )
def node_clear(env, node_name, allow_clear_cluster_node=False):
"""
diff --git a/pcs/lib/nodes_task.py b/pcs/lib/nodes_task.py
index 703609b..6086c4b 100644
--- a/pcs/lib/nodes_task.py
+++ b/pcs/lib/nodes_task.py
@@ -277,7 +277,8 @@ def availability_checker_remote_node(
def check_can_add_node_to_cluster(
node_communicator, node, report_items,
- check_response=availability_checker_node
+ check_response=availability_checker_node,
+ warn_on_communication_exception=False,
):
"""
Analyze result of node_available check if it is possible use the node as
@@ -294,13 +295,21 @@ def check_can_add_node_to_cluster(
node_communicator,
node,
"remote/node_available",
- safe_report_items
+ safe_report_items,
+ warn_on_communication_exception=warn_on_communication_exception
)
report_items.extend(safe_report_items)
if ReportListAnalyzer(safe_report_items).error_list:
return
+ #If there was a communication error and --skip-offline is in effect, no
+ #exception was raised. If there is no result cannot process it.
+ #Note: the error may be caused by older pcsd daemon not supporting commands
+ #sent by newer client.
+ if not availability_info:
+ return
+
is_in_expected_format = (
isinstance(availability_info, dict)
and
diff --git a/pcs/lib/test/test_nodes_task.py b/pcs/lib/test/test_nodes_task.py
index 61ba132..5459337 100644
--- a/pcs/lib/test/test_nodes_task.py
+++ b/pcs/lib/test/test_nodes_task.py
@@ -790,10 +790,6 @@ class CheckCanAddNodeToCluster(TestCase):
def test_report_no_dict_in_json_response(self):
self.assert_result_causes_invalid_format("bad answer")
- def test_report_dict_without_mandatory_key(self):
- self.assert_result_causes_invalid_format({})
-
-
class OnNodeTest(TestCase):
def setUp(self):
self.reporter = MockLibraryReportProcessor()
diff --git a/pcs/test/test_cluster_pcmk_remote.py b/pcs/test/test_cluster_pcmk_remote.py
index 5dc1633..0db4a5c 100644
--- a/pcs/test/test_cluster_pcmk_remote.py
+++ b/pcs/test/test_cluster_pcmk_remote.py
@@ -399,11 +399,11 @@ class NodeRemoveRemote(ResourceTest):
self.assert_effect(
"cluster node remove-remote NODE-HOST",
"<resources/>",
- outdent(
+ fixture_nolive_remove_report(["NODE-HOST"]) + outdent(
"""\
Deleting Resource - NODE-NAME
"""
- ) + fixture_nolive_remove_report(["NODE-HOST"])
+ )
)
def test_success_remove_by_node_name(self):
@@ -411,11 +411,11 @@ class NodeRemoveRemote(ResourceTest):
self.assert_effect(
"cluster node remove-remote NODE-NAME",
"<resources/>",
- outdent(
+ fixture_nolive_remove_report(["NODE-HOST"]) + outdent(
"""\
Deleting Resource - NODE-NAME
"""
- ) + fixture_nolive_remove_report(["NODE-HOST"])
+ )
)
def test_refuse_on_duplicit(self):
@@ -431,13 +431,17 @@ class NodeRemoveRemote(ResourceTest):
self.assert_effect(
"cluster node remove-remote HOST-A --force",
"<resources/>",
+
+ "Warning: multiple resource for 'HOST-A' found: 'HOST-A', 'NODE-NAME'\n"
+ +
+ fixture_nolive_remove_report(["HOST-A", "HOST-B"])
+ +
outdent(
"""\
- Warning: multiple resource for 'HOST-A' found: 'HOST-A', 'NODE-NAME'
Deleting Resource - NODE-NAME
Deleting Resource - HOST-A
"""
- ) + fixture_nolive_remove_report(["HOST-A", "HOST-B"])
+ )
)
class NodeRemoveGuest(ResourceTest):
--
1.8.3.1