From 9bcaddbe97067f10e643a7d99fa13716126f6e60 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Tue, 25 Aug 2020 14:09:18 +0200 Subject: [PATCH 1/4] mdraid: Do not ignore errors from bd_md_canonicalize_uuid in bd_md_examine --- src/plugins/mdraid.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/plugins/mdraid.c b/src/plugins/mdraid.c index b97bc641..d41b6372 100644 --- a/src/plugins/mdraid.c +++ b/src/plugins/mdraid.c @@ -983,12 +983,24 @@ BDMDExamineData* bd_md_examine (const gchar *device, GError **error) { orig_data = ret->uuid; if (orig_data) { ret->uuid = bd_md_canonicalize_uuid (orig_data, error); + if (!ret->uuid) { + g_prefix_error (error, "Failed to canonicalize MD UUID '%s': ", orig_data); + g_free (orig_data); + bd_md_examine_data_free (ret); + return NULL; + } g_free (orig_data); } orig_data = ret->dev_uuid; if (orig_data) { ret->dev_uuid = bd_md_canonicalize_uuid (orig_data, error); + if (!ret->uuid) { + g_prefix_error (error, "Failed to canonicalize MD UUID '%s': ", orig_data); + g_free (orig_data); + bd_md_examine_data_free (ret); + return NULL; + } g_free (orig_data); } -- 2.37.1 From 1805734e8315d5fb73f036dae043312c88f3c3ec Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Tue, 25 Aug 2020 14:12:52 +0200 Subject: [PATCH 2/4] mdraid: Try harder to get container UUID in bd_md_examine For containers UUID is not printed in 'mdadm --examine' but it is printed when using the '--export' option. --- src/plugins/mdraid.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/plugins/mdraid.c b/src/plugins/mdraid.c index d41b6372..3a23cf2e 100644 --- a/src/plugins/mdraid.c +++ b/src/plugins/mdraid.c @@ -1023,6 +1023,17 @@ BDMDExamineData* bd_md_examine (const gchar *device, GError **error) { value++; g_free (ret->level); ret->level = g_strdup (value); + } else if (!ret->uuid && g_str_has_prefix (output_fields[i], "MD_UUID=")) { + value = strchr (output_fields[i], '='); + value++; + ret->uuid = bd_md_canonicalize_uuid (value, error); + if (!ret->uuid) { + g_prefix_error (error, "Failed to canonicalize MD UUID '%s': ", orig_data); + g_free (orig_data); + bd_md_examine_data_free (ret); + g_strfreev (output_fields); + return NULL; + } } g_strfreev (output_fields); -- 2.37.1 From 166756338f90d90b32ae0989db706dd52f7df234 Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Thu, 4 Aug 2022 12:47:53 +0200 Subject: [PATCH 3/4] mdraid: Try harder to get container UUID in bd_md_detail Similarly to bd_md_examine (see a10ad4e0), "mdadm --detail" doesn't contain container UUID, we need to need "--export" for that. --- src/plugins/mdraid.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/plugins/mdraid.c b/src/plugins/mdraid.c index 3a23cf2e..67bdc1f9 100644 --- a/src/plugins/mdraid.c +++ b/src/plugins/mdraid.c @@ -1093,13 +1093,16 @@ BDMDExamineData* bd_md_examine (const gchar *device, GError **error) { * Tech category: %BD_MD_TECH_MDRAID-%BD_MD_TECH_MODE_QUERY */ BDMDDetailData* bd_md_detail (const gchar *raid_spec, GError **error) { - const gchar *argv[] = {"mdadm", "--detail", NULL, NULL}; + const gchar *argv[] = {"mdadm", "--detail", NULL, NULL, NULL}; gchar *output = NULL; gboolean success = FALSE; GHashTable *table = NULL; guint num_items = 0; gchar *orig_uuid = NULL; - gchar *mdadm_spec = NULL; + g_autofree gchar *mdadm_spec = NULL; + gchar *value = NULL; + gchar **output_fields = NULL; + guint i = 0; BDMDDetailData *ret = NULL; if (!check_deps (&avail_deps, DEPS_MDADM_MASK, deps, DEPS_LAST, &deps_check_lock, error)) @@ -1113,16 +1116,13 @@ BDMDDetailData* bd_md_detail (const gchar *raid_spec, GError **error) { argv[2] = mdadm_spec; success = bd_utils_exec_and_capture_output (argv, NULL, &output, error); - if (!success) { - g_free (mdadm_spec); + if (!success) /* error is already populated */ return NULL; - } table = parse_mdadm_vars (output, "\n", ":", &num_items); g_free (output); if (!table || (num_items == 0)) { - g_free (mdadm_spec); /* something bad happened or some expected items were missing */ g_set_error (error, BD_MD_ERROR, BD_MD_ERROR_PARSE, "Failed to parse mddetail data"); if (table) @@ -1132,7 +1132,6 @@ BDMDDetailData* bd_md_detail (const gchar *raid_spec, GError **error) { ret = get_detail_data_from_table (table, TRUE); if (!ret) { - g_free (mdadm_spec); g_set_error (error, BD_MD_ERROR, BD_MD_ERROR_PARSE, "Failed to get mddetail data"); return NULL; } @@ -1145,7 +1144,35 @@ BDMDDetailData* bd_md_detail (const gchar *raid_spec, GError **error) { g_free (orig_uuid); } - g_free (mdadm_spec); + if (!ret->uuid) { + argv[2] = "--export"; + argv[3] = mdadm_spec; + success = bd_utils_exec_and_capture_output (argv, NULL, &output, error); + if (!success) { + /* error is already populated */ + bd_md_detail_data_free (ret); + return NULL; + } + + /* try to get a better information about RAID level because it may be + missing in the output without --export */ + output_fields = g_strsplit (output, "\n", 0); + g_free (output); + output = NULL; + for (i = 0; (i < g_strv_length (output_fields) - 1); i++) + if (g_str_has_prefix (output_fields[i], "MD_UUID=")) { + value = strchr (output_fields[i], '='); + value++; + ret->uuid = bd_md_canonicalize_uuid (value, error); + if (!ret->uuid) { + g_prefix_error (error, "Failed to canonicalize MD UUID '%s': ", value); + bd_md_detail_data_free (ret); + g_strfreev (output_fields); + return NULL; + } + } + g_strfreev (output_fields); + } return ret; } -- 2.37.1 From 25dd2f8c7cc3cf540902fc40e808faabda3c691a Mon Sep 17 00:00:00 2001 From: Vojtech Trefny Date: Thu, 4 Aug 2022 12:51:48 +0200 Subject: [PATCH 4/4] Add a test case for DDF arrays/containers --- tests/mdraid_test.py | 51 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/tests/mdraid_test.py b/tests/mdraid_test.py index 0b2bdc9b..38f43a0d 100644 --- a/tests/mdraid_test.py +++ b/tests/mdraid_test.py @@ -6,7 +6,7 @@ from contextlib import contextmanager import overrides_hack import six -from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test +from utils import create_sparse_tempfile, create_lio_device, delete_lio_device, fake_utils, fake_path, TestTags, tag_test, run_command from gi.repository import BlockDev, GLib @@ -90,14 +90,16 @@ class MDNoDevTestCase(MDTest): class MDTestCase(MDTest): + _sparse_size = 10 * 1024**2 + def setUp(self): if os.uname()[-1] == "i686": self.skipTest("Skipping hanging MD RAID tests on i686") self.addCleanup(self._clean_up) - self.dev_file = create_sparse_tempfile("md_test", 10 * 1024**2) - self.dev_file2 = create_sparse_tempfile("md_test", 10 * 1024**2) - self.dev_file3 = create_sparse_tempfile("md_test", 10 * 1024**2) + self.dev_file = create_sparse_tempfile("md_test", self._sparse_size) + self.dev_file2 = create_sparse_tempfile("md_test", self._sparse_size) + self.dev_file3 = create_sparse_tempfile("md_test", self._sparse_size) try: self.loop_dev = create_lio_device(self.dev_file) @@ -586,6 +588,47 @@ class MDTestRequestSyncAction(MDTestCase): action = f.read().strip() self.assertEqual(action, "check") + +class MDTestDDFRAID(MDTestCase): + + _sparse_size = 50 * 1024**2 + + def _clean_up(self): + try: + BlockDev.md_deactivate("bd_test_ddf") + except: + pass + try: + BlockDev.md_deactivate(BlockDev.md_node_from_name("bd_test_ddf")) + except: + pass + + super(MDTestDDFRAID, self)._clean_up() + + def test_examine_ddf_container(self): + succ = BlockDev.md_create("bd_test_md", "container", + [self.loop_dev, self.loop_dev2], + 0, "ddf", False) + self.assertTrue(succ) + + # we cannot create the array with libblockdev because we cannot pass the --raid-devices option + ret, _out, err = run_command("mdadm --create /dev/md/bd_test_ddf --run --level=raid0 --raid-devices=2 /dev/md/bd_test_md") + self.assertEqual(ret, 0, msg="Failed to create RAID for DDF test: %s" % err) + + edata = BlockDev.md_examine(self.loop_dev) + self.assertIsNotNone(edata) + self.assertIsNotNone(edata.uuid) + self.assertEqual(edata.level, "container") + self.assertEqual(edata.metadata, "ddf") + + ddata = BlockDev.md_detail("bd_test_md") + self.assertIsNotNone(ddata) + self.assertIsNotNone(ddata.uuid) + self.assertEqual(ddata.uuid, edata.uuid) + self.assertEqual(ddata.level, "container") + self.assertEqual(ddata.metadata, "ddf") + + class FakeMDADMutilTest(MDTest): # no setUp nor tearDown needed, we are gonna use fake utils @tag_test(TestTags.NOSTORAGE) -- 2.37.1