From 85ca00d6ade4029aa02b3ac93c36f7f7848d200e Mon Sep 17 00:00:00 2001 From: David Scott Date: Fri, 1 May 2015 14:04:30 +0100 Subject: [PATCH] lvresize,lvextend: default to resizing offline unless '--live' is provided The live incremental allocations will call 'xenvm lvextend --live' to ensure that communication is peformed via the shared block ring. The offline regular control-plane resize will use RPC to the master, destroying and recreating the device mapper device. Signed-off-by: David Scott --- xenvm/lvchange.ml | 52 +++++++++++++++++++++++++++-------------------- xenvm/lvresize.ml | 46 +++++++++++++++++++++++++++++------------ 2 files changed, 63 insertions(+), 35 deletions(-) diff --git a/xenvm/lvchange.ml b/xenvm/lvchange.ml index 1cf6374..c4a37b6 100644 --- a/xenvm/lvchange.ml +++ b/xenvm/lvchange.ml @@ -10,6 +10,22 @@ type action = Activate | Deactivate let dev_path_of vg_name lv_name = Printf.sprintf "/dev/%s/%s" vg_name lv_name +let activate vg lv local_device = + let path = dev_path_of vg.Lvm.Vg.name lv.Lvm.Lv.name in + Lwt.catch (fun () -> Lwt_unix.mkdir (Filename.dirname path) 0x755) (fun _ -> Lwt.return ()) >>= fun () -> + Mapper.read [ local_device ] + >>= fun devices -> + let targets = Mapper.to_targets devices vg lv in + let name = Mapper.name_of vg lv in + (* Don't recreate it if it already exists *) + let all = Devmapper.ls () in + if not(List.mem name all) + then Devmapper.create name targets; + (* Recreate the device node *) + Lwt.catch (fun () -> Lwt_unix.unlink path) (fun _ -> Lwt.return ()) >>= fun () -> + Devmapper.mknod name path 0o0600; + return () + let lvchange_activate copts vg_name lv_name physical_device = let open Xenvm_common in Lwt_main.run ( @@ -22,20 +38,18 @@ let lvchange_activate copts vg_name lv_name physical_device = | Some info, None -> info.local_device (* If we've got a default, use that *) | None, None -> failwith "Need to know the local device!" in - let path = dev_path_of vg_name lv_name in - Lwt.catch (fun () -> Lwt_unix.mkdir (Filename.dirname path) 0x755) (fun _ -> Lwt.return ()) >>= fun () -> - Mapper.read [ local_device ] - >>= fun devices -> - let targets = Mapper.to_targets devices vg lv in - let name = Mapper.name_of vg lv in - (* Don't recreate it if it already exists *) - let all = Devmapper.ls () in - if not(List.mem name all) - then Devmapper.create name targets; - (* Recreate the device node *) - Lwt.catch (fun () -> Lwt_unix.unlink path) (fun _ -> Lwt.return ()) >>= fun () -> - Devmapper.mknod name path 0o0600; - return ()) + activate vg lv local_device + ) + +let deactivate vg lv = + let name = Mapper.name_of vg lv in + let all = Devmapper.ls () in + if List.mem name all + then Devmapper.remove name; + (* Delete the device node *) + let path = dev_path_of vg.Lvm.Vg.name lv.Lvm.Lv.name in + Lwt.catch (fun () -> Lwt_unix.unlink path) (fun _ -> Lwt.return ()) >>= fun () -> + return () let lvchange_deactivate copts vg_name lv_name = let open Xenvm_common in @@ -43,14 +57,8 @@ let lvchange_deactivate copts vg_name lv_name = get_vg_info_t copts vg_name >>= fun info -> set_uri copts info; Client.get_lv ~name:lv_name >>= fun (vg, lv) -> - let name = Mapper.name_of vg lv in - let all = Devmapper.ls () in - if List.mem name all - then Devmapper.remove name; - (* Delete the device node *) - let path = dev_path_of vg_name lv_name in - Lwt.catch (fun () -> Lwt_unix.unlink path) (fun _ -> Lwt.return ()) >>= fun () -> - return ()) + deactivate vg lv + ) let lvchange copts (vg_name,lv_name_opt) physical_device action perm = let lv_name = match lv_name_opt with Some l -> l | None -> failwith "Need LV name" in diff --git a/xenvm/lvresize.ml b/xenvm/lvresize.ml index 8f134a6..605ef6c 100644 --- a/xenvm/lvresize.ml +++ b/xenvm/lvresize.ml @@ -3,22 +3,41 @@ open Cmdliner open Lwt -let lvresize copts (vg_name,lv_opt) real_size percent_size = +let lvresize copts live (vg_name,lv_opt) real_size percent_size = let lv_name = match lv_opt with | Some l -> l | None -> failwith "Need an LV name" in let open Xenvm_common in let size = match parse_size real_size percent_size with | `IncreaseBy x -> `IncreaseBy x | `Absolute x -> `Absolute x | `DecreaseBy _ -> failwith "Shrinking volumes not supported" in + Lwt_main.run ( get_vg_info_t copts vg_name >>= fun info -> set_uri copts info; Client.get_lv ~name:lv_name >>= fun (vg, lv) -> if vg.Lvm.Vg.name <> vg_name then failwith "Invalid VG name"; + let local_device = match info with + | Some info -> info.local_device (* If we've got a default, use that *) + | None -> failwith "Need to know the local device!" in - let resize_remotely () = match size with - | `Absolute size -> Client.resize lv_name size - | `IncreaseBy delta -> Client.resize lv_name Int64.(add delta (mul (mul 512L vg.Lvm.Vg.extent_size) (Lvm.Lv.size_in_extents lv))) in + let device_is_active = + let name = Mapper.name_of vg lv in + let all = Devmapper.ls () in + List.mem name all in + + let resize_remotely () = + ( if device_is_active + then Lvchange.deactivate vg lv + else return () ) + >>= fun () -> + ( match size with + | `Absolute size -> Client.resize lv_name size + | `IncreaseBy delta -> Client.resize lv_name Int64.(add delta (mul (mul 512L vg.Lvm.Vg.extent_size) (Lvm.Lv.size_in_extents lv))) ) + >>= fun () -> + ( if device_is_active then begin + Client.get_lv ~name:lv_name >>= fun (vg, lv) -> + Lvchange.activate vg lv local_device + end else return () ) in let resize_locally allocator = let name = Mapper.name_of vg lv in @@ -31,26 +50,27 @@ let lvresize copts (vg_name,lv_opt) real_size percent_size = >>= fun () -> Lwt_io.close oc in - match info with - | Some { Xenvm_common.local_allocator_path = Some allocator } -> - let name = Mapper.name_of vg lv in - let all = Devmapper.ls () in - (* An active device with local allocator running must be resized locally *) - if List.mem name all + match live, info with + | true, Some { Xenvm_common.local_allocator_path = Some allocator } -> + if device_is_active then resize_locally allocator else resize_remotely () - | _ -> + | _, _ -> (* safe to allocate remotely *) resize_remotely () ) +let live_arg = + let doc = "Resize a live device using the local allocator" in + Arg.(value & flag & info ["live"] ~doc) + let lvresize_cmd = let doc = "Resize a logical volume" in let man = [ `S "DESCRIPTION"; `P "lvresize will resize an existing logical volume."; ] in - Term.(pure lvresize $ Xenvm_common.copts_t $ Xenvm_common.name_arg $ Xenvm_common.real_size_arg $ Xenvm_common.percent_size_arg), + Term.(pure lvresize $ Xenvm_common.copts_t $ live_arg $ Xenvm_common.name_arg $ Xenvm_common.real_size_arg $ Xenvm_common.percent_size_arg), Term.info "lvresize" ~sdocs:"COMMON OPTIONS" ~doc ~man let lvextend_cmd = @@ -59,5 +79,5 @@ let lvextend_cmd = `S "DESCRIPTION"; `P "lvextend will resize an existing logical volume."; ] in - Term.(pure lvresize $ Xenvm_common.copts_t $ Xenvm_common.name_arg $ Xenvm_common.real_size_arg $ Xenvm_common.percent_size_arg), + Term.(pure lvresize $ Xenvm_common.copts_t $ live_arg $ Xenvm_common.name_arg $ Xenvm_common.real_size_arg $ Xenvm_common.percent_size_arg), Term.info "lvextend" ~sdocs:"COMMON OPTIONS" ~doc ~man