Skip to content

Commit 55b97bf

Browse files
author
David Scott
committed
Log all script execution, including arguments and results
Note the log functions nolonger return Deferred.ts. In the case of syslog the logging is actually synchronous (not ideal) whereas in the stdout case it's lazily-flushed. Signed-off-by: David Scott <dave.scott@eu.citrix.com>
1 parent 21dedb9 commit 55b97bf

File tree

1 file changed

+30
-22
lines changed

1 file changed

+30
-22
lines changed

main.ml

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,23 @@ open Types
2222

2323
let use_syslog = ref false
2424

25-
let info fmt =
25+
let log level fmt =
2626
Printf.ksprintf (fun s ->
2727
if !use_syslog then begin
2828
(* FIXME: this is synchronous and will block other I/O *)
29-
Core.Syslog.syslog ~level:Core.Syslog.Level.INFO ~facility:Core.Syslog.Facility.DAEMON s;
30-
return ()
29+
Core.Syslog.syslog ~level ~facility:Core.Syslog.Facility.DAEMON s;
3130
end else begin
3231
let w = Lazy.force Writer.stderr in
3332
Writer.write w s;
34-
Writer.newline w;
35-
Writer.flushed w;
33+
Writer.newline w
3634
end
3735
) fmt
3836

37+
let debug fmt = log Core.Syslog.Level.DEBUG fmt
38+
let info fmt = log Core.Syslog.Level.INFO fmt
39+
let warn fmt = log Core.Syslog.Level.WARNING fmt
40+
let error fmt = log Core.Syslog.Level.ERR fmt
41+
3942
let _nonpersistent = "NONPERSISTENT"
4043
let _clone_on_boot_key = "clone-on-boot"
4144

@@ -56,21 +59,25 @@ let missing_uri () =
5659
let (>>>=) = Deferred.Result.(>>=)
5760

5861
let fork_exec_rpc root_dir script_name args response_of_rpc =
62+
info "%s/%s %s" root_dir script_name (Jsonrpc.to_string args);
5963
( Sys.is_file ~follow_symlinks:true script_name
6064
>>= function
6165
| `No | `Unknown ->
66+
error "%s/%s is not a file" root_dir script_name;
6267
return (Error(backend_error "SCRIPT_MISSING" [ script_name; "Check whether the file exists and has correct permissions" ]))
6368
| `Yes -> return (Ok ())
6469
) >>>= fun () ->
6570
( Unix.access script_name [ `Exec ]
6671
>>= function
6772
| Error exn ->
73+
error "%s/%s is not executable" root_dir script_name;
6874
return (Error (backend_error "SCRIPT_NOT_EXECUTABLE" [ script_name; Exn.to_string exn ]))
6975
| Ok () -> return (Ok ())
7076
) >>>= fun () ->
7177
Process.create ~prog:script_name ~args:["--json"] ~working_dir:root_dir ()
7278
>>= function
7379
| Error e ->
80+
error "%s/%s failed: %s" root_dir script_name (Error.to_string_hum e);
7481
return (Error(backend_error "SCRIPT_FAILED" [ script_name; Error.to_string_hum e ]))
7582
| Ok p ->
7683
(* Send the request as json on stdin *)
@@ -85,26 +92,34 @@ let fork_exec_rpc root_dir script_name args response_of_rpc =
8592
(* Expect an exception and backtrace on stderr *)
8693
begin match Or_error.try_with (fun () -> Jsonrpc.of_string output.Process.Output.stderr) with
8794
| Error _ ->
95+
error "%s/%s failed and printed bad error json: %s" root_dir script_name output.Process.Output.stderr;
8896
return (Error (backend_error "SCRIPT_FAILED" [ script_name; "non-zero exit and bad json on stderr"; string_of_int code; output.Process.Output.stdout; output.Process.Output.stderr ]))
8997
| Ok response ->
9098
begin match Or_error.try_with (fun () -> error_of_rpc response) with
91-
| Error _ -> return (Error (backend_error "SCRIPT_FAILED" [ script_name; "non-zero exit and bad json on stderr"; string_of_int code; output.Process.Output.stdout; output.Process.Output.stderr ]))
99+
| Error _ ->
100+
error "%s/%s failed and printed bad error json: %s" root_dir script_name output.Process.Output.stderr;
101+
return (Error (backend_error "SCRIPT_FAILED" [ script_name; "non-zero exit and bad json on stderr"; string_of_int code; output.Process.Output.stdout; output.Process.Output.stderr ]))
92102
| Ok x -> return (Error(backend_backtrace_error "SCRIPT_FAILED" [ script_name; "non-zero exit"; string_of_int code; output.Process.Output.stdout ] x))
93103
end
94104
end
95105
| Error (`Signal signal) ->
106+
error "%s/%s caught a signal and failed" root_dir script_name;
96107
return (Error (backend_error "SCRIPT_FAILED" [ script_name; "signalled"; Signal.to_string signal; output.Process.Output.stdout; output.Process.Output.stderr ]))
97108
| Ok () ->
98109

99110
(* Parse the json on stdout *)
100111
begin match Or_error.try_with (fun () -> Jsonrpc.of_string output.Process.Output.stdout) with
101112
| Error _ ->
113+
error "%s/%s succeeded but printed bad json: %s" root_dir script_name output.Process.Output.stdout;
102114
return (Error (backend_error "SCRIPT_FAILED" [ script_name; "bad json on stdout"; output.Process.Output.stdout ]))
103115
| Ok response ->
104116
begin match Or_error.try_with (fun () -> response_of_rpc response) with
105117
| Error _ ->
118+
error "%s/%s succeeded but printed bad json: %s" root_dir script_name output.Process.Output.stdout;
106119
return (Error (backend_error "SCRIPT_FAILED" [ script_name; "json did not match schema"; output.Process.Output.stdout ]))
107-
| Ok x -> return (Ok x)
120+
| Ok x ->
121+
info "%s/%s succeeded: %s" root_dir script_name output.Process.Output.stdout;
122+
return (Ok x)
108123
end
109124
end
110125
end
@@ -162,13 +177,11 @@ module Datapath_plugins = struct
162177
fork_exec_rpc root_dir (script root_dir name (`Datapath name) "Plugin.Query") args Storage.Plugin.Types.Plugin.Query.Out.t_of_rpc
163178
>>= function
164179
| Ok response ->
165-
info "Registered datapath plugin %s" name
166-
>>= fun () ->
180+
info "Registered datapath plugin %s" name;
167181
Hashtbl.replace !table name response;
168182
return ()
169183
| _ ->
170-
info "Failed to register datapath plugin %s" name
171-
>>= fun () ->
184+
info "Failed to register datapath plugin %s" name;
172185
return ()
173186

