Skip to content

Commit ea80a89

Browse files
authored
Sync master into feature/host-network-device-order (#6674)
2 parents 99fd22d + a1ea40a commit ea80a89

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+948
-983
lines changed

doc/content/xapi/guides/howtos/add-function.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ the Host module:
172172
let price_of ~__context ~host ~item =
173173
info "Host.price_of for item %s" item;
174174
let local_fn = Local.Host.price_of ~host ~item in
175-
do_op_on ~local_fn ~__context ~host
176-
(fun session_id rpc -> Client.Host.price_of ~rpc ~session_id ~host ~item)
175+
let remote_fn = Client.Host.price_of ~host ~item in
176+
do_op_on ~local_fn ~__context ~host ~remote_fn
177177

178178
After the ~__context parameter, the parameters of this new function should
179179
match the parameters we specified for the message. In this case, that is the

ocaml/database/db_cache_impl.ml

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,7 @@ let read_field t tblname fldname objref =
6767
occurs. *)
6868
let ensure_utf8_xml string =
6969
let length = String.length string in
70-
let prefix =
71-
Xapi_stdext_encodings.Encodings.UTF8_XML.longest_valid_prefix string
72-
in
70+
let prefix = Xapi_stdext_encodings.Utf8.XML.longest_valid_prefix string in
7371
if length > String.length prefix then
7472
warn "string truncated to: '%s'." prefix ;
7573
prefix
@@ -86,20 +84,32 @@ let write_field_locked t tblname objref fldname newval =
8684
(get_database t)
8785
)
8886

87+
(** Ensure a value is conforming to UTF-8 with XML restrictions *)
88+
let is_valid v =
89+
let valid = Xapi_stdext_encodings.Utf8.XML.is_valid in
90+
let valid_pair (x, y) = valid x && valid y in
91+
match v with
92+
| Schema.Value.String s ->
93+
valid s
94+
| Schema.Value.Set ss ->
95+
List.for_all valid ss
96+
| Schema.Value.Pairs pairs ->
97+
List.for_all valid_pair pairs
98+
99+
let share_string = function
100+
| Schema.Value.String s ->
101+
Schema.Value.String (Share.merge s)
102+
| v ->
103+
(* we assume strings in the tree have been shared already *)
104+
v
105+
89106
let write_field t tblname objref fldname newval =
90-
let newval =
91-
match newval with
92-
| Schema.Value.String s ->
93-
(* the other caller of write_field_locked only uses sets and maps,
94-
so we only need to check for String here
95-
*)
96-
if not (Xapi_stdext_encodings.Encodings.UTF8_XML.is_valid s) then
97-
raise Invalid_value ;
98-
Schema.Value.String (Share.merge s)
99-
| _ ->
100-
newval
101-
in
102-
with_lock (fun () -> write_field_locked t tblname objref fldname newval)
107+
if not @@ is_valid newval then
108+
raise Invalid_value
109+
else
110+
with_lock (fun () ->
111+
write_field_locked t tblname objref fldname (share_string newval)
112+
)
103113

104114
let touch_row t tblname objref =
105115
update_database t (touch tblname objref) ;

ocaml/database/string_marshall_helper.ml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ module D = Debug.Make (struct let name = __MODULE__ end)
2222

2323
let ensure_utf8_xml string =
2424
let length = String.length string in
25-
let prefix =
26-
Xapi_stdext_encodings.Encodings.UTF8_XML.longest_valid_prefix string
27-
in
25+
let prefix = Xapi_stdext_encodings.Utf8.XML.longest_valid_prefix string in
2826
if length > String.length prefix then
2927
D.warn "Whilst doing 'set' of structured field, string truncated to: '%s'."
3028
prefix ;

ocaml/idl/datamodel_common.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ open Datamodel_roles
1010
to leave a gap for potential hotfixes needing to increment the schema version.*)
1111
let schema_major_vsn = 5
1212

13-
let schema_minor_vsn = 789
13+
let schema_minor_vsn = 790
1414

1515
(* Historical schema versions just in case this is useful later *)
1616
let rio_schema_major_vsn = 5

