Skip to content

Commit a5f0ad0

Browse files
committed
CP-10203: XenAPI: api call for RDP on/off request
Signed-off-by: Hui Zhang <[email protected]>
1 parent b07fd68 commit a5f0ad0

File tree

9 files changed

+131
-0
lines changed

9 files changed

+131
-0
lines changed

ocaml/idl/api_errors.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ let vm_old_pv_drivers = "VM_OLD_PV_DRIVERS"
174174
let vm_lacks_feature_shutdown = "VM_LACKS_FEATURE_SHUTDOWN"
175175
let vm_lacks_feature_suspend = "VM_LACKS_FEATURE_SUSPEND"
176176
let vm_lacks_feature_vcpu_hotplug = "VM_LACKS_FEATURE_VCPU_HOTPLUG"
177+
let vm_lacks_feature_rdp = "VM_LACKS_FEATURE_RDP"
177178
let vm_cannot_delete_default_template = "VM_CANNOT_DELETE_DEFAULT_TEMPLATE"
178179
let vm_memory_size_too_low = "VM_MEMORY_SIZE_TOO_LOW"
179180
let vm_memory_target_wait_timeout = "VM_MEMORY_TARGET_WAIT_TIMEOUT"

ocaml/idl/datamodel.ml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,8 @@ let _ =
623623
~doc:"You attempted an operation which needs the VM hotplug-vcpu feature on a VM which lacks it." ();
624624
error Api_errors.vm_lacks_feature_suspend [ "vm" ]
625625
~doc:"You attempted an operation which needs the VM cooperative suspend feature on a VM which lacks it." ();
626+
error Api_errors.vm_lacks_feature_rdp [ "vm" ]
627+
~doc:"You attempted to ask a VM to enable or disable Remote Desktop Protocol but the VM lacks this control feature." ();
626628
error Api_errors.vm_is_template ["vm"]
627629
~doc:"The operation attempted is not valid for a template VM" ();
628630
error Api_errors.other_operation_in_progress ["class"; "object"]
@@ -2090,6 +2092,30 @@ let vm_pool_migrate_complete = call
20902092
~allowed_roles:_R_VM_POWER_ADMIN
20912093
()
20922094

2095+
let vm_request_rdp_on = call
2096+
~name:"request_rdp_on"
2097+
~lifecycle:[
2098+
Published, rel_augusta, "Ask the VM to enable Remote Desktop Protocol. Error if the VM is halted or does not advertise this control feature. The VM may or may not cooperate."
2099+
]
2100+
~in_oss_since:None
2101+
~doc:"Ask the VM to enable Remote Desktop Protocol. Error if the VM is halted or does not advertise this control feature. The VM may or may not cooperate."
2102+
~params:[Ref _vm, "vm", "The VM to ask to enable Remote Desktop Protocol"]
2103+
~errs:[Api_errors.vm_bad_power_state; Api_errors.vm_lacks_feature_rdp]
2104+
~allowed_roles:_R_VM_OP
2105+
()
2106+
2107+
let vm_request_rdp_off = call
2108+
~name:"request_rdp_off"
2109+
~lifecycle:[
2110+
Published, rel_augusta, "Ask the VM to disable Remote Desktop Protocol. Error if the VM is halted or does not advertise this control feature. The VM may or may not cooperate."
2111+
]
2112+
~in_oss_since:None
2113+
~doc:"Ask the VM to disable Remote Desktop Protocol. Error if the VM is halted or does not advertise this control feature. The VM may or may not cooperate."
2114+
~params:[Ref _vm, "vm", "The VM to ask to disable Remote Desktop Protocol"]
2115+
~errs:[Api_errors.vm_bad_power_state; Api_errors.vm_lacks_feature_rdp]
2116+
~allowed_roles:_R_VM_OP
2117+
()
2118+
20932119
let host_migrate_receive = call
20942120
~in_oss_since:None
20952121
~in_product_since:rel_tampa
@@ -2334,6 +2360,18 @@ let vm_set_appliance = call
23342360
~allowed_roles:_R_POOL_OP
23352361
()
23362362

