1 /* Kernel info for virtual domains.
2 * (C) Copyright 2008-2010 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <libvirt/libvirt.h>
29 #include <libvirt/virterror.h>
37 /* Linked list of registered tools. */
38 static struct tool *tools = NULL;
40 /* Currently selected tool (may be NULL). */
41 struct tool *tool = NULL;
43 /* External DB location. */
44 static const char *externaldb = DATADIR "/" PACKAGE_NAME "/kerneldb";
45 static int fail_if_no_externaldb = 0;
47 /* URI and libvirt connection. */
48 static const char *uri = NULL;
49 static virConnectPtr conn = NULL;
51 /* If -t option was passed, this is the filename of the test image. */
52 static const char *test_image = NULL;
54 /* If --list-kernels was passed. */
55 static int list_kernels = 0;
57 /* Local functions. */
58 static void load_externaldb (const char *, int);
59 static void do_list_kernels (void) ATTRIBUTE_NORETURN;
60 static void usage (void) ATTRIBUTE_NORETURN;
62 static virDomainPtr *get_named_domains (char * const*, int);
63 static virDomainPtr *get_all_domains (void);
66 main (int argc, char *argv[])
70 /* argv[0] can be the name of the tool, or if not recognized then
71 * the name of the tool must be the first anonymous argument.
74 const char *prog = strrchr (argv[0], '/');
79 if (STRCASEEQLEN (prog+1, "virt-", 5)) {
84 for (t = tools; t != NULL; t = t->next) {
85 if (STRCASEEQ (prog, t->name)) {
93 /* Parse command line parameters. */
95 static const char *shortopts = "A:E:T:W:c:dt:x:?";
96 static struct option longopts[] = {
97 { "arch", required_argument, 0, 'A' },
98 { "endian", required_argument, 0, 'E' },
99 { "kernel-min", required_argument, 0, 0 },
100 { "kernel-max", required_argument, 0, 0 },
101 { "text", required_argument, 0, 'T' },
102 { "wordsize", required_argument, 0, 'W' },
103 { "connect", required_argument, 0, 'c' },
104 { "csv", no_argument, 0, 0 },
105 { "debug", no_argument, 0, 'd' },
106 { "help", no_argument, 0, '?' },
107 { "list-kernels", no_argument, 0, 0 },
108 { "image", required_argument, 0, 't' },
109 { "externaldb", required_argument, 0, 'x' },
110 { "version", no_argument, 0, 0 }
112 int option_index = 0;
114 c = getopt_long (argc, argv, shortopts, longopts, &option_index);
118 case 0: { /* longopt without short equivalent */
119 const char *longopt_name = longopts[option_index].name;
121 if (STRCASEEQ (longopt_name, "csv")) /* csv output */
123 /* list kernels and exit */
124 else if (STRCASEEQ (longopt_name, "list-kernels"))
127 else if (STRCASEEQ (longopt_name, "kernel-min"))
130 else if (STRCASEEQ (longopt_name, "kernel-max"))
132 /* display version and exit */
133 else if (STRCASEEQ (longopt_name, "version")) {
134 printf ("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
138 INTERNAL_ERROR; /* this shouldn't happen */
143 case 'A': /* set architecture */
145 case 'E': /* set endianness */
147 case 'T': /* set text address */
149 case 'W': /* set wordsize */
152 case 'c': /* connect to URI */
156 case 'd': /* enable debugging */
160 case 't': /* load kernel image */
164 case 'x': /* location of external database */
166 fail_if_no_externaldb = 1;
169 case '?': /* print help */
173 INTERNAL_ERROR; /* this shouldn't happen */
177 /* Load the external database / kernel updates, if necessary. */
178 load_externaldb (externaldb, fail_if_no_externaldb);
180 /* If asked, list kernels and exit. */
184 /* If we haven't got a tool name yet, then the first anon parameter
185 * must be a tool name.
194 for (t = tools; t != NULL; t = t->next) {
195 if (STRCASEEQ (p, t->name)) {
201 error (_("'%s' is not a recognized virt-kernel-info tool.\n\nMake sure you specify the virt-kernel-info tool as the first argument on the command line. To get a list of recognized tools, use 'virt-kernel-info --help'."), p);
203 error (_("Could not work out which virt-kernel-info tool you are trying to use.\n\nMake sure you specify the virt-kernel-info tool as the first argument on the command line. To get a list of recognized tools, use 'virt-kernel-info --help'."));
208 /* We should have worked out which tool it is by now. */
209 assert (tool != NULL);
211 /* If -t was passed, then we load that forensic image, else we have
212 * to connect to libvirt.
216 error (_("If '-t' is passed then there shouldn't be any additional command line arguments."));
223 /* Connect to libvirt. */
224 conn = virConnectOpenReadOnly (uri);
226 error (_("failed to connect to hypervisor '%s'.\nWhen connecting to some hypervisors you may need to be running as root.\nThere may be a more detailed error message above this, but if not then we didn't print one because libvirt's virterror mechanism is next to useless."),
227 uri != NULL ? uri : _("default"));
229 /* Extra parameters are a list of domain names, IDs or UUIDs. */
231 doms = get_named_domains (&argv[optind], argc - optind);
233 doms = get_all_domains ();
235 /* Act on each domain. */
243 static void usage (void)
248 virt-kernel-info: Tools for providing information about virtual machines\n\
252 <tool> [-options] [domain-name|ID|UUID ...]\n\
253 <tool> [-options] -t <image>\n\
254 where <tool> is 'virt-ps', 'virt-dmesg' etc. (full list below) or a\n\
255 subtool such as 'virt-kernel-info ps', 'virt-kernel-info capture' etc.\n\
258 --connect | -c <libvirt-uri> Connect to URI (default: autodetect)\n\
259 --csv Output in CSV format for spreadsheets etc.\n\
260 --debug Print extra debugging information\n\
261 --list-kernels List known kernels, then exit\n\
262 --image | -t <image> Examine saved image (see: virt-kernel-info capture)\n\
263 --externaldb | -x <externaldb> Load/override external kernels database\n\
264 --version Print program name and version, then exit\n\
266 These options may be used to override automatic detection of guest\n\
267 architecture, endianness, kernel location, etc.:\n\
268 -A | --arch auto | <arch> | ...\n\
269 -E | --endian auto | le | be\n\
270 --kernel-min auto | <arch> | ... | 0x<addr>\n\
271 --kernel-max auto | <arch> | ... | 0x<addr>\n\
272 -T | --text auto | <arch> | ... | 0x<addr>\n\
273 -W | --wordsize auto | 32 | 64\n\
274 where <arch> is the name of an architecture such as i386, x86-64, etc.\n\
279 for (t = tools; t != NULL; t = t->next) {
283 printf (" virt-%-12s - %s\n", t->name, t->summary);
285 printf (" virt-kernel-info %8s - %s\n", t->name, t->summary);
287 printf ("%s", t->description);
288 if (t->next) printf ("\n");
295 load_externaldb (const char *externaldb, int fail_if_no_externaldb)
309 do_list_kernels (void)
314 static virDomainPtr *
315 get_named_domains (char * const *domains, int nr_domains)
320 static virDomainPtr *
321 get_all_domains (void)
326 /* Tools register themselves by calling this function. Note that the
327 * function is called from constructors. In particular it is called
328 * before main(). Also can be called in unspecified order.
331 register_tool (struct tool *tool)
335 /* Insertion sort. */
337 for (t = tools; t != NULL; t = t->next) {
338 if (strcmp (t->name, tool->name) < 0)
347 /* Warning, error message functions. See internal.h for usage. */
349 message (const char *pre, const char *fs, va_list args)
351 fprintf (stderr, "%s-%s: %s: ", PACKAGE_NAME, PACKAGE_VERSION, pre);
352 vfprintf (stderr, fs, args);
353 fprintf (stderr, "\n");
357 error (const char *fs, ...)
361 message (_("error"), fs, args);
367 warning (const char *fs, ...)
371 message (_("warning"), fs, args);
376 internal_error (const char *fs, ...)
380 message (_("internal error"), fs, args);