Skip to content

Commit cc986a0

Browse files
simonjbeaumontjohnelse
authored andcommitted
Unit tests for Xapi_vm_helpers (vGPU related)
Tests for assert_gpus_available and for group_hosts_by_best_pgpu_in_group. Signed-off-by: Si Beaumont <[email protected]>
1 parent 8b9276e commit cc986a0

File tree

4 files changed

+229
-2
lines changed

4 files changed

+229
-2
lines changed

ocaml/test/OMakefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ OCAML_OBJS = \
4444
test_vgpu_common \
4545
test_pgpu \
4646
test_pgpu_helpers \
47+
test_vm_helpers \
4748
test_xenopsd_metadata \
4849
test_ca121350 \
4950

ocaml/test/suite.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ let base_suite =
3131
Test_vgpu_type.test;
3232
Test_pgpu.test;
3333
Test_pgpu_helpers.test;
34+
Test_vm_helpers.test;
3435
Test_xenopsd_metadata.test;
3536
Test_ca121350.test;
3637
]

ocaml/test/test_vgpu_common.ml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ let make_vgpu ~__context pgpu_ref vgpu_type =
124124
~resident_on:pgpu_ref ();
125125
vgpu_ref
126126

127-
let make_pgpu ~__context pgpu =
127+
let make_pgpu ~__context ?(host=Ref.null) ?(gPU_group=Ref.null) pgpu =
128128
let pCI = Ref.make () in
129-
Test_common.make_pci ~__context ~ref:pCI ~functions:1L ();
129+
Test_common.make_pci ~__context ~ref:pCI ~host ~functions:1L ();
130130
let supported_VGPU_types =
131131
List.map (find_or_create ~__context) pgpu.supported_VGPU_types
132132
in
@@ -137,6 +137,8 @@ let make_pgpu ~__context pgpu =
137137
Test_common.make_pgpu ~__context
138138
~ref:pgpu_ref
139139
~pCI
140+
~host
141+
~gPU_group
140142
~supported_VGPU_types
141143
~enabled_VGPU_types ();
142144
List.iter