2363+
let vm_call_plugin = call
2364+
~name:"call_plugin"
2365+
~in_product_since:rel_augusta
2366+
~doc:"Call a XenAPI plugin on this vm"
2367+
~params:[Ref _vm, "vm", "The vm";
2368+
String, "plugin", "The name of the plugin";
2369+
String, "fn", "The name of the function within the plugin";
2370+
Map(String, String), "args", "Arguments for the function"]
2371+
~result:(String, "Result from the plugin")
2372+
~allowed_roles:_R_VM_OP
2373+
()
2374+
23372375
(* ------------------------------------------------------------------------------------------------------------
23382376
Host Management
23392377
------------------------------------------------------------------------------------------------------------ *)
@@ -6742,6 +6780,8 @@ let vm_operations =
67426780
vm_migrate_send;
67436781
vm_get_boot_record; vm_send_sysrq; vm_send_trigger;
67446782
vm_query_services;vm_shutdown;
6783+
vm_request_rdp_on;vm_request_rdp_off;
6784+
vm_call_plugin;
67456785
]
67466786
@ [ "changing_memory_live", "Changing the memory settings";
67476787
"awaiting_memory_live", "Waiting for the memory settings to change";
@@ -6825,6 +6865,7 @@ let vm =
68256865
vm_import_convert;
68266866
vm_set_appliance;
68276867
vm_query_services;
6868+
vm_call_plugin;
68286869
]
68296870
~contents:
68306871
([ uid _vm;

ocaml/xapi/cli_frontend.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,6 +1335,15 @@ there are two or more empty CD devices, please use the command 'vbd-insert' and
13351335
flags=[Vm_selectors];
13361336
};
13371337

1338+
"vm-call-plugin",
1339+
{
1340+
reqd=["vm-uuid"; "plugin"; "fn"];
1341+
optn=["args:"];
1342+
help="Calls the function within the plugin on the given vm with optional arguments.";
1343+
implementation=No_fd Cli_operations.vm_call_plugin;
1344+
flags=[];
1345+
};
1346+
13381347
"snapshot-export-to-template",
13391348
{
13401349
reqd=["filename"; "snapshot-uuid"];

ocaml/xapi/cli_operations.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1963,6 +1963,15 @@ let vm_memory_target_wait printer rpc session_id params =
19631963
let vm=vm.getref () in
19641964
Client.VM.wait_memory_target_live rpc session_id vm) params [])
19651965

