# HG changeset patch # User David Scott # Date 1264517064 0 # Node ID ca18fc5c917111068f242fe8b21b9e9558f3d5a9 # Parent 22cd3f304b9e0818b80ac5a40e6d4c6438c5e58a CA-37080: fix terrible error message when a 'rhlike' guest (e.g. CentOS) cannot be installed because an update file is missing in dom0. Converts this: [root@h07 ~]# xe vm-start vm=centos54 The bootloader returned an error vm: 13b688dd-da80-1ee3-bbe8-875fffc5736f (centos54) msg: Error from bootloader: Failed to parse the output of bootloader: () Into this: [root@h07 ~]# xe vm-start vm=centos54 Error code: SUPPORT_PACKAGE_MISSING Error parameters: Dom0 does not contain a required file: /opt/xensource/packages/files/guest-installer/el5.4-initrd-additions.cpio, , Thanks to Vern Burke for helping me debug this. Signed-off-by: David Scott diff -r 22cd3f304b9e -r ca18fc5c9171 ocaml/xapi/bootloader.ml --- a/ocaml/xapi/bootloader.ml Thu Jan 21 15:45:09 2010 +0000 +++ b/ocaml/xapi/bootloader.ml Tue Jan 26 14:44:24 2010 +0000 @@ -52,7 +52,7 @@ let parse_output x = let sexpr = "(" ^ x ^ ")" in - let parse_failed = Error(Printf.sprintf "Failed to parse the output of bootloader: %s" sexpr) in + let parse_failed = Error(Printf.sprintf "Expecting an s-expression; received: %s" sexpr) in let sexpr' = SExpr_TS.of_string sexpr in match sexpr' with (* linux (kernel /var/lib/xen/vmlinuz.y1Wmrp)(args 'root=/dev/sda1 ro') *) @@ -68,6 +68,11 @@ debug "Failed to parse: %s" sexpr; raise parse_failed +let parse_exception x = + match Stringext.String.split '\n' x with + | code :: params -> raise (Api_errors.Server_error(code, params)) + | _ -> failwith (Printf.sprintf "Failed to parse stderr output of bootloader: %s" x) + (** Extract the default kernel using the -q option *) let extract_default_kernel bootloader disks legacy_args extra_args pv_bootloader_args vm_uuid = let bootloader_path = List.assoc bootloader Xapi_globs.supported_bootloaders in @@ -78,34 +83,11 @@ let disk = List.hd disks in let cmdline = bootloader_args true extra_args legacy_args pv_bootloader_args disk vm_uuid in debug "Bootloader commandline: %s %s\n" bootloader_path (String.concat " " cmdline); + try + parse_output (Helpers.call_script ~log_successful_output:false bootloader_path cmdline) + with Forkhelpers.Spawn_internal_error(stderr, stdout, _) -> + parse_exception stderr - let result_out, result_in = Unix.pipe() in - let fds_to_close = ref [ result_out; result_in ] in - let close' fd = - if List.mem fd !fds_to_close - then (Unix.close fd; fds_to_close := List.filter (fun x -> x <> fd) !fds_to_close) in - finally (* make sure I close all my open fds in the end *) - (fun () -> - (* Capture stderr output for logging *) - match with_logfile_fd "bootloader" - (fun log_fd -> - let pid = safe_close_and_exec None (Some result_in) (Some log_fd) [] bootloader_path cmdline in - (* parent *) - List.iter close' [ result_in ]; - finally (* always waitpid eventually *) - (fun () -> - let output = Unixext.read_whole_file 500 500 result_out in - (* Do something with it *) - parse_output output) - (fun () -> waitpid pid)) with - | Success(_, x) -> debug "bootloader subprocess succeeded"; x - | Failure(log, Subprocess_failed n) -> - raise (Error (Printf.sprintf "Return code: %d; Log = %s" n log)) - | Failure(log, exn) -> - debug "Error from bootloader: %s" log; - raise exn) - (fun () -> List.iter Unix.close !fds_to_close) - let delete_extracted_kernel x = Unix.unlink x.kernel_path; match x.initrd_path with