Skip to content

Commit

Permalink
nbd: pass the fd to tapdisk if the control socket exists, otherwise u…
Browse files Browse the repository at this point in the history
…se vhd-tool

Signed-off-by: David Scott <dave.scott@eu.citrix.com>
  • Loading branch information
David Scott committed Oct 24, 2013
1 parent 05efc0e commit b8a6932
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 44 deletions.
3 changes: 2 additions & 1 deletion ocaml/xapi/OMakefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ OCamlProgram(sparse_dd, sparse_dd sparse_encoding ../util/stats)
OCamlProgram(show_bat, show_bat)
#OCamlProgram(monitor_fake_plugin, monitor_fake_plugin rrdd_fake_common rrd)

OCamlProgram(storage_impl_test, sparse_encoding sparse_dd_wrapper ../xenops/updates storage_migrate storage_impl ../xenops/task_server storage_task storage_locks storage_impl_test)
OCamlProgram(storage_impl_test, sparse_encoding sparse_dd_wrapper ../xenops/updates vhd_tool_wrapper storage_migrate storage_impl ../xenops/task_server storage_task storage_locks storage_impl_test)

OCamlProgram(cancel_tests, cancel_tests ../xenops/xenops_helpers)

Expand Down Expand Up @@ -78,6 +78,7 @@ XAPI_MODULES = $(COMMON) \
storage_task \
storage_access \
storage_mux \
vhd_tool_wrapper \
storage_migrate \
storage_proxy \
storage_utils \
Expand Down
29 changes: 2 additions & 27 deletions ocaml/xapi/import_raw_vdi.ml
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,6 @@ open Unixext
open Pervasiveext
open Client

let vhd_tool = "/usr/sbin/vhd-tool"

let receive protocol (s: Unix.file_descr) (path: string) =
let s' = Uuidm.to_string (Uuidm.create `V4) in
let args = [ "serve";
"--direct";
"--source-protocol"; protocol;
"--source-fd"; s';
"--destination"; "file://" ^ path;
"--destination-format"; "raw" ] in
info "Executing %s %s" vhd_tool (String.concat " " args);
let open Forkhelpers in
match with_logfile_fd "vhd-tool"
(fun log_fd ->
let pid = safe_close_and_exec None (Some log_fd) (Some log_fd) [ s', s ] vhd_tool args in
let (_, status) = waitpid pid in
if status <> Unix.WEXITED 0 then begin
error "vhd-tool failed, returning VDI_IO_ERROR";
raise (Api_errors.Server_error (Api_errors.vdi_io_error, ["Device I/O errors"]))
end
) with
| Success(out, _) -> debug "%s" out
| Failure(out, e) -> error "vhd-tool output: %s" out; raise e


let localhost_handler rpc session_id vdi (req: Request.t) (s: Unix.file_descr) =
req.Request.close <- true;
Xapi_http.with_context "Importing raw VDI" req s
Expand All @@ -74,8 +49,8 @@ let localhost_handler rpc session_id vdi (req: Request.t) (s: Unix.file_descr) =
content_type ] in
Http_svr.headers s headers;
if chunked
then receive "chunked" s path
else receive "none" s path
then Vhd_tool_wrapper.receive "chunked" s path
else Vhd_tool_wrapper.receive "none" s path
)
);
TaskHelper.complete ~__context None;
Expand Down
41 changes: 25 additions & 16 deletions ocaml/xapi/storage_migrate.ml
Original file line number Diff line number Diff line change
Expand Up @@ -572,30 +572,39 @@ let post_detach_hook ~sr ~vdi ~dp =
Opt.iter (fun id -> Updates.Scheduler.cancel id) r.watchdog;
debug "Created thread %d to call receive finalize and dp destroy" (Thread.id t))

let tapdisk_control_socket pid minor =
Printf.sprintf "/var/run/blktap-control/nbdserver%d.%d" pid minor

let hand_fd_to_tapdisk s pid minor dp =
debug "attempting to transfer NBD fd to existing tapdisk (pid %d; minor %d)" pid minor;
let path = tapdisk_control_socket pid minor in
let control_fd = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in
finally
(fun () ->
Unix.connect control_fd (Unix.ADDR_UNIX path);
let msg = dp in
let len = String.length msg in
let written = Unixext.send_fd control_fd msg 0 len [] s in
if written <> len then begin
error "Failed to transfer fd to %s" path;
failwith "failed to transfer fd to tapdisk"
end;
)
(fun () -> Unix.close control_fd)

let nbd_handler req s sr vdi dp =
debug "sr=%s vdi=%s dp=%s" sr vdi dp;
let attach_info = Local.DP.attach_info ~dbg:"nbd" ~sr ~vdi ~dp in
req.Http.Request.close <- true;
match tapdisk_of_attach_info attach_info with
| Some tapdev ->
Http_svr.headers s (Http.http_200_ok () @ ["Transfer-encoding: nbd"]);
let minor = Tapctl.get_minor tapdev in
let pid = Tapctl.get_tapdisk_pid tapdev in
let path = Printf.sprintf "/var/run/blktap-control/nbdserver%d.%d" pid minor in
Http_svr.headers s (Http.http_200_ok () @ ["Transfer-encoding: nbd"]);
let control_fd = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in
finally
(fun () ->
Unix.connect control_fd (Unix.ADDR_UNIX path);
let msg = dp in
let len = String.length msg in
let written = Unixext.send_fd control_fd msg 0 len [] s in
if written <> len then begin
error "Failed to transfer fd to %s" path;
Http_svr.headers s (Http.http_404_missing ~version:"1.0" ());
req.Http.Request.close <- true
end;
)
(fun () -> Unix.close control_fd)
let path = tapdisk_control_socket pid minor in
if Sys.file_exists path
then hand_fd_to_tapdisk s pid minor dp
else Vhd_tool_wrapper.receive "nbd" s attach_info.params
| None ->
()

Expand Down
45 changes: 45 additions & 0 deletions ocaml/xapi/vhd_tool_wrapper.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
(*
* Copyright (C) 2006-2009 Citrix Systems Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*)
(** HTTP handler for importing a raw VDI.
* @group Import and Export
*)

module D=Debug.Make(struct let name="vdi_tool_wrapper" end)
open D

let vhd_tool = "/usr/bin/vhd-tool"

let receive protocol (s: Unix.file_descr) (path: string) =
let s' = Uuidm.to_string (Uuidm.create `V4) in
let args = [ "serve";
"--direct";
"--source-protocol"; protocol;
"--source-fd"; s';
"--destination"; "file://" ^ path;
"--destination-format"; "raw" ] in
info "Executing %s %s" vhd_tool (String.concat " " args);
let open Forkhelpers in
match with_logfile_fd "vhd-tool"
(fun log_fd ->
let pid = safe_close_and_exec None (Some log_fd) (Some log_fd) [ s', s ] vhd_tool args in
let (_, status) = waitpid pid in
if status <> Unix.WEXITED 0 then begin
error "vhd-tool failed, returning VDI_IO_ERROR";
raise (Api_errors.Server_error (Api_errors.vdi_io_error, ["Device I/O errors"]))
end
) with
| Success(out, _) -> debug "%s" out
| Failure(out, e) -> error "vhd-tool output: %s" out; raise e


0 comments on commit b8a6932

Please sign in to comment.