# HG changeset patch # User David Scott # Date 1282565001 -3600 # Node ID 838461861723b2801ffc5496df81c55ecbe8ebe9 # Parent 2580868fdc435e5c729f98bd707d018dafd3dc2a CA-42836: in VDI import, issue an HTTP 302 redirect to the correct host rather than just assuming the current host has access to the SR. Signed-off-by: David Scott diff -r 2580868fdc43 -r 838461861723 ocaml/xapi/import_raw_vdi.ml --- a/ocaml/xapi/import_raw_vdi.ml Fri Jul 23 18:18:39 2010 +0100 +++ b/ocaml/xapi/import_raw_vdi.ml Mon Aug 23 13:03:21 2010 +0100 @@ -23,14 +23,20 @@ open Unixext open Pervasiveext -let handler (req: request) (s: Unix.file_descr) = +let vdi_of_req ~__context (req: request) = + let vdi = + if List.mem_assoc "vdi" req.Http.query + then List.assoc "vdi" req.Http.query + else raise (Failure "Missing vdi query parameter") in + if Db_cache.DBCache.is_valid_ref vdi + then Ref.of_string vdi + else Db.VDI.get_by_uuid ~__context ~uuid:vdi + +let localhost_handler rpc session_id (req: request) (s: Unix.file_descr) = req.close <- true; Xapi_http.with_context "Importing raw VDI" req s (fun __context -> - let vdi = - if List.mem_assoc "vdi" req.Http.query - then Ref.of_string (List.assoc "vdi" req.Http.query) - else raise (Failure "Missing vdi query parameter") in + let vdi = vdi_of_req ~__context req in try match req.transfer_encoding, req.content_length with | Some "chunked", _ -> @@ -43,8 +49,7 @@ content_type ] in Http_svr.headers s headers; - Helpers.call_api_functions ~__context - (fun rpc session_id -> + Sm_fs_ops.with_block_attached_device __context rpc session_id vdi `RW (fun device -> let fd = Unix.openfile device [ Unix.O_WRONLY ] 0 in @@ -57,10 +62,37 @@ raise (Api_errors.Server_error (Api_errors.vdi_io_error, ["Device I/O errors"])) ) (fun () -> Unix.close fd) - ) - ); + ); TaskHelper.complete ~__context [] with e -> TaskHelper.failed ~__context (Api_errors.internal_error, ["Caught exception: " ^ (ExnHelper.string_of_exn e)]); raise e) + +let return_302_redirect (req: request) s address = + let url = Printf.sprintf "https://%s%s?%s" address req.uri (String.concat "&" (List.map (fun (a,b) -> a^"="^b) req.query)) in + let headers = Http.http_302_redirect url in + debug "HTTP 302 redirect to: %s" url; + Http_svr.headers s headers + +let handler (req: request) (s: Unix.file_descr) = + Xapi_http.assert_credentials_ok "VDI.import" ~http_action:"put_import_raw_vdi" req; + + (* Perform the SR reachability check using a fresh context/task because + we don't want to complete the task in the forwarding case *) + Server_helpers.exec_with_new_task "VDI.import" + (fun __context -> + Helpers.call_api_functions ~__context + (fun rpc session_id -> + let vdi = vdi_of_req ~__context req in + let sr = Db.VDI.get_SR ~__context ~self:vdi in + debug "Checking whether localhost can see SR: %s" (Ref.string_of sr); + if (Importexport.check_sr_availability ~__context sr) + then localhost_handler rpc session_id req s + else + let host = Importexport.find_host_for_sr ~__context sr in + let address = Db.Host.get_address ~__context ~self:host in + return_302_redirect req s address + ) + ) +