From 02d55960436948e81f1a7f11e8eb7a0dcdb6c007 Mon Sep 17 00:00:00 2001 From: David Scott Date: Tue, 26 May 2015 16:06:50 +0000 Subject: [PATCH 1/3] local allocator: support the same --mock-devmapper argument as xenvm This will allow us to write test cases involving the local allocator too. Signed-off-by: David Scott --- xenvm-local-allocator/local_allocator.ml | 51 ++++++++++++++---------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/xenvm-local-allocator/local_allocator.ml b/xenvm-local-allocator/local_allocator.ml index 79de4b6..4f6cfe0 100644 --- a/xenvm-local-allocator/local_allocator.ml +++ b/xenvm-local-allocator/local_allocator.ml @@ -19,6 +19,8 @@ module Time = struct let sleep = Lwt_unix.sleep end +let dm = ref (module Devmapper.Linux : Devmapper.S.DEVMAPPER) + let journal_size = Int64.(mul 4L (mul 1024L 1024L)) let rec try_forever msg f = @@ -242,21 +244,19 @@ module Op = struct end (* Return the virtual size of the volume *) -let sizeof volume = +let sizeof dm_targets = let open Devmapper in - let open Devmapper.Linux in - let ends = List.map (fun t -> Int64.add t.Target.start t.Target.size) volume.targets in + let ends = List.map (fun t -> Int64.add t.Target.start t.Target.size) dm_targets in List.fold_left max 0L ends (* Compute the new segments and device mapper targets if [extents] are appended onto [lv] *) -let extend_volume device vg lv extents = +let extend_volume device vg existing_targets extents = let open Lvm in let to_sector pv segment = Int64.(add pv.Pv.pe_start (mul segment vg.Vg.extent_size)) in (* We will extend the LV, so find the next 'virtual segment' *) - let next_sector = sizeof lv in + let next_sector = sizeof existing_targets in let _, segments, targets = let open Devmapper in - let open Devmapper.Linux in List.fold_left (fun (next_sector, segments, targets) (pvname, (psegment, size)) -> try @@ -282,14 +282,15 @@ let extend_volume device vg lv extents = ) (next_sector, [], []) extents in List.rev segments, List.rev targets -let stat x = - match Devmapper.Linux.stat x with - | Some x -> return (`Ok x) +let targets_of x = + let module D = (val !dm: Devmapper.S.DEVMAPPER) in + match D.stat x with + | Some x -> return (`Ok x.D.targets) | None -> error "The device mapper device %s has disappeared." x; return (`Error `Retry) -let main config daemon socket journal fromLVM toLVM = +let main use_mock config daemon socket journal fromLVM toLVM = let config = Config.t_of_sexp (Sexplib.Sexp.load_sexp config) in let config = { config with Config.socket = (match socket with None -> config.Config.socket | Some x -> x); @@ -298,6 +299,10 @@ let main config daemon socket journal fromLVM toLVM = fromLVM = (match fromLVM with None -> config.Config.fromLVM | Some x -> x); } in debug "Loaded configuration: %s" (Sexplib.Sexp.to_string_hum (Config.sexp_of_t config)); + dm := if use_mock then (module Devmapper.Mock: Devmapper.S.DEVMAPPER) else (module Devmapper.Linux: Devmapper.S.DEVMAPPER); + + let module D = (val !dm: Devmapper.S.DEVMAPPER) in + if daemon then Lwt_daemon.daemonize (); Pidfile.write_pid (config.Config.socket ^ ".lock"); @@ -352,18 +357,18 @@ let main config daemon socket journal fromLVM toLVM = ToLVM.push tolvm t.volume >>= fun position -> let msg = Printf.sprintf "Querying dm device %s" t.device.ExpandDevice.device in - try_forever msg (fun () -> stat t.device.ExpandDevice.device) + try_forever msg (fun () -> targets_of t.device.ExpandDevice.device) >>= fun x -> fatal_error msg (return x) - >>= fun to_device -> + >>= fun to_device_targets -> (* Append the physical blocks to toLV *) - let to_targets = to_device.Devmapper.Linux.targets @ t.device.ExpandDevice.targets in - Devmapper.Linux.suspend t.device.ExpandDevice.device; + let to_targets = to_device_targets @ t.device.ExpandDevice.targets in + D.suspend t.device.ExpandDevice.device; print_endline "Suspend local dm device"; - Devmapper.Linux.reload t.device.ExpandDevice.device to_targets; + D.reload t.device.ExpandDevice.device to_targets; ToLVM.advance tolvm position >>= fun () -> - Devmapper.Linux.resume t.device.ExpandDevice.device; + D.resume t.device.ExpandDevice.device; print_endline "Resume local dm device"; return () ) ops @@ -404,7 +409,7 @@ let main config daemon socket journal fromLVM toLVM = Lwt_mutex.with_lock m (fun () -> (* We may need to enlarge in multiple chunks if the free pool is depleted *) - let rec expand action = match Devmapper.Linux.stat device with + let rec expand action = match D.stat device with | None -> (* Log this kind of error. This tapdisk may block but at least others will keep going *) @@ -412,7 +417,7 @@ let main config daemon socket journal fromLVM toLVM = return (ResizeResponse.Device_mapper_device_does_not_exist device) | Some data_volume -> let sector_size = Int64.of_int sector_size in - let current = Int64.mul sector_size (sizeof data_volume) in + let current = Int64.mul sector_size (sizeof data_volume.D.targets) in let extent_b = Int64.mul sector_size extent_size in (* NB: make sure we round up to the next extent *) let nr_extents = match action with @@ -428,7 +433,7 @@ let main config daemon socket journal fromLVM toLVM = >>= fun extents -> (* This may have allocated short *) let nr_extents' = Lvm.Pv.Allocator.size extents in - let segments, targets = extend_volume vg_device metadata data_volume extents in + let segments, targets = extend_volume vg_device metadata data_volume.D.targets extents in let _, volume = Mapper.vg_lv_of_name device in let volume = { ExpandVolume.volume; segments } in let device = { ExpandDevice.extents; device; targets } in @@ -448,7 +453,7 @@ let main config daemon socket journal fromLVM toLVM = expand action ) in - let ls = Devmapper.Linux.ls () in + let ls = D.ls () in debug "Visible device mapper devices: [ %s ]\n%!" (String.concat "; " ls); let rec stdin () = @@ -533,8 +538,12 @@ let fromLVM = let doc = "Path to the device or file which contains new free blocks from LVM" in Arg.(value & opt (some file) None & info [ "fromLVM" ] ~docv:"FROMLVM" ~doc) +let mock_dm_arg = + let doc = "Enable mock interfaces on device mapper." in + Arg.(value & flag & info ["mock-devmapper"] ~doc) + let () = - let t = Term.(pure main $ config $ daemon $ socket $ journal $ fromLVM $ toLVM) in + let t = Term.(pure main $ mock_dm_arg $ config $ daemon $ socket $ journal $ fromLVM $ toLVM) in match Term.eval (t, info) with | `Error _ -> exit 1 | _ -> exit 0 From 7b5b72b0dfbd589514722555311217c3f0ffdd14 Mon Sep 17 00:00:00 2001 From: David Scott Date: Tue, 26 May 2015 16:23:43 +0000 Subject: [PATCH 2/3] setup.sh: allow to be run as non-root If we are running as root: we use real device mapper. If we are not running as root: we use the mock device mapper. Signed-off-by: David Scott --- setup.sh | 59 +++++++++++++++++++++--------------- test.local_allocator.conf.in | 4 +-- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/setup.sh b/setup.sh index db60e4a..d66d81b 100755 --- a/setup.sh +++ b/setup.sh @@ -8,55 +8,64 @@ set -x # already included in the RPM. if [ "$EUID" -ne "0" ]; then - echo "Please run me as uid 0. I need to create a loop device and device mapper devices" - exit 1 + echo "I am not running with EUID 0. I will use the mock device mapper interface" + USE_MOCK=1 + MOCK_ARG="--mock-devmapper" +else + echo "I am running with EUID 0. I will use the real device mapper interface" + USE_MOCK=0 + MOCK_ARG="" fi # Making a 1G disk -rm -f bigdisk _build/xenvm*.out +rm -f bigdisk dd if=/dev/zero of=bigdisk bs=1 seek=256G count=0 -LOOP=$(losetup -f) -echo Using $LOOP -losetup $LOOP bigdisk +if [ "$USE_MOCK" -eq "0" ]; then + LOOP=$(losetup -f) + echo Using $LOOP + losetup $LOOP bigdisk +else + LOOP=`pwd`/bigdisk +fi cat test.xenvmd.conf.in | sed -r "s|@BIGDISK@|$LOOP|g" > test.xenvmd.conf -mkdir -p /etc/xenvm.d -BISECT_FILE=_build/xenvm.coverage ./xenvm.native format $LOOP --vg djstest +mkdir -p /tmp/xenvm.d +BISECT_FILE=_build/xenvm.coverage ./xenvm.native format $LOOP --vg djstest --configdir /tmp/xenvm.d $MOCK_ARG BISECT_FILE=_build/xenvmd.coverage ./xenvmd.native --config ./test.xenvmd.conf --daemon export BISECT_FILE=_build/xenvm.coverage -./xenvm.native set-vg-info --pvpath $LOOP -S /tmp/xenvmd djstest --local-allocator-path /tmp/xenvm-local-allocator --uri file://local/services/xenvmd/djstest +./xenvm.native set-vg-info --pvpath $LOOP -S /tmp/xenvmd djstest --local-allocator-path /tmp/xenvm-local-allocator --uri file://local/services/xenvmd/djstest --configdir /tmp/xenvm.d $MOCK_ARG -./xenvm.native lvcreate -n live -L 4 djstest -./xenvm.native lvchange -ay /dev/djstest/live +./xenvm.native lvcreate -n live -L 4 djstest --configdir /tmp/xenvm.d $MOCK_ARG +./xenvm.native lvchange -ay /dev/djstest/live --configdir /tmp/xenvm.d $MOCK_ARG #./xenvm.native benchmark # create and connect to hosts -./xenvm.native host-create /dev/djstest host1 -./xenvm.native host-connect /dev/djstest host1 +./xenvm.native host-create /dev/djstest host1 --configdir /tmp/xenvm.d $MOCK_ARG +./xenvm.native host-connect /dev/djstest host1 --configdir /tmp/xenvm.d $MOCK_ARG cat test.local_allocator.conf.in | sed -r "s|@BIGDISK@|$LOOP|g" | sed -r "s|@HOST@|host1|g" > test.local_allocator.host1.conf -./local_allocator.native --config ./test.local_allocator.host1.conf > /dev/null & +./local_allocator.native --config ./test.local_allocator.host1.conf $MOCK_ARG > /dev/null & -./xenvm.native host-create /dev/djstest host2 -./xenvm.native host-connect /dev/djstest host2 +./xenvm.native host-create /dev/djstest host2 --configdir /tmp/xenvm.d $MOCK_ARG +./xenvm.native host-connect /dev/djstest host2 --configdir /tmp/xenvm.d $MOCK_ARG cat test.local_allocator.conf.in | sed -r "s|@BIGDISK@|$LOOP|g" | sed -r "s|@HOST@|host2|g" > test.local_allocator.host2.conf -./local_allocator.native --config ./test.local_allocator.host2.conf > /dev/null & +./local_allocator.native --config ./test.local_allocator.host2.conf $MOCK_ARG > /dev/null & sleep 30 -./xenvm.native host-list /dev/djstest +./xenvm.native host-list /dev/djstest --configdir /tmp/xenvm.d $MOCK_ARG # destroy hosts -./xenvm.native host-disconnect /dev/djstest host2 -./xenvm.native host-destroy /dev/djstest host2 -./xenvm.native host-disconnect /dev/djstest host1 -./xenvm.native host-destroy /dev/djstest host1 +./xenvm.native host-disconnect /dev/djstest host2 --configdir /tmp/xenvm.d $MOCK_ARG +./xenvm.native host-destroy /dev/djstest host2 --configdir /tmp/xenvm.d $MOCK_ARG +./xenvm.native host-disconnect /dev/djstest host1 --configdir /tmp/xenvm.d $MOCK_ARG +./xenvm.native host-destroy /dev/djstest host1 --configdir /tmp/xenvm.d $MOCK_ARG -./xenvm.native host-list /dev/djstest +./xenvm.native host-list /dev/djstest --configdir /tmp/xenvm.d $MOCK_ARG #shutdown -./xenvm.native lvchange -an /dev/djstest/live || true -./xenvm.native shutdown /dev/djstest +./xenvm.native lvchange -an /dev/djstest/live --configdir /tmp/xenvm.d $MOCK_ARG || true +./xenvm.native shutdown /dev/djstest --configdir /tmp/xenvm.d $MOCK_ARG #echo Run 'sudo ./xenvm.native host-connect /dev/djstest host1' to connect to the local allocator' #echo Run 'sudo ./local_allocator.native' and type 'djstest-live' to request an allocation diff --git a/test.local_allocator.conf.in b/test.local_allocator.conf.in index a86f540..c3d0a22 100644 --- a/test.local_allocator.conf.in +++ b/test.local_allocator.conf.in @@ -1,7 +1,7 @@ ( - (socket @HOST@-socket) + (socket /tmp/@HOST@-socket) (allocation_quantum 16) - (localJournal localJournal) + (localJournal /tmp/@HOST@-localJournal) (devices (@BIGDISK@)) (toLVM @HOST@-toLVM) (fromLVM @HOST@-fromLVM) From 5d05350b217f2904c5f8fecaa064e6fc8f9e1e31 Mon Sep 17 00:00:00 2001 From: David Scott Date: Tue, 26 May 2015 16:28:00 +0000 Subject: [PATCH 3/3] travis: run both test suites and measure coverage We have 2 small test suites which test different things: - test/test.ml: checks LV-level operations - setup.sh: uses the local allocator Signed-off-by: David Scott --- .travis.sh | 3 +++ setup.sh | 6 ++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.sh b/.travis.sh index 338ad72..a41991d 100755 --- a/.travis.sh +++ b/.travis.sh @@ -5,7 +5,10 @@ eval `opam config env` export BISECT_FILE=_build/xenvm.coverage # Needed to support Unix domain sockets: sudo opam pin add conduit git://github.com/mirage/ocaml-conduit -y +# run the OCaml test suite make test +# run the bash test suite +./setup.sh echo Generating bisect report-- this fails on travis (cd _build; bisect-report xenvm*.out -summary-only -html /vagrant/report/ || echo Ignoring bisect-report failure) diff --git a/setup.sh b/setup.sh index d66d81b..b310e04 100755 --- a/setup.sh +++ b/setup.sh @@ -30,10 +30,8 @@ else fi cat test.xenvmd.conf.in | sed -r "s|@BIGDISK@|$LOOP|g" > test.xenvmd.conf mkdir -p /tmp/xenvm.d -BISECT_FILE=_build/xenvm.coverage ./xenvm.native format $LOOP --vg djstest --configdir /tmp/xenvm.d $MOCK_ARG -BISECT_FILE=_build/xenvmd.coverage ./xenvmd.native --config ./test.xenvmd.conf --daemon - -export BISECT_FILE=_build/xenvm.coverage +./xenvm.native format $LOOP --vg djstest --configdir /tmp/xenvm.d $MOCK_ARG +./xenvmd.native --config ./test.xenvmd.conf --daemon ./xenvm.native set-vg-info --pvpath $LOOP -S /tmp/xenvmd djstest --local-allocator-path /tmp/xenvm-local-allocator --uri file://local/services/xenvmd/djstest --configdir /tmp/xenvm.d $MOCK_ARG