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

[Xen-API] [PATCH] Merge Stunnel.attempt_one_connect_new into Stunnel.attempt_one_connect and other minor improvements


  • To: xen-api@xxxxxxxxxxxxxxxxxxx
  • From: Zheng Li <dev@xxxxxxxx>
  • Date: Fri, 02 Apr 2010 21:20:04 -0000
  • Delivery-date: Fri, 02 Apr 2010 14:20:56 -0700
  • List-id: Discussion of API issues surrounding Xen <xen-api.lists.xensource.com>

Signed-off-by: Zheng Li <dev@xxxxxxxx>


 stunnel/stunnel.ml |  183 ++++++++++++++++++++-------------------------
 1 files changed, 80 insertions(+), 103 deletions(-)


diff -r 30faec648dfb -r 704a6cc45f4b stunnel/stunnel.ml
--- a/stunnel/stunnel.ml        Tue Mar 23 00:39:58 2010 +0000
+++ b/stunnel/stunnel.ml        Wed Mar 31 10:26:20 2010 +0100
@@ -29,6 +29,7 @@
 let new_stunnel_path = "/usr/sbin/stunnelng"
 
 let cached_stunnel_path = ref None
+let stunnel_logger = ref ignore
 
 let init_stunnel_path () =
   try cached_stunnel_path := Some (Unix.getenv "XE_STUNNEL")
@@ -142,112 +143,83 @@
    exception instead *)
 exception Stunnel_initialisation_failed
 
-let attempt_one_connect_new ?unique_id ?(use_external_fd_wrapper = true) 
?(write_to_log = fun _ -> ()) verify_cert extended_diagnosis host port = 
-  assert (not verify_cert); (* !!! Unimplemented *)
-  assert (not extended_diagnosis); (* !!! Unimplemented *)
-  let data_out,data_in = Unix.socketpair Unix.PF_UNIX Unix.SOCK_STREAM 0 in
-  let args = [ "-m"; "client"; "-s"; "-"; "-d"; Printf.sprintf "%s:%d" host 
port ] in
-  let t = { pid = Nopid; fd = data_out; host = host; port = port; 
-           connected_time = Unix.gettimeofday (); unique_id = unique_id;
-           logfile = "" } in
-  let to_close = ref [ data_in ] in
-  let result = Forkhelpers.with_logfile_fd "stunnel" (fun logfd ->
-    let fdops = [
-      Unsafe.Dup2(data_in, Unix.stdin);
-      Unsafe.Dup2(data_in, Unix.stdout);
-      Unsafe.Dup2(logfd, Unix.stderr)
-    ] in
-    let fds_needed = [ Unix.stdin; Unix.stdout; Unix.stderr ] in
-    t.pid <- (
-      if use_external_fd_wrapper then
-        FEFork (Forkhelpers.safe_close_and_exec (Some data_in) (Some data_in) 
(Some logfd) [] (stunnel_path ()) args)
-      else
-               StdFork(Unsafe.fork_and_exec ~pre_exec:(fun _ -> 
-          List.iter Unsafe.do_fd_operation fdops;
-          Unixext.close_all_fds_except fds_needed
-               
-               ) ((stunnel_path ()) :: args))
-    );
-    List.iter Unix.close [ data_in ];
-  ) in
-  List.iter Unix.close !to_close; 
-  match result with
-  | Forkhelpers.Failure(log, exn) ->
-      write_to_log ("failed: Log from stunnel: [" ^ log ^ "]");
-      disconnect t;
-      raise exn
-  | Forkhelpers.Success(log, _) -> 
-      write_to_log ("success: Log from stunnel: [" ^ log ^ "]");
-      t
 
 (* Internal function which may throw Stunnel_initialisation_failed *)
