[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-API] [SPAM] [PATCH] Make xapi use the fork/exec daemon


  • To: xen-api@xxxxxxxxxxxxxxxxxxx
  • From: David Scott <dave.scott@xxxxxxxxxxxxx>
  • Date: Fri, 18 Dec 2009 20:57:18 +0000
  • Delivery-date: Fri, 18 Dec 2009 12:54:14 -0800
  • Importance: Low
  • List-id: Discussion of API issues surrounding Xen <xen-api.lists.xensource.com>

# HG changeset patch
# User David Scott <dave.scott@xxxxxxxxxxxxx>
# Date 1261169770 0
# Node ID d0c22775c225d814fff66afbaf075ac52603e39a
# Parent  5d6a3e43431f73d0af2bf28082960499819cd9b8
CA-33440: Slight modification to the fork/exec API to support fork/exec via an 
external daemon.

We modify at least:
* likewise/AD
* database/stunnel handling
* database redo log
* gpg
* xmlrpc client
* pygrub
* PV coredump handling
* bugtool
* blob handling
* interface-reconfigure
* patching
* SM stuff
* template scripts
* udhcpd
* vncsnapshots
* qemu, vncterm, xenguest

Signed-off-by: Jon Ludlam <Jonathan.Ludlam@xxxxxxxxxxxxx>
Acked-by: David Scott <dave.scott@xxxxxxxxxxxxx>

diff -r 5d6a3e43431f -r d0c22775c225 ocaml/auth/extauth_plugin_ADlikewise.ml
--- a/ocaml/auth/extauth_plugin_ADlikewise.ml   Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/auth/extauth_plugin_ADlikewise.ml   Fri Dec 18 20:56:10 2009 +0000
@@ -90,34 +90,11 @@
        let err_writeme = Unix.openfile err_tmpfile [ Unix.O_WRONLY] 0o0 in
        fds_to_close := err_writeme :: !fds_to_close;
 
