summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel P. Berrangé <berrange@redhat.com>2021-11-24 18:27:53 +0000
committerDaniel P. Berrangé <berrange@redhat.com>2022-02-04 14:14:49 +0000
commitc0ba8e5d0b74625f1236c904d951f4bd6221818e (patch)
treefc5797e40c89138e3498931532bcb4c62b45a45a
parentcb34f72a4045b9beade1222cb393a141746e227c (diff)
downloadlibosinfo-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.syms1
-rw-r--r--osinfo/osinfo_db.c36
-rw-r--r--osinfo/osinfo_db.h2
-rw-r--r--tests/dbdata/os/libosinfo.org/test-db-media-dupe1.xml17
-rw-r--r--tests/dbdata/os/libosinfo.org/test-db-media-dupe2.xml17
-rw-r--r--tests/dbdata/os/libosinfo.org/test-db-media-dupe3.xml17
-rw-r--r--tests/dbdata/os/libosinfo.org/test-db-media-dupe4.xml17
-rw-r--r--tests/test-db.c193
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 */