-let attempt_one_connect ?unique_id ?(use_external_fd_wrapper = true) 
?(write_to_log = fun _ -> ()) verify_cert extended_diagnosis host port =
-  let data_out,data_in = Unix.socketpair Unix.PF_UNIX Unix.SOCK_STREAM 0
-  and config_out, config_in = Unix.pipe ()
-  in
-  let config_out_uuid = Uuid.to_string (Uuid.make_uuid ()) in
-  (* FDs we must close. NB stdin_in and stdout_out end up in our 't' record *)
-  let to_close = ref [ data_in; config_out; config_in  ] in
-  let close fd = 
-    if List.mem fd !to_close 
-    then (Unix.close fd; to_close := List.filter (fun x -> x <> fd) !to_close) 
in
-  let t = { pid = Nopid; fd = data_out; host = host; port = port; 
-           connected_time = Unix.gettimeofday (); unique_id = unique_id;
-           logfile = "" } in
+let attempt_one_connect ?unique_id ?(use_external_fd_wrapper = true)
+    ?(write_to_log = fun _ -> ()) verify_cert extended_diagnosis host port =
+  let fds_needed = ref [ Unix.stdin; Unix.stdout; Unix.stderr ] in
+  let config_in, config_out, configs, args = 
+    if !use_new_stunnel
+    then begin
+      assert (not verify_cert); (* !! Unimplemented *)
+      let args = [ "-m"; "client"; "-s"; "-"; "-d"; 
+                   Printf.sprintf "%s:%d" host port ] in
+      None, None, [], (if extended_diagnosis then "-v" :: args else args)
+    end else begin
+      let config_out, config_in = Unix.pipe () in
+      let config_out_uuid = Uuid.to_string (Uuid.make_uuid ()) in
+      let config_out_fd = 
+        string_of_int (Unixext.int_of_file_descr config_out) in
+      fds_needed := config_out :: !fds_needed;
+      Some config_in, Some config_out, [(config_out_uuid, config_out)],
+      ["-fd"; if use_external_fd_wrapper then config_out_uuid else 
config_out_fd]
+    end in
+  let data_out,data_in = Unix.socketpair Unix.PF_UNIX Unix.SOCK_STREAM 0 in
+  let t = 
+    { pid = Nopid; fd = data_out; host = host; port = port; 
+      connected_time = Unix.gettimeofday (); unique_id = unique_id; 
+      logfile = "" } in
   let result = Forkhelpers.with_logfile_fd "stunnel"
     ~delete:(not extended_diagnosis)
     (fun logfd ->
        let path = stunnel_path() in
        let fdops = 
-        [ Unsafe.Dup2(data_in, Unix.stdin);
-          Unsafe.Dup2(data_in, Unix.stdout);
-          Unsafe.Dup2(logfd, Unix.stderr) ] in
-       let fds_needed = [ Unix.stdin; Unix.stdout; Unix.stderr; config_out ] in
-       let args_external = [ "-fd"; config_out_uuid ] in
-          let args_internal = [ "-fd"; string_of_int 
(Unixext.int_of_file_descr config_out) ] in
-       if use_external_fd_wrapper then begin
-        let cmdline = Printf.sprintf "Using commandline: %s\n" (String.concat 
" " (path::args_external)) in
-        write_to_log cmdline;
-       end;
+         [ Unsafe.Dup2(data_in, Unix.stdin);
+                Unsafe.Dup2(data_in, Unix.stdout);
+                Unsafe.Dup2(logfd, Unix.stderr) ] in
        t.pid <-
-        if use_external_fd_wrapper
-        then FEFork(Forkhelpers.safe_close_and_exec (Some data_in) (Some 
data_in) (Some logfd) [(config_out_uuid, config_out)] path args_external)
-        else StdFork(Unsafe.fork_and_exec ~pre_exec:
-                         (fun _ -> 
-                           List.iter Unsafe.do_fd_operation fdops;
-                           Unixext.close_all_fds_except fds_needed) 
-                         (path::args_internal));
-       List.iter close [ data_in; config_out; ]; 
+         if use_external_fd_wrapper then begin
+                let cmdline = Printf.sprintf "Using commandline: %s\n" 
(String.concat " " (path::args)) in
+                write_to_log cmdline;
+                FEFork(Forkhelpers.safe_close_and_exec 
+                    (Some data_in) (Some data_in) (Some logfd) configs path 
args)
+         end else
+                StdFork(Unsafe.fork_and_exec 
+                     ~pre_exec:(fun _ -> 
+                                                   List.iter 
Unsafe.do_fd_operation fdops;
+                                                   
Unixext.close_all_fds_except !fds_needed) 
+                                      (path::args));
+       (match config_out with Some fd -> Unix.close fd | _ -> ());
+       Unix.close data_in;
        (* Make sure we close config_in eventually *)
-       finally
-        (fun () ->
-
-           let pidmsg = Printf.sprintf "stunnel has pidty: %s\n" 
(string_of_pid t.pid) in
-           write_to_log pidmsg;
-
-           let config = config_file verify_cert extended_diagnosis host port in
-           (* Catch the occasional initialisation failure of stunnel: *)
-           try
-             let n = Unix.write config_in config 0 (String.length config) in
-             if n < String.length config then raise 
Stunnel_initialisation_failed
-           with Unix.Unix_error(err, fn, arg) -> 
-             write_to_log (Printf.sprintf "Caught Unix.Unix_error(%s, %s, %s); 
raising Stunnel_initialisation_failed" (Unix.error_message err) fn arg);
-             raise Stunnel_initialisation_failed)
-        (fun () -> close config_in)) in
-    (* Tidy up any remaining unclosed fds *)
-  List.iter Unix.close !to_close; 
+         finally
+              (fun () ->
+                 let pidmsg = Printf.sprintf "stunnel has pidty: %s" 
(string_of_pid t.pid) in
+                 write_to_log pidmsg;
+            match config_in with
+            | Some fd -> begin
+                     let config = config_file verify_cert extended_diagnosis 
host port in
+                     (* Catch the occasional initialisation failure of 
stunnel: *)
+                     try
+                       let n = Unix.write fd config 0 (String.length config) in
+                       if n < String.length config then raise 
Stunnel_initialisation_failed
+                     with Unix.Unix_error(err, fn, arg) -> 
+                       write_to_log (Printf.sprintf "Caught 
Unix.Unix_error(%s, %s, %s); raising Stunnel_initialisation_failed" 
(Unix.error_message err) fn arg);
+                       raise Stunnel_initialisation_failed
+              end 
+            | _ -> ())
+              (fun () -> match config_in with Some fd -> Unix.close fd | _ -> 
assert false)) in
+  (* Tidy up any remaining unclosed fds *)
   match result with
   | Forkhelpers.Success(log, _) -> 