174187
let unregister root_dir name =
@@ -728,8 +741,7 @@ let process root_dir name x =
728741
Deferred.return (Error (backend_error "UNIMPLEMENTED" [ name ])))
729742
>>= function
730743
| Result.Error error ->
731-
info "returning error %s" (Jsonrpc.string_of_response (R.failure error))
732-
>>= fun () ->
744+
info "returning error %s" (Jsonrpc.string_of_response (R.failure error));
733745
return (Jsonrpc.string_of_response (R.failure error))
734746
| Result.Ok rpc ->
735747
return (Jsonrpc.string_of_response rpc)
@@ -759,17 +771,15 @@ let watch_volume_plugins ~root_dir ~switch_path =
759771
if Hashtbl.mem servers name
760772
then return ()
761773
else begin
762-
info "Adding %s" name
763-
>>= fun () ->
774+
info "Adding %s" name;
764775
Protocol_async.Server.listen ~process:(process root_dir name) ~switch:switch_path ~queue:(Filename.basename name) ()
765776
>>= fun result ->
766777
let server = get_ok result in
767778
Hashtbl.add_exn servers name server;
768779
return ()
769780
end in
770781
let destroy switch_path name =
771-
info "Removing %s" name
772-
>>= fun () ->
782+
info "Removing %s" name;
773783
if Hashtbl.mem servers name then begin
774784
let t = Hashtbl.find_exn servers name in
775785
Protocol_async.Server.shutdown ~t () >>= fun () ->
@@ -793,8 +803,7 @@ let watch_volume_plugins ~root_dir ~switch_path =
793803
let rec loop () =
794804
( Pipe.read pipe >>= function
795805
| `Eof ->
796-
info "Received EOF from inotify event pipe"
797-
>>= fun () ->
806+
info "Received EOF from inotify event pipe";
798807
Shutdown.exit 1
799808
| `Ok (Created path)
800809
| `Ok (Moved (Into path)) ->
@@ -833,8 +842,7 @@ let watch_datapath_plugins ~root_dir =
833842
let rec loop () =
834843
( Pipe.read pipe >>= function
835844
| `Eof ->
836-
info "Received EOF from inotify event pipe"
837-
>>= fun () ->
845+
info "Received EOF from inotify event pipe";
838846
Shutdown.exit 1
839847
| `Ok (Created path)
840848
| `Ok (Moved (Into path)) ->
@@ -907,7 +915,7 @@ let _ =
907915
if !Xcp_service.daemon then begin
908916
Xcp_service.maybe_daemonize ();
909917
use_syslog := true;
910-
Deferred.don't_wait_for (info "Daemonisation successful.");
918+
info "Daemonisation successful.";
911919
end;
912920
main ~root_dir:!root_dir ~state_path:!state_path ~switch_path:!Xcp_client.switch_path
913921

0 commit comments

Comments
 (0)