-       (*enforces that likewise cmd only inherits the fds explicitly cited 
below*)
-       let args = Forkhelpers.close_and_exec_cmdline
-               (* we use stdin,stdout and stderr instead of 
in_readme,out_writeme,err_writeme because *)
-               (* this function maps them internally: in_readme->unix.stdin, 
out_writeme->unix.stdout, err_writeme->unix.stderr *)
-               [Unix.stdin;Unix.stdout;Unix.stderr]
-               likewise_cmd
-               params_list
-       in
-       (* we bypass the shell here, calling create_process that forks and 
calls unix.execvp directly, *)
-       (* in order to avoid potential cmd injections that use shell 
vulnerabilities\escape sequences *)
-       let pid = 
-               (try 
-                       Unix.create_process
-                               (List.hd args) (*this is the likewise_cmd*)
-                               (Array.append [|(List.hd args)|] (Array.of_list 
(List.tl args))) (* these are the parameters *)
-                               in_readme       (* pass along to likewise_cmd 
the read-only end point of our new stdin pipe *)
-                               out_writeme     (* pass along to likewise_cmd 
the write-only end point of our new stdout file *)
-                               err_writeme     (* pass along to likewise_cmd 
the write-only end point of our new stderr file *)
-               with 
-               | e-> begin
-                       let msg = (Printf.sprintf "Error creating process for 
cmd %s: %s" debug_cmd (ExnHelper.string_of_exn e)) in
-                       debug "%s" msg;
-                       raise (Auth_signature.Auth_service_error msg) (* 
general error *)
-               end)
-       in
+       let pid = Forkhelpers.safe_close_and_exec (Some in_readme) (Some 
out_writeme) (Some err_writeme) [] likewise_cmd params_list in
+
        finally
          (fun () ->
-               debug "Created process pid %i for cmd %s" pid debug_cmd;
+               debug "Created process pid %s for cmd %s" 
(Forkhelpers.string_of_pidty pid) debug_cmd;
                (* Insert this delay to reproduce the cannot write to stdin 
bug: 
                   Thread.delay 5.; *)
                (* WARNING: we don't close the in_readme because otherwise in 
the case where the likewise 
@@ -143,7 +120,8 @@
                end
                end;
          )
-         (fun () -> Unix.waitpid [] pid);
+         (fun () -> Forkhelpers.waitpid pid);
+
        (* <-- at this point the process has quit and left us its output in 
temporary files *)
 
        (* we parse the likewise cmd's STDOUT *)
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/database/master_connection.ml
--- a/ocaml/database/master_connection.ml       Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/database/master_connection.ml       Fri Dec 18 20:56:10 2009 +0000
@@ -38,7 +38,7 @@
   match !my_connection with
     None -> ()
   | Some st_proc ->
-      Unix.kill st_proc.Stunnel.pid Sys.sigterm
+      Unix.kill (Forkhelpers.getpid st_proc.Stunnel.pid) Sys.sigterm
        
 (* whenever a call is made that involves read/write to the master connection, 
a timestamp is
    written into this global: *)
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/database/redo_log.ml
--- a/ocaml/database/redo_log.ml        Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/database/redo_log.ml        Fri Dec 18 20:56:10 2009 +0000
@@ -187,7 +187,7 @@
   (* Execute the process *)
   let args = ["-device"; block_dev; "-ctrlsock"; ctrlsockpath; "-datasock"; 
datasockpath] in
   let fds_needed = [ Unix.stdin; Unix.stdout; Unix.stderr ] in
-  Forkhelpers.fork_and_exec ~pre_exec:(fun _ -> Unixext.close_all_fds_except 
fds_needed) (prog::args)
+  Forkhelpers.safe_close_and_exec None None None [] prog args
 
 let connect sockpath latest_response_time =
   let s = Unix.socket Unix.PF_UNIX Unix.SOCK_STREAM 0 in
@@ -426,7 +426,7 @@
 let marker = Uuid.to_string (Uuid.make_uuid ())
 
 let sock = ref None
-let pid : (int * string * string) option ref = ref None (* pid, filename of 
control socket, filename of data socket *)
+let pid : (Forkhelpers.pidty * string * string) option ref = ref None (* pid, 
filename of control socket, filename of data socket *)
 
 let dying_processes_mutex = Mutex.create ()
 let num_dying_processes = ref 0
@@ -451,14 +451,15 @@
           end;
   
           (* Terminate the child process *)
-          R.debug "Killing I/O process with pid %d" p;
-          Unix.kill p Sys.sigkill;
+           let ipid = Forkhelpers.getpid p in
+          R.debug "Killing I/O process with pid %d" ipid;
+          Unix.kill ipid Sys.sigkill;
           (* Wait for the process to die. This is done in a separate thread in 
case it does not respond to the signal immediately. *)
           ignore (Thread.create (fun () ->
-            R.debug "Waiting for I/O process with pid %d to die..." p;
+            R.debug "Waiting for I/O process with pid %d to die..." ipid;
             Mutex.execute dying_processes_mutex (fun () -> num_dying_processes 
:= !num_dying_processes + 1);
-            ignore (Unix.waitpid [] p);
-            R.debug "Finished waiting for process %d" p;
+            ignore(Forkhelpers.waitpid p);
+            R.debug "Finished waiting for process %d" ipid;
             Mutex.execute dying_processes_mutex (fun () -> num_dying_processes 
:= !num_dying_processes - 1)
           ) ());
           (* Forget about that process *)
@@ -515,7 +516,7 @@
                        let p = start_io_process block_dev ctrlsockpath 
datasockpath in
                          
                        pid := Some (p, ctrlsockpath, datasockpath);
-                       R.debug "Block device I/O process has PID [%d]" p
+                       R.debug "Block device I/O process has PID [%d]" 
(Forkhelpers.getpid p)
                      end
           end
       end;
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/gpg/gpg.ml
--- a/ocaml/gpg/gpg.ml  Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/gpg/gpg.ml  Fri Dec 18 20:56:10 2009 +0000
@@ -58,6 +58,7 @@
   Unix.unlink tmp_file; 
   (* no need to close the 'tmp_oc' -> closing the fd is enough *)
   let status_out, status_in = Unix.pipe() in
+  let status_in_uuid = Uuid.to_string (Uuid.make_uuid ()) in
   (* from the parent's PoV *)
   let fds_to_close = ref [ result_out; result_in; status_out; status_in ] in
   let close' fd = 
@@ -70,7 +71,7 @@
                  "--homedir"; gpg_homedir;
                  "--no-default-keyring";
                  "--keyring"; gpg_pub_keyring;
-                 "--status-fd"; string_of_int (Unixext.int_of_file_descr 
status_in);
+                 "--status-fd"; status_in_uuid;
                  "--decrypt"; filename
                ]
     | `detached_signature ->
@@ -79,7 +80,7 @@
                  "--homedir"; gpg_homedir;
                  "--no-default-keyring";
                  "--keyring"; gpg_pub_keyring;
-                 "--status-fd"; string_of_int (Unixext.int_of_file_descr 
status_in);
+                 "--status-fd"; status_in_uuid;
                  "--verify"; signature
                ]
   in
@@ -97,12 +98,7 @@
            (* Capture stderr output for logging *)
            match Forkhelpers.with_logfile_fd "gpg"
              (fun log_fd ->
-                let pid = Forkhelpers.safe_close_and_exec
-                  [ Forkhelpers.Dup2(result_in, Unix.stdout);
-                    Forkhelpers.Dup2(log_fd, Unix.stderr);
-                    Forkhelpers.Close(result_out);
-                    Forkhelpers.Close(status_out) ]
-                  [ Unix.stdout; Unix.stderr; status_in ] (* close all but 
these *)
+                let pid = Forkhelpers.safe_close_and_exec None (Some 
result_in) (Some log_fd) [(status_in_uuid,status_in)] 
                   gpg_path gpg_args in
                 (* parent *)
                 List.iter close' [ result_in; status_in ];
@@ -111,7 +107,7 @@
                      let gpg_status = Unixext.read_whole_file 500 500 
status_out in
                      let fingerprint = parse_gpg_status gpg_status in
                      f fingerprint result_out)
-                  (fun () -> Forkhelpers.waitpid pid)) with
+                  (fun () -> Forkhelpers.waitpid_fail_if_bad_exit pid)) with
              | Forkhelpers.Success(_, x) -> debug "gpg subprocess succeeded"; x
              | Forkhelpers.Failure(log, Forkhelpers.Subprocess_failed 2) ->
                  (* Happens when gpg cannot find a readable signature *)
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/idl/ocaml_backend/xmlrpcclient.ml
--- a/ocaml/idl/ocaml_backend/xmlrpcclient.ml   Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/idl/ocaml_backend/xmlrpcclient.ml   Fri Dec 18 20:56:10 2009 +0000
@@ -331,34 +331,34 @@
       let unique_id = get_new_stunnel_id () in
       Stunnel.connect ~use_external_fd_wrapper ~write_to_log ~unique_id 
~verify_cert ~extended_diagnosis:true host port in
   let s = st_proc.Stunnel.fd in
-  let s_pid = st_proc.Stunnel.pid in
-    begin
-      match task_id with
-          None -> debug "Did not write stunnel pid: no task passed to http_rpc 
fn"
-        | Some t ->
-            match !set_stunnelpid_callback with
-                                 None -> warn "Did not write stunnel pid: no 
callback registered"
-                               | Some f -> f t s_pid
-    end;
-    finally
+  let s_pid = Forkhelpers.getpid st_proc.Stunnel.pid in
+  begin
+    match task_id with
+        None -> debug "Did not write stunnel pid: no task passed to http_rpc 
fn"
+      | Some t ->
+          match !set_stunnelpid_callback with
+             None -> warn "Did not write stunnel pid: no callback registered"
+           | Some f -> f t s_pid
+  end;
+  finally
     (fun () ->
-       try
-         let content_length, task_id = http_rpc_fd s headers body in
-           f content_length task_id s
-       with
-         | Connection_reset ->
-             if not use_stunnel_cache then
-               Stunnel.diagnose_failure st_proc;
-             raise Connection_reset)
+      try
+        let content_length, task_id = http_rpc_fd s headers body in
+        f content_length task_id s
+      with
+        | Connection_reset ->
+            if not use_stunnel_cache then
+              Stunnel.diagnose_failure st_proc;
+            raise Connection_reset)
     (fun () ->
-       if use_stunnel_cache
-       then
-         Stunnel_cache.add st_proc
-       else
-         begin
-           Unix.unlink st_proc.Stunnel.logfile;
-           Stunnel.disconnect st_proc
-         end
+      if use_stunnel_cache
+      then
+        Stunnel_cache.add st_proc
+      else
+        begin
+          Unix.unlink st_proc.Stunnel.logfile;
+          Stunnel.disconnect st_proc
+        end
     )
       
 
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/perftest/instrumented_xmlrpcclient.ml
--- a/ocaml/perftest/instrumented_xmlrpcclient.ml       Thu Dec 17 14:08:46 
2009 +0000
+++ b/ocaml/perftest/instrumented_xmlrpcclient.ml       Fri Dec 18 20:56:10 
2009 +0000
@@ -327,7 +327,7 @@
       let unique_id = get_new_stunnel_id () in
       Stunnel.connect ~use_external_fd_wrapper ~write_to_log ~unique_id host 
port in
   let s = st_proc.Stunnel.fd in
-  let s_pid = st_proc.Stunnel.pid in
+  let s_pid = Forkhelpers.getpid st_proc.Stunnel.pid in
     begin
       match task_id with
           None -> debug "Did not write stunnel pid: no task passed to http_rpc 
fn"
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/bootloader.ml
--- a/ocaml/xapi/bootloader.ml  Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/bootloader.ml  Fri Dec 18 20:56:10 2009 +0000
@@ -89,11 +89,7 @@
        (* Capture stderr output for logging *)
        match with_logfile_fd "bootloader"
        (fun log_fd ->
-         let pid = safe_close_and_exec
-           [ Dup2(result_in, Unix.stdout);
-             Dup2(log_fd, Unix.stderr) ]
-           [ Unix.stdout; Unix.stderr ] (* close all but these *)
-           bootloader_path cmdline in
+         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 *)
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/events.ml
--- a/ocaml/xapi/events.ml      Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/events.ml      Fri Dec 18 20:56:10 2009 +0000
@@ -49,8 +49,8 @@
                let path = "/opt/xensource/libexec/dumpcore" in
                let args = [ "-domid"; string_of_int domid;
                              "-file"; filename ] in
-               let pid = Forkhelpers.safe_close_and_exec [] [] path args in
-               match snd (Unix.waitpid [] pid) with
+               let pid = Forkhelpers.safe_close_and_exec None None None [] 
path args in
+               match snd (Forkhelpers.waitpid pid) with
                | Unix.WEXITED 0   -> ()
                | Unix.WEXITED n   -> raise (Failed (sprintf "exit code %d" n));
                | Unix.WSIGNALED i -> raise (Failed (sprintf "signal %d" i));
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/helper_process.ml
--- a/ocaml/xapi/helper_process.ml      Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/helper_process.ml      Fri Dec 18 20:56:10 2009 +0000
@@ -15,5 +15,15 @@
 (* a reasonable error. For now, just return the error code! *)
 let generic_handler cmd n =
   raise (Api_errors.Server_error (Api_errors.internal_error, [string_of_int 
n]))
-    
-let get_process_output ?(handler=generic_handler) cmd = 
Unixext.get_process_output ~handler cmd
+
+exception Process_output_error of string    
+let get_process_output ?(handler=generic_handler) cmd = 
+  let args = Stringext.String.split ' ' cmd in
+  try
+    fst (Forkhelpers.execute_command_get_output (List.hd args) (List.tl args))
+  with 
+    | Forkhelpers.Spawn_internal_error(err,out,Unix.WEXITED n) ->
+       handler cmd n
+    | _ -> 
+       raise (Process_output_error cmd)
+
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/system_status.ml
--- a/ocaml/xapi/system_status.ml       Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/system_status.ml       Fri Dec 18 20:56:10 2009 +0000
@@ -32,56 +32,47 @@
 (* This fn outputs xen-bugtool straight to the socket, only
    for tar output. It should work on embedded edition *)
 let send_via_fd __context s entries output =
-  (* Make a copy of the socket fd as it closes when we exec *)
-  let cp_of_s = Unix.dup s in
-    finally
-      (fun () ->
-         let output_fd = Unixext.int_of_file_descr cp_of_s in
-         let params = 
-           [sprintf "--entries=%s" entries;
-            "--silent";
-            "--yestoall";
-            sprintf "--output=%s" output;
-            sprintf "--outfd=%i" output_fd]
-         in
-         let cmd = 
-           sprintf "%s %s" xen_bugtool (String.concat " " params)
-         in
-           debug "running %s" cmd;
-           try
-             let headers = 
-               Http.http_200_ok ~keep_alive:false ~version:"1.0" () @
-                 [ "Server: "^Xapi_globs.xapi_user_agent;
-                   "Content-Type: " ^ content_type;
-                   "Content-Disposition: attachment; 
filename=\"system_status.tgz\""] 
-             in
-               Http_svr.headers s headers;
-                   
-               let result =  with_logfile_fd "get-system-status"
-                    (fun log_fd ->
-                       let pid = 
-                      safe_close_and_exec 
-                        [ Close(Unix.stdin);
-                          Dup2(log_fd, Unix.stdout);
-                                 Dup2(log_fd, Unix.stderr); ]
-                               [ Unix.stdout; Unix.stderr; cp_of_s ] 
-                        xen_bugtool params
-                    in
-                      waitpid pid
-                 )
-               in
-                 match result with
-                      | Success _ -> debug "xen-bugtool exited successfully"
-                       
-                      | Failure (log, exn) ->
-                          debug "xen-bugtool failed with output: %s" log;
-                          raise exn
-           with e ->
-             let msg = "xen-bugtool failed: " ^ (Printexc.to_string e) in
-               error "%s" msg;
-               raise (Api_errors.Server_error 
(Api_errors.system_status_retrieval_failed, [msg]))
+  let s_uuid = Uuid.to_string (Uuid.make_uuid ()) in
+  
+  let params = 
+    [sprintf "--entries=%s" entries;
+     "--silent";
+     "--yestoall";
+     sprintf "--output=%s" output;
+     "--outfd="^s_uuid]
+  in
+  let cmd = 
+    sprintf "%s %s" xen_bugtool (String.concat " " params)
+  in
+  debug "running %s" cmd;
+  try
+    let headers = 
+      Http.http_200_ok ~keep_alive:false ~version:"1.0" () @
+        [ "Server: "^Xapi_globs.xapi_user_agent;
+          "Content-Type: " ^ content_type;
+          "Content-Disposition: attachment; filename=\"system_status.tgz\""] 
+    in
+    Http_svr.headers s headers;
+    
+    let result =  with_logfile_fd "get-system-status"
+      (fun log_fd ->
+       let pid = 
+          safe_close_and_exec None (Some log_fd) (Some log_fd) [(s_uuid,s)] 
xen_bugtool params
+       in
+       waitpid_fail_if_bad_exit pid
       )
-      (fun () -> Unix.close cp_of_s)
+    in
+    match result with
+      | Success _ -> debug "xen-bugtool exited successfully"
+         
+      | Failure (log, exn) ->
+         debug "xen-bugtool failed with output: %s" log;
+         raise exn
+  with e ->
+    let msg = "xen-bugtool failed: " ^ (Printexc.to_string e) in
+    error "%s" msg;
+    raise (Api_errors.Server_error (Api_errors.system_status_retrieval_failed, 
[msg]))
+
       
 (* This fn outputs xen-bugtool into a file and then write the 
    file out to the socket, to deal with zipped bugtool outputs 
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/xapi_host.ml
--- a/ocaml/xapi/xapi_host.ml   Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/xapi_host.ml   Fri Dec 18 20:56:10 2009 +0000
@@ -924,7 +924,7 @@
   Db.Host.remove_from_other_config ~__context ~self:host 
~key:Xapi_globs.host_no_local_storage
 
 let disable_binary_storage ~__context ~host =
-  ignore(Unixext.get_process_output (Printf.sprintf "/bin/rm -rf %s" 
Xapi_globs.xapi_blob_location));
+  ignore(Helpers.get_process_output (Printf.sprintf "/bin/rm -rf %s" 
Xapi_globs.xapi_blob_location));
   Db.Host.remove_from_other_config ~__context ~self:host 
~key:Xapi_globs.host_no_local_storage;
   Db.Host.add_to_other_config ~__context ~self:host 
~key:Xapi_globs.host_no_local_storage ~value:"true"
 
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/xapi_host_backup.ml
--- a/ocaml/xapi/xapi_host_backup.ml    Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/xapi_host_backup.ml    Fri Dec 18 20:56:10 2009 +0000
@@ -30,13 +30,10 @@
   match 
        (with_logfile_fd "host-backup" 
           (fun log_fd ->
-                 let pid = safe_close_and_exec 
-                   [ Dup2(s, Unix.stdout);
-                     Dup2(log_fd, Unix.stderr) ] 
-                   [ Unix.stdout; Unix.stderr ] host_backup [] in
-
-          let waitpid () =
-            match Unix.waitpid [Unix.WNOHANG] pid with
+                 let pid = safe_close_and_exec None (Some s) (Some log_fd) [] 
host_backup [] in
+                 
+         let waitpid () =
+            match Forkhelpers.waitpid_nohang pid with
               | 0, _ -> false
               | _, Unix.WEXITED 0 -> true
               | _, Unix.WEXITED n -> raise (Subprocess_failed n)
@@ -108,12 +105,7 @@
          (* XXX: ideally need to log this stuff *)
           let result =  with_logfile_fd "host-restore-log"
            (fun log_fd ->
-             let pid = safe_close_and_exec 
-               [ Dup2(out_pipe, Unix.stdin);
-                 Dup2(log_fd, Unix.stdout);
-                 Dup2(log_fd, Unix.stderr) ]
-               [ Unix.stdin; Unix.stdout; Unix.stderr ] 
-                host_restore [] in
+             let pid = safe_close_and_exec (Some out_pipe) (Some log_fd) (Some 
log_fd) [] host_restore [] in
               
               close out_pipe;
               
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/xapi_logs_download.ml
--- a/ocaml/xapi/xapi_logs_download.ml  Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/xapi_logs_download.ml  Fri Dec 18 20:56:10 2009 +0000
@@ -28,6 +28,5 @@
       
       debug "send the http headers";
       let fd = string_of_int (Unixext.int_of_file_descr Unix.stdout) in
-      let pid = safe_close_and_exec [ Dup2(s, Unix.stdout) ] 
-       [ Unix.stdout ] logs_download [] in
-      waitpid pid)
+      let pid = safe_close_and_exec None (Some s) None [] logs_download [] in
+      waitpid_fail_if_bad_exit pid)
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/xapi_network_real.ml
--- a/ocaml/xapi/xapi_network_real.ml   Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/xapi_network_real.ml   Fri Dec 18 20:56:10 2009 +0000
@@ -59,12 +59,8 @@
   begin
     match with_logfile_fd "ifconfig"
       (fun out ->
-       let pid = safe_close_and_exec
-         [ Dup2(out, Unix.stdout);
-           Dup2(out, Unix.stderr)]
-         [ Unix.stdout; Unix.stderr ] (* close all but these *)
-         "/sbin/ifconfig" [bridge;ip;"up"] in
-       Unix.waitpid [] pid)
+       let pid = safe_close_and_exec None (Some out) (Some out) [] 
"/sbin/ifconfig" [bridge;ip;"up"] in
+       waitpid pid)
     with
       | Success(log,_) -> ()
       | Failure(log,_) -> error "ifconfig failure: %s" log
@@ -72,12 +68,8 @@
   begin
     match with_logfile_fd "fix_firewall"
       (fun out ->
-       let pid = safe_close_and_exec
-         [ Dup2(out, Unix.stdout);
-           Dup2(out, Unix.stderr)]
-         [ Unix.stdout; Unix.stderr ] (* close all but these *)
-         "/bin/bash" [Constants.fix_firewall_script;bridge;"start"] in
-       Unix.waitpid [] pid)
+       let pid = safe_close_and_exec None (Some out) (Some out) [] "/bin/bash" 
[Constants.fix_firewall_script;bridge;"start"] in
+       waitpid pid)
     with
       | Success(log,_) -> ()
       | Failure(log,_) -> error "ifconfig failure: %s" log
@@ -98,12 +90,8 @@
   begin
     match with_logfile_fd "fix_firewall"
       (fun out ->
-       let pid = safe_close_and_exec
-         [ Dup2(out, Unix.stdout);
-           Dup2(out, Unix.stderr)]
-         [ Unix.stdout; Unix.stderr ] (* close all but these *)
-         "/bin/bash " [Constants.fix_firewall_script;bridge] in
-       Unix.waitpid [] pid)
+       let pid = safe_close_and_exec None (Some out) (Some out) [] "/bin/bash 
" [Constants.fix_firewall_script;bridge] in
+       waitpid pid)
     with
       | Success(log,_) -> ()
       | Failure(log,_) -> error "ifconfig failure: %s" log
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/xapi_pool_patch.ml
--- a/ocaml/xapi/xapi_pool_patch.ml     Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/xapi_pool_patch.ml     Fri Dec 18 20:56:10 2009 +0000
@@ -98,11 +98,8 @@
       (fun () ->
         with_logfile_fd "patch"
           (fun log_fd ->
-            let pid = safe_close_and_exec [ Dup2(log_fd, Unix.stdout);
-                                           Dup2(log_fd, Unix.stderr);
-                                           Close(Unix.stdin) ]
-             [ Unix.stdout; Unix.stderr ] run_path args in
-            waitpid pid)
+            let pid = safe_close_and_exec None (Some log_fd) (Some log_fd) [] 
run_path args in
+            waitpid_fail_if_bad_exit pid)
       )
       (fun () -> Unixext.unlink_safe run_path)
 
@@ -265,11 +262,8 @@
   let output =
     with_logfile_fd "sync"
       (fun log_fd ->
-         let pid = safe_close_and_exec [ Dup2(log_fd, Unix.stdout);
-                                                        Dup2(log_fd, 
Unix.stderr);
-                                                        Close(Unix.stdin) ]
-              [ Unix.stdout; Unix.stderr ] bin_sync [] in
-           waitpid pid) 
+         let pid = safe_close_and_exec None (Some log_fd) (Some log_fd) [] 
bin_sync [] in
+         waitpid_fail_if_bad_exit pid) 
   in 
     match output with
       | Failure(log, exn) ->
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/xapi_remotecmd.ml
--- a/ocaml/xapi/xapi_remotecmd.ml      Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/xapi_remotecmd.ml      Fri Dec 18 20:56:10 2009 +0000
@@ -24,17 +24,12 @@
 let do_cmd s cmd args =
   let cmdline = String.concat " " (cmd :: args) in
 
-  let pid = ref 0 in
+  let pid = ref Forkhelpers.nopid in
   match with_logfile_fd "execute_command_get_output"
     (fun log_fd ->
       (* Capture stderr output for logging *)
-      pid := safe_close_and_exec
-       [ Dup2(s, Unix.stdout);
-         Dup2(s, Unix.stdin);
-         Dup2(log_fd, Unix.stderr);]
-       [ Unix.stdout; Unix.stdin; Unix.stderr ] (* close all but these *)
-       cmd args;
-      snd(Unix.waitpid [] !pid)) with
+      pid := safe_close_and_exec (Some s) (Some s) (Some log_fd) [] cmd args;
+      snd(waitpid !pid)) with
       | Success(log, status) ->
          debug "log: %s" log;
          begin match status with
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/xapi_sr.ml
--- a/ocaml/xapi/xapi_sr.ml     Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/xapi_sr.ml     Fri Dec 18 20:56:10 2009 +0000
@@ -254,6 +254,15 @@
            Client.PBD.destroy ~rpc ~session_id ~self:pbd)
         pbds)
 
+let probe ~__context ~host ~device_config ~_type ~sm_config =
+       debug "SR.probe sm_config=[ %s ]" (String.concat "; " (List.map (fun 
(k, v) -> k ^ " = " ^ v) sm_config));
+
+       let _type = String.lowercase _type in
+       if not(List.mem _type (Sm.supported_drivers ()))
+       then raise (Api_errors.Server_error(Api_errors.sr_unknown_driver, [ 
_type ]));
+       let subtask_of = Some (Context.get_task_id __context) in
+       Sm.sr_probe (subtask_of, Sm.sm_master true :: device_config) _type 
sm_config
+
 (* Create actually makes the SR on disk, and introduces it into db, and 
creates PDB record for current host *)
 let create  ~__context ~host ~device_config ~(physical_size:int64) ~name_label 
~name_description
                ~_type ~content_type ~shared ~sm_config =
@@ -261,6 +270,21 @@
        let _type = String.lowercase _type in
        if not(List.mem _type (Sm.supported_drivers ()))
                then raise 
(Api_errors.Server_error(Api_errors.sr_unknown_driver, [ _type ]));
+
+       let probe_result = probe ~__context ~host ~device_config ~_type 
~sm_config in
+       begin 
+         match Xml.parse_string probe_result with
+           | Xml.Element("SRlist", _, children) -> ()
+           | _ -> 
+               (* Figure out what was missing, then throw the appropriate 
error *)
+               match String.lowercase _type with
+                 | "lvmoiscsi" ->
+                     if not (List.exists (fun (s,_) -> "targetiqn" = 
String.lowercase s) device_config)
+                     then raise (Api_errors.Server_error 
("SR_BACKEND_FAILURE_96",["";"";probe_result]))
+                     else if not (List.exists (fun (s,_) -> "scsiid" = 
String.lowercase s) device_config)
+                     then raise (Api_errors.Server_error 
("SR_BACKEND_FAILURE_107",["";"";probe_result]))
+                 | _ -> ()
+       end;
 
        let sr_uuid = Uuid.make_uuid() in
        let sr_uuid_str = Uuid.to_string sr_uuid in
@@ -392,15 +416,6 @@
       Db.SR.set_shared ~__context ~self:sr ~value
     end
   
-let probe ~__context ~host ~device_config ~_type ~sm_config =
-       debug "SR.probe sm_config=[ %s ]" (String.concat "; " (List.map (fun 
(k, v) -> k ^ " = " ^ v) sm_config));
-
-       let _type = String.lowercase _type in
-       if not(List.mem _type (Sm.supported_drivers ()))
-       then raise (Api_errors.Server_error(Api_errors.sr_unknown_driver, [ 
_type ]));
-       let subtask_of = Some (Context.get_task_id __context) in
-       Sm.sr_probe (subtask_of, Sm.sm_master true :: device_config) _type 
sm_config
-
 let set_virtual_allocation ~__context ~self ~value = 
   Db.SR.set_virtual_allocation ~__context ~self ~value
 
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/xapi_support.ml
--- a/ocaml/xapi/xapi_support.ml        Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/xapi_support.ml        Fri Dec 18 20:56:10 2009 +0000
@@ -33,11 +33,7 @@
 
   match with_logfile_fd label
   (fun log_fd ->
-     let pid = safe_close_and_exec 
-       [ Close(Unix.stdin);
-        Dup2(log_fd, Unix.stdout);
-        Dup2(log_fd,Unix.stderr) ]
-       [ Unix.stdin; Unix.stdout; Unix.stderr ] upload_wrapper [file; url; 
proxy] in
+     let pid = safe_close_and_exec None (Some log_fd) (Some log_fd) [] 
upload_wrapper [file; url; proxy] in
      waitpid pid) with
   | Success _ -> debug "Upload succeeded"
   | Failure (log, exn) ->
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/xapi_templates_install.ml
--- a/ocaml/xapi/xapi_templates_install.ml      Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/xapi_templates_install.ml      Fri Dec 18 20:56:10 2009 +0000
@@ -66,24 +66,20 @@
 
           match with_logfile_fd "install-log"
             (fun log ->
-              let pid = safe_close_and_exec ~env:(Array.of_list env)
-                [ Dup2(log, Unix.stdout);
-                  Dup2(log, Unix.stderr) ]
-                [ Unix.stdout; Unix.stderr ]
-                script [] in
+              let pid = safe_close_and_exec ~env:(Array.of_list env) None 
(Some log) (Some log) [] script [] in
               let starttime = Unix.time () in
               let rec update_progress () =
                 (* Check for cancelling *)
                 if TaskHelper.is_cancelling ~__context
                 then
                   begin
-                    Unix.kill pid Sys.sigterm;
-                    let _ = Unix.waitpid [] pid in
+                    Unix.kill (Forkhelpers.getpid pid) Sys.sigterm;
+                    let _ = Forkhelpers.waitpid pid in
                     raise (Api_errors.Server_error (Api_errors.task_cancelled, 
[]))
                   end;
                 
-                let (newpid,status) = Unix.waitpid [Unix.WNOHANG] pid in
-                if newpid = pid 
+                let (newpid,status) = Forkhelpers.waitpid_nohang pid in
+                if newpid <> 0 
                 then 
                   (match status with 
                     | Unix.WEXITED 0 -> (newpid,status) 
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/xapi_udhcpd.ml
--- a/ocaml/xapi/xapi_udhcpd.ml Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/xapi_udhcpd.ml Fri Dec 18 20:56:10 2009 +0000
@@ -75,12 +75,8 @@
   kill_if_running ();
   match with_logfile_fd "udhcpd"
     (fun out ->
-      let pid = safe_close_and_exec
-       [ Dup2(out, Unix.stdout);
-         Dup2(out, Unix.stderr)]
-       [ Unix.stdout; Unix.stderr ] (* close all but these *)
-       command ["/var/xapi/udhcpd.conf"] in
-      ignore(Unix.waitpid [] pid))
+      let pid = safe_close_and_exec None (Some out) (Some out) [] command 
["/var/xapi/udhcpd.conf"] in
+      ignore(waitpid pid))
   with
     | Success(log,_) -> debug "success! %s" log
     | Failure(log,_) -> debug "failure! %s" log
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/xapi_vbd_helpers.ml
--- a/ocaml/xapi/xapi_vbd_helpers.ml    Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/xapi_vbd_helpers.ml    Fri Dec 18 20:56:10 2009 +0000
@@ -136,8 +136,8 @@
     if not vdi_record.Db_actions.vDI_managed
     then set_errors Api_errors.vdi_not_managed [ _ref ] all_ops;
 
-       let operations_not_allowed_when_vdi_is_busy =
-               List.exists (fun x -> List.mem x current_ops) [ `attach; `plug; 
`insert ] in
+    let operations_not_allowed_when_vdi_is_busy =
+      List.exists (fun x -> List.mem x current_ops) [ `attach; `plug; `insert 
] in
 
     if operations_not_allowed_when_vdi_is_busy && 
vdi_record.Db_actions.vDI_current_operations <> [] then begin
       debug "VBD operation %s not allowed because VDI.current-operations = [ 
%s ]"
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xapi/xapi_vncsnapshot.ml
--- a/ocaml/xapi/xapi_vncsnapshot.ml    Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xapi/xapi_vncsnapshot.ml    Fri Dec 18 20:56:10 2009 +0000
@@ -34,10 +34,10 @@
           (fun () ->
              let vnc_port = Int64.to_int (Db.Console.get_port ~__context 
~self:console) in
              
-           let pid = safe_close_and_exec [ ] [ ]
-             vncsnapshot [ "-quiet"; "-encodings"; "\"raw\"";
-                           Printf.sprintf "%s:%d" "127.0.0.1" (vnc_port-5900); 
tmp ] in
-           waitpid pid;
+           let pid = safe_close_and_exec None None None [] vncsnapshot 
+             [ "-quiet"; "-encodings"; "\"raw\"";
+               Printf.sprintf "%s:%d" "127.0.0.1" (vnc_port-5900); tmp ] in
+           waitpid_fail_if_bad_exit pid;
            Http_svr.response_file ~mime_content_type:None s tmp
           )
           (fun () -> try Unix.unlink tmp with _ -> ())
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xenops/device.ml
--- a/ocaml/xenops/device.ml    Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xenops/device.ml    Fri Dec 18 20:56:10 2009 +0000
@@ -903,15 +903,9 @@
                  "-x"; sprintf "/local/domain/%d/serial/0" domid;
                ] @ load_args statefile in
        (* Now add the close fds wrapper *)
-       let cmdline = Forkhelpers.close_and_exec_cmdline [] vncterm_wrapper l in
-       debug "Executing [ %s ]" (String.concat " " cmdline);
-
-       let argv_0 = List.hd cmdline and argv = Array.of_list cmdline in
-       Unixext.double_fork (fun () ->
-               Sys.set_signal Sys.sigint Sys.Signal_ignore;
-
-               Unix.execvp argv_0 argv
-       );
+       let pid = Forkhelpers.safe_close_and_exec None None None [] 
vncterm_wrapper l in
+       Forkhelpers.dontwaitpid pid;
+       
        (* Block waiting for it to write the VNC port into the store *)
        try
          let port = Watch.wait_for ~xs (Watch.value_to_appear (path domid)) in
@@ -1489,15 +1483,9 @@
           @ (List.fold_left (fun l (k, v) -> ("-" ^ k) :: (match v with None 
-> l | Some v -> v :: l)) [] info.extras)
                in
        (* Now add the close fds wrapper *)
-       let cmdline = Forkhelpers.close_and_exec_cmdline [] dmpath l in
-       debug "qemu-dm: executing commandline: %s" (String.concat " " cmdline);
+       let pid = Forkhelpers.safe_close_and_exec None None None [] dmpath l in
+       Forkhelpers.dontwaitpid pid;
 
-       let argv_0 = List.hd cmdline and argv = Array.of_list cmdline in
-       Unixext.double_fork (fun () ->
-               Sys.set_signal Sys.sigint Sys.Signal_ignore;
-
-               Unix.execvp argv_0 argv
-       );
        debug "qemu-dm: should be running in the background (stdout and stderr 
redirected to %s)" log;
 
        (* We know qemu is ready (and the domain may be unpaused) when
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xenops/domain.ml
--- a/ocaml/xenops/domain.ml    Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xenops/domain.ml    Fri Dec 18 20:56:10 2009 +0000
@@ -581,15 +581,17 @@
                raise Restore_signature_mismatch;
 
        Unix.clear_close_on_exec fd;
+       let fd_uuid = Uuid.to_string (Uuid.make_uuid ()) in
+
        let cnx = XenguestHelper.connect
          ([
            "-mode"; if hvm then "hvm_restore" else "restore";
            "-domid"; string_of_int domid;
-           "-fd"; string_of_int (Obj.magic fd);
+           "-fd"; fd_uuid;
            "-store_port"; string_of_int store_port;
            "-console_port"; string_of_int console_port;
            "-fork"; "true";
-         ] @ extras) [ fd ] in
+         ] @ extras) [ fd_uuid, fd ] in
 
        let line = finally
          (fun () -> XenguestHelper.receive_success cnx)
@@ -703,6 +705,7 @@
 let suspend ~xc ~xs ~hvm domid fd flags ?(progress_callback = fun _ -> ()) 
do_suspend_callback =
        debug "Domain.suspend domid=%d" domid;
        Io.write fd save_signature;
+       let fd_uuid = Uuid.to_string (Uuid.make_uuid ()) in
 
        let cmdline_to_flag flag =
                match flag with
@@ -712,13 +715,13 @@
        let flags' = List.map cmdline_to_flag flags in
 
        let xenguestargs = [
-               "-fd"; string_of_int (Obj.magic fd);
+               "-fd"; fd_uuid;
                "-mode"; if hvm then "hvm_save" else "save";
                "-domid"; string_of_int domid;
                "-fork"; "true";
        ] @ (List.concat flags') in
 
-       let cnx = XenguestHelper.connect xenguestargs [ fd ] in
+       let cnx = XenguestHelper.connect xenguestargs [ fd_uuid, fd ] in
        finally (fun () ->
                debug "Blocking for suspend notification from xenguest";
 
diff -r 5d6a3e43431f -r d0c22775c225 ocaml/xenops/xenguestHelper.ml
--- a/ocaml/xenops/xenguestHelper.ml    Thu Dec 17 14:08:46 2009 +0000
+++ b/ocaml/xenops/xenguestHelper.ml    Fri Dec 18 20:56:10 2009 +0000
@@ -32,11 +32,11 @@
 
 (** We do all our IO through the buffered channels but pass the 
     underlying fds as integers to the forked helper on the commandline. *)
-type t = in_channel * out_channel * Unix.file_descr * Unix.file_descr * int
+type t = in_channel * out_channel * Unix.file_descr * Unix.file_descr * 
Forkhelpers.pidty
 
 (** Fork and run a xenguest helper with particular args, leaving 'fds' open 
     (in addition to internal control I/O fds) *)
-let connect (args: string list) (fds: Unix.file_descr list) : t =
+let connect (args: string list) (fds: (string * Unix.file_descr) list) : t =
        debug "connect: args = [ %s ]" (String.concat " " args);
        (* Need to send commands and receive responses from the
           slave process *)
@@ -46,19 +46,22 @@
        let last_log_file = "/tmp/xenguest.log" in
        (try Unix.unlink last_log_file with _ -> ());
 
+       let slave_to_server_w_uuid = Uuid.to_string (Uuid.make_uuid ()) in
+       let server_to_slave_r_uuid = Uuid.to_string (Uuid.make_uuid ()) in
+
        let slave_to_server_r, slave_to_server_w = Unix.pipe () in
        let server_to_slave_r, server_to_slave_w = Unix.pipe () in
-       let args = [ "-controloutfd";
-                    string_of_int (Obj.magic slave_to_server_w);
-                    "-controlinfd";
-                    string_of_int (Obj.magic server_to_slave_r);
+
+       let args = [ "-controloutfd"; slave_to_server_w_uuid;
+                    "-controlinfd"; server_to_slave_r_uuid;
                     "-debuglog";
                     last_log_file
-                  ] @ (if using_xiu then [ "-fake" ] else []) @ args in
-       let pid = Forkhelpers.safe_close_and_exec [] 
-            (fds @ [ Unix.stdout; Unix.stderr; slave_to_server_w; 
server_to_slave_r ]) (* close all but these *)
-            path args in
-
+       ] @ (if using_xiu then [ "-fake" ] else []) @ args in
+       let pid = Forkhelpers.safe_close_and_exec None None None 
+         ([ slave_to_server_w_uuid, slave_to_server_w;
+           server_to_slave_r_uuid, server_to_slave_r ] @ fds)
+         path args in
+       
        Unix.close slave_to_server_w;
        Unix.close server_to_slave_r;
 
@@ -73,8 +76,8 @@
        Unix.close r;
        Unix.close w;
        (* just in case *)
-       Unix.kill pid Sys.sigterm;
-       ignore(Unix.waitpid [] pid)
+       (try Unix.kill (Forkhelpers.getpid pid) Sys.sigterm with _ -> ());
+       ignore(Forkhelpers.waitpid pid)
 
 (** immediately write a command to the control channel *)
 let send (_, out, _, _, _) txt = output_string out txt; flush out
25 files changed, 189 insertions(+), 252 deletions(-)
ocaml/auth/extauth_plugin_ADlikewise.ml     |   32 +--------
ocaml/database/master_connection.ml         |    2 
ocaml/database/redo_log.ml                  |   17 ++---
ocaml/gpg/gpg.ml                            |   14 +---
ocaml/idl/ocaml_backend/xmlrpcclient.ml     |   52 +++++++--------
ocaml/perftest/instrumented_xmlrpcclient.ml |    2 
ocaml/xapi/bootloader.ml                    |    6 -
ocaml/xapi/events.ml                        |    4 -
ocaml/xapi/helper_process.ml                |   14 +++-
ocaml/xapi/system_status.ml                 |   89 ++++++++++++---------------
ocaml/xapi/xapi_host.ml                     |    2 
ocaml/xapi/xapi_host_backup.ml              |   18 +----
ocaml/xapi/xapi_logs_download.ml            |    5 -
ocaml/xapi/xapi_network_real.ml             |   24 +------
ocaml/xapi/xapi_pool_patch.ml               |   14 +---
ocaml/xapi/xapi_remotecmd.ml                |   11 ---
ocaml/xapi/xapi_sr.ml                       |   33 +++++++---
ocaml/xapi/xapi_support.ml                  |    6 -
ocaml/xapi/xapi_templates_install.ml        |   14 +---
ocaml/xapi/xapi_udhcpd.ml                   |    8 --
ocaml/xapi/xapi_vbd_helpers.ml              |    4 -
ocaml/xapi/xapi_vncsnapshot.ml              |    8 +-
ocaml/xenops/device.ml                      |   22 +-----
ocaml/xenops/domain.ml                      |   11 ++-
ocaml/xenops/xenguestHelper.ml              |   29 ++++----


Attachment: xen-api.hg.patch
Description: Text Data

_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.