def get_nodes(self): """ Get all defined nodes """ result = NodeAddressesList() for node in self.config.findall("./clusternodes/clusternode"): altname = node.find("altname") result.append(NodeAddresses( ring0=node.get("name"), ring1=altname.get("name") if altname is not None else None, name=None, id=node.get("nodeid") )) return result
def test_one_node_down_forced(self, mock_corosync_live): conf_text = "test conf text" nodes = ["node1", "node2"] node_addrs_list = NodeAddressesList( [NodeAddresses(addr) for addr in nodes]) mock_corosync_live.set_remote_corosync_conf = mock.MagicMock() def raiser(comm, node, conf): if node.ring0 == nodes[1]: raise NodeAuthenticationException(nodes[1], "command", "HTTP error: 401") mock_corosync_live.set_remote_corosync_conf.side_effect = raiser lib.distribute_corosync_conf(self.mock_communicator, self.mock_reporter, node_addrs_list, conf_text, skip_offline_nodes=True) corosync_live_calls = [ mock.call.set_remote_corosync_conf("mock node communicator", nodes[0], conf_text), mock.call.set_remote_corosync_conf("mock node communicator", nodes[1], conf_text), ] self.assertEqual(len(corosync_live_calls), len(mock_corosync_live.mock_calls)) mock_corosync_live.set_remote_corosync_conf.assert_has_calls( [ mock.call("mock node communicator", node_addrs_list[0], conf_text), mock.call("mock node communicator", node_addrs_list[1], conf_text), ], any_order=True) assert_report_item_list_equal(self.mock_reporter.report_item_list, [ (severity.INFO, report_codes.COROSYNC_CONFIG_DISTRIBUTION_STARTED, {}), (severity.INFO, report_codes.COROSYNC_CONFIG_ACCEPTED_BY_NODE, { "node": nodes[0] }), (severity.WARNING, report_codes.NODE_COMMUNICATION_ERROR_NOT_AUTHORIZED, { "node": nodes[1], "command": "command", "reason": "HTTP error: 401", }), (severity.WARNING, report_codes.COROSYNC_CONFIG_DISTRIBUTION_NODE_ERROR, { "node": nodes[1], }), ])
def get_nodes(self): """ Get all defined nodes """ result = NodeAddressesList() for nodelist in self.config.get_sections("nodelist"): for node in nodelist.get_sections("node"): node_data = { "ring0_addr": None, "ring1_addr": None, "name": None, "nodeid": None, } for attr_name, attr_value in node.get_attributes(): if attr_name in node_data: node_data[attr_name] = attr_value result.append( NodeAddresses(node_data["ring0_addr"], node_data["ring1_addr"], node_data["name"], node_data["nodeid"])) return result
def test_errors_forced(self): nodes = ["node1", "node2"] node_addrs_list = NodeAddressesList( [NodeAddresses(addr) for addr in nodes] ) def side_effect(node, request, data): if node.ring0 == nodes[1]: raise NodeAuthenticationException( nodes[1], "command", "HTTP error: 401" ) return '{' # invalid json self.mock_communicator.call_node.side_effect = side_effect lib.check_corosync_offline_on_nodes( self.mock_communicator, self.mock_reporter, node_addrs_list, skip_offline_nodes=True ) assert_report_item_list_equal( self.mock_reporter.report_item_list, [ ( severity.INFO, report_codes.COROSYNC_NOT_RUNNING_CHECK_STARTED, {} ), ( severity.WARNING, report_codes.COROSYNC_NOT_RUNNING_CHECK_NODE_ERROR, { "node": nodes[0], } ), ( severity.WARNING, report_codes.NODE_COMMUNICATION_ERROR_NOT_AUTHORIZED, { "node": nodes[1], "command": "command", "reason" : "HTTP error: 401", } ), ( severity.WARNING, report_codes.COROSYNC_NOT_RUNNING_CHECK_NODE_ERROR, { "node": nodes[1], } ) ] )
def test_success(self, mock_corosync_live): conf_text = "test conf text" nodes = ["node1", "node2"] node_addrs_list = NodeAddressesList( [NodeAddresses(addr) for addr in nodes] ) mock_corosync_live.set_remote_corosync_conf = mock.MagicMock() lib.distribute_corosync_conf( self.mock_communicator, self.mock_reporter, node_addrs_list, conf_text ) corosync_live_calls = [ mock.call.set_remote_corosync_conf( "mock node communicator", node_addrs_list[0], conf_text ), mock.call.set_remote_corosync_conf( "mock node communicator", node_addrs_list[1], conf_text ), ] self.assertEqual( len(corosync_live_calls), len(mock_corosync_live.mock_calls) ) mock_corosync_live.set_remote_corosync_conf.assert_has_calls( corosync_live_calls, any_order=True ) assert_report_item_list_equal( self.mock_reporter.report_item_list, [ ( severity.INFO, report_codes.COROSYNC_CONFIG_DISTRIBUTION_STARTED, {} ), ( severity.INFO, report_codes.COROSYNC_CONFIG_ACCEPTED_BY_NODE, {"node": nodes[0]} ), ( severity.INFO, report_codes.COROSYNC_CONFIG_ACCEPTED_BY_NODE, {"node": nodes[1]} ), ] )
def setUp(self): self.mock_env = mock.MagicMock(spec_set=LibraryEnvironment) self.mock_log = mock.MagicMock(spec_set=logging.Logger) self.mock_env.logger = self.mock_log self.mock_com = mock.MagicMock(spec_set=NodeCommunicator) self.mock_env.node_communicator.return_value = self.mock_com self.mock_run = mock.MagicMock(spec_set=CommandRunner) self.mock_env.cmd_runner.return_value = self.mock_run self.mock_rep = MockLibraryReportProcessor() self.mock_env.report_processor = self.mock_rep self.node_list = NodeAddressesList( [NodeAddresses("node" + str(i)) for i in range(3)])
def setUp(self): self.env_assistant, self.config = get_env_tools(self) self.corosync_conf_facade = mock.MagicMock(CorosyncConfigFacade) self.corosync_conf_text = "corosync conf" self.corosync_conf_facade.config.export.return_value = ( self.corosync_conf_text ) self.corosync_conf_facade.get_nodes.return_value = NodeAddressesList([ NodeAddresses("node-1"), NodeAddresses("node-2"), ]) self.corosync_conf_facade.need_stopped_cluster = False self.corosync_conf_facade.need_qdevice_reload = False self.node_labels = ["node-1", "node-2"]
def get_nodes(self): """ Get all defined nodes """ result = NodeAddressesList() for nodelist in self.config.get_sections("nodelist"): for node in nodelist.get_sections("node"): node_data = { "ring0_addr": None, "ring1_addr": None, "name": None, "nodeid": None, } for attr_name, attr_value in node.get_attributes(): if attr_name in node_data: node_data[attr_name] = attr_value result.append(NodeAddresses( node_data["ring0_addr"], node_data["ring1_addr"], node_data["name"], node_data["nodeid"] )) return result
def test_one_node_running(self): nodes = ["node1", "node2"] node_addrs_list = NodeAddressesList( [NodeAddresses(addr) for addr in nodes]) self.mock_communicator.call_node.side_effect = [ '{"corosync": false}', '{"corosync": true}', ] assert_raise_library_error( lambda: lib.check_corosync_offline_on_nodes( self.mock_communicator, self.mock_reporter, node_addrs_list), (severity.ERROR, report_codes.COROSYNC_RUNNING_ON_NODE, { "node": nodes[1], }))
def test_one_node_running(self): node_responses = { "node1": '{"corosync": false}', "node2": '{"corosync": true}', } node_addrs_list = NodeAddressesList( [NodeAddresses(addr) for addr in node_responses.keys()]) self.mock_communicator.call_node.side_effect = ( lambda node, request, data: node_responses[node.label]) assert_raise_library_error( lambda: lib.check_corosync_offline_on_nodes( self.mock_communicator, self.mock_reporter, node_addrs_list), (severity.ERROR, report_codes.COROSYNC_RUNNING_ON_NODE, { "node": "node2", }))
def _share_authkey(env, current_nodes, candidate_node_addresses, allow_incomplete_distribution=False): if env.pacemaker.has_authkey: authkey_content = env.pacemaker.get_authkey_content() node_addresses_list = NodeAddressesList([candidate_node_addresses]) else: authkey_content = generate_key() node_addresses_list = current_nodes + [candidate_node_addresses] nodes_task.distribute_files( env.node_communicator(), env.report_processor, node_communication_format.pcmk_authkey_file(authkey_content), node_addresses_list, allow_incomplete_distribution, description="remote node configuration files")
def test_json_error(self): nodes = ["node1", "node2"] node_addrs_list = NodeAddressesList( [NodeAddresses(addr) for addr in nodes]) self.mock_communicator.call_node.side_effect = [ '{}', # missing key '{', # not valid json ] assert_raise_library_error( lambda: lib.check_corosync_offline_on_nodes( self.mock_communicator, self.mock_reporter, node_addrs_list), (severity.ERROR, report_codes.COROSYNC_NOT_RUNNING_CHECK_NODE_ERROR, { "node": nodes[0], }, report_codes.SKIP_OFFLINE_NODES), (severity.ERROR, report_codes.COROSYNC_NOT_RUNNING_CHECK_NODE_ERROR, { "node": nodes[1], }, report_codes.SKIP_OFFLINE_NODES))
def test_success(self): nodes = ["node1", "node2"] node_addrs_list = NodeAddressesList( [NodeAddresses(addr) for addr in nodes]) self.mock_communicator.call_node.return_value = '{"corosync": false}' lib.check_corosync_offline_on_nodes(self.mock_communicator, self.mock_reporter, node_addrs_list) assert_report_item_list_equal(self.mock_reporter.report_item_list, [ (severity.INFO, report_codes.COROSYNC_NOT_RUNNING_CHECK_STARTED, {}), (severity.INFO, report_codes.COROSYNC_NOT_RUNNING_ON_NODE, { "node": nodes[0] }), (severity.INFO, report_codes.COROSYNC_NOT_RUNNING_ON_NODE, { "node": nodes[1] }), ])
def _share_authkey(env, current_nodes, candidate_node_addresses, skip_offline_nodes=False, allow_incomplete_distribution=False): if env.pacemaker.has_authkey: authkey_content = env.pacemaker.get_authkey_content() node_addresses_list = NodeAddressesList([candidate_node_addresses]) else: authkey_content = generate_key() node_addresses_list = current_nodes + [candidate_node_addresses] com_cmd = DistributeFiles( env.report_processor, node_communication_format.pcmk_authkey_file(authkey_content), skip_offline_targets=skip_offline_nodes, allow_fails=allow_incomplete_distribution, description="remote node configuration files", ) com_cmd.set_targets( env.get_node_target_factory().get_target_list(node_addresses_list)) run_and_raise(env.get_node_communicator(), com_cmd)
def test_success(self, mock_remote_start, mock_remote_stop): nodes = ["node1", "node2"] node_addrs_list = NodeAddressesList( [NodeAddresses(addr) for addr in nodes]) lib.qdevice_reload_on_nodes(self.mock_communicator, self.mock_reporter, node_addrs_list) node_calls = [ mock.call(self.mock_reporter, self.mock_communicator, node_addrs_list[0]), mock.call(self.mock_reporter, self.mock_communicator, node_addrs_list[1]), ] self.assertEqual(len(node_calls), len(mock_remote_stop.mock_calls)) self.assertEqual(len(node_calls), len(mock_remote_start.mock_calls)) mock_remote_stop.assert_has_calls(node_calls, any_order=True) mock_remote_start.assert_has_calls(node_calls, any_order=True) assert_report_item_list_equal(self.mock_reporter.report_item_list, [ (severity.INFO, report_codes.QDEVICE_CLIENT_RELOAD_STARTED, {}), ])
def test_node_down(self): nodes = ["node1", "node2"] node_addrs_list = NodeAddressesList( [NodeAddresses(addr) for addr in nodes] ) def side_effect(node, request, data): if node.ring0 == nodes[1]: raise NodeAuthenticationException( nodes[1], "command", "HTTP error: 401" ) return '{"corosync": false}' self.mock_communicator.call_node.side_effect = side_effect assert_raise_library_error( lambda: lib.check_corosync_offline_on_nodes( self.mock_communicator, self.mock_reporter, node_addrs_list ), ( severity.ERROR, report_codes.NODE_COMMUNICATION_ERROR_NOT_AUTHORIZED, { "node": nodes[1], "command": "command", "reason" : "HTTP error: 401", }, report_codes.SKIP_OFFLINE_NODES ), ( severity.ERROR, report_codes.COROSYNC_NOT_RUNNING_CHECK_NODE_ERROR, { "node": nodes[1], }, report_codes.SKIP_OFFLINE_NODES ) )
def setUp(self): self.mock_communicator = mock.MagicMock(spec_set=NodeCommunicator) self.mock_reporter = MockLibraryReportProcessor() self.node_list = NodeAddressesList( [NodeAddresses("node" + str(i) for i in range(5))])
def test_fail_doesnt_prevent_start(self, mock_remote_start, mock_remote_stop): nodes = ["node1", "node2"] node_addrs_list = NodeAddressesList( [NodeAddresses(addr) for addr in nodes]) def raiser(reporter, communicator, node): if node.ring0 == nodes[1]: raise NodeAuthenticationException(node.label, "command", "HTTP error: 401") mock_remote_start.side_effect = raiser assert_raise_library_error( lambda: lib.qdevice_reload_on_nodes( self.mock_communicator, self.mock_reporter, node_addrs_list), # why the same error twice? # 1. Tested piece of code calls a function which puts an error # into the reporter. The reporter raises an exception. The # exception is caught in the tested piece of code, stored, and # later put to reporter again. # 2. Mock reporter remembers everything that goes through it # and by the machanism described in 1 the error goes througt it # twice. (severity.ERROR, report_codes.NODE_COMMUNICATION_ERROR_NOT_AUTHORIZED, { "node": nodes[1], "command": "command", "reason": "HTTP error: 401", }, report_codes.SKIP_OFFLINE_NODES), (severity.ERROR, report_codes.NODE_COMMUNICATION_ERROR_NOT_AUTHORIZED, { "node": nodes[1], "command": "command", "reason": "HTTP error: 401", }, report_codes.SKIP_OFFLINE_NODES)) node_calls = [ mock.call(self.mock_reporter, self.mock_communicator, node_addrs_list[0]), mock.call(self.mock_reporter, self.mock_communicator, node_addrs_list[1]), ] self.assertEqual(len(node_calls), len(mock_remote_stop.mock_calls)) self.assertEqual(len(node_calls), len(mock_remote_start.mock_calls)) mock_remote_stop.assert_has_calls(node_calls, any_order=True) mock_remote_start.assert_has_calls(node_calls, any_order=True) assert_report_item_list_equal( self.mock_reporter.report_item_list, [ (severity.INFO, report_codes.QDEVICE_CLIENT_RELOAD_STARTED, {}), # why the same error twice? # 1. Tested piece of code calls a function which puts an error # into the reporter. The reporter raises an exception. The # exception is caught in the tested piece of code, stored, and # later put to reporter again. # 2. Mock reporter remembers everything that goes through it # and by the machanism described in 1 the error goes througt it # twice. (severity.ERROR, report_codes.NODE_COMMUNICATION_ERROR_NOT_AUTHORIZED, { "node": nodes[1], "command": "command", "reason": "HTTP error: 401", }, report_codes.SKIP_OFFLINE_NODES), (severity.ERROR, report_codes.NODE_COMMUNICATION_ERROR_NOT_AUTHORIZED, { "node": nodes[1], "command": "command", "reason": "HTTP error: 401", }, report_codes.SKIP_OFFLINE_NODES), ])
def setUp(self): self.node_list = NodeAddressesList([ NodeAddresses("node1"), NodeAddresses("node2"), NodeAddresses("node3"), ])
def get_nodes_remote(tree): return NodeAddressesList(remote_node.find_node_list(get_root(tree)))
def get_nodes_guest(tree): return NodeAddressesList(guest_node.find_node_list(get_root(tree)))
def setUp(self): self.node_list = NodeAddressesList( [NodeAddresses("node" + str(i)) for i in range(5)] )