diff --git a/ocaml/xapi-cli-server/record_util.ml b/ocaml/xapi-cli-server/record_util.ml index 4d5f36976d2..ed574bb62a2 100644 --- a/ocaml/xapi-cli-server/record_util.ml +++ b/ocaml/xapi-cli-server/record_util.ml @@ -108,6 +108,7 @@ let vm_operation_table = ; (`changing_NVRAM, "changing_NVRAM") ; (`start, "start") ; (`start_on, "start_on") + ; (`shutdown, "shutdown") ; (`suspend, "suspend") ; (`unpause, "unpause") ; (`update_allowed_operations, "update_allowed_operations") diff --git a/ocaml/xapi/message_forwarding.ml b/ocaml/xapi/message_forwarding.ml index c4e1feae1b2..bbe3f1932e8 100644 --- a/ocaml/xapi/message_forwarding.ml +++ b/ocaml/xapi/message_forwarding.ml @@ -1858,6 +1858,7 @@ functor ; `hard_reboot ; `pool_migrate ; `call_plugin + ; `shutdown ; `suspend ] ; (* If VM is actually suspended and we ask to hard_shutdown, we need to diff --git a/ocaml/xapi/rrdd_proxy.ml b/ocaml/xapi/rrdd_proxy.ml index 13a49f11493..f419007d841 100644 --- a/ocaml/xapi/rrdd_proxy.ml +++ b/ocaml/xapi/rrdd_proxy.ml @@ -51,6 +51,7 @@ let fail_req_with (s : Unix.file_descr) msg (http_err : unit -> string list) = *) let get_vm_rrd_forwarder (req : Http.Request.t) (s : Unix.file_descr) _ = debug "put_rrd_forwarder: start" ; + let __FUNCTION__ = "get_vm_rrd_forwarder" in let query = req.Http.Request.query in req.Http.Request.close <- true ; let vm_uuid = List.assoc "uuid" query in @@ -65,49 +66,64 @@ let get_vm_rrd_forwarder (req : Http.Request.t) (s : Unix.file_descr) _ = Xapi_http.with_context ~dummy:true "Get VM RRD." req s (fun __context -> let open Http.Request in (* List of possible actions. *) - let read_at_owner owner = - let address = Db.Host.get_address ~__context ~self:owner in + let read_at address = let url = make_url ~address ~req in Http_svr.headers s (Http.http_302_redirect url) in - let unarchive_at_master () = - let address = Pool_role.get_master_address () in + let unarchive_at address = let query = (Constants.rrd_unarchive, "") :: query in let url = make_url_from_query ~address ~uri:req.uri ~query in Http_svr.headers s (Http.http_302_redirect url) in let unarchive () = - let req = {req with uri= Constants.rrd_unarchive_uri} in + let req = {req with m= Post; uri= Constants.rrd_unarchive_uri} in ignore (Xapi_services.hand_over_connection req s !Rrd_interface.forwarded_path ) in + let unavailable () = + Http_svr.headers s (Http.http_503_service_unavailable ()) + in (* List of conditions involved. *) let is_unarchive_request = List.mem_assoc Constants.rrd_unarchive query in - let is_master = Pool_role.is_master () in - let is_owner_online owner = Db.is_valid_ref __context owner in - let is_xapi_initialising = List.mem_assoc "dbsync" query in + let metrics_at () = + let ( let* ) = Option.bind in + let owner_of vm = + let owner = Db.VM.get_resident_on ~__context ~self:vm in + let is_xapi_initialising = List.mem_assoc "dbsync" query in + let is_available = not is_xapi_initialising in + if Db.is_valid_ref __context owner && is_available then + Some owner + else + None + in + let* owner = owner_of (Db.VM.get_by_uuid ~__context ~uuid:vm_uuid) in + let owner_uuid = Db.Host.get_uuid ~__context ~self:owner in + if owner_uuid = Helpers.get_localhost_uuid () then + (* VM is local but metrics aren't available *) + None + else + let address = Db.Host.get_address ~__context ~self:owner in + Some address + in (* The logic. *) if is_unarchive_request then unarchive () else - let localhost_uuid = Helpers.get_localhost_uuid () in - let vm_ref = Db.VM.get_by_uuid ~__context ~uuid:vm_uuid in - let owner = Db.VM.get_resident_on ~__context ~self:vm_ref in - let owner_uuid = Ref.string_of owner in - let is_owner_localhost = owner_uuid = localhost_uuid in - if is_owner_localhost then - if is_master then + match (Pool_role.get_role (), metrics_at ()) with + | (Master | Slave _), Some owner -> + read_at owner + | Master, None -> unarchive () - else - unarchive_at_master () - else if is_owner_online owner && not is_xapi_initialising then - read_at_owner owner - else - unarchive_at_master () + | Slave coordinator, None -> + unarchive_at coordinator + | Broken, _ -> + info "%s: host is broken, VM's metrics are not available" + __FUNCTION__ ; + unavailable () ) (* Forward the request for host RRD data to the RRDD HTTP handler. If the host diff --git a/ocaml/xapi/taskHelper.ml b/ocaml/xapi/taskHelper.ml index 76f5185b00e..4d254a5b66a 100644 --- a/ocaml/xapi/taskHelper.ml +++ b/ocaml/xapi/taskHelper.ml @@ -56,6 +56,15 @@ let rbac_assert_permission_fn = ref None (* required to break dep-cycle with rbac.ml *) +let are_auth_user_ids_of_sessions_equal ~__context s1 s2 = + let s1_auth_user_sid = + Db_actions.DB_Action.Session.get_auth_user_sid ~__context ~self:s1 + in + let s2_auth_user_sid = + Db_actions.DB_Action.Session.get_auth_user_sid ~__context ~self:s2 + in + s1_auth_user_sid = s2_auth_user_sid + let assert_op_valid ?(ok_if_no_session_in_context = false) ~__context task_id = let assert_permission_task_op_any () = match !rbac_assert_permission_fn with @@ -80,19 +89,14 @@ let assert_op_valid ?(ok_if_no_session_in_context = false) ~__context task_id = | Some context_session -> let is_own_task = try - let task_session = - Db_actions.DB_Action.Task.get_session ~__context ~self:task_id - in - let task_auth_user_sid = - Db_actions.DB_Action.Session.get_auth_user_sid ~__context - ~self:task_session - in - let context_auth_user_sid = - Db_actions.DB_Action.Session.get_auth_user_sid ~__context - ~self:context_session - in - (*debug "task_auth_user_sid=%s,context_auth_user_sid=%s" task_auth_user_sid context_auth_user_sid;*) - task_auth_user_sid = context_auth_user_sid + (* If the task id is the same as the context's task id, we don't need + to go theough their respective sessions.*) + match Context.get_task_id __context = task_id with + | true -> + true + | false -> + are_auth_user_ids_of_sessions_equal ~__context context_session + (Db_actions.DB_Action.Task.get_session ~__context ~self:task_id) with e -> debug "assert_op_valid: %s" (ExnHelper.string_of_exn e) ; false