Skip to content

Commit 54abab8

Browse files
authored
Merge pull request #5855 from psafont/rrd-unpack
2 parents 9e33053 + 3658806 commit 54abab8

File tree

4 files changed

+79
-62
lines changed

4 files changed

+79
-62
lines changed

ocaml/libs/http-lib/http.ml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ let http_501_method_not_implemented ?(version = "1.0") () =
9494
; "Cache-Control: no-cache, no-store"
9595
]
9696

97+
let http_503_service_unavailable ?(version = "1.0") () =
98+
[
99+
Printf.sprintf "HTTP/%s 503 Service Unavailable" version
100+
; "Connection: close"
101+
; "Cache-Control: no-cache, no-store"
102+
]
103+
97104
module Hdr = struct
98105
let task_id = "task-id"
99106

ocaml/libs/http-lib/http.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ val http_500_internal_server_error : ?version:string -> unit -> string list
189189

190190
val http_501_method_not_implemented : ?version:string -> unit -> string list
191191

192+
val http_503_service_unavailable : ?version:string -> unit -> string list
193+
192194
module Hdr : sig
193195
val task_id : string
194196
(** Header used for task id *)

ocaml/libs/http-lib/http_svr.ml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ open D
4141

4242
module E = Debug.Make (struct let name = "http_internal_errors" end)
4343

44+
let ( let* ) = Option.bind
45+
4446
type uri_path = string
4547

4648
module Stats = struct
@@ -296,22 +298,17 @@ module Server = struct
296298

297299
let add_handler x ty uri handler =
298300
let existing =
299-
if MethodMap.mem ty x.handlers then
300-
MethodMap.find ty x.handlers
301-
else
302-
Radix_tree.empty
301+
Option.value (MethodMap.find_opt ty x.handlers) ~default:Radix_tree.empty
303302
in
304303
x.handlers <-
305304
MethodMap.add ty
306305
(Radix_tree.insert uri {(TE.empty ()) with TE.handler} existing)
307306
x.handlers
308307

309308
let find_stats x m uri =
310-
if not (MethodMap.mem m x.handlers) then
311-
None
312-
else
313-
let rt = MethodMap.find m x.handlers in
314-
Option.map (fun te -> te.TE.stats) (Radix_tree.longest_prefix uri rt)
309+
let* rt = MethodMap.find_opt m x.handlers in
310+
let* te = Radix_tree.longest_prefix uri rt in
311+
Some te.TE.stats
315312

316313
let all_stats x =
317314
let open Radix_tree in

ocaml/xapi/rrdd_proxy.ml