ocaml/idl/datamodel_errors.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,11 @@ let _ =
648648
"The specified server is disabled and cannot be re-enabled until after \
649649
it has rebooted."
650650
() ;
651+
error Api_errors.host_disabled_indefinitely ["host"]
652+
~doc:
653+
"The specified server is disabled and can only be re-enabled manually \
654+
with Host.enable."
655+
() ;
651656
error Api_errors.no_hosts_available []
652657
~doc:"There were no servers available to complete the specified operation."
653658
() ;

ocaml/idl/datamodel_host.ml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,12 +625,37 @@ let disable =
625625
, "Puts the host into a state in which no new VMs can be started. \
626626
Currently active VMs on the host continue to execute."
627627
)
628+
; ( Changed
629+
, "25.31.0"
630+
, "Added auto_enable option to allow persisting the state across \
631+
toolstack restarts and host reboots."
632+
)
628633
]
629634
~name:"disable"
630635
~doc:
631636
"Puts the host into a state in which no new VMs can be started. \
632637
Currently active VMs on the host continue to execute."
633-
~params:[(Ref _host, "host", "The Host to disable")]
638+
~versioned_params:
639+
[
640+
{
641+
param_type= Ref _host
642+
; param_name= "host"
643+
; param_doc= "The Host to disable"
644+
; param_release= rio_release
645+
; param_default= None
646+
}
647+
; {
648+
param_type= Bool
649+
; param_name= "auto_enable"
650+
; param_doc=
651+
"If true (default), the host will be re-enabled after a toolstack \
652+
restart automatically. If false, the host will be disabled \
653+
indefinitely, across toolstack restarts and host reboots, until \
654+
re-enabled explicitly with Host.enable."
655+
; param_release= numbered_release "25.31.0"
656+
; param_default= Some (VBool true)
657+
}
658+
]
634659
~allowed_roles:(_R_POOL_OP ++ _R_CLIENT_CERT)
635660
()
636661

