Skip to content

Commit 7753e0f

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 f5c5b4f commit 7753e0f

File tree

3 files changed

+66
-39
lines changed

3 files changed

+66
-39
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
@@ -85,10 +85,16 @@ let send ?relative_to (progress_cb : int -> unit) (unix_fd : Unix.file_descr)
8585

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

9090
(* Parse the header of the VDI we are diffing against as well *)
91-
let relative_to_qcow_path = Option.bind relative_to qcow_of_device in
91+
let relative_to_qcow_path =
92+
match relative_to with
93+
| Some x ->
94+
Result.to_option (qcow_of_device x)
95+
| None ->
96+
None
97+
in
9298
let diff_fd = Option.map read_header relative_to_qcow_path in
9399

94100
let unique_string = Uuidx.(to_string (make ())) in
@@ -101,7 +107,7 @@ let send ?relative_to (progress_cb : int -> unit) (unix_fd : Unix.file_descr)
101107
| Some _ ->
102108
["--json-header-diff"; unique_string]
103109
)
104-
@ match qcow_path with None -> [] | Some _ -> ["--json-header"]
110+
@ match qcow_path with Error _ -> [] | Ok _ -> ["--json-header"]
105111
in
106112
let qcow_tool = !Xapi_globs.qcow_to_stdout in
107113
let replace_fds = Option.map (fun fd -> [(unique_string, fd)]) diff_fd in

ocaml/xapi/vhd_tool_wrapper.ml

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -150,41 +150,62 @@ let find_backend_device path =
150150
raise Not_found
151151
with _ -> None
152152

153+
type backing_file_error =
154+
| Driver_mismatch of {expected: string; actual: string option}
155+
| Driver_unknown of {path: string}
156+
| Not_a_device
157+
158+
let backing_file_error_to_string = function
159+
| Not_a_device ->
160+
"Not a device"
161+
| Driver_mismatch {expected; actual= None} ->
162+
Printf.sprintf "Driver mismatch {expected=%s; actual=None}" expected
163+
| Driver_mismatch {expected; actual= Some actual} ->
164+
Printf.sprintf "Driver mismatch {expected=%s; actual=%s}" expected actual
165+
| Driver_unknown {path} ->
166+
Printf.sprintf "Driver unknown {path=%s}" path
167+
153168
(** [backing_file_of_device path] returns (Some backing_file) where 'backing_file'
154169
is the leaf backing a particular device [path] (with a driver of type
155170
[driver] or None. [path] may either be a blktap2 device *or* a blkfront
156171
device backed by a blktap2 device. If the latter then the script must be
157172
run in the same domain as blkback. *)
158173
let backing_file_of_device path ~driver =
159174
let tapdisk_of_path path =
160-
try
161-
match Tapctl.of_device (Tapctl.create ()) path with
162-
| _, _, Some (typ, backing_file) when typ = driver ->
163-
Some backing_file
164-
| _, _, _ ->
165-
raise Not_found
166-
with
167-
| Tapctl.Not_blktap -> (
175+
match Tapctl.of_device (Tapctl.create ()) path with
176+
| _, _, Some (typ, backing_file) when typ = driver ->
177+
Ok backing_file
178+
| _, _, Some (typ, _) ->
179+
Error (Driver_mismatch {expected= driver; actual= Some typ})
180+
| _, _, None ->
181+
Error (Driver_mismatch {expected= driver; actual= None})
182+
| exception Tapctl.Not_blktap -> (
168183
debug "Device %s is not controlled by blktap" path ;
169184
(* Check if it is a [driver] behind a NBD device *)
170185
Stream_vdi.(get_nbd_device path |> image_behind_nbd_device) |> function
171186
| Some (typ, backing_file) when typ = driver ->
172187
debug "%s is a %s behind NBD device %s" backing_file driver path ;
173-
Some backing_file
174-
| _ ->
175-
None
188+
Ok backing_file
189+
| Some (typ, _) ->
190+
Error (Driver_mismatch {expected= driver; actual= Some typ})
191+
| None ->
192+
Error (Driver_mismatch {expected= driver; actual= None})
176193
)
177-
| Tapctl.Not_a_device ->
194+
| exception Tapctl.Not_a_device ->
178195
debug "%s is not a device" path ;
179-
None
180-
| _ ->
196+
Error Not_a_device
197+
| exception Not_found ->
181198
debug "Device %s has an unknown driver" path ;
182-
None
199+
Error (Driver_unknown {path})
200+
| exception (Unix.Unix_error _ as e) ->
201+
debug "Could not read device %s: %s" path (Printexc.to_string e) ;
202+
Error (Driver_unknown {path})
183203
in
184204
find_backend_device path |> Option.value ~default:path |> tapdisk_of_path
185205

186206
let send progress_cb ?relative_to (protocol : string) (dest_format : string)
187207
(s : Unix.file_descr) (path : string) (size : Int64.t) (prefix : string) =
208+
let __FUN = __FUNCTION__ in
188209
let vhd_of_device = backing_file_of_device ~driver:"vhd" in
189210
let s' = Uuidx.(to_string (make ())) in
190211
let source_format, source =
@@ -193,26 +214,29 @@ let send progress_cb ?relative_to (protocol : string) (dest_format : string)
193214
( "nbdhybrid"
194215
, Printf.sprintf "%s:%s:%s:%Ld" path nbd_server exportname size
195216
)
196-
| Some _, Some vhd, Some _ | None, Some vhd, _ ->
217+
| Some _, Ok vhd, Some _ | None, Ok vhd, _ ->
197218
("hybrid", path ^ ":" ^ vhd)
198-
| None, None, None ->
219+
| None, Error _, None ->
199220
("raw", path)
200-
| _, None, Some _ ->
221+
| _, Error _, Some _ ->
201222
let msg = "Cannot compute differences on non-VHD images" in
202223
error "%s" msg ; failwith msg
203224
in
204225
let relative_to =
205-
match relative_to with
206-
| Some path -> (
226+
let maybe_device path =
207227
match vhd_of_device path with
208-
| Some vhd ->
228+
| Ok vhd ->
209229
Some vhd
210-
| None ->
211-
error "base VDI is not a vhd; cannot compute differences" ;
212-
failwith "base VDI is not a vhd; cannot compute differences"
213-
)
214-
| None ->
215-
None
230+
| Error e ->
231+
let explanation = backing_file_error_to_string e in
232+
let msg =
233+
Printf.sprintf
234+
"%s: base VDI is not a vhd; cannot compute differences: %s" __FUN
235+
explanation
236+
in
237+
error "%s" msg ; failwith msg
238+
in
239+
Option.bind relative_to maybe_device
216240
in
217241
let args =
218242
[

0 commit comments

Comments
 (0)