/* Kernel info for virtual domains. * (C) Copyright 2008-2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include "internal.h" /* Global flags. */ int csv = 0; int debug = 0; /* Linked list of registered tools. */ static struct tool *tools = NULL; /* Currently selected tool (may be NULL). */ struct tool *tool = NULL; /* External DB location. */ static const char *externaldb = DATADIR "/" PACKAGE_NAME "/kerneldb"; static int fail_if_no_externaldb = 0; /* URI and libvirt connection. */ static const char *uri = NULL; static virConnectPtr conn = NULL; /* If -t option was passed, this is the filename of the test image. */ static const char *test_image = NULL; /* If --list-kernels was passed. */ static int list_kernels = 0; /* Local functions. */ static void load_externaldb (const char *, int); static void do_list_kernels (void) ATTRIBUTE_NORETURN; static void usage (void) ATTRIBUTE_NORETURN; static virDomainPtr *get_named_domains (char * const*, int); static virDomainPtr *get_all_domains (void); int main (int argc, char *argv[]) { int c; /* argv[0] can be the name of the tool, or if not recognized then * the name of the tool must be the first anonymous argument. */ if (argv[0]) { const char *prog = strrchr (argv[0], '/'); if (!prog) prog = argv[0]; if (STRCASEEQLEN (prog+1, "virt-", 5)) { struct tool *t; prog += 6; for (t = tools; t != NULL; t = t->next) { if (STRCASEEQ (prog, t->name)) { tool = t; break; } } } } /* Parse command line parameters. */ while (1) { static const char *shortopts = "A:E:T:W:c:dt:x:?"; static struct option longopts[] = { { "arch", required_argument, 0, 'A' }, { "endian", required_argument, 0, 'E' }, { "kernel-min", required_argument, 0, 0 }, { "kernel-max", required_argument, 0, 0 }, { "text", required_argument, 0, 'T' }, { "wordsize", required_argument, 0, 'W' }, { "connect", required_argument, 0, 'c' }, { "csv", no_argument, 0, 0 }, { "debug", no_argument, 0, 'd' }, { "help", no_argument, 0, '?' }, { "list-kernels", no_argument, 0, 0 }, { "image", required_argument, 0, 't' }, { "externaldb", required_argument, 0, 'x' }, { "version", no_argument, 0, 0 } }; int option_index = 0; c = getopt_long (argc, argv, shortopts, longopts, &option_index); if (c == -1) break; switch (c) { case 0: { /* longopt without short equivalent */ const char *longopt_name = longopts[option_index].name; if (STRCASEEQ (longopt_name, "csv")) /* csv output */ csv = 1; /* list kernels and exit */ else if (STRCASEEQ (longopt_name, "list-kernels")) list_kernels = 1; /* set kernel-min */ else if (STRCASEEQ (longopt_name, "kernel-min")) NOT_IMPL; /* set kernel-max */ else if (STRCASEEQ (longopt_name, "kernel-max")) NOT_IMPL; /* display version and exit */ else if (STRCASEEQ (longopt_name, "version")) { printf ("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION); exit (0); } else INTERNAL_ERROR; /* this shouldn't happen */ break; } case 'A': /* set architecture */ NOT_IMPL; case 'E': /* set endianness */ NOT_IMPL; case 'T': /* set text address */ NOT_IMPL; case 'W': /* set wordsize */ NOT_IMPL; case 'c': /* connect to URI */ uri = optarg; break; case 'd': /* enable debugging */ debug = 1; break; case 't': /* load kernel image */ test_image = optarg; break; case 'x': /* location of external database */ externaldb = optarg; fail_if_no_externaldb = 1; break; case '?': /* print help */ usage (); default: INTERNAL_ERROR; /* this shouldn't happen */ } } /* while */ /* Load the external database / kernel updates, if necessary. */ load_externaldb (externaldb, fail_if_no_externaldb); /* If asked, list kernels and exit. */ if (list_kernels) do_list_kernels (); /* If we haven't got a tool name yet, then the first anon parameter * must be a tool name. */ if (!tool) { if (optind < argc) { const char *p; struct tool *t; p = argv[optind++]; for (t = tools; t != NULL; t = t->next) { if (STRCASEEQ (p, t->name)) { tool = t; goto found_tool; } } 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); } else 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'.")); found_tool: ; } /* We should have worked out which tool it is by now. */ assert (tool != NULL); /* If -t was passed, then we load that forensic image, else we have * to connect to libvirt. */ if (test_image) { if (optind < argc) error (_("If '-t' is passed then there shouldn't be any additional command line arguments.")); NOT_IMPL; } else { virDomainPtr *doms; /* Connect to libvirt. */ conn = virConnectOpenReadOnly (uri); if (!conn) 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."), uri != NULL ? uri : _("default")); /* Extra parameters are a list of domain names, IDs or UUIDs. */ if (optind < argc) doms = get_named_domains (&argv[optind], argc - optind); else doms = get_all_domains (); /* Act on each domain. */ NOT_IMPL; } exit (0); } /* Usage. */ static void usage (void) { struct tool *t; printf (_("\ virt-kernel-info: Tools for providing information about virtual machines\n\ \n\ General usage is:\n\ [-options]\n\ [-options] [domain-name|ID|UUID ...]\n\ [-options] -t \n\ where is 'virt-ps', 'virt-dmesg' etc. (full list below) or a\n\ subtool such as 'virt-kernel-info ps', 'virt-kernel-info capture' etc.\n\ \n\ General options:\n\ --connect | -c Connect to URI (default: autodetect)\n\ --csv Output in CSV format for spreadsheets etc.\n\ --debug Print extra debugging information\n\ --list-kernels List known kernels, then exit\n\ --image | -t Examine saved image (see: virt-kernel-info capture)\n\ --externaldb | -x Load/override external kernels database\n\ --version Print program name and version, then exit\n\ \n\ These options may be used to override automatic detection of guest\n\ architecture, endianness, kernel location, etc.:\n\ -A | --arch auto | | ...\n\ -E | --endian auto | le | be\n\ --kernel-min auto | | ... | 0x\n\ --kernel-max auto | | ... | 0x\n\ -T | --text auto | | ... | 0x\n\ -W | --wordsize auto | 32 | 64\n\ where is the name of an architecture such as i386, x86-64, etc.\n\ \n\ List of tools:\n\ ")); for (t = tools; t != NULL; t = t->next) { printf ("\n"); if (t->external_cmd) printf (" virt-%-12s - %s\n", t->name, t->summary); else printf (" virt-kernel-info %8s - %s\n", t->name, t->summary); printf ("%s", t->description); if (t->next) printf ("\n"); } exit (0); } static void load_externaldb (const char *externaldb, int fail_if_no_externaldb) { NOT_IMPL; } static void do_list_kernels (void) { NOT_IMPL; } static virDomainPtr * get_named_domains (char * const *domains, int nr_domains) { NOT_IMPL; } static virDomainPtr * get_all_domains (void) { NOT_IMPL; } /* Tools register themselves by calling this function. Note that the * function is called from constructors. In particular it is called * before main(). Also can be called in unspecified order. */ void register_tool (struct tool *tool) { struct tool *t, **p; /* Insertion sort. */ p = &tools; for (t = tools; t != NULL; t = t->next) { if (strcmp (t->name, tool->name) < 0) goto insert; p = &t->next; } insert: tool->next = *p; *p = tool; } /* Warning, error message functions. See internal.h for usage. */ static void message (const char *pre, const char *fs, va_list args) { fprintf (stderr, "%s-%s: %s: ", PACKAGE_NAME, PACKAGE_VERSION, pre); vfprintf (stderr, fs, args); fprintf (stderr, "\n"); } void error (const char *fs, ...) { va_list args; va_start (args, fs); message (_("error"), fs, args); va_end (args); exit (1); } void warning (const char *fs, ...) { va_list args; va_start (args, fs); message (_("warning"), fs, args); va_end (args); } void internal_error (const char *fs, ...) { va_list args; va_start (args, fs); message (_("internal error"), fs, args); va_end (args); abort (); }