1966+
let vm_call_plugin printer rpc session_id params =
1967+
let vm_uuid = List.assoc "vm-uuid" params in
1968+
let vm = Client.VM.get_by_uuid rpc session_id vm_uuid in
1969+
let plugin = List.assoc "plugin" params in
1970+
let fn = List.assoc "fn" params in
1971+
let args = read_map_params "args" params in
1972+
let result = Client.VM.call_plugin rpc session_id vm plugin fn args in
1973+
printer (Cli_printer.PList [ result ])
1974+
19661975
let data_source_to_kvs ds =
19671976
["name_label",ds.API.data_source_name_label;
19681977
"name_description",ds.API.data_source_name_description;

ocaml/xapi/message_forwarding.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,13 @@ module Forward = functor(Local: Custom_actions.CUSTOM_ACTIONS) -> struct
13061306
update_vbd_operations ~__context ~vm;
13071307
update_vif_operations ~__context ~vm
13081308

1309+
let call_plugin ~__context ~vm ~plugin ~fn ~args =
1310+
info "VM.call_plugin: VM = '%s'" (vm_uuid ~__context vm);
1311+
let local_fn = Local.VM.call_plugin ~vm ~plugin ~fn ~args in
1312+
with_vm_operation ~__context ~self:vm ~doc:"VM.call_plugin" ~op:`call_plugin
1313+
(fun () ->
1314+
forward_vm_op ~local_fn ~__context ~vm (fun session_id rpc -> Client.VM.call_plugin rpc session_id vm plugin fn args))
1315+
13091316
let set_xenstore_data ~__context ~self ~value =
13101317
info "VM.set_xenstore_data: VM = '%s'" (vm_uuid ~__context self);
13111318
Db.VM.set_xenstore_data ~__context ~self ~value;
@@ -1990,6 +1997,7 @@ module Forward = functor(Local: Custom_actions.CUSTOM_ACTIONS) -> struct
19901997
info "VM.import_convert: type = '%s'; remote_config = '%s;'"
19911998
_type (String.concat "," (List.map (fun (k,v) -> k ^ "=" ^ v) remote_config));
19921999
Local.VM.import_convert ~__context ~_type ~username ~password ~sr ~remote_config
2000+
19932001
end
19942002

19952003
module VM_metrics = struct

ocaml/xapi/xapi_vm.ml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,49 @@ let set_memory_dynamic_range ~__context ~self ~min ~max =
700700
if power_state = `Running
701701
then Xapi_xenops.set_memory_dynamic_range ~__context ~self min max
702702

703+
let request_rdp ~__context ~vm ~enabled =
704+
let vm_gm = Db.VM.get_guest_metrics ~__context ~self:vm in
705+
let vm_gmr = try Some (Db.VM_guest_metrics.get_record_internal ~__context ~self:vm_gm) with _ -> None in
706+
let is_feature_ts_on =
707+
match vm_gmr with
708+
| None -> false
709+
| Some vm_gmr ->
710+
let other = vm_gmr.Db_actions.vM_guest_metrics_other in
711+
try
712+
List.assoc "feature-ts" other = "1"
713+
with Not_found -> false
714+
in
715+
if is_feature_ts_on
716+
then
717+
Xapi_xenops.request_rdp ~__context ~self:vm enabled
718+
else raise (Api_errors.Server_error (Api_errors.vm_lacks_feature_rdp, [ Ref.string_of vm ]))
719+
720+
let request_rdp_on ~__context ~vm =
721+
request_rdp ~__context ~vm ~enabled:true
722+
723+
let request_rdp_off ~__context ~vm =
724+
request_rdp ~__context ~vm ~enabled:false
725+
726+
(* this is the generic plugin call available to xapi users *)
727+
let call_plugin ~__context ~vm ~plugin ~fn ~args =
728+
if plugin <> "guest-agent-operation" then
729+
raise (Api_errors.Server_error(Api_errors.xenapi_missing_plugin, [ plugin ]));
730+
let _ =
731+
try List.assoc "foobar" args
732+
with _ -> ""
733+
in
734+
735+
match fn with
736+
| "request-rdp-on" ->
737+
request_rdp_on ~__context ~vm;
738+
""
739+
| "request-rdp-off" ->
740+
request_rdp_off ~__context ~vm;
741+
""
742+
| value ->
743+
let msg = Printf.sprintf "The requested fn \"%s\" could not be found in plugin \"%s\"." value plugin in
744+
raise (Api_errors.Server_error(Api_errors.xenapi_missing_plugin, [ msg ]))
745+
703746
let send_sysrq ~__context ~vm ~key =
704747
raise (Api_errors.Server_error (Api_errors.not_implemented, [ "send_sysrq" ]))
705748

ocaml/xapi/xapi_vm.mli

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,8 @@ val import_convert : __context:Context.t -> _type:string -> username:string -> p
244244
(** [query_services __context self] returns a Map of service type -> name label provided
245245
by the specific VM. *)
246246
val query_services : __context:Context.t -> self:API.ref_VM -> (string * string) list
247+
248+
val request_rdp_on : __context:Context.t -> vm:API.ref_VM -> unit
249+
val request_rdp_off: __context:Context.t -> vm:API.ref_VM -> unit
250+
251+
val call_plugin : __context:Context.t -> vm:API.ref_VM -> plugin:string -> fn:string -> args:(string * string) list -> string

ocaml/xapi/xapi_vm_lifecycle.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ let allowed_power_states ~__context ~vmr ~(op:API.vm_operations) =
5151
| `resume_on
5252
-> [`Suspended]
5353
| `awaiting_memory_live
54+
| `call_plugin
5455
| `clean_reboot
5556
| `clean_shutdown
5657
| `changing_memory_live
@@ -60,6 +61,8 @@ let allowed_power_states ~__context ~vmr ~(op:API.vm_operations) =
6061
| `migrate_send
6162
| `pause
6263
| `pool_migrate
64+
| `request_rdp_on
65+
| `request_rdp_off
6366
| `send_sysrq
6467
| `send_trigger
6568
| `snapshot_with_quiesce

ocaml/xapi/xapi_xenops.ml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,6 +1882,18 @@ let unpause ~__context ~self =
18821882
check_power_state ~__context ~self ~expected:`Running
18831883
)
18841884

1885+
let request_rdp ~__context ~self enabled =
1886+
let queue_name = queue_of_vm ~__context ~self in
1887+
transform_xenops_exn ~__context queue_name
1888+
(fun () ->
1889+
let id = id_of_vm ~__context ~self in
1890+
debug "xenops: VM.request_rdp %s %b" id enabled;
1891+
let dbg = Context.string_of_task __context in
1892+
let module Client = (val make_client queue_name : XENOPS) in
1893+
Client.VM.request_rdp dbg id enabled |> sync_with_task __context queue_name;
1894+
Events_from_xenopsd.wait queue_name dbg id ()
1895+
)
1896+
18851897
let set_xenstore_data ~__context ~self xsdata =
18861898
let queue_name = queue_of_vm ~__context ~self in
18871899
transform_xenops_exn ~__context queue_name

0 commit comments

Comments
 (0)