In data lunedì 31 agosto 2015 15:07:37, Maros Zatko ha scritto:
Lets user view journald log from VM in a similar format as journalctl uses.
"Let the user view the journald log from a guest, with a format similar to what journalctl uses."
Fixes RFE: journal reader in guestfish --- cat/log.c | 4 +++ fish/journal.c | 3 +- generator/Makefile.am | 6 ++-- generator/actions.ml | 22 ++++++++++++ generator/journal.ml | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ generator/main.ml | 3 ++ 6 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 generator/journal.ml
diff --git a/cat/log.c b/cat/log.c index f05eae0..157ee55 100644 --- a/cat/log.c +++ b/cat/log.c @@ -36,6 +36,7 @@
#include "guestfs.h" #include "options.h" +#include "journal.h"
/* Currently open libguestfs handle. */ guestfs_h *g; @@ -279,6 +280,9 @@ do_log_journal (void) if (guestfs_journal_open (g, JOURNAL_DIR) == -1) return -1;
+ if (journal_view ("~3axv") == -1) + return -1; + if (guestfs_journal_close (g) == -1) return -1;
This should be part of patch #1 if possible.
diff --git a/fish/journal.c b/fish/journal.c index 9afdf60..579a1d1 100644 --- a/fish/journal.c +++ b/fish/journal.c @@ -83,9 +83,8 @@ lookup_field (char field) int journal_view (const char *fields) { - int r; int errors = 0; - while ((r = guestfs_journal_next(g)) > 0) { + while (guestfs_journal_next(g) > 0) { CLEANUP_FREE_XATTR_LIST struct guestfs_xattr_list *xattrs = NULL; int64_t ts; int priority = LOG_INFO;
Ditto.
diff --git a/generator/Makefile.am b/generator/Makefile.am index a3fe50d..bd466c2 100644 --- a/generator/Makefile.am +++ b/generator/Makefile.am @@ -37,6 +37,7 @@ sources = \ haskell.ml \ java.ml \ lua.ml \ + journal.ml \ main.ml \ ocaml.ml \ optgroups.ml \ @@ -60,13 +61,14 @@ sources = \ objects = \ types.cmo \ utils.cmo \ + pr.cmo \ + docstrings.cmo \ + journal.cmo \ actions.cmo \ structs.cmo \ optgroups.cmo \ prepopts.cmo \ events.cmo \ - pr.cmo \ - docstrings.cmo \ checks.cmo \ c.cmo \ xdr.cmo \ diff --git a/generator/actions.ml b/generator/actions.ml index 13c8bc8..e914fd3 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -21,6 +21,8 @@ open Types open Utils
+open Journal + (* Default settings for all action fields. So we copy and override * this struct by writing '{ defaults with name = &c }' *) @@ -12897,6 +12899,26 @@ environment variable. See also L</hexdump>." };
{ defaults with + name = "journal_view"; + shortdesc = "view journald log"; + longdesc = " journal-view [FORMAT] + +View journald log in format similar to journalctl.
"journalctl" could be linkified, so L<journalctl(1)>.
+ +=over + +" +^ (Journal.ops_to_pod_string ()) ^ +" +=back + +Default format is C<~3axv>
"The default format is C<~3axv>."
+ +For fields description see C<man SYSTEMD.JOURNAL-FIELDS>
There's the proper format for linking man pages, so it should be L<systemd.journal-fields(7)>.
+ +Use C<journal-open> first." };
C<guestfs_journal_open> here, so it gets proper linking.
+ + { defaults with name = "lcd"; shortdesc = "change working directory"; longdesc = " lcd directory diff --git a/generator/journal.ml b/generator/journal.ml new file mode 100644 index 0000000..46d93cd --- /dev/null +++ b/generator/journal.ml @@ -0,0 +1,97 @@ +(* libguestfs + * Copyright (C) 2015 Red Hat Inc. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + *) + +(* Please read generator/README first. *) + +open Printf + +open String +open Docstrings +open Pr + +open Char +open List
I guess you don't need to open List, if later you always use it like List.foo.
+ +(* Arguments used by journal-view command *) + +type op_type = Options of (char * string) list;; (* option, option name*)
What is Options? I cannot find it neither in the OCaml standard library nor in the generator own types... As a style note, usually ;; at the end of top-level statements are not used in libguestfs' code.
+let op = Options [ + (* Trusted fields *) + ('a', "_PID"); + ('b', "_UID"); + ('c', "_GID"); + ('d', "_COMM"); + ('e', "_EXE"); + ('f', "_CMDLINE"); + ('g', "_CAP_EFFECTIVE"); + ('h', "_AUDIT_SESSION"); + ('i', "_AUDIT_LOGINUID"); + ('j', "_SYSTEMD_CGROUP"); + ('k', "_SYSTEMD_SESSION"); + ('l', "_SYSTEMD_UNIT"); + ('m', "_SYSTEMD_USER_UNIT"); + ('n', "_SYSTEMD_OWNER_UID"); + ('o', "_SYSTEMD_SLICE"); + ('p', "_SELINUX_CONTEXT"); + ('q', "_SOURCE_REALTIME_TIMESTAMP"); + ('r', "_BOOT_ID"); + ('s', "_MACHINE_ID"); + ('t', "_HOSTNAME"); + ('u', "_TRANSPORT"); + (* User fields *) + ('v', "MESSAGE"); + ('w', "MESSAGE_ID"); + ('x', "PRIORITY"); + ('y', "CODE_FILE"); + ('z', "CODE_LINE"); + ('0', "CODE_FUNC"); + ('1', "ERRNO"); + ('2', "SYSLOG_FACILITY"); + ('3', "SYSLOG_IDENTIFIER"); + ('4', "SYSLOG_PID"); + ('~', "timestamp") +];; + +let deopt x = match x with Options y -> y;;
Considering you always call deopt on 'op', declaring it as (char * string) list should be enough, I guess.
+let string_list_to_string s = List.fold_left (fun a b -> a ^ b) "" s;;
Using String.concat would make it easier to read/understand... although seems not used at all.
+let ops_to_pod_string () = + List.fold_left (fun a b -> a ^ b) ""
String.concat here would be easier.
+ (List.map (fun (a,b) -> "=item " ^ escaped a ^ " " ^ b ^ "\n\n") + (deopt op));; + +let ops_to_c_array arrname () = + let decl = "static const char *const " ^ arrname ^ "[] = {\n" in
Considering it does not change, you could put the array opening and closing directly in the printed C code.
+ decl ^ String.concat ",\n" + (List.map (fun (a,b) -> " \"" ^ escaped a ^ "\", \"" ^ b ^ "\"") + (deopt op)) ^ "\n};";;
IMHO this could be inline in generate_journal_h, just using List.iter to print each line in the array.
+let generate_journal_h () = + generate_header CStyle LGPLv2plus; + pr "#include <config.h>\n"; + pr "\n"; + pr "#ifndef JOURNAL_H\n"; + pr "#define JOURNAL_H\n"; + pr "\n"; + pr "%s\n" (ops_to_c_array "journal_fields" ()); + pr "\n"; + pr "/* in journal.c */\n"; + pr "extern int journal_view (const char *fields);\n"; + pr "#endif /* JOURNAL_H */\n";
The generated code here could be better: instead of generating an array each field code (as string) and name one after the other, have a list of structs: static const struct JournalField { char field; const char *name; } fields[] = { { 'a', "_PID" }, ... };
From what I see in these patches, it seems like the array with fields is just an implementation detail of journal_view, and thus not worth exposing in journal.h. Maybe generate a journal-fields.h (or even .c) to include directly in journal.c, so journal.h can stay as non-generated file.
Thanks, -- Pino Toscano