-      if extended_diagnosis then
-        begin
-          write_to_log "success";
-          t.logfile <- log
-        end
-      else
-        write_to_log ("success: Log from stunnel: [" ^ log ^ "]");
+      if extended_diagnosis then begin
+        write_to_log "stunnel start";
+        t.logfile <- log
+      end else
+        write_to_log ("stunnel start: Log from stunnel: [" ^ log ^ "]");
       t
   | Forkhelpers.Failure(log, exn) ->
-      write_to_log ("failed: Log from stunnel: [" ^ log ^ "]");
+      write_to_log ("stunnel abort: Log from stunnel: [" ^ log ^ "]");
       disconnect t;
       raise exn
 
@@ -274,12 +246,13 @@
                ?(extended_diagnosis=false)
                host
                port = 
-       let connect = if !use_new_stunnel then attempt_one_connect_new else 
attempt_one_connect in
        let _verify_cert = match verify_cert with
                | Some x -> x
-               | None -> Sys.file_exists verify_certificates_ctrl
-       in
-       retry (fun () -> connect ?unique_id ?use_external_fd_wrapper 
?write_to_log _verify_cert extended_diagnosis host port) 5
+               | None -> Sys.file_exists verify_certificates_ctrl in
+  let _ = match write_to_log with 
+    | Some logger -> stunnel_logger := logger
+    | None -> () in
+       retry (fun () -> attempt_one_connect ?unique_id 
?use_external_fd_wrapper ?write_to_log _verify_cert extended_diagnosis host 
port) 5
 
 let sub_after i s =
   let len = String.length s in
@@ -312,14 +285,18 @@
     
 let diagnose_failure st_proc =
   let check_line line =
-    Printf.eprintf "stunnel_failure: %s\n" line;
+    !stunnel_logger line;
     check_verify_error line;
-    check_error "Connection refused" line; 
+    check_error "Connection refused" line;
     check_error "No host resolved" line;
-    check_error "Invalid argument" line;
-  in
-    Unixext.readfile_line check_line st_proc.logfile;
-    raise (Stunnel_error (Unixext.read_whole_file_to_string st_proc.logfile))
+    check_error "Invalid argument" line in
+  Unixext.readfile_line check_line st_proc.logfile
+  (* If we reach here the whole stunnel log should have been gone through
+     (possibly printed/logged somewhere. No necessity to raise an exception,
+     since when this function being called, there is usually some exception
+     already existing in the caller's context, and it's not necessary always a
+     stunnel error.
+  *)
 
 let test host port = 
   let counter = ref 0 in

Attachment: xen-api-lib.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®.