Skip to content

Commit bbd6e1f

Browse files
committed
Merge pull request #113 from xapi-project/creation_time
Print nice error messages if out of space
2 parents df8c967 + de6e02a commit bbd6e1f

File tree

8 files changed

+90
-9
lines changed

8 files changed

+90
-9
lines changed

idl/errors.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ open Lwt
1616
let (>>*=) m f = match m with
1717
| `Error (`Msg e) -> fail (Failure e)
1818
| `Error (`DuplicateLV lv) -> fail (Failure (Printf.sprintf "An LV with name %s already exists" lv))
19-
| `Error (`OnlyThisMuchFree space) -> fail (Failure (Printf.sprintf "Only this much space is available: %Ld" space))
19+
| `Error (`OnlyThisMuchFree (needed, available)) -> fail (Xenvm_interface.Insufficient_free_space(needed, available))
2020
| `Error (`UnknownLV lv) -> fail (Failure (Printf.sprintf "The LV with name %s was not found" lv))
2121
| `Ok x -> f x
2222
let (>>|=) m f = m >>= fun x -> x >>*= f

idl/xenvm_interface.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ external get : unit -> Vg_wrapper.t = ""
1313
external create : name:string -> size:int64 -> creation_host:string -> creation_time:int64 -> tags:string list -> unit = ""
1414
external rename : oldname:string -> newname:string -> unit = ""
1515
external remove : name:string -> unit = ""
16+
17+
exception Insufficient_free_space of (int64 (* extents needed *) * int64 (* extents available *))
18+
(** There's not enough space to create or resize the LV *)
19+
1620
external resize : name:string -> size:int64 -> unit = ""
1721
external set_status : name:string -> readonly:bool -> unit = ""
1822

test/test.ml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,62 @@ let lvcreate_percent =
9696
assert_equal ~printer:Int64.to_string 0L free;
9797
xenvm [ "lvremove"; vg ^ "/test" ] |> ignore_string
9898

99+
let kib = 1024L
100+
let mib = Int64.mul kib 1024L
101+
let gib = Int64.mul mib 1024L
102+
let tib = Int64.mul mib 1024L
103+
let xib = Int64.mul tib 1024L
104+
105+
let contains s1 s2 =
106+
let re = Str.regexp_string s2 in
107+
try
108+
ignore (Str.search_forward re s1 0);
109+
true
110+
with Not_found -> false
111+
112+
let lvcreate_toobig =
113+
"lvcreate -n <name> -l <too many>: check that we fail nicely" >::
114+
fun () ->
115+
Lwt_main.run (
116+
Lwt.catch
117+
(fun () -> Client.create "toobig" xib "unknown" 0L [])
118+
(function Xenvm_interface.Insufficient_free_space(needed, available) -> return ()
119+
| e -> failwith (Printf.sprintf "Did not get Insufficient_free_space: %s" (Printexc.to_string e)))
120+
);
121+
try
122+
xenvm [ "lvcreate"; "-n"; "test"; "-l"; Int64.to_string xib; vg ] |> ignore_string;
123+
failwith "Did not get Insufficient_free_space"
124+
with
125+
| Bad_exit(5, _, _, stdout, stderr) ->
126+
let expected = "insufficient free space" in
127+
if not (contains stderr expected)
128+
then failwith (Printf.sprintf "stderr [%s] did not have expected string [%s]" stderr expected)
129+
| _ ->
130+
failwith "Expected exit code 5"
131+
132+
let lvextend_toobig =
133+
"lvextend packer-virtualbox-iso-vg/swap_1 -L 1T: check that the failure is nice" >::
134+
fun () ->
135+
xenvm [ "lvcreate"; "-n"; "test"; "-l"; "100%F"; vg ] |> ignore_string;
136+
begin
137+
Lwt_main.run (
138+
Lwt.catch
139+
(fun () -> Client.resize "test" xib)
140+
(function Xenvm_interface.Insufficient_free_space(needed, available) -> return ()
141+
| e -> failwith (Printf.sprintf "Did not get Insufficient_free_space: %s" (Printexc.to_string e)))
142+
);
143+
try
144+
xenvm [ "lvextend"; vg ^ "/test"; "-L"; Int64.to_string xib ] |> ignore_string;
145+
failwith "Did not get Insufficient_free_space"
146+
with
147+
| Bad_exit(5, _, _, stdout, stderr) ->
148+
let expected = "Insufficient free space" in
149+
if not (contains stderr expected)
150+
then failwith (Printf.sprintf "stderr [%s] did not have expected string [%s]" stderr expected)
151+
| e ->
152+
failwith (Printf.sprintf "Expected exit code 5: %s" (Printexc.to_string e))
153+
end;
154+
xenvm [ "lvremove"; vg ^ "/test" ] |> ignore_string
99155

100156
let file_exists filename =
101157
try
@@ -154,7 +210,9 @@ let xenvmd_suite = "Commands which require xenvmd" >::: [
154210
lvcreate_L;
155211
lvcreate_l;
156212
lvcreate_percent;
213+
lvcreate_toobig;
157214
lvchange_n;
215+
lvextend_toobig;
158216
vgs_online;
159217
]
160218

xenvm-local-allocator/local_allocator.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,11 @@ module FreePool = struct
165165
| `Ok x ->
166166
free := Lvm.Pv.Allocator.sub !free x;
167167
return x
168-
| `Error (`OnlyThisMuchFree 0L) ->
168+
| `Error (`OnlyThisMuchFree (_, 0L)) ->
169169
Lwt_condition.wait ~mutex:m c
170170
>>= fun () ->
171171
wait ()
172-
| `Error (`OnlyThisMuchFree n) ->
172+
| `Error (`OnlyThisMuchFree (_, n)) ->
173173
begin match Lvm.Pv.Allocator.find !free n with
174174
| `Ok x ->
175175
free := Lvm.Pv.Allocator.sub !free x;

xenvm/lvcreate.ml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,15 @@ let lvcreate copts lv_name real_size percent_size tags vg_name =
2525
if vg.Lvm.Vg.name <> vg_name then failwith "Invalid VG name";
2626
let creation_host = Unix.gethostname () in
2727
let creation_time = Unix.gettimeofday () |> Int64.of_float in
28-
Client.create lv_name size creation_host creation_time tags >>= fun () ->
28+
Lwt.catch
29+
(fun () ->
30+
Client.create lv_name size creation_host creation_time tags
31+
) (function
32+
| Xenvm_interface.Insufficient_free_space(needed, available) ->
33+
Printf.fprintf Pervasives.stderr "Volume group \"%s\" has insufficient free space (%Ld extents): %Ld required.\n%!" vg.Lvm.Vg.name available needed;
34+
exit 5
35+
| e -> fail e
36+
) >>= fun () ->
2937
return info) in
3038
match info with | Some i -> Lvchange.lvchange_activate copts vg_name lv_name (Some i.local_device) | None -> ()
3139

xenvm/lvresize.ml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,20 @@ let lvresize copts live (vg_name,lv_opt) real_size percent_size =
3232

3333
let resize_remotely () =
3434
if device_is_active then Devmapper.suspend name;
35-
( match size with
36-
| `Absolute size -> Client.resize lv_name size
37-
| `IncreaseBy delta -> Client.resize lv_name Int64.(add delta (mul (mul 512L vg.Lvm.Vg.extent_size) (Lvm.Lv.size_in_extents lv))) )
35+
Lwt.catch
36+
(fun () ->
37+
match size with
38+
| `Absolute size -> Client.resize lv_name size
39+
| `IncreaseBy delta -> Client.resize lv_name Int64.(add delta (mul (mul 512L vg.Lvm.Vg.extent_size) (Lvm.Lv.size_in_extents lv)))
40+
) (function
41+
| Xenvm_interface.Insufficient_free_space(needed, available) ->
42+
Printf.fprintf Pervasives.stderr "Insufficient free space: %Ld extents needed, but only %Ld available\n%!" needed available;
43+
if device_is_active then Devmapper.resume name;
44+
exit 5
45+
| e ->
46+
if device_is_active then Devmapper.resume name;
47+
fail e
48+
)
3849
>>= fun () ->
3950
if device_is_active then begin
4051
Client.get_lv ~name:lv_name >>= fun (vg, lv) ->

xenvm/xenvm_common.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ let print_table noheadings header rows =
462462
let (>>*=) m f = match m with
463463
| `Error (`Msg e) -> fail (Failure e)
464464
| `Error (`DuplicateLV x) -> fail (Failure (Printf.sprintf "%s is a duplicate LV name" x))
465-
| `Error (`OnlyThisMuchFree x) -> fail (Failure (Printf.sprintf "There is only %Ld free" x))
465+
| `Error (`OnlyThisMuchFree (needed, available)) -> fail (Xenvm_interface.Insufficient_free_space(needed, available))
466466
| `Error (`UnknownLV x) -> fail (Failure (Printf.sprintf "I couldn't find an LV named %s" x))
467467
| `Ok x -> f x
468468

xenvmd/xenvmd.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ module FreePool = struct
541541
freename size_mib config.Config.host_low_water_mark config.Config.host_allocation_quantum;
542542
(* find free space in the VG *)
543543
begin match !journal, Lvm.Pv.Allocator.find x.Lvm.Vg.free_space Int64.(div config.Config.host_allocation_quantum extent_size_mib) with
544-
| _, `Error (`OnlyThisMuchFree free_extents) ->
544+
| _, `Error (`OnlyThisMuchFree (needed_extents, free_extents)) ->
545545
info "LV %s is %Ld MiB but total space free (%Ld MiB) is less than allocation quantum (%Ld MiB)"
546546
freename size_mib Int64.(mul free_extents extent_size_mib) config.Config.host_allocation_quantum;
547547
(* try again later *)

0 commit comments

Comments
 (0)