class NodeTargetLibFactory(TestCase): def setUp(self): self.known_hosts = { "host{}".format(i): PcsKnownHost("host{}".format(i), "token{}".format(i), [ Destination("addr{}{}".format(i, j), "port{}{}".format(i, j)) for j in range(2) ]) for i in range(2) } self.report_processor = MockLibraryReportProcessor() self.factory = lib.NodeTargetLibFactory(self.known_hosts, self.report_processor) def assert_equal_known_host_target(self, known_host, target): self.assertEqual(known_host.name, target.label) self.assertEqual(known_host.token, target.token) self.assertEqual(known_host.dest_list, target.dest_list) def test_one_host(self): host = "host0" self.assert_equal_known_host_target( self.known_hosts[host], self.factory.get_target_list([host])[0]) self.report_processor.assert_reports([]) def test_multiple_hosts(self): host_list = ["host0", "host1"] target_list = self.factory.get_target_list(host_list) for i, host in enumerate(host_list): self.assert_equal_known_host_target(self.known_hosts[host], target_list[i]) self.report_processor.assert_reports([]) def test_multiple_not_found(self): host = "host0" unknown_hosts = ["node0", "node1"] report = fixture.error(report_codes.HOST_NOT_FOUND, force_code=report_codes.SKIP_OFFLINE_NODES, host_list=unknown_hosts) assert_raise_library_error( lambda: self.factory.get_target_list([host] + unknown_hosts), report) self.report_processor.assert_reports([report]) def test_multiple_skip_not_allowed(self): host = "host0" unknown_hosts = ["node0", "node1"] report = fixture.error(report_codes.HOST_NOT_FOUND, host_list=unknown_hosts) assert_raise_library_error( lambda: self.factory.get_target_list( [host] + unknown_hosts, allow_skip=False, ), report) self.report_processor.assert_reports([report]) def test_multiple_not_found_skip_offline(self): host = "host0" unknown_hosts = ["node0", "node1"] target_list = self.factory.get_target_list([host] + unknown_hosts, skip_non_existing=True) self.assert_equal_known_host_target(self.known_hosts[host], target_list[0]) self.report_processor.assert_reports([ fixture.warn(report_codes.HOST_NOT_FOUND, host_list=unknown_hosts) ]) def test_no_host_found(self): unknown_hosts = ["node0", "node1"] report_list = [ fixture.error(report_codes.HOST_NOT_FOUND, force_code=report_codes.SKIP_OFFLINE_NODES, host_list=unknown_hosts), fixture.error(report_codes.NONE_HOST_FOUND) ] assert_raise_library_error( lambda: self.factory.get_target_list(unknown_hosts), *report_list) self.report_processor.assert_reports(report_list) def test_no_host_found_skip_offline(self): unknown_hosts = ["node0", "node1"] report_list = [ fixture.warn(report_codes.HOST_NOT_FOUND, host_list=unknown_hosts), fixture.error(report_codes.NONE_HOST_FOUND) ] assert_raise_library_error( lambda: self.factory.get_target_list(unknown_hosts, skip_non_existing=True), report_list[1]) self.report_processor.assert_reports(report_list) def test_empty_host_list(self): self.assertEqual([], self.factory.get_target_list([])) self.report_processor.assert_reports([])
class CommunicatorLoggerTest(TestCase): def setUp(self): self.logger = mock.MagicMock(spec_set=logging.Logger) self.reporter = MockLibraryReportProcessor() self.com_logger = lib.LibCommunicatorLogger(self.logger, self.reporter) def test_log_request_start(self): request = fixture_request() self.com_logger.log_request_start(request) self.reporter.assert_reports( fixture_report_item_list_send(request.url, request.data)) self.assertEqual([fixture_logger_call_send(request.url, request.data)], self.logger.mock_calls) def test_log_response_connected(self): expected_code = 200 expected_data = "data" expected_debug_data = "* text\n>> data out\n" response = Response.connection_successful( MockCurlSimple( info={pycurl.RESPONSE_CODE: expected_code}, output=expected_data.encode("utf-8"), debug_output=expected_debug_data.encode("utf-8"), request=fixture_request(), )) self.com_logger.log_response(response) self.reporter.assert_reports( fixture_report_item_list_on_success(response.request.url, expected_code, expected_data, expected_debug_data)) logger_calls = fixture_logger_calls_on_success(response.request.url, expected_code, expected_data, expected_debug_data) self.assertEqual(logger_calls, self.logger.mock_calls) @mock.patch("pcs.lib.node_communication.is_proxy_set") def test_log_response_not_connected(self, mock_proxy): mock_proxy.return_value = False expected_debug_data = "* text\n>> data out\n" error_msg = "error" response = Response.connection_failure( MockCurlSimple( debug_output=expected_debug_data.encode("utf-8"), request=fixture_request(), ), pycurl.E_HTTP_POST_ERROR, error_msg, ) self.com_logger.log_response(response) self.reporter.assert_reports( fixture_report_item_list_not_connected(response.request.host_label, error_msg) + fixture_report_item_list_debug(response.request.url, expected_debug_data)) logger_calls = [ fixture_logger_call_not_connected(response.request.host_label, error_msg), fixture_logger_call_debug_data(response.request.url, expected_debug_data) ] self.assertEqual(logger_calls, self.logger.mock_calls) @mock.patch("pcs.lib.node_communication.is_proxy_set") def test_log_response_not_connected_with_proxy(self, mock_proxy): mock_proxy.return_value = True expected_debug_data = "* text\n>> data out\n" error_msg = "error" response = Response.connection_failure( MockCurlSimple( debug_output=expected_debug_data.encode("utf-8"), request=fixture_request(), ), pycurl.E_HTTP_POST_ERROR, error_msg, ) self.com_logger.log_response(response) self.reporter.assert_reports( fixture_report_item_list_not_connected(response.request.host_label, error_msg) + fixture_report_item_list_proxy_set(response.request.host_label, response.request.host_label) + fixture_report_item_list_debug(response.request.url, expected_debug_data)) logger_calls = [ fixture_logger_call_not_connected(response.request.host_label, error_msg), fixture_logger_call_proxy_set(), fixture_logger_call_debug_data(response.request.url, expected_debug_data) ] self.assertEqual(logger_calls, self.logger.mock_calls) def test_log_retry(self): prev_addr = "addr" prev_port = 2225 prev_host = Destination(prev_addr, prev_port) response = Response.connection_failure( MockCurlSimple(request=fixture_request()), pycurl.E_HTTP_POST_ERROR, "e", ) self.com_logger.log_retry(response, prev_host) self.reporter.assert_reports([ (severity.WARNING, report_codes.NODE_COMMUNICATION_RETRYING, { "node": response.request.host_label, "failed_address": prev_addr, "failed_port": prev_port, "next_address": response.request.dest.addr, "next_port": settings.pcsd_default_port, "request": response.request.url, }, None) ]) logger_call = mock.call.warning( ("Unable to connect to '{label}' via address '{old_addr}' and " "port '{old_port}'. Retrying request '{req}' via address " "'{new_addr}' and port '{new_port}'").format( label=response.request.host_label, old_addr=prev_addr, old_port=prev_port, new_addr=response.request.dest.addr, new_port=settings.pcsd_default_port, req=response.request.url, )) self.assertEqual([logger_call], self.logger.mock_calls) def test_log_no_more_addresses(self): response = Response.connection_failure( MockCurlSimple(request=fixture_request()), pycurl.E_HTTP_POST_ERROR, "e") self.com_logger.log_no_more_addresses(response) self.reporter.assert_reports([ (severity.WARNING, report_codes.NODE_COMMUNICATION_NO_MORE_ADDRESSES, { "node": response.request.host_label, "request": response.request.url, }, None) ]) logger_call = mock.call.warning( "No more addresses for node {label} to run '{req}'".format( label=response.request.host_label, req=response.request.url, )) self.assertEqual([logger_call], self.logger.mock_calls)
class EnsureResourceState(TestCase): resource_id = "R" def setUp(self): self.report_processor = MockLibraryReportProcessor( raise_on_errors=False ) self.cluster_state = "state" patcher = mock.patch( "pcs.lib.pacemaker.state.get_resource_roles_with_nodes" ) self.addCleanup(patcher.stop) self.get_resource_roles_with_nodes = patcher.start() def fixture_running_state_info(self): return { "Started": ["node1"], "Master": ["node2"], "Slave": ["node3", "node4"], } def fixture_running_report(self, severity): return (severity, report_codes.RESOURCE_RUNNING_ON_NODES, { "resource_id": self.resource_id, "roles_with_nodes": self.fixture_running_state_info(), }) def fixture_not_running_report(self, severity): return (severity, report_codes.RESOURCE_DOES_NOT_RUN, { "resource_id": self.resource_id }) def assert_running_info_transform(self, run_info, report, expected_running): self.get_resource_roles_with_nodes.return_value = run_info state.ensure_resource_state( expected_running, self.report_processor, self.cluster_state, self.resource_id ) self.report_processor.assert_reports([report]) self.get_resource_roles_with_nodes.assert_called_once_with( self.cluster_state, self.resource_id ) def test_report_info_running(self): self.assert_running_info_transform( self.fixture_running_state_info(), self.fixture_running_report(severities.INFO), expected_running=True, ) def test_report_error_running(self): self.assert_running_info_transform( self.fixture_running_state_info(), self.fixture_running_report(severities.ERROR), expected_running=False, ) def test_report_error_not_running(self): self.assert_running_info_transform( [], self.fixture_not_running_report(severities.ERROR), expected_running=True, ) def test_report_info_not_running(self): self.assert_running_info_transform( [], self.fixture_not_running_report(severities.INFO), expected_running=False, )