(* 'df' command for virtual domains.
+ (C) Copyright 2007-2008 Richard W.M. Jones, Red Hat Inc.
+ http://libvirt.org/
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*)
open Printf
open ExtList
-
open Unix
+open Virt_df_gettext.Gettext
+
module C = Libvirt.Connect
module D = Libvirt.Domain
module N = Libvirt.Network
let uri = ref None
let inodes = ref false
let human = ref false
+let all = ref false
(* Maximum number of extended partitions possible. *)
let max_extended_partitions = 100
let size = (LargeFile.fstat fd).LargeFile.st_size in
let size = size /^ sector_size in (* Size in sectors. *)
- print_device dom_name target source size;
+ (*print_device dom_name target source size;*)
let partitions = probe_mbr fd in
None
) partitions in
let stats = List.filter_map (fun x -> x) stats in
- print_stats stats
+ print_stats dom_name stats
) else (* Not an MBR, assume it's a single partition. *)
- print_stats [target, probe_partition target None fd 0L size];
+ print_stats dom_name [target, probe_partition target None fd 0L size];
close fd
lseek fd 446 SEEK_SET;
let str = String.create 64 in
if read fd str 0 64 <> 64 then
- failwith "error reading partition table"
+ failwith (s_ "error reading partition table")
else (
(* Extract partitions from the data. *)
let primaries = List.map (get_partition str) [ 0; 16; 32; 48 ] in
LargeFile.lseek fd (ebr_offs +^ 446L) SEEK_SET;
let str = String.create 32 in
if read fd str 0 32 <> 32 then
- failwith "error reading extended partition"
+ failwith (s_ "error reading extended partition")
else (
(* Extract partitions from the data. *)
let part1, part2 =
match List.map (get_partition str) [ 0; 16 ] with
| [p1;p2] -> p1,p2
- | _ -> failwith "probe_extended_partition: internal error" in
+ | _ -> failwith (s_ "probe_extended_partition: internal error") in
(* First partition entry has offset to the start of this partition. *)
let part1 = { part1 with
part_lba_start = sect +^ part1.part_lba_start } in
and probe_partition target part_type fd start size =
match part_type with
| None ->
- ProbeFailed "detection of unpartitioned devices not yet supported"
+ ProbeFailed (s_ "detection of unpartitioned devices not yet supported")
| Some 0x05 ->
ProbeIgnore (* Extended partition - ignore it. *)
| Some part_type ->
with
Not_found ->
ProbeFailed
- (sprintf "unsupported partition type %02x" part_type)
+ (sprintf (f_ "unsupported partition type %02x") part_type)
-and print_stats statss =
+and print_stats dom_name statss =
List.iter (
- function
- (* Swap partition. *)
- | (target, Swap { swap_name = swap_name;
- swap_block_size = block_size;
- swap_blocks_total = blocks_total }) ->
- if not !human then
- printf "\t%s %Ld %s\n"
- target (block_size *^ blocks_total /^ 1024L) swap_name
- else
- printf "\t%s %s %s\n"
- target (printable_size (block_size *^ blocks_total)) swap_name
-
- (* Ordinary filesystem. *)
- | (target, Filesystem stats) ->
- printf "\t%s " target;
-
- if not !inodes then ( (* Block display. *)
- (* 'df' doesn't count the restricted blocks. *)
- let blocks_total =
- stats.fs_blocks_total -^ stats.fs_blocks_reserved in
- let blocks_avail =
- stats.fs_blocks_avail -^ stats.fs_blocks_reserved in
- let blocks_avail =
- if blocks_avail < 0L then 0L else blocks_avail in
-
- if not !human then ( (* Display 1K blocks. *)
- printf "%Ld %Ld %Ld %s\n"
- (blocks_total *^ stats.fs_block_size /^ 1024L)
- (stats.fs_blocks_used *^ stats.fs_block_size /^ 1024L)
- (blocks_avail *^ stats.fs_block_size /^ 1024L)
- stats.fs_name
- ) else ( (* Human-readable blocks. *)
- printf "%s %s %s %s\n"
- (printable_size (blocks_total *^ stats.fs_block_size))
- (printable_size (stats.fs_blocks_used *^ stats.fs_block_size))
- (printable_size (blocks_avail *^ stats.fs_block_size))
+ fun (target, fs_probe_t) ->
+ let dom_target = dom_name ^ ":" ^ target in
+ printf "%-20s " dom_target;
+
+ match fs_probe_t with
+ (* Swap partition. *)
+ | Swap { swap_name = swap_name;
+ swap_block_size = block_size;
+ swap_blocks_total = blocks_total } ->
+ if not !human then
+ printf "%10Ld %s\n"
+ (block_size *^ blocks_total /^ 1024L) swap_name
+ else
+ printf "%10s %s\n"
+ (printable_size (block_size *^ blocks_total)) swap_name
+
+ (* Ordinary filesystem. *)
+ | Filesystem stats ->
+ if not !inodes then ( (* Block display. *)
+ (* 'df' doesn't count the restricted blocks. *)
+ let blocks_total =
+ stats.fs_blocks_total -^ stats.fs_blocks_reserved in
+ let blocks_avail =
+ stats.fs_blocks_avail -^ stats.fs_blocks_reserved in
+ let blocks_avail =
+ if blocks_avail < 0L then 0L else blocks_avail in
+
+ if not !human then ( (* Display 1K blocks. *)
+ printf "%10Ld %10Ld %10Ld %s\n"
+ (blocks_total *^ stats.fs_block_size /^ 1024L)
+ (stats.fs_blocks_used *^ stats.fs_block_size /^ 1024L)
+ (blocks_avail *^ stats.fs_block_size /^ 1024L)
+ stats.fs_name
+ ) else ( (* Human-readable blocks. *)
+ printf "%10s %10s %10s %s\n"
+ (printable_size (blocks_total *^ stats.fs_block_size))
+ (printable_size (stats.fs_blocks_used *^ stats.fs_block_size))
+ (printable_size (blocks_avail *^ stats.fs_block_size))
+ stats.fs_name
+ )
+ ) else ( (* Inodes display. *)
+ printf "%10Ld %10Ld %10Ld %s\n"
+ stats.fs_inodes_total stats.fs_inodes_used stats.fs_inodes_avail
stats.fs_name
)
- ) else ( (* Inodes display. *)
- printf "%Ld %Ld %Ld %s\n"
- stats.fs_inodes_total stats.fs_inodes_used stats.fs_inodes_avail
- stats.fs_name
- )
- (* Unsupported filesystem or other failure. *)
- | (target, ProbeFailed reason) ->
- printf "\t%s %s\n" target reason
+ (* Unsupported filesystem or other failure. *)
+ | ProbeFailed reason ->
+ printf " %s\n" reason
- | (_, ProbeIgnore) -> ()
+ | ProbeIgnore -> ()
) statss
(* Target is something like "hda" and size is the size in sectors. *)
(* Command line argument parsing. *)
let set_uri = function "" -> uri := None | u -> uri := Some u in
+ let version () =
+ printf "virt-df %s\n" (Libvirt_version.version);
+
+ let major, minor, release =
+ let v, _ = Libvirt.get_version () in
+ v / 1_000_000, (v / 1_000) mod 1_000, v mod 1_000 in
+ printf "libvirt %d.%d.%d\n" major minor release;
+ exit 0
+ in
+
let argspec = Arg.align [
- "-c", Arg.String set_uri, "uri Connect to URI (default: Xen)";
- "--connect", Arg.String set_uri, "uri Connect to URI (default: Xen)";
- "-h", Arg.Set human, " Print sizes in human-readable format";
- "--human-readable", Arg.Set human, " Print sizes in human-readable format";
- "-i", Arg.Set inodes, " Show inodes instead of blocks";
- "--inodes", Arg.Set inodes, " Show inodes instead of blocks";
+ "-a", Arg.Set all,
+ " " ^ s_ "Show all domains (default: only active domains)";
+ "--all", Arg.Set all,
+ " " ^ s_ "Show all domains (default: only active domains)";
+ "-c", Arg.String set_uri,
+ "uri " ^ s_ "Connect to URI (default: Xen)";
+ "--connect", Arg.String set_uri,
+ "uri " ^ s_ "Connect to URI (default: Xen)";
+ "-h", Arg.Set human,
+ " " ^ s_ "Print sizes in human-readable format";
+ "--human-readable", Arg.Set human,
+ " " ^ s_ "Print sizes in human-readable format";
+ "-i", Arg.Set inodes,
+ " " ^ s_ "Show inodes instead of blocks";
+ "--inodes", Arg.Set inodes,
+ " " ^ s_ "Show inodes instead of blocks";
+ "--version", Arg.Unit version,
+ " " ^ s_ "Display version and exit";
] in
- let anon_fun str = raise (Arg.Bad (str ^ ": unknown parameter")) in
- let usage_msg = "virt-df : like 'df', shows disk space used in guests
+ let anon_fun str =
+ raise (Arg.Bad (sprintf (f_ "%s: unknown parameter") str)) in
+ let usage_msg = s_ "virt-df : like 'df', shows disk space used in guests
SUMMARY
virt-df [-options]
prerr_endline (Libvirt.Virterror.to_string err);
(* If non-root and no explicit connection URI, print a warning. *)
if geteuid () <> 0 && name = None then (
- print_endline "NB: If you want to monitor a local Xen hypervisor, you usually need to be root";
+ print_endline (s_ "NB: If you want to monitor a local Xen hypervisor, you usually need to be root");
);
exit 1 in
let nr_active_doms = C.num_of_domains conn in
let active_doms = Array.to_list (C.list_domains conn nr_active_doms) in
let active_doms = List.map (D.lookup_by_id conn) active_doms in
- let nr_inactive_doms = C.num_of_defined_domains conn in
- let inactive_doms =
- Array.to_list (C.list_defined_domains conn nr_inactive_doms) in
- let inactive_doms = List.map (D.lookup_by_name conn) inactive_doms in
- active_doms @ inactive_doms in
+ if not !all then
+ active_doms
+ else (
+ let nr_inactive_doms = C.num_of_defined_domains conn in
+ let inactive_doms =
+ Array.to_list (C.list_defined_domains conn nr_inactive_doms) in
+ let inactive_doms = List.map (D.lookup_by_name conn) inactive_doms in
+ active_doms @ inactive_doms
+ ) in
(* Get their XML. *)
let xmls = List.map D.get_xml_desc doms in
let nodes, domain_attrs =
match xml with
| Xml.Element ("domain", attrs, children) -> children, attrs
- | _ -> failwith "get_xml_desc didn't return <domain/>" in
+ | _ -> failwith (s_ "get_xml_desc didn't return <domain/>") in
let domid =
try Some (int_of_string (List.assoc "id" domain_attrs))
let rec loop = function
| [] ->
- failwith "get_xml_desc returned no <name> node in XML"
+ failwith (s_ "get_xml_desc returned no <name> node in XML")
| Xml.Element ("name", _, [Xml.PCData name]) :: _ -> name
| Xml.Element ("name", _, _) :: _ ->
- failwith "get_xml_desc returned strange <name> node"
+ failwith (s_ "get_xml_desc returned strange <name> node")
| _ :: rest -> loop rest
in
let name = loop nodes in
{ dom_name = name; dom_id = domid; dom_disks = disks }
) xmls in
+ (* Print the title. *)
+ let () =
+ let total, used, avail =
+ match !inodes, !human with
+ | false, false -> s_ "1K-blocks", s_ "Used", s_ "Available"
+ | false, true -> s_ "Size", s_ "Used", s_ "Available"
+ | true, _ -> s_ "Inodes", s_ "IUse", s_ "IFree" in
+ printf "%-20s %10s %10s %10s %s\n%!"
+ (s_ "Filesystem") total used avail (s_ "Type") in
+
(* Probe the devices. *)
List.iter (
fun { dom_name = dom_name; dom_disks = dom_disks } ->
| { d_device = Some "cdrom" } ->
() (* Ignore physical CD-ROM devices. *)
| _ ->
- printf "(device omitted)\n";
+ print_endline (s_ "(device omitted)");
) dom_disks
) doms