WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-api

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

To: xen-api@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-API] [SPAM] [PATCH] Make xapi use the fork/exec daemon
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
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
Importance: Low
List-help: <mailto:xen-api-request@lists.xensource.com?subject=help>
List-id: Discussion of API issues surrounding Xen <xen-api.lists.xensource.com>
List-post: <mailto:xen-api@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-api>, <mailto:xen-api-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-api>, <mailto:xen-api-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-api-bounces@xxxxxxxxxxxxxxxxxxx
# 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
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-API] [SPAM] [PATCH] Make xapi use the fork/exec daemon, David Scott <=