[PATCH 6/6] virsh: blockresize: Use VIR_DOMAIN_BLOCK_RESIZE_EXTEND when available and introduce --allow-shrink

Peter Krempa via Devel posted 6 patches 7 hours ago
[PATCH 6/6] virsh: blockresize: Use VIR_DOMAIN_BLOCK_RESIZE_EXTEND when available and introduce --allow-shrink
Posted by Peter Krempa via Devel 7 hours ago
From: Peter Krempa <pkrempa@redhat.com>

Use the new VIR_DOMAIN_BLOCK_RESIZE_PROBE_FLAGS flag to probe for
VIR_DOMAIN_BLOCK_RESIZE_EXTEND and use it if available.

This will give users the same protection as with --extend in the default
case.

IMPORTANT: This patch changes behaviour for users who want to
shrink their VM's block device knowingly. Such users, when using a newer
daemon will be required to pass --allow-shrink now.

I've contemplated either renaming the whole command to preserve
functionality for the existing one and deprecating 'virsh blockresize'
or adding just the '--extend', but unfortunately neither of those in the
end looked appealing to me.

As shrinking filesystems is much more invloved and much less common the
benefit of preventing accidental data loss should outweigh the breakage
from the change.

To aleviate issues with scripts virsh now also provides the
'--probe-arguments' option to allow safe probe if virsh supports this
new argument.

Closes: https://gitlab.com/libvirt/libvirt/-/work_items/789
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
---
 docs/manpages/virsh.rst | 11 ++++++++++-
 tools/virsh-domain.c    | 16 ++++++++++++++++
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index 9ede859aaf..5138591595 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -1657,7 +1657,7 @@ blockresize

 ::

-   blockresize domain path ([size] | [--capacity]) [--extend]
+   blockresize domain path ([size] | [--capacity]) [--extend] [--allow-shrink]

 Resize a block device of domain while the domain is running, *path*
 specifies the absolute path of the block device; it corresponds
@@ -1670,6 +1670,15 @@ smaller than the old size, thus prevents (accidental) shrinking of the block
 device which may lead to data loss. Users are encouraged to always use this
 flag unless communicating with an older hypervisor.

+As of libvirt 12.3.0 the 'virsh blockresize' command now probes whether the
+hypervisor supports enforcing that the device is not shrunk accidentally and
+if it is supported this feature will be used as a precaution from accidental
+data loss even at the cost of change of behaviour. With older hypervisors
+which do not support the feature the protection will not be avaliable.
+Users wanting to shrink the block device must use the *--allow-shrink*
+flag. In scripts it's possible to use the *--probe-arguments* flag to determine
+if the flag is supported.
+
 For image formats without metadata (raw) stored inside fixed-size storage (e.g.
 block devices) the --capacity flag can be used to resize the device to the
 full size of the backing device.
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 08a1ce3953..95ce4dc845 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -3343,6 +3343,10 @@ static const vshCmdOptDef opts_blockresize[] = {
      .type = VSH_OT_BOOL,
      .help = N_("ensure that the new size is larger than actual capacity (prevent shrink)")
     },
+    {.name = "allow-shrink",
+     .type = VSH_OT_BOOL,
+     .help = N_("disable size checks so that device can be shrunk")
+    },
     {.name = NULL}
 };

@@ -3378,6 +3382,18 @@ cmdBlockresize(vshControl *ctl, const vshCmd *cmd)
     if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
         return false;

+    /* probe for support of VIR_DOMAIN_BLOCK_RESIZE_EXTEND and use it if it's
+     * supported to prevent mishaps even at the cost of usability change */
+    if (!vshCommandOptBool(cmd, "allow-shrink")) {
+        if (virDomainBlockResize(dom, "", 0,
+                                 VIR_DOMAIN_BLOCK_RESIZE_EXTEND |
+                                 VIR_DOMAIN_BLOCK_RESIZE_PROBE_FLAGS) == 0) {
+            flags |= VIR_DOMAIN_BLOCK_RESIZE_EXTEND;
+        } else {
+            vshResetLibvirtError();
+        }
+    }
+
     if (virDomainBlockResize(dom, path, size, flags) < 0) {
         vshError(ctl, _("Failed to resize block device '%1$s'"), path);
         return false;
-- 
2.53.0