X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;ds=sidebyside;f=virt-df%2Fvirt_df_main.ml;h=65d1f2fc76afb401ee3b00394744de0abc2110ab;hb=0bdb08c61ec66a16a81c2778a2a76cac77b08fda;hp=c989d767a6efec25005144233c59c48d9db80378;hpb=40c683ea4c9d921a6fe23c2639125261b92da472;p=virt-top.git diff --git a/virt-df/virt_df_main.ml b/virt-df/virt_df_main.ml index c989d76..65d1f2f 100644 --- a/virt-df/virt_df_main.ml +++ b/virt-df/virt_df_main.ml @@ -54,6 +54,8 @@ let () = "uri " ^ s_ "Connect to URI (default: Xen)"; "--connect", Arg.String set_uri, "uri " ^ s_ "Connect to URI (default: Xen)"; + "--debug", Arg.Set debug, + " " ^ s_ "Debug mode (default: false)"; "-h", Arg.Set human, " " ^ s_ "Print sizes in human-readable format"; "--human-readable", Arg.Set human, @@ -63,7 +65,7 @@ let () = "--inodes", Arg.Set inodes, " " ^ s_ "Show inodes instead of blocks"; "-t", Arg.String test_mode, - "dev" ^ s_ "(Test mode) Display contents of block device or file"; + "dev " ^ s_ "(Test mode) Display contents of block device or file"; "--version", Arg.Unit version, " " ^ s_ "Display version and exit"; ] in @@ -223,7 +225,8 @@ OPTIONS" in | _ -> None ) devices in - { dom_name = name; dom_id = domid; dom_disks = disks } + { dom_name = name; dom_id = domid; + dom_disks = disks; dom_lv_filesystems = [] } ) xmls ) else ( (* In test mode (-t option) the user can pass one or more @@ -241,7 +244,8 @@ OPTIONS" in d_source = filename; d_target = "hda"; d_dev = new block_device filename; d_content = `Unknown; } - ] + ]; + dom_lv_filesystems = [] } ) !test_files ) in @@ -311,13 +315,76 @@ OPTIONS" in | disk -> disk ) in - (* XXX LVM filesystem detection ... *) - - - - - - (* Print the title. *) + (* LVM filesystem detection + * + * For each domain, look for all disks/partitions which have been + * identified as PVs and pass those back to the respective LVM + * plugin for LV detection. + * + * (Note - a two-stage process because an LV can be spread over + * several PVs, so we have to detect all PVs belonging to a + * domain first). + * + * XXX To deal with RAID (ie. md devices) we will need to loop + * around here because RAID is like LVM except that they normally + * present as block devices which can be used by LVM. + *) + (* First: LV detection. *) + let doms = List.map ( + fun ({ dom_disks = disks } as dom) -> + (* Find all physical volumes, can be disks or partitions. *) + let pvs_on_disks = List.filter_map ( + function + | { d_dev = d_dev; + d_content = `PhysicalVolume pv } -> Some (pv, d_dev) + | _ -> None + ) disks in + let pvs_on_partitions = List.map ( + function + | { d_content = `Partitions { parts = parts } } -> + List.filter_map ( + function + | { part_dev = part_dev; + part_content = `PhysicalVolume pv } -> + Some (pv, part_dev) + | _ -> None + ) parts + | _ -> [] + ) disks in + let lvs = List.concat (pvs_on_disks :: pvs_on_partitions) in + dom, lvs + ) doms in + + (* Second: filesystem on LV detection. *) + let doms = List.map ( + fun (dom, lvs) -> + (* Group the LVs by plug-in type. *) + let cmp (a,_) (b,_) = compare a b in + let lvs = List.sort ~cmp lvs in + let lvs = group_by lvs in + + let lvs = + List.map (fun (pv, devs) -> list_lvs pv.lvm_plugin_id devs) lvs in + let lvs = List.concat lvs in + + (* lvs is a list of potential LV devices. Now run them through the + * probes to see if any contain filesystems. + *) + let filesystems = + List.filter_map ( + fun ({ lv_dev = dev } as lv) -> + match probe_for_filesystem dev with + | Some fs -> Some (lv, fs) + | None -> None + ) lvs in + + { dom with dom_lv_filesystems = filesystems } + ) doms in + + (* Now print the results. + * + * Print the title. + *) let () = let total, used, avail = match !inodes, !human with @@ -337,37 +404,49 @@ OPTIONS" in in (* HOF to iterate over filesystems. *) - let iter_over_filesystems doms f = + let iter_over_filesystems doms + (f : domain -> ?disk:disk -> ?partno:int -> device -> filesystem -> + unit) = List.iter ( - fun ({ dom_disks = disks } as dom) -> + fun ({ dom_disks = disks; dom_lv_filesystems = filesystems } as dom) -> + (* Ordinary filesystems found on disks & partitions. *) List.iter ( function - | ({ d_content = `Filesystem fs } as disk) -> - f dom disk None fs + | ({ d_content = `Filesystem fs; d_dev = dev } as disk) -> + f dom ~disk dev fs | ({ d_content = `Partitions partitions } as disk) -> List.iteri ( fun i -> function - | ({ part_content = `Filesystem fs } as part) -> - f dom disk (Some (part, i)) fs + | { part_content = `Filesystem fs; part_dev = dev } -> + f dom ~disk ~partno:(i+1) dev fs | _ -> () ) partitions.parts | _ -> () - ) disks + ) disks; + (* LV filesystems. *) + List.iter (fun ({lv_dev = dev}, fs) -> f dom dev fs) filesystems ) doms in (* Print stats for each recognized filesystem. *) - let print_stats dom disk part fs = + let print_stats dom ?disk ?partno dev fs = (* Printable name is like "domain:hda" or "domain:hda1". *) let name = let dom_name = dom.dom_name in - let d_target = disk.d_target in - match part with + (* Get the disk name (eg. "hda") from the domain XML, if + * we have it, otherwise use the device name (eg. for LVM). + *) + let disk_name = + match disk with + | None -> dev#name + | Some disk -> disk.d_target + in + match partno with | None -> - dom_name ^ ":" ^ d_target - | Some (_, pnum) -> - dom_name ^ ":" ^ d_target ^ string_of_int pnum in + dom_name ^ ":" ^ disk_name + | Some partno -> + dom_name ^ ":" ^ disk_name ^ string_of_int partno in printf "%-20s " name; if fs.fs_is_swap then (