- (sprintf "unsupported partition type %02x" part_type)
-
-and print_stats 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))
- 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
-
- | (_, ProbeIgnore) -> ()
- ) statss
-
-(* Target is something like "hda" and size is the size in sectors. *)
-and print_device dom_name target source size =
- printf "%s /dev/%s (%s) %s\n"
- dom_name target (printable_size (size *^ sector_size)) source
-
-and printable_size bytes =
- if bytes < 1024L *^ 1024L then
- sprintf "%Ld bytes" bytes
- else if bytes < 1024L *^ 1024L *^ 1024L then
- sprintf "%.1f MiB" (Int64.to_float (bytes /^ 1024L) /. 1024.)
- else
- sprintf "%.1f GiB" (Int64.to_float (bytes /^ 1024L /^ 1024L) /. 1024.)
-
-and read_int32_le str offs =
- Int64.of_int (Char.code str.[offs]) +^
- 256L *^ Int64.of_int (Char.code str.[offs+1]) +^
- 65536L *^ Int64.of_int (Char.code str.[offs+2]) +^
- 16777216L *^ Int64.of_int (Char.code str.[offs+3])
-
-and read_int16_le str offs =
- Int64.of_int (Char.code str.[offs]) +^
- 256L *^ Int64.of_int (Char.code str.[offs+1])
-
-let main () =
- (* Command line argument parsing. *)
- let set_uri = function "" -> uri := None | u -> uri := Some u 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";
- ] 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
-
-SUMMARY
- virt-df [-options]
-
-OPTIONS" in
-
- Arg.parse argspec anon_fun usage_msg;
-
- let xmls =
- (* Connect to the hypervisor. *)
- let conn =
- let name = !uri in
- try C.connect_readonly ?name ()
- with
- Libvirt.Virterror err ->
- 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";
- );
- exit 1 in
-
- (* Get the list of active & inactive domains. *)
- let doms =
- 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
-
- (* Get their XML. *)
- let xmls = List.map D.get_xml_desc doms in
-
- (* Parse the XML. *)
- let xmls = List.map Xml.parse_string xmls in
-
- (* Return just the XML documents - everything else will be closed
- * and freed including the connection to the hypervisor.
- *)
- xmls in
-
- let doms : domain list =
- (* Grr.. Need to use a library which has XPATH support (or cduce). *)
- List.map (
- fun xml ->
- let nodes, domain_attrs =
- match xml with
- | Xml.Element ("domain", attrs, children) -> children, attrs
- | _ -> failwith "get_xml_desc didn't return <domain/>" in
-
- let domid =
- try Some (int_of_string (List.assoc "id" domain_attrs))
- with Not_found -> None in
-
- let rec loop = function
- | [] ->
- failwith "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"
- | _ :: rest -> loop rest
- in
- let name = loop nodes in
-
- let devices =
- let devices =
- List.filter_map (
- function
- | Xml.Element ("devices", _, devices) -> Some devices
- | _ -> None
- ) nodes in
- List.concat devices in
-
- let rec target_dev_of = function
- | [] -> None
- | Xml.Element ("target", attrs, _) :: rest ->
- (try Some (List.assoc "dev" attrs)
- with Not_found -> target_dev_of rest)
- | _ :: rest -> target_dev_of rest
- in
-
- let rec source_file_of = function
- | [] -> None
- | Xml.Element ("source", attrs, _) :: rest ->
- (try Some (List.assoc "file" attrs)
- with Not_found -> source_file_of rest)
- | _ :: rest -> source_file_of rest
- in
-
- let rec source_dev_of = function
- | [] -> None
- | Xml.Element ("source", attrs, _) :: rest ->
- (try Some (List.assoc "dev" attrs)
- with Not_found -> source_dev_of rest)
- | _ :: rest -> source_dev_of rest
- in
-
- let disks =
- List.filter_map (
- function
- | Xml.Element ("disk", attrs, children) ->
- let typ =
- try Some (List.assoc "type" attrs)
- with Not_found -> None in
- let device =
- try Some (List.assoc "device" attrs)
- with Not_found -> None in
- let source =
- match source_file_of children with
- | (Some _) as source -> source
- | None -> source_dev_of children in
- let target = target_dev_of children in
-
- Some {
- d_type = typ; d_device = device;
- d_source = source; d_target = target
- }
- | _ -> None
- ) devices in
-
- { dom_name = name; dom_id = domid; dom_disks = disks }
- ) xmls in
-
- (* Probe the devices. *)
- List.iter (
- fun { dom_name = dom_name; dom_disks = dom_disks } ->
- List.iter (
- function
- | { d_source = Some source; d_target = Some target } ->
- probe_device dom_name target source
- | { d_device = Some "cdrom" } ->
- () (* Ignore physical CD-ROM devices. *)
- | _ ->
- printf "(device omitted)\n";
- ) dom_disks
- ) doms