def node_remove_guest( env: LibraryEnvironment, node_identifier, skip_offline_nodes=False, allow_remove_multiple_nodes=False, allow_pacemaker_remote_service_fail=False, wait: WaitType = False, ): """ remove a resource representing remote node and destroy remote node LibraryEnvironment env provides all for communication with externals string node_identifier -- node name, hostname or resource id bool skip_offline_nodes -- a flag for ignoring when some nodes are offline bool allow_remove_multiple_nodes -- is a flag for allowing remove unexpected multiple occurrence of remote node for node_identifier bool allow_pacemaker_remote_service_fail -- is a flag for allowing successfully finish this command even if stoping/disabling pacemaker_remote not succeeded """ wait_timeout = env.ensure_wait_satisfiable(wait) cib = env.get_cib() resource_element_list = _find_resources_to_remove( cib, env.report_processor, "guest", node_identifier, allow_remove_multiple_nodes, guest_node.find_node_resources, ) node_names_list = sorted( { guest_node.get_node_name_from_resource(node_element) for node_element in resource_element_list } ) if not env.is_cib_live: env.report_processor.report_list( _report_skip_live_parts_in_remove(node_names_list) ) else: _destroy_pcmk_remote_env( env, node_names_list, skip_offline_nodes, allow_pacemaker_remote_service_fail, ) for resource_element in resource_element_list: guest_node.unset_guest(resource_element) env.push_cib(wait_timeout=wait_timeout) # remove node from pcmk caches if env.is_cib_live: for node_name in node_names_list: remove_node(env.cmd_runner(), node_name)
def node_clear(env, node_name, allow_clear_cluster_node=False): """ Remove specified node from various cluster caches. LibraryEnvironment env provides all for communication with externals string node_name bool allow_clear_cluster_node -- flag allows to clear node even if it's still in a cluster """ mocked_envs = [] if not env.is_cib_live: mocked_envs.append("CIB") if not env.is_corosync_conf_live: mocked_envs.append("COROSYNC_CONF") if mocked_envs: raise LibraryError(reports.live_environment_required(mocked_envs)) current_nodes = get_nodes(env.get_corosync_conf(), env.get_cib()) if (node_addresses_contain_name(current_nodes, node_name) or node_addresses_contain_host(current_nodes, node_name)): env.report_processor.process( reports.get_problem_creator( report_codes.FORCE_CLEAR_CLUSTER_NODE, allow_clear_cluster_node)( reports.node_to_clear_is_still_in_cluster, node_name)) remove_node(env.cmd_runner(), node_name)
def test_success(self): mock_runner = get_runner("", "", 0) lib.remove_node(mock_runner, "NODE_NAME") mock_runner.run.assert_called_once_with([ self.path("crm_node"), "--force", "--remove", "NODE_NAME", ])
def node_remove_guest( env, node_identifier, skip_offline_nodes=False, allow_remove_multiple_nodes=False, allow_pacemaker_remote_service_fail=False, wait=False, ): """ remove a resource representing remote node and destroy remote node LibraryEnvironment env provides all for communication with externals string node_identifier -- node name, hostname or resource id bool skip_offline_nodes -- a flag for ignoring when some nodes are offline bool allow_remove_multiple_nodes -- is a flag for allowing remove unexpected multiple occurence of remote node for node_identifier bool allow_pacemaker_remote_service_fail -- is a flag for allowing successfully finish this command even if stoping/disabling pacemaker_remote not succeeded """ env.ensure_wait_satisfiable(wait) cib = env.get_cib() resource_element_list = _find_resources_to_remove( cib, env.report_processor, "guest", node_identifier, allow_remove_multiple_nodes, guest_node.find_node_resources, ) node_names_list = sorted({ guest_node.get_node_name_from_resource(node_element) for node_element in resource_element_list }) if not env.is_cib_live: env.report_processor.process_list( _report_skip_live_parts_in_remove(node_names_list) ) else: _destroy_pcmk_remote_env( env, node_names_list, skip_offline_nodes, allow_pacemaker_remote_service_fail ) for resource_element in resource_element_list: guest_node.unset_guest(resource_element) env.push_cib(wait=wait) #remove node from pcmk caches if env.is_cib_live: for node_name in node_names_list: remove_node(env.cmd_runner(), node_name)
def node_remove_guest( env, node_identifier, allow_remove_multiple_nodes=False, allow_pacemaker_remote_service_fail=False, wait=False, ): """ remove a resource representing remote node and destroy remote node LibraryEnvironment env provides all for communication with externals string node_identifier -- node name, hostname or resource id bool allow_remove_multiple_nodes -- is a flag for allowing remove unexpected multiple occurence of remote node for node_identifier bool allow_pacemaker_remote_service_fail -- is a flag for allowing successfully finish this command even if stoping/disabling pacemaker_remote not succeeded """ _ensure_consistently_live_env(env) env.ensure_wait_satisfiable(wait) cib = env.get_cib() resource_element_list = _find_resources_to_remove( cib, env.report_processor, "guest", node_identifier, allow_remove_multiple_nodes, guest_node.find_node_resources, ) node_addresses_list = _get_node_addresses_from_resources( get_nodes_guest(cib), resource_element_list, guest_node.get_host, ) if not env.is_corosync_conf_live: env.report_processor.process_list( _report_skip_live_parts_in_remove(node_addresses_list)) 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 if env.is_cib_live: for node_addresses in node_addresses_list: remove_node(env.cmd_runner(), node_addresses.name)
def test_success(self): mock_runner = get_runner("", "", 0) lib.remove_node( mock_runner, "NODE_NAME" ) mock_runner.run.assert_called_once_with([ self.path("crm_node"), "--force", "--remove", "NODE_NAME", ])
def test_error(self): expected_stderr = "expected stderr" mock_runner = get_runner("", expected_stderr, 1) assert_raise_library_error( lambda: lib.remove_node(mock_runner, "NODE_NAME"), (Severity.ERROR, report_codes.NODE_REMOVE_IN_PACEMAKER_FAILED, { "node_name": "NODE_NAME", "reason": expected_stderr, }))
def remove_nodes_from_cib(env, node_list): """ Remove specified nodes from CIB. When pcmk is running 'crm_node -R <node>' will be used. Otherwise nodes will be removed directly from CIB file. env LibraryEnvironment node_list iterable -- names of nodes to remove """ # TODO: more advanced error handling # TODO: Tests if not env.is_cib_live: raise LibraryError(reports.live_environment_required(["CIB"])) if is_service_running(env.cmd_runner(), "pacemaker"): for node in node_list: # this may raise a LibraryError # NOTE: crm_node cannot remove multiple nodes at once remove_node(env.cmd_runner(), node) return # TODO: We need to remove nodes from the CIB file. We don't want to do it # using environment as this is a special case in which we have to edit CIB # file directly. for node in node_list: stdout, stderr, retval = env.cmd_runner().run( [ settings.cibadmin, "--delete-all", "--force", f"--xpath=/cib/configuration/nodes/node[@uname='{node}']", ], env_extend={"CIB_file": os.path.join(settings.cib_dir, "cib.xml")} ) if retval != 0: raise LibraryError( reports.node_remove_in_pacemaker_failed( [node], reason=join_multilines([stderr, stdout]) ) )
def test_error(self): expected_stderr = "expected stderr" mock_runner = get_runner("", expected_stderr, 1) assert_raise_library_error( lambda: lib.remove_node(mock_runner, "NODE_NAME"), ( Severity.ERROR, report_codes.NODE_REMOVE_IN_PACEMAKER_FAILED, { "node": None, "node_list_to_remove": ["NODE_NAME"], "reason": expected_stderr, } ) )