summaryrefslogtreecommitdiffstats
path: root/fish
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2010-11-09 18:56:00 +0000
committerRichard W.M. Jones <rjones@redhat.com>2010-11-11 11:24:13 +0000
commit7509c91a71c729b3223eef4cde10d70daca66c72 (patch)
tree927c56e258c843439d545081d8af3c27125a8b9a /fish
parentf08fe63761d4186d49212b1d2382b1a5a2b8a62f (diff)
downloadlibguestfs-7509c91a71c729b3223eef4cde10d70daca66c72.tar.gz
libguestfs-7509c91a71c729b3223eef4cde10d70daca66c72.tar.xz
libguestfs-7509c91a71c729b3223eef4cde10d70daca66c72.zip
fish: Use core add-domain API to implement '-d' option.
This also makes libxml2 and libvirt into optional dependencies. If they are missing then the core API will print an error, as will the '-d' option to guestfish.
Diffstat (limited to 'fish')
-rw-r--r--fish/Makefile.am2
-rw-r--r--fish/virt.c189
2 files changed, 8 insertions, 183 deletions
diff --git a/fish/Makefile.am b/fish/Makefile.am
index dadda91e..6debdced 100644
--- a/fish/Makefile.am
+++ b/fish/Makefile.am
@@ -103,11 +103,9 @@ guestfish_CFLAGS = \
-DGUESTFS_DEFAULT_PATH='"$(libdir)/guestfs"' \
-DLOCALEBASEDIR=\""$(datadir)/locale"\" \
-I$(srcdir)/../gnulib/lib -I../gnulib/lib \
- $(LIBVIRT_CFLAGS) $(LIBXML2_CFLAGS) \
$(WARN_CFLAGS) $(WERROR_CFLAGS)
guestfish_LDADD = \
- $(LIBVIRT_LIBS) $(LIBXML2_LIBS) \
$(top_builddir)/src/libguestfs.la $(LIBREADLINE) -lm
# Make guestfish use the convenience libraries.
diff --git a/fish/virt.c b/fish/virt.c
index 728f9c28..13a6d127 100644
--- a/fish/virt.c
+++ b/fish/virt.c
@@ -23,199 +23,26 @@
#include <string.h>
#include <assert.h>
-#include <libvirt/libvirt.h>
-#include <libvirt/virterror.h>
-
-#include <libxml/xpath.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-
#include "guestfs.h"
#include "options.h"
/* Implements the guts of the '-d' option.
- *
- * Note that we have to observe the '--ro' flag in two respects: by
- * adding the drives read-only if the flag is set, and by restricting
- * guests to shut down ones unless '--ro' is set.
- *
* Returns the number of drives added (> 0), or -1 for failure.
*/
int
add_libvirt_drives (const char *guest)
{
- static int initialized = 0;
- if (!initialized) {
- initialized = 1;
-
- if (virInitialize () == -1)
- return -1;
-
- xmlInitParser ();
- LIBXML_TEST_VERSION;
- }
-
- int r = -1, nr_added = 0, i;
- virErrorPtr err;
- virConnectPtr conn = NULL;
- virDomainPtr dom = NULL;
- xmlDocPtr doc = NULL;
- xmlXPathContextPtr xpathCtx = NULL;
- xmlXPathObjectPtr xpathObj = NULL;
- char *xml = NULL;
-
- /* Connect to libvirt, find the domain. */
- conn = virConnectOpenReadOnly (libvirt_uri);
- if (!conn) {
- err = virGetLastError ();
- fprintf (stderr, _("%s: could not connect to libvirt (code %d, domain %d): %s\n"),
- program_name, err->code, err->domain, err->message);
- goto cleanup;
- }
-
- dom = virDomainLookupByName (conn, guest);
- if (!dom) {
- err = virConnGetLastError (conn);
- fprintf (stderr, _("%s: no libvirt domain called '%s': %s\n"),
- program_name, guest, err->message);
- goto cleanup;
- }
- if (!read_only) {
- virDomainInfo info;
- if (virDomainGetInfo (dom, &info) == -1) {
- err = virConnGetLastError (conn);
- fprintf (stderr, _("%s: error getting domain info about '%s': %s\n"),
- program_name, guest, err->message);
- goto cleanup;
- }
- if (info.state != VIR_DOMAIN_SHUTOFF) {
- fprintf (stderr, _("%s: error: '%s' is a live virtual machine.\nYou must use '--ro' because write access to a running virtual machine can\ncause disk corruption.\n"),
- program_name, guest);
- goto cleanup;
- }
- }
-
- /* Domain XML. */
- xml = virDomainGetXMLDesc (dom, 0);
-
- if (!xml) {
- err = virConnGetLastError (conn);
- fprintf (stderr, _("%s: error reading libvirt XML information about '%s': %s\n"),
- program_name, guest, err->message);
- goto cleanup;
- }
-
- /* Now the horrible task of parsing out the fields we need from the XML.
- * http://www.xmlsoft.org/examples/xpath1.c
- */
- doc = xmlParseMemory (xml, strlen (xml));
- if (doc == NULL) {
- fprintf (stderr, _("%s: unable to parse XML information returned by libvirt\n"),
- program_name);
- goto cleanup;
- }
+ struct guestfs_add_domain_argv optargs = { .bitmask = 0 };
- xpathCtx = xmlXPathNewContext (doc);
- if (xpathCtx == NULL) {
- fprintf (stderr, _("%s: unable to create new XPath context\n"),
- program_name);
- goto cleanup;
+ if (libvirt_uri) {
+ optargs.bitmask |= GUESTFS_ADD_DOMAIN_LIBVIRTURI_BITMASK;
+ optargs.libvirturi = libvirt_uri;
}
-
- /* This gives us a set of all the <disk> nodes. */
- xpathObj = xmlXPathEvalExpression (BAD_CAST "//devices/disk", xpathCtx);
- if (xpathObj == NULL) {
- fprintf (stderr, _("%s: unable to evaluate XPath expression\n"),
- program_name);
- goto cleanup;
+ if (read_only) {
+ optargs.bitmask |= GUESTFS_ADD_DOMAIN_READONLY_BITMASK;
+ optargs.readonly = 1;
}
- xmlNodeSetPtr nodes = xpathObj->nodesetval;
- for (i = 0; i < nodes->nodeNr; ++i) {
- xmlXPathObjectPtr xpfilename;
- xmlXPathObjectPtr xpformat;
-
- /* Change the context to the current <disk> node.
- * DV advises to reset this before each search since older versions of
- * libxml2 might overwrite it.
- */
- xpathCtx->node = nodes->nodeTab[i];
-
- /* Filename can be in <source dev=..> or <source file=..> attribute. */
- xpfilename = xmlXPathEvalExpression (BAD_CAST "./source/@dev", xpathCtx);
- if (xpfilename == NULL ||
- xpfilename->nodesetval == NULL ||
- xpfilename->nodesetval->nodeNr == 0) {
- xmlXPathFreeObject (xpfilename);
- xpathCtx->node = nodes->nodeTab[i];
- xpfilename = xmlXPathEvalExpression (BAD_CAST "./source/@file", xpathCtx);
- if (xpfilename == NULL ||
- xpfilename->nodesetval == NULL ||
- xpfilename->nodesetval->nodeNr == 0) {
- xmlXPathFreeObject (xpfilename);
- continue; /* disk filename not found, skip this */
- }
- }
-
- assert (xpfilename->nodesetval->nodeTab[0]);
- assert (xpfilename->nodesetval->nodeTab[0]->type == XML_ATTRIBUTE_NODE);
- xmlAttrPtr attr = (xmlAttrPtr) xpfilename->nodesetval->nodeTab[0];
- char *filename = (char *) xmlNodeListGetString (doc, attr->children, 1);
-
- /* Get the disk format (may not be set). */
- xpathCtx->node = nodes->nodeTab[i];
- xpformat = xmlXPathEvalExpression (BAD_CAST "./driver/@type", xpathCtx);
- char *format = NULL;
- if (xpformat != NULL &&
- xpformat->nodesetval &&
- xpformat->nodesetval->nodeNr > 0) {
- assert (xpformat->nodesetval->nodeTab[0]);
- assert (xpformat->nodesetval->nodeTab[0]->type == XML_ATTRIBUTE_NODE);
- attr = (xmlAttrPtr) xpformat->nodesetval->nodeTab[0];
- format = (char *) xmlNodeListGetString (doc, attr->children, 1);
- }
-
- /* Add the disk, with optional format. */
- struct guestfs_add_drive_opts_argv optargs = { .bitmask = 0 };
- if (read_only) {
- optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK;
- optargs.readonly = read_only;
- }
- if (format) {
- optargs.bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK;
- optargs.format = format;
- }
-
- int t = guestfs_add_drive_opts_argv (g, filename, &optargs);
-
- xmlFree (filename);
- xmlFree (format);
- xmlXPathFreeObject (xpfilename);
- xmlXPathFreeObject (xpformat);
-
- if (t == -1)
- goto cleanup;
-
- nr_added++;
- }
-
- if (nr_added == 0) {
- fprintf (stderr, _("%s: libvirt domain '%s' has no disks\n"),
- program_name, guest);
- goto cleanup;
- }
-
- /* Successful. */
- r = nr_added;
-
-cleanup:
- free (xml);
- if (xpathObj) xmlXPathFreeObject (xpathObj);
- if (xpathCtx) xmlXPathFreeContext (xpathCtx);
- if (doc) xmlFreeDoc (doc);
- if (dom) virDomainFree (dom);
- if (conn) virConnectClose (conn);
-
- return r;
+ return guestfs_add_domain_argv (g, guest, &optargs);
}