Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions ocaml/idl/datamodel.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2334,6 +2334,18 @@ let vm_set_appliance = call
~allowed_roles:_R_POOL_OP
()

let vm_call_plugin = call
~name:"call_plugin"
~in_product_since:rel_augusta
~doc:"Call a XenAPI plugin on this vm"
~params:[Ref _vm, "vm", "The vm";
String, "plugin", "The name of the plugin";
String, "fn", "The name of the function within the plugin";
Map(String, String), "args", "Arguments for the function"]
~result:(String, "Result from the plugin")
~allowed_roles:_R_VM_OP
()

(* ------------------------------------------------------------------------------------------------------------
Host Management
------------------------------------------------------------------------------------------------------------ *)
Expand Down Expand Up @@ -6742,6 +6754,7 @@ let vm_operations =
vm_migrate_send;
vm_get_boot_record; vm_send_sysrq; vm_send_trigger;
vm_query_services;vm_shutdown;
vm_call_plugin;
]
@ [ "changing_memory_live", "Changing the memory settings";
"awaiting_memory_live", "Waiting for the memory settings to change";
Expand Down Expand Up @@ -6825,6 +6838,7 @@ let vm =
vm_import_convert;
vm_set_appliance;
vm_query_services;
vm_call_plugin;
]
~contents:
([ uid _vm;
Expand Down
9 changes: 9 additions & 0 deletions ocaml/xapi/cli_frontend.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,15 @@ there are two or more empty CD devices, please use the command 'vbd-insert' and
flags=[Vm_selectors];
};

"vm-call-plugin",
{
reqd=["vm-uuid"; "plugin"; "fn"];
optn=["args:"];
help="Calls the function within the plugin on the given vm with optional arguments.";
implementation=No_fd Cli_operations.vm_call_plugin;
flags=[];
};

"snapshot-export-to-template",
{
reqd=["filename"; "snapshot-uuid"];
Expand Down
9 changes: 9 additions & 0 deletions ocaml/xapi/cli_operations.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1963,6 +1963,15 @@ let vm_memory_target_wait printer rpc session_id params =
let vm=vm.getref () in
Client.VM.wait_memory_target_live rpc session_id vm) params [])

let vm_call_plugin printer rpc session_id params =
let vm_uuid = List.assoc "vm-uuid" params in
let vm = Client.VM.get_by_uuid rpc session_id vm_uuid in
let plugin = List.assoc "plugin" params in
let fn = List.assoc "fn" params in
let args = read_map_params "args" params in
let result = Client.VM.call_plugin rpc session_id vm plugin fn args in
printer (Cli_printer.PList [ result ])