ocaml/idl/ocaml_backend/gen_server.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ let gen_module api : O.Module.t =
457457
([
458458
"let __call, __params = call.Rpc.name, call.Rpc.params in"
459459
; "List.iter (fun p -> let s = Rpc.to_string p in if not \
460-
(Xapi_stdext_encodings.Encodings.UTF8_XML.is_valid s) then"
460+
(Xapi_stdext_encodings.Utf8.is_valid s) then"
461461
; "raise (Api_errors.Server_error(Api_errors.invalid_value, \
462462
[\"Invalid UTF-8 string in parameter\"; s]))) __params;"
463463
; "let __label = __call in"

ocaml/libs/tracing/tracing.ml

Lines changed: 93 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ module TraceContext = struct
222222

223223
let empty = {traceparent= None; baggage= None}
224224

225+
let depth_key = "span.depth"
226+
225227
let with_traceparent traceparent ctx = {ctx with traceparent}
226228

227229
let with_baggage baggage ctx = {ctx with baggage}
@@ -230,6 +232,20 @@ module TraceContext = struct
230232

231233
let baggage_of ctx = ctx.baggage
232234

235+
let baggage_depth_of ctx =
236+
Option.bind (baggage_of ctx) (List.assoc_opt depth_key)
237+
|> Option.value ~default:"1"
238+
|> int_of_string
239+
240+
let update_with_baggage k v ctx =
241+
let new_baggage =
242+
baggage_of ctx
243+
|> Option.value ~default:[]
244+
|> List.remove_assoc k
245+
|> List.cons (k, v)
246+
in
247+
with_baggage (Some new_baggage) ctx
248+
233249
let parse input =
234250
let open Astring.String in
235251
let trim_pair (key, value) = (trim key, trim value) in
@@ -322,22 +338,36 @@ module Span = struct
322338

323339
let start ?(attributes = Attributes.empty)
324340
?(trace_context : TraceContext.t option) ~name ~parent ~span_kind () =
325-
let trace_id, extra_context =
341+
let trace_id, extra_context, depth =
326342
match parent with
327343
| None ->
328-
(Trace_id.make (), TraceContext.empty)
344+
(Trace_id.make (), TraceContext.empty, 1)
329345
| Some span_parent ->
330-
(span_parent.context.trace_id, span_parent.context.trace_context)
346+
( span_parent.context.trace_id
347+
, span_parent.context.trace_context
348+
, TraceContext.baggage_depth_of span_parent.context.trace_context + 1
349+
)
331350
in
332351
let span_id = Span_id.make () in
352+
let extra_context_with_depth =
353+
TraceContext.(
354+
update_with_baggage depth_key (string_of_int depth) extra_context
355+
)
356+
in
333357
let context : SpanContext.t =
334-
{trace_id; span_id; trace_context= extra_context}
358+
{trace_id; span_id; trace_context= extra_context_with_depth}
335359
in
336360
let context =
337-
(* If trace_context is provided to the call, override any inherited trace context. *)
338-
trace_context
339-
|> Option.fold ~none:context
340-
~some:(Fun.flip SpanContext.with_trace_context context)
361+
(* If trace_context is provided to the call, override any inherited trace
362+
context except span.depth which should still be maintained. *)
363+
match trace_context with
364+
| Some tc ->
365+
let tc_with_depth =
366+
TraceContext.(update_with_baggage depth_key (string_of_int depth) tc)
367+
in
368+
SpanContext.with_trace_context tc_with_depth context
369+
| None ->
370+
context
341371
in
342372
(* Using gettimeofday over Mtime as it is better for sharing timestamps between the systems *)
343373
let begin_time = Unix.gettimeofday () in
@@ -473,6 +503,11 @@ module Spans = struct
473503

474504
let set_max_traces x = Atomic.set max_traces x
475505

506+
(* Default is much larger than the largest current traces, so effectively off *)
507+
let max_depth = Atomic.make 100
508+
509+
let set_max_depth x = Atomic.set max_depth x
510+
476511
let finished_spans = Atomic.make ([], 0)
477512

478513
let span_hashtbl_is_empty () = TraceMap.is_empty (Atomic.get spans)
@@ -713,12 +748,18 @@ module Tracer = struct
713748
let get_tracer ~name:_ = TracerProvider.get_current ()
714749

715750
let span_of_span_context context name : Span.t =
751+
let tc = SpanContext.context_of_span_context context in
752+
let new_depth = TraceContext.baggage_depth_of tc in
753+
let new_tc =
754+
TraceContext.(update_with_baggage depth_key (string_of_int new_depth) tc)
755+
in
756+
let context = SpanContext.with_trace_context new_tc context in
716757
{
717758
context
718759
; status= {status_code= Status.Unset; _description= None}
719760
; name
720761
; parent= None
721-
; span_kind= SpanKind.Client (* This will be the span of the client call*)
762+
; span_kind= SpanKind.Client (* This will be the span of the client call *)
722763
; begin_time= Unix.gettimeofday ()
723764
; end_time= None
724765
; links= []
@@ -730,10 +771,32 @@ module Tracer = struct
730771
?(span_kind = SpanKind.Internal) ~name ~parent () :
731772
(Span.t option, exn) result =
732773
let open TracerProvider in
733-
(* Do not start span if the TracerProvider is disabled*)
774+
let parent_depth =
775+
Option.fold ~none:1
776+
~some:(fun parent ->
777+
parent.Span.context
778+
|> SpanContext.context_of_span_context
779+
|> TraceContext.baggage_depth_of
780+
)
781+
parent
782+
in
783+
(* Do not start span if the TracerProvider is disabled *)
734784
if not t.enabled then
785+
ok_none (* Do not start span if the max depth has been reached *)
786+
else if parent_depth >= Atomic.get Spans.max_depth then (
787+
let parent_trace_id =
788+
Option.fold ~none:"None"
789+
~some:(fun p ->
790+
p.Span.context
791+
|> SpanContext.span_id_of_span_context
792+
|> Span_id.to_string
793+
)
794+
parent
795+
in
796+
debug "Max_span_depth limit reached, not creating span %s (parent %s)"
797+
name parent_trace_id ;
735798
ok_none
736-
else
799+
) else
737800
let attributes = Attributes.merge_into t.attributes attributes in
738801
let span =
739802
Span.start ~attributes ?trace_context ~name ~parent ~span_kind ()
@@ -750,16 +813,24 @@ module Tracer = struct
750813
|> Spans.remove_from_spans
751814
|> Option.map (fun existing_span ->
752815
let old_context = Span.get_context existing_span in
816+
let parent_trace_context = Span.get_trace_context parent in
817+
let new_depth =
818+
TraceContext.baggage_depth_of parent_trace_context + 1
819+
in
753820
let new_context : SpanContext.t =
754-
let trace_context = span.Span.context.trace_context in
821+
let trace_context =
822+
TraceContext.(
823+
update_with_baggage depth_key (string_of_int new_depth)
824+
span.Span.context.trace_context
825+
)
826+
in
755827
SpanContext.context
756828
(SpanContext.trace_id_of_span_context parent.context)
757829
old_context.span_id
758830
|> SpanContext.with_trace_context trace_context
759831
in
760832
let updated_span = {existing_span with parent= Some parent} in
761833
let updated_span = {updated_span with context= new_context} in
762-
763834
let () = Spans.add_to_spans ~span:updated_span in
764835
updated_span
765836
)
@@ -926,7 +997,15 @@ module Propagator = struct
926997
let trace_context' =
927998
TraceContext.with_traceparent (Some traceparent) trace_context
928999
in
929-
let carrier' = P.inject_into trace_context' carrier in
1000+
let new_depth =
1001+
TraceContext.baggage_depth_of trace_context' + 1 |> string_of_int
1002+
in
1003+
let trace_context'' =
1004+
TraceContext.(
1005+
update_with_baggage depth_key new_depth trace_context'
1006+
)
1007+
in
1008+
let carrier' = P.inject_into trace_context'' carrier in
9301009
f carrier'
9311010
| _ ->
9321011
f carrier

ocaml/libs/tracing/tracing.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ module Spans : sig
165165

166166
val set_max_traces : int -> unit
167167

168+
val set_max_depth : int -> unit
169+
168170
val span_count : unit -> int
169171

170172
val since : unit -> Span.t list * int

ocaml/libs/tracing/tracing_export.ml

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ let export_interval = ref 30.
2424

2525
let set_export_interval t = export_interval := t
2626

27+
let export_chunk_size = Atomic.make 10000
28+
29+
let set_export_chunk_size x = Atomic.set export_chunk_size x
30+
2731
let host_id = ref "localhost"
2832

2933
let set_host_id id = host_id := id
@@ -289,17 +293,40 @@ module Destination = struct
289293
with exn ->
290294
debug "Tracing: unable to export span : %s" (Printexc.to_string exn)
291295

296+
let rec span_info_chunks span_info batch_size =
297+
let rec list_to_chunks_inner l n curr chunks =
298+
if n = 0 then
299+
if l <> [] then
300+
list_to_chunks_inner l batch_size [] ((curr, batch_size) :: chunks)
301+
else
302+
(curr, batch_size) :: chunks
303+
else
304+
match l with
305+
| [] ->
306+
(curr, List.length curr) :: chunks
307+
| h :: t ->
308+
list_to_chunks_inner t (n - 1) (h :: curr) chunks
309+
in
310+
list_to_chunks_inner (fst span_info) batch_size [] []
311+
292312
let flush_spans () =
293313
let ((_span_list, span_count) as span_info) = Spans.since () in
294314
let attributes = [("export.traces.count", string_of_int span_count)] in
295315
let@ parent =
296316
with_tracing ~span_kind:Server ~trace_context:TraceContext.empty
297317
~parent:None ~attributes ~name:"Tracing.flush_spans"
298318
in
299-
TracerProvider.get_tracer_providers ()
300-
|> List.filter TracerProvider.get_enabled
301-
|> List.concat_map TracerProvider.get_endpoints
302-
|> List.iter (export_to_endpoint parent span_info)
319+
let endpoints =
320+
TracerProvider.get_tracer_providers ()
321+
|> List.filter TracerProvider.get_enabled
322+
|> List.concat_map TracerProvider.get_endpoints
323+
in
324+
let span_info_chunks =
325+
span_info_chunks span_info (Atomic.get export_chunk_size)
326+
in
327+
List.iter
328+
(fun s_i -> List.iter (export_to_endpoint parent s_i) endpoints)
329+
span_info_chunks
303330

304331
let delay = Delay.make ()
305332

0 commit comments

Comments
 (0)