patchman 4.0.11__tar.gz → 4.0.13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {patchman-4.0.11 → patchman-4.0.13}/PKG-INFO +1 -1
- patchman-4.0.13/VERSION.txt +1 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/models.py +0 -1
- {patchman-4.0.11 → patchman-4.0.13}/errata/tests/test_models.py +19 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/models.py +287 -36
- patchman-4.0.13/hosts/tests/test_models.py +699 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/utils.py +7 -3
- {patchman-4.0.11 → patchman-4.0.13}/patchman.egg-info/PKG-INFO +1 -1
- {patchman-4.0.11 → patchman-4.0.13}/patchman.egg-info/SOURCES.txt +1 -1
- patchman-4.0.11/VERSION.txt +0 -1
- patchman-4.0.11/hosts/tests/test_models.py +0 -130
- {patchman-4.0.11 → patchman-4.0.13}/AUTHORS +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/COPYING +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/INSTALL.md +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/MANIFEST.in +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/README.md +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/admin.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/apps.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/migrations/0001_initial.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/migrations/0002_alter_machinearchitecture_options_and_more.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/migrations/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/serializers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/tests/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/tests/test_api.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/tests/test_models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/utils.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/arch/views.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/domains/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/domains/admin.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/domains/apps.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/domains/migrations/0001_initial.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/domains/migrations/0002_alter_domain_options.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/domains/migrations/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/domains/models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/domains/serializers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/domains/tests/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/domains/tests/test_api.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/domains/tests/test_models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/domains/views.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/admin.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/apps.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/managers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/migrations/0001_initial.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/migrations/0002_alter_erratumreference_unique_together.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/migrations/0003_delete_erratumreference_alter_erratum_references.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/migrations/0004_rename_packages_erratum_fixed_packages.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/migrations/0005_erratum_affected_packages_and_more.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/migrations/0006_alter_erratum_options.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/migrations/0007_alter_erratum_fixed_packages.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/migrations/0008_add_cached_count_fields.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/migrations/0009_backfill_cached_counts.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/migrations/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/serializers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/signals.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/sources/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/sources/distros/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/sources/distros/alma.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/sources/distros/arch.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/sources/distros/centos.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/sources/distros/debian.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/sources/distros/rocky.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/sources/distros/ubuntu.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/sources/repos/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/sources/repos/yum.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/tables.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/tasks.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/templates/errata/erratum_detail.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/templates/errata/erratum_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/tests/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/tests/test_api.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/tests/test_integration.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/urls.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/utils.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/errata/views.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/etc/patchman/apache.conf.example +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/etc/patchman/celery.conf +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/etc/patchman/local_settings.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/etc/systemd/system/patchman-celery-beat.service +0 -0
- /patchman-4.0.11/etc/systemd/system/patchman-celery-worker.service → /patchman-4.0.13/etc/systemd/system/patchman-celery-worker@.service +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/admin.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/apps.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/forms.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/managers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/0001_initial.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/0002_initial.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/0003_host_modules.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/0004_remove_host_tags_host_tags.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/0005_rename_os_host_osvariant.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/0006_migrate_to_tz_aware.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/0007_alter_host_tags.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/0008_alter_host_options.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/0009_host_errata.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/0010_alter_hostrepo_options.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/0011_host_bug_updates_count_host_errata_count_and_more.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/0012_backfill_cached_counts.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/migrations/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/serializers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/signals.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/tables.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/tasks.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/templates/hosts/host_delete.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/templates/hosts/host_detail.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/templates/hosts/host_edit.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/templates/hosts/host_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/templatetags/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/templatetags/report_alert.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/tests/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/tests/test_api.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/tests/test_find_updates.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/tests/test_managers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/urls.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/hosts/views.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/admin.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/apps.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/managers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/migrations/0001_initial.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/migrations/0002_auto_20240204_2214.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/migrations/0003_alter_module_options.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/migrations/0004_alter_module_options.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/migrations/0005_alter_module_unique_together.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/migrations/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/serializers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/tables.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/templates/modules/module_detail.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/templates/modules/module_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/urls.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/utils.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/modules/views.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/admin.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/apps.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/fixtures/os.json +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/fixtures/osgroup.json +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/forms.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/managers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/migrations/0001_initial.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/migrations/0002_initial.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/migrations/0003_os_arch.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/migrations/0003_osgroup_codename.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/migrations/0004_alter_osgroup_unique_together.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/migrations/0005_rename_osgroup_osrelease_rename_os_osvariant_and_more.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/migrations/0006_osrelease_cpe_name_osvariant_codename.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/migrations/0007_alter_osrelease_unique_together.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/migrations/0008_alter_osrelease_options_alter_osvariant_options.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/migrations/0009_osvariant_hosts_count.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/migrations/0010_backfill_osvariant_counts.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/migrations/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/serializers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/signals.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/tables.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/templates/operatingsystems/os_landing.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/templates/operatingsystems/osrelease_delete.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/templates/operatingsystems/osrelease_detail.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/templates/operatingsystems/osrelease_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/templates/operatingsystems/osvariant_delete.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/templates/operatingsystems/osvariant_delete_multiple.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/templates/operatingsystems/osvariant_detail.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/templates/operatingsystems/osvariant_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/tests/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/tests/test_api.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/tests/test_models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/urls.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/utils.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/operatingsystems/views.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/admin.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/apps.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/managers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/migrations/0001_initial.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/migrations/0002_auto_20250207_1319.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/migrations/0002_delete_erratum_delete_erratumreference.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/migrations/0003_auto_20250207_1746.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/migrations/0004_alter_package_options_alter_packagecategory_options_and_more.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/migrations/0005_alter_package_packagetype.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/migrations/0006_alter_packageupdate_options.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/migrations/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/serializers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/tables.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/templates/packages/package_detail.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/templates/packages/package_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/templates/packages/package_name_detail.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/templates/packages/package_name_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/tests/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/tests/test_api.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/tests/test_models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/tests/test_version_compare.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/urls.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/utils.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/packages/views.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman/celery.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman/receivers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman/settings.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman/signals.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman/sqlite3/base.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman/static/css/base.css +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman/static/js/expandable-text.js +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman/static/js/sidebar.js +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman/urls.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman/wsgi.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman.egg-info/dependency_links.txt +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman.egg-info/requires.txt +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/patchman.egg-info/top_level.txt +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/admin.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/apps.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/migrations/0001_initial.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/migrations/0002_report_modules.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/migrations/0003_remove_report_accessed.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/migrations/0004_migrate_to_tz_aware.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/migrations/0005_alter_report_options.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/migrations/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/serializers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/tables.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/tasks.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/templates/reports/report.txt +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/templates/reports/report_delete.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/templates/reports/report_detail.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/templates/reports/report_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/tests/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/tests/test_api.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/tests/test_edge_cases.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/tests/test_integration.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/tests/test_models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/tests/test_parsing.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/tests/test_serializers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/tests/test_tasks.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/tests/test_utils.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/urls.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/utils.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/reports/views.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/admin.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/apps.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/forms.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/managers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/migrations/0001_initial.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/migrations/0002_alter_repository_repotype.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/migrations/0003_migrate_to_tz_aware.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/migrations/0004_rename_file_checksum_mirror_package_checksum.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/migrations/0005_rename_package_checksum_mirror_packages_checksum.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/migrations/0006_mirror_errata_checksum_mirror_modules_checksum.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/migrations/0007_alter_mirror_options_alter_mirrorpackage_options_and_more.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/migrations/0008_mirror_packages_count.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/migrations/0009_backfill_mirror_counts.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/migrations/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/repo_types/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/repo_types/arch.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/repo_types/deb.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/repo_types/gentoo.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/repo_types/rpm.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/repo_types/yast.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/repo_types/yum.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/serializers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/signals.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/tables.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/tasks.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/templates/repos/mirror_delete.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/templates/repos/mirror_detail.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/templates/repos/mirror_edit.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/templates/repos/mirror_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/templates/repos/mirror_with_repo_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/templates/repos/repo_delete.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/templates/repos/repo_detail.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/templates/repos/repo_edit.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/templates/repos/repo_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/templatetags/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/tests/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/tests/test_api.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/tests/test_managers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/tests/test_mirror_sync.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/tests/test_models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/urls.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/utils.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/repos/views.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/requirements.txt +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/sbin/patchman +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/sbin/patchman-manage +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/sbin/patchman-set-secret-key +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/scripts/clear-django-logs.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/scripts/create_graph.sh +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/scripts/rpm-install.sh +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/scripts/rpm-post-install.sh +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/admin.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/apps.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/managers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/migrations/0001_initial.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/migrations/0002_alter_cve_options.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/migrations/0003_alter_cve_description_alter_cwe_description.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/migrations/0004_alter_cve_options.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/migrations/0005_reference_cve_references.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/migrations/0006_alter_cve_options_alter_cvss_unique_together.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/migrations/0007_remove_cve_title.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/migrations/0008_alter_cwe_options_alter_reference_options.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/migrations/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/serializers.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/tables.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/tasks.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/templates/security/cve_detail.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/templates/security/cve_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/templates/security/cwe_detail.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/templates/security/cwe_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/templates/security/reference_list.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/templates/security/security_landing.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/tests/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/tests/test_api.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/tests/test_models.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/urls.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/utils.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/security/views.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/setup.cfg +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/setup.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/apps.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/context_processors.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/filterspecs.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/logging.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/management/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/management/commands/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/management/commands/create_api_key.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/management/commands/list_api_keys.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/management/commands/revoke_api_key.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/tables.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/tasks.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/templates/404.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/templates/500.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/templates/base.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/templates/bulk_actions.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/templates/dashboard.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/templates/navbar.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/templates/objectlist.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/templates/registration/login.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/templates/searchbar.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/templates/table.html +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/templatetags/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/templatetags/common.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/tests/__init__.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/tests/test_commands.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/tests/test_utils.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/urls.py +0 -0
- {patchman-4.0.11 → patchman-4.0.13}/util/views.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.0.13
|
|
@@ -239,3 +239,22 @@ class ErratumCachedCountTests(TestCase):
|
|
|
239
239
|
self.erratum.refresh_from_db()
|
|
240
240
|
self.assertEqual(self.erratum.cves_count, self.erratum.cves.count())
|
|
241
241
|
self.assertEqual(self.erratum.osreleases_count, self.erratum.osreleases.count())
|
|
242
|
+
|
|
243
|
+
def test_add_fixed_packages_no_stale_save(self):
|
|
244
|
+
"""Test that add_fixed_packages does not overwrite cached counts.
|
|
245
|
+
|
|
246
|
+
Regression test: add_fixed_packages previously called self.save()
|
|
247
|
+
after the M2M .add() loop, which overwrote the signal-updated
|
|
248
|
+
fixed_packages_count with the stale in-memory value.
|
|
249
|
+
"""
|
|
250
|
+
from arch.models import PackageArchitecture
|
|
251
|
+
from packages.models import Package, PackageName
|
|
252
|
+
pkg_arch = PackageArchitecture.objects.create(name='amd64')
|
|
253
|
+
pkg_name = PackageName.objects.create(name='libssl3')
|
|
254
|
+
pkg = Package.objects.create(
|
|
255
|
+
name=pkg_name, arch=pkg_arch, epoch='',
|
|
256
|
+
version='3.0.1', release='1', packagetype='D'
|
|
257
|
+
)
|
|
258
|
+
self.erratum.add_fixed_packages({pkg})
|
|
259
|
+
self.erratum.refresh_from_db()
|
|
260
|
+
self.assertEqual(self.erratum.fixed_packages_count, 1)
|
|
@@ -178,27 +178,28 @@ class Host(models.Model):
|
|
|
178
178
|
def find_updates(self):
|
|
179
179
|
|
|
180
180
|
kernels_q = Q(name__name='kernel') | \
|
|
181
|
-
Q(
|
|
182
|
-
Q(
|
|
183
|
-
Q(
|
|
184
|
-
Q(
|
|
185
|
-
Q(
|
|
186
|
-
Q(
|
|
187
|
-
Q(
|
|
188
|
-
Q(
|
|
189
|
-
Q(
|
|
190
|
-
Q(
|
|
191
|
-
Q(name__name='
|
|
192
|
-
Q(name__name='
|
|
193
|
-
Q(name__name='
|
|
194
|
-
Q(name__name='
|
|
195
|
-
Q(name__name='
|
|
196
|
-
Q(name__name='
|
|
197
|
-
Q(name__name='
|
|
198
|
-
Q(name__name='
|
|
199
|
-
Q(name__name='
|
|
200
|
-
Q(name__name='
|
|
201
|
-
Q(name__name='
|
|
181
|
+
Q(name__name__startswith='kernel-') | \
|
|
182
|
+
Q(name__name__startswith='virtualbox-kmp-') | \
|
|
183
|
+
Q(name__name__startswith='linux-image-') | \
|
|
184
|
+
Q(name__name__startswith='linux-headers-') | \
|
|
185
|
+
Q(name__name__regex=r'^linux-modules-\d') | \
|
|
186
|
+
Q(name__name__regex=r'^linux-modules-extra-\d') | \
|
|
187
|
+
Q(name__name__startswith='linux-tools-') | \
|
|
188
|
+
Q(name__name__startswith='linux-cloud-tools-') | \
|
|
189
|
+
Q(name__name__startswith='linux-kbuild-') | \
|
|
190
|
+
Q(name__name__startswith='linux-support-') | \
|
|
191
|
+
Q(name__name='linux') | \
|
|
192
|
+
Q(name__name='linux-lts') | \
|
|
193
|
+
Q(name__name='linux-zen') | \
|
|
194
|
+
Q(name__name='linux-hardened') | \
|
|
195
|
+
Q(name__name='linux-rt') | \
|
|
196
|
+
Q(name__name='linux-rt-lts') | \
|
|
197
|
+
Q(name__name='linux-headers') | \
|
|
198
|
+
Q(name__name='linux-lts-headers') | \
|
|
199
|
+
Q(name__name='linux-zen-headers') | \
|
|
200
|
+
Q(name__name='linux-hardened-headers') | \
|
|
201
|
+
Q(name__name='linux-rt-headers') | \
|
|
202
|
+
Q(name__name='linux-rt-lts-headers')
|
|
202
203
|
repo_packages = self.get_host_repo_packages()
|
|
203
204
|
host_packages = self.packages.exclude(kernels_q).distinct()
|
|
204
205
|
kernel_packages = self.packages.filter(kernels_q)
|
|
@@ -313,42 +314,292 @@ class Host(models.Model):
|
|
|
313
314
|
return update_ids
|
|
314
315
|
|
|
315
316
|
def check_if_reboot_required(self, host_highest):
|
|
317
|
+
"""Check if a reboot is required (running kernel < installed highest).
|
|
316
318
|
|
|
317
|
-
|
|
319
|
+
Uses labelCompare for RPM-style version tuples parsed from uname -r.
|
|
320
|
+
Only valid for RPM kernels — DEB and Arch use compare_version via
|
|
321
|
+
their respective find_*_kernel_updates methods.
|
|
322
|
+
"""
|
|
323
|
+
parts = self.kernel.split('-')
|
|
324
|
+
if len(parts) < 2:
|
|
325
|
+
return
|
|
326
|
+
ver, rel = parts[:2]
|
|
327
|
+
# strip arch suffix from uname -r release (e.g. '.x86_64', '.aarch64')
|
|
328
|
+
arch_suffix = '.' + self.arch.name
|
|
329
|
+
if rel.endswith(arch_suffix):
|
|
330
|
+
rel = rel[:-len(arch_suffix)]
|
|
331
|
+
# SUSE uname -r truncates the micro release (e.g. '160000.8' vs
|
|
332
|
+
# RPM release '160000.8.1'), so check for prefix match first
|
|
333
|
+
if host_highest.version == ver and \
|
|
334
|
+
(host_highest.release == rel or
|
|
335
|
+
host_highest.release.startswith(rel + '.')):
|
|
336
|
+
self.reboot_required = False
|
|
337
|
+
return
|
|
318
338
|
kernel_ver = ('', str(ver), str(rel))
|
|
319
339
|
host_highest_ver = ('', host_highest.version, host_highest.release)
|
|
320
340
|
if labelCompare(kernel_ver, host_highest_ver) == -1:
|
|
321
341
|
self.reboot_required = True
|
|
322
342
|
else:
|
|
323
343
|
self.reboot_required = False
|
|
324
|
-
|
|
344
|
+
|
|
345
|
+
def _get_deb_kernel_flavour(self, pkg_name):
|
|
346
|
+
"""Extract the flavour suffix from a DEB kernel package name.
|
|
347
|
+
|
|
348
|
+
e.g. 'linux-image-6.8.0-51-generic' → 'generic'
|
|
349
|
+
'linux-image-6.8.0-51-lowlatency' → 'lowlatency'
|
|
350
|
+
'linux-image-6.1.0-28-cloud-amd64' → 'cloud-amd64'
|
|
351
|
+
'linux-modules-extra-6.8.0-51-generic' → 'generic'
|
|
352
|
+
Returns None if the flavour cannot be determined.
|
|
353
|
+
"""
|
|
354
|
+
for prefix in self._deb_kernel_prefixes:
|
|
355
|
+
if pkg_name.startswith(prefix):
|
|
356
|
+
# strip prefix, then split version from flavour
|
|
357
|
+
# e.g. '6.8.0-51-generic' or '6.1.0-28-cloud-amd64'
|
|
358
|
+
remainder = pkg_name[len(prefix):]
|
|
359
|
+
# version parts are numeric/dotted, flavour starts after
|
|
360
|
+
# e.g. '6.8.0-51-generic' → parts=['6.8.0', '51', 'generic']
|
|
361
|
+
parts = remainder.split('-')
|
|
362
|
+
# find first non-numeric part (not starting with digit)
|
|
363
|
+
for i, part in enumerate(parts):
|
|
364
|
+
if part and not part[0].isdigit():
|
|
365
|
+
return '-'.join(parts[i:])
|
|
366
|
+
return None
|
|
367
|
+
return None
|
|
368
|
+
|
|
369
|
+
def _get_running_kernel_flavour(self):
|
|
370
|
+
"""Extract the flavour from the running kernel string.
|
|
371
|
+
|
|
372
|
+
e.g. '6.8.0-51-generic' → 'generic'
|
|
373
|
+
'6.8.0-51-lowlatency' → 'lowlatency'
|
|
374
|
+
'6.1.0-28-cloud-amd64' → 'cloud-amd64'
|
|
375
|
+
Returns None for RPM-style kernels (no flavour suffix).
|
|
376
|
+
"""
|
|
377
|
+
parts = self.kernel.split('-')
|
|
378
|
+
if len(parts) >= 2:
|
|
379
|
+
# find first non-numeric part after the version
|
|
380
|
+
for i, part in enumerate(parts):
|
|
381
|
+
if i > 0 and part and not part[0].isdigit():
|
|
382
|
+
return '-'.join(parts[i:])
|
|
383
|
+
return None
|
|
384
|
+
|
|
385
|
+
# longest prefixes first to avoid linux-modules- matching linux-modules-extra-
|
|
386
|
+
_deb_kernel_prefixes = [
|
|
387
|
+
'linux-image-unsigned-',
|
|
388
|
+
'linux-modules-extra-',
|
|
389
|
+
'linux-cloud-tools-',
|
|
390
|
+
'linux-image-uc-',
|
|
391
|
+
'linux-image-',
|
|
392
|
+
'linux-headers-',
|
|
393
|
+
'linux-modules-',
|
|
394
|
+
'linux-support-',
|
|
395
|
+
'linux-kbuild-',
|
|
396
|
+
'linux-tools-',
|
|
397
|
+
]
|
|
325
398
|
|
|
326
399
|
def find_kernel_updates(self, kernel_packages, repo_packages):
|
|
327
400
|
|
|
328
401
|
update_ids = []
|
|
402
|
+
self.reboot_required = False
|
|
403
|
+
|
|
404
|
+
deb_kernels = kernel_packages.filter(packagetype='D')
|
|
405
|
+
rpm_kernels = kernel_packages.filter(packagetype='R')
|
|
406
|
+
arch_kernels = kernel_packages.filter(packagetype='A')
|
|
407
|
+
|
|
408
|
+
update_ids.extend(self._find_rpm_kernel_updates(rpm_kernels, repo_packages))
|
|
409
|
+
update_ids.extend(self._find_deb_kernel_updates(deb_kernels, repo_packages))
|
|
410
|
+
update_ids.extend(self._find_arch_kernel_updates(arch_kernels, repo_packages))
|
|
411
|
+
|
|
412
|
+
self.save(update_fields=['reboot_required'])
|
|
413
|
+
return update_ids
|
|
414
|
+
|
|
415
|
+
def _find_rpm_kernel_updates(self, kernel_packages, repo_packages):
|
|
416
|
+
|
|
417
|
+
update_ids = []
|
|
418
|
+
|
|
419
|
+
# parse running kernel version for comparison
|
|
420
|
+
parts = self.kernel.split('-')
|
|
421
|
+
if len(parts) < 2:
|
|
422
|
+
return update_ids
|
|
423
|
+
ver, rel = parts[:2]
|
|
424
|
+
# strip arch suffix from uname -r release (e.g. '.x86_64')
|
|
425
|
+
arch_suffix = '.' + self.arch.name
|
|
426
|
+
if rel.endswith(arch_suffix):
|
|
427
|
+
rel = rel[:-len(arch_suffix)]
|
|
428
|
+
|
|
429
|
+
# deduplicate: only process each kernel package name once
|
|
430
|
+
processed_names = set()
|
|
431
|
+
|
|
329
432
|
for package in kernel_packages:
|
|
330
|
-
|
|
331
|
-
|
|
433
|
+
if package.name_id in processed_names:
|
|
434
|
+
continue
|
|
435
|
+
processed_names.add(package.name_id)
|
|
332
436
|
|
|
333
437
|
pu_q = Q(name=package.name)
|
|
334
|
-
|
|
335
|
-
for
|
|
336
|
-
|
|
337
|
-
|
|
438
|
+
|
|
439
|
+
# find repo highest for this kernel name
|
|
440
|
+
repo_highest = None
|
|
441
|
+
for pu in repo_packages.filter(pu_q):
|
|
442
|
+
if repo_highest is None or repo_highest.compare_version(pu) == -1:
|
|
338
443
|
repo_highest = pu
|
|
339
444
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
445
|
+
if repo_highest is None:
|
|
446
|
+
continue
|
|
447
|
+
|
|
448
|
+
# find host highest installed for reboot check
|
|
449
|
+
host_highest = None
|
|
450
|
+
running_package = None
|
|
451
|
+
for hp in self.packages.filter(pu_q):
|
|
452
|
+
if host_highest is None or host_highest.compare_version(hp) == -1:
|
|
344
453
|
host_highest = hp
|
|
454
|
+
# match installed package to running kernel
|
|
455
|
+
# SUSE uname -r truncates micro release ('160000.8' vs
|
|
456
|
+
# RPM '160000.8.1') so use prefix match with dot boundary
|
|
457
|
+
if hp.version == ver and \
|
|
458
|
+
(hp.release == rel or
|
|
459
|
+
hp.release.startswith(rel + '.')):
|
|
460
|
+
running_package = hp
|
|
461
|
+
|
|
462
|
+
# for the running kernel's flavour, compare running vs repo
|
|
463
|
+
# for other flavours, compare highest installed vs repo
|
|
464
|
+
if running_package:
|
|
465
|
+
base_package = running_package
|
|
466
|
+
else:
|
|
467
|
+
base_package = host_highest
|
|
345
468
|
|
|
346
|
-
if
|
|
347
|
-
uid = self.process_update(
|
|
469
|
+
if base_package and base_package.compare_version(repo_highest) == -1:
|
|
470
|
+
uid = self.process_update(base_package, repo_highest)
|
|
348
471
|
if uid is not None:
|
|
349
472
|
update_ids.append(uid)
|
|
350
473
|
|
|
351
|
-
|
|
474
|
+
# reboot check only on primary kernel packages
|
|
475
|
+
if host_highest and package.name.name in (
|
|
476
|
+
'kernel', 'kernel-core', 'kernel-debug-core',
|
|
477
|
+
'kernel-default', 'kernel-rt', 'kernel-azure',
|
|
478
|
+
'kernel-kvmsmall',
|
|
479
|
+
'kernel-uek', 'kernel-uki-virt', 'kernel-debug-uki-virt',
|
|
480
|
+
):
|
|
481
|
+
self.check_if_reboot_required(host_highest)
|
|
482
|
+
|
|
483
|
+
return update_ids
|
|
484
|
+
|
|
485
|
+
def _find_arch_kernel_updates(self, kernel_packages, repo_packages):
|
|
486
|
+
|
|
487
|
+
update_ids = []
|
|
488
|
+
|
|
489
|
+
for package in kernel_packages:
|
|
490
|
+
pu_q = Q(name=package.name)
|
|
491
|
+
|
|
492
|
+
repo_highest = None
|
|
493
|
+
for rp in repo_packages.filter(pu_q):
|
|
494
|
+
if repo_highest is None or repo_highest.compare_version(rp) == -1:
|
|
495
|
+
repo_highest = rp
|
|
496
|
+
|
|
497
|
+
if repo_highest is None:
|
|
498
|
+
continue
|
|
499
|
+
|
|
500
|
+
if package.compare_version(repo_highest) == -1:
|
|
501
|
+
uid = self.process_update(package, repo_highest)
|
|
502
|
+
if uid is not None:
|
|
503
|
+
update_ids.append(uid)
|
|
504
|
+
|
|
505
|
+
# reboot check for main kernel packages (not -headers)
|
|
506
|
+
# Arch uname -r format varies by flavour:
|
|
507
|
+
# linux: 6.12.8-arch1-1 (pkgver=6.12.8.arch1)
|
|
508
|
+
# linux-lts: 6.1.68-1-lts (pkgver=6.1.68)
|
|
509
|
+
# linux-zen: 6.12.8-zen1-1-zen (pkgver=6.12.8.zen1)
|
|
510
|
+
# The only reliable common part is the base version (first segment
|
|
511
|
+
# of uname -r) which maps to the numeric prefix of pkgver
|
|
512
|
+
if package.name.name in (
|
|
513
|
+
'linux', 'linux-lts', 'linux-zen', 'linux-hardened',
|
|
514
|
+
'linux-rt', 'linux-rt-lts',
|
|
515
|
+
):
|
|
516
|
+
running_base = self.kernel.split('-')[0] if self.kernel else ''
|
|
517
|
+
pkg_ver = package.version
|
|
518
|
+
# pkgver is either 'X.Y.Z' (lts) or 'X.Y.Z.flavourN' (others)
|
|
519
|
+
# check if the package version matches or extends the base
|
|
520
|
+
if pkg_ver != running_base and not pkg_ver.startswith(running_base + '.'):
|
|
521
|
+
self.reboot_required = True
|
|
522
|
+
|
|
523
|
+
return update_ids
|
|
524
|
+
|
|
525
|
+
def _find_deb_kernel_updates(self, kernel_packages, repo_packages):
|
|
526
|
+
|
|
527
|
+
update_ids = []
|
|
528
|
+
running_flavour = self._get_running_kernel_flavour()
|
|
529
|
+
|
|
530
|
+
# find the linux-image package matching the running kernel
|
|
531
|
+
running_kernel_pkg = None
|
|
532
|
+
for package in kernel_packages:
|
|
533
|
+
pkg_name = package.name.name
|
|
534
|
+
if pkg_name.startswith('linux-image-') and pkg_name.endswith(self.kernel):
|
|
535
|
+
running_kernel_pkg = package
|
|
536
|
+
break
|
|
537
|
+
|
|
538
|
+
processed_prefixes = set()
|
|
539
|
+
for package in kernel_packages:
|
|
540
|
+
pkg_name = package.name.name
|
|
541
|
+
flavour = self._get_deb_kernel_flavour(pkg_name)
|
|
542
|
+
|
|
543
|
+
# if we know the running flavour, only process matching packages
|
|
544
|
+
# if we don't (unflavoured kernel), process all kernel packages
|
|
545
|
+
if running_flavour and flavour != running_flavour:
|
|
546
|
+
continue
|
|
547
|
+
|
|
548
|
+
# determine the prefix (e.g. 'linux-image-')
|
|
549
|
+
prefix = None
|
|
550
|
+
for p in self._deb_kernel_prefixes:
|
|
551
|
+
if pkg_name.startswith(p):
|
|
552
|
+
prefix = p
|
|
553
|
+
break
|
|
554
|
+
if prefix is None or prefix in processed_prefixes:
|
|
555
|
+
continue
|
|
556
|
+
processed_prefixes.add(prefix)
|
|
557
|
+
|
|
558
|
+
# build endswith filter for flavoured kernels
|
|
559
|
+
name_filter = Q(
|
|
560
|
+
name__name__startswith=prefix,
|
|
561
|
+
packagetype='D',
|
|
562
|
+
)
|
|
563
|
+
if running_flavour:
|
|
564
|
+
name_filter &= Q(name__name__endswith=f'-{running_flavour}')
|
|
565
|
+
|
|
566
|
+
# find repo highest for this prefix+flavour
|
|
567
|
+
repo_highest = None
|
|
568
|
+
for rp in repo_packages.filter(name_filter):
|
|
569
|
+
if repo_highest is None or repo_highest.compare_version(rp) == -1:
|
|
570
|
+
repo_highest = rp
|
|
571
|
+
|
|
572
|
+
if repo_highest is None:
|
|
573
|
+
continue
|
|
574
|
+
|
|
575
|
+
# find the installed package matching the running kernel for this prefix
|
|
576
|
+
base_package = None
|
|
577
|
+
expected_name = prefix + self.kernel
|
|
578
|
+
for hp in self.packages.filter(name_filter):
|
|
579
|
+
if hp.name.name == expected_name:
|
|
580
|
+
base_package = hp
|
|
581
|
+
break
|
|
582
|
+
|
|
583
|
+
# fallback: if no running match, use the installed package we started with
|
|
584
|
+
if base_package is None:
|
|
585
|
+
base_package = package
|
|
586
|
+
|
|
587
|
+
if base_package.compare_version(repo_highest) == -1:
|
|
588
|
+
uid = self.process_update(base_package, repo_highest)
|
|
589
|
+
if uid is not None:
|
|
590
|
+
update_ids.append(uid)
|
|
591
|
+
|
|
592
|
+
# reboot check: see if a newer linux-image is installed but not running
|
|
593
|
+
# use compare_version (DEB semantics) instead of labelCompare
|
|
594
|
+
if running_kernel_pkg:
|
|
595
|
+
for package in kernel_packages:
|
|
596
|
+
if package.name.name.startswith('linux-image-'):
|
|
597
|
+
flavour = self._get_deb_kernel_flavour(package.name.name)
|
|
598
|
+
if running_flavour is None or flavour == running_flavour:
|
|
599
|
+
if running_kernel_pkg.compare_version(package) == -1:
|
|
600
|
+
self.reboot_required = True
|
|
601
|
+
break
|
|
602
|
+
|
|
352
603
|
return update_ids
|
|
353
604
|
|
|
354
605
|
|