Skip to content

Commit 8e7ab20

Browse files
committed
CA-409431: Use an Observer forwarder for xapi-storage-script
Currently, xapi-storage-script uses the presence/absence of a smapi observer config file to determine whether it should create traces. This only happens on startup which means smapiv3 traces will often not be created when they should be. This commit updates the Smapi Observer forwarder to use an RPC client to send messages to xapi-storage-script, updating it on any relevant changes to the Observer.
1 parent 13042fd commit 8e7ab20

File tree

6 files changed

+212
-17
lines changed

6 files changed

+212
-17
lines changed

ocaml/xapi-idl/lib/dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
(wrapped false)
4141
(preprocess
4242
(per_module
43-
((pps ppx_deriving_rpc) Xcp_channel Xcp_channel_protocol TypeCombinators Observer_helpers)
43+
((pps ppx_deriving_rpc) Xcp_channel Xcp_channel_protocol TypeCombinators Observer_helpers Observer_skeleton)
4444
((pps ppx_sexp_conv ppx_deriving_rpc) Xcp_pci))))
4545

4646
(library

ocaml/xapi-idl/lib/observer_helpers.ml

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ module D = Debug.Make (struct let name = "observer_interface" end)
1919

2020
open D
2121

22+
let service_name = "observer"
23+
24+
let queue_name = Xcp_service.common_prefix ^ service_name
25+
26+
let default_sockets_dir = "/var/lib/xcp"
27+
28+
let default_path = Filename.concat default_sockets_dir service_name
29+
30+
let uri () = "file:" ^ default_path
31+
2232
module Errors = struct
2333
type error =
2434
| Internal_error of string
@@ -148,3 +158,107 @@ module ObserverAPI (R : RPC) = struct
148158
declare "Observer.set_compress_tracing_files" []
149159
(dbg_p @-> bool_p @-> returning unit_p err)
150160
end
161+
162+
module type Server_impl = sig
163+
type context = unit
164+
165+
val create :
166+
context
167+
-> dbg:debug_info
168+
-> uuid:string
169+
-> name_label:string
170+
-> attributes:(string * string) list
171+
-> endpoints:string list
172+
-> enabled:bool
173+
-> unit
174+
175+
val destroy : context -> dbg:debug_info -> uuid:string -> unit
176+
177+
val set_enabled :
178+
context -> dbg:debug_info -> uuid:string -> enabled:bool -> unit
179+
180+
val set_attributes :
181+
context
182+
-> dbg:debug_info
183+
-> uuid:string
184+
-> attributes:(string * string) list
185+
-> unit
186+
187+
val set_endpoints :
188+
context -> dbg:debug_info -> uuid:string -> endpoints:string list -> unit
189+
190+
val init : context -> dbg:debug_info -> unit
191+
192+
val set_trace_log_dir : context -> dbg:debug_info -> dir:string -> unit
193+
194+
val set_export_interval : context -> dbg:debug_info -> interval:float -> unit
195+
196+
val set_max_spans : context -> dbg:debug_info -> spans:int -> unit
197+
198+
val set_max_traces : context -> dbg:debug_info -> traces:int -> unit
199+
200+
val set_max_file_size : context -> dbg:debug_info -> file_size:int -> unit
201+
202+
val set_host_id : context -> dbg:debug_info -> host_id:string -> unit
203+
204+
val set_compress_tracing_files :
205+
context -> dbg:debug_info -> enabled:bool -> unit
206+
end
207+
208+
module Server (Impl : Server_impl) () = struct
209+
module S = ObserverAPI (Idl.Exn.GenServer ())
210+
211+
let _ =
212+
S.create (fun dbg uuid name_label attributes endpoints enabled ->
213+
Impl.create () ~dbg ~uuid ~name_label ~attributes ~endpoints ~enabled
214+
) ;
215+
S.destroy (fun dbg uuid -> Impl.destroy () ~dbg ~uuid) ;
216+
S.set_enabled (fun dbg uuid enabled ->
217+
Impl.set_enabled () ~dbg ~uuid ~enabled
218+
) ;
219+
S.set_attributes (fun dbg uuid attributes ->
220+
Impl.set_attributes () ~dbg ~uuid ~attributes
221+
) ;
222+
S.set_endpoints (fun dbg uuid endpoints ->
223+
Impl.set_endpoints () ~dbg ~uuid ~endpoints
224+
) ;
225+
S.init (fun dbg -> Impl.init () ~dbg) ;
226+
S.set_trace_log_dir (fun dbg dir -> Impl.set_trace_log_dir () ~dbg ~dir) ;
227+
S.set_export_interval (fun dbg interval ->
228+
Impl.set_export_interval () ~dbg ~interval
229+
) ;
230+
S.set_max_spans (fun dbg spans -> Impl.set_max_spans () ~dbg ~spans) ;
231+
S.set_max_traces (fun dbg traces -> Impl.set_max_traces () ~dbg ~traces) ;
232+
S.set_max_file_size (fun dbg file_size ->
233+
Impl.set_max_file_size () ~dbg ~file_size
234+
) ;
235+
S.set_host_id (fun dbg host_id -> Impl.set_host_id () ~dbg ~host_id) ;
236+
S.set_compress_tracing_files (fun dbg enabled ->
237+
Impl.set_compress_tracing_files () ~dbg ~enabled
238+
)
239+
240+
(* Bind all *)
241+
let process call = Idl.Exn.server S.implementation call
242+
end
243+
244+
let rec retry_econnrefused f =
245+
try f () with
246+
| Unix.Unix_error (Unix.ECONNREFUSED, "connect", _) ->
247+
(* debug "Caught ECONNREFUSED; retrying in 5s"; *)
248+
Thread.delay 5. ; retry_econnrefused f
249+
| e ->
250+
(* error "Caught %s: does the observer service need restarting?"
251+
(Printexc.to_string e); *)
252+
raise e
253+
254+
module Client = ObserverAPI (Idl.Exn.GenClient (struct
255+
open Xcp_client
256+
257+
let rpc call =
258+
retry_econnrefused (fun () ->
259+
if !use_switch then
260+
json_switch_rpc queue_name call
261+
else
262+
xml_http_rpc ~srcstr:(get_user_agent ()) ~dststr:queue_name uri call
263+
)
264+
end))
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
(*
2+
* Copyright (c) Cloud Software Group
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU Lesser General Public License as published
6+
* by the Free Software Foundation; version 2.1 only. with the special
7+
* exception on linking described in file LICENSE.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU Lesser General Public License for more details.
13+
*)
14+
[@@@ocaml.warning "-27"]
15+
16+
let u x = raise Observer_helpers.(Observer_error (Errors.Unimplemented x))
17+
18+
module Observer = struct
19+
type context = unit
20+
21+
let create ctx ~dbg ~uuid ~name_label ~attributes ~endpoints ~enabled =
22+
u "Observer.create"
23+
24+
let destroy ctx ~dbg ~uuid = u "Observer.destroy"
25+
26+
let set_enabled ctx ~dbg ~uuid ~enabled = u "Observer.set_enabled"
27+
28+
let set_attributes ctx ~dbg ~uuid ~attributes = u "Observer.set_attributes"
29+
30+
let set_endpoints ctx ~dbg ~uuid ~endpoints = u "Observer.set_endpoints"
31+
32+
let init ctx ~dbg = u "Observer.init"
33+
34+
let set_trace_log_dir ctx ~dbg ~dir = u "Observer.set_trace_log_dir"
35+
36+
let set_export_interval ctx ~dbg ~interval = u "Observer.set_export_interval"
37+
38+
let set_max_spans ctx ~dbg ~spans = u "Observer.set_max_spans"
39+
40+
let set_max_traces ctx ~dbg ~traces = u "Observer.set_max_traces"
41+
42+
let set_max_file_size ctx ~dbg ~file_size = u "Observer.set_max_file_size"
43+
44+
let set_host_id ctx ~dbg ~host_id = u "Observer.set_host_id"
45+
46+
let set_compress_tracing_files ctx ~dbg ~enabled =
47+
u "Observer.set_compress_tracing_files"
48+
end

ocaml/xapi-storage-script/dune

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
sexplib
4242
sexplib0
4343
uri
44+
threads.posix
4445
xapi-backtrace
4546
xapi-consts
4647
xapi-consts.xapi_version

ocaml/xapi-storage-script/main.ml

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -411,19 +411,6 @@ let observer_config_dir =
411411
in
412412
dir // component // "enabled"
413413

414-
(** Determine if SM API observation is enabled from the
415-
filesystem. Ordinarily, determining if a component is enabled
416-
would consist of querying the 'components' field of an observer
417-
from the xapi database. *)
418-
let observer_is_component_enabled () =
419-
let is_enabled () =
420-
let is_config_file path = Filename.check_suffix path ".observer.conf" in
421-
let* files = Sys.readdir observer_config_dir in
422-
Lwt.return (List.exists is_config_file files)
423-
in
424-
let* result = Deferred.try_with is_enabled in
425-
Lwt.return (Option.value (Result.to_option result) ~default:false)
426-
427414
(** Call the script named after the RPC method in the [script_dir]
428415
directory. The arguments (not the whole JSON-RPC call) are passed as JSON
429416
to its stdin, and stdout is returned. In case of a non-zero exit code,
@@ -2247,6 +2234,19 @@ let register_exn_pretty_printers () =
22472234
assert false
22482235
)
22492236

2237+
module XapiStorageScript : Observer_helpers.Server_impl = struct
2238+
include Observer_skeleton.Observer
2239+
2240+
let create _context ~dbg:_ ~uuid:_ ~name_label:_ ~attributes:_ ~endpoints:_
2241+
~enabled =
2242+
config.use_observer <- enabled
2243+
2244+
let destroy _context ~dbg:_ ~uuid:_ = config.use_observer <- false
2245+
2246+
let set_enabled _context ~dbg:_ ~uuid:_ ~enabled =
2247+
config.use_observer <- enabled
2248+
end
2249+
22502250
let () =
22512251
register_exn_pretty_printers () ;
22522252
let root_dir = ref "/var/lib/xapi/storage-scripts" in
@@ -2293,9 +2293,17 @@ let () =
22932293

22942294
Logs.set_reporter (lwt_reporter ()) ;
22952295
Logs.set_level ~all:true (Some Logs.Info) ;
2296+
2297+
let module S = Observer_helpers.Server (XapiStorageScript) () in
2298+
let s =
2299+
Xcp_service.make ~path:Observer_helpers.default_path
2300+
~queue_name:Observer_helpers.queue_name ~rpc_fn:S.process ()
2301+
in
2302+
let (_ : Thread.t) =
2303+
Thread.create (fun () -> Xcp_service.serve_forever s) ()
2304+
in
2305+
22962306
let main =
2297-
let* observer_enabled = observer_is_component_enabled () in
2298-
config.use_observer <- observer_enabled ;
22992307
if !self_test_only then
23002308
self_test ~root_dir:!root_dir
23012309
else

ocaml/xapi/xapi_observer.ml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,30 @@ end
383383

384384
module SMObserverConfig = Dom0ObserverConfig (struct let component = SMApi end)
385385

386+
module SMObserver = struct
387+
include SMObserverConfig
388+
open Observer_helpers
389+
390+
let create ~__context ~uuid ~name_label ~attributes ~endpoints ~enabled =
391+
debug "SMObserver Observer.create %s" uuid ;
392+
SMObserverConfig.create ~__context ~uuid ~name_label ~attributes ~endpoints
393+
~enabled ;
394+
let dbg = Context.string_of_task __context in
395+
Client.create dbg uuid name_label attributes endpoints enabled
396+
397+
let destroy ~__context ~uuid =
398+
debug "SMObserver Observer.destroy %s" uuid ;
399+
SMObserverConfig.destroy ~__context ~uuid ;
400+
let dbg = Context.string_of_task __context in
401+
Client.destroy dbg uuid
402+
403+
let set_enabled ~__context ~uuid ~enabled =
404+
debug "SMObserver Observer.set_enabled %s" uuid ;
405+
SMObserverConfig.set_enabled ~__context ~uuid ~enabled ;
406+
let dbg = Context.string_of_task __context in
407+
Client.set_enabled dbg uuid enabled
408+
end
409+
386410
let get_forwarder c =
387411
let module Forwarder =
388412
( val match c with
@@ -393,7 +417,7 @@ let get_forwarder c =
393417
| Xapi_clusterd ->
394418
(module Xapi_cluster.Observer)
395419
| SMApi ->
396-
(module SMObserverConfig)
420+
(module SMObserver)
397421
: ObserverInterface
398422
)
399423
in

0 commit comments

Comments
 (0)