X-Git-Url: http://git.annexia.org/?p=virt-top.git;a=blobdiff_plain;f=virt-df%2Fvirt_df.ml;h=c02c8e3d19b4f38f67bc4da523d3088bf1897e0a;hp=b992e1b95484a302dc06f9918a05b913bad82655;hb=0bdb08c61ec66a16a81c2778a2a76cac77b08fda;hpb=40c683ea4c9d921a6fe23c2639125261b92da472 diff --git a/virt-df/virt_df.ml b/virt-df/virt_df.ml index b992e1b..c02c8e3 100644 --- a/virt-df/virt_df.ml +++ b/virt-df/virt_df.ml @@ -23,8 +23,6 @@ open Unix open Virt_df_gettext.Gettext -let debug = true (* If true emit lots of debugging information. *) - let ( +* ) = Int32.add let ( -* ) = Int32.sub let ( ** ) = Int32.mul @@ -35,6 +33,7 @@ let ( -^ ) = Int64.sub let ( *^ ) = Int64.mul let ( /^ ) = Int64.div +let debug = ref false let uri = ref None let inodes = ref false let human = ref false @@ -68,6 +67,21 @@ object (self) method name = filename end +(* A linear offset/size from an underlying device. *) +class offset_device name start size (dev : device) = +object + inherit device + method name = name + method size = size + method read offset len = + if offset < 0L || len < 0 || offset +^ Int64.of_int len > size then + invalid_arg ( + sprintf "%s: tried to read outside device boundaries (%Ld/%d/%Ld)" + name offset len size + ); + dev#read (start+^offset) len +end + (* The null device. Any attempt to read generates an error. *) let null_device : device = object @@ -81,6 +95,8 @@ type domain = { dom_name : string; (* Domain name. *) dom_id : int option; (* Domain ID (if running). *) dom_disks : disk list; (* Domain disks. *) + dom_lv_filesystems : + (lv * filesystem) list; (* Domain LV filesystems. *) } and disk = { (* From the XML ... *) @@ -97,7 +113,7 @@ and disk_content = [ `Unknown (* Not probed or unknown. *) | `Partitions of partitions (* Contains partitions. *) | `Filesystem of filesystem (* Contains a filesystem directly. *) - | `PhysicalVolume of string (* Contains an LVM PV. *) + | `PhysicalVolume of pv (* Contains an LVM PV. *) ] (* Partitions. *) @@ -116,7 +132,7 @@ and partition_status = Bootable | Nonbootable | Malformed | NullEntry and partition_content = [ `Unknown (* Not probed or unknown. *) | `Filesystem of filesystem (* Filesystem. *) - | `PhysicalVolume of string (* Contains an LVM PV. *) + | `PhysicalVolume of pv (* Contains an LVM PV. *) ] (* Filesystems (also swap devices). *) @@ -134,6 +150,19 @@ and filesystem = { fs_inodes_used : int64; (* Inodes in use. *) } +(* Physical volumes. *) +and pv = { + lvm_plugin_id : lvm_plugin_id; (* The LVM plug-in. *) + pv_uuid : string; (* UUID. *) +} + +(* Logical volumes. *) +and lv = { + lv_dev : device; (* Logical volume device. *) +} + +and lvm_plugin_id = string + (* Convert partition, filesystem types to printable strings for debugging. *) let string_of_partition { part_status = status; part_type = typ; part_dev = dev } = @@ -150,6 +179,20 @@ let string_of_filesystem { fs_name = name; fs_is_swap = swap } = if not swap then name else name ^ " [swap]" +(* Convert a UUID (containing '-' chars) to canonical form. *) +let canonical_uuid uuid = + let uuid' = String.make 32 ' ' in + let j = ref 0 in + for i = 0 to String.length uuid - 1 do + if !j >= 32 then + invalid_arg (sprintf (f_ "canonical_uuid: UUID is too long: %s") uuid); + let c = uuid.[i] in + if c <> '-' then ( uuid'.[!j] <- c; incr j ) + done; + if !j <> 32 then + invalid_arg (sprintf (f_ "canonical_uuid: invalid UUID: %s") uuid); + uuid' + (* Register a partition scheme. *) let partition_types = ref [] let partition_type_register (parts_name : string) probe_fn = @@ -157,7 +200,7 @@ let partition_type_register (parts_name : string) probe_fn = (* Probe a device for partitions. Returns [Some parts] or [None]. *) let probe_for_partitions dev = - if debug then eprintf "probing for partitions on %s ...\n%!" dev#name; + if !debug then eprintf "probing for partitions on %s ...\n%!" dev#name; let rec loop = function | [] -> None | (parts_name, probe_fn) :: rest -> @@ -165,7 +208,7 @@ let probe_for_partitions dev = with Not_found -> loop rest in let r = loop !partition_types in - if debug then ( + if !debug then ( match r with | None -> eprintf "no partitions found on %s\n%!" dev#name | Some { parts_name = name; parts = parts } -> @@ -182,7 +225,7 @@ let filesystem_type_register (fs_name : string) probe_fn = (* Probe a device for a filesystem. Returns [Some fs] or [None]. *) let probe_for_filesystem dev = - if debug then eprintf "probing for a filesystem on %s ...\n%!" dev#name; + if !debug then eprintf "probing for a filesystem on %s ...\n%!" dev#name; let rec loop = function | [] -> None | (fs_name, probe_fn) :: rest -> @@ -190,7 +233,7 @@ let probe_for_filesystem dev = with Not_found -> loop rest in let r = loop !filesystem_types in - if debug then ( + if !debug then ( match r with | None -> eprintf "no filesystem found on %s\n%!" dev#name | Some fs -> @@ -206,17 +249,45 @@ let lvm_type_register (lvm_name : string) probe_fn list_lvs_fn = (* Probe a device for a PV. Returns [Some lvm_name] or [None]. *) let probe_for_pv dev = - if debug then eprintf "probing if %s is a PV ...\n%!" dev#name; + if !debug then eprintf "probing if %s is a PV ...\n%!" dev#name; let rec loop = function | [] -> None | (lvm_name, (probe_fn, _)) :: rest -> - if probe_fn dev then Some lvm_name else loop rest + try Some (probe_fn lvm_name dev) + with Not_found -> loop rest in let r = loop !lvm_types in - if debug then ( + if !debug then ( match r with | None -> eprintf "no PV found on %s\n%!" dev#name - | Some lvm_name -> - eprintf "%s contains a %s PV\n%!" dev#name lvm_name + | Some { lvm_plugin_id = name } -> + eprintf "%s contains a %s PV\n%!" dev#name name ); r + +let list_lvs lvm_name devs = + let _, list_lvs_fn = List.assoc lvm_name !lvm_types in + list_lvs_fn devs + +(*----------------------------------------------------------------------*) + +(* This version by Isaac Trotts. *) +let group_by ?(cmp = Pervasives.compare) ls = + let ls' = + List.fold_left + (fun acc (day1, x1) -> + match acc with + [] -> [day1, [x1]] + | (day2, ls2) :: acctl -> + if cmp day1 day2 = 0 + then (day1, x1 :: ls2) :: acctl + else (day1, [x1]) :: acc) + [] + ls + in + let ls' = List.rev ls' in + List.map (fun (x, xs) -> x, List.rev xs) ls' + +let rec range a b = + if a < b then a :: range (a+1) b + else []