Blame SOURCES/0016-RHV-outputs-limit-copied-disk-count-to-23.patch

c1a9fa
From 50a74177b3577952159d87335cf40c0ad3e51b4d Mon Sep 17 00:00:00 2001
c1a9fa
From: Laszlo Ersek <lersek@redhat.com>
c1a9fa
Date: Fri, 17 Jun 2022 11:53:37 +0200
c1a9fa
Subject: [PATCH] RHV outputs: limit copied disk count to 23
c1a9fa
c1a9fa
We currently support virtio-blk (commonly) or IDE (unusually) for exposing
c1a9fa
disks to the converted guest; refer to "guestcaps.gcaps_block_bus" in
c1a9fa
"lib/create_ovf.ml". When using virtio-blk (i.e., in the common case), RHV
c1a9fa
can deal with at most 23 disks, as it plugs each virtio-blk device in a
c1a9fa
separate slot on the PCI(e) root bus; and the other slots are reserved for
c1a9fa
various purposes. When a domain has too many disks, the problem only
c1a9fa
becomes apparent once the copying finishes and an import is attempted.
c1a9fa
Modify the RHV outputs to fail relatively early when a domain has more
c1a9fa
than 23 disks that need to be copied.
c1a9fa
c1a9fa
Notes:
c1a9fa
c1a9fa
- With IDE, the theoretical limit may even be as low as 4. However, in the
c1a9fa
  "Output_module.setup" function, we don't have access to
c1a9fa
  "guestcaps.gcaps_block_bus", and in practice the IDE limitation has not
c1a9fa
  caused surprises. So for now stick with 23, assuming virtio-blk.
c1a9fa
  Modifying the "Output_module.setup" parameter list just for this seems
c1a9fa
  overkill.
c1a9fa
c1a9fa
- We could move the new check to an even earlier step, namely
c1a9fa
  "Output_module.parse_options", due to the v2v directory deliberately
c1a9fa
  existing (and having been populated with input sockets) at that time.
c1a9fa
  However, even discounting the fact that "parse_options" is not a good
c1a9fa
  name for including this kind of step, "parse_options" does not have
c1a9fa
  access to the v2v directory name, and modifying the signature just for
c1a9fa
  this is (again) overkill.
c1a9fa
c1a9fa
- By adding the check to "Output_module.setup", we waste *some* effort
c1a9fa
  (namely, the conversion occurs between "parse_options" and "setup"),
c1a9fa
  but: (a) the "rhv-disk-uuid" count check (against the disk count) is
c1a9fa
  already being done in the rhv-upload module's "setup" function, (b) in
c1a9fa
  practice the slowest step ought to be the copying, and placing the new
c1a9fa
  check in "setup" is early enough to prevent that.
c1a9fa
c1a9fa
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2051564
c1a9fa
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
c1a9fa
Message-Id: <20220617095337.9122-1-lersek@redhat.com>
c1a9fa
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
c1a9fa
(cherry picked from commit e186cc2bea99a077990f192953e1bf6c9ba70e79)
c1a9fa
---
c1a9fa
 output/output.ml            | 5 +++++
c1a9fa
 output/output.mli           | 7 +++++++
c1a9fa
 output/output_rhv.ml        | 1 +
c1a9fa
 output/output_rhv_upload.ml | 1 +
c1a9fa
 output/output_vdsm.ml       | 1 +
c1a9fa
 5 files changed, 15 insertions(+)
c1a9fa
c1a9fa
diff --git a/output/output.ml b/output/output.ml
c1a9fa
index 10e685c4..5c6670b9 100644
c1a9fa
--- a/output/output.ml
c1a9fa
+++ b/output/output.ml
c1a9fa
@@ -64,6 +64,11 @@ let get_disks dir =
c1a9fa
   in
c1a9fa
   loop [] 0
c1a9fa
 
c1a9fa
+let error_if_disk_count_gt dir n =
c1a9fa
+  let socket = sprintf "%s/in%d" dir n in
c1a9fa
+  if Sys.file_exists socket then
c1a9fa
+    error (f_"this output module doesn't support copying more than %d disks") n
c1a9fa
+
c1a9fa
 let output_to_local_file ?(changeuid = fun f -> f ())
c1a9fa
       output_alloc output_format filename size socket =
c1a9fa
   (* Check nbdkit is installed and has the required plugin. *)
c1a9fa
diff --git a/output/output.mli b/output/output.mli
c1a9fa
index 533a0c51..8d3d6865 100644
c1a9fa
--- a/output/output.mli
c1a9fa
+++ b/output/output.mli
c1a9fa
@@ -76,6 +76,13 @@ val get_disks : string -> (int * int64) list
c1a9fa
 (** Examines the v2v directory and opens each input socket (in0 etc),
c1a9fa
     returning a list of input disk index and size. *)
c1a9fa
 
c1a9fa
+val error_if_disk_count_gt : string -> int -> unit
c1a9fa
+(** This function lets an output module enforce a maximum disk count.
c1a9fa
+    [error_if_disk_count_gt dir n] checks whether the domain has more than [n]
c1a9fa
+    disks that need to be copied, by examining the existence of input NBD socket
c1a9fa
+    "in[n]" in the v2v directory [dir].  If the socket exists, [error] is
c1a9fa
+    called. *)
c1a9fa
+
c1a9fa
 val output_to_local_file : ?changeuid:((unit -> unit) -> unit) ->
c1a9fa
                            Types.output_allocation ->
c1a9fa
                            string -> string -> int64 -> string ->
c1a9fa
diff --git a/output/output_rhv.ml b/output/output_rhv.ml
c1a9fa
index 119207fd..8571e07b 100644
c1a9fa
--- a/output/output_rhv.ml
c1a9fa
+++ b/output/output_rhv.ml
c1a9fa
@@ -56,6 +56,7 @@ module RHV = struct
c1a9fa
     (options.output_alloc, options.output_format, output_name, output_storage)
c1a9fa
 
c1a9fa
   let rec setup dir options source =
c1a9fa
+    error_if_disk_count_gt dir 23;
c1a9fa
     let disks = get_disks dir in
c1a9fa
     let output_alloc, output_format, output_name, output_storage = options in
c1a9fa
 
c1a9fa
diff --git a/output/output_rhv_upload.ml b/output/output_rhv_upload.ml
c1a9fa
index 828996b3..f2ced4f4 100644
c1a9fa
--- a/output/output_rhv_upload.ml
c1a9fa
+++ b/output/output_rhv_upload.ml
c1a9fa
@@ -133,6 +133,7 @@ after their uploads (if you do, you must supply one for each disk):
c1a9fa
     else PCRE.matches (Lazy.force rex_uuid) uuid
c1a9fa
 
c1a9fa
   let rec setup dir options source =
c1a9fa
+    error_if_disk_count_gt dir 23;
c1a9fa
     let disks = get_disks dir in
c1a9fa
     let output_conn, output_format,
c1a9fa
         output_password, output_name, output_storage,
c1a9fa
diff --git a/output/output_vdsm.ml b/output/output_vdsm.ml
c1a9fa
index a1e8c246..23d1b9cd 100644
c1a9fa
--- a/output/output_vdsm.ml
c1a9fa
+++ b/output/output_vdsm.ml
c1a9fa
@@ -119,6 +119,7 @@ For each disk you must supply one of each of these options:
c1a9fa
      compat, ovf_flavour)
c1a9fa
 
c1a9fa
   let setup dir options source =
c1a9fa
+    error_if_disk_count_gt dir 23;
c1a9fa
     let disks = get_disks dir in
c1a9fa
     let output_alloc, output_format,
c1a9fa
         output_name, output_storage,