Lines changed: 64 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -51,61 +51,72 @@ let get_vm_rrd_forwarder (req : Http.Request.t) (s : Unix.file_descr) _ =
5151
debug "put_rrd_forwarder: start" ;
5252
let query = req.Http.Request.query in
5353
req.Http.Request.close <- true ;
54-
let vm_uuid = List.assoc "uuid" query in
55-
if (not (List.mem_assoc "ref" query)) && not (List.mem_assoc "uuid" query)
56-
then
57-
fail_req_with s "get_vm_rrd: missing the 'uuid' parameter"
58-
Http.http_400_badrequest
59-
else if Rrdd.has_vm_rrd vm_uuid then
60-
ignore
61-
(Xapi_services.hand_over_connection req s !Rrd_interface.forwarded_path)
62-
else
63-
Xapi_http.with_context ~dummy:true "Get VM RRD." req s (fun __context ->
64-
let open Http.Request in
65-
(* List of possible actions. *)
66-
let read_at_owner owner =
67-
let address = Db.Host.get_address ~__context ~self:owner in
68-
let url = make_url ~address ~req in
69-
Http_svr.headers s (Http.http_302_redirect url)
70-
in
71-
let unarchive_at_master () =
72-
let address = Pool_role.get_master_address () in
73-
let query = (Constants.rrd_unarchive, "") :: query in
74-
let url = make_url_from_query ~address ~uri:req.uri ~query in
75-
Http_svr.headers s (Http.http_302_redirect url)
76-
in
77-
let unarchive () =
78-
let req = {req with uri= Constants.rrd_unarchive_uri} in
79-
ignore
80-
(Xapi_services.hand_over_connection req s
81-
!Rrd_interface.forwarded_path
82-
)
83-
in
84-
(* List of conditions involved. *)
85-
let is_unarchive_request =
86-
List.mem_assoc Constants.rrd_unarchive query
54+
match List.assoc_opt "uuid" query with
55+
| None ->
56+
fail_req_with s "get_vm_rrd: missing the 'uuid' parameter"
57+
Http.http_400_badrequest
58+
| Some vm_uuid when Rrdd.has_vm_rrd vm_uuid ->
59+
ignore
60+
(Xapi_services.hand_over_connection req s !Rrd_interface.forwarded_path)
61+
| Some vm_uuid -> (
62+
Xapi_http.with_context ~dummy:true "Get VM RRD." req s @@ fun __context ->
63+
(* List of possible actions. *)
64+
let read_at address =
65+
let url = make_url ~address ~req in
66+
Http_svr.headers s (Http.http_302_redirect url)
67+
in
68+
let unarchive_at address =
69+
let query = (Constants.rrd_unarchive, "") :: query in
70+
let url = make_url_from_query ~address ~uri:req.uri ~query in
71+
Http_svr.headers s (Http.http_302_redirect url)
72+
in
73+
let unarchive () =
74+
let req = {req with m= Post; uri= Constants.rrd_unarchive_uri} in
75+
ignore
76+
(Xapi_services.hand_over_connection req s
77+
!Rrd_interface.forwarded_path
78+
)
79+
in
80+
let unavailable () =
81+
Http_svr.headers s (Http.http_503_service_unavailable ())
82+
in
83+
(* List of conditions involved. *)
84+
let is_unarchive_request = List.mem_assoc Constants.rrd_unarchive query in
85+
let metrics_at () =
86+
let ( let* ) = Option.bind in
87+
let owner_of vm =
88+
let owner = Db.VM.get_resident_on ~__context ~self:vm in
89+
let is_xapi_initialising = List.mem_assoc "dbsync" query in
90+
let is_available = not is_xapi_initialising in
91+
if Db.is_valid_ref __context owner && is_available then
92+
Some owner
93+
else
94+
None
8795
in
88-
let is_master = Pool_role.is_master () in
89-
let is_owner_online owner = Db.is_valid_ref __context owner in
90-
let is_xapi_initialising = List.mem_assoc "dbsync" query in
91-
(* The logic. *)
92-
if is_unarchive_request then
93-
unarchive ()
96+
let* owner = owner_of (Db.VM.get_by_uuid ~__context ~uuid:vm_uuid) in
97+
let owner_uuid = Db.Host.get_uuid ~__context ~self:owner in
98+
if owner_uuid = Helpers.get_localhost_uuid () then
99+
(* VM is local but metrics aren't available *)
100+
None
94101
else
95-
let localhost_uuid = Helpers.get_localhost_uuid () in
96-
let vm_ref = Db.VM.get_by_uuid ~__context ~uuid:vm_uuid in
97-
let owner = Db.VM.get_resident_on ~__context ~self:vm_ref in
98-
let owner_uuid = Db.Host.get_uuid ~__context ~self:owner in
99-
let is_owner_localhost = owner_uuid = localhost_uuid in
100-
if is_owner_localhost then
101-
if is_master then
102-
unarchive ()
103-
else
104-
unarchive_at_master ()
105-
else if is_owner_online owner && not is_xapi_initialising then
106-
read_at_owner owner
107-
else
108-
unarchive_at_master ()
102+
let address = Db.Host.get_address ~__context ~self:owner in
103+
Some address
104+
in
105+
(* The logic. *)
106+
if is_unarchive_request then
107+
unarchive ()
108+
else
109+
match (Pool_role.get_role (), metrics_at ()) with
110+
| (Master | Slave _), Some owner ->
111+
read_at owner
112+
| Master, None ->
113+
unarchive ()
114+
| Slave coordinator, None ->
115+
unarchive_at coordinator
116+
| Broken, _ ->
117+
info "%s: host is broken, VM's metrics are not available"
118+
__FUNCTION__ ;
119+
unavailable ()
109120
)
110121

111122
(* Forward the request for host RRD data to the RRDD HTTP handler. If the host

0 commit comments

Comments
 (0)