Skip to content

Commit

Permalink
CP-45016: Implement a new nbd proxy handler
Browse files Browse the repository at this point in the history
The new http handler nbd_proxy accepts a connection from an nbd client,
and acts as a proxy between the client and the nbd server of the
underlying storage backend, as returned by get_nbd_server.

This proxy is used in place of the old style of fd passing to tapdisks
for VDI copying during storage migration, since the new nbd server from
qemu-dp does not support accepting fds.

This might also be used in the future for outbound storage migration for
mirroring.

Signed-off-by: Vincent Liu <[email protected]>
  • Loading branch information
Vincent-lau committed Dec 10, 2024
1 parent b7a5124 commit 6bff4e2
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 3 deletions.
34 changes: 31 additions & 3 deletions ocaml/xapi/storage_migrate.ml
Original file line number Diff line number Diff line change
Expand Up @@ -529,15 +529,15 @@ module MigrateLocal = struct
let dest_vdi_url =
let url' = Http.Url.of_string url in
Http.Url.set_uri url'
(Printf.sprintf "%s/nbd/%s/%s/%s/%s" (Http.Url.get_uri url')
(Printf.sprintf "%s/nbdproxy/%s/%s/%s/%s" (Http.Url.get_uri url')
(Storage_interface.Vm.string_of vm)
(Storage_interface.Sr.string_of dest)
(Storage_interface.Vdi.string_of dest_vdi)
remote_dp
)
|> Http.Url.to_string
in
debug "copy remote NBD URL = %s" dest_vdi_url ;
debug "%s copy remote NBD URL = %s" __FUNCTION__ dest_vdi_url ;
let id = State.copy_id_of (sr, vdi) in
debug "Persisting state for copy (id=%s)" id ;
State.add id
Expand Down Expand Up @@ -762,7 +762,7 @@ module MigrateLocal = struct
; watchdog= None
}
in

State.add mirror_id (State.Send_op alm) ;
debug "%s Added mirror %s to active local mirrors" __FUNCTION__ mirror_id ;
(* A list of cleanup actions to perform if the operation should fail. *)
Expand Down Expand Up @@ -1383,6 +1383,34 @@ let nbd_handler req s ?(vm = "0") sr vdi dp =
)
(fun () -> Unix.close control_fd)

(** nbd_proxy is a http handler but will turn the http connection into an nbd connection.
It proxies the connection between the sender and the generic nbd server, as returned
by [get_nbd_server dp sr vdi vm]. *)
let nbd_proxy req s vm sr vdi dp =
debug "%s: vm=%s sr=%s vdi=%s dp=%s" __FUNCTION__ vm sr vdi dp ;
let sr, vdi = Storage_interface.(Sr.of_string sr, Vdi.of_string vdi) in
req.Http.Request.close <- true ;
let vm = Vm.of_string vm in
let path =
Storage_utils.transform_storage_exn (fun () ->
Local.DATA.MIRROR.get_nbd_server "nbd" dp sr vdi vm
)
in
debug "%s got nbd server path %s" __FUNCTION__ path ;
Http_svr.headers s (Http.http_200_ok () @ ["Transfer-encoding: nbd"]) ;
let control_fd = Unixext.open_connection_unix_fd path in
finally
(fun () ->
let s' = Unix.dup s in
let control_fd' = Unix.dup control_fd in
debug "%s: Connected; running proxy (between fds: %d and %d)" __FUNCTION__
(Unixext.int_of_file_descr control_fd')
(Unixext.int_of_file_descr s') ;
Unixext.proxy s' control_fd' ;
debug "%s: proxy exited" __FUNCTION__
)
(fun () -> Unix.close control_fd)

let with_task_and_thread ~dbg f =
let task =
Storage_task.add tasks dbg.Debug_info.log (fun task ->
Expand Down
3 changes: 3 additions & 0 deletions ocaml/xapi/xapi_services.ml
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ let put_handler (req : Http.Request.t) s _ =
| [""; services; "SM"; "nbd"; vm; sr; vdi; dp] when services = _services
->
Storage_migrate.nbd_handler req s ~vm sr vdi dp
| [""; services; "SM"; "nbdproxy"; vm; sr; vdi; dp]
when services = _services ->
Storage_migrate.nbd_proxy req s vm sr vdi dp
| _ ->
Http_svr.headers s (Http.http_404_missing ~version:"1.0" ()) ;
req.Http.Request.close <- true
Expand Down

0 comments on commit 6bff4e2

Please sign in to comment.