From 4663113542dbe5851d64032536870ab8ec0ab074 Mon Sep 17 00:00:00 2001 From: Chris Hambridge Date: Wed, 21 Feb 2018 21:02:09 -0500 Subject: [PATCH] Handle Satellite errors on a per system basis. Closes #792. --- quipucords/scanner/satellite/api.py | 27 ++++++---- quipucords/scanner/satellite/five.py | 13 +++-- quipucords/scanner/satellite/six.py | 52 +++++++++++-------- .../scanner/satellite/tests_sat_five.py | 15 ++++-- quipucords/scanner/satellite/tests_sat_six.py | 30 +++++++++++ 5 files changed, 97 insertions(+), 40 deletions(-) diff --git a/quipucords/scanner/satellite/api.py b/quipucords/scanner/satellite/api.py index 31f49d54d..7c8352593 100644 --- a/quipucords/scanner/satellite/api.py +++ b/quipucords/scanner/satellite/api.py @@ -60,29 +60,36 @@ def record_conn_result(self, name, credential): name, increment_sys_scanned=True) @transaction.atomic - def record_inspect_result(self, name, facts): + def record_inspect_result(self, name, facts, + status=SystemInspectionResult.SUCCESS): """Record a new result. :param name: The host name :param facts: The dictionary of facts + :param status: The status of the inspection """ sys_result = SystemInspectionResult( name=name, - status=SystemInspectionResult.SUCCESS) + status=status) sys_result.save() - for key, val in facts.items(): - if val is not None: - final_value = json.dumps(val) - stored_fact = RawFact(name=key, value=final_value) - stored_fact.save() - sys_result.facts.add(stored_fact) + if status == SystemInspectionResult.SUCCESS: + for key, val in facts.items(): + if val is not None: + final_value = json.dumps(val) + stored_fact = RawFact(name=key, value=final_value) + stored_fact.save() + sys_result.facts.add(stored_fact) self.inspect_scan_task.inspection_result.systems.add(sys_result) self.inspect_scan_task.inspection_result.save() - self.inspect_scan_task.increment_stats( - name, increment_sys_scanned=True) + if status == SystemInspectionResult.SUCCESS: + self.inspect_scan_task.increment_stats( + name, increment_sys_scanned=True) + else: + self.inspect_scan_task.increment_stats( + name, increment_sys_failed=True) def host_count(self): """Obtain the count of managed hosts.""" diff --git a/quipucords/scanner/satellite/five.py b/quipucords/scanner/satellite/five.py index d6fb8fe34..03ef8fdaa 100644 --- a/quipucords/scanner/satellite/five.py +++ b/quipucords/scanner/satellite/five.py @@ -12,6 +12,7 @@ import logging import xmlrpc.client +from api.models import SystemInspectionResult from scanner.satellite.api import SatelliteInterface, SatelliteException from scanner.satellite import utils @@ -187,12 +188,16 @@ def host_details(self, host_id, host_name, last_checkin, details[VIRTUAL_HOST_NAME] = virtual_host.get(NAME) client.auth.logout(key) + + self.record_inspect_result(host_name, details) + logger.debug('host_id=%s, host_details=%s', + host_id, details) except xmlrpc.client.Fault as xml_error: - raise SatelliteException(str(xml_error)) + error_message = 'Satellite error encountered: %s\n' % xml_error + self.record_inspect_result(host_name, details, + status=SystemInspectionResult.FAILED) + logger.error(error_message) - self.record_inspect_result(host_name, details) - logger.debug('host_id=%s, host_details=%s', - host_id, details) return details def virtual_guests(self, virtual_host_id): diff --git a/quipucords/scanner/satellite/six.py b/quipucords/scanner/satellite/six.py index ebfa973fa..523d8aba0 100644 --- a/quipucords/scanner/satellite/six.py +++ b/quipucords/scanner/satellite/six.py @@ -12,6 +12,7 @@ import logging import requests +from api.models import SystemInspectionResult from scanner.satellite.api import SatelliteInterface, SatelliteException from scanner.satellite import utils @@ -403,16 +404,21 @@ def host_details(self, org_id, host_id, host_name): host_name) return details - details.update(host_fields(self.inspect_scan_task, 1, - HOSTS_FIELDS_V1_URL, - org_id, host_id)) - details.update(host_subscriptions(self.inspect_scan_task, - HOSTS_SUBS_V1_URL, - org_id, host_id)) - - self.record_inspect_result(host_name, details) - logger.debug('host_id=%s, host_details=%s', - host_id, details) + try: + details.update(host_fields(self.inspect_scan_task, 1, + HOSTS_FIELDS_V1_URL, + org_id, host_id)) + details.update(host_subscriptions(self.inspect_scan_task, + HOSTS_SUBS_V1_URL, + org_id, host_id)) + self.record_inspect_result(host_name, details) + logger.debug('host_id=%s, host_details=%s', + host_id, details) + except SatelliteException as sat_error: + error_message = 'Satellite error encountered: %s\n' % sat_error + self.record_inspect_result(host_name, details, + status=SystemInspectionResult.FAILED) + logger.error(error_message) return details def hosts_facts(self): @@ -512,17 +518,21 @@ def host_details(self, host_id, host_name): logger.debug('Results already captured for host_name=%s', host_name) return details - - details.update(host_fields(self.inspect_scan_task, 2, - HOSTS_FIELDS_V2_URL, - None, host_id)) - details.update(host_subscriptions(self.inspect_scan_task, - HOSTS_SUBS_V2_URL, - None, host_id)) - - self.record_inspect_result(host_name, details) - logger.debug('host_id=%s, host_details=%s', - host_id, details) + try: + details.update(host_fields(self.inspect_scan_task, 2, + HOSTS_FIELDS_V2_URL, + None, host_id)) + details.update(host_subscriptions(self.inspect_scan_task, + HOSTS_SUBS_V2_URL, + None, host_id)) + self.record_inspect_result(host_name, details) + logger.debug('host_id=%s, host_details=%s', + host_id, details) + except SatelliteException as sat_error: + error_message = 'Satellite error encountered: %s\n' % sat_error + self.record_inspect_result(host_name, details, + status=SystemInspectionResult.FAILED) + logger.error(error_message) return details def hosts_facts(self): diff --git a/quipucords/scanner/satellite/tests_sat_five.py b/quipucords/scanner/satellite/tests_sat_five.py index 09f057698..d3edd27f0 100644 --- a/quipucords/scanner/satellite/tests_sat_five.py +++ b/quipucords/scanner/satellite/tests_sat_five.py @@ -188,11 +188,16 @@ def test_host_details_with_err(self, mock_serverproxy): """Test the host details with an error.""" client = mock_serverproxy.return_value client.auth.login.side_effect = mock_xml_fault - with self.assertRaises(SatelliteException): - virt = {2: {'uuid': 2, 'name': 'sys2', 'num_virtual_guests': 3}} - self.api.host_details(host_id=1, host_name='sys1', - last_checkin='', virtual_hosts=virt, - virtual_guests={1: 2}) + virt = {2: {'uuid': 2, 'name': 'sys2', 'num_virtual_guests': 3}} + details = self.api.host_details(host_id=1, host_name='sys1', + last_checkin='', + virtual_hosts=virt, + virtual_guests={1: 2}) + inspect_result = self.scan_task.inspection_result + self.assertEqual(len(inspect_result.systems.all()), 1) + sys_result = inspect_result.systems.all().first() + self.assertEqual(sys_result.status, SystemInspectionResult.FAILED) + self.assertEqual(details, {}) @patch('xmlrpc.client.ServerProxy') def test_virtual_guests_with_err(self, mock_serverproxy): diff --git a/quipucords/scanner/satellite/tests_sat_six.py b/quipucords/scanner/satellite/tests_sat_six.py index a12d22684..95d6ccf42 100644 --- a/quipucords/scanner/satellite/tests_sat_six.py +++ b/quipucords/scanner/satellite/tests_sat_six.py @@ -24,6 +24,12 @@ from scanner.test_util import create_scan_job +# pylint: disable=unused-argument +def mock_sat_exception(param1, param2, param3, param4, param5): + """Mock method to throw satellite error.""" + raise SatelliteException() + + # pylint: disable=too-many-instance-attributes class SatelliteSixV1Test(TestCase): """Tests Satellite 6 v1 functions.""" @@ -233,6 +239,18 @@ def test_host_details_skip(self): self.assertEqual(len(inspect_result.systems.all()), 1) self.assertEqual(detail, {}) + def test_host_details_err(self): + """Test host_details method for error mark a failed system.""" + with patch('scanner.satellite.six.host_fields', + side_effect=mock_sat_exception) as mock_fields: + detail = self.api.host_details(1, 1, 'sys1') + inspect_result = self.scan_task.inspection_result + self.assertEqual(len(inspect_result.systems.all()), 1) + sys_result = inspect_result.systems.all().first() + self.assertEqual(sys_result.status, SystemInspectionResult.FAILED) + self.assertEqual(detail, {}) + mock_fields.assert_called_once_with(ANY, ANY, ANY, ANY, ANY) + def test_host_details(self): """Test host_details method with mock data.""" fields_return_value = { @@ -614,6 +632,18 @@ def test_host_subscriptons(self): 'end_date': '2022-01-01 04:59:59 UTC'}]} self.assertEqual(subs, expected) + def test_host_details_err(self): + """Test host_details method for error mark a failed system.""" + with patch('scanner.satellite.six.host_fields', + side_effect=mock_sat_exception) as mock_fields: + detail = self.api.host_details(1, 'sys1') + inspect_result = self.scan_task.inspection_result + self.assertEqual(len(inspect_result.systems.all()), 1) + sys_result = inspect_result.systems.all().first() + self.assertEqual(sys_result.status, SystemInspectionResult.FAILED) + self.assertEqual(detail, {}) + mock_fields.assert_called_once_with(ANY, ANY, ANY, ANY, ANY) + def test_host_details(self): """Test host_details method with mock data.""" fields_return_value = {