diff options
author | Daniel P. Berrangé <berrange@redhat.com> | 2021-11-24 18:27:53 +0000 |
---|---|---|
committer | Daniel P. Berrangé <berrange@redhat.com> | 2022-02-04 14:14:49 +0000 |
commit | c0ba8e5d0b74625f1236c904d951f4bd6221818e (patch) | |
tree | fc5797e40c89138e3498931532bcb4c62b45a45a | |
parent | cb34f72a4045b9beade1222cb393a141746e227c (diff) | |
download | libosinfo-c0ba8e5d0b74625f1236c904d951f4bd6221818e.tar.gz |
osinfo: add API for resolving multiple media matches
A provided media object might match multiple entries from the
database. Add an API that allows for this possibility to let
applications decide how to handle it.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
-rw-r--r-- | osinfo/libosinfo.syms | 1 | ||||
-rw-r--r-- | osinfo/osinfo_db.c | 36 | ||||
-rw-r--r-- | osinfo/osinfo_db.h | 2 | ||||
-rw-r--r-- | tests/dbdata/os/libosinfo.org/test-db-media-dupe1.xml | 17 | ||||
-rw-r--r-- | tests/dbdata/os/libosinfo.org/test-db-media-dupe2.xml | 17 | ||||
-rw-r--r-- | tests/dbdata/os/libosinfo.org/test-db-media-dupe3.xml | 17 | ||||
-rw-r--r-- | tests/dbdata/os/libosinfo.org/test-db-media-dupe4.xml | 17 | ||||
-rw-r--r-- | tests/test-db.c | 193 |
8 files changed, 300 insertions, 0 deletions
diff --git a/osinfo/libosinfo.syms b/osinfo/libosinfo.syms index a49678c..5c4221d 100644 --- a/osinfo/libosinfo.syms +++ b/osinfo/libosinfo.syms @@ -639,6 +639,7 @@ LIBOSINFO_1.8.0 { LIBOSINFO_1.10.0 { global: + osinfo_db_identify_medialist; osinfo_media_matches; osinfo_os_get_complete_firmware_list; osinfo_tree_matches; diff --git a/osinfo/osinfo_db.c b/osinfo/osinfo_db.c index 13ff04f..7b5ea9b 100644 --- a/osinfo/osinfo_db.c +++ b/osinfo/osinfo_db.c @@ -797,6 +797,13 @@ static void fill_media(OsinfoDb *db, OsinfoMedia *media, * the media could be identified, its OsinfoEntify::id and OsinfoMedia::os * properties will be set. * + * The match for @media in @db is not guaranteed to be unique and + * this method will only return the first match found. The order + * in which matches are identified is not guaranteed, so when there + * are multiple matches, the returned match may vary over time. + * Applications are recommended to use the #osinfo_db_identify_all_media + * method instead to receive all matched media. + * * Returns: TRUE if @media was found in @db, FALSE otherwise * * Since: 0.2.3 @@ -821,6 +828,35 @@ gboolean osinfo_db_identify_media(OsinfoDb *db, OsinfoMedia *media) return TRUE; } +/** + * osinfo_db_identify_medialist: + * @db: an #OsinfoDb database + * @media: the installation media data + * + * Try to match a newly created @media with a media description from @db. + * The return list will contain any #OsinfoMedia instances from @db that + * matched @media. Usuaully there will only be one match returned, but + * applications should be prepared to deal with multiple matches. The + * returned #OsinfoMedia instances will have their OsinfoEntify::id and + * OsinfoMedia::os properties will be set, while @media is left unmodified. + * + * Returns: (transfer full): a list containing any matches for @media found in @db + * + * Since: 1.10.0 + */ +OsinfoMediaList *osinfo_db_identify_medialist(OsinfoDb *db, OsinfoMedia *media) +{ + OsinfoMediaList *matched_media = osinfo_medialist_new(); + + g_return_val_if_fail(OSINFO_IS_MEDIA(media), FALSE); + g_return_val_if_fail(OSINFO_IS_DB(db), FALSE); + + osinfo_db_guess_os_from_media_internal(db, media, matched_media, + FALSE, NULL); + + return matched_media; +} + /* * Fill @matched_tree with all OsinfoOs in @oss * that match @tree. diff --git a/osinfo/osinfo_db.h b/osinfo/osinfo_db.h index 31ee7a0..aee2e64 100644 --- a/osinfo/osinfo_db.h +++ b/osinfo/osinfo_db.h @@ -71,6 +71,8 @@ OsinfoOs *osinfo_db_guess_os_from_media(OsinfoDb *db, OsinfoMedia **matched_media); gboolean osinfo_db_identify_media(OsinfoDb *db, OsinfoMedia *media); +OsinfoMediaList *osinfo_db_identify_medialist(OsinfoDb *db, + OsinfoMedia *media); G_DEPRECATED_FOR(osinfo_db_identify_tree) OsinfoOs *osinfo_db_guess_os_from_tree(OsinfoDb *db, diff --git a/tests/dbdata/os/libosinfo.org/test-db-media-dupe1.xml b/tests/dbdata/os/libosinfo.org/test-db-media-dupe1.xml new file mode 100644 index 0000000..312197d --- /dev/null +++ b/tests/dbdata/os/libosinfo.org/test-db-media-dupe1.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<libosinfo version="0.0.1"> + <os id="http://libosinfo.org/test/db/media-dupe1"> + <short-id>db-media-dupe1</short-id> + <name>DB Media Dupe1</name> + <version>unknown</version> + <vendor>libosinfo.org</vendor> + <family>test</family> + + <media arch="i686"> + <iso> + <volume-id>dupe</volume-id> + <system-id>LINUX</system-id> + </iso> + </media> + </os> +</libosinfo> diff --git a/tests/dbdata/os/libosinfo.org/test-db-media-dupe2.xml b/tests/dbdata/os/libosinfo.org/test-db-media-dupe2.xml new file mode 100644 index 0000000..152a6a4 --- /dev/null +++ b/tests/dbdata/os/libosinfo.org/test-db-media-dupe2.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<libosinfo version="0.0.1"> + <os id="http://libosinfo.org/test/db/media-dupe2"> + <short-id>db-media-dupe2</short-id> + <name>DB Media Dupe2</name> + <version>unknown</version> + <vendor>libosinfo.org</vendor> + <family>test</family> + + <media arch="i686"> + <iso> + <volume-id>dupe</volume-id> + <system-id>LINUX</system-id> + </iso> + </media> + </os> +</libosinfo> diff --git a/tests/dbdata/os/libosinfo.org/test-db-media-dupe3.xml b/tests/dbdata/os/libosinfo.org/test-db-media-dupe3.xml new file mode 100644 index 0000000..215bbf9 --- /dev/null +++ b/tests/dbdata/os/libosinfo.org/test-db-media-dupe3.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<libosinfo version="0.0.1"> + <os id="http://libosinfo.org/test/db/media-dupe3"> + <short-id>db-media-dupe3</short-id> + <name>DB Media Dupe3</name> + <version>unknown</version> + <vendor>libosinfo.org</vendor> + <family>test</family> + + <media arch="ppc64"> + <iso> + <volume-id>dupe</volume-id> + <system-id>LINUX</system-id> + </iso> + </media> + </os> +</libosinfo> diff --git a/tests/dbdata/os/libosinfo.org/test-db-media-dupe4.xml b/tests/dbdata/os/libosinfo.org/test-db-media-dupe4.xml new file mode 100644 index 0000000..b2b2075 --- /dev/null +++ b/tests/dbdata/os/libosinfo.org/test-db-media-dupe4.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<libosinfo version="0.0.1"> + <os id="http://libosinfo.org/test/db/media-dupe4"> + <short-id>db-media-dupe4</short-id> + <name>DB Media Dupe4</name> + <version>unknown</version> + <vendor>libosinfo.org</vendor> + <family>test</family> + + <media arch="all"> + <iso> + <volume-id>dupe</volume-id> + <system-id>LINUX</system-id> + </iso> + </media> + </os> +</libosinfo> diff --git a/tests/test-db.c b/tests/test-db.c index 32c2835..ac5bfed 100644 --- a/tests/test-db.c +++ b/tests/test-db.c @@ -529,6 +529,198 @@ test_identify_media(void) } +static void +test_identify_all_media(void) +{ + OsinfoLoader *loader = osinfo_loader_new(); + OsinfoDb *db; + OsinfoMedia *media, *newmedia; + OsinfoMediaList *medialist; + OsinfoOs *os; + OsinfoInstallScriptList *scripts; + GError *error = NULL; + int i; + gboolean seenDupe1, seenDupe2, seenDupe3, seenDupe4; + gboolean seenRolling, seenVersioned; + + osinfo_loader_process_path(loader, SRCDIR "/tests/dbdata", &error); + g_assert_no_error(error); + db = osinfo_loader_get_db(loader); + + media = osinfo_media_new("foo", "ppc64le"); + osinfo_entity_set_param(OSINFO_ENTITY(media), + OSINFO_MEDIA_PROP_VOLUME_ID, + "DB Media"); + osinfo_entity_set_param(OSINFO_ENTITY(media), + OSINFO_MEDIA_PROP_SYSTEM_ID, + "LINUX"); + + medialist = osinfo_db_identify_medialist(db, media); + g_assert_nonnull(medialist); + g_assert_cmpint(osinfo_list_get_length(OSINFO_LIST(medialist)), ==, 1); + newmedia = OSINFO_MEDIA(osinfo_list_get_nth(OSINFO_LIST(medialist), 0)); + g_object_unref(medialist); + g_assert_cmpstr(osinfo_media_get_architecture(newmedia), ==, "ppc64le"); + g_assert_true(osinfo_media_get_live(newmedia)); + g_assert_true(osinfo_media_get_installer(newmedia)); + g_assert_false(osinfo_media_supports_installer_script(newmedia)); + g_assert_cmpint(osinfo_media_get_installer_reboots(newmedia), ==, 6); + g_assert_false(osinfo_media_get_eject_after_install(newmedia)); + g_assert_cmpstr(osinfo_media_get_kernel_path(newmedia), ==, "isolinux/vmlinuz"); + g_assert_cmpstr(osinfo_media_get_initrd_path(newmedia), ==, "isolinux/initrd.img"); + scripts = osinfo_media_get_install_script_list(newmedia); + g_assert_nonnull(scripts); + g_assert_cmpint(osinfo_list_get_length(OSINFO_LIST(scripts)), ==, 1); + os = osinfo_media_get_os(newmedia); + g_assert_nonnull(os); + g_assert_cmpstr(osinfo_entity_get_id(OSINFO_ENTITY(os)), ==, "http://libosinfo.org/test/db/media"); + g_object_unref(scripts); + + media = osinfo_media_new("foo", "ppc64le"); + osinfo_entity_set_param(OSINFO_ENTITY(media), + OSINFO_MEDIA_PROP_VOLUME_ID, + "Media DB"); + osinfo_entity_set_param(OSINFO_ENTITY(media), + OSINFO_MEDIA_PROP_SYSTEM_ID, + "LINUX"); + + medialist = osinfo_db_identify_medialist(db, media); + g_assert_cmpint(osinfo_list_get_length(OSINFO_LIST(medialist)), ==, 0); + g_object_unref(medialist); + g_object_unref(media); + + /* Matching against an "all" architecture */ + media = osinfo_media_new("foo", "x86_64"); + osinfo_entity_set_param(OSINFO_ENTITY(media), + OSINFO_MEDIA_PROP_VOLUME_ID, + "bootimg"); + medialist = osinfo_db_identify_medialist(db, media); + g_assert_cmpint(osinfo_list_get_length(OSINFO_LIST(medialist)), ==, 1); + newmedia = OSINFO_MEDIA(osinfo_list_get_nth(OSINFO_LIST(medialist), 0)); + g_assert_cmpstr(osinfo_media_get_architecture(newmedia), ==, "all"); + g_object_unref(medialist); + g_object_unref(media); + + /* Matching against a known architecture, which has to have precedence */ + media = osinfo_media_new("foo", "i686"); + osinfo_entity_set_param(OSINFO_ENTITY(media), + OSINFO_MEDIA_PROP_VOLUME_ID, + "bootimg"); + osinfo_entity_set_param(OSINFO_ENTITY(media), + OSINFO_MEDIA_PROP_SYSTEM_ID, + "LINUX"); + medialist = osinfo_db_identify_medialist(db, media); + g_assert_cmpint(osinfo_list_get_length(OSINFO_LIST(medialist)), ==, 1); + newmedia = OSINFO_MEDIA(osinfo_list_get_nth(OSINFO_LIST(medialist), 0)); + g_assert_cmpstr(osinfo_media_get_architecture(newmedia), ==, "i686"); + g_object_unref(medialist); + g_object_unref(media); + + /* Should return both the version and non-versioned rolling OS matches */ + media = osinfo_media_new("foo", "x86_64"); + osinfo_entity_set_param(OSINFO_ENTITY(media), + OSINFO_MEDIA_PROP_VOLUME_ID, + "ROLLING_VERSIONED"); + medialist = osinfo_db_identify_medialist(db, media); + g_assert_cmpint(osinfo_list_get_length(OSINFO_LIST(medialist)), ==, 2); + seenVersioned = seenRolling = FALSE; + for (i = 0; i < 2; i++) { + newmedia = OSINFO_MEDIA(osinfo_list_get_nth(OSINFO_LIST(medialist), i)); + os = osinfo_media_get_os(newmedia); + g_assert_nonnull(os); + if (g_str_equal(osinfo_product_get_short_id(OSINFO_PRODUCT(os)), "versioned")) { + g_assert_false(seenVersioned); + seenVersioned = TRUE; + } + if (g_str_equal(osinfo_product_get_short_id(OSINFO_PRODUCT(os)), "rolling")) { + g_assert_false(seenRolling); + seenRolling = TRUE; + } + } + g_assert(seenVersioned && seenRolling); + g_object_unref(medialist); + g_object_unref(media); + + /* Matching against a image with many matches. Should match two OS + * with corresponding arch, and one with fallback arch */ + media = osinfo_media_new("foo", "i686"); + osinfo_entity_set_param(OSINFO_ENTITY(media), + OSINFO_MEDIA_PROP_VOLUME_ID, + "dupe"); + osinfo_entity_set_param(OSINFO_ENTITY(media), + OSINFO_MEDIA_PROP_SYSTEM_ID, + "LINUX"); + medialist = osinfo_db_identify_medialist(db, media); + g_assert_cmpint(osinfo_list_get_length(OSINFO_LIST(medialist)), ==, 3); + seenDupe1 = seenDupe2 = seenDupe3 = seenDupe4 = FALSE; + for (i = 0; i < 3; i++) { + newmedia = OSINFO_MEDIA(osinfo_list_get_nth(OSINFO_LIST(medialist), i)); + os = osinfo_media_get_os(newmedia); + g_assert_nonnull(os); + if (g_str_equal(osinfo_product_get_short_id(OSINFO_PRODUCT(os)), "db-media-dupe1")) { + g_assert_false(seenDupe1); + seenDupe1 = TRUE; + } + if (g_str_equal(osinfo_product_get_short_id(OSINFO_PRODUCT(os)), "db-media-dupe2")) { + g_assert_false(seenDupe2); + seenDupe2 = TRUE; + } + if (g_str_equal(osinfo_product_get_short_id(OSINFO_PRODUCT(os)), "db-media-dupe3")) { + g_assert_false(seenDupe3); + seenDupe3 = TRUE; + } + if (g_str_equal(osinfo_product_get_short_id(OSINFO_PRODUCT(os)), "db-media-dupe4")) { + g_assert_false(seenDupe4); + seenDupe4 = TRUE; + } + } + g_assert(seenDupe1 && seenDupe2 && !seenDupe3 && seenDupe4); + + g_object_unref(medialist); + g_object_unref(media); + + /* Matching without arch against a image with many matches. + * Should match all OS regardless of their media arch */ + media = osinfo_media_new("foo", NULL); + osinfo_entity_set_param(OSINFO_ENTITY(media), + OSINFO_MEDIA_PROP_VOLUME_ID, + "dupe"); + osinfo_entity_set_param(OSINFO_ENTITY(media), + OSINFO_MEDIA_PROP_SYSTEM_ID, + "LINUX"); + medialist = osinfo_db_identify_medialist(db, media); + g_assert_cmpint(osinfo_list_get_length(OSINFO_LIST(medialist)), ==, 4); + seenDupe1 = seenDupe2 = seenDupe3 = seenDupe4 = FALSE; + for (i = 0; i < 4; i++) { + newmedia = OSINFO_MEDIA(osinfo_list_get_nth(OSINFO_LIST(medialist), i)); + os = osinfo_media_get_os(newmedia); + g_assert_nonnull(os); + if (g_str_equal(osinfo_product_get_short_id(OSINFO_PRODUCT(os)), "db-media-dupe1")) { + g_assert_false(seenDupe1); + seenDupe1 = TRUE; + } + if (g_str_equal(osinfo_product_get_short_id(OSINFO_PRODUCT(os)), "db-media-dupe2")) { + g_assert_false(seenDupe2); + seenDupe2 = TRUE; + } + if (g_str_equal(osinfo_product_get_short_id(OSINFO_PRODUCT(os)), "db-media-dupe3")) { + g_assert_false(seenDupe3); + seenDupe3 = TRUE; + } + if (g_str_equal(osinfo_product_get_short_id(OSINFO_PRODUCT(os)), "db-media-dupe4")) { + g_assert_false(seenDupe4); + seenDupe4 = TRUE; + } + } + g_assert(seenDupe1 && seenDupe2 && seenDupe3 && seenDupe4); + + g_object_unref(medialist); + g_object_unref(media); + + g_object_unref(loader); +} + + static OsinfoTree * create_tree(const gchar *arch, const gchar *treeinfo_arch) { @@ -611,6 +803,7 @@ main(int argc, char *argv[]) g_test_add_func("/db/prop_os", test_prop_os); g_test_add_func("/db/rel_os", test_rel_os); g_test_add_func("/db/identify_media", test_identify_media); + g_test_add_func("/db/identify_all_media", test_identify_all_media); g_test_add_func("/db/identify_tree", test_identify_tree); /* Upfront so we don't confuse valgrind */ |