[Pkg-libvirt-commits] [libguestfs] 20/29: v2v: Introduce the concept of target buses.

Hilko Bengen bengen at moszumanska.debian.org
Sun Nov 1 17:15:05 UTC 2015


This is an automated email from the git hooks/post-receive script.

bengen pushed a commit to annotated tag upstream/1.29.49
in repository libguestfs.

commit ce83f2751bea272b96107482aeb37af2358214dc
Author: Richard W.M. Jones <rjones at redhat.com>
Date:   Wed Jul 1 17:33:28 2015 +0100

    v2v: Introduce the concept of target buses.
    
    The target VM will have several buses to which disks can be attached.
    Commonly it will have an IDE bus, and possibly a virtio-blk "bus" (not
    really a bus) and/or a SCSI bus.
    
    Virt-v2v does not model this at the moment.  Disks are just added to
    the output XML in the order that we write them, and so they can move
    around with respect to the target VM.
    
    This commit introduces the idea that we should model the target disk
    buses, and we should try to assign fixed and removable disks to slots
    on each of those buses.  In this commit, the modelling is not used by
    any output mode, but that will be fixed in the next commit.
---
 v2v/types.ml  | 29 ++++++++++++++++++++++
 v2v/types.mli | 14 +++++++++++
 v2v/v2v.ml    | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 123 insertions(+)

diff --git a/v2v/types.ml b/v2v/types.ml
index 34e169c..522814e 100644
--- a/v2v/types.ml
+++ b/v2v/types.ml
@@ -350,6 +350,35 @@ gcaps_acpi = %b
   gcaps.gcaps_arch
   gcaps.gcaps_acpi
 
+type target_buses = {
+  target_virtio_blk_bus : target_bus_slot array;
+  target_ide_bus : target_bus_slot array;
+  target_scsi_bus : target_bus_slot array;
+}
+
+and target_bus_slot =
+  | BusSlotEmpty
+  | BusSlotTarget of target
+  | BusSlotRemovable of source_removable
+
+let string_of_target_bus_slots bus_name slots =
+  let slots =
+    Array.mapi (
+      fun slot_nr slot ->
+        sprintf "%s slot %d:\n" bus_name slot_nr ^
+          (match slot with
+           | BusSlotEmpty -> "\t(slot empty)\n"
+           | BusSlotTarget t -> string_of_target t
+           | BusSlotRemovable r -> string_of_source_removable r ^ "\n"
+          )
+    ) slots in
+  String.concat "" (Array.to_list slots)
+
+let string_of_target_buses buses =
+  string_of_target_bus_slots "virtio-blk" buses.target_virtio_blk_bus ^
+  string_of_target_bus_slots "ide" buses.target_ide_bus ^
+  string_of_target_bus_slots "scsi" buses.target_scsi_bus
+
 class virtual input = object
   method virtual as_options : string
   method virtual source : unit -> source
diff --git a/v2v/types.mli b/v2v/types.mli
index 6f9bf0d..45014a7 100644
--- a/v2v/types.mli
+++ b/v2v/types.mli
@@ -196,6 +196,20 @@ and guestcaps_video_type = QXL | Cirrus
 
 val string_of_guestcaps : guestcaps -> string
 
