Skip to content

Commit fc6ed07

Browse files
committed
vhd_tool_wrapper: generate detailed errors when getting tapctl devices
Previously, when a failure happened while getting a base vhd, a non-descriptive error was printed. Because there can be many reasons that can cause this code to fail, model the possible errors and print them when needed. Signed-off-by: Pau Ruiz Safont <pau.safont@vates.tech>
1 parent 6046cce commit fc6ed07

File tree

5 files changed

+68
-43
lines changed

5 files changed

+68
-43
lines changed

ocaml/tapctl/tapctl.ml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -507,18 +507,15 @@ let stats ctx t =
507507
let read_proc_devices () : (int * string) list =
508508
let parse_line x =
509509
match List.filter (fun x -> x <> "") (String.split_on_char ' ' x) with
510-
| [x; y] -> (
511-
try Some (int_of_string x, y) with _ -> None
512-
)
510+
| [x; y] ->
511+
Option.bind (int_of_string_opt x) (fun x -> Some (x, y))
513512
| _ ->
514513
None
515514
in
516-
List.concat
517-
(List.map Option.to_list
518-
(Unixext.file_lines_fold
519-
(fun acc x -> parse_line x :: acc)
520-
[] "/proc/devices"
521-
)
515+
List.concat_map Option.to_list
516+
(Unixext.file_lines_fold
517+
(fun acc x -> parse_line x :: acc)
518+
[] "/proc/devices"
522519
)
523520

524521
let driver_of_major major = List.assoc major (read_proc_devices ())

ocaml/xapi/qcow_tool_wrapper.ml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,16 @@ let send ?relative_to (progress_cb : int -> unit) (unix_fd : Unix.file_descr)
4848

4949
(* If VDI is backed by QCOW, parse the header to determine nonzero clusters
5050
to avoid reading all of the raw disk *)
51-
let input_fd = Option.map read_header qcow_path in
51+
let input_fd = Result.map read_header qcow_path |> Result.to_option in
5252

5353
(* Parse the header of the VDI we are diffing against as well *)
54-
let relative_to_qcow_path = Option.bind relative_to qcow_of_device in
54+
let relative_to_qcow_path =
55+
match relative_to with
56+
| Some x ->
57+
Result.to_option (qcow_of_device x)
58+
| None ->
59+
None
60+
in
5561
let diff_fd = Option.map read_header relative_to_qcow_path in
5662

5763
let unique_string = Uuidx.(to_string (make ())) in
@@ -64,7 +70,7 @@ let send ?relative_to (progress_cb : int -> unit) (unix_fd : Unix.file_descr)
6470
| Some _ ->
6571
["--json-header-diff"; unique_string]
6672
)
67-
@ match qcow_path with None -> [] | Some _ -> ["--json-header"]
73+
@ match qcow_path with Error _ -> [] | Ok _ -> ["--json-header"]
6874
in
6975
let qcow_tool = !Xapi_globs.qcow_to_stdout in
7076
let replace_fds = Option.map (fun fd -> [(unique_string, fd)]) diff_fd in