ocaml/test/test_vm_helpers.ml

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
2+
(*
3+
* Copyright (C) 2013 Citrix Systems Inc.
4+
*
5+
* This program is free software; you can redistribute it and/or modify
6+
* it under the terms of the GNU Lesser General Public License as published
7+
* by the Free Software Foundation; version 2.1 only. with the special
8+
* exception on linking described in file LICENSE.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Lesser General Public License for more details.
14+
*)
15+
16+
open OUnit
17+
open Test_common
18+
open Test_vgpu_common
19+
open Xapi_vm_helpers
20+
21+
(*--- Helper functions ---*)
22+
let on_pool_of_k1s (f : Context.t -> API.ref_host -> API.ref_host -> API.ref_host -> 'a) =
23+
(* Note: f c h h' h'' applied to hosts with the same number of k1s as 's
24+
* +----------+ +----------+ +----------+
25+
* | | | +--+ | |+--+ +--+|
26+
* | | | |K1| | ||K1| |K1||
27+
* | | | +--+ | |+--+ +--+|
28+
* +----------+ +----------+ +----------+
29+
* h h' h''
30+
*)
31+
let __context = make_test_database () in
32+
let h = List.hd (Db.Host.get_all ~__context) in
33+
(* Make two more hosts *)
34+
match (make_host ~__context (), make_host ~__context ()) with
35+
| (h', h'') ->
36+
let gPU_group = Ref.make () in
37+
make_gpu_group ~__context ~ref:gPU_group ();
38+
let rec make_k1s_on (host, num) =
39+
if num > 0 then
40+
let _ = make_pgpu ~__context ~host ~gPU_group default_k1 in
41+
make_k1s_on (host, (num - 1))
42+
in
43+
List.iter make_k1s_on [(h, 0); (h', 1); (h'', 2)];
44+
f __context h h' h''
45+
46+
let make_vm_with_vgpu_in_group ~__context vgpu_type gpu_group_ref =
47+
let vgpu_ref = make_vgpu ~__context Ref.null vgpu_type
48+
and vm_ref = make_vm ~__context () in
49+
Db.VGPU.set_GPU_group ~__context ~self:vgpu_ref ~value:gpu_group_ref;
50+
Db.VGPU.set_VM ~__context ~self:vgpu_ref ~value:vm_ref;
51+
vm_ref
52+
53+
(*--- Xapi_vm_helpers.assert_gpus_available ---*)
54+
let test_gpus_available_succeeds () =
55+
on_pool_of_k1s (fun __context _ h' _ ->
56+
let group = List.hd (Db.GPU_group.get_all ~__context) in
57+
let vm = make_vm_with_vgpu_in_group ~__context k100 group in
58+
assert_gpus_available ~__context ~self:vm ~host:h')
59+
60+
let test_gpus_available_fails_no_pgpu () =
61+
on_pool_of_k1s (fun __context h _ _ ->
62+
let group = List.hd (Db.GPU_group.get_all ~__context) in
63+
let vm = make_vm_with_vgpu_in_group ~__context k100 group in
64+
assert_raises_api_error Api_errors.vm_requires_gpu (fun () ->
65+
assert_gpus_available ~__context ~self:vm ~host:h))
66+
67+
let test_gpus_available_fails_disabled_type () =
68+
on_pool_of_k1s (fun __context _ h' _ ->
69+
let group = List.hd (Db.GPU_group.get_all ~__context) in
70+
let pgpus = Db.GPU_group.get_PGPUs ~__context ~self:group in
71+
List.iter (fun p ->
72+
Db.PGPU.set_enabled_VGPU_types ~__context ~self:p ~value:[])
73+
pgpus;
74+
let vm = make_vm_with_vgpu_in_group ~__context k100 group in
75+
assert_raises_api_error Api_errors.vm_requires_gpu (fun () ->
76+
assert_gpus_available ~__context ~self:vm ~host:h'))
77+
78+
let test_gpus_available_fails_no_capacity () =
79+
on_pool_of_k1s (fun __context _ h' _ ->
80+
let group = List.hd (Db.GPU_group.get_all ~__context) in
81+
let pgpus = Db.GPU_group.get_PGPUs ~__context ~self:group in
82+
(* Fill up all the PGPUs *)
83+
List.iter (fun p ->
84+
ignore (make_vgpu ~__context p Xapi_vgpu_type.entire_gpu))
85+
pgpus;
86+
let vm = make_vm_with_vgpu_in_group ~__context k100 group in
87+
assert_raises_api_error Api_errors.vm_requires_gpu
88+
(fun () -> assert_gpus_available ~__context ~self:vm ~host:h'))
89+
90+
(*--- Xapi_vm_helpers.group_hosts_by_best_pgpu ---*)
91+
let assert_list_is_set l =
92+
let rec inner ac = function
93+
| [] -> ()
94+
| x :: xs ->
95+
if (List.mem x ac) then assert_failure "List is not set"
96+
else inner (x :: ac) xs
97+
in
98+
inner [] l
99+
100+
let assert_host_group_coherent g =
101+
match g with
102+
| [] -> assert_failure "Empty host group"
103+
| (h, c) :: _ ->
104+
assert_list_is_set (List.map fst g);
105+
assert_bool "Score not same for all hosts in group"
106+
(List.for_all (fun x -> snd x = c) g)
107+
108+
let assert_host_groups_equal g g' =
109+
let extract_host_strings g =
110+
let hosts = List.map fst g in
111+
List.sort String.compare (List.map Ref.string_of hosts)
112+
in
113+
assert_equal (extract_host_strings g) (extract_host_strings g');
114+
let score_of g = snd (List.hd g) in
115+
assert_equal (score_of g) (score_of g')
116+
117+
let rec assert_equivalent expected_grouping actual_grouping =
118+
match (expected_grouping, actual_grouping) with
119+
| [], [] -> ()
120+
| [], xx -> assert_failure (Printf.sprintf "%d more groups than expected." (List.length xx))
121+
| xx, [] -> assert_failure (Printf.sprintf "%d less groups than expected." (List.length xx))
122+
| e :: es, g :: gs ->
123+
assert_host_group_coherent g;
124+
assert_host_groups_equal e g;
125+
assert_equivalent es gs
126+
127+
let assert_grouping ~__context gpu_group vgpu_type g =
128+
let vgpu_type_ref = Xapi_vgpu_type.find_or_create ~__context vgpu_type in
129+
let host_lists = group_hosts_by_best_pgpu_in_group ~__context gpu_group vgpu_type_ref in
130+
try assert_equivalent g host_lists
131+
with e ->
132+
let item_to_string (h, c) = Printf.sprintf "(%s, %Ld)" (Ref.string_of h) c in
133+
let group_to_string g = Printf.sprintf "[ %s ]"
134+
(String.concat "; " (List.map item_to_string g)) in
135+
let groups_to_string gs = Printf.sprintf "[ %s ]"
136+
(String.concat "; " (List.map group_to_string gs)) in
137+
let diff_string = Printf.sprintf "Expected: %s\nActual: %s\n"
138+
(groups_to_string g) (groups_to_string host_lists) in
139+
assert_failure (diff_string ^ Printexc.to_string e)
140+
141+
let rec assert_expectations ~__context gpu_group = function
142+
| [] -> ()
143+
| (vgpu_type, expected_grouping) :: remaining ->
144+
assert_grouping ~__context gpu_group vgpu_type expected_grouping;
145+
assert_expectations ~__context gpu_group remaining
146+
147+
let test_group_hosts_bf () =
148+
on_pool_of_k1s (fun __context h h' h'' ->
149+
let gpu_group = List.hd (Db.GPU_group.get_all ~__context) in
150+
Db.GPU_group.set_allocation_algorithm ~__context ~self:gpu_group ~value:`breadth_first;
151+
match Db.Host.get_PGPUs ~__context ~self:h' @ Db.Host.get_PGPUs ~__context ~self:h'' with
152+
| [h'_p; h''_p; h''_p'] ->
153+
assert_expectations ~__context gpu_group [
154+
k100, [ [(h',8L);(h'',8L)] ];
155+
k140q, [ [(h',4L);(h'',4L)] ];
156+
];
157+
ignore (make_vgpu ~__context h''_p k100);
158+
assert_expectations ~__context gpu_group [
159+
k100, [ [(h',8L);(h'',8L)] ];
160+
k140q, [ [(h',4L);(h'',4L)] ];
161+
];
162+
ignore (make_vgpu ~__context h''_p' k140q);
163+
assert_expectations ~__context gpu_group [
164+
k100, [ [(h',8L)]; [(h'',7L)] ];
165+
k140q, [ [(h',4L)]; [(h'',3L)] ];
166+
];
167+
ignore (make_vgpu ~__context h'_p k100);
168+
assert_expectations ~__context gpu_group [
169+
k100, [ [(h',7L);(h'',7L)] ];
170+
k140q, [ [(h'',3L)]; ];
171+
];
172+
ignore (make_vgpu ~__context h'_p k100);
173+
assert_expectations ~__context gpu_group [
174+
k100, [ [(h'',7L)]; [(h',6L)] ];
175+
k140q, [ [(h'',3L)]; ];
176+
];
177+
| _ -> failwith "Test-failure: Unexpected number of pgpus in test setup"
178+
)
179+
180+
let test_group_hosts_df () =
181+
on_pool_of_k1s (fun __context h h' h'' ->
182+
let gpu_group = List.hd (Db.GPU_group.get_all ~__context) in
183+
Db.GPU_group.set_allocation_algorithm ~__context ~self:gpu_group ~value:`depth_first;
184+
match Db.Host.get_PGPUs ~__context ~self:h' @ Db.Host.get_PGPUs ~__context ~self:h'' with
185+
| [h'_p; h''_p; h''_p'] ->
186+
assert_expectations ~__context gpu_group [
187+
k100, [ [(h',8L);(h'',8L)] ];
188+
k140q, [ [(h',4L);(h'',4L)] ];
189+
];
190+
ignore (make_vgpu ~__context h''_p k100);
191+
assert_expectations ~__context gpu_group [
192+
k100, [ [(h'',7L)]; [(h',8L)] ];
193+
k140q, [ [(h',4L);(h'',4L)] ];
194+
];
195+
ignore (make_vgpu ~__context h''_p' k140q);
196+
assert_expectations ~__context gpu_group [
197+
k100, [ [(h'',7L)]; [(h',8L)] ];
198+
k140q, [ [(h'',3L)]; [(h',4L)] ];
199+
];
200+
ignore (make_vgpu ~__context h'_p k100);
201+
assert_expectations ~__context gpu_group [
202+
k100, [ [(h',7L);(h'',7L)] ];
203+
k140q, [ [(h'',3L)]; ];
204+
];
205+
ignore (make_vgpu ~__context h'_p k100);
206+
assert_expectations ~__context gpu_group [
207+
k100, [ [(h',6L)]; [(h'',7L)] ];
208+
k140q, [ [(h'',3L)]; ];
209+
];
210+
| _ -> failwith "Test-failure: Unexpected number of pgpus in test setup"
211+
)
212+
213+
let test =
214+
"test_vm_helpers" >:::
215+
[
216+
"test_gpus_available_succeeds" >:: test_gpus_available_succeeds;
217+
"test_gpus_available_fails_no_pgpu" >:: test_gpus_available_fails_no_pgpu;
218+
"test_gpus_available_fails_disabled_type" >:: test_gpus_available_fails_disabled_type;
219+
"test_gpus_available_fails_no_capacity" >:: test_gpus_available_fails_no_capacity;
220+
221+
"test_group_hosts_bf" >:: test_group_hosts_bf;
222+
"test_group_hosts_df" >:: test_group_hosts_df;
223+
]

0 commit comments

Comments
 (0)