+type target_buses = {
+  target_virtio_blk_bus : target_bus_slot array;
+  target_ide_bus : target_bus_slot array;
+  target_scsi_bus : target_bus_slot array;
+}
+(** Mapping of fixed and removable disks to buses. *)
+
+and target_bus_slot =
+| BusSlotEmpty                  (** This bus slot is empty. *)
+| BusSlotTarget of target       (** Contains a fixed disk. *)
+| BusSlotRemovable of source_removable (** Contains a removable CD/floppy. *)
+
+val string_of_target_buses : target_buses -> string
+
 class virtual input : object
   method virtual as_options : string
   (** Converts the input object back to the equivalent command line options.
diff --git a/v2v/v2v.ml b/v2v/v2v.ml
index 5bca846..04b99c1 100644
--- a/v2v/v2v.ml
+++ b/v2v/v2v.ml
@@ -311,6 +311,11 @@ let rec main () =
   g#shutdown ();
   g#close ();
 
+  message (f_"Assigning disks to buses");
+  let target_buses = target_bus_assignment source targets guestcaps in
+  if verbose () then
+    printf "%s%!" (string_of_target_buses target_buses);
+
   (* Force a GC here, to ensure that we're using the minimum resources
    * as we go into the copy stage.  The particular reason is that
    * Windows conversion may have opened a second libguestfs handle
@@ -833,4 +838,79 @@ and du filename =
   | line::_ -> (try Some (Int64.of_string line) with _ -> None)
   | [] -> None
 
+(* Assign fixed and removable disks to target buses, as best we can.
+ * This is not solvable for all guests, but at least avoid overlapping
+ * disks (RHBZ#1238053).
+ *
+ * XXX This doesn't do the right thing for PC legacy floppy devices.
+ * XXX This could handle slot assignment better when we have a mix of
+ * devices desiring their own slot, and others that don't care.  Allocate
+ * the first group in the first pass, then the second group afterwards.
+ *)
+and target_bus_assignment source targets guestcaps =
+  let virtio_blk_bus = ref [| |]
+  and ide_bus = ref [| |]
+  and scsi_bus = ref [| |] in
+
+  (* Insert a slot into the bus array, making the array bigger if necessary. *)
+  let insert bus i slot =
+    let oldbus = !bus in
+    let oldlen = Array.length oldbus in
+    if i >= oldlen then (
+      bus := Array.make (i+1) BusSlotEmpty;
+      Array.blit oldbus 0 !bus 0 oldlen
+    );
+    Array.set !bus i slot
+  in
+
+  (* Insert a slot into the bus, but if the desired slot is not empty, then
+   * increment the slot number until we find an empty one.  Returns
+   * true if we got the desired slot.
+   *)
+  let rec insert_after bus i slot =
+    let len = Array.length !bus in
+    if i >= len || Array.get !bus i = BusSlotEmpty then (
+      insert bus i slot; true
+    ) else (
+      ignore (insert_after bus (i+1) slot); false
+    )
+  in
+
+  (* Add the fixed disks (targets) to either the virtio-blk or IDE bus,
+   * depending on whether the guest has virtio drivers or not.
+   *)
+  iteri (
+    fun i t ->
+      let t = BusSlotTarget t in
+      match guestcaps.gcaps_block_bus with
+      | Virtio_blk -> insert virtio_blk_bus i t
+      | IDE -> insert ide_bus i t
+  ) targets;
+
+  (* Now try to add the removable disks to the bus at the same slot
+   * they originally occupied, but if the slot is occupied, emit a
+   * a warning and insert the disk in the next empty slot in that bus.
+   *)
+  List.iter (
+    fun r ->
+      let bus = match r.s_removable_controller with
+        | None -> ide_bus (* Wild guess, but should be safe. *)
+        | Some Source_virtio_blk -> virtio_blk_bus
+        | Some Source_IDE -> ide_bus
+        | Some Source_SCSI -> scsi_bus in
+      match r.s_removable_slot with
+      | None -> ignore (insert_after bus 0 (BusSlotRemovable r))
+      | Some desired_slot_nr ->
+         if not (insert_after bus desired_slot_nr (BusSlotRemovable r)) then
+           warning (f_"removable %s device in slot %d clashes with another disk, so it has been moved to a higher numbered slot on the same bus.  This may mean that this removable device has a different name inside the guest (for example a CD-ROM originally called /dev/hdc might move to /dev/hdd, or from D: to E: on a Windows guest).")
+                   (match r.s_removable_type with
+                    | CDROM -> s_"CD-ROM"
+                    | Floppy -> s_"floppy disk")
+                   desired_slot_nr
+  ) source.s_removables;
+
+  { target_virtio_blk_bus = !virtio_blk_bus;
+    target_ide_bus = !ide_bus;
+    target_scsi_bus = !scsi_bus }
+
 let () = run_main_and_handle_errors main

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-libvirt/libguestfs.git



More information about the Pkg-libvirt-commits mailing list