The NBD protocol is adding an extension to let servers advertise initialization state to the client: whether the image contains holes, and whether it is known to read as all zeroes. For python, the hardest part was figuring out how to conditionally test things depending on new-enough libnbd (and that wasn't hard).
Note that the python bindings do not yet support extents, so this is one case where the new protocol addition is definitely useful when dealing with an initially-empty destination. Signed-off-by: Eric Blake <[email protected]> --- plugins/python/nbdkit-python-plugin.pod | 14 ++++++++++++++ plugins/python/python.c | 16 +++++++++++++++- tests/test-python-plugin.py | 8 +++++++- tests/test_python.py | 22 +++++++++++++++++++++- 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/plugins/python/nbdkit-python-plugin.pod b/plugins/python/nbdkit-python-plugin.pod index 4065ec7..c2d1257 100644 --- a/plugins/python/nbdkit-python-plugin.pod +++ b/plugins/python/nbdkit-python-plugin.pod @@ -245,6 +245,20 @@ contents will be garbage collected. # return nbdkit.CACHE_NONE or nbdkit.CACHE_EMULATE # or nbdkit.CACHE_NATIVE +=item C<init_sparse> + +(Optional) + + def init_sparse(h): + # return a boolean + +=item C<init_zero> + +(Optional) + + def init_zero(h): + # return a boolean + =item C<pread> (Required) diff --git a/plugins/python/python.c b/plugins/python/python.c index 5e2e526..5a4a702 100644 --- a/plugins/python/python.c +++ b/plugins/python/python.c @@ -1,5 +1,5 @@ /* nbdkit - * Copyright (C) 2013-2018 Red Hat Inc. + * Copyright (C) 2013-2020 Red Hat Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -871,6 +871,18 @@ py_can_cache (void *handle) return NBDKIT_CACHE_NONE; } +static int +py_init_sparse (void *handle) +{ + return boolean_callback (handle, "init_sparse", NULL); +} + +static int +py_init_zero (void *handle) +{ + return boolean_callback (handle, "init_zero", NULL); +} + #define py_config_help \ "script=<FILENAME> (required) The Python plugin to run.\n" \ "[other arguments may be used by the plugin that you load]" @@ -902,6 +914,8 @@ static struct nbdkit_plugin plugin = { .can_fast_zero = py_can_fast_zero, .can_fua = py_can_fua, .can_cache = py_can_cache, + .init_sparse = py_init_sparse, + .init_zero = py_init_zero, .pread = py_pread, .pwrite = py_pwrite, diff --git a/tests/test-python-plugin.py b/tests/test-python-plugin.py index 8e90bc2..0f3faaf 100644 --- a/tests/test-python-plugin.py +++ b/tests/test-python-plugin.py @@ -1,5 +1,5 @@ # nbdkit test plugin -# Copyright (C) 2019 Red Hat Inc. +# Copyright (C) 2019-2020 Red Hat Inc. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -95,6 +95,12 @@ def can_cache (h): elif cache == "native": return nbdkit.CACHE_NATIVE +def init_sparse (h): + return cfg.get ('init_sparse', False) + +def init_zero (h): + return cfg.get ('init_zero', False) + def pread (h, buf, offset, flags): assert flags == 0 end = offset + len(buf) diff --git a/tests/test_python.py b/tests/test_python.py index 6b9f297..e19b895 100755 --- a/tests/test_python.py +++ b/tests/test_python.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # nbdkit -# Copyright (C) 2019 Red Hat Inc. +# Copyright (C) 2019-2020 Red Hat Inc. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -155,6 +155,26 @@ class Test (unittest.TestCase): # Not yet implemented: can_extents. + def test_init_sparse_false (self): + self.connect ({"size": 512, "init_sparse": False}) + if hasattr (self.h, "get_init_flags"): + assert not self.h.get_init_flags () & nbd.INIT_SPARSE + + def test_init_sparse_true (self): + self.connect ({"size": 512, "init_sparse": True}) + if hasattr (self.h, "get_init_flags"): + assert self.h.get_init_flags () & nbd.INIT_SPARSE + + def test_init_zero_false (self): + self.connect ({"size": 512, "init_zero": False}) + if hasattr (self.h, "get_init_flags"): + assert not self.h.get_init_flags () & nbd.INIT_ZERO + + def test_init_zero_true (self): + self.connect ({"size": 512, "init_zero": True}) + if hasattr (self.h, "get_init_flags"): + assert self.h.get_init_flags () & nbd.INIT_ZERO + def test_pread (self): """Test pread.""" self.connect ({"size": 512}) -- 2.24.1 _______________________________________________ Libguestfs mailing list [email protected] https://www.redhat.com/mailman/listinfo/libguestfs