ocaml/xapi/stream_vdi.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ let send_one ofd (__context : Context.t) rpc session_id progress refresh_session
304304
Xapi_vdi_helpers.backing_info_of_device dom0_path
305305
in
306306
match backing_info with
307-
| Some (driver, path) when driver = "vhd" || driver = "qcow2" -> (
307+
| Ok (Some (driver, path)) when driver = "vhd" || driver = "qcow2" -> (
308308
try
309309
(* Read backing file headers, then only read and write
310310
allocated clusters from the bitmap *)

ocaml/xapi/vhd_tool_wrapper.ml

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ let parse_header vhd_path =
131131

132132
let send progress_cb ?relative_to (protocol : string) (dest_format : string)
133133
(s : Unix.file_descr) (path : string) (size : Int64.t) (prefix : string) =
134+
let __FUN = __FUNCTION__ in
134135
let vhd_of_device =
135136
Xapi_vdi_helpers.backing_file_of_device_with_driver ~driver:"vhd"
136137
in
@@ -143,26 +144,29 @@ let send progress_cb ?relative_to (protocol : string) (dest_format : string)
143144
( "nbdhybrid"
144145
, Printf.sprintf "%s:%s:%s:%Ld" path nbd_server exportname size
145146
)
146-
| Some _, Some vhd, Some _ | None, Some vhd, _ ->
147+
| Some _, Ok vhd, Some _ | None, Ok vhd, _ ->
147148
("hybrid", path ^ ":" ^ vhd)
148-
| None, None, None ->
149+
| None, Error _, None ->
149150
("raw", path)
150-
| _, None, Some _ ->
151+
| _, Error _, Some _ ->
151152
let msg = "Cannot compute differences on non-VHD images" in
152153
error "%s" msg ; failwith msg
153154
in
154155
let relative_to =
155-
match relative_to with
156-
| Some path -> (
156+
let maybe_device path =
157157
match vhd_of_device path with
158-
| Some vhd ->
158+
| Ok vhd ->
159159
Some vhd
160-
| None ->
161-
error "base VDI is not a vhd; cannot compute differences" ;
162-
failwith "base VDI is not a vhd; cannot compute differences"
163-
)
164-
| None ->
165-
None
160+
| Error e ->
161+
let explanation = Xapi_vdi_helpers.backing_file_error_to_string e in
162+
let msg =
163+
Printf.sprintf
164+
"%s: base VDI is not a vhd; cannot compute differences: %s" __FUN
165+
explanation
166+
in
167+
error "%s" msg ; failwith msg
168+
in
169+
Option.bind relative_to maybe_device
166170
in
167171
let args =
168172
[

ocaml/xapi/xapi_vdi_helpers.ml

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -391,41 +391,59 @@ let find_backend_device path =
391391
raise Not_found
392392
with _ -> None
393393

394-
(** [backing_info_of_device] returns Some (driver_type, backing_file) for the
395-
leaf backing a particular device [path]. *)
394+
type backing_file_error =
395+
| Driver_mismatch of {expected: string; actual: string option}
396+
| Driver_unknown of {path: string}
397+
| Not_a_device
398+
399+
let backing_file_error_to_string = function
400+
| Not_a_device ->
401+
"Not a device"
402+
| Driver_mismatch {expected; actual= None} ->
403+
Printf.sprintf "Driver mismatch {expected=%s; actual=None}" expected
404+
| Driver_mismatch {expected; actual= Some actual} ->
405+
Printf.sprintf "Driver mismatch {expected=%s; actual=%s}" expected actual
406+
| Driver_unknown {path} ->
407+
Printf.sprintf "Driver unknown {path=%s}" path
408+
409+
(** [backing_info_of_device] returns [Ok (Some (driver_type, backing_file))]
410+
for the leaf backing a particular device [path]. *)
396411
let backing_info_of_device path =
397412
let tapdisk_of_path path =
398-
try
399-
let ( let* ) = Option.bind in
400-
let* _, _, backing_info = Tapctl.of_device (Tapctl.create ()) path in
401-
backing_info
402-
with
403-
| Tapctl.Not_a_device ->
413+
match Tapctl.of_device (Tapctl.create ()) path with
414+
| Some (_, _, backing_info) ->
415+
Ok backing_info
416+
| None ->
417+
Ok None
418+
| exception Tapctl.Not_a_device ->
404419
debug "%s is not a device" path ;
405-
None
406-
| Tapctl.Not_blktap -> (
420+
Error Not_a_device
421+
| exception Tapctl.Not_blktap -> (
407422
debug "Device %s is not controlled by blktap" path ;
408423
(* Check if it is a [driver] behind a NBD device *)
409424
get_nbd_device path |> image_behind_nbd_device |> function
410425
| Some (typ, backing_file) as backing_info ->
411426
debug "%s is a %s behind NBD device %s" backing_file typ path ;
412-
backing_info
427+
Ok backing_info
413428
| _ ->
414-
None
429+
Ok None
415430
)
416431
in
417432
find_backend_device path |> Option.value ~default:path |> tapdisk_of_path
418433

419-
(** [backing_file_of_device_with_driver path driver] returns Some backing_file
434+
(** [backing_file_of_device_with_driver path driver] returns [Ok backing_file]
420435
where [backing_file] is the leaf backing a particular device [path]
421-
(with a driver of type [driver]) or None.
436+
(with a driver of type [driver]) or [Error backing_file_error].
422437
[path] may either be a blktap2 device *or* a blkfront device backed by a
423438
blktap2 device. If the latter then the script must be
424439
run in the same domain as blkback. *)
425440
let backing_file_of_device_with_driver path ~driver =
426441
match backing_info_of_device path with
427-
| Some (typ, backing_file) when typ = driver ->
428-
Some backing_file
429-
| _ ->
442+
| Ok (Some (typ, backing_file)) when typ = driver ->
443+
Ok backing_file
444+
| Ok info ->
430445
debug "Device %s has an unknown driver" path ;
431-
None
446+
let typ = Option.map fst info in
447+
Error (Driver_mismatch {expected= driver; actual= typ})
448+
| Error _ as err ->
449+
err

0 commit comments

Comments
 (0)