Skip to content

Commit 18ff5f5

Browse files
committed
CP-28427: add Bond.create test
Test creating a bond, setting up a GFS2 SR on one host, and then join more hosts to the pool. This allows to just rollback to snapshot, upload a new XAPI, and run the bonding test to reproduce problems during pool join. Signed-off-by: Edwin Török <[email protected]>
1 parent 78bef60 commit 18ff5f5

File tree

4 files changed

+152
-1
lines changed

4 files changed

+152
-1
lines changed

lib/test_sr.ml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,40 @@ let make_pool ~uname ~pwd conf ips =
342342
m "All hosts enabled in the pool, master is: %a" Ipaddr.V4.pp_hum master ) ;
343343
Lwt.return t ) )
344344

345+
let destroy_pools ~uname ~pwd ips =
346+
let destroy_pool master =
347+
let ipstr = Ipaddr.V4.to_string master in
348+
with_login ~uname ~pwd ipstr (fun t ->
349+
step t (Printf.sprintf "Unplug PBDs on %s" ipstr) (fun ctx ->
350+
rpc ctx @@ PBD.get_all_records
351+
>>= Lwt_list.iter_p (fun (pbd, pbdr) ->
352+
if pbdr.API.pBD_currently_attached then
353+
rpc ctx @@ PBD.unplug ~self:pbd
354+
else Lwt.return_unit
355+
)
356+
) >>= fun () ->
357+
step t (Printf.sprintf "Destroy cluster if any on %s" ipstr) (fun ctx ->
358+
rpc ctx @@ Cluster.get_all
359+
>>= Lwt_list.iter_s (fun self ->
360+
rpc ctx @@ Cluster.pool_force_destroy ~self
361+
)
362+
) >>= fun () ->
363+
step t (Printf.sprintf "Pool eject on %s's pool" ipstr) @@ fun ctx ->
364+
rpc ctx @@ Host.get_all_records
365+
>>= Lwt_list.iter_s (fun (host, hostr) ->
366+
debug (fun m -> m "Host %s is %s" (Ref.string_of host) hostr.API.host_name_label);
367+
if hostr.API.host_address <> ipstr then
368+
rpc ctx @@ Pool.eject ~host
369+
else Lwt.return_unit
370+
)
371+
)
372+
in
373+
debug (fun m -> m "Destroying pool(s)");
374+
Lwt_list.map_p (get_master ~uname ~pwd) ips
375+
>>= fun masters ->
376+
List.sort_uniq Ipaddr.V4.compare masters
377+
|> Lwt_list.iter_p destroy_pool
378+
345379
let find_templates ctx label =
346380
rpc ctx @@ VM.get_by_name_label ~label
347381
>>= Lwt_list.filter_map_p (fun vm_ref ->

src/cmd_bonding.ml

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
open Lwt.Infix
2+
open Testarossa
3+
open Cmd_types
4+
open Context
5+
open Xen_api_lwt_unix
6+
7+
let ensure_vm_off ctx vifr =
8+
let self = vifr.API.vIF_VM in
9+
rpc ctx @@ VM.get_power_state ~self
10+
>>= function
11+
| `Halted -> Lwt.return_unit
12+
| _ ->
13+
rpc ctx @@ VM.shutdown ~vm:self
14+
15+
let ensure_vm_on ctx (vm, vmr) =
16+
match vmr.API.vM_power_state with
17+
| `Halted -> rpc ctx @@ VM.start ~start_paused:false ~force:false ~vm
18+
| _ -> Lwt.return_unit
19+
20+
let ensure_vhosts_on conf =
21+
match conf.physical with
22+
| None -> Lwt.return_unit
23+
| Some host ->
24+
Context.with_login ~uname:conf.uname ~pwd:conf.pwd host (fun phys ->
25+
Context.step phys "ensure vhosts are powered on" @@ fun ctx ->
26+
Rollback.list_vms ctx
27+
>>= Lwt_list.iter_p (ensure_vm_on ctx)
28+
)
29+
30+
let ensure_vhost_nics conf =
31+
match conf.physical with
32+
| None -> Lwt.return_unit
33+
| Some host ->
34+
Context.with_login ~uname:conf.uname ~pwd:conf.pwd host (fun phys ->
35+
Context.step phys "ensure vhost has enough NICs" @@ fun ctx ->
36+
Rollback.list_vms ctx
37+
>>= Lwt_list.iter_p (fun (vm, vmr) ->
38+
match vmr.API.vM_VIFs with
39+
| [] -> Lwt.fail_with "No NICs"
40+
| [ one ] ->
41+
rpc ctx @@ VIF.get_network ~self:one
42+
>>= fun network ->
43+
rpc ctx @@ VIF.create ~device:"1" ~network ~vM:vm ~mAC:""
44+
~mTU:1500L ~other_config:[] ~qos_algorithm_type:""
45+
~qos_algorithm_params:[] ~locking_mode:`network_default
46+
~ipv4_allowed:[] ~ipv6_allowed:[]
47+
>>= fun vif ->
48+
debug (fun m -> m "VIF %s created" (Ref.string_of vif));
49+
(* can't hotplug due to pure HVM mode *)
50+
rpc ctx @@ VM.hard_reboot ~vm
51+
| _ -> Lwt.return_unit
52+
)
53+
)
54+
55+
let ensure_bonding_on_master conf =
56+
let master = List.hd conf.hosts |> Ipaddr.V4.to_string in
57+
Context.with_login ~uname:conf.uname ~pwd:conf.pwd master (fun t ->
58+
step t "Create bond on master if needed" @@ fun ctx ->
59+
rpc ctx @@ Pool.get_all
60+
>>= fun pools ->
61+
rpc ctx @@ Pool.get_master ~self:(List.hd pools)
62+
>>= fun host ->
63+
rpc ctx @@ PIF.scan ~host
64+
>>= fun () ->
65+
rpc ctx @@ Bond.get_all
66+
>>= function
67+
| [] ->
68+
info (fun m -> m "No bond, creating one");
69+
rpc ctx @@ Host.get_management_interface ~host
70+
>>= fun pif ->
71+
rpc ctx @@ PIF.get_record ~self:pif
72+
>>= fun pifr ->
73+
rpc ctx @@ Host.get_PIFs ~self:host
74+
>>= fun members ->
75+
rpc ctx @@ Network.create ~name_label:"bonded network"
76+
~name_description:"" ~mTU:1500L ~other_config:[]
77+
~bridge:"" ~managed:true ~tags:[]
78+
>>= fun network ->
79+
rpc ctx @@ Bond.create ~network ~members ~mAC:"" ~mode:`balanceslb ~properties:[]
80+
>>= fun bond ->
81+
debug (fun m -> m "Created bond %s" (Ref.string_of bond));
82+
Lwt.return_unit
83+
| _ -> Lwt.return_unit
84+
)
85+
86+
87+
let do_prepare conf =
88+
let master = List.hd conf.hosts |> Ipaddr.V4.to_string in
89+
Context.with_login ~uname:conf.uname ~pwd:conf.pwd master (fun t ->
90+
License.maybe_apply_license_pool t conf [Features.HA; Features.Corosync]
91+
>>= fun () ->
92+
Test_sr.enable_clustering t
93+
>>= fun _cluster ->
94+
(match (conf.iscsi, conf.iqn) with
95+
| Some iscsi, Some iqn ->
96+
Test_sr.get_gfs2_sr t ~iscsi ~iqn ?scsiid:conf.scsiid () >>= fun _gfs2 -> Lwt.return_unit
97+
| _ -> Lwt.return_unit)
98+
>>= fun () ->
99+
Test_sr.make_pool ~uname:conf.uname ~pwd:conf.pwd conf conf.hosts)
100+
101+
let run conf =
102+
ensure_vhost_nics conf
103+
>>= fun () ->
104+
ensure_vhosts_on conf
105+
>>= fun () ->
106+
(* Test_sr.destroy_pools ~uname:conf.uname ~pwd:conf.pwd conf.hosts :
107+
>>= fun () ->*)
108+
ensure_bonding_on_master conf
109+
>>= fun ()->
110+
do_prepare conf

src/cmd_lwt.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,8 @@ let run ~common ~sdocs ~exits =
120120
let doc = "Run tests in a prepared environment" in
121121
let main () config skip_serial tests = lwt_main config (fun conf -> run_tests conf skip_serial tests) in
122122
(Term.(const main $ common $ config $ skip_serial $ tests), Term.info "run" ~doc ~sdocs ~exits)
123+
124+
let bonding ~common ~sdocs ~exits =
125+
let doc = "Run bonding tests" in
126+
let main () config = lwt_main config Cmd_bonding.run in
127+
Term.(const main $ common $ config), Term.info "bonding" ~doc ~sdocs ~exits

src/main.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,6 @@ let () =
6464
; Cmd_lwt.prepare ~sdocs ~exits ~common
6565
; Cmd_lwt.rollback ~sdocs ~exits ~common
6666
; Cmd_init.list ~sdocs ~exits ~common
67-
; Cmd_lwt.run ~sdocs ~exits ~common ])
67+
; Cmd_lwt.run ~sdocs ~exits ~common
68+
; Cmd_lwt.bonding ~sdocs ~exits ~common
69+
])

0 commit comments

Comments
 (0)