let data_source_to_kvs ds =
["name_label",ds.API.data_source_name_label;
"name_description",ds.API.data_source_name_description;
Expand Down
7 changes: 7 additions & 0 deletions ocaml/xapi/message_forwarding.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,13 @@ module Forward = functor(Local: Custom_actions.CUSTOM_ACTIONS) -> struct
update_vbd_operations ~__context ~vm;
update_vif_operations ~__context ~vm

let call_plugin ~__context ~vm ~plugin ~fn ~args =
info "VM.call_plugin: VM = '%s'" (vm_uuid ~__context vm);
let local_fn = Local.VM.call_plugin ~vm ~plugin ~fn ~args in
with_vm_operation ~__context ~self:vm ~doc:"VM.call_plugin" ~op:`call_plugin
(fun () ->
forward_vm_op ~local_fn ~__context ~vm (fun session_id rpc -> Client.VM.call_plugin rpc session_id vm plugin fn args))

let set_xenstore_data ~__context ~self ~value =
info "VM.set_xenstore_data: VM = '%s'" (vm_uuid ~__context self);
Db.VM.set_xenstore_data ~__context ~self ~value;
Expand Down
42 changes: 42 additions & 0 deletions ocaml/xapi/xapi_vm.ml
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,48 @@ let set_memory_dynamic_range ~__context ~self ~min ~max =
if power_state = `Running
then Xapi_xenops.set_memory_dynamic_range ~__context ~self min max

let request_rdp ~__context ~vm ~enabled =
let vm_gm = Db.VM.get_guest_metrics ~__context ~self:vm in
let vm_gmr = try Some (Db.VM_guest_metrics.get_record_internal ~__context ~self:vm_gm) with _ -> None in
let is_feature_ts_on =
match vm_gmr with
| None -> false
| Some vm_gmr ->
let other = vm_gmr.Db_actions.vM_guest_metrics_other in
try
List.assoc "feature-ts" other = "1"
with Not_found -> false
in
if is_feature_ts_on
then
Xapi_xenops.request_rdp ~__context ~self:vm enabled
else raise Not_found

let request_rdp_on ~__context ~vm =
request_rdp ~__context ~vm ~enabled:true

let request_rdp_off ~__context ~vm =
request_rdp ~__context ~vm ~enabled:false

(* this is the generic plugin call available to xapi users *)
let call_plugin ~__context ~vm ~plugin ~fn ~args =
if plugin <> "guest-agent-operation" then
raise (Api_errors.Server_error(Api_errors.xenapi_missing_plugin, [ plugin ]));
try
match fn with
| "request-rdp-on" ->
request_rdp_on ~__context ~vm;
""
| "request-rdp-off" ->
request_rdp_off ~__context ~vm;
""
| _ ->
let msg = Printf.sprintf "The requested fn \"%s\" could not be found in plugin \"%s\"." fn plugin in
raise (Api_errors.Server_error(Api_errors.xenapi_plugin_failure, [ "failed to find fn"; msg; msg ]))
with Not_found ->
let msg = Printf.sprintf "The requested fn \"%s\" of plugin \"%s\" could not be executed for lack of guest agent control feature." fn plugin in
raise (Api_errors.Server_error(Api_errors.xenapi_plugin_failure, [ "failed to execute fn"; msg; msg ]))

let send_sysrq ~__context ~vm ~key =
raise (Api_errors.Server_error (Api_errors.not_implemented, [ "send_sysrq" ]))

Expand Down
5 changes: 5 additions & 0 deletions ocaml/xapi/xapi_vm.mli
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,8 @@ val import_convert : __context:Context.t -> _type:string -> username:string -> p
(** [query_services __context self] returns a Map of service type -> name label provided
by the specific VM. *)
val query_services : __context:Context.t -> self:API.ref_VM -> (string * string) list

val request_rdp_on : __context:Context.t -> vm:API.ref_VM -> unit
val request_rdp_off: __context:Context.t -> vm:API.ref_VM -> unit

val call_plugin : __context:Context.t -> vm:API.ref_VM -> plugin:string -> fn:string -> args:(string * string) list -> string
1 change: 1 addition & 0 deletions ocaml/xapi/xapi_vm_lifecycle.ml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ let allowed_power_states ~__context ~vmr ~(op:API.vm_operations) =
| `resume_on
-> [`Suspended]
| `awaiting_memory_live
| `call_plugin
| `clean_reboot
| `clean_shutdown
| `changing_memory_live
Expand Down
12 changes: 12 additions & 0 deletions ocaml/xapi/xapi_xenops.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1882,6 +1882,18 @@ let unpause ~__context ~self =
check_power_state ~__context ~self ~expected:`Running
)

let request_rdp ~__context ~self enabled =
let queue_name = queue_of_vm ~__context ~self in
transform_xenops_exn ~__context queue_name
(fun () ->
let id = id_of_vm ~__context ~self in
debug "xenops: VM.request_rdp %s %b" id enabled;
let dbg = Context.string_of_task __context in
let module Client = (val make_client queue_name : XENOPS) in
Client.VM.request_rdp dbg id enabled |> sync_with_task __context queue_name;
Events_from_xenopsd.wait queue_name dbg id ()
)

let set_xenstore_data ~__context ~self xsdata =
let queue_name = queue_of_vm ~__context ~self in
transform_xenops_exn ~__context queue_name
Expand Down