summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--README1
-rw-r--r--TODO.virt-top4
-rw-r--r--configure.ac2
-rw-r--r--virt-top/.depend2
-rw-r--r--virt-top/Makefile.in5
-rw-r--r--virt-top/README6
-rw-r--r--virt-top/virt-top.159
-rw-r--r--virt-top/virt-top.pod55
-rw-r--r--virt-top/virt-top.txt47
-rw-r--r--virt-top/virt_top.ml56
-rw-r--r--virt-top/virt_top.mli5
-rw-r--r--virt-top/virt_top_calendar.ml51
13 files changed, 286 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 250a8dd..6f2a981 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2007-10-19 Richard Jones <rjones@redhat.com>
+ * virt-top/virt_top_calendar.ml: Added --end-time option.
+ Extra optional dep on ocaml-calendar.
+ * virt-top/virt-top.pod: Document how to compress and split
+ CSV files. Document --end-time option and time formats.
+ * virt-top/virt_top.ml: Allow sub-second delays when in batch
+ and script mode.
* virt-top/virt_top_utils.mli, virt-top/virt_top.mli: Reorganise
the code and add some interfaces.
diff --git a/README b/README
index 1737c47..8f09eae 100644
--- a/README
+++ b/README
@@ -30,6 +30,7 @@ To build virt-top (optional):
ocaml-curses (from http://www.nongnu.org/ocaml-tmk/)
xml-light (from http://tech.motion-twin.com/doc/xml-light/)
ocaml CSV library (from http://merjis.com/developers/csv)
+ ocaml-calendar (http://www.lri.fr/~signoles/prog.en.html)
[Only ocaml-curses is required for building virt-top. The other
packages are not required, but you will get reduced functionality].
diff --git a/TODO.virt-top b/TODO.virt-top
index 03cda9c..442ba1c 100644
--- a/TODO.virt-top
+++ b/TODO.virt-top
@@ -69,13 +69,15 @@ Thinking about maybe this is something we could controly via a
be true for other options such as the selection of subsystems and/or
ordering/sorting ?
-*** 10 [jmh] End time for data collection
+*** 10 [jmh] End time for data collection [DONE 0.3.3.0]
In --script mode allow an end time to be specified (when the program
quits). Be nice to allow the end time to also be specified relative
to the current time.
*** 11 [jmh] Roll over CSV log file
+ [PUNTED, but documented a way to do it using ordinary shell
+ scripting in the manual page]
In --csv mode, allow the CSV file to be rolled over and compressed
periodically (eg. every so often, specific time of day, etc.)
diff --git a/configure.ac b/configure.ac
index 6246fb4..97b8533 100644
--- a/configure.ac
+++ b/configure.ac
@@ -77,12 +77,14 @@ AC_CHECK_OCAML_PKG(curses)
AC_CHECK_OCAML_PKG(gettext)
AC_CHECK_OCAML_PKG(xml-light)
AC_CHECK_OCAML_PKG(csv)
+AC_CHECK_OCAML_PKG(calendar)
AC_SUBST(pkg_lablgtk2)
AC_SUBST(pkg_curses)
AC_SUBST(pkg_gettext)
AC_SUBST(pkg_xml_light)
AC_SUBST(pkg_csv)
+AC_SUBST(pkg_calendar)
dnl Check for optional perldoc (for building manual pages).
AC_CHECK_PROG(HAVE_PERLDOC,perldoc,perldoc)
diff --git a/virt-top/.depend b/virt-top/.depend
index 4a36b22..97dce08 100644
--- a/virt-top/.depend
+++ b/virt-top/.depend
@@ -1,5 +1,7 @@
virt_top.cmi: ../libvirt/libvirt.cmi
virt_top_utils.cmi: ../libvirt/libvirt.cmi
+virt_top_calendar.cmo: virt_top.cmi
+virt_top_calendar.cmx: virt_top.cmx
virt_top_csv.cmo: virt_top.cmi
virt_top_csv.cmx: virt_top.cmx
virt_top_main.cmo: virt_top.cmi ../libvirt/libvirt.cmi
diff --git a/virt-top/Makefile.in b/virt-top/Makefile.in
index 8eec720..1b80472 100644
--- a/virt-top/Makefile.in
+++ b/virt-top/Makefile.in
@@ -28,6 +28,7 @@ bindir = @bindir@
pkg_curses = @pkg_curses@
pkg_xml_light = @pkg_xml_light@
pkg_csv = @pkg_csv@
+pkg_calendar = @pkg_calendar@
OCAMLCPACKAGES := -package unix,extlib,curses,str
@@ -40,6 +41,10 @@ ifeq ($(pkg_csv),yes)
OBJS += virt_top_csv.cmo
OCAMLCPACKAGES := $(OCAMLCPACKAGES),csv
endif
+ifeq ($(pkg_calendar),yes)
+OBJS += virt_top_calendar.cmo
+OCAMLCPACKAGES := $(OCAMLCPACKAGES),calendar
+endif
OBJS += virt_top_main.cmo
XOBJS := $(OBJS:.cmo=.cmx)
diff --git a/virt-top/README b/virt-top/README
index f557c9b..3b64e88 100644
--- a/virt-top/README
+++ b/virt-top/README
@@ -36,6 +36,12 @@ The code is structured into these files:
Any code which needs the optional ocaml-csv library goes
in here. This implements the --csv command line option.
+ virt_top_calendar.ml
+
+ Any code which needs the optional ocaml-calendar library
+ goes in here. This implements the --end-time command line
+ option.
+
virt_top_main.ml
This is just a small bit of code to glue whatever modules
diff --git a/virt-top/virt-top.1 b/virt-top/virt-top.1
index 137b61f..cf33621 100644
--- a/virt-top/virt-top.1
+++ b/virt-top/virt-top.1
@@ -129,7 +129,7 @@
.\" ========================================================================
.\"
.IX Title "VIRT-TOP 1"
-.TH VIRT-TOP 1 "2007-10-17" "ocaml-libvirt-0.3.2.9" "Virtualization Support"
+.TH VIRT-TOP 1 "2007-10-19" "ocaml-libvirt-0.3.3.0" "Virtualization Support"
.SH "NAME"
virt\-top \- 'top'\-like utility for virtualization stats
.SH "SUMMARY"
@@ -214,6 +214,21 @@ those to process the \s-1CSV\s0 file).
Not every version of virt-top supports \s-1CSV\s0 output \- it depends how the
program was compiled (see \fI\s-1README\s0\fR file in the source distribution
for details).
+.Sp
+To save space you can compress your \s-1CSV\s0 files (if your shell supports
+this feature, eg. \fIbash\fR):
+.Sp
+.Vb 1
+\& virt-top --csv >(gzip -9 > output.csv.gz)
+.Ve
+.Sp
+You can use a similar trick to split the \s-1CSV\s0 file up. In this example
+the \s-1CSV\s0 file is split every 1000 lines into files called
+\&\fIoutput.csv.00\fR, \fIoutput.csv.01\fR etc.
+.Sp
+.Vb 1
+\& virt-top --csv >(split -d -l 1000 - output.csv.)
+.Ve
.IP "\fB\-\-no\-csv\-cpu\fR" 4
.IX Item "--no-csv-cpu"
Disable domain \s-1CPU\s0 stats in \s-1CSV\s0 output.
@@ -244,6 +259,44 @@ Do not read any init file.
.IX Item "--script"
Script mode. There will be no user interface. This is most useful
when used together with the \fI\-\-csv\fR and \fI\-n\fR options.
+.IP "\fB\-\-end\-time time\fR" 4
+.IX Item "--end-time time"
+The program will exit at the \fItime\fR given.
+.Sp
+The time may be given in one of the following formats:
+.RS 4
+.IP "\fIYYYY-MM-DD \s-1HH:MM:SS\s0\fR" 4
+.IX Item "YYYY-MM-DD HH:MM:SS"
+End time is the date and time given.
+.IP "\fI\s-1HH:MM:SS\s0\fR" 4
+.IX Item "HH:MM:SS"
+End time is the time given, today.
+.IP "\fI+HH:MM:SS\fR" 4
+.IX Item "+HH:MM:SS"
+End time is \s-1HH\s0 hours, \s-1MM\s0 minutes, \s-1SS\s0 seconds in the future (counted
+from the moment that program starts).
+.IP "\fI+secs\fR" 4
+.IX Item "+secs"
+End time is \fIsecs\fR seconds in the future.
+.RE
+.RS 4
+.Sp
+For example to run the program for 3 minutes you could do:
+.Sp
+.Vb 1
+\& virt-top --end-time +00:03:00
+.Ve
+.Sp
+or:
+.Sp
+.Vb 1
+\& virt-top --end-time +180
+.Ve
+.Sp
+Not every version of virt-top supports this option \- it depends how the
+program was compiled (see \fI\s-1README\s0\fR file in the source distribution
+for details).
+.RE
.IP "\fB\-\-help\fR" 4
.IX Item "--help"
Display usage summary.
@@ -361,6 +414,10 @@ Sets secure mode.
.IP "\fBscript\fR \fItrue|false\fR" 4
.IX Item "script true|false"
Sets script mode.
+.IP "\fBend-time\fR \fItime\fR" 4
+.IX Item "end-time time"
+Set the time at which the program exits. See above for the
+time formats supported.
.IP "\fBoverwrite-init-file\fR \fIfalse\fR" 4
.IX Item "overwrite-init-file false"
If set to \fIfalse\fR then the \fIW\fR key will not overwrite the
diff --git a/virt-top/virt-top.pod b/virt-top/virt-top.pod
index af31c27..a708357 100644
--- a/virt-top/virt-top.pod
+++ b/virt-top/virt-top.pod
@@ -99,6 +99,17 @@ Not every version of virt-top supports CSV output - it depends how the
program was compiled (see I<README> file in the source distribution
for details).
+To save space you can compress your CSV files (if your shell supports
+this feature, eg. I<bash>):
+
+ virt-top --csv >(gzip -9 > output.csv.gz)
+
+You can use a similar trick to split the CSV file up. In this example
+the CSV file is split every 1000 lines into files called
+I<output.csv.00>, I<output.csv.01> etc.
+
+ virt-top --csv >(split -d -l 1000 - output.csv.)
+
=item B<--no-csv-cpu>
Disable domain CPU stats in CSV output.
@@ -134,6 +145,45 @@ Do not read any init file.
Script mode. There will be no user interface. This is most useful
when used together with the I<--csv> and I<-n> options.
+=item B<--end-time time>
+
+The program will exit at the I<time> given.
+
+The time may be given in one of the following formats:
+
+=over 4
+
+=item I<YYYY-MM-DD HH:MM:SS>
+
+End time is the date and time given.
+
+=item I<HH:MM:SS>
+
+End time is the time given, today.
+
+=item I<+HH:MM:SS>
+
+End time is HH hours, MM minutes, SS seconds in the future (counted
+from the moment that program starts).
+
+=item I<+secs>
+
+End time is I<secs> seconds in the future.
+
+=back
+
+For example to run the program for 3 minutes you could do:
+
+ virt-top --end-time +00:03:00
+
+or:
+
+ virt-top --end-time +180
+
+Not every version of virt-top supports this option - it depends how the
+program was compiled (see I<README> file in the source distribution
+for details).
+
=item B<--help>
Display usage summary.
@@ -290,6 +340,11 @@ Sets secure mode.
Sets script mode.
+=item B<end-time> I<time>
+
+Set the time at which the program exits. See above for the
+time formats supported.
+
=item B<overwrite-init-file> I<false>
If set to I<false> then the I<W> key will not overwrite the
diff --git a/virt-top/virt-top.txt b/virt-top/virt-top.txt
index f3f7ac5..052b51a 100644
--- a/virt-top/virt-top.txt
+++ b/virt-top/virt-top.txt
@@ -72,6 +72,17 @@ OPTIONS
the program was compiled (see *README* file in the source
distribution for details).
+ To save space you can compress your CSV files (if your shell
+ supports this feature, eg. *bash*):
+
+ virt-top --csv >(gzip -9 > output.csv.gz)
+
+ You can use a similar trick to split the CSV file up. In this
+ example the CSV file is split every 1000 lines into files called
+ *output.csv.00*, *output.csv.01* etc.
+
+ virt-top --csv >(split -d -l 1000 - output.csv.)
+
--no-csv-cpu
Disable domain CPU stats in CSV output.
@@ -100,8 +111,38 @@ OPTIONS
Script mode. There will be no user interface. This is most useful
when used together with the *--csv* and *-n* options.
+ --end-time time
+ The program will exit at the *time* given.
+
+ The time may be given in one of the following formats:
+
+ *YYYY-MM-DD HH:MM:SS*
+ End time is the date and time given.
+
+ *HH:MM:SS*
+ End time is the time given, today.
+
+ *+HH:MM:SS*
+ End time is HH hours, MM minutes, SS seconds in the future (counted
+ from the moment that program starts).
+
+ *+secs*
+ End time is *secs* seconds in the future.
+
+ For example to run the program for 3 minutes you could do:
+
+ virt-top --end-time +00:03:00
+
+ or:
+
+ virt-top --end-time +180
+
+ Not every version of virt-top supports this option - it depends how the
+ program was compiled (see *README* file in the source distribution for
+ details).
+
--help
- Display usage summary.
+ Display usage summary.
KEYS
Note that keys are case sensitive. For example use upper-case *P* (shift
@@ -205,6 +246,10 @@ INIT FILE
script *true|false*
Sets script mode.
+ end-time *time*
+ Set the time at which the program exits. See above for the time
+ formats supported.
+
overwrite-init-file *false*
If set to *false* then the *W* key will not overwrite the init file.
diff --git a/virt-top/virt_top.ml b/virt-top/virt_top.ml
index 6047f8e..4bce7dd 100644
--- a/virt-top/virt_top.ml
+++ b/virt-top/virt_top.ml
@@ -36,13 +36,20 @@ let parse_device_xml : (int -> [>`R] D.t -> string list * string list) ref =
(* Hooks for CSV support (see virt_top_csv.ml). *)
let csv_start : (string -> unit) ref =
ref (
- fun _ -> failwith "virt-top was compiled without support for CSV"
+ fun _ -> failwith "virt-top was compiled without support for CSV files"
)
let csv_write : (string list -> unit) ref =
ref (
fun _ -> ()
)
+(* Hook for calendar support (see virt_top_calendar.ml). *)
+let parse_date_time : (string -> float) ref =
+ ref (
+ fun _ ->
+ failwith "virt-top was compiled without support for dates and times"
+ )
+
(* Sort order. *)
type sort_order =
| DomainID | DomainName | Processor | Memory | Time
@@ -104,6 +111,7 @@ let quit = ref false
let delay = ref 3000 (* milliseconds *)
let historical_cpu_delay = ref 20 (* secs *)
let iterations = ref (-1)
+let end_time = ref None
let batch_mode = ref false
let secure_mode = ref false
let sort_order = ref Processor
@@ -139,6 +147,7 @@ let start_up () =
csv_enabled := true
and no_init_file () = init_file := NoInitFile
and set_init_file filename = init_file := InitFile filename
+ and set_end_time time = end_time := Some ((!parse_date_time) time)
in
let argspec = Arg.align [
"-1", Arg.Unit set_pcpu_mode, " Start by displaying pCPUs (default: tasks)";
@@ -153,6 +162,7 @@ let start_up () =
"--no-csv-net", Arg.Clear csv_net, " Disable net stats in CSV";
"-d", Arg.Float set_delay, "delay Delay time interval (seconds)";
"--debug", Arg.Set_string debug_file, "file Send debug messages to file";
+ "--end-time", Arg.String set_end_time, "time Exit at given time";
"--hist-cpu", Arg.Set_int historical_cpu_delay, "secs Historical CPU delay";
"--init-file", Arg.String set_init_file, "file Set name of init file";
"--no-init-file", Arg.Unit no_init_file, " Do not read init file";
@@ -189,6 +199,7 @@ OPTIONS" in
| _, "batch", b -> batch_mode := bool_of_string b
| _, "secure", b -> secure_mode := bool_of_string b
| _, "script", b -> script_mode := bool_of_string b
+ | _, "end-time", t -> set_end_time t
| _, "overwrite-init-file", "false" -> no_init_file ()
| lineno, key, _ ->
eprintf "%s:%d: configuration item ``%s'' ignored\n%!"
@@ -287,8 +298,12 @@ let show_state = function
| D.InfoShutoff -> 'O'
| D.InfoCrashed -> 'X'
-(* Update the display and sleep for given number of seconds. *)
-let sleep n = refresh (); Unix.sleep n
+(* Sleep in seconds. *)
+let sleep = Unix.sleep
+
+(* Sleep in milliseconds. *)
+let usleep n =
+ ignore (Unix.select [] [] [] (float n /. 1000.))
(* The curses getstr/getnstr functions are just weird.
* This helper function also enables echo temporarily.
@@ -1220,16 +1235,31 @@ let rec main_loop ((_, batch_mode, script_mode, csv_enabled, _, _, _)
(* Clear up unused virDomainPtr objects. *)
Gc.compact ();
+ (* Get next key. This does the sleep. *)
if not batch_mode && not script_mode then
- get_key_press setup
- else (* Batch mode or script mode - just sleep, ignore keys. *)
- Unix.sleep (!delay / 1000);
+ get_key_press setup;
(* Max iterations? *)
if !iterations >= 0 then (
decr iterations;
if !iterations = 0 then quit := true
);
+
+ (* End time? *)
+ (match !end_time with
+ | None -> ()
+ | Some end_time ->
+ let (_, time, _, _, _, _, _, _) = state in
+ let delay_secs = float !delay /. 1000. in
+ if end_time <= time +. delay_secs then quit := true
+ );
+
+ (* Batch mode or script mode. We didn't call get_key_press above, so
+ * we didn't sleep. Sleep now, unless we are about to quit.
+ *)
+ if batch_mode || script_mode then
+ if not !quit then
+ usleep !delay;
done
and get_key_press setup =
@@ -1271,6 +1301,7 @@ and change_delay () =
with
Failure "float_of_string" ->
print_msg "Not a valid number"; true in
+ refresh ();
sleep (if error then 2 else 1)
and change_sort_order () =
@@ -1360,7 +1391,10 @@ and change_sort_order () =
sort_order := new_order;
print_msg (sprintf "Sort order changed to: %s"
(printable_sort_order new_order));
- if not loop then sleep 1
+ if not loop then (
+ refresh ();
+ sleep 1
+ )
);
if loop then change_sort_order ()
@@ -1457,11 +1491,14 @@ and _write_init_file filename =
(* Rename filename.new to filename. *)
Unix.rename (filename ^ ".new") filename;
- print_msg (sprintf "Wrote settings to %s" filename); sleep 2
+ print_msg (sprintf "Wrote settings to %s" filename);
+ refresh ();
+ sleep 2
with
- | Sys_error err -> print_msg "Error: %s"; sleep 2
+ | Sys_error err -> print_msg "Error: %s"; refresh (); sleep 2
| Unix.Unix_error (err, fn, str) ->
print_msg (sprintf "Error: %s %s %s" (Unix.error_message err) fn str);
+ refresh ();
sleep 2
and show_help (_, _, _, _, _, hostname,
@@ -1553,4 +1590,5 @@ and show_help (_, _, _, _, _, hostname,
and unknown_command k =
print_msg "Unknown command - try 'h' for help";
+ refresh ();
sleep 1
diff --git a/virt-top/virt_top.mli b/virt-top/virt_top.mli
index 7b0ac3b..790eb31 100644
--- a/virt-top/virt_top.mli
+++ b/virt-top/virt_top.mli
@@ -17,7 +17,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*)
-(* Hooks for virt_top_xml to override (if present). *)
+(* Hook for virt_top_xml to override (if present). *)
val parse_device_xml :
(int -> [ `R ] Libvirt.Domain.t -> string list * string list) ref
@@ -25,6 +25,9 @@ val parse_device_xml :
val csv_start : (string -> unit) ref
val csv_write : (string list -> unit) ref
+(* Hook for virt_top_calendar to override (if present). *)
+val parse_date_time : (string -> float) ref
+
type setup =
Libvirt.ro Libvirt.Connect.t (* connection *)
* bool * bool * bool (* batch, script, csv modes *)
diff --git a/virt-top/virt_top_calendar.ml b/virt-top/virt_top_calendar.ml
new file mode 100644
index 0000000..a99f90f
--- /dev/null
+++ b/virt-top/virt_top_calendar.ml
@@ -0,0 +1,51 @@
+(* 'top'-like tool for libvirt domains.
+ (C) Copyright 2007 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.
+
+ This file contains all code which requires ocaml-calendar.
+*)
+
+open Printf
+open ExtString ;;
+
+Virt_top.parse_date_time :=
+fun time ->
+ let cal : Calendar.t =
+ if String.starts_with time "+" then ( (* +something *)
+ let period = String.sub time 1 (String.length time - 1) in
+ let period =
+ if String.contains period ':' then ( (* +HH:MM:SS *)
+ let t = Printer.TimePrinter.from_string period in
+ let hh = Time.hour t and mm = Time.minute t and ss = Time.second t in
+ Calendar.Period.make 0 0 0 hh mm ss
+ ) else (* +seconds *)
+ Calendar.Period.second (int_of_string period) in
+ (* Add it as an offset from the current time. *)
+ Calendar.add (Calendar.now ()) period
+ ) else (
+ if String.contains time '-' then (* YYYY-MM-DD HH:MM:SS *)
+ Printer.CalendarPrinter.from_string time
+ else ( (* HH:MM:SS *)
+ let time = Printer.TimePrinter.from_string time in
+ Calendar.create (Date.today ()) time
+ )
+ ) in
+
+ eprintf "end time: %s\n" (Printer.CalendarPrinter.to_string cal);
+
+ (* Convert to a time_t, adjusting for the current timezone. *)
+ fst (Unix.mktime (Calendar.to_unixtm cal))