diff --git a/yupana/processor/report_slice_processor.py b/yupana/processor/report_slice_processor.py index c3418854..5123e5b7 100644 --- a/yupana/processor/report_slice_processor.py +++ b/yupana/processor/report_slice_processor.py @@ -23,6 +23,7 @@ import re import threading +from uuid import UUID from aiokafka import AIOKafkaProducer from kafka.errors import KafkaConnectionError from processor.abstract_processor import (AbstractProcessor, FAILED_TO_VALIDATE) @@ -247,6 +248,31 @@ def _remove_empty_mac_addresses(self, host: dict): )) return host + @staticmethod + def is_valid_uuid(uuid): + """Validate a UUID string.""" + try: + uuid_obj = UUID(uuid) + except ValueError: + return False + + return str(uuid_obj) == uuid + + def _remove_invalid_bios_uuid(self, host): + """Remove invalid bios UUID.""" + uuid = host.get('bios_uuid') + if not isinstance(uuid, str): + return host + + if not self.is_valid_uuid(uuid): + LOG.error(format_message( + self.prefix, + "Invalid uuid: %s for host with FQDN '%s'" + % (uuid, host.get('fqdn', '')))) + del host['bios_uuid'] + + return host + def _match_regex_and_find_os_details(self, os_release): """Match Regex with os_release and return os_details.""" source_os_release = os_release.strip() @@ -397,6 +423,7 @@ def _transform_single_host(self, host: dict): host = self._remove_empty_ip_addresses(host) host = self._remove_empty_mac_addresses(host) host = self._remove_display_name(host) + host = self._remove_invalid_bios_uuid(host) return host # pylint:disable=too-many-locals diff --git a/yupana/processor/tests_report_slice_processor.py b/yupana/processor/tests_report_slice_processor.py index e71b57bf..c539b509 100644 --- a/yupana/processor/tests_report_slice_processor.py +++ b/yupana/processor/tests_report_slice_processor.py @@ -268,7 +268,7 @@ def test_determine_retry_limit(self): async def async_test_transition_to_hosts_uploaded(self): """Test the transition to hosts being uploaded.""" - hosts = [{str(self.uuid): {'bios_uuid': 'value', 'name': 'value', + hosts = [{str(self.uuid): {'bios_uuid': str(self.uuid), 'name': 'value', 'system_platform_id': str(self.uuid)}}, {str(self.uuid2): {'insights_client_id': 'value', 'name': 'foo', 'system_platform_id': str(self.uuid2)}}, @@ -303,7 +303,7 @@ def test_transition_to_hosts_uploaded(self): async def async_test_transition_to_hosts_uploaded_kafka_mode(self): """Test the transition to hosts being uploaded.""" - hosts = [{str(self.uuid): {'bios_uuid': 'value', 'name': 'value', + hosts = [{str(self.uuid): {'bios_uuid': str(self.uuid), 'name': 'value', 'system_platform_id': str(self.uuid)}}, {str(self.uuid2): {'insights_client_id': 'value', 'name': 'foo', 'system_platform_id': str(self.uuid2)}}, @@ -373,7 +373,7 @@ def test_test_transition_to_hosts_uploaded_no_candidates(self): async def async_test_transition_to_hosts_uploaded_exception(self): """Test the transition to hosts being uploaded.""" - hosts = {str(self.uuid): {'bios_uuid': 'value', 'name': 'value'}, + hosts = {str(self.uuid): {'bios_uuid': str(self.uuid), 'name': 'value'}, str(self.uuid2): {'insights_client_id': 'value', 'name': 'foo'}, str(self.uuid3): {'ip_addresses': 'value', 'name': 'foo'}, str(self.uuid4): {'mac_addresses': 'value', 'name': 'foo'}, @@ -406,7 +406,7 @@ async def async_test_upload_to_host_inventory_via_kafka(self): """Test uploading to inventory via kafka.""" self.processor.report_or_slice = self.report_slice hosts = { - str(self.uuid): {'bios_uuid': 'value', 'name': 'value'}, + str(self.uuid): {'bios_uuid': str(self.uuid), 'name': 'value'}, str(self.uuid2): {'insights_client_id': 'value', 'name': 'foo'}, str(self.uuid3): {'ip_addresses': 'value', 'name': 'foo'}, str(self.uuid4): {'mac_addresses': 'value', 'name': 'foo'}, @@ -442,7 +442,7 @@ def test_upload_to_host_inventory_via_kafka(self): async def async_test_upload_to_host_inventory_via_kafka_exception(self): """Test uploading to inventory via kafka.""" self.processor.report_or_slice = self.report_slice - hosts = {str(self.uuid): {'bios_uuid': 'value', 'name': 'value'}, + hosts = {str(self.uuid): {'bios_uuid': str(self.uuid), 'name': 'value'}, str(self.uuid2): {'insights_client_id': 'value', 'name': 'foo'}, str(self.uuid3): {'ip_addresses': 'value', 'name': 'foo'}, str(self.uuid4): {'mac_addresses': 'value', 'name': 'foo'}, @@ -479,7 +479,7 @@ def test_upload_to_host_inventory_via_kafka_exception(self): async def async_test_upload_to_host_inventory_via_kafka_send_exception(self): """Test uploading to inventory via kafka.""" self.processor.report_or_slice = self.report_slice - hosts = {str(self.uuid): {'bios_uuid': 'value', 'name': 'value'}, + hosts = {str(self.uuid): {'bios_uuid': str(self.uuid), 'name': 'value'}, str(self.uuid2): {'insights_client_id': 'value', 'name': 'foo'}, str(self.uuid3): {'ip_addresses': 'value', 'name': 'foo'}, str(self.uuid4): {'mac_addresses': 'value', 'name': 'foo'}, @@ -855,3 +855,30 @@ def test_remove_empty_strings_in_ipv6_addresses(self): filtered_nics = [nic for nic in nics if nic.get('name') == 'eth0'] self.assertTrue(len(filtered_nics)) self.assertEqual(len(filtered_nics[0]['ipv6_addresses']), 1) + + def test_remove_invalid_bios_uuid(self): + """Test remove invalid bios UUID.""" + host = { + 'fqdn': 'virt-who.example.com', + 'bios_uuid': '45AA7104-5CB0-4A75-945D-7173C8DC5744443' + } + host = self.processor._remove_invalid_bios_uuid(host) + self.assertEqual(host, {'fqdn': 'virt-who.example.com'}) + + def test_remove_empty_bios_uuid(self): + """Test remove empty bios UUID field.""" + host = { + 'fqdn': 'virt-who.example.com', + 'bios_uuid': '' + } + host = self.processor._remove_invalid_bios_uuid(host) + self.assertEqual(host, {'fqdn': 'virt-who.example.com'}) + + def test_do_not_remove_valid_bios_uuid(self): + """Test do not remove valid bios UUID.""" + host = { + 'fqdn': 'virt-who.example.com', + 'bios_uuid': '123e4567-e89b-12d3-a456-426614174000' + } + new_host = self.processor._remove_invalid_bios_uuid(host) + self.assertEqual